From e498687a583a0a781430c0b46d272cc4ffea0ddd Mon Sep 17 00:00:00 2001 From: BruceOu <1576690133@qq.com> Date: Thu, 5 Jan 2023 14:45:17 +0800 Subject: [PATCH] [BSP] Add n32g4frml-stb bsp (#6773) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增n32g4frml-stb bsp,在n32g4frml-stb 开发板上测试通过。 Add n32g4frml-stb bsp. passed the test on the n32g4frml-stb board. --- .github/workflows/action.yml | 1 + bsp/n32/libraries/Kconfig | 5 + .../CMSIS/core/arm_common_tables.h | 121 + .../CMSIS/core/arm_const_structs.h | 66 + .../CMSIS/core/arm_math.h | 7157 +++++++++++++ .../CMSIS/core/cmsis_armcc.h | 865 ++ .../CMSIS/core/cmsis_armclang.h | 1869 ++++ .../CMSIS/core/cmsis_compiler.h | 266 + .../CMSIS/core/cmsis_gcc.h | 2085 ++++ .../CMSIS/core/cmsis_iccarm.h | 935 ++ .../CMSIS/core/cmsis_version.h | 39 + .../CMSIS/core/core_cm4.h | 2129 ++++ .../CMSIS/core/mpu_armv7.h | 270 + .../CMSIS/device/n32g4fr.h | 8862 +++++++++++++++++ .../CMSIS/device/n32g4fr_conf.h | 85 + .../CMSIS/device/n32g4fr_flash.ld | 164 + .../CMSIS/device/startup/startup_n32g4fr.s | 426 + .../device/startup/startup_n32g4fr_EWARM.s | 612 ++ .../device/startup/startup_n32g4fr_gcc.s | 485 + .../CMSIS/device/system_n32g4fr.c | 421 + .../CMSIS/device/system_n32g4fr.h | 59 + .../N32G4FR_Firmware_Library/SConscript | 58 + .../n32g4fr_algo_lib/inc/n32g4fr_aes.h | 126 + .../inc/n32g4fr_algo_common.h | 154 + .../n32g4fr_algo_lib/inc/n32g4fr_des.h | 119 + .../n32g4fr_algo_lib/inc/n32g4fr_hash.h | 218 + .../n32g4fr_algo_lib/inc/n32g4fr_rng.h | 93 + .../n32g4fr_std_periph_driver/inc/misc.h | 228 + .../inc/n32g4fr_adc.h | 613 ++ .../inc/n32g4fr_bkp.h | 181 + .../inc/n32g4fr_can.h | 671 ++ .../inc/n32g4fr_crc.h | 105 + .../inc/n32g4fr_dac.h | 307 + .../inc/n32g4fr_dbg.h | 124 + .../inc/n32g4fr_dma.h | 569 ++ .../inc/n32g4fr_dvp.h | 602 ++ .../inc/n32g4fr_exti.h | 206 + .../inc/n32g4fr_flash.h | 375 + .../inc/n32g4fr_gpio.h | 459 + .../inc/n32g4fr_i2c.h | 671 ++ .../inc/n32g4fr_iwdg.h | 145 + .../inc/n32g4fr_pwr.h | 179 + .../inc/n32g4fr_qspi.h | 317 + .../inc/n32g4fr_rcc.h | 706 ++ .../inc/n32g4fr_rtc.h | 662 ++ .../inc/n32g4fr_sdio.h | 494 + .../inc/n32g4fr_spi.h | 471 + .../inc/n32g4fr_tim.h | 1112 +++ .../inc/n32g4fr_tsc.h | 576 ++ .../inc/n32g4fr_usart.h | 398 + .../inc/n32g4fr_wwdg.h | 122 + .../inc/n32xx_tsc_alg_api.h | 302 + .../n32g4fr_std_periph_driver/src/misc.c | 228 + .../src/n32g4fr_adc.c | 1471 +++ .../src/n32g4fr_bkp.c | 252 + .../src/n32g4fr_can.c | 1478 +++ .../src/n32g4fr_crc.c | 228 + .../src/n32g4fr_dac.c | 425 + .../src/n32g4fr_dbg.c | 264 + .../src/n32g4fr_dma.c | 888 ++ .../src/n32g4fr_dvp.c | 166 + .../src/n32g4fr_exti.c | 286 + .../src/n32g4fr_flash.c | 1123 +++ .../src/n32g4fr_gpio.c | 852 ++ .../src/n32g4fr_i2c.c | 1324 +++ .../src/n32g4fr_iwdg.c | 193 + .../src/n32g4fr_pwr.c | 399 + .../src/n32g4fr_qspi.c | 576 ++ .../src/n32g4fr_rcc.c | 1364 +++ .../src/n32g4fr_rtc.c | 2006 ++++ .../src/n32g4fr_sdio.c | 789 ++ .../src/n32g4fr_spi.c | 862 ++ .../src/n32g4fr_tim.c | 3306 ++++++ .../src/n32g4fr_tsc.c | 500 + .../src/n32g4fr_usart.c | 974 ++ .../src/n32g4fr_wwdg.c | 223 + .../n32g4fr_usbfs_driver/inc/usb_core.h | 264 + .../n32g4fr_usbfs_driver/inc/usb_def.h | 98 + .../n32g4fr_usbfs_driver/inc/usb_init.h | 71 + .../n32g4fr_usbfs_driver/inc/usb_int.h | 50 + .../n32g4fr_usbfs_driver/inc/usb_lib.h | 47 + .../n32g4fr_usbfs_driver/inc/usb_mem.h | 52 + .../n32g4fr_usbfs_driver/inc/usb_regs.h | 715 ++ .../n32g4fr_usbfs_driver/inc/usb_sil.h | 53 + .../n32g4fr_usbfs_driver/inc/usb_type.h | 54 + .../n32g4fr_usbfs_driver/src/usb_core.c | 950 ++ .../n32g4fr_usbfs_driver/src/usb_init.c | 69 + .../n32g4fr_usbfs_driver/src/usb_int.c | 179 + .../n32g4fr_usbfs_driver/src/usb_mem.c | 81 + .../n32g4fr_usbfs_driver/src/usb_regs.c | 598 ++ .../n32g4fr_usbfs_driver/src/usb_sil.c | 83 + bsp/n32/libraries/n32_drivers/drv_adc.c | 4 +- bsp/n32/libraries/n32_drivers/drv_can.c | 16 +- bsp/n32/libraries/n32_drivers/drv_dac.c | 8 +- bsp/n32/libraries/n32_drivers/drv_gpio.c | 14 +- bsp/n32/libraries/n32_drivers/drv_rtc.c | 12 +- bsp/n32/libraries/n32_drivers/drv_spi.c | 6 +- bsp/n32/libraries/n32_drivers/drv_usart.c | 6 +- bsp/n32/libraries/n32_drivers/drv_wdt.c | 2 +- bsp/n32/n32g4frml-stb/.config | 883 ++ bsp/n32/n32g4frml-stb/Kconfig | 21 + bsp/n32/n32g4frml-stb/README.md | 115 + bsp/n32/n32g4frml-stb/SConscript | 15 + bsp/n32/n32g4frml-stb/SConstruct | 60 + bsp/n32/n32g4frml-stb/applications/SConscript | 15 + bsp/n32/n32g4frml-stb/applications/main.c | 30 + bsp/n32/n32g4frml-stb/board/Kconfig | 201 + bsp/n32/n32g4frml-stb/board/SConscript | 28 + bsp/n32/n32g4frml-stb/board/board.c | 69 + bsp/n32/n32g4frml-stb/board/board.h | 44 + .../board/linker_scripts/link.icf | 40 + .../board/linker_scripts/link.lds | 142 + .../board/linker_scripts/link.sct | 15 + bsp/n32/n32g4frml-stb/figures/board.png | Bin 0 -> 1181447 bytes bsp/n32/n32g4frml-stb/project.ewd | 2974 ++++++ bsp/n32/n32g4frml-stb/project.ewp | 2422 +++++ bsp/n32/n32g4frml-stb/project.eww | 10 + bsp/n32/n32g4frml-stb/project.uvoptx | 1205 +++ bsp/n32/n32g4frml-stb/project.uvprojx | 848 ++ bsp/n32/n32g4frml-stb/rtconfig.h | 246 + bsp/n32/n32g4frml-stb/rtconfig.py | 184 + bsp/n32/n32g4frml-stb/template.ewp | 2088 ++++ bsp/n32/n32g4frml-stb/template.eww | 10 + bsp/n32/n32g4frml-stb/template.uvoptx | 185 + bsp/n32/n32g4frml-stb/template.uvprojx | 418 + 125 files changed, 74128 insertions(+), 34 deletions(-) create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/arm_common_tables.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/arm_const_structs.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/arm_math.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_armcc.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_armclang.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_compiler.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_gcc.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_iccarm.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_version.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/core_cm4.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/mpu_armv7.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/n32g4fr.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/n32g4fr_conf.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/n32g4fr_flash.ld create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/startup/startup_n32g4fr.s create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/startup/startup_n32g4fr_EWARM.s create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/startup/startup_n32g4fr_gcc.s create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/system_n32g4fr.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/system_n32g4fr.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/SConscript create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_aes.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_algo_common.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_des.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_hash.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_rng.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/misc.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_adc.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_bkp.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_can.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_crc.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_dac.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_dbg.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_dma.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_dvp.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_exti.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_flash.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_gpio.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_i2c.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_iwdg.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_pwr.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_qspi.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_rcc.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_rtc.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_sdio.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_spi.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_tim.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_tsc.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_usart.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_wwdg.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32xx_tsc_alg_api.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/misc.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_adc.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_bkp.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_can.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_crc.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_dac.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_dbg.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_dma.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_dvp.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_exti.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_flash.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_gpio.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_i2c.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_iwdg.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_pwr.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_qspi.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_rcc.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_rtc.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_sdio.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_spi.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_tim.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_tsc.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_usart.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_wwdg.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_core.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_def.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_init.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_int.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_lib.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_mem.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_regs.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_sil.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_type.h create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_core.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_init.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_int.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_mem.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_regs.c create mode 100644 bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_sil.c create mode 100644 bsp/n32/n32g4frml-stb/.config create mode 100644 bsp/n32/n32g4frml-stb/Kconfig create mode 100644 bsp/n32/n32g4frml-stb/README.md create mode 100644 bsp/n32/n32g4frml-stb/SConscript create mode 100644 bsp/n32/n32g4frml-stb/SConstruct create mode 100644 bsp/n32/n32g4frml-stb/applications/SConscript create mode 100644 bsp/n32/n32g4frml-stb/applications/main.c create mode 100644 bsp/n32/n32g4frml-stb/board/Kconfig create mode 100644 bsp/n32/n32g4frml-stb/board/SConscript create mode 100644 bsp/n32/n32g4frml-stb/board/board.c create mode 100644 bsp/n32/n32g4frml-stb/board/board.h create mode 100644 bsp/n32/n32g4frml-stb/board/linker_scripts/link.icf create mode 100644 bsp/n32/n32g4frml-stb/board/linker_scripts/link.lds create mode 100644 bsp/n32/n32g4frml-stb/board/linker_scripts/link.sct create mode 100644 bsp/n32/n32g4frml-stb/figures/board.png create mode 100644 bsp/n32/n32g4frml-stb/project.ewd create mode 100644 bsp/n32/n32g4frml-stb/project.ewp create mode 100644 bsp/n32/n32g4frml-stb/project.eww create mode 100644 bsp/n32/n32g4frml-stb/project.uvoptx create mode 100644 bsp/n32/n32g4frml-stb/project.uvprojx create mode 100644 bsp/n32/n32g4frml-stb/rtconfig.h create mode 100644 bsp/n32/n32g4frml-stb/rtconfig.py create mode 100644 bsp/n32/n32g4frml-stb/template.ewp create mode 100644 bsp/n32/n32g4frml-stb/template.eww create mode 100644 bsp/n32/n32g4frml-stb/template.uvoptx create mode 100644 bsp/n32/n32g4frml-stb/template.uvprojx diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index 056ca614a2..02371b00f6 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -53,6 +53,7 @@ jobs: - {RTT_BSP: "n32/n32g45xrl-stb", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "n32/n32g45xvl-stb", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "n32/n32g457qel-stb", RTT_TOOL_CHAIN: "sourcery-arm"} + - {RTT_BSP: "n32/n32g4frml-stb", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "n32/n32l40xcl-stb", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "n32/n32l43xml-stb", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "n32/n32l43xrl-stb", RTT_TOOL_CHAIN: "sourcery-arm"} diff --git a/bsp/n32/libraries/Kconfig b/bsp/n32/libraries/Kconfig index c08c8d2b97..cdcd5bfc26 100644 --- a/bsp/n32/libraries/Kconfig +++ b/bsp/n32/libraries/Kconfig @@ -15,3 +15,8 @@ config SOC_SERIES_N32WB452 bool select ARCH_ARM_CORTEX_M4 select SOC_FAMILY_N32 + +config SOC_SERIES_N32G4FR + bool + select ARCH_ARM_CORTEX_M4 + select SOC_FAMILY_N32 \ No newline at end of file diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/arm_common_tables.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/arm_common_tables.h new file mode 100644 index 0000000000..dfea7460e9 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/arm_common_tables.h @@ -0,0 +1,121 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_common_tables.h + * Description: Extern declaration for common tables + * + * $Date: 27. January 2017 + * $Revision: V.1.5.1 + * + * Target Processor: Cortex-M cores + * -------------------------------------------------------------------- */ +/* + * Copyright (C) 2010-2017 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. + */ + +#ifndef _ARM_COMMON_TABLES_H +#define _ARM_COMMON_TABLES_H + +#include "arm_math.h" + +extern const uint16_t armBitRevTable[1024]; +extern const q15_t armRecipTableQ15[64]; +extern const q31_t armRecipTableQ31[64]; +extern const float32_t twiddleCoef_16[32]; +extern const float32_t twiddleCoef_32[64]; +extern const float32_t twiddleCoef_64[128]; +extern const float32_t twiddleCoef_128[256]; +extern const float32_t twiddleCoef_256[512]; +extern const float32_t twiddleCoef_512[1024]; +extern const float32_t twiddleCoef_1024[2048]; +extern const float32_t twiddleCoef_2048[4096]; +extern const float32_t twiddleCoef_4096[8192]; +#define twiddleCoef twiddleCoef_4096 +extern const q31_t twiddleCoef_16_q31[24]; +extern const q31_t twiddleCoef_32_q31[48]; +extern const q31_t twiddleCoef_64_q31[96]; +extern const q31_t twiddleCoef_128_q31[192]; +extern const q31_t twiddleCoef_256_q31[384]; +extern const q31_t twiddleCoef_512_q31[768]; +extern const q31_t twiddleCoef_1024_q31[1536]; +extern const q31_t twiddleCoef_2048_q31[3072]; +extern const q31_t twiddleCoef_4096_q31[6144]; +extern const q15_t twiddleCoef_16_q15[24]; +extern const q15_t twiddleCoef_32_q15[48]; +extern const q15_t twiddleCoef_64_q15[96]; +extern const q15_t twiddleCoef_128_q15[192]; +extern const q15_t twiddleCoef_256_q15[384]; +extern const q15_t twiddleCoef_512_q15[768]; +extern const q15_t twiddleCoef_1024_q15[1536]; +extern const q15_t twiddleCoef_2048_q15[3072]; +extern const q15_t twiddleCoef_4096_q15[6144]; +extern const float32_t twiddleCoef_rfft_32[32]; +extern const float32_t twiddleCoef_rfft_64[64]; +extern const float32_t twiddleCoef_rfft_128[128]; +extern const float32_t twiddleCoef_rfft_256[256]; +extern const float32_t twiddleCoef_rfft_512[512]; +extern const float32_t twiddleCoef_rfft_1024[1024]; +extern const float32_t twiddleCoef_rfft_2048[2048]; +extern const float32_t twiddleCoef_rfft_4096[4096]; + +/* floating-point bit reversal tables */ +#define ARMBITREVINDEXTABLE_16_TABLE_LENGTH ((uint16_t)20) +#define ARMBITREVINDEXTABLE_32_TABLE_LENGTH ((uint16_t)48) +#define ARMBITREVINDEXTABLE_64_TABLE_LENGTH ((uint16_t)56) +#define ARMBITREVINDEXTABLE_128_TABLE_LENGTH ((uint16_t)208) +#define ARMBITREVINDEXTABLE_256_TABLE_LENGTH ((uint16_t)440) +#define ARMBITREVINDEXTABLE_512_TABLE_LENGTH ((uint16_t)448) +#define ARMBITREVINDEXTABLE_1024_TABLE_LENGTH ((uint16_t)1800) +#define ARMBITREVINDEXTABLE_2048_TABLE_LENGTH ((uint16_t)3808) +#define ARMBITREVINDEXTABLE_4096_TABLE_LENGTH ((uint16_t)4032) + +extern const uint16_t armBitRevIndexTable16[ARMBITREVINDEXTABLE_16_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable32[ARMBITREVINDEXTABLE_32_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable64[ARMBITREVINDEXTABLE_64_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable128[ARMBITREVINDEXTABLE_128_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable256[ARMBITREVINDEXTABLE_256_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable512[ARMBITREVINDEXTABLE_512_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable1024[ARMBITREVINDEXTABLE_1024_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable2048[ARMBITREVINDEXTABLE_2048_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable4096[ARMBITREVINDEXTABLE_4096_TABLE_LENGTH]; + +/* fixed-point bit reversal tables */ +#define ARMBITREVINDEXTABLE_FIXED_16_TABLE_LENGTH ((uint16_t)12) +#define ARMBITREVINDEXTABLE_FIXED_32_TABLE_LENGTH ((uint16_t)24) +#define ARMBITREVINDEXTABLE_FIXED_64_TABLE_LENGTH ((uint16_t)56) +#define ARMBITREVINDEXTABLE_FIXED_128_TABLE_LENGTH ((uint16_t)112) +#define ARMBITREVINDEXTABLE_FIXED_256_TABLE_LENGTH ((uint16_t)240) +#define ARMBITREVINDEXTABLE_FIXED_512_TABLE_LENGTH ((uint16_t)480) +#define ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH ((uint16_t)992) +#define ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH ((uint16_t)1984) +#define ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH ((uint16_t)4032) + +extern const uint16_t armBitRevIndexTable_fixed_16[ARMBITREVINDEXTABLE_FIXED_16_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_32[ARMBITREVINDEXTABLE_FIXED_32_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_64[ARMBITREVINDEXTABLE_FIXED_64_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_128[ARMBITREVINDEXTABLE_FIXED_128_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_256[ARMBITREVINDEXTABLE_FIXED_256_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_512[ARMBITREVINDEXTABLE_FIXED_512_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_1024[ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_2048[ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_4096[ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH]; + +/* Tables for Fast Math Sine and Cosine */ +extern const float32_t sinTable_f32[FAST_MATH_TABLE_SIZE + 1]; +extern const q31_t sinTable_q31[FAST_MATH_TABLE_SIZE + 1]; +extern const q15_t sinTable_q15[FAST_MATH_TABLE_SIZE + 1]; + +#endif /* ARM_COMMON_TABLES_H */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/arm_const_structs.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/arm_const_structs.h new file mode 100644 index 0000000000..80a3e8bbe7 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/arm_const_structs.h @@ -0,0 +1,66 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_const_structs.h + * Description: Constant structs that are initialized for user convenience. + * For example, some can be given as arguments to the arm_cfft_f32() function. + * + * $Date: 27. January 2017 + * $Revision: V.1.5.1 + * + * Target Processor: Cortex-M cores + * -------------------------------------------------------------------- */ +/* + * Copyright (C) 2010-2017 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. + */ + +#ifndef _ARM_CONST_STRUCTS_H +#define _ARM_CONST_STRUCTS_H + +#include "arm_math.h" +#include "arm_common_tables.h" + + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len16; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len32; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len64; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len128; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len256; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len512; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len1024; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len2048; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len4096; + + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len16; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len32; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len64; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len128; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len256; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len512; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len1024; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len2048; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len4096; + + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len16; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len32; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len64; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len128; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len256; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len512; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len1024; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len2048; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len4096; + +#endif diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/arm_math.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/arm_math.h new file mode 100644 index 0000000000..ea9dd26aa8 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/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/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_armcc.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_armcc.h new file mode 100644 index 0000000000..4d9d0645d3 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_armcc.h @@ -0,0 +1,865 @@ +/**************************************************************************//** + * @file cmsis_armcc.h + * @brief CMSIS compiler ARMCC (Arm Compiler 5) header file + * @version V5.0.4 + * @date 10. January 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_ARMCC_H +#define __CMSIS_ARMCC_H + + +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677) + #error "Please use Arm Compiler Toolchain V4.0.677 or later!" +#endif + +/* CMSIS compiler control architecture macros */ +#if ((defined (__TARGET_ARCH_6_M ) && (__TARGET_ARCH_6_M == 1)) || \ + (defined (__TARGET_ARCH_6S_M ) && (__TARGET_ARCH_6S_M == 1)) ) + #define __ARM_ARCH_6M__ 1 +#endif + +#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M == 1)) + #define __ARM_ARCH_7M__ 1 +#endif + +#if (defined (__TARGET_ARCH_7E_M) && (__TARGET_ARCH_7E_M == 1)) + #define __ARM_ARCH_7EM__ 1 +#endif + + /* __ARM_ARCH_8M_BASE__ not applicable */ + /* __ARM_ARCH_8M_MAIN__ not applicable */ + + +/* 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 static __forceinline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __declspec(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 __packed struct +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION __packed union +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x))) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr))) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr))) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#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(); */ + + +/** + \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(); */ + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** + \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_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** + \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_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 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 + + +/** + \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 + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xFFU); +} + + +/** + \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_INLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + register uint32_t __regBasePriMax __ASM("basepri_max"); + __regBasePriMax = (basePri & 0xFFU); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1U); +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#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_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#else + (void)fpscr; +#endif +} + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __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 __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 __wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __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() do {\ + __schedule_barrier();\ + __isb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \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() do {\ + __schedule_barrier();\ + __dsb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \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() do {\ + __schedule_barrier();\ + __dmb(0xF);\ + __schedule_barrier();\ + } while (0U) + + +/** + \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 __rev + + +/** + \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 + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + + +/** + \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 + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value) +{ + revsh r0, r0 + bx lr +} +#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 + */ +#define __ROR __ror + + +/** + \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) __breakpoint(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 + */ +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + #define __RBIT __rbit +#else +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + 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 */ + 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/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_armclang.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_armclang.h new file mode 100644 index 0000000000..162a400ea1 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_armclang.h @@ -0,0 +1,1869 @@ +/**************************************************************************//** + * @file cmsis_armclang.h + * @brief CMSIS compiler armclang (Arm Compiler 6) header file + * @version V5.0.4 + * @date 10. January 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. + */ + +/*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 + + +/* ########################### 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 + */ +#define __CLZ (uint8_t)__builtin_clz + + +#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); +} + +#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 */ + + +#endif /* __CMSIS_ARMCLANG_H */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_compiler.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_compiler.h new file mode 100644 index 0000000000..94212eb87a --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_compiler.h @@ -0,0 +1,266 @@ +/**************************************************************************//** + * @file cmsis_compiler.h + * @brief CMSIS compiler generic header file + * @version V5.0.4 + * @date 10. January 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 (armclang) + */ +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #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 + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #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 + + +/* + * 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 + + +#else + #error Unknown compiler. +#endif + + +#endif /* __CMSIS_COMPILER_H */ + diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_gcc.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_gcc.h new file mode 100644 index 0000000000..2d9db15a5d --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_gcc.h @@ -0,0 +1,2085 @@ +/**************************************************************************//** + * @file cmsis_gcc.h + * @brief CMSIS compiler GCC header file + * @version V5.0.4 + * @date 09. April 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_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 + + +/* ########################### 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 + */ +#define __CLZ (uint8_t)__builtin_clz + + +#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/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_iccarm.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_iccarm.h new file mode 100644 index 0000000000..b82874d0e4 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_iccarm.h @@ -0,0 +1,935 @@ +/**************************************************************************//** + * @file cmsis_iccarm.h + * @brief CMSIS compiler ICCARM (IAR Compiler for Arm) header file + * @version V5.0.7 + * @date 19. June 2018 + ******************************************************************************/ + +//------------------------------------------------------------------------------ +// +// Copyright (c) 2017-2018 IAR Systems +// +// 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 __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 + #define __RESTRICT restrict//__restrict +#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 __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/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_version.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_version.h new file mode 100644 index 0000000000..660f612aa3 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/cmsis_version.h @@ -0,0 +1,39 @@ +/**************************************************************************//** + * @file cmsis_version.h + * @brief CMSIS Core(M) Version definitions + * @version V5.0.2 + * @date 19. April 2017 + ******************************************************************************/ +/* + * Copyright (c) 2009-2017 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 ( 1U) /*!< [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/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/core_cm4.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/core_cm4.h new file mode 100644 index 0000000000..7d56873532 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/core_cm4.h @@ -0,0 +1,2129 @@ +/**************************************************************************//** + * @file core_cm4.h + * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File + * @version V5.0.8 + * @date 04. June 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_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_PCS_VFP + #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 RSERVED1[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[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[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 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 */ + __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 (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_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 (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_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 */ +} 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 */ + +/*@} 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) + { + 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); + } +} + + +/** + \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; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; +} + + +/** + \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(); + } +} + +/*@} 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/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/mpu_armv7.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/mpu_armv7.h new file mode 100644 index 0000000000..01422033d0 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/core/mpu_armv7.h @@ -0,0 +1,270 @@ +/****************************************************************************** + * @file mpu_armv7.h + * @brief CMSIS MPU API for Armv7-M MPU + * @version V5.0.4 + * @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 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))) + +/** +* 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 non-shareable) or 010b (if 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) +{ + __DSB(); + __ISB(); + MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; +#endif +} + +/** Disable the MPU. +*/ +__STATIC_INLINE void ARM_MPU_Disable(void) +{ + __DSB(); + __ISB(); +#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 orderedCpy(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) { + orderedCpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize); + table += MPU_TYPE_RALIASES; + cnt -= MPU_TYPE_RALIASES; + } + orderedCpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize); +} + +#endif diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/n32g4fr.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/n32g4fr.h new file mode 100644 index 0000000000..da61e9bebe --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/n32g4fr.h @@ -0,0 +1,8862 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr.h + * @author Nations + * @version v1.0.4 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_H__ +#define __N32G4FR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup N32G4FR_Library_Basic + * @{ + */ + +#if !defined USE_STDPERIPH_DRIVER +/* + * Comment the line below if you will not use the peripherals drivers. + In this case, these drivers will not be included and the application code will + be based on direct access to peripherals registers + */ +#define USE_STDPERIPH_DRIVER +#endif + +/* + * In the following line adjust the value of External High Speed oscillator (HSE) + used in your application + + Tip: To avoid modifying this file each time you need to use different HSE, you + can define the HSE value in your toolchain compiler preprocessor. + */ +#if !defined HSE_VALUE +#define HSE_VALUE (8000000) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +/* + * In the following line adjust the External High Speed oscillator (HSE) Startup + Timeout value + */ +#define HSE_STARTUP_TIMEOUT ((uint16_t)0x8000) /*!< Time out for HSE start up */ + +#define HSI_VALUE (8000000) /*!< Value of the Internal oscillator in Hz*/ + +#define __N32G4FR_STDPERIPH_VERSION_MAIN (0x00) /*!< [31:24] main version */ +#define __N32G4FR_STDPERIPH_VERSION_SUB1 (0x04) /*!< [23:16] sub1 version */ +#define __N32G4FR_STDPERIPH_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */ +#define __N32G4FR_STDPERIPH_VERSION_RC (0x00) /*!< [7:0] release candidate */ + +/** + * @brief N32G4FR Standard Peripheral Library version number + */ +#define __N32G4FR_STDPERIPH_VERSION \ + ((__N32G4FR_STDPERIPH_VERSION_MAIN << 24) | (__N32G4FR_STDPERIPH_VERSION_SUB1 << 16) \ + | (__N32G4FR_STDPERIPH_VERSION_SUB2 << 8) | (__N32G4FR_STDPERIPH_VERSION_RC)) + +/* + * Configuration of the Cortex-M4 Processor and Core Peripherals + */ +#ifdef N32G4FR +#define __MPU_PRESENT 1 /*!< N32G4FR devices does not provide an MPU */ +#define __FPU_PRESENT 1 /*!< FPU present */ +#endif /* N32G4FR */ +#define __NVIC_PRIO_BITS 4 /*!< N32G4FR uses 4 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ + +/** + * @brief N32G4FR Interrupt Number Definition + */ +typedef enum IRQn +{ + /****** Cortex-M4 Processor Exceptions Numbers ***************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 3 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 */ + + /****** N32G4FR specific Interrupt Numbers ********************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ + PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */ + TAMPER_IRQn = 2, /*!< Tamper Interrupt */ + RTC_IRQn = 3, /*!< RTC global Interrupt */ + 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 and ADC2 global Interrupt */ + USB_HP_CAN1_TX_IRQn = 19, /*!< USB Device High Priority or CAN1 TX Interrupts */ + USB_LP_CAN1_RX0_IRQn = 20, /*!< USB Device Low Priority or CAN1 RX0 Interrupts */ + 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_IRQn = 24, /*!< TIM1 Break Interrupt */ + TIM1_UP_IRQn = 25, /*!< TIM1 Update Interrupt */ + TIM1_TRG_COM_IRQn = 26, /*!< TIM1 Trigger and Commutation 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 */ + RTCAlarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */ + USBWakeUp_IRQn = 42, /*!< USB Device WakeUp from suspend through EXTI Line 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 */ + RESERVE47_IRQn = 47, /*!< RESERVE47 Interrupt */ + RESERVE48_IRQn = 48, /*!< RESERVE48 Interrupt */ + SDIO_IRQn = 49, /*!< SDIO 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_IRQn = 54, /*!< TIM6 global Interrupt */ + 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 */ + ETH_IRQn = 61, /*!< Ethernet global Interrupt */ + ETH_WKUP_IRQn = 62, /*!< Ethernet Wakeup through EXTI Line interrupt */ + CAN2_TX_IRQn = 63, /*!< CAN2 TX Interrupt */ + CAN2_RX0_IRQn = 64, /*!< CAN2 RX0 Interrupt */ + CAN2_RX1_IRQn = 65, /*!< CAN2 RX1 Interrupt */ + CAN2_SCE_IRQn = 66, /*!< CAN2 SCE Interrupt */ + QSPI_IRQn = 67, /*!< QSPI global Interrupt */ + DMA2_Channel6_IRQn = 68, /*!< DMA2 Channel 6 global Interrupt */ + DMA2_Channel7_IRQn = 69, /*!< DMA2 Channel 7 global Interrupt */ + I2C3_EV_IRQn = 70, /*!< I2C3 Event Interrupt */ + I2C3_ER_IRQn = 71, /*!< I2C3 Error Interrupt */ + I2C4_EV_IRQn = 72, /*!< I2C4 Event Interrupt */ + I2C4_ER_IRQn = 73, /*!< I2C4 Error Interrupt */ + UART6_IRQn = 74, /*!< UART6 global Interrupt */ + UART7_IRQn = 75, /*!< UART7 global Interrupt */ + DMA1_Channel8_IRQn = 76, /*!< DMA1 Channel 8 global Interrupt */ + DMA2_Channel8_IRQn = 77, /*!< DMA2 Channel 8 global Interrupt */ + DVP_IRQn = 78, /*!< DVP global Interrupt */ + SAC_IRQn = 79, /*!< SAC global Interrupt */ + MMU_IRQn = 80, /*!< MMU global Interrupt */ + TSC_IRQn = 81, /*!< TSC global Interrupt */ + RESERVE82_IRQn = 82, /*!< RESERVE82 Interrupt */ + RESERVE83_IRQn = 83, /*!< RESERVE83 Interrupt */ + RESERVE84_IRQn = 84 /*!< RESERVE84 Interrupt */ + +} IRQn_Type; + +#include "core_cm4.h" +#include "system_n32g4fr.h" +#include +#include + +typedef int32_t s32; +typedef int16_t s16; +typedef int8_t s8; + +typedef const int32_t sc32; /*!< Read Only */ +typedef const int16_t sc16; /*!< Read Only */ +typedef const int8_t sc8; /*!< Read Only */ + +typedef __IO int32_t vs32; +typedef __IO int16_t vs16; +typedef __IO int8_t vs8; + +typedef __I int32_t vsc32; /*!< Read Only */ +typedef __I int16_t vsc16; /*!< Read Only */ +typedef __I int8_t vsc8; /*!< Read Only */ + +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; + +typedef const uint32_t uc32; /*!< Read Only */ +typedef const uint16_t uc16; /*!< Read Only */ +typedef const uint8_t uc8; /*!< Read Only */ + +typedef __IO uint32_t vu32; +typedef __IO uint16_t vu16; +typedef __IO uint8_t vu8; + +typedef __I uint32_t vuc32; /*!< Read Only */ +typedef __I uint16_t vuc16; /*!< Read Only */ +typedef __I uint8_t vuc8; /*!< Read Only */ +typedef enum +{ + RESET = 0, + SET = !RESET +} FlagStatus, + INTStatus; + +typedef enum +{ + DISABLE = 0, + ENABLE = !DISABLE +} FunctionalState; +#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE)) + +typedef enum +{ + ERROR = 0, + SUCCESS = !ERROR +} ErrorStatus; + +/* N32G4FR Standard Peripheral Library old definitions (maintained for legacy purpose) */ +#define HSEStartUp_TimeOut HSE_STARTUP_TIMEOUT +#define HSE_Value HSE_VALUE +#define HSI_Value HSI_VALUE + +/** + * @brief Analog to Digital Converter + */ +typedef struct +{ + __IO uint32_t STS; + __IO uint32_t CTRL1; + __IO uint32_t CTRL2; + __IO uint32_t SAMPT1; + __IO uint32_t SAMPT2; + __IO uint32_t JOFFSET1; + __IO uint32_t JOFFSET2; + __IO uint32_t JOFFSET3; + __IO uint32_t JOFFSET4; + __IO uint32_t WDGHIGH; + __IO uint32_t WDGLOW; + __IO uint32_t RSEQ1; + __IO uint32_t RSEQ2; + __IO uint32_t RSEQ3; + __IO uint32_t JSEQ; + __IO uint32_t JDAT1; + __IO uint32_t JDAT2; + __IO uint32_t JDAT3; + __IO uint32_t JDAT4; + __IO uint32_t DAT; + __IO uint32_t DIFSEL; + __IO uint32_t CALFACT; + __IO uint32_t CTRL3; + __IO uint32_t SAMPT3; +} ADC_Module; + +/** + * @brief AFEC + */ + +typedef struct +{ + __IO uint32_t TRIMR0; + __IO uint32_t TRIMR1; + __IO uint32_t TRIMR2; + __IO uint32_t TRIMR3; + __IO uint32_t TRIMR4; + __IO uint32_t TRIMR5; + __IO uint32_t TRIMR6; + uint32_t RESERVED0; + __IO uint32_t TESTR0; + __IO uint32_t TESTR1; +} AFEC_Module; + +/** + * @brief Backup Registers + */ + +typedef struct +{ + uint32_t RESERVED0; + __IO uint16_t DAT1; + uint16_t RESERVED1; + __IO uint16_t DAT2; + uint16_t RESERVED2; + __IO uint16_t DAT3; + uint16_t RESERVED3; + __IO uint16_t DAT4; + uint16_t RESERVED4; + __IO uint16_t DAT5; + uint16_t RESERVED5; + __IO uint16_t DAT6; + uint16_t RESERVED6; + __IO uint16_t DAT7; + uint16_t RESERVED7; + __IO uint16_t DAT8; + uint16_t RESERVED8; + __IO uint16_t DAT9; + uint16_t RESERVED9; + __IO uint16_t DAT10; + uint16_t RESERVED10; + __IO uint16_t RESERVED; + uint16_t RESERVED11; + __IO uint16_t CTRL; + uint16_t RESERVED12; + __IO uint16_t CTRLSTS; + uint16_t RESERVED13[5]; + __IO uint16_t DAT11; + uint16_t RESERVED14; + __IO uint16_t DAT12; + uint16_t RESERVED15; + __IO uint16_t DAT13; + uint16_t RESERVED16; + __IO uint16_t DAT14; + uint16_t RESERVED17; + __IO uint16_t DAT15; + uint16_t RESERVED18; + __IO uint16_t DAT16; + uint16_t RESERVED19; + __IO uint16_t DAT17; + uint16_t RESERVED20; + __IO uint16_t DAT18; + uint16_t RESERVED21; + __IO uint16_t DAT19; + uint16_t RESERVED22; + __IO uint16_t DAT20; + uint16_t RESERVED23; + __IO uint16_t DAT21; + uint16_t RESERVED24; + __IO uint16_t DAT22; + uint16_t RESERVED25; + __IO uint16_t DAT23; + uint16_t RESERVED26; + __IO uint16_t DAT24; + uint16_t RESERVED27; + __IO uint16_t DAT25; + uint16_t RESERVED28; + __IO uint16_t DAT26; + uint16_t RESERVED29; + __IO uint16_t DAT27; + uint16_t RESERVED30; + __IO uint16_t DAT28; + uint16_t RESERVED31; + __IO uint16_t DAT29; + uint16_t RESERVED32; + __IO uint16_t DAT30; + uint16_t RESERVED33; + __IO uint16_t DAT31; + uint16_t RESERVED34; + __IO uint16_t DAT32; + uint16_t RESERVED35; + __IO uint16_t DAT33; + uint16_t RESERVED36; + __IO uint16_t DAT34; + uint16_t RESERVED37; + __IO uint16_t DAT35; + uint16_t RESERVED38; + __IO uint16_t DAT36; + uint16_t RESERVED39; + __IO uint16_t DAT37; + uint16_t RESERVED40; + __IO uint16_t DAT38; + uint16_t RESERVED41; + __IO uint16_t DAT39; + uint16_t RESERVED42; + __IO uint16_t DAT40; + uint16_t RESERVED43; + __IO uint16_t DAT41; + uint16_t RESERVED44; + __IO uint16_t DAT42; + uint16_t RESERVED45; +} BKP_Module; + +/** + * @brief Controller Area Network TxMailBox + */ + +typedef struct +{ + __IO uint32_t TMI; + __IO uint32_t TMDT; + __IO uint32_t TMDL; + __IO uint32_t TMDH; +} CAN_TxMailBox_Param; + +/** + * @brief Controller Area Network FIFOMailBox + */ + +typedef struct +{ + __IO uint32_t RMI; + __IO uint32_t RMDT; + __IO uint32_t RMDL; + __IO uint32_t RMDH; +} CAN_FIFOMailBox_Param; + +/** + * @brief Controller Area Network FilterRegister + */ + +typedef struct +{ + __IO uint32_t FR1; + __IO uint32_t FR2; +} CAN_FilterRegister_Param; + +/** + * @brief Controller Area Network + */ + +typedef struct +{ + __IO uint32_t MCTRL; + __IO uint32_t MSTS; + __IO uint32_t TSTS; + __IO uint32_t RFF0; + __IO uint32_t RFF1; + __IO uint32_t INTE; + __IO uint32_t ESTS; + __IO uint32_t BTIM; + uint32_t RESERVED0[88]; + CAN_TxMailBox_Param sTxMailBox[3]; + CAN_FIFOMailBox_Param sFIFOMailBox[2]; + uint32_t RESERVED1[12]; + __IO uint32_t FMC; + __IO uint32_t FM1; + uint32_t RESERVED2; + __IO uint32_t FS1; + uint32_t RESERVED3; + __IO uint32_t FFA1; + uint32_t RESERVED4; + __IO uint32_t FA1; + uint32_t RESERVED5[8]; + CAN_FilterRegister_Param sFilterRegister[14]; +} CAN_Module; + +/** + * @brief CRC calculation unit + */ + +typedef struct +{ + __IO uint32_t CRC32DAT; /*!< CRC data register */ + __IO uint8_t CRC32IDAT; /*!< CRC independent data register*/ + uint8_t RESERVED0; + uint16_t RESERVED1; + __IO uint32_t CRC32CTRL; /*!< CRC control register */ + __IO uint32_t CRC16CTRL; + __IO uint8_t CRC16DAT; + uint8_t RESERVED2; + uint16_t RESERVED3; + __IO uint16_t CRC16D; + uint16_t RESERVED4; + __IO uint8_t LRC; + uint8_t RESERVED5; + uint16_t RESERVED6; +} CRC_Module; + +/** + * @brief Digital to Analog Converter + */ + +typedef struct +{ + __IO uint32_t CTRL; + __IO uint32_t SOTTR; + __IO uint32_t DR12CH1; + __IO uint32_t DL12CH1; + __IO uint32_t DR8CH1; + __IO uint32_t DR12CH2; + __IO uint32_t DL12CH2; + __IO uint32_t DR8CH2; + __IO uint32_t DR12DCH; + __IO uint32_t DL12DCH; + __IO uint32_t DR8DCH; + __IO uint32_t DATO1; + __IO uint32_t DATO2; +} DAC_Module; +/** + * @brief USB + */ + +typedef struct +{ + __IO uint32_t EP0; + __IO uint32_t EP1; + __IO uint32_t EP2; + __IO uint32_t EP3; + __IO uint32_t EP4; + __IO uint32_t EP5; + __IO uint32_t EP6; + __IO uint32_t EP7; + __IO uint32_t Reserve20h; + __IO uint32_t Reserve24h; + __IO uint32_t Reserve28h; + __IO uint32_t Reserve2Ch; + __IO uint32_t Reserve30h; + __IO uint32_t Reserve34h; + __IO uint32_t Reserve38h; + __IO uint32_t Reserve3Ch; + __IO uint32_t CTRL; + __IO uint32_t STS; + __IO uint32_t FN; + __IO uint32_t ADDR; + __IO uint32_t BUFTAB; +} USB_Module; + +/** + * @brief Debug MCU + */ + +typedef struct +{ + __IO uint32_t ID; + __IO uint32_t CTRL; +} DBG_Module; + +/** + * @brief DMA Controller + */ + +typedef struct +{ + __IO uint32_t CHCFG; + __IO uint32_t TXNUM; + __IO uint32_t PADDR; + __IO uint32_t MADDR; + __IO uint32_t CHSEL; + +} DMA_ChannelType; + +typedef struct +{ + __IO uint32_t INTSTS; + __IO uint32_t INTCLR; + __IO DMA_ChannelType DMA_Channel[8]; + __IO uint32_t CHMAPEN; +} DMA_Module; + + +/** + * @brief External Interrupt/Event Controller + */ + +typedef struct +{ + __IO uint32_t IMASK; + __IO uint32_t EMASK; + __IO uint32_t RT_CFG; + __IO uint32_t FT_CFG; + __IO uint32_t SWIE; + __IO uint32_t PEND; + __IO uint32_t TSSEL; +} EXTI_Module; + +/** + * @brief FLASH Registers + */ + +typedef struct +{ + __IO uint32_t AC; + __IO uint32_t KEY; + __IO uint32_t OPTKEY; + __IO uint32_t STS; + __IO uint32_t CTRL; + __IO uint32_t ADD; + __IO uint32_t RESERVED0; + __IO uint32_t OBR; + __IO uint32_t WRP; + __IO uint32_t RESERVED1; + __IO uint32_t RESERVED2; + __IO uint32_t RDN; + __IO uint32_t CAHR; +} FLASH_Module; + +/** + * @brief Option Bytes Registers + */ + +typedef struct +{ + __IO uint32_t USER_RDP; + __IO uint32_t Data1_Data0; + __IO uint32_t WRP1_WRP0; + __IO uint32_t WRP3_WRP2; + __IO uint32_t RDP2; +} OB_Module; + +/** + * @brief General Purpose I/O + */ + +typedef struct +{ + __IO uint32_t PL_CFG; + __IO uint32_t PH_CFG; + __IO uint32_t PID; + __IO uint32_t POD; + __IO uint32_t PBSC; + __IO uint32_t PBC; + __IO uint32_t PLOCK_CFG; + uint32_t RESERVED0; + __IO uint32_t DS_CFG; + __IO uint32_t SR_CFG; +} GPIO_Module; + +/** + * @brief Alternate Function I/O + */ + +typedef struct +{ + __IO uint32_t ECTRL; + __IO uint32_t RMP_CFG; + __IO uint32_t EXTI_CFG[4]; + uint32_t RESERVED0; + uint32_t RESERVED1; + __IO uint32_t RMP_CFG3; + __IO uint32_t RMP_CFG4; + __IO uint32_t RMP_CFG5; +} AFIO_Module; +/** + * @brief Inter Integrated Circuit Interface + */ + +typedef struct +{ + __IO uint16_t CTRL1; + uint16_t RESERVED0; + __IO uint16_t CTRL2; + uint16_t RESERVED1; + __IO uint16_t OADDR1; + uint16_t RESERVED2; + __IO uint16_t OADDR2; + uint16_t RESERVED3; + __IO uint16_t DAT; + uint16_t RESERVED4; + __IO uint16_t STS1; + uint16_t RESERVED5; + __IO uint16_t STS2; + uint16_t RESERVED6; + __IO uint16_t CLKCTRL; + uint16_t RESERVED7; + __IO uint16_t TMRISE; + uint16_t RESERVED8; +} I2C_Module; + +/** + * @brief Independent WATCHDOG + */ + +typedef struct +{ + __IO uint32_t KEY; + __IO uint32_t PREDIV; /*!< IWDG PREDIV */ + __IO uint32_t RELV; + __IO uint32_t STS; +} IWDG_Module; + +/** + * @brief Power Control + */ + +typedef struct +{ + __IO uint32_t CTRL; + __IO uint32_t CTRLSTS; + __IO uint32_t CTRL2; + __IO uint32_t CTRL3; +} PWR_Module; + +/** + * @brief Reset and Clock Control + */ + +typedef struct +{ + __IO uint32_t CTRL; + __IO uint32_t CFG; + __IO uint32_t CLKINT; + __IO uint32_t APB2PRST; + __IO uint32_t APB1PRST; + __IO uint32_t AHBPCLKEN; + __IO uint32_t APB2PCLKEN; + __IO uint32_t APB1PCLKEN; + __IO uint32_t BDCTRL; + __IO uint32_t CTRLSTS; + + __IO uint32_t AHBPRST; + __IO uint32_t CFG2; + __IO uint32_t CFG3; +} RCC_Module; + +/** + * @brief Real-Time Clock + */ + +typedef struct +{ + __IO uint32_t TSH; /*!< RTC time register, Address offset: 0x00 */ + __IO uint32_t DATE; /*!< RTC date register, Address offset: 0x04 */ + __IO uint32_t CTRL; /*!< RTC control register, Address offset: 0x08 */ + __IO uint32_t INITSTS; /*!< RTC initialization and status register, Address offset: 0x0C */ + __IO uint32_t PRE; /*!< RTC prescaler register, Address offset: 0x10 */ + __IO uint32_t WKUPT; /*!< RTC wakeup timer register, Address offset: 0x14 */ + uint32_t reserved0; /*!< Reserved */ + __IO uint32_t ALARMA; /*!< RTC alarm A register, Address offset: 0x1C */ + __IO uint32_t ALARMB; /*!< RTC alarm B register, Address offset: 0x20 */ + __IO uint32_t WRP; /*!< RTC write protection register, Address offset: 0x24 */ + __IO uint32_t SUBS; /*!< RTC sub second register, Address offset: 0x28 */ + __IO uint32_t SCTRL; /*!< RTC shift control register, Address offset: 0x2C */ + __IO uint32_t TST; /*!< RTC time stamp time register, Address offset: 0x30 */ + __IO uint32_t TSD; /*!< RTC time stamp date register, Address offset: 0x34 */ + __IO uint32_t TSSS; /*!< RTC time-stamp sub second register, Address offset: 0x38 */ + __IO uint32_t CALIB; /*!< RTC calibration register, Address offset: 0x3C */ + uint32_t reserved6; /*!< RTC tamper configuration register, Address offset: 0x40 */ + __IO uint32_t ALRMASS; /*!< RTC alarm A sub second register, Address offset: 0x44 */ + __IO uint32_t ALRMBSS; /*!< RTC alarm B sub second register, Address offset: 0x48 */ + __IO uint32_t OPT; /*!< RTC option register, Address offset: 0x4C */ + uint32_t reserved1; /*!< Reserved Address offset: 0x50 */ + uint32_t reserved2; /*!< Reserved Address offset: 0x54 */ + uint32_t reserved3; /*!< Reserved Address offset: 0x58 */ + uint32_t reserved4; /*!< Reserved Address offset: 0x5C */ + uint32_t reserved5; /*!< Reserved Address offset: 0x60 */ + __IO uint32_t TSCWKUPCTRL; /*!< RTC backup register 5, Address offset: 0x64 */ + __IO uint32_t TSCWKUPCNT; /*!< RTC backup register 6, Address offset: 0x68 */ +} RTC_Module; + +/** + * @brief SD host Interface + */ + +typedef struct +{ + __IO uint32_t PWRCTRL; + __IO uint32_t CLKCTRL; + __IO uint32_t CMDARG; + __IO uint32_t CMDCTRL; + __I uint32_t CMDRESP; + __I uint32_t RESPONSE1; + __I uint32_t RESPONSE2; + __I uint32_t RESPONSE3; + __I uint32_t RESPONSE4; + __IO uint32_t DTIMER; + __IO uint32_t DATLEN; + __IO uint32_t DATCTRL; + __I uint32_t DATCOUNT; + __I uint32_t STS; + __IO uint32_t INTCLR; + __IO uint32_t INTEN; + uint32_t RESERVED0[2]; + __I uint32_t FIFOCOUNT; + uint32_t RESERVED1[13]; + __IO uint32_t DATFIFO; +} SDIO_Module; + +/** + * @brief Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint16_t CTRL1; + uint16_t RESERVED0; + __IO uint16_t CTRL2; + uint16_t RESERVED1; + __IO uint16_t STS; + uint16_t RESERVED2; + __IO uint16_t DAT; + uint16_t RESERVED3; + __IO uint16_t CRCPOLY; + uint16_t RESERVED4; + __IO uint16_t CRCRDAT; + uint16_t RESERVED5; + __IO uint16_t CRCTDAT; + uint16_t RESERVED6; + __IO uint16_t I2SCFG; + uint16_t RESERVED7; + __IO uint16_t I2SPREDIV; + uint16_t RESERVED8; +} SPI_Module; + +/** + * @brief TIM + */ + +typedef struct +{ + __IO uint32_t CTRL1; + __IO uint32_t CTRL2; + __IO uint16_t SMCTRL; + uint16_t RESERVED1; + __IO uint16_t DINTEN; + uint16_t RESERVED2; + __IO uint32_t STS; + __IO uint16_t EVTGEN; + uint16_t RESERVED3; + __IO uint16_t CCMOD1; + uint16_t RESERVED4; + __IO uint16_t CCMOD2; + uint16_t RESERVED5; + __IO uint32_t CCEN; + __IO uint16_t CNT; + uint16_t RESERVED6; + __IO uint16_t PSC; + uint16_t RESERVED7; + __IO uint16_t AR; + uint16_t RESERVED8; + __IO uint16_t REPCNT; + uint16_t RESERVED9; + __IO uint16_t CCDAT1; + uint16_t RESERVED10; + __IO uint16_t CCDAT2; + uint16_t RESERVED11; + __IO uint16_t CCDAT3; + uint16_t RESERVED12; + __IO uint16_t CCDAT4; + uint16_t RESERVED13; + __IO uint16_t BKDT; + uint16_t RESERVED14; + __IO uint16_t DCTRL; + uint16_t RESERVED15; + __IO uint16_t DADDR; + uint16_t RESERVED16; + uint32_t RESERVED17; + __IO uint16_t CCMOD3; + uint16_t RESERVED18; + __IO uint16_t CCDAT5; + uint16_t RESERVED19; + __IO uint16_t CCDAT6; + uint16_t RESERVED20; +} TIM_Module; + +/** + * @brief Universal Synchronous Asynchronous Receiver Transmitter + */ + +typedef struct +{ + __IO uint16_t STS; + uint16_t RESERVED0; + __IO uint16_t DAT; + uint16_t RESERVED1; + __IO uint16_t BRCF; + uint16_t RESERVED2; + __IO uint16_t CTRL1; + uint16_t RESERVED3; + __IO uint16_t CTRL2; + uint16_t RESERVED4; + __IO uint16_t CTRL3; + uint16_t RESERVED5; + __IO uint16_t GTP; + uint16_t RESERVED6; +} USART_Module; + +/** + * @brief Window WATCHDOG + */ + +typedef struct +{ + __IO uint32_t CTRL; + __IO uint32_t CFG; + __IO uint32_t STS; +} WWDG_Module; + +/** + * @brief QSPI + */ +typedef struct +{ + __IO uint32_t CTRL0; + __IO uint32_t CTRL1; + __IO uint32_t EN; + __IO uint32_t MW_CTRL; + __IO uint32_t SLAVE_EN; + __IO uint32_t BAUD; + __IO uint32_t TXFT; + __IO uint32_t RXFT; + __IO uint32_t TXFN; + __IO uint32_t RXFN; + __IO uint32_t STS; + __IO uint32_t IMASK; + __IO uint32_t ISTS; + __IO uint32_t RISTS; + __IO uint32_t TXFOI_CLR; + __IO uint32_t RXFOI_CLR; + __IO uint32_t RXFUI_CLR; + __IO uint32_t MMC_CLR; + __IO uint32_t ICLR; + __IO uint32_t DMA_CTRL; + __IO uint32_t DMATDL_CTRL; + __IO uint32_t DMARDL_CTRL; + __IO uint32_t RESERVED0; + __IO uint32_t RESERVED1; + __IO uint32_t DAT0; + __IO uint32_t DAT1; + __IO uint32_t DAT2; + __IO uint32_t DAT3; + __IO uint32_t DAT4; + __IO uint32_t DAT5; + __IO uint32_t DAT6; + __IO uint32_t DAT7; + __IO uint32_t DAT8; + __IO uint32_t DAT9; + __IO uint32_t DAT10; + __IO uint32_t DAT11; + __IO uint32_t DAT12; + __IO uint32_t DAT13; + __IO uint32_t DAT14; + __IO uint32_t DAT15; + __IO uint32_t DAT16; + __IO uint32_t DAT17; + __IO uint32_t DAT18; + __IO uint32_t DAT19; + __IO uint32_t DAT20; + __IO uint32_t DAT21; + __IO uint32_t DAT22; + __IO uint32_t DAT23; + __IO uint32_t DAT24; + __IO uint32_t DAT25; + __IO uint32_t DAT26; + __IO uint32_t DAT27; + __IO uint32_t DAT28; + __IO uint32_t DAT29; + __IO uint32_t DAT30; + __IO uint32_t DAT31; + __IO uint32_t RESERVED2; /*DAT32-DAT35 is reserved*/ + __IO uint32_t RESERVED3; /*DAT32-DAT35 is reserved*/ + __IO uint32_t RESERVED4; /*DAT32-DAT35 is reserved*/ + __IO uint32_t RESERVED5; /*DAT32-DAT35 is reserved*/ + __IO uint32_t RS_DELAY; + __IO uint32_t ENH_CTRL0; + __IO uint32_t DDR_TXDE; + __IO uint32_t XIP_MODE; + __IO uint32_t XIP_INCR_TOC; + __IO uint32_t XIP_WRAP_TOC; + __IO uint32_t XIP_CTRL; + __IO uint32_t XIP_SLAVE_EN; + __IO uint32_t XIP_RXFOI_CLR; + __IO uint32_t XIP_TOUT; + +} QSPI_Module; + +/** + * @brief Touch Sensor Controller + */ +typedef struct +{ + __IO uint32_t CTRL; + __IO uint32_t CHNEN; + __IO uint32_t STS; + __IO uint32_t RESERVED; + __IO uint32_t ANA_CTRL; + __IO uint32_t ANA_SEL; + __IO uint32_t RESR0; + __IO uint32_t RESR1; + __IO uint32_t RESR2; + __IO uint32_t THRHD0; + __IO uint32_t THRHD1; + __IO uint32_t THRHD2; + __IO uint32_t THRHD3; + __IO uint32_t THRHD4; + __IO uint32_t THRHD5; + __IO uint32_t THRHD6; + __IO uint32_t THRHD7; + __IO uint32_t THRHD8; + __IO uint32_t THRHD9; + __IO uint32_t THRHD10; + __IO uint32_t THRHD11; + __IO uint32_t THRHD12; + __IO uint32_t THRHD13; + __IO uint32_t THRHD14; + __IO uint32_t THRHD15; + __IO uint32_t THRHD16; + __IO uint32_t THRHD17; + __IO uint32_t THRHD18; + __IO uint32_t THRHD19; + __IO uint32_t THRHD20; + __IO uint32_t THRHD21; + __IO uint32_t THRHD22; + __IO uint32_t THRHD23; +} TSC_Module; + +/** + * @brief DVP + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< DVP control register*/ + __IO uint32_t STS; /*!< DVP status register*/ + __IO uint32_t INTSTS; /*!< DVP interrupt status register*/ + __IO uint32_t INTEN; /*!< DVP interrupt enable register*/ + __IO uint32_t MINTSTS; /*!< DVP interrupt mask status register */ + __IO uint32_t WST; /*!< DVP start register */ + __IO uint32_t WSIZE; /*!< DVP size register */ + __IO uint32_t FIFO; /*!< DVP FIFO register */ +} DVP_Module; + +#define FLASH_BASE ((uint32_t)0x08000000) /*!< FLASH base address in the alias region */ +#define SRAM_BASE ((uint32_t)0x20000000) /*!< SRAM base address in the alias region */ +#define PERIPH_BASE ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */ + +#define SRAM_BB_BASE ((uint32_t)0x22000000) /*!< SRAM base address in the bit-band region */ +#define PERIPH_BB_BASE ((uint32_t)0x42000000) /*!< Peripheral base address in the bit-band region */ + +#define UCID_BASE ((uint32_t)0x1FFFF7C0) /*!< UCID Address : 0x1FFF_F7C0 */ +#define UCID_LENGTH ((uint32_t)0x10) /*!< UCID Length : 16Bytes */ +#define UID_BASE ((uint32_t)0x1FFFF7F0) /*!< UID Address : 0x1FFF_F7F0 */ +#define UID_LENGTH ((uint32_t)0x0C) /*!< UID Length : 12Bytes */ +#define DBGMCU_ID_BASE ((uint32_t)0xE0042000) /*!< DBGMCU_ID Address */ +#define DBGMCU_ID_LENGTH ((uint8_t)0x04) /*!< DBGMCU_ID Length : 4 Bytes */ + +/*!< Peripheral memory map */ +#define APB1PERIPH_BASE (PERIPH_BASE) +#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) +#define AHBPERIPH_BASE (PERIPH_BASE + 0x18000) + +/* APB1 */ +#define TIM2_BASE (APB1PERIPH_BASE + 0x0000) +#define TIM3_BASE (APB1PERIPH_BASE + 0x0400) +#define TIM4_BASE (APB1PERIPH_BASE + 0x0800) +#define TIM5_BASE (APB1PERIPH_BASE + 0x0C00) +#define TIM6_BASE (APB1PERIPH_BASE + 0x1000) +#define TIM7_BASE (APB1PERIPH_BASE + 0x1400) +#define AFEC_BASE (APB1PERIPH_BASE + 0x1800) +#define RTC_BASE (APB1PERIPH_BASE + 0x2800) +#define WWDG_BASE (APB1PERIPH_BASE + 0x2C00) +#define IWDG_BASE (APB1PERIPH_BASE + 0x3000) +#define TSC_BASE (APB1PERIPH_BASE + 0x3400) +#define SPI2_BASE (APB1PERIPH_BASE + 0x3800) +#define SPI3_BASE (APB1PERIPH_BASE + 0x3C00) +#define USART2_BASE (APB1PERIPH_BASE + 0x4400) +#define USART3_BASE (APB1PERIPH_BASE + 0x4800) +#define UART4_BASE (APB1PERIPH_BASE + 0x4C00) +#define UART5_BASE (APB1PERIPH_BASE + 0x5000) +#define I2C1_BASE (APB1PERIPH_BASE + 0x5400) +#define I2C2_BASE (APB1PERIPH_BASE + 0x5800) +#define USB_BASE (APB1PERIPH_BASE + 0x5C00) +#define USB_CAN1_SRAM_BASE (APB1PERIPH_BASE + 0x6000) +#define CAN1_BASE (APB1PERIPH_BASE + 0x6400) +#define CAN2_BASE (APB1PERIPH_BASE + 0x6800) +#define BKP_BASE (APB1PERIPH_BASE + 0x6C00) +#define PWR_BASE (APB1PERIPH_BASE + 0x7000) +#define DAC_BASE (APB1PERIPH_BASE + 0x7400) + +/* APB2 */ +#define AFIO_BASE (APB2PERIPH_BASE + 0x0000) +#define EXTI_BASE (APB2PERIPH_BASE + 0x0400) +#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) +#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00) +#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000) +#define GPIOD_BASE (APB2PERIPH_BASE + 0x1400) +#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800) +#define TIM1_BASE (APB2PERIPH_BASE + 0x2C00) +#define SPI1_BASE (APB2PERIPH_BASE + 0x3000) +#define TIM8_BASE (APB2PERIPH_BASE + 0x3400) +#define USART1_BASE (APB2PERIPH_BASE + 0x3800) +#define I2C3_BASE (APB2PERIPH_BASE + 0x4400) +#define I2C4_BASE (APB2PERIPH_BASE + 0x4800) +#define DVP_BASE (APB2PERIPH_BASE + 0x4C00) +#define UART6_BASE (APB2PERIPH_BASE + 0x5000) +#define UART7_BASE (APB2PERIPH_BASE + 0x5400) + +/* AHB */ +#define SDIO_BASE (AHBPERIPH_BASE + 0x0000) +#define DMA1_BASE (AHBPERIPH_BASE + 0x8000) +#define DMA1_CH1_BASE (AHBPERIPH_BASE + 0x8008) +#define DMA1_CH2_BASE (AHBPERIPH_BASE + 0x801C) +#define DMA1_CH3_BASE (AHBPERIPH_BASE + 0x8030) +#define DMA1_CH4_BASE (AHBPERIPH_BASE + 0x8044) +#define DMA1_CH5_BASE (AHBPERIPH_BASE + 0x8058) +#define DMA1_CH6_BASE (AHBPERIPH_BASE + 0x806C) +#define DMA1_CH7_BASE (AHBPERIPH_BASE + 0x8080) +#define DMA1_CH8_BASE (AHBPERIPH_BASE + 0x8094) +#define DMA2_BASE (AHBPERIPH_BASE + 0x8400) +#define DMA2_CH1_BASE (AHBPERIPH_BASE + 0x8408) +#define DMA2_CH2_BASE (AHBPERIPH_BASE + 0x841C) +#define DMA2_CH3_BASE (AHBPERIPH_BASE + 0x8430) +#define DMA2_CH4_BASE (AHBPERIPH_BASE + 0x8444) +#define DMA2_CH5_BASE (AHBPERIPH_BASE + 0x8458) +#define DMA2_CH6_BASE (AHBPERIPH_BASE + 0x846C) +#define DMA2_CH7_BASE (AHBPERIPH_BASE + 0x8480) +#define DMA2_CH8_BASE (AHBPERIPH_BASE + 0x8494) +#define ADC1_BASE (AHBPERIPH_BASE + 0x8800) +#define ADC2_BASE (AHBPERIPH_BASE + 0x8C00) +#define RCC_BASE (AHBPERIPH_BASE + 0x9000) +#define FLASH_R_BASE (AHBPERIPH_BASE + 0xA000) /*!< Flash registers base address */ +#define OB_BASE ((uint32_t)0x1FFFF800) /*!< Flash Option Bytes base address */ +#define CRC_BASE (AHBPERIPH_BASE + 0xB000) +#define SAC_BASE (AHBPERIPH_BASE + 0xC000) +#define SAC_SRAM_BASE (AHBPERIPH_BASE + 0xC400) +#define MMU_BASE (AHBPERIPH_BASE + 0xCC00) + +#define QSPI_BASE (((uint32_t)0xA0001000)) + +#define DBG_BASE ((uint32_t)0xE0042000) /*!< Debug MCU registers base address */ + +#define TIM2 ((TIM_Module*)TIM2_BASE) +#define TIM3 ((TIM_Module*)TIM3_BASE) +#define TIM4 ((TIM_Module*)TIM4_BASE) +#define TIM5 ((TIM_Module*)TIM5_BASE) +#define TIM6 ((TIM_Module*)TIM6_BASE) +#define TIM7 ((TIM_Module*)TIM7_BASE) +#define AFEC ((AFEC_Module*)AFEC_BASE) +#define RTC ((RTC_Module*)RTC_BASE) +#define WWDG ((WWDG_Module*)WWDG_BASE) +#define IWDG ((IWDG_Module*)IWDG_BASE) +#define TSC ((TSC_Module*)TSC_BASE) +#define SPI2 ((SPI_Module*)SPI2_BASE) +#define SPI3 ((SPI_Module*)SPI3_BASE) +#define USART2 ((USART_Module*)USART2_BASE) +#define USART3 ((USART_Module*)USART3_BASE) +#define UART4 ((USART_Module*)UART4_BASE) +#define UART5 ((USART_Module*)UART5_BASE) +#define I2C1 ((I2C_Module*)I2C1_BASE) +#define I2C2 ((I2C_Module*)I2C2_BASE) +#define USB ((USB_Module*)USB_BASE) +#define CAN1 ((CAN_Module*)CAN1_BASE) +#define CAN2 ((CAN_Module*)CAN2_BASE) +#define BKP ((BKP_Module*)BKP_BASE) +#define PWR ((PWR_Module*)PWR_BASE) +#define DAC ((DAC_Module*)DAC_BASE) +#define AFIO ((AFIO_Module*)AFIO_BASE) +#define EXTI ((EXTI_Module*)EXTI_BASE) +#define GPIOA ((GPIO_Module*)GPIOA_BASE) +#define GPIOB ((GPIO_Module*)GPIOB_BASE) +#define GPIOC ((GPIO_Module*)GPIOC_BASE) +#define GPIOD ((GPIO_Module*)GPIOD_BASE) +#define GPIOE ((GPIO_Module*)GPIOE_BASE) +#define TIM1 ((TIM_Module*)TIM1_BASE) +#define SPI1 ((SPI_Module*)SPI1_BASE) +#define TIM8 ((TIM_Module*)TIM8_BASE) +#define USART1 ((USART_Module*)USART1_BASE) +#define I2C3 ((I2C_Module*)I2C3_BASE) +#define I2C4 ((I2C_Module*)I2C4_BASE) +#define DVP ((DVP_Module*)DVP_BASE) +#define UART6 ((USART_Module*)UART6_BASE) +#define UART7 ((USART_Module*)UART7_BASE) +#define SDIO ((SDIO_Module*)SDIO_BASE) +#define DMA1 ((DMA_Module*)DMA1_BASE) +#define DMA2 ((DMA_Module*)DMA2_BASE) +#define DMA1_CH1 ((DMA_ChannelType*)DMA1_CH1_BASE) +#define DMA1_CH2 ((DMA_ChannelType*)DMA1_CH2_BASE) +#define DMA1_CH3 ((DMA_ChannelType*)DMA1_CH3_BASE) +#define DMA1_CH4 ((DMA_ChannelType*)DMA1_CH4_BASE) +#define DMA1_CH5 ((DMA_ChannelType*)DMA1_CH5_BASE) +#define DMA1_CH6 ((DMA_ChannelType*)DMA1_CH6_BASE) +#define DMA1_CH7 ((DMA_ChannelType*)DMA1_CH7_BASE) +#define DMA1_CH8 ((DMA_ChannelType*)DMA1_CH8_BASE) +#define DMA2_CH1 ((DMA_ChannelType*)DMA2_CH1_BASE) +#define DMA2_CH2 ((DMA_ChannelType*)DMA2_CH2_BASE) +#define DMA2_CH3 ((DMA_ChannelType*)DMA2_CH3_BASE) +#define DMA2_CH4 ((DMA_ChannelType*)DMA2_CH4_BASE) +#define DMA2_CH5 ((DMA_ChannelType*)DMA2_CH5_BASE) +#define DMA2_CH6 ((DMA_ChannelType*)DMA2_CH6_BASE) +#define DMA2_CH7 ((DMA_ChannelType*)DMA2_CH7_BASE) +#define DMA2_CH8 ((DMA_ChannelType*)DMA2_CH8_BASE) +#define ADC1 ((ADC_Module*)ADC1_BASE) +#define ADC2 ((ADC_Module*)ADC2_BASE) +#define RCC ((RCC_Module*)RCC_BASE) +#define FLASH ((FLASH_Module*)FLASH_R_BASE) +#define OB ((OB_Module*)OB_BASE) +#define CRC ((CRC_Module*)CRC_BASE) + +#define QSPI ((QSPI_Module*)QSPI_BASE) + +#define DBG ((DBG_Module*)DBG_BASE) + +/******************************************************************************/ +/* Peripheral Registers_Bits_Definition */ +/******************************************************************************/ + +/******************************************************************************/ +/* */ +/* CRC calculation unit */ +/* */ +/******************************************************************************/ + +/******************* Bit definition for CRC_CRC32DAT register *********************/ +#define CRC32_DAT_DAT ((uint32_t)0xFFFFFFFF) /*!< Data register bits */ + +/******************* Bit definition for CRC_CRC32IDAT register ********************/ +#define CRC32_IDAT_IDAT ((uint8_t)0xFF) /*!< General-purpose 8-bit data register bits */ + +/******************** Bit definition for CRC_CRC32CTRL register ********************/ +#define CRC32_CTRL_RESET ((uint8_t)0x01) /*!< RESET bit */ + +/******************** Bit definition for CRC16_CR register ********************/ +#define CRC16_CTRL_LITTLE ((uint8_t)0x02) +#define CRC16_CTRL_BIG ((uint8_t)0xFD) + +#define CRC16_CTRL_RESET ((uint8_t)0x04) +#define CRC16_CTRL_NO_RESET ((uint8_t)0xFB) + +/******************************************************************************/ +/* */ +/* Power Control */ +/* */ +/******************************************************************************/ + +/******************** Bit definition for PWR_CTRL register ********************/ +#define PWR_CTRL_LPS ((uint16_t)0x0001) /*!< Low-Power Deepsleep */ +#define PWR_CTRL_PDS ((uint16_t)0x0002) /*!< Power Down Deepsleep */ +#define PWR_CTRL_CWKUP ((uint16_t)0x0004) /*!< Clear Wakeup Flag */ +#define PWR_CTRL_CSBVBAT ((uint16_t)0x0008) /*!< Clear Standby Flag */ +#define PWR_CTRL_PVDEN ((uint16_t)0x0010) /*!< Power Voltage Detector Enable */ + +#define PWR_CTRL_PRS ((uint16_t)0x00E0) /*!< PRS[2:0] bits (PVD Level Selection) */ +#define PWR_CTRL_PRS_0 ((uint16_t)0x0020) /*!< Bit 0 */ +#define PWR_CTRL_PRS_1 ((uint16_t)0x0040) /*!< Bit 1 */ +#define PWR_CTRL_PRS_2 ((uint16_t)0x0080) /*!< Bit 2 */ + +/*!< PVD level configuration */ +#define PWR_CTRL_PRS_2V2 ((uint16_t)0x0000) /*!< PVD level 2.2V */ +#define PWR_CTRL_PRS_2V3 ((uint16_t)0x0020) /*!< PVD level 2.3V */ +#define PWR_CTRL_PRS_2V4 ((uint16_t)0x0040) /*!< PVD level 2.4V */ +#define PWR_CTRL_PRS_2V5 ((uint16_t)0x0060) /*!< PVD level 2.5V */ +#define PWR_CTRL_PRS_2V6 ((uint16_t)0x0080) /*!< PVD level 2.6V */ +#define PWR_CTRL_PRS_2V7 ((uint16_t)0x00A0) /*!< PVD level 2.7V */ +#define PWR_CTRL_PRS_2V8 ((uint16_t)0x00C0) /*!< PVD level 2.8V */ +#define PWR_CTRL_PRS_2V9 ((uint16_t)0x00E0) /*!< PVD level 2.9V */ + +#define PWR_CTRL_DBKP ((uint16_t)0x0100) /*!< Disable Backup Domain write protection */ +#define PWR_CTRL_MSB ((uint16_t)0x0200) /*!< Bit 9 */ + +/******************* Bit definition for PWR_CTRLSTS register ********************/ +#define PWR_CTRLSTS_WKUPF ((uint16_t)0x0001) /*!< Wakeup Flag */ +#define PWR_CTRLSTS_SBF ((uint16_t)0x0002) /*!< Standby Flag */ +#define PWR_CTRLSTS_PVDO ((uint16_t)0x0004) /*!< PVD Output */ +#define PWR_CTRLSTS_VBATF ((uint16_t)0x0008) /*!< VBAT Flag */ +#define PWR_CTRLSTS_WKUPEN ((uint16_t)0x0100) /*!< Enable WKUP pin */ + +/******************* Bit definition for PWR_CTRL2 register ********************/ +#define PWR_CTRL2_STOP2S ((uint16_t)0x0001) /*!< Enable STOP2 */ +#define PWR_CTRL2_SR2VBRET ((uint16_t)0x0002) /*!< VBAT mode SRAM2 retention */ +#define PWR_CTRL2_SR2STBRET ((uint16_t)0x0004) /*!< Standby mode SRAM2 retention */ +#define PWR_CTRL2_TMPWPEN ((uint16_t)0x0008) /*!< Enable Tamper WakeUp */ +#define PWR_CTRL2_LSITRIM ((uint16_t)0x01F0) /*!< config the LSI trimming value */ +#define PWR_CTRL2_IWDGWPEN ((uint16_t)0x0200) /*!< Enable IWDG WakeUp */ +#define PWR_CTRL2_IWDGRSTEN ((uint16_t)0x0400) /*!< Enable IWDG RST WakeUp */ + +/******************* Bit definition for PWR_CTRL3 register ********************/ +#define PWR_CTRL3_EXMODE ((uint16_t)0x0001) /*!< BKPM Mode */ +#define PWR_CTRL3_EXMODE_EXTEND ((uint16_t)0x0001) /*!< EXTEND Mode */ +#define PWR_CTRL3_EXMODE_NORMAL ((uint16_t)0x0000) /*!< NORMAL Mode */ + + +/******************************************************************************/ +/* */ +/* Backup registers */ +/* */ +/******************************************************************************/ + +/******************* Bit definition for BKP_DAT1 register ********************/ +#define BKP_DAT1_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT2 register ********************/ +#define BKP_DAT2_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT3 register ********************/ +#define BKP_DAT3_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT4 register ********************/ +#define BKP_DAT4_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT5 register ********************/ +#define BKP_DAT5_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT6 register ********************/ +#define BKP_DAT6_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT7 register ********************/ +#define BKP_DAT7_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT8 register ********************/ +#define BKP_DAT8_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT9 register ********************/ +#define BKP_DAT9_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT10 register *******************/ +#define BKP_DAT10_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT11 register *******************/ +#define BKP_DAT11_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT12 register *******************/ +#define BKP_DAT12_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT13 register *******************/ +#define BKP_DAT13_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT14 register *******************/ +#define BKP_DAT14_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT15 register *******************/ +#define BKP_DAT15_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT16 register *******************/ +#define BKP_DAT16_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT17 register *******************/ +#define BKP_DAT17_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/****************** Bit definition for BKP_DAT18 register ********************/ +#define BKP_DAT18_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT19 register *******************/ +#define BKP_DAT19_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT20 register *******************/ +#define BKP_DAT20_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT21 register *******************/ +#define BKP_DAT21_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT22 register *******************/ +#define BKP_DAT22_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT23 register *******************/ +#define BKP_DAT23_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT24 register *******************/ +#define BKP_DAT24_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT25 register *******************/ +#define BKP_DAT25_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT26 register *******************/ +#define BKP_DAT26_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT27 register *******************/ +#define BKP_DAT27_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT28 register *******************/ +#define BKP_DAT28_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT29 register *******************/ +#define BKP_DAT29_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT30 register *******************/ +#define BKP_DAT30_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT31 register *******************/ +#define BKP_DAT31_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT32 register *******************/ +#define BKP_DAT32_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT33 register *******************/ +#define BKP_DAT33_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT34 register *******************/ +#define BKP_DAT34_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT35 register *******************/ +#define BKP_DAT35_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT36 register *******************/ +#define BKP_DAT36_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT37 register *******************/ +#define BKP_DAT37_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT38 register *******************/ +#define BKP_DAT38_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT39 register *******************/ +#define BKP_DAT39_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT40 register *******************/ +#define BKP_DAT40_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT41 register *******************/ +#define BKP_DAT41_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DAT42 register *******************/ +#define BKP_DAT42_DAT ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************** Bit definition for BKP_CTRL register ********************/ +#define BKP_CTRL_TP_EN ((uint8_t)0x01) /*!< TAMPER pin enable */ +#define BKP_CTRL_TP_ALEV ((uint8_t)0x02) /*!< TAMPER pin active level */ + +/******************* Bit definition for BKP_CTRLSTS register ********************/ +#define BKP_CTRLSTS_CLRTE ((uint16_t)0x0001) /*!< Clear Tamper event */ +#define BKP_CTRLSTS_CLRTINT ((uint16_t)0x0002) /*!< Clear Tamper Interrupt */ +#define BKP_CTRLSTS_TPINT_EN ((uint16_t)0x0004) /*!< TAMPER Pin interrupt enable */ +#define BKP_CTRLSTS_TEF ((uint16_t)0x0100) /*!< Tamper Event Flag */ +#define BKP_CTRLSTS_TINTF ((uint16_t)0x0200) /*!< Tamper Interrupt Flag */ + +/******************************************************************************/ +/* */ +/* Reset and Clock Control */ +/* */ +/******************************************************************************/ + +/******************** Bit definition for RCC_CTRL register ********************/ +#define RCC_CTRL_HSIEN ((uint32_t)0x00000001) /*!< Internal High Speed clock enable */ +#define RCC_CTRL_HSIRDF ((uint32_t)0x00000002) /*!< Internal High Speed clock ready flag */ +#define RCC_CTRL_HSITRIM ((uint32_t)0x000000F8) /*!< Internal High Speed clock trimming */ +#define RCC_CTRL_HSICAL ((uint32_t)0x0000FF00) /*!< Internal High Speed clock Calibration */ +#define RCC_CTRL_HSEEN ((uint32_t)0x00010000) /*!< External High Speed clock enable */ +#define RCC_CTRL_HSERDF ((uint32_t)0x00020000) /*!< External High Speed clock ready flag */ +#define RCC_CTRL_HSEBP ((uint32_t)0x00040000) /*!< External High Speed clock Bypass */ +#define RCC_CTRL_CLKSSEN ((uint32_t)0x00080000) /*!< Clock Security System enable */ +#define RCC_CTRL_PLLEN ((uint32_t)0x01000000) /*!< PLL enable */ +#define RCC_CTRL_PLLRDF ((uint32_t)0x02000000) /*!< PLL clock ready flag */ + +/******************* Bit definition for RCC_CFG register *******************/ +/*!< SW configuration */ +#define RCC_CFG_SCLKSW ((uint32_t)0x00000003) /*!< SW[1:0] bits (System clock Switch) */ +#define RCC_CFG_SCLKSW_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define RCC_CFG_SCLKSW_1 ((uint32_t)0x00000002) /*!< Bit 1 */ + +#define RCC_CFG_SCLKSW_HSI ((uint32_t)0x00000000) /*!< HSI selected as system clock */ +#define RCC_CFG_SCLKSW_HSE ((uint32_t)0x00000001) /*!< HSE selected as system clock */ +#define RCC_CFG_SCLKSW_PLL ((uint32_t)0x00000002) /*!< PLL selected as system clock */ + +/*!< SWS configuration */ +#define RCC_CFG_SCLKSTS ((uint32_t)0x0000000C) /*!< SWS[1:0] bits (System Clock Switch Status) */ +#define RCC_CFG_SCLKSTS_0 ((uint32_t)0x00000004) /*!< Bit 0 */ +#define RCC_CFG_SCLKSTS_1 ((uint32_t)0x00000008) /*!< Bit 1 */ + +#define RCC_CFG_SCLKSTS_HSI ((uint32_t)0x00000000) /*!< HSI oscillator used as system clock */ +#define RCC_CFG_SCLKSTS_HSE ((uint32_t)0x00000004) /*!< HSE oscillator used as system clock */ +#define RCC_CFG_SCLKSTS_PLL ((uint32_t)0x00000008) /*!< PLL used as system clock */ + +/*!< HPRE configuration */ +#define RCC_CFG_AHBPRES ((uint32_t)0x000000F0) /*!< HPRE[3:0] bits (AHB prescaler) */ +#define RCC_CFG_AHBPRES_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define RCC_CFG_AHBPRES_1 ((uint32_t)0x00000020) /*!< Bit 1 */ +#define RCC_CFG_AHBPRES_2 ((uint32_t)0x00000040) /*!< Bit 2 */ +#define RCC_CFG_AHBPRES_3 ((uint32_t)0x00000080) /*!< Bit 3 */ + +#define RCC_CFG_AHBPRES_DIV1 ((uint32_t)0x00000000) /*!< SYSCLK not divided */ +#define RCC_CFG_AHBPRES_DIV2 ((uint32_t)0x00000080) /*!< SYSCLK divided by 2 */ +#define RCC_CFG_AHBPRES_DIV4 ((uint32_t)0x00000090) /*!< SYSCLK divided by 4 */ +#define RCC_CFG_AHBPRES_DIV8 ((uint32_t)0x000000A0) /*!< SYSCLK divided by 8 */ +#define RCC_CFG_AHBPRES_DIV16 ((uint32_t)0x000000B0) /*!< SYSCLK divided by 16 */ +#define RCC_CFG_AHBPRES_DIV64 ((uint32_t)0x000000C0) /*!< SYSCLK divided by 64 */ +#define RCC_CFG_AHBPRES_DIV128 ((uint32_t)0x000000D0) /*!< SYSCLK divided by 128 */ +#define RCC_CFG_AHBPRES_DIV256 ((uint32_t)0x000000E0) /*!< SYSCLK divided by 256 */ +#define RCC_CFG_AHBPRES_DIV512 ((uint32_t)0x000000F0) /*!< SYSCLK divided by 512 */ + +/*!< PPRE1 configuration */ +#define RCC_CFG_APB1PRES ((uint32_t)0x00000700) /*!< PRE1[2:0] bits (APB1 prescaler) */ +#define RCC_CFG_APB1PRES_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define RCC_CFG_APB1PRES_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define RCC_CFG_APB1PRES_2 ((uint32_t)0x00000400) /*!< Bit 2 */ + +#define RCC_CFG_APB1PRES_DIV1 ((uint32_t)0x00000000) /*!< HCLK not divided */ +#define RCC_CFG_APB1PRES_DIV2 ((uint32_t)0x00000400) /*!< HCLK divided by 2 */ +#define RCC_CFG_APB1PRES_DIV4 ((uint32_t)0x00000500) /*!< HCLK divided by 4 */ +#define RCC_CFG_APB1PRES_DIV8 ((uint32_t)0x00000600) /*!< HCLK divided by 8 */ +#define RCC_CFG_APB1PRES_DIV16 ((uint32_t)0x00000700) /*!< HCLK divided by 16 */ + +/*!< PPRE2 configuration */ +#define RCC_CFG_APB2PRES ((uint32_t)0x00003800) /*!< PRE2[2:0] bits (APB2 prescaler) */ +#define RCC_CFG_APB2PRES_0 ((uint32_t)0x00000800) /*!< Bit 0 */ +#define RCC_CFG_APB2PRES_1 ((uint32_t)0x00001000) /*!< Bit 1 */ +#define RCC_CFG_APB2PRES_2 ((uint32_t)0x00002000) /*!< Bit 2 */ + +#define RCC_CFG_APB2PRES_DIV1 ((uint32_t)0x00000000) /*!< HCLK not divided */ +#define RCC_CFG_APB2PRES_DIV2 ((uint32_t)0x00002000) /*!< HCLK divided by 2 */ +#define RCC_CFG_APB2PRES_DIV4 ((uint32_t)0x00002800) /*!< HCLK divided by 4 */ +#define RCC_CFG_APB2PRES_DIV8 ((uint32_t)0x00003000) /*!< HCLK divided by 8 */ +#define RCC_CFG_APB2PRES_DIV16 ((uint32_t)0x00003800) /*!< HCLK divided by 16 */ + +/*!< PLLSRC configuration */ +#define RCC_CFG_PLLSRC ((uint32_t)0x00010000) /*!< PLL entry clock source */ + +/*!< PLLXTPRE configuration */ +#define RCC_CFG_PLLHSEPRES ((uint32_t)0x00020000) /*!< HSE divider for PLL entry */ + +/*!< PLLMUL configuration */ +#define RCC_CFG_PLLMULFCT ((uint32_t)0x083C0000) /*!< PLLMUL[4:0] bits (PLL multiplication factor) */ +#define RCC_CFG_PLLMULFCT_0 ((uint32_t)0x00040000) /*!< Bit 0 */ +#define RCC_CFG_PLLMULFCT_1 ((uint32_t)0x00080000) /*!< Bit 1 */ +#define RCC_CFG_PLLMULFCT_2 ((uint32_t)0x00100000) /*!< Bit 2 */ +#define RCC_CFG_PLLMULFCT_3 ((uint32_t)0x00200000) /*!< Bit 3 */ +#define RCC_CFG_PLLMULFCT_4 ((uint32_t)0x08000000) /*!< Bit 4 */ + +#define RCC_CFG_PLLSRC_HSI_DIV2 \ + ((uint32_t)0x00000000) /*!< HSI clock divided by 2 selected as PLL entry clock source \ + */ +#define RCC_CFG_PLLSRC_HSE ((uint32_t)0x00010000) /*!< HSE clock selected as PLL entry clock source */ + +#define RCC_CFG_PLLHSEPRES_HSE ((uint32_t)0x00000000) /*!< HSE clock not divided for PLL entry */ +#define RCC_CFG_PLLHSEPRES_HSE_DIV2 ((uint32_t)0x00020000) /*!< HSE clock divided by 2 for PLL entry */ +#define RCC_CFG_PLLMULFCT2 ((uint32_t)0x00000000) /*!< PLL input clock*2 */ +#define RCC_CFG_PLLMULFCT3 ((uint32_t)0x00040000) /*!< PLL input clock*3 */ +#define RCC_CFG_PLLMULFCT4 ((uint32_t)0x00080000) /*!< PLL input clock*4 */ +#define RCC_CFG_PLLMULFCT5 ((uint32_t)0x000C0000) /*!< PLL input clock*5 */ +#define RCC_CFG_PLLMULFCT6 ((uint32_t)0x00100000) /*!< PLL input clock*6 */ +#define RCC_CFG_PLLMULFCT7 ((uint32_t)0x00140000) /*!< PLL input clock*7 */ +#define RCC_CFG_PLLMULFCT8 ((uint32_t)0x00180000) /*!< PLL input clock*8 */ +#define RCC_CFG_PLLMULFCT9 ((uint32_t)0x001C0000) /*!< PLL input clock*9 */ +#define RCC_CFG_PLLMULFCT10 ((uint32_t)0x00200000) /*!< PLL input clock*10 */ +#define RCC_CFG_PLLMULFCT11 ((uint32_t)0x00240000) /*!< PLL input clock*11 */ +#define RCC_CFG_PLLMULFCT12 ((uint32_t)0x00280000) /*!< PLL input clock*12 */ +#define RCC_CFG_PLLMULFCT13 ((uint32_t)0x002C0000) /*!< PLL input clock*13 */ +#define RCC_CFG_PLLMULFCT14 ((uint32_t)0x00300000) /*!< PLL input clock*14 */ +#define RCC_CFG_PLLMULFCT15 ((uint32_t)0x00340000) /*!< PLL input clock*15 */ +#define RCC_CFG_PLLMULFCT16 ((uint32_t)0x00380000) /*!< PLL input clock*16 */ +#define RCC_CFG_PLLMULFCT16N ((uint32_t)0x003C0000) /*!< PLL input clock*16 */ +#define RCC_CFG_PLLMULFCT17 ((uint32_t)0x08000000) /*!< PLL input clock*17 */ +#define RCC_CFG_PLLMULFCT18 ((uint32_t)0x08040000) /*!< PLL input clock*18 */ +#define RCC_CFG_PLLMULFCT19 ((uint32_t)0x08080000) /*!< PLL input clock*19 */ +#define RCC_CFG_PLLMULFCT20 ((uint32_t)0x080C0000) /*!< PLL input clock*20 */ +#define RCC_CFG_PLLMULFCT21 ((uint32_t)0x08100000) /*!< PLL input clock*21 */ +#define RCC_CFG_PLLMULFCT22 ((uint32_t)0x08140000) /*!< PLL input clock*22 */ +#define RCC_CFG_PLLMULFCT23 ((uint32_t)0x08180000) /*!< PLL input clock*23 */ +#define RCC_CFG_PLLMULFCT24 ((uint32_t)0x081C0000) /*!< PLL input clock*24 */ +#define RCC_CFG_PLLMULFCT25 ((uint32_t)0x08200000) /*!< PLL input clock*25 */ +#define RCC_CFG_PLLMULFCT26 ((uint32_t)0x08240000) /*!< PLL input clock*26 */ +#define RCC_CFG_PLLMULFCT27 ((uint32_t)0x08280000) /*!< PLL input clock*27 */ +#define RCC_CFG_PLLMULFCT28 ((uint32_t)0x082C0000) /*!< PLL input clock*28 */ +#define RCC_CFG_PLLMULFCT29 ((uint32_t)0x08300000) /*!< PLL input clock*29 */ +#define RCC_CFG_PLLMULFCT30 ((uint32_t)0x08340000) /*!< PLL input clock*30 */ +#define RCC_CFG_PLLMULFCT31 ((uint32_t)0x08380000) /*!< PLL input clock*31 */ +#define RCC_CFG_PLLMULFCT32 ((uint32_t)0x083C0000) /*!< PLL input clock*32 */ + +/*!< USBPRES configuration */ +#define RCC_CFG_USBPRES ((uint32_t)0x00C00000) /*!< USB Device prescaler */ +#define RCC_CFG_USBPRES_0 ((uint32_t)0x00400000) /*!< Bit 0 */ +#define RCC_CFG_USBPRES_1 ((uint32_t)0x00800000) /*!< Bit 1 */ + +#define RCC_CFG_USBPRES_PLLDIV1_5 ((uint32_t)0x00000000) /*!< PLL clock is divided by 1.5 */ +#define RCC_CFG_USBPRES_PLLDIV1 ((uint32_t)0x00400000) /*!< PLL clock is not divided */ +#define RCC_CFG_USBPRES_PLLDIV2 ((uint32_t)0x00800000) /*!< PLL clock is divided by 2 */ +#define RCC_CFG_USBPRES_PLLDIV3 ((uint32_t)0x00C00000) /*!< PLL clock is divided by 3 */ + +/*!< MCO configuration */ +#define RCC_CFG_MCO ((uint32_t)0x07000000) /*!< MCO[2:0] bits (Microcontroller Clock Output) */ +#define RCC_CFG_MCO_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define RCC_CFG_MCO_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define RCC_CFG_MCO_2 ((uint32_t)0x04000000) /*!< Bit 2 */ + +#define RCC_CFG_MCO_NOCLK ((uint32_t)0x00000000) /*!< No clock */ +#define RCC_CFG_MCO_SYSCLK ((uint32_t)0x04000000) /*!< System clock selected as MCO source */ +#define RCC_CFG_MCO_HSI ((uint32_t)0x05000000) /*!< HSI clock selected as MCO source */ +#define RCC_CFG_MCO_HSE ((uint32_t)0x06000000) /*!< HSE clock selected as MCO source */ +#define RCC_CFG_MCO_PLL ((uint32_t)0x07000000) /*!< PLL clock divided by 2 selected as MCO source */ + +/*!< MCOPRE configuration */ +#define RCC_CFG_MCOPRES \ + ((uint32_t)0xF0000000) /*!< MCOPRE[3:0] bits ( PLL prescaler set and cleared by software to generate MCOPRE \ + clock.) */ +#define RCC_CFG_MCOPRES_0 ((uint32_t)0x10000000) /*!< Bit 0 */ +#define RCC_CFG_MCOPRES_1 ((uint32_t)0x20000000) /*!< Bit 1 */ +#define RCC_CFG_MCOPRES_2 ((uint32_t)0x40000000) /*!< Bit 2 */ +#define RCC_CFG_MCOPRES_3 ((uint32_t)0x80000000) /*!< Bit 3 */ + +#define RCC_CFG_MCOPRES_PLLDIV2 ((uint32_t)0x20000000) /*!< PLL clock is divided by 2 */ +#define RCC_CFG_MCOPRES_PLLDIV3 ((uint32_t)0x30000000) /*!< PLL clock is divided by 3 */ +#define RCC_CFG_MCOPRES_PLLDIV4 ((uint32_t)0x40000000) /*!< PLL clock is divided by 4 */ +#define RCC_CFG_MCOPRES_PLLDIV5 ((uint32_t)0x50000000) /*!< PLL clock is divided by 5 */ +#define RCC_CFG_MCOPRES_PLLDIV6 ((uint32_t)0x60000000) /*!< PLL clock is divided by 6 */ +#define RCC_CFG_MCOPRES_PLLDIV7 ((uint32_t)0x70000000) /*!< PLL clock is divided by 7 */ +#define RCC_CFG_MCOPRES_PLLDIV8 ((uint32_t)0x80000000) /*!< PLL clock is divided by 8 */ +#define RCC_CFG_MCOPRES_PLLDIV9 ((uint32_t)0x90000000) /*!< PLL clock is divided by 9 */ +#define RCC_CFG_MCOPRES_PLLDIV10 ((uint32_t)0xA0000000) /*!< PLL clock is divided by 10 */ +#define RCC_CFG_MCOPRES_PLLDIV11 ((uint32_t)0xB0000000) /*!< PLL clock is divided by 11 */ +#define RCC_CFG_MCOPRES_PLLDIV12 ((uint32_t)0xC0000000) /*!< PLL clock is divided by 12 */ +#define RCC_CFG_MCOPRES_PLLDIV13 ((uint32_t)0xD0000000) /*!< PLL clock is divided by 13 */ +#define RCC_CFG_MCOPRES_PLLDIV14 ((uint32_t)0xE0000000) /*!< PLL clock is divided by 14 */ +#define RCC_CFG_MCOPRES_PLLDIV15 ((uint32_t)0xF0000000) /*!< PLL clock is divided by 15 */ + +/*!<****************** Bit definition for RCC_CLKINT register ********************/ +#define RCC_CLKINT_LSIRDIF ((uint32_t)0x00000001) /*!< LSI Ready Interrupt flag */ +#define RCC_CLKINT_LSERDIF ((uint32_t)0x00000002) /*!< LSE Ready Interrupt flag */ +#define RCC_CLKINT_HSIRDIF ((uint32_t)0x00000004) /*!< HSI Ready Interrupt flag */ +#define RCC_CLKINT_HSERDIF ((uint32_t)0x00000008) /*!< HSE Ready Interrupt flag */ +#define RCC_CLKINT_PLLRDIF ((uint32_t)0x00000010) /*!< PLL Ready Interrupt flag */ +#define RCC_CLKINT_CLKSSIF ((uint32_t)0x00000080) /*!< Clock Security System Interrupt flag */ +#define RCC_CLKINT_LSIRDIEN ((uint32_t)0x00000100) /*!< LSI Ready Interrupt Enable */ +#define RCC_CLKINT_LSERDIEN ((uint32_t)0x00000200) /*!< LSE Ready Interrupt Enable */ +#define RCC_CLKINT_HSIRDIEN ((uint32_t)0x00000400) /*!< HSI Ready Interrupt Enable */ +#define RCC_CLKINT_HSERDIEN ((uint32_t)0x00000800) /*!< HSE Ready Interrupt Enable */ +#define RCC_CLKINT_PLLRDIEN ((uint32_t)0x00001000) /*!< PLL Ready Interrupt Enable */ +#define RCC_CLKINT_LSIRDICLR ((uint32_t)0x00010000) /*!< LSI Ready Interrupt Clear */ +#define RCC_CLKINT_LSERDICLR ((uint32_t)0x00020000) /*!< LSE Ready Interrupt Clear */ +#define RCC_CLKINT_HSIRDICLR ((uint32_t)0x00040000) /*!< HSI Ready Interrupt Clear */ +#define RCC_CLKINT_HSERDICLR ((uint32_t)0x00080000) /*!< HSE Ready Interrupt Clear */ +#define RCC_CLKINT_PLLRDICLR ((uint32_t)0x00100000) /*!< PLL Ready Interrupt Clear */ +#define RCC_CLKINT_CLKSSICLR ((uint32_t)0x00800000) /*!< Clock Security System Interrupt Clear */ + +/***************** Bit definition for RCC_APB2PRST register *****************/ +#define RCC_APB2PRST_AFIORST ((uint32_t)0x00000001) /*!< Alternate Function I/O reset */ +#define RCC_APB2PRST_IOPARST ((uint32_t)0x00000004) /*!< I/O port A reset */ +#define RCC_APB2PRST_IOPBRST ((uint32_t)0x00000008) /*!< I/O port B reset */ +#define RCC_APB2PRST_IOPCRST ((uint32_t)0x00000010) /*!< I/O port C reset */ +#define RCC_APB2PRST_IOPDRST ((uint32_t)0x00000020) /*!< I/O port D reset */ +#define RCC_APB2PRST_IOPERST ((uint32_t)0x00000040) /*!< I/O port E reset */ +#define RCC_APB2PRST_IOPFRST ((uint32_t)0x00000080) /*!< I/O port F reset */ +#define RCC_APB2PRST_IOPGRST ((uint32_t)0x00000100) /*!< I/O port G reset */ +#define RCC_APB2PRST_TIM1RST ((uint32_t)0x00000800) /*!< TIM1 Timer reset */ +#define RCC_APB2PRST_SPI1RST ((uint32_t)0x00001000) /*!< SPI 1 reset */ +#define RCC_APB2PRST_TIM8RST ((uint32_t)0x00002000) /*!< TIM8 Timer reset */ +#define RCC_APB2PRST_USART1RST ((uint32_t)0x00004000) /*!< USART1 reset */ +#define RCC_APB2PRST_DVPRST ((uint32_t)0x00010000) /*!< DVP reset */ +#define RCC_APB2PRST_UART6RST ((uint32_t)0x00020000) /*!< UART6 reset */ +#define RCC_APB2PRST_UART7RST ((uint32_t)0x00040000) /*!< UART7 reset */ +#define RCC_APB2PRST_I2C3RST ((uint32_t)0x00080000) /*!< I2C3 reset */ +#define RCC_APB2PRST_I2C4RST ((uint32_t)0x00100000) /*!< I2C4 reset */ + +/***************** Bit definition for RCC_APB1PRST register *****************/ +#define RCC_APB1PRST_TIM2RST ((uint32_t)0x00000001) /*!< Timer 2 reset */ +#define RCC_APB1PRST_TIM3RST ((uint32_t)0x00000002) /*!< Timer 3 reset */ +#define RCC_APB1PRST_TIM4RST ((uint32_t)0x00000004) /*!< Timer 4 reset */ +#define RCC_APB1PRST_TIM5RST ((uint32_t)0x00000008) /*!< Timer 5 reset */ +#define RCC_APB1PRST_TIM6RST ((uint32_t)0x00000010) /*!< Timer 6 reset */ +#define RCC_APB1PRST_TIM7RST ((uint32_t)0x00000020) /*!< Timer 7 reset */ +#define RCC_APB1PRST_TSCRST ((uint32_t)0x00000400) /*!< TSC reset */ +#define RCC_APB1PRST_WWDGRST ((uint32_t)0x00000800) /*!< Window Watchdog reset */ +#define RCC_APB1PRST_SPI2RST ((uint32_t)0x00004000) /*!< SPI 2 reset */ +#define RCC_APB1PRST_SPI3RST ((uint32_t)0x00008000) /*!< SPI 3 reset */ +#define RCC_APB1PRST_USART2RST ((uint32_t)0x00020000) /*!< USART 2 reset */ +#define RCC_APB1PRST_USART3RST ((uint32_t)0x00040000) /*!< USART 3 reset */ +#define RCC_APB1PRST_UART4RST ((uint32_t)0x00080000) /*!< UART 4 reset */ +#define RCC_APB1PRST_UART5RST ((uint32_t)0x00100000) /*!< UART 5 reset */ +#define RCC_APB1PRST_I2C1RST ((uint32_t)0x00200000) /*!< I2C 1 reset */ +#define RCC_APB1PRST_I2C2RST ((uint32_t)0x00400000) /*!< I2C 2 reset */ +#define RCC_APB1PRST_USBRST ((uint32_t)0x00800000) /*!< USB Device reset */ +#define RCC_APB1PRST_CAN1RST ((uint32_t)0x02000000) /*!< CAN1 reset */ +#define RCC_APB1PRST_CAN2RST ((uint32_t)0x04000000) /*!< CAN2 reset */ +#define RCC_APB1PRST_BKPRST ((uint32_t)0x08000000) /*!< Backup interface reset */ +#define RCC_APB1PRST_PWRRST ((uint32_t)0x10000000) /*!< Power interface reset */ +#define RCC_APB1PRST_DACRST ((uint32_t)0x20000000) /*!< DAC interface reset */ + +/****************** Bit definition for RCC_AHBPCLKEN register ******************/ +#define RCC_AHBPCLKEN_DMA1EN ((uint32_t)0x00000001) /*!< DMA1 clock enable */ +#define RCC_AHBPCLKEN_DMA2EN ((uint32_t)0x00000002) /*!< DMA2 clock enable */ +#define RCC_AHBPCLKEN_SRAMEN ((uint32_t)0x00000004) /*!< SRAM interface clock enable */ +#define RCC_AHBPCLKEN_FLITFEN ((uint32_t)0x00000010) /*!< FLITF clock enable */ +#define RCC_AHBPCLKEN_CRCEN ((uint32_t)0x00000040) /*!< CRC clock enable */ +#define RCC_AHBPCLKEN_RNGCEN ((uint32_t)0x00000200) /*!< RNGC clock enable */ +#define RCC_AHBPCLKEN_SDIOEN ((uint32_t)0x00000400) /*!< SDIO clock enable */ +#define RCC_AHBPCLKEN_SACEN ((uint32_t)0x00000800) /*!< SAC clock enable */ +#define RCC_AHBPCLKEN_ADC1EN ((uint32_t)0x00001000) /*!< ADC1 clock enable */ +#define RCC_AHBPCLKEN_ADC2EN ((uint32_t)0x00002000) /*!< ADC2 clock enable */ +#define RCC_AHBPCLKEN_ETHMACEN ((uint32_t)0x00010000) /*!< ETHMAC clock enable */ +#define RCC_AHBPCLKEN_QSPIEN ((uint32_t)0x00020000) /*!< QSPI clock enable */ + +/****************** Bit definition for RCC_APB2PCLKEN register *****************/ +#define RCC_APB2PCLKEN_AFIOEN ((uint32_t)0x00000001) /*!< Alternate Function I/O clock enable */ +#define RCC_APB2PCLKEN_IOPAEN ((uint32_t)0x00000004) /*!< I/O port A clock enable */ +#define RCC_APB2PCLKEN_IOPBEN ((uint32_t)0x00000008) /*!< I/O port B clock enable */ +#define RCC_APB2PCLKEN_IOPCEN ((uint32_t)0x00000010) /*!< I/O port C clock enable */ +#define RCC_APB2PCLKEN_IOPDEN ((uint32_t)0x00000020) /*!< I/O port D clock enable */ +#define RCC_APB2PCLKEN_IOPEEN ((uint32_t)0x00000040) /*!< I/O port E clock enable */ +#define RCC_APB2PCLKEN_IOPFEN ((uint32_t)0x00000080) /*!< I/O port F clock enable */ +#define RCC_APB2PCLKEN_IOPGEN ((uint32_t)0x00000100) /*!< I/O port G clock enable */ +#define RCC_APB2PCLKEN_TIM1EN ((uint32_t)0x00000800) /*!< TIM1 Timer clock enable */ +#define RCC_APB2PCLKEN_SPI1EN ((uint32_t)0x00001000) /*!< SPI1 clock enable */ +#define RCC_APB2PCLKEN_TIM8EN ((uint32_t)0x00002000) /*!< TIM8 Timer clock enable */ +#define RCC_APB2PCLKEN_USART1EN ((uint32_t)0x00004000) /*!< USART1 clock enable */ +#define RCC_APB2PCLKEN_DVPEN ((uint32_t)0x00010000) /*!< DVP clock enable */ +#define RCC_APB2PCLKEN_UART6EN ((uint32_t)0x00020000) /*!< UART6 clock enable */ +#define RCC_APB2PCLKEN_UART7EN ((uint32_t)0x00040000) /*!< UART7 clock enable */ +#define RCC_APB2PCLKEN_I2C3EN ((uint32_t)0x00080000) /*!< I2C3 clock enable */ +#define RCC_APB2PCLKEN_I2C4EN ((uint32_t)0x00100000) /*!< I2C4 clock enable */ + +/***************** Bit definition for RCC_APB1PCLKEN register ******************/ +#define RCC_APB1PCLKEN_TIM2EN ((uint32_t)0x00000001) /*!< Timer 2 clock enabled*/ +#define RCC_APB1PCLKEN_TIM3EN ((uint32_t)0x00000002) /*!< Timer 3 clock enable */ +#define RCC_APB1PCLKEN_TIM4EN ((uint32_t)0x00000004) /*!< Timer 4 clock enable */ +#define RCC_APB1PCLKEN_TIM5EN ((uint32_t)0x00000008) /*!< Timer 5 clock enable */ +#define RCC_APB1PCLKEN_TIM6EN ((uint32_t)0x00000010) /*!< Timer 6 clock enable */ +#define RCC_APB1PCLKEN_TIM7EN ((uint32_t)0x00000020) /*!< Timer 7 clock enable */ +#define RCC_APB1PCLKEN_COMPEN ((uint32_t)0x00000040) /*!< COMP clock enable */ +#define RCC_APB1PCLKEN_COMPFILTEN ((uint32_t)0x00000080) /*!< COMPFILT clock enable */ +#define RCC_APB1PCLKEN_TSCEN ((uint32_t)0x00000400) /*!< TSC clock enable */ +#define RCC_APB1PCLKEN_WWDGEN ((uint32_t)0x00000800) /*!< Window Watchdog clock enable */ +#define RCC_APB1PCLKEN_SPI2EN ((uint32_t)0x00004000) /*!< SPI 2 clock enable */ +#define RCC_APB1PCLKEN_SPI3EN ((uint32_t)0x00008000) /*!< SPI 3 clock enable */ +#define RCC_APB1PCLKEN_USART2EN ((uint32_t)0x00020000) /*!< USART 2 clock enable */ +#define RCC_APB1PCLKEN_USART3EN ((uint32_t)0x00040000) /*!< USART 3 clock enable */ +#define RCC_APB1PCLKEN_UART4EN ((uint32_t)0x00080000) /*!< UART 4 clock enable */ +#define RCC_APB1PCLKEN_UART5EN ((uint32_t)0x00100000) /*!< UART 5 clock enable */ +#define RCC_APB1PCLKEN_I2C1EN ((uint32_t)0x00200000) /*!< I2C 1 clock enable */ +#define RCC_APB1PCLKEN_I2C2EN ((uint32_t)0x00400000) /*!< I2C 2 clock enable */ +#define RCC_APB1PCLKEN_USBEN ((uint32_t)0x00800000) /*!< USB Device clock enable */ +#define RCC_APB1PCLKEN_CAN1EN ((uint32_t)0x02000000) /*!< CAN1 clock enable */ +#define RCC_APB1PCLKEN_CAN2EN ((uint32_t)0x04000000) /*!< CAN2 clock enable */ +#define RCC_APB1PCLKEN_BKPEN ((uint32_t)0x08000000) /*!< Backup interface clock enable */ +#define RCC_APB1PCLKEN_PWREN ((uint32_t)0x10000000) /*!< Power interface clock enable */ +#define RCC_APB1PCLKEN_DACEN ((uint32_t)0x20000000) /*!< DAC interface clock enable */ +#define RCC_APB1PCLKEN_OPAMPEN ((uint32_t)0x80000000) /*!< OPAMP interface clock enable */ + +/******************* Bit definition for RCC_BDCTRL register *******************/ +#define RCC_BDCTRL_LSEEN ((uint32_t)0x00000001) /*!< External Low Speed oscillator enable */ +#define RCC_BDCTRL_LSERD ((uint32_t)0x00000002) /*!< External Low Speed oscillator Ready */ +#define RCC_BDCTRL_LSEBP ((uint32_t)0x00000004) /*!< External Low Speed oscillator Bypass */ + +#define RCC_BDCTRL_RTCSEL ((uint32_t)0x00000300) /*!< RTCSEL[1:0] bits (RTC clock source selection) */ +#define RCC_BDCTRL_RTCSEL_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define RCC_BDCTRL_RTCSEL_1 ((uint32_t)0x00000200) /*!< Bit 1 */ + +/*!< RTC congiguration */ +#define RCC_BDCTRL_RTCSEL_NOCLOCK ((uint32_t)0x00000000) /*!< No clock */ +#define RCC_BDCTRL_RTCSEL_LSE ((uint32_t)0x00000100) /*!< LSE oscillator clock used as RTC clock */ +#define RCC_BDCTRL_RTCSEL_LSI ((uint32_t)0x00000200) /*!< LSI oscillator clock used as RTC clock */ +#define RCC_BDCTRL_RTCSEL_HSE ((uint32_t)0x00000300) /*!< HSE oscillator clock divided by 128 used as RTC clock */ + +#define RCC_BDCTRL_RTCEN ((uint32_t)0x00008000) /*!< RTC clock enable */ +#define RCC_BDCTRL_BDSFTRST ((uint32_t)0x00010000) /*!< Backup domain software reset */ + +/******************* Bit definition for RCC_CTRLSTS register ********************/ +#define RCC_CTRLSTS_LSIEN ((uint32_t)0x00000001) /*!< Internal Low Speed oscillator enable */ +#define RCC_CTRLSTS_LSIRD ((uint32_t)0x00000002) /*!< Internal Low Speed oscillator Ready */ +#define RCC_CTRLSTS_BORRSTF ((uint32_t)0x00080000) /*!< BOR reset flag */ +#define RCC_CTRLSTS_RETEMCF ((uint32_t)0x00100000) /*!< RET_EMC reset flag */ +#define RCC_CTRLSTS_BKPEMCF ((uint32_t)0x00200000) /*!< BKP_EMC reset flag */ +#define RCC_CTRLSTS_RAMRSTF ((uint32_t)0x00800000) /*!< RAM reset flag */ +#define RCC_CTRLSTS_RMRSTF ((uint32_t)0x01000000) /*!< Remove reset flag */ +#define RCC_CTRLSTS_MMURSTF ((uint32_t)0x02000000) /*!< MMU reset flag */ +#define RCC_CTRLSTS_PINRSTF ((uint32_t)0x04000000) /*!< PIN reset flag */ +#define RCC_CTRLSTS_PORRSTF ((uint32_t)0x08000000) /*!< POR/PDR reset flag */ +#define RCC_CTRLSTS_SFTRSTF ((uint32_t)0x10000000) /*!< Software Reset flag */ +#define RCC_CTRLSTS_IWDGRSTF ((uint32_t)0x20000000) /*!< Independent Watchdog reset flag */ +#define RCC_CTRLSTS_WWDGRSTF ((uint32_t)0x40000000) /*!< Window watchdog reset flag */ +#define RCC_CTRLSTS_LPWRRSTF ((uint32_t)0x80000000) /*!< Low-Power reset flag */ + +/******************* Bit definition for RCC_AHBPRST register ****************/ +#define RCC_AHBRST_RNGCRST ((uint32_t)0x00000200) /*!< RNGC reset */ +#define RCC_AHBRST_SACRST ((uint32_t)0x00000800) /*!< SAC reset */ +#define RCC_AHBRST_ADC1RST ((uint32_t)0x00001000) /*!< ADC1 reset */ +#define RCC_AHBRST_ADC2RST ((uint32_t)0x00002000) /*!< ADC2 reset */ +#define RCC_AHBRST_ETHMACRST ((uint32_t)0x00010000) /*!< ETHMAC reset */ +#define RCC_AHBRST_QSPIRST ((uint32_t)0x00020000) /*!< QSPI reset */ + +/******************* Bit definition for RCC_CFG2 register ******************/ +/*!< ADCHPRE configuration */ +#define RCC_CFG2_ADCHPRES ((uint32_t)0x0000000F) /*!< ADCHPRE[3:0] bits */ +#define RCC_CFG2_ADCHPRES_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define RCC_CFG2_ADCHPRES_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define RCC_CFG2_ADCHPRES_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define RCC_CFG2_ADCHPRES_3 ((uint32_t)0x00000008) /*!< Bit 3 */ + +#define RCC_CFG2_ADCHPRES_DIV1 ((uint32_t)0x00000000) /*!< HCLK clock divided by 1 */ +#define RCC_CFG2_ADCHPRES_DIV2 ((uint32_t)0x00000001) /*!< HCLK clock divided by 2 */ +#define RCC_CFG2_ADCHPRES_DIV4 ((uint32_t)0x00000002) /*!< HCLK clock divided by 4 */ +#define RCC_CFG2_ADCHPRES_DIV6 ((uint32_t)0x00000003) /*!< HCLK clock divided by 6 */ +#define RCC_CFG2_ADCHPRES_DIV8 ((uint32_t)0x00000004) /*!< HCLK clock divided by 8 */ +#define RCC_CFG2_ADCHPRES_DIV10 ((uint32_t)0x00000005) /*!< HCLK clock divided by 10 */ +#define RCC_CFG2_ADCHPRES_DIV12 ((uint32_t)0x00000006) /*!< HCLK clock divided by 12 */ +#define RCC_CFG2_ADCHPRES_DIV16 ((uint32_t)0x00000007) /*!< HCLK clock divided by 16 */ +#define RCC_CFG2_ADCHPRES_DIV32 ((uint32_t)0x00000008) /*!< HCLK clock divided by 32 */ +#define RCC_CFG2_ADCHPRES_OTHERS ((uint32_t)0x00000008) /*!< HCLK clock divided by 32 */ + +/*!< ADCPLLPRES configuration */ +#define RCC_CFG2_ADCPLLPRES ((uint32_t)0x000001F0) /*!< ADCPLLPRES[4:0] bits */ +#define RCC_CFG2_ADCPLLPRES_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define RCC_CFG2_ADCPLLPRES_1 ((uint32_t)0x00000020) /*!< Bit 1 */ +#define RCC_CFG2_ADCPLLPRES_2 ((uint32_t)0x00000040) /*!< Bit 2 */ +#define RCC_CFG2_ADCPLLPRES_3 ((uint32_t)0x00000080) /*!< Bit 3 */ +#define RCC_CFG2_ADCPLLPRES_4 ((uint32_t)0x00000100) /*!< Bit 4 */ + +#define RCC_CFG2_ADCPLLCLK_DISABLE ((uint32_t)0xFFFFFEFF) /*!< ADC PLL clock Disable */ +#define RCC_CFG2_ADCPLLPRES_DIV1 ((uint32_t)0x00000100) /*!< PLL clock divided by 1 */ +#define RCC_CFG2_ADCPLLPRES_DIV2 ((uint32_t)0x00000110) /*!< PLL clock divided by 2 */ +#define RCC_CFG2_ADCPLLPRES_DIV4 ((uint32_t)0x00000120) /*!< PLL clock divided by 4 */ +#define RCC_CFG2_ADCPLLPRES_DIV6 ((uint32_t)0x00000130) /*!< PLL clock divided by 6 */ +#define RCC_CFG2_ADCPLLPRES_DIV8 ((uint32_t)0x00000140) /*!< PLL clock divided by 8 */ +#define RCC_CFG2_ADCPLLPRES_DIV10 ((uint32_t)0x00000150) /*!< PLL clock divided by 10 */ +#define RCC_CFG2_ADCPLLPRES_DIV12 ((uint32_t)0x00000160) /*!< PLL clock divided by 12 */ +#define RCC_CFG2_ADCPLLPRES_DIV16 ((uint32_t)0x00000170) /*!< PLL clock divided by 16 */ +#define RCC_CFG2_ADCPLLPRES_DIV32 ((uint32_t)0x00000180) /*!< PLL clock divided by 32 */ +#define RCC_CFG2_ADCPLLPRES_DIV64 ((uint32_t)0x00000190) /*!< PLL clock divided by 64 */ +#define RCC_CFG2_ADCPLLPRES_DIV128 ((uint32_t)0x000001A0) /*!< PLL clock divided by 128 */ +#define RCC_CFG2_ADCPLLPRES_DIV256 ((uint32_t)0x000001B0) /*!< PLL clock divided by 256 */ +#define RCC_CFG2_ADCPLLPRES_DIV256N ((uint32_t)0x000001C0) /*!< PLL clock divided by 256 */ + +/*!< ADC1MSEL configuration */ +#define RCC_CFG2_ADC1MSEL ((uint32_t)0x00000400) /*!< ADC1M clock source select */ + +#define RCC_CFG2_ADC1MSEL_HSI ((uint32_t)0x00000000) /*!< HSI clock selected as ADC1M input clock */ +#define RCC_CFG2_ADC1MSEL_HSE ((uint32_t)0x00000400) /*!< HSE clock selected as ADC1M input clock */ + +/*!< ADC1MPRE configuration */ +#define RCC_CFG2_ADC1MPRES ((uint32_t)0x0000F800) /*!< ADC1MPRE[4:0] bits */ +#define RCC_CFG2_ADC1MPRES_0 ((uint32_t)0x00000800) /*!< Bit 0 */ +#define RCC_CFG2_ADC1MPRES_1 ((uint32_t)0x00001000) /*!< Bit 1 */ +#define RCC_CFG2_ADC1MPRES_2 ((uint32_t)0x00002000) /*!< Bit 2 */ +#define RCC_CFG2_ADC1MPRES_3 ((uint32_t)0x00004000) /*!< Bit 3 */ +#define RCC_CFG2_ADC1MPRES_4 ((uint32_t)0x00008000) /*!< Bit 4 */ + +#define RCC_CFG2_ADC1MPRES_DIV1 ((uint32_t)0x00000000) /*!< ADC1M source clock is divided by 1 */ +#define RCC_CFG2_ADC1MPRES_DIV2 ((uint32_t)0x00000800) /*!< ADC1M source clock is divided by 2 */ +#define RCC_CFG2_ADC1MPRES_DIV3 ((uint32_t)0x00001000) /*!< ADC1M source clock is divided by 3 */ +#define RCC_CFG2_ADC1MPRES_DIV4 ((uint32_t)0x00001800) /*!< ADC1M source clock is divided by 4 */ +#define RCC_CFG2_ADC1MPRES_DIV5 ((uint32_t)0x00002000) /*!< ADC1M source clock is divided by 5 */ +#define RCC_CFG2_ADC1MPRES_DIV6 ((uint32_t)0x00002800) /*!< ADC1M source clock is divided by 6 */ +#define RCC_CFG2_ADC1MPRES_DIV7 ((uint32_t)0x00003000) /*!< ADC1M source clock is divided by 7 */ +#define RCC_CFG2_ADC1MPRES_DIV8 ((uint32_t)0x00003800) /*!< ADC1M source clock is divided by 8 */ +#define RCC_CFG2_ADC1MPRES_DIV9 ((uint32_t)0x00004000) /*!< ADC1M source clock is divided by 9 */ +#define RCC_CFG2_ADC1MPRES_DIV10 ((uint32_t)0x00004800) /*!< ADC1M source clock is divided by 10 */ +#define RCC_CFG2_ADC1MPRES_DIV11 ((uint32_t)0x00005000) /*!< ADC1M source clock is divided by 11 */ +#define RCC_CFG2_ADC1MPRES_DIV12 ((uint32_t)0x00005800) /*!< ADC1M source clock is divided by 12 */ +#define RCC_CFG2_ADC1MPRES_DIV13 ((uint32_t)0x00006000) /*!< ADC1M source clock is divided by 13 */ +#define RCC_CFG2_ADC1MPRES_DIV14 ((uint32_t)0x00006800) /*!< ADC1M source clock is divided by 14 */ +#define RCC_CFG2_ADC1MPRES_DIV15 ((uint32_t)0x00007000) /*!< ADC1M source clock is divided by 15 */ +#define RCC_CFG2_ADC1MPRES_DIV16 ((uint32_t)0x00007800) /*!< ADC1M source clock is divided by 16 */ +#define RCC_CFG2_ADC1MPRES_DIV17 ((uint32_t)0x00008000) /*!< ADC1M source clock is divided by 17 */ +#define RCC_CFG2_ADC1MPRES_DIV18 ((uint32_t)0x00008800) /*!< ADC1M source clock is divided by 18 */ +#define RCC_CFG2_ADC1MPRES_DIV19 ((uint32_t)0x00009000) /*!< ADC1M source clock is divided by 19 */ +#define RCC_CFG2_ADC1MPRES_DIV20 ((uint32_t)0x00009800) /*!< ADC1M source clock is divided by 20 */ +#define RCC_CFG2_ADC1MPRES_DIV21 ((uint32_t)0x0000A000) /*!< ADC1M source clock is divided by 21 */ +#define RCC_CFG2_ADC1MPRES_DIV22 ((uint32_t)0x0000A800) /*!< ADC1M source clock is divided by 22 */ +#define RCC_CFG2_ADC1MPRES_DIV23 ((uint32_t)0x0000B000) /*!< ADC1M source clock is divided by 23 */ +#define RCC_CFG2_ADC1MPRES_DIV24 ((uint32_t)0x0000B800) /*!< ADC1M source clock is divided by 24 */ +#define RCC_CFG2_ADC1MPRES_DIV25 ((uint32_t)0x0000C000) /*!< ADC1M source clock is divided by 25 */ +#define RCC_CFG2_ADC1MPRES_DIV26 ((uint32_t)0x0000C800) /*!< ADC1M source clock is divided by 26 */ +#define RCC_CFG2_ADC1MPRES_DIV27 ((uint32_t)0x0000D000) /*!< ADC1M source clock is divided by 27 */ +#define RCC_CFG2_ADC1MPRES_DIV28 ((uint32_t)0x0000D800) /*!< ADC1M source clock is divided by 28 */ +#define RCC_CFG2_ADC1MPRES_DIV29 ((uint32_t)0x0000E000) /*!< ADC1M source clock is divided by 29 */ +#define RCC_CFG2_ADC1MPRES_DIV30 ((uint32_t)0x0000E800) /*!< ADC1M source clock is divided by 30 */ +#define RCC_CFG2_ADC1MPRES_DIV31 ((uint32_t)0x0000F000) /*!< ADC1M source clock is divided by 31 */ +#define RCC_CFG2_ADC1MPRES_DIV32 ((uint32_t)0x0000F800) /*!< ADC1M source clock is divided by 32 */ + +/*!< RNGCPRE configuration */ +#define RCC_CFG2_RNGCPRES ((uint32_t)0x1F000000) /*!< RNGCPRE[4:0] bits */ +#define RCC_CFG2_RNGCPRES_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define RCC_CFG2_RNGCPRES_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define RCC_CFG2_RNGCPRES_2 ((uint32_t)0x04000000) /*!< Bit 2 */ +#define RCC_CFG2_RNGCPRES_3 ((uint32_t)0x08000000) /*!< Bit 3 */ +#define RCC_CFG2_RNGCPRES_4 ((uint32_t)0x10000000) /*!< Bit 4 */ + +#define RCC_CFG2_RNGCPRES_DIV1 ((uint32_t)0x00000000) /*!< SYSCLK source clock is divided by 1 */ +#define RCC_CFG2_RNGCPRES_DIV2 ((uint32_t)0x01000000) /*!< SYSCLK source clock is divided by 2 */ +#define RCC_CFG2_RNGCPRES_DIV3 ((uint32_t)0x02000000) /*!< SYSCLK source clock is divided by 3 */ +#define RCC_CFG2_RNGCPRES_DIV4 ((uint32_t)0x03000000) /*!< SYSCLK source clock is divided by 4 */ +#define RCC_CFG2_RNGCPRES_DIV5 ((uint32_t)0x04000000) /*!< SYSCLK source clock is divided by 5 */ +#define RCC_CFG2_RNGCPRES_DIV6 ((uint32_t)0x05000000) /*!< SYSCLK source clock is divided by 6 */ +#define RCC_CFG2_RNGCPRES_DIV7 ((uint32_t)0x06000000) /*!< SYSCLK source clock is divided by 7 */ +#define RCC_CFG2_RNGCPRES_DIV8 ((uint32_t)0x07000000) /*!< SYSCLK source clock is divided by 8 */ +#define RCC_CFG2_RNGCPRES_DIV9 ((uint32_t)0x08000000) /*!< SYSCLK source clock is divided by 9 */ +#define RCC_CFG2_RNGCPRES_DIV10 ((uint32_t)0x09000000) /*!< SYSCLK source clock is divided by 10 */ +#define RCC_CFG2_RNGCPRES_DIV11 ((uint32_t)0x0A000000) /*!< SYSCLK source clock is divided by 11 */ +#define RCC_CFG2_RNGCPRES_DIV12 ((uint32_t)0x0B000000) /*!< SYSCLK source clock is divided by 12 */ +#define RCC_CFG2_RNGCPRES_DIV13 ((uint32_t)0x0C000000) /*!< SYSCLK source clock is divided by 13 */ +#define RCC_CFG2_RNGCPRES_DIV14 ((uint32_t)0x0D000000) /*!< SYSCLK source clock is divided by 14 */ +#define RCC_CFG2_RNGCPRES_DIV15 ((uint32_t)0x0E000000) /*!< SYSCLK source clock is divided by 15 */ +#define RCC_CFG2_RNGCPRES_DIV16 ((uint32_t)0x0F000000) /*!< SYSCLK source clock is divided by 16 */ +#define RCC_CFG2_RNGCPRES_DIV17 ((uint32_t)0x10000000) /*!< SYSCLK source clock is divided by 17 */ +#define RCC_CFG2_RNGCPRES_DIV18 ((uint32_t)0x11000000) /*!< SYSCLK source clock is divided by 18 */ +#define RCC_CFG2_RNGCPRES_DIV19 ((uint32_t)0x12000000) /*!< SYSCLK source clock is divided by 19 */ +#define RCC_CFG2_RNGCPRES_DIV20 ((uint32_t)0x13000000) /*!< SYSCLK source clock is divided by 20 */ +#define RCC_CFG2_RNGCPRES_DIV21 ((uint32_t)0x14000000) /*!< SYSCLK source clock is divided by 21 */ +#define RCC_CFG2_RNGCPRES_DIV22 ((uint32_t)0x15000000) /*!< SYSCLK source clock is divided by 22 */ +#define RCC_CFG2_RNGCPRES_DIV23 ((uint32_t)0x16000000) /*!< SYSCLK source clock is divided by 23 */ +#define RCC_CFG2_RNGCPRES_DIV24 ((uint32_t)0x17000000) /*!< SYSCLK source clock is divided by 24 */ +#define RCC_CFG2_RNGCPRES_DIV25 ((uint32_t)0x18000000) /*!< SYSCLK source clock is divided by 25 */ +#define RCC_CFG2_RNGCPRES_DIV26 ((uint32_t)0x19000000) /*!< SYSCLK source clock is divided by 26 */ +#define RCC_CFG2_RNGCPRES_DIV27 ((uint32_t)0x1A000000) /*!< SYSCLK source clock is divided by 27 */ +#define RCC_CFG2_RNGCPRES_DIV28 ((uint32_t)0x1B000000) /*!< SYSCLK source clock is divided by 28 */ +#define RCC_CFG2_RNGCPRES_DIV29 ((uint32_t)0x1C000000) /*!< SYSCLK source clock is divided by 29 */ +#define RCC_CFG2_RNGCPRES_DIV30 ((uint32_t)0x1D000000) /*!< SYSCLK source clock is divided by 30 */ +#define RCC_CFG2_RNGCPRES_DIV31 ((uint32_t)0x1E000000) /*!< SYSCLK source clock is divided by 31 */ +#define RCC_CFG2_RNGCPRES_DIV32 ((uint32_t)0x1F000000) /*!< SYSCLK source clock is divided by 32 */ + +/*!< TIMCLK_SEL configuration */ +#define RCC_CFG2_TIMCLKSEL ((uint32_t)0x20000000) /*!< Timer1/8 clock source select */ + +#define RCC_CFG2_TIMCLKSEL_TIM18CLK ((uint32_t)0x00000000) /*!< Timer1/8 clock selected as tim1/8_clk input clock */ +#define RCC_CFG2_TIMCLKSEL_SYSCLK ((uint32_t)0x20000000) /*!< Timer1/8 clock selected as sysclk input clock */ + +/******************* Bit definition for RCC_CFG3 register ******************/ +/*!< BORRSTEN configuration */ +#define RCC_CFG3_BORRSTEN ((uint32_t)0x00000040) /*!< BOR reset enable */ + +#define RCC_CFG3_BORRSTEN_ENABLE ((uint32_t)0x00000040) /*!< BOR reset enable */ +#define RCC_CFG3_BORRSTEN_DISABLE ((uint32_t)0x00000000) /*!< BOR reset disable */ + +/*!< TRNG1MPRE configuration */ +#define RCC_CFG3_TRNG1MPRES ((uint32_t)0x0000F800) /*!< TRNG1MPRE[4:0] bits */ +#define RCC_CFG3_TRNG1MPRES_0 ((uint32_t)0x00000800) /*!< Bit 0 */ +#define RCC_CFG3_TRNG1MPRES_1 ((uint32_t)0x00001000) /*!< Bit 1 */ +#define RCC_CFG3_TRNG1MPRES_2 ((uint32_t)0x00002000) /*!< Bit 2 */ +#define RCC_CFG3_TRNG1MPRES_3 ((uint32_t)0x00004000) /*!< Bit 3 */ +#define RCC_CFG3_TRNG1MPRES_4 ((uint32_t)0x00008000) /*!< Bit 4 */ + +#define RCC_CFG3_TRNG1MPRES_VAL1 ((uint32_t)0x00000000) /*!< TRNG 1M source clock is divided by 2 */ +#define RCC_CFG3_TRNG1MPRES_VAL2 ((uint32_t)0x00000800) /*!< TRNG 1M source clock is divided by 2 */ +#define RCC_CFG3_TRNG1MPRES_VAL3 ((uint32_t)0x00001000) /*!< TRNG 1M source clock is divided by 4 */ +#define RCC_CFG3_TRNG1MPRES_VAL4 ((uint32_t)0x00001800) /*!< TRNG 1M source clock is divided by 4 */ +#define RCC_CFG3_TRNG1MPRES_VAL5 ((uint32_t)0x00002000) /*!< TRNG 1M source clock is divided by 6 */ +#define RCC_CFG3_TRNG1MPRES_VAL6 ((uint32_t)0x00002800) /*!< TRNG 1M source clock is divided by 6 */ +#define RCC_CFG3_TRNG1MPRES_VAL7 ((uint32_t)0x00003000) /*!< TRNG 1M source clock is divided by 8 */ +#define RCC_CFG3_TRNG1MPRES_VAL8 ((uint32_t)0x00003800) /*!< TRNG 1M source clock is divided by 8 */ +#define RCC_CFG3_TRNG1MPRES_VAL9 ((uint32_t)0x00004000) /*!< TRNG 1M source clock is divided by 10 */ +#define RCC_CFG3_TRNG1MPRES_VAL10 ((uint32_t)0x00004800) /*!< TRNG 1M source clock is divided by 10 */ +#define RCC_CFG3_TRNG1MPRES_VAL11 ((uint32_t)0x00005000) /*!< TRNG 1M source clock is divided by 12 */ +#define RCC_CFG3_TRNG1MPRES_VAL12 ((uint32_t)0x00005800) /*!< TRNG 1M source clock is divided by 12 */ +#define RCC_CFG3_TRNG1MPRES_VAL13 ((uint32_t)0x00006000) /*!< TRNG 1M source clock is divided by 14 */ +#define RCC_CFG3_TRNG1MPRES_VAL14 ((uint32_t)0x00006800) /*!< TRNG 1M source clock is divided by 14 */ +#define RCC_CFG3_TRNG1MPRES_VAL15 ((uint32_t)0x00007000) /*!< TRNG 1M source clock is divided by 16 */ +#define RCC_CFG3_TRNG1MPRES_VAL16 ((uint32_t)0x00007800) /*!< TRNG 1M source clock is divided by 16 */ +#define RCC_CFG3_TRNG1MPRES_VAL17 ((uint32_t)0x00008000) /*!< TRNG 1M source clock is divided by 18 */ +#define RCC_CFG3_TRNG1MPRES_VAL18 ((uint32_t)0x00008800) /*!< TRNG 1M source clock is divided by 18 */ +#define RCC_CFG3_TRNG1MPRES_VAL19 ((uint32_t)0x00009000) /*!< TRNG 1M source clock is divided by 20 */ +#define RCC_CFG3_TRNG1MPRES_VAL20 ((uint32_t)0x00009800) /*!< TRNG 1M source clock is divided by 20 */ +#define RCC_CFG3_TRNG1MPRES_VAL21 ((uint32_t)0x0000A000) /*!< TRNG 1M source clock is divided by 22 */ +#define RCC_CFG3_TRNG1MPRES_VAL22 ((uint32_t)0x0000A800) /*!< TRNG 1M source clock is divided by 22 */ +#define RCC_CFG3_TRNG1MPRES_VAL23 ((uint32_t)0x0000B000) /*!< TRNG 1M source clock is divided by 24 */ +#define RCC_CFG3_TRNG1MPRES_VAL24 ((uint32_t)0x0000B800) /*!< TRNG 1M source clock is divided by 24 */ +#define RCC_CFG3_TRNG1MPRES_VAL25 ((uint32_t)0x0000C000) /*!< TRNG 1M source clock is divided by 26 */ +#define RCC_CFG3_TRNG1MPRES_VAL26 ((uint32_t)0x0000C800) /*!< TRNG 1M source clock is divided by 26 */ +#define RCC_CFG3_TRNG1MPRES_VAL27 ((uint32_t)0x0000D000) /*!< TRNG 1M source clock is divided by 28 */ +#define RCC_CFG3_TRNG1MPRES_VAL28 ((uint32_t)0x0000D800) /*!< TRNG 1M source clock is divided by 28 */ +#define RCC_CFG3_TRNG1MPRES_VAL29 ((uint32_t)0x0000E000) /*!< TRNG 1M source clock is divided by 30 */ +#define RCC_CFG3_TRNG1MPRES_VAL30 ((uint32_t)0x0000E800) /*!< TRNG 1M source clock is divided by 30 */ +#define RCC_CFG3_TRNG1MPRES_VAL31 ((uint32_t)0x0000F000) /*!< TRNG 1M source clock is divided by 32 */ +#define RCC_CFG3_TRNG1MPRES_VAL32 ((uint32_t)0x0000F800) /*!< TRNG 1M source clock is divided by 32 */ + +/*!< TRNG1MSEL configuration */ +#define RCC_CFG3_TRNG1MSEL ((uint32_t)0x00020000) /*!< TRNG_1M clock source select */ + +#define RCC_CFG3_TRNG1MSEL_HSI ((uint32_t)0x00000000) /*!< HSI clock selected as TRNG_1M input clock */ +#define RCC_CFG3_TRNG1MSEL_HSE ((uint32_t)0x00020000) /*!< HSE clock selected as TRNG_1M input clock */ + +/*!< TRNG1MEN configuration */ +#define RCC_CFG3_TRNG1MEN ((uint32_t)0x00040000) /*!< TRNG_1M clock enable */ + +#define RCC_CFG3_TRNG1MEN_DISABLE ((uint32_t)0x00000000) /*!< TRNG_1M clock disable */ +#define RCC_CFG3_TRNG1MEN_ENABLE ((uint32_t)0x00040000) /*!< TRNG_1M clock enable */ + +/******************************************************************************/ +/* */ +/* General Purpose and Alternate Function I/O */ +/* */ +/******************************************************************************/ + +/******************* Bit definition for GPIO_PL_CFG register *******************/ +#define GPIO_PL_CFG_PMODE ((uint32_t)0x33333333) /*!< Port x mode bits */ + +#define GPIO_PL_CFG_PMODE0 ((uint32_t)0x00000003) /*!< MODE0[1:0] bits (Port x mode bits, pin 0) */ +#define GPIO_PL_CFG_PMODE0_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define GPIO_PL_CFG_PMODE0_1 ((uint32_t)0x00000002) /*!< Bit 1 */ + +#define GPIO_PL_CFG_PMODE1 ((uint32_t)0x00000030) /*!< MODE1[1:0] bits (Port x mode bits, pin 1) */ +#define GPIO_PL_CFG_PMODE1_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define GPIO_PL_CFG_PMODE1_1 ((uint32_t)0x00000020) /*!< Bit 1 */ + +#define GPIO_PL_CFG_PMODE2 ((uint32_t)0x00000300) /*!< MODE2[1:0] bits (Port x mode bits, pin 2) */ +#define GPIO_PL_CFG_PMODE2_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define GPIO_PL_CFG_PMODE2_1 ((uint32_t)0x00000200) /*!< Bit 1 */ + +#define GPIO_PL_CFG_PMODE3 ((uint32_t)0x00003000) /*!< MODE3[1:0] bits (Port x mode bits, pin 3) */ +#define GPIO_PL_CFG_PMODE3_0 ((uint32_t)0x00001000) /*!< Bit 0 */ +#define GPIO_PL_CFG_PMODE3_1 ((uint32_t)0x00002000) /*!< Bit 1 */ + +#define GPIO_PL_CFG_PMODE4 ((uint32_t)0x00030000) /*!< MODE4[1:0] bits (Port x mode bits, pin 4) */ +#define GPIO_PL_CFG_PMODE4_0 ((uint32_t)0x00010000) /*!< Bit 0 */ +#define GPIO_PL_CFG_PMODE4_1 ((uint32_t)0x00020000) /*!< Bit 1 */ + +#define GPIO_PL_CFG_PMODE5 ((uint32_t)0x00300000) /*!< MODE5[1:0] bits (Port x mode bits, pin 5) */ +#define GPIO_PL_CFG_PMODE5_0 ((uint32_t)0x00100000) /*!< Bit 0 */ +#define GPIO_PL_CFG_PMODE5_1 ((uint32_t)0x00200000) /*!< Bit 1 */ + +#define GPIO_PL_CFG_PMODE6 ((uint32_t)0x03000000) /*!< MODE6[1:0] bits (Port x mode bits, pin 6) */ +#define GPIO_PL_CFG_PMODE6_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define GPIO_PL_CFG_PMODE6_1 ((uint32_t)0x02000000) /*!< Bit 1 */ + +#define GPIO_PL_CFG_PMODE7 ((uint32_t)0x30000000) /*!< MODE7[1:0] bits (Port x mode bits, pin 7) */ +#define GPIO_PL_CFG_PMODE7_0 ((uint32_t)0x10000000) /*!< Bit 0 */ +#define GPIO_PL_CFG_PMODE7_1 ((uint32_t)0x20000000) /*!< Bit 1 */ + +#define GPIO_PL_CFG_PCFG ((uint32_t)0xCCCCCCCC) /*!< Port x configuration bits */ + +#define GPIO_PL_CFG_PCFG0 ((uint32_t)0x0000000C) /*!< CNF0[1:0] bits (Port x configuration bits, pin 0) */ +#define GPIO_PL_CFG_PCFG0_0 ((uint32_t)0x00000004) /*!< Bit 0 */ +#define GPIO_PL_CFG_PCFG0_1 ((uint32_t)0x00000008) /*!< Bit 1 */ + +#define GPIO_PL_CFG_PCFG1 ((uint32_t)0x000000C0) /*!< CNF1[1:0] bits (Port x configuration bits, pin 1) */ +#define GPIO_PL_CFG_PCFG1_0 ((uint32_t)0x00000040) /*!< Bit 0 */ +#define GPIO_PL_CFG_PCFG1_1 ((uint32_t)0x00000080) /*!< Bit 1 */ + +#define GPIO_PL_CFG_PCFG2 ((uint32_t)0x00000C00) /*!< CNF2[1:0] bits (Port x configuration bits, pin 2) */ +#define GPIO_PL_CFG_PCFG2_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define GPIO_PL_CFG_PCFG2_1 ((uint32_t)0x00000800) /*!< Bit 1 */ + +#define GPIO_PL_CFG_PCFG3 ((uint32_t)0x0000C000) /*!< CNF3[1:0] bits (Port x configuration bits, pin 3) */ +#define GPIO_PL_CFG_PCFG3_0 ((uint32_t)0x00004000) /*!< Bit 0 */ +#define GPIO_PL_CFG_PCFG3_1 ((uint32_t)0x00008000) /*!< Bit 1 */ + +#define GPIO_PL_CFG_PCFG4 ((uint32_t)0x000C0000) /*!< CNF4[1:0] bits (Port x configuration bits, pin 4) */ +#define GPIO_PL_CFG_PCFG4_0 ((uint32_t)0x00040000) /*!< Bit 0 */ +#define GPIO_PL_CFG_PCFG4_1 ((uint32_t)0x00080000) /*!< Bit 1 */ + +#define GPIO_PL_CFG_PCFG5 ((uint32_t)0x00C00000) /*!< CNF5[1:0] bits (Port x configuration bits, pin 5) */ +#define GPIO_PL_CFG_PCFG5_0 ((uint32_t)0x00400000) /*!< Bit 0 */ +#define GPIO_PL_CFG_PCFG5_1 ((uint32_t)0x00800000) /*!< Bit 1 */ + +#define GPIO_PL_CFG_PCFG6 ((uint32_t)0x0C000000) /*!< CNF6[1:0] bits (Port x configuration bits, pin 6) */ +#define GPIO_PL_CFG_PCFG6_0 ((uint32_t)0x04000000) /*!< Bit 0 */ +#define GPIO_PL_CFG_PCFG6_1 ((uint32_t)0x08000000) /*!< Bit 1 */ + +#define GPIO_PL_CFG_PCFG7 ((uint32_t)0xC0000000) /*!< CNF7[1:0] bits (Port x configuration bits, pin 7) */ +#define GPIO_PL_CFG_PCFG7_0 ((uint32_t)0x40000000) /*!< Bit 0 */ +#define GPIO_PL_CFG_PCFG7_1 ((uint32_t)0x80000000) /*!< Bit 1 */ + +/******************* Bit definition for GPIO_PH_CFG register *******************/ +#define GPIO_PH_CFG_PMODE ((uint32_t)0x33333333) /*!< Port x mode bits */ + +#define GPIO_PH_CFG_PMODE8 ((uint32_t)0x00000003) /*!< MODE8[1:0] bits (Port x mode bits, pin 8) */ +#define GPIO_PH_CFG_PMODE8_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define GPIO_PH_CFG_PMODE8_1 ((uint32_t)0x00000002) /*!< Bit 1 */ + +#define GPIO_PH_CFG_PMODE1 ((uint32_t)0x00000030) /*!< MODE9[1:0] bits (Port x mode bits, pin 9) */ +#define GPIO_PH_CFG_PMODE9_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define GPIO_PH_CFG_PMODE9_1 ((uint32_t)0x00000020) /*!< Bit 1 */ + +#define GPIO_PH_CFG_PMODE10 ((uint32_t)0x00000300) /*!< MODE10[1:0] bits (Port x mode bits, pin 10) */ +#define GPIO_PH_CFG_PMODE10_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define GPIO_PH_CFG_PMODE10_1 ((uint32_t)0x00000200) /*!< Bit 1 */ + +#define GPIO_PH_CFG_PMODE11 ((uint32_t)0x00003000) /*!< MODE11[1:0] bits (Port x mode bits, pin 11) */ +#define GPIO_PH_CFG_PMODE11_0 ((uint32_t)0x00001000) /*!< Bit 0 */ +#define GPIO_PH_CFG_PMODE11_1 ((uint32_t)0x00002000) /*!< Bit 1 */ + +#define GPIO_PH_CFG_PMODE12 ((uint32_t)0x00030000) /*!< MODE12[1:0] bits (Port x mode bits, pin 12) */ +#define GPIO_PH_CFG_PMODE12_0 ((uint32_t)0x00010000) /*!< Bit 0 */ +#define GPIO_PH_CFG_PMODE12_1 ((uint32_t)0x00020000) /*!< Bit 1 */ + +#define GPIO_PH_CFG_PMODE13 ((uint32_t)0x00300000) /*!< MODE13[1:0] bits (Port x mode bits, pin 13) */ +#define GPIO_PH_CFG_PMODE13_0 ((uint32_t)0x00100000) /*!< Bit 0 */ +#define GPIO_PH_CFG_PMODE13_1 ((uint32_t)0x00200000) /*!< Bit 1 */ + +#define GPIO_PH_CFG_PMODE14 ((uint32_t)0x03000000) /*!< MODE14[1:0] bits (Port x mode bits, pin 14) */ +#define GPIO_PH_CFG_PMODE14_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define GPIO_PH_CFG_PMODE14_1 ((uint32_t)0x02000000) /*!< Bit 1 */ + +#define GPIO_PH_CFG_PMODE15 ((uint32_t)0x30000000) /*!< MODE15[1:0] bits (Port x mode bits, pin 15) */ +#define GPIO_PH_CFG_PMODE15_0 ((uint32_t)0x10000000) /*!< Bit 0 */ +#define GPIO_PH_CFG_PMODE15_1 ((uint32_t)0x20000000) /*!< Bit 1 */ + +#define GPIO_PH_CFG_PCFG ((uint32_t)0xCCCCCCCC) /*!< Port x configuration bits */ + +#define GPIO_PH_CFG_PCFG8 ((uint32_t)0x0000000C) /*!< CNF8[1:0] bits (Port x configuration bits, pin 8) */ +#define GPIO_PH_CFG_PCFG8_0 ((uint32_t)0x00000004) /*!< Bit 0 */ +#define GPIO_PH_CFG_PCFG8_1 ((uint32_t)0x00000008) /*!< Bit 1 */ + +#define GPIO_PH_CFG_PCFG9 ((uint32_t)0x000000C0) /*!< CNF9[1:0] bits (Port x configuration bits, pin 9) */ +#define GPIO_PH_CFG_PCFG9_0 ((uint32_t)0x00000040) /*!< Bit 0 */ +#define GPIO_PH_CFG_PCFG9_1 ((uint32_t)0x00000080) /*!< Bit 1 */ + +#define GPIO_PH_CFG_PCFG10 ((uint32_t)0x00000C00) /*!< CNF10[1:0] bits (Port x configuration bits, pin 10) */ +#define GPIO_PH_CFG_PCFG10_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define GPIO_PH_CFG_PCFG10_1 ((uint32_t)0x00000800) /*!< Bit 1 */ + +#define GPIO_PH_CFG_PCFG11 ((uint32_t)0x0000C000) /*!< CNF11[1:0] bits (Port x configuration bits, pin 11) */ +#define GPIO_PH_CFG_PCFG11_0 ((uint32_t)0x00004000) /*!< Bit 0 */ +#define GPIO_PH_CFG_PCFG11_1 ((uint32_t)0x00008000) /*!< Bit 1 */ + +#define GPIO_PH_CFG_PCFG12 ((uint32_t)0x000C0000) /*!< CNF12[1:0] bits (Port x configuration bits, pin 12) */ +#define GPIO_PH_CFG_PCFG12_0 ((uint32_t)0x00040000) /*!< Bit 0 */ +#define GPIO_PH_CFG_PCFG12_1 ((uint32_t)0x00080000) /*!< Bit 1 */ + +#define GPIO_PH_CFG_PCFG13 ((uint32_t)0x00C00000) /*!< CNF13[1:0] bits (Port x configuration bits, pin 13) */ +#define GPIO_PH_CFG_PCFG13_0 ((uint32_t)0x00400000) /*!< Bit 0 */ +#define GPIO_PH_CFG_PCFG13_1 ((uint32_t)0x00800000) /*!< Bit 1 */ + +#define GPIO_PH_CFG_PCFG14 ((uint32_t)0x0C000000) /*!< CNF14[1:0] bits (Port x configuration bits, pin 14) */ +#define GPIO_PH_CFG_PCFG14_0 ((uint32_t)0x04000000) /*!< Bit 0 */ +#define GPIO_PH_CFG_PCFG14_1 ((uint32_t)0x08000000) /*!< Bit 1 */ + +#define GPIO_PH_CFG_PCFG15 ((uint32_t)0xC0000000) /*!< CNF15[1:0] bits (Port x configuration bits, pin 15) */ +#define GPIO_PH_CFG_PCFG15_0 ((uint32_t)0x40000000) /*!< Bit 0 */ +#define GPIO_PH_CFG_PCFG15_1 ((uint32_t)0x80000000) /*!< Bit 1 */ + +/*!<****************** Bit definition for GPIO_PID register *******************/ +#define GPIO_PID_PID0 ((uint16_t)0x0001) /*!< Port input data, bit 0 */ +#define GPIO_PID_PID1 ((uint16_t)0x0002) /*!< Port input data, bit 1 */ +#define GPIO_PID_PID2 ((uint16_t)0x0004) /*!< Port input data, bit 2 */ +#define GPIO_PID_PID3 ((uint16_t)0x0008) /*!< Port input data, bit 3 */ +#define GPIO_PID_PID4 ((uint16_t)0x0010) /*!< Port input data, bit 4 */ +#define GPIO_PID_PID5 ((uint16_t)0x0020) /*!< Port input data, bit 5 */ +#define GPIO_PID_PID6 ((uint16_t)0x0040) /*!< Port input data, bit 6 */ +#define GPIO_PID_PID7 ((uint16_t)0x0080) /*!< Port input data, bit 7 */ +#define GPIO_PID_PID8 ((uint16_t)0x0100) /*!< Port input data, bit 8 */ +#define GPIO_PID_PID9 ((uint16_t)0x0200) /*!< Port input data, bit 9 */ +#define GPIO_PID_PID10 ((uint16_t)0x0400) /*!< Port input data, bit 10 */ +#define GPIO_PID_PID11 ((uint16_t)0x0800) /*!< Port input data, bit 11 */ +#define GPIO_PID_PID12 ((uint16_t)0x1000) /*!< Port input data, bit 12 */ +#define GPIO_PID_PID13 ((uint16_t)0x2000) /*!< Port input data, bit 13 */ +#define GPIO_PID_PID14 ((uint16_t)0x4000) /*!< Port input data, bit 14 */ +#define GPIO_PID_PID15 ((uint16_t)0x8000) /*!< Port input data, bit 15 */ + +/******************* Bit definition for GPIO_POD register *******************/ +#define GPIO_POD_POD0 ((uint16_t)0x0001) /*!< Port output data, bit 0 */ +#define GPIO_POD_POD1 ((uint16_t)0x0002) /*!< Port output data, bit 1 */ +#define GPIO_POD_POD2 ((uint16_t)0x0004) /*!< Port output data, bit 2 */ +#define GPIO_POD_POD3 ((uint16_t)0x0008) /*!< Port output data, bit 3 */ +#define GPIO_POD_POD4 ((uint16_t)0x0010) /*!< Port output data, bit 4 */ +#define GPIO_POD_POD5 ((uint16_t)0x0020) /*!< Port output data, bit 5 */ +#define GPIO_POD_POD6 ((uint16_t)0x0040) /*!< Port output data, bit 6 */ +#define GPIO_POD_POD7 ((uint16_t)0x0080) /*!< Port output data, bit 7 */ +#define GPIO_POD_POD8 ((uint16_t)0x0100) /*!< Port output data, bit 8 */ +#define GPIO_POD_POD9 ((uint16_t)0x0200) /*!< Port output data, bit 9 */ +#define GPIO_POD_POD10 ((uint16_t)0x0400) /*!< Port output data, bit 10 */ +#define GPIO_POD_POD11 ((uint16_t)0x0800) /*!< Port output data, bit 11 */ +#define GPIO_POD_POD12 ((uint16_t)0x1000) /*!< Port output data, bit 12 */ +#define GPIO_POD_POD13 ((uint16_t)0x2000) /*!< Port output data, bit 13 */ +#define GPIO_POD_POD14 ((uint16_t)0x4000) /*!< Port output data, bit 14 */ +#define GPIO_POD_POD15 ((uint16_t)0x8000) /*!< Port output data, bit 15 */ + +/****************** Bit definition for GPIO_PBSC register *******************/ +#define GPIO_PBSC_PBS0 ((uint32_t)0x00000001) /*!< Port x Set bit 0 */ +#define GPIO_PBSC_PBS1 ((uint32_t)0x00000002) /*!< Port x Set bit 1 */ +#define GPIO_PBSC_PBS2 ((uint32_t)0x00000004) /*!< Port x Set bit 2 */ +#define GPIO_PBSC_PBS3 ((uint32_t)0x00000008) /*!< Port x Set bit 3 */ +#define GPIO_PBSC_PBS4 ((uint32_t)0x00000010) /*!< Port x Set bit 4 */ +#define GPIO_PBSC_PBS5 ((uint32_t)0x00000020) /*!< Port x Set bit 5 */ +#define GPIO_PBSC_PBS6 ((uint32_t)0x00000040) /*!< Port x Set bit 6 */ +#define GPIO_PBSC_PBS7 ((uint32_t)0x00000080) /*!< Port x Set bit 7 */ +#define GPIO_PBSC_PBS8 ((uint32_t)0x00000100) /*!< Port x Set bit 8 */ +#define GPIO_PBSC_PBS9 ((uint32_t)0x00000200) /*!< Port x Set bit 9 */ +#define GPIO_PBSC_PBS10 ((uint32_t)0x00000400) /*!< Port x Set bit 10 */ +#define GPIO_PBSC_PBS11 ((uint32_t)0x00000800) /*!< Port x Set bit 11 */ +#define GPIO_PBSC_PBS12 ((uint32_t)0x00001000) /*!< Port x Set bit 12 */ +#define GPIO_PBSC_PBS13 ((uint32_t)0x00002000) /*!< Port x Set bit 13 */ +#define GPIO_PBSC_PBS14 ((uint32_t)0x00004000) /*!< Port x Set bit 14 */ +#define GPIO_PBSC_PBS15 ((uint32_t)0x00008000) /*!< Port x Set bit 15 */ + +#define GPIO_PBSC_PBC0 ((uint32_t)0x00010000) /*!< Port x Reset bit 0 */ +#define GPIO_PBSC_PBC1 ((uint32_t)0x00020000) /*!< Port x Reset bit 1 */ +#define GPIO_PBSC_PBC2 ((uint32_t)0x00040000) /*!< Port x Reset bit 2 */ +#define GPIO_PBSC_PBC3 ((uint32_t)0x00080000) /*!< Port x Reset bit 3 */ +#define GPIO_PBSC_PBC4 ((uint32_t)0x00100000) /*!< Port x Reset bit 4 */ +#define GPIO_PBSC_PBC5 ((uint32_t)0x00200000) /*!< Port x Reset bit 5 */ +#define GPIO_PBSC_PBC6 ((uint32_t)0x00400000) /*!< Port x Reset bit 6 */ +#define GPIO_PBSC_PBC7 ((uint32_t)0x00800000) /*!< Port x Reset bit 7 */ +#define GPIO_PBSC_PBC8 ((uint32_t)0x01000000) /*!< Port x Reset bit 8 */ +#define GPIO_PBSC_PBC9 ((uint32_t)0x02000000) /*!< Port x Reset bit 9 */ +#define GPIO_PBSC_PBC10 ((uint32_t)0x04000000) /*!< Port x Reset bit 10 */ +#define GPIO_PBSC_PBC11 ((uint32_t)0x08000000) /*!< Port x Reset bit 11 */ +#define GPIO_PBSC_PBC12 ((uint32_t)0x10000000) /*!< Port x Reset bit 12 */ +#define GPIO_PBSC_PBC13 ((uint32_t)0x20000000) /*!< Port x Reset bit 13 */ +#define GPIO_PBSC_PBC14 ((uint32_t)0x40000000) /*!< Port x Reset bit 14 */ +#define GPIO_PBSC_PBC15 ((uint32_t)0x80000000) /*!< Port x Reset bit 15 */ + +/******************* Bit definition for GPIO_PBC register *******************/ +#define GPIO_PBC_PBC0 ((uint16_t)0x0001) /*!< Port x Reset bit 0 */ +#define GPIO_PBC_PBC1 ((uint16_t)0x0002) /*!< Port x Reset bit 1 */ +#define GPIO_PBC_PBC2 ((uint16_t)0x0004) /*!< Port x Reset bit 2 */ +#define GPIO_PBC_PBC3 ((uint16_t)0x0008) /*!< Port x Reset bit 3 */ +#define GPIO_PBC_PBC4 ((uint16_t)0x0010) /*!< Port x Reset bit 4 */ +#define GPIO_PBC_PBC5 ((uint16_t)0x0020) /*!< Port x Reset bit 5 */ +#define GPIO_PBC_PBC6 ((uint16_t)0x0040) /*!< Port x Reset bit 6 */ +#define GPIO_PBC_PBC7 ((uint16_t)0x0080) /*!< Port x Reset bit 7 */ +#define GPIO_PBC_PBC8 ((uint16_t)0x0100) /*!< Port x Reset bit 8 */ +#define GPIO_PBC_PBC9 ((uint16_t)0x0200) /*!< Port x Reset bit 9 */ +#define GPIO_PBC_PBC10 ((uint16_t)0x0400) /*!< Port x Reset bit 10 */ +#define GPIO_PBC_PBC11 ((uint16_t)0x0800) /*!< Port x Reset bit 11 */ +#define GPIO_PBC_PBC12 ((uint16_t)0x1000) /*!< Port x Reset bit 12 */ +#define GPIO_PBC_PBC13 ((uint16_t)0x2000) /*!< Port x Reset bit 13 */ +#define GPIO_PBC_PBC14 ((uint16_t)0x4000) /*!< Port x Reset bit 14 */ +#define GPIO_PBC_PBC15 ((uint16_t)0x8000) /*!< Port x Reset bit 15 */ + +/****************** Bit definition for GPIO_PLOCK_CFG register *******************/ +#define GPIO_PLOCK_CFG_PLOCK_CFG0 ((uint32_t)0x00000001) /*!< Port x Lock bit 0 */ +#define GPIO_PLOCK_CFG_PLOCK_CFG1 ((uint32_t)0x00000002) /*!< Port x Lock bit 1 */ +#define GPIO_PLOCK_CFG_PLOCK_CFG2 ((uint32_t)0x00000004) /*!< Port x Lock bit 2 */ +#define GPIO_PLOCK_CFG_PLOCK_CFG3 ((uint32_t)0x00000008) /*!< Port x Lock bit 3 */ +#define GPIO_PLOCK_CFG_PLOCK_CFG4 ((uint32_t)0x00000010) /*!< Port x Lock bit 4 */ +#define GPIO_PLOCK_CFG_PLOCK_CFG5 ((uint32_t)0x00000020) /*!< Port x Lock bit 5 */ +#define GPIO_PLOCK_CFG_PLOCK_CFG6 ((uint32_t)0x00000040) /*!< Port x Lock bit 6 */ +#define GPIO_PLOCK_CFG_PLOCK_CFG7 ((uint32_t)0x00000080) /*!< Port x Lock bit 7 */ +#define GPIO_PLOCK_CFG_PLOCK_CFG8 ((uint32_t)0x00000100) /*!< Port x Lock bit 8 */ +#define GPIO_PLOCK_CFG_PLOCK_CFG9 ((uint32_t)0x00000200) /*!< Port x Lock bit 9 */ +#define GPIO_PLOCK_CFG_PLOCK_CFG10 ((uint32_t)0x00000400) /*!< Port x Lock bit 10 */ +#define GPIO_PLOCK_CFG_PLOCK_CFG11 ((uint32_t)0x00000800) /*!< Port x Lock bit 11 */ +#define GPIO_PLOCK_CFG_PLOCK_CFG12 ((uint32_t)0x00001000) /*!< Port x Lock bit 12 */ +#define GPIO_PLOCK_CFG_PLOCK_CFG13 ((uint32_t)0x00002000) /*!< Port x Lock bit 13 */ +#define GPIO_PLOCK_CFG_PLOCK_CFG14 ((uint32_t)0x00004000) /*!< Port x Lock bit 14 */ +#define GPIO_PLOCK_CFG_PLOCK_CFG15 ((uint32_t)0x00008000) /*!< Port x Lock bit 15 */ +#define GPIO_PLOCK_CFG_PLOCKK_CFG ((uint32_t)0x00010000) /*!< Lock key */ + +/******************* Bit definition for GPIO_DS_CFG register *******************/ +#define GPIO_DS_CFG0 ((uint16_t)0x0001) /*!< Port x Drive bit 0 */ +#define GPIO_DS_CFG1 ((uint16_t)0x0002) /*!< Port x Drive bit 1 */ +#define GPIO_DS_CFG2 ((uint16_t)0x0004) /*!< Port x Drive bit 2 */ +#define GPIO_DS_CFG3 ((uint16_t)0x0008) /*!< Port x Drive bit 3 */ +#define GPIO_DS_CFG4 ((uint16_t)0x0010) /*!< Port x Drive bit 4 */ +#define GPIO_DS_CFG5 ((uint16_t)0x0020) /*!< Port x Drive bit 5 */ +#define GPIO_DS_CFG6 ((uint16_t)0x0040) /*!< Port x Drive bit 6 */ +#define GPIO_DS_CFG7 ((uint16_t)0x0080) /*!< Port x Drive bit 7 */ +#define GPIO_DS_CFG8 ((uint16_t)0x0100) /*!< Port x Drive bit 8 */ +#define GPIO_DS_CFG9 ((uint16_t)0x0200) /*!< Port x Drive bit 9 */ +#define GPIO_DS_CFG10 ((uint16_t)0x0400) /*!< Port x Drive bit 10 */ +#define GPIO_DS_CFG11 ((uint16_t)0x0800) /*!< Port x Drive bit 11 */ +#define GPIO_DS_CFG12 ((uint16_t)0x1000) /*!< Port x Drive bit 12 */ +#define GPIO_DS_CFG13 ((uint16_t)0x2000) /*!< Port x Drive bit 13 */ +#define GPIO_DS_CFG14 ((uint16_t)0x4000) /*!< Port x Drive bit 14 */ +#define GPIO_DS_CFG15 ((uint16_t)0x8000) /*!< Port x Drive bit 15 */ + +/******************* Bit definition for GPIO_SR_CFG register *******************/ +#define GPIO_SR_CFG0 ((uint16_t)0x0001) /*!< Port x Turn bit 0 */ +#define GPIO_SR_CFG1 ((uint16_t)0x0002) /*!< Port x Turn bit 1 */ +#define GPIO_SR_CFG2 ((uint16_t)0x0004) /*!< Port x Turn bit 2 */ +#define GPIO_SR_CFG3 ((uint16_t)0x0008) /*!< Port x Turn bit 3 */ +#define GPIO_SR_CFG4 ((uint16_t)0x0010) /*!< Port x Turn bit 4 */ +#define GPIO_SR_CFG5 ((uint16_t)0x0020) /*!< Port x Turn bit 5 */ +#define GPIO_SR_CFG6 ((uint16_t)0x0040) /*!< Port x Turn bit 6 */ +#define GPIO_SR_CFG7 ((uint16_t)0x0080) /*!< Port x Turn bit 7 */ +#define GPIO_SR_CFG8 ((uint16_t)0x0100) /*!< Port x Turn bit 8 */ +#define GPIO_SR_CFG9 ((uint16_t)0x0200) /*!< Port x Turn bit 9 */ +#define GPIO_SR_CFG10 ((uint16_t)0x0400) /*!< Port x Turn bit 10 */ +#define GPIO_SR_CFG11 ((uint16_t)0x0800) /*!< Port x Turn bit 11 */ +#define GPIO_SR_CFG12 ((uint16_t)0x1000) /*!< Port x Turn bit 12 */ +#define GPIO_SR_CFG13 ((uint16_t)0x2000) /*!< Port x Turn bit 13 */ +#define GPIO_SR_CFG14 ((uint16_t)0x4000) /*!< Port x Turn bit 14 */ +#define GPIO_SR_CFG15 ((uint16_t)0x8000) /*!< Port x Turn bit 15 */ + +/*----------------------------------------------------------------------------*/ + +/****************** Bit definition for AFIO_ECTRL register *******************/ +#define AFIO_ECTRL_PIN_SEL ((uint8_t)0x0F) /*!< PIN[3:0] bits (Pin selection) */ +#define AFIO_ECTRL_PIN_SEL_0 ((uint8_t)0x01) /*!< Bit 0 */ +#define AFIO_ECTRL_PIN_SEL_1 ((uint8_t)0x02) /*!< Bit 1 */ +#define AFIO_ECTRL_PIN_SEL_2 ((uint8_t)0x04) /*!< Bit 2 */ +#define AFIO_ECTRL_PIN_SEL_3 ((uint8_t)0x08) /*!< Bit 3 */ + +/*!< PIN configuration */ +#define AFIO_ECTRL_PIN_SEL_PIN0 ((uint8_t)0x00) /*!< Pin 0 selected */ +#define AFIO_ECTRL_PIN_SEL_PIN1 ((uint8_t)0x01) /*!< Pin 1 selected */ +#define AFIO_ECTRL_PIN_SEL_PIN2 ((uint8_t)0x02) /*!< Pin 2 selected */ +#define AFIO_ECTRL_PIN_SEL_PIN3 ((uint8_t)0x03) /*!< Pin 3 selected */ +#define AFIO_ECTRL_PIN_SEL_PIN4 ((uint8_t)0x04) /*!< Pin 4 selected */ +#define AFIO_ECTRL_PIN_SEL_PIN5 ((uint8_t)0x05) /*!< Pin 5 selected */ +#define AFIO_ECTRL_PIN_SEL_PIN6 ((uint8_t)0x06) /*!< Pin 6 selected */ +#define AFIO_ECTRL_PIN_SEL_PIN7 ((uint8_t)0x07) /*!< Pin 7 selected */ +#define AFIO_ECTRL_PIN_SEL_PIN8 ((uint8_t)0x08) /*!< Pin 8 selected */ +#define AFIO_ECTRL_PIN_SEL_PIN9 ((uint8_t)0x09) /*!< Pin 9 selected */ +#define AFIO_ECTRL_PIN_SEL_PIN10 ((uint8_t)0x0A) /*!< Pin 10 selected */ +#define AFIO_ECTRL_PIN_SEL_PIN11 ((uint8_t)0x0B) /*!< Pin 11 selected */ +#define AFIO_ECTRL_PIN_SEL_PIN12 ((uint8_t)0x0C) /*!< Pin 12 selected */ +#define AFIO_ECTRL_PIN_SEL_PIN13 ((uint8_t)0x0D) /*!< Pin 13 selected */ +#define AFIO_ECTRL_PIN_SEL_PIN14 ((uint8_t)0x0E) /*!< Pin 14 selected */ +#define AFIO_ECTRL_PIN_SEL_PIN15 ((uint8_t)0x0F) /*!< Pin 15 selected */ + +#define AFIO_ECTRL_PORT_SEL ((uint8_t)0x70) /*!< PORT[2:0] bits (Port selection) */ +#define AFIO_ECTRL_PORT_SEL_0 ((uint8_t)0x10) /*!< Bit 0 */ +#define AFIO_ECTRL_PORT_SEL_1 ((uint8_t)0x20) /*!< Bit 1 */ +#define AFIO_ECTRL_PORT_SEL_2 ((uint8_t)0x40) /*!< Bit 2 */ + +/*!< PORT configuration */ +#define AFIO_ECTRL_PORT_SEL_PA ((uint8_t)0x00) /*!< Port A selected */ +#define AFIO_ECTRL_PORT_SEL_PB ((uint8_t)0x10) /*!< Port B selected */ +#define AFIO_ECTRL_PORT_SEL_PC ((uint8_t)0x20) /*!< Port C selected */ +#define AFIO_ECTRL_PORT_SEL_PD ((uint8_t)0x30) /*!< Port D selected */ +#define AFIO_ECTRL_PORT_SEL_PE ((uint8_t)0x40) /*!< Port E selected */ + +#define AFIO_ECTRL_EOE ((uint8_t)0x80) /*!< Event Output Enable */ + +/****************** Bit definition for AFIO_RMP_CFG register *******************/ +#define AFIO_RMP_CFG_SPI1_RMP_0 ((uint32_t)0x00000001) /*!< SPI1_RMP_0 remapping */ +#define AFIO_RMP_CFG_I2C1_RMP ((uint32_t)0x00000002) /*!< I2C1 remapping */ +#define AFIO_RMP_CFG_USART1_RMP ((uint32_t)0x00000004) /*!< USART1 remapping */ +#define AFIO_RMP_CFG_USART2_RMP_0 ((uint32_t)0x00000008) /*!< USART2_RMP_0 remapping */ + +#define AFIO_RMP_CFG_USART3_RMP ((uint32_t)0x00000030) /*!< USART3_REMAP[1:0] bits (USART3 remapping) */ +#define AFIO_RMP_CFG_USART3_RMP_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define AFIO_RMP_CFG_USART3_RMP_1 ((uint32_t)0x00000020) /*!< Bit 1 */ + +/* USART3_REMAP configuration */ +#define AFIO_RMP_CFG_USART3_RMP_NONE \ + ((uint32_t)0x00000000) /*!< No remap (TX/PB10, RX/PB11, CK/PB12, CTS/PB13, RTS/PB14) */ +#define AFIO_RMP_CFG_USART3_RMP_PART \ + ((uint32_t)0x00000010) /*!< Partial remap (TX/PC10, RX/PC11, CK/PC12, CTS/PB13, RTS/PB14) */ +#define AFIO_RMP_CFG_USART3_RMP_ALL \ + ((uint32_t)0x00000030) /*!< Full remap (TX/PD8, RX/PD9, CK/PD10, CTS/PD11, RTS/PD12) */ + +#define AFIO_RMP_CFG_TIM1_RMP ((uint32_t)0x000000C0) /*!< TIM1_REMAP[1:0] bits (TIM1 remapping) */ +#define AFIO_RMP_CFG_TIM1_RMP_0 ((uint32_t)0x00000040) /*!< Bit 0 */ +#define AFIO_RMP_CFG_TIM1_RMP_1 ((uint32_t)0x00000080) /*!< Bit 1 */ + +/*!< TIM1_REMAP configuration */ +#define AFIO_RMP_CFG_TIM1_RMP_NONE \ + ((uint32_t)0x00000000) /*!< No remap (ETR/PA12, CH1/PA8, CH2/PA9, CH3/PA10, CH4/PA11, BKIN/PB12, CH1N/PB13, \ + CH2N/PB14, CH3N/PB15) */ +#define AFIO_RMP_CFG_TIM1_RMP_PART \ + ((uint32_t)0x00000040) /*!< Partial remap (ETR/PA12, CH1/PA8, CH2/PA9, CH3/PA10, CH4/PA11, BKIN/PA6, CH1N/PA7, \ + CH2N/PB0, CH3N/PB1) */ +#define AFIO_RMP_CFG_TIM1_RMP_ALL \ + ((uint32_t)0x000000C0) /*!< Full remap (ETR/PE7, CH1/PE9, CH2/PE11, CH3/PE13, CH4/PE14, BKIN/PE15, CH1N/PE8, \ + CH2N/PE10, CH3N/PE12) */ + +#define AFIO_RMP_CFG_TIM2_RMP ((uint32_t)0x00000300) /*!< TIM2_REMAP[1:0] bits (TIM2 remapping) */ +#define AFIO_RMP_CFG_TIM2_RMP_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define AFIO_RMP_CFG_TIM2_RMP_1 ((uint32_t)0x00000200) /*!< Bit 1 */ + +/*!< TIM2_REMAP configuration */ +#define AFIO_RMP_CFG_TIM2_RMP_NONE ((uint32_t)0x00000000) /*!< No remap (CH1/ETR/PA0, CH2/PA1, CH3/PA2, CH4/PA3) */ +#define AFIO_RMP_CFG_TIM2_RMP_PART1 \ + ((uint32_t)0x00000100) /*!< Partial remap (CH1/ETR/PA15, CH2/PB3, CH3/PA2, CH4/PA3) */ +#define AFIO_RMP_CFG_TIM2_RMP_PART2 \ + ((uint32_t)0x00000200) /*!< Partial remap (CH1/ETR/PA0, CH2/PA1, CH3/PB10, CH4/PB11) */ +#define AFIO_RMP_CFG_TIM2_RMP_ALL \ + ((uint32_t)0x00000300) /*!< Full remap (CH1/ETR/PA15, CH2/PB3, CH3/PB10, CH4/PB11) \ + */ + +#define AFIO_RMP_CFG_TIM3_RMP ((uint32_t)0x00000C00) /*!< TIM3_REMAP[1:0] bits (TIM3 remapping) */ +#define AFIO_RMP_CFG_TIM3_RMP_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define AFIO_RMP_CFG_TIM3_RMP_1 ((uint32_t)0x00000800) /*!< Bit 1 */ + +/*!< TIM3_REMAP configuration */ +#define AFIO_RMP_CFG_TIM3_RMP_NONE ((uint32_t)0x00000000) /*!< No remap (CH1/PA6, CH2/PA7, CH3/PB0, CH4/PB1) */ +#define AFIO_RMP_CFG_TIM3_RMP_PART ((uint32_t)0x00000800) /*!< Partial remap (CH1/PB4, CH2/PB5, CH3/PB0, CH4/PB1) */ +#define AFIO_RMP_CFG_TIM3_RMP_ALL ((uint32_t)0x00000C00) /*!< Full remap (CH1/PC6, CH2/PC7, CH3/PC8, CH4/PC9) */ + +#define AFIO_RMP_CFG_TIM4_RMP ((uint32_t)0x00001000) /*!< TIM4_REMAP bit (TIM4 remapping) */ + +#define AFIO_RMP_CFG_CAN1_RMP ((uint32_t)0x00006000) /*!< CAN1_RMP[1:0] bits (CAN1 Alternate function remapping) */ +#define AFIO_RMP_CFG_CAN1_RMP_0 ((uint32_t)0x00002000) /*!< Bit 0 */ +#define AFIO_RMP_CFG_CAN1_RMP_1 ((uint32_t)0x00004000) /*!< Bit 1 */ + +/*!< CAN1_REMAP configuration */ +#define AFIO_RMP_CFG_CAN1_RMP_RMP1 ((uint32_t)0x00000000) /*!< CAN1RX mapped to PA11, CAN1TX mapped to PA12 */ +#define AFIO_RMP_CFG_CAN1_RMP_RMP2 ((uint32_t)0x00004000) /*!< CAN1RX mapped to PB8, CAN1TX mapped to PB9 */ +#define AFIO_RMP_CFG_CAN1_RMP_RMP3 ((uint32_t)0x00006000) /*!< CAN1RX mapped to PD0, CAN1TX mapped to PD1 */ +#define AFIO_RMP_CFG_CAN1_RMP_RMP4 ((uint32_t)0x00002000) /*!< CAN1RX mapped to PD12, CAN1TX mapped to PD13 */ + +#define AFIO_RMP_CFG_PD01_RMP ((uint32_t)0x00008000) /*!< Port D0/Port D1 mapping on OSC_IN/OSC_OUT */ +#define AFIO_RMP_CFG_TIM5CH4_RMP ((uint32_t)0x00010000) /*!< TIM5 Channel4 Internal Remap */ +#define AFIO_RMP_CFG_ADC1_ETRI_RMP ((uint32_t)0x00020000) /*!< ADC 1 External Trigger Injected Conversion remapping */ +#define AFIO_RMP_CFG_ADC1_ETRR_RMP ((uint32_t)0x00040000) /*!< ADC 1 External Trigger Regular Conversion remapping */ +#define AFIO_RMP_CFG_ADC2_ETRI_RMP ((uint32_t)0x00080000) /*!< ADC 2 External Trigger Injected Conversion remapping */ +#define AFIO_RMP_CFG_ADC2_ETRR_RMP ((uint32_t)0x00100000) /*!< ADC 2 External Trigger Regular Conversion remapping */ +#define AFIO_RMP_CFG_MII_RMII_SEL ((uint32_t)0x00800000) /*!< ETH MAC MII_RMII_SEL remapping */ +/*!< SWJ_CFG configuration */ +#define AFIO_RMP_CFG_SW_JTAG_CFG ((uint32_t)0x07000000) /*!< SWJ_CFG[2:0] bits (Serial Wire JTAG configuration) */ +#define AFIO_RMP_CFG_SW_JTAG_CFG0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define AFIO_RMP_CFG_SW_JTAG_CFG1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define AFIO_RMP_CFG_SW_JTAG_CFG2 ((uint32_t)0x04000000) /*!< Bit 2 */ + +#define AFIO_RMP_CFG_SW_JTAG_CFG_RESET ((uint32_t)0x00000000) /*!< Full SWJ (JTAG-DP + SW-DP) : Reset State */ +#define AFIO_RMP_CFG_SW_JTAG_CFG_NO_NJTRST ((uint32_t)0x01000000) /*!< Full SWJ (JTAG-DP + SW-DP) but without JNTRST \ + */ +#define AFIO_RMP_CFG_SW_JTAG_CFG_SW_ENABLE ((uint32_t)0x02000000) /*!< JTAG-DP Disabled and SW-DP Enabled */ +#define AFIO_RMP_CFG_SW_JTAG_CFG_DISABLE ((uint32_t)0x04000000) /*!< JTAG-DP Disabled and SW-DP Disabled */ + +/***************** Bit definition for AFIO_EXTI_CFG1 register *****************/ +#define AFIO_EXTI_CFG1_EXTI0 ((uint16_t)0x000F) /*!< EXTI 0 configuration */ +#define AFIO_EXTI_CFG1_EXTI1 ((uint16_t)0x00F0) /*!< EXTI 1 configuration */ +#define AFIO_EXTI_CFG1_EXTI2 ((uint16_t)0x0F00) /*!< EXTI 2 configuration */ +#define AFIO_EXTI_CFG1_EXTI3 ((uint16_t)0xF000) /*!< EXTI 3 configuration */ + +/*!< EXTI0 configuration */ +#define AFIO_EXTI_CFG1_EXTI0_PA ((uint16_t)0x0000) /*!< PA[0] pin */ +#define AFIO_EXTI_CFG1_EXTI0_PB ((uint16_t)0x0001) /*!< PB[0] pin */ +#define AFIO_EXTI_CFG1_EXTI0_PC ((uint16_t)0x0002) /*!< PC[0] pin */ +#define AFIO_EXTI_CFG1_EXTI0_PD ((uint16_t)0x0003) /*!< PD[0] pin */ +#define AFIO_EXTI_CFG1_EXTI0_PE ((uint16_t)0x0004) /*!< PE[0] pin */ +#define AFIO_EXTI_CFG1_EXTI0_PF ((uint16_t)0x0005) /*!< PF[0] pin */ +#define AFIO_EXTI_CFG1_EXTI0_PG ((uint16_t)0x0006) /*!< PG[0] pin */ + +/*!< EXTI1 configuration */ +#define AFIO_EXTI_CFG1_EXTI1_PA ((uint16_t)0x0000) /*!< PA[1] pin */ +#define AFIO_EXTI_CFG1_EXTI1_PB ((uint16_t)0x0010) /*!< PB[1] pin */ +#define AFIO_EXTI_CFG1_EXTI1_PC ((uint16_t)0x0020) /*!< PC[1] pin */ +#define AFIO_EXTI_CFG1_EXTI1_PD ((uint16_t)0x0030) /*!< PD[1] pin */ +#define AFIO_EXTI_CFG1_EXTI1_PE ((uint16_t)0x0040) /*!< PE[1] pin */ +#define AFIO_EXTI_CFG1_EXTI1_PF ((uint16_t)0x0050) /*!< PF[1] pin */ +#define AFIO_EXTI_CFG1_EXTI1_PG ((uint16_t)0x0060) /*!< PG[1] pin */ + +/*!< EXTI2 configuration */ +#define AFIO_EXTI_CFG1_EXTI2_PA ((uint16_t)0x0000) /*!< PA[2] pin */ +#define AFIO_EXTI_CFG1_EXTI2_PB ((uint16_t)0x0100) /*!< PB[2] pin */ +#define AFIO_EXTI_CFG1_EXTI2_PC ((uint16_t)0x0200) /*!< PC[2] pin */ +#define AFIO_EXTI_CFG1_EXTI2_PD ((uint16_t)0x0300) /*!< PD[2] pin */ +#define AFIO_EXTI_CFG1_EXTI2_PE ((uint16_t)0x0400) /*!< PE[2] pin */ +#define AFIO_EXTI_CFG1_EXTI2_PF ((uint16_t)0x0500) /*!< PF[2] pin */ +#define AFIO_EXTI_CFG1_EXTI2_PG ((uint16_t)0x0600) /*!< PG[2] pin */ + +/*!< EXTI3 configuration */ +#define AFIO_EXTI_CFG1_EXTI3_PA ((uint16_t)0x0000) /*!< PA[3] pin */ +#define AFIO_EXTI_CFG1_EXTI3_PB ((uint16_t)0x1000) /*!< PB[3] pin */ +#define AFIO_EXTI_CFG1_EXTI3_PC ((uint16_t)0x2000) /*!< PC[3] pin */ +#define AFIO_EXTI_CFG1_EXTI3_PD ((uint16_t)0x3000) /*!< PD[3] pin */ +#define AFIO_EXTI_CFG1_EXTI3_PE ((uint16_t)0x4000) /*!< PE[3] pin */ +#define AFIO_EXTI_CFG1_EXTI3_PF ((uint16_t)0x5000) /*!< PF[3] pin */ +#define AFIO_EXTI_CFG1_EXTI3_PG ((uint16_t)0x6000) /*!< PG[3] pin */ + +/***************** Bit definition for AFIO_EXTI_CFG2 register *****************/ +#define AFIO_EXTI_CFG2_EXTI4 ((uint16_t)0x000F) /*!< EXTI 4 configuration */ +#define AFIO_EXTI_CFG2_EXTI5 ((uint16_t)0x00F0) /*!< EXTI 5 configuration */ +#define AFIO_EXTI_CFG2_EXTI6 ((uint16_t)0x0F00) /*!< EXTI 6 configuration */ +#define AFIO_EXTI_CFG2_EXTI7 ((uint16_t)0xF000) /*!< EXTI 7 configuration */ + +/*!< EXTI4 configuration */ +#define AFIO_EXTI_CFG2_EXTI4_PA ((uint16_t)0x0000) /*!< PA[4] pin */ +#define AFIO_EXTI_CFG2_EXTI4_PB ((uint16_t)0x0001) /*!< PB[4] pin */ +#define AFIO_EXTI_CFG2_EXTI4_PC ((uint16_t)0x0002) /*!< PC[4] pin */ +#define AFIO_EXTI_CFG2_EXTI4_PD ((uint16_t)0x0003) /*!< PD[4] pin */ +#define AFIO_EXTI_CFG2_EXTI4_PE ((uint16_t)0x0004) /*!< PE[4] pin */ +#define AFIO_EXTI_CFG2_EXTI4_PF ((uint16_t)0x0005) /*!< PF[4] pin */ +#define AFIO_EXTI_CFG2_EXTI4_PG ((uint16_t)0x0006) /*!< PG[4] pin */ + +/* EXTI5 configuration */ +#define AFIO_EXTI_CFG2_EXTI5_PA ((uint16_t)0x0000) /*!< PA[5] pin */ +#define AFIO_EXTI_CFG2_EXTI5_PB ((uint16_t)0x0010) /*!< PB[5] pin */ +#define AFIO_EXTI_CFG2_EXTI5_PC ((uint16_t)0x0020) /*!< PC[5] pin */ +#define AFIO_EXTI_CFG2_EXTI5_PD ((uint16_t)0x0030) /*!< PD[5] pin */ +#define AFIO_EXTI_CFG2_EXTI5_PE ((uint16_t)0x0040) /*!< PE[5] pin */ +#define AFIO_EXTI_CFG2_EXTI5_PF ((uint16_t)0x0050) /*!< PF[5] pin */ +#define AFIO_EXTI_CFG2_EXTI5_PG ((uint16_t)0x0060) /*!< PG[5] pin */ + +/*!< EXTI6 configuration */ +#define AFIO_EXTI_CFG2_EXTI6_PA ((uint16_t)0x0000) /*!< PA[6] pin */ +#define AFIO_EXTI_CFG2_EXTI6_PB ((uint16_t)0x0100) /*!< PB[6] pin */ +#define AFIO_EXTI_CFG2_EXTI6_PC ((uint16_t)0x0200) /*!< PC[6] pin */ +#define AFIO_EXTI_CFG2_EXTI6_PD ((uint16_t)0x0300) /*!< PD[6] pin */ +#define AFIO_EXTI_CFG2_EXTI6_PE ((uint16_t)0x0400) /*!< PE[6] pin */ +#define AFIO_EXTI_CFG2_EXTI6_PF ((uint16_t)0x0500) /*!< PF[6] pin */ +#define AFIO_EXTI_CFG2_EXTI6_PG ((uint16_t)0x0600) /*!< PG[6] pin */ + +/*!< EXTI7 configuration */ +#define AFIO_EXTI_CFG2_EXTI7_PA ((uint16_t)0x0000) /*!< PA[7] pin */ +#define AFIO_EXTI_CFG2_EXTI7_PB ((uint16_t)0x1000) /*!< PB[7] pin */ +#define AFIO_EXTI_CFG2_EXTI7_PC ((uint16_t)0x2000) /*!< PC[7] pin */ +#define AFIO_EXTI_CFG2_EXTI7_PD ((uint16_t)0x3000) /*!< PD[7] pin */ +#define AFIO_EXTI_CFG2_EXTI7_PE ((uint16_t)0x4000) /*!< PE[7] pin */ +#define AFIO_EXTI_CFG2_EXTI7_PF ((uint16_t)0x5000) /*!< PF[7] pin */ +#define AFIO_EXTI_CFG2_EXTI7_PG ((uint16_t)0x6000) /*!< PG[7] pin */ + +/***************** Bit definition for AFIO_EXTI_CFG3 register *****************/ +#define AFIO_EXTI_CFG3_EXTI8 ((uint16_t)0x000F) /*!< EXTI 8 configuration */ +#define AFIO_EXTI_CFG3_EXTI9 ((uint16_t)0x00F0) /*!< EXTI 9 configuration */ +#define AFIO_EXTI_CFG3_EXTI10 ((uint16_t)0x0F00) /*!< EXTI 10 configuration */ +#define AFIO_EXTI_CFG3_EXTI11 ((uint16_t)0xF000) /*!< EXTI 11 configuration */ + +/*!< EXTI8 configuration */ +#define AFIO_EXTI_CFG3_EXTI8_PA ((uint16_t)0x0000) /*!< PA[8] pin */ +#define AFIO_EXTI_CFG3_EXTI8_PB ((uint16_t)0x0001) /*!< PB[8] pin */ +#define AFIO_EXTI_CFG3_EXTI8_PC ((uint16_t)0x0002) /*!< PC[8] pin */ +#define AFIO_EXTI_CFG3_EXTI8_PD ((uint16_t)0x0003) /*!< PD[8] pin */ +#define AFIO_EXTI_CFG3_EXTI8_PE ((uint16_t)0x0004) /*!< PE[8] pin */ +#define AFIO_EXTI_CFG3_EXTI8_PF ((uint16_t)0x0005) /*!< PF[8] pin */ +#define AFIO_EXTI_CFG3_EXTI8_PG ((uint16_t)0x0006) /*!< PG[8] pin */ + +/*!< EXTI9 configuration */ +#define AFIO_EXTI_CFG3_EXTI9_PA ((uint16_t)0x0000) /*!< PA[9] pin */ +#define AFIO_EXTI_CFG3_EXTI9_PB ((uint16_t)0x0010) /*!< PB[9] pin */ +#define AFIO_EXTI_CFG3_EXTI9_PC ((uint16_t)0x0020) /*!< PC[9] pin */ +#define AFIO_EXTI_CFG3_EXTI9_PD ((uint16_t)0x0030) /*!< PD[9] pin */ +#define AFIO_EXTI_CFG3_EXTI9_PE ((uint16_t)0x0040) /*!< PE[9] pin */ +#define AFIO_EXTI_CFG3_EXTI9_PF ((uint16_t)0x0050) /*!< PF[9] pin */ +#define AFIO_EXTI_CFG3_EXTI9_PG ((uint16_t)0x0060) /*!< PG[9] pin */ + +/*!< EXTI10 configuration */ +#define AFIO_EXTI_CFG3_EXTI10_PA ((uint16_t)0x0000) /*!< PA[10] pin */ +#define AFIO_EXTI_CFG3_EXTI10_PB ((uint16_t)0x0100) /*!< PB[10] pin */ +#define AFIO_EXTI_CFG3_EXTI10_PC ((uint16_t)0x0200) /*!< PC[10] pin */ +#define AFIO_EXTI_CFG3_EXTI10_PD ((uint16_t)0x0300) /*!< PD[10] pin */ +#define AFIO_EXTI_CFG3_EXTI10_PE ((uint16_t)0x0400) /*!< PE[10] pin */ +#define AFIO_EXTI_CFG3_EXTI10_PF ((uint16_t)0x0500) /*!< PF[10] pin */ +#define AFIO_EXTI_CFG3_EXTI10_PG ((uint16_t)0x0600) /*!< PG[10] pin */ + +/*!< EXTI11 configuration */ +#define AFIO_EXTI_CFG3_EXTI11_PA ((uint16_t)0x0000) /*!< PA[11] pin */ +#define AFIO_EXTI_CFG3_EXTI11_PB ((uint16_t)0x1000) /*!< PB[11] pin */ +#define AFIO_EXTI_CFG3_EXTI11_PC ((uint16_t)0x2000) /*!< PC[11] pin */ +#define AFIO_EXTI_CFG3_EXTI11_PD ((uint16_t)0x3000) /*!< PD[11] pin */ +#define AFIO_EXTI_CFG3_EXTI11_PE ((uint16_t)0x4000) /*!< PE[11] pin */ +#define AFIO_EXTI_CFG3_EXTI11_PF ((uint16_t)0x5000) /*!< PF[11] pin */ +#define AFIO_EXTI_CFG3_EXTI11_PG ((uint16_t)0x6000) /*!< PG[11] pin */ + +/***************** Bit definition for AFIO_EXTI_CFG4 register *****************/ +#define AFIO_EXTI_CFG4_EXTI12 ((uint16_t)0x000F) /*!< EXTI 12 configuration */ +#define AFIO_EXTI_CFG4_EXTI13 ((uint16_t)0x00F0) /*!< EXTI 13 configuration */ +#define AFIO_EXTI_CFG4_EXTI14 ((uint16_t)0x0F00) /*!< EXTI 14 configuration */ +#define AFIO_EXTI_CFG4_EXTI15 ((uint16_t)0xF000) /*!< EXTI 15 configuration */ + +/* EXTI12 configuration */ +#define AFIO_EXTI_CFG4_EXTI12_PA ((uint16_t)0x0000) /*!< PA[12] pin */ +#define AFIO_EXTI_CFG4_EXTI12_PB ((uint16_t)0x0001) /*!< PB[12] pin */ +#define AFIO_EXTI_CFG4_EXTI12_PC ((uint16_t)0x0002) /*!< PC[12] pin */ +#define AFIO_EXTI_CFG4_EXTI12_PD ((uint16_t)0x0003) /*!< PD[12] pin */ +#define AFIO_EXTI_CFG4_EXTI12_PE ((uint16_t)0x0004) /*!< PE[12] pin */ +#define AFIO_EXTI_CFG4_EXTI12_PF ((uint16_t)0x0005) /*!< PF[12] pin */ +#define AFIO_EXTI_CFG4_EXTI12_PG ((uint16_t)0x0006) /*!< PG[12] pin */ + +/* EXTI13 configuration */ +#define AFIO_EXTI_CFG4_EXTI13_PA ((uint16_t)0x0000) /*!< PA[13] pin */ +#define AFIO_EXTI_CFG4_EXTI13_PB ((uint16_t)0x0010) /*!< PB[13] pin */ +#define AFIO_EXTI_CFG4_EXTI13_PC ((uint16_t)0x0020) /*!< PC[13] pin */ +#define AFIO_EXTI_CFG4_EXTI13_PD ((uint16_t)0x0030) /*!< PD[13] pin */ +#define AFIO_EXTI_CFG4_EXTI13_PE ((uint16_t)0x0040) /*!< PE[13] pin */ +#define AFIO_EXTI_CFG4_EXTI13_PF ((uint16_t)0x0050) /*!< PF[13] pin */ +#define AFIO_EXTI_CFG4_EXTI13_PG ((uint16_t)0x0060) /*!< PG[13] pin */ + +/*!< EXTI14 configuration */ +#define AFIO_EXTI_CFG4_EXTI14_PA ((uint16_t)0x0000) /*!< PA[14] pin */ +#define AFIO_EXTI_CFG4_EXTI14_PB ((uint16_t)0x0100) /*!< PB[14] pin */ +#define AFIO_EXTI_CFG4_EXTI14_PC ((uint16_t)0x0200) /*!< PC[14] pin */ +#define AFIO_EXTI_CFG4_EXTI14_PD ((uint16_t)0x0300) /*!< PD[14] pin */ +#define AFIO_EXTI_CFG4_EXTI14_PE ((uint16_t)0x0400) /*!< PE[14] pin */ +#define AFIO_EXTI_CFG4_EXTI14_PF ((uint16_t)0x0500) /*!< PF[14] pin */ +#define AFIO_EXTI_CFG4_EXTI14_PG ((uint16_t)0x0600) /*!< PG[14] pin */ + +/*!< EXTI15 configuration */ +#define AFIO_EXTI_CFG4_EXTI15_PA ((uint16_t)0x0000) /*!< PA[15] pin */ +#define AFIO_EXTI_CFG4_EXTI15_PB ((uint16_t)0x1000) /*!< PB[15] pin */ +#define AFIO_EXTI_CFG4_EXTI15_PC ((uint16_t)0x2000) /*!< PC[15] pin */ +#define AFIO_EXTI_CFG4_EXTI15_PD ((uint16_t)0x3000) /*!< PD[15] pin */ +#define AFIO_EXTI_CFG4_EXTI15_PE ((uint16_t)0x4000) /*!< PE[15] pin */ +#define AFIO_EXTI_CFG4_EXTI15_PF ((uint16_t)0x5000) /*!< PF[15] pin */ +#define AFIO_EXTI_CFG4_EXTI15_PG ((uint16_t)0x6000) /*!< PG[15] pin */ + +/****************** Bit definition for AFIO_RMP_CFG3 register *******************/ +#define AFIO_RMP_CFG3_SDIO_RMP ((uint32_t)0x00000001) /*!< SDIO remapping */ +#define AFIO_RMP_CFG3_CAN2_RMP ((uint32_t)0x00000006) /*!FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM AT> FLASH + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(4); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(4); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/startup/startup_n32g4fr.s b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/startup/startup_n32g4fr.s new file mode 100644 index 0000000000..f8e1075112 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/startup/startup_n32g4fr.s @@ -0,0 +1,426 @@ +; **************************************************************************** +; Copyright (c) 2019, Nations Technologies Inc. +; +; All rights reserved. +; **************************************************************************** +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; - Redistributions of source code must retain the above copyright notice, +; this list of conditions and the disclaimer below. +; +; Nations' name may not be used to endorse or promote products derived from +; this software without specific prior written permission. +; +; DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR +; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE +; DISCLAIMED. IN NO EVENT SHALL NATIONS 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. +; **************************************************************************** + +; 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 0x00001500 + + 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 0x00000300 + + 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_IRQHandler ; PVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Tamper + DCD RTC_WKUP_IRQHandler ; RTC_WKUP + DCD FLASH_IRQHandler ; Flash + DCD RCC_IRQHandler ; RCC + DCD EXTI0_IRQHandler ; EXTI Line 0 + DCD EXTI1_IRQHandler ; EXTI Line 1 + DCD EXTI2_IRQHandler ; EXTI Line 2 + DCD EXTI3_IRQHandler ; EXTI Line 3 + DCD EXTI4_IRQHandler ; EXTI Line 4 + 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 USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TX + DCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; CAN1 RX1 + DCD CAN1_SCE_IRQHandler ; CAN1 SCE + DCD EXTI9_5_IRQHandler ; EXTI Line 9..5 + DCD TIM1_BRK_IRQHandler ; TIM1 Break + DCD TIM1_UP_IRQHandler ; TIM1 Update + DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation + 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/I2S2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_IRQHandler ; USART3 + DCD EXTI15_10_IRQHandler ; EXTI Line 15..10 + DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line + DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend + DCD TIM8_BRK_IRQHandler ; TIM8 Break + DCD TIM8_UP_IRQHandler ; TIM8 Update + DCD TIM8_TRG_COM_IRQHandler ; TIM8 Trigger and Commutation + DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare + DCD RESERVE47_IRQHandler ; RESERVE47 + DCD RESERVE48_IRQHandler ; RESERVE48 + DCD SDIO_IRQHandler ; SDIO + DCD TIM5_IRQHandler ; TIM5 + DCD SPI3_IRQHandler ; SPI3/I2S3 + DCD UART4_IRQHandler ; UART4 + DCD UART5_IRQHandler ; UART5 + DCD TIM6_IRQHandler ; TIM6 + DCD TIM7_IRQHandler ; TIM7 + DCD DMA2_Channel1_IRQHandler ; DMA2 Channel1 + DCD DMA2_Channel2_IRQHandler ; DMA2 Channel2 + DCD DMA2_Channel3_IRQHandler ; DMA2 Channel3 + DCD DMA2_Channel4_IRQHandler ; DMA2 Channel4 + DCD DMA2_Channel5_IRQHandler ; DMA2 Channel5 + DCD RESERVE61_IRQHandler ; RESERVE61 + DCD RESERVE62_IRQHandler ; RESERVE62 + DCD CAN2_TX_IRQHandler ; CAN2 TX + DCD CAN2_RX0_IRQHandler ; CAN2 RX0 + DCD CAN2_RX1_IRQHandler ; CAN2 RX1 + DCD CAN2_SCE_IRQHandler ; CAN2 SCE + DCD QSPI_IRQHandler ; QSPI + DCD DMA2_Channel6_IRQHandler ; DMA2 Channel6 + DCD DMA2_Channel7_IRQHandler ; DMA2 Channel7 + DCD I2C3_EV_IRQHandler ; I2C3 event + DCD I2C3_ER_IRQHandler ; I2C3 error + DCD I2C4_EV_IRQHandler ; I2C4 event + DCD I2C4_ER_IRQHandler ; I2C4 error + DCD UART6_IRQHandler ; UART6 + DCD UART7_IRQHandler ; UART7 + DCD DMA1_Channel8_IRQHandler ; DMA1 Channel8 + DCD DMA2_Channel8_IRQHandler ; DMA2 Channel8 + DCD DVP_IRQHandler ; DVP + DCD SAC_IRQHandler ; SAC + DCD MMU_IRQHandler ; MMU + DCD TSC_IRQHandler ; TSC + DCD RESERVE82_IRQHandler ; RESERVE82 + DCD RESERVE83_IRQHandler ; RESERVE83 + DCD RESERVE84_IRQHandler ; RESERVE84 + DCD RSRAM_IRQHandler ; R-SRAM parity error interrupt +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + 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_IRQHandler [WEAK] + EXPORT TAMPER_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 USB_HP_CAN1_TX_IRQHandler [WEAK] + EXPORT USB_LP_CAN1_RX0_IRQHandler [WEAK] + EXPORT CAN1_RX1_IRQHandler [WEAK] + EXPORT CAN1_SCE_IRQHandler [WEAK] + EXPORT EXTI9_5_IRQHandler [WEAK] + EXPORT TIM1_BRK_IRQHandler [WEAK] + EXPORT TIM1_UP_IRQHandler [WEAK] + EXPORT TIM1_TRG_COM_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 RTCAlarm_IRQHandler [WEAK] + EXPORT USBWakeUp_IRQHandler [WEAK] + EXPORT TIM8_BRK_IRQHandler [WEAK] + EXPORT TIM8_UP_IRQHandler [WEAK] + EXPORT TIM8_TRG_COM_IRQHandler [WEAK] + EXPORT TIM8_CC_IRQHandler [WEAK] + EXPORT SDIO_IRQHandler [WEAK] + EXPORT TIM5_IRQHandler [WEAK] + EXPORT SPI3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT UART5_IRQHandler [WEAK] + EXPORT TIM6_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 CAN2_TX_IRQHandler [WEAK] + EXPORT CAN2_RX0_IRQHandler [WEAK] + EXPORT CAN2_RX1_IRQHandler [WEAK] + EXPORT CAN2_SCE_IRQHandler [WEAK] + EXPORT QSPI_IRQHandler [WEAK] + EXPORT DMA2_Channel6_IRQHandler [WEAK] + EXPORT DMA2_Channel7_IRQHandler [WEAK] + EXPORT I2C3_EV_IRQHandler [WEAK] + EXPORT I2C3_ER_IRQHandler [WEAK] + EXPORT I2C4_EV_IRQHandler [WEAK] + EXPORT I2C4_ER_IRQHandler [WEAK] + EXPORT UART6_IRQHandler [WEAK] + EXPORT UART7_IRQHandler [WEAK] + EXPORT DMA1_Channel8_IRQHandler [WEAK] + EXPORT DMA2_Channel8_IRQHandler [WEAK] + EXPORT DVP_IRQHandler [WEAK] + EXPORT SAC_IRQHandler [WEAK] + EXPORT MMU_IRQHandler [WEAK] + EXPORT TSC_IRQHandler [WEAK] + EXPORT RSRAM_IRQHandler [WEAK] + +WWDG_IRQHandler +PVD_IRQHandler +TAMPER_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 +USB_HP_CAN1_TX_IRQHandler +USB_LP_CAN1_RX0_IRQHandler +CAN1_RX1_IRQHandler +CAN1_SCE_IRQHandler +EXTI9_5_IRQHandler +TIM1_BRK_IRQHandler +TIM1_UP_IRQHandler +TIM1_TRG_COM_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 +RTCAlarm_IRQHandler +USBWakeUp_IRQHandler +TIM8_BRK_IRQHandler +TIM8_UP_IRQHandler +TIM8_TRG_COM_IRQHandler +TIM8_CC_IRQHandler +RESERVE47_IRQHandler +RESERVE48_IRQHandler +SDIO_IRQHandler +TIM5_IRQHandler +SPI3_IRQHandler +UART4_IRQHandler +UART5_IRQHandler +TIM6_IRQHandler +TIM7_IRQHandler +DMA2_Channel1_IRQHandler +DMA2_Channel2_IRQHandler +DMA2_Channel3_IRQHandler +DMA2_Channel4_IRQHandler +DMA2_Channel5_IRQHandler +RESERVE61_IRQHandler +RESERVE62_IRQHandler +CAN2_TX_IRQHandler +CAN2_RX0_IRQHandler +CAN2_RX1_IRQHandler +CAN2_SCE_IRQHandler +QSPI_IRQHandler +DMA2_Channel6_IRQHandler +DMA2_Channel7_IRQHandler +I2C3_EV_IRQHandler +I2C3_ER_IRQHandler +I2C4_EV_IRQHandler +I2C4_ER_IRQHandler +UART6_IRQHandler +UART7_IRQHandler +DMA1_Channel8_IRQHandler +DMA2_Channel8_IRQHandler +DVP_IRQHandler +SAC_IRQHandler +MMU_IRQHandler +TSC_IRQHandler +RESERVE82_IRQHandler +RESERVE83_IRQHandler +RESERVE84_IRQHandler +RSRAM_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/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/startup/startup_n32g4fr_EWARM.s b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/startup/startup_n32g4fr_EWARM.s new file mode 100644 index 0000000000..e87759457c --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/startup/startup_n32g4fr_EWARM.s @@ -0,0 +1,612 @@ +; **************************************************************************** +; Copyright (c) 2019, Nations Technologies Inc. +; +; All rights reserved. +; **************************************************************************** +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; - Redistributions of source code must retain the above copyright notice, +; this list of conditions and the disclaimer below. +; +; Nations name may not be used to endorse or promote products derived from +; this software without specific prior written permission. +; +; DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR +; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE +; DISCLAIMED. IN NO EVENT SHALL NATIONS 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. +; **************************************************************************** + +; Amount of memory (in bytes) allocated for Stack +; Tailor this value to your application needs +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + + DATA + +__vector_table + DCD sfe(CSTACK) + 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_IRQHandler ; PVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Tamper + DCD RTC_WKUP_IRQHandler ; RTC + DCD FLASH_IRQHandler ; Flash + DCD RCC_IRQHandler ; RCC + DCD EXTI0_IRQHandler ; EXTI Line 0 + DCD EXTI1_IRQHandler ; EXTI Line 1 + DCD EXTI2_IRQHandler ; EXTI Line 2 + DCD EXTI3_IRQHandler ; EXTI Line 3 + DCD EXTI4_IRQHandler ; EXTI Line 4 + 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 USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TX + DCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; CAN1 RX1 + DCD CAN1_SCE_IRQHandler ; CAN1 SCE + DCD EXTI9_5_IRQHandler ; EXTI Line 9..5 + DCD TIM1_BRK_IRQHandler ; TIM1 Break + DCD TIM1_UP_IRQHandler ; TIM1 Update + DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation + 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 ; EXTI Line 15..10 + DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line + DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend + DCD TIM8_BRK_IRQHandler ; TIM8 Break + DCD TIM8_UP_IRQHandler ; TIM8 Update + DCD TIM8_TRG_COM_IRQHandler ; TIM8 Trigger and Commutation + DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare + DCD DEFAULT_IRQHandler ; RESERVE47 + DCD DEFAULT_IRQHandler ; RESERVE48 + DCD SDIO_IRQHandler ; SDIO + DCD TIM5_IRQHandler ; TIM5 + DCD SPI3_IRQHandler ; SPI3 + DCD UART4_IRQHandler ; UART4 + DCD UART5_IRQHandler ; UART5 + DCD TIM6_IRQHandler ; TIM6 + DCD TIM7_IRQHandler ; TIM7 + DCD DMA2_Channel1_IRQHandler ; DMA2 Channel1 + DCD DMA2_Channel2_IRQHandler ; DMA2 Channel2 + DCD DMA2_Channel3_IRQHandler ; DMA2 Channel3 + DCD DMA2_Channel4_IRQHandler ; DMA2 Channel4 + DCD DMA2_Channel5_IRQHandler ; DMA2 Channel5 + DCD DEFAULT_IRQHandler ; RESERVE61 + DCD DEFAULT_IRQHandler ; RESERVE62 + DCD CAN2_TX_IRQHandler ; CAN2 TX + DCD CAN2_RX0_IRQHandler ; CAN2 RX0 + DCD CAN2_RX1_IRQHandler ; CAN2 RX1 + DCD CAN2_SCE_IRQHandler ; CAN2 SCE + DCD QSPI_IRQHandler ; QSPI + DCD DMA2_Channel6_IRQHandler ; DMA2 Channel6 + DCD DMA2_Channel7_IRQHandler ; DMA2 Channel7 + DCD I2C3_EV_IRQHandler ; I2C3 event + DCD I2C3_ER_IRQHandler ; I2C3 error + DCD I2C4_EV_IRQHandler ; I2C4 event + DCD I2C4_ER_IRQHandler ; I2C4 error + DCD UART6_IRQHandler ; UART6 + DCD UART7_IRQHandler ; UART7 + DCD DMA1_Channel8_IRQHandler ; DMA1 Channel8 + DCD DMA2_Channel8_IRQHandler ; DMA2 Channel8 + DCD DVP_IRQHandler ; DVP + DCD SAC_IRQHandler ; SAC + DCD MMU_IRQHandler ; MMU + DCD TSC_IRQHandler ; TSC + DCD DEFAULT_IRQHandler ; RESERVE82 + DCD DEFAULT_IRQHandler ; RESERVE83 + DCD DEFAULT_IRQHandler ; RESERVE84 + DCD RSRAM_IRQHandler ; R-SRAM parity error interrupt +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:REORDER:NOROOT(2) +Reset_Handler + LDR R0, =SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK MemManage_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +MemManage_Handler + B MemManage_Handler + + PUBWEAK BusFault_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +BusFault_Handler + B BusFault_Handler + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +UsageFault_Handler + B UsageFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDG_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +WWDG_IRQHandler + B WWDG_IRQHandler + + PUBWEAK PVD_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +PVD_IRQHandler + B PVD_IRQHandler + + PUBWEAK TAMPER_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TAMPER_IRQHandler + B TAMPER_IRQHandler + + PUBWEAK RTC_WKUP_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +RTC_WKUP_IRQHandler + B RTC_WKUP_IRQHandler + + PUBWEAK FLASH_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +FLASH_IRQHandler + B FLASH_IRQHandler + + PUBWEAK RCC_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +RCC_IRQHandler + B RCC_IRQHandler + + PUBWEAK EXTI0_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +EXTI0_IRQHandler + B EXTI0_IRQHandler + + PUBWEAK EXTI1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +EXTI1_IRQHandler + B EXTI1_IRQHandler + + PUBWEAK EXTI2_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +EXTI2_IRQHandler + B EXTI2_IRQHandler + + PUBWEAK EXTI3_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +EXTI3_IRQHandler + B EXTI3_IRQHandler + + PUBWEAK EXTI4_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +EXTI4_IRQHandler + B EXTI4_IRQHandler + + PUBWEAK DMA1_Channel1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DMA1_Channel1_IRQHandler + B DMA1_Channel1_IRQHandler + + PUBWEAK DMA1_Channel2_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DMA1_Channel2_IRQHandler + B DMA1_Channel2_IRQHandler + + PUBWEAK DMA1_Channel3_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DMA1_Channel3_IRQHandler + B DMA1_Channel3_IRQHandler + + PUBWEAK DMA1_Channel4_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DMA1_Channel4_IRQHandler + B DMA1_Channel4_IRQHandler + + PUBWEAK DMA1_Channel5_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DMA1_Channel5_IRQHandler + B DMA1_Channel5_IRQHandler + + PUBWEAK DMA1_Channel6_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DMA1_Channel6_IRQHandler + B DMA1_Channel6_IRQHandler + + PUBWEAK DMA1_Channel7_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DMA1_Channel7_IRQHandler + B DMA1_Channel7_IRQHandler + + PUBWEAK ADC1_2_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ADC1_2_IRQHandler + B ADC1_2_IRQHandler + + PUBWEAK USB_HP_CAN1_TX_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +USB_HP_CAN1_TX_IRQHandler + B USB_HP_CAN1_TX_IRQHandler + + PUBWEAK USB_LP_CAN1_RX0_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +USB_LP_CAN1_RX0_IRQHandler + B USB_LP_CAN1_RX0_IRQHandler + + PUBWEAK CAN1_RX1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +CAN1_RX1_IRQHandler + B CAN1_RX1_IRQHandler + + PUBWEAK CAN1_SCE_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +CAN1_SCE_IRQHandler + B CAN1_SCE_IRQHandler + + PUBWEAK EXTI9_5_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +EXTI9_5_IRQHandler + B EXTI9_5_IRQHandler + + PUBWEAK TIM1_BRK_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TIM1_BRK_IRQHandler + B TIM1_BRK_IRQHandler + + PUBWEAK TIM1_UP_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TIM1_UP_IRQHandler + B TIM1_UP_IRQHandler + + PUBWEAK TIM1_TRG_COM_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TIM1_TRG_COM_IRQHandler + B TIM1_TRG_COM_IRQHandler + + PUBWEAK TIM1_CC_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TIM1_CC_IRQHandler + B TIM1_CC_IRQHandler + + PUBWEAK TIM2_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TIM2_IRQHandler + B TIM2_IRQHandler + + PUBWEAK TIM3_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TIM3_IRQHandler + B TIM3_IRQHandler + + PUBWEAK TIM4_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TIM4_IRQHandler + B TIM4_IRQHandler + + PUBWEAK I2C1_EV_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +I2C1_EV_IRQHandler + B I2C1_EV_IRQHandler + + PUBWEAK I2C1_ER_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +I2C1_ER_IRQHandler + B I2C1_ER_IRQHandler + + PUBWEAK I2C2_EV_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +I2C2_EV_IRQHandler + B I2C2_EV_IRQHandler + + PUBWEAK I2C2_ER_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +I2C2_ER_IRQHandler + B I2C2_ER_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK USART3_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +USART3_IRQHandler + B USART3_IRQHandler + + PUBWEAK EXTI15_10_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +EXTI15_10_IRQHandler + B EXTI15_10_IRQHandler + + PUBWEAK RTCAlarm_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +RTCAlarm_IRQHandler + B RTCAlarm_IRQHandler + + PUBWEAK USBWakeUp_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +USBWakeUp_IRQHandler + B USBWakeUp_IRQHandler + + PUBWEAK TIM8_BRK_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TIM8_BRK_IRQHandler + B TIM8_BRK_IRQHandler + + PUBWEAK TIM8_UP_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TIM8_UP_IRQHandler + B TIM8_UP_IRQHandler + + PUBWEAK TIM8_TRG_COM_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TIM8_TRG_COM_IRQHandler + B TIM8_TRG_COM_IRQHandler + + PUBWEAK TIM8_CC_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TIM8_CC_IRQHandler + B TIM8_CC_IRQHandler + + PUBWEAK SDIO_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +SDIO_IRQHandler + B SDIO_IRQHandler + + PUBWEAK TIM5_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TIM5_IRQHandler + B TIM5_IRQHandler + + PUBWEAK SPI3_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +SPI3_IRQHandler + B SPI3_IRQHandler + + PUBWEAK UART4_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +UART4_IRQHandler + B UART4_IRQHandler + + PUBWEAK UART5_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +UART5_IRQHandler + B UART5_IRQHandler + + PUBWEAK TIM6_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TIM6_IRQHandler + B TIM6_IRQHandler + + PUBWEAK TIM7_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TIM7_IRQHandler + B TIM7_IRQHandler + + PUBWEAK DMA2_Channel1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DMA2_Channel1_IRQHandler + B DMA2_Channel1_IRQHandler + + PUBWEAK DMA2_Channel2_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DMA2_Channel2_IRQHandler + B DMA2_Channel2_IRQHandler + + PUBWEAK DMA2_Channel3_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DMA2_Channel3_IRQHandler + B DMA2_Channel3_IRQHandler + + PUBWEAK DMA2_Channel4_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DMA2_Channel4_IRQHandler + B DMA2_Channel4_IRQHandler + + PUBWEAK DMA2_Channel5_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DMA2_Channel5_IRQHandler + B DMA2_Channel5_IRQHandler + + PUBWEAK CAN2_TX_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +CAN2_TX_IRQHandler + B CAN2_TX_IRQHandler + + PUBWEAK CAN2_RX0_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +CAN2_RX0_IRQHandler + B CAN2_RX0_IRQHandler + + PUBWEAK CAN2_RX1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +CAN2_RX1_IRQHandler + B CAN2_RX1_IRQHandler + + PUBWEAK CAN2_SCE_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +CAN2_SCE_IRQHandler + B CAN2_SCE_IRQHandler + + PUBWEAK QSPI_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +QSPI_IRQHandler + B QSPI_IRQHandler + + PUBWEAK DMA2_Channel6_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DMA2_Channel6_IRQHandler + B DMA2_Channel6_IRQHandler + + PUBWEAK DMA2_Channel7_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DMA2_Channel7_IRQHandler + B DMA2_Channel7_IRQHandler + + PUBWEAK I2C3_EV_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +I2C3_EV_IRQHandler + B I2C3_EV_IRQHandler + + PUBWEAK I2C3_ER_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +I2C3_ER_IRQHandler + B I2C3_ER_IRQHandler + + PUBWEAK I2C4_EV_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +I2C4_EV_IRQHandler + B I2C4_EV_IRQHandler + + PUBWEAK I2C4_ER_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +I2C4_ER_IRQHandler + B I2C4_ER_IRQHandler + + PUBWEAK UART6_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +UART6_IRQHandler + B UART6_IRQHandler + + PUBWEAK UART7_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +UART7_IRQHandler + B UART7_IRQHandler + + PUBWEAK DMA1_Channel8_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DMA1_Channel8_IRQHandler + B DMA1_Channel8_IRQHandler + + PUBWEAK DMA2_Channel8_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DMA2_Channel8_IRQHandler + B DMA2_Channel8_IRQHandler + + PUBWEAK DVP_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DVP_IRQHandler + B DVP_IRQHandler + + PUBWEAK SAC_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +SAC_IRQHandler + B SAC_IRQHandler + + PUBWEAK MMU_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +MMU_IRQHandler + B MMU_IRQHandler + + PUBWEAK TSC_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TSC_IRQHandler + B TSC_IRQHandler + + PUBWEAK RSRAM_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +RSRAM_IRQHandler + B RSRAM_IRQHandler + + PUBWEAK DEFAULT_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +DEFAULT_IRQHandler + B DEFAULT_IRQHandler + + END + diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/startup/startup_n32g4fr_gcc.s b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/startup/startup_n32g4fr_gcc.s new file mode 100644 index 0000000000..fe3bec3262 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/startup/startup_n32g4fr_gcc.s @@ -0,0 +1,485 @@ +/** + ****************************************************************************** + * @file startup_n32g4fr.S + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m4 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss +/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ + +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + +/* Copy the data segment initializers from flash to SRAM */ + movs r1, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r3, =_sidata + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + +LoopCopyDataInit: + ldr r0, =_sdata + ldr r3, =_edata + adds r2, r0, r1 + cmp r2, r3 + bcc CopyDataInit + ldr r2, =_sbss + b LoopFillZerobss +/* Zero fill the bss segment. */ +FillZerobss: + movs r3, #0 + str r3, [r2], #4 + +LoopFillZerobss: + ldr r3, = _ebss + cmp r2, r3 + bcc FillZerobss + +/* Call the clock system intitialization function.*/ + bl SystemInit +/* Call static constructors */ + bl __libc_init_array +/* Call the application's entry point.*/ + bl main + bx lr +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * @param None + * @retval None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M3. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +*******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + + /* External Interrupts */ + .word WWDG_IRQHandler /* Window WatchDog */ + .word PVD_IRQHandler /* PVD through EXTI Line detection */ + .word TAMPER_IRQHandler /* Tamper */ + .word RTC_WKUP_IRQHandler /* RTC Wakeup */ + .word FLASH_IRQHandler /* FLASH */ + .word RCC_IRQHandler /* RCC */ + .word EXTI0_IRQHandler /* EXTI Line0 */ + .word EXTI1_IRQHandler /* EXTI Line1 */ + .word EXTI2_IRQHandler /* EXTI Line2 */ + .word EXTI3_IRQHandler /* EXTI Line3 */ + .word EXTI4_IRQHandler /* EXTI Line4 */ + .word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */ + .word DMA1_Channel2_IRQHandler /* DMA1 Channel 2 */ + .word DMA1_Channel3_IRQHandler /* DMA1 Channel 3 */ + .word DMA1_Channel4_IRQHandler /* DMA1 Channel 4 */ + .word DMA1_Channel5_IRQHandler /* DMA1 Channel 5 */ + .word DMA1_Channel6_IRQHandler /* DMA1 Channel 6 */ + .word DMA1_Channel7_IRQHandler /* DMA1 Channel 7 */ + .word ADC1_2_IRQHandler /* ADC1, ADC2 */ + .word USB_HP_CAN1_TX_IRQHandler /* USB High Priority or CAN1 TX */ + .word USB_LP_CAN1_RX0_IRQHandler /* USB Low Priority or CAN1 RX0 */ + .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ + .word CAN1_SCE_IRQHandler /* CAN1 SCE */ + .word EXTI9_5_IRQHandler /* EXTI Line 9..5 */ + .word TIM1_BRK_IRQHandler /* TIM1 Break */ + .word TIM1_UP_IRQHandler /* TIM1 Update */ + .word TIM1_TRG_COM_IRQHandler /* TIM1 Trigger and Commutation */ + .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ + .word TIM2_IRQHandler /* TIM2 */ + .word TIM3_IRQHandler /* TIM3 */ + .word TIM4_IRQHandler /* TIM4 */ + .word I2C1_EV_IRQHandler /* I2C1 Event */ + .word I2C1_ER_IRQHandler /* I2C1 Error */ + .word I2C2_EV_IRQHandler /* I2C2 Event */ + .word I2C2_ER_IRQHandler /* I2C2 Error */ + .word SPI1_IRQHandler /* SPI1 */ + .word SPI2_IRQHandler /* SPI2 */ + .word USART1_IRQHandler /* USART1 */ + .word USART2_IRQHandler /* USART2 */ + .word USART3_IRQHandler /* USART3 */ + .word EXTI15_10_IRQHandler /* EXTI Line 15..10 */ + .word RTCAlarm_IRQHandler /* RTC Alarm through EXTI Line */ + .word USBWakeUp_IRQHandler /* USB Wakeup from suspend */ + .word TIM8_BRK_IRQHandler /* TIM8 Break */ + .word TIM8_UP_IRQHandler /* TIM8 Update */ + .word TIM8_TRG_COM_IRQHandler /* TIM8 Trigger and Commutation */ + .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ + .word ADC3_4_IRQHandler /* ADC3 & ADC4 */ + .word XFMC_IRQHandler /* XFMC */ + .word SDIO_IRQHandler /* SDIO */ + .word TIM5_IRQHandler /* TIM5 */ + .word SPI3_IRQHandler /* SPI3 */ + .word UART4_IRQHandler /* UART4 */ + .word UART5_IRQHandler /* UART5 */ + .word TIM6_IRQHandler /* TIM6 */ + .word TIM7_IRQHandler /* TIM7 */ + .word DMA2_Channel1_IRQHandler /* DMA2 Channel1 */ + .word DMA2_Channel2_IRQHandler /* DMA2 Channel2 */ + .word DMA2_Channel3_IRQHandler /* DMA2 Channel3 */ + .word DMA2_Channel4_IRQHandler /* DMA2 Channel4 */ + .word DMA2_Channel5_IRQHandler /* DMA2 Channel5 */ + .word ETH_IRQHandler /* Ethernet global interrupt */ + .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line interrupt */ + .word CAN2_TX_IRQHandler /* CAN2 TX */ + .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ + .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ + .word CAN2_SCE_IRQHandler /* CAN2 SCE */ + .word QSPI_IRQHandler /* QSPI */ + .word DMA2_Channel6_IRQHandler /* DMA2 Channel6 */ + .word DMA2_Channel7_IRQHandler /* DMA2 Channel7 */ + .word I2C3_EV_IRQHandler /* I2C3 event */ + .word I2C3_ER_IRQHandler /* I2C3 error */ + .word I2C4_EV_IRQHandler /* I2C4 event */ + .word I2C4_ER_IRQHandler /* I2C4 error */ + .word UART6_IRQHandler /* UART6 */ + .word UART7_IRQHandler /* UART7 */ + .word DMA1_Channel8_IRQHandler /* DMA1 Channel8 */ + .word DMA2_Channel8_IRQHandler /* DMA2 Channel8 */ + .word DVP_IRQHandler /* DVP */ + .word SAC_IRQHandler /* SAC */ + .word MMU_IRQHandler /* MMU */ + .word TSC_IRQHandler /* TSC */ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMPER_IRQHandler + .thumb_set TAMPER_IRQHandler,Default_Handler + + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Channel1_IRQHandler + .thumb_set DMA1_Channel1_IRQHandler,Default_Handler + + .weak DMA1_Channel2_IRQHandler + .thumb_set DMA1_Channel2_IRQHandler,Default_Handler + + .weak DMA1_Channel3_IRQHandler + .thumb_set DMA1_Channel3_IRQHandler,Default_Handler + + .weak DMA1_Channel4_IRQHandler + .thumb_set DMA1_Channel4_IRQHandler,Default_Handler + + .weak DMA1_Channel5_IRQHandler + .thumb_set DMA1_Channel5_IRQHandler,Default_Handler + + .weak DMA1_Channel6_IRQHandler + .thumb_set DMA1_Channel6_IRQHandler,Default_Handler + + .weak DMA1_Channel7_IRQHandler + .thumb_set DMA1_Channel7_IRQHandler,Default_Handler + + .weak ADC1_2_IRQHandler + .thumb_set ADC1_2_IRQHandler,Default_Handler + + .weak USB_HP_CAN1_TX_IRQHandler + .thumb_set USB_HP_CAN1_TX_IRQHandler,Default_Handler + + .weak USB_LP_CAN1_RX0_IRQHandler + .thumb_set USB_LP_CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_SCE_IRQHandler + .thumb_set CAN1_SCE_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_IRQHandler + .thumb_set TIM1_BRK_IRQHandler,Default_Handler + + .weak TIM1_UP_IRQHandler + .thumb_set TIM1_UP_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_IRQHandler + .thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTCAlarm_IRQHandler + .thumb_set RTCAlarm_IRQHandler,Default_Handler + + .weak USBWakeUp_IRQHandler + .thumb_set USBWakeUp_IRQHandler,Default_Handler + + .weak TIM8_BRK_IRQHandler + .thumb_set TIM8_BRK_IRQHandler,Default_Handler + + .weak TIM8_UP_IRQHandler + .thumb_set TIM8_UP_IRQHandler,Default_Handler + + .weak TIM8_TRG_COM_IRQHandler + .thumb_set TIM8_TRG_COM_IRQHandler,Default_Handler + + .weak TIM8_CC_IRQHandler + .thumb_set TIM8_CC_IRQHandler,Default_Handler + + .weak ADC3_4_IRQHandler + .thumb_set ADC3_4_IRQHandler,Default_Handler + + .weak XFMC_IRQHandler + .thumb_set XFMC_IRQHandler,Default_Handler + + .weak SDIO_IRQHandler + .thumb_set SDIO_IRQHandler,Default_Handler + + .weak TIM5_IRQHandler + .thumb_set TIM5_IRQHandler,Default_Handler + + .weak SPI3_IRQHandler + .thumb_set SPI3_IRQHandler,Default_Handler + + .weak UART4_IRQHandler + .thumb_set UART4_IRQHandler,Default_Handler + + .weak UART5_IRQHandler + .thumb_set UART5_IRQHandler,Default_Handler + + .weak TIM6_IRQHandler + .thumb_set TIM6_IRQHandler,Default_Handler + + .weak TIM7_IRQHandler + .thumb_set TIM7_IRQHandler,Default_Handler + + .weak DMA2_Channel1_IRQHandler + .thumb_set DMA2_Channel1_IRQHandler,Default_Handler + + .weak DMA2_Channel2_IRQHandler + .thumb_set DMA2_Channel2_IRQHandler,Default_Handler + + .weak DMA2_Channel3_IRQHandler + .thumb_set DMA2_Channel3_IRQHandler,Default_Handler + + .weak DMA2_Channel4_IRQHandler + .thumb_set DMA2_Channel4_IRQHandler,Default_Handler + + .weak DMA2_Channel5_IRQHandler + .thumb_set DMA2_Channel5_IRQHandler,Default_Handler + + .weak ETH_IRQHandler + .thumb_set ETH_IRQHandler,Default_Handler + + .weak ETH_WKUP_IRQHandler + .thumb_set ETH_WKUP_IRQHandler,Default_Handler + + .weak CAN2_TX_IRQHandler + .thumb_set CAN2_TX_IRQHandler,Default_Handler + + .weak CAN2_RX0_IRQHandler + .thumb_set CAN2_RX0_IRQHandler,Default_Handler + + .weak CAN2_RX1_IRQHandler + .thumb_set CAN2_RX1_IRQHandler,Default_Handler + + .weak CAN2_SCE_IRQHandler + .thumb_set CAN2_SCE_IRQHandler,Default_Handler + + .weak QSPI_IRQHandler + .thumb_set QSPI_IRQHandler,Default_Handler + + .weak DMA2_Channel6_IRQHandler + .thumb_set DMA2_Channel6_IRQHandler,Default_Handler + + .weak DMA2_Channel7_IRQHandler + .thumb_set DMA2_Channel7_IRQHandler,Default_Handler + + .weak I2C3_EV_IRQHandler + .thumb_set I2C3_EV_IRQHandler,Default_Handler + + .weak I2C3_ER_IRQHandler + .thumb_set I2C3_ER_IRQHandler,Default_Handler + + .weak I2C4_EV_IRQHandler + .thumb_set I2C4_EV_IRQHandler,Default_Handler + + .weak I2C4_ER_IRQHandler + .thumb_set I2C4_ER_IRQHandler,Default_Handler + + .weak UART6_IRQHandler + .thumb_set UART6_IRQHandler,Default_Handler + + .weak UART7_IRQHandler + .thumb_set UART7_IRQHandler,Default_Handler + + .weak DMA1_Channel8_IRQHandler + .thumb_set DMA1_Channel8_IRQHandler,Default_Handler + + .weak DMA2_Channel8_IRQHandler + .thumb_set DMA2_Channel8_IRQHandler,Default_Handler + + .weak DVP_IRQHandler + .thumb_set DVP_IRQHandler,Default_Handler + + .weak SAC_IRQHandler + .thumb_set SAC_IRQHandler,Default_Handler + + .weak MMU_IRQHandler + .thumb_set MMU_IRQHandler,Default_Handler + + .weak TSC_IRQHandler + .thumb_set TSC_IRQHandler,Default_Handler + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/system_n32g4fr.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/system_n32g4fr.c new file mode 100644 index 0000000000..8094a929a4 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/system_n32g4fr.c @@ -0,0 +1,421 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file system_n32g4fr.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr.h" + +/* Uncomment the line corresponding to the desired System clock (SYSCLK) + frequency (after reset the HSI is used as SYSCLK source) + + IMPORTANT NOTE: + ============== + 1. After each device reset the HSI is used as System clock source. + + 2. Please make sure that the selected System clock doesn't exceed your + device's maximum frequency. + + 3. If none of the define below is enabled, the HSI is used as System clock + source. + + 4. The System clock configuration functions provided within this file assume + that: + - For Low, Medium and High density Value line devices an external 8MHz + crystal is used to drive the System clock. + - For Low, Medium and High density devices an external 8MHz crystal is + used to drive the System clock. + - For Connectivity line devices an external 25MHz crystal is used to + drive the System clock. If you are using different crystal you have to adapt + those functions accordingly. + */ + +#define SYSCLK_USE_HSI 0 +#define SYSCLK_USE_HSE 1 +#define SYSCLK_USE_HSI_PLL 2 +#define SYSCLK_USE_HSE_PLL 3 + +#ifndef SYSCLK_FREQ +#define SYSCLK_FREQ 144000000 +#endif + +#ifndef SYSCLK_SRC +#define SYSCLK_SRC SYSCLK_USE_HSE_PLL +#endif + +#if SYSCLK_SRC == SYSCLK_USE_HSI + +#if SYSCLK_FREQ != HSI_VALUE +#error SYSCL_FREQ must be set to HSI_VALUE +#endif + +#elif SYSCLK_SRC == SYSCLK_USE_HSE + +#ifndef HSE_VALUE +#error HSE_VALUE must be defined! +#endif + +#if SYSCLK_FREQ != HSE_VALUE +#error SYSCL_FREQ must be set to HSE_VALUE +#endif + +#elif SYSCLK_SRC == SYSCLK_USE_HSI_PLL + +#if (SYSCLK_FREQ % (HSI_VALUE / 2) == 0) && (SYSCLK_FREQ / (HSI_VALUE / 2) >= 2) \ + && (SYSCLK_FREQ / (HSI_VALUE / 2) <= 32) + +#define PLLSRC_DIV 2 +#define PLL_MUL (SYSCLK_FREQ / (HSI_VALUE / 2)) + +#else +#error Cannot make a PLL multiply factor to SYSCLK_FREQ. +#endif + +#elif SYSCLK_SRC == SYSCLK_USE_HSE_PLL + +#ifndef HSE_VALUE +#error HSE_VALUE must be defined! +#endif + +#if ((SYSCLK_FREQ % (HSE_VALUE / 2)) == 0) && (SYSCLK_FREQ / (HSE_VALUE / 2) >= 2) \ + && (SYSCLK_FREQ / (HSE_VALUE / 2) <= 32) + +#define PLLSRC_DIV 2 +#define PLL_MUL (SYSCLK_FREQ / (HSE_VALUE / 2)) + +#elif (SYSCLK_FREQ % HSE_VALUE == 0) && (SYSCLK_FREQ / HSE_VALUE >= 2) && (SYSCLK_FREQ / HSE_VALUE <= 32) + +#define PLLSRC_DIV 1 +#define PLL_MUL (SYSCLK_FREQ / HSE_VALUE) + +#else +#error Cannot make a PLL multiply factor to SYSCLK_FREQ. +#endif + +#else +#error wrong value for SYSCLK_SRC +#endif + +/* #define VECT_TAB_SRAM */ +#define VECT_TAB_OFFSET 0x0 /*!< Vector Table base offset field. This value must be a multiple of 0x200. */ + +/******************************************************************************* + * Clock Definitions + *******************************************************************************/ +uint32_t SystemCoreClock = SYSCLK_FREQ; /*!< System Clock Frequency (Core Clock) */ + +const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + +static void SetSysClock(void); + +#ifdef DATA_IN_ExtSRAM +static void SystemInit_ExtMemCtl(void); +#endif /* DATA_IN_ExtSRAM */ + +/** + * @brief Setup the microcontroller system + * Initialize the Embedded Flash Interface, the PLL and update the + * SystemCoreClock variable. + * @note This function should be used only after reset. + */ +void SystemInit(void) +{ + /* FPU settings + * ------------------------------------------------------------*/ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10 and CP11 Full Access */ +#endif + + /* Reset the RCC clock configuration to the default reset state(for debug purpose) */ + /* Set HSIEN bit */ + RCC->CTRL |= (uint32_t)0x00000001; + + /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */ + RCC->CFG &= (uint32_t)0xF8FFC000; + + /* Reset HSEON, CLKSSEN and PLLEN bits */ + RCC->CTRL &= (uint32_t)0xFEF6FFFF; + + /* Reset HSEBYP bit */ + RCC->CTRL &= (uint32_t)0xFFFBFFFF; + + /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRES/OTGFSPRE bits */ + RCC->CFG &= (uint32_t)0xF700FFFF; + + /* Reset CFG2 register */ + RCC->CFG2 = 0x00003800; + + /* Reset CFG3 register */ + RCC->CFG3 = 0x00003840; + + /* Disable all interrupts and clear pending bits */ + RCC->CLKINT = 0x009F0000; + + /* Enable ex mode */ + RCC->APB1PCLKEN |= RCC_APB1PCLKEN_PWREN; + PWR->CTRL3 |= 0x00000001; + RCC->APB1PCLKEN &= (uint32_t)(~RCC_APB1PCLKEN_PWREN); + + /* Enable ICACHE and Prefetch Buffer */ + FLASH->AC |= (uint32_t)(FLASH_AC_ICAHEN | FLASH_AC_PRFTBFEN); + +#ifdef DATA_IN_ExtSRAM + SystemInit_ExtMemCtl(); +#endif /* DATA_IN_ExtSRAM */ + + /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */ + /* Configure the Flash Latency cycles and enable prefetch buffer */ + SetSysClock(); + +#ifdef VECT_TAB_SRAM + SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */ +#else + SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */ +#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 HSI, SystemCoreClock will contain the + * HSI_VALUE(*) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the + * HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the + * HSE_VALUE(**) or HSI_VALUE(*) multiplied by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in n32g4fr.h file (default value + * 8 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSE_VALUE is a constant defined in N32G4FR.h file (default value + * 8 MHz or 25 MHz, depedning on the product used), 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. + */ +void SystemCoreClockUpdate(void) +{ + uint32_t tmp = 0, pllmull = 0, pllsource = 0; + + /* Get SYSCLK source + * -------------------------------------------------------*/ + tmp = RCC->CFG & RCC_CFG_SCLKSTS; + + switch (tmp) + { + case 0x00: /* HSI used as system clock */ + SystemCoreClock = HSI_VALUE; + break; + case 0x04: /* HSE used as system clock */ + SystemCoreClock = HSE_VALUE; + break; + case 0x08: /* PLL used as system clock */ + + /* Get PLL clock source and multiplication factor + * ----------------------*/ + pllmull = RCC->CFG & RCC_CFG_PLLMULFCT; + pllsource = RCC->CFG & RCC_CFG_PLLSRC; + + if ((pllmull & RCC_CFG_PLLMULFCT_4) == 0) + { + pllmull = (pllmull >> 18) + 2; // PLLMUL[4]=0 + } + else + { + pllmull = ((pllmull >> 18) - 496) + 1; // PLLMUL[4]=1 + } + + if (pllsource == 0x00) + { + /* HSI oscillator clock divided by 2 selected as PLL clock entry */ + SystemCoreClock = (HSI_VALUE >> 1) * pllmull; + } + else + { + /* HSE selected as PLL clock entry */ + if ((RCC->CFG & RCC_CFG_PLLHSEPRES) != (uint32_t)RESET) + { /* HSE oscillator clock divided by 2 */ + SystemCoreClock = (HSE_VALUE >> 1) * pllmull; + } + else + { + SystemCoreClock = HSE_VALUE * pllmull; + } + } + + break; + + default: + SystemCoreClock = HSI_VALUE; + break; + } + + /* Compute HCLK clock frequency ----------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFG & RCC_CFG_AHBPRES) >> 4)]; + /* HCLK clock frequency */ + SystemCoreClock >>= tmp; +} + +/** + * @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 + * prescalers. + */ +static void SetSysClock(void) +{ + uint32_t rcc_cfgr = 0; + bool HSEStatus = 0; + uint32_t StartUpCounter = 0; + +#if SYSCLK_SRC == SYSCLK_USE_HSE || SYSCLK_SRC == SYSCLK_USE_HSE_PLL + + /* Enable HSE */ + RCC->CTRL |= ((uint32_t)RCC_CTRL_HSEEN); + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CTRL & RCC_CTRL_HSERDF; + StartUpCounter++; + } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + HSEStatus = ((RCC->CTRL & RCC_CTRL_HSERDF) != RESET); + if (!HSEStatus) + { + /* If HSE fails to start-up, the application will have wrong clock + * configuration. User can add here some code to deal with this error */ + SystemCoreClock = HSI_VALUE; + return; + } +#endif + + /* Flash wait state + 0: HCLK <= 32M + 1: HCLK <= 64M + 2: HCLK <= 96M + 3: HCLK <= 128M + 4: HCLK <= 144M + */ + FLASH->AC &= (uint32_t)((uint32_t)~FLASH_AC_LATENCY); + FLASH->AC |= (uint32_t)((SYSCLK_FREQ - 1) / 32000000); + + /* HCLK = SYSCLK */ + RCC->CFG |= (uint32_t)RCC_CFG_AHBPRES_DIV1; + + /* PCLK2 max 72M */ + if (SYSCLK_FREQ > 72000000) + { + RCC->CFG |= (uint32_t)RCC_CFG_APB2PRES_DIV2; + } + else + { + RCC->CFG |= (uint32_t)RCC_CFG_APB2PRES_DIV1; + } + + /* PCLK1 max 36M */ + if (SYSCLK_FREQ > 72000000) + { + RCC->CFG |= (uint32_t)RCC_CFG_APB1PRES_DIV4; + } + else if (SYSCLK_FREQ > 36000000) + { + RCC->CFG |= (uint32_t)RCC_CFG_APB1PRES_DIV2; + } + else + { + RCC->CFG |= (uint32_t)RCC_CFG_APB1PRES_DIV1; + } + +#if SYSCLK_SRC == SYSCLK_USE_HSE + /* Select HSE as system clock source */ + RCC->CFG &= (uint32_t)((uint32_t) ~(RCC_CFG_SCLKSW)); + RCC->CFG |= (uint32_t)RCC_CFG_SCLKSW_HSE; + + /* Wait till HSE is used as system clock source */ + while ((RCC->CFG & (uint32_t)RCC_CFG_SCLKSTS) != (uint32_t)0x04) + { + } +#elif SYSCLK_SRC == SYSCLK_USE_HSI_PLL || SYSCLK_SRC == SYSCLK_USE_HSE_PLL + + /* clear bits */ + RCC->CFG &= (uint32_t)((uint32_t) ~(RCC_CFG_PLLSRC | RCC_CFG_PLLHSEPRES | RCC_CFG_PLLMULFCT)); + + /* set PLL source */ + rcc_cfgr = RCC->CFG; + rcc_cfgr |= (SYSCLK_SRC == SYSCLK_USE_HSI_PLL ? RCC_CFG_PLLSRC_HSI_DIV2 : RCC_CFG_PLLSRC_HSE); + +#if SYSCLK_SRC == SYSCLK_USE_HSE_PLL + rcc_cfgr |= (PLLSRC_DIV == 1 ? RCC_CFG_PLLHSEPRES_HSE : RCC_CFG_PLLHSEPRES_HSE_DIV2); +#endif + + /* set PLL multiply factor */ +#if PLL_MUL <= 16 + rcc_cfgr |= (PLL_MUL - 2) << 18; +#else + rcc_cfgr |= ((PLL_MUL - 17) << 18) | (1 << 27); +#endif + + RCC->CFG = rcc_cfgr; + + /* Enable PLL */ + RCC->CTRL |= RCC_CTRL_PLLEN; + + /* Wait till PLL is ready */ + while ((RCC->CTRL & RCC_CTRL_PLLRDF) == 0) + { + } + + /* Select PLL as system clock source */ + RCC->CFG &= (uint32_t)((uint32_t) ~(RCC_CFG_SCLKSW)); + RCC->CFG |= (uint32_t)RCC_CFG_SCLKSW_PLL; + + /* Wait till PLL is used as system clock source */ + while ((RCC->CFG & (uint32_t)RCC_CFG_SCLKSTS) != (uint32_t)0x08) + { + } +#endif +} diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/system_n32g4fr.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/system_n32g4fr.h new file mode 100644 index 0000000000..1c4f34c8ff --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/CMSIS/device/system_n32g4fr.h @@ -0,0 +1,59 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file system_n32g4fr.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __SYSTEM_N32G4FR_H__ +#define __SYSTEM_N32G4FR_H__ + +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup N32G4FR_System + * @{ + */ + +extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ + +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*__SYSTEM_N32G4FR_H__ */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/SConscript b/bsp/n32/libraries/N32G4FR_Firmware_Library/SConscript new file mode 100644 index 0000000000..a22f97e338 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/SConscript @@ -0,0 +1,58 @@ +import rtconfig +from building import * + +# get current directory +cwd = GetCurrentDir() + +# The set of src files associated with this SConscript file. + +src = Split(''' +CMSIS/device/system_n32g4fr.c +n32g4fr_std_periph_driver/src/n32g4fr_gpio.c +n32g4fr_std_periph_driver/src/n32g4fr_rcc.c +n32g4fr_std_periph_driver/src/n32g4fr_exti.c +n32g4fr_std_periph_driver/src/misc.c +''') + +if GetDepend(['RT_USING_SERIAL']): + src += ['n32g4fr_std_periph_driver/src/n32g4fr_usart.c'] + +if GetDepend(['RT_USING_I2C']): + src += ['n32g4fr_std_periph_driver/src/n32g4fr_i2c.c'] + +if GetDepend(['RT_USING_SPI']): + src += ['n32g4fr_std_periph_driver/src/n32g4fr_spi.c'] + +if GetDepend(['RT_USING_CAN']): + src += ['n32g4fr_std_periph_driver/src/n32g4fr_can.c'] + +if GetDepend(['RT_USING_ADC']): + src += ['n32g4fr_std_periph_driver/src/n32g4fr_adc.c'] + +if GetDepend(['RT_USING_DAC']): + src += ['n32g4fr_std_periph_driver/src/n32g4fr_dac.c'] + +if GetDepend(['RT_USING_HWTIMER']): + src += ['n32g4fr_std_periph_driver/src/n32g4fr_tim.c'] + +if GetDepend(['RT_USING_RTC']): + src += ['n32g4fr_std_periph_driver/src/n32g4fr_rtc.c'] + +if GetDepend(['RT_USING_WDT']): + src += ['n32g4fr_std_periph_driver/src/n32g4fr_wwdg.c'] + src += ['n32g4fr_std_periph_driver/src/n32g4fr_iwdg.c'] + +if GetDepend(['RT_USING_SDIO']): + src += ['n32g4fr_std_periph_driver/src/n32g4fr_sdio.c'] + +path = [ + cwd + '/CMSIS/core', + cwd + '/CMSIS/device', + cwd + '/CMSIS', + cwd + '/n32g4fr_std_periph_driver/inc',] + +CPPDEFINES = ['USE_STDPERIPH_DRIVER'] + +group = DefineGroup('libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_aes.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_aes.h new file mode 100644 index 0000000000..88f87bc01e --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_aes.h @@ -0,0 +1,126 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_aes.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_AES_H__ +#define __N32G4FR_AES_H__ + +#include +/** @addtogroup N32G4FR_Algorithm_Library + * @{ + */ + +/** @addtogroup AES + * @brief AES symmetrical cipher algorithm + * @{ + */ + +#define AES_ECB (0x11111111) +#define AES_CBC (0x22222222) +#define AES_CTR (0x33333333) + +#define AES_ENC (0x44444444) +#define AES_DEC (0x55555555) + +enum +{ + AES_Crypto_OK = 0x0, //AES opreation success + AES_Init_OK = 0x0, //AES Init opreation success + AES_Crypto_ModeError = 0x5a5a5a5a, //Working mode error(Neither ECB nor CBC nor CTR) + AES_Crypto_EnOrDeError, //En&De error(Neither encryption nor decryption) + AES_Crypto_ParaNull, // the part of input(output/iv) Null + AES_Crypto_LengthError, // if Working mode is ECB or CBC,the length of input message must be 4 times and cannot be zero; + //if Working mode is CTR,the length of input message cannot be zero; othets: return AES_Crypto_LengthError + + AES_Crypto_KeyLengthError, //the keyWordLen must be 4 or 6 or 8; othets:return AES_Crypto_KeyLengthError + AES_Crypto_UnInitError, //AES uninitialized +}; + +typedef struct +{ + uint32_t *in; // the part of input to be encrypted or decrypted + uint32_t *iv; // the part of initial vector + uint32_t *out; // the part of out + uint32_t *key; // the part of key + uint32_t keyWordLen; // the length(by word) of key + uint32_t inWordLen; // the length(by word) of plaintext or cipher + uint32_t En_De; // 0x44444444- encrypt, 0x55555555 - decrypt + uint32_t Mode; // 0x11111111 - ECB, 0x22222222 - CBC, 0x33333333 - CTR +}AES_PARM; + + /** + * @brief AES_Init + * @return AES_Init_OK, AES Init success; othets: AES Init fail + * @note + */ + +uint32_t AES_Init(AES_PARM *parm); + +/** + * @brief AES crypto + * @param[in] parm pointer to AES context and the detail please refer to struct AES_PARM in AES.h + * @return AES_Crypto_OK, AES crypto success; othets: AES crypto fail(reference to the definition by enum variation) + * @note 1.Please refer to the demo in user guidance before using this function + * 2.Input and output can be the same buffer + * 3. IV can be NULL when ECB mode + * 4. If Working mode is ECB or CBC,the length of input message must be 4 times and cannot be zero; + * if Working mode is CTR,the length of input message cannot be zero; + * 5. If the input is in byte, make sure align by word. + */ +uint32_t AES_Crypto(AES_PARM *parm); + +/** + * @brief AES close + * @return none + * @note if you want to close AES algorithm, this function can be recalled. + */ +void AES_Close(void); + +/** + * @brief Get AES lib version + * @param[out] type pointer one byte type information represents the type of the lib, like Commercial version.\ + * @Bits 0~4 stands for Commercial (C), Security (S), Normal (N), Evaluation (E), Test (T), Bits 5~7 are reserved. e.g. 0x09 stands for CE version. + * @param[out] customer pointer one byte customer information represents customer ID. for example, 0x00 stands for standard version, 0x01 is for Tianyu customized version... + * @param[out] date pointer array which include three bytes date information. If the returned bytes are 18,9,13,this denotes September 13,2018 + * @param[out] version pointer one byte version information represents develop version of the lib. e.g. 0x12 denotes version 1.2. + * @return none + * @1.You can recall this function to get AES lib information + */ +void AES_Version(uint8_t *type, uint8_t *customer, uint8_t date[3], uint8_t *version); + + + + +#endif + + diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_algo_common.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_algo_common.h new file mode 100644 index 0000000000..9d68204121 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_algo_common.h @@ -0,0 +1,154 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_algo_common.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_ALGO_COMMON_H__ +#define __N32G4FR_ALGO_COMMON_H__ + +#include +/** @addtogroup N32G4FR_Algorithm_Library + * @{ + */ +enum{ + Cpy_OK=0,//copy success + SetZero_OK = 0,//set zero success + XOR_OK = 0, //XOR success + Reverse_OK = 0, //Reverse success + Cmp_EQUAL = 0, //Two big number are equal + Cmp_UNEQUAL = 1, //Two big number are not equal + +}; + +/** + * @brief disturb the sequence order + * @param[in] order pointer to the sequence to be disturbed + * @param[in] rand pointer to random number + * @param[in] the length of order + * @return RandomSort_OK: disturb order success; Others: disturb order fail; + * @note + */ +uint32_t RandomSort(uint8_t *order, const uint8_t *rand, uint32_t len); + +/** + * @brief Copy data by byte + * @param[in] dst pointer to destination data + * @param[in] src pointer to source data + * @param[in] byte length + * @return Cpy_OK: success; others: fail. + * @note 1. dst and src cannot be same + */ +uint32_t Cpy_U8(uint8_t *dst, uint8_t *src, uint32_t byteLen); + +/** + * @brief Copy data by word + * @param[in] dst pointer to destination data + * @param[in] src pointer to source data + * @param[in] word length + * @return Cpy_OK: success; others: fail. + * @note 1. dst and src must be aligned by word + */ +uint32_t Cpy_U32(uint32_t *dst, const uint32_t *src, uint32_t wordLen); + + /** + * @brief XOR + * @param[in] a pointer to one data to be XORed + * @param[in] b pointer to another data to be XORed + * @param[in] the length of order + * @return XOR_OK: operation success; Others: operation fail; + * @note + */ +uint32_t XOR_U8(uint8_t *a, uint8_t *b, uint8_t *c, uint32_t byteLen); + + /** + * @brief XORed two u32 arrays + * @param[in] a pointer to one data to be XORed + * @param[in] b pointer to another data to be XORed + * @param[in] the length of order + * @return XOR_OK: operation success; Others: operation fail; + * @note + */ +uint32_t XOR_U32(uint32_t *a,uint32_t *b,uint32_t *c,uint32_t wordLen); + +/** + * @brief set zero by byte + * @param[in] dst pointer to the address to be set zero + * @param[in] byte length + * @return SetZero_OK: success; others: fail. + * @note + */ +uint32_t SetZero_U8(uint8_t *dst, uint32_t byteLen); + +/** + * @brief set zero by word + * @param[in] dst pointer to the address to be set zero + * @param[in] word length + * @return SetZero_OK: success; others: fail. + * @note + */ +uint32_t SetZero_U32(uint32_t *dst, uint32_t wordLen); + +/** + * @brief reverse byte order of every word, the words stay the same + * @param[in] dst pointer to the destination address + * @param[in] src pointer to the source address + * @param[in] word length + * @return Reverse_OK: success; others: fail. + * @note 1.dst and src can be same + */ +uint32_t ReverseBytesInWord_U32(uint32_t *dst, const uint32_t *src, uint32_t wordLen); + +/** + * @brief compare two big number + * @param[in] a pointer to one big number + * @param[in] word length of a + * @param[in] b pointer to another big number + * @param[in] word length of b + * @return Cmp_UNEQUAL:a!=b;Cmp_EQUAL: a==b. + * + */ +int32_t Cmp_U32(const uint32_t *a, uint32_t aWordLen, const uint32_t *b, uint32_t bWordLen); + +/** + * @brief compare two big number + * @param[in] a pointer to one big number + * @param[in] word length of a + * @param[in] b pointer to another big number + * @param[in] word length of b + * @return Cmp_UNEQUAL:a!=b;Cmp_EQUAL: a==b. + * + */ +int32_t Cmp_U8(const uint8_t *a, uint32_t aByteLen, const uint8_t *b, uint32_t bByteLen); + + +#endif + diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_des.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_des.h new file mode 100644 index 0000000000..ff7b9ce23b --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_des.h @@ -0,0 +1,119 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_des.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_DES_H__ +#define __N32G4FR_DES_H__ +#include +/** @addtogroup N32G4FR_Algorithm_Library + * @{ + */ + +/** @addtogroup DES + * @brief DES symmetrical cipher algorithm + * @{ + */ +#define DES_ECB (0x11111111) +#define DES_CBC (0x22222222) + + +#define DES_ENC (0x33333333) +#define DES_DEC (0x44444444) + +#define DES_KEY (0x55555555) +#define TDES_2KEY (0x66666666) +#define TDES_3KEY (0x77777777) + +enum DES +{ + DES_Crypto_OK = 0x0, // DES/TDES opreation success + DES_Init_OK = 0x0, // DES/TDES Init opreation success + DES_Crypto_ModeError = 0x5a5a5a5a, // Working mode error(Neither ECB nor CBC) + DES_Crypto_EnOrDeError, // En&De error(Neither encryption nor decryption) + DES_Crypto_ParaNull, // the part of input(output/iv) Null + DES_Crypto_LengthError, // the length of input message must be 2 times and cannot be zero + DES_Crypto_KeyError, // keyMode error(Neither DES_KEY nor TDES_2KEY nor TDES_3KEY) + DES_Crypto_UnInitError, // DES/TDES uninitialized +}; + +typedef struct +{ + uint32_t* in; // the part of input to be encrypted or decrypted + uint32_t* iv; // the part of initial vector + uint32_t* out; // the part of out + uint32_t* key; // the part of key + uint32_t inWordLen; // the length(by word) of plaintext or cipher + uint32_t En_De; // 0x33333333- encrypt, 0x44444444 - decrypt + uint32_t Mode; // 0x11111111 - ECB, 0x22222222 - CBC + uint32_t keyMode; // TDES key mode: 0x55555555-key,0x66666666-2key, 0x77777777-3key +} DES_PARM; + + /** + * @brief DES_Init + * @return DES_Init_OK, DES/TDES Init success; othets: DES/TDES Init fail + * @note + */ +uint32_t DES_Init(DES_PARM *parm); + +/** + * @brief DES crypto + * @param[in] parm pointer to DES/TDES context and the detail please refer to struct DES_PARM in DES.h + * @return DES_Crypto_OK, DES/TDES crypto success; othets: DES/TDES crypto fail(reference to the definition by enum variation) + * @note 1.Please refer to the demo in user guidance before using this function + * 2.Input and output can be the same buffer + * 3. IV can be NULL when ECB mode + * 4. The word lengrh of message must be as times as 2. + * 5. If the input is in byte, make sure align by word. + */ +uint32_t DES_Crypto(DES_PARM *parm); + +/** + * @brief DES close + * @return none + * @note if you want to close DES algorithm, this function can be recalled. + */ +void DES_Close(void); + +/** + * @brief Get DES/TDES lib version + * @param[out] type pointer one byte type information represents the type of the lib, like Commercial version.\ + * @Bits 0~4 stands for Commercial (C), Security (S), Normal (N), Evaluation (E), Test (T), Bits 5~7 are reserved. e.g. 0x09 stands for CE version. + * @param[out] customer pointer one byte customer information represents customer ID. for example, 0x00 stands for standard version, 0x01 is for Tianyu customized version... + * @param[out] date pointer array which include three bytes date information. If the returned bytes are 18,9,13,this denotes September 13,2018 + * @param[out] version pointer one byte version information represents develop version of the lib. e.g. 0x12 denotes version 1.2. + * @return none + * @1.You can recall this function to get DES/TDES lib information + */ +void DES_Version(uint8_t *type, uint8_t *customer, uint8_t date[3], uint8_t *version); + +#endif diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_hash.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_hash.h new file mode 100644 index 0000000000..6fa32441ac --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_hash.h @@ -0,0 +1,218 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_hash.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_HASH_H__ +#define __N32G4FR_HASH_H__ + +#include +/** @addtogroup N32G4FR_Algorithm_Library + * @{ + */ + +/** @addtogroup HASH + * @brief Message digest algorithms + * @{ + */ +#define ALG_SHA1 (uint16_t)(0x0004) +#define ALG_SHA224 (uint16_t)(0x000A) +#define ALG_SHA256 (uint16_t)(0x000B) +#define ALG_MD5 (uint16_t)(0x000C) +#define ALG_SM3 (uint16_t)(0x0012) + +enum +{ + HASH_SEQUENCE_TRUE = 0x0105A5A5,//save IV + HASH_SEQUENCE_FALSE = 0x010A5A5A, //not save IV + HASH_Init_OK = 0,//hash init success + HASH_Start_OK = 0,//hash update success + HASH_Update_OK = 0,//hash update success + HASH_Complete_OK = 0,//hash complete success + HASH_Close_OK = 0,//hash close success + HASH_ByteLenPlus_OK = 0,//byte length plus success + HASH_PadMsg_OK = 0,//message padding success + HASH_ProcMsgBuf_OK = 0, //message processing success + SHA1_Hash_OK = 0,//sha1 operation success + SM3_Hash_OK = 0,//sm3 operation success + SHA224_Hash_OK = 0,//sha224 operation success + SHA256_Hash_OK = 0,//sha256 operation success + MD5_Hash_OK = 0,//MD5 operation success + + HASH_Init_ERROR = 0x01044400,//hash init error + HASH_Start_ERROR, //hash start error + HASH_Update_ERROR, //hash update error + HASH_ByteLenPlus_ERROR,//hash byte plus error +}; + +struct _HASH_CTX_; + +typedef struct +{ + const uint16_t HashAlgID;//choice hash algorithm + const uint32_t * const K, KLen;//K and word length of K + const uint32_t * const IV, IVLen;//IV and word length of IV + const uint32_t HASH_SACCR, HASH_HASHCTRL;//relate registers + const uint32_t BlockByteLen, BlockWordLen; //byte length of block, word length of block + const uint32_t DigestByteLen, DigestWordLen; //byte length of digest,word length of digest + const uint32_t Cycle; //interation times + uint32_t (* const ByteLenPlus)(uint32_t *, uint32_t); //function pointer + uint32_t (* const PadMsg)(struct _HASH_CTX_ *); //function pointer +}HASH_ALG; + +typedef struct _HASH_CTX_ +{ + const HASH_ALG *hashAlg;//pointer to HASH_ALG + uint32_t sequence; // TRUE if the IV should be saved + uint32_t IV[16]; + uint32_t msgByteLen[4]; + uint8_t msgBuf[128+4]; + uint32_t msgIdx; +}HASH_CTX; + +extern const HASH_ALG HASH_ALG_SHA1[1]; +extern const HASH_ALG HASH_ALG_SHA224[1]; +extern const HASH_ALG HASH_ALG_SHA256[1]; +extern const HASH_ALG HASH_ALG_MD5[1]; +extern const HASH_ALG HASH_ALG_SM3[1]; + +/** + * @brief Hash init + * @param[in] ctx pointer to HASH_CTX struct + * @return HASH_Init_OK, Hash init success; othets: Hash init fail + * @note 1.Please refer to the demo in user guidance before using this function + */ +uint32_t HASH_Init(HASH_CTX *ctx); + +/** + * @brief Hash start + * @param[in] ctx pointer to HASH_CTX struct + * @return HASH_Start_OK, Hash start success; othets: Hash start fail + * @note 1.Please refer to the demo in user guidance before using this function + * 2.HASH_Init() should be recalled before use this function + */ +uint32_t HASH_Start(HASH_CTX *ctx); + +/** + * @brief Hash update + * @param[in] ctx pointer to HASH_CTX struct + * @param[in] in pointer to message + * @param[out] out pointer tohash result,digest + * @return HASH_Update_OK, Hash update success; othets: Hash update fail + * @note 1.Please refer to the demo in user guidance before using this function + * 2.HASH_Init() and HASH_Start() should be recalled before use this function + */ +uint32_t HASH_Update(HASH_CTX *ctx, uint8_t *in, uint32_t byteLen); + +/** + * @brief Hash complete + * @param[in] ctx pointer to HASH_CTX struct + * @param[out] out pointer tohash result,digest + * @return HASH_Complete_OK, Hash complete success; othets: Hash complete fail + * @note 1.Please refer to the demo in user guidance before using this function + * 2.HASH_Init(), HASH_Start() and HASH_Update() should be recalled before use this function + */ +uint32_t HASH_Complete(HASH_CTX *ctx, uint8_t *out); + +/** + * @brief Hash close + * @return HASH_Close_OK, Hash close success; othets: Hash close fail + * @note 1.Please refer to the demo in user guidance before using this function + */ +uint32_t HASH_Close(void); + +/** + * @brief SM3 Hash for 256bits digest + * @param[in] in pointer to message + * @param[in] byte length of in + * @param[out] out pointer tohash result,digest + * @return SM3_Hash_OK, SM3 hash success; othets: SM3 hash fail + * @note 1.Please refer to the demo in user guidance before using this function + */ +uint32_t SM3_Hash(uint8_t* in,uint32_t byteLen, uint8_t* out); + + +/** + * @brief SHA1 Hash + * @param[in] in pointer to message + * @param[in] byte length of in + * @param[out] out pointer tohash result,digest + * @return SHA1_Hash_OK, SHA1 hash success; othets: SHA1 hash fail + * @note 1.Please refer to the demo in user guidance before using this function + */ +uint32_t SHA1_Hash(uint8_t* in,uint32_t byteLen, uint8_t* out); + +/** + * @brief SHA224 Hash + * @param[in] in pointer to message + * @param[in] byte length of in + * @param[out] out pointer tohash result,digest + * @return SHA224_Hash_OK, SHA224 hash success; othets: SHA224 hash fail + * @note 1.Please refer to the demo in user guidance before using this function + */ +uint32_t SHA224_Hash(uint8_t* in,uint32_t byteLen, uint8_t* out); + + +/** + * @brief SHA256 Hash + * @param[in] in pointer to message + * @param[in] byte length of in + * @param[out] out pointer tohash result,digest + * @return SHA256_Hash_OK, SHA256 hash success; othets: SHA256 hash fail + * @note 1.Please refer to the demo in user guidance before using this function + */ +uint32_t SHA256_Hash(uint8_t* in,uint32_t byteLen, uint8_t* out); + +/** + * @brief MD5 Hash + * @param[in] in pointer to message + * @param[in] byte length of in + * @param[in] out pointer tohash result,digest + * @return MD5_Hash_OK, MD5 hash success; othets: MD5 hash fail + * @note 1.Please refer to the demo in user guidance before using this function + */ +uint32_t MD5_Hash(uint8_t* in,uint32_t byteLen, uint8_t* out); + +/** + * @brief Get HASH lib version + * @param[out] type pointer one byte type information represents the type of the lib, like Commercial version.\ + * @Bits 0~4 stands for Commercial (C), Security (S), Normal (N), Evaluation (E), Test (T), Bits 5~7 are reserved. e.g. 0x09 stands for CE version. + * @param[out] customer pointer one byte customer information represents customer ID. for example, 0x00 stands for standard version, 0x01 is for Tianyu customized version... + * @param[out] date pointer array which include three bytes date information. If the returned bytes are 18,9,13,this denotes September 13,2018 + * @param[out] version pointer one byte version information represents develop version of the lib. e.g. 0x12 denotes version 1.2. + * @return none + * @1.You can recall this function to get RSA lib information + */ +void HASH_Version(uint8_t *type, uint8_t *customer, uint8_t date[3], uint8_t *version); + + +#endif diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_rng.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_rng.h new file mode 100644 index 0000000000..aec294b8c9 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_algo_lib/inc/n32g4fr_rng.h @@ -0,0 +1,93 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_rng.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_RNG_H__ +#define __N32G4FR_RNG_H__ + +#include + +/** @addtogroup N32G4FR_Algorithm_Library + * @{ + */ + +/** @addtogroup RNG + * @brief Random number generator + * @{ + */ + + + +enum{ + RNG_OK = 0x5a5a5a5a, + LENError = 0x311ECF50, //RNG generation of key length error + ADDRNULL = 0x7A9DB86C, // This address is empty +}; + + +//u32 RNG_init(void); +/** + * @brief Get pseudo random number + * @param[out] rand pointer to random number + * @param[in] the wordlen of random number + * @param[in] the seed, can be NULL + * @return RNG_OK:get random number success; othets: get random number fail + * @note + */ +uint32_t GetPseudoRand_U32(uint32_t *rand, uint32_t wordLen,uint32_t seed[2]); + + +/** + * @brief Get true random number + * @param[out] rand pointer to random number + * @param[in] the wordlen of random number + * @return RNG_OK:get random number success; othets: get random number fail + * @note + */ +uint32_t GetTrueRand_U32(uint32_t *rand, uint32_t wordLen); + +/** + * @brief Get RNG lib version + * @param[out] type pointer one byte type information represents the type of the lib, like Commercial version.\ + * @Bits 0~4 stands for Commercial (C), Security (S), Normal (N), Evaluation (E), Test (T), Bits 5~7 are reserved. e.g. 0x09 stands for CE version. + * @param[out] customer pointer one byte customer information represents customer ID. for example, 0x00 stands for standard version, 0x01 is for Tianyu customized version... + * @param[out] date pointer array which include three bytes date information. If the returned bytes are 18,9,13,this denotes September 13,2018 + * @param[out] version pointer one byte version information represents develop version of the lib. e.g. 0x12 denotes version 1.2. + * @return none + * @1.You can recall this function to get RSA lib information + */ +void RNG_Version(uint8_t *type, uint8_t *customer, uint8_t date[3], uint8_t *version); + +#endif + + diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/misc.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/misc.h new file mode 100644 index 0000000000..fda67efe29 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/misc.h @@ -0,0 +1,228 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file misc.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __MISC_H__ +#define __MISC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup MISC + * @{ + */ + +/** @addtogroup MISC_Exported_Types + * @{ + */ + +/** + * @brief NVIC Init Structure definition + */ + +typedef struct +{ + uint8_t NVIC_IRQChannel; /*!< Specifies the IRQ channel to be enabled or disabled. + This parameter can be a value of @ref IRQn_Type + (For the complete N32G4FR Devices IRQ Channels list, please + refer to n32g4fr.h file) */ + + uint8_t + NVIC_IRQChannelPreemptionPriority; /*!< Specifies the pre-emption priority for the IRQ channel + specified in NVIC_IRQChannel. This parameter can be a value + between 0 and 15 as described in the table @ref NVIC_Priority_Table */ + + uint8_t NVIC_IRQChannelSubPriority; /*!< Specifies the subpriority level for the IRQ channel specified + in NVIC_IRQChannel. This parameter can be a value + between 0 and 15 as described in the table @ref NVIC_Priority_Table */ + + FunctionalState NVIC_IRQChannelCmd; /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel + will be enabled or disabled. + This parameter can be set either to ENABLE or DISABLE */ +} NVIC_InitType; + +/** + * @} + */ + +/** @addtogroup NVIC_Priority_Table + * @{ + */ + +/** +@code + The table below gives the allowed values of the pre-emption priority and subpriority according + to the Priority Grouping configuration performed by NVIC_PriorityGroupConfig function + ============================================================================================================================ + NVIC_PriorityGroup | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority | Description + ============================================================================================================================ + NVIC_PriorityGroup_0 | 0 | 0-15 | 0 bits for pre-emption +priority | | | 4 bits for subpriority + ---------------------------------------------------------------------------------------------------------------------------- + NVIC_PriorityGroup_1 | 0-1 | 0-7 | 1 bits for pre-emption +priority | | | 3 bits for subpriority + ---------------------------------------------------------------------------------------------------------------------------- + NVIC_PriorityGroup_2 | 0-3 | 0-3 | 2 bits for pre-emption +priority | | | 2 bits for subpriority + ---------------------------------------------------------------------------------------------------------------------------- + NVIC_PriorityGroup_3 | 0-7 | 0-1 | 3 bits for pre-emption +priority | | | 1 bits for subpriority + ---------------------------------------------------------------------------------------------------------------------------- + NVIC_PriorityGroup_4 | 0-15 | 0 | 4 bits for pre-emption +priority | | | 0 bits for subpriority + ============================================================================================================================ +@endcode +*/ + +/** + * @} + */ + +/** @addtogroup MISC_Exported_Constants + * @{ + */ + +/** @addtogroup Vector_Table_Base + * @{ + */ + +#define NVIC_VectTab_RAM ((uint32_t)0x20000000) +#define NVIC_VectTab_FLASH ((uint32_t)0x08000000) +#define IS_NVIC_VECTTAB(VECTTAB) (((VECTTAB) == NVIC_VectTab_RAM) || ((VECTTAB) == NVIC_VectTab_FLASH)) +/** + * @} + */ + +/** @addtogroup System_Low_Power + * @{ + */ + +#define NVIC_LP_SEVONPEND ((uint8_t)0x10) +#define NVIC_LP_SLEEPDEEP ((uint8_t)0x04) +#define NVIC_LP_SLEEPONEXIT ((uint8_t)0x02) +#define IS_NVIC_LP(LP) (((LP) == NVIC_LP_SEVONPEND) || ((LP) == NVIC_LP_SLEEPDEEP) || ((LP) == NVIC_LP_SLEEPONEXIT)) +/** + * @} + */ + +/** @addtogroup Preemption_Priority_Group + * @{ + */ + +#define NVIC_PriorityGroup_0 \ + ((uint32_t)0x700) /*!< 0 bits for pre-emption priority \ + 4 bits for subpriority */ +#define NVIC_PriorityGroup_1 \ + ((uint32_t)0x600) /*!< 1 bits for pre-emption priority \ + 3 bits for subpriority */ +#define NVIC_PriorityGroup_2 \ + ((uint32_t)0x500) /*!< 2 bits for pre-emption priority \ + 2 bits for subpriority */ +#define NVIC_PriorityGroup_3 \ + ((uint32_t)0x400) /*!< 3 bits for pre-emption priority \ + 1 bits for subpriority */ +#define NVIC_PriorityGroup_4 \ + ((uint32_t)0x300) /*!< 4 bits for pre-emption priority \ + 0 bits for subpriority */ + +#define IS_NVIC_PRIORITY_GROUP(GROUP) \ + (((GROUP) == NVIC_PriorityGroup_0) || ((GROUP) == NVIC_PriorityGroup_1) || ((GROUP) == NVIC_PriorityGroup_2) \ + || ((GROUP) == NVIC_PriorityGroup_3) || ((GROUP) == NVIC_PriorityGroup_4)) + +#define IS_NVIC_PREEMPTION_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) + +#define IS_NVIC_SUB_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) + +#define IS_NVIC_OFFSET(OFFSET) ((OFFSET) < 0x000FFFFF) + +/** + * @} + */ + +/** @addtogroup SysTick_clock_source + * @{ + */ + +//#define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB) +#define SysTick_CLKSource_HCLK ((uint32_t)0x00000004) +#define IS_SYSTICK_CLK_SOURCE(SOURCE) ((SOURCE) == SysTick_CLKSource_HCLK) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup MISC_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup MISC_Exported_Functions + * @{ + */ + +void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); +void NVIC_Init(NVIC_InitType* NVIC_InitStruct); +void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset); +void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState Cmd); +void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource); + +#ifdef __cplusplus +} +#endif + +#endif /* __MISC_H__ */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_adc.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_adc.h new file mode 100644 index 0000000000..748ed76380 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_adc.h @@ -0,0 +1,613 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_adc.h + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_ADC_H__ +#define __N32G4FR_ADC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" +#include + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ +#define VREF1P2_CTRL (*(uint32_t*)(0x40001800+0x20)) +#define _EnVref1p2() do{VREF1P2_CTRL|=(1<<10);}while(0); +#define _DisVref1p2() do{VREF1P2_CTRL&=~(1<<10);}while(0); +/** @addtogroup ADC + * @{ + */ + +/** @addtogroup ADC_Exported_Types + * @{ + */ + +/** + * @brief ADC Init structure definition + */ +typedef struct +{ + uint32_t WorkMode; /*!< Configures the ADC to operate in independent or + dual mode. + This parameter can be a value of @ref ADC_mode */ + + FunctionalState MultiChEn; /*!< Specifies whether the conversion is performed in + Scan (multichannels) or Single (one channel) mode. + This parameter can be set to ENABLE or DISABLE */ + + FunctionalState ContinueConvEn; /*!< Specifies whether the conversion is performed in + Continuous or Single mode. + This parameter can be set to ENABLE or DISABLE. */ + + uint32_t ExtTrigSelect; /*!< Defines the external trigger used to start the analog + to digital conversion of regular channels. This parameter + can be a value of @ref + ADC_external_trigger_sources_for_regular_channels_conversion */ + + uint32_t DatAlign; /*!< Specifies whether the ADC data alignment is left or right. + This parameter can be a value of @ref ADC_data_align */ + + uint8_t ChsNumber; /*!< Specifies the number of ADC channels that will be converted + using the sequencer for regular channel group. + This parameter must range from 1 to 16. */ +} ADC_InitType; +/** + * @} + */ + +/** @addtogroup ADC_Exported_Constants + * @{ + */ + +#define IsAdcModule(PERIPH) (((PERIPH) == ADC1) || ((PERIPH) == ADC2)) + +#define IsAdcDmaModule(PERIPH) (((PERIPH) == ADC1) || ((PERIPH) == ADC2)) + +/** @addtogroup ADC_mode + * @{ + */ + +#define ADC_WORKMODE_INDEPENDENT ((uint32_t)0x00000000) +#define ADC_WORKMODE_REG_INJECT_SIMULT ((uint32_t)0x00010000) +#define ADC_WORKMODE_REG_SIMULT_ALTER_TRIG ((uint32_t)0x00020000) +#define ADC_WORKMODE_INJ_SIMULT_FAST_INTERL ((uint32_t)0x00030000) +#define ADC_WORKMODE_INJ_SIMULT_SLOW_INTERL ((uint32_t)0x00040000) +#define ADC_WORKMODE_INJ_SIMULT ((uint32_t)0x00050000) +#define ADC_WORKMODE_REG_SIMULT ((uint32_t)0x00060000) +#define ADC_WORKMODE_FAST_INTERL ((uint32_t)0x00070000) +#define ADC_WORKMODE_SLOW_INTERL ((uint32_t)0x00080000) +#define ADC_WORKMODE_ALTER_TRIG ((uint32_t)0x00090000) + +#define IsAdcWorkMode(MODE) \ + (((MODE) == ADC_WORKMODE_INDEPENDENT) || ((MODE) == ADC_WORKMODE_REG_INJECT_SIMULT) \ + || ((MODE) == ADC_WORKMODE_REG_SIMULT_ALTER_TRIG) || ((MODE) == ADC_WORKMODE_INJ_SIMULT_FAST_INTERL) \ + || ((MODE) == ADC_WORKMODE_INJ_SIMULT_SLOW_INTERL) || ((MODE) == ADC_WORKMODE_INJ_SIMULT) \ + || ((MODE) == ADC_WORKMODE_REG_SIMULT) || ((MODE) == ADC_WORKMODE_FAST_INTERL) \ + || ((MODE) == ADC_WORKMODE_SLOW_INTERL) || ((MODE) == ADC_WORKMODE_ALTER_TRIG)) +/** + * @} + */ + +/** @addtogroup ADC_external_trigger_sources_for_regular_channels_conversion + * @{ + */ + +#define ADC_EXT_TRIGCONV_T1_CC1 ((uint32_t)0x00000000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIGCONV_T1_CC2 ((uint32_t)0x00020000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIGCONV_T2_CC2 ((uint32_t)0x00060000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIGCONV_T3_TRGO ((uint32_t)0x00080000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIGCONV_T4_CC4 ((uint32_t)0x000A0000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIGCONV_EXT_INT11_TIM8_TRGO ((uint32_t)0x000C0000) /*!< For ADC1 and ADC2 */ + +#define ADC_EXT_TRIGCONV_T1_CC3 ((uint32_t)0x00040000) /*!< For ADC1, ADC2 */ +#define ADC_EXT_TRIGCONV_NONE ((uint32_t)0x000E0000) /*!< For ADC1, ADC2 */ + + +#define IsAdcExtTrig(REGTRIG) \ + (((REGTRIG) == ADC_EXT_TRIGCONV_T1_CC1) || ((REGTRIG) == ADC_EXT_TRIGCONV_T1_CC2) \ + || ((REGTRIG) == ADC_EXT_TRIGCONV_T1_CC3) || ((REGTRIG) == ADC_EXT_TRIGCONV_T2_CC2) \ + || ((REGTRIG) == ADC_EXT_TRIGCONV_T3_TRGO) || ((REGTRIG) == ADC_EXT_TRIGCONV_T4_CC4) \ + || ((REGTRIG) == ADC_EXT_TRIGCONV_EXT_INT11_TIM8_TRGO) || ((REGTRIG) == ADC_EXT_TRIGCONV_NONE)) +/** + * @} + */ + +/** @addtogroup ADC_data_align + * @{ + */ + +#define ADC_DAT_ALIGN_R ((uint32_t)0x00000000) +#define ADC_DAT_ALIGN_L ((uint32_t)0x00000800) +#define IsAdcDatAlign(ALIGN) (((ALIGN) == ADC_DAT_ALIGN_R) || ((ALIGN) == ADC_DAT_ALIGN_L)) +/** + * @} + */ + +/** @addtogroup ADC_channels + * @{ + */ + +#define ADC_CH_0 ((uint8_t)0x00) +#define ADC_CH_1 ((uint8_t)0x01) +#define ADC_CH_2 ((uint8_t)0x02) +#define ADC_CH_3 ((uint8_t)0x03) +#define ADC_CH_4 ((uint8_t)0x04) +#define ADC_CH_5 ((uint8_t)0x05) +#define ADC_CH_6 ((uint8_t)0x06) +#define ADC_CH_7 ((uint8_t)0x07) +#define ADC_CH_8 ((uint8_t)0x08) +#define ADC_CH_9 ((uint8_t)0x09) +#define ADC_CH_10 ((uint8_t)0x0A) +#define ADC_CH_11 ((uint8_t)0x0B) +#define ADC_CH_12 ((uint8_t)0x0C) +#define ADC_CH_13 ((uint8_t)0x0D) +#define ADC_CH_14 ((uint8_t)0x0E) +#define ADC_CH_15 ((uint8_t)0x0F) +#define ADC_CH_16 ((uint8_t)0x10) +#define ADC_CH_17 ((uint8_t)0x11) +#define ADC_CH_18 ((uint8_t)0x12) + +#define ADC_CH_TEMP_SENSOR ((uint8_t)ADC_CH_16) +#define ADC_CH_INT_VREF ((uint8_t)ADC_CH_18) + +#define IsAdcChannel(CHANNEL) \ + (((CHANNEL) == ADC_CH_0) || ((CHANNEL) == ADC_CH_1) || ((CHANNEL) == ADC_CH_2) || ((CHANNEL) == ADC_CH_3) \ + || ((CHANNEL) == ADC_CH_4) || ((CHANNEL) == ADC_CH_5) || ((CHANNEL) == ADC_CH_6) || ((CHANNEL) == ADC_CH_7) \ + || ((CHANNEL) == ADC_CH_8) || ((CHANNEL) == ADC_CH_9) || ((CHANNEL) == ADC_CH_10) || ((CHANNEL) == ADC_CH_11) \ + || ((CHANNEL) == ADC_CH_12) || ((CHANNEL) == ADC_CH_13) || ((CHANNEL) == ADC_CH_14) || ((CHANNEL) == ADC_CH_15) \ + || ((CHANNEL) == ADC_CH_16) || ((CHANNEL) == ADC_CH_17) || ((CHANNEL) == ADC_CH_18)) +/** + * @} + */ + +/** @addtogroup ADC_sampling_time + * @{ + */ + +#define ADC_SAMP_TIME_1CYCLES5 ((uint8_t)0x00) +#define ADC_SAMP_TIME_7CYCLES5 ((uint8_t)0x01) +#define ADC_SAMP_TIME_13CYCLES5 ((uint8_t)0x02) +#define ADC_SAMP_TIME_28CYCLES5 ((uint8_t)0x03) +#define ADC_SAMP_TIME_41CYCLES5 ((uint8_t)0x04) +#define ADC_SAMP_TIME_55CYCLES5 ((uint8_t)0x05) +#define ADC_SAMP_TIME_71CYCLES5 ((uint8_t)0x06) +#define ADC_SAMP_TIME_239CYCLES5 ((uint8_t)0x07) +#define IsAdcSampleTime(TIME) \ + (((TIME) == ADC_SAMP_TIME_1CYCLES5) || ((TIME) == ADC_SAMP_TIME_7CYCLES5) || ((TIME) == ADC_SAMP_TIME_13CYCLES5) \ + || ((TIME) == ADC_SAMP_TIME_28CYCLES5) || ((TIME) == ADC_SAMP_TIME_41CYCLES5) \ + || ((TIME) == ADC_SAMP_TIME_55CYCLES5) || ((TIME) == ADC_SAMP_TIME_71CYCLES5) \ + || ((TIME) == ADC_SAMP_TIME_239CYCLES5)) +/** + * @} + */ + +/** @addtogroup ADC_external_trigger_sources_for_injected_channels_conversion + * @{ + */ + +#define ADC_EXT_TRIG_INJ_CONV_T2_TRGO ((uint32_t)0x00002000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIG_INJ_CONV_T2_CC1 ((uint32_t)0x00003000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIG_INJ_CONV_T3_CC4 ((uint32_t)0x00004000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIG_INJ_CONV_T4_TRGO ((uint32_t)0x00005000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIG_INJ_CONV_EXT_INT15_TIM8_CC4 ((uint32_t)0x00006000) /*!< For ADC1 and ADC2 */ + +#define ADC_EXT_TRIG_INJ_CONV_T1_TRGO ((uint32_t)0x00000000) /*!< For ADC1, ADC2 */ +#define ADC_EXT_TRIG_INJ_CONV_T1_CC4 ((uint32_t)0x00001000) /*!< For ADC1, ADC2 */ +#define ADC_EXT_TRIG_INJ_CONV_NONE ((uint32_t)0x00007000) /*!< For ADC1, ADC2 */ + +#define IsAdcExtInjTrig(INJTRIG) \ + (((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T1_TRGO) || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T1_CC4) \ + || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T2_TRGO) || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T2_CC1) \ + || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T3_CC4) || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T4_TRGO) \ + || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_EXT_INT15_TIM8_CC4) || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_NONE)) +/** + * @} + */ + +/** @addtogroup ADC_injected_channel_selection + * @{ + */ + +#define ADC_INJ_CH_1 ((uint8_t)0x14) +#define ADC_INJ_CH_2 ((uint8_t)0x18) +#define ADC_INJ_CH_3 ((uint8_t)0x1C) +#define ADC_INJ_CH_4 ((uint8_t)0x20) +#define IsAdcInjCh(CHANNEL) \ + (((CHANNEL) == ADC_INJ_CH_1) || ((CHANNEL) == ADC_INJ_CH_2) || ((CHANNEL) == ADC_INJ_CH_3) \ + || ((CHANNEL) == ADC_INJ_CH_4)) +/** + * @} + */ + +/** @addtogroup ADC_analog_watchdog_selection + * @{ + */ + +#define ADC_ANALOG_WTDG_SINGLEREG_ENABLE ((uint32_t)0x00800200) +#define ADC_ANALOG_WTDG_SINGLEINJEC_ENABLE ((uint32_t)0x00400200) +#define ADC_ANALOG_WTDG_SINGLEREG_OR_INJEC_ENABLE ((uint32_t)0x00C00200) +#define ADC_ANALOG_WTDG_ALLREG_ENABLE ((uint32_t)0x00800000) +#define ADC_ANALOG_WTDG_ALLINJEC_ENABLE ((uint32_t)0x00400000) +#define ADC_ANALOG_WTDG_ALLREG_ALLINJEC_ENABLE ((uint32_t)0x00C00000) +#define ADC_ANALOG_WTDG_NONE ((uint32_t)0x00000000) + +#define IsAdcAnalogWatchdog(WATCHDOG) \ + (((WATCHDOG) == ADC_ANALOG_WTDG_SINGLEREG_ENABLE) || ((WATCHDOG) == ADC_ANALOG_WTDG_SINGLEINJEC_ENABLE) \ + || ((WATCHDOG) == ADC_ANALOG_WTDG_SINGLEREG_OR_INJEC_ENABLE) || ((WATCHDOG) == ADC_ANALOG_WTDG_ALLREG_ENABLE) \ + || ((WATCHDOG) == ADC_ANALOG_WTDG_ALLINJEC_ENABLE) || ((WATCHDOG) == ADC_ANALOG_WTDG_ALLREG_ALLINJEC_ENABLE) \ + || ((WATCHDOG) == ADC_ANALOG_WTDG_NONE)) +/** + * @} + */ + +/** @addtogroup ADC_interrupts_definition + * @{ + */ + +#define ADC_INT_ENDC ((uint16_t)0x0220) +#define ADC_INT_AWD ((uint16_t)0x0140) +#define ADC_INT_JENDC ((uint16_t)0x0480) + +#define IsAdcInt(IT) ((((IT) & (uint16_t)0xF81F) == 0x00) && ((IT) != 0x00)) + +#define IsAdcGetInt(IT) (((IT) == ADC_INT_ENDC) || ((IT) == ADC_INT_AWD) || ((IT) == ADC_INT_JENDC)) +/** + * @} + */ + +/** @addtogroup ADC_flags_definition + * @{ + */ + +#define ADC_FLAG_AWDG ((uint8_t)0x01) +#define ADC_FLAG_ENDC ((uint8_t)0x02) +#define ADC_FLAG_JENDC ((uint8_t)0x04) +#define ADC_FLAG_JSTR ((uint8_t)0x08) +#define ADC_FLAG_STR ((uint8_t)0x10) +#define ADC_FLAG_EOC_ANY ((uint8_t)0x20) +#define ADC_FLAG_JEOC_ANY ((uint8_t)0x40) +#define IsAdcClrFlag(FLAG) ((((FLAG) & (uint8_t)0x80) == 0x00) && ((FLAG) != 0x00)) +#define IsAdcGetFlag(FLAG) \ + (((FLAG) == ADC_FLAG_AWDG) || ((FLAG) == ADC_FLAG_ENDC) || ((FLAG) == ADC_FLAG_JENDC) || ((FLAG) == ADC_FLAG_JSTR) \ + || ((FLAG) == ADC_FLAG_STR) || ((FLAG) == ADC_FLAG_EOC_ANY) || ((FLAG) == ADC_FLAG_JEOC_ANY)) +/** + * @} + */ + +/** @addtogroup ADC_thresholds + * @{ + */ +#define IsAdcValid(THRESHOLD) ((THRESHOLD) <= 0xFFF) +/** + * @} + */ + +/** @addtogroup ADC_injected_offset + * @{ + */ + +#define IsAdcOffsetValid(OFFSET) ((OFFSET) <= 0xFFF) + +/** + * @} + */ + +/** @addtogroup ADC_injected_length + * @{ + */ + +#define IsAdcInjLenValid(LENGTH) (((LENGTH) >= 0x1) && ((LENGTH) <= 0x4)) + +/** + * @} + */ + +/** @addtogroup ADC_injected_rank + * @{ + */ + +#define IsAdcInjRankValid(RANK) (((RANK) >= 0x1) && ((RANK) <= 0x4)) + +/** + * @} + */ + +/** @addtogroup ADC_regular_length + * @{ + */ + +#define IsAdcSeqLenValid(LENGTH) (((LENGTH) >= 0x1) && ((LENGTH) <= 0x10)) +/** + * @} + */ + +/** @addtogroup ADC_regular_rank + * @{ + */ + +#define IsAdcReqRankValid(RANK) (((RANK) >= 0x1) && ((RANK) <= 0x10)) + +/** + * @} + */ + +/** @addtogroup ADC_regular_discontinuous_mode_number + * @{ + */ + +#define IsAdcSeqDiscNumberValid(NUMBER) (((NUMBER) >= 0x1) && ((NUMBER) <= 0x8)) + +/** + * @} + */ + +/************************** fllowing bit seg in ex register **********************/ +/**@addtogroup ADC_channels_ex_style + * @{ + */ +#define ADC1_Channel_01_PA0 ((uint8_t)0x01) +#define ADC1_Channel_02_PA1 ((uint8_t)0x02) +#define ADC1_Channel_03_PA6 ((uint8_t)0x03) +#define ADC1_Channel_04_PA3 ((uint8_t)0x04) +#define ADC1_Channel_05_PF4 ((uint8_t)0x05) +#define ADC1_Channel_06_PC0 ((uint8_t)0x06) +#define ADC1_Channel_07_PC1 ((uint8_t)0x07) +#define ADC1_Channel_08_PC2 ((uint8_t)0x08) +#define ADC1_Channel_09_PC3 ((uint8_t)0x09) +#define ADC1_Channel_10_PF2 ((uint8_t)0x0A) +#define ADC1_Channel_11_PA2 ((uint8_t)0x0B) + +#define ADC2_Channel_01_PA4 ((uint8_t)0x01) +#define ADC2_Channel_02_PA5 ((uint8_t)0x02) +#define ADC2_Channel_03_PB1 ((uint8_t)0x03) +#define ADC2_Channel_04_PA7 ((uint8_t)0x04) +#define ADC2_Channel_05_PC4 ((uint8_t)0x05) +#define ADC2_Channel_06_PC0 ((uint8_t)0x06) +#define ADC2_Channel_07_PC1 ((uint8_t)0x07) +#define ADC2_Channel_08_PC2 ((uint8_t)0x08) +#define ADC2_Channel_09_PC3 ((uint8_t)0x09) +#define ADC2_Channel_10_PF2 ((uint8_t)0x0A) +#define ADC2_Channel_11_PA2 ((uint8_t)0x0B) +#define ADC2_Channel_12_PC5 ((uint8_t)0x0C) +#define ADC2_Channel_13_PB2 ((uint8_t)0x0D) + +#define ADC_CH_0 ((uint8_t)0x00) +#define ADC_CH_1 ((uint8_t)0x01) +#define ADC_CH_2 ((uint8_t)0x02) +#define ADC_CH_3 ((uint8_t)0x03) +#define ADC_CH_4 ((uint8_t)0x04) +#define ADC_CH_5 ((uint8_t)0x05) +#define ADC_CH_6 ((uint8_t)0x06) +#define ADC_CH_7 ((uint8_t)0x07) +#define ADC_CH_8 ((uint8_t)0x08) +#define ADC_CH_9 ((uint8_t)0x09) +#define ADC_CH_10 ((uint8_t)0x0A) +#define ADC_CH_11 ((uint8_t)0x0B) +#define ADC_CH_12 ((uint8_t)0x0C) +#define ADC_CH_13 ((uint8_t)0x0D) +#define ADC_CH_14 ((uint8_t)0x0E) +#define ADC_CH_15 ((uint8_t)0x0F) +#define ADC_CH_16 ((uint8_t)0x10) +#define ADC_CH_17 ((uint8_t)0x11) +#define ADC_CH_18 ((uint8_t)0x12) +/** + * @} + */ + +/**@addtogroup ADC_dif_sel_ch_definition + * @{ + */ +#define ADC_DIFSEL_CHS_MASK ((uint32_t)0x0007FFFE) +#define ADC_DIFSEL_CHS_1 ((uint32_t)0x00000002) +#define ADC_DIFSEL_CHS_2 ((uint32_t)0x00000004) +#define ADC_DIFSEL_CHS_3 ((uint32_t)0x00000008) +#define ADC_DIFSEL_CHS_4 ((uint32_t)0x00000010) +#define ADC_DIFSEL_CHS_5 ((uint32_t)0x00000020) +#define ADC_DIFSEL_CHS_6 ((uint32_t)0x00000040) +#define ADC_DIFSEL_CHS_7 ((uint32_t)0x00000080) +#define ADC_DIFSEL_CHS_8 ((uint32_t)0x00000100) +#define ADC_DIFSEL_CHS_9 ((uint32_t)0x00000200) +#define ADC_DIFSEL_CHS_10 ((uint32_t)0x00000400) +#define ADC_DIFSEL_CHS_11 ((uint32_t)0x00000800) +#define ADC_DIFSEL_CHS_12 ((uint32_t)0x00001000) +#define ADC_DIFSEL_CHS_13 ((uint32_t)0x00002000) +#define ADC_DIFSEL_CHS_14 ((uint32_t)0x00004000) +#define ADC_DIFSEL_CHS_15 ((uint32_t)0x00008000) +#define ADC_DIFSEL_CHS_16 ((uint32_t)0x00010000) +#define ADC_DIFSEL_CHS_17 ((uint32_t)0x00020000) +#define ADC_DIFSEL_CHS_18 ((uint32_t)0x00040000) +/** + * @} + */ + +/**@addtogroup ADC_calfact_definition + * @{ + */ +#define ADC_CALFACT_CALFACTD_MSK ((uint32_t)0x3FL << 16) +#define ADC_CALFACT_CALFACTS_MSK ((uint32_t)0x3FL << 0) +/** + * @} + */ + +/**@addtogroup ADC_ctrl3_definition + * @{ + */ +#define ADC_CTRL3_VABTMEN_MSK ((uint32_t)0x01L << 11) +#define ADC_CTRL3_DPWMOD_MSK ((uint32_t)0x01L << 10) +#define ADC_CTRL3_JENDCAIEN_MSK ((uint32_t)0x01L << 9) +#define ADC_CTRL3_ENDCAIEN_MSK ((uint32_t)0x01L << 8) +#define ADC_CTRL3_BPCAL_MSK ((uint32_t)0x01L << 7) +#define ADC_CTRL3_PDRDY_MSK ((uint32_t)0x01L << 6) +#define ADC_CTRL3_RDY_MSK ((uint32_t)0x01L << 5) +#define ADC_CTRL3_CKMOD_MSK ((uint32_t)0x01L << 4) +#define ADC_CTRL3_CALALD_MSK ((uint32_t)0x01L << 3) +#define ADC_CTRL3_CALDIF_MSK ((uint32_t)0x01L << 2) +#define ADC_CTRL3_RES_MSK ((uint32_t)0x03L << 0) + +/** + * @} + */ + +#define ADC_CLOCK_PLL ((uint32_t)ADC_CTRL3_CKMOD_MSK) +#define ADC_CLOCK_AHB ((uint32_t)(~ADC_CTRL3_CKMOD_MSK)) + +/**@addtogroup ADC_sampt3_definition + * @{ + */ +#define ADC_SAMPT3_SAMPSEL_MSK ((uint32_t)0x01L << 3) +/** + * @} + */ + +typedef enum +{ + ADC_CTRL3_CKMOD_AHB = 0, + ADC_CTRL3_CKMOD_PLL = 1, +} ADC_CTRL3_CKMOD; +typedef enum +{ + ADC_CTRL3_RES_12BIT = 3, + ADC_CTRL3_RES_10BIT = 2, + ADC_CTRL3_RES_8BIT = 1, + ADC_CTRL3_RES_6BIT = 0, +} ADC_CTRL3_RES; +typedef struct +{ + FunctionalState VbatMinitEn; + FunctionalState DeepPowerModEn; + FunctionalState JendcIntEn; + FunctionalState EndcIntEn; + ADC_CTRL3_CKMOD ClkMode; + FunctionalState CalAtuoLoadEn; + bool DifModCal; + ADC_CTRL3_RES ResBit; + bool Samp303Style; +} ADC_InitTypeEx; +/** + * @} + */ + +/*ADC_SAMPT3 only have samp time and smp18[2:0],samp18 is refint ch, change to row function*/ +/*ADC_IPTST reseverd register ,not to do it*/ + +/**@addtogroup ADC_bit_num_definition + * @{ + */ +#define ADC_RST_BIT_12 ((uint32_t)0x03) +#define ADC_RST_BIT_10 ((uint32_t)0x02) +#define ADC_RST_BIT_8 ((uint32_t)0x01) +#define ADC_RESULT_BIT_6 ((uint32_t)0x00) +/** + * @} + */ + +/** @addtogroup ADC_flags_ex_definition + * @{ + */ +#define ADC_FLAG_RDY ((uint8_t)0x20) +#define ADC_FLAG_PD_RDY ((uint8_t)0x40) +#define IS_ADC_GET_READY(FLAG) (((FLAG) == ADC_FLAG_RDY) || ((FLAG) == ADC_FLAG_PD_RDY) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup ADC_Exported_Functions + * @{ + */ + +void ADC_DeInit(ADC_Module* ADCx); +void ADC_Init(ADC_Module* ADCx, ADC_InitType* ADC_InitStruct); +void ADC_InitStruct(ADC_InitType* ADC_InitStruct); +void ADC_Enable(ADC_Module* ADCx, FunctionalState Cmd); +void ADC_EnableDMA(ADC_Module* ADCx, FunctionalState Cmd); +void ADC_ConfigInt(ADC_Module* ADCx, uint16_t ADC_IT, FunctionalState Cmd); +void ADC_StartCalibration(ADC_Module* ADCx); +FlagStatus ADC_GetCalibrationStatus(ADC_Module* ADCx); +void ADC_EnableSoftwareStartConv(ADC_Module* ADCx, FunctionalState Cmd); +FlagStatus ADC_GetSoftwareStartConvStatus(ADC_Module* ADCx); +void ADC_ConfigDiscModeChannelCount(ADC_Module* ADCx, uint8_t Number); +void ADC_EnableDiscMode(ADC_Module* ADCx, FunctionalState Cmd); +void ADC_ConfigRegularChannel(ADC_Module* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); +void ADC_EnableExternalTrigConv(ADC_Module* ADCx, FunctionalState Cmd); +uint16_t ADC_GetDat(ADC_Module* ADCx); +uint32_t ADC_GetDualModeConversionDat(ADC_Module* ADCx); +void ADC_EnableAutoInjectedConv(ADC_Module* ADCx, FunctionalState Cmd); +void ADC_EnableInjectedDiscMode(ADC_Module* ADCx, FunctionalState Cmd); +void ADC_ConfigExternalTrigInjectedConv(ADC_Module* ADCx, uint32_t ADC_ExternalTrigInjecConv); +void ADC_EnableExternalTrigInjectedConv(ADC_Module* ADCx, FunctionalState Cmd); +void ADC_EnableSoftwareStartInjectedConv(ADC_Module* ADCx, FunctionalState Cmd); +FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_Module* ADCx); +void ADC_ConfigInjectedChannel(ADC_Module* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); +void ADC_ConfigInjectedSequencerLength(ADC_Module* ADCx, uint8_t Length); +void ADC_SetInjectedOffsetDat(ADC_Module* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset); +uint16_t ADC_GetInjectedConversionDat(ADC_Module* ADCx, uint8_t ADC_InjectedChannel); +void ADC_ConfigAnalogWatchdogWorkChannelType(ADC_Module* ADCx, uint32_t ADC_AnalogWatchdog); +void ADC_ConfigAnalogWatchdogThresholds(ADC_Module* ADCx, uint16_t HighThreshold, uint16_t LowThreshold); +void ADC_ConfigAnalogWatchdogSingleChannel(ADC_Module* ADCx, uint8_t ADC_Channel); +void ADC_EnableTempSensorVrefint(FunctionalState Cmd); +FlagStatus ADC_GetFlagStatus(ADC_Module* ADCx, uint8_t ADC_FLAG); +void ADC_ClearFlag(ADC_Module* ADCx, uint8_t ADC_FLAG); +INTStatus ADC_GetIntStatus(ADC_Module* ADCx, uint16_t ADC_IT); +void ADC_ClearIntPendingBit(ADC_Module* ADCx, uint16_t ADC_IT); + +void ADC_InitEx(ADC_Module* ADCx, ADC_InitTypeEx* ADC_InitStructEx); +void ADC_SetDifChs(ADC_Module* ADCx,uint32_t DifChs); +FlagStatus ADC_GetFlagStatusNew(ADC_Module* ADCx, uint8_t ADC_FLAG_NEW); +void ADC_SetBypassCalibration(ADC_Module* ADCx, FunctionalState en); +void ADC_SetConvResultBitNum(ADC_Module* ADCx, uint32_t ResultBitNum); + +void ADC_ConfigClk(ADC_CTRL3_CKMOD ADC_ClkMode, uint32_t RCC_ADCHCLKPrescaler); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G4FR_ADC_H__ */ + +/** + * @} + */ +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_bkp.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_bkp.h new file mode 100644 index 0000000000..b42c9bf820 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_bkp.h @@ -0,0 +1,181 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_bkp.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_BKP_H__ +#define __N32G4FR_BKP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup BKP + * @{ + */ + +/** @addtogroup BKP_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @addtogroup BKP_Exported_Constants + * @{ + */ + +/** @addtogroup Tamper_Pin_active_level + * @{ + */ + +#define BKP_TP_HIGH ((uint16_t)0x0000) +#define BKP_TP_LOW ((uint16_t)0x0001) +#define IS_BKP_TP_LEVEL(LEVEL) (((LEVEL) == BKP_TP_HIGH) || ((LEVEL) == BKP_TP_LOW)) +/** + * @} + */ + +/** @addtogroup Data_Backup_Register + * @{ + */ + +#define BKP_DAT1 ((uint16_t)0x0004) +#define BKP_DAT2 ((uint16_t)0x0008) +#define BKP_DAT3 ((uint16_t)0x000C) +#define BKP_DAT4 ((uint16_t)0x0010) +#define BKP_DAT5 ((uint16_t)0x0014) +#define BKP_DAT6 ((uint16_t)0x0018) +#define BKP_DAT7 ((uint16_t)0x001C) +#define BKP_DAT8 ((uint16_t)0x0020) +#define BKP_DAT9 ((uint16_t)0x0024) +#define BKP_DAT10 ((uint16_t)0x0028) +#define BKP_DAT11 ((uint16_t)0x0040) +#define BKP_DAT12 ((uint16_t)0x0044) +#define BKP_DAT13 ((uint16_t)0x0048) +#define BKP_DAT14 ((uint16_t)0x004C) +#define BKP_DAT15 ((uint16_t)0x0050) +#define BKP_DAT16 ((uint16_t)0x0054) +#define BKP_DAT17 ((uint16_t)0x0058) +#define BKP_DAT18 ((uint16_t)0x005C) +#define BKP_DAT19 ((uint16_t)0x0060) +#define BKP_DAT20 ((uint16_t)0x0064) +#define BKP_DAT21 ((uint16_t)0x0068) +#define BKP_DAT22 ((uint16_t)0x006C) +#define BKP_DAT23 ((uint16_t)0x0070) +#define BKP_DAT24 ((uint16_t)0x0074) +#define BKP_DAT25 ((uint16_t)0x0078) +#define BKP_DAT26 ((uint16_t)0x007C) +#define BKP_DAT27 ((uint16_t)0x0080) +#define BKP_DAT28 ((uint16_t)0x0084) +#define BKP_DAT29 ((uint16_t)0x0088) +#define BKP_DAT30 ((uint16_t)0x008C) +#define BKP_DAT31 ((uint16_t)0x0090) +#define BKP_DAT32 ((uint16_t)0x0094) +#define BKP_DAT33 ((uint16_t)0x0098) +#define BKP_DAT34 ((uint16_t)0x009C) +#define BKP_DAT35 ((uint16_t)0x00A0) +#define BKP_DAT36 ((uint16_t)0x00A4) +#define BKP_DAT37 ((uint16_t)0x00A8) +#define BKP_DAT38 ((uint16_t)0x00AC) +#define BKP_DAT39 ((uint16_t)0x00B0) +#define BKP_DAT40 ((uint16_t)0x00B4) +#define BKP_DAT41 ((uint16_t)0x00B8) +#define BKP_DAT42 ((uint16_t)0x00BC) + +#define IS_BKP_DAT(DAT) \ + (((DAT) == BKP_DAT1) || ((DAT) == BKP_DAT2) || ((DAT) == BKP_DAT3) || ((DAT) == BKP_DAT4) || ((DAT) == BKP_DAT5) \ + || ((DAT) == BKP_DAT6) || ((DAT) == BKP_DAT7) || ((DAT) == BKP_DAT8) || ((DAT) == BKP_DAT9) \ + || ((DAT) == BKP_DAT10) || ((DAT) == BKP_DAT11) || ((DAT) == BKP_DAT12) || ((DAT) == BKP_DAT13) \ + || ((DAT) == BKP_DAT14) || ((DAT) == BKP_DAT15) || ((DAT) == BKP_DAT16) || ((DAT) == BKP_DAT17) \ + || ((DAT) == BKP_DAT18) || ((DAT) == BKP_DAT19) || ((DAT) == BKP_DAT20) || ((DAT) == BKP_DAT21) \ + || ((DAT) == BKP_DAT22) || ((DAT) == BKP_DAT23) || ((DAT) == BKP_DAT24) || ((DAT) == BKP_DAT25) \ + || ((DAT) == BKP_DAT26) || ((DAT) == BKP_DAT27) || ((DAT) == BKP_DAT28) || ((DAT) == BKP_DAT29) \ + || ((DAT) == BKP_DAT30) || ((DAT) == BKP_DAT31) || ((DAT) == BKP_DAT32) || ((DAT) == BKP_DAT33) \ + || ((DAT) == BKP_DAT34) || ((DAT) == BKP_DAT35) || ((DAT) == BKP_DAT36) || ((DAT) == BKP_DAT37) \ + || ((DAT) == BKP_DAT38) || ((DAT) == BKP_DAT39) || ((DAT) == BKP_DAT40) || ((DAT) == BKP_DAT41) \ + || ((DAT) == BKP_DAT42)) + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup BKP_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup BKP_Exported_Functions + * @{ + */ + +void BKP_DeInit(void); +void BKP_ConfigTPLevel(uint16_t BKP_TamperPinLevel); +void BKP_TPEnable(FunctionalState Cmd); +void BKP_TPIntEnable(FunctionalState Cmd); +void BKP_WriteBkpData(uint16_t BKP_DAT, uint16_t Data); +uint16_t BKP_ReadBkpData(uint16_t BKP_DAT); +FlagStatus BKP_GetTEFlag(void); +void BKP_ClrTEFlag(void); +INTStatus BKP_GetTINTFlag(void); +void BKP_ClrTINTFlag(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G4FR_BKP_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_can.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_can.h new file mode 100644 index 0000000000..947dd31354 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_can.h @@ -0,0 +1,671 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_can.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_CAN_H__ +#define __N32G4FR_CAN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup CAN + * @{ + */ + +/** @addtogroup CAN_Exported_Types + * @{ + */ + +#define IS_CAN_ALL_PERIPH(PERIPH) (((PERIPH) == CAN1) || ((PERIPH) == CAN2)) + +/** + * @brief CAN init structure definition + */ + +typedef struct +{ + uint16_t BaudRatePrescaler; /*!< Specifies the length of a time quantum. + It ranges from 1 to 1024. */ + + uint8_t OperatingMode; /*!< Specifies the CAN operating mode. + This parameter can be a value of + @ref CAN_operating_mode */ + + uint8_t RSJW; /*!< Specifies the maximum number of time quanta + the CAN hardware is allowed to lengthen or + shorten a bit to perform resynchronization. + This parameter can be a value of + @ref CAN_synchronisation_jump_width */ + + uint8_t TBS1; /*!< Specifies the number of time quanta in Bit + Segment 1. This parameter can be a value of + @ref CAN_time_quantum_in_bit_segment_1 */ + + uint8_t TBS2; /*!< Specifies the number of time quanta in Bit + Segment 2. + This parameter can be a value of + @ref CAN_time_quantum_in_bit_segment_2 */ + + FunctionalState TTCM; /*!< Enable or disable the time triggered + communication mode. This parameter can be set + either to ENABLE or DISABLE. */ + + FunctionalState ABOM; /*!< Enable or disable the automatic bus-off + management. This parameter can be set either + to ENABLE or DISABLE. */ + + FunctionalState AWKUM; /*!< Enable or disable the automatic wake-up mode. + This parameter can be set either to ENABLE or + DISABLE. */ + + FunctionalState NART; /*!< Enable or disable the no-automatic + retransmission mode. This parameter can be + set either to ENABLE or DISABLE. */ + + FunctionalState RFLM; /*!< Enable or disable the Receive DATFIFO Locked mode. + This parameter can be set either to ENABLE + or DISABLE. */ + + FunctionalState TXFP; /*!< Enable or disable the transmit DATFIFO priority. + This parameter can be set either to ENABLE + or DISABLE. */ +} CAN_InitType; + +/** + * @brief CAN filter init structure definition + */ + +typedef struct +{ + uint16_t Filter_HighId; /*!< Specifies the filter identification number (MSBs for a 32-bit + configuration, first one for a 16-bit configuration). + This parameter can be a value between 0x0000 and 0xFFFF */ + + uint16_t Filter_LowId; /*!< Specifies the filter identification number (LSBs for a 32-bit + configuration, second one for a 16-bit configuration). + This parameter can be a value between 0x0000 and 0xFFFF */ + + uint16_t FilterMask_HighId; /*!< Specifies the filter mask number or identification number, + according to the mode (MSBs for a 32-bit configuration, + first one for a 16-bit configuration). + This parameter can be a value between 0x0000 and 0xFFFF */ + + uint16_t FilterMask_LowId; /*!< Specifies the filter mask number or identification number, + according to the mode (LSBs for a 32-bit configuration, + second one for a 16-bit configuration). + This parameter can be a value between 0x0000 and 0xFFFF */ + + uint16_t Filter_FIFOAssignment; /*!< Specifies the DATFIFO (0 or 1) which will be assigned to the filter. + This parameter can be a value of @ref CAN_filter_FIFO */ + + uint8_t Filter_Num; /*!< Specifies the filter which will be initialized. It ranges from 0 to 13. */ + + uint8_t Filter_Mode; /*!< Specifies the filter mode to be initialized. + This parameter can be a value of @ref CAN_filter_mode */ + + uint8_t Filter_Scale; /*!< Specifies the filter scale. + This parameter can be a value of @ref CAN_filter_scale */ + + FunctionalState Filter_Act; /*!< Enable or disable the filter. + This parameter can be set either to ENABLE or DISABLE. */ +} CAN_FilterInitType; + +/** + * @brief CAN Tx message structure definition + */ + +typedef struct +{ + uint32_t StdId; /*!< Specifies the standard identifier. + This parameter can be a value between 0 to 0x7FF. */ + + uint32_t ExtId; /*!< Specifies the extended identifier. + This parameter can be a value between 0 to 0x1FFFFFFF. */ + + uint8_t IDE; /*!< Specifies the type of identifier for the message that + will be transmitted. This parameter can be a value + of @ref CAN_identifier_type */ + + uint8_t RTR; /*!< Specifies the type of frame for the message that will + be transmitted. This parameter can be a value of + @ref CAN_remote_transmission_request */ + + uint8_t DLC; /*!< Specifies the length of the frame that will be + transmitted. This parameter can be a value between + 0 to 8 */ + + uint8_t Data[8]; /*!< Contains the data to be transmitted. It ranges from 0 + to 0xFF. */ +} CanTxMessage; + +/** + * @brief CAN Rx message structure definition + */ + +typedef struct +{ + uint32_t StdId; /*!< Specifies the standard identifier. + This parameter can be a value between 0 to 0x7FF. */ + + uint32_t ExtId; /*!< Specifies the extended identifier. + This parameter can be a value between 0 to 0x1FFFFFFF. */ + + uint8_t IDE; /*!< Specifies the type of identifier for the message that + will be received. This parameter can be a value of + @ref CAN_identifier_type */ + + uint8_t RTR; /*!< Specifies the type of frame for the received message. + This parameter can be a value of + @ref CAN_remote_transmission_request */ + + uint8_t DLC; /*!< Specifies the length of the frame that will be received. + This parameter can be a value between 0 to 8 */ + + uint8_t Data[8]; /*!< Contains the data to be received. It ranges from 0 to + 0xFF. */ + + uint8_t FMI; /*!< Specifies the index of the filter the message stored in + the mailbox passes through. This parameter can be a + value between 0 to 0xFF */ +} CanRxMessage; + +/** + * @} + */ + +/** @addtogroup CAN_Exported_Constants + * @{ + */ + +/** @addtogroup CAN_sleep_constants + * @{ + */ + +#define CAN_InitSTS_Failed ((uint8_t)0x00) /*!< CAN initialization failed */ +#define CAN_InitSTS_Success ((uint8_t)0x01) /*!< CAN initialization OK */ + +/** + * @} + */ + +/** @addtogroup OperatingMode + * @{ + */ + +#define CAN_Normal_Mode ((uint8_t)0x00) /*!< normal mode */ +#define CAN_LoopBack_Mode ((uint8_t)0x01) /*!< loopback mode */ +#define CAN_Silent_Mode ((uint8_t)0x02) /*!< silent mode */ +#define CAN_Silent_LoopBack_Mode ((uint8_t)0x03) /*!< loopback combined with silent mode */ + +#define IS_CAN_MODE(MODE) \ + (((MODE) == CAN_Normal_Mode) || ((MODE) == CAN_LoopBack_Mode) || ((MODE) == CAN_Silent_Mode) \ + || ((MODE) == CAN_Silent_LoopBack_Mode)) +/** + * @} + */ + +/** + * @addtogroup CAN_operating_mode + * @{ + */ +#define CAN_Operating_InitMode ((uint8_t)0x00) /*!< Initialization mode */ +#define CAN_Operating_NormalMode ((uint8_t)0x01) /*!< Normal mode */ +#define CAN_Operating_SleepMode ((uint8_t)0x02) /*!< sleep mode */ + +#define IS_CAN_OPERATING_MODE(MODE) \ + (((MODE) == CAN_Operating_InitMode) || ((MODE) == CAN_Operating_NormalMode) || ((MODE) == CAN_Operating_SleepMode)) +/** + * @} + */ + +/** + * @addtogroup CAN_Mode_Status + * @{ + */ + +#define CAN_ModeSTS_Failed ((uint8_t)0x00) /*!< CAN entering the specific mode failed */ +#define CAN_ModeSTS_Success ((uint8_t)!CAN_ModeSTS_Failed) /*!< CAN entering the specific mode Succeed */ + +/** + * @} + */ + +/** @addtogroup CAN_synchronisation_jump_width + * @{ + */ + +#define CAN_RSJW_1tq ((uint8_t)0x00) /*!< 1 time quantum */ +#define CAN_RSJW_2tq ((uint8_t)0x01) /*!< 2 time quantum */ +#define CAN_RSJW_3tq ((uint8_t)0x02) /*!< 3 time quantum */ +#define CAN_RSJW_4tq ((uint8_t)0x03) /*!< 4 time quantum */ + +#define IS_CAN_RSJW(SJW) \ + (((SJW) == CAN_RSJW_1tq) || ((SJW) == CAN_RSJW_2tq) || ((SJW) == CAN_RSJW_3tq) || ((SJW) == CAN_RSJW_4tq)) +/** + * @} + */ + +/** @addtogroup CAN_time_quantum_in_bit_segment_1 + * @{ + */ + +#define CAN_TBS1_1tq ((uint8_t)0x00) /*!< 1 time quantum */ +#define CAN_TBS1_2tq ((uint8_t)0x01) /*!< 2 time quantum */ +#define CAN_TBS1_3tq ((uint8_t)0x02) /*!< 3 time quantum */ +#define CAN_TBS1_4tq ((uint8_t)0x03) /*!< 4 time quantum */ +#define CAN_TBS1_5tq ((uint8_t)0x04) /*!< 5 time quantum */ +#define CAN_TBS1_6tq ((uint8_t)0x05) /*!< 6 time quantum */ +#define CAN_TBS1_7tq ((uint8_t)0x06) /*!< 7 time quantum */ +#define CAN_TBS1_8tq ((uint8_t)0x07) /*!< 8 time quantum */ +#define CAN_TBS1_9tq ((uint8_t)0x08) /*!< 9 time quantum */ +#define CAN_TBS1_10tq ((uint8_t)0x09) /*!< 10 time quantum */ +#define CAN_TBS1_11tq ((uint8_t)0x0A) /*!< 11 time quantum */ +#define CAN_TBS1_12tq ((uint8_t)0x0B) /*!< 12 time quantum */ +#define CAN_TBS1_13tq ((uint8_t)0x0C) /*!< 13 time quantum */ +#define CAN_TBS1_14tq ((uint8_t)0x0D) /*!< 14 time quantum */ +#define CAN_TBS1_15tq ((uint8_t)0x0E) /*!< 15 time quantum */ +#define CAN_TBS1_16tq ((uint8_t)0x0F) /*!< 16 time quantum */ + +#define IS_CAN_TBS1(BS1) ((BS1) <= CAN_TBS1_16tq) +/** + * @} + */ + +/** @addtogroup CAN_time_quantum_in_bit_segment_2 + * @{ + */ + +#define CAN_TBS2_1tq ((uint8_t)0x00) /*!< 1 time quantum */ +#define CAN_TBS2_2tq ((uint8_t)0x01) /*!< 2 time quantum */ +#define CAN_TBS2_3tq ((uint8_t)0x02) /*!< 3 time quantum */ +#define CAN_TBS2_4tq ((uint8_t)0x03) /*!< 4 time quantum */ +#define CAN_TBS2_5tq ((uint8_t)0x04) /*!< 5 time quantum */ +#define CAN_TBS2_6tq ((uint8_t)0x05) /*!< 6 time quantum */ +#define CAN_TBS2_7tq ((uint8_t)0x06) /*!< 7 time quantum */ +#define CAN_TBS2_8tq ((uint8_t)0x07) /*!< 8 time quantum */ + +#define IS_CAN_TBS2(BS2) ((BS2) <= CAN_TBS2_8tq) + +/** + * @} + */ + +/** @addtogroup CAN_clock_prescaler + * @{ + */ + +#define IS_CAN_BAUDRATEPRESCALER(PRESCALER) (((PRESCALER) >= 1) && ((PRESCALER) <= 1024)) + +/** + * @} + */ + +/** @addtogroup CAN_filter_number + * @{ + */ +#define IS_CAN_FILTER_NUM(NUMBER) ((NUMBER) <= 13) +/** + * @} + */ + +/** @addtogroup CAN_filter_mode + * @{ + */ + +#define CAN_Filter_IdMaskMode ((uint8_t)0x00) /*!< identifier/mask mode */ +#define CAN_Filter_IdListMode ((uint8_t)0x01) /*!< identifier list mode */ + +#define IS_CAN_FILTER_MODE(MODE) (((MODE) == CAN_Filter_IdMaskMode) || ((MODE) == CAN_Filter_IdListMode)) +/** + * @} + */ + +/** @addtogroup CAN_filter_scale + * @{ + */ + +#define CAN_Filter_16bitScale ((uint8_t)0x00) /*!< Two 16-bit filters */ +#define CAN_Filter_32bitScale ((uint8_t)0x01) /*!< One 32-bit filter */ + +#define IS_CAN_FILTER_SCALE(SCALE) (((SCALE) == CAN_Filter_16bitScale) || ((SCALE) == CAN_Filter_32bitScale)) + +/** + * @} + */ + +/** @addtogroup CAN_filter_FIFO + * @{ + */ + +#define CAN_Filter_FIFO0 ((uint8_t)0x00) /*!< Filter DATFIFO 0 assignment for filter x */ +#define CAN_Filter_FIFO1 ((uint8_t)0x01) /*!< Filter DATFIFO 1 assignment for filter x */ +#define IS_CAN_FILTER_FIFO(DATFIFO) (((DATFIFO) == CAN_FilterFIFO0) || ((DATFIFO) == CAN_FilterFIFO1)) +/** + * @} + */ + +/** @addtogroup CAN_Tx + * @{ + */ + +#define IS_CAN_TRANSMITMAILBOX(TRANSMITMAILBOX) ((TRANSMITMAILBOX) <= ((uint8_t)0x02)) +#define IS_CAN_STDID(STDID) ((STDID) <= ((uint32_t)0x7FF)) +#define IS_CAN_EXTID(EXTID) ((EXTID) <= ((uint32_t)0x1FFFFFFF)) +#define IS_CAN_DLC(DLC) ((DLC) <= ((uint8_t)0x08)) + +/** + * @} + */ + +/** @addtogroup CAN_identifier_type + * @{ + */ + +#define CAN_Standard_Id ((uint32_t)0x00000000) /*!< Standard Id */ +#define CAN_Extended_Id ((uint32_t)0x00000004) /*!< Extended Id */ +#define IS_CAN_ID(IDTYPE) (((IDTYPE) == CAN_Standard_Id) || ((IDTYPE) == CAN_Extended_Id)) +/** + * @} + */ + +/** @addtogroup CAN_remote_transmission_request + * @{ + */ + +#define CAN_RTRQ_Data ((uint32_t)0x00000000) /*!< Data frame */ +#define CAN_RTRQ_Remote ((uint32_t)0x00000002) /*!< Remote frame */ +#define IS_CAN_RTRQ(RTR) (((RTR) == CAN_RTRQ_Data) || ((RTR) == CAN_RTRQ_Remote)) + +/** + * @} + */ + +/** @addtogroup CAN_transmit_constants + * @{ + */ + +#define CAN_TxSTS_Failed ((uint8_t)0x00) /*!< CAN transmission failed */ +#define CAN_TxSTS_Ok ((uint8_t)0x01) /*!< CAN transmission succeeded */ +#define CAN_TxSTS_Pending ((uint8_t)0x02) /*!< CAN transmission pending */ +#define CAN_TxSTS_NoMailBox ((uint8_t)0x04) /*!< CAN cell did not provide an empty mailbox */ + +/** + * @} + */ + +/** @addtogroup CAN_receive_FIFO_number_constants + * @{ + */ + +#define CAN_FIFO0 ((uint8_t)0x00) /*!< CAN DATFIFO 0 used to receive */ +#define CAN_FIFO1 ((uint8_t)0x01) /*!< CAN DATFIFO 1 used to receive */ + +#define IS_CAN_FIFO(DATFIFO) (((DATFIFO) == CAN_FIFO0) || ((DATFIFO) == CAN_FIFO1)) + +/** + * @} + */ + +/** @addtogroup CAN_sleep_constants + * @{ + */ + +#define CAN_SLEEP_Failed ((uint8_t)0x00) /*!< CAN did not enter the sleep mode */ +#define CAN_SLEEP_Ok ((uint8_t)0x01) /*!< CAN entered the sleep mode */ + +/** + * @} + */ + +/** @addtogroup CAN_wake_up_constants + * @{ + */ + +#define CAN_WKU_Failed ((uint8_t)0x00) /*!< CAN did not leave the sleep mode */ +#define CAN_WKU_Ok ((uint8_t)0x01) /*!< CAN leaved the sleep mode */ + +/** + * @} + */ + +/** + * @addtogroup CAN_Error_Code_constants + * @{ + */ + +#define CAN_ERRCode_NoErr ((uint8_t)0x00) /*!< No Error */ +#define CAN_ERRCode_StuffErr ((uint8_t)0x10) /*!< Stuff Error */ +#define CAN_ERRCode_FormErr ((uint8_t)0x20) /*!< Form Error */ +#define CAN_ERRCode_ACKErr ((uint8_t)0x30) /*!< Acknowledgment Error */ +#define CAN_ERRCode_BitRecessiveErr ((uint8_t)0x40) /*!< Bit Recessive Error */ +#define CAN_ERRCode_BitDominantErr ((uint8_t)0x50) /*!< Bit Dominant Error */ +#define CAN_ERRCode_CRCErr ((uint8_t)0x60) /*!< CRC Error */ +#define CAN_ERRCode_SWSetErr ((uint8_t)0x70) /*!< Software Set Error */ + +/** + * @} + */ + +/** @addtogroup CAN_flags + * @{ + */ +/* If the flag is 0x3XXXXXXX, it means that it can be used with CAN_GetFlagSTS() + and CAN_ClearFlag() functions. */ +/* If the flag is 0x1XXXXXXX, it means that it can only be used with CAN_GetFlagSTS() function. */ + +/* Transmit Flags */ +#define CAN_FLAG_RQCPM0 ((uint32_t)0x38000001) /*!< Request MailBox0 Flag */ +#define CAN_FLAG_RQCPM1 ((uint32_t)0x38000100) /*!< Request MailBox1 Flag */ +#define CAN_FLAG_RQCPM2 ((uint32_t)0x38010000) /*!< Request MailBox2 Flag */ + +/* Receive Flags */ +#define CAN_FLAG_FFMP0 ((uint32_t)0x12000003) /*!< DATFIFO 0 Message Pending Flag */ +#define CAN_FLAG_FFULL0 ((uint32_t)0x32000008) /*!< DATFIFO 0 Full Flag */ +#define CAN_FLAG_FFOVR0 ((uint32_t)0x32000010) /*!< DATFIFO 0 Overrun Flag */ +#define CAN_FLAG_FFMP1 ((uint32_t)0x14000003) /*!< DATFIFO 1 Message Pending Flag */ +#define CAN_FLAG_FFULL1 ((uint32_t)0x34000008) /*!< DATFIFO 1 Full Flag */ +#define CAN_FLAG_FFOVR1 ((uint32_t)0x34000010) /*!< DATFIFO 1 Overrun Flag */ + +/* Operating Mode Flags */ +#define CAN_FLAG_WKU ((uint32_t)0x31000008) /*!< Wake up Flag */ +#define CAN_FLAG_SLAK ((uint32_t)0x31000012) /*!< Sleep acknowledge Flag */ +/* Note: When SLAK intterupt is disabled (SLKIE=0), no polling on SLAKI is possible. + In this case the SLAK bit can be polled.*/ + +/* Error Flags */ +#define CAN_FLAG_EWGFL ((uint32_t)0x10F00001) /*!< Error Warning Flag */ +#define CAN_FLAG_EPVFL ((uint32_t)0x10F00002) /*!< Error Passive Flag */ +#define CAN_FLAG_BOFFL ((uint32_t)0x10F00004) /*!< Bus-Off Flag */ +#define CAN_FLAG_LEC ((uint32_t)0x30F00070) /*!< Last error code Flag */ + +#define IS_CAN_GET_FLAG(FLAG) \ + (((FLAG) == CAN_FLAG_LEC) || ((FLAG) == CAN_FLAG_BOFFL) || ((FLAG) == CAN_FLAG_EPVFL) \ + || ((FLAG) == CAN_FLAG_EWGFL) || ((FLAG) == CAN_FLAG_WKU) || ((FLAG) == CAN_FLAG_FFOVR0) \ + || ((FLAG) == CAN_FLAG_FFULL0) || ((FLAG) == CAN_FLAG_FFMP0) || ((FLAG) == CAN_FLAG_FFOVR1) \ + || ((FLAG) == CAN_FLAG_FFULL1) || ((FLAG) == CAN_FLAG_FFMP1) || ((FLAG) == CAN_FLAG_RQCPM2) \ + || ((FLAG) == CAN_FLAG_RQCPM1) || ((FLAG) == CAN_FLAG_RQCPM0) || ((FLAG) == CAN_FLAG_SLAK)) + +#define IS_CAN_CLEAR_FLAG(FLAG) \ + (((FLAG) == CAN_FLAG_LEC) || ((FLAG) == CAN_FLAG_RQCPM2) || ((FLAG) == CAN_FLAG_RQCPM1) \ + || ((FLAG) == CAN_FLAG_RQCPM0) || ((FLAG) == CAN_FLAG_FFULL0) || ((FLAG) == CAN_FLAG_FFOVR0) \ + || ((FLAG) == CAN_FLAG_FFULL1) || ((FLAG) == CAN_FLAG_FFOVR1) || ((FLAG) == CAN_FLAG_WKU) \ + || ((FLAG) == CAN_FLAG_SLAK)) +/** + * @} + */ + +/** @addtogroup CAN_interrupts + * @{ + */ + +#define CAN_INT_TME ((uint32_t)0x00000001) /*!< Transmit mailbox empty Interrupt*/ + +/* Receive Interrupts */ +#define CAN_INT_FMP0 ((uint32_t)0x00000002) /*!< DATFIFO 0 message pending Interrupt*/ +#define CAN_INT_FF0 ((uint32_t)0x00000004) /*!< DATFIFO 0 full Interrupt*/ +#define CAN_INT_FOV0 ((uint32_t)0x00000008) /*!< DATFIFO 0 overrun Interrupt*/ +#define CAN_INT_FMP1 ((uint32_t)0x00000010) /*!< DATFIFO 1 message pending Interrupt*/ +#define CAN_INT_FF1 ((uint32_t)0x00000020) /*!< DATFIFO 1 full Interrupt*/ +#define CAN_INT_FOV1 ((uint32_t)0x00000040) /*!< DATFIFO 1 overrun Interrupt*/ + +/* Operating Mode Interrupts */ +#define CAN_INT_WKU ((uint32_t)0x00010000) /*!< Wake-up Interrupt*/ +#define CAN_INT_SLK ((uint32_t)0x00020000) /*!< Sleep acknowledge Interrupt*/ + +/* Error Interrupts */ +#define CAN_INT_EWG ((uint32_t)0x00000100) /*!< Error warning Interrupt*/ +#define CAN_INT_EPV ((uint32_t)0x00000200) /*!< Error passive Interrupt*/ +#define CAN_INT_BOF ((uint32_t)0x00000400) /*!< Bus-off Interrupt*/ +#define CAN_INT_LEC ((uint32_t)0x00000800) /*!< Last error code Interrupt*/ +#define CAN_INT_ERR ((uint32_t)0x00008000) /*!< Error Interrupt*/ + +/* Flags named as Interrupts : kept only for FW compatibility */ +#define CAN_INT_RQCPM0 CAN_INT_TME +#define CAN_INT_RQCPM1 CAN_INT_TME +#define CAN_INT_RQCPM2 CAN_INT_TME + +#define IS_CAN_INT(IT) \ + (((IT) == CAN_INT_TME) || ((IT) == CAN_INT_FMP0) || ((IT) == CAN_INT_FF0) || ((IT) == CAN_INT_FOV0) \ + || ((IT) == CAN_INT_FMP1) || ((IT) == CAN_INT_FF1) || ((IT) == CAN_INT_FOV1) || ((IT) == CAN_INT_EWG) \ + || ((IT) == CAN_INT_EPV) || ((IT) == CAN_INT_BOF) || ((IT) == CAN_INT_LEC) || ((IT) == CAN_INT_ERR) \ + || ((IT) == CAN_INT_WKU) || ((IT) == CAN_INT_SLK)) + +#define IS_CAN_CLEAR_INT(IT) \ + (((IT) == CAN_INT_TME) || ((IT) == CAN_INT_FF0) || ((IT) == CAN_INT_FOV0) || ((IT) == CAN_INT_FF1) \ + || ((IT) == CAN_INT_FOV1) || ((IT) == CAN_INT_EWG) || ((IT) == CAN_INT_EPV) || ((IT) == CAN_INT_BOF) \ + || ((IT) == CAN_INT_LEC) || ((IT) == CAN_INT_ERR) || ((IT) == CAN_INT_WKU) || ((IT) == CAN_INT_SLK)) + +/** + * @} + */ + +/** @addtogroup CAN_Legacy + * @{ + */ +#define CANINITSTSFAILED CAN_InitSTS_Failed +#define CANINITSTSOK CAN_InitSTS_Success +#define CAN_FilterFIFO0 CAN_Filter_FIFO0 +#define CAN_FilterFIFO1 CAN_Filter_FIFO1 +#define CAN_ID_STD CAN_Standard_Id +#define CAN_ID_EXT CAN_Extended_Id +#define CAN_RTRQ_DATA CAN_RTRQ_Data +#define CAN_RTRQ_REMOTE CAN_RTRQ_Remote +#define CANTXSTSFAILE CAN_TxSTS_Failed +#define CANTXSTSOK CAN_TxSTS_Ok +#define CANTXSTSPENDING CAN_TxSTS_Pending +#define CAN_STS_NO_MB CAN_TxSTS_NoMailBox +#define CANSLEEPFAILED CAN_SLEEP_Failed +#define CANSLEEPOK CAN_SLEEP_Ok +#define CANWKUFAILED CAN_WKU_Failed +#define CANWKUOK CAN_WKU_Ok + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup CAN_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CAN_Exported_Functions + * @{ + */ +/* Function used to set the CAN configuration to the default reset state *****/ +void CAN_DeInit(CAN_Module* CANx); + +/* Initialization and Configuration functions *********************************/ +uint8_t CAN_Init(CAN_Module* CANx, CAN_InitType* CAN_InitParam); +void CAN1_InitFilter(CAN_FilterInitType* CAN_InitFilterStruct); +void CAN2_InitFilter(CAN_FilterInitType* CAN_InitFilterStruct); +void CAN_InitStruct(CAN_InitType* CAN_InitParam); +void CAN_DebugFreeze(CAN_Module* CANx, FunctionalState Cmd); +void CAN_EnTTComMode(CAN_Module* CANx, FunctionalState Cmd); + +/* Transmit functions *********************************************************/ +uint8_t CAN_TransmitMessage(CAN_Module* CANx, CanTxMessage* TxMessage); +uint8_t CAN_TransmitSTS(CAN_Module* CANx, uint8_t TransmitMailbox); +void CAN_CancelTransmitMessage(CAN_Module* CANx, uint8_t Mailbox); + +/* Receive functions **********************************************************/ +void CAN_ReceiveMessage(CAN_Module* CANx, uint8_t FIFONum, CanRxMessage* RxMessage); +void CAN_ReleaseFIFO(CAN_Module* CANx, uint8_t FIFONum); +uint8_t CAN_PendingMessage(CAN_Module* CANx, uint8_t FIFONum); + +/* Operation modes functions **************************************************/ +uint8_t CAN_OperatingModeReq(CAN_Module* CANx, uint8_t CAN_OperatingMode); +uint8_t CAN_EnterSleep(CAN_Module* CANx); +uint8_t CAN_WakeUp(CAN_Module* CANx); + +/* Error management functions *************************************************/ +uint8_t CAN_GetLastErrCode(CAN_Module* CANx); +uint8_t CAN_GetReceiveErrCounter(CAN_Module* CANx); +uint8_t CAN_GetLSBTransmitErrCounter(CAN_Module* CANx); + +/* Interrupts and flags management functions **********************************/ +void CAN_INTConfig(CAN_Module* CANx, uint32_t CAN_INT, FunctionalState Cmd); +FlagStatus CAN_GetFlagSTS(CAN_Module* CANx, uint32_t CAN_FLAG); +void CAN_ClearFlag(CAN_Module* CANx, uint32_t CAN_FLAG); +INTStatus CAN_GetIntStatus(CAN_Module* CANx, uint32_t CAN_INT); +void CAN_ClearINTPendingBit(CAN_Module* CANx, uint32_t CAN_INT); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G4FR_CAN_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_crc.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_crc.h new file mode 100644 index 0000000000..9d9ce91d65 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_crc.h @@ -0,0 +1,105 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_crc.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_CRC_H__ +#define __N32G4FR_CRC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup CRC + * @{ + */ + +/** @addtogroup CRC_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CRC_Exported_Constants + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CRC_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CRC_Exported_Functions + * @{ + */ + +void CRC32_ResetCrc(void); +uint32_t CRC32_CalcCrc(uint32_t Data); +uint32_t CRC32_CalcBufCrc(uint32_t pBuffer[], uint32_t BufferLength); +uint32_t CRC32_GetCrc(void); +void CRC32_SetIDat(uint8_t IDValue); +uint8_t CRC32_GetIDat(void); + +uint16_t CRC16_CalcBufCrc(uint8_t pBuffer[], uint32_t BufferLength); +uint16_t CRC16_CalcCRC(uint8_t Data); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G4FR_CRC_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_dac.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_dac.h new file mode 100644 index 0000000000..33941cf144 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_dac.h @@ -0,0 +1,307 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_dac.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_DAC_H__ +#define __N32G4FR_DAC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DAC + * @{ + */ + +/** @addtogroup DAC_Exported_Types + * @{ + */ + +/** + * @brief DAC Init structure definition + */ + +typedef struct +{ + uint32_t Trigger; /*!< Specifies the external trigger for the selected DAC channel. + This parameter can be a value of @ref DAC_trigger_selection */ + + uint32_t WaveGen; /*!< Specifies whether DAC channel noise waves or triangle waves + are generated, or whether no wave is generated. + This parameter can be a value of @ref DAC_wave_generation */ + + uint32_t + LfsrUnMaskTriAmp; /*!< Specifies the LFSR mask for noise wave generation or + the maximum amplitude triangle generation for the DAC channel. + This parameter can be a value of @ref DAC_lfsrunmask_triangleamplitude */ + + uint32_t BufferOutput; /*!< Specifies whether the DAC channel output buffer is enabled or disabled. + This parameter can be a value of @ref DAC_output_buffer */ +} DAC_InitType; + +/** + * @} + */ + +/** @addtogroup DAC_Exported_Constants + * @{ + */ + +/** @addtogroup DAC_trigger_selection + * @{ + */ + +#define DAC_TRG_NONE \ + ((uint32_t)0x00000000) /*!< Conversion is automatic once the DAC1_DHRxxxx register \ + has been loaded, and not by external trigger */ +#define DAC_TRG_T6_TRGO \ + ((uint32_t)0x00000004) /*!< TIM6 TRGO selected as external conversion trigger for DAC channel \ + */ +#define DAC_TRG_T8_TRGO \ + ((uint32_t)0x0000000C) /*!< TIM8 TRGO selected as external conversion trigger for DAC channel \ + only in High-density devices*/ +#define DAC_TRG_T3_TRGO \ + ((uint32_t)0x0000000C) /*!< TIM8 TRGO selected as external conversion trigger for DAC channel \ + only in Connectivity line, Medium-density and Low-density Value Line devices */ +#define DAC_TRG_T7_TRGO \ + ((uint32_t)0x00000014) /*!< TIM7 TRGO selected as external conversion trigger for DAC channel \ + */ +#define DAC_TRG_T5_TRGO \ + ((uint32_t)0x0000001C) /*!< TIM5 TRGO selected as external conversion trigger for DAC channel \ + */ +#define DAC_TRG_T15_TRGO \ + ((uint32_t)0x0000001C) /*!< TIM15 TRGO selected as external conversion trigger for DAC channel \ + only in Medium-density and Low-density Value Line devices*/ +#define DAC_TRG_T2_TRGO \ + ((uint32_t)0x00000024) /*!< TIM2 TRGO selected as external conversion trigger for DAC channel \ + */ +#define DAC_TRG_T4_TRGO \ + ((uint32_t)0x0000002C) /*!< TIM4 TRGO selected as external conversion trigger for DAC channel \ + */ +#define DAC_TRG_EXT_IT9 \ + ((uint32_t)0x00000034) /*!< EXTI Line9 event selected as external conversion trigger for DAC channel */ +#define DAC_TRG_SOFTWARE ((uint32_t)0x0000003C) /*!< Conversion started by software trigger for DAC channel */ + +#define IS_DAC_TRIGGER(TRIGGER) \ + (((TRIGGER) == DAC_TRG_NONE) || ((TRIGGER) == DAC_TRG_T6_TRGO) || ((TRIGGER) == DAC_TRG_T8_TRGO) \ + || ((TRIGGER) == DAC_TRG_T7_TRGO) || ((TRIGGER) == DAC_TRG_T5_TRGO) || ((TRIGGER) == DAC_TRG_T2_TRGO) \ + || ((TRIGGER) == DAC_TRG_T4_TRGO) || ((TRIGGER) == DAC_TRG_EXT_IT9) || ((TRIGGER) == DAC_TRG_SOFTWARE)) + +/** + * @} + */ + +/** @addtogroup DAC_wave_generation + * @{ + */ + +#define DAC_WAVEGEN_NONE ((uint32_t)0x00000000) +#define DAC_WAVEGEN_NOISE ((uint32_t)0x00000040) +#define DAC_WAVEGEN_TRIANGLE ((uint32_t)0x00000080) +#define IS_DAC_GENERATE_WAVE(WAVE) \ + (((WAVE) == DAC_WAVEGEN_NONE) || ((WAVE) == DAC_WAVEGEN_NOISE) || ((WAVE) == DAC_WAVEGEN_TRIANGLE)) +/** + * @} + */ + +/** @addtogroup DAC_lfsrunmask_triangleamplitude + * @{ + */ + +#define DAC_UNMASK_LFSRBIT0 ((uint32_t)0x00000000) /*!< Unmask DAC channel LFSR bit0 for noise wave generation */ +#define DAC_UNMASK_LFSRBITS1_0 \ + ((uint32_t)0x00000100) /*!< Unmask DAC channel LFSR bit[1:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS2_0 \ + ((uint32_t)0x00000200) /*!< Unmask DAC channel LFSR bit[2:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS3_0 \ + ((uint32_t)0x00000300) /*!< Unmask DAC channel LFSR bit[3:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS4_0 \ + ((uint32_t)0x00000400) /*!< Unmask DAC channel LFSR bit[4:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS5_0 \ + ((uint32_t)0x00000500) /*!< Unmask DAC channel LFSR bit[5:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS6_0 \ + ((uint32_t)0x00000600) /*!< Unmask DAC channel LFSR bit[6:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS7_0 \ + ((uint32_t)0x00000700) /*!< Unmask DAC channel LFSR bit[7:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS8_0 \ + ((uint32_t)0x00000800) /*!< Unmask DAC channel LFSR bit[8:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS9_0 \ + ((uint32_t)0x00000900) /*!< Unmask DAC channel LFSR bit[9:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS10_0 \ + ((uint32_t)0x00000A00) /*!< Unmask DAC channel LFSR bit[10:0] for noise wave generation */ +#define DAC_UNMASK_LFSRBITS11_0 \ + ((uint32_t)0x00000B00) /*!< Unmask DAC channel LFSR bit[11:0] for noise wave generation */ +#define DAC_TRIAMP_1 ((uint32_t)0x00000000) /*!< Select max triangle amplitude of 1 */ +#define DAC_TRIAMP_3 ((uint32_t)0x00000100) /*!< Select max triangle amplitude of 3 */ +#define DAC_TRIAMP_7 ((uint32_t)0x00000200) /*!< Select max triangle amplitude of 7 */ +#define DAC_TRIAMP_15 ((uint32_t)0x00000300) /*!< Select max triangle amplitude of 15 */ +#define DAC_TRIAMP_31 ((uint32_t)0x00000400) /*!< Select max triangle amplitude of 31 */ +#define DAC_TRIAMP_63 ((uint32_t)0x00000500) /*!< Select max triangle amplitude of 63 */ +#define DAC_TRIAMP_127 ((uint32_t)0x00000600) /*!< Select max triangle amplitude of 127 */ +#define DAC_TRIAMP_255 ((uint32_t)0x00000700) /*!< Select max triangle amplitude of 255 */ +#define DAC_TRIAMP_511 ((uint32_t)0x00000800) /*!< Select max triangle amplitude of 511 */ +#define DAC_TRIAMP_1023 ((uint32_t)0x00000900) /*!< Select max triangle amplitude of 1023 */ +#define DAC_TRIAMP_2047 ((uint32_t)0x00000A00) /*!< Select max triangle amplitude of 2047 */ +#define DAC_TRIAMP_4095 ((uint32_t)0x00000B00) /*!< Select max triangle amplitude of 4095 */ + +#define IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(VALUE) \ + (((VALUE) == DAC_UNMASK_LFSRBIT0) || ((VALUE) == DAC_UNMASK_LFSRBITS1_0) || ((VALUE) == DAC_UNMASK_LFSRBITS2_0) \ + || ((VALUE) == DAC_UNMASK_LFSRBITS3_0) || ((VALUE) == DAC_UNMASK_LFSRBITS4_0) \ + || ((VALUE) == DAC_UNMASK_LFSRBITS5_0) || ((VALUE) == DAC_UNMASK_LFSRBITS6_0) \ + || ((VALUE) == DAC_UNMASK_LFSRBITS7_0) || ((VALUE) == DAC_UNMASK_LFSRBITS8_0) \ + || ((VALUE) == DAC_UNMASK_LFSRBITS9_0) || ((VALUE) == DAC_UNMASK_LFSRBITS10_0) \ + || ((VALUE) == DAC_UNMASK_LFSRBITS11_0) || ((VALUE) == DAC_TRIAMP_1) || ((VALUE) == DAC_TRIAMP_3) \ + || ((VALUE) == DAC_TRIAMP_7) || ((VALUE) == DAC_TRIAMP_15) || ((VALUE) == DAC_TRIAMP_31) \ + || ((VALUE) == DAC_TRIAMP_63) || ((VALUE) == DAC_TRIAMP_127) || ((VALUE) == DAC_TRIAMP_255) \ + || ((VALUE) == DAC_TRIAMP_511) || ((VALUE) == DAC_TRIAMP_1023) || ((VALUE) == DAC_TRIAMP_2047) \ + || ((VALUE) == DAC_TRIAMP_4095)) +/** + * @} + */ + +/** @addtogroup DAC_output_buffer + * @{ + */ + +#define DAC_BUFFOUTPUT_ENABLE ((uint32_t)0x00000002) +#define DAC_BUFFOUTPUT_DISABLE ((uint32_t)0x00000000) +#define IS_DAC_OUTPUT_BUFFER_STATE(STATE) (((STATE) == DAC_BUFFOUTPUT_ENABLE) || ((STATE) == DAC_BUFFOUTPUT_DISABLE)) +/** + * @} + */ + +/** @addtogroup DAC_Channel_selection + * @{ + */ + +#define DAC_CHANNEL_1 ((uint32_t)0x00000000) +#define DAC_CHANNEL_2 ((uint32_t)0x00000010) +#define IS_DAC_CHANNEL(CHANNEL) (((CHANNEL) == DAC_CHANNEL_1) || ((CHANNEL) == DAC_CHANNEL_2)) +/** + * @} + */ + +/** @addtogroup DAC_data_alignment + * @{ + */ + +#define DAC_ALIGN_R_12BIT ((uint32_t)0x00000000) +#define DAC_ALIGN_L_12BIT ((uint32_t)0x00000004) +#define DAC_ALIGN_R_8BIT ((uint32_t)0x00000008) +#define IS_DAC_ALIGN(ALIGN) \ + (((ALIGN) == DAC_ALIGN_R_12BIT) || ((ALIGN) == DAC_ALIGN_L_12BIT) || ((ALIGN) == DAC_ALIGN_R_8BIT)) +/** + * @} + */ + +/** @addtogroup DAC_wave_generation + * @{ + */ + +#define DAC_WAVE_NOISE ((uint32_t)0x00000040) +#define DAC_WAVE_TRIANGLE ((uint32_t)0x00000080) +#define IS_DAC_WAVE(WAVE) (((WAVE) == DAC_WAVE_NOISE) || ((WAVE) == DAC_WAVE_TRIANGLE)) +/** + * @} + */ + +/** @addtogroup DAC_data + * @{ + */ + +#define IS_DAC_DATA(DATA) ((DATA) <= 0xFFF0) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup DAC_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DAC_Exported_Functions + * @{ + */ + +void DAC_DeInit(void); +void DAC_Init(uint32_t DAC_Channel, DAC_InitType* DAC_InitStruct); +void DAC_ClearStruct(DAC_InitType* DAC_InitStruct); +void DAC_Enable(uint32_t DAC_Channel, FunctionalState Cmd); + +void DAC_DmaEnable(uint32_t DAC_Channel, FunctionalState Cmd); +void DAC_SoftTrgEnable(uint32_t DAC_Channel, FunctionalState Cmd); +void DAC_DualSoftwareTrgEnable(FunctionalState Cmd); +void DAC_WaveGenerationEnable(uint32_t DAC_Channel, uint32_t DAC_Wave, FunctionalState Cmd); +void DAC_SetCh1Data(uint32_t DAC_Align, uint16_t Data); +void DAC_SetCh2Data(uint32_t DAC_Align, uint16_t Data); +void DAC_SetDualChData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1); +uint16_t DAC_GetOutputDataVal(uint32_t DAC_Channel); + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G4FR_DAC_H__ */ + /** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_dbg.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_dbg.h new file mode 100644 index 0000000000..4e3b2f41e4 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_dbg.h @@ -0,0 +1,124 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_dbg.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_DBG_H__ +#define __N32G4FR_DBG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DBG + * @{ + */ + +/** @addtogroup DBGMCU_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DBGMCU_Exported_Constants + * @{ + */ + +#define DBG_SLEEP ((uint32_t)0x00000001) +#define DBG_STOP ((uint32_t)0x00000002) +#define DBG_STDBY ((uint32_t)0x00000004) +#define DBG_IWDG_STOP ((uint32_t)0x00000100) +#define DBG_WWDG_STOP ((uint32_t)0x00000200) +#define DBG_TIM1_STOP ((uint32_t)0x00000400) +#define DBG_TIM2_STOP ((uint32_t)0x00000800) +#define DBG_TIM3_STOP ((uint32_t)0x00001000) +#define DBG_TIM4_STOP ((uint32_t)0x00002000) +#define DBG_CAN1_STOP ((uint32_t)0x00004000) +#define DBG_I2C1SMBUS_TIMEOUT ((uint32_t)0x00008000) +#define DBG_I2C2SMBUS_TIMEOUT ((uint32_t)0x00010000) +#define DBG_TIM8_STOP ((uint32_t)0x00020000) +#define DBG_TIM5_STOP ((uint32_t)0x00040000) +#define DBG_TIM6_STOP ((uint32_t)0x00080000) +#define DBG_TIM7_STOP ((uint32_t)0x00100000) +#define DBG_CAN2_STOP ((uint32_t)0x00200000) + +#define IS_DBGMCU_PERIPH(PERIPH) ((((PERIPH)&0xFFC000F8) == 0x00) && ((PERIPH) != 0x00)) +/** + * @} + */ + +/** @addtogroup DBGMCU_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DBGMCU_Exported_Functions + * @{ + */ + +void GetUCID(uint8_t *UCIDbuf); +void GetUID(uint8_t *UIDbuf); +void GetDBGMCU_ID(uint8_t *DBGMCU_IDbuf); +uint32_t DBG_GetRevNum(void); +uint32_t DBG_GetDevNum(void); +void DBG_ConfigPeriph(uint32_t DBG_Periph, FunctionalState Cmd); + +uint32_t DBG_GetFlashSize(void); +uint32_t DBG_GetSramSize(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G4FR_DBG_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_dma.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_dma.h new file mode 100644 index 0000000000..60422b501c --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_dma.h @@ -0,0 +1,569 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_dma.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_DMA_H__ +#define __N32G4FR_DMA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DMA + * @{ + */ + +/** @addtogroup DMA_Exported_Types + * @{ + */ + +/** + * @brief DMA Init structure definition + */ + +typedef struct +{ + uint32_t PeriphAddr; /*!< Specifies the peripheral base address for DMAy Channelx. */ + + uint32_t MemAddr; /*!< Specifies the memory base address for DMAy Channelx. */ + + uint32_t Direction; /*!< Specifies if the peripheral is the source or destination. + This parameter can be a value of @ref DMA_data_transfer_direction */ + + uint32_t BufSize; /*!< Specifies the buffer size, in data unit, of the specified Channel. + The data unit is equal to the configuration set in PeriphDataSize + or MemDataSize members depending in the transfer direction. */ + + uint32_t PeriphInc; /*!< Specifies whether the Peripheral address register is incremented or not. + This parameter can be a value of @ref DMA_peripheral_incremented_mode */ + + uint32_t DMA_MemoryInc; /*!< Specifies whether the memory address register is incremented or not. + This parameter can be a value of @ref DMA_memory_incremented_mode */ + + uint32_t PeriphDataSize; /*!< Specifies the Peripheral data width. + This parameter can be a value of @ref DMA_peripheral_data_size */ + + uint32_t MemDataSize; /*!< Specifies the Memory data width. + This parameter can be a value of @ref DMA_memory_data_size */ + + uint32_t CircularMode; /*!< Specifies the operation mode of the DMAy Channelx. + This parameter can be a value of @ref DMA_circular_normal_mode. + @note: The circular buffer mode cannot be used if the memory-to-memory + data transfer is configured on the selected Channel */ + + uint32_t Priority; /*!< Specifies the software priority for the DMAy Channelx. + This parameter can be a value of @ref DMA_priority_level */ + + uint32_t Mem2Mem; /*!< Specifies if the DMAy Channelx will be used in memory-to-memory transfer. + This parameter can be a value of @ref DMA_memory_to_memory */ +} DMA_InitType; + +/** + * @} + */ + +/** @addtogroup DMA_Exported_Constants + * @{ + */ + +#define IS_DMA_ALL_PERIPH(PERIPH) \ + (((PERIPH) == DMA1_CH1) || ((PERIPH) == DMA1_CH2) || ((PERIPH) == DMA1_CH3) || ((PERIPH) == DMA1_CH4) \ + || ((PERIPH) == DMA1_CH5) || ((PERIPH) == DMA1_CH6) || ((PERIPH) == DMA1_CH7) || ((PERIPH) == DMA1_CH8) \ + || ((PERIPH) == DMA2_CH1) || ((PERIPH) == DMA2_CH2) || ((PERIPH) == DMA2_CH3) || ((PERIPH) == DMA2_CH4) \ + || ((PERIPH) == DMA2_CH5) || ((PERIPH) == DMA2_CH6) || ((PERIPH) == DMA2_CH7) || ((PERIPH) == DMA2_CH8)) + +/** @addtogroup DMA_data_transfer_direction + * @{ + */ + +#define DMA_DIR_PERIPH_DST ((uint32_t)0x00000010) +#define DMA_DIR_PERIPH_SRC ((uint32_t)0x00000000) +#define IS_DMA_DIR(DIR) (((DIR) == DMA_DIR_PERIPH_DST) || ((DIR) == DMA_DIR_PERIPH_SRC)) +/** + * @} + */ + +/** @addtogroup DMA_peripheral_incremented_mode + * @{ + */ + +#define DMA_PERIPH_INC_ENABLE ((uint32_t)0x00000040) +#define DMA_PERIPH_INC_DISABLE ((uint32_t)0x00000000) +#define IS_DMA_PERIPH_INC_STATE(STATE) (((STATE) == DMA_PERIPH_INC_ENABLE) || ((STATE) == DMA_PERIPH_INC_DISABLE)) +/** + * @} + */ + +/** @addtogroup DMA_memory_incremented_mode + * @{ + */ + +#define DMA_MEM_INC_ENABLE ((uint32_t)0x00000080) +#define DMA_MEM_INC_DISABLE ((uint32_t)0x00000000) +#define IS_DMA_MEM_INC_STATE(STATE) (((STATE) == DMA_MEM_INC_ENABLE) || ((STATE) == DMA_MEM_INC_DISABLE)) +/** + * @} + */ + +/** @addtogroup DMA_peripheral_data_size + * @{ + */ + +#define DMA_PERIPH_DATA_SIZE_BYTE ((uint32_t)0x00000000) +#define DMA_PERIPH_DATA_SIZE_HALFWORD ((uint32_t)0x00000100) +#define DMA_PERIPH_DATA_SIZE_WORD ((uint32_t)0x00000200) +#define IS_DMA_PERIPH_DATA_SIZE(SIZE) \ + (((SIZE) == DMA_PERIPH_DATA_SIZE_BYTE) || ((SIZE) == DMA_PERIPH_DATA_SIZE_HALFWORD) \ + || ((SIZE) == DMA_PERIPH_DATA_SIZE_WORD)) +/** + * @} + */ + +/** @addtogroup DMA_memory_data_size + * @{ + */ + +#define DMA_MemoryDataSize_Byte ((uint32_t)0x00000000) +#define DMA_MemoryDataSize_HalfWord ((uint32_t)0x00000400) +#define DMA_MemoryDataSize_Word ((uint32_t)0x00000800) +#define IS_DMA_MEMORY_DATA_SIZE(SIZE) \ + (((SIZE) == DMA_MemoryDataSize_Byte) || ((SIZE) == DMA_MemoryDataSize_HalfWord) \ + || ((SIZE) == DMA_MemoryDataSize_Word)) +/** + * @} + */ + +/** @addtogroup DMA_circular_normal_mode + * @{ + */ + +#define DMA_MODE_CIRCULAR ((uint32_t)0x00000020) +#define DMA_MODE_NORMAL ((uint32_t)0x00000000) +#define IS_DMA_MODE(MODE) (((MODE) == DMA_MODE_CIRCULAR) || ((MODE) == DMA_MODE_NORMAL)) +/** + * @} + */ + +/** @addtogroup DMA_priority_level + * @{ + */ + +#define DMA_PRIORITY_VERY_HIGH ((uint32_t)0x00003000) +#define DMA_PRIORITY_HIGH ((uint32_t)0x00002000) +#define DMA_PRIORITY_MEDIUM ((uint32_t)0x00001000) +#define DMA_PRIORITY_LOW ((uint32_t)0x00000000) +#define IS_DMA_PRIORITY(PRIORITY) \ + (((PRIORITY) == DMA_PRIORITY_VERY_HIGH) || ((PRIORITY) == DMA_PRIORITY_HIGH) \ + || ((PRIORITY) == DMA_PRIORITY_MEDIUM) || ((PRIORITY) == DMA_PRIORITY_LOW)) +/** + * @} + */ + +/** @addtogroup DMA_memory_to_memory + * @{ + */ + +#define DMA_M2M_ENABLE ((uint32_t)0x00004000) +#define DMA_M2M_DISABLE ((uint32_t)0x00000000) +#define IS_DMA_M2M_STATE(STATE) (((STATE) == DMA_M2M_ENABLE) || ((STATE) == DMA_M2M_DISABLE)) + +/** + * @} + */ + +/** @addtogroup DMA_interrupts_definition + * @{ + */ + +#define DMA_INT_TXC ((uint32_t)0x00000002) +#define DMA_INT_HTX ((uint32_t)0x00000004) +#define DMA_INT_ERR ((uint32_t)0x00000008) +#define IS_DMA_CONFIG_INT(IT) ((((IT)&0xFFFFFFF1) == 0x00) && ((IT) != 0x00)) + +#define DMA1_INT_GLB1 ((uint32_t)0x00000001) +#define DMA1_INT_TXC1 ((uint32_t)0x00000002) +#define DMA1_INT_HTX1 ((uint32_t)0x00000004) +#define DMA1_INT_ERR1 ((uint32_t)0x00000008) +#define DMA1_INT_GLB2 ((uint32_t)0x00000010) +#define DMA1_INT_TXC2 ((uint32_t)0x00000020) +#define DMA1_INT_HTX2 ((uint32_t)0x00000040) +#define DMA1_INT_ERR2 ((uint32_t)0x00000080) +#define DMA1_INT_GLB3 ((uint32_t)0x00000100) +#define DMA1_INT_TXC3 ((uint32_t)0x00000200) +#define DMA1_INT_HTX3 ((uint32_t)0x00000400) +#define DMA1_INT_ERR3 ((uint32_t)0x00000800) +#define DMA1_INT_GLB4 ((uint32_t)0x00001000) +#define DMA1_INT_TXC4 ((uint32_t)0x00002000) +#define DMA1_INT_HTX4 ((uint32_t)0x00004000) +#define DMA1_INT_ERR4 ((uint32_t)0x00008000) +#define DMA1_INT_GLB5 ((uint32_t)0x00010000) +#define DMA1_INT_TXC5 ((uint32_t)0x00020000) +#define DMA1_INT_HTX5 ((uint32_t)0x00040000) +#define DMA1_INT_ERR5 ((uint32_t)0x00080000) +#define DMA1_INT_GLB6 ((uint32_t)0x00100000) +#define DMA1_INT_TXC6 ((uint32_t)0x00200000) +#define DMA1_INT_HTX6 ((uint32_t)0x00400000) +#define DMA1_INT_ERR6 ((uint32_t)0x00800000) +#define DMA1_INT_GLB7 ((uint32_t)0x01000000) +#define DMA1_INT_TXC7 ((uint32_t)0x02000000) +#define DMA1_INT_HTX7 ((uint32_t)0x04000000) +#define DMA1_INT_ERR7 ((uint32_t)0x08000000) +#define DMA1_INT_GLB8 ((uint32_t)0x10000000) +#define DMA1_INT_TXC8 ((uint32_t)0x20000000) +#define DMA1_INT_HTX8 ((uint32_t)0x40000000) +#define DMA1_INT_ERR8 ((uint32_t)0x80000000) + +#define DMA2_INT_GLB1 ((uint32_t)0x00000001) +#define DMA2_INT_TXC1 ((uint32_t)0x00000002) +#define DMA2_INT_HTX1 ((uint32_t)0x00000004) +#define DMA2_INT_ERR1 ((uint32_t)0x00000008) +#define DMA2_INT_GLB2 ((uint32_t)0x00000010) +#define DMA2_INT_TXC2 ((uint32_t)0x00000020) +#define DMA2_INT_HTX2 ((uint32_t)0x00000040) +#define DMA2_INT_ERR2 ((uint32_t)0x00000080) +#define DMA2_INT_GLB3 ((uint32_t)0x00000100) +#define DMA2_INT_TXC3 ((uint32_t)0x00000200) +#define DMA2_INT_HTX3 ((uint32_t)0x00000400) +#define DMA2_INT_ERR3 ((uint32_t)0x00000800) +#define DMA2_INT_GLB4 ((uint32_t)0x00001000) +#define DMA2_INT_TXC4 ((uint32_t)0x00002000) +#define DMA2_INT_HTX4 ((uint32_t)0x00004000) +#define DMA2_INT_ERR4 ((uint32_t)0x00008000) +#define DMA2_INT_GLB5 ((uint32_t)0x00010000) +#define DMA2_INT_TXC5 ((uint32_t)0x00020000) +#define DMA2_INT_HTX5 ((uint32_t)0x00040000) +#define DMA2_INT_ERR5 ((uint32_t)0x00080000) +#define DMA2_INT_GLB6 ((uint32_t)0x00100000) +#define DMA2_INT_TXC6 ((uint32_t)0x00200000) +#define DMA2_INT_HTX6 ((uint32_t)0x00400000) +#define DMA2_INT_ERR6 ((uint32_t)0x00800000) +#define DMA2_INT_GLB7 ((uint32_t)0x01000000) +#define DMA2_INT_TXC7 ((uint32_t)0x02000000) +#define DMA2_INT_HTX7 ((uint32_t)0x04000000) +#define DMA2_INT_ERR7 ((uint32_t)0x08000000) +#define DMA2_INT_GLB8 ((uint32_t)0x10000000) +#define DMA2_INT_TXC8 ((uint32_t)0x20000000) +#define DMA2_INT_HTX8 ((uint32_t)0x40000000) +#define DMA2_INT_ERR8 ((uint32_t)0x80000000) + +#define IS_DMA_CLR_INT(IT) ((IT) != 0x00) + +#define IS_DMA_GET_IT(IT) \ + (((IT) == DMA1_INT_GLB1) || ((IT) == DMA1_INT_TXC1) || ((IT) == DMA1_INT_HTX1) || ((IT) == DMA1_INT_ERR1) \ + || ((IT) == DMA1_INT_GLB2) || ((IT) == DMA1_INT_TXC2) || ((IT) == DMA1_INT_HTX2) || ((IT) == DMA1_INT_ERR2) \ + || ((IT) == DMA1_INT_GLB3) || ((IT) == DMA1_INT_TXC3) || ((IT) == DMA1_INT_HTX3) || ((IT) == DMA1_INT_ERR3) \ + || ((IT) == DMA1_INT_GLB4) || ((IT) == DMA1_INT_TXC4) || ((IT) == DMA1_INT_HTX4) || ((IT) == DMA1_INT_ERR4) \ + || ((IT) == DMA1_INT_GLB5) || ((IT) == DMA1_INT_TXC5) || ((IT) == DMA1_INT_HTX5) || ((IT) == DMA1_INT_ERR5) \ + || ((IT) == DMA1_INT_GLB6) || ((IT) == DMA1_INT_TXC6) || ((IT) == DMA1_INT_HTX6) || ((IT) == DMA1_INT_ERR6) \ + || ((IT) == DMA1_INT_GLB7) || ((IT) == DMA1_INT_TXC7) || ((IT) == DMA1_INT_HTX7) || ((IT) == DMA1_INT_ERR7) \ + || ((IT) == DMA1_INT_GLB8) || ((IT) == DMA1_INT_TXC8) || ((IT) == DMA1_INT_HTX8) || ((IT) == DMA1_INT_ERR8) \ + || ((IT) == DMA2_INT_GLB1) || ((IT) == DMA2_INT_TXC1) || ((IT) == DMA2_INT_HTX1) || ((IT) == DMA2_INT_ERR1) \ + || ((IT) == DMA2_INT_GLB2) || ((IT) == DMA2_INT_TXC2) || ((IT) == DMA2_INT_HTX2) || ((IT) == DMA2_INT_ERR2) \ + || ((IT) == DMA2_INT_GLB3) || ((IT) == DMA2_INT_TXC3) || ((IT) == DMA2_INT_HTX3) || ((IT) == DMA2_INT_ERR3) \ + || ((IT) == DMA2_INT_GLB4) || ((IT) == DMA2_INT_TXC4) || ((IT) == DMA2_INT_HTX4) || ((IT) == DMA2_INT_ERR4) \ + || ((IT) == DMA2_INT_GLB5) || ((IT) == DMA2_INT_TXC5) || ((IT) == DMA2_INT_HTX5) || ((IT) == DMA2_INT_ERR5) \ + || ((IT) == DMA2_INT_GLB6) || ((IT) == DMA2_INT_TXC6) || ((IT) == DMA2_INT_HTX6) || ((IT) == DMA2_INT_ERR6) \ + || ((IT) == DMA2_INT_GLB7) || ((IT) == DMA2_INT_TXC7) || ((IT) == DMA2_INT_HTX7) || ((IT) == DMA2_INT_ERR7) \ + || ((IT) == DMA2_INT_GLB8) || ((IT) == DMA2_INT_TXC8) || ((IT) == DMA2_INT_HTX8) || ((IT) == DMA2_INT_ERR8)) + +/** + * @} + */ + +/** @addtogroup DMA_flags_definition + * @{ + */ +#define DMA1_FLAG_GL1 ((uint32_t)0x00000001) +#define DMA1_FLAG_TC1 ((uint32_t)0x00000002) +#define DMA1_FLAG_HT1 ((uint32_t)0x00000004) +#define DMA1_FLAG_TE1 ((uint32_t)0x00000008) +#define DMA1_FLAG_GL2 ((uint32_t)0x00000010) +#define DMA1_FLAG_TC2 ((uint32_t)0x00000020) +#define DMA1_FLAG_HT2 ((uint32_t)0x00000040) +#define DMA1_FLAG_TE2 ((uint32_t)0x00000080) +#define DMA1_FLAG_GL3 ((uint32_t)0x00000100) +#define DMA1_FLAG_TC3 ((uint32_t)0x00000200) +#define DMA1_FLAG_HT3 ((uint32_t)0x00000400) +#define DMA1_FLAG_TE3 ((uint32_t)0x00000800) +#define DMA1_FLAG_GL4 ((uint32_t)0x00001000) +#define DMA1_FLAG_TC4 ((uint32_t)0x00002000) +#define DMA1_FLAG_HT4 ((uint32_t)0x00004000) +#define DMA1_FLAG_TE4 ((uint32_t)0x00008000) +#define DMA1_FLAG_GL5 ((uint32_t)0x00010000) +#define DMA1_FLAG_TC5 ((uint32_t)0x00020000) +#define DMA1_FLAG_HT5 ((uint32_t)0x00040000) +#define DMA1_FLAG_TE5 ((uint32_t)0x00080000) +#define DMA1_FLAG_GL6 ((uint32_t)0x00100000) +#define DMA1_FLAG_TC6 ((uint32_t)0x00200000) +#define DMA1_FLAG_HT6 ((uint32_t)0x00400000) +#define DMA1_FLAG_TE6 ((uint32_t)0x00800000) +#define DMA1_FLAG_GL7 ((uint32_t)0x01000000) +#define DMA1_FLAG_TC7 ((uint32_t)0x02000000) +#define DMA1_FLAG_HT7 ((uint32_t)0x04000000) +#define DMA1_FLAG_TE7 ((uint32_t)0x08000000) +#define DMA1_FLAG_GL8 ((uint32_t)0x10000000) +#define DMA1_FLAG_TC8 ((uint32_t)0x20000000) +#define DMA1_FLAG_HT8 ((uint32_t)0x40000000) +#define DMA1_FLAG_TE8 ((uint32_t)0x80000000) + +#define DMA2_FLAG_GL1 ((uint32_t)0x00000001) +#define DMA2_FLAG_TC1 ((uint32_t)0x00000002) +#define DMA2_FLAG_HT1 ((uint32_t)0x00000004) +#define DMA2_FLAG_TE1 ((uint32_t)0x00000008) +#define DMA2_FLAG_GL2 ((uint32_t)0x00000010) +#define DMA2_FLAG_TC2 ((uint32_t)0x00000020) +#define DMA2_FLAG_HT2 ((uint32_t)0x00000040) +#define DMA2_FLAG_TE2 ((uint32_t)0x00000080) +#define DMA2_FLAG_GL3 ((uint32_t)0x00000100) +#define DMA2_FLAG_TC3 ((uint32_t)0x00000200) +#define DMA2_FLAG_HT3 ((uint32_t)0x00000400) +#define DMA2_FLAG_TE3 ((uint32_t)0x00000800) +#define DMA2_FLAG_GL4 ((uint32_t)0x00001000) +#define DMA2_FLAG_TC4 ((uint32_t)0x00002000) +#define DMA2_FLAG_HT4 ((uint32_t)0x00004000) +#define DMA2_FLAG_TE4 ((uint32_t)0x00008000) +#define DMA2_FLAG_GL5 ((uint32_t)0x00010000) +#define DMA2_FLAG_TC5 ((uint32_t)0x00020000) +#define DMA2_FLAG_HT5 ((uint32_t)0x00040000) +#define DMA2_FLAG_TE5 ((uint32_t)0x00080000) +#define DMA2_FLAG_GL6 ((uint32_t)0x00100000) +#define DMA2_FLAG_TC6 ((uint32_t)0x00200000) +#define DMA2_FLAG_HT6 ((uint32_t)0x00400000) +#define DMA2_FLAG_TE6 ((uint32_t)0x00800000) +#define DMA2_FLAG_GL7 ((uint32_t)0x01000000) +#define DMA2_FLAG_TC7 ((uint32_t)0x02000000) +#define DMA2_FLAG_HT7 ((uint32_t)0x04000000) +#define DMA2_FLAG_TE7 ((uint32_t)0x08000000) +#define DMA2_FLAG_GL8 ((uint32_t)0x10000000) +#define DMA2_FLAG_TC8 ((uint32_t)0x20000000) +#define DMA2_FLAG_HT8 ((uint32_t)0x40000000) +#define DMA2_FLAG_TE8 ((uint32_t)0x80000000) + +#define IS_DMA_CLEAR_FLAG(FLAG) ((FLAG) != 0x00) + +#define IS_DMA_GET_FLAG(FLAG) \ + (((FLAG) == DMA1_FLAG_GL1) || ((FLAG) == DMA1_FLAG_TC1) || ((FLAG) == DMA1_FLAG_HT1) || ((FLAG) == DMA1_FLAG_TE1) \ + || ((FLAG) == DMA1_FLAG_GL2) || ((FLAG) == DMA1_FLAG_TC2) || ((FLAG) == DMA1_FLAG_HT2) \ + || ((FLAG) == DMA1_FLAG_TE2) || ((FLAG) == DMA1_FLAG_GL3) || ((FLAG) == DMA1_FLAG_TC3) \ + || ((FLAG) == DMA1_FLAG_HT3) || ((FLAG) == DMA1_FLAG_TE3) || ((FLAG) == DMA1_FLAG_GL4) \ + || ((FLAG) == DMA1_FLAG_TC4) || ((FLAG) == DMA1_FLAG_HT4) || ((FLAG) == DMA1_FLAG_TE4) \ + || ((FLAG) == DMA1_FLAG_GL5) || ((FLAG) == DMA1_FLAG_TC5) || ((FLAG) == DMA1_FLAG_HT5) \ + || ((FLAG) == DMA1_FLAG_TE5) || ((FLAG) == DMA1_FLAG_GL6) || ((FLAG) == DMA1_FLAG_TC6) \ + || ((FLAG) == DMA1_FLAG_HT6) || ((FLAG) == DMA1_FLAG_TE6) || ((FLAG) == DMA1_FLAG_GL7) \ + || ((FLAG) == DMA1_FLAG_TC7) || ((FLAG) == DMA1_FLAG_HT7) || ((FLAG) == DMA1_FLAG_TE7) \ + || ((FLAG) == DMA1_FLAG_GL8) || ((FLAG) == DMA1_FLAG_TC8) || ((FLAG) == DMA1_FLAG_HT8) \ + || ((FLAG) == DMA1_FLAG_TE8) || ((FLAG) == DMA2_FLAG_GL1) || ((FLAG) == DMA2_FLAG_TC1) \ + || ((FLAG) == DMA2_FLAG_HT1) || ((FLAG) == DMA2_FLAG_TE1) || ((FLAG) == DMA2_FLAG_GL2) \ + || ((FLAG) == DMA2_FLAG_TC2) || ((FLAG) == DMA2_FLAG_HT2) || ((FLAG) == DMA2_FLAG_TE2) \ + || ((FLAG) == DMA2_FLAG_GL3) || ((FLAG) == DMA2_FLAG_TC3) || ((FLAG) == DMA2_FLAG_HT3) \ + || ((FLAG) == DMA2_FLAG_TE3) || ((FLAG) == DMA2_FLAG_GL4) || ((FLAG) == DMA2_FLAG_TC4) \ + || ((FLAG) == DMA2_FLAG_HT4) || ((FLAG) == DMA2_FLAG_TE4) || ((FLAG) == DMA2_FLAG_GL5) \ + || ((FLAG) == DMA2_FLAG_TC5) || ((FLAG) == DMA2_FLAG_HT5) || ((FLAG) == DMA2_FLAG_TE5) \ + || ((FLAG) == DMA2_FLAG_GL6) || ((FLAG) == DMA2_FLAG_TC6) || ((FLAG) == DMA2_FLAG_HT6) \ + || ((FLAG) == DMA2_FLAG_TE6) || ((FLAG) == DMA2_FLAG_GL7) || ((FLAG) == DMA2_FLAG_TC7) \ + || ((FLAG) == DMA2_FLAG_HT7) || ((FLAG) == DMA2_FLAG_TE7) || ((FLAG) == DMA2_FLAG_GL8) \ + || ((FLAG) == DMA2_FLAG_TC8) || ((FLAG) == DMA2_FLAG_HT8) || ((FLAG) == DMA2_FLAG_TE8)) +/** + * @} + */ + +/** @addtogroup DMA_Buffer_Size + * @{ + */ + +#define IS_DMA_BUF_SIZE(SIZE) (((SIZE) >= 0x1) && ((SIZE) < 0x10000)) + +/** + * @} + */ + +/** @addtogroup DMA_remap_request_definition + * @{ + */ +#define DMA1_REMAP_ADC1 ((uint32_t)0x00000000) +#define DMA1_REMAP_UART5_TX ((uint32_t)0x00000001) +#define DMA1_REMAP_I2C3_TX ((uint32_t)0x00000002) +#define DMA1_REMAP_TIM2_CH3 ((uint32_t)0x00000003) +#define DMA1_REMAP_TIM4_CH1 ((uint32_t)0x00000004) +#define DMA1_REMAP_USART3_TX ((uint32_t)0x00000005) +#define DMA1_REMAP_I2C3_RX ((uint32_t)0x00000006) +#define DMA1_REMAP_TIM1_CH1 ((uint32_t)0x00000007) +#define DMA1_REMAP_TIM2_UP ((uint32_t)0x00000008) +#define DMA1_REMAP_TIM3_CH3 ((uint32_t)0x00000009) +#define DMA1_REMAP_SPI1_RX ((uint32_t)0x0000000A) +#define DMA1_REMAP_USART3_RX ((uint32_t)0x0000000B) +#define DMA1_REMAP_TIM1_CH2 ((uint32_t)0x0000000C) +#define DMA1_REMAP_TIM3_CH4 ((uint32_t)0x0000000D) +#define DMA1_REMAP_TIM3_UP ((uint32_t)0x0000000E) +#define DMA1_REMAP_SPI1_TX ((uint32_t)0x0000000F) +#define DMA1_REMAP_USART1_TX ((uint32_t)0x00000010) +#define DMA1_REMAP_TIM1_CH4 ((uint32_t)0x00000011) +#define DMA1_REMAP_TIM1_TRIG ((uint32_t)0x00000012) +#define DMA1_REMAP_TIM1_COM ((uint32_t)0x00000013) +#define DMA1_REMAP_TIM4_CH2 ((uint32_t)0x00000014) +#define DMA1_REMAP_SPI_I2S2_RX ((uint32_t)0x00000015) +#define DMA1_REMAP_I2C2_TX ((uint32_t)0x00000016) +#define DMA1_REMAP_USART1_RX ((uint32_t)0x00000017) +#define DMA1_REMAP_TIM1_UP ((uint32_t)0x00000018) +#define DMA1_REMAP_SPI_I2S2_TX ((uint32_t)0x00000019) +#define DMA1_REMAP_TIM4_CH3 ((uint32_t)0x0000001B) +#define DMA1_REMAP_I2C2_RX ((uint32_t)0x0000001C) +#define DMA1_REMAP_TIM2_CH1 ((uint32_t)0x0000001A) +#define DMA1_REMAP_USART2_RX ((uint32_t)0x0000001D) +#define DMA1_REMAP_TIM1_CH3 ((uint32_t)0x0000001E) +#define DMA1_REMAP_TIM3_CH1 ((uint32_t)0x0000001F) +#define DMA1_REMAP_TIM3_TRIG ((uint32_t)0x00000020) +#define DMA1_REMAP_I2C1_TX ((uint32_t)0x00000021) +#define DMA1_REMAP_USART2_TX ((uint32_t)0x00000022) +#define DMA1_REMAP_TIM2_CH2 ((uint32_t)0x00000023) +#define DMA1_REMAP_TIM2_CH4 ((uint32_t)0x00000024) +#define DMA1_REMAP_TIM4_UP ((uint32_t)0x00000025) +#define DMA1_REMAP_I2C1_RX ((uint32_t)0x00000026) +#define DMA1_REMAP_ADC2 ((uint32_t)0x00000027) +#define DMA1_REMAP_UART5_RX ((uint32_t)0x00000028) +#define DMA2_REMAP_TIM5_CH4 ((uint32_t)0x00000000) +#define DMA2_REMAP_TIM5_TRIG ((uint32_t)0x00000001) +#define DMA2_REMAP_TIM8_CH3 ((uint32_t)0x00000002) +#define DMA2_REMAP_TIM8_UP ((uint32_t)0x00000003) +#define DMA2_REMAP_SPI_I2S3_RX ((uint32_t)0x00000004) +#define DMA2_REMAP_UART6_RX ((uint32_t)0x00000005) +#define DMA2_REMAP_TIM8_CH4 ((uint32_t)0x00000006) +#define DMA2_REMAP_TIM8_TRIG ((uint32_t)0x00000007) +#define DMA2_REMAP_TIM8_COM ((uint32_t)0x00000008) +#define DMA2_REMAP_TIM5_CH3 ((uint32_t)0x00000009) +#define DMA2_REMAP_TIM5_UP ((uint32_t)0x0000000A) +#define DMA2_REMAP_SPI_I2S3_TX ((uint32_t)0x0000000B) +#define DMA2_REMAP_UART6_TX ((uint32_t)0x0000000C) +#define DMA2_REMAP_TIM8_CH1 ((uint32_t)0x0000000D) +#define DMA2_REMAP_UART4_RX ((uint32_t)0x0000000E) +#define DMA2_REMAP_TIM6_UP ((uint32_t)0x0000000F) +#define DMA2_REMAP_DAC1 ((uint32_t)0x00000010) +#define DMA2_REMAP_TIM5_CH2 ((uint32_t)0x00000011) +#define DMA2_REMAP_SDIO ((uint32_t)0x00000012) +#define DMA2_REMAP_TIM7_UP ((uint32_t)0x00000013) +#define DMA2_REMAP_DAC2 ((uint32_t)0x00000014) +#define DMA2_REMAP_ADC3 ((uint32_t)0x00000015) +#define DMA2_REMAP_TIM8_CH2 ((uint32_t)0x00000016) +#define DMA2_REMAP_TIM5_CH1 ((uint32_t)0x00000017) +#define DMA2_REMAP_UART4_TX ((uint32_t)0x00000018) +#define DMA2_REMAP_QSPI_RX ((uint32_t)0x00000019) +#define DMA2_REMAP_I2C4_TX ((uint32_t)0x0000001A) +#define DMA2_REMAP_UART7_RX ((uint32_t)0x0000001B) +#define DMA2_REMAP_QSPI_TX ((uint32_t)0x0000001C) +#define DMA2_REMAP_I2C4_RX ((uint32_t)0x0000001D) +#define DMA2_REMAP_UART7_TX ((uint32_t)0x0000001E) +#define DMA2_REMAP_ADC4 ((uint32_t)0x0000001F) +#define DMA2_REMAP_DVP ((uint32_t)0x00000020) + +#define IS_DMA_REMAP(FLAG) \ + (((FLAG) == DMA1_REMAP_ADC1) || ((FLAG) == DMA1_REMAP_UART5_TX) || ((FLAG) == DMA1_REMAP_I2C3_TX) \ + || ((FLAG) == DMA1_REMAP_TIM2_CH3) || ((FLAG) == DMA1_REMAP_TIM4_CH1) || ((FLAG) == DMA1_REMAP_USART3_TX) \ + || ((FLAG) == DMA1_REMAP_I2C3_RX) || ((FLAG) == DMA1_REMAP_TIM1_CH1) || ((FLAG) == DMA1_REMAP_TIM2_UP) \ + || ((FLAG) == DMA1_REMAP_TIM3_CH3) || ((FLAG) == DMA1_REMAP_SPI1_RX) || ((FLAG) == DMA1_REMAP_USART3_RX) \ + || ((FLAG) == DMA1_REMAP_TIM1_CH2) || ((FLAG) == DMA1_REMAP_TIM3_CH4) || ((FLAG) == DMA1_REMAP_TIM3_UP) \ + || ((FLAG) == DMA1_REMAP_SPI1_TX) || ((FLAG) == DMA1_REMAP_USART1_TX) || ((FLAG) == DMA1_REMAP_TIM1_CH4) \ + || ((FLAG) == DMA1_REMAP_TIM1_TRIG) || ((FLAG) == DMA1_REMAP_TIM1_COM) || ((FLAG) == DMA1_REMAP_TIM4_CH2) \ + || ((FLAG) == DMA1_REMAP_SPI_I2S2_RX) || ((FLAG) == DMA1_REMAP_I2C2_TX) || ((FLAG) == DMA1_REMAP_USART1_RX) \ + || ((FLAG) == DMA1_REMAP_TIM1_UP) || ((FLAG) == DMA1_REMAP_SPI_I2S2_TX) || ((FLAG) == DMA1_REMAP_TIM4_CH3) \ + || ((FLAG) == DMA1_REMAP_I2C2_RX) || ((FLAG) == DMA1_REMAP_TIM2_CH1) || ((FLAG) == DMA1_REMAP_USART2_RX) \ + || ((FLAG) == DMA1_REMAP_TIM1_CH3) || ((FLAG) == DMA1_REMAP_TIM3_CH1) || ((FLAG) == DMA1_REMAP_TIM3_TRIG) \ + || ((FLAG) == DMA1_REMAP_I2C1_TX) || ((FLAG) == DMA1_REMAP_USART2_TX) || ((FLAG) == DMA1_REMAP_TIM2_CH2) \ + || ((FLAG) == DMA1_REMAP_TIM2_CH4) || ((FLAG) == DMA1_REMAP_TIM4_UP) || ((FLAG) == DMA1_REMAP_I2C1_RX) \ + || ((FLAG) == DMA1_REMAP_ADC2) || ((FLAG) == DMA1_REMAP_UART5_RX) || ((FLAG) == DMA2_REMAP_TIM5_CH4) \ + || ((FLAG) == DMA2_REMAP_TIM5_TRIG) || ((FLAG) == DMA2_REMAP_TIM8_CH3) || ((FLAG) == DMA2_REMAP_TIM8_UP) \ + || ((FLAG) == DMA2_REMAP_SPI_I2S3_RX) || ((FLAG) == DMA2_REMAP_UART6_RX) || ((FLAG) == DMA2_REMAP_TIM8_CH4) \ + || ((FLAG) == DMA2_REMAP_TIM8_TRIG) || ((FLAG) == DMA2_REMAP_TIM8_COM) || ((FLAG) == DMA2_REMAP_TIM5_CH3) \ + || ((FLAG) == DMA2_REMAP_TIM5_UP) || ((FLAG) == DMA2_REMAP_SPI_I2S3_TX) || ((FLAG) == DMA2_REMAP_UART6_TX) \ + || ((FLAG) == DMA2_REMAP_TIM8_CH1) || ((FLAG) == DMA2_REMAP_UART4_RX) || ((FLAG) == DMA2_REMAP_TIM6_UP) \ + || ((FLAG) == DMA2_REMAP_DAC1) || ((FLAG) == DMA2_REMAP_TIM5_CH2) || ((FLAG) == DMA2_REMAP_SDIO) \ + || ((FLAG) == DMA2_REMAP_TIM7_UP) || ((FLAG) == DMA2_REMAP_DAC2) || ((FLAG) == DMA2_REMAP_ADC3) \ + || ((FLAG) == DMA2_REMAP_TIM8_CH2) || ((FLAG) == DMA2_REMAP_TIM5_CH1) || ((FLAG) == DMA2_REMAP_UART4_TX) \ + || ((FLAG) == DMA2_REMAP_QSPI_RX) || ((FLAG) == DMA2_REMAP_I2C4_TX) || ((FLAG) == DMA2_REMAP_UART7_RX) \ + || ((FLAG) == DMA2_REMAP_QSPI_TX) || ((FLAG) == DMA2_REMAP_I2C4_RX) || ((FLAG) == DMA2_REMAP_UART7_TX) \ + || ((FLAG) == DMA2_REMAP_ADC4) || ((FLAG) == DMA2_REMAP_DVP)) + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup DMA_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DMA_Exported_Functions + * @{ + */ + +void DMA_DeInit(DMA_ChannelType* DMAyChx); +void DMA_Init(DMA_ChannelType* DMAyChx, DMA_InitType* DMA_InitParam); +void DMA_StructInit(DMA_InitType* DMA_InitParam); +void DMA_EnableChannel(DMA_ChannelType* DMAyChx, FunctionalState Cmd); +void DMA_ConfigInt(DMA_ChannelType* DMAyChx, uint32_t DMAInt, FunctionalState Cmd); +void DMA_SetCurrDataCounter(DMA_ChannelType* DMAyChx, uint16_t DataNumber); +uint16_t DMA_GetCurrDataCounter(DMA_ChannelType* DMAyChx); +FlagStatus DMA_GetFlagStatus(uint32_t DMAyFlag, DMA_Module* DMAy); +void DMA_ClearFlag(uint32_t DMAyFlag, DMA_Module* DMAy); +INTStatus DMA_GetIntStatus(uint32_t DMAy_IT, DMA_Module* DMAy); +void DMA_ClrIntPendingBit(uint32_t DMAy_IT, DMA_Module* DMAy); +void DMA_RequestRemap(uint32_t DMAy_REMAP, DMA_Module* DMAy, DMA_ChannelType* DMAyChx, FunctionalState Cmd); + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G4FR_DMA_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_dvp.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_dvp.h new file mode 100644 index 0000000000..6cdd38796a --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_dvp.h @@ -0,0 +1,602 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_dvp.h + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#ifndef __N32G4FR_DVP_H__ +#define __N32G4FR_DVP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DVP + * @brief DVP driver modules + * @{ + */ + +/** @addtogroup DVP_Exported_Types + * @{ + */ +/** + * @brief DVP Init Structure definition + */ +typedef struct +{ + uint32_t FifoWatermark; /*!< Specifies the max number of fifo data which will request INT or DMA + This parameter can be a value of @ref DVP_FifoWatermark */ + + uint16_t LineCapture; /*!< Specifies the number of data line captuered in x lines. + This parameter can be a value of @ref DVP_LineSelect_Mode */ + + uint16_t ByteCapture; /*!< Specifies the number of stop byte captuered in x bytes. + This parameter can be a value of @ref DVP_ByteSelect_Mode */ + + uint16_t DataInvert; /*!< Specifies the data invert. + This parameter can be a value of @ref DVP_DATA_INVERT */ + + uint16_t PixelClkPolarity; /*!< Specifies the pixel clock polarity + This parameter can be a value of @ref DVP_Pixel_Polarity */ + + uint16_t VsyncPolarity; /*!< Specifies the vertical synchronization polarity + This parameter can be a value of @ref DVP_Vsync_Polarity */ + + uint16_t HsyncPolarity; /*!< Specifies the Horizontal synchronization polarity + This parameter can be a value of @ref DVP_Hsync_Polarity */ + + uint16_t CaptureMode; /*!< Specifies the capture mode. + This parameter can be a value of @ref DVP_Capture_Mode */ + + uint16_t RowStart; /*!< Specifies the startint row of the pixel array in a frame */ + + uint16_t ColumnStart; /*!< Specifies the starting column of the pixel array row in a frame */ + + uint16_t ImageHeight; /*!< Specifies the image's height in a frame */ + + uint16_t ImageWidth; /*!< Specifies the image's width in a frame */ + +} DVP_InitType; +/** + * @} + */ + +/** @addtogroup DVP_Exported_Constants + * @{ + */ + +/** @addtogroup DVP_FIFO_SOFT_RESET + * @{ + */ +#define DVP_FIFO_SOFT_RESET (DVP_CTRL_FFSWRST) +/** + * @} + */ + +/** @addtogroup DVP_LineSelect_Mode + * @{ + */ +#define DVP_LINE_CAPTURE_ALL (0x00000000) +#define DVP_LINE_CAPTURE_1_2 (0x1UL << DVP_CTRL_LSM_SHIFT) +#define DVP_LINE_CAPTURE_1_3 (0x2UL << DVP_CTRL_LSM_SHIFT) +#define DVP_LINE_CAPTURE_1_4 (0x3UL << DVP_CTRL_LSM_SHIFT) +#define DVP_LINE_CAPTURE_1_5 (0x4UL << DVP_CTRL_LSM_SHIFT) +#define DVP_LINE_CAPTURE_1_6 (0x5UL << DVP_CTRL_LSM_SHIFT) +#define DVP_LINE_CAPTURE_1_7 (0x6UL << DVP_CTRL_LSM_SHIFT) +#define DVP_LINE_CAPTURE_1_8 (0x7UL << DVP_CTRL_LSM_SHIFT) +#define IS_DVP_LINE_CAPTURE(_LSM_) (((_LSM_) & (~DVP_CTRL_LSM_MASK) )==0) +/** + * @} + */ + +/** @addtogroup DVP_ByteSelect_Mode + * @{ + */ +#define DVP_BYTE_CAPTURE_ALL (0x00000000) +#define DVP_BYTE_CAPTURE_1_2 (0x1UL << DVP_CTRL_BSM_SHIFT) +#define DVP_BYTE_CAPTURE_1_3 (0x2UL << DVP_CTRL_BSM_SHIFT) +#define DVP_BYTE_CAPTURE_1_4 (0x3UL << DVP_CTRL_BSM_SHIFT) +#define DVP_BYTE_CAPTURE_1_5 (0x4UL << DVP_CTRL_BSM_SHIFT) +#define DVP_BYTE_CAPTURE_1_6 (0x5UL << DVP_CTRL_BSM_SHIFT) +#define DVP_BYTE_CAPTURE_1_7 (0x6UL << DVP_CTRL_BSM_SHIFT) +#define DVP_BYTE_CAPTURE_1_8 (0x7UL << DVP_CTRL_BSM_SHIFT) +#define IS_DVP_BYTE_CAPTURE(_BSM_) (((_BSM_) & (~DVP_CTRL_BSM_MASK) )==0) + +/** + * @} + */ + +/** @addtogroup DVP_DATA_INVERT + * @{ + */ +#define DVP_DATA_INVERT (DVP_CTRL_DATINV) +#define DVP_DATA_NOTINVERT (0x00000000) +#define IS_DVP_DATA_INVERT(_INV_) (((_INV_) & (~DVP_CTRL_DATINV_MASK) )==0) +/** + * @} + */ + +/** @addtogroup DVP_Pixel_Polarity + * @{ + */ +#define DVP_PIXEL_POLARITY_FALLING (0x00000000) +#define DVP_PIXEL_POLARITY_RISING (DVP_CTRL_PCKPOL) +#define IS_DVP_PIXEL_POLARITY(_POL_) (((_POL_) & (~DVP_CTRL_PCKPOL_MASK) )==0) +/** + * @} + */ + +/** @addtogroup DVP_FifoWatermark + * @{ + */ +#define DVP_WATER_MARK_0 (0x00000000) +#define DVP_WATER_MARK_1 (0x1UL << DVP_CTRL_FWM_SHIFT) +#define DVP_WATER_MARK_2 (0x2UL << DVP_CTRL_FWM_SHIFT) +#define DVP_WATER_MARK_3 (0x3UL << DVP_CTRL_FWM_SHIFT) +#define DVP_WATER_MARK_4 (0x4UL << DVP_CTRL_FWM_SHIFT) +#define DVP_WATER_MARK_5 (0x5UL << DVP_CTRL_FWM_SHIFT) +#define DVP_WATER_MARK_6 (0x6UL << DVP_CTRL_FWM_SHIFT) +#define DVP_WATER_MARK_7 (0x7UL << DVP_CTRL_FWM_SHIFT) + +#define IS_DVP_FIFOWATERMARK(_WATER_) (((_WATER_) >= DVP_WATER_MARK_1) && ((_WATER_) <= DVP_WATER_MARK_7)) + +/** @addtogroup DVP_Vsync_Polarity + * @{ + */ +#define DVP_VSYNC_POLARITY_HIGH (DVP_CTRL_VSPOL) +#define DVP_VSYNC_POLARITY_LOW (0x00000000) +#define IS_DVP_VSYNC_POLARITY(_POL_) (((_POL_) == DVP_VSYNC_POLARITY_HIGH) || ((_POL_) == DVP_VSYNC_POLARITY_LOW)) +/** + * @} + */ + +/** @addtogroup DVP_Hsync_Polarity + * @{ + */ +#define DVP_HSYNC_POLARITY_HIGH (DVP_CTRL_HSPOL) +#define DVP_HSYNC_POLARITY_LOW (0x00000000) +#define IS_DVP_HSYNC_POLARITY(_POL_) (((_POL_) == DVP_HSYNC_POLARITY_HIGH) || ((_POL_) == DVP_HSYNC_POLARITY_LOW)) +/** + * @} + */ + +/** @addtogroup DVP_Capture_Mode + * @{ + */ +#define DVP_CAPTURE_MODE_SINGLE (0x00000000) +#define DVP_CAPTURE_MODE_CONTINUE (DVP_CTRL_CM) +#define IS_DVP_CAPTURE_MODE(_MODE_) (((_MODE_) == DVP_CAPTURE_MODE_SINGLE) || ((_MODE_) == DVP_CAPTURE_MODE_CONTINUE)) +/** + * @} + */ + +/** @addtogroup DVP_CAPTURE_ENABLE + * @{ + */ +#define DVP_CAPTURE_DISABLE (0x00000000) +#define DVP_CAPTURE_ENABLE (DVP_CTRL_CAPTURE) +#define IS_DVP_CAPTURE(_CAPTURE_) (((_CAPTURE_) == DVP_CAPTURE_DISABLE) || ((_CAPTURE_) == DVP_CAPTURE_ENABLE)) +/** + * @} + */ + +/** @addtogroup DVP_DMA + * @{ + */ +#define DVP_DMA_DISABLE (0x00000000) +#define DVP_DMA_ENABLE (DVP_INTEN_DMAEN) +/** + * @} + */ + +/** @addtogroup DVP_StatusFlag + * @{ + */ +#define DVP_FLAG_HERR (DVP_INTSTS_HERRIS) +#define DVP_FLAG_VERR (DVP_INTSTS_VERRIS) +#define DVP_FLAG_FO (DVP_INTSTS_FOIS) +#define DVP_FLAG_FW (DVP_INTSTS_FWIS) +#define DVP_FLAG_FF (DVP_INTSTS_FFIS) +#define DVP_FLAG_FE (DVP_INTSTS_FEIS) +#define DVP_FLAG_LE (DVP_INTSTS_LEIS) +#define DVP_FLAG_LS (DVP_INTSTS_LSIS) +#define DVP_FLAG_FME (DVP_INTSTS_FMEIS) +#define DVP_FLAG_FMS (DVP_INTSTS_FMSIS) +#define DVP_FLAG_MASK (DVP_FLAG_HERR |DVP_FLAG_VERR |DVP_FLAG_FO \ + |DVP_FLAG_FW |DVP_FLAG_FF |DVP_FLAG_FE \ + |DVP_FLAG_LE |DVP_FLAG_LS |DVP_FLAG_FME \ + |DVP_FLAG_FMS) +#define IS_DVP_FLAG(_FLAG_) (((_FLAG_) & (~DVP_FLAG_MASK))==0) + +/** @addtogroup DVP_ClearFlag + * @{ + */ +#define DVP_CLEAR_FLAG_HERR (DVP_INTSTS_HERRIS) +#define DVP_CLEAR_FLAG_VERR (DVP_INTSTS_VERRIS) +#define DVP_CLEAR_FLAG_FO (DVP_INTSTS_FOIS) +#define DVP_CLEAR_FLAG_FE (DVP_INTSTS_FEIS) +#define DVP_CLEAR_FLAG_LE (DVP_INTSTS_LEIS) +#define DVP_CLEAR_FLAG_LS (DVP_INTSTS_LSIS) +#define DVP_CLEAR_FLAG_FME (DVP_INTSTS_FMEIS) +#define DVP_CLEAR_FLAG_FMS (DVP_INTSTS_FMSIS) +#define DVP_CLEAR_FLAG_MASK (DVP_CLEAR_FLAG_HERR |DVP_CLEAR_FLAG_VERR \ + |DVP_CLEAR_FLAG_FO |DVP_CLEAR_FLAG_FE \ + |DVP_CLEAR_FLAG_LE |DVP_CLEAR_FLAG_LS \ + |DVP_CLEAR_FLAG_FME |DVP_CLEAR_FLAG_FMS) +#define IS_DVP_CLEAR_FLAG(_FLAG_) (((_FLAG_) & (~DVP_CLEAR_FLAG_MASK))==0) + + +/** + * @} + */ + +/** @addtogroup DVP_IntEnable + * @{ + */ +#define DVP_INTEN_HERR (DVP_INTEN_HERRIE) +#define DVP_INTEN_VERR (DVP_INTEN_VERRIE) +#define DVP_INTEN_FO (DVP_INTEN_FOIE) +#define DVP_INTEN_FW (DVP_INTEN_FWIE) +#define DVP_INTEN_FF (DVP_INTEN_FFIE) +#define DVP_INTEN_FE (DVP_INTEN_FEIE) +#define DVP_INTEN_LE (DVP_INTEN_LEIE) +#define DVP_INTEN_LS (DVP_INTEN_LSIE) +#define DVP_INTEN_FME (DVP_INTEN_FMEIE) +#define DVP_INTEN_FMS (DVP_INTEN_FMSIE) +#define DVP_INTEN_MASK (DVP_INTEN_HERR |DVP_INTEN_VERR |DVP_INTEN_FO |DVP_INTEN_FW \ + |DVP_INTEN_FF |DVP_INTEN_FE |DVP_INTEN_LE |DVP_INTEN_LS \ + |DVP_INTEN_FME |DVP_INTEN_FMS) +#define IS_DVP_INTEN(_INT_) (((_INT_) & (~DVP_INTEN_MASK))==0) +/** + * @} + */ + +/** @addtogroup DVP_IntMark + * @{ + */ +#define DVP_MINT_HERR (DVP_MINTSTS_HERRMIS) +#define DVP_MINT_VERR (DVP_MINTSTS_VERRMIS) +#define DVP_MINT_FO (DVP_MINTSTS_FOMIS) +#define DVP_MINT_FW (DVP_MINTSTS_FWMIS) +#define DVP_MINT_FF (DVP_MINTSTS_FFMIS) +#define DVP_MINT_FE (DVP_MINTSTS_FEMIS) +#define DVP_MINT_LE (DVP_MINTSTS_LEMIS) +#define DVP_MINT_LS (DVP_MINTSTS_LSMIS) +#define DVP_MINT_FME (DVP_MINTSTS_FMEMIS) +#define DVP_MINT_FMS (DVP_MINTSTS_FMSMIS) +#define DVP_MINT_MASK (DVP_MINT_HERR |DVP_MINT_VERR |DVP_MINT_FO |DVP_MINT_FW \ + |DVP_MINT_FF |DVP_MINT_FE |DVP_MINT_LE |DVP_MINT_LS \ + |DVP_MINT_FME |DVP_MINT_FMS) +#define IS_DVP_MINT(_MINT_) (((_MINT_) & (~DVP_MINT_MASK))==0) +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @addtogroup DVP_Exported_Macros + * @{ + */ + +/** + * @brief Config the water mark of FIFO. + * @param _Watermark_ Select the new water mark of FIFO. + * This parameter can be one of the following values: + * @arg DVP_WATER_MARK_1 + * @arg DVP_WATER_MARK_2 + * @arg DVP_WATER_MARK_3 + * @arg DVP_WATER_MARK_4 + * @retval None + */ +#define __DVP_SetFifoWatermark(_Watermark_) (MODIFY_REG(DVP->CTRL, DVP_CTRL_FWM_MASK, _Watermark_)) + +/** + * @brief Config the line capture mode. + * @param _LSM_ Specifies the new mode of line capture. + * This parameter can be one of the following values: + * @arg DVP_LINE_CAPTURE_ALL Capture all lines + * @arg DVP_LINE_CAPTURE_1_2 Capture 1 line of each 2 lines + * @arg DVP_LINE_CAPTURE_1_3 Capture 1 line of each 3 lines + * @arg DVP_LINE_CAPTURE_1_4 Capture 1 line of each 4 lines + * @arg DVP_LINE_CAPTURE_1_5 Capture 1 line of each 5 lines + * @arg DVP_LINE_CAPTURE_1_6 Capture 1 line of each 6 lines + * @arg DVP_LINE_CAPTURE_1_7 Capture 1 line of each 7 lines + * @arg DVP_LINE_CAPTURE_1_8 Capture 1 line of each 8 lines + * @retval None + */ +#define __DVP_SetLineCaptureMode(_LSM_) (MODIFY_REG(DVP->CTRL, DVP_CTRL_LSM_MASK, _LSM_)) + +/** + * @brief Config the byte capture mode. + * @param _BSM_ Specifies the new mode of byte capture. + * This parameter can be one of the following values: + * @arg DVP_BYTE_CAPTURE_ALL Capture all pixels + * @arg DVP_BYTE_CAPTURE_1_2 Capture 1 pixel of each 2 pixels + * @arg DVP_BYTE_CAPTURE_1_3 Capture 1 pixel of each 3 pixels + * @arg DVP_BYTE_CAPTURE_1_4 Capture 1 pixel of each 4 pixels + * @arg DVP_BYTE_CAPTURE_1_5 Capture 1 pixel of each 5 pixels + * @arg DVP_BYTE_CAPTURE_1_6 Capture 1 pixel of each 6 pixels + * @arg DVP_BYTE_CAPTURE_1_7 Capture 1 pixel of each 7 pixels + * @arg DVP_BYTE_CAPTURE_1_8 Capture 1 pixel of each 8 pixels + * @retval None + */ +#define __DVP_SetByteCaptureMode(_BSM_) (MODIFY_REG(DVP->CTRL, DVP_CTRL_BSM_MASK, _BSM_)) + +/** + * @brief Config the data invert function. + * @param _INV_ Specifies the data invert or not. + * This parameter can be one of the following values: + * @arg DVP_DATA_INVERT Invert capture data + * @arg DVP_DATA_NOTINVERT Capture data not invert + * @retval None + */ +#define __DVP_SetDataInvert(_INV_) (MODIFY_REG(DVP->CTRL, DVP_CTRL_DATINV_MASK, _INV_)) + +/** + * @brief Config the pixel clock polarity. + * @param _POL_ Specifies the clock edge of pixel clock. + * This parameter can be one of the following values: + * @arg DVP_PIXEL_POLARITY_FALLING Get data at falling edge + * @arg DVP_PIXEL_POLARITY_RISING Get data at rising edge + * @retval None + */ +#define __DVP_SetPclkPol(_POL_) (MODIFY_REG(DVP->CTRL, DVP_CTRL_PCKPOL_MASK, _POL_)) + +/** + * @brief Config the VSYNC polarity. + * @param _POL_ Specifies the active polarity of VSYNC pin. + * This parameter can be one of the following values: + * @arg DVP_VSYNC_POLARITY_HIGH VSYNC active high + * @arg DVP_VSYNC_POLARITY_LOW VSYNC active low + * @retval None + */ +#define __DVP_SetVsyncPol(_POL_) (MODIFY_REG(DVP->CTRL, DVP_CTRL_VSPOL_MASK, _POL_)) + +/** + * @brief Config the HSYNC polarity. + * @param _POL_ Specifies the active polarity of HSYNC pin. + * This parameter can be one of the following values: + * @arg DVP_HSYNC_POLARITY_HIGH VSYNC active high + * @arg DVP_HSYNC_POLARITY_LOW VSYNC active low + * @retval None + */ +#define __DVP_SetHsyncPol(_POL_) (MODIFY_REG(DVP->CTRL, DVP_CTRL_HSPOL_MASK, _POL_)) + +/** + * @brief Config the capture mode. + * @param _POL_ Specifies the new capture mode. + * This parameter can be one of the following values: + * @arg DVP_CAPTURE_MODE_SINGLE Capture one frame + * @arg DVP_CAPTURE_MODE_CONTINUE Capture many frames + * @retval None + */ +#define __DVP_SetCaptureMode(_MODE_) (MODIFY_REG(DVP->CTRL, DVP_CTRL_CM_MASK, _MODE_)) + +/** + * @brief Enable DVP interface. + * @param None + * @retval None + */ +#define __DVP_StartCapture() (SET_BIT(DVP->CTRL, DVP_CAPTURE_ENABLE)) + +/** + * @brief Disable DVP interface. + * @param None + * @retval None + */ +#define __DVP_StopCapture() (CLEAR_BIT(DVP->CTRL, DVP_CAPTURE_ENABLE)) + +/** + * @brief Disable DVP interface. + * @param None + * @retval None + */ +#define __FIFOIsNotEmpty() (READ_BIT(DVP->STS, DVP_STS_FNE)) + +/** + * @brief Checks whether the specified DVP flag is set. + * @param _FLAG_ specifies the flag to check. + * This parameter can be any combination of the following values: + * @arg DVP_FLAG_HERR Hsync error interrupt flag + * @arg DVP_FLAG_VERR Vsync error interrupt flag + * @arg DVP_FLAG_FO FIFO overflow intterrupt flag + * @arg DVP_FLAG_FW FIFO watermark interrupt flag + * @arg DVP_FLAG_FF FIFO full interrupt flag + * @arg DVP_FLAG_FE FIFO empty interrupt flag + * @arg DVP_FLAG_LE Line end interrupt flag + * @arg DVP_FLAG_LS Line start interrupt flag + * @arg DVP_FLAG_FME Frame end interrupt flag + * @arg DVP_FLAG_FMS Frame start interrupt flag + * @retval true or false. + */ +#define __DVP_FlagIsSet(_FLAG_) (((DVP->INTSTS) & (_FLAG_))==(_FLAG_)) + +/** + * @brief Checks whether the specified DVP flag is not set. + * @param _FLAG_ specifies the flag to check. + * This parameter can be any combination of the following values: + * @arg DVP_FLAG_HERR Hsync error interrupt flag + * @arg DVP_FLAG_VERR Vsync error interrupt flag + * @arg DVP_FLAG_FO FIFO overflow intterrupt flag + * @arg DVP_FLAG_FW FIFO watermark interrupt flag + * @arg DVP_FLAG_FF FIFO full interrupt flag + * @arg DVP_FLAG_FE FIFO empty interrupt flag + * @arg DVP_FLAG_LE Line end interrupt flag + * @arg DVP_FLAG_LS Line start interrupt flag + * @arg DVP_FLAG_FME Frame end interrupt flag + * @arg DVP_FLAG_FMS Frame start interrupt flag + * @retval true or false. + */ +#define __DVP_FlagIsNotSet(_FLAG_) (((DVP->INTSTS) & (_FLAG_))!=(_FLAG_)) + +/** + * @brief Clears the DVP flags. + * @param _FLAG_ specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg DVP_CLEAR_FLAG_HERR Hsync error interrupt flag clear + * @arg DVP_CLEAR_FLAG_VERR Vsync error interrupt flag clear + * @arg DVP_CLEAR_FLAG_FO FIFO overflow intterrupt flag clear + * @arg DVP_CLEAR_FLAG_FE FIFO empty interrupt flag clear + * @arg DVP_CLEAR_FLAG_LE Line end interrupt flag clear + * @arg DVP_CLEAR_FLAG_LS Line start interrupt flag clear + * @arg DVP_CLEAR_FLAG_FME Frame end interrupt flag clear + * @arg DVP_CLEAR_FLAG_FMS Frame start interrupt flag clear + * @retval None. + */ +#define __DVP_ClrFlag(_FLAG_) (DVP->INTSTS = (~(_FLAG_)) & DVP_CLEAR_FLAG_MASK) + +/** + * @brief Enable DVP interrupts. + * @param _INT_ specifies the interrupt to be enable. + * This parameter can be any combination of the following values: + * @arg DVP_INTEN_HERR Hsync error interrupt enable + * @arg DVP_INTEN_VERR Vsync error interrupt enable + * @arg DVP_INTEN_FO FIFO overflow intterrupt enable + * @arg DVP_INTEN_FE FIFO empty interrupt enable + * @arg DVP_INTEN_LE Line end interrupt enable + * @arg DVP_INTEN_LS Line start interrupt enable + * @arg DVP_INTEN_FME Frame end interrupt enable + * @arg DVP_INTEN_FMS Frame start interrupt enable + * @retval None. + */ +#define __DVP_EnableInt(_INT_) (SET_BIT(DVP->INTEN, _INT_)) + +/** + * @brief Disable DVP interrupts. + * @param _INT_ specifies the interrupt to be disable. + * This parameter can be any combination of the following values: + * @arg DVP_INTEN_HERR Hsync error interrupt disable + * @arg DVP_INTEN_VERR Vsync error interrupt disable + * @arg DVP_INTEN_FO FIFO overflow intterrupt disable + * @arg DVP_INTEN_FE FIFO empty interrupt disable + * @arg DVP_INTEN_LE Line end interrupt disable + * @arg DVP_INTEN_LS Line start interrupt disable + * @arg DVP_INTEN_FME Frame end interrupt disable + * @arg DVP_INTEN_FMS Frame start interrupt disable + * @retval None. + */ +#define __DVP_DisableInt(_INT_) (CLEAR_BIT(DVP->INTEN, _INT_)) + +/** + * @brief Enable DVP DMA. + * @param None. + * @retval None. + */ +#define __DVP_EnableDMA() (SET_BIT(DVP->INTEN, DVP_INTEN_DMAEN)) + +/** + * @brief Enable DVP DMA. + * @param None. + * @retval None. + */ +#define __DVP_DisableDMA() (CLEAR_BIT(DVP->INTEN, DVP_INTEN_DMAEN)) + +/** + * @brief Checks whether the specified DVP interrupt has occurred or not. + * @param _INT_ specifies the DVP interrupt source to check. + * This parameter can be one of the following values: + * @arg DVP_MINT_HERR Hsync error interrupt + * @arg DVP_MINT_VERR Vsync error interrupt + * @arg DVP_MINT_FO FIFO overflow intterrupt + * @arg DVP_MINT_FW FIFO watermark interrupt + * @arg DVP_MINT_FF FIFO full interrupt + * @arg DVP_MINT_FE FIFO empty interrupt + * @arg DVP_MINT_LE Line end interrupt + * @arg DVP_MINT_LS Line start interrupt + * @arg DVP_MINT_FME Frame end interrupt + * @arg DVP_MINT_FMS Frame start interrupt + * @retval The state of _INT_ (SET or RESET). + */ +#define __DVP_GetIntMark(_INT_) (((DVP->MINTSTS) & (_INT_))==(_INT_)) + +/** + * @brief Config the positon of first capture pixel . + * @param _VST_ specifies the line positon. + * This parameter must be less than 2048. + * @param _HST_ specifies the pixel positon. + * This parameter must be less than 2048. + * @retval None. + */ +#define __DVP_SetStartSHIFT(_VST_,_HST_) (DVP->WST=((_VST_)<WSIZE=((_VLINE_)<FIFO)) + + +/** + * @} + */ + +/** @addtogroup DVP_Exported_Functions + * @{ + */ +void DVP_ResetReg(void); +void DVP_Init(DVP_InitType* DVP_InitStruct); +void DVP_DafaultInitParam(DVP_InitType* DVP_InitStruct); +uint32_t DVP_GetFifoCount(void); +void DVP_ResetFifo(void); +void DVP_ConfigDma( FunctionalState Cmd); + +/** + * @} + */ +/** + * @} + */ +/** + * @} + */ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_exti.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_exti.h new file mode 100644 index 0000000000..9c436e1dd9 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_exti.h @@ -0,0 +1,206 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_exti.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_EXTI_H__ +#define __N32G4FR_EXTI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup EXTI + * @{ + */ + +/** @addtogroup EXTI_Exported_Types + * @{ + */ + +/** + * @brief EXTI mode enumeration + */ + +typedef enum +{ + EXTI_Mode_Interrupt = 0x00, + EXTI_Mode_Event = 0x04 +} EXTI_ModeType; + +#define IS_EXTI_MODE(MODE) (((MODE) == EXTI_Mode_Interrupt) || ((MODE) == EXTI_Mode_Event)) + +/** + * @brief EXTI Trigger enumeration + */ + +typedef enum +{ + EXTI_Trigger_Rising = 0x08, + EXTI_Trigger_Falling = 0x0C, + EXTI_Trigger_Rising_Falling = 0x10 +} EXTI_TriggerType; + +#define IS_EXTI_TRIGGER(TRIGGER) \ + (((TRIGGER) == EXTI_Trigger_Rising) || ((TRIGGER) == EXTI_Trigger_Falling) \ + || ((TRIGGER) == EXTI_Trigger_Rising_Falling)) +/** + * @brief EXTI Init Structure definition + */ + +typedef struct +{ + uint32_t EXTI_Line; /*!< Specifies the EXTI lines to be enabled or disabled. + This parameter can be any combination of @ref EXTI_Lines */ + + EXTI_ModeType EXTI_Mode; /*!< Specifies the mode for the EXTI lines. + This parameter can be a value of @ref EXTI_ModeType */ + + EXTI_TriggerType EXTI_Trigger; /*!< Specifies the trigger signal active edge for the EXTI lines. + This parameter can be a value of @ref EXTI_ModeType */ + + FunctionalState EXTI_LineCmd; /*!< Specifies the new state of the selected EXTI lines. + This parameter can be set either to ENABLE or DISABLE */ +} EXTI_InitType; + +/** + * @} + */ + +/** @addtogroup EXTI_Exported_Constants + * @{ + */ + +/** @addtogroup EXTI_Lines + * @{ + */ + +#define EXTI_LINE0 ((uint32_t)0x00001) /*!< External interrupt line 0 */ +#define EXTI_LINE1 ((uint32_t)0x00002) /*!< External interrupt line 1 */ +#define EXTI_LINE2 ((uint32_t)0x00004) /*!< External interrupt line 2 */ +#define EXTI_LINE3 ((uint32_t)0x00008) /*!< External interrupt line 3 */ +#define EXTI_LINE4 ((uint32_t)0x00010) /*!< External interrupt line 4 */ +#define EXTI_LINE5 ((uint32_t)0x00020) /*!< External interrupt line 5 */ +#define EXTI_LINE6 ((uint32_t)0x00040) /*!< External interrupt line 6 */ +#define EXTI_LINE7 ((uint32_t)0x00080) /*!< External interrupt line 7 */ +#define EXTI_LINE8 ((uint32_t)0x00100) /*!< External interrupt line 8 */ +#define EXTI_LINE9 ((uint32_t)0x00200) /*!< External interrupt line 9 */ +#define EXTI_LINE10 ((uint32_t)0x00400) /*!< External interrupt line 10 */ +#define EXTI_LINE11 ((uint32_t)0x00800) /*!< External interrupt line 11 */ +#define EXTI_LINE12 ((uint32_t)0x01000) /*!< External interrupt line 12 */ +#define EXTI_LINE13 ((uint32_t)0x02000) /*!< External interrupt line 13 */ +#define EXTI_LINE14 ((uint32_t)0x04000) /*!< External interrupt line 14 */ +#define EXTI_LINE15 ((uint32_t)0x08000) /*!< External interrupt line 15 */ +#define EXTI_LINE16 ((uint32_t)0x10000) /*!< External interrupt line 16 Connected to the PVD Output */ +#define EXTI_LINE17 ((uint32_t)0x20000) /*!< External interrupt line 17 Connected to the RTC Alarm event */ +#define EXTI_LINE18 ((uint32_t)0x40000) /*!< External interrupt line 18 Connected to the USB Device/USB OTG FS Wakeup from suspend event */ +#define EXTI_LINE19 ((uint32_t)0x80000) /*!< External interrupt line 19 Connected to the Ethernet Wakeup event */ +#define EXTI_LINE20 ((uint32_t)0x100000) /*!< External interrupt line 20 Connected to the RTC Wakeup event */ +#define EXTI_LINE21 ((uint32_t)0x200000) /*!< External interrupt line 21 Connected to the TSC event */ + +#define IS_EXTI_LINE(LINE) ((((LINE) & (uint32_t)0xFFC00000) == 0x00) && ((LINE) != (uint16_t)0x00)) +#define IS_GET_EXTI_LINE(LINE) \ + (((LINE) == EXTI_LINE0) || ((LINE) == EXTI_LINE1) || ((LINE) == EXTI_LINE2) || ((LINE) == EXTI_LINE3) \ + || ((LINE) == EXTI_LINE4) || ((LINE) == EXTI_LINE5) || ((LINE) == EXTI_LINE6) || ((LINE) == EXTI_LINE7) \ + || ((LINE) == EXTI_LINE8) || ((LINE) == EXTI_LINE9) || ((LINE) == EXTI_LINE10) || ((LINE) == EXTI_LINE11) \ + || ((LINE) == EXTI_LINE12) || ((LINE) == EXTI_LINE13) || ((LINE) == EXTI_LINE14) || ((LINE) == EXTI_LINE15) \ + || ((LINE) == EXTI_LINE16) || ((LINE) == EXTI_LINE17) || ((LINE) == EXTI_LINE18) || ((LINE) == EXTI_LINE19) \ + || ((LINE) == EXTI_LINE20) || ((LINE) == EXTI_LINE21)) + +/** + * @} + */ + +/** @addtogroup EXTI_TSSEL_Line + * @{ + */ + + +#define IS_EXTI_TSSEL_LINE(LINE) \ + (((LINE) == EXTI_TSSEL_LINE0) || ((LINE) == EXTI_TSSEL_LINE1) || ((LINE) == EXTI_TSSEL_LINE2) \ + || ((LINE) == EXTI_TSSEL_LINE3) || ((LINE) == EXTI_TSSEL_LINE4) || ((LINE) == EXTI_TSSEL_LINE5) \ + || ((LINE) == EXTI_TSSEL_LINE6) || ((LINE) == EXTI_TSSEL_LINE7) || ((LINE) == EXTI_TSSEL_LINE8) \ + || ((LINE) == EXTI_TSSEL_LINE9) || ((LINE) == EXTI_TSSEL_LINE10) || ((LINE) == EXTI_TSSEL_LINE11) \ + || ((LINE) == EXTI_TSSEL_LINE12) || ((LINE) == EXTI_TSSEL_LINE13) || ((LINE) == EXTI_TSSEL_LINE14) \ + || ((LINE) == EXTI_TSSEL_LINE15)) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup EXTI_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup EXTI_Exported_Functions + * @{ + */ + +void EXTI_DeInit(void); +void EXTI_InitPeripheral(EXTI_InitType* EXTI_InitStruct); +void EXTI_InitStruct(EXTI_InitType* EXTI_InitStruct); +void EXTI_TriggerSWInt(uint32_t EXTI_Line); +FlagStatus EXTI_GetStatusFlag(uint32_t EXTI_Line); +void EXTI_ClrStatusFlag(uint32_t EXTI_Line); +INTStatus EXTI_GetITStatus(uint32_t EXTI_Line); +void EXTI_ClrITPendBit(uint32_t EXTI_Line); +void EXTI_RTCTimeStampSel(uint32_t EXTI_TSSEL_Line); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G4FR_EXTI_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_flash.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_flash.h new file mode 100644 index 0000000000..5433dc10bb --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_flash.h @@ -0,0 +1,375 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_flash.h + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_FLASH_H__ +#define __N32G4FR_FLASH_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup FLASH + * @{ + */ + +/** @addtogroup FLASH_Exported_Types + * @{ + */ + +/** + * @brief FLASH Status + */ + +typedef enum +{ + FLASH_BUSY = 1, + FLASH_RESERVED, + FLASH_ERR_PG, + FLASH_ERR_PV, + FLASH_ERR_WRP, + FLASH_COMPL, + FLASH_ERR_EV, + FLASH_ERR_RDP2, + FLASH_ERR_ADD, + FLASH_TIMEOUT +} FLASH_STS; + +typedef enum +{ + FLASH_SMP1 = 0, + FLASH_SMP2 +} FLASH_SMPSEL; + +/** + * @} + */ + +/** @addtogroup FLASH_Exported_Constants + * @{ + */ + +/** @addtogroup Flash_Latency + * @{ + */ + +#define FLASH_LATENCY_0 ((uint32_t)0x00000000) /*!< FLASH Zero Latency cycle */ +#define FLASH_LATENCY_1 ((uint32_t)0x00000001) /*!< FLASH One Latency cycle */ +#define FLASH_LATENCY_2 ((uint32_t)0x00000002) /*!< FLASH Two Latency cycles */ +#define FLASH_LATENCY_3 ((uint32_t)0x00000003) /*!< FLASH Three Latency cycles */ +#define FLASH_LATENCY_4 ((uint32_t)0x00000004) /*!< FLASH Four Latency cycles */ +#define IS_FLASH_LATENCY(LATENCY) \ + (((LATENCY) == FLASH_LATENCY_0) || ((LATENCY) == FLASH_LATENCY_1) || ((LATENCY) == FLASH_LATENCY_2) \ + || ((LATENCY) == FLASH_LATENCY_3) || ((LATENCY) == FLASH_LATENCY_4)) +/** + * @} + */ + +/** @addtogroup Prefetch_Buffer_Enable_Disable + * @{ + */ + +#define FLASH_PrefetchBuf_EN ((uint32_t)0x00000010) /*!< FLASH Prefetch Buffer Enable */ +#define FLASH_PrefetchBuf_DIS ((uint32_t)0x00000000) /*!< FLASH Prefetch Buffer Disable */ +#define IS_FLASH_PREFETCHBUF_STATE(STATE) (((STATE) == FLASH_PrefetchBuf_EN) || ((STATE) == FLASH_PrefetchBuf_DIS)) +/** + * @} + */ + +/** @addtogroup iCache_Enable_Disable + * @{ + */ + +#define FLASH_iCache_EN ((uint32_t)0x00000080) /*!< FLASH iCache Enable */ +#define FLASH_iCache_DIS ((uint32_t)0x00000000) /*!< FLASH iCache Disable */ +#define IS_FLASH_ICACHE_STATE(STATE) (((STATE) == FLASH_iCache_EN) || ((STATE) == FLASH_iCache_DIS)) +/** + * @} + */ + +/** @addtogroup SMPSEL_SMP1_SMP2 + * @{ + */ + +#define FLASH_SMPSEL_SMP1 ((uint32_t)0x00000000) /*!< FLASH SMPSEL SMP1 */ +#define FLASH_SMPSEL_SMP2 ((uint32_t)0x00000100) /*!< FLASH SMPSEL SMP2 */ +#define IS_FLASH_SMPSEL_STATE(STATE) (((STATE) == FLASH_SMPSEL_SMP1) || ((STATE) == FLASH_SMPSEL_SMP2)) +/** + * @} + */ + +/* Values to be used with N32G4FR devices */ +#define FLASH_WRP_Pages0to1 \ + ((uint32_t)0x00000001) /*!< N32G4FR devices: \ + Write protection of page 0 to 1 */ +#define FLASH_WRP_Pages2to3 \ + ((uint32_t)0x00000002) /*!< N32G4FR devices: \ + Write protection of page 2 to 3 */ +#define FLASH_WRP_Pages4to5 \ + ((uint32_t)0x00000004) /*!< N32G4FR devices: \ + Write protection of page 4 to 5 */ +#define FLASH_WRP_Pages6to7 \ + ((uint32_t)0x00000008) /*!< N32G4FR devices: \ + Write protection of page 6 to 7 */ +#define FLASH_WRP_Pages8to9 \ + ((uint32_t)0x00000010) /*!< N32G4FR devices: \ + Write protection of page 8 to 9 */ +#define FLASH_WRP_Pages10to11 \ + ((uint32_t)0x00000020) /*!< N32G4FR devices: \ + Write protection of page 10 to 11 */ +#define FLASH_WRP_Pages12to13 \ + ((uint32_t)0x00000040) /*!< N32G4FR devices: \ + Write protection of page 12 to 13 */ +#define FLASH_WRP_Pages14to15 \ + ((uint32_t)0x00000080) /*!< N32G4FR devices: \ + Write protection of page 14 to 15 */ +#define FLASH_WRP_Pages16to17 \ + ((uint32_t)0x00000100) /*!< N32G4FR devices: \ + Write protection of page 16 to 17 */ +#define FLASH_WRP_Pages18to19 \ + ((uint32_t)0x00000200) /*!< N32G4FR devices: \ + Write protection of page 18 to 19 */ +#define FLASH_WRP_Pages20to21 \ + ((uint32_t)0x00000400) /*!< N32G4FR devices: \ + Write protection of page 20 to 21 */ +#define FLASH_WRP_Pages22to23 \ + ((uint32_t)0x00000800) /*!< N32G4FR devices: \ + Write protection of page 22 to 23 */ +#define FLASH_WRP_Pages24to25 \ + ((uint32_t)0x00001000) /*!< N32G4FR devices: \ + Write protection of page 24 to 25 */ +#define FLASH_WRP_Pages26to27 \ + ((uint32_t)0x00002000) /*!< N32G4FR devices: \ + Write protection of page 26 to 27 */ +#define FLASH_WRP_Pages28to29 \ + ((uint32_t)0x00004000) /*!< N32G4FR devices: \ + Write protection of page 28 to 29 */ +#define FLASH_WRP_Pages30to31 \ + ((uint32_t)0x00008000) /*!< N32G4FR devices: \ + Write protection of page 30 to 31 */ +#define FLASH_WRP_Pages32to33 \ + ((uint32_t)0x00010000) /*!< N32G4FR devices: \ + Write protection of page 32 to 33 */ +#define FLASH_WRP_Pages34to35 \ + ((uint32_t)0x00020000) /*!< N32G4FR devices: \ + Write protection of page 34 to 35 */ +#define FLASH_WRP_Pages36to37 \ + ((uint32_t)0x00040000) /*!< N32G4FR devices: \ + Write protection of page 36 to 37 */ +#define FLASH_WRP_Pages38to39 \ + ((uint32_t)0x00080000) /*!< N32G4FR devices: \ + Write protection of page 38 to 39 */ +#define FLASH_WRP_Pages40to41 \ + ((uint32_t)0x00100000) /*!< N32G4FR devices: \ + Write protection of page 40 to 41 */ +#define FLASH_WRP_Pages42to43 \ + ((uint32_t)0x00200000) /*!< N32G4FR devices: \ + Write protection of page 42 to 43 */ +#define FLASH_WRP_Pages44to45 \ + ((uint32_t)0x00400000) /*!< N32G4FR devices: \ + Write protection of page 44 to 45 */ +#define FLASH_WRP_Pages46to47 \ + ((uint32_t)0x00800000) /*!< N32G4FR devices: \ + Write protection of page 46 to 47 */ +#define FLASH_WRP_Pages48to49 \ + ((uint32_t)0x01000000) /*!< N32G4FR devices: \ + Write protection of page 48 to 49 */ +#define FLASH_WRP_Pages50to51 \ + ((uint32_t)0x02000000) /*!< N32G4FR devices: \ + Write protection of page 50 to 51 */ +#define FLASH_WRP_Pages52to53 \ + ((uint32_t)0x04000000) /*!< N32G4FR devices: \ + Write protection of page 52 to 53 */ +#define FLASH_WRP_Pages54to55 \ + ((uint32_t)0x08000000) /*!< N32G4FR devices: \ + Write protection of page 54 to 55 */ +#define FLASH_WRP_Pages56to57 \ + ((uint32_t)0x10000000) /*!< N32G4FR devices: \ + Write protection of page 56 to 57 */ +#define FLASH_WRP_Pages58to59 \ + ((uint32_t)0x20000000) /*!< N32G4FR devices: \ + Write protection of page 58 to 59 */ +#define FLASH_WRP_Pages60to61 \ + ((uint32_t)0x40000000) /*!< N32G4FR devices: \ + Write protection of page 60 to 61 */ +#define FLASH_WRP_Pages62to127 \ + ((uint32_t)0x80000000) /*!< N32G4FR - 256KB devices: Write protection of page 62 to 127 */ +#define FLASH_WRP_Pages62to255 \ + ((uint32_t)0x80000000) /*!< N32G4FR - 512KB devices: Write protection of page 62 to 255 */ + +#define FLASH_WRP_AllPages ((uint32_t)0xFFFFFFFF) /*!< Write protection of all Pages */ + +#define IS_FLASH_WRP_PAGE(PAGE) (((PAGE) != 0x00000000)) + +#define IS_FLASH_ADDRESS(ADDRESS) (((ADDRESS) >= 0x08000000) && ((ADDRESS) < 0x0807FFFF)) + +#define IS_OB_DATA_ADDRESS(ADDRESS) ((ADDRESS) == 0x1FFFF804) + +/** + * @} + */ + +/** @addtogroup Option_Bytes_IWatchdog + * @{ + */ + +#define OB_IWDG_SW ((uint16_t)0x0001) /*!< Software IWDG selected */ +#define OB_IWDG_HW ((uint16_t)0x0000) /*!< Hardware IWDG selected */ +#define IS_OB_IWDG_SOURCE(SOURCE) (((SOURCE) == OB_IWDG_SW) || ((SOURCE) == OB_IWDG_HW)) + +/** + * @} + */ + +/** @addtogroup Option_Bytes_nRST_STOP + * @{ + */ + +#define OB_STOP0_NORST ((uint16_t)0x0002) /*!< No reset generated when entering in STOP */ +#define OB_STOP0_RST ((uint16_t)0x0000) /*!< Reset generated when entering in STOP */ +#define IS_OB_STOP0_SOURCE(SOURCE) (((SOURCE) == OB_STOP0_NORST) || ((SOURCE) == OB_STOP0_RST)) + +/** + * @} + */ + +/** @addtogroup Option_Bytes_nRST_STDBY + * @{ + */ + +#define OB_STDBY_NORST ((uint16_t)0x0004) /*!< No reset generated when entering in STANDBY */ +#define OB_STDBY_RST ((uint16_t)0x0000) /*!< Reset generated when entering in STANDBY */ +#define IS_OB_STDBY_SOURCE(SOURCE) (((SOURCE) == OB_STDBY_NORST) || ((SOURCE) == OB_STDBY_RST)) + +/** + * @} + */ +/** @addtogroup FLASH_Interrupts + * @{ + */ +#define FLASH_INT_ERRIE ((uint32_t)0x00000400) /*!< PGERR WRPERR ERROR error interrupt source */ +#define FLASH_INT_FERR ((uint32_t)0x00000800) /*!< EVERR PVERR interrupt source */ +#define FLASH_INT_EOP ((uint32_t)0x00001000) /*!< End of FLASH Operation Interrupt source */ + +#define IS_FLASH_INT(IT) ((((IT) & (uint32_t)0xFFFFE3FF) == 0x00000000) && (((IT) != 0x00000000))) + +/** + * @} + */ + +/** @addtogroup FLASH_Flags + * @{ + */ +#define FLASH_FLAG_BUSY ((uint32_t)0x00000001) /*!< FLASH Busy flag */ +#define FLASH_FLAG_PGERR ((uint32_t)0x00000004) /*!< FLASH Program error flag */ +#define FLASH_FLAG_PVERR ((uint32_t)0x00000008) /*!< FLASH Program Verify ERROR flag after program */ +#define FLASH_FLAG_WRPERR ((uint32_t)0x00000010) /*!< FLASH Write protected error flag */ +#define FLASH_FLAG_EOP ((uint32_t)0x00000020) /*!< FLASH End of Operation flag */ +#define FLASH_FLAG_EVERR ((uint32_t)0x00000040) /*!< FLASH Erase Verify ERROR flag after page erase */ +#define FLASH_FLAG_OBERR ((uint32_t)0x00000001) /*!< FLASH Option Byte error flag */ + +#define IS_FLASH_CLEAR_FLAG(FLAG) ((((FLAG) & 0xFFFFFF83) == 0x00) && (FLAG != 0x00)) + +#define IS_FLASH_GET_FLAG(FLAG) \ + (((FLAG) == FLASH_FLAG_BUSY) || ((FLAG) == FLASH_FLAG_PGERR) || ((FLAG) == FLASH_FLAG_PVERR) \ + || ((FLAG) == FLASH_FLAG_WRPERR) || ((FLAG) == FLASH_FLAG_EOP) || ((FLAG) == FLASH_FLAG_EVERR) \ + || ((FLAG) == FLASH_FLAG_OBERR)) + +/** + * @} + */ + +/** @addtogroup FLASH_STS_CLRFLAG + * @{ + */ +#define FLASH_STS_CLRFLAG (FLASH_FLAG_PGERR | FLASH_FLAG_PVERR | FLASH_FLAG_WRPERR | FLASH_FLAG_EOP |FLASH_FLAG_EVERR) + +/** + * @} + */ + +/** @addtogroup FLASH_Exported_Functions + * @{ + */ + +/*------------ Functions used for N32G4FR devices -----*/ +void FLASH_SetLatency(uint32_t FLASH_Latency); +void FLASH_PrefetchBufSet(uint32_t FLASH_PrefetchBuf); +void FLASH_iCacheRST(void); +void FLASH_iCacheCmd(uint32_t FLASH_iCache); +void FLASH_Unlock(void); +void FLASH_Lock(void); +FLASH_STS FLASH_EraseOnePage(uint32_t Page_Address); +FLASH_STS FLASH_MassErase(void); +FLASH_STS FLASH_EraseOB(void); +FLASH_STS FLASH_ProgramWord(uint32_t Address, uint32_t Data); +FLASH_STS FLASH_ProgramOBData(uint32_t Address, uint32_t Data); +FLASH_STS FLASH_EnWriteProtection(uint32_t FLASH_Pages); +FLASH_STS FLASH_ReadOutProtectionL1(FunctionalState Cmd); +FLASH_STS FLASH_ReadOutProtectionL2_ENABLE(void); +FLASH_STS FLASH_ConfigUserOB(uint16_t OB_IWDG, uint16_t OB_STOP, uint16_t OB_STDBY); +uint32_t FLASH_GetUserOB(void); +uint32_t FLASH_GetWriteProtectionOB(void); +FlagStatus FLASH_GetReadOutProtectionSTS(void); +FlagStatus FLASH_GetReadOutProtectionL2STS(void); +FlagStatus FLASH_GetPrefetchBufSTS(void); +void FLASH_SetSMPSELStatus(uint32_t FLASH_smpsel); +FLASH_SMPSEL FLASH_GetSMPSELStatus(void); +void FLASH_INTConfig(uint32_t FLASH_INT, FunctionalState Cmd); +FlagStatus FLASH_GetFlagSTS(uint32_t FLASH_FLAG); +void FLASH_ClearFlag(uint32_t FLASH_FLAG); +FLASH_STS FLASH_GetSTS(void); +FLASH_STS FLASH_WaitForLastOpt(uint32_t Timeout); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G4FR_FLASH_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_gpio.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_gpio.h new file mode 100644 index 0000000000..3ab1157aa4 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_gpio.h @@ -0,0 +1,459 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_gpio.h + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_GPIO_H__ +#define __N32G4FR_GPIO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup GPIO + * @{ + */ + +/** @addtogroup GPIO_Exported_Types + * @{ + */ + +#define IS_GPIO_ALL_PERIPH(PERIPH) \ + (((PERIPH) == GPIOA) || ((PERIPH) == GPIOB) || ((PERIPH) == GPIOC) || ((PERIPH) == GPIOD) || ((PERIPH) == GPIOE)) + +/** + * @brief Output Maximum frequency selection + */ + +typedef enum +{ + GPIO_INPUT = 0, + GPIO_Speed_2MHz = 1, + GPIO_Speed_10MHz, + GPIO_Speed_50MHz +} GPIO_SpeedType; +#define IS_GPIO_SPEED(SPEED) \ + (((SPEED) == GPIO_INPUT) || ((SPEED) == GPIO_Speed_10MHz) || ((SPEED) == GPIO_Speed_2MHz) \ + || ((SPEED) == GPIO_Speed_50MHz)) + +/** + * @brief Configuration Mode enumeration + */ + +typedef enum +{ + GPIO_Mode_AIN = 0x0, + GPIO_Mode_IN_FLOATING = 0x04, + GPIO_Mode_IPD = 0x28, + GPIO_Mode_IPU = 0x48, + GPIO_Mode_Out_OD = 0x14, + GPIO_Mode_Out_PP = 0x10, + GPIO_Mode_AF_OD = 0x1C, + GPIO_Mode_AF_PP = 0x18 +} GPIO_ModeType; + +#define IS_GPIO_MODE(MODE) \ + (((MODE) == GPIO_Mode_AIN) || ((MODE) == GPIO_Mode_IN_FLOATING) || ((MODE) == GPIO_Mode_IPD) \ + || ((MODE) == GPIO_Mode_IPU) || ((MODE) == GPIO_Mode_Out_OD) || ((MODE) == GPIO_Mode_Out_PP) \ + || ((MODE) == GPIO_Mode_AF_OD) || ((MODE) == GPIO_Mode_AF_PP)) + +/** + * @brief GPIO Init structure definition + */ + +typedef struct +{ + uint16_t Pin; /*!< Specifies the GPIO pins to be configured. + This parameter can be any value of @ref GPIO_pins_define */ + + GPIO_SpeedType GPIO_Speed; /*!< Specifies the speed for the selected pins. + This parameter can be a value of @ref GPIO_SpeedType */ + + GPIO_ModeType GPIO_Mode; /*!< Specifies the operating mode for the selected pins. + This parameter can be a value of @ref GPIO_ModeType */ +} GPIO_InitType; + +/** + * @brief Bit_SET and Bit_RESET enumeration + */ + +typedef enum +{ + Bit_RESET = 0, + Bit_SET +} Bit_OperateType; + +#define IS_GPIO_BIT_OPERATE(OPERATE) (((OPERATE) == Bit_RESET) || ((OPERATE) == Bit_SET)) + +/** + * @} + */ + +/** @addtogroup GPIO_Exported_Constants + * @{ + */ + +/** @addtogroup GPIO_pins_define + * @{ + */ + +#define GPIO_PIN_0 ((uint16_t)0x0001) /*!< Pin 0 selected */ +#define GPIO_PIN_1 ((uint16_t)0x0002) /*!< Pin 1 selected */ +#define GPIO_PIN_2 ((uint16_t)0x0004) /*!< Pin 2 selected */ +#define GPIO_PIN_3 ((uint16_t)0x0008) /*!< Pin 3 selected */ +#define GPIO_PIN_4 ((uint16_t)0x0010) /*!< Pin 4 selected */ +#define GPIO_PIN_5 ((uint16_t)0x0020) /*!< Pin 5 selected */ +#define GPIO_PIN_6 ((uint16_t)0x0040) /*!< Pin 6 selected */ +#define GPIO_PIN_7 ((uint16_t)0x0080) /*!< Pin 7 selected */ +#define GPIO_PIN_8 ((uint16_t)0x0100) /*!< Pin 8 selected */ +#define GPIO_PIN_9 ((uint16_t)0x0200) /*!< Pin 9 selected */ +#define GPIO_PIN_10 ((uint16_t)0x0400) /*!< Pin 10 selected */ +#define GPIO_PIN_11 ((uint16_t)0x0800) /*!< Pin 11 selected */ +#define GPIO_PIN_12 ((uint16_t)0x1000) /*!< Pin 12 selected */ +#define GPIO_PIN_13 ((uint16_t)0x2000) /*!< Pin 13 selected */ +#define GPIO_PIN_14 ((uint16_t)0x4000) /*!< Pin 14 selected */ +#define GPIO_PIN_15 ((uint16_t)0x8000) /*!< Pin 15 selected */ +#define GPIO_PIN_ALL ((uint16_t)0xFFFF) /*!< All pins selected */ + +#define IS_GPIO_PIN(PIN) ((((PIN) & (uint16_t)0x00) == 0x00) && ((PIN) != (uint16_t)0x00)) + +#define IS_GET_GPIO_PIN(PIN) \ + (((PIN) == GPIO_PIN_0) || ((PIN) == GPIO_PIN_1) || ((PIN) == GPIO_PIN_2) || ((PIN) == GPIO_PIN_3) \ + || ((PIN) == GPIO_PIN_4) || ((PIN) == GPIO_PIN_5) || ((PIN) == GPIO_PIN_6) || ((PIN) == GPIO_PIN_7) \ + || ((PIN) == GPIO_PIN_8) || ((PIN) == GPIO_PIN_9) || ((PIN) == GPIO_PIN_10) || ((PIN) == GPIO_PIN_11) \ + || ((PIN) == GPIO_PIN_12) || ((PIN) == GPIO_PIN_13) || ((PIN) == GPIO_PIN_14) || ((PIN) == GPIO_PIN_15)) + +/** + * @} + */ + +/** @addtogroup GPIO_Remap_define + * @{ + */ + +#define GPIO_RMP_SPI1 ((uint32_t)0x00000001) /*!< SPI1 Alternate Function mapping */ +#define GPIO_RMP_I2C1 ((uint32_t)0x00000002) /*!< I2C1 Alternate Function mapping */ +#define GPIO_RMP_USART1 ((uint32_t)0x00000004) /*!< USART1 Alternate Function mapping */ +#define GPIO_RMP_USART2 ((uint32_t)0x00000008) /*!< USART2 Alternate Function mapping */ +#define GPIO_PART_RMP_USART3 ((uint32_t)0x00140010) /*!< USART3 Partial Alternate Function mapping */ +#define GPIO_ALL_RMP_USART3 ((uint32_t)0x00140030) /*!< USART3 Full Alternate Function mapping */ +#define GPIO_PART1_RMP_TIM1 ((uint32_t)0x00160040) /*!< TIM1 Partial Alternate Function mapping */ +#define GPIO_PART2_RMP_TIM1 ((uint32_t)0x00160080) /*!< TIM1 Partial Alternate Function mapping */ +#define GPIO_ALL_RMP_TIM1 ((uint32_t)0x001600C0) /*!< TIM1 Full Alternate Function mapping */ +#define GPIO_PartialRemap1_TIM2 ((uint32_t)0x00180100) /*!< TIM2 Partial1 Alternate Function mapping */ +#define GPIO_PART2_RMP_TIM2 ((uint32_t)0x00180200) /*!< TIM2 Partial2 Alternate Function mapping */ +#define GPIO_ALL_RMP_TIM2 ((uint32_t)0x00180300) /*!< TIM2 Full Alternate Function mapping */ +#define GPIO_PART1_RMP_TIM3 ((uint32_t)0x001A0800) /*!< TIM3 Partial Alternate Function mapping */ +#define GPIO_ALL_RMP_TIM3 ((uint32_t)0x001A0C00) /*!< TIM3 Full Alternate Function mapping */ +#define GPIO_RMP_TIM4 ((uint32_t)0x00001000) /*!< TIM4 Alternate Function mapping */ +#define GPIO_RMP1_CAN1 ((uint32_t)0x001D2000) /*!< CAN1 Alternate Function mapping */ +#define GPIO_RMP2_CAN1 ((uint32_t)0x001D4000) /*!< CAN1 Alternate Function mapping */ +#define GPIO_RMP3_CAN1 ((uint32_t)0x001D6000) /*!< CAN1 Alternate Function mapping */ +#define GPIO_RMP_PD01 ((uint32_t)0x00008000) /*!< PD01 Alternate Function mapping */ +#define GPIO_RMP_TIM5CH4 ((uint32_t)0x00200001) /*!< LSI connected to TIM5 Channel4 input capture for calibration */ +#define GPIO_RMP_ADC1_ETRI ((uint32_t)0x00200002) /*!< ADC1 External Trigger Injected Conversion remapping */ +#define GPIO_RMP_ADC1_ETRR ((uint32_t)0x00200004) /*!< ADC1 External Trigger Regular Conversion remapping */ +#define GPIO_RMP_ADC2_ETRI ((uint32_t)0x00200008) /*!< ADC2 External Trigger Injected Conversion remapping */ +#define GPIO_RMP_ADC2_ETRR ((uint32_t)0x00200010) /*!< ADC2 External Trigger Regular Conversion remapping */ +#define GPIO_RMP_MII_RMII_SEL ((uint32_t)0x00200080) /*!< MII_RMII_SEL remapping */ +#define GPIO_RMP_SW_JTAG_NO_NJTRST ((uint32_t)0x00300100) /*!< Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST */ +#define GPIO_RMP_SW_JTAG_SW_ENABLE ((uint32_t)0x00300200) /*!< JTAG-DP Disabled and SW-DP Enabled */ +#define GPIO_RMP_SW_JTAG_DISABLE ((uint32_t)0x00300400) /*!< Full SWJ Disabled (JTAG-DP + SW-DP) */ + +/* AFIO_RMP_CFG3 */ +#define GPIO_RMP_SDIO ((uint32_t)0x40000001) /*!< SDIO Alternate Function mapping */ +#define GPIO_RMP1_CAN2 ((uint32_t)0x40110002) /*!< CAN2 Alternate Function mapping */ +#define GPIO_RMP3_CAN2 ((uint32_t)0x40110006) /*!< CAN2 Alternate Function mapping */ +#define GPIO_RMP1_QSPI ((uint32_t)0x40140020) /*!< QSPI Alternate Function mapping */ +#define GPIO_RMP3_QSPI ((uint32_t)0x40140030) /*!< QSPI Alternate Function mapping */ +#define GPIO_RMP1_I2C2 ((uint32_t)0x40160040) /*!< I2C2 Alternate Function mapping */ +#define GPIO_RMP3_I2C2 ((uint32_t)0x401600C0) /*!< I2C2 Alternate Function mapping */ +#define GPIO_RMP2_I2C3 ((uint32_t)0x40180200) /*!< I2C3 Alternate Function mapping */ +#define GPIO_RMP3_I2C3 ((uint32_t)0x40180300) /*!< I2C3 Alternate Function mapping */ +#define GPIO_RMP1_I2C4 ((uint32_t)0x401A0400) /*!< I2C4 Alternate Function mapping */ +#define GPIO_RMP3_I2C4 ((uint32_t)0x401A0C00) /*!< I2C4 Alternate Function mapping */ +#define GPIO_RMP1_SPI2 ((uint32_t)0x401C1000) /*!< SPI2 Alternate Function mapping */ +#define GPIO_RMP2_SPI2 ((uint32_t)0x401C3000) /*!< SPI2 Alternate Function mapping */ +#define GPIO_RMP1_SPI3 ((uint32_t)0x401E4000) /*!< SPI3 Alternate Function mapping */ +#define GPIO_RMP2_SPI3 ((uint32_t)0x401E8000) /*!< SPI3 Alternate Function mapping */ +#define GPIO_RMP3_SPI3 ((uint32_t)0x401EC000) /*!< SPI3 Alternate Function mapping */ +#define GPIO_RMP1_ETH ((uint32_t)0x40300001) /*!< ETH Alternate Function mapping */ +#define GPIO_RMP2_ETH ((uint32_t)0x40300002) /*!< ETH Alternate Function mapping */ +#define GPIO_RMP3_ETH ((uint32_t)0x40300003) /*!< ETH Alternate Function mapping */ +#define GPIO_RMP1_SPI1 ((uint32_t)0x41200000) /*!< SPI1 Alternate Function mapping */ +#define GPIO_RMP2_SPI1 ((uint32_t)0x41200004) /*!< SPI1 Alternate Function mapping */ +#define GPIO_RMP3_SPI1 ((uint32_t)0x43200004) /*!< SPI1 Alternate Function mapping */ +#define GPIO_RMP1_USART2 ((uint32_t)0x44200000) /*!< USART2 Alternate Function mapping */ +#define GPIO_RMP2_USART2 ((uint32_t)0x44200008) /*!< USART2 Alternate Function mapping */ +#define GPIO_RMP3_USART2 ((uint32_t)0x46200008) /*!< USART2 Alternate Function mapping */ +#define GPIO_RMP1_UART4 ((uint32_t)0x40340010) /*!< UART4 Alternate Function mapping */ +#define GPIO_RMP2_UART4 ((uint32_t)0x40340020) /*!< UART4 Alternate Function mapping */ +#define GPIO_RMP3_UART4 ((uint32_t)0x40340030) /*!< UART4 Alternate Function mapping */ +#define GPIO_RMP1_UART5 ((uint32_t)0x40360040) /*!< UART5 Alternate Function mapping */ +#define GPIO_RMP2_UART5 ((uint32_t)0x40360080) /*!< UART5 Alternate Function mapping */ +#define GPIO_RMP3_UART5 ((uint32_t)0x403600C0) /*!< UART5 Alternate Function mapping */ +#define GPIO_RMP2_UART6 ((uint32_t)0x40380200) /*!< UART6 Alternate Function mapping */ +#define GPIO_RMP3_UART6 ((uint32_t)0x40380300) /*!< UART6 Alternate Function mapping */ +#define GPIO_RMP1_UART7 ((uint32_t)0x403A0400) /*!< UART7 Alternate Function mapping */ +#define GPIO_RMP3_UART7 ((uint32_t)0x403A0C00) /*!< UART7 Alternate Function mapping */ +#define GPIO_RMP1_TIM8 ((uint32_t)0x403E4000) /*!< TIM8 Alternate Function mapping */ +#define GPIO_RMP3_TIM8 ((uint32_t)0x403EC000) /*!< TIM8 Alternate Function mapping */ + +/* AFIO_RMP_CFG4 */ +#define GPIO_RMP1_COMP1 ((uint32_t)0x20100001) /*!< COMP1 Alternate Function mapping */ +#define GPIO_RMP2_COMP1 ((uint32_t)0x20100002) /*!< COMP1 Alternate Function mapping */ +#define GPIO_RMP3_COMP1 ((uint32_t)0x20100003) /*!< COMP1 Alternate Function mapping */ +#define GPIO_RMP1_COMP2 ((uint32_t)0x20120004) /*!< COMP2 Alternate Function mapping */ +#define GPIO_RMP2_COMP2 ((uint32_t)0x20120008) /*!< COMP2 Alternate Function mapping */ +#define GPIO_RMP3_COMP2 ((uint32_t)0x2012000C) /*!< COMP2 Alternate Function mapping */ +#define GPIO_RMP1_COMP3 ((uint32_t)0x20140010) /*!< COMP3 Alternate Function mapping */ +#define GPIO_RMP3_COMP3 ((uint32_t)0x20140030) /*!< COMP3 Alternate Function mapping */ +#define GPIO_RMP1_COMP4 ((uint32_t)0x20160040) /*!< COMP4 Alternate Function mapping */ +#define GPIO_RMP3_COMP4 ((uint32_t)0x201600C0) /*!< COMP4 Alternate Function mapping */ +#define GPIO_RMP1_COMP5 ((uint32_t)0x20180100) /*!< COMP5 Alternate Function mapping */ +#define GPIO_RMP2_COMP5 ((uint32_t)0x20180200) /*!< COMP5 Alternate Function mapping */ +#define GPIO_RMP3_COMP5 ((uint32_t)0x20180300) /*!< COMP5 Alternate Function mapping */ +#define GPIO_RMP1_COMP6 ((uint32_t)0x201A0400) /*!< COMP6 Alternate Function mapping */ +#define GPIO_RMP3_COMP6 ((uint32_t)0x201A0C00) /*!< COMP6 Alternate Function mapping */ +#define GPIO_RMP_COMP7 ((uint32_t)0x20001000) /*!< COMP7 Alternate Function mapping */ +#define GPIO_RMP_ADC3_ETRI ((uint32_t)0x20004000) /*!< ADC3_ETRGINJ Alternate Function mapping */ +#define GPIO_RMP_ADC3_ETRR ((uint32_t)0x20008000) /*!< ADC3_ETRGREG Alternate Function mapping */ +#define GPIO_RMP_ADC4_ETRI ((uint32_t)0x20200001) /*!< ADC4_ETRGINJ Alternate Function mapping */ +#define GPIO_RMP_ADC4_ETRR ((uint32_t)0x20200002) /*!< ADC4_ETRGREG Alternate Function mapping */ +#define GPIO_RMP_TSC_OUT_CTRL ((uint32_t)0x20200004) /*!< TSC_OUT_CTRL Alternate Function mapping */ +#define GPIO_RMP_QSPI_XIP_EN ((uint32_t)0x20200008) /*!< QSPI_XIP_EN Alternate Function mapping */ +#define GPIO_RMP1_DVP ((uint32_t)0x20340010) /*!< DVP Alternate Function mapping */ +#define GPIO_RMP3_DVP ((uint32_t)0x20340030) /*!< DVP Alternate Function mapping */ +#define GPIO_Remap_SPI1_NSS ((uint32_t)0x20200040) /*!< SPI1 NSS Alternate Function mapping */ +#define GPIO_Remap_SPI2_NSS ((uint32_t)0x20200080) /*!< SPI2 NSS Alternate Function mapping */ +#define GPIO_Remap_SPI3_NSS ((uint32_t)0x20200100) /*!< SPI3 NSS Alternate Function mapping */ +#define GPIO_Remap_QSPI_MISO ((uint32_t)0x20200200) /*!< QSPI MISO Alternate Function mapping */ + +/* AFIO_RMP_CFG5 */ +#define GPIO_Remap_DET_EN_EGB4 ((uint32_t)0x10200080) /*!< EGB4 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_EGB3 ((uint32_t)0x10200040) /*!< EGB4 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_EGB2 ((uint32_t)0x10200020) /*!< EGB4 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_EGB1 ((uint32_t)0x10200010) /*!< EGB4 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_EGBN4 ((uint32_t)0x10200008) /*!< EGBN4 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_EGBN3 ((uint32_t)0x10200004) /*!< EGBN3 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_EGBN2 ((uint32_t)0x10200002) /*!< EGBN2 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_EGBN1 ((uint32_t)0x10200001) /*!< EGBN1 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_ECLAMP4 ((uint32_t)0x10008000) /*!< ECLAMP4 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_ECLAMP3 ((uint32_t)0x10004000) /*!< ECLAMP3 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_ECLAMP2 ((uint32_t)0x10002000) /*!< ECLAMP2 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_ECLAMP1 ((uint32_t)0x10001000) /*!< ECLAMP1 Detect Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_EGB4 ((uint32_t)0x10000800) /*!< EGB4 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_EGB3 ((uint32_t)0x10000400) /*!< EGB3 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_EGB2 ((uint32_t)0x10000200) /*!< EGB2 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_EGB1 ((uint32_t)0x10000100) /*!< EGB1 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_EGBN4 ((uint32_t)0x10000080) /*!< EGBN4 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_EGBN3 ((uint32_t)0x10000040) /*!< EGBN3 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_EGBN2 ((uint32_t)0x10000020) /*!< EGBN2 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_EGBN1 ((uint32_t)0x10000010) /*!< EGBN1 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_ECLAMP4 ((uint32_t)0x10000008) /*!< ECLAMP4 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_ECLAMP3 ((uint32_t)0x10000004) /*!< ECLAMP3 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_ECLAMP2 ((uint32_t)0x10000002) /*!< ECLAMP2 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_ECLAMP1 ((uint32_t)0x10000001) /*!< ECLAMP1 Reset Alternate Function mapping*/ + +#define IS_GPIO_REMAP(REMAP) \ + (((REMAP) == GPIO_RMP_SPI1) || ((REMAP) == GPIO_RMP_I2C1) || ((REMAP) == GPIO_RMP_USART1) \ + || ((REMAP) == GPIO_RMP_USART2) || ((REMAP) == GPIO_PART_RMP_USART3) || ((REMAP) == GPIO_ALL_RMP_USART3) \ + || ((REMAP) == GPIO_PART1_RMP_TIM1) || ((REMAP) == GPIO_ALL_RMP_TIM1) || ((REMAP) == GPIO_PartialRemap1_TIM2) \ + || ((REMAP) == GPIO_PART2_RMP_TIM2) || ((REMAP) == GPIO_ALL_RMP_TIM2) || ((REMAP) == GPIO_PART1_RMP_TIM3) \ + || ((REMAP) == GPIO_ALL_RMP_TIM3) || ((REMAP) == GPIO_RMP_TIM4) || ((REMAP) == GPIO_RMP1_CAN1) \ + || ((REMAP) == GPIO_RMP2_CAN1) || ((REMAP) == GPIO_RMP3_CAN1) || ((REMAP) == GPIO_RMP_PD01) || ((REMAP) == GPIO_RMP_TIM5CH4) \ + || ((REMAP) == GPIO_RMP_ADC1_ETRI) || ((REMAP) == GPIO_RMP_ADC1_ETRR) || ((REMAP) == GPIO_RMP_ADC2_ETRI) \ + || ((REMAP) == GPIO_RMP_ADC2_ETRR) || ((REMAP) == GPIO_RMP_SW_JTAG_NO_NJTRST) \ + || ((REMAP) == GPIO_RMP_SW_JTAG_SW_ENABLE) || ((REMAP) == GPIO_RMP_SW_JTAG_DISABLE) \ + || ((REMAP) == GPIO_RMP_SDIO) || ((REMAP) == GPIO_RMP1_CAN2) \ + || ((REMAP) == GPIO_RMP3_CAN2) || ((REMAP) == GPIO_RMP1_QSPI) || ((REMAP) == GPIO_RMP3_QSPI) \ + || ((REMAP) == GPIO_RMP1_I2C2) || ((REMAP) == GPIO_RMP3_I2C2) || ((REMAP) == GPIO_RMP2_I2C3) \ + || ((REMAP) == GPIO_RMP3_I2C3) || ((REMAP) == GPIO_RMP1_I2C4) || ((REMAP) == GPIO_RMP3_I2C4) \ + || ((REMAP) == GPIO_RMP1_SPI2) || ((REMAP) == GPIO_RMP2_SPI2) || ((REMAP) == GPIO_RMP1_SPI3) \ + || ((REMAP) == GPIO_RMP2_SPI3) || ((REMAP) == GPIO_RMP3_SPI3) || ((REMAP) == GPIO_RMP1_ETH) \ + || ((REMAP) == GPIO_RMP2_ETH) || ((REMAP) == GPIO_RMP3_ETH) || ((REMAP) == GPIO_RMP1_SPI1) \ + || ((REMAP) == GPIO_RMP2_SPI1) || ((REMAP) == GPIO_RMP3_SPI1) || ((REMAP) == GPIO_RMP1_USART2) \ + || ((REMAP) == GPIO_RMP2_USART2) || ((REMAP) == GPIO_RMP3_USART2) || ((REMAP) == GPIO_RMP1_UART4) \ + || ((REMAP) == GPIO_RMP2_UART4) || ((REMAP) == GPIO_RMP3_UART4) || ((REMAP) == GPIO_RMP1_UART5) \ + || ((REMAP) == GPIO_RMP2_UART5) || ((REMAP) == GPIO_RMP3_UART5) || ((REMAP) == GPIO_RMP2_UART6) \ + || ((REMAP) == GPIO_RMP3_UART6) || ((REMAP) == GPIO_RMP1_UART7) || ((REMAP) == GPIO_RMP3_UART7) \ + || ((REMAP) == GPIO_RMP1_TIM8) \ + || ((REMAP) == GPIO_RMP3_TIM8) || ((REMAP) == GPIO_RMP1_COMP1) || ((REMAP) == GPIO_RMP2_COMP1) \ + || ((REMAP) == GPIO_RMP3_COMP1) || ((REMAP) == GPIO_RMP1_COMP2) || ((REMAP) == GPIO_RMP2_COMP2) \ + || ((REMAP) == GPIO_RMP3_COMP2) || ((REMAP) == GPIO_RMP1_COMP3) || ((REMAP) == GPIO_RMP3_COMP3) \ + || ((REMAP) == GPIO_RMP1_COMP4) || ((REMAP) == GPIO_RMP3_COMP4) || ((REMAP) == GPIO_RMP1_COMP5) \ + || ((REMAP) == GPIO_RMP2_COMP5) || ((REMAP) == GPIO_RMP3_COMP5) || ((REMAP) == GPIO_RMP1_COMP6) \ + || ((REMAP) == GPIO_RMP3_COMP6) || ((REMAP) == GPIO_RMP_COMP7) || ((REMAP) == GPIO_RMP_ADC3_ETRI) \ + || ((REMAP) == GPIO_RMP_ADC3_ETRR) || ((REMAP) == GPIO_RMP_ADC4_ETRI) || ((REMAP) == GPIO_RMP_ADC4_ETRR) \ + || ((REMAP) == GPIO_RMP_TSC_OUT_CTRL) || ((REMAP) == GPIO_RMP_QSPI_XIP_EN) || ((REMAP) == GPIO_RMP1_DVP) \ + || ((REMAP) == GPIO_RMP3_DVP) || ((REMAP) == GPIO_Remap_SPI1_NSS) || ((REMAP) == GPIO_Remap_SPI2_NSS) \ + || ((REMAP) == GPIO_Remap_SPI3_NSS) || ((REMAP) == GPIO_Remap_QSPI_MISO) || ((REMAP) == GPIO_RMP_MII_RMII_SEL) \ + || ((REMAP) == GPIO_PART2_RMP_TIM1) || ((REMAP) == GPIO_Remap_DET_EN_EGB4) || ((REMAP) == GPIO_Remap_DET_EN_EGB3) \ + || ((REMAP) == GPIO_Remap_DET_EN_EGB2) || ((REMAP) == GPIO_Remap_DET_EN_EGB1) \ + || ((REMAP) == GPIO_Remap_DET_EN_EGBN4) || ((REMAP) == GPIO_Remap_DET_EN_EGBN3) \ + || ((REMAP) == GPIO_Remap_DET_EN_EGBN2) || ((REMAP) == GPIO_Remap_DET_EN_EGBN1) \ + || ((REMAP) == GPIO_Remap_DET_EN_ECLAMP4) || ((REMAP) == GPIO_Remap_DET_EN_ECLAMP3) \ + || ((REMAP) == GPIO_Remap_DET_EN_ECLAMP2) || ((REMAP) == GPIO_Remap_DET_EN_ECLAMP1) \ + || ((REMAP) == GPIO_Remap_RST_EN_EGB4) || ((REMAP) == GPIO_Remap_RST_EN_EGB3) \ + || ((REMAP) == GPIO_Remap_RST_EN_EGB2) || ((REMAP) == GPIO_Remap_RST_EN_EGB1) \ + || ((REMAP) == GPIO_Remap_RST_EN_EGBN4) || ((REMAP) == GPIO_Remap_RST_EN_EGBN3) \ + || ((REMAP) == GPIO_Remap_RST_EN_EGBN2) || ((REMAP) == GPIO_Remap_RST_EN_EGBN1) \ + || ((REMAP) == GPIO_Remap_RST_EN_ECLAMP4) || ((REMAP) == GPIO_Remap_RST_EN_ECLAMP3) \ + || ((REMAP) == GPIO_Remap_RST_EN_ECLAMP2) || ((REMAP) == GPIO_Remap_RST_EN_ECLAMP1)) + +/** + * @} + */ + +/** @addtogroup GPIO_Port_Sources + * @{ + */ + +#define GPIOA_PORT_SOURCE ((uint8_t)0x00) +#define GPIOB_PORT_SOURCE ((uint8_t)0x01) +#define GPIOC_PORT_SOURCE ((uint8_t)0x02) +#define GPIOD_PORT_SOURCE ((uint8_t)0x03) +#define GPIOE_PORT_SOURCE ((uint8_t)0x04) +#define IS_GPIO_EVENTOUT_PORT_SOURCE(PORTSOURCE) \ + (((PORTSOURCE) == GPIOA_PORT_SOURCE) || ((PORTSOURCE) == GPIOB_PORT_SOURCE) || ((PORTSOURCE) == GPIOC_PORT_SOURCE) \ + || ((PORTSOURCE) == GPIOD_PORT_SOURCE) || ((PORTSOURCE) == GPIOE_PORT_SOURCE)) + +#define IS_GPIO_EXTI_PORT_SOURCE(PORTSOURCE) \ + (((PORTSOURCE) == GPIOA_PORT_SOURCE) || ((PORTSOURCE) == GPIOB_PORT_SOURCE) || ((PORTSOURCE) == GPIOC_PORT_SOURCE) \ + || ((PORTSOURCE) == GPIOD_PORT_SOURCE) || ((PORTSOURCE) == GPIOE_PORT_SOURCE)) + +/** + * @} + */ + +/** @addtogroup GPIO_Pin_sources + * @{ + */ + +#define GPIO_PIN_SOURCE0 ((uint8_t)0x00) +#define GPIO_PIN_SOURCE1 ((uint8_t)0x01) +#define GPIO_PIN_SOURCE2 ((uint8_t)0x02) +#define GPIO_PIN_SOURCE3 ((uint8_t)0x03) +#define GPIO_PIN_SOURCE4 ((uint8_t)0x04) +#define GPIO_PIN_SOURCE5 ((uint8_t)0x05) +#define GPIO_PIN_SOURCE6 ((uint8_t)0x06) +#define GPIO_PIN_SOURCE7 ((uint8_t)0x07) +#define GPIO_PIN_SOURCE8 ((uint8_t)0x08) +#define GPIO_PIN_SOURCE9 ((uint8_t)0x09) +#define GPIO_PIN_SOURCE10 ((uint8_t)0x0A) +#define GPIO_PIN_SOURCE11 ((uint8_t)0x0B) +#define GPIO_PIN_SOURCE12 ((uint8_t)0x0C) +#define GPIO_PIN_SOURCE13 ((uint8_t)0x0D) +#define GPIO_PIN_SOURCE14 ((uint8_t)0x0E) +#define GPIO_PIN_SOURCE15 ((uint8_t)0x0F) + +#define IS_GPIO_PIN_SOURCE(PINSOURCE) \ + (((PINSOURCE) == GPIO_PIN_SOURCE0) || ((PINSOURCE) == GPIO_PIN_SOURCE1) || ((PINSOURCE) == GPIO_PIN_SOURCE2) \ + || ((PINSOURCE) == GPIO_PIN_SOURCE3) || ((PINSOURCE) == GPIO_PIN_SOURCE4) || ((PINSOURCE) == GPIO_PIN_SOURCE5) \ + || ((PINSOURCE) == GPIO_PIN_SOURCE6) || ((PINSOURCE) == GPIO_PIN_SOURCE7) || ((PINSOURCE) == GPIO_PIN_SOURCE8) \ + || ((PINSOURCE) == GPIO_PIN_SOURCE9) || ((PINSOURCE) == GPIO_PIN_SOURCE10) || ((PINSOURCE) == GPIO_PIN_SOURCE11) \ + || ((PINSOURCE) == GPIO_PIN_SOURCE12) || ((PINSOURCE) == GPIO_PIN_SOURCE13) || ((PINSOURCE) == GPIO_PIN_SOURCE14) \ + || ((PINSOURCE) == GPIO_PIN_SOURCE15)) + +/** + * @} + */ + +/** @addtogroup Ethernet_Media_Interface + * @{ + */ +#define GPIO_ETH_MII_CFG ((uint32_t)0x00000000) +#define GPIO_ETH_RMII_CFG ((uint32_t)0x00800000) + +#define IS_GPIO_ETH_MEDIA_INTERFACE(INTERFACE) (((INTERFACE) == GPIO_ETH_MII_CFG) || ((INTERFACE) == GPIO_ETH_RMII_CFG)) + +/** + * @} + */ +/** + * @} + */ + +/** @addtogroup GPIO_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup GPIO_Exported_Functions + * @{ + */ + +void GPIO_DeInit(GPIO_Module* GPIOx); +void GPIO_AFIOInitDefault(void); +void GPIO_InitPeripheral(GPIO_Module* GPIOx, GPIO_InitType* GPIO_InitStruct); +void GPIO_InitStruct(GPIO_InitType* GPIO_InitStruct); +uint8_t GPIO_ReadInputDataBit(GPIO_Module* GPIOx, uint16_t Pin); +uint16_t GPIO_ReadInputData(GPIO_Module* GPIOx); +uint8_t GPIO_ReadOutputDataBit(GPIO_Module* GPIOx, uint16_t Pin); +uint16_t GPIO_ReadOutputData(GPIO_Module* GPIOx); +void GPIO_SetBits(GPIO_Module* GPIOx, uint16_t Pin); +void GPIO_ResetBits(GPIO_Module* GPIOx, uint16_t Pin); +void GPIO_WriteBit(GPIO_Module* GPIOx, uint16_t Pin, Bit_OperateType BitCmd); +void GPIO_Write(GPIO_Module* GPIOx, uint16_t PortVal); +void GPIO_ConfigPinLock(GPIO_Module* GPIOx, uint16_t Pin); +void GPIO_ConfigEventOutput(uint8_t PortSource, uint8_t PinSource); +void GPIO_CtrlEventOutput(FunctionalState Cmd); +void GPIO_ConfigPinRemap(uint32_t RmpPin, FunctionalState Cmd); +void GPIO_ConfigEXTILine(uint8_t PortSource, uint8_t PinSource); +void GPIO_ETH_ConfigMediaInterface(uint32_t ETH_ConfigSel); +void GPIO_SetBitsHigh16(GPIO_Module* GPIOx, uint32_t Pin); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G4FR_GPIO_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_i2c.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_i2c.h new file mode 100644 index 0000000000..7390a08f10 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_i2c.h @@ -0,0 +1,671 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_i2c.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_I2C_H__ +#define __N32G4FR_I2C_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup I2C + * @{ + */ + +/** @addtogroup I2C_Exported_Types + * @{ + */ + +/** + * @brief I2C Init structure definition + */ + +typedef struct +{ + uint32_t ClkSpeed; /*!< Specifies the clock frequency. + This parameter must be set to a value lower than 400kHz */ + + uint16_t BusMode; /*!< Specifies the I2C mode. + This parameter can be a value of @ref I2C_BusMode */ + + uint16_t FmDutyCycle; /*!< Specifies the I2C fast mode duty cycle. + This parameter can be a value of @ref I2C_duty_cycle_in_fast_mode */ + + uint16_t OwnAddr1; /*!< Specifies the first device own address. + This parameter can be a 7-bit or 10-bit address. */ + + uint16_t AckEnable; /*!< Enables or disables the acknowledgement. + This parameter can be a value of @ref I2C_acknowledgement */ + + uint16_t AddrMode; /*!< Specifies if 7-bit or 10-bit address is acknowledged. + This parameter can be a value of @ref I2C_acknowledged_address */ +} I2C_InitType; + +/** + * @} + */ + +/** @addtogroup I2C_Exported_Constants + * @{ + */ + +#define IS_I2C_PERIPH(PERIPH) (((PERIPH) == I2C1) || ((PERIPH) == I2C2) || ((PERIPH) == I2C3) || ((PERIPH) == I2C4)) +/** @addtogroup I2C_BusMode + * @{ + */ + +#define I2C_BUSMODE_I2C ((uint16_t)0x0000) +#define I2C_BUSMODE_SMBDEVICE ((uint16_t)0x0002) +#define I2C_BUSMODE_SMBHOST ((uint16_t)0x000A) +#define IS_I2C_BUS_MODE(MODE) \ + (((MODE) == I2C_BUSMODE_I2C) || ((MODE) == I2C_BUSMODE_SMBDEVICE) || ((MODE) == I2C_BUSMODE_SMBHOST)) +/** + * @} + */ + +/** @addtogroup I2C_duty_cycle_in_fast_mode + * @{ + */ + +#define I2C_FMDUTYCYCLE_16_9 ((uint16_t)0x4000) /*!< I2C fast mode Tlow/Thigh = 16/9 */ +#define I2C_FMDUTYCYCLE_2 ((uint16_t)0xBFFF) /*!< I2C fast mode Tlow/Thigh = 2 */ +#define IS_I2C_FM_DUTY_CYCLE(CYCLE) (((CYCLE) == I2C_FMDUTYCYCLE_16_9) || ((CYCLE) == I2C_FMDUTYCYCLE_2)) +/** + * @} + */ + +/** @addtogroup I2C_acknowledgement + * @{ + */ + +#define I2C_ACKEN ((uint16_t)0x0400) +#define I2C_ACKDIS ((uint16_t)0x0000) +#define IS_I2C_ACK_STATE(STATE) (((STATE) == I2C_ACKEN) || ((STATE) == I2C_ACKDIS)) +/** + * @} + */ + +/** @addtogroup I2C_transfer_direction + * @{ + */ + +#define I2C_DIRECTION_SEND ((uint8_t)0x00) +#define I2C_DIRECTION_RECV ((uint8_t)0x01) +#define IS_I2C_DIRECTION(DIRECTION) (((DIRECTION) == I2C_DIRECTION_SEND) || ((DIRECTION) == I2C_DIRECTION_RECV)) +/** + * @} + */ + +/** @addtogroup I2C_acknowledged_address + * @{ + */ + +#define I2C_ADDR_MODE_7BIT ((uint16_t)0x4000) +#define I2C_ADDR_MODE_10BIT ((uint16_t)0xC000) +#define IS_I2C_ADDR_MODE(ADDRESS) (((ADDRESS) == I2C_ADDR_MODE_7BIT) || ((ADDRESS) == I2C_ADDR_MODE_10BIT)) +/** + * @} + */ + +/** @addtogroup I2C_registers + * @{ + */ + +#define I2C_REG_CTRL1 ((uint8_t)0x00) +#define I2C_REG_CTRL2 ((uint8_t)0x04) +#define I2C_REG_OADDR1 ((uint8_t)0x08) +#define I2C_REG_OADDR2 ((uint8_t)0x0C) +#define I2C_REG_DAT ((uint8_t)0x10) +#define I2C_REG_STS1 ((uint8_t)0x14) +#define I2C_REG_STS2 ((uint8_t)0x18) +#define I2C_REG_CLKCTRL ((uint8_t)0x1C) +#define I2C_REG_TMRISE ((uint8_t)0x20) +#define IS_I2C_REG(REGISTER) \ + (((REGISTER) == I2C_REG_CTRL1) || ((REGISTER) == I2C_REG_CTRL2) || ((REGISTER) == I2C_REG_OADDR1) \ + || ((REGISTER) == I2C_REG_OADDR2) || ((REGISTER) == I2C_REG_DAT) || ((REGISTER) == I2C_REG_STS1) \ + || ((REGISTER) == I2C_REG_STS2) || ((REGISTER) == I2C_REG_CLKCTRL) || ((REGISTER) == I2C_REG_TMRISE)) +/** + * @} + */ + +/** @addtogroup I2C_SMBus_alert_pin_level + * @{ + */ + +#define I2C_SMBALERT_LOW ((uint16_t)0x2000) +#define I2C_SMBALERT_HIGH ((uint16_t)0xDFFF) +#define IS_I2C_SMB_ALERT(ALERT) (((ALERT) == I2C_SMBALERT_LOW) || ((ALERT) == I2C_SMBALERT_HIGH)) +/** + * @} + */ + +/** @addtogroup I2C_PEC_position + * @{ + */ + +#define I2C_PEC_POS_NEXT ((uint16_t)0x0800) +#define I2C_PEC_POS_CURRENT ((uint16_t)0xF7FF) +#define IS_I2C_PEC_POS(POSITION) (((POSITION) == I2C_PEC_POS_NEXT) || ((POSITION) == I2C_PEC_POS_CURRENT)) +/** + * @} + */ + +/** @addtogroup I2C_NCAK_position + * @{ + */ + +#define I2C_NACK_POS_NEXT ((uint16_t)0x0800) +#define I2C_NACK_POS_CURRENT ((uint16_t)0xF7FF) +#define IS_I2C_NACK_POS(POSITION) (((POSITION) == I2C_NACK_POS_NEXT) || ((POSITION) == I2C_NACK_POS_CURRENT)) +/** + * @} + */ + +/** @addtogroup I2C_interrupts_definition + * @{ + */ + +#define I2C_INT_BUF ((uint16_t)0x0400) +#define I2C_INT_EVENT ((uint16_t)0x0200) +#define I2C_INT_ERR ((uint16_t)0x0100) +#define IS_I2C_CFG_INT(IT) ((((IT) & (uint16_t)0xF8FF) == 0x00) && ((IT) != 0x00)) +/** + * @} + */ + +/** @addtogroup I2C_interrupts_definition + * @{ + */ + +#define I2C_INT_SMBALERT ((uint32_t)0x01008000) +#define I2C_INT_TIMOUT ((uint32_t)0x01004000) +#define I2C_INT_PECERR ((uint32_t)0x01001000) +#define I2C_INT_OVERRUN ((uint32_t)0x01000800) +#define I2C_INT_ACKFAIL ((uint32_t)0x01000400) +#define I2C_INT_ARLOST ((uint32_t)0x01000200) +#define I2C_INT_BUSERR ((uint32_t)0x01000100) +#define I2C_INT_TXDATE ((uint32_t)0x06000080) +#define I2C_INT_RXDATNE ((uint32_t)0x06000040) +#define I2C_INT_STOPF ((uint32_t)0x02000010) +#define I2C_INT_ADDR10F ((uint32_t)0x02000008) +#define I2C_INT_BYTEF ((uint32_t)0x02000004) +#define I2C_INT_ADDRF ((uint32_t)0x02000002) +#define I2C_INT_STARTBF ((uint32_t)0x02000001) + +#define IS_I2C_CLR_INT(IT) ((((IT) & (uint16_t)0x20FF) == 0x00) && ((IT) != (uint16_t)0x00)) + +#define IS_I2C_GET_INT(IT) \ + (((IT) == I2C_INT_SMBALERT) || ((IT) == I2C_INT_TIMOUT) || ((IT) == I2C_INT_PECERR) || ((IT) == I2C_INT_OVERRUN) \ + || ((IT) == I2C_INT_ACKFAIL) || ((IT) == I2C_INT_ARLOST) || ((IT) == I2C_INT_BUSERR) || ((IT) == I2C_INT_TXDATE) \ + || ((IT) == I2C_INT_RXDATNE) || ((IT) == I2C_INT_STOPF) || ((IT) == I2C_INT_ADDR10F) || ((IT) == I2C_INT_BYTEF) \ + || ((IT) == I2C_INT_ADDRF) || ((IT) == I2C_INT_STARTBF)) +/** + * @} + */ + +/** @addtogroup I2C_flags_definition + * @{ + */ + +/** + * @brief STS2 register flags + */ + +#define I2C_FLAG_DUALFLAG ((uint32_t)0x00800000) +#define I2C_FLAG_SMBHADDR ((uint32_t)0x00400000) +#define I2C_FLAG_SMBDADDR ((uint32_t)0x00200000) +#define I2C_FLAG_GCALLADDR ((uint32_t)0x00100000) +#define I2C_FLAG_TRF ((uint32_t)0x00040000) +#define I2C_FLAG_BUSY ((uint32_t)0x00020000) +#define I2C_FLAG_MSMODE ((uint32_t)0x00010000) + +/** + * @brief STS1 register flags + */ + +#define I2C_FLAG_SMBALERT ((uint32_t)0x10008000) +#define I2C_FLAG_TIMOUT ((uint32_t)0x10004000) +#define I2C_FLAG_PECERR ((uint32_t)0x10001000) +#define I2C_FLAG_OVERRUN ((uint32_t)0x10000800) +#define I2C_FLAG_ACKFAIL ((uint32_t)0x10000400) +#define I2C_FLAG_ARLOST ((uint32_t)0x10000200) +#define I2C_FLAG_BUSERR ((uint32_t)0x10000100) +#define I2C_FLAG_TXDATE ((uint32_t)0x10000080) +#define I2C_FLAG_RXDATNE ((uint32_t)0x10000040) +#define I2C_FLAG_STOPF ((uint32_t)0x10000010) +#define I2C_FLAG_ADDR10F ((uint32_t)0x10000008) +#define I2C_FLAG_BYTEF ((uint32_t)0x10000004) +#define I2C_FLAG_ADDRF ((uint32_t)0x10000002) +#define I2C_FLAG_STARTBF ((uint32_t)0x10000001) + +#define IS_I2C_CLR_FLAG(FLAG) ((((FLAG) & (uint16_t)0x20FF) == 0x00) && ((FLAG) != (uint16_t)0x00)) + +#define IS_I2C_GET_FLAG(FLAG) \ + (((FLAG) == I2C_FLAG_DUALFLAG) || ((FLAG) == I2C_FLAG_SMBHADDR) || ((FLAG) == I2C_FLAG_SMBDADDR) \ + || ((FLAG) == I2C_FLAG_GCALLADDR) || ((FLAG) == I2C_FLAG_TRF) || ((FLAG) == I2C_FLAG_BUSY) \ + || ((FLAG) == I2C_FLAG_MSMODE) || ((FLAG) == I2C_FLAG_SMBALERT) || ((FLAG) == I2C_FLAG_TIMOUT) \ + || ((FLAG) == I2C_FLAG_PECERR) || ((FLAG) == I2C_FLAG_OVERRUN) || ((FLAG) == I2C_FLAG_ACKFAIL) \ + || ((FLAG) == I2C_FLAG_ARLOST) || ((FLAG) == I2C_FLAG_BUSERR) || ((FLAG) == I2C_FLAG_TXDATE) \ + || ((FLAG) == I2C_FLAG_RXDATNE) || ((FLAG) == I2C_FLAG_STOPF) || ((FLAG) == I2C_FLAG_ADDR10F) \ + || ((FLAG) == I2C_FLAG_BYTEF) || ((FLAG) == I2C_FLAG_ADDRF) || ((FLAG) == I2C_FLAG_STARTBF)) +/** + * @} + */ + +/** @addtogroup I2C_Events + * @{ + */ + +/*======================================== + + I2C Master Events (Events grouped in order of communication) + ==========================================*/ +/** + * @brief Communication start + * + * After sending the START condition (I2C_GenerateStart() function) the master + * has to wait for this event. It means that the Start condition has been correctly + * released on the I2C bus (the bus is free, no other devices is communicating). + * + */ +/* Master mode */ +#define I2C_ROLE_MASTER ((uint32_t)0x00010000) /* MSMODE */ +/* --EV5 */ +#define I2C_EVT_MASTER_MODE_FLAG ((uint32_t)0x00030001) /* BUSY, MSL and SB flag */ + +/** + * @brief Address Acknowledge + * + * After checking on EV5 (start condition correctly released on the bus), the + * master sends the address of the slave(s) with which it will communicate + * (I2C_SendAddr7bit() function, it also determines the direction of the communication: + * Master transmitter or Receiver). Then the master has to wait that a slave acknowledges + * his address. If an acknowledge is sent on the bus, one of the following events will + * be set: + * + * 1) In case of Master Receiver (7-bit addressing): the I2C_EVT_MASTER_RXMODE_FLAG + * event is set. + * + * 2) In case of Master Transmitter (7-bit addressing): the I2C_EVT_MASTER_TXMODE_FLAG + * is set + * + * 3) In case of 10-Bit addressing mode, the master (just after generating the START + * and checking on EV5) has to send the header of 10-bit addressing mode (I2C_SendData() + * function). Then master should wait on EV9. It means that the 10-bit addressing + * header has been correctly sent on the bus. Then master should send the second part of + * the 10-bit address (LSB) using the function I2C_SendAddr7bit(). Then master + * should wait for event EV6. + * + */ + +/* --EV6 */ +#define I2C_EVT_MASTER_TXMODE_FLAG ((uint32_t)0x00070082) /* BUSY, MSL, ADDR, TXE and TRA flags */ +#define I2C_EVT_MASTER_RXMODE_FLAG ((uint32_t)0x00030002) /* BUSY, MSL and ADDR flags */ +/* --EV9 */ +#define I2C_EVT_MASTER_MODE_ADDRESS10_FLAG ((uint32_t)0x00030008) /* BUSY, MSL and ADD10 flags */ + +/** + * @brief Communication events + * + * If a communication is established (START condition generated and slave address + * acknowledged) then the master has to check on one of the following events for + * communication procedures: + * + * 1) Master Receiver mode: The master has to wait on the event EV7 then to read + * the data received from the slave (I2C_RecvData() function). + * + * 2) Master Transmitter mode: The master has to send data (I2C_SendData() + * function) then to wait on event EV8 or EV8_2. + * These two events are similar: + * - EV8 means that the data has been written in the data register and is + * being shifted out. + * - EV8_2 means that the data has been physically shifted out and output + * on the bus. + * In most cases, using EV8 is sufficient for the application. + * Using EV8_2 leads to a slower communication but ensure more reliable test. + * EV8_2 is also more suitable than EV8 for testing on the last data transmission + * (before Stop condition generation). + * + * @note In case the user software does not guarantee that this event EV7 is + * managed before the current byte end of transfer, then user may check on EV7 + * and BTF flag at the same time (ie. (I2C_EVT_MASTER_DATA_RECVD_FLAG | I2C_FLAG_BYTEF)). + * In this case the communication may be slower. + * + */ + +/* Master RECEIVER mode -----------------------------*/ +/* --EV7 */ +#define I2C_EVT_MASTER_DATA_RECVD_FLAG ((uint32_t)0x00030040) /* BUSY, MSL and RXNE flags */ +/* EV7x shifter register full */ +#define I2C_EVT_MASTER_SFT_DATA_RECVD_FLAG ((uint32_t)0x00030044) /* BUSY, MSMODE, BSF and RXDATNE flags */ + +/* Master TRANSMITTER mode --------------------------*/ +/* --EV8 */ +#define I2C_EVT_MASTER_DATA_SENDING ((uint32_t)0x00070080) /* TRA, BUSY, MSL, TXE flags */ +/* --EV8_2 */ +#define I2C_EVT_MASTER_DATA_SENDED ((uint32_t)0x00070084) /* TRA, BUSY, MSL, TXE and BTF flags */ + +/*======================================== + + I2C Slave Events (Events grouped in order of communication) + ==========================================*/ + +/** + * @brief Communication start events + * + * Wait on one of these events at the start of the communication. It means that + * the I2C peripheral detected a Start condition on the bus (generated by master + * device) followed by the peripheral address. The peripheral generates an ACK + * condition on the bus (if the acknowledge feature is enabled through function + * I2C_ConfigAck()) and the events listed above are set : + * + * 1) In normal case (only one address managed by the slave), when the address + * sent by the master matches the own address of the peripheral (configured by + * OwnAddr1 field) the I2C_EVENT_SLAVE_XXX_ADDRESS_MATCHED event is set + * (where XXX could be TRANSMITTER or RECEIVER). + * + * 2) In case the address sent by the master matches the second address of the + * peripheral (configured by the function I2C_ConfigOwnAddr2() and enabled + * by the function I2C_EnableDualAddr()) the events I2C_EVENT_SLAVE_XXX_SECONDADDRESS_MATCHED + * (where XXX could be TRANSMITTER or RECEIVER) are set. + * + * 3) In case the address sent by the master is General Call (address 0x00) and + * if the General Call is enabled for the peripheral (using function I2C_EnableGeneralCall()) + * the following event is set I2C_EVT_SLAVE_GCALLADDR_MATCHED. + * + */ + +/* --EV1 (all the events below are variants of EV1) */ +/* 1) Case of One Single Address managed by the slave */ +#define I2C_EVT_SLAVE_RECV_ADDR_MATCHED ((uint32_t)0x00020002) /* BUSY and ADDR flags */ +#define I2C_EVT_SLAVE_SEND_ADDR_MATCHED ((uint32_t)0x00060082) /* TRA, BUSY, TXE and ADDR flags */ + +/* 2) Case of Dual address managed by the slave */ +#define I2C_EVT_SLAVE_RECV_ADDR2_MATCHED ((uint32_t)0x00820000) /* DUALF and BUSY flags */ +#define I2C_EVT_SLAVE_SEND_ADDR2_MATCHED ((uint32_t)0x00860080) /* DUALF, TRA, BUSY and TXE flags */ + +/* 3) Case of General Call enabled for the slave */ +#define I2C_EVT_SLAVE_GCALLADDR_MATCHED ((uint32_t)0x00120000) /* GENCALL and BUSY flags */ + +/** + * @brief Communication events + * + * Wait on one of these events when EV1 has already been checked and: + * + * - Slave RECEIVER mode: + * - EV2: When the application is expecting a data byte to be received. + * - EV4: When the application is expecting the end of the communication: master + * sends a stop condition and data transmission is stopped. + * + * - Slave Transmitter mode: + * - EV3: When a byte has been transmitted by the slave and the application is expecting + * the end of the byte transmission. The two events I2C_EVT_SLAVE_DATA_SENDED and + * I2C_EVT_SLAVE_DATA_SENDING are similar. The second one can optionally be + * used when the user software doesn't guarantee the EV3 is managed before the + * current byte end of transfer. + * - EV3_2: When the master sends a NACK in order to tell slave that data transmission + * shall end (before sending the STOP condition). In this case slave has to stop sending + * data bytes and expect a Stop condition on the bus. + * + * @note In case the user software does not guarantee that the event EV2 is + * managed before the current byte end of transfer, then user may check on EV2 + * and BTF flag at the same time (ie. (I2C_EVT_SLAVE_DATA_RECVD | I2C_FLAG_BYTEF)). + * In this case the communication may be slower. + * + */ + +/* Slave RECEIVER mode --------------------------*/ +/* --EV2 */ +#define I2C_EVT_SLAVE_DATA_RECVD ((uint32_t)0x00020040) /* BUSY and RXNE flags */ +/* --EV2x */ +#define I2C_EVT_SLAVE_DATA_RECVD_NOBUSY ((uint32_t)0x00000040) /* no BUSY and RXDATNE flags */ +/* --EV4 */ +#define I2C_EVT_SLAVE_STOP_RECVD ((uint32_t)0x00000010) /* STOPF flag */ + +/* Slave TRANSMITTER mode -----------------------*/ +/* --EV3 */ +#define I2C_EVT_SLAVE_DATA_SENDED ((uint32_t)0x00060084) /* TRA, BUSY, TXE and BTF flags */ +#define I2C_EVT_SLAVE_DATA_SENDING ((uint32_t)0x00060080) /* TRA, BUSY and TXE flags */ +/* --EV3_2 */ +#define I2C_EVT_SLAVE_ACK_MISS ((uint32_t)0x00000400) /* AF flag */ + +/*=========================== End of Events Description ==========================================*/ + +#define IS_I2C_EVT(EVENT) \ + (((EVENT) == I2C_EVT_SLAVE_SEND_ADDR_MATCHED) || ((EVENT) == I2C_EVT_SLAVE_RECV_ADDR_MATCHED) \ + || ((EVENT) == I2C_EVT_SLAVE_SEND_ADDR2_MATCHED) || ((EVENT) == I2C_EVT_SLAVE_RECV_ADDR2_MATCHED) \ + || ((EVENT) == I2C_EVT_SLAVE_GCALLADDR_MATCHED) || ((EVENT) == I2C_EVT_SLAVE_DATA_RECVD) \ + || ((EVENT) == (I2C_EVT_SLAVE_DATA_RECVD | I2C_FLAG_DUALFLAG)) \ + || ((EVENT) == (I2C_EVT_SLAVE_DATA_RECVD | I2C_FLAG_GCALLADDR)) || ((EVENT) == I2C_EVT_SLAVE_DATA_SENDED) \ + || ((EVENT) == (I2C_EVT_SLAVE_DATA_SENDED | I2C_FLAG_DUALFLAG)) \ + || ((EVENT) == (I2C_EVT_SLAVE_DATA_SENDED | I2C_FLAG_GCALLADDR)) || ((EVENT) == I2C_EVT_SLAVE_STOP_RECVD) \ + || ((EVENT) == I2C_EVT_MASTER_MODE_FLAG) || ((EVENT) == I2C_EVT_MASTER_TXMODE_FLAG) \ + || ((EVENT) == I2C_EVT_MASTER_RXMODE_FLAG) || ((EVENT) == I2C_EVT_MASTER_DATA_RECVD_FLAG) \ + || ((EVENT) == I2C_EVT_MASTER_DATA_SENDED) || ((EVENT) == I2C_EVT_MASTER_DATA_SENDING) \ + || ((EVENT) == I2C_EVT_MASTER_MODE_ADDRESS10_FLAG) || ((EVENT) == I2C_EVT_SLAVE_ACK_MISS)) +/** + * @} + */ + +/** @addtogroup I2C_own_address1 + * @{ + */ + +#define IS_I2C_OWN_ADDR1(ADDRESS1) ((ADDRESS1) <= 0x3FF) +/** + * @} + */ + +/** @addtogroup I2C_clock_speed + * @{ + */ + +//#define IS_I2C_CLK_SPEED(SPEED) (((SPEED) >= 0x1) && ((SPEED) <= 400000)) +#define IS_I2C_CLK_SPEED(SPEED) (((SPEED) >= 0x1) && ((SPEED) <= 1000000)) + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup I2C_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup I2C_Exported_Functions + * @{ + */ + +void I2C_DeInit(I2C_Module* I2Cx); +void I2C_Init(I2C_Module* I2Cx, I2C_InitType* I2C_InitStruct); +void I2C_InitStruct(I2C_InitType* I2C_InitStruct); +void I2C_Enable(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_EnableDMA(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_EnableDmaLastSend(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_GenerateStart(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_GenerateStop(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_ConfigAck(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_ConfigOwnAddr2(I2C_Module* I2Cx, uint8_t Address); +void I2C_EnableDualAddr(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_EnableGeneralCall(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_ConfigInt(I2C_Module* I2Cx, uint16_t I2C_IT, FunctionalState Cmd); +void I2C_SendData(I2C_Module* I2Cx, uint8_t Data); +uint8_t I2C_RecvData(I2C_Module* I2Cx); +void I2C_SendAddr7bit(I2C_Module* I2Cx, uint8_t Address, uint8_t I2C_Direction); +uint16_t I2C_GetRegister(I2C_Module* I2Cx, uint8_t I2C_Register); +void I2C_EnableSoftwareReset(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_ConfigNackLocation(I2C_Module* I2Cx, uint16_t I2C_NACKPosition); +void I2C_ConfigSmbusAlert(I2C_Module* I2Cx, uint16_t I2C_SMBusAlert); +void I2C_SendPEC(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_ConfigPecLocation(I2C_Module* I2Cx, uint16_t I2C_PECPosition); +void I2C_ComputePec(I2C_Module* I2Cx, FunctionalState Cmd); +uint8_t I2C_GetPec(I2C_Module* I2Cx); +void I2C_EnableArp(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_EnableExtendClk(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_ConfigFastModeDutyCycle(I2C_Module* I2Cx, uint16_t FmDutyCycle); + +/** + * @brief + **************************************************************************************** + * + * I2C State Monitoring Functions + * + **************************************************************************************** + * This I2C driver provides three different ways for I2C state monitoring + * depending on the application requirements and constraints: + * + * + * 1) Basic state monitoring: + * Using I2C_CheckEvent() function: + * It compares the status registers (STS1 and STS2) content to a given event + * (can be the combination of one or more flags). + * It returns SUCCESS if the current status includes the given flags + * and returns ERROR if one or more flags are missing in the current status. + * - When to use: + * - This function is suitable for most applications as well as for startup + * activity since the events are fully described in the product reference manual + * (RM0008). + * - It is also suitable for users who need to define their own events. + * - Limitations: + * - If an error occurs (ie. error flags are set besides to the monitored flags), + * the I2C_CheckEvent() function may return SUCCESS despite the communication + * hold or corrupted real state. + * In this case, it is advised to use error interrupts to monitor the error + * events and handle them in the interrupt IRQ handler. + * + * @note + * For error management, it is advised to use the following functions: + * - I2C_ConfigInt() to configure and enable the error interrupts (I2C_INT_ERR). + * - I2Cx_ER_IRQHandler() which is called when the error interrupt occurs. + * Where x is the peripheral instance (I2C1, I2C2 ...) + * - I2C_GetFlag() or I2C_GetIntStatus() to be called into I2Cx_ER_IRQHandler() + * in order to determine which error occurred. + * - I2C_ClrFlag() or I2C_ClrIntPendingBit() and/or I2C_EnableSoftwareReset() + * and/or I2C_GenerateStop() in order to clear the error flag and source, + * and return to correct communication status. + * + * + * 2) Advanced state monitoring: + * Using the function I2C_GetLastEvent() which returns the image of both status + * registers in a single word (uint32_t) (Status Register 2 value is shifted left + * by 16 bits and concatenated to Status Register 1). + * - When to use: + * - This function is suitable for the same applications above but it allows to + * overcome the limitations of I2C_GetFlag() function (see below). + * The returned value could be compared to events already defined in the + * library (n32g4fr_i2c.h) or to custom values defined by user. + * - This function is suitable when multiple flags are monitored at the same time. + * - At the opposite of I2C_CheckEvent() function, this function allows user to + * choose when an event is accepted (when all events flags are set and no + * other flags are set or just when the needed flags are set like + * I2C_CheckEvent() function). + * - Limitations: + * - User may need to define his own events. + * - Same remark concerning the error management is applicable for this + * function if user decides to check only regular communication flags (and + * ignores error flags). + * + * + * 3) Flag-based state monitoring: + * Using the function I2C_GetFlag() which simply returns the status of + * one single flag (ie. I2C_FLAG_RXDATNE ...). + * - When to use: + * - This function could be used for specific applications or in debug phase. + * - It is suitable when only one flag checking is needed (most I2C events + * are monitored through multiple flags). + * - Limitations: + * - When calling this function, the Status register is accessed. Some flags are + * cleared when the status register is accessed. So checking the status + * of one Flag, may clear other ones. + * - Function may need to be called twice or more in order to monitor one + * single event. + * + */ + +/** + * + * 1) Basic state monitoring + ******************************************************************************* + */ +ErrorStatus I2C_CheckEvent(I2C_Module* I2Cx, uint32_t I2C_EVENT); +/** + * + * 2) Advanced state monitoring + ******************************************************************************* + */ +uint32_t I2C_GetLastEvent(I2C_Module* I2Cx); +/** + * + * 3) Flag-based state monitoring + ******************************************************************************* + */ +FlagStatus I2C_GetFlag(I2C_Module* I2Cx, uint32_t I2C_FLAG); +/** + * + ******************************************************************************* + */ + +void I2C_ClrFlag(I2C_Module* I2Cx, uint32_t I2C_FLAG); +INTStatus I2C_GetIntStatus(I2C_Module* I2Cx, uint32_t I2C_IT); +void I2C_ClrIntPendingBit(I2C_Module* I2Cx, uint32_t I2C_IT); + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G4FR_I2C_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_iwdg.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_iwdg.h new file mode 100644 index 0000000000..09add896e6 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_iwdg.h @@ -0,0 +1,145 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_iwdg.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_IWDG_H__ +#define __N32G4FR_IWDG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup IWDG + * @{ + */ + +/** @addtogroup IWDG_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @addtogroup IWDG_Exported_Constants + * @{ + */ + +/** @addtogroup IWDG_WriteAccess + * @{ + */ + +#define IWDG_WRITE_ENABLE ((uint16_t)0x5555) +#define IWDG_WRITE_DISABLE ((uint16_t)0x0000) +#define IS_IWDG_WRITE(ACCESS) (((ACCESS) == IWDG_WRITE_ENABLE) || ((ACCESS) == IWDG_WRITE_DISABLE)) +/** + * @} + */ + +/** @addtogroup IWDG_prescaler + * @{ + */ + +#define IWDG_PRESCALER_DIV4 ((uint8_t)0x00) +#define IWDG_PRESCALER_DIV8 ((uint8_t)0x01) +#define IWDG_PRESCALER_DIV16 ((uint8_t)0x02) +#define IWDG_PRESCALER_DIV32 ((uint8_t)0x03) +#define IWDG_PRESCALER_DIV64 ((uint8_t)0x04) +#define IWDG_PRESCALER_DIV128 ((uint8_t)0x05) +#define IWDG_PRESCALER_DIV256 ((uint8_t)0x06) +#define IS_IWDG_PRESCALER_DIV(PRESCALER) \ + (((PRESCALER) == IWDG_PRESCALER_DIV4) || ((PRESCALER) == IWDG_PRESCALER_DIV8) \ + || ((PRESCALER) == IWDG_PRESCALER_DIV16) || ((PRESCALER) == IWDG_PRESCALER_DIV32) \ + || ((PRESCALER) == IWDG_PRESCALER_DIV64) || ((PRESCALER) == IWDG_PRESCALER_DIV128) \ + || ((PRESCALER) == IWDG_PRESCALER_DIV256)) +/** + * @} + */ + +/** @addtogroup IWDG_Flag + * @{ + */ + +#define IWDG_PVU_FLAG ((uint16_t)0x0001) +#define IWDG_CRVU_FLAG ((uint16_t)0x0002) +#define IS_IWDG_FLAG(FLAG) (((FLAG) == IWDG_PVU_FLAG) || ((FLAG) == IWDG_CRVU_FLAG)) +#define IS_IWDG_RELOAD(RELOAD) ((RELOAD) <= 0xFFF) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup IWDG_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup IWDG_Exported_Functions + * @{ + */ + +void IWDG_WriteConfig(uint16_t IWDG_WriteAccess); +void IWDG_SetPrescalerDiv(uint8_t IWDG_Prescaler); +void IWDG_CntReload(uint16_t Reload); +void IWDG_ReloadKey(void); +void IWDG_Enable(void); +FlagStatus IWDG_GetStatus(uint16_t IWDG_FLAG); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G4FR_IWDG_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_pwr.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_pwr.h new file mode 100644 index 0000000000..dffc67d2d7 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_pwr.h @@ -0,0 +1,179 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_pwr.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_PWR_H__ +#define __N32G4FR_PWR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup PWR + * @{ + */ + +/** @addtogroup PWR_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @addtogroup PWR_Exported_Constants + * @{ + */ + +/** @addtogroup PVD_detection_level + * @{ + */ + +#define PWR_PVDRANGRE_2V2 ((uint32_t)0x00000000) +#define PWR_PVDRANGRE_2V3 ((uint32_t)0x00000020) +#define PWR_PVDRANGRE_2V4 ((uint32_t)0x00000040) +#define PWR_PVDRANGRE_2V5 ((uint32_t)0x00000060) +#define PWR_PVDRANGRE_2V6 ((uint32_t)0x00000080) +#define PWR_PVDRANGRE_2V7 ((uint32_t)0x000000A0) +#define PWR_PVDRANGRE_2V8 ((uint32_t)0x000000C0) +#define PWR_PVDRANGRE_2V9 ((uint32_t)0x000000E0) + +#define PWR_PVDRANGE_1V78 ((uint32_t)0x00000200) +#define PWR_PVDRANGE_1V88 ((uint32_t)0x00000220) +#define PWR_PVDRANGE_1V98 ((uint32_t)0x00000240) +#define PWR_PVDRANGE_2V08 ((uint32_t)0x00000260) +#define PWR_PVDRANGE_3V06 ((uint32_t)0x00000280) +#define PWR_PVDRANGE_3V24 ((uint32_t)0x000002A0) +#define PWR_PVDRANGE_3V42 ((uint32_t)0x000002C0) +#define PWR_PVDRANGE_3V60 ((uint32_t)0x000002E0) +#define IS_PWR_PVD_LEVEL(LEVEL) \ + (((LEVEL) == PWR_PVDRANGRE_2V2) || ((LEVEL) == PWR_PVDRANGRE_2V3) || ((LEVEL) == PWR_PVDRANGRE_2V4) \ + || ((LEVEL) == PWR_PVDRANGRE_2V5) || ((LEVEL) == PWR_PVDRANGRE_2V6) || ((LEVEL) == PWR_PVDRANGRE_2V7) \ + || ((LEVEL) == PWR_PVDRANGRE_2V8) || ((LEVEL) == PWR_PVDRANGRE_2V9) || ((LEVEL) == PWR_PVDRANGE_1V78) \ + || ((LEVEL) == PWR_PVDRANGE_1V88) || ((LEVEL) == PWR_PVDRANGE_1V98) || ((LEVEL) == PWR_PVDRANGE_2V08) \ + || ((LEVEL) == PWR_PVDRANGE_3V06) || ((LEVEL) == PWR_PVDRANGE_3V24) || ((LEVEL) == PWR_PVDRANGE_3V42) \ + || ((LEVEL) == PWR_PVDRANGE_3V60)) + +/** + * @} + */ + +/** @addtogroup Regulator_state_is_STOP_mode + * @{ + */ + +#define PWR_REGULATOR_ON ((uint32_t)0x00000000) +#define PWR_REGULATOR_LOWPOWER ((uint32_t)0x00000001) +#define IS_PWR_REGULATOR(REGULATOR) (((REGULATOR) == PWR_REGULATOR_ON) || ((REGULATOR) == PWR_REGULATOR_LOWPOWER)) +/** + * @} + */ + +/** @addtogroup STOP_mode_entry + * @{ + */ + +#define PWR_STOPENTRY_WFI ((uint8_t)0x01) +#define PWR_STOPENTRY_WFE ((uint8_t)0x02) +#define IS_PWR_STOP_ENTRY(ENTRY) (((ENTRY) == PWR_STOPENTRY_WFI) || ((ENTRY) == PWR_STOPENTRY_WFE)) + +/** + * @} + */ + +/** @addtogroup PWR_Flag + * @{ + */ + +#define PWR_WU_FLAG ((uint32_t)0x00000001) +#define PWR_SB_FLAG ((uint32_t)0x00000002) +#define PWR_PVDO_FLAG ((uint32_t)0x00000004) +#define PWR_VBATF_FLAG ((uint32_t)0x00000008) +#define IS_PWR_GET_FLAG(FLAG) \ + (((FLAG) == PWR_WU_FLAG) || ((FLAG) == PWR_SB_FLAG) || ((FLAG) == PWR_PVDO_FLAG) || ((FLAG) == PWR_VBATF_FLAG)) + +#define IS_PWR_CLEAR_FLAG(FLAG) (((FLAG) == PWR_WU_FLAG) || ((FLAG) == PWR_SB_FLAG) || ((FLAG) == PWR_VBATF_FLAG)) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup PWR_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup PWR_Exported_Functions + * @{ + */ + +void PWR_DeInit(void); +void PWR_BackupAccessEnable(FunctionalState Cmd); +void PWR_PvdEnable(FunctionalState Cmd); +void PWR_PvdRangeConfig(uint32_t PWR_PVDLevel); +void PWR_WakeUpPinEnable(FunctionalState Cmd); +void PWR_EnterStopState(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry); +void PWR_EnterSLEEPMode(uint8_t SLEEPONEXIT, uint8_t PWR_STOPEntry); +void PWR_EnterSTOP2Mode(uint8_t PWR_STOPEntry); +void PWR_EnterStandbyState(void); +FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG); +void PWR_ClearFlag(uint32_t PWR_FLAG); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G4FR_PWR_H__ */ + /** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_qspi.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_qspi.h new file mode 100644 index 0000000000..591252dfcf --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_qspi.h @@ -0,0 +1,317 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_qspi.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_QSPI_H__ +#define __N32G4FR_QSPI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" +#include +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup QSPI + * @brief QSPI driver modules + * @{ + */ +//////////////////////////////////////////////////////////////////////////////////////////////////// +typedef enum +{ + STANDARD_SPI_FORMAT_SEL = 0, + DUAL_SPI_FORMAT_SEL, + QUAD_SPI_FORMAT_SEL, + XIP_SPI_FORMAT_SEL +} QSPI_FORMAT_SEL; + +typedef enum +{ + TX_AND_RX = 0, + TX_ONLY, + RX_ONLY +} QSPI_DATA_DIR; + +typedef enum +{ + QSPI_NSS_PORTA_SEL, + QSPI_NSS_PORTC_SEL, + QSPI_NSS_PORTF_SEL +} QSPI_NSS_PORT_SEL; + +typedef enum +{ + QSPI_NULL = 0, + QSPI_SUCCESS, +} QSPI_STATUS; +//////////////////////////////////////////////////////////////////////////////////////////////////// +typedef struct +{ + /*QSPI_CTRL0*/ + uint32_t DFS; + uint32_t FRF; + uint32_t SCPH; + uint32_t SCPOL; + uint32_t TMOD; + uint32_t SSTE; + uint32_t CFS; + uint32_t SPI_FRF; + + /*QSPI_CTRL1*/ + uint32_t NDF; + + /*QSPI_MW_CTRL*/ + uint32_t MWMOD; + uint32_t MC_DIR; + uint32_t MHS_EN; + + /*QSPI_BAUD*/ + uint32_t CLK_DIV; + + /*QSPI_TXFT*/ + uint32_t TXFT; + + /*QSPI_RXFT*/ + uint32_t RXFT; + + /*QSPI_TXFN*/ + uint32_t TXFN; + + /*QSPI_RXFN*/ + uint32_t RXFN; + + /*QSPI_RS_DELAY*/ + uint32_t SDCN; + uint32_t SES; + + /*QSPI_ENH_CTRL0*/ + uint32_t ENHANCED_TRANS_TYPE; + uint32_t ENHANCED_ADDR_LEN; + + uint32_t ENHANCED_INST_L; + uint32_t ENHANCED_WAIT_CYCLES; + uint32_t ENHANCED_SPI_DDR_EN; + uint32_t ENHANCED_INST_DDR_EN; + uint32_t ENHANCED_CLK_STRETCH_EN; + + /*QSPI_DDR_TXDE*/ + uint32_t TXDE; + + /*QSPI_XIP_MODE*/ + uint32_t XIP_MD_BITS; + + /*QSPI_XIP_INCR_TOC*/ + uint32_t ITOC; + + /*QSPI_XIP_WRAP_TOC*/ + uint32_t WTOC; + + /*QSPI_XIP_CTRL*/ + uint32_t XIP_FRF; + uint32_t XIP_TRANS_TYPE; + uint32_t XIP_ADDR_LEN; + uint32_t XIP_INST_L; + uint32_t XIP_MD_BITS_EN; + uint32_t XIP_WAIT_CYCLES; + uint32_t XIP_DFS_HC; + uint32_t XIP_DDR_EN; + uint32_t XIP_INST_DDR_EN; + uint32_t XIP_INST_EN; + uint32_t XIP_CT_EN; + uint32_t XIP_MBL; + + /*QSPI_XIP_TOUT*/ + uint32_t XTOUT; + +} QSPI_InitType; +//////////////////////////////////////////////////////////////////////////////////////////////////// +#define QSPI_TIME_OUT_CNT 200 + +#define IS_QSPI_SPI_FRF(SPI_FRF) \ + (((SPI_FRF) == QSPI_CTRL0_SPI_FRF_STANDARD_FORMAT) || ((SPI_FRF) == QSPI_CTRL0_SPI_FRF_DUAL_FORMAT) || ((SPI_FRF) == QSPI_CTRL0_SPI_FRF_QUAD_FORMAT)) + +#define IS_QSPI_CFS(CFS) ((((CFS) >= QSPI_CTRL0_CFS_2_BIT) && ((CFS) <= QSPI_CTRL0_CFS_16_BIT)) || ((CFS) == QSPI_CTRL0_CFS_1_BIT)) + +#define IS_QSPI_SSTE(SSTE) (((SSTE) == QSPI_CTRL0_SSTE_EN) || ((SSTE) == 0)) + +#define IS_QSPI_TMOD(TMOD) \ + (((TMOD) == QSPI_CTRL0_TMOD_TX_AND_RX) || ((TMOD) == QSPI_CTRL0_TMOD_TX_ONLY) || ((TMOD) == QSPI_CTRL0_TMOD_RX_ONLY) || ((TMOD) == QSPI_CTRL0_TMOD_EEPROM_READ)) + +#define IS_QSPI_SCPOL(SCPOL) (((SCPOL) == QSPI_CTRL0_SCPOL_LOW) || ((SCPOL) == QSPI_CTRL0_SCPOL_HIGH)) + +#define IS_QSPI_SCPH(SCPH) (((SCPH) == QSPI_CTRL0_SCPH_FIRST_EDGE) || ((SCPH) == QSPI_CTRL0_SCPH_SECOND_EDGE)) + +#define IS_QSPI_FRF(FRF) (((FRF) == QSPI_CTRL0_FRF_MOTOROLA) || ((FRF) == QSPI_CTRL0_FRF_TI) || ((FRF) == QSPI_CTRL0_FRF_MICROWIRE)) + +#define IS_QSPI_DFS(DFS) (((DFS) >= QSPI_CTRL0_DFS_4_BIT) && ((DFS) <= QSPI_CTRL0_DFS_32_BIT)) + + +#define IS_QSPI_NDF(NDF) (((NDF) <= 0xFFFF)) + +#define IS_QSPI_MWMOD(MWMOD) (((MWMOD) == QSPI_MW_CTRL_MWMOD_UNSEQUENTIAL) || ((MWMOD) == QSPI_MW_CTRL_MWMOD_SEQUENTIAL)) + +#define IS_QSPI_MC_DIR(MC_DIR) (((MC_DIR) == QSPI_MW_CTRL_MC_DIR_RX) || ((MC_DIR) == QSPI_MW_CTRL_MC_DIR_TX)) + +#define IS_QSPI_MHS_EN(MHS_EN) (((MHS_EN) == QSPI_MW_CTRL_MHS_EN) || ((MHS_EN) == 0)) + +#define IS_QSPI_CLK_DIV(CLK_DIV) (((CLK_DIV) <= 0xFFFF)) + +#define IS_QSPI_TXFT(TXFT) (((TXFT) <= 0x1FFFFF)) + +#define IS_QSPI_RXFT(RXFT) (((RXFT) <= 0x1F)) + +#define IS_QSPI_TXFN(TXFN) (((TXFN) <= 0x3F)) + +#define IS_QSPI_RXFN(RXFN) (((RXFN) <= 0x3F)) + +#define IS_QSPI_DMA_CTRL(DMA_CTRL) (((DMA_CTRL) == QSPI_DMA_CTRL_TX_DMA_EN) || ((DMA_CTRL) == QSPI_DMA_CTRL_RX_DMA_EN)) + +#define IS_QSPI_DMATDL_CTRL(DMATDL_CTRL) (((DMATDL_CTRL) <= 0x3F)) + +#define IS_QSPI_DMARDL_CTRL(DMARDL_CTRL) (((DMARDL_CTRL) <= 0x3F)) + +#define IS_QSPI_SES(SES) (((SES) == QSPI_RS_DELAY_SES_RISING_EDGE) || ((SES) == QSPI_RS_DELAY_SES_FALLING_EDGE)) + +#define IS_QSPI_SDCN(SDCN) (((SDCN) <= 0xFF)) + +#define IS_QSPI_ENH_CLK_STRETCH_EN(ENH_CLK_STRETCH_EN) (((ENH_CLK_STRETCH_EN) == QSPI_ENH_CTRL0_CLK_STRETCH_EN) || ((ENH_CLK_STRETCH_EN) == 0)) + +#define IS_QSPI_ENH_INST_DDR_EN(ENH_INST_DDR_EN) (((ENH_INST_DDR_EN) == QSPI_ENH_CTRL0_INST_DDR_EN) || ((ENH_INST_DDR_EN) == 0)) + +#define IS_QSPI_ENH_SPI_DDR_EN(ENH_SPI_DDR_EN) (((ENH_SPI_DDR_EN) == QSPI_ENH_CTRL0_SPI_DDR_EN) || ((ENH_SPI_DDR_EN) == 0)) + +#define IS_QSPI_ENH_WAIT_CYCLES(ENH_WAIT_CYCLES) ((((ENH_WAIT_CYCLES) >= QSPI_ENH_CTRL0_WAIT_1CYCLES) && ((ENH_WAIT_CYCLES) <= QSPI_ENH_CTRL0_WAIT_31CYCLES)) || \ + ((ENH_WAIT_CYCLES) == 0)) + +#define IS_QSPI_ENH_INST_L(ENH_INST_L) \ + (((ENH_INST_L) == QSPI_ENH_CTRL0_INST_L_0_LINE) || ((ENH_INST_L) == QSPI_ENH_CTRL0_INST_L_4_LINE) || \ + ((ENH_INST_L) == QSPI_ENH_CTRL0_INST_L_8_LINE) || ((ENH_INST_L) == QSPI_ENH_CTRL0_INST_L_16_LINE)) + +#define IS_QSPI_ENH_ADDR_LEN(ENH_ADDR_LEN) ((((ENH_ADDR_LEN) >= QSPI_ENH_CTRL0_ADDR_LEN_4_BIT) && ((ENH_ADDR_LEN) <= QSPI_ENH_CTRL0_ADDR_LEN_60_BIT)) || \ + ((ENH_ADDR_LEN) == 0)) + +#define IS_QSPI_ENH_TRANS_TYPE(ENH_TRANS_TYPE) (((ENH_TRANS_TYPE) == QSPI_ENH_CTRL0_TRANS_TYPE_STANDARD) || \ + ((ENH_TRANS_TYPE) == QSPI_ENH_CTRL0_TRANS_TYPE_ADDRESS_BY_FRF) || \ + ((ENH_TRANS_TYPE) == QSPI_ENH_CTRL0_TRANS_TYPE_ALL_BY_FRF)) + + +#define IS_QSPI_DDR_TXDE(DDR_TXDE) (((DDR_TXDE) <= 0xFF)) + +#define IS_QSPI_XIP_MODE(XIP_MODE) (((XIP_MODE) <= 0xFFFF)) + +#define IS_QSPI_XIP_INCR_TOC(XIP_INCR_TOC) (((XIP_INCR_TOC) <= 0xFFFF)) + +#define IS_QSPI_XIP_WRAP_TOC(XIP_WRAP_TOC) (((XIP_WRAP_TOC) <= 0xFFFF)) + +#define IS_QSPI_XIP_TOUT(XIP_TOUT) (((XIP_TOUT) <= 0xFF)) + +#define IS_QSPI_XIP_MBL(XIP_MBL) \ + (((XIP_MBL) == QSPI_XIP_CTRL_XIP_MBL_LEN_2_BIT) || ((XIP_MBL) == QSPI_XIP_CTRL_XIP_MBL_LEN_4_BIT) || \ + ((XIP_MBL) == QSPI_XIP_CTRL_XIP_MBL_LEN_8_BIT) || ((XIP_MBL) == QSPI_XIP_CTRL_XIP_MBL_LEN_16_BIT)) + +#define IS_QSPI_XIP_CT_EN(XIP_CT_EN) (((XIP_CT_EN) == QSPI_XIP_CTRL_XIP_CT_EN) || ((XIP_CT_EN) == 0)) + +#define IS_QSPI_XIP_INST_EN(XIP_INST_EN) (((XIP_INST_EN) == QSPI_XIP_CTRL_XIP_INST_EN) || ((XIP_INST_EN) == 0)) + +#define IS_QSPI_INST_DDR_EN(INST_DDR_EN) (((INST_DDR_EN) == QSPI_XIP_CTRL_XIP_INST_EN) || ((INST_DDR_EN) == 0)) + +#define IS_QSPI_DDR_EN(DDR_EN) (((DDR_EN) == QSPI_XIP_CTRL_DDR_EN) || ((DDR_EN) == 0)) + +#define IS_QSPI_XIP_DFS_HC(XIP_DFS_HC) (((XIP_DFS_HC) == QSPI_XIP_CTRL_DFS_HC) || ((XIP_DFS_HC) == 0)) + +#define IS_QSPI_XIP_WAIT_CYCLES(XIP_WAIT_CYCLES) ((((XIP_WAIT_CYCLES) >= QSPI_XIP_CTRL_WAIT_1CYCLES) && ((XIP_WAIT_CYCLES) <= QSPI_XIP_CTRL_WAIT_31CYCLES)) || \ + ((XIP_WAIT_CYCLES) == 0)) + +#define IS_QSPI_XIP_MD_BIT_EN(XIP_MD_BIT_EN) (((XIP_MD_BIT_EN) == QSPI_XIP_CTRL_MD_BIT_EN) || ((XIP_MD_BIT_EN) == 0)) + +#define IS_QSPI_XIP_INST_L(XIP_INST_L) \ + (((XIP_INST_L) == QSPI_XIP_CTRL_INST_L_0_LINE) || ((XIP_INST_L) == QSPI_XIP_CTRL_INST_L_4_LINE) || \ + ((XIP_INST_L) == QSPI_XIP_CTRL_INST_L_8_LINE) || ((XIP_INST_L) == QSPI_XIP_CTRL_INST_L_16_LINE)) + +#define IS_QSPI_XIP_ADDR_LEN(XIP_ADDR_LEN) ((((XIP_ADDR_LEN) >= QSPI_XIP_CTRL_ADDR_4BIT) && ((XIP_ADDR_LEN) <= QSPI_XIP_CTRL_ADDR_60BIT)) || \ + ((XIP_ADDR_LEN) == 0)) + +#define IS_QSPI_XIP_TRANS_TYPE(XIP_TRANS_TYPE) (((XIP_TRANS_TYPE) == QSPI_XIP_CTRL_TRANS_TYPE_STANDARD_SPI) || \ + ((XIP_TRANS_TYPE) == QSPI_XIP_CTRL_TRANS_TYPE_ADDRESS_BY_XIP_FRF) || \ + ((XIP_TRANS_TYPE) == QSPI_XIP_CTRL_TRANS_TYPE_INSTRUCT_BY_XIP_FRF)) + +#define IS_QSPI_XIP_FRF(XIP_FRF) (((XIP_FRF) == QSPI_XIP_CTRL_FRF_2_LINE) || ((XIP_FRF) == QSPI_XIP_CTRL_FRF_4_LINE) || ((XIP_FRF) == 0)) + + + + + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +void QSPI_Cmd(bool cmd); +void QSPI_XIP_Cmd(bool cmd); +void QSPI_DeInit(void); +void QspiInitConfig(QSPI_InitType* QSPI_InitStruct); +void QSPI_GPIO(QSPI_NSS_PORT_SEL qspi_nss_port_sel, bool IO1_Input, bool IO3_Output); +void QSPI_Tx_DMA_CTRL_Config(uint8_t Cmd,uint8_t TxDataLevel); +void QSPI_Rx_DMA_CTRL_Config(uint8_t Cmd, uint8_t RxDataLevel); +uint16_t QSPI_GetITStatus(uint16_t FLAG); +void QSPI_ClearITFLAG(uint16_t FLAG); +void QSPI_XIP_ClearITFLAG(uint16_t FLAG); +bool GetQspiBusyStatus(void); +bool GetQspiTxDataBusyStatus(void); +bool GetQspiTxDataEmptyStatus(void); +bool GetQspiRxHaveDataStatus(void); +bool GetQspiRxDataFullStatus(void); +bool GetQspiDataConflictErrorStatus(void); +void QspiSendWord(uint32_t SendData); +uint32_t QspiReadWord(void); +uint32_t QspiGetDataPointer(void); +uint32_t QspiReadRxFifoNum(void); +void ClrFifo(void); +uint32_t GetFifoData(uint32_t* pData, uint32_t Len); +void QspiSendAndGetWords(uint32_t* pSrcData, uint32_t* pDstData, uint32_t cnt); +uint32_t QspiSendWordAndGetWords(uint32_t WrData, uint32_t* pRdData, uint8_t LastRd); + + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G4FR_QSPI_H__ */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_rcc.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_rcc.h new file mode 100644 index 0000000000..a5786f2d82 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_rcc.h @@ -0,0 +1,706 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_rcc.h + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_RCC_H__ +#define __N32G4FR_RCC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup RCC + * @{ + */ + +/** @addtogroup RCC_Exported_Types + * @{ + */ + +typedef struct +{ + uint32_t SysclkFreq; /*!< returns SYSCLK clock frequency expressed in Hz */ + uint32_t HclkFreq; /*!< returns HCLK clock frequency expressed in Hz */ + uint32_t Pclk1Freq; /*!< returns PCLK1 clock frequency expressed in Hz */ + uint32_t Pclk2Freq; /*!< returns PCLK2 clock frequency expressed in Hz */ + uint32_t AdcPllClkFreq; /*!< returns ADCPLLCLK clock frequency expressed in Hz */ + uint32_t AdcHclkFreq; /*!< returns ADCHCLK clock frequency expressed in Hz */ +} RCC_ClocksType; + +/** + * @} + */ + +/** @addtogroup RCC_Exported_Constants + * @{ + */ + +/** @addtogroup HSE_configuration + * @{ + */ + +#define RCC_HSE_DISABLE ((uint32_t)0x00000000) +#define RCC_HSE_ENABLE ((uint32_t)0x00010000) +#define RCC_HSE_BYPASS ((uint32_t)0x00040000) +#define IS_RCC_HSE(HSE) (((HSE) == RCC_HSE_DISABLE) || ((HSE) == RCC_HSE_ENABLE) || ((HSE) == RCC_HSE_BYPASS)) + +/** + * @} + */ + +/** @addtogroup PLL_entry_clock_source + * @{ + */ + +#define RCC_PLL_SRC_HSI_DIV2 ((uint32_t)0x00000000) + +#define RCC_PLL_SRC_HSE_DIV1 ((uint32_t)0x00010000) +#define RCC_PLL_SRC_HSE_DIV2 ((uint32_t)0x00030000) +#define IS_RCC_PLL_SRC(SOURCE) \ + (((SOURCE) == RCC_PLL_SRC_HSI_DIV2) || ((SOURCE) == RCC_PLL_SRC_HSE_DIV1) || ((SOURCE) == RCC_PLL_SRC_HSE_DIV2)) + +/** + * @} + */ + +/** @addtogroup PLL_multiplication_factor + * @{ + */ +#define RCC_PLL_MUL_2 ((uint32_t)0x00000000) +#define RCC_PLL_MUL_3 ((uint32_t)0x00040000) +#define RCC_PLL_MUL_4 ((uint32_t)0x00080000) +#define RCC_PLL_MUL_5 ((uint32_t)0x000C0000) +#define RCC_PLL_MUL_6 ((uint32_t)0x00100000) +#define RCC_PLL_MUL_7 ((uint32_t)0x00140000) +#define RCC_PLL_MUL_8 ((uint32_t)0x00180000) +#define RCC_PLL_MUL_9 ((uint32_t)0x001C0000) +#define RCC_PLL_MUL_10 ((uint32_t)0x00200000) +#define RCC_PLL_MUL_11 ((uint32_t)0x00240000) +#define RCC_PLL_MUL_12 ((uint32_t)0x00280000) +#define RCC_PLL_MUL_13 ((uint32_t)0x002C0000) +#define RCC_PLL_MUL_14 ((uint32_t)0x00300000) +#define RCC_PLL_MUL_15 ((uint32_t)0x00340000) +#define RCC_PLL_MUL_16 ((uint32_t)0x00380000) +#define RCC_PLL_MUL_17 ((uint32_t)0x08000000) +#define RCC_PLL_MUL_18 ((uint32_t)0x08040000) +#define RCC_PLL_MUL_19 ((uint32_t)0x08080000) +#define RCC_PLL_MUL_20 ((uint32_t)0x080C0000) +#define RCC_PLL_MUL_21 ((uint32_t)0x08100000) +#define RCC_PLL_MUL_22 ((uint32_t)0x08140000) +#define RCC_PLL_MUL_23 ((uint32_t)0x08180000) +#define RCC_PLL_MUL_24 ((uint32_t)0x081C0000) +#define RCC_PLL_MUL_25 ((uint32_t)0x08200000) +#define RCC_PLL_MUL_26 ((uint32_t)0x08240000) +#define RCC_PLL_MUL_27 ((uint32_t)0x08280000) +#define RCC_PLL_MUL_28 ((uint32_t)0x082C0000) +#define RCC_PLL_MUL_29 ((uint32_t)0x08300000) +#define RCC_PLL_MUL_30 ((uint32_t)0x08340000) +#define RCC_PLL_MUL_31 ((uint32_t)0x08380000) +#define RCC_PLL_MUL_32 ((uint32_t)0x083C0000) +#define IS_RCC_PLL_MUL(MUL) \ + (((MUL) == RCC_PLL_MUL_2) || ((MUL) == RCC_PLL_MUL_3) || ((MUL) == RCC_PLL_MUL_4) || ((MUL) == RCC_PLL_MUL_5) \ + || ((MUL) == RCC_PLL_MUL_6) || ((MUL) == RCC_PLL_MUL_7) || ((MUL) == RCC_PLL_MUL_8) || ((MUL) == RCC_PLL_MUL_9) \ + || ((MUL) == RCC_PLL_MUL_10) || ((MUL) == RCC_PLL_MUL_11) || ((MUL) == RCC_PLL_MUL_12) \ + || ((MUL) == RCC_PLL_MUL_13) || ((MUL) == RCC_PLL_MUL_14) || ((MUL) == RCC_PLL_MUL_15) \ + || ((MUL) == RCC_PLL_MUL_16) || ((MUL) == RCC_PLL_MUL_17) || ((MUL) == RCC_PLL_MUL_18) \ + || ((MUL) == RCC_PLL_MUL_19) || ((MUL) == RCC_PLL_MUL_20) || ((MUL) == RCC_PLL_MUL_21) \ + || ((MUL) == RCC_PLL_MUL_22) || ((MUL) == RCC_PLL_MUL_23) || ((MUL) == RCC_PLL_MUL_24) \ + || ((MUL) == RCC_PLL_MUL_25) || ((MUL) == RCC_PLL_MUL_26) || ((MUL) == RCC_PLL_MUL_27) \ + || ((MUL) == RCC_PLL_MUL_28) || ((MUL) == RCC_PLL_MUL_29) || ((MUL) == RCC_PLL_MUL_30) \ + || ((MUL) == RCC_PLL_MUL_31) || ((MUL) == RCC_PLL_MUL_32)) + +/** + * @} + */ + +/** @addtogroup System_clock_source + * @{ + */ + +#define RCC_SYSCLK_SRC_HSI ((uint32_t)0x00000000) +#define RCC_SYSCLK_SRC_HSE ((uint32_t)0x00000001) +#define RCC_SYSCLK_SRC_PLLCLK ((uint32_t)0x00000002) +#define IS_RCC_SYSCLK_SRC(SOURCE) \ + (((SOURCE) == RCC_SYSCLK_SRC_HSI) || ((SOURCE) == RCC_SYSCLK_SRC_HSE) || ((SOURCE) == RCC_SYSCLK_SRC_PLLCLK)) +/** + * @} + */ + +/** @addtogroup AHB_clock_source + * @{ + */ + +#define RCC_SYSCLK_DIV1 ((uint32_t)0x00000000) +#define RCC_SYSCLK_DIV2 ((uint32_t)0x00000080) +#define RCC_SYSCLK_DIV4 ((uint32_t)0x00000090) +#define RCC_SYSCLK_DIV8 ((uint32_t)0x000000A0) +#define RCC_SYSCLK_DIV16 ((uint32_t)0x000000B0) +#define RCC_SYSCLK_DIV64 ((uint32_t)0x000000C0) +#define RCC_SYSCLK_DIV128 ((uint32_t)0x000000D0) +#define RCC_SYSCLK_DIV256 ((uint32_t)0x000000E0) +#define RCC_SYSCLK_DIV512 ((uint32_t)0x000000F0) +#define IS_RCC_SYSCLK_DIV(HCLK) \ + (((HCLK) == RCC_SYSCLK_DIV1) || ((HCLK) == RCC_SYSCLK_DIV2) || ((HCLK) == RCC_SYSCLK_DIV4) \ + || ((HCLK) == RCC_SYSCLK_DIV8) || ((HCLK) == RCC_SYSCLK_DIV16) || ((HCLK) == RCC_SYSCLK_DIV64) \ + || ((HCLK) == RCC_SYSCLK_DIV128) || ((HCLK) == RCC_SYSCLK_DIV256) || ((HCLK) == RCC_SYSCLK_DIV512)) +/** + * @} + */ + +/** @addtogroup APB1_APB2_clock_source + * @{ + */ + +#define RCC_HCLK_DIV1 ((uint32_t)0x00000000) +#define RCC_HCLK_DIV2 ((uint32_t)0x00000400) +#define RCC_HCLK_DIV4 ((uint32_t)0x00000500) +#define RCC_HCLK_DIV8 ((uint32_t)0x00000600) +#define RCC_HCLK_DIV16 ((uint32_t)0x00000700) +#define IS_RCC_HCLK_DIV(PCLK) \ + (((PCLK) == RCC_HCLK_DIV1) || ((PCLK) == RCC_HCLK_DIV2) || ((PCLK) == RCC_HCLK_DIV4) || ((PCLK) == RCC_HCLK_DIV8) \ + || ((PCLK) == RCC_HCLK_DIV16)) +/** + * @} + */ + +/** @addtogroup RCC_Interrupt_source + * @{ + */ + +#define RCC_INT_LSIRDIF ((uint8_t)0x01) +#define RCC_INT_LSERDIF ((uint8_t)0x02) +#define RCC_INT_HSIRDIF ((uint8_t)0x04) +#define RCC_INT_HSERDIF ((uint8_t)0x08) +#define RCC_INT_PLLRDIF ((uint8_t)0x10) +#define RCC_INT_CLKSSIF ((uint8_t)0x80) + +#define IS_RCC_INT(IT) ((((IT) & (uint8_t)0xE0) == 0x00) && ((IT) != 0x00)) +#define IS_RCC_GET_INT(IT) \ + (((IT) == RCC_INT_LSIRDIF) || ((IT) == RCC_INT_LSERDIF) || ((IT) == RCC_INT_HSIRDIF) || ((IT) == RCC_INT_HSERDIF) \ + || ((IT) == RCC_INT_PLLRDIF) || ((IT) == RCC_INT_CLKSSIF)) +#define IS_RCC_CLR_INT(IT) ((((IT) & (uint8_t)0x60) == 0x00) && ((IT) != 0x00)) + +/** + * @} + */ + +/** @addtogroup USB_Device_clock_source + * @{ + */ + +#define RCC_USBCLK_SRC_PLLCLK_DIV1_5 ((uint8_t)0x00) +#define RCC_USBCLK_SRC_PLLCLK_DIV1 ((uint8_t)0x01) +#define RCC_USBCLK_SRC_PLLCLK_DIV2 ((uint8_t)0x02) +#define RCC_USBCLK_SRC_PLLCLK_DIV3 ((uint8_t)0x03) + +#define IS_RCC_USBCLK_SRC(SOURCE) \ + (((SOURCE) == RCC_USBCLK_SRC_PLLCLK_DIV1_5) || ((SOURCE) == RCC_USBCLK_SRC_PLLCLK_DIV1) \ + || ((SOURCE) == RCC_USBCLK_SRC_PLLCLK_DIV2) || ((SOURCE) == RCC_USBCLK_SRC_PLLCLK_DIV3)) +/** + * @} + */ + +/** @addtogroup ADC_clock_source + * @{ + */ + +#define RCC_PCLK2_DIV2 ((uint32_t)0x00000000) +#define RCC_PCLK2_DIV4 ((uint32_t)0x00004000) +#define RCC_PCLK2_DIV6 ((uint32_t)0x00008000) +#define RCC_PCLK2_DIV8 ((uint32_t)0x0000C000) +#define IS_RCC_PCLK2_DIV(ADCCLK) \ + (((ADCCLK) == RCC_PCLK2_DIV2) || ((ADCCLK) == RCC_PCLK2_DIV4) || ((ADCCLK) == RCC_PCLK2_DIV6) \ + || ((ADCCLK) == RCC_PCLK2_DIV8)) + +/** + * @} + */ + +/** @addtogroup RCC_CFGR2_Config + * @{ + */ +#define RCC_TIM18CLK_SRC_TIM18CLK ((uint32_t)0x00000000) +#define RCC_TIM18CLK_SRC_SYSCLK ((uint32_t)0x20000000) +#define IS_RCC_TIM18CLKSRC(TIM18CLK) \ + (((TIM18CLK) == RCC_TIM18CLK_SRC_TIM18CLK) || ((TIM18CLK) == RCC_TIM18CLK_SRC_SYSCLK)) + +#define RCC_RNGCCLK_SYSCLK_DIV1 ((uint32_t)0x00000000) +#define RCC_RNGCCLK_SYSCLK_DIV2 ((uint32_t)0x01000000) +#define RCC_RNGCCLK_SYSCLK_DIV3 ((uint32_t)0x02000000) +#define RCC_RNGCCLK_SYSCLK_DIV4 ((uint32_t)0x03000000) +#define RCC_RNGCCLK_SYSCLK_DIV5 ((uint32_t)0x04000000) +#define RCC_RNGCCLK_SYSCLK_DIV6 ((uint32_t)0x05000000) +#define RCC_RNGCCLK_SYSCLK_DIV7 ((uint32_t)0x06000000) +#define RCC_RNGCCLK_SYSCLK_DIV8 ((uint32_t)0x07000000) +#define RCC_RNGCCLK_SYSCLK_DIV9 ((uint32_t)0x08000000) +#define RCC_RNGCCLK_SYSCLK_DIV10 ((uint32_t)0x09000000) +#define RCC_RNGCCLK_SYSCLK_DIV11 ((uint32_t)0x0A000000) +#define RCC_RNGCCLK_SYSCLK_DIV12 ((uint32_t)0x0B000000) +#define RCC_RNGCCLK_SYSCLK_DIV13 ((uint32_t)0x0C000000) +#define RCC_RNGCCLK_SYSCLK_DIV14 ((uint32_t)0x0D000000) +#define RCC_RNGCCLK_SYSCLK_DIV15 ((uint32_t)0x0E000000) +#define RCC_RNGCCLK_SYSCLK_DIV16 ((uint32_t)0x0F000000) +#define RCC_RNGCCLK_SYSCLK_DIV17 ((uint32_t)0x10000000) +#define RCC_RNGCCLK_SYSCLK_DIV18 ((uint32_t)0x11000000) +#define RCC_RNGCCLK_SYSCLK_DIV19 ((uint32_t)0x12000000) +#define RCC_RNGCCLK_SYSCLK_DIV20 ((uint32_t)0x13000000) +#define RCC_RNGCCLK_SYSCLK_DIV21 ((uint32_t)0x14000000) +#define RCC_RNGCCLK_SYSCLK_DIV22 ((uint32_t)0x15000000) +#define RCC_RNGCCLK_SYSCLK_DIV23 ((uint32_t)0x16000000) +#define RCC_RNGCCLK_SYSCLK_DIV24 ((uint32_t)0x17000000) +#define RCC_RNGCCLK_SYSCLK_DIV25 ((uint32_t)0x18000000) +#define RCC_RNGCCLK_SYSCLK_DIV26 ((uint32_t)0x19000000) +#define RCC_RNGCCLK_SYSCLK_DIV27 ((uint32_t)0x1A000000) +#define RCC_RNGCCLK_SYSCLK_DIV28 ((uint32_t)0x1B000000) +#define RCC_RNGCCLK_SYSCLK_DIV29 ((uint32_t)0x1C000000) +#define RCC_RNGCCLK_SYSCLK_DIV30 ((uint32_t)0x1D000000) +#define RCC_RNGCCLK_SYSCLK_DIV31 ((uint32_t)0x1E000000) +#define RCC_RNGCCLK_SYSCLK_DIV32 ((uint32_t)0x1F000000) +#define IS_RCC_RNGCCLKPRE(DIV) \ + (((DIV) == RCC_RNGCCLK_SYSCLK_DIV1) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV2) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV3) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV4) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV5) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV6) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV7) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV8) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV9) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV10) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV11) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV12) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV13) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV14) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV15) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV16) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV17) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV18) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV19) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV20) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV21) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV22) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV23) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV24) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV25) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV26) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV27) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV28) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV29) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV30) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV31) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV32)) + +#define RCC_ADC1MCLK_SRC_HSI ((uint32_t)0x00000000) +#define RCC_ADC1MCLK_SRC_HSE ((uint32_t)0x00000400) +#define IS_RCC_ADC1MCLKSRC(ADC1MCLK) (((ADC1MCLK) == RCC_ADC1MCLK_SRC_HSI) || ((ADC1MCLK) == RCC_ADC1MCLK_SRC_HSE)) + +#define RCC_ADC1MCLK_DIV1 ((uint32_t)0x00000000) +#define RCC_ADC1MCLK_DIV2 ((uint32_t)0x00000800) +#define RCC_ADC1MCLK_DIV3 ((uint32_t)0x00001000) +#define RCC_ADC1MCLK_DIV4 ((uint32_t)0x00001800) +#define RCC_ADC1MCLK_DIV5 ((uint32_t)0x00002000) +#define RCC_ADC1MCLK_DIV6 ((uint32_t)0x00002800) +#define RCC_ADC1MCLK_DIV7 ((uint32_t)0x00003000) +#define RCC_ADC1MCLK_DIV8 ((uint32_t)0x00003800) +#define RCC_ADC1MCLK_DIV9 ((uint32_t)0x00004000) +#define RCC_ADC1MCLK_DIV10 ((uint32_t)0x00004800) +#define RCC_ADC1MCLK_DIV11 ((uint32_t)0x00005000) +#define RCC_ADC1MCLK_DIV12 ((uint32_t)0x00005800) +#define RCC_ADC1MCLK_DIV13 ((uint32_t)0x00006000) +#define RCC_ADC1MCLK_DIV14 ((uint32_t)0x00006800) +#define RCC_ADC1MCLK_DIV15 ((uint32_t)0x00007000) +#define RCC_ADC1MCLK_DIV16 ((uint32_t)0x00007800) +#define RCC_ADC1MCLK_DIV17 ((uint32_t)0x00008000) +#define RCC_ADC1MCLK_DIV18 ((uint32_t)0x00008800) +#define RCC_ADC1MCLK_DIV19 ((uint32_t)0x00009000) +#define RCC_ADC1MCLK_DIV20 ((uint32_t)0x00009800) +#define RCC_ADC1MCLK_DIV21 ((uint32_t)0x0000A000) +#define RCC_ADC1MCLK_DIV22 ((uint32_t)0x0000A800) +#define RCC_ADC1MCLK_DIV23 ((uint32_t)0x0000B000) +#define RCC_ADC1MCLK_DIV24 ((uint32_t)0x0000B800) +#define RCC_ADC1MCLK_DIV25 ((uint32_t)0x0000C000) +#define RCC_ADC1MCLK_DIV26 ((uint32_t)0x0000C800) +#define RCC_ADC1MCLK_DIV27 ((uint32_t)0x0000D000) +#define RCC_ADC1MCLK_DIV28 ((uint32_t)0x0000D800) +#define RCC_ADC1MCLK_DIV29 ((uint32_t)0x0000E000) +#define RCC_ADC1MCLK_DIV30 ((uint32_t)0x0000E800) +#define RCC_ADC1MCLK_DIV31 ((uint32_t)0x0000F000) +#define RCC_ADC1MCLK_DIV32 ((uint32_t)0x0000F800) +#define IS_RCC_ADC1MCLKPRE(DIV) \ + (((DIV) == RCC_ADC1MCLK_DIV1) || ((DIV) == RCC_ADC1MCLK_DIV2) || ((DIV) == RCC_ADC1MCLK_DIV3) \ + || ((DIV) == RCC_ADC1MCLK_DIV4) || ((DIV) == RCC_ADC1MCLK_DIV5) || ((DIV) == RCC_ADC1MCLK_DIV6) \ + || ((DIV) == RCC_ADC1MCLK_DIV7) || ((DIV) == RCC_ADC1MCLK_DIV8) || ((DIV) == RCC_ADC1MCLK_DIV9) \ + || ((DIV) == RCC_ADC1MCLK_DIV10) || ((DIV) == RCC_ADC1MCLK_DIV11) || ((DIV) == RCC_ADC1MCLK_DIV12) \ + || ((DIV) == RCC_ADC1MCLK_DIV13) || ((DIV) == RCC_ADC1MCLK_DIV14) || ((DIV) == RCC_ADC1MCLK_DIV15) \ + || ((DIV) == RCC_ADC1MCLK_DIV16) || ((DIV) == RCC_ADC1MCLK_DIV17) || ((DIV) == RCC_ADC1MCLK_DIV18) \ + || ((DIV) == RCC_ADC1MCLK_DIV19) || ((DIV) == RCC_ADC1MCLK_DIV20) || ((DIV) == RCC_ADC1MCLK_DIV21) \ + || ((DIV) == RCC_ADC1MCLK_DIV22) || ((DIV) == RCC_ADC1MCLK_DIV23) || ((DIV) == RCC_ADC1MCLK_DIV24) \ + || ((DIV) == RCC_ADC1MCLK_DIV25) || ((DIV) == RCC_ADC1MCLK_DIV26) || ((DIV) == RCC_ADC1MCLK_DIV27) \ + || ((DIV) == RCC_ADC1MCLK_DIV28) || ((DIV) == RCC_ADC1MCLK_DIV29) || ((DIV) == RCC_ADC1MCLK_DIV30) \ + || ((DIV) == RCC_ADC1MCLK_DIV31) || ((DIV) == RCC_ADC1MCLK_DIV32)) + +#define RCC_ADCPLLCLK_DISABLE ((uint32_t)0xFFFFFEFF) +#define RCC_ADCPLLCLK_DIV1 ((uint32_t)0x00000100) +#define RCC_ADCPLLCLK_DIV2 ((uint32_t)0x00000110) +#define RCC_ADCPLLCLK_DIV4 ((uint32_t)0x00000120) +#define RCC_ADCPLLCLK_DIV6 ((uint32_t)0x00000130) +#define RCC_ADCPLLCLK_DIV8 ((uint32_t)0x00000140) +#define RCC_ADCPLLCLK_DIV10 ((uint32_t)0x00000150) +#define RCC_ADCPLLCLK_DIV12 ((uint32_t)0x00000160) +#define RCC_ADCPLLCLK_DIV16 ((uint32_t)0x00000170) +#define RCC_ADCPLLCLK_DIV32 ((uint32_t)0x00000180) +#define RCC_ADCPLLCLK_DIV64 ((uint32_t)0x00000190) +#define RCC_ADCPLLCLK_DIV128 ((uint32_t)0x000001A0) +#define RCC_ADCPLLCLK_DIV256 ((uint32_t)0x000001B0) +#define RCC_ADCPLLCLK_DIV_OTHERS ((uint32_t)0x000001C0) +#define IS_RCC_ADCPLLCLKPRE(DIV) \ + (((DIV) == RCC_ADCPLLCLK_DIV1) || ((DIV) == RCC_ADCPLLCLK_DIV2) || ((DIV) == RCC_ADCPLLCLK_DIV4) \ + || ((DIV) == RCC_ADCPLLCLK_DIV6) || ((DIV) == RCC_ADCPLLCLK_DIV8) || ((DIV) == RCC_ADCPLLCLK_DIV10) \ + || ((DIV) == RCC_ADCPLLCLK_DIV12) || ((DIV) == RCC_ADCPLLCLK_DIV16) || ((DIV) == RCC_ADCPLLCLK_DIV32) \ + || ((DIV) == RCC_ADCPLLCLK_DIV64) || ((DIV) == RCC_ADCPLLCLK_DIV128) || ((DIV) == RCC_ADCPLLCLK_DIV256) \ + || ((DIV) == RCC_ADC1MCLK_DIV15) || ((DIV) == RCC_ADCPLLCLK_DIV16) \ + || (((DIV)&RCC_ADCPLLCLK_DIV_OTHERS) == 0x000001C0)) + +#define RCC_ADCHCLK_DIV1 ((uint32_t)0x00000000) +#define RCC_ADCHCLK_DIV2 ((uint32_t)0x00000001) +#define RCC_ADCHCLK_DIV4 ((uint32_t)0x00000002) +#define RCC_ADCHCLK_DIV6 ((uint32_t)0x00000003) +#define RCC_ADCHCLK_DIV8 ((uint32_t)0x00000004) +#define RCC_ADCHCLK_DIV10 ((uint32_t)0x00000005) +#define RCC_ADCHCLK_DIV12 ((uint32_t)0x00000006) +#define RCC_ADCHCLK_DIV16 ((uint32_t)0x00000007) +#define RCC_ADCHCLK_DIV32 ((uint32_t)0x00000008) +#define RCC_ADCHCLK_DIV_OTHERS ((uint32_t)0x00000008) +#define IS_RCC_ADCHCLKPRE(DIV) \ + (((DIV) == RCC_ADCHCLK_DIV1) || ((DIV) == RCC_ADCHCLK_DIV2) || ((DIV) == RCC_ADCHCLK_DIV4) \ + || ((DIV) == RCC_ADCHCLK_DIV6) || ((DIV) == RCC_ADCHCLK_DIV8) || ((DIV) == RCC_ADCHCLK_DIV10) \ + || ((DIV) == RCC_ADCHCLK_DIV12) || ((DIV) == RCC_ADCHCLK_DIV16) || ((DIV) == RCC_ADCHCLK_DIV32) \ + || (((DIV)&RCC_ADCHCLK_DIV_OTHERS) != 0x00)) +/** + * @} + */ + +/** @addtogroup RCC_CFGR3_Config + * @{ + */ +#define RCC_BOR_RST_ENABLE ((uint32_t)0x00000040) + +#define RCC_TRNG1MCLK_ENABLE ((uint32_t)0x00040000) +#define RCC_TRNG1MCLK_DISABLE ((uint32_t)0xFFFBFFFF) + +#define RCC_TRNG1MCLK_SRC_HSI ((uint32_t)0x00000000) +#define RCC_TRNG1MCLK_SRC_HSE ((uint32_t)0x00020000) +#define IS_RCC_TRNG1MCLK_SRC(TRNG1MCLK) \ + (((TRNG1MCLK) == RCC_TRNG1MCLK_SRC_HSI) || ((TRNG1MCLK) == RCC_TRNG1MCLK_SRC_HSE)) + +#define RCC_TRNG1MCLK_DIV2 ((uint32_t)0x00000800) +#define RCC_TRNG1MCLK_DIV4 ((uint32_t)0x00001800) +#define RCC_TRNG1MCLK_DIV6 ((uint32_t)0x00002800) +#define RCC_TRNG1MCLK_DIV8 ((uint32_t)0x00003800) +#define RCC_TRNG1MCLK_DIV10 ((uint32_t)0x00004800) +#define RCC_TRNG1MCLK_DIV12 ((uint32_t)0x00005800) +#define RCC_TRNG1MCLK_DIV14 ((uint32_t)0x00006800) +#define RCC_TRNG1MCLK_DIV16 ((uint32_t)0x00007800) +#define RCC_TRNG1MCLK_DIV18 ((uint32_t)0x00008800) +#define RCC_TRNG1MCLK_DIV20 ((uint32_t)0x00009800) +#define RCC_TRNG1MCLK_DIV22 ((uint32_t)0x0000A800) +#define RCC_TRNG1MCLK_DIV24 ((uint32_t)0x0000B800) +#define RCC_TRNG1MCLK_DIV26 ((uint32_t)0x0000C800) +#define RCC_TRNG1MCLK_DIV28 ((uint32_t)0x0000D800) +#define RCC_TRNG1MCLK_DIV30 ((uint32_t)0x0000E800) +#define RCC_TRNG1MCLK_DIV32 ((uint32_t)0x0000F800) +#define IS_RCC_TRNG1MCLKPRE(VAL) \ + (((VAL) == RCC_TRNG1MCLK_DIV2) || ((VAL) == RCC_TRNG1MCLK_DIV4) || ((VAL) == RCC_TRNG1MCLK_DIV6) \ + || ((VAL) == RCC_TRNG1MCLK_DIV8) || ((VAL) == RCC_TRNG1MCLK_DIV10) || ((VAL) == RCC_TRNG1MCLK_DIV12) \ + || ((VAL) == RCC_TRNG1MCLK_DIV14) || ((VAL) == RCC_TRNG1MCLK_DIV16) || ((VAL) == RCC_TRNG1MCLK_DIV18) \ + || ((VAL) == RCC_TRNG1MCLK_DIV20) || ((VAL) == RCC_TRNG1MCLK_DIV22) || ((VAL) == RCC_TRNG1MCLK_DIV24) \ + || ((VAL) == RCC_TRNG1MCLK_DIV26) || ((VAL) == RCC_TRNG1MCLK_DIV28) || ((VAL) == RCC_TRNG1MCLK_DIV30) \ + || ((VAL) == RCC_TRNG1MCLK_DIV32)) + +/** + * @} + */ + +/** @addtogroup LSE_configuration + * @{ + */ + +#define RCC_LSE_DISABLE ((uint8_t)0x00) +#define RCC_LSE_ENABLE ((uint8_t)0x01) +#define RCC_LSE_BYPASS ((uint8_t)0x04) +#define IS_RCC_LSE(LSE) (((LSE) == RCC_LSE_DISABLE) || ((LSE) == RCC_LSE_ENABLE) || ((LSE) == RCC_LSE_BYPASS)) +/** + * @} + */ + +/** @addtogroup RTC_clock_source + * @{ + */ + +#define RCC_RTCCLK_SRC_LSE ((uint32_t)0x00000100) +#define RCC_RTCCLK_SRC_LSI ((uint32_t)0x00000200) +#define RCC_RTCCLK_SRC_HSE_DIV128 ((uint32_t)0x00000300) +#define IS_RCC_RTCCLK_SRC(SOURCE) \ + (((SOURCE) == RCC_RTCCLK_SRC_LSE) || ((SOURCE) == RCC_RTCCLK_SRC_LSI) || ((SOURCE) == RCC_RTCCLK_SRC_HSE_DIV128)) +/** + * @} + */ + +/** @addtogroup AHB_peripheral + * @{ + */ + +#define RCC_AHB_PERIPH_DMA1 ((uint32_t)0x00000001) +#define RCC_AHB_PERIPH_DMA2 ((uint32_t)0x00000002) +#define RCC_AHB_PERIPH_SRAM ((uint32_t)0x00000004) +#define RCC_AHB_PERIPH_FLITF ((uint32_t)0x00000010) +#define RCC_AHB_PERIPH_CRC ((uint32_t)0x00000040) +#define RCC_AHB_PERIPH_RNGC ((uint32_t)0x00000200) +#define RCC_AHB_PERIPH_SDIO ((uint32_t)0x00000400) +#define RCC_AHB_PERIPH_SAC ((uint32_t)0x00000800) +#define RCC_AHB_PERIPH_ADC1 ((uint32_t)0x00001000) +#define RCC_AHB_PERIPH_ADC2 ((uint32_t)0x00002000) +#define RCC_AHB_PERIPH_ADC3 ((uint32_t)0x00004000) +#define RCC_AHB_PERIPH_ADC4 ((uint32_t)0x00008000) +#define RCC_AHB_PERIPH_ETHMAC ((uint32_t)0x00010000) +#define RCC_AHB_PERIPH_QSPI ((uint32_t)0x00020000) + +#define IS_RCC_AHB_PERIPH(PERIPH) ((((PERIPH)&0xFFFC02A8) == 0x00) && ((PERIPH) != 0x00)) + +/** + * @} + */ + +/** @addtogroup APB2_peripheral + * @{ + */ + +#define RCC_APB2_PERIPH_AFIO ((uint32_t)0x00000001) +#define RCC_APB2_PERIPH_GPIOA ((uint32_t)0x00000004) +#define RCC_APB2_PERIPH_GPIOB ((uint32_t)0x00000008) +#define RCC_APB2_PERIPH_GPIOC ((uint32_t)0x00000010) +#define RCC_APB2_PERIPH_GPIOD ((uint32_t)0x00000020) +#define RCC_APB2_PERIPH_GPIOE ((uint32_t)0x00000040) +#define RCC_APB2_PERIPH_TIM1 ((uint32_t)0x00000800) +#define RCC_APB2_PERIPH_SPI1 ((uint32_t)0x00001000) +#define RCC_APB2_PERIPH_TIM8 ((uint32_t)0x00002000) +#define RCC_APB2_PERIPH_USART1 ((uint32_t)0x00004000) +#define RCC_APB2_PERIPH_DVP ((uint32_t)0x00010000) +#define RCC_APB2_PERIPH_UART6 ((uint32_t)0x00020000) +#define RCC_APB2_PERIPH_UART7 ((uint32_t)0x00040000) +#define RCC_APB2_PERIPH_I2C3 ((uint32_t)0x00080000) +#define RCC_APB2_PERIPH_I2C4 ((uint32_t)0x00100000) + +#define IS_RCC_APB2_PERIPH(PERIPH) ((((PERIPH)&0xFFE08602) == 0x00) && ((PERIPH) != 0x00)) +/** + * @} + */ + +/** @addtogroup APB1_peripheral + * @{ + */ + +#define RCC_APB1_PERIPH_TIM2 ((uint32_t)0x00000001) +#define RCC_APB1_PERIPH_TIM3 ((uint32_t)0x00000002) +#define RCC_APB1_PERIPH_TIM4 ((uint32_t)0x00000004) +#define RCC_APB1_PERIPH_TIM5 ((uint32_t)0x00000008) +#define RCC_APB1_PERIPH_TIM6 ((uint32_t)0x00000010) +#define RCC_APB1_PERIPH_TIM7 ((uint32_t)0x00000020) +#define RCC_APB1_PERIPH_COMP ((uint32_t)0x00000040) +#define RCC_APB1_PERIPH_COMP_FILT ((uint32_t)0x00000080) +#define RCC_APB1_PERIPH_TSC ((uint32_t)0x00000400) +#define RCC_APB1_PERIPH_WWDG ((uint32_t)0x00000800) +#define RCC_APB1_PERIPH_SPI2 ((uint32_t)0x00004000) +#define RCC_APB1_PERIPH_SPI3 ((uint32_t)0x00008000) +#define RCC_APB1_PERIPH_USART2 ((uint32_t)0x00020000) +#define RCC_APB1_PERIPH_USART3 ((uint32_t)0x00040000) +#define RCC_APB1_PERIPH_UART4 ((uint32_t)0x00080000) +#define RCC_APB1_PERIPH_UART5 ((uint32_t)0x00100000) +#define RCC_APB1_PERIPH_I2C1 ((uint32_t)0x00200000) +#define RCC_APB1_PERIPH_I2C2 ((uint32_t)0x00400000) +#define RCC_APB1_PERIPH_USB ((uint32_t)0x00800000) +#define RCC_APB1_PERIPH_CAN1 ((uint32_t)0x02000000) +#define RCC_APB1_PERIPH_CAN2 ((uint32_t)0x04000000) +#define RCC_APB1_PERIPH_BKP ((uint32_t)0x08000000) +#define RCC_APB1_PERIPH_PWR ((uint32_t)0x10000000) +#define RCC_APB1_PERIPH_DAC ((uint32_t)0x20000000) +#define RCC_APB1_PERIPH_OPAMP ((uint32_t)0x80000000) + +#define IS_RCC_APB1_PERIPH(PERIPH) ((((PERIPH)&0x41013300) == 0x00) && ((PERIPH) != 0x00)) + +/** + * @} + */ + +#define RCC_MCO_PLLCLK_DIV2 ((uint32_t)0x20000000) +#define RCC_MCO_PLLCLK_DIV3 ((uint32_t)0x30000000) +#define RCC_MCO_PLLCLK_DIV4 ((uint32_t)0x40000000) +#define RCC_MCO_PLLCLK_DIV5 ((uint32_t)0x50000000) +#define RCC_MCO_PLLCLK_DIV6 ((uint32_t)0x60000000) +#define RCC_MCO_PLLCLK_DIV7 ((uint32_t)0x70000000) +#define RCC_MCO_PLLCLK_DIV8 ((uint32_t)0x80000000) +#define RCC_MCO_PLLCLK_DIV9 ((uint32_t)0x90000000) +#define RCC_MCO_PLLCLK_DIV10 ((uint32_t)0xA0000000) +#define RCC_MCO_PLLCLK_DIV11 ((uint32_t)0xB0000000) +#define RCC_MCO_PLLCLK_DIV12 ((uint32_t)0xC0000000) +#define RCC_MCO_PLLCLK_DIV13 ((uint32_t)0xD0000000) +#define RCC_MCO_PLLCLK_DIV14 ((uint32_t)0xE0000000) +#define RCC_MCO_PLLCLK_DIV15 ((uint32_t)0xF0000000) +#define IS_RCC_MCOPLLCLKPRE(DIV) \ + (((DIV) == RCC_MCO_PLLCLK_DIV2) || ((DIV) == RCC_MCO_PLLCLK_DIV3) || ((DIV) == RCC_MCO_PLLCLK_DIV4) \ + || ((DIV) == RCC_MCO_PLLCLK_DIV5) || ((DIV) == RCC_MCO_PLLCLK_DIV6) || ((DIV) == RCC_MCO_PLLCLK_DIV7) \ + || ((DIV) == RCC_MCO_PLLCLK_DIV8) || ((DIV) == RCC_MCO_PLLCLK_DIV9) || ((DIV) == RCC_MCO_PLLCLK_DIV10) \ + || ((DIV) == RCC_MCO_PLLCLK_DIV11) || ((DIV) == RCC_MCO_PLLCLK_DIV12) || ((DIV) == RCC_MCO_PLLCLK_DIV13) \ + || ((DIV) == RCC_MCO_PLLCLK_DIV14) || ((DIV) == RCC_MCO_PLLCLK_DIV15)) + +/** @addtogroup Clock_source_to_output_on_MCO_pin + * @{ + */ + +#define RCC_MCO_NOCLK ((uint8_t)0x00) +#define RCC_MCO_SYSCLK ((uint8_t)0x04) +#define RCC_MCO_HSI ((uint8_t)0x05) +#define RCC_MCO_HSE ((uint8_t)0x06) +#define RCC_MCO_PLLCLK ((uint8_t)0x07) + +#define IS_RCC_MCO(MCO) \ + (((MCO) == RCC_MCO_NOCLK) || ((MCO) == RCC_MCO_HSI) || ((MCO) == RCC_MCO_SYSCLK) || ((MCO) == RCC_MCO_HSE) \ + || ((MCO) == RCC_MCO_PLLCLK)) + +/** + * @} + */ + +/** @addtogroup RCC_Flag + * @{ + */ +#define RCC_FLAG_HSIRD ((uint8_t)0x21) +#define RCC_FLAG_HSERD ((uint8_t)0x31) +#define RCC_FLAG_PLLRD ((uint8_t)0x39) +#define RCC_FLAG_LSERD ((uint8_t)0x41) +#define RCC_FLAG_LSIRD ((uint8_t)0x61) +#define RCC_FLAG_BORRST ((uint8_t)0x73) +#define RCC_FLAG_RETEMC ((uint8_t)0x74) +#define RCC_FLAG_BKPEMC ((uint8_t)0x75) +#define RCC_FLAG_RAMRST ((uint8_t)0x77) +#define RCC_FLAG_MMURST ((uint8_t)0x79) +#define RCC_FLAG_PINRST ((uint8_t)0x7A) +#define RCC_FLAG_PORRST ((uint8_t)0x7B) +#define RCC_FLAG_SFTRST ((uint8_t)0x7C) +#define RCC_FLAG_IWDGRST ((uint8_t)0x7D) +#define RCC_FLAG_WWDGRST ((uint8_t)0x7E) +#define RCC_FLAG_LPWRRST ((uint8_t)0x7F) + +#define IS_RCC_FLAG(FLAG) \ + (((FLAG) == RCC_FLAG_HSIRD) || ((FLAG) == RCC_FLAG_HSERD) || ((FLAG) == RCC_FLAG_PLLRD) \ + || ((FLAG) == RCC_FLAG_LSERD) || ((FLAG) == RCC_FLAG_LSIRD) || ((FLAG) == RCC_FLAG_BORRST) \ + || ((FLAG) == RCC_FLAG_RETEMC) || ((FLAG) == RCC_FLAG_BKPEMC) || ((FLAG) == RCC_FLAG_RAMRST) \ + || ((FLAG) == RCC_FLAG_MMURST) || ((FLAG) == RCC_FLAG_PINRST) || ((FLAG) == RCC_FLAG_PORRST) \ + || ((FLAG) == RCC_FLAG_SFTRST) || ((FLAG) == RCC_FLAG_IWDGRST) || ((FLAG) == RCC_FLAG_WWDGRST) \ + || ((FLAG) == RCC_FLAG_LPWRRST)) + +#define IS_RCC_CALIB_VALUE(VALUE) ((VALUE) <= 0x1F) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup RCC_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup RCC_Exported_Functions + * @{ + */ + +void RCC_DeInit(void); +void RCC_ConfigHse(uint32_t RCC_HSE); +ErrorStatus RCC_WaitHseStable(void); +void RCC_SetHsiCalibValue(uint8_t HSICalibrationValue); +void RCC_EnableHsi(FunctionalState Cmd); +void RCC_ConfigPll(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul); +void RCC_EnablePll(FunctionalState Cmd); + +void RCC_ConfigSysclk(uint32_t RCC_SYSCLKSource); +uint8_t RCC_GetSysclkSrc(void); +void RCC_ConfigHclk(uint32_t RCC_SYSCLK); +void RCC_ConfigPclk1(uint32_t RCC_HCLK); +void RCC_ConfigPclk2(uint32_t RCC_HCLK); +void RCC_ConfigInt(uint8_t RccInt, FunctionalState Cmd); + +void RCC_ConfigUsbClk(uint32_t RCC_USBCLKSource); + +void RCC_ConfigTim18Clk(uint32_t RCC_TIM18CLKSource); +void RCC_ConfigRngcClk(uint32_t RCC_RNGCCLKPrescaler); + +void RCC_ConfigAdc1mClk(uint32_t RCC_ADC1MCLKSource, uint32_t RCC_ADC1MPrescaler); +void RCC_ConfigAdcPllClk(uint32_t RCC_ADCPLLCLKPrescaler, FunctionalState Cmd); +void RCC_ConfigAdcHclk(uint32_t RCC_ADCHCLKPrescaler); + +void RCC_ConfigTrng1mClk(uint32_t RCC_TRNG1MCLKSource, uint32_t RCC_TRNG1MPrescaler); +void RCC_EnableTrng1mClk(FunctionalState Cmd); + +void RCC_ConfigLse(uint8_t RCC_LSE); +void RCC_EnableLsi(FunctionalState Cmd); +void RCC_ConfigRtcClk(uint32_t RCC_RTCCLKSource); +void RCC_EnableRtcClk(FunctionalState Cmd); +void RCC_GetClocksFreqValue(RCC_ClocksType* RCC_Clocks); +void RCC_EnableAHBPeriphClk(uint32_t RCC_AHBPeriph, FunctionalState Cmd); +void RCC_EnableAPB2PeriphClk(uint32_t RCC_APB2Periph, FunctionalState Cmd); +void RCC_EnableAPB1PeriphClk(uint32_t RCC_APB1Periph, FunctionalState Cmd); + +void RCC_EnableAHBPeriphReset(uint32_t RCC_AHBPeriph, FunctionalState Cmd); +void RCC_EnableAPB2PeriphReset(uint32_t RCC_APB2Periph, FunctionalState Cmd); +void RCC_EnableAPB1PeriphReset(uint32_t RCC_APB1Periph, FunctionalState Cmd); +void RCC_EnableBORReset(FunctionalState Cmd); +void RCC_EnableBackupReset(FunctionalState Cmd); +void RCC_EnableClockSecuritySystem(FunctionalState Cmd); +void RCC_ConfigMcoPllClk(uint32_t RCC_MCOPLLCLKPrescaler); +void RCC_ConfigMco(uint8_t RCC_MCO); +FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG); +void RCC_ClrFlag(void); +INTStatus RCC_GetIntStatus(uint8_t RccInt); +void RCC_ClrIntPendingBit(uint8_t RccInt); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G4FR_RCC_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_rtc.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_rtc.h new file mode 100644 index 0000000000..a8873cd55d --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_rtc.h @@ -0,0 +1,662 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_rtc.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_RTC_H__ +#define __N32G4FR_RTC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup RTC + * @{ + */ + +/** + * @brief RTC Init structures definition + */ +typedef struct +{ + uint32_t RTC_HourFormat; /*!< Specifies the RTC Hour Format. + This parameter can be a value of @ref RTC_Hour_Formats */ + + uint32_t RTC_AsynchPrediv; /*!< Specifies the RTC Asynchronous Predivider value. + This parameter must be set to a value lower than 0x7F */ + + uint32_t RTC_SynchPrediv; /*!< Specifies the RTC Synchronous Predivider value. + This parameter must be set to a value lower than 0x7FFF */ +} RTC_InitType; + +/** + * @brief RTC Time structure definition + */ +typedef struct +{ + uint8_t Hours; /*!< Specifies the RTC Time Hour. + This parameter must be set to a value in the 0-12 range + if the RTC_12HOUR_FORMAT is selected or 0-23 range if + the RTC_24HOUR_FORMAT is selected. */ + + uint8_t Minutes; /*!< Specifies the RTC Time Minutes. + This parameter must be set to a value in the 0-59 range. */ + + uint8_t Seconds; /*!< Specifies the RTC Time Seconds. + This parameter must be set to a value in the 0-59 range. */ + + uint8_t H12; /*!< Specifies the RTC AM/PM Time. + This parameter can be a value of @ref RTC_AM_PM_Definitions */ +} RTC_TimeType; + +/** + * @brief RTC Date structure definition + */ +typedef struct +{ + uint8_t WeekDay; /*!< Specifies the RTC Date WeekDay. + This parameter can be a value of @ref RTC_WeekDay_Definitions */ + + uint8_t Month; /*!< Specifies the RTC Date Month (in BCD format). + This parameter can be a value of @ref RTC_Month_Date_Definitions */ + + uint8_t Date; /*!< Specifies the RTC Date. + This parameter must be set to a value in the 1-31 range. */ + + uint8_t Year; /*!< Specifies the RTC Date Year. + This parameter must be set to a value in the 0-99 range. */ +} RTC_DateType; + +/** + * @brief RTC Alarm structure definition + */ +typedef struct +{ + RTC_TimeType AlarmTime; /*!< Specifies the RTC Alarm Time members. */ + + uint32_t AlarmMask; /*!< Specifies the RTC Alarm Masks. + This parameter can be a value of @ref RTC_AlarmMask_Definitions */ + + uint32_t DateWeekMode; /*!< Specifies the RTC Alarm is on Date or WeekDay. + This parameter can be a value of @ref RTC_AlarmDateWeekDay_Definitions */ + + uint8_t DateWeekValue; /*!< Specifies the RTC Alarm Date/WeekDay. + If the Alarm Date is selected, this parameter + must be set to a value in the 1-31 range. + If the Alarm WeekDay is selected, this + parameter can be a value of @ref RTC_WeekDay_Definitions */ +} RTC_AlarmType; + +/** @addtogroup RTC_Exported_Constants + * @{ + */ + +/** @addtogroup RTC_Hour_Formats + * @{ + */ +#define RTC_24HOUR_FORMAT ((uint32_t)0x00000000) +#define RTC_12HOUR_FORMAT ((uint32_t)0x00000040) +#define IS_RTC_HOUR_FORMAT(FORMAT) (((FORMAT) == RTC_12HOUR_FORMAT) || ((FORMAT) == RTC_24HOUR_FORMAT)) +/** + * @} + */ + +/** @addtogroup RTC_Asynchronous_Predivider + * @{ + */ +#define IS_RTC_PREDIV_ASYNCH(PREDIV) ((PREDIV) <= 0x7F) + +/** + * @} + */ + +/** @addtogroup RTC_Synchronous_Predivider + * @{ + */ +#define IS_RTC_PREDIV_SYNCH(PREDIV) ((PREDIV) <= 0x7FFF) + +/** + * @} + */ + +/** @addtogroup RTC_Time_Definitions + * @{ + */ +#define IS_RTC_12HOUR(HOUR) (((HOUR) > 0) && ((HOUR) <= 12)) +#define IS_RTC_24HOUR(HOUR) ((HOUR) <= 23) +#define IS_RTC_MINUTES(MINUTES) ((MINUTES) <= 59) +#define IS_RTC_SECONDS(SECONDS) ((SECONDS) <= 59) + +/** + * @} + */ + +/** @addtogroup RTC_AM_PM_Definitions + * @{ + */ +#define RTC_AM_H12 ((uint8_t)0x00) +#define RTC_PM_H12 ((uint8_t)0x40) +#define IS_RTC_H12(PM) (((PM) == RTC_AM_H12) || ((PM) == RTC_PM_H12)) + +/** + * @} + */ + +/** @addtogroup RTC_Year_Date_Definitions + * @{ + */ +#define IS_RTC_YEAR(YEAR) ((YEAR) <= 99) + +/** + * @} + */ + +/** @addtogroup RTC_Month_Date_Definitions + * @{ + */ + +/* Coded in BCD format */ +#define RTC_MONTH_JANUARY ((uint8_t)0x01) +#define RTC_MONTH_FEBRURY ((uint8_t)0x02) +#define RTC_MONTH_MARCH ((uint8_t)0x03) +#define RTC_MONTH_APRIL ((uint8_t)0x04) +#define RTC_MONTH_MAY ((uint8_t)0x05) +#define RTC_MONTH_JUNE ((uint8_t)0x06) +#define RTC_MONTH_JULY ((uint8_t)0x07) +#define RTC_MONTH_AUGUST ((uint8_t)0x08) +#define RTC_MONTH_SEPTEMBER ((uint8_t)0x09) +#define RTC_MONTH_OCTOBER ((uint8_t)0x10) +#define RTC_MONTH_NOVEMBER ((uint8_t)0x11) +#define RTC_MONTH_DECEMBER ((uint8_t)0x12) +#define IS_RTC_MONTH(MONTH) (((MONTH) >= 1) && ((MONTH) <= 12)) +#define IS_RTC_DATE(DATE) (((DATE) >= 1) && ((DATE) <= 31)) + +/** + * @} + */ + +/** @addtogroup RTC_WeekDay_Definitions + * @{ + */ + +#define RTC_WEEKDAY_MONDAY ((uint8_t)0x01) +#define RTC_WEEKDAY_TUESDAY ((uint8_t)0x02) +#define RTC_WEEKDAY_WEDNESDAY ((uint8_t)0x03) +#define RTC_WEEKDAY_THURSDAY ((uint8_t)0x04) +#define RTC_WEEKDAY_FRIDAY ((uint8_t)0x05) +#define RTC_WEEKDAY_SATURDAY ((uint8_t)0x06) +#define RTC_WEEKDAY_SUNDAY ((uint8_t)0x07) +#define IS_RTC_WEEKDAY(WEEKDAY) \ + (((WEEKDAY) == RTC_WEEKDAY_MONDAY) || ((WEEKDAY) == RTC_WEEKDAY_TUESDAY) || ((WEEKDAY) == RTC_WEEKDAY_WEDNESDAY) \ + || ((WEEKDAY) == RTC_WEEKDAY_THURSDAY) || ((WEEKDAY) == RTC_WEEKDAY_FRIDAY) \ + || ((WEEKDAY) == RTC_WEEKDAY_SATURDAY) || ((WEEKDAY) == RTC_WEEKDAY_SUNDAY)) +/** + * @} + */ + +/** @addtogroup RTC_Alarm_Definitions + * @{ + */ +#define IS_RTC_ALARM_WEEKDAY_DATE(DATE) (((DATE) > 0) && ((DATE) <= 31)) +#define IS_RTC_ALARM_WEEKDAY_WEEKDAY(WEEKDAY) \ + (((WEEKDAY) == RTC_WEEKDAY_MONDAY) || ((WEEKDAY) == RTC_WEEKDAY_TUESDAY) || ((WEEKDAY) == RTC_WEEKDAY_WEDNESDAY) \ + || ((WEEKDAY) == RTC_WEEKDAY_THURSDAY) || ((WEEKDAY) == RTC_WEEKDAY_FRIDAY) \ + || ((WEEKDAY) == RTC_WEEKDAY_SATURDAY) || ((WEEKDAY) == RTC_WEEKDAY_SUNDAY)) + +/** + * @} + */ + +/** @addtogroup RTC_AlarmDateWeekDay_Definitions + * @{ + */ +#define RTC_ALARM_SEL_WEEKDAY_DATE ((uint32_t)0x00000000) +#define RTC_ALARM_SEL_WEEKDAY_WEEKDAY ((uint32_t)0x40000000) + +#define IS_RTC_ALARM_WEEKDAY_SEL(SEL) \ + (((SEL) == RTC_ALARM_SEL_WEEKDAY_DATE) || ((SEL) == RTC_ALARM_SEL_WEEKDAY_WEEKDAY)) + +/** + * @} + */ + +/** @addtogroup RTC_AlarmMask_Definitions + * @{ + */ +#define RTC_ALARMMASK_NONE ((uint32_t)0x00000000) +#define RTC_ALARMMASK_WEEKDAY ((uint32_t)0x80000000) +#define RTC_ALARMMASK_HOURS ((uint32_t)0x00800000) +#define RTC_ALARMMASK_MINUTES ((uint32_t)0x00008000) +#define RTC_ALARMMASK_SECONDS ((uint32_t)0x00000080) +#define RTC_ALARMMASK_ALL ((uint32_t)0x80808080) +#define IS_ALARM_MASK(INTEN) (((INTEN)&0x7F7F7F7F) == (uint32_t)RESET) + +/** + * @} + */ + +/** @addtogroup RTC_Alarms_Definitions + * @{ + */ +#define RTC_A_ALARM ((uint32_t)0x00000100) +#define RTC_B_ALARM ((uint32_t)0x00000200) +#define IS_RTC_ALARM_SEL(ALARM) (((ALARM) == RTC_A_ALARM) || ((ALARM) == RTC_B_ALARM)) +#define IS_RTC_ALARM_ENABLE(ALARM) (((ALARM) & (RTC_A_ALARM | RTC_B_ALARM)) != (uint32_t)RESET) + +/** + * @} + */ + +/** @addtogroup RTC_Alarm_Sub_Seconds_Masks_Definitions + * @{ + */ +#define RTC_SUBS_MASK_ALL \ + ((uint32_t)0x00000000) /*!< All Alarm SS fields are masked. \ + There is no comparison on sub seconds \ + for Alarm */ +#define RTC_SUBS_MASK_SS14_1 \ + ((uint32_t)0x01000000) /*!< SS[14:1] are don't care in Alarm \ + comparison. Only SS[0] is compared. */ +#define RTC_SUBS_MASK_SS14_2 \ + ((uint32_t)0x02000000) /*!< SS[14:2] are don't care in Alarm \ + comparison. Only SS[1:0] are compared */ +#define RTC_SUBS_MASK_SS14_3 \ + ((uint32_t)0x03000000) /*!< SS[14:3] are don't care in Alarm \ + comparison. Only SS[2:0] are compared */ +#define RTC_SUBS_MASK_SS14_4 \ + ((uint32_t)0x04000000) /*!< SS[14:4] are don't care in Alarm \ + comparison. Only SS[3:0] are compared */ +#define RTC_SUBS_MASK_SS14_5 \ + ((uint32_t)0x05000000) /*!< SS[14:5] are don't care in Alarm \ + comparison. Only SS[4:0] are compared */ +#define RTC_SUBS_MASK_SS14_6 \ + ((uint32_t)0x06000000) /*!< SS[14:6] are don't care in Alarm \ + comparison. Only SS[5:0] are compared */ +#define RTC_SUBS_MASK_SS14_7 \ + ((uint32_t)0x07000000) /*!< SS[14:7] are don't care in Alarm \ + comparison. Only SS[6:0] are compared */ +#define RTC_SUBS_MASK_SS14_8 \ + ((uint32_t)0x08000000) /*!< SS[14:8] are don't care in Alarm \ + comparison. Only SS[7:0] are compared */ +#define RTC_SUBS_MASK_SS14_9 \ + ((uint32_t)0x09000000) /*!< SS[14:9] are don't care in Alarm \ + comparison. Only SS[8:0] are compared */ +#define RTC_SUBS_MASK_SS14_10 \ + ((uint32_t)0x0A000000) /*!< SS[14:10] are don't care in Alarm \ + comparison. Only SS[9:0] are compared */ +#define RTC_SUBS_MASK_SS14_11 \ + ((uint32_t)0x0B000000) /*!< SS[14:11] are don't care in Alarm \ + comparison. Only SS[10:0] are compared */ +#define RTC_SUBS_MASK_SS14_12 \ + ((uint32_t)0x0C000000) /*!< SS[14:12] are don't care in Alarm \ + comparison.Only SS[11:0] are compared */ +#define RTC_SUBS_MASK_SS14_13 \ + ((uint32_t)0x0D000000) /*!< SS[14:13] are don't care in Alarm \ + comparison. Only SS[12:0] are compared */ +#define RTC_SUBS_MASK_SS14_14 \ + ((uint32_t)0x0E000000) /*!< SS[14] is don't care in Alarm \ + comparison.Only SS[13:0] are compared */ +#define RTC_SUBS_MASK_NONE \ + ((uint32_t)0x0F000000) /*!< SS[14:0] are compared and must match \ + to activate alarm. */ +#define IS_RTC_ALARM_SUB_SECOND_MASK_MODE(INTEN) \ + (((INTEN) == RTC_SUBS_MASK_ALL) || ((INTEN) == RTC_SUBS_MASK_SS14_1) || ((INTEN) == RTC_SUBS_MASK_SS14_2) \ + || ((INTEN) == RTC_SUBS_MASK_SS14_3) || ((INTEN) == RTC_SUBS_MASK_SS14_4) || ((INTEN) == RTC_SUBS_MASK_SS14_5) \ + || ((INTEN) == RTC_SUBS_MASK_SS14_6) || ((INTEN) == RTC_SUBS_MASK_SS14_7) || ((INTEN) == RTC_SUBS_MASK_SS14_8) \ + || ((INTEN) == RTC_SUBS_MASK_SS14_9) || ((INTEN) == RTC_SUBS_MASK_SS14_10) || ((INTEN) == RTC_SUBS_MASK_SS14_11) \ + || ((INTEN) == RTC_SUBS_MASK_SS14_12) || ((INTEN) == RTC_SUBS_MASK_SS14_13) || ((INTEN) == RTC_SUBS_MASK_SS14_14) \ + || ((INTEN) == RTC_SUBS_MASK_NONE)) +/** + * @} + */ + +/** @addtogroup RTC_Alarm_Sub_Seconds_Value + * @{ + */ + +#define IS_RTC_ALARM_SUB_SECOND_VALUE(VALUE) ((VALUE) <= 0x00007FFF) + +/** + * @} + */ + +/** @addtogroup RTC_Wakeup_Timer_Definitions + * @{ + */ +#define RTC_WKUPCLK_RTCCLK_DIV16 ((uint32_t)0x00000000) +#define RTC_WKUPCLK_RTCCLK_DIV8 ((uint32_t)0x00000001) +#define RTC_WKUPCLK_RTCCLK_DIV4 ((uint32_t)0x00000002) +#define RTC_WKUPCLK_RTCCLK_DIV2 ((uint32_t)0x00000003) +#define RTC_WKUPCLK_CK_SPRE_16BITS ((uint32_t)0x00000004) + +#define IS_RTC_WKUP_CLOCK(CLOCK) \ + (((CLOCK) == RTC_WKUPCLK_RTCCLK_DIV16) || ((CLOCK) == RTC_WKUPCLK_RTCCLK_DIV8) \ + || ((CLOCK) == RTC_WKUPCLK_RTCCLK_DIV4) || ((CLOCK) == RTC_WKUPCLK_RTCCLK_DIV2) \ + || ((CLOCK) == RTC_WKUPCLK_CK_SPRE_16BITS)) +#define IS_RTC_WKUP_COUNTER(COUNTER) ((COUNTER) <= 0xFFFF) +/** + * @} + */ + +/** @addtogroup RTC_Time_Stamp_Edges_definitions + * @{ + */ +#define RTC_TIMESTAMP_EDGE_RISING ((uint32_t)0x00000000) +#define RTC_TIMESTAMP_EDGE_FALLING ((uint32_t)0x00000008) +#define IS_RTC_TIMESTAMP_EDGE_MODE(EDGE) \ + (((EDGE) == RTC_TIMESTAMP_EDGE_RISING) || ((EDGE) == RTC_TIMESTAMP_EDGE_FALLING)) +/** + * @} + */ + +/** @addtogroup RTC_Output_selection_Definitions + * @{ + */ +#define RTC_OUTPUT_DIS ((uint32_t)0x00000000) +#define RTC_OUTPUT_ALA ((uint32_t)0x00200000) +#define RTC_OUTPUT_ALB ((uint32_t)0x00400000) +#define RTC_OUTPUT_WKUP ((uint32_t)0x00600000) + +#define IS_RTC_OUTPUT_MODE(OUTPUT) \ + (((OUTPUT) == RTC_OUTPUT_DIS) || ((OUTPUT) == RTC_OUTPUT_ALA) || ((OUTPUT) == RTC_OUTPUT_ALB) \ + || ((OUTPUT) == RTC_OUTPUT_WKUP)) + +/** + * @} + */ + +/** @addtogroup RTC_Output_Polarity_Definitions + * @{ + */ +#define RTC_OUTPOL_HIGH ((uint32_t)0x00000000) +#define RTC_OUTPOL_LOW ((uint32_t)0x00100000) +#define IS_RTC_OUTPUT_POL(POL) (((POL) == RTC_OUTPOL_HIGH) || ((POL) == RTC_OUTPOL_LOW)) +/** + * @} + */ + + +/** @addtogroup RTC_Calib_Output_selection_Definitions + * @{ + */ +#define RTC_CALIB_OUTPUT_256HZ ((uint32_t)0x00000000) +#define RTC_CALIB_OUTPUT_1HZ ((uint32_t)0x00080000) +#define IS_RTC_CALIB_OUTPUT(OUTPUT) (((OUTPUT) == RTC_CALIB_OUTPUT_256HZ) || ((OUTPUT) == RTC_CALIB_OUTPUT_1HZ)) +/** + * @} + */ + +/** @addtogroup RTC_Smooth_calib_period_Definitions + * @{ + */ +#define SMOOTH_CALIB_32SEC \ + ((uint32_t)0x00000000) /*!< if RTCCLK = 32768 Hz, Smooth calibation \ + period is 32s, else 2exp20 RTCCLK seconds */ +#define SMOOTH_CALIB_16SEC \ + ((uint32_t)0x00002000) /*!< if RTCCLK = 32768 Hz, Smooth calibation \ + period is 16s, else 2exp19 RTCCLK seconds */ +#define SMOOTH_CALIB_8SEC \ + ((uint32_t)0x00004000) /*!< if RTCCLK = 32768 Hz, Smooth calibation \ + period is 8s, else 2exp18 RTCCLK seconds */ +#define IS_RTC_SMOOTH_CALIB_PERIOD_SEL(PERIOD) \ + (((PERIOD) == SMOOTH_CALIB_32SEC) || ((PERIOD) == SMOOTH_CALIB_16SEC) || ((PERIOD) == SMOOTH_CALIB_8SEC)) + +/** + * @} + */ + +/** @addtogroup RTC_Smooth_calib_Plus_pulses_Definitions + * @{ + */ +#define RTC_SMOOTH_CALIB_PLUS_PULSES_SET \ + ((uint32_t)0x00008000) /*!< The number of RTCCLK pulses added \ + during a X -second window = Y - CALM[8:0]. \ + with Y = 512, 256, 128 when X = 32, 16, 8 */ +#define RTC_SMOOTH_CALIB_PLUS_PULSES__RESET \ + ((uint32_t)0x00000000) /*!< The number of RTCCLK pulses subbstited \ + during a 32-second window = CALM[8:0]. */ +#define IS_RTC_SMOOTH_CALIB_PLUS(PLUS) \ + (((PLUS) == RTC_SMOOTH_CALIB_PLUS_PULSES_SET) || ((PLUS) == RTC_SMOOTH_CALIB_PLUS_PULSES__RESET)) + +/** + * @} + */ + +/** @addtogroup RTC_Smooth_calib_Minus_pulses_Definitions + * @{ + */ +#define IS_RTC_SMOOTH_CALIB_MINUS(VALUE) ((VALUE) <= 0x000001FF) + +/** + * @} + */ + +/** @addtogroup RTC_DayLightSaving_Definitions + * @{ + */ +#define RTC_DAYLIGHT_SAVING_SUB1H ((uint32_t)0x00020000) +#define RTC_DAYLIGHT_SAVING_ADD1H ((uint32_t)0x00010000) +#define IS_RTC_DAYLIGHT_SAVING(SAVE) (((SAVE) == RTC_DAYLIGHT_SAVING_SUB1H) || ((SAVE) == RTC_DAYLIGHT_SAVING_ADD1H)) + +#define RTC_STORE_OPERATION_RESET ((uint32_t)0x00000000) +#define RTC_STORE_OPERATION_SET ((uint32_t)0x00040000) +#define IS_RTC_STORE_OPERATION(OPERATION) \ + (((OPERATION) == RTC_STORE_OPERATION_RESET) || ((OPERATION) == RTC_STORE_OPERATION_SET)) +/** + * @} + */ + +/** @addtogroup RTC_Output_Type_ALARM_OUT + * @{ + */ +#define RTC_OUTPUT_OPENDRAIN ((uint32_t)0x00000000) +#define RTC_OUTPUT_PUSHPULL ((uint32_t)0x00000001) +#define IS_RTC_OUTPUT_TYPE(TYPE) (((TYPE) == RTC_OUTPUT_OPENDRAIN) || ((TYPE) == RTC_OUTPUT_PUSHPULL)) + +/** + * @} + */ +/** @addtogroup RTC_Add_Fraction_Of_Second_Value + * @{ + */ +#define RTC_SHIFT_SUB1S_DISABLE ((uint32_t)0x00000000) +#define RTC_SHIFT_SUB1S_ENABLE ((uint32_t)0x80000000) +#define IS_RTC_SHIFT_SUB1S(SEL) (((SEL) == RTC_SHIFT_SUB1S_DISABLE) || ((SEL) == RTC_SHIFT_SUB1S_ENABLE)) +/** + * @} + */ +/** @addtogroup RTC_Substract_1_Second_Parameter_Definitions + * @{ + */ +#define IS_RTC_SHIFT_ADFS(FS) ((FS) <= 0x00007FFF) + +/** + * @} + */ + +/** @addtogroup RTC_Input_parameter_format_definitions + * @{ + */ +#define RTC_FORMAT_BIN ((uint32_t)0x000000000) +#define RTC_FORMAT_BCD ((uint32_t)0x000000001) +#define IS_RTC_FORMAT(FORMAT) (((FORMAT) == RTC_FORMAT_BIN) || ((FORMAT) == RTC_FORMAT_BCD)) + +/** + * @} + */ + +/** @addtogroup RTC_Flags_Definitions + * @{ + */ +#define RTC_FLAG_RECPF ((uint32_t)0x00010000) +#define RTC_FLAG_TISOVF ((uint32_t)0x00001000) +#define RTC_FLAG_TISF ((uint32_t)0x00000800) +#define RTC_FLAG_WTF ((uint32_t)0x00000400) +#define RTC_FLAG_ALBF ((uint32_t)0x00000200) +#define RTC_FLAG_ALAF ((uint32_t)0x00000100) +#define RTC_FLAG_INITF ((uint32_t)0x00000040) +#define RTC_FLAG_RSYF ((uint32_t)0x00000020) +#define RTC_FLAG_INITSF ((uint32_t)0x00000010) +#define RTC_FLAG_SHOPF ((uint32_t)0x00000008) +#define RTC_FLAG_WTWF ((uint32_t)0x00000004) +#define RTC_FLAG_ALBWF ((uint32_t)0x00000002) +#define RTC_FLAG_ALAWF ((uint32_t)0x00000001) +#define IS_RTC_GET_FLAG(FLAG) \ + (((FLAG) == RTC_FLAG_TISOVF) || ((FLAG) == RTC_FLAG_TISF) || ((FLAG) == RTC_FLAG_WTF) || ((FLAG) == RTC_FLAG_ALBF) \ + || ((FLAG) == RTC_FLAG_ALAF) || ((FLAG) == RTC_FLAG_INITF) || ((FLAG) == RTC_FLAG_RSYF) \ + || ((FLAG) == RTC_FLAG_WTWF) || ((FLAG) == RTC_FLAG_ALBWF) || ((FLAG) == RTC_FLAG_ALAWF) \ + || ((FLAG) == RTC_FLAG_RECPF) || ((FLAG) == RTC_FLAG_SHOPF) || ((FLAG) == RTC_FLAG_INITSF)) +#define IS_RTC_CLEAR_FLAG(FLAG) (((FLAG) != (uint32_t)RESET) && (((FLAG)&0x00011fff) == (uint32_t)SET)) + +/** + * @} + */ + +/** @addtogroup RTC_Interrupts_Definitions + * @{ + */ + +#define RTC_INT_WUT ((uint32_t)0x00004000) +#define RTC_INT_ALRB ((uint32_t)0x00002000) +#define RTC_INT_ALRA ((uint32_t)0x00001000) + +#define IS_RTC_CONFIG_INT(IT) (((IT) != (uint32_t)RESET) && (((IT)&0xFFFF0FFB) == (uint32_t)RESET)) +#define IS_RTC_GET_INT(IT) \ + (((IT) == RTC_INT_WUT) || ((IT) == RTC_INT_ALRB) || ((IT) == RTC_INT_ALRA)) +#define IS_RTC_CLEAR_INT(IT) (((IT) != (uint32_t)RESET) && (((IT)&0x00007000) == (uint32_t)SET)) + +/** + * @} + */ + +/** @addtogroup RTC_Legacy + * @{ + */ +#define RTC_DigitalCalibConfig RTC_CoarseCalibConfig +#define RTC_DigitalCalibCmd RTC_CoarseCalibCmd + +/** + * @} + */ + +/** + * @} + */ + +/* Function used to set the RTC configuration to the default reset state *****/ +ErrorStatus RTC_DeInit(void); + +/* Initialization and Configuration functions *********************************/ +ErrorStatus RTC_Init(RTC_InitType* RTC_InitStruct); +void RTC_StructInit(RTC_InitType* RTC_InitStruct); +void RTC_EnableWriteProtection(FunctionalState Cmd); +ErrorStatus RTC_EnterInitMode(void); +void RTC_ExitInitMode(void); +ErrorStatus RTC_WaitForSynchro(void); +ErrorStatus RTC_EnableRefClock(FunctionalState Cmd); +void RTC_EnableBypassShadow(FunctionalState Cmd); + +/* Time and Date configuration functions **************************************/ +ErrorStatus RTC_ConfigTime(uint32_t RTC_Format, RTC_TimeType* RTC_TimeStruct); +void RTC_TimeStructInit(RTC_TimeType* RTC_TimeStruct); +void RTC_GetTime(uint32_t RTC_Format, RTC_TimeType* RTC_TimeStruct); +uint32_t RTC_GetSubSecond(void); +ErrorStatus RTC_SetDate(uint32_t RTC_Format, RTC_DateType* RTC_DateStruct); +void RTC_DateStructInit(RTC_DateType* RTC_DateStruct); +void RTC_GetDate(uint32_t RTC_Format, RTC_DateType* RTC_DateStruct); + +/* Alarms (Alarm A and Alarm B) configuration functions **********************/ +void RTC_SetAlarm(uint32_t RTC_Format, uint32_t RTC_Alarm, RTC_AlarmType* RTC_AlarmStruct); +void RTC_AlarmStructInit(RTC_AlarmType* RTC_AlarmStruct); +void RTC_GetAlarm(uint32_t RTC_Format, uint32_t RTC_Alarm, RTC_AlarmType* RTC_AlarmStruct); +ErrorStatus RTC_EnableAlarm(uint32_t RTC_Alarm, FunctionalState Cmd); +void RTC_ConfigAlarmSubSecond(uint32_t RTC_Alarm, uint32_t RTC_AlarmSubSecondValue, uint32_t RTC_AlarmSubSecondMask); +uint32_t RTC_GetAlarmSubSecond(uint32_t RTC_Alarm); + +/* WakeUp Timer configuration functions ***************************************/ +void RTC_ConfigWakeUpClock(uint32_t RTC_WakeUpClock); +void RTC_SetWakeUpCounter(uint32_t RTC_WakeUpCounter); +uint32_t RTC_GetWakeUpCounter(void); +ErrorStatus RTC_EnableWakeUp(FunctionalState Cmd); + +/* Daylight Saving configuration functions ************************************/ +void RTC_ConfigDayLightSaving(uint32_t RTC_DayLightSaving, uint32_t RTC_StoreOperation); +uint32_t RTC_GetStoreOperation(void); + +/* Output pin Configuration function ******************************************/ +void RTC_ConfigOutput(uint32_t RTC_Output, uint32_t RTC_OutputPolarity); + +/* Coarse and Smooth Calibration configuration functions **********************/ +void RTC_EnableCalibOutput(FunctionalState Cmd); +void RTC_ConfigCalibOutput(uint32_t RTC_CalibOutput); +ErrorStatus RTC_ConfigSmoothCalib(uint32_t RTC_SmoothCalibPeriod, + uint32_t RTC_SmoothCalibPlusPulses, + uint32_t RTC_SmouthCalibMinusPulsesValue); + +/* TimeStamp configuration functions ******************************************/ +void RTC_EnableTimeStamp(uint32_t RTC_TimeStampEdge, FunctionalState Cmd); +void RTC_GetTimeStamp(uint32_t RTC_Format, RTC_TimeType* RTC_StampTimeStruct, RTC_DateType* RTC_StampDateStruct); +uint32_t RTC_GetTimeStampSubSecond(void); + +/* Output Type Config configuration functions *********************************/ +void RTC_ConfigOutputType(uint32_t RTC_OutputType); + +/* RTC_Shift_control_synchonisation_functions *********************************/ +ErrorStatus RTC_ConfigSynchroShift(uint32_t RTC_ShiftAddFS, uint32_t RTC_ShiftSub1s); + +/* Interrupts and flags management functions **********************************/ +void RTC_ConfigInt(uint32_t RTC_INT, FunctionalState Cmd); +FlagStatus RTC_GetFlagStatus(uint32_t RTC_FLAG); +void RTC_ClrFlag(uint32_t RTC_FLAG); +INTStatus RTC_GetITStatus(uint32_t RTC_INT); +void RTC_ClrIntPendingBit(uint32_t RTC_INT); +/* WakeUp TSC function **********************************/ +void RTC_EnableWakeUpTsc(uint32_t count); +#ifdef __cplusplus +} +#endif + +#endif /*__N32G4FR_RTC_H__ */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_sdio.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_sdio.h new file mode 100644 index 0000000000..6870d518e4 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_sdio.h @@ -0,0 +1,494 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_sdio.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_SDIO_H__ +#define __N32G4FR_SDIO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup SDIO + * @{ + */ + +/** @addtogroup SDIO_Exported_Types + * @{ + */ + +typedef struct +{ + uint32_t ClkEdge; /*!< Specifies the clock transition on which the bit capture is made. + This parameter can be a value of @ref SDIO_Clock_Edge */ + + uint32_t ClkBypass; /*!< Specifies whether the SDIO Clock divider bypass is + enabled or disabled. + This parameter can be a value of @ref SDIO_Clock_Bypass */ + + uint32_t ClkPwrSave; /*!< Specifies whether SDIO Clock output is enabled or + disabled when the bus is idle. + This parameter can be a value of @ref SDIO_Clock_Power_Save */ + + uint32_t BusWidth; /*!< Specifies the SDIO bus width. + This parameter can be a value of @ref SDIO_Bus_Wide */ + + uint32_t HardwareClkCtrl; /*!< Specifies whether the SDIO hardware flow control is enabled or disabled. + This parameter can be a value of @ref SDIO_Hardware_Flow_Control */ + + uint8_t ClkDiv; /*!< Specifies the clock frequency of the SDIO controller. + This parameter can be a value between 0x00 and 0xFF. */ + +} SDIO_InitType; + +typedef struct +{ + uint32_t CmdArgument; /*!< Specifies the SDIO command argument which is sent + to a card as part of a command message. If a command + contains an argument, it must be loaded into this register + before writing the command to the command register */ + + uint32_t CmdIndex; /*!< Specifies the SDIO command index. It must be lower than 0x40. */ + + uint32_t ResponseType; /*!< Specifies the SDIO response type. + This parameter can be a value of @ref SDIO_Response_Type */ + + uint32_t WaitType; /*!< Specifies whether SDIO wait-for-interrupt request is enabled or disabled. + This parameter can be a value of @ref SDIO_Wait_Interrupt_State */ + + uint32_t CPSMConfig; /*!< Specifies whether SDIO Command path state machine (CPSM) + is enabled or disabled. + This parameter can be a value of @ref SDIO_CPSM_State */ +} SDIO_CmdInitType; + +typedef struct +{ + uint32_t DatTimeout; /*!< Specifies the data timeout period in card bus clock periods. */ + + uint32_t DatLen; /*!< Specifies the number of data bytes to be transferred. */ + + uint32_t DatBlkSize; /*!< Specifies the data block size for block transfer. + This parameter can be a value of @ref SDIO_Data_Block_Size */ + + uint32_t TransferDirection; /*!< Specifies the data transfer direction, whether the transfer + is a read or write. + This parameter can be a value of @ref SDIO_Transfer_Direction */ + + uint32_t TransferMode; /*!< Specifies whether data transfer is in stream or block mode. + This parameter can be a value of @ref SDIO_Transfer_Type */ + + uint32_t DPSMConfig; /*!< Specifies whether SDIO Data path state machine (DPSM) + is enabled or disabled. + This parameter can be a value of @ref SDIO_DPSM_State */ +} SDIO_DataInitType; + +/** + * @} + */ + +/** @addtogroup SDIO_Exported_Constants + * @{ + */ + +/** @addtogroup SDIO_Clock_Edge + * @{ + */ + +#define SDIO_CLKEDGE_RISING ((uint32_t)0x00000000) +#define SDIO_CLKEDGE_FALLING ((uint32_t)0x00002000) +#define IS_SDIO_CLK_EDGE(EDGE) (((EDGE) == SDIO_CLKEDGE_RISING) || ((EDGE) == SDIO_CLKEDGE_FALLING)) +/** + * @} + */ + +/** @addtogroup SDIO_Clock_Bypass + * @{ + */ + +#define SDIO_ClkBYPASS_DISABLE ((uint32_t)0x00000000) +#define SDIO_ClkBYPASS_ENABLE ((uint32_t)0x00000400) +#define IS_SDIO_CLK_BYPASS(BYPASS) (((BYPASS) == SDIO_ClkBYPASS_DISABLE) || ((BYPASS) == SDIO_ClkBYPASS_ENABLE)) +/** + * @} + */ + +/** @addtogroup SDIO_Clock_Power_Save + * @{ + */ + +#define SDIO_CLKPOWERSAVE_DISABLE ((uint32_t)0x00000000) +#define SDIO_CLKPOWERSAVE_ENABLE ((uint32_t)0x00000200) +#define IS_SDIO_CLK_POWER_SAVE(SAVE) (((SAVE) == SDIO_CLKPOWERSAVE_DISABLE) || ((SAVE) == SDIO_CLKPOWERSAVE_ENABLE)) +/** + * @} + */ + +/** @addtogroup SDIO_Bus_Wide + * @{ + */ + +#define SDIO_BUSWIDTH_1B ((uint32_t)0x00000000) +#define SDIO_BUSWIDTH_4B ((uint32_t)0x00000800) +#define SDIO_BUSWIDTH_8B ((uint32_t)0x00001000) +#define IS_SDIO_BUS_WIDTH(WIDE) \ + (((WIDE) == SDIO_BUSWIDTH_1B) || ((WIDE) == SDIO_BUSWIDTH_4B) || ((WIDE) == SDIO_BUSWIDTH_8B)) + +/** + * @} + */ + +/** @addtogroup SDIO_Hardware_Flow_Control + * @{ + */ + +#define SDIO_HARDWARE_CLKCTRL_DISABLE ((uint32_t)0x00000000) +#define SDIO_HARDWARE_CLKCTRL_ENABLE ((uint32_t)0x00004000) +#define IS_SDIO_HARDWARE_CLKCTRL(CONTROL) \ + (((CONTROL) == SDIO_HARDWARE_CLKCTRL_DISABLE) || ((CONTROL) == SDIO_HARDWARE_CLKCTRL_ENABLE)) +/** + * @} + */ + +/** @addtogroup SDIO_Power_State + * @{ + */ + +#define SDIO_POWER_CTRL_OFF ((uint32_t)0x00000000) +#define SDIO_POWER_CTRL_ON ((uint32_t)0x00000003) +#define IS_SDIO_POWER_CTRL(STATE) (((STATE) == SDIO_POWER_CTRL_OFF) || ((STATE) == SDIO_POWER_CTRL_ON)) +/** + * @} + */ + +/** @addtogroup SDIO_Interrupt_sources + * @{ + */ + +#define SDIO_INT_CCRCERR ((uint32_t)0x00000001) +#define SDIO_INT_DCRCERR ((uint32_t)0x00000002) +#define SDIO_INT_CMDTIMEOUT ((uint32_t)0x00000004) +#define SDIO_INT_DATTIMEOUT ((uint32_t)0x00000008) +#define SDIO_INT_TXURERR ((uint32_t)0x00000010) +#define SDIO_INT_RXORERR ((uint32_t)0x00000020) +#define SDIO_INT_CMDRESPRECV ((uint32_t)0x00000040) +#define SDIO_INT_CMDSEND ((uint32_t)0x00000080) +#define SDIO_INT_DATEND ((uint32_t)0x00000100) +#define SDIO_INT_SBERR ((uint32_t)0x00000200) +#define SDIO_INT_DATBLKEND ((uint32_t)0x00000400) +#define SDIO_INT_CMDRUN ((uint32_t)0x00000800) +#define SDIO_INT_TXRUN ((uint32_t)0x00001000) +#define SDIO_INT_RXRUN ((uint32_t)0x00002000) +#define SDIO_INT_TFIFOHE ((uint32_t)0x00004000) +#define SDIO_INT_RFIFOHF ((uint32_t)0x00008000) +#define SDIO_INT_TFIFOF ((uint32_t)0x00010000) +#define SDIO_INT_RFIFOF ((uint32_t)0x00020000) +#define SDIO_INT_TFIFOE ((uint32_t)0x00040000) +#define SDIO_INT_RFIFOE ((uint32_t)0x00080000) +#define SDIO_INT_TDATVALID ((uint32_t)0x00100000) +#define SDIO_INT_RDATVALID ((uint32_t)0x00200000) +#define SDIO_INT_SDIOINT ((uint32_t)0x00400000) +#define SDIO_INT_CEATAF ((uint32_t)0x00800000) +#define IS_SDIO_INT(IT) ((((IT) & (uint32_t)0xFF000000) == 0x00) && ((IT) != (uint32_t)0x00)) +/** + * @} + */ + +/** @addtogroup SDIO_Command_Index + * @{ + */ + +#define IS_SDIO_CMD_INDEX(INDEX) ((INDEX) < 0x40) +/** + * @} + */ + +/** @addtogroup SDIO_Response_Type + * @{ + */ + +#define SDIO_RESP_NO ((uint32_t)0x00000000) +#define SDIO_RESP_SHORT ((uint32_t)0x00000040) +#define SDIO_RESP_LONG ((uint32_t)0x000000C0) +#define IS_SDIO_RESP(RESPONSE) \ + (((RESPONSE) == SDIO_RESP_NO) || ((RESPONSE) == SDIO_RESP_SHORT) || ((RESPONSE) == SDIO_RESP_LONG)) +/** + * @} + */ + +/** @addtogroup SDIO_Wait_Interrupt_State + * @{ + */ + +#define SDIO_WAIT_NO ((uint32_t)0x00000000) /*!< SDIO No Wait, TimeOut is enabled */ +#define SDIO_WAIT_INT ((uint32_t)0x00000100) /*!< SDIO Wait Interrupt Request */ +#define SDIO_WAIT_PEND ((uint32_t)0x00000200) /*!< SDIO Wait End of transfer */ +#define IS_SDIO_WAIT(WAIT) (((WAIT) == SDIO_WAIT_NO) || ((WAIT) == SDIO_WAIT_INT) || ((WAIT) == SDIO_WAIT_PEND)) +/** + * @} + */ + +/** @addtogroup SDIO_CPSM_State + * @{ + */ + +#define SDIO_CPSM_DISABLE ((uint32_t)0x00000000) +#define SDIO_CPSM_ENABLE ((uint32_t)0x00000400) +#define IS_SDIO_CPSM(CPSM) (((CPSM) == SDIO_CPSM_ENABLE) || ((CPSM) == SDIO_CPSM_DISABLE)) +/** + * @} + */ + +/** @addtogroup SDIO_Response_Registers + * @{ + */ + +#define SDIO_RESPONSE_1 ((uint32_t)0x00000000) +#define SDIO_RESPONSE_2 ((uint32_t)0x00000004) +#define SDIO_RESPONSE_3 ((uint32_t)0x00000008) +#define SDIO_RESPONSE_4 ((uint32_t)0x0000000C) +#define IS_SDIO_RESPONSE(RESP) \ + (((RESP) == SDIO_RESPONSE_1) || ((RESP) == SDIO_RESPONSE_2) || ((RESP) == SDIO_RESPONSE_3) \ + || ((RESP) == SDIO_RESPONSE_4)) +/** + * @} + */ + +/** @addtogroup SDIO_Data_Length + * @{ + */ + +#define IS_SDIO_DAT_LEN(LENGTH) ((LENGTH) <= 0x01FFFFFF) +/** + * @} + */ + +/** @addtogroup SDIO_Data_Block_Size + * @{ + */ + +#define SDIO_DATBLK_SIZE_1B ((uint32_t)0x00000000) +#define SDIO_DATBLK_SIZE_2B ((uint32_t)0x00000010) +#define SDIO_DATBLK_SIZE_4B ((uint32_t)0x00000020) +#define SDIO_DATBLK_SIZE_8B ((uint32_t)0x00000030) +#define SDIO_DATBLK_SIZE_16B ((uint32_t)0x00000040) +#define SDIO_DATBLK_SIZE_32B ((uint32_t)0x00000050) +#define SDIO_DATBLK_SIZE_64B ((uint32_t)0x00000060) +#define SDIO_DATBLK_SIZE_128B ((uint32_t)0x00000070) +#define SDIO_DATBLK_SIZE_256B ((uint32_t)0x00000080) +#define SDIO_DATBLK_SIZE_512B ((uint32_t)0x00000090) +#define SDIO_DATBLK_SIZE_1024B ((uint32_t)0x000000A0) +#define SDIO_DATBLK_SIZE_2048B ((uint32_t)0x000000B0) +#define SDIO_DATBLK_SIZE_4096B ((uint32_t)0x000000C0) +#define SDIO_DATBLK_SIZE_8192B ((uint32_t)0x000000D0) +#define SDIO_DATBLK_SIZE_16384B ((uint32_t)0x000000E0) +#define IS_SDIO_BLK_SIZE(SIZE) \ + (((SIZE) == SDIO_DATBLK_SIZE_1B) || ((SIZE) == SDIO_DATBLK_SIZE_2B) || ((SIZE) == SDIO_DATBLK_SIZE_4B) \ + || ((SIZE) == SDIO_DATBLK_SIZE_8B) || ((SIZE) == SDIO_DATBLK_SIZE_16B) || ((SIZE) == SDIO_DATBLK_SIZE_32B) \ + || ((SIZE) == SDIO_DATBLK_SIZE_64B) || ((SIZE) == SDIO_DATBLK_SIZE_128B) || ((SIZE) == SDIO_DATBLK_SIZE_256B) \ + || ((SIZE) == SDIO_DATBLK_SIZE_512B) || ((SIZE) == SDIO_DATBLK_SIZE_1024B) || ((SIZE) == SDIO_DATBLK_SIZE_2048B) \ + || ((SIZE) == SDIO_DATBLK_SIZE_4096B) || ((SIZE) == SDIO_DATBLK_SIZE_8192B) \ + || ((SIZE) == SDIO_DATBLK_SIZE_16384B)) +/** + * @} + */ + +/** @addtogroup SDIO_Transfer_Direction + * @{ + */ + +#define SDIO_TRANSDIR_TOCARD ((uint32_t)0x00000000) +#define SDIO_TRANSDIR_TOSDIO ((uint32_t)0x00000002) +#define IS_SDIO_TRANSFER_DIRECTION(DIR) (((DIR) == SDIO_TRANSDIR_TOCARD) || ((DIR) == SDIO_TRANSDIR_TOSDIO)) +/** + * @} + */ + +/** @addtogroup SDIO_Transfer_Type + * @{ + */ + +#define SDIO_TRANSMODE_BLOCK ((uint32_t)0x00000000) +#define SDIO_TRANSMODE_STREAM ((uint32_t)0x00000004) +#define IS_SDIO_TRANS_MODE(MODE) (((MODE) == SDIO_TRANSMODE_STREAM) || ((MODE) == SDIO_TRANSMODE_BLOCK)) +/** + * @} + */ + +/** @addtogroup SDIO_DPSM_State + * @{ + */ + +#define SDIO_DPSM_DISABLE ((uint32_t)0x00000000) +#define SDIO_DPSM_ENABLE ((uint32_t)0x00000001) +#define IS_SDIO_DPSM(DPSM) (((DPSM) == SDIO_DPSM_ENABLE) || ((DPSM) == SDIO_DPSM_DISABLE)) +/** + * @} + */ + +/** @addtogroup SDIO_Flags + * @{ + */ + +#define SDIO_FLAG_CCRCERR ((uint32_t)0x00000001) +#define SDIO_FLAG_DCRCERR ((uint32_t)0x00000002) +#define SDIO_FLAG_CMDTIMEOUT ((uint32_t)0x00000004) +#define SDIO_FLAG_DATTIMEOUT ((uint32_t)0x00000008) +#define SDIO_FLAG_TXURERR ((uint32_t)0x00000010) +#define SDIO_FLAG_RXORERR ((uint32_t)0x00000020) +#define SDIO_FLAG_CMDRESPRECV ((uint32_t)0x00000040) +#define SDIO_FLAG_CMDSEND ((uint32_t)0x00000080) +#define SDIO_FLAG_DATEND ((uint32_t)0x00000100) +#define SDIO_FLAG_SBERR ((uint32_t)0x00000200) +#define SDIO_FLAG_DATBLKEND ((uint32_t)0x00000400) +#define SDIO_FLAG_CMDRUN ((uint32_t)0x00000800) +#define SDIO_FLAG_TXRUN ((uint32_t)0x00001000) +#define SDIO_FLAG_RXRUN ((uint32_t)0x00002000) +#define SDIO_FLAG_TFIFOHE ((uint32_t)0x00004000) +#define SDIO_FLAG_RFIFOHF ((uint32_t)0x00008000) +#define SDIO_FLAG_TFIFOF ((uint32_t)0x00010000) +#define SDIO_FLAG_RFIFOF ((uint32_t)0x00020000) +#define SDIO_FLAG_TFIFOE ((uint32_t)0x00040000) +#define SDIO_FLAG_RFIFOE ((uint32_t)0x00080000) +#define SDIO_FLAG_TDATVALID ((uint32_t)0x00100000) +#define SDIO_FLAG_RDATVALID ((uint32_t)0x00200000) +#define SDIO_FLAG_SDIOINT ((uint32_t)0x00400000) +#define SDIO_FLAG_CEATAF ((uint32_t)0x00800000) +#define IS_SDIO_FLAG(FLAG) \ + (((FLAG) == SDIO_FLAG_CCRCERR) || ((FLAG) == SDIO_FLAG_DCRCERR) || ((FLAG) == SDIO_FLAG_CMDTIMEOUT) \ + || ((FLAG) == SDIO_FLAG_DATTIMEOUT) || ((FLAG) == SDIO_FLAG_TXURERR) || ((FLAG) == SDIO_FLAG_RXORERR) \ + || ((FLAG) == SDIO_FLAG_CMDRESPRECV) || ((FLAG) == SDIO_FLAG_CMDSEND) || ((FLAG) == SDIO_FLAG_DATEND) \ + || ((FLAG) == SDIO_FLAG_SBERR) || ((FLAG) == SDIO_FLAG_DATBLKEND) || ((FLAG) == SDIO_FLAG_CMDRUN) \ + || ((FLAG) == SDIO_FLAG_TXRUN) || ((FLAG) == SDIO_FLAG_RXRUN) || ((FLAG) == SDIO_FLAG_TFIFOHE) \ + || ((FLAG) == SDIO_FLAG_RFIFOHF) || ((FLAG) == SDIO_FLAG_TFIFOF) || ((FLAG) == SDIO_FLAG_RFIFOF) \ + || ((FLAG) == SDIO_FLAG_TFIFOE) || ((FLAG) == SDIO_FLAG_RFIFOE) || ((FLAG) == SDIO_FLAG_TDATVALID) \ + || ((FLAG) == SDIO_FLAG_RDATVALID) || ((FLAG) == SDIO_FLAG_SDIOINT) || ((FLAG) == SDIO_FLAG_CEATAF)) + +#define IS_SDIO_CLR_FLAG(FLAG) ((((FLAG) & (uint32_t)0xFF3FF800) == 0x00) && ((FLAG) != (uint32_t)0x00)) + +#define IS_SDIO_GET_INT(IT) \ + (((IT) == SDIO_INT_CCRCERR) || ((IT) == SDIO_INT_DCRCERR) || ((IT) == SDIO_INT_CMDTIMEOUT) \ + || ((IT) == SDIO_INT_DATTIMEOUT) || ((IT) == SDIO_INT_TXURERR) || ((IT) == SDIO_INT_RXORERR) \ + || ((IT) == SDIO_INT_CMDRESPRECV) || ((IT) == SDIO_INT_CMDSEND) || ((IT) == SDIO_INT_DATEND) \ + || ((IT) == SDIO_INT_SBERR) || ((IT) == SDIO_INT_DATBLKEND) || ((IT) == SDIO_INT_CMDRUN) \ + || ((IT) == SDIO_INT_TXRUN) || ((IT) == SDIO_INT_RXRUN) || ((IT) == SDIO_INT_TFIFOHE) \ + || ((IT) == SDIO_INT_RFIFOHF) || ((IT) == SDIO_INT_TFIFOF) || ((IT) == SDIO_INT_RFIFOF) \ + || ((IT) == SDIO_INT_TFIFOE) || ((IT) == SDIO_INT_RFIFOE) || ((IT) == SDIO_INT_TDATVALID) \ + || ((IT) == SDIO_INT_RDATVALID) || ((IT) == SDIO_INT_SDIOINT) || ((IT) == SDIO_INT_CEATAF)) + +#define IS_SDIO_CLR_INT(IT) ((((IT) & (uint32_t)0xFF3FF800) == 0x00) && ((IT) != (uint32_t)0x00)) + +/** + * @} + */ + +/** @addtogroup SDIO_Read_Wait_Mode + * @{ + */ + +#define SDIO_RDWAIT_MODE_CLK ((uint32_t)0x00000001) +#define SDIO_RDWAIT_MODE_DAT2 ((uint32_t)0x00000000) +#define IS_SDIO_RDWAIT_MODE(MODE) (((MODE) == SDIO_RDWAIT_MODE_CLK) || ((MODE) == SDIO_RDWAIT_MODE_DAT2)) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup SDIO_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SDIO_Exported_Functions + * @{ + */ + +void SDIO_DeInit(void); +void SDIO_Init(SDIO_InitType* SDIO_InitStruct); +void SDIO_InitStruct(SDIO_InitType* SDIO_InitStruct); +void SDIO_EnableClock(FunctionalState Cmd); +void SDIO_SetPower(uint32_t SDIO_PowerState); +uint32_t SDIO_GetPower(void); +void SDIO_ConfigInt(uint32_t SDIO_IT, FunctionalState Cmd); +void SDIO_DMACmd(FunctionalState Cmd); +void SDIO_SendCmd(SDIO_CmdInitType* SDIO_CmdInitStruct); +void SDIO_InitCmdStruct(SDIO_CmdInitType* SDIO_CmdInitStruct); +uint8_t SDIO_GetCmdResp(void); +uint32_t SDIO_GetResp(uint32_t SDIO_RESP); +void SDIO_ConfigData(SDIO_DataInitType* SDIO_DataInitStruct); +void SDIO_InitDataStruct(SDIO_DataInitType* SDIO_DataInitStruct); +uint32_t SDIO_GetDataCountValue(void); +uint32_t SDIO_ReadData(void); +void SDIO_WriteData(uint32_t Data); +uint32_t SDIO_GetFifoCounter(void); +void SDIO_EnableReadWait(FunctionalState Cmd); +void SDIO_DisableReadWait(FunctionalState Cmd); +void SDIO_EnableSdioReadWaitMode(uint32_t SDIO_ReadWaitMode); +void SDIO_EnableSdioOperation(FunctionalState Cmd); +void SDIO_EnableSendSdioSuspend(FunctionalState Cmd); +void SDIO_EnableCommandCompletion(FunctionalState Cmd); +void SDIO_EnableCEATAInt(FunctionalState Cmd); +void SDIO_EnableSendCEATA(FunctionalState Cmd); +FlagStatus SDIO_GetFlag(uint32_t SDIO_FLAG); +void SDIO_ClrFlag(uint32_t SDIO_FLAG); +INTStatus SDIO_GetIntStatus(uint32_t SDIO_IT); +void SDIO_ClrIntPendingBit(uint32_t SDIO_IT); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G4FR_SDIO_H__ */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_spi.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_spi.h new file mode 100644 index 0000000000..348b804169 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_spi.h @@ -0,0 +1,471 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_spi.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_SPI_H__ +#define __N32G4FR_SPI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup SPI + * @{ + */ + +/** @addtogroup SPI_Exported_Types + * @{ + */ + +/** + * @brief SPI Init structure definition + */ + +typedef struct +{ + uint16_t DataDirection; /*!< Specifies the SPI unidirectional or bidirectional data mode. + This parameter can be a value of @ref SPI_data_direction */ + + uint16_t SpiMode; /*!< Specifies the SPI operating mode. + This parameter can be a value of @ref SPI_mode */ + + uint16_t DataLen; /*!< Specifies the SPI data size. + This parameter can be a value of @ref SPI_data_size */ + + uint16_t CLKPOL; /*!< Specifies the serial clock steady state. + This parameter can be a value of @ref SPI_Clock_Polarity */ + + uint16_t CLKPHA; /*!< Specifies the clock active edge for the bit capture. + This parameter can be a value of @ref SPI_Clock_Phase */ + + uint16_t NSS; /*!< Specifies whether the NSS signal is managed by + hardware (NSS pin) or by software using the SSI bit. + This parameter can be a value of @ref SPI_Slave_Select_management */ + + uint16_t BaudRatePres; /*!< Specifies the Baud Rate prescaler value which will be + used to configure the transmit and receive SCK clock. + This parameter can be a value of @ref SPI_BaudRate_Prescaler. + @note The communication clock is derived from the master + clock. The slave clock does not need to be set. */ + + uint16_t FirstBit; /*!< Specifies whether data transfers start from MSB or LSB bit. + This parameter can be a value of @ref SPI_MSB_LSB_transmission */ + + uint16_t CRCPoly; /*!< Specifies the polynomial used for the CRC calculation. */ +} SPI_InitType; + +/** + * @brief I2S Init structure definition + */ + +typedef struct +{ + uint16_t I2sMode; /*!< Specifies the I2S operating mode. + This parameter can be a value of @ref I2sMode */ + + uint16_t Standard; /*!< Specifies the standard used for the I2S communication. + This parameter can be a value of @ref Standard */ + + uint16_t DataFormat; /*!< Specifies the data format for the I2S communication. + This parameter can be a value of @ref I2S_Data_Format */ + + uint16_t MCLKEnable; /*!< Specifies whether the I2S MCLK output is enabled or not. + This parameter can be a value of @ref I2S_MCLK_Output */ + + uint32_t AudioFrequency; /*!< Specifies the frequency selected for the I2S communication. + This parameter can be a value of @ref I2S_Audio_Frequency */ + + uint16_t CLKPOL; /*!< Specifies the idle state of the I2S clock. + This parameter can be a value of @ref I2S_Clock_Polarity */ +} I2S_InitType; + +/** + * @} + */ + +/** @addtogroup SPI_Exported_Constants + * @{ + */ + +#define IS_SPI_PERIPH(PERIPH) (((PERIPH) == SPI1) || ((PERIPH) == SPI2) || ((PERIPH) == SPI3)) + +#define IS_SPI_2OR3_PERIPH(PERIPH) (((PERIPH) == SPI2) || ((PERIPH) == SPI3)) + +/** @addtogroup SPI_data_direction + * @{ + */ + +#define SPI_DIR_DOUBLELINE_FULLDUPLEX ((uint16_t)0x0000) +#define SPI_DIR_DOUBLELINE_RONLY ((uint16_t)0x0400) +#define SPI_DIR_SINGLELINE_RX ((uint16_t)0x8000) +#define SPI_DIR_SINGLELINE_TX ((uint16_t)0xC000) +#define IS_SPI_DIR_MODE(MODE) \ + (((MODE) == SPI_DIR_DOUBLELINE_FULLDUPLEX) || ((MODE) == SPI_DIR_DOUBLELINE_RONLY) \ + || ((MODE) == SPI_DIR_SINGLELINE_RX) || ((MODE) == SPI_DIR_SINGLELINE_TX)) +/** + * @} + */ + +/** @addtogroup SPI_mode + * @{ + */ + +#define SPI_MODE_MASTER ((uint16_t)0x0104) +#define SPI_MODE_SLAVE ((uint16_t)0x0000) +#define IS_SPI_MODE(MODE) (((MODE) == SPI_MODE_MASTER) || ((MODE) == SPI_MODE_SLAVE)) +/** + * @} + */ + +/** @addtogroup SPI_data_size + * @{ + */ + +#define SPI_DATA_SIZE_16BITS ((uint16_t)0x0800) +#define SPI_DATA_SIZE_8BITS ((uint16_t)0x0000) +#define IS_SPI_DATASIZE(DATASIZE) (((DATASIZE) == SPI_DATA_SIZE_16BITS) || ((DATASIZE) == SPI_DATA_SIZE_8BITS)) +/** + * @} + */ + +/** @addtogroup SPI_Clock_Polarity + * @{ + */ + +#define SPI_CLKPOL_LOW ((uint16_t)0x0000) +#define SPI_CLKPOL_HIGH ((uint16_t)0x0002) +#define IS_SPI_CLKPOL(CPOL) (((CPOL) == SPI_CLKPOL_LOW) || ((CPOL) == SPI_CLKPOL_HIGH)) +/** + * @} + */ + +/** @addtogroup SPI_Clock_Phase + * @{ + */ + +#define SPI_CLKPHA_FIRST_EDGE ((uint16_t)0x0000) +#define SPI_CLKPHA_SECOND_EDGE ((uint16_t)0x0001) +#define IS_SPI_CLKPHA(CPHA) (((CPHA) == SPI_CLKPHA_FIRST_EDGE) || ((CPHA) == SPI_CLKPHA_SECOND_EDGE)) +/** + * @} + */ + +/** @addtogroup SPI_Slave_Select_management + * @{ + */ + +#define SPI_NSS_SOFT ((uint16_t)0x0200) +#define SPI_NSS_HARD ((uint16_t)0x0000) +#define IS_SPI_NSS(NSS) (((NSS) == SPI_NSS_SOFT) || ((NSS) == SPI_NSS_HARD)) +/** + * @} + */ + +/** @addtogroup SPI_BaudRate_Prescaler + * @{ + */ + +#define SPI_BR_PRESCALER_2 ((uint16_t)0x0000) +#define SPI_BR_PRESCALER_4 ((uint16_t)0x0008) +#define SPI_BR_PRESCALER_8 ((uint16_t)0x0010) +#define SPI_BR_PRESCALER_16 ((uint16_t)0x0018) +#define SPI_BR_PRESCALER_32 ((uint16_t)0x0020) +#define SPI_BR_PRESCALER_64 ((uint16_t)0x0028) +#define SPI_BR_PRESCALER_128 ((uint16_t)0x0030) +#define SPI_BR_PRESCALER_256 ((uint16_t)0x0038) +#define IS_SPI_BR_PRESCALER(PRESCALER) \ + (((PRESCALER) == SPI_BR_PRESCALER_2) || ((PRESCALER) == SPI_BR_PRESCALER_4) || ((PRESCALER) == SPI_BR_PRESCALER_8) \ + || ((PRESCALER) == SPI_BR_PRESCALER_16) || ((PRESCALER) == SPI_BR_PRESCALER_32) \ + || ((PRESCALER) == SPI_BR_PRESCALER_64) || ((PRESCALER) == SPI_BR_PRESCALER_128) \ + || ((PRESCALER) == SPI_BR_PRESCALER_256)) +/** + * @} + */ + +/** @addtogroup SPI_MSB_LSB_transmission + * @{ + */ + +#define SPI_FB_MSB ((uint16_t)0x0000) +#define SPI_FB_LSB ((uint16_t)0x0080) +#define IS_SPI_FIRST_BIT(BIT) (((BIT) == SPI_FB_MSB) || ((BIT) == SPI_FB_LSB)) +/** + * @} + */ + +/** @addtogroup I2sMode + * @{ + */ + +#define I2S_MODE_SlAVE_TX ((uint16_t)0x0000) +#define I2S_MODE_SlAVE_RX ((uint16_t)0x0100) +#define I2S_MODE_MASTER_TX ((uint16_t)0x0200) +#define I2S_MODE_MASTER_RX ((uint16_t)0x0300) +#define IS_I2S_MODE(MODE) \ + (((MODE) == I2S_MODE_SlAVE_TX) || ((MODE) == I2S_MODE_SlAVE_RX) || ((MODE) == I2S_MODE_MASTER_TX) \ + || ((MODE) == I2S_MODE_MASTER_RX)) +/** + * @} + */ + +/** @addtogroup Standard + * @{ + */ + +#define I2S_STD_PHILLIPS ((uint16_t)0x0000) +#define I2S_STD_MSB_ALIGN ((uint16_t)0x0010) +#define I2S_STD_LSB_ALIGN ((uint16_t)0x0020) +#define I2S_STD_PCM_SHORTFRAME ((uint16_t)0x0030) +#define I2S_STD_PCM_LONGFRAME ((uint16_t)0x00B0) +#define IS_I2S_STANDARD(STANDARD) \ + (((STANDARD) == I2S_STD_PHILLIPS) || ((STANDARD) == I2S_STD_MSB_ALIGN) || ((STANDARD) == I2S_STD_LSB_ALIGN) \ + || ((STANDARD) == I2S_STD_PCM_SHORTFRAME) || ((STANDARD) == I2S_STD_PCM_LONGFRAME)) +/** + * @} + */ + +/** @addtogroup I2S_Data_Format + * @{ + */ + +#define I2S_DATA_FMT_16BITS ((uint16_t)0x0000) +#define I2S_DATA_FMT_16BITS_EXTENDED ((uint16_t)0x0001) +#define I2S_DATA_FMT_24BITS ((uint16_t)0x0003) +#define I2S_DATA_FMT_32BITS ((uint16_t)0x0005) +#define IS_I2S_DATA_FMT(FORMAT) \ + (((FORMAT) == I2S_DATA_FMT_16BITS) || ((FORMAT) == I2S_DATA_FMT_16BITS_EXTENDED) \ + || ((FORMAT) == I2S_DATA_FMT_24BITS) || ((FORMAT) == I2S_DATA_FMT_32BITS)) +/** + * @} + */ + +/** @addtogroup I2S_MCLK_Output + * @{ + */ + +#define I2S_MCLK_ENABLE ((uint16_t)0x0200) +#define I2S_MCLK_DISABLE ((uint16_t)0x0000) +#define IS_I2S_MCLK_ENABLE(OUTPUT) (((OUTPUT) == I2S_MCLK_ENABLE) || ((OUTPUT) == I2S_MCLK_DISABLE)) +/** + * @} + */ + +/** @addtogroup I2S_Audio_Frequency + * @{ + */ + +#define I2S_AUDIO_FREQ_192K ((uint32_t)192000) +#define I2S_AUDIO_FREQ_96K ((uint32_t)96000) +#define I2S_AUDIO_FREQ_48K ((uint32_t)48000) +#define I2S_AUDIO_FREQ_44K ((uint32_t)44100) +#define I2S_AUDIO_FREQ_32K ((uint32_t)32000) +#define I2S_AUDIO_FREQ_22K ((uint32_t)22050) +#define I2S_AUDIO_FREQ_16K ((uint32_t)16000) +#define I2S_AUDIO_FREQ_11K ((uint32_t)11025) +#define I2S_AUDIO_FREQ_8K ((uint32_t)8000) +#define I2S_AUDIO_FREQ_DEFAULT ((uint32_t)2) + +#define IS_I2S_AUDIO_FREQ(FREQ) \ + ((((FREQ) >= I2S_AUDIO_FREQ_8K) && ((FREQ) <= I2S_AUDIO_FREQ_192K)) || ((FREQ) == I2S_AUDIO_FREQ_DEFAULT)) +/** + * @} + */ + +/** @addtogroup I2S_Clock_Polarity + * @{ + */ + +#define I2S_CLKPOL_LOW ((uint16_t)0x0000) +#define I2S_CLKPOL_HIGH ((uint16_t)0x0008) +#define IS_I2S_CLKPOL(CPOL) (((CPOL) == I2S_CLKPOL_LOW) || ((CPOL) == I2S_CLKPOL_HIGH)) +/** + * @} + */ + +/** @addtogroup SPI_I2S_DMA_transfer_requests + * @{ + */ + +#define SPI_I2S_DMA_TX ((uint16_t)0x0002) +#define SPI_I2S_DMA_RX ((uint16_t)0x0001) +#define IS_SPI_I2S_DMA(DMAREQ) ((((DMAREQ) & (uint16_t)0xFFFC) == 0x00) && ((DMAREQ) != 0x00)) +/** + * @} + */ + +/** @addtogroup SPI_NSS_internal_software_management + * @{ + */ + +#define SPI_NSS_HIGH ((uint16_t)0x0100) +#define SPI_NSS_LOW ((uint16_t)0xFEFF) +#define IS_SPI_NSS_LEVEL(INTERNAL) (((INTERNAL) == SPI_NSS_HIGH) || ((INTERNAL) == SPI_NSS_LOW)) +/** + * @} + */ + +/** @addtogroup SPI_CRC_Transmit_Receive + * @{ + */ + +#define SPI_CRC_TX ((uint8_t)0x00) +#define SPI_CRC_RX ((uint8_t)0x01) +#define IS_SPI_CRC(CRC) (((CRC) == SPI_CRC_TX) || ((CRC) == SPI_CRC_RX)) +/** + * @} + */ + +/** @addtogroup SPI_direction_transmit_receive + * @{ + */ + +#define SPI_BIDIRECTION_RX ((uint16_t)0xBFFF) +#define SPI_BIDIRECTION_TX ((uint16_t)0x4000) +#define IS_SPI_BIDIRECTION(DIRECTION) (((DIRECTION) == SPI_BIDIRECTION_RX) || ((DIRECTION) == SPI_BIDIRECTION_TX)) +/** + * @} + */ + +/** @addtogroup SPI_I2S_interrupts_definition + * @{ + */ + +#define SPI_I2S_INT_TE ((uint8_t)0x71) +#define SPI_I2S_INT_RNE ((uint8_t)0x60) +#define SPI_I2S_INT_ERR ((uint8_t)0x50) +#define IS_SPI_I2S_CONFIG_INT(IT) (((IT) == SPI_I2S_INT_TE) || ((IT) == SPI_I2S_INT_RNE) || ((IT) == SPI_I2S_INT_ERR)) +#define SPI_I2S_INT_OVER ((uint8_t)0x56) +#define SPI_INT_MODERR ((uint8_t)0x55) +#define SPI_INT_CRCERR ((uint8_t)0x54) +#define I2S_INT_UNDER ((uint8_t)0x53) +#define IS_SPI_I2S_CLR_INT(IT) (((IT) == SPI_INT_CRCERR)) +#define IS_SPI_I2S_GET_INT(IT) \ + (((IT) == SPI_I2S_INT_RNE) || ((IT) == SPI_I2S_INT_TE) || ((IT) == I2S_INT_UNDER) || ((IT) == SPI_INT_CRCERR) \ + || ((IT) == SPI_INT_MODERR) || ((IT) == SPI_I2S_INT_OVER)) +/** + * @} + */ + +/** @addtogroup SPI_I2S_flags_definition + * @{ + */ + +#define SPI_I2S_RNE_FLAG ((uint16_t)0x0001) +#define SPI_I2S_TE_FLAG ((uint16_t)0x0002) +#define I2S_CHSIDE_FLAG ((uint16_t)0x0004) +#define I2S_UNDER_FLAG ((uint16_t)0x0008) +#define SPI_CRCERR_FLAG ((uint16_t)0x0010) +#define SPI_MODERR_FLAG ((uint16_t)0x0020) +#define SPI_I2S_OVER_FLAG ((uint16_t)0x0040) +#define SPI_I2S_BUSY_FLAG ((uint16_t)0x0080) +#define IS_SPI_I2S_CLR_FLAG(FLAG) (((FLAG) == SPI_CRCERR_FLAG)) +#define IS_SPI_I2S_GET_FLAG(FLAG) \ + (((FLAG) == SPI_I2S_BUSY_FLAG) || ((FLAG) == SPI_I2S_OVER_FLAG) || ((FLAG) == SPI_MODERR_FLAG) \ + || ((FLAG) == SPI_CRCERR_FLAG) || ((FLAG) == I2S_UNDER_FLAG) || ((FLAG) == I2S_CHSIDE_FLAG) \ + || ((FLAG) == SPI_I2S_TE_FLAG) || ((FLAG) == SPI_I2S_RNE_FLAG)) +/** + * @} + */ + +/** @addtogroup SPI_CRC_polynomial + * @{ + */ + +#define IS_SPI_CRC_POLYNOMIAL(POLYNOMIAL) ((POLYNOMIAL) >= 0x1) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup SPI_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SPI_Exported_Functions + * @{ + */ + +void SPI_I2S_DeInit(SPI_Module* SPIx); +void SPI_Init(SPI_Module* SPIx, SPI_InitType* SPI_InitStruct); +void I2S_Init(SPI_Module* SPIx, I2S_InitType* I2S_InitStruct); +void SPI_InitStruct(SPI_InitType* SPI_InitStruct); +void I2S_InitStruct(I2S_InitType* I2S_InitStruct); +void SPI_Enable(SPI_Module* SPIx, FunctionalState Cmd); +void I2S_Enable(SPI_Module* SPIx, FunctionalState Cmd); +void SPI_I2S_EnableInt(SPI_Module* SPIx, uint8_t SPI_I2S_IT, FunctionalState Cmd); +void SPI_I2S_EnableDma(SPI_Module* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState Cmd); +void SPI_I2S_TransmitData(SPI_Module* SPIx, uint16_t Data); +uint16_t SPI_I2S_ReceiveData(SPI_Module* SPIx); +void SPI_SetNssLevel(SPI_Module* SPIx, uint16_t SPI_NSSInternalSoft); +void SPI_SSOutputEnable(SPI_Module* SPIx, FunctionalState Cmd); +void SPI_ConfigDataLen(SPI_Module* SPIx, uint16_t DataLen); +void SPI_TransmitCrcNext(SPI_Module* SPIx); +void SPI_EnableCalculateCrc(SPI_Module* SPIx, FunctionalState Cmd); +uint16_t SPI_GetCRCDat(SPI_Module* SPIx, uint8_t SPI_CRC); +uint16_t SPI_GetCRCPoly(SPI_Module* SPIx); +void SPI_ConfigBidirectionalMode(SPI_Module* SPIx, uint16_t DataDirection); +FlagStatus SPI_I2S_GetStatus(SPI_Module* SPIx, uint16_t SPI_I2S_FLAG); +void SPI_I2S_ClrCRCErrFlag(SPI_Module* SPIx, uint16_t SPI_I2S_FLAG); +INTStatus SPI_I2S_GetIntStatus(SPI_Module* SPIx, uint8_t SPI_I2S_IT); +void SPI_I2S_ClrITPendingBit(SPI_Module* SPIx, uint8_t SPI_I2S_IT); + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G4FR_SPI_H__ */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_tim.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_tim.h new file mode 100644 index 0000000000..baf87ddefb --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_tim.h @@ -0,0 +1,1112 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_tim.h + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_TIM_H__ +#define __N32G4FR_TIM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" +#include "stdbool.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup TIM + * @{ + */ + +/** @addtogroup TIM_Exported_Types + * @{ + */ + +/** + * @brief TIM Time Base Init structure definition + * @note This structure is used with all TIMx except for TIM6 and TIM7. + */ + +typedef struct +{ + uint16_t Prescaler; /*!< Specifies the prescaler value used to divide the TIM clock. + This parameter can be a number between 0x0000 and 0xFFFF */ + + uint16_t CntMode; /*!< Specifies the counter mode. + This parameter can be a value of @ref TIM_Counter_Mode */ + + uint16_t Period; /*!< Specifies the period value to be loaded into the active + Auto-Reload Register at the next update event. + This parameter must be a number between 0x0000 and 0xFFFF. */ + + uint16_t ClkDiv; /*!< Specifies the clock division. + This parameter can be a value of @ref TIM_Clock_Division_CKD */ + + uint8_t RepetCnt; /*!< Specifies the repetition counter value. Each time the REPCNT downcounter + reaches zero, an update event is generated and counting restarts + from the REPCNT 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 + This parameter must be a number between 0x00 and 0xFF. + @note This parameter is valid only for TIM1 and TIM8. */ + + bool CapCh1FromCompEn; /*!< channel 1 select capture in from comp if 1, from IOM if 0 + Tim1,Tim8,Tim2,Tim3,Tim4,Tim5 valid*/ + bool CapCh2FromCompEn; /*!< channel 2 select capture in from comp if 1, from IOM if 0 + Tim2,Tim3,Tim4,Tim5 valid*/ + bool CapCh3FromCompEn; /*!< channel 3 select capture in from comp if 1, from IOM if 0 + Tim2,Tim3,Tim4,Tim5 valid*/ + bool CapCh4FromCompEn; /*!< channel 4 select capture in from comp if 1, from IOM if 0 + Tim2,Tim3,Tim4 valid*/ + bool CapEtrClrFromCompEn; /*!< etr clearref select from comp if 1, from ETR IOM if 0 + Tim2,Tim3,Tim4 valid*/ + bool CapEtrSelFromTscEn; /*!< etr select from TSC if 1, from IOM if 0 + Tim2,Tim4 valid*/ +} TIM_TimeBaseInitType; + +/** + * @brief TIM Output Compare Init structure definition + */ + +typedef struct +{ + uint16_t OcMode; /*!< Specifies the TIM mode. + This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */ + + uint16_t OutputState; /*!< Specifies the TIM Output Compare state. + This parameter can be a value of @ref TIM_Output_Compare_state */ + + uint16_t OutputNState; /*!< Specifies the TIM complementary Output Compare state. + This parameter can be a value of @ref TIM_Output_Compare_N_state + @note This parameter is valid only for TIM1 and TIM8. */ + + uint16_t Pulse; /*!< Specifies the pulse value to be loaded into the Capture Compare Register. + This parameter can be a number between 0x0000 and 0xFFFF */ + + uint16_t OcPolarity; /*!< Specifies the output polarity. + This parameter can be a value of @ref TIM_Output_Compare_Polarity */ + + uint16_t OcNPolarity; /*!< Specifies the complementary output polarity. + This parameter can be a value of @ref TIM_Output_Compare_N_Polarity + @note This parameter is valid only for TIM1 and TIM8. */ + + uint16_t OcIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_Idle_State + @note This parameter is valid only for TIM1 and TIM8. */ + + uint16_t OcNIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State + @note This parameter is valid only for TIM1 and TIM8. */ +} OCInitType; + +/** + * @brief TIM Input Capture Init structure definition + */ + +typedef struct +{ + uint16_t Channel; /*!< Specifies the TIM channel. + This parameter can be a value of @ref Channel */ + + uint16_t IcPolarity; /*!< Specifies the active edge of the input signal. + This parameter can be a value of @ref TIM_Input_Capture_Polarity */ + + uint16_t IcSelection; /*!< Specifies the input. + This parameter can be a value of @ref TIM_Input_Capture_Selection */ + + uint16_t IcPrescaler; /*!< Specifies the Input Capture Prescaler. + This parameter can be a value of @ref TIM_Input_Capture_Prescaler */ + + uint16_t IcFilter; /*!< Specifies the input capture filter. + This parameter can be a number between 0x0 and 0xF */ +} TIM_ICInitType; + +/** + * @brief BKDT structure definition + * @note This structure is used only with TIM1 and TIM8. + */ + +typedef struct +{ + uint16_t OssrState; /*!< Specifies the Off-State selection used in Run mode. + This parameter can be a value of @ref OSSR_Off_State_Selection_for_Run_mode_state */ + + uint16_t OssiState; /*!< Specifies the Off-State used in Idle state. + This parameter can be a value of @ref OSSI_Off_State_Selection_for_Idle_mode_state */ + + uint16_t LockLevel; /*!< Specifies the LOCK level parameters. + This parameter can be a value of @ref Lock_level */ + + uint16_t DeadTime; /*!< Specifies the delay time between the switching-off and the + switching-on of the outputs. + This parameter can be a number between 0x00 and 0xFF */ + + uint16_t Break; /*!< Specifies whether the TIM Break input is enabled or not. + This parameter can be a value of @ref Break_Input_enable_disable */ + + uint16_t BreakPolarity; /*!< Specifies the TIM Break Input pin polarity. + This parameter can be a value of @ref Break_Polarity */ + + uint16_t AutomaticOutput; /*!< Specifies whether the TIM Automatic Output feature is enabled or not. + This parameter can be a value of @ref TIM_AOE_Bit_Set_Reset */ + bool IomBreakEn; /*!< EXTENDMODE valid, open iom as break in*/ + bool LockUpBreakEn; /*!< EXTENDMODE valid, open lockup(haldfault) as break in*/ + bool PvdBreakEn; /*!< EXTENDMODE valid, open pvd(sys voltage too high or too low) as break in*/ +} TIM_BDTRInitType; + +/** @addtogroup TIM_Exported_constants + * @{ + */ + +#define IsTimAllModule(PERIPH) \ + (((PERIPH) == TIM1) || ((PERIPH) == TIM2) || ((PERIPH) == TIM3) || ((PERIPH) == TIM4) || ((PERIPH) == TIM5) \ + || ((PERIPH) == TIM6) || ((PERIPH) == TIM7) || ((PERIPH) == TIM8)) + +/* LIST1: TIM 1 and 8 */ +#define IsTimList1Module(PERIPH) (((PERIPH) == TIM1) || ((PERIPH) == TIM8)) + +/* LIST2: TIM 1, 8 */ +#define IsTimList2Module(PERIPH) (((PERIPH) == TIM1) || ((PERIPH) == TIM8)) + +/* LIST3: TIM 1, 2, 3, 4, 5 and 8 */ +#define IsTimList3Module(PERIPH) \ + (((PERIPH) == TIM1) || ((PERIPH) == TIM2) || ((PERIPH) == TIM3) || ((PERIPH) == TIM4) || ((PERIPH) == TIM5) \ + || ((PERIPH) == TIM8)) + +/* LIST4: TIM 1, 2, 3, 4, 5, 8 */ +#define IsTimList4Module(PERIPH) \ + (((PERIPH) == TIM1) || ((PERIPH) == TIM2) || ((PERIPH) == TIM3) || ((PERIPH) == TIM4) || ((PERIPH) == TIM5) \ + || ((PERIPH) == TIM8)) + +/* LIST5: TIM 1, 2, 3, 4, 5, 8 */ +#define IsTimList5Module(PERIPH) \ + (((PERIPH) == TIM1) || ((PERIPH) == TIM2) || ((PERIPH) == TIM3) || ((PERIPH) == TIM4) || ((PERIPH) == TIM5) \ + || ((PERIPH) == TIM8)) + +/* LIST6: TIM 1, 2, 3, 4, 5, 8 */ +#define IsTimList6Module(PERIPH) \ + (((PERIPH) == TIM1) || ((PERIPH) == TIM2) || ((PERIPH) == TIM3) || ((PERIPH) == TIM4) || ((PERIPH) == TIM5) \ + || ((PERIPH) == TIM8)) + +/* LIST7: TIM 1, 2, 3, 4, 5, 6, 7, 8 */ +#define IsTimList7Module(PERIPH) \ + (((PERIPH) == TIM1) || ((PERIPH) == TIM2) || ((PERIPH) == TIM3) || ((PERIPH) == TIM4) || ((PERIPH) == TIM5) \ + || ((PERIPH) == TIM6) || ((PERIPH) == TIM7) || ((PERIPH) == TIM8)) + +/* LIST8: TIM 1, 2, 3, 4, 5, 8 */ +#define IsTimList8Module(PERIPH) \ + (((PERIPH) == TIM1) || ((PERIPH) == TIM2) || ((PERIPH) == TIM3) || ((PERIPH) == TIM4) || ((PERIPH) == TIM5) \ + || ((PERIPH) == TIM8)) + +/* LIST9: TIM 1, 2, 3, 4, 5, 6, 7, 8 */ +#define IsTimList9Module(PERIPH) \ + (((PERIPH) == TIM1) || ((PERIPH) == TIM2) || ((PERIPH) == TIM3) || ((PERIPH) == TIM4) || ((PERIPH) == TIM5) \ + || ((PERIPH) == TIM6) || ((PERIPH) == TIM7) || ((PERIPH) == TIM8)) + +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_and_PWM_modes + * @{ + */ + +#define TIM_OCMODE_TIMING ((uint16_t)0x0000) +#define TIM_OCMODE_ACTIVE ((uint16_t)0x0010) +#define TIM_OCMODE_INACTIVE ((uint16_t)0x0020) +#define TIM_OCMODE_TOGGLE ((uint16_t)0x0030) +#define TIM_OCMODE_PWM1 ((uint16_t)0x0060) +#define TIM_OCMODE_PWM2 ((uint16_t)0x0070) +#define IsTimOcMode(MODE) \ + (((MODE) == TIM_OCMODE_TIMING) || ((MODE) == TIM_OCMODE_ACTIVE) || ((MODE) == TIM_OCMODE_INACTIVE) \ + || ((MODE) == TIM_OCMODE_TOGGLE) || ((MODE) == TIM_OCMODE_PWM1) || ((MODE) == TIM_OCMODE_PWM2)) +#define IsTimOc(MODE) \ + (((MODE) == TIM_OCMODE_TIMING) || ((MODE) == TIM_OCMODE_ACTIVE) || ((MODE) == TIM_OCMODE_INACTIVE) \ + || ((MODE) == TIM_OCMODE_TOGGLE) || ((MODE) == TIM_OCMODE_PWM1) || ((MODE) == TIM_OCMODE_PWM2) \ + || ((MODE) == TIM_FORCED_ACTION_ACTIVE) || ((MODE) == TIM_FORCED_ACTION_INACTIVE)) +/** + * @} + */ + +/** @addtogroup TIM_One_Pulse_Mode + * @{ + */ + +#define TIM_OPMODE_SINGLE ((uint16_t)0x0008) +#define TIM_OPMODE_REPET ((uint16_t)0x0000) +#define IsTimOpMOde(MODE) (((MODE) == TIM_OPMODE_SINGLE) || ((MODE) == TIM_OPMODE_REPET)) +/** + * @} + */ + +/** @addtogroup Channel + * @{ + */ + +#define TIM_CH_1 ((uint16_t)0x0000) +#define TIM_CH_2 ((uint16_t)0x0004) +#define TIM_CH_3 ((uint16_t)0x0008) +#define TIM_CH_4 ((uint16_t)0x000C) +#define IsTimCh(CHANNEL) \ + (((CHANNEL) == TIM_CH_1) || ((CHANNEL) == TIM_CH_2) || ((CHANNEL) == TIM_CH_3) || ((CHANNEL) == TIM_CH_4)) +#define IsTimPwmInCh(CHANNEL) (((CHANNEL) == TIM_CH_1) || ((CHANNEL) == TIM_CH_2)) +#define IsTimComplementaryCh(CHANNEL) (((CHANNEL) == TIM_CH_1) || ((CHANNEL) == TIM_CH_2) || ((CHANNEL) == TIM_CH_3)) +/** + * @} + */ + +/** @addtogroup TIM_Clock_Division_CKD + * @{ + */ + +#define TIM_CLK_DIV1 ((uint16_t)0x0000) +#define TIM_CLK_DIV2 ((uint16_t)0x0100) +#define TIM_CLK_DIV4 ((uint16_t)0x0200) +#define IsTimClkDiv(DIV) (((DIV) == TIM_CLK_DIV1) || ((DIV) == TIM_CLK_DIV2) || ((DIV) == TIM_CLK_DIV4)) +/** + * @} + */ + +/** @addtogroup TIM_Counter_Mode + * @{ + */ + +#define TIM_CNT_MODE_UP ((uint16_t)0x0000) +#define TIM_CNT_MODE_DOWN ((uint16_t)0x0010) +#define TIM_CNT_MODE_CENTER_ALIGN1 ((uint16_t)0x0020) +#define TIM_CNT_MODE_CENTER_ALIGN2 ((uint16_t)0x0040) +#define TIM_CNT_MODE_CENTER_ALIGN3 ((uint16_t)0x0060) +#define IsTimCntMode(MODE) \ + (((MODE) == TIM_CNT_MODE_UP) || ((MODE) == TIM_CNT_MODE_DOWN) || ((MODE) == TIM_CNT_MODE_CENTER_ALIGN1) \ + || ((MODE) == TIM_CNT_MODE_CENTER_ALIGN2) || ((MODE) == TIM_CNT_MODE_CENTER_ALIGN3)) +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_Polarity + * @{ + */ + +#define TIM_OC_POLARITY_HIGH ((uint16_t)0x0000) +#define TIM_OC_POLARITY_LOW ((uint16_t)0x0002) +#define IsTimOcPolarity(POLARITY) (((POLARITY) == TIM_OC_POLARITY_HIGH) || ((POLARITY) == TIM_OC_POLARITY_LOW)) +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_N_Polarity + * @{ + */ + +#define TIM_OCN_POLARITY_HIGH ((uint16_t)0x0000) +#define TIM_OCN_POLARITY_LOW ((uint16_t)0x0008) +#define IsTimOcnPolarity(POLARITY) (((POLARITY) == TIM_OCN_POLARITY_HIGH) || ((POLARITY) == TIM_OCN_POLARITY_LOW)) +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_state + * @{ + */ + +#define TIM_OUTPUT_STATE_DISABLE ((uint16_t)0x0000) +#define TIM_OUTPUT_STATE_ENABLE ((uint16_t)0x0001) +#define IsTimOutputState(STATE) (((STATE) == TIM_OUTPUT_STATE_DISABLE) || ((STATE) == TIM_OUTPUT_STATE_ENABLE)) +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_N_state + * @{ + */ + +#define TIM_OUTPUT_NSTATE_DISABLE ((uint16_t)0x0000) +#define TIM_OUTPUT_NSTATE_ENABLE ((uint16_t)0x0004) +#define IsTimOutputNState(STATE) (((STATE) == TIM_OUTPUT_NSTATE_DISABLE) || ((STATE) == TIM_OUTPUT_NSTATE_ENABLE)) +/** + * @} + */ + +/** @addtogroup TIM_Capture_Compare_state + * @{ + */ + +#define TIM_CAP_CMP_ENABLE ((uint16_t)0x0001) +#define TIM_CAP_CMP_DISABLE ((uint16_t)0x0000) +#define IsTimCapCmpState(CCX) (((CCX) == TIM_CAP_CMP_ENABLE) || ((CCX) == TIM_CAP_CMP_DISABLE)) +/** + * @} + */ + +/** @addtogroup TIM_Capture_Compare_N_state + * @{ + */ + +#define TIM_CAP_CMP_N_ENABLE ((uint16_t)0x0004) +#define TIM_CAP_CMP_N_DISABLE ((uint16_t)0x0000) +#define IsTimCapCmpNState(CCXN) (((CCXN) == TIM_CAP_CMP_N_ENABLE) || ((CCXN) == TIM_CAP_CMP_N_DISABLE)) +/** + * @} + */ + +/** @addtogroup Break_Input_enable_disable + * @{ + */ + +#define TIM_BREAK_IN_ENABLE ((uint16_t)0x1000) +#define TIM_BREAK_IN_DISABLE ((uint16_t)0x0000) +#define IsTimBreakInState(STATE) (((STATE) == TIM_BREAK_IN_ENABLE) || ((STATE) == TIM_BREAK_IN_DISABLE)) +/** + * @} + */ + +/** @addtogroup Break_Polarity + * @{ + */ + +#define TIM_BREAK_POLARITY_LOW ((uint16_t)0x0000) +#define TIM_BREAK_POLARITY_HIGH ((uint16_t)0x2000) +#define IsTimBreakPalarity(POLARITY) (((POLARITY) == TIM_BREAK_POLARITY_LOW) || ((POLARITY) == TIM_BREAK_POLARITY_HIGH)) +/** + * @} + */ + +/** @addtogroup TIM_AOE_Bit_Set_Reset + * @{ + */ + +#define TIM_AUTO_OUTPUT_ENABLE ((uint16_t)0x4000) +#define TIM_AUTO_OUTPUT_DISABLE ((uint16_t)0x0000) +#define IsTimAutoOutputState(STATE) (((STATE) == TIM_AUTO_OUTPUT_ENABLE) || ((STATE) == TIM_AUTO_OUTPUT_DISABLE)) +/** + * @} + */ + +/** @addtogroup Lock_level + * @{ + */ + +#define TIM_LOCK_LEVEL_OFF ((uint16_t)0x0000) +#define TIM_LOCK_LEVEL_1 ((uint16_t)0x0100) +#define TIM_LOCK_LEVEL_2 ((uint16_t)0x0200) +#define TIM_LOCK_LEVEL_3 ((uint16_t)0x0300) +#define IsTimLockLevel(LEVEL) \ + (((LEVEL) == TIM_LOCK_LEVEL_OFF) || ((LEVEL) == TIM_LOCK_LEVEL_1) || ((LEVEL) == TIM_LOCK_LEVEL_2) \ + || ((LEVEL) == TIM_LOCK_LEVEL_3)) +/** + * @} + */ + +/** @addtogroup OSSI_Off_State_Selection_for_Idle_mode_state + * @{ + */ + +#define TIM_OSSI_STATE_ENABLE ((uint16_t)0x0400) +#define TIM_OSSI_STATE_DISABLE ((uint16_t)0x0000) +#define IsTimOssiState(STATE) (((STATE) == TIM_OSSI_STATE_ENABLE) || ((STATE) == TIM_OSSI_STATE_DISABLE)) +/** + * @} + */ + +/** @addtogroup OSSR_Off_State_Selection_for_Run_mode_state + * @{ + */ + +#define TIM_OSSR_STATE_ENABLE ((uint16_t)0x0800) +#define TIM_OSSR_STATE_DISABLE ((uint16_t)0x0000) +#define IsTimOssrState(STATE) (((STATE) == TIM_OSSR_STATE_ENABLE) || ((STATE) == TIM_OSSR_STATE_DISABLE)) +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_Idle_State + * @{ + */ + +#define TIM_OC_IDLE_STATE_SET ((uint16_t)0x0100) +#define TIM_OC_IDLE_STATE_RESET ((uint16_t)0x0000) +#define IsTimOcIdleState(STATE) (((STATE) == TIM_OC_IDLE_STATE_SET) || ((STATE) == TIM_OC_IDLE_STATE_RESET)) +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_N_Idle_State + * @{ + */ + +#define TIM_OCN_IDLE_STATE_SET ((uint16_t)0x0200) +#define TIM_OCN_IDLE_STATE_RESET ((uint16_t)0x0000) +#define IsTimOcnIdleState(STATE) (((STATE) == TIM_OCN_IDLE_STATE_SET) || ((STATE) == TIM_OCN_IDLE_STATE_RESET)) +/** + * @} + */ + +/** @addtogroup TIM_Input_Capture_Polarity + * @{ + */ + +#define TIM_IC_POLARITY_RISING ((uint16_t)0x0000) +#define TIM_IC_POLARITY_FALLING ((uint16_t)0x0002) +#define TIM_IC_POLARITY_BOTHEDGE ((uint16_t)0x000A) +#define IsTimIcPalaritySingleEdge(POLARITY) \ + (((POLARITY) == TIM_IC_POLARITY_RISING) || ((POLARITY) == TIM_IC_POLARITY_FALLING)) +#define IsTimIcPolarityAnyEdge(POLARITY) \ + (((POLARITY) == TIM_IC_POLARITY_RISING) || ((POLARITY) == TIM_IC_POLARITY_FALLING) \ + || ((POLARITY) == TIM_IC_POLARITY_BOTHEDGE)) +/** + * @} + */ + +/** @addtogroup TIM_Input_Capture_Selection + * @{ + */ + +#define TIM_IC_SELECTION_DIRECTTI \ + ((uint16_t)0x0001) /*!< TIM Input 1, 2, 3 or 4 is selected to be \ + connected to IC1, IC2, IC3 or IC4, respectively */ +#define TIM_IC_SELECTION_INDIRECTTI \ + ((uint16_t)0x0002) /*!< TIM Input 1, 2, 3 or 4 is selected to be \ + connected to IC2, IC1, IC4 or IC3, respectively. */ +#define TIM_IC_SELECTION_TRC ((uint16_t)0x0003) /*!< TIM Input 1, 2, 3 or 4 is selected to be connected to TRC. */ +#define IsTimIcSelection(SELECTION) \ + (((SELECTION) == TIM_IC_SELECTION_DIRECTTI) || ((SELECTION) == TIM_IC_SELECTION_INDIRECTTI) \ + || ((SELECTION) == TIM_IC_SELECTION_TRC)) +/** + * @} + */ + +/** @addtogroup TIM_Input_Capture_Prescaler + * @{ + */ + +#define TIM_IC_PSC_DIV1 ((uint16_t)0x0000) /*!< Capture performed each time an edge is detected on the capture input. \ + */ +#define TIM_IC_PSC_DIV2 ((uint16_t)0x0004) /*!< Capture performed once every 2 events. */ +#define TIM_IC_PSC_DIV4 ((uint16_t)0x0008) /*!< Capture performed once every 4 events. */ +#define TIM_IC_PSC_DIV8 ((uint16_t)0x000C) /*!< Capture performed once every 8 events. */ +#define IsTimIcPrescaler(PRESCALER) \ + (((PRESCALER) == TIM_IC_PSC_DIV1) || ((PRESCALER) == TIM_IC_PSC_DIV2) || ((PRESCALER) == TIM_IC_PSC_DIV4) \ + || ((PRESCALER) == TIM_IC_PSC_DIV8)) +/** + * @} + */ + +/** @addtogroup TIM_interrupt_sources + * @{ + */ + +#define TIM_INT_UPDATE ((uint16_t)0x0001) +#define TIM_INT_CC1 ((uint16_t)0x0002) +#define TIM_INT_CC2 ((uint16_t)0x0004) +#define TIM_INT_CC3 ((uint16_t)0x0008) +#define TIM_INT_CC4 ((uint16_t)0x0010) +#define TIM_INT_COM ((uint16_t)0x0020) +#define TIM_INT_TRIG ((uint16_t)0x0040) +#define TIM_INT_BREAK ((uint16_t)0x0080) +#define IsTimInt(IT) ((((IT) & (uint16_t)0xFF00) == 0x0000) && ((IT) != 0x0000)) + +#define IsTimGetInt(IT) \ + (((IT) == TIM_INT_UPDATE) || ((IT) == TIM_INT_CC1) || ((IT) == TIM_INT_CC2) || ((IT) == TIM_INT_CC3) \ + || ((IT) == TIM_INT_CC4) || ((IT) == TIM_INT_COM) || ((IT) == TIM_INT_TRIG) || ((IT) == TIM_INT_BREAK)) +/** + * @} + */ + +/** @addtogroup TIM_DMA_Base_address + * @{ + */ + +#define TIM_DMABASE_CTRL1 ((uint16_t)0x0000) +#define TIM_DMABASE_CTRL2 ((uint16_t)0x0001) +#define TIM_DMABASE_SMCTRL ((uint16_t)0x0002) +#define TIM_DMABASE_DMAINTEN ((uint16_t)0x0003) +#define TIM_DMABASE_STS ((uint16_t)0x0004) +#define TIM_DMABASE_EVTGEN ((uint16_t)0x0005) +#define TIM_DMABASE_CAPCMPMOD1 ((uint16_t)0x0006) +#define TIM_DMABASE_CAPCMPMOD2 ((uint16_t)0x0007) +#define TIM_DMABASE_CAPCMPEN ((uint16_t)0x0008) +#define TIM_DMABASE_CNT ((uint16_t)0x0009) +#define TIM_DMABASE_PSC ((uint16_t)0x000A) +#define TIM_DMABASE_AR ((uint16_t)0x000B) +#define TIM_DMABASE_REPCNT ((uint16_t)0x000C) +#define TIM_DMABASE_CAPCMPDAT1 ((uint16_t)0x000D) +#define TIM_DMABASE_CAPCMPDAT2 ((uint16_t)0x000E) +#define TIM_DMABASE_CAPCMPDAT3 ((uint16_t)0x000F) +#define TIM_DMABASE_CAPCMPDAT4 ((uint16_t)0x0010) +#define TIM_DMABASE_BKDT ((uint16_t)0x0011) +#define TIM_DMABASE_DMACTRL ((uint16_t)0x0012) + + + +#define IsTimDmaBase(BASE) \ + (((BASE) == TIM_DMABASE_CTRL1) || ((BASE) == TIM_DMABASE_CTRL2) || ((BASE) == TIM_DMABASE_SMCTRL) \ + || ((BASE) == TIM_DMABASE_DMAINTEN) || ((BASE) == TIM_DMABASE_STS) || ((BASE) == TIM_DMABASE_EVTGEN) \ + || ((BASE) == TIM_DMABASE_CAPCMPMOD1) || ((BASE) == TIM_DMABASE_CAPCMPMOD2) \ + || ((BASE) == TIM_DMABASE_CAPCMPEN) || ((BASE) == TIM_DMABASE_CNT) || ((BASE) == TIM_DMABASE_PSC) \ + || ((BASE) == TIM_DMABASE_AR) || ((BASE) == TIM_DMABASE_REPCNT) || ((BASE) == TIM_DMABASE_CAPCMPDAT1) \ + || ((BASE) == TIM_DMABASE_CAPCMPDAT2) || ((BASE) == TIM_DMABASE_CAPCMPDAT3) || ((BASE) == TIM_DMABASE_CAPCMPDAT4) \ + || ((BASE) == TIM_DMABASE_BKDT)|| ((BASE) == TIM_DMABASE_DMACTRL)) +/** + * @} + */ + +/** @addtogroup TIM_DMA_Burst_Length + * @{ + */ + +#define TIM_DMABURST_LENGTH_1TRANSFER ((uint16_t)0x0000) +#define TIM_DMABURST_LENGTH_2TRANSFERS ((uint16_t)0x0100) +#define TIM_DMABURST_LENGTH_3TRANSFERS ((uint16_t)0x0200) +#define TIM_DMABURST_LENGTH_4TRANSFERS ((uint16_t)0x0300) +#define TIM_DMABURST_LENGTH_5TRANSFERS ((uint16_t)0x0400) +#define TIM_DMABURST_LENGTH_6TRANSFERS ((uint16_t)0x0500) +#define TIM_DMABURST_LENGTH_7TRANSFERS ((uint16_t)0x0600) +#define TIM_DMABURST_LENGTH_8TRANSFERS ((uint16_t)0x0700) +#define TIM_DMABURST_LENGTH_9TRANSFERS ((uint16_t)0x0800) +#define TIM_DMABURST_LENGTH_10TRANSFERS ((uint16_t)0x0900) +#define TIM_DMABURST_LENGTH_11TRANSFERS ((uint16_t)0x0A00) +#define TIM_DMABURST_LENGTH_12TRANSFERS ((uint16_t)0x0B00) +#define TIM_DMABURST_LENGTH_13TRANSFERS ((uint16_t)0x0C00) +#define TIM_DMABURST_LENGTH_14TRANSFERS ((uint16_t)0x0D00) +#define TIM_DMABURST_LENGTH_15TRANSFERS ((uint16_t)0x0E00) +#define TIM_DMABURST_LENGTH_16TRANSFERS ((uint16_t)0x0F00) +#define TIM_DMABURST_LENGTH_17TRANSFERS ((uint16_t)0x1000) +#define TIM_DMABURST_LENGTH_18TRANSFERS ((uint16_t)0x1100) +#define TIM_DMABURST_LENGTH_19TRANSFERS ((uint16_t)0x1200) +#define TIM_DMABURST_LENGTH_20TRANSFERS ((uint16_t)0x1300) +#define TIM_DMABURST_LENGTH_21TRANSFERS ((uint16_t)0x1400) +#define IsTimDmaLength(LENGTH) \ + (((LENGTH) == TIM_DMABURST_LENGTH_1TRANSFER) || ((LENGTH) == TIM_DMABURST_LENGTH_2TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_3TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_4TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_5TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_6TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_7TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_8TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_9TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_10TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_11TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_12TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_13TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_14TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_15TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_16TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_17TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_18TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_19TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_20TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_21TRANSFERS)) +/** + * @} + */ + +/** @addtogroup TIM_DMA_sources + * @{ + */ + +#define TIM_DMA_UPDATE ((uint16_t)0x0100) +#define TIM_DMA_CC1 ((uint16_t)0x0200) +#define TIM_DMA_CC2 ((uint16_t)0x0400) +#define TIM_DMA_CC3 ((uint16_t)0x0800) +#define TIM_DMA_CC4 ((uint16_t)0x1000) +#define TIM_DMA_COM ((uint16_t)0x2000) +#define TIM_DMA_TRIG ((uint16_t)0x4000) +#define IsTimDmaSrc(SOURCE) ((((SOURCE) & (uint16_t)0x80FF) == 0x0000) && ((SOURCE) != 0x0000)) + +/** + * @} + */ + +/** @addtogroup TIM_External_Trigger_Prescaler + * @{ + */ + +#define TIM_EXT_TRG_PSC_OFF ((uint16_t)0x0000) +#define TIM_EXT_TRG_PSC_DIV2 ((uint16_t)0x1000) +#define TIM_EXT_TRG_PSC_DIV4 ((uint16_t)0x2000) +#define TIM_EXT_TRG_PSC_DIV8 ((uint16_t)0x3000) +#define IsTimExtPreDiv(PRESCALER) \ + (((PRESCALER) == TIM_EXT_TRG_PSC_OFF) || ((PRESCALER) == TIM_EXT_TRG_PSC_DIV2) \ + || ((PRESCALER) == TIM_EXT_TRG_PSC_DIV4) || ((PRESCALER) == TIM_EXT_TRG_PSC_DIV8)) +/** + * @} + */ + +/** @addtogroup TIM_Internal_Trigger_Selection + * @{ + */ + +#define TIM_TRIG_SEL_IN_TR0 ((uint16_t)0x0000) +#define TIM_TRIG_SEL_IN_TR1 ((uint16_t)0x0010) +#define TIM_TRIG_SEL_IN_TR2 ((uint16_t)0x0020) +#define TIM_TRIG_SEL_IN_TR3 ((uint16_t)0x0030) +#define TIM_TRIG_SEL_TI1F_ED ((uint16_t)0x0040) +#define TIM_TRIG_SEL_TI1FP1 ((uint16_t)0x0050) +#define TIM_TRIG_SEL_TI2FP2 ((uint16_t)0x0060) +#define TIM_TRIG_SEL_ETRF ((uint16_t)0x0070) +#define IsTimTrigSel(SELECTION) \ + (((SELECTION) == TIM_TRIG_SEL_IN_TR0) || ((SELECTION) == TIM_TRIG_SEL_IN_TR1) \ + || ((SELECTION) == TIM_TRIG_SEL_IN_TR2) || ((SELECTION) == TIM_TRIG_SEL_IN_TR3) \ + || ((SELECTION) == TIM_TRIG_SEL_TI1F_ED) || ((SELECTION) == TIM_TRIG_SEL_TI1FP1) \ + || ((SELECTION) == TIM_TRIG_SEL_TI2FP2) || ((SELECTION) == TIM_TRIG_SEL_ETRF)) +#define IsTimInterTrigSel(SELECTION) \ + (((SELECTION) == TIM_TRIG_SEL_IN_TR0) || ((SELECTION) == TIM_TRIG_SEL_IN_TR1) \ + || ((SELECTION) == TIM_TRIG_SEL_IN_TR2) || ((SELECTION) == TIM_TRIG_SEL_IN_TR3)) +/** + * @} + */ + +/** @addtogroup TIM_TIx_External_Clock_Source + * @{ + */ + +#define TIM_EXT_CLK_SRC_TI1 ((uint16_t)0x0050) +#define TIM_EXT_CLK_SRC_TI2 ((uint16_t)0x0060) +#define TIM_EXT_CLK_SRC_TI1ED ((uint16_t)0x0040) +#define IsTimExtClkSrc(SOURCE) \ + (((SOURCE) == TIM_EXT_CLK_SRC_TI1) || ((SOURCE) == TIM_EXT_CLK_SRC_TI2) || ((SOURCE) == TIM_EXT_CLK_SRC_TI1ED)) +/** + * @} + */ + +/** @addtogroup TIM_External_Trigger_Polarity + * @{ + */ +#define TIM_EXT_TRIG_POLARITY_INVERTED ((uint16_t)0x8000) +#define TIM_EXT_TRIG_POLARITY_NONINVERTED ((uint16_t)0x0000) +#define IsTimExtTrigPolarity(POLARITY) \ + (((POLARITY) == TIM_EXT_TRIG_POLARITY_INVERTED) || ((POLARITY) == TIM_EXT_TRIG_POLARITY_NONINVERTED)) +/** + * @} + */ + +/** @addtogroup TIM_Prescaler_Reload_Mode + * @{ + */ + +#define TIM_PSC_RELOAD_MODE_UPDATE ((uint16_t)0x0000) +#define TIM_PSC_RELOAD_MODE_IMMEDIATE ((uint16_t)0x0001) +#define IsTimPscReloadMode(RELOAD) \ + (((RELOAD) == TIM_PSC_RELOAD_MODE_UPDATE) || ((RELOAD) == TIM_PSC_RELOAD_MODE_IMMEDIATE)) +/** + * @} + */ + +/** @addtogroup TIM_Forced_Action + * @{ + */ + +#define TIM_FORCED_ACTION_ACTIVE ((uint16_t)0x0050) +#define TIM_FORCED_ACTION_INACTIVE ((uint16_t)0x0040) +#define IsTimForceActive(OPERATE) (((OPERATE) == TIM_FORCED_ACTION_ACTIVE) || ((OPERATE) == TIM_FORCED_ACTION_INACTIVE)) +/** + * @} + */ + +/** @addtogroup TIM_Encoder_Mode + * @{ + */ + +#define TIM_ENCODE_MODE_TI1 ((uint16_t)0x0001) +#define TIM_ENCODE_MODE_TI2 ((uint16_t)0x0002) +#define TIM_ENCODE_MODE_TI12 ((uint16_t)0x0003) +#define IsTimEncodeMode(MODE) \ + (((MODE) == TIM_ENCODE_MODE_TI1) || ((MODE) == TIM_ENCODE_MODE_TI2) || ((MODE) == TIM_ENCODE_MODE_TI12)) +/** + * @} + */ + +/** @addtogroup TIM_Event_Source + * @{ + */ + +#define TIM_EVT_SRC_UPDATE ((uint16_t)0x0001) +#define TIM_EVT_SRC_CC1 ((uint16_t)0x0002) +#define TIM_EVT_SRC_CC2 ((uint16_t)0x0004) +#define TIM_EVT_SRC_CC3 ((uint16_t)0x0008) +#define TIM_EVT_SRC_CC4 ((uint16_t)0x0010) +#define TIM_EVT_SRC_COM ((uint16_t)0x0020) +#define TIM_EVT_SRC_TRIG ((uint16_t)0x0040) +#define TIM_EVT_SRC_BREAK ((uint16_t)0x0080) +#define IsTimEvtSrc(SOURCE) ((((SOURCE) & (uint16_t)0xFF00) == 0x0000) && ((SOURCE) != 0x0000)) + +/** + * @} + */ + +/** @addtogroup TIM_Update_Source + * @{ + */ + +#define TIM_UPDATE_SRC_GLOBAL \ + ((uint16_t)0x0000) /*!< Source of update is the counter overflow/underflow \ + or the setting of UG bit, or an update generation \ + through the slave mode controller. */ +#define TIM_UPDATE_SRC_REGULAr ((uint16_t)0x0001) /*!< Source of update is counter overflow/underflow. */ +#define IsTimUpdateSrc(SOURCE) (((SOURCE) == TIM_UPDATE_SRC_GLOBAL) || ((SOURCE) == TIM_UPDATE_SRC_REGULAr)) +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_Preload_State + * @{ + */ + +#define TIM_OC_PRE_LOAD_ENABLE ((uint16_t)0x0008) +#define TIM_OC_PRE_LOAD_DISABLE ((uint16_t)0x0000) +#define IsTimOcPreLoadState(STATE) (((STATE) == TIM_OC_PRE_LOAD_ENABLE) || ((STATE) == TIM_OC_PRE_LOAD_DISABLE)) +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_Fast_State + * @{ + */ + +#define TIM_OC_FAST_ENABLE ((uint16_t)0x0004) +#define TIM_OC_FAST_DISABLE ((uint16_t)0x0000) +#define IsTimOcFastState(STATE) (((STATE) == TIM_OC_FAST_ENABLE) || ((STATE) == TIM_OC_FAST_DISABLE)) + +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_Clear_State + * @{ + */ + +#define TIM_OC_CLR_ENABLE ((uint16_t)0x0080) +#define TIM_OC_CLR_DISABLE ((uint16_t)0x0000) +#define IsTimOcClrState(STATE) (((STATE) == TIM_OC_CLR_ENABLE) || ((STATE) == TIM_OC_CLR_DISABLE)) +/** + * @} + */ + +/** @addtogroup TIM_Trigger_Output_Source + * @{ + */ + +#define TIM_TRGO_SRC_RESET ((uint16_t)0x0000) +#define TIM_TRGO_SRC_ENABLE ((uint16_t)0x0010) +#define TIM_TRGO_SRC_UPDATE ((uint16_t)0x0020) +#define TIM_TRGO_SRC_OC1 ((uint16_t)0x0030) +#define TIM_TRGO_SRC_OC1REF ((uint16_t)0x0040) +#define TIM_TRGO_SRC_OC2REF ((uint16_t)0x0050) +#define TIM_TRGO_SRC_OC3REF ((uint16_t)0x0060) +#define TIM_TRGO_SRC_OC4REF ((uint16_t)0x0070) +#define IsTimTrgoSrc(SOURCE) \ + (((SOURCE) == TIM_TRGO_SRC_RESET) || ((SOURCE) == TIM_TRGO_SRC_ENABLE) || ((SOURCE) == TIM_TRGO_SRC_UPDATE) \ + || ((SOURCE) == TIM_TRGO_SRC_OC1) || ((SOURCE) == TIM_TRGO_SRC_OC1REF) || ((SOURCE) == TIM_TRGO_SRC_OC2REF) \ + || ((SOURCE) == TIM_TRGO_SRC_OC3REF) || ((SOURCE) == TIM_TRGO_SRC_OC4REF)) +/** + * @} + */ + +/** @defgroup ETR selection + * @{ + */ +#define TIM_ETR_Seletct_ExtGpio ((uint16_t)0x0000) +#define TIM_ETR_Seletct_innerTsc ((uint16_t)0x0100) +/** + * @} + */ + +/** @addtogroup TIM_Slave_Mode + * @{ + */ + +#define TIM_SLAVE_MODE_RESET ((uint16_t)0x0004) +#define TIM_SLAVE_MODE_GATED ((uint16_t)0x0005) +#define TIM_SLAVE_MODE_TRIG ((uint16_t)0x0006) +#define TIM_SLAVE_MODE_EXT1 ((uint16_t)0x0007) +#define IsTimSlaveMode(MODE) \ + (((MODE) == TIM_SLAVE_MODE_RESET) || ((MODE) == TIM_SLAVE_MODE_GATED) || ((MODE) == TIM_SLAVE_MODE_TRIG) \ + || ((MODE) == TIM_SLAVE_MODE_EXT1)) +/** + * @} + */ + +/** @addtogroup TIM_Master_Slave_Mode + * @{ + */ + +#define TIM_MASTER_SLAVE_MODE_ENABLE ((uint16_t)0x0080) +#define TIM_MASTER_SLAVE_MODE_DISABLE ((uint16_t)0x0000) +#define IsTimMasterSlaveMode(STATE) \ + (((STATE) == TIM_MASTER_SLAVE_MODE_ENABLE) || ((STATE) == TIM_MASTER_SLAVE_MODE_DISABLE)) +/** + * @} + */ + +/** @addtogroup TIM_Flags + * @{ + */ + +#define TIM_FLAG_UPDATE ((uint32_t)0x0001) +#define TIM_FLAG_CC1 ((uint32_t)0x0002) +#define TIM_FLAG_CC2 ((uint32_t)0x0004) +#define TIM_FLAG_CC3 ((uint32_t)0x0008) +#define TIM_FLAG_CC4 ((uint32_t)0x0010) +#define TIM_FLAG_COM ((uint32_t)0x0020) +#define TIM_FLAG_TRIG ((uint32_t)0x0040) +#define TIM_FLAG_BREAK ((uint32_t)0x0080) +#define TIM_FLAG_CC1OF ((uint32_t)0x0200) +#define TIM_FLAG_CC2OF ((uint32_t)0x0400) +#define TIM_FLAG_CC3OF ((uint32_t)0x0800) +#define TIM_FLAG_CC4OF ((uint32_t)0x1000) +#define TIM_FLAG_CC5 ((uint32_t)0x010000) +#define TIM_FLAG_CC6 ((uint32_t)0x020000) + +#define IsTimGetFlag(FLAG) \ + (((FLAG) == TIM_FLAG_UPDATE) || ((FLAG) == TIM_FLAG_CC1) || ((FLAG) == TIM_FLAG_CC2) || ((FLAG) == TIM_FLAG_CC3) \ + || ((FLAG) == TIM_FLAG_CC4) || ((FLAG) == TIM_FLAG_COM) || ((FLAG) == TIM_FLAG_TRIG) \ + || ((FLAG) == TIM_FLAG_BREAK) || ((FLAG) == TIM_FLAG_CC1OF) || ((FLAG) == TIM_FLAG_CC2OF) \ + || ((FLAG) == TIM_FLAG_CC3OF) || ((FLAG) == TIM_FLAG_CC4OF) || ((FLAG) == TIM_FLAG_CC5) \ + || ((FLAG) == TIM_FLAG_CC6)) + +#define IsTimClrFlag(TIM_FLAG) ((((TIM_FLAG) & (uint16_t)0xE100) == 0x0000) && ((TIM_FLAG) != 0x0000)) +/** + * @} + */ + +/** @addtogroup TIM_Input_Capture_Filer_Value + * @{ + */ + +#define IsTimInCapFilter(ICFILTER) ((ICFILTER) <= 0xF) +/** + * @} + */ + +/** @addtogroup TIM_External_Trigger_Filter + * @{ + */ + +#define IsTimExtTrigFilter(EXTFILTER) ((EXTFILTER) <= 0xF) +/** + * @} + */ + +#define TIM_CC1EN ((uint32_t)1<<0) +#define TIM_CC1NEN ((uint32_t)1<<2) +#define TIM_CC2EN ((uint32_t)1<<4) +#define TIM_CC2NEN ((uint32_t)1<<6) +#define TIM_CC3EN ((uint32_t)1<<8) +#define TIM_CC3NEN ((uint32_t)1<<10) +#define TIM_CC4EN ((uint32_t)1<<12) +#define TIM_CC5EN ((uint32_t)1<<16) +#define TIM_CC6EN ((uint32_t)1<<20) + +#define IsAdvancedTimCCENFlag(FLAG) \ + (((FLAG) == TIM_CC1EN) || ((FLAG) == TIM_CC1NEN) || ((FLAG) == TIM_CC2EN) || ((FLAG) == TIM_CC2NEN) \ + || ((FLAG) == TIM_CC3EN) || ((FLAG) == TIM_CC3NEN) \ + || ((FLAG) == TIM_CC4EN) || ((FLAG) == TIM_CC5EN) || ((FLAG) == TIM_CC6EN) ) +#define IsGeneralTimCCENFlag(FLAG) \ + (((FLAG) == TIM_CC1EN) || ((FLAG) == TIM_CC2EN) \ + || ((FLAG) == TIM_CC3EN) \ + || ((FLAG) == TIM_CC4EN) ) + +/** @addtogroup TIM_Legacy + * @{ + */ + +#define TIM_DMA_BURST_LEN_1BYTE TIM_DMABURST_LENGTH_1TRANSFER +#define TIM_DMA_BURST_LEN_2BYTES TIM_DMABURST_LENGTH_2TRANSFERS +#define TIM_DMA_BURST_LEN_3BYTES TIM_DMABURST_LENGTH_3TRANSFERS +#define TIM_DMA_BURST_LEN_4BYTES TIM_DMABURST_LENGTH_4TRANSFERS +#define TIM_DMA_BURST_LEN_5BYTES TIM_DMABURST_LENGTH_5TRANSFERS +#define TIM_DMA_BURST_LEN_6BYTES TIM_DMABURST_LENGTH_6TRANSFERS +#define TIM_DMA_BURST_LEN_7BYTES TIM_DMABURST_LENGTH_7TRANSFERS +#define TIM_DMA_BURST_LEN_8BYTES TIM_DMABURST_LENGTH_8TRANSFERS +#define TIM_DMA_BURST_LEN_9BYTES TIM_DMABURST_LENGTH_9TRANSFERS +#define TIM_DMA_BURST_LEN_10BYTES TIM_DMABURST_LENGTH_10TRANSFERS +#define TIM_DMA_BURST_LEN_11BYTES TIM_DMABURST_LENGTH_11TRANSFERS +#define TIM_DMA_BURST_LEN_12BYTES TIM_DMABURST_LENGTH_12TRANSFERS +#define TIM_DMA_BURST_LEN_13BYTES TIM_DMABURST_LENGTH_13TRANSFERS +#define TIM_DMA_BURST_LEN_14BYTES TIM_DMABURST_LENGTH_14TRANSFERS +#define TIM_DMA_BURST_LEN_15BYTES TIM_DMABURST_LENGTH_15TRANSFERS +#define TIM_DMA_BURST_LEN_16BYTES TIM_DMABURST_LENGTH_16TRANSFERS +#define TIM_DMA_BURST_LEN_17BYTES TIM_DMABURST_LENGTH_17TRANSFERS +#define TIM_DMA_BURST_LEN_18BYTES TIM_DMABURST_LENGTH_18TRANSFERS +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup TIM_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup TIM_Exported_Functions + * @{ + */ + +void TIM_DeInit(TIM_Module* TIMx); +void TIM_InitTimeBase(TIM_Module* TIMx, TIM_TimeBaseInitType* TIM_TimeBaseInitStruct); +void TIM_InitOc1(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct); +void TIM_InitOc2(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct); +void TIM_InitOc3(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct); +void TIM_InitOc4(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct); +void TIM_InitOc5(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct); +void TIM_InitOc6(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct); +void TIM_ICInit(TIM_Module* TIMx, TIM_ICInitType* TIM_ICInitStruct); +void TIM_ConfigPwmIc(TIM_Module* TIMx, TIM_ICInitType* TIM_ICInitStruct); +void TIM_ConfigBkdt(TIM_Module* TIMx, TIM_BDTRInitType* TIM_BDTRInitStruct); +void TIM_InitTimBaseStruct(TIM_TimeBaseInitType* TIM_TimeBaseInitStruct); +void TIM_InitOcStruct(OCInitType* TIM_OCInitStruct); +void TIM_InitIcStruct(TIM_ICInitType* TIM_ICInitStruct); +void TIM_InitBkdtStruct(TIM_BDTRInitType* TIM_BDTRInitStruct); +void TIM_Enable(TIM_Module* TIMx, FunctionalState Cmd); +void TIM_EnableCtrlPwmOutputs(TIM_Module* TIMx, FunctionalState Cmd); +void TIM_ConfigInt(TIM_Module* TIMx, uint16_t TIM_IT, FunctionalState Cmd); +void TIM_GenerateEvent(TIM_Module* TIMx, uint16_t TIM_EventSource); +void TIM_ConfigDma(TIM_Module* TIMx, uint16_t TIM_DMABase, uint16_t TIM_DMABurstLength); +void TIM_EnableDma(TIM_Module* TIMx, uint16_t TIM_DMASource, FunctionalState Cmd); +void TIM_ConfigInternalClk(TIM_Module* TIMx); +void TIM_ConfigInternalTrigToExt(TIM_Module* TIMx, uint16_t TIM_InputTriggerSource); +void TIM_ConfigExtTrigAsClk(TIM_Module* TIMx, + uint16_t TIM_TIxExternalCLKSource, + uint16_t IcPolarity, + uint16_t ICFilter); +void TIM_ConfigExtClkMode1(TIM_Module* TIMx, + uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter); +void TIM_ConfigExtClkMode2(TIM_Module* TIMx, + uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter); +void TIM_ConfigExtTrig(TIM_Module* TIMx, + uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter); +void TIM_ConfigPrescaler(TIM_Module* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode); +void TIM_ConfigCntMode(TIM_Module* TIMx, uint16_t CntMode); +void TIM_SelectInputTrig(TIM_Module* TIMx, uint16_t TIM_InputTriggerSource); +void TIM_ConfigEncoderInterface(TIM_Module* TIMx, + uint16_t TIM_EncoderMode, + uint16_t TIM_IC1Polarity, + uint16_t TIM_IC2Polarity); +void TIM_ConfigForcedOc1(TIM_Module* TIMx, uint16_t TIM_ForcedAction); +void TIM_ConfigForcedOc2(TIM_Module* TIMx, uint16_t TIM_ForcedAction); +void TIM_ConfigForcedOc3(TIM_Module* TIMx, uint16_t TIM_ForcedAction); +void TIM_ConfigForcedOc4(TIM_Module* TIMx, uint16_t TIM_ForcedAction); +void TIM_ConfigForcedOc5(TIM_Module* TIMx, uint16_t TIM_ForcedAction); +void TIM_ConfigForcedOc6(TIM_Module* TIMx, uint16_t TIM_ForcedAction); +void TIM_ConfigArPreload(TIM_Module* TIMx, FunctionalState Cmd); +void TIM_SelectComEvt(TIM_Module* TIMx, FunctionalState Cmd); +void TIM_SelectCapCmpDmaSrc(TIM_Module* TIMx, FunctionalState Cmd); +void TIM_EnableCapCmpPreloadControl(TIM_Module* TIMx, FunctionalState Cmd); +void TIM_ConfigOc1Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload); +void TIM_ConfigOc2Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload); +void TIM_ConfigOc3Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload); +void TIM_ConfigOc4Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload); +void TIM_ConfigOc5Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload); +void TIM_ConfigOc6Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload); +void TIM_ConfigOc1Fast(TIM_Module* TIMx, uint16_t TIM_OCFast); +void TIM_ConfigOc2Fast(TIM_Module* TIMx, uint16_t TIM_OCFast); +void TIM_ConfigOc3Fast(TIM_Module* TIMx, uint16_t TIM_OCFast); +void TIM_ConfigOc4Fast(TIM_Module* TIMx, uint16_t TIM_OCFast); +void TIM_ConfigOc5Fast(TIM_Module* TIMx, uint16_t TIM_OCFast); +void TIM_ConfigOc6Fast(TIM_Module* TIMx, uint16_t TIM_OCFast); +void TIM_ClrOc1Ref(TIM_Module* TIMx, uint16_t TIM_OCClear); +void TIM_ClrOc2Ref(TIM_Module* TIMx, uint16_t TIM_OCClear); +void TIM_ClrOc3Ref(TIM_Module* TIMx, uint16_t TIM_OCClear); +void TIM_ClrOc4Ref(TIM_Module* TIMx, uint16_t TIM_OCClear); +void TIM_ClrOc5Ref(TIM_Module* TIMx, uint16_t TIM_OCClear); +void TIM_ClrOc6Ref(TIM_Module* TIMx, uint16_t TIM_OCClear); +void TIM_ConfigOc1Polarity(TIM_Module* TIMx, uint16_t OcPolarity); +void TIM_ConfigOc1NPolarity(TIM_Module* TIMx, uint16_t OcNPolarity); +void TIM_ConfigOc2Polarity(TIM_Module* TIMx, uint16_t OcPolarity); +void TIM_ConfigOc2NPolarity(TIM_Module* TIMx, uint16_t OcNPolarity); +void TIM_ConfigOc3Polarity(TIM_Module* TIMx, uint16_t OcPolarity); +void TIM_ConfigOc3NPolarity(TIM_Module* TIMx, uint16_t OcNPolarity); +void TIM_ConfigOc4Polarity(TIM_Module* TIMx, uint16_t OcPolarity); +void TIM_ConfigOc5Polarity(TIM_Module* TIMx, uint16_t OcPolarity); +void TIM_ConfigOc6Polarity(TIM_Module* TIMx, uint16_t OcPolarity); +void TIM_EnableCapCmpCh(TIM_Module* TIMx, uint16_t Channel, uint32_t TIM_CCx); +void TIM_EnableCapCmpChN(TIM_Module* TIMx, uint16_t Channel, uint32_t TIM_CCxN); +void TIM_SelectOcMode(TIM_Module* TIMx, uint16_t Channel, uint16_t OcMode); +void TIM_EnableUpdateEvt(TIM_Module* TIMx, FunctionalState Cmd); +void TIM_ConfigUpdateRequestIntSrc(TIM_Module* TIMx, uint16_t TIM_UpdateSource); +void TIM_SelectHallSensor(TIM_Module* TIMx, FunctionalState Cmd); +void TIM_SelectOnePulseMode(TIM_Module* TIMx, uint16_t TIM_OPMode); +void TIM_SelectOutputTrig(TIM_Module* TIMx, uint16_t TIM_TRGOSource); +void TIM_SelectExtSignalSource(TIM_Module* TIMx, uint16_t ExtSigalSource); +void TIM_SelectSlaveMode(TIM_Module* TIMx, uint16_t TIM_SlaveMode); +void TIM_SelectMasterSlaveMode(TIM_Module* TIMx, uint16_t TIM_MasterSlaveMode); +void TIM_SetCnt(TIM_Module* TIMx, uint16_t Counter); +void TIM_SetAutoReload(TIM_Module* TIMx, uint16_t Autoreload); +void TIM_SetCmp1(TIM_Module* TIMx, uint16_t Compare1); +void TIM_SetCmp2(TIM_Module* TIMx, uint16_t Compare2); +void TIM_SetCmp3(TIM_Module* TIMx, uint16_t Compare3); +void TIM_SetCmp4(TIM_Module* TIMx, uint16_t Compare4); +void TIM_SetCmp5(TIM_Module* TIMx, uint16_t Compare5); +void TIM_SetCmp6(TIM_Module* TIMx, uint16_t Compare6); +void TIM_SetInCap1Prescaler(TIM_Module* TIMx, uint16_t TIM_ICPSC); +void TIM_SetInCap2Prescaler(TIM_Module* TIMx, uint16_t TIM_ICPSC); +void TIM_SetInCap3Prescaler(TIM_Module* TIMx, uint16_t TIM_ICPSC); +void TIM_SetInCap4Prescaler(TIM_Module* TIMx, uint16_t TIM_ICPSC); +void TIM_SetClkDiv(TIM_Module* TIMx, uint16_t TIM_CKD); +uint16_t TIM_GetCap1(TIM_Module* TIMx); +uint16_t TIM_GetCap2(TIM_Module* TIMx); +uint16_t TIM_GetCap3(TIM_Module* TIMx); +uint16_t TIM_GetCap4(TIM_Module* TIMx); +uint16_t TIM_GetCap5(TIM_Module* TIMx); +uint16_t TIM_GetCap6(TIM_Module* TIMx); +uint16_t TIM_GetCnt(TIM_Module* TIMx); +uint16_t TIM_GetPrescaler(TIM_Module* TIMx); +uint16_t TIM_GetAutoReload(TIM_Module* TIMx); +FlagStatus TIM_GetCCENStatus(TIM_Module* TIMx, uint32_t TIM_CCEN); +FlagStatus TIM_GetFlagStatus(TIM_Module* TIMx, uint32_t TIM_FLAG); +void TIM_ClearFlag(TIM_Module* TIMx, uint32_t TIM_FLAG); +INTStatus TIM_GetIntStatus(TIM_Module* TIMx, uint32_t TIM_IT); +void TIM_ClrIntPendingBit(TIM_Module* TIMx, uint32_t TIM_IT); + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G4FR_TIM_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_tsc.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_tsc.h new file mode 100644 index 0000000000..7cd8c37ebd --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_tsc.h @@ -0,0 +1,576 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_tsc.h + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_TSC_H__ +#define __N32G4FR_TSC_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup TSC + * @{ + */ + +/** + * @brief TSC error code + */ + typedef enum { + TSC_ERROR_OK = 0x00U, /*!< No error */ + TSC_ERROR_CLOCK = 0x01U, /*!< clock config error */ + TSC_ERROR_PARAMETER = 0x02U, /*!< parameter error */ + TSC_ERROR_HW_MODE = 0x02U, /*!< Exit hw mode timeout */ + + }TSC_ErrorTypeDef; + /** + * @ + */ + +/** + * @brief TSC clock source + */ +#define TSC_CLK_SRC_LSI (0x00000000) /*!< LSI*/ +#define TSC_CLK_SRC_LSE (RCC_LSE_ENABLE) /*!< LSE */ +#define TSC_CLK_SRC_LSE_BYPASS (RCC_LSE_BYPASS) /*!< LSE bypass */ +/** + * @ + */ + + +/** + * @defgroup Detect_Period + */ +#define TSC_DET_PERIOD_8 (0x00000000U) /*!< DET_PERIOD[3:0] = 8/TSC_CLOCK */ +#define TSC_DET_PERIOD_16 (0x01UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000001U DET_PERIOD[3:0] = 16/TSC_CLOCK */ +#define TSC_DET_PERIOD_24 (0x02UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000002U DET_PERIOD[3:0] = 24/TSC_CLOCK */ +#define TSC_DET_PERIOD_32 (0x03UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000003U DET_PERIOD[3:0] = 32/TSC_CLOCK(default) */ +#define TSC_DET_PERIOD_40 (0x04UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000004U DET_PERIOD[3:0] = 40/TSC_CLOCK */ +#define TSC_DET_PERIOD_48 (0x05UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000005U DET_PERIOD[3:0] = 48/TSC_CLOCK */ +#define TSC_DET_PERIOD_56 (0x06UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000006U DET_PERIOD[3:0] = 56/TSC_CLOCK */ +#define TSC_DET_PERIOD_64 (0x07UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000007U DET_PERIOD[3:0] = 64/TSC_CLOCK */ +#define TSC_DET_PERIOD_72 (0x08UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000008U DET_PERIOD[3:0] = 72/TSC_CLOCK */ +#define TSC_DET_PERIOD_80 (0x09UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000009U DET_PERIOD[3:0] = 80/TSC_CLOCK */ +#define TSC_DET_PERIOD_88 (0x0AUL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x0000000AU DET_PERIOD[3:0] = 88/TSC_CLOCK */ +#define TSC_DET_PERIOD_96 (0x0BUL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x0000000BU DET_PERIOD[3:0] = 96/TSC_CLOCK */ +#define TSC_DET_PERIOD_104 (0x0CUL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x0000000CU DET_PERIOD[3:0] = 104/TSC_CLOCK */ + +#define TSC_DET_PERIOD_8_32KHZ ((uint8_t)TSC_DET_PERIOD_8) +#define TSC_DET_PERIOD_16_32KHZ ((uint8_t)TSC_DET_PERIOD_16) +#define TSC_DET_PERIOD_24_32KHZ ((uint8_t)TSC_DET_PERIOD_24) +#define TSC_DET_PERIOD_32_32KHZ ((uint8_t)TSC_DET_PERIOD_32) +#define TSC_DET_PERIOD_40_32KHZ ((uint8_t)TSC_DET_PERIOD_40) +#define TSC_DET_PERIOD_48_32KHZ ((uint8_t)TSC_DET_PERIOD_48) +#define TSC_DET_PERIOD_56_32KHZ ((uint8_t)TSC_DET_PERIOD_56) +#define TSC_DET_PERIOD_64_32KHZ ((uint8_t)TSC_DET_PERIOD_64) +#define TSC_DET_PERIOD_72_32KHZ ((uint8_t)TSC_DET_PERIOD_72) +#define TSC_DET_PERIOD_80_32KHZ ((uint8_t)TSC_DET_PERIOD_80) +#define TSC_DET_PERIOD_88_32KHZ ((uint8_t)TSC_DET_PERIOD_88) +#define TSC_DET_PERIOD_96_32KHZ ((uint8_t)TSC_DET_PERIOD_96) +#define TSC_DET_PERIOD_104_32KHZ ((uint8_t)TSC_DET_PERIOD_104) +/** + * @ + */ + +/** + * @defgroup Detect_Filter + */ +#define TSC_DET_FILTER_1 (0x00000000U) /*!< DET_FILTER[3:0] = 1 sample */ +#define TSC_DET_FILTER_2 (0x01UL << TSC_CTRL_DET_FILTER_SHIFT) /*!< 0x00000010U DET_FILTER[3:0] = 2 samples */ +#define TSC_DET_FILTER_3 (0x02UL << TSC_CTRL_DET_FILTER_SHIFT) /*!< 0x00000020U DET_FILTER[3:0] = 3 samples */ +#define TSC_DET_FILTER_4 (0x03UL << TSC_CTRL_DET_FILTER_SHIFT) /*!< 0x00000030U DET_FILTER[3:0] = 4 samples */ + +#define TSC_HW_DET_FILTER_1 ((uint8_t)TSC_DET_FILTER_1) +#define TSC_HW_DET_FILTER_2 ((uint8_t)TSC_DET_FILTER_2) +#define TSC_HW_DET_FILTER_3 ((uint8_t)TSC_DET_FILTER_3) +#define TSC_HW_DET_FILTER_4 ((uint8_t)TSC_DET_FILTER_4) + +/** + * @ + */ + +/** + * @defgroup HW_Detect_Mode + */ +#define TSC_HW_DET_MODE_DISABLE (0x00000000U) /*!< Hardware detect mode disable */ +#define TSC_HW_DET_MODE_ENABLE (0x01UL << TSC_CTRL_HW_DET_MODE_SHIFT) /*!< 0x00000040U Hardware detect mode enable */ + +#define TSC_HW_DET_ENABLE TSC_HW_DET_MODE_ENABLE +/** + * @ + */ + +/** + * @defgroup Detect_Type + */ +#define TSC_DET_TYPE_MASK (TSC_CTRL_LESS_DET_SEL_MASK|TSC_CTRL_GREAT_DET_SEL_MASK) +#define TSC_DET_TYPE_SHIFT (TSC_CTRL_LESS_DET_SEL_SHIFT) + +#define TSC_DET_TYPE_NONE (0UL) /*!< 0x00000000U Disable detect */ +#define TSC_DET_TYPE_LESS (0x01UL << TSC_DET_TYPE_SHIFT) /*!< 0x00000100U Less detect enable */ +#define TSC_DET_TYPE_GREAT (0x02UL << TSC_DET_TYPE_SHIFT) /*!< 0x00000200U Great detect enable */ +#define TSC_DET_TYPE_PERIOD (0x03UL << TSC_DET_TYPE_SHIFT) /*!< 0x00000300U Both great and less detct enable */ +/** + * @ + */ + +/** + * @defgroup TSC_Interrupt + */ +#define TSC_IT_DET_ENABLE (TSC_CTRL_DET_INTEN) /*!< Enable TSC detect interrupt */ +#define TSC_IT_DET_DISABLE (0UL) /*!< Disable TSC detect interrupt */ +/** + * @ + */ + +/** + * @defgroup TSC_Out + */ +#define TSC_OUT_PIN (0x00000000U) /*!< TSC output to TSC_OUT pin */ +#define TSC_OUT_TIM4_ETR (0x1UL << TSC_CTRL_TM4_ETR_SHIFT) /*!< TSC output to TIM4 ETR */ +#define TSC_OUT_TIM2_ETR (0x2UL << TSC_CTRL_TM4_ETR_SHIFT) /*!< TSC output to TIM2 ETR and TIM2 CH1*/ +/** + * @ + */ + +/** + * @defgroup TSC_Flag + */ +#define TSC_FLAG_HW (0x1UL << TSC_CTRL_HW_DET_ST_SHIFT) /*!< Flag of hardware detect mode */ + +#define TSC_FLAG_GREAT_DET (0x1UL << TSC_STS_GREAT_DET_SHIFT) /*!< Flag of great detect type */ +#define TSC_FLAG_LESS_DET (0x1UL << TSC_STS_LESS_DET_SHIFT) /*!< Flag of less detect type */ +#define TSC_FLAG_PERIOD_DET (TSC_FLAG_GREAT_DET|TSC_FLAG_LESS_DET) /*!< Flag of period detect type */ +/** + * @ + */ + +/** + * @defgroup TSC_SW_Detect + */ +#define TSC_SW_MODE_DISABLE (0x00000000U) /*!< Disable software detect mode */ +#define TSC_SW_MODE_ENABLE (0x1UL << TSC_ANA_CTRL_SW_TSC_EN_SHIFT) /*!< Enable software detect mode */ +/** + * @ + */ + +/** + * @defgroup TSC_PadOption + */ +#define TSC_PAD_INTERNAL_RES (0x00000000U) /*!< Use internal resistor */ +#define TSC_PAD_EXTERNAL_RES (0x1UL << TSC_ANA_SEL_PAD_OPT_SHIFT) /*!< Use external resistor */ + +#define TSC_INNER_RESIST TSC_PAD_INTERNAL_RES + +/** + * @ + */ + +/** + * @defgroup TSC_PadSpeed + */ +#define TSC_PAD_SPEED_0 (0x00000000U) /*!< Low speed,about 100K */ +#define TSC_PAD_SPEED_1 (0x1UL << TSC_ANA_SEL_SP_OPT_SHIFT) /*!< Middle spped */ +#define TSC_PAD_SPEED_2 (0x2UL << TSC_ANA_SEL_SP_OPT_SHIFT) /*!< Middle spped */ +#define TSC_PAD_SPEED_3 (0x3UL << TSC_ANA_SEL_SP_OPT_SHIFT) /*!< Middle spped */ + +#define TSC_CMP_MASK (0x03UL) // comparator offset bit mask +#define TSC_CMP_OFFSET TSC_ANA_SEL_SP_OPT_SHIFT // offset of comparator speed configuration +#define TSC_CMP_SPEED_0 TSC_PAD_SPEED_0 // 100KHZ~200KHZ +#define TSC_CMP_SPEED_1 TSC_PAD_SPEED_1 // 300KHZ~700KHZ +#define TSC_CMP_SPEED_2 TSC_PAD_SPEED_2 // 300KHZ~700KHZ +#define TSC_CMP_SPEED_3 TSC_PAD_SPEED_3 // 300KHZ~700KHZ + +/** + * @ + */ + +/** + * @defgroup TSC_Touch_Lib + */ +#define TSC_RESIST_1M TSC_RESR_CHN_RESIST_1M +#define TSC_RESIST_875K TSC_RESR_CHN_RESIST_875K +#define TSC_RESIST_750K TSC_RESR_CHN_RESIST_750K +#define TSC_RESIST_625K TSC_RESR_CHN_RESIST_625K +#define TSC_RESIST_500K TSC_RESR_CHN_RESIST_500K +#define TSC_RESIST_375K TSC_RESR_CHN_RESIST_375K +#define TSC_RESIST_250K TSC_RESR_CHN_RESIST_250K +#define TSC_RESIST_125K TSC_RESR_CHN_RESIST_125K + +#define TSC_HW_CHN_MASK (0x00FFFFFF) +#define TSC_CHN_ADDR_WIDTH (4) + +#define TSC_HW_BASE_BITS_OFFSET (0) +#define TSC_HW_DELTA_BITS_OFFSET (16) + +/** + * @ + */ + +/** + * @defgroup TSC_Constant + */ +#define TSC_CHN_SEL_ALL (TSC_CHNEN_CHN_SEL_MASK) +#define MAX_TSC_HW_CHN (24) /*Maximum number of tsc pin*/ +#define TSC_DET_MAX_CHN_COUNT MAX_TSC_HW_CHN +#define MAX_TSC_THRESHOLD_BASE (2047) /*Maximum detect base value of threshold*/ +#define MAX_TSC_THRESHOLD_DELTA (255) /*Maximum detect delta value of threshold*/ +#define TSC_TIMEOUT (0x01000000) /*TSC normal timeout */ +/** + * @ + */ + +/* TSC Exported macros -----------------------------------------------------------*/ +/** @defgroup TSC_Exported_Macros + * @{ + */ + +/** @brief Enable the TSC HW detect mode + * @param None + * @retval None + */ +#define __TSC_HW_ENABLE() SET_BIT(TSC->CTRL, TSC_HW_DET_MODE_ENABLE) + +/** @brief Disable the TSC HW detect mode + * @param None + * @retval None + */ +#define __TSC_HW_DISABLE() CLEAR_BIT(TSC->CTRL, TSC_HW_DET_MODE_ENABLE) + +/** @brief Config TSC detect period for HW detect mode + * @param __PERIOD__ specifies the TSC detect period during HW detect mode + * @arg TSC_DET_PERIOD_8: Detect period = 8/TSC_CLK + * @arg TSC_DET_PERIOD_16: Detect Period = 1/TSC_CLK + * @arg TSC_DET_PERIOD_24: Detect Period = 2/TSC_CLK + * @arg TSC_DET_PERIOD_32: Detect Period = 3/TSC_CLK + * @arg TSC_DET_PERIOD_40: Detect Period = 4/TSC_CLK + * @arg TSC_DET_PERIOD_48: Detect Period = 5/TSC_CLK + * @arg TSC_DET_PERIOD_56: Detect Period = 6/TSC_CLK + * @arg TSC_DET_PERIOD_64: Detect Period = 7/TSC_CLK + * @arg TSC_DET_PERIOD_72: Detect Period = 7/TSC_CLK + * @arg TSC_DET_PERIOD_80: Detect Period = 7/TSC_CLK + * @arg TSC_DET_PERIOD_88: Detect Period = 7/TSC_CLK + * @arg TSC_DET_PERIOD_96: Detect Period = 7/TSC_CLK + * @arg TSC_DET_PERIOD_104:Detect Period = 7/TSC_CLK + * @retval None + */ +#define __TSC_PERIOD_CONFIG(__PERIOD__) MODIFY_REG(TSC->CTRL, TSC_CTRL_DET_PERIOD_MASK,__PERIOD__) + +/** @brief Config TSC detect filter for HW detect mode + * @param __FILTER__ specifies the least usefull continuous samples during HW detect mode + * @arg TSC_DET_FILTER_1: Detect filter = 1 pulse + * @arg TSC_DET_FILTER_2: Detect filter = 2 pulse + * @arg TSC_DET_FILTER_3: Detect filter = 3 pulse + * @arg TSC_DET_FILTER_4: Detect filter = 4 pulse + * @retval None + */ +#define __TSC_FILTER_CONFIG(__FILTER__) MODIFY_REG(TSC->CTRL, TSC_CTRL_DET_FILTER_MASK,__FILTER__) + +/** @brief Config TSC detect type for HW detect mode,less great or both + * @param __TYPE__ specifies the detect type of a sample during HW detect mode + * @arg TSC_DET_TYPE_NONE: Detect disable + * @arg TSC_DET_TYPE_LESS: Pulse number must be greater than the threshold(basee-delta) during a sample time + * @arg TSC_DET_TYPE_GREAT: Pulse number must be less than the threshold(basee+delta) during a sample time + * @arg TSC_DET_TYPE_PERIOD:Pulse number must be greater than (basee-delta) + and also be less than (basee+delta) during a sample time + * @retval None + */ +#define __TSC_LESS_GREAT_CONFIG(__TYPE__) MODIFY_REG(TSC->CTRL, \ + (TSC_CTRL_LESS_DET_SEL_MASK|TSC_CTRL_GREAT_DET_SEL_MASK), \ + __TYPE__) + +/** @brief Enable TSC interrupt + * @param None + * @retval None + */ +#define __TSC_INT_ENABLE() SET_BIT(TSC->CTRL, TSC_IT_DET_ENABLE) + +/** @brief Disable TSC interrupt + * @param None + * @retval None + */ +#define __TSC_INT_DISABLE() CLEAR_BIT(TSC->CTRL, TSC_IT_DET_ENABLE) + +/** @brief Config the TSC output + * @param __OUT__ specifies where the TSC output should go + * @arg TSC_OUT_PIN: TSC output to the TSC_OUT pin + * @arg TSC_OUT_TIM4_ETR: TSC output to TIM4 as ETR + * @arg TSC_OUT_TIM2_ETR: TSC output to TIM2 as ETR + * @retval None + */ +#define __TSC_OUT_CONFIG(__OUT__) MODIFY_REG( TSC->CTRL, \ + (TSC_CTRL_TM4_ETR_MASK|TSC_CTRL_TM2_ETR_CH1_MASK),\ + __OUT__) + +/** @brief Config the TSC channel + * @param __CHN__ specifies the pin of channels used for detect + * This parameter:bit[0:23] used,bit[24:31] must be 0 + * bitx: TSC channel x + * @retval None + */ +#define __TSC_CHN_CONFIG(__CHN__) WRITE_REG(TSC->CHNEN, __CHN__) + +/** @brief Enable the TSC SW detect mode + * @param None + * @retval None + */ +#define __TSC_SW_ENABLE() SET_BIT(TSC->ANA_CTRL, TSC_ANA_CTRL_SW_TSC_EN) + +/** @brief Disable the TSC SW detect mode + * @param None + * @retval None + */ +#define __TSC_SW_DISABLE() CLEAR_BIT(TSC->ANA_CTRL, TSC_ANA_CTRL_SW_TSC_EN) + +/** @brief Config the detect channel number during SW detect mode + * @param __NUM__ specifies channel number,must be less than MAX_TSC_HW_CHN + * @retval None + */ +#define __TSC_SW_CHN_NUM_CONFIG(__NUM__) MODIFY_REG(TSC->ANA_CTRL, TSC_ANA_CTRL_SW_PAD_MUX_MASK,__NUM__) + +/** @brief Config the pad charge type + * @param __OPT__ specifies which resistor is used for charge + * @arg TSC_PAD_INTERNAL_RES: Internal resistor is used + * @arg TSC_PAD_EXTERNAL_RES: External resistor is used + * @retval None + */ +#define __TSC_PAD_OPT_CONFIG(__OPT__) MODIFY_REG(TSC->ANA_SEL, TSC_ANA_SEL_PAD_OPT_MASK,__OPT__) + +/** @brief Config TSC speed + * @param __SPEED__ specifies the TSC speed range + * @arg TSC_PAD_SPEED_0: Low speed + * @arg TSC_PAD_SPEED_1: Middle speed + * @arg TSC_PAD_SPEED_2: Middle speed + * @arg TSC_PAD_SPEED_3: High speed + * @retval None + */ +#define __TSC_PAD_SPEED_CONFIG(__SPEED__) MODIFY_REG(TSC->ANA_SEL, TSC_ANA_SEL_SP_OPT_MASK,__SPEED__) + + +/** @brief Check if the HW detect mode is enable + * @param None + * @retval Current state of HW detect mode + */ +#define __TSC_GET_HW_MODE() (((TSC->CTRL) & TSC_FLAG_HW) == (TSC_FLAG_HW)) + +/** @brief Check the detect type during HW detect mode + * @param __FLAG__ specifies the flag of detect type + * @arg TSC_FLAG_LESS_DET: Flag of less detect type + * @arg TSC_FLAG_GREAT_DET: Flag of great detect type + * @arg TSC_FLAG_PERIOD_DET: Flag of priod detect type + * @retval Current state of flag + */ +#define __TSC_GET_HW_DET_TYPE(__FLAG__) (((TSC->STS) & (__FLAG__))==(__FLAG__)) + +/** @brief Get the number of channel which is detected now + * @param None + * @retval Current channel number + */ +#define __TSC_GET_CHN_NUMBER() (((TSC->STS) & TSC_STS_CHN_NUM_MASK) >> TSC_STS_CHN_NUM_SHIFT ) + +/** @brief Get the count value of pulse + * @param None + * @retval Pulse count of current channel + */ +#define __TSC_GET_CHN_CNT() (((TSC->STS) & TSC_STS_CNT_VAL_MASK ) >> TSC_STS_CNT_VAL_SHIFT ) + +/** @brief Get the base value of one channel + * @param __NUM__ specifies channel number,must be less than MAX_TSC_HW_CHN + * @retval base value of the channel + */ +#define __TSC_GET_CHN_BASE(__NUM__) ((*((&(TSC->THRHD0))+(__NUM__)) & TSC_THRHD_BASE_MASK ) >> TSC_THRHD_BASE_SHIFT) + +/** @brief Get the delta value of one channel + * @param __NUM__ specifies channel number,must be less than MAX_TSC_HW_CHN + * @retval delta value of the channel + */ +#define __TSC_GET_CHN_DELTA(__NUM__) ((*((&(TSC->THRHD0))+(__NUM__)) & TSC_THRHD_DELTA_MASK ) >> TSC_THRHD_DELTA_SHIFT ) + +/** @brief Get the internal resist value of one channel + * @param __NUM__ specifies channel number,must be less than MAX_TSC_HW_CHN + * @retval resist value of the channel + */ +#define __TSC_GET_CHN_RESIST(__NUM__) (((*((&(TSC->RESR0))+((__NUM__)>>3))) >>(((__NUM__) & 0x7UL)*4)) & TSC_RESR_CHN_RESIST_MASK) + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup TSC_Private_Macros + * @{ + */ +#define IS_TSC_DET_PERIOD(_PERIOD_) \ + (((_PERIOD_)==TSC_DET_PERIOD_8) ||((_PERIOD_)==TSC_DET_PERIOD_16)||((_PERIOD_)==TSC_DET_PERIOD_24) \ + ||((_PERIOD_)==TSC_DET_PERIOD_32)||((_PERIOD_)==TSC_DET_PERIOD_40)||((_PERIOD_)==TSC_DET_PERIOD_48) \ + ||((_PERIOD_)==TSC_DET_PERIOD_56)||((_PERIOD_)==TSC_DET_PERIOD_64)||((_PERIOD_)==TSC_DET_PERIOD_72) \ + ||((_PERIOD_)==TSC_DET_PERIOD_80)||((_PERIOD_)==TSC_DET_PERIOD_88)||((_PERIOD_)==TSC_DET_PERIOD_96) \ + ||((_PERIOD_)==TSC_DET_PERIOD_104) ) + +#define IS_TSC_FILTER(_FILTER_) \ + ( ((_FILTER_)==TSC_DET_FILTER_1) ||((_FILTER_)==TSC_DET_FILTER_2)\ + ||((_FILTER_)==TSC_DET_FILTER_3) ||((_FILTER_)==TSC_DET_FILTER_4) ) + +#define IS_TSC_DET_MODE(_MODE_) \ + ( ((_MODE_)==TSC_HW_DETECT_MODE) ||((_MODE_)==TSC_SW_DETECT_MODE) ) + +#define IS_TSC_DET_TYPE(_TYPE_) \ + ( ((_TYPE_)==TSC_DET_TYPE_GREAT) ||((_TYPE_)==TSC_DET_TYPE_LESS) \ + ||((_TYPE_)==TSC_DET_TYPE_PERIOD)|| ((_TYPE_)==TSC_DET_TYPE_NONE) ) + +#define IS_TSC_INT(_INT_) (((_INT_)==TSC_IT_DET_ENABLE)||((_INT_)==TSC_IT_DET_DISABLE)) + +#define IS_TSC_OUT(_ETR_) (((_ETR_)==TSC_OUT_PIN)||((_ETR_)==TSC_OUT_TIM2_ETR)||((_ETR_)==TSC_OUT_TIM4_ETR)) + +#define IS_TSC_CHN(_CHN_) (0==((_CHN_)&(~TSC_CHNEN_CHN_SEL_MASK))) + +#define IS_TSC_CHN_NUMBER(_NUM_) ((uint32_t)(_NUM_)BaudRate))) + - FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */ + + uint16_t WordLength; /*!< Specifies the number of data bits transmitted or received in a frame. + This parameter can be a value of @ref USART_Word_Length */ + + uint16_t StopBits; /*!< Specifies the number of stop bits transmitted. + This parameter can be a value of @ref USART_Stop_Bits */ + + uint16_t Parity; /*!< Specifies the parity mode. + This parameter can be a value of @ref Parity + @note When parity is enabled, the computed parity is inserted + at the MSB position of the transmitted data (9th bit when + the word length is set to 9 data bits; 8th bit when the + word length is set to 8 data bits). */ + + uint16_t Mode; /*!< Specifies wether the Receive or Transmit mode is enabled or disabled. + This parameter can be a value of @ref Mode */ + + uint16_t HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled + or disabled. + This parameter can be a value of @ref USART_Hardware_Flow_Control */ +} USART_InitType; + +/** + * @brief USART Clock Init Structure definition + */ + +typedef struct +{ + uint16_t Clock; /*!< Specifies whether the USART clock is enabled or disabled. + This parameter can be a value of @ref Clock */ + + uint16_t Polarity; /*!< Specifies the steady state value of the serial clock. + This parameter can be a value of @ref USART_Clock_Polarity */ + + uint16_t Phase; /*!< Specifies the clock transition on which the bit capture is made. + This parameter can be a value of @ref USART_Clock_Phase */ + + uint16_t LastBit; /*!< Specifies whether the clock pulse corresponding to the last transmitted + data bit (MSB) has to be output on the SCLK pin in synchronous mode. + This parameter can be a value of @ref USART_Last_Bit */ +} USART_ClockInitType; + +/** + * @} + */ + +/** @addtogroup USART_Exported_Constants + * @{ + */ + +#define IS_USART_ALL_PERIPH(PERIPH) \ + (((PERIPH) == USART1) || ((PERIPH) == USART2) || ((PERIPH) == USART3) || ((PERIPH) == UART4) \ + || ((PERIPH) == UART5) || ((PERIPH) == UART6) || ((PERIPH) == UART7)) + +#define IS_USART_123_PERIPH(PERIPH) (((PERIPH) == USART1) || ((PERIPH) == USART2) || ((PERIPH) == USART3)) + +#define IS_USART_1234_PERIPH(PERIPH) \ + (((PERIPH) == USART1) || ((PERIPH) == USART2) || ((PERIPH) == USART3) || ((PERIPH) == UART4)) +/** @addtogroup USART_Word_Length + * @{ + */ + +#define USART_WL_8B ((uint16_t)0x0000) +#define USART_WL_9B ((uint16_t)0x1000) + +#define IS_USART_WORD_LENGTH(LENGTH) (((LENGTH) == USART_WL_8B) || ((LENGTH) == USART_WL_9B)) +/** + * @} + */ + +/** @addtogroup USART_Stop_Bits + * @{ + */ + +#define USART_STPB_1 ((uint16_t)0x0000) +#define USART_STPB_0_5 ((uint16_t)0x1000) +#define USART_STPB_2 ((uint16_t)0x2000) +#define USART_STPB_1_5 ((uint16_t)0x3000) +#define IS_USART_STOPBITS(STOPBITS) \ + (((STOPBITS) == USART_STPB_1) || ((STOPBITS) == USART_STPB_0_5) || ((STOPBITS) == USART_STPB_2) \ + || ((STOPBITS) == USART_STPB_1_5)) +/** + * @} + */ + +/** @addtogroup Parity + * @{ + */ + +#define USART_PE_NO ((uint16_t)0x0000) +#define USART_PE_EVEN ((uint16_t)0x0400) +#define USART_PE_ODD ((uint16_t)0x0600) +#define IS_USART_PARITY(PARITY) (((PARITY) == USART_PE_NO) || ((PARITY) == USART_PE_EVEN) || ((PARITY) == USART_PE_ODD)) +/** + * @} + */ + +/** @addtogroup Mode + * @{ + */ + +#define USART_MODE_RX ((uint16_t)0x0004) +#define USART_MODE_TX ((uint16_t)0x0008) +#define IS_USART_MODE(MODE) ((((MODE) & (uint16_t)0xFFF3) == 0x00) && ((MODE) != (uint16_t)0x00)) +/** + * @} + */ + +/** @addtogroup USART_Hardware_Flow_Control + * @{ + */ +#define USART_HFCTRL_NONE ((uint16_t)0x0000) +#define USART_HFCTRL_RTS ((uint16_t)0x0100) +#define USART_HFCTRL_CTS ((uint16_t)0x0200) +#define USART_HFCTRL_RTS_CTS ((uint16_t)0x0300) +#define IS_USART_HARDWARE_FLOW_CONTROL(CONTROL) \ + (((CONTROL) == USART_HFCTRL_NONE) || ((CONTROL) == USART_HFCTRL_RTS) || ((CONTROL) == USART_HFCTRL_CTS) \ + || ((CONTROL) == USART_HFCTRL_RTS_CTS)) +/** + * @} + */ + +/** @addtogroup Clock + * @{ + */ +#define USART_CLK_DISABLE ((uint16_t)0x0000) +#define USART_CLK_ENABLE ((uint16_t)0x0800) +#define IS_USART_CLOCK(CLOCK) (((CLOCK) == USART_CLK_DISABLE) || ((CLOCK) == USART_CLK_ENABLE)) +/** + * @} + */ + +/** @addtogroup USART_Clock_Polarity + * @{ + */ + +#define USART_CLKPOL_LOW ((uint16_t)0x0000) +#define USART_CLKPOL_HIGH ((uint16_t)0x0400) +#define IS_USART_CPOL(CPOL) (((CPOL) == USART_CLKPOL_LOW) || ((CPOL) == USART_CLKPOL_HIGH)) + +/** + * @} + */ + +/** @addtogroup USART_Clock_Phase + * @{ + */ + +#define USART_CLKPHA_1EDGE ((uint16_t)0x0000) +#define USART_CLKPHA_2EDGE ((uint16_t)0x0200) +#define IS_USART_CPHA(CPHA) (((CPHA) == USART_CLKPHA_1EDGE) || ((CPHA) == USART_CLKPHA_2EDGE)) + +/** + * @} + */ + +/** @addtogroup USART_Last_Bit + * @{ + */ + +#define USART_CLKLB_DISABLE ((uint16_t)0x0000) +#define USART_CLKLB_ENABLE ((uint16_t)0x0100) +#define IS_USART_LASTBIT(LASTBIT) (((LASTBIT) == USART_CLKLB_DISABLE) || ((LASTBIT) == USART_CLKLB_ENABLE)) +/** + * @} + */ + +/** @addtogroup USART_Interrupt_definition + * @{ + */ + +#define USART_INT_PEF ((uint16_t)0x0028) +#define USART_INT_TXDE ((uint16_t)0x0727) +#define USART_INT_TXC ((uint16_t)0x0626) +#define USART_INT_RXDNE ((uint16_t)0x0525) +#define USART_INT_IDLEF ((uint16_t)0x0424) +#define USART_INT_LINBD ((uint16_t)0x0846) +#define USART_INT_CTSF ((uint16_t)0x096A) +#define USART_INT_ERRF ((uint16_t)0x0060) +#define USART_INT_OREF ((uint16_t)0x0360) +#define USART_INT_NEF ((uint16_t)0x0260) +#define USART_INT_FEF ((uint16_t)0x0160) +#define IS_USART_CFG_INT(IT) \ + (((IT) == USART_INT_PEF) || ((IT) == USART_INT_TXDE) || ((IT) == USART_INT_TXC) || ((IT) == USART_INT_RXDNE) \ + || ((IT) == USART_INT_IDLEF) || ((IT) == USART_INT_LINBD) || ((IT) == USART_INT_CTSF) \ + || ((IT) == USART_INT_ERRF)) +#define IS_USART_GET_INT(IT) \ + (((IT) == USART_INT_PEF) || ((IT) == USART_INT_TXDE) || ((IT) == USART_INT_TXC) || ((IT) == USART_INT_RXDNE) \ + || ((IT) == USART_INT_IDLEF) || ((IT) == USART_INT_LINBD) || ((IT) == USART_INT_CTSF) || ((IT) == USART_INT_OREF) \ + || ((IT) == USART_INT_NEF) || ((IT) == USART_INT_FEF)) +#define IS_USART_CLR_INT(IT) \ + (((IT) == USART_INT_TXC) || ((IT) == USART_INT_RXDNE) || ((IT) == USART_INT_LINBD) || ((IT) == USART_INT_CTSF)) +/** + * @} + */ + +/** @addtogroup USART_DMA_Requests + * @{ + */ + +#define USART_DMAREQ_TX ((uint16_t)0x0080) +#define USART_DMAREQ_RX ((uint16_t)0x0040) +#define IS_USART_DMAREQ(DMAREQ) ((((DMAREQ) & (uint16_t)0xFF3F) == 0x00) && ((DMAREQ) != (uint16_t)0x00)) + +/** + * @} + */ + +/** @addtogroup USART_WakeUp_methods + * @{ + */ + +#define USART_WUM_IDLELINE ((uint16_t)0x0000) +#define USART_WUM_ADDRMASK ((uint16_t)0x0800) +#define IS_USART_WAKEUP(WAKEUP) (((WAKEUP) == USART_WUM_IDLELINE) || ((WAKEUP) == USART_WUM_ADDRMASK)) +/** + * @} + */ + +/** @addtogroup USART_LIN_Break_Detection_Length + * @{ + */ + +#define USART_LINBDL_10B ((uint16_t)0x0000) +#define USART_LINBDL_11B ((uint16_t)0x0020) +#define IS_USART_LIN_BREAK_DETECT_LENGTH(LENGTH) (((LENGTH) == USART_LINBDL_10B) || ((LENGTH) == USART_LINBDL_11B)) +/** + * @} + */ + +/** @addtogroup USART_IrDA_Low_Power + * @{ + */ + +#define USART_IRDAMODE_LOWPPWER ((uint16_t)0x0004) +#define USART_IRDAMODE_NORMAL ((uint16_t)0x0000) +#define IS_USART_IRDA_MODE(MODE) (((MODE) == USART_IRDAMODE_LOWPPWER) || ((MODE) == USART_IRDAMODE_NORMAL)) +/** + * @} + */ + +/** @addtogroup USART_Flags + * @{ + */ + +#define USART_FLAG_CTSF ((uint16_t)0x0200) +#define USART_FLAG_LINBD ((uint16_t)0x0100) +#define USART_FLAG_TXDE ((uint16_t)0x0080) +#define USART_FLAG_TXC ((uint16_t)0x0040) +#define USART_FLAG_RXDNE ((uint16_t)0x0020) +#define USART_FLAG_IDLEF ((uint16_t)0x0010) +#define USART_FLAG_OREF ((uint16_t)0x0008) +#define USART_FLAG_NEF ((uint16_t)0x0004) +#define USART_FLAG_FEF ((uint16_t)0x0002) +#define USART_FLAG_PEF ((uint16_t)0x0001) +#define IS_USART_FLAG(FLAG) \ + (((FLAG) == USART_FLAG_PEF) || ((FLAG) == USART_FLAG_TXDE) || ((FLAG) == USART_FLAG_TXC) \ + || ((FLAG) == USART_FLAG_RXDNE) || ((FLAG) == USART_FLAG_IDLEF) || ((FLAG) == USART_FLAG_LINBD) \ + || ((FLAG) == USART_FLAG_CTSF) || ((FLAG) == USART_FLAG_OREF) || ((FLAG) == USART_FLAG_NEF) \ + || ((FLAG) == USART_FLAG_FEF)) + +#define IS_USART_CLEAR_FLAG(FLAG) ((((FLAG) & (uint16_t)0xFC9F) == 0x00) && ((FLAG) != (uint16_t)0x00)) +#define IS_USART_PERIPH_FLAG(PERIPH, USART_FLAG) \ + ((((*(uint32_t*)&(PERIPH)) != UART4_BASE) && ((*(uint32_t*)&(PERIPH)) != UART5_BASE)) \ + || ((USART_FLAG) != USART_FLAG_CTSF)) +#define IS_USART_BAUDRATE(BAUDRATE) (((BAUDRATE) > 0) && ((BAUDRATE) < 0x0044AA21)) +#define IS_USART_ADDRESS(ADDRESS) ((ADDRESS) <= 0xF) +#define IS_USART_DATA(DATA) ((DATA) <= 0x1FF) + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup USART_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup USART_Exported_Functions + * @{ + */ + +void USART_DeInit(USART_Module* USARTx); +void USART_Init(USART_Module* USARTx, USART_InitType* USART_InitStruct); +void USART_StructInit(USART_InitType* USART_InitStruct); +void USART_ClockInit(USART_Module* USARTx, USART_ClockInitType* USART_ClockInitStruct); +void USART_ClockStructInit(USART_ClockInitType* USART_ClockInitStruct); +void USART_Enable(USART_Module* USARTx, FunctionalState Cmd); +void USART_ConfigInt(USART_Module* USARTx, uint16_t USART_INT, FunctionalState Cmd); +void USART_EnableDMA(USART_Module* USARTx, uint16_t USART_DMAReq, FunctionalState Cmd); +void USART_SetAddr(USART_Module* USARTx, uint8_t USART_Addr); +void USART_ConfigWakeUpMode(USART_Module* USARTx, uint16_t USART_WakeUpMode); +void USART_EnableRcvWakeUp(USART_Module* USARTx, FunctionalState Cmd); +void USART_ConfigLINBreakDetectLength(USART_Module* USARTx, uint16_t USART_LINBreakDetectLength); +void USART_EnableLIN(USART_Module* USARTx, FunctionalState Cmd); +void USART_SendData(USART_Module* USARTx, uint16_t Data); +uint16_t USART_ReceiveData(USART_Module* USARTx); +void USART_SendBreak(USART_Module* USARTx); +void USART_SetGuardTime(USART_Module* USARTx, uint8_t USART_GuardTime); +void USART_SetPrescaler(USART_Module* USARTx, uint8_t USART_Prescaler); +void USART_EnableSmartCard(USART_Module* USARTx, FunctionalState Cmd); +void USART_SetSmartCardNACK(USART_Module* USARTx, FunctionalState Cmd); +void USART_EnableHalfDuplex(USART_Module* USARTx, FunctionalState Cmd); +void USART_ConfigIrDAMode(USART_Module* USARTx, uint16_t USART_IrDAMode); +void USART_EnableIrDA(USART_Module* USARTx, FunctionalState Cmd); +FlagStatus USART_GetFlagStatus(USART_Module* USARTx, uint16_t USART_FLAG); +void USART_ClrFlag(USART_Module* USARTx, uint16_t USART_FLAG); +INTStatus USART_GetIntStatus(USART_Module* USARTx, uint16_t USART_INT); +void USART_ClrIntPendingBit(USART_Module* USARTx, uint16_t USART_INT); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G4FR_USART_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_wwdg.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_wwdg.h new file mode 100644 index 0000000000..dacc9bf7ac --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32g4fr_wwdg.h @@ -0,0 +1,122 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_wwdg.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G4FR_WWDG_H__ +#define __N32G4FR_WWDG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g4fr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup WWDG + * @{ + */ + +/** @addtogroup WWDG_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @addtogroup WWDG_Exported_Constants + * @{ + */ + +/** @addtogroup WWDG_Prescaler + * @{ + */ + +#define WWDG_PRESCALER_DIV1 ((uint32_t)0x00000000) +#define WWDG_PRESCALER_DIV2 ((uint32_t)0x00000080) +#define WWDG_PRESCALER_DIV4 ((uint32_t)0x00000100) +#define WWDG_PRESCALER_DIV8 ((uint32_t)0x00000180) +#define IS_WWDG_PRESCALER_DIV(PRESCALER) \ + (((PRESCALER) == WWDG_PRESCALER_DIV1) || ((PRESCALER) == WWDG_PRESCALER_DIV2) \ + || ((PRESCALER) == WWDG_PRESCALER_DIV4) || ((PRESCALER) == WWDG_PRESCALER_DIV8)) +#define IS_WWDG_WVALUE(VALUE) ((VALUE) <= 0x7F) +#define IS_WWDG_CNT(COUNTER) (((COUNTER) >= 0x40) && ((COUNTER) <= 0x7F)) + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup WWDG_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @addtogroup WWDG_Exported_Functions + * @{ + */ + +void WWDG_DeInit(void); +void WWDG_SetPrescalerDiv(uint32_t WWDG_Prescaler); +void WWDG_SetWValue(uint8_t WindowValue); +void WWDG_EnableInt(void); +void WWDG_SetCnt(uint8_t Counter); +void WWDG_Enable(uint8_t Counter); +FlagStatus WWDG_GetEWINTF(void); +void WWDG_ClrEWINTF(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G4FR__WWDG_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32xx_tsc_alg_api.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32xx_tsc_alg_api.h new file mode 100644 index 0000000000..a0bc723d76 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/inc/n32xx_tsc_alg_api.h @@ -0,0 +1,302 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @brief 㷨ͷļ. + * :(TIMER->صAPI->ʼ->) + * @file n32xx_tsc_alg_api.h + * @author Nations + * @version v1.0.1 + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32XX_TSC_ALG_API__ +#define __N32XX_TSC_ALG_API__ + +#ifdef __cplusplus +extern "C" { +#endif // defined __cplusplus + +#define TSC_ALG_VERSION_NUMBER "Ver1.0.4" //㷨汾 + +#define TSC_ALG_HANDLER_STOP2_DATA_SIZE (144) //STOP2ģʽ±津ػѹصTSCݡ +#define TSC_ALG_HANDLER_PERIOD_PER_CHN (400) //㷨ͨĴӡ +#define TSC_ALG_WAKEUP_TIMES (1000) //йTSCѹܵʱãҪ޸ +#define TSC_ALG_DEBUG_BUF_SIZE (260) //ģʽµBUFС +#define TSC_ALG_REF_SIZE_PER_CHN (430) //ÿͨIJοСʵʴСtsc_alg_need_sramsize()Ϊ׼ + +/** + * @brief 崥 + */ +typedef enum tsc_alg_type_e +{ + TSC_ALG_BUTTON_TYPE = 0, ///< tsc application of simple button + TSC_ALG_TYPE_MAX ///< +} tsc_alg_type; + +/** + * @brief ¼ + */ +typedef enum tsc_press_key_event_e +{ + TSC_PRESS_KEY_NORMAL = 0, //̰¼ + TSC_PRESS_KEY_MAX ///< +} tsc_press_key_event; + +/** + * @brief Ͷ + */ +typedef enum tsc_ret_code_e +{ + TSC_SUCCESS = 0, ///< ɹ + TSC_NOT_INIT_ERR, ///< ģδʼ + TSC_NOT_REG_CHN_ERR, ///< ģעЧĴͨ + TSC_NOT_ACCORD_LIB_ERR, ///< 㷨汾 + TSC_POINTER_NULL_ERR, ///< ָΪմ + TSC_PARAM_ZERO_ERR, ///< + TSC_REPEAT_REG_ERR, ///< ظע + TSC_CHN_NUM_ERR, ///< ʼͨһ´ + TSC_REG_CHANNEL_ENOUGH_ERR, ///< עͨŴ򳬳ϵͳͨ + TSC_REG_TIMX_ERR, ///< עTimerԴ + TSC_REG_DMA_ERR, ///< עDMAԴ + TSC_SOURCE_NOT_ENOUGH_ERR, ///< Դ + TSC_NOT_SUPPORT_ERR, ///< δʵִֻ֧ + TSC_LEVEL_CFG_ERR, ///< ͨô + TSC_AUTO_CALIB_TIMER_ERR, ///< ԶУ׼ʱС2ͨʱ. + TSC_DISTURB_ERR, ///< Ŵ. + TSC_CHN_RAM_NOT_ENOUGH_ERR, ///< ṩTSCͨRAMΪNULLռ䲻 + TSC_STOP2_NULL_OR_INVALID_ERR, ///< ṩStop2DataݿռΪNULL16K retentionڡ + TSC_DEBUG_BUF_ENOUGH_ERR ///< ṩĵԻռ䲻 +} tsc_ret_code; + +/** + * @brief ذȼ + * ȼԽС:ӦٶԽ죬˲ĸҲԽ + * ȼԽ:Ӧٶ˲Խǿ + */ +typedef enum tsc_hld_lev_e +{ + TSC_HOLD_LEV1 = 1, // HOLDȼ1(5ms) + TSC_HOLD_LEV2 = 2, // HOLDȼ2(7ms) + TSC_HOLD_LEV3 = 3, // HOLDȼ3(11ms) + TSC_HOLD_LEV4 = 4, // HOLDȼ4(17ms) + TSC_HOLD_LEV5 = 5, // HOLDȼ5(25ms) + TSC_HOLD_LEV6 = 6, // HOLDȼ6(35ms) + TSC_HOLD_LEV7 = 7, // HOLDȼ7(47ms) + TSC_HOLD_LEV8 = 8, // HOLDȼ8(61ms) + TSC_HOLD_LEV9 = 9, // HOLDȼ9(77ms) + TSC_HOLD_LEV10 = 10, // HOLDȼ10(95ms) + TSC_HOLD_LEV11 = 11, // HOLDȼ11(115ms) + TSC_HOLD_LEV12 = 12, // HOLDȼ12(137ms) + TSC_HOLD_LEV13 = 13, // HOLDȼ13(161ms) + TSC_HOLD_LEV14 = 14, // HOLDȼ14(187ms) + TSC_HOLD_LEV15 = 15, // HOLDȼ15(215ms) + TSC_HOLD_LEV16 = 16, // HOLDȼ16(245ms) + TSC_HOLD_LEV17 = 17, // HOLDȼ17(277ms) + TSC_HOLD_LEV18 = 18, // HOLDȼ18(311ms) + TSC_HOLD_LEV19 = 19, // HOLDȼ19(347ms) + TSC_HOLD_LEV20 = 20, // HOLDȼ20(385ms) + TSC_HOLD_MAX ///< Ч +} tsc_hld_lev; + +/** + * @brief ڵ͹ģʽ£滷仯»ޡ + * һ仯ӡ + * Сڴ˱仯ӵdeltaΪЧ仯ͨ˽ӿڸTSCޣ + * ڴ˱仯ӵdeltaΪЧ仯˽ӿں֮»ޡ + * 仯Խʾ仯ԽһΪLEV15 + */ +typedef enum tsc_delta_limit_lev_e +{ + TSC_DELTA_LIMIT_LEV1 = 1, // + TSC_DELTA_LIMIT_LEV2 = 2, // + TSC_DELTA_LIMIT_LEV3 = 3, // + TSC_DELTA_LIMIT_LEV4 = 4, // + TSC_DELTA_LIMIT_LEV5 = 5, // + TSC_DELTA_LIMIT_LEV6 = 6, // + TSC_DELTA_LIMIT_LEV7 = 7, // + TSC_DELTA_LIMIT_LEV8 = 8, // + TSC_DELTA_LIMIT_LEV9 = 9, // + TSC_DELTA_LIMIT_LEV10 = 10, // + TSC_DELTA_LIMIT_LEV11 = 11, // + TSC_DELTA_LIMIT_LEV12 = 12, // + TSC_DELTA_LIMIT_LEV13 = 13, // + TSC_DELTA_LIMIT_LEV14 = 14, // + TSC_DELTA_LIMIT_LEV15 = 15, // + TSC_DELTA_LIMIT_LEV16 = 16, // + TSC_DELTA_LIMIT_LEV17 = 17, // + TSC_DELTA_LIMIT_LEV18 = 18, // + TSC_DELTA_LIMIT_LEV19 = 19, // + TSC_DELTA_LIMIT_LEV20 = 20, // + TSC_DELTA_LIMIT_MAX ///< Ч +} tsc_delta_limit_lev; + +/** + * @brief ŵȼ + * ŵȼ,ȼԽ߿ԽǿҲ԰弶ҪԽϿ. + */ +typedef enum tsc_resist_disturb_lev_e +{ + TSC_RESIST_DIS_LEV0 = 0, //Ĭϵȼⲿһ㡣֧PCBA&ǿ + TSC_RESIST_DIS_LEV1 = 1, //ǿȼⲿǿǿá + TSC_RESIST_DIS_LEV2 = 2, //ݱ + TSC_RESIST_DIS_MAX ///< Ч +} tsc_resist_disturb_lev; + +/** + * @brief TSCͨʼֵ + */ +typedef struct TSC_AlgInitThreValue_t +{ + uint16_t hold_level; /* ȼ */ + uint16_t rate_of_change; /* ͨ仯(ѹΪ70,ѹΪ77仯Ϊ(77-70)/70 = 0.1%10(ע:ʵΪ8%)ĬΪ5,仯%5 */ + uint32_t chn; /* ͨ */ +} TSC_AlgInitThreValue; + +/** + * @brief TSCʼò + */ +typedef struct TSC_AlgInitTypeDef_t +{ + TIM_Module* TIMx; /* 㷨ʹõTIMERԴ(֧TIMER2) */ + DMA_ChannelType* DMAyChx; /* 㷨ʹõDMAԴ(֧DMA1_CH5) */ + uint32_t DMARemapEnable; /* ǷʹDMA ȫREMAP(DMA1ͨʹREMAPܣ˴Ϊ1) */ + TSC_AlgInitThreValue* pTScChannelList; /* ɴͨб顣Ŀǰ֧1(ͨλ,TSCͨһб) */ + uint32_t AutoCalibrateTimer; /* иµԶУ׼ʱ(޸ʱУ׼),һ1000ms,65535λmsֵڰʱ2ϣʼ */ + uint32_t ResistDisturbLev; /* ŵȼ(tsc_resist_disturb_lev),ȼԽ߿ԽǿҲ԰弶װ价ҪԽ. */ + uint8_t* pTscSramAddr; /* ӦóṩTSCĴͨRAMռַ*/ + uint32_t TscSramSize; /* ӦóṩTSCĴͨRAMռС.λ(bytes) */ + uint16_t* LogBuf; /* ڵģʽµbuf,ǵģʽΪ0 */ + uint16_t LogBufSize; /* ÿͨСΪu16 * 256.λ(bytes) */ + uint8_t* Stop2Data; /* STOP2ģʽ±津ػѹصTSCBUF */ + uint16_t Stop2DataSize; /* STOP2ģʽ±津ػѹصTSCBUFСλ(bytes) */ +} TSC_AlgInitTypeDef; + +/** + * @brief 㷨ʵʱ(TIMERжϺ) + * @TIMERʱڲοӣʱڲοDEMO. + * @param void + * @return void + */ +void tsc_alg_analyze_handler(void); + +/** + * @brief ͹У׼ + * @param uint32_t delta_limit_level 仯ֵȼtsc_delta_limit_lev + * @uint32_t hse_or_hsi 0:HSI, 1:HSE; + * @return + * - `TSC_SUCCESS ʾɹ + * - ֵʾ + * - ע⣺STOP2͹ģʽ£ʱУ׼ + */ +int32_t tsc_alg_set_powerdown_calibrate(tsc_delta_limit_lev delta_limit_level, uint32_t hse_or_hsi); + +/** + * @brief ͹ģʽ,Ƿ񱻸Ż + * @param void + * @return 0:ѣ1:Ż + */ +int32_t tsc_alg_wakeup_disturb_check(uint32_t* wakeup_src); + +/** + * @brief ȡ㷨汾 + * @param void + * @return void + */ +char* tsc_alg_get_version(void); + +/** + * @brief 㷨ϵͳδ,Ĭ1ms + * @param void + * @return void + */ +void tsc_alg_tick_count(void); + +/** + * @brief ȡTSC㷨ҪSRAMС + * uint32_t chn_totals; // ʹõTSCͨ + * @return + * - 0: ʾʧ + * - 0: ʾɹ + */ +uint32_t tsc_alg_need_sramsize(uint32_t chn_totals); + +/** + * @brief 㷨ʼ + * @param tsc_init_parameter *ptsc_init_parameter 㷨ʼṹַ. + * @param void + * @return + * - `TSC_SUCCESS ʾɹ + * - ֵʾ + */ +int32_t tsc_alg_init(TSC_AlgInitTypeDef* TSC_AlgInitStruct); + +/** + * @brief ؿʼ + * @param void + * @return + * - `TSC_SUCCESS ʾɹ + * - ֵʾ + */ +int32_t tsc_alg_start(void); + +/** + * @brief TSC͹(ڵ͹Ļģʽ) + * @param uint32_t TScChannelList Ϊ0ʾʹעͨ + * @return + * - `TSC_SUCCESS ʾɹ + * - ֵʾ + * - ע⣺STOP2͹ģʽʹãģʽ²ע + */ +int32_t tsc_alg_set_powerdown(uint32_t TscChannelList); + +//////////////////////////////////////////////////////////// + +/*****************ϲӦṩİص********* + * @brief עᰴť͡͡תʹصĻص + * @param tsc_touch_type type Ĵ(ְֻ֧) + * @param uint32_t event 0:¼ + * @param uint32_t chn ʾͨţ + * @param uint32_t value ״̬1ѹ£0ɿ + * @return + * - `TSC_SUCCESS ʾɹ + * - ֵʾ + * ע:˻صжеã˾ٻصĴʱ䡣 + ********************************************************/ +int32_t tsc_alg_isr_callback(tsc_alg_type type, uint32_t event, uint32_t chn, uint32_t value); + +/** + * @brief PCĽӿڣԱPC˹߹۲죬趨Ĵֵ + * @param uint32_t chn ͨ + * @return uint8_t data ôͨ + */ +void tsc_alg_debug_output(uint32_t chn, uint8_t data); + +#ifdef __cplusplus +} +#endif // defined __cplusplus + +#endif //__N32XX_TSC_ALG_API__ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/misc.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/misc.c new file mode 100644 index 0000000000..8bf013baaa --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/misc.c @@ -0,0 +1,228 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file misc.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "misc.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup MISC + * @brief MISC driver modules + * @{ + */ + +/** @addtogroup MISC_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup MISC_Private_Defines + * @{ + */ + +#define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000) +/** + * @} + */ + +/** @addtogroup MISC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup MISC_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup MISC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup MISC_Private_Functions + * @{ + */ + +/** + * @brief Configures the priority grouping: pre-emption priority and subpriority. + * @param NVIC_PriorityGroup specifies the priority grouping bits length. + * This parameter can be one of the following values: + * @arg NVIC_PriorityGroup_0 0 bits for pre-emption priority + * 4 bits for subpriority + * @arg NVIC_PriorityGroup_1 1 bits for pre-emption priority + * 3 bits for subpriority + * @arg NVIC_PriorityGroup_2 2 bits for pre-emption priority + * 2 bits for subpriority + * @arg NVIC_PriorityGroup_3 3 bits for pre-emption priority + * 1 bits for subpriority + * @arg NVIC_PriorityGroup_4 4 bits for pre-emption priority + * 0 bits for subpriority + */ +void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup) +{ + /* Check the parameters */ + assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup)); + + /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */ + SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup; +} + +/** + * @brief Initializes the NVIC peripheral according to the specified + * parameters in the NVIC_InitStruct. + * @param NVIC_InitStruct pointer to a NVIC_InitType structure that contains + * the configuration information for the specified NVIC peripheral. + */ +void NVIC_Init(NVIC_InitType* NVIC_InitStruct) +{ + uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F; + + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd)); + assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority)); + assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority)); + + if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE) + { + /* Compute the Corresponding IRQ Priority --------------------------------*/ + tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700)) >> 0x08; + tmppre = (0x4 - tmppriority); + tmpsub = tmpsub >> tmppriority; + + tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre; + tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub; + tmppriority = tmppriority << 0x04; + + NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority; + + /* Enable the Selected IRQ Channels --------------------------------------*/ + NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = (uint32_t)0x01 + << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); + } + else + { + /* Disable the Selected IRQ Channels -------------------------------------*/ + NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = (uint32_t)0x01 + << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); + } +} + +/** + * @brief Sets the vector table location and Offset. + * @param NVIC_VectTab specifies if the vector table is in RAM or FLASH memory. + * This parameter can be one of the following values: + * @arg NVIC_VectTab_RAM + * @arg NVIC_VectTab_FLASH + * @param Offset Vector Table base offset field. This value must be a multiple + * of 0x200. + */ +void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset) +{ + /* Check the parameters */ + assert_param(IS_NVIC_VECTTAB(NVIC_VectTab)); + assert_param(IS_NVIC_OFFSET(Offset)); + + SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80); +} + +/** + * @brief Selects the condition for the system to enter low power mode. + * @param LowPowerMode Specifies the new mode for the system to enter low power mode. + * This parameter can be one of the following values: + * @arg NVIC_LP_SEVONPEND + * @arg NVIC_LP_SLEEPDEEP + * @arg NVIC_LP_SLEEPONEXIT + * @param Cmd new state of LP condition. This parameter can be: ENABLE or DISABLE. + */ +void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_NVIC_LP(LowPowerMode)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + SCB->SCR |= LowPowerMode; + } + else + { + SCB->SCR &= (uint32_t)(~(uint32_t)LowPowerMode); + } +} + +/** + * @brief Configures the SysTick clock source. + * @param SysTick_CLKSource specifies the SysTick clock source. + * This parameter can be one of the following values: + * @arg SysTick_CLKSource_HCLK AHB clock selected as SysTick clock source. + */ +void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource) +{ + /* Check the parameters */ + assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource)); + if (SysTick_CLKSource == SysTick_CLKSource_HCLK) + { + SysTick->CTRL |= SysTick_CLKSource_HCLK; + } +// else +// { +// SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8; +// } +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_adc.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_adc.c new file mode 100644 index 0000000000..b8a785b995 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_adc.c @@ -0,0 +1,1471 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_adc.c + * @author Nations + * @version v1.0.4 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_adc.h" +#include "n32g4fr_rcc.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup ADC + * @brief ADC driver modules + * @{ + */ + +/** @addtogroup ADC_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup ADC_Private_Defines + * @{ + */ + +/* ADC DISC_NUM mask */ +#define CR1_DISCNUM_Reset ((uint32_t)0xFFFF1FFF) + +/* ADC DISC_EN mask */ +#define CTRL1_DISC_EN_SET ((uint32_t)0x00000800) +#define CTRL1_DISC_EN_RESET ((uint32_t)0xFFFFF7FF) + +/* ADC INJ_AUTO mask */ +#define CR1_JAUTO_Set ((uint32_t)0x00000400) +#define CR1_JAUTO_Reset ((uint32_t)0xFFFFFBFF) + +/* ADC INJ_DISC_EN mask */ +#define CTRL1_INJ_DISC_EN_SET ((uint32_t)0x00001000) +#define CTRL1_INJ_DISC_EN_RESET ((uint32_t)0xFFFFEFFF) + +/* ADC AWDG_CH mask */ +#define CTRL1_AWDG_CH_RESET ((uint32_t)0xFFFFFFE0) + +/* ADC Analog watchdog enable mode mask */ +#define CTRL1_AWDG_MODE_RESET ((uint32_t)0xFF3FFDFF) + +/* CTRL1 register Mask */ +#define CTRL1_CLR_MASK ((uint32_t)0xFFF0FEFF) + +/* ADC AD_ON mask */ +#define CTRL2_AD_ON_SET ((uint32_t)0x00000001) +#define CTRL2_AD_ON_RESET ((uint32_t)0xFFFFFFFE) + +/* ADC DMA mask */ +#define CTRL2_DMA_SET ((uint32_t)0x00000100) +#define CTRL2_DMA_RESET ((uint32_t)0xFFFFFEFF) + +/* ADC RST_CALI mask */ +#define CTRL2_RST_CALI_SET ((uint32_t)0x00000008) + +/* ADC CAL mask */ +#define CTRL2_CAL_SET ((uint32_t)0x00000004) + +/* ADC SOFT_START mask */ +#define CTRL2_SOFT_START_SET ((uint32_t)0x00400000) + +/* ADC EXT_TRIG mask */ +#define CTRL2_EXT_TRIG_SET ((uint32_t)0x00100000) +#define CTRL2_EXT_TRIG_RESET ((uint32_t)0xFFEFFFFF) + +/* ADC Software start mask */ +#define CTRL2_EXT_TRIG_SWSTART_SET ((uint32_t)0x00500000) +#define CTRL2_EXT_TRIG_SWSTART_RESET ((uint32_t)0xFFAFFFFF) + +/* ADC INJ_EXT_SEL mask */ +#define CTRL2_INJ_EXT_SEL_RESET ((uint32_t)0xFFFF8FFF) + +/* ADC INJ_EXT_TRIG mask */ +#define CTRL2_INJ_EXT_TRIG_SET ((uint32_t)0x00008000) +#define CTRL2_INJ_EXT_TRIG_RESET ((uint32_t)0xFFFF7FFF) + +/* ADC INJ_SWSTART mask */ +#define CTRL2_INJ_SWSTART_SET ((uint32_t)0x00200000) + +/* ADC injected software start mask */ +#define CTRL2_INJ_EXT_TRIG_JSWSTART_SET ((uint32_t)0x00208000) +#define CTRL2_INJ_EXT_TRIG_JSWSTART_RESET ((uint32_t)0xFFDF7FFF) + +/* ADC TSPD mask */ +#define CTRL2_TSVREFE_SET ((uint32_t)0x00800000) +#define CTRL2_TSVREFE_RESET ((uint32_t)0xFF7FFFFF) + +/* CTRL2 register Mask */ +#define CTRL2_CLR_MASK ((uint32_t)0xFFF1F7FD) + +/* ADC SQx mask */ +#define SQR4_SEQ_SET ((uint32_t)0x0000001F) +#define SQR3_SEQ_SET ((uint32_t)0x0000001F) +#define SQR2_SEQ_SET ((uint32_t)0x0000001F) +#define SQR1_SEQ_SET ((uint32_t)0x0000001F) + +/* RSEQ1 register Mask */ +#define RSEQ1_CLR_MASK ((uint32_t)0xFF0FFFFF) + +/* ADC JSQx mask */ +#define JSEQ_JSQ_SET ((uint32_t)0x0000001F) + +/* ADC INJ_LEN mask */ +#define JSEQ_INJ_LEN_SET ((uint32_t)0x00300000) +#define JSEQ_INJ_LEN_RESET ((uint32_t)0xFFCFFFFF) + +/* ADC SAMPTx mask */ +#define SAMPT1_SMP_SET ((uint32_t)0x00000007) +#define SAMPT2_SMP_SET ((uint32_t)0x00000007) + +/* ADC JDATx registers offset */ +#define JDAT_OFFSET ((uint8_t)0x28) + +/* ADC1 DAT register base address */ +#define DAT_ADDR ((uint32_t)0x4001244C) + +/* ADC STS register mask */ +#define ADC_STS_RESERVE_MASK ((uint32_t)0x0000007F) + +/** + * @} + */ + +/** @addtogroup ADC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup ADC_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup ADC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup ADC_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the ADCx peripheral registers to their default reset values. + * @param ADCx where x can be 1, 2 to select the ADC peripheral. + */ +void ADC_DeInit(ADC_Module* ADCx) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + + if (ADCx == ADC1) + { + /* Enable ADC1 reset state */ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ADC1, ENABLE); + /* Release ADC1 from reset state */ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ADC1, DISABLE); + } + else if (ADCx == ADC2) + { + /* Enable ADC2 reset state */ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ADC2, ENABLE); + /* Release ADC2 from reset state */ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ADC2, DISABLE); + } +} + +/** + * @brief Initializes the ADCx peripheral according to the specified parameters + * in the ADC_InitStruct. + * @param ADCx where x can be 1, 2 to select the ADC peripheral. + * @param ADC_InitStruct pointer to an ADC_InitType structure that contains + * the configuration information for the specified ADC peripheral. + */ +void ADC_Init(ADC_Module* ADCx, ADC_InitType* ADC_InitStruct) +{ + uint32_t tmpreg1 = 0; + uint8_t tmpreg2 = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcWorkMode(ADC_InitStruct->WorkMode)); + assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->MultiChEn)); + assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->ContinueConvEn)); + assert_param(IsAdcExtTrig(ADC_InitStruct->ExtTrigSelect)); + assert_param(IsAdcDatAlign(ADC_InitStruct->DatAlign)); + assert_param(IsAdcSeqLenValid(ADC_InitStruct->ChsNumber)); + + /*---------------------------- ADCx CTRL1 Configuration -----------------*/ + /* Get the ADCx CTRL1 value */ + tmpreg1 = ADCx->CTRL1; + /* Clear DUALMOD and SCAN bits */ + tmpreg1 &= CTRL1_CLR_MASK; + /* Configure ADCx: Dual mode and scan conversion mode */ + /* Set DUALMOD bits according to WorkMode value */ + /* Set SCAN bit according to MultiChEn value */ + tmpreg1 |= (uint32_t)(ADC_InitStruct->WorkMode | ((uint32_t)ADC_InitStruct->MultiChEn << 8)); + /* Write to ADCx CTRL1 */ + ADCx->CTRL1 = tmpreg1; + + /*---------------------------- ADCx CTRL2 Configuration -----------------*/ + /* Get the ADCx CTRL2 value */ + tmpreg1 = ADCx->CTRL2; + /* Clear CONT, ALIGN and EXTSEL bits */ + tmpreg1 &= CTRL2_CLR_MASK; + /* Configure ADCx: external trigger event and continuous conversion mode */ + /* Set ALIGN bit according to DatAlign value */ + /* Set EXTSEL bits according to ExtTrigSelect value */ + /* Set CONT bit according to ContinueConvEn value */ + tmpreg1 |= (uint32_t)(ADC_InitStruct->DatAlign | ADC_InitStruct->ExtTrigSelect + | ((uint32_t)ADC_InitStruct->ContinueConvEn << 1)); + /* Write to ADCx CTRL2 */ + ADCx->CTRL2 = tmpreg1; + + /*---------------------------- ADCx RSEQ1 Configuration -----------------*/ + /* Get the ADCx RSEQ1 value */ + tmpreg1 = ADCx->RSEQ1; + /* Clear L bits */ + tmpreg1 &= RSEQ1_CLR_MASK; + /* Configure ADCx: regular channel sequence length */ + /* Set L bits according to ChsNumber value */ + tmpreg2 |= (uint8_t)(ADC_InitStruct->ChsNumber - (uint8_t)1); + tmpreg1 |= (uint32_t)tmpreg2 << 20; + /* Write to ADCx RSEQ1 */ + ADCx->RSEQ1 = tmpreg1; +} + +/** + * @brief Fills each ADC_InitStruct member with its default value. + * @param ADC_InitStruct pointer to an ADC_InitType structure which will be initialized. + */ +void ADC_InitStruct(ADC_InitType* ADC_InitStruct) +{ + /* Reset ADC init structure parameters values */ + /* Initialize the WorkMode member */ + ADC_InitStruct->WorkMode = ADC_WORKMODE_INDEPENDENT; + /* initialize the MultiChEn member */ + ADC_InitStruct->MultiChEn = DISABLE; + /* Initialize the ContinueConvEn member */ + ADC_InitStruct->ContinueConvEn = DISABLE; + /* Initialize the ExtTrigSelect member */ + ADC_InitStruct->ExtTrigSelect = ADC_EXT_TRIGCONV_T1_CC1; + /* Initialize the DatAlign member */ + ADC_InitStruct->DatAlign = ADC_DAT_ALIGN_R; + /* Initialize the ChsNumber member */ + ADC_InitStruct->ChsNumber = 1; +} + +/** + * @brief Enables or disables the specified ADC peripheral. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the ADCx peripheral. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_Enable(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Set the AD_ON bit to wake up the ADC from power down mode */ + ADCx->CTRL2 |= CTRL2_AD_ON_SET; + } + else + { + /* Disable the selected ADC peripheral */ + ADCx->CTRL2 &= CTRL2_AD_ON_RESET; + } +} + +/** + * @brief Enables or disables the specified ADC DMA request. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the selected ADC DMA transfer. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableDMA(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcDmaModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected ADC DMA request */ + ADCx->CTRL2 |= CTRL2_DMA_SET; + } + else + { + /* Disable the selected ADC DMA request */ + ADCx->CTRL2 &= CTRL2_DMA_RESET; + } +} + +/** + * @brief Enables or disables the specified ADC interrupts. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_IT specifies the ADC interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg ADC_INT_ENDC End of conversion interrupt mask + * @arg ADC_INT_AWD Analog watchdog interrupt mask + * @arg ADC_INT_JENDC End of injected conversion interrupt mask + * @param Cmd new state of the specified ADC interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_ConfigInt(ADC_Module* ADCx, uint16_t ADC_IT, FunctionalState Cmd) +{ + uint8_t itmask = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + assert_param(IsAdcInt(ADC_IT)); + /* Get the ADC IT index */ + itmask = (uint8_t)ADC_IT; + if (Cmd != DISABLE) + { + /* Enable the selected ADC interrupts */ + ADCx->CTRL1 |= itmask; + } + else + { + /* Disable the selected ADC interrupts */ + ADCx->CTRL1 &= (~(uint32_t)itmask); + } +} + + + +/** + * @brief Starts the selected ADC calibration process. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + */ +void ADC_StartCalibration(ADC_Module* ADCx) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + /* Enable the selected ADC calibration process */ + if(ADCx->CALFACT==0) + ADCx->CTRL2 |= CTRL2_CAL_SET; +} + +/** + * @brief Gets the selected ADC calibration status. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @return The new state of ADC calibration (SET or RESET). + */ +FlagStatus ADC_GetCalibrationStatus(ADC_Module* ADCx) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + /* Check the status of CAL bit */ + if ((ADCx->CTRL2 & CTRL2_CAL_SET) != (uint32_t)RESET) + { + /* CAL bit is set: calibration on going */ + bitstatus = SET; + } + else + { + /* CAL bit is reset: end of calibration */ + bitstatus = RESET; + } + if(ADCx->CALFACT!=0) + bitstatus = RESET; + /* Return the CAL bit status */ + return bitstatus; +} + +/** + * @brief Enables or disables the selected ADC software start conversion . + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the selected ADC software start conversion. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableSoftwareStartConv(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected ADC conversion on external event and start the selected + ADC conversion */ + ADCx->CTRL2 |= CTRL2_EXT_TRIG_SWSTART_SET; + } + else + { + /* Disable the selected ADC conversion on external event and stop the selected + ADC conversion */ + ADCx->CTRL2 &= CTRL2_EXT_TRIG_SWSTART_RESET; + } +} + +/** + * @brief Gets the selected ADC Software start conversion Status. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @return The new state of ADC software start conversion (SET or RESET). + */ +FlagStatus ADC_GetSoftwareStartConvStatus(ADC_Module* ADCx) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + /* Check the status of SOFT_START bit */ + if ((ADCx->CTRL2 & CTRL2_SOFT_START_SET) != (uint32_t)RESET) + { + /* SOFT_START bit is set */ + bitstatus = SET; + } + else + { + /* SOFT_START bit is reset */ + bitstatus = RESET; + } + /* Return the SOFT_START bit status */ + return bitstatus; +} + +/** + * @brief Configures the discontinuous mode for the selected ADC regular + * group channel. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Number specifies the discontinuous mode regular channel + * count value. This number must be between 1 and 8. + */ +void ADC_ConfigDiscModeChannelCount(ADC_Module* ADCx, uint8_t Number) +{ + uint32_t tmpreg1 = 0; + uint32_t tmpreg2 = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcSeqDiscNumberValid(Number)); + /* Get the old register value */ + tmpreg1 = ADCx->CTRL1; + /* Clear the old discontinuous mode channel count */ + tmpreg1 &= CR1_DISCNUM_Reset; + /* Set the discontinuous mode channel count */ + tmpreg2 = Number - 1; + tmpreg1 |= tmpreg2 << 13; + /* Store the new register value */ + ADCx->CTRL1 = tmpreg1; +} + +/** + * @brief Enables or disables the discontinuous mode on regular group + * channel for the specified ADC + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the selected ADC discontinuous mode + * on regular group channel. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableDiscMode(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected ADC regular discontinuous mode */ + ADCx->CTRL1 |= CTRL1_DISC_EN_SET; + } + else + { + /* Disable the selected ADC regular discontinuous mode */ + ADCx->CTRL1 &= CTRL1_DISC_EN_RESET; + } +} + +/** + * @brief Configures for the selected ADC regular channel its corresponding + * rank in the sequencer and its sample time. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_Channel the ADC channel to configure. + * This parameter can be one of the following values: + * @arg ADC_CH_0 ADC Channel0 selected + * @arg ADC_CH_1 ADC Channel1 selected + * @arg ADC_CH_2 ADC Channel2 selected + * @arg ADC_CH_3 ADC Channel3 selected + * @arg ADC_CH_4 ADC Channel4 selected + * @arg ADC_CH_5 ADC Channel5 selected + * @arg ADC_CH_6 ADC Channel6 selected + * @arg ADC_CH_7 ADC Channel7 selected + * @arg ADC_CH_8 ADC Channel8 selected + * @arg ADC_CH_9 ADC Channel9 selected + * @arg ADC_CH_10 ADC Channel10 selected + * @arg ADC_CH_11 ADC Channel11 selected + * @arg ADC_CH_12 ADC Channel12 selected + * @arg ADC_CH_13 ADC Channel13 selected + * @arg ADC_CH_14 ADC Channel14 selected + * @arg ADC_CH_15 ADC Channel15 selected + * @arg ADC_CH_16 ADC Channel16 selected + * @arg ADC_CH_17 ADC Channel17 selected + * @arg ADC_CH_18 ADC Channel18 selected + * @param Rank The rank in the regular group sequencer. This parameter must be between 1 to 16. + * @param ADC_SampleTime The sample time value to be set for the selected channel. + * This parameter can be one of the following values: + * @arg ADC_SAMP_TIME_1CYCLES5 Sample time equal to 1.5 cycles + * @arg ADC_SAMP_TIME_7CYCLES5 Sample time equal to 7.5 cycles + * @arg ADC_SAMP_TIME_13CYCLES5 Sample time equal to 13.5 cycles + * @arg ADC_SAMP_TIME_28CYCLES5 Sample time equal to 28.5 cycles + * @arg ADC_SAMP_TIME_41CYCLES5 Sample time equal to 41.5 cycles + * @arg ADC_SAMP_TIME_55CYCLES5 Sample time equal to 55.5 cycles + * @arg ADC_SAMP_TIME_71CYCLES5 Sample time equal to 71.5 cycles + * @arg ADC_SAMP_TIME_239CYCLES5 Sample time equal to 239.5 cycles + */ +void ADC_ConfigRegularChannel(ADC_Module* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcChannel(ADC_Channel)); + assert_param(IsAdcReqRankValid(Rank)); + assert_param(IsAdcSampleTime(ADC_SampleTime)); + + if (ADC_Channel == ADC_CH_18) + { + tmpreg1 = ADCx->SAMPT3; + tmpreg1 &= (~0x00000007); + tmpreg1 |= ADC_SampleTime; + ADCx->SAMPT3 = tmpreg1; + } + else if (ADC_Channel > ADC_CH_9) /* if ADC_CH_10 ... ADC_CH_17 is selected */ + { + /* Get the old register value */ + tmpreg1 = ADCx->SAMPT1; + /* Calculate the mask to clear */ + tmpreg2 = SAMPT1_SMP_SET << (3 * (ADC_Channel - 10)); + /* Clear the old channel sample time */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * (ADC_Channel - 10)); + /* Set the new channel sample time */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SAMPT1 = tmpreg1; + } + else /* ADC_Channel include in ADC_Channel_[0..9] */ + { + /* Get the old register value */ + tmpreg1 = ADCx->SAMPT2; + /* Calculate the mask to clear */ + tmpreg2 = SAMPT2_SMP_SET << (3 * ADC_Channel); + /* Clear the old channel sample time */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel); + /* Set the new channel sample time */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SAMPT2 = tmpreg1; + } + /* For Rank 1 to 6 */ + if (Rank < 7) + { + /* Get the old register value */ + tmpreg1 = ADCx->RSEQ3; + /* Calculate the mask to clear */ + tmpreg2 = SQR3_SEQ_SET << (5 * (Rank - 1)); + /* Clear the old SQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 1)); + /* Set the SQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->RSEQ3 = tmpreg1; + } + /* For Rank 7 to 12 */ + else if (Rank < 13) + { + /* Get the old register value */ + tmpreg1 = ADCx->RSEQ2; + /* Calculate the mask to clear */ + tmpreg2 = SQR2_SEQ_SET << (5 * (Rank - 7)); + /* Clear the old SQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 7)); + /* Set the SQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->RSEQ2 = tmpreg1; + } + /* For Rank 13 to 16 */ + else + { + /* Get the old register value */ + tmpreg1 = ADCx->RSEQ1; + /* Calculate the mask to clear */ + tmpreg2 = SQR1_SEQ_SET << (5 * (Rank - 13)); + /* Clear the old SQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 13)); + /* Set the SQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->RSEQ1 = tmpreg1; + } +} + +/** + * @brief Enables or disables the ADCx conversion through external trigger. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the selected ADC external trigger start of conversion. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableExternalTrigConv(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected ADC conversion on external event */ + ADCx->CTRL2 |= CTRL2_EXT_TRIG_SET; + } + else + { + /* Disable the selected ADC conversion on external event */ + ADCx->CTRL2 &= CTRL2_EXT_TRIG_RESET; + } +} + +/** + * @brief Returns the last ADCx conversion result data for regular channel. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @return The Data conversion value. + */ +uint16_t ADC_GetDat(ADC_Module* ADCx) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + /* Return the selected ADC conversion value */ + return (uint16_t)ADCx->DAT; +} + +/** + * @brief Returns the last ADC1 and ADC2 conversion result data in dual mode. + * @return The Data conversion value. + */ +uint32_t ADC_GetDualModeConversionDat(ADC_Module* ADCx) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + /* Return the dual mode conversion value */ + if((ADCx==ADC1) | (ADCx==ADC2)) + return (uint32_t)ADC1->DAT; + else + return (uint32_t)ADC1->DAT; +} + +/** + * @brief Enables or disables the selected ADC automatic injected group + * conversion after regular one. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the selected ADC auto injected conversion + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableAutoInjectedConv(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected ADC automatic injected group conversion */ + ADCx->CTRL1 |= CR1_JAUTO_Set; + } + else + { + /* Disable the selected ADC automatic injected group conversion */ + ADCx->CTRL1 &= CR1_JAUTO_Reset; + } +} + +/** + * @brief Enables or disables the discontinuous mode for injected group + * channel for the specified ADC + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the selected ADC discontinuous mode + * on injected group channel. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableInjectedDiscMode(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected ADC injected discontinuous mode */ + ADCx->CTRL1 |= CTRL1_INJ_DISC_EN_SET; + } + else + { + /* Disable the selected ADC injected discontinuous mode */ + ADCx->CTRL1 &= CTRL1_INJ_DISC_EN_RESET; + } +} + +/** + * @brief Configures the ADCx external trigger for injected channels conversion. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_ExternalTrigInjecConv specifies the ADC trigger to start injected conversion. + * This parameter can be one of the following values: + * @arg ADC_EXT_TRIG_INJ_CONV_T1_TRGO Timer1 TRGO event selected (for ADC1, ADC2) + * @arg ADC_EXT_TRIG_INJ_CONV_T1_CC4 Timer1 capture compare4 selected (for ADC1, ADC2) + * @arg ADC_EXT_TRIG_INJ_CONV_T2_TRGO Timer2 TRGO event selected (for ADC1 and ADC2) + * @arg ADC_EXT_TRIG_INJ_CONV_T2_CC1 Timer2 capture compare1 selected (for ADC1 and ADC2) + * @arg ADC_EXT_TRIG_INJ_CONV_T3_CC4 Timer3 capture compare4 selected (for ADC1 and ADC2) + * @arg ADC_EXT_TRIG_INJ_CONV_T4_TRGO Timer4 TRGO event selected (for ADC1 and ADC2) + * @arg ADC_EXT_TRIG_INJ_CONV_EXT_INT15_TIM8_CC4 External interrupt line 15 or Timer8 + * capture compare4 event selected (for ADC1 and ADC2) + */ +void ADC_ConfigExternalTrigInjectedConv(ADC_Module* ADCx, uint32_t ADC_ExternalTrigInjecConv) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcExtInjTrig(ADC_ExternalTrigInjecConv)); + /* Get the old register value */ + tmpregister = ADCx->CTRL2; + /* Clear the old external event selection for injected group */ + tmpregister &= CTRL2_INJ_EXT_SEL_RESET; + /* Set the external event selection for injected group */ + tmpregister |= ADC_ExternalTrigInjecConv; + /* Store the new register value */ + ADCx->CTRL2 = tmpregister; +} + +/** + * @brief Enables or disables the ADCx injected channels conversion through + * external trigger + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the selected ADC external trigger start of + * injected conversion. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableExternalTrigInjectedConv(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected ADC external event selection for injected group */ + ADCx->CTRL2 |= CTRL2_INJ_EXT_TRIG_SET; + } + else + { + /* Disable the selected ADC external event selection for injected group */ + ADCx->CTRL2 &= CTRL2_INJ_EXT_TRIG_RESET; + } +} + +/** + * @brief Enables or disables the selected ADC start of the injected + * channels conversion. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the selected ADC software start injected conversion. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableSoftwareStartInjectedConv(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected ADC conversion for injected group on external event and start the selected + ADC injected conversion */ + ADCx->CTRL2 |= CTRL2_INJ_EXT_TRIG_JSWSTART_SET; + } + else + { + /* Disable the selected ADC conversion on external event for injected group and stop the selected + ADC injected conversion */ + ADCx->CTRL2 &= CTRL2_INJ_EXT_TRIG_JSWSTART_RESET; + } +} + +/** + * @brief Gets the selected ADC Software start injected conversion Status. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @return The new state of ADC software start injected conversion (SET or RESET). + */ +FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_Module* ADCx) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + /* Check the status of INJ_SWSTART bit */ + if ((ADCx->CTRL2 & CTRL2_INJ_SWSTART_SET) != (uint32_t)RESET) + { + /* INJ_SWSTART bit is set */ + bitstatus = SET; + } + else + { + /* INJ_SWSTART bit is reset */ + bitstatus = RESET; + } + /* Return the INJ_SWSTART bit status */ + return bitstatus; +} + +/** + * @brief Configures for the selected ADC injected channel its corresponding + * rank in the sequencer and its sample time. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_Channel the ADC channel to configure. + * This parameter can be one of the following values: + * @arg ADC_CH_0 ADC Channel0 selected + * @arg ADC_CH_1 ADC Channel1 selected + * @arg ADC_CH_2 ADC Channel2 selected + * @arg ADC_CH_3 ADC Channel3 selected + * @arg ADC_CH_4 ADC Channel4 selected + * @arg ADC_CH_5 ADC Channel5 selected + * @arg ADC_CH_6 ADC Channel6 selected + * @arg ADC_CH_7 ADC Channel7 selected + * @arg ADC_CH_8 ADC Channel8 selected + * @arg ADC_CH_9 ADC Channel9 selected + * @arg ADC_CH_10 ADC Channel10 selected + * @arg ADC_CH_11 ADC Channel11 selected + * @arg ADC_CH_12 ADC Channel12 selected + * @arg ADC_CH_13 ADC Channel13 selected + * @arg ADC_CH_14 ADC Channel14 selected + * @arg ADC_CH_15 ADC Channel15 selected + * @arg ADC_CH_16 ADC Channel16 selected + * @arg ADC_CH_17 ADC Channel17 selected + * @arg ADC_CH_18 ADC Channel18 selected + * @param Rank The rank in the injected group sequencer. This parameter must be between 1 and 4. + * @param ADC_SampleTime The sample time value to be set for the selected channel. + * This parameter can be one of the following values: + * @arg ADC_SAMP_TIME_1CYCLES5 Sample time equal to 1.5 cycles + * @arg ADC_SAMP_TIME_7CYCLES5 Sample time equal to 7.5 cycles + * @arg ADC_SAMP_TIME_13CYCLES5 Sample time equal to 13.5 cycles + * @arg ADC_SAMP_TIME_28CYCLES5 Sample time equal to 28.5 cycles + * @arg ADC_SAMP_TIME_41CYCLES5 Sample time equal to 41.5 cycles + * @arg ADC_SAMP_TIME_55CYCLES5 Sample time equal to 55.5 cycles + * @arg ADC_SAMP_TIME_71CYCLES5 Sample time equal to 71.5 cycles + * @arg ADC_SAMP_TIME_239CYCLES5 Sample time equal to 239.5 cycles + */ +void ADC_ConfigInjectedChannel(ADC_Module* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0, tmpreg3 = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcChannel(ADC_Channel)); + assert_param(IsAdcInjRankValid(Rank)); + assert_param(IsAdcSampleTime(ADC_SampleTime)); + + if (ADC_Channel == ADC_CH_18) + { + tmpreg1 = ADCx->SAMPT3; + tmpreg1 &= (~0x00000007); + tmpreg1 |= ADC_SampleTime; + ADCx->SAMPT3 = tmpreg1; + } + else if (ADC_Channel > ADC_CH_9) /* if ADC_CH_10 ... ADC_CH_17 is selected */ + { + /* Get the old register value */ + tmpreg1 = ADCx->SAMPT1; + /* Calculate the mask to clear */ + tmpreg2 = SAMPT1_SMP_SET << (3 * (ADC_Channel - 10)); + /* Clear the old channel sample time */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * (ADC_Channel - 10)); + /* Set the new channel sample time */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SAMPT1 = tmpreg1; + } + else /* ADC_Channel include in ADC_Channel_[0..9] */ + { + /* Get the old register value */ + tmpreg1 = ADCx->SAMPT2; + /* Calculate the mask to clear */ + tmpreg2 = SAMPT2_SMP_SET << (3 * ADC_Channel); + /* Clear the old channel sample time */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel); + /* Set the new channel sample time */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SAMPT2 = tmpreg1; + } + /* Rank configuration */ + /* Get the old register value */ + tmpreg1 = ADCx->JSEQ; + /* Get INJ_LEN value: Number = INJ_LEN+1 */ + tmpreg3 = (tmpreg1 & JSEQ_INJ_LEN_SET) >> 20; + /* Calculate the mask to clear: ((Rank-1)+(4-INJ_LEN-1)) */ + tmpreg2 = JSEQ_JSQ_SET << (5 * (uint8_t)((Rank + 3) - (tmpreg3 + 1))); + /* Clear the old JSQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set: ((Rank-1)+(4-INJ_LEN-1)) */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (uint8_t)((Rank + 3) - (tmpreg3 + 1))); + /* Set the JSQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->JSEQ = tmpreg1; +} + +/** + * @brief Configures the sequencer length for injected channels + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Length The sequencer length. + * This parameter must be a number between 1 to 4. + */ +void ADC_ConfigInjectedSequencerLength(ADC_Module* ADCx, uint8_t Length) +{ + uint32_t tmpreg1 = 0; + uint32_t tmpreg2 = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcInjLenValid(Length)); + + /* Get the old register value */ + tmpreg1 = ADCx->JSEQ; + /* Clear the old injected sequnence lenght INJ_LEN bits */ + tmpreg1 &= JSEQ_INJ_LEN_RESET; + /* Set the injected sequnence lenght INJ_LEN bits */ + tmpreg2 = Length - 1; + tmpreg1 |= tmpreg2 << 20; + /* Store the new register value */ + ADCx->JSEQ = tmpreg1; +} + +/** + * @brief Set the injected channels conversion value offset + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_InjectedChannel the ADC injected channel to set its offset. + * This parameter can be one of the following values: + * @arg ADC_INJ_CH_1 Injected Channel1 selected + * @arg ADC_INJ_CH_2 Injected Channel2 selected + * @arg ADC_INJ_CH_3 Injected Channel3 selected + * @arg ADC_INJ_CH_4 Injected Channel4 selected + * @param Offset the offset value for the selected ADC injected channel + * This parameter must be a 12bit value. + */ +void ADC_SetInjectedOffsetDat(ADC_Module* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcInjCh(ADC_InjectedChannel)); + assert_param(IsAdcOffsetValid(Offset)); + + tmp = (uint32_t)ADCx; + tmp += ADC_InjectedChannel; + + /* Set the selected injected channel data offset */ + *(__IO uint32_t*)tmp = (uint32_t)Offset; +} + +/** + * @brief Returns the ADC injected channel conversion result + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_InjectedChannel the converted ADC injected channel. + * This parameter can be one of the following values: + * @arg ADC_INJ_CH_1 Injected Channel1 selected + * @arg ADC_INJ_CH_2 Injected Channel2 selected + * @arg ADC_INJ_CH_3 Injected Channel3 selected + * @arg ADC_INJ_CH_4 Injected Channel4 selected + * @return The Data conversion value. + */ +uint16_t ADC_GetInjectedConversionDat(ADC_Module* ADCx, uint8_t ADC_InjectedChannel) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcInjCh(ADC_InjectedChannel)); + + tmp = (uint32_t)ADCx; + tmp += ADC_InjectedChannel + JDAT_OFFSET; + + /* Returns the selected injected channel conversion data value */ + return (uint16_t)(*(__IO uint32_t*)tmp); +} + +/** + * @brief Enables or disables the analog watchdog on single/all regular + * or injected channels + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_AnalogWatchdog the ADC analog watchdog configuration. + * This parameter can be one of the following values: + * @arg ADC_ANALOG_WTDG_SINGLEREG_ENABLE Analog watchdog on a single regular channel + * @arg ADC_ANALOG_WTDG_SINGLEINJEC_ENABLE Analog watchdog on a single injected channel + * @arg ADC_ANALOG_WTDG_SINGLEREG_OR_INJEC_ENABLE Analog watchdog on a single regular or injected channel + * @arg ADC_ANALOG_WTDG_ALLREG_ENABLE Analog watchdog on all regular channel + * @arg ADC_ANALOG_WTDG_ALLINJEC_ENABLE Analog watchdog on all injected channel + * @arg ADC_ANALOG_WTDG_ALLREG_ALLINJEC_ENABLE Analog watchdog on all regular and injected channels + * @arg ADC_ANALOG_WTDG_NONE No channel guarded by the analog watchdog + */ +void ADC_ConfigAnalogWatchdogWorkChannelType(ADC_Module* ADCx, uint32_t ADC_AnalogWatchdog) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcAnalogWatchdog(ADC_AnalogWatchdog)); + /* Get the old register value */ + tmpregister = ADCx->CTRL1; + /* Clear AWDEN, AWDENJ and AWDSGL bits */ + tmpregister &= CTRL1_AWDG_MODE_RESET; + /* Set the analog watchdog enable mode */ + tmpregister |= ADC_AnalogWatchdog; + /* Store the new register value */ + ADCx->CTRL1 = tmpregister; +} + +/** + * @brief Configures the high and low thresholds of the analog watchdog. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param HighThreshold the ADC analog watchdog High threshold value. + * This parameter must be a 12bit value. + * @param LowThreshold the ADC analog watchdog Low threshold value. + * This parameter must be a 12bit value. + */ +void ADC_ConfigAnalogWatchdogThresholds(ADC_Module* ADCx, uint16_t HighThreshold, uint16_t LowThreshold) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcValid(HighThreshold)); + assert_param(IsAdcValid(LowThreshold)); + /* Set the ADCx high threshold */ + ADCx->WDGHIGH = HighThreshold; + /* Set the ADCx low threshold */ + ADCx->WDGLOW = LowThreshold; +} + +/** + * @brief Configures the analog watchdog guarded single channel + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_Channel the ADC channel to configure for the analog watchdog. + * This parameter can be one of the following values: + * @arg ADC_CH_0 ADC Channel0 selected + * @arg ADC_CH_1 ADC Channel1 selected + * @arg ADC_CH_2 ADC Channel2 selected + * @arg ADC_CH_3 ADC Channel3 selected + * @arg ADC_CH_4 ADC Channel4 selected + * @arg ADC_CH_5 ADC Channel5 selected + * @arg ADC_CH_6 ADC Channel6 selected + * @arg ADC_CH_7 ADC Channel7 selected + * @arg ADC_CH_8 ADC Channel8 selected + * @arg ADC_CH_9 ADC Channel9 selected + * @arg ADC_CH_10 ADC Channel10 selected + * @arg ADC_CH_11 ADC Channel11 selected + * @arg ADC_CH_12 ADC Channel12 selected + * @arg ADC_CH_13 ADC Channel13 selected + * @arg ADC_CH_14 ADC Channel14 selected + * @arg ADC_CH_15 ADC Channel15 selected + * @arg ADC_CH_16 ADC Channel16 selected + * @arg ADC_CH_17 ADC Channel17 selected + * @arg ADC_CH_18 ADC Channel18 selected + */ +void ADC_ConfigAnalogWatchdogSingleChannel(ADC_Module* ADCx, uint8_t ADC_Channel) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcChannel(ADC_Channel)); + /* Get the old register value */ + tmpregister = ADCx->CTRL1; + /* Clear the Analog watchdog channel select bits */ + tmpregister &= CTRL1_AWDG_CH_RESET; + /* Set the Analog watchdog channel */ + tmpregister |= ADC_Channel; + /* Store the new register value */ + ADCx->CTRL1 = tmpregister; +} + +/** + * @brief Enables or disables the temperature sensor and Vrefint channel. + * @param Cmd new state of the temperature sensor. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableTempSensorVrefint(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the temperature sensor and Vrefint channel*/ + ADC1->CTRL2 |= CTRL2_TSVREFE_SET; + _EnVref1p2() + } + else + { + /* Disable the temperature sensor and Vrefint channel*/ + ADC1->CTRL2 &= CTRL2_TSVREFE_RESET; + _DisVref1p2() + } +} + +/** + * @brief Checks whether the specified ADC flag is set or not. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg ADC_FLAG_AWDG Analog watchdog flag + * @arg ADC_FLAG_ENDC End of conversion flag + * @arg ADC_FLAG_JENDC End of injected group conversion flag + * @arg ADC_FLAG_JSTR Start of injected group conversion flag + * @arg ADC_FLAG_STR Start of regular group conversion flag + * @return The new state of ADC_FLAG (SET or RESET). + */ +FlagStatus ADC_GetFlagStatus(ADC_Module* ADCx, uint8_t ADC_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcGetFlag(ADC_FLAG)); + /* Check the status of the specified ADC flag */ + if ((ADCx->STS & ADC_FLAG) != (uint8_t)RESET) + { + /* ADC_FLAG is set */ + bitstatus = SET; + } + else + { + /* ADC_FLAG is reset */ + bitstatus = RESET; + } + /* Return the ADC_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the ADCx's pending flags. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_FLAG specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg ADC_FLAG_AWDG Analog watchdog flag + * @arg ADC_FLAG_ENDC End of conversion flag + * @arg ADC_FLAG_JENDC End of injected group conversion flag + * @arg ADC_FLAG_JSTR Start of injected group conversion flag + * @arg ADC_FLAG_STR Start of regular group conversion flag + */ +void ADC_ClearFlag(ADC_Module* ADCx, uint8_t ADC_FLAG) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcClrFlag(ADC_FLAG)); + /* Clear the selected ADC flags */ + ADCx->STS = (~(uint32_t)ADC_FLAG & ADC_STS_RESERVE_MASK); +} + +/** + * @brief Checks whether the specified ADC interrupt has occurred or not. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_IT specifies the ADC interrupt source to check. + * This parameter can be one of the following values: + * @arg ADC_INT_ENDC End of conversion interrupt mask + * @arg ADC_INT_AWD Analog watchdog interrupt mask + * @arg ADC_INT_JENDC End of injected conversion interrupt mask + * @return The new state of ADC_IT (SET or RESET). + */ +INTStatus ADC_GetIntStatus(ADC_Module* ADCx, uint16_t ADC_IT) +{ + INTStatus bitstatus = RESET; + uint32_t itmask = 0, enablestatus = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcGetInt(ADC_IT)); + /* Get the ADC IT index */ + itmask = ADC_IT >> 8; + /* Get the ADC_IT enable bit status */ + enablestatus = (ADCx->CTRL1 & (uint8_t)ADC_IT); + /* Check the status of the specified ADC interrupt */ + if (((ADCx->STS & itmask) != (uint32_t)RESET) && enablestatus) + { + /* ADC_IT is set */ + bitstatus = SET; + } + else + { + /* ADC_IT is reset */ + bitstatus = RESET; + } + /* Return the ADC_IT status */ + return bitstatus; +} + +/** + * @brief Clears the ADCx's interrupt pending bits. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_IT specifies the ADC interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg ADC_INT_ENDC End of conversion interrupt mask + * @arg ADC_INT_AWD Analog watchdog interrupt mask + * @arg ADC_INT_JENDC End of injected conversion interrupt mask + */ +void ADC_ClearIntPendingBit(ADC_Module* ADCx, uint16_t ADC_IT) +{ + uint8_t itmask = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcInt(ADC_IT)); + /* Get the ADC IT index */ + itmask = (uint8_t)(ADC_IT >> 8); + /* Clear the selected ADC interrupt pending bits */ + ADCx->STS = (~(uint32_t)itmask & ADC_STS_RESERVE_MASK); +} + + +/** + * @brief Initializes the ADCx peripheral according to the specified parameters + * in the ADC_InitStructEx. + * @param ADCx where x can be 1, 2 to select the ADC peripheral. + * @param ADC_InitStructEx pointer to an ADC_InitTypeEx structure that contains + * the configuration information for the specified ADC peripheral. + */ +void ADC_InitEx(ADC_Module* ADCx, ADC_InitTypeEx* ADC_InitStructEx) +{ + uint32_t tmpregister = 0; + /*ADC_SAMPT3 samp time sele ,as sam 103 or 303 style*/ + if (ADC_InitStructEx->Samp303Style) + ADCx->SAMPT3 |= ADC_SAMPT3_SAMPSEL_MSK; + else + ADCx->SAMPT3 &= (~ADC_SAMPT3_SAMPSEL_MSK); + + /*intial ADC_CTRL3 once initiall config*/ + tmpregister = ADCx->CTRL3; + if (ADC_InitStructEx->VbatMinitEn) + { + tmpregister |= ADC_CTRL3_VABTMEN_MSK; + _EnVref1p2() + } + else + { + tmpregister &= (~ADC_CTRL3_VABTMEN_MSK); + _DisVref1p2() + } + + if (ADC_InitStructEx->DeepPowerModEn) + tmpregister |= ADC_CTRL3_DPWMOD_MSK; + else + tmpregister &= (~ADC_CTRL3_DPWMOD_MSK); + + if (ADC_InitStructEx->JendcIntEn) + tmpregister |= ADC_CTRL3_JENDCAIEN_MSK; + else + tmpregister &= (~ADC_CTRL3_JENDCAIEN_MSK); + + if (ADC_InitStructEx->EndcIntEn) + tmpregister |= ADC_CTRL3_ENDCAIEN_MSK; + else + tmpregister &= (~ADC_CTRL3_ENDCAIEN_MSK); + + if (ADC_InitStructEx->CalAtuoLoadEn) + tmpregister |= ADC_CTRL3_CALALD_MSK; + else + tmpregister &= (~ADC_CTRL3_CALALD_MSK); + + if (ADC_InitStructEx->DifModCal) + tmpregister |= ADC_CTRL3_CALDIF_MSK; + else + tmpregister &= (~ADC_CTRL3_CALDIF_MSK); + + tmpregister &= (~ADC_CTRL3_RES_MSK); + tmpregister |= ADC_InitStructEx->ResBit; + + tmpregister &= (~ADC_CTRL3_CKMOD_MSK); + if(ADC_InitStructEx->ClkMode==ADC_CTRL3_CKMOD_PLL) + tmpregister |= ADC_CTRL3_CKMOD_MSK; + + ADCx->CTRL3 = tmpregister; +} +/** + * @brief Configure differential channels enable. + * @param ADCx where x can be 1, 2 to select the ADC peripheral. + * @param DifChs differential channels,see @ADC_dif_sel_ch_definition. eg: ADC_DIFSEL_CHS_3|ADC_DIFSEL_CHS_4 + */ +void ADC_SetDifChs(ADC_Module* ADCx,uint32_t DifChs) +{ + ADCx->DIFSEL = DifChs; +} +/** + * @brief Checks whether the specified ADC flag is set or not. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_FLAG_NEW specifies the flag to check. + * This parameter can be one of the following values: + * @arg ADC_FLAG_RDY ADC ready flag + * @arg ADC_FLAG_PD_RDY ADC powerdown ready flag + * @return The new state of ADC_FLAG_NEW (SET or RESET). + */ +FlagStatus ADC_GetFlagStatusNew(ADC_Module* ADCx, uint8_t ADC_FLAG_NEW) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcGetFlag(ADC_FLAG_NEW)); + /* Check the status of the specified ADC flag */ + if ((ADCx->CTRL3 & ADC_FLAG_NEW) != (uint8_t)RESET) + { + /* ADC_FLAG_NEW is set */ + bitstatus = SET; + } + else + { + /* ADC_FLAG_NEW is reset */ + bitstatus = RESET; + } + /* Return the ADC_FLAG_NEW status */ + return bitstatus; +} +/** + * @brief Set Adc calibration bypass or enable. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param en enable bypass calibration. + * This parameter can be one of the following values: + * @arg true bypass calibration + * @arg false not bypass calibration + */ +void ADC_SetBypassCalibration(ADC_Module* ADCx, FunctionalState en) +{ + uint32_t tmpregister = 0; + + tmpregister = ADCx->CTRL3; + if (en) + tmpregister |= ADC_CTRL3_BPCAL_MSK; + else + tmpregister &= (~ADC_CTRL3_BPCAL_MSK); + ADCx->CTRL3 = tmpregister; +} +/** + * @brief Set Adc trans bits width. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ResultBitNum specifies num with adc trans width. + * This parameter can be one of the following values: + * @arg ADC_RST_BIT_12 12 bit trans + * @arg ADC_RST_BIT_10 10 bit trans + * @arg ADC_RST_BIT_8 8 bit trans + * @arg ADC_RESULT_BIT_6 6 bit trans + */ +void ADC_SetConvResultBitNum(ADC_Module* ADCx, uint32_t ResultBitNum) +{ + uint32_t tmpregister = 0; + + tmpregister = ADCx->CTRL3; + tmpregister &= 0xFFFFFFFC; + tmpregister |= ResultBitNum; + ADCx->CTRL3 = tmpregister; + return; +} + +/** + * @brief Set Adc Clock bits for AHB . + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + */ +void ADC_AHB_Clock_Mode_Config(ADC_Module* ADCx) +{ + ADCx->CTRL3 &= ADC_CLOCK_AHB; +} + +/** + * @brief Set Adc Clock bits for PLL . + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + */ +void ADC_PLL_Clock_Mode_Config(ADC_Module* ADCx) +{ + ADCx->CTRL3 |= ADC_CLOCK_PLL; +} + +/** + * @brief Configures the ADCHCLK prescaler. + * @param RCC_ADCHCLKPrescaler specifies the ADCHCLK prescaler. + * This parameter can be on of the following values: + * @arg RCC_ADCHCLK_DIV1 ADCHCLKPRE[3:0] = 0000, HCLK Clock Divided By 1 + * @arg RCC_ADCHCLK_DIV2 ADCHCLKPRE[3:0] = 0001, HCLK Clock Divided By 2 + * @arg RCC_ADCHCLK_DIV4 ADCHCLKPRE[3:0] = 0010, HCLK Clock Divided By 4 + * @arg RCC_ADCHCLK_DIV6 ADCHCLKPRE[3:0] = 0011, HCLK Clock Divided By 6 + * @arg RCC_ADCHCLK_DIV8 ADCHCLKPRE[3:0] = 0100, HCLK Clock Divided By 8 + * @arg RCC_ADCHCLK_DIV10 ADCHCLKPRE[3:0] = 0101, HCLK Clock Divided By 10 + * @arg RCC_ADCHCLK_DIV12 ADCHCLKPRE[3:0] = 0110, HCLK Clock Divided By 12 + * @arg RCC_ADCHCLK_DIV16 ADCHCLKPRE[3:0] = 0111, HCLK Clock Divided By 16 + * @arg RCC_ADCHCLK_DIV32 ADCHCLKPRE[3:0] = 1000, HCLK Clock Divided By 32 + * @arg RCC_ADCHCLK_DIV32 ADCHCLKPRE[3:0] = others, HCLK Clock Divided By 32 + + * @arg RCC_ADCPLLCLK_DISABLE ADCPLLCLKPRES[4:0] = 0xxxx, ADC Pll Clock Disable + * @arg RCC_ADCPLLCLK_DIV1 ADCPLLCLKPRES[4:0] = 10000, Pll Clock Divided By 1 + * @arg RCC_ADCPLLCLK_DIV2 ADCPLLCLKPRES[4:0] = 10001, Pll Clock Divided By 2 + * @arg RCC_ADCPLLCLK_DIV4 ADCPLLCLKPRES[4:0] = 10010, Pll Clock Divided By 4 + * @arg RCC_ADCPLLCLK_DIV6 ADCPLLCLKPRES[4:0] = 10011, Pll Clock Divided By 6 + * @arg RCC_ADCPLLCLK_DIV8 ADCPLLCLKPRES[4:0] = 10100, Pll Clock Divided By 8 + * @arg RCC_ADCPLLCLK_DIV10 ADCPLLCLKPRES[4:0] = 10101, Pll Clock Divided By 10 + * @arg RCC_ADCPLLCLK_DIV12 ADCPLLCLKPRES[4:0] = 10110, Pll Clock Divided By 12 + * @arg RCC_ADCPLLCLK_DIV16 ADCPLLCLKPRES[4:0] = 10111, Pll Clock Divided By 16 + * @arg RCC_ADCPLLCLK_DIV32 ADCPLLCLKPRES[4:0] = 11000, Pll Clock Divided By 32 + * @arg RCC_ADCPLLCLK_DIV64 ADCPLLCLKPRES[4:0] = 11001, Pll Clock Divided By 64 + * @arg RCC_ADCPLLCLK_DIV128 ADCPLLCLKPRES[4:0] = 11010, Pll Clock Divided By 128 + * @arg RCC_ADCPLLCLK_DIV256 ADCPLLCLKPRES[4:0] = 11011, Pll Clock Divided By 256 + * @arg RCC_ADCPLLCLK_DIV256 ADCPLLCLKPRES[4:0] = others, Pll Clock Divided By 256 + */ +void ADC_ConfigClk(ADC_CTRL3_CKMOD ADC_ClkMode, uint32_t RCC_ADCHCLKPrescaler) +{ + if(ADC_ClkMode==ADC_CTRL3_CKMOD_AHB){ + RCC_ConfigAdcPllClk(RCC_ADCPLLCLK_DIV1, DISABLE); + RCC_ConfigAdcHclk(RCC_ADCHCLKPrescaler); + ADC_AHB_Clock_Mode_Config(ADC1); + ADC_AHB_Clock_Mode_Config(ADC2); + }else{ + RCC_ConfigAdcPllClk(RCC_ADCHCLKPrescaler, ENABLE); + RCC_ConfigAdcHclk(RCC_ADCHCLK_DIV1); + ADC_PLL_Clock_Mode_Config(ADC1); + ADC_PLL_Clock_Mode_Config(ADC2); + } +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_bkp.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_bkp.c new file mode 100644 index 0000000000..a9c01a5f84 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_bkp.c @@ -0,0 +1,252 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_bkp.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_bkp.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup BKP + * @brief BKP driver modules + * @{ + */ + +/** @addtogroup BKP_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup BKP_Private_Defines + * @{ + */ + +/* ------------ BKP registers bit address in the alias region --------------- */ +#define BKP_OFFSET (BKP_BASE - PERIPH_BASE) + +/* --- CTRL Register ----*/ + +/* Alias word address of TP_ALEV bit */ +#define CTRL_OFFSET (BKP_OFFSET + 0x30) +#define TP_ALEV_BIT 0x01 +#define CTRL_TP_ALEV_BB (PERIPH_BB_BASE + (CTRL_OFFSET * 32) + (TP_ALEV_BIT * 4)) + +/* Alias word address of TP_EN bit */ +#define TP_EN_BIT 0x00 +#define CTRL_TP_EN_BB (PERIPH_BB_BASE + (CTRL_OFFSET * 32) + (TP_EN_BIT * 4)) + +/* --- CTRLSTS Register ---*/ + +/* Alias word address of TPINT_EN bit */ +#define CTRLSTS_OFFSET (BKP_OFFSET + 0x34) +#define TPINT_EN_BIT 0x02 +#define CTRLSTS_TPINT_EN_BB (PERIPH_BB_BASE + (CTRLSTS_OFFSET * 32) + (TPINT_EN_BIT * 4)) + +/* Alias word address of TINTF bit */ +#define TINTF_BIT 0x09 +#define CTRLSTS_TINTF_BB (PERIPH_BB_BASE + (CTRLSTS_OFFSET * 32) + (TINTF_BIT * 4)) + +/* Alias word address of TEF bit */ +#define TEF_BIT 0x08 +#define CTRLSTS_TEF_BB (PERIPH_BB_BASE + (CTRLSTS_OFFSET * 32) + (TEF_BIT * 4)) + + +/** + * @} + */ + +/** @addtogroup BKP_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup BKP_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup BKP_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup BKP_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the BKP peripheral registers to their default reset values. + */ +void BKP_DeInit(void) +{ + RCC_EnableBackupReset(ENABLE); + RCC_EnableBackupReset(DISABLE); +} + +/** + * @brief Configures the Tamper Pin active level. + * @param BKP_TamperPinLevel specifies the Tamper Pin active level. + * This parameter can be one of the following values: + * @arg BKP_TP_HIGH Tamper pin active on high level + * @arg BKP_TP_LOW Tamper pin active on low level + */ +void BKP_ConfigTPLevel(uint16_t BKP_TamperPinLevel) +{ + /* Check the parameters */ + assert_param(IS_BKP_TP_LEVEL(BKP_TamperPinLevel)); + *(__IO uint32_t*)CTRL_TP_ALEV_BB = BKP_TamperPinLevel; +} + +/** + * @brief Enables or disables the Tamper Pin activation. + * @param Cmd new state of the Tamper Pin activation. + * This parameter can be: ENABLE or DISABLE. + */ +void BKP_TPEnable(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)CTRL_TP_EN_BB = (uint32_t)Cmd; +} + +/** + * @brief Enables or disables the Tamper Pin Interrupt. + * @param Cmd new state of the Tamper Pin Interrupt. + * This parameter can be: ENABLE or DISABLE. + */ +void BKP_TPIntEnable(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)CTRLSTS_TPINT_EN_BB = (uint32_t)Cmd; +} + + +/** + * @brief Writes user data to the specified Data Backup Register. + * @param BKP_DAT specifies the Data Backup Register. + * This parameter can be BKP_DATx where x:[1, 42] + * @param Data data to write + */ +void BKP_WriteBkpData(uint16_t BKP_DAT, uint16_t Data) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_BKP_DAT(BKP_DAT)); + + tmp = (uint32_t)BKP_BASE; + tmp += BKP_DAT; + + *(__IO uint32_t*)tmp = Data; +} + +/** + * @brief Reads data from the specified Data Backup Register. + * @param BKP_DAT specifies the Data Backup Register. + * This parameter can be BKP_DATx where x:[1, 42] + * @return The content of the specified Data Backup Register + */ +uint16_t BKP_ReadBkpData(uint16_t BKP_DAT) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_BKP_DAT(BKP_DAT)); + + tmp = (uint32_t)BKP_BASE; + tmp += BKP_DAT; + + return (*(__IO uint16_t*)tmp); +} + +/** + * @brief Checks whether the Tamper Pin Event flag is set or not. + * @return The new state of the Tamper Pin Event flag (SET or RESET). + */ +FlagStatus BKP_GetTEFlag(void) +{ + return (FlagStatus)(*(__IO uint32_t*)CTRLSTS_TEF_BB); +} + +/** + * @brief Clears Tamper Pin Event pending flag. + */ +void BKP_ClrTEFlag(void) +{ + /* Set CTE bit to clear Tamper Pin Event flag */ + BKP->CTRLSTS |= BKP_CTRLSTS_CLRTE; +} + +/** + * @brief Checks whether the Tamper Pin Interrupt has occurred or not. + * @return The new state of the Tamper Pin Interrupt (SET or RESET). + */ +INTStatus BKP_GetTINTFlag(void) +{ + return (INTStatus)(*(__IO uint32_t*)CTRLSTS_TINTF_BB); +} + +/** + * @brief Clears Tamper Pin Interrupt pending bit. + */ +void BKP_ClrTINTFlag(void) +{ + /* Set CTI bit to clear Tamper Pin Interrupt pending bit */ + BKP->CTRLSTS |= BKP_CTRLSTS_CLRTINT; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_can.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_can.c new file mode 100644 index 0000000000..b2913176ea --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_can.c @@ -0,0 +1,1478 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_can.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_can.h" +#include "n32g4fr_rcc.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup CAN + * @brief CAN driver modules + * @{ + */ + +/** @addtogroup CAN_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CAN_Private_Defines + * @{ + */ + +/* CAN Master Control Register bits */ +#define MCTRL_DBGF ((uint32_t)0x00010000) /* Debug freeze */ +#define MCTRL_MRST ((uint32_t)0x00010000) /* software master reset */ + +/* CAN Mailbox Transmit Request */ +#define TMIDxR_TXRQ ((uint32_t)0x00000001) /* Transmit mailbox request */ + +/* CAN Filter Master Register bits */ +#define FMC_FINITM ((uint32_t)0x00000001) /* Filter init mode */ + +/* Time out for INAK bit */ +#define INIAK_TIMEOUT ((uint32_t)0x0000FFFF) +/* Time out for SLAK bit */ +#define SLPAK_TIMEOUT ((uint32_t)0x0000FFFF) + +/* Flags in TSTS register */ +#define CAN_FLAGS_TSTS ((uint32_t)0x08000000) +/* Flags in RFF1 register */ +#define CAN_FLAGS_RFF1 ((uint32_t)0x04000000) +/* Flags in RFF0 register */ +#define CAN_FLAGS_RFF0 ((uint32_t)0x02000000) +/* Flags in MSTS register */ +#define CAN_FLAGS_MSTS ((uint32_t)0x01000000) +/* Flags in ESTS register */ +#define CAN_FLAGS_ESTS ((uint32_t)0x00F00000) + +/* Mailboxes definition */ +#define CAN_TXMAILBOX_0 ((uint8_t)0x00) +#define CAN_TXMAILBOX_1 ((uint8_t)0x01) +#define CAN_TXMAILBOX_2 ((uint8_t)0x02) + +#define CAN_MODE_MASK ((uint32_t)0x00000003) +/** + * @} + */ + +/** @addtogroup CAN_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CAN_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CAN_Private_FunctionPrototypes + * @{ + */ + +static INTStatus CheckINTStatus(uint32_t CAN_Reg, uint32_t Int_Bit); + +/** + * @} + */ + +/** @addtogroup CAN_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the CAN peripheral registers to their default reset values. + * @param CANx where x can be 1 or 2 to select the CAN peripheral. + */ +void CAN_DeInit(CAN_Module* CANx) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + if (CANx == CAN1) + { + /* Enable CAN1 reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_CAN1, ENABLE); + /* Release CAN1 from reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_CAN1, DISABLE); + } + else + { + /* Enable CAN2 reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_CAN2, ENABLE); + /* Release CAN2 from reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_CAN2, DISABLE); + } +} + +/** + * @brief Initializes the CAN peripheral according to the specified + * parameters in the CAN_InitParam. + * @param CANx where x can be 1 or 2 to to select the CAN + * peripheral. + * @param CAN_InitParam pointer to a CAN_InitType structure that + * contains the configuration information for the + * CAN peripheral. + * @return Constant indicates initialization succeed which will be + * CAN_InitSTS_Failed or CAN_InitSTS_Success. + */ +uint8_t CAN_Init(CAN_Module* CANx, CAN_InitType* CAN_InitParam) +{ + uint8_t InitStatus = CAN_InitSTS_Failed; + uint32_t wait_ack = 0x00000000; + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitParam->TTCM)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitParam->ABOM)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitParam->AWKUM)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitParam->NART)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitParam->RFLM)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitParam->TXFP)); + assert_param(IS_CAN_MODE(CAN_InitParam->OperatingMode)); + assert_param(IS_CAN_RSJW(CAN_InitParam->RSJW)); + assert_param(IS_CAN_TBS1(CAN_InitParam->TBS1)); + assert_param(IS_CAN_TBS2(CAN_InitParam->TBS2)); + assert_param(IS_CAN_BAUDRATEPRESCALER(CAN_InitParam->BaudRatePrescaler)); + + /* Exit from sleep mode */ + CANx->MCTRL &= (~(uint32_t)CAN_MCTRL_SLPRQ); + + /* Request initialisation */ + CANx->MCTRL |= CAN_MCTRL_INIRQ; + + /* Wait the acknowledge */ + while (((CANx->MSTS & CAN_MSTS_INIAK) != CAN_MSTS_INIAK) && (wait_ack != INIAK_TIMEOUT)) + { + wait_ack++; + } + + /* Check acknowledge */ + if ((CANx->MSTS & CAN_MSTS_INIAK) != CAN_MSTS_INIAK) + { + InitStatus = CAN_InitSTS_Failed; + } + else + { + /* Set the time triggered communication mode */ + if (CAN_InitParam->TTCM == ENABLE) + { + CANx->MCTRL |= CAN_MCTRL_TTCM; + } + else + { + CANx->MCTRL &= ~(uint32_t)CAN_MCTRL_TTCM; + } + + /* Set the automatic bus-off management */ + if (CAN_InitParam->ABOM == ENABLE) + { + CANx->MCTRL |= CAN_MCTRL_ABOM; + } + else + { + CANx->MCTRL &= ~(uint32_t)CAN_MCTRL_ABOM; + } + + /* Set the automatic wake-up mode */ + if (CAN_InitParam->AWKUM == ENABLE) + { + CANx->MCTRL |= CAN_MCTRL_AWKUM; + } + else + { + CANx->MCTRL &= ~(uint32_t)CAN_MCTRL_AWKUM; + } + + /* Set the no automatic retransmission */ + if (CAN_InitParam->NART == ENABLE) + { + CANx->MCTRL |= CAN_MCTRL_NART; + } + else + { + CANx->MCTRL &= ~(uint32_t)CAN_MCTRL_NART; + } + + /* Set the receive DATFIFO locked mode */ + if (CAN_InitParam->RFLM == ENABLE) + { + CANx->MCTRL |= CAN_MCTRL_RFLM; + } + else + { + CANx->MCTRL &= ~(uint32_t)CAN_MCTRL_RFLM; + } + + /* Set the transmit DATFIFO priority */ + if (CAN_InitParam->TXFP == ENABLE) + { + CANx->MCTRL |= CAN_MCTRL_TXFP; + } + else + { + CANx->MCTRL &= ~(uint32_t)CAN_MCTRL_TXFP; + } + + /* Set the bit timing register */ + CANx->BTIM = (uint32_t)((uint32_t)CAN_InitParam->OperatingMode << 30) | ((uint32_t)CAN_InitParam->RSJW << 24) + | ((uint32_t)CAN_InitParam->TBS1 << 16) | ((uint32_t)CAN_InitParam->TBS2 << 20) + | ((uint32_t)CAN_InitParam->BaudRatePrescaler - 1); + + /* Request leave initialisation */ + CANx->MCTRL &= ~(uint32_t)CAN_MCTRL_INIRQ; + + /* Wait the acknowledge */ + wait_ack = 0; + + while (((CANx->MSTS & CAN_MSTS_INIAK) == CAN_MSTS_INIAK) && (wait_ack != INIAK_TIMEOUT)) + { + wait_ack++; + } + + /* ...and check acknowledged */ + if ((CANx->MSTS & CAN_MSTS_INIAK) == CAN_MSTS_INIAK) + { + InitStatus = CAN_InitSTS_Failed; + } + else + { + InitStatus = CAN_InitSTS_Success; + } + } + + /* At this step, return the status of initialization */ + return InitStatus; +} + +/** + * @brief Initializes the CAN1 peripheral according to the specified + * parameters in the CAN_InitFilterStruct. + * @param CAN_InitFilterStruct pointer to a CAN_FilterInitType + * structure that contains the configuration + * information. + */ +void CAN1_InitFilter(CAN_FilterInitType* CAN_InitFilterStruct) +{ + uint32_t filter_number_bit_pos = 0; + /* Check the parameters */ + assert_param(IS_CAN_FILTER_NUM(CAN_InitFilterStruct->Filter_Num)); + assert_param(IS_CAN_FILTER_MODE(CAN_InitFilterStruct->Filter_Mode)); + assert_param(IS_CAN_FILTER_SCALE(CAN_InitFilterStruct->Filter_Scale)); + assert_param(IS_CAN_FILTER_FIFO(CAN_InitFilterStruct->Filter_FIFOAssignment)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitFilterStruct->Filter_Act)); + + filter_number_bit_pos = ((uint32_t)1) << CAN_InitFilterStruct->Filter_Num; + + /* Initialisation mode for the filter */ + CAN1->FMC |= FMC_FINITM; + + /* Filter Deactivation */ + CAN1->FA1 &= ~(uint32_t)filter_number_bit_pos; + + /* Filter Scale */ + if (CAN_InitFilterStruct->Filter_Scale == CAN_Filter_16bitScale) + { + /* 16-bit scale for the filter */ + CAN1->FS1 &= ~(uint32_t)filter_number_bit_pos; + + /* First 16-bit identifier and First 16-bit mask */ + /* Or First 16-bit identifier and Second 16-bit identifier */ + CAN1->sFilterRegister[CAN_InitFilterStruct->Filter_Num].FR1 = + ((0x0000FFFF & (uint32_t)CAN_InitFilterStruct->FilterMask_LowId) << 16) + | (0x0000FFFF & (uint32_t)CAN_InitFilterStruct->Filter_LowId); + + /* Second 16-bit identifier and Second 16-bit mask */ + /* Or Third 16-bit identifier and Fourth 16-bit identifier */ + CAN1->sFilterRegister[CAN_InitFilterStruct->Filter_Num].FR2 = + ((0x0000FFFF & (uint32_t)CAN_InitFilterStruct->FilterMask_HighId) << 16) + | (0x0000FFFF & (uint32_t)CAN_InitFilterStruct->Filter_HighId); + } + + if (CAN_InitFilterStruct->Filter_Scale == CAN_Filter_32bitScale) + { + /* 32-bit scale for the filter */ + CAN1->FS1 |= filter_number_bit_pos; + /* 32-bit identifier or First 32-bit identifier */ + CAN1->sFilterRegister[CAN_InitFilterStruct->Filter_Num].FR1 = + ((0x0000FFFF & (uint32_t)CAN_InitFilterStruct->Filter_HighId) << 16) + | (0x0000FFFF & (uint32_t)CAN_InitFilterStruct->Filter_LowId); + /* 32-bit mask or Second 32-bit identifier */ + CAN1->sFilterRegister[CAN_InitFilterStruct->Filter_Num].FR2 = + ((0x0000FFFF & (uint32_t)CAN_InitFilterStruct->FilterMask_HighId) << 16) + | (0x0000FFFF & (uint32_t)CAN_InitFilterStruct->FilterMask_LowId); + } + + /* Filter Mode */ + if (CAN_InitFilterStruct->Filter_Mode == CAN_Filter_IdMaskMode) + { + /*Id/Mask mode for the filter*/ + CAN1->FM1 &= ~(uint32_t)filter_number_bit_pos; + } + else /* CAN_InitFilterStruct->Filter_Mode == CAN_Filter_IdListMode */ + { + /*Identifier list mode for the filter*/ + CAN1->FM1 |= (uint32_t)filter_number_bit_pos; + } + + /* Filter DATFIFO assignment */ + if (CAN_InitFilterStruct->Filter_FIFOAssignment == CAN_Filter_FIFO0) + { + /* DATFIFO 0 assignation for the filter */ + CAN1->FFA1 &= ~(uint32_t)filter_number_bit_pos; + } + + if (CAN_InitFilterStruct->Filter_FIFOAssignment == CAN_Filter_FIFO1) + { + /* DATFIFO 1 assignation for the filter */ + CAN1->FFA1 |= (uint32_t)filter_number_bit_pos; + } + + /* Filter activation */ + if (CAN_InitFilterStruct->Filter_Act == ENABLE) + { + CAN1->FA1 |= filter_number_bit_pos; + } + + /* Leave the initialisation mode for the filter */ + CAN1->FMC &= ~FMC_FINITM; +} + +/** + * @brief Initializes the CAN2 peripheral according to the specified + * parameters in the CAN_InitFilterStruct. + * @param CAN_InitFilterStruct pointer to a CAN_FilterInitType + * structure that contains the configuration + * information. + */ +void CAN2_InitFilter(CAN_FilterInitType* CAN_InitFilterStruct) +{ + uint32_t filter_number_bit_pos = 0; + /* Check the parameters */ + assert_param(IS_CAN_FILTER_NUM(CAN_InitFilterStruct->Filter_Num)); + assert_param(IS_CAN_FILTER_MODE(CAN_InitFilterStruct->Filter_Mode)); + assert_param(IS_CAN_FILTER_SCALE(CAN_InitFilterStruct->Filter_Scale)); + assert_param(IS_CAN_FILTER_FIFO(CAN_InitFilterStruct->Filter_FIFOAssignment)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitFilterStruct->Filter_Act)); + + filter_number_bit_pos = ((uint32_t)1) << CAN_InitFilterStruct->Filter_Num; + + /* Initialisation mode for the filter */ + CAN2->FMC |= FMC_FINITM; + + /* Filter Deactivation */ + CAN2->FA1 &= ~(uint32_t)filter_number_bit_pos; + + /* Filter Scale */ + if (CAN_InitFilterStruct->Filter_Scale == CAN_Filter_16bitScale) + { + /* 16-bit scale for the filter */ + CAN2->FS1 &= ~(uint32_t)filter_number_bit_pos; + + /* First 16-bit identifier and First 16-bit mask */ + /* Or First 16-bit identifier and Second 16-bit identifier */ + CAN2->sFilterRegister[CAN_InitFilterStruct->Filter_Num].FR1 = + ((0x0000FFFF & (uint32_t)CAN_InitFilterStruct->FilterMask_LowId) << 16) + | (0x0000FFFF & (uint32_t)CAN_InitFilterStruct->Filter_LowId); + + /* Second 16-bit identifier and Second 16-bit mask */ + /* Or Third 16-bit identifier and Fourth 16-bit identifier */ + CAN2->sFilterRegister[CAN_InitFilterStruct->Filter_Num].FR2 = + ((0x0000FFFF & (uint32_t)CAN_InitFilterStruct->FilterMask_HighId) << 16) + | (0x0000FFFF & (uint32_t)CAN_InitFilterStruct->Filter_HighId); + } + + if (CAN_InitFilterStruct->Filter_Scale == CAN_Filter_32bitScale) + { + /* 32-bit scale for the filter */ + CAN2->FS1 |= filter_number_bit_pos; + /* 32-bit identifier or First 32-bit identifier */ + CAN2->sFilterRegister[CAN_InitFilterStruct->Filter_Num].FR1 = + ((0x0000FFFF & (uint32_t)CAN_InitFilterStruct->Filter_HighId) << 16) + | (0x0000FFFF & (uint32_t)CAN_InitFilterStruct->Filter_LowId); + /* 32-bit mask or Second 32-bit identifier */ + CAN2->sFilterRegister[CAN_InitFilterStruct->Filter_Num].FR2 = + ((0x0000FFFF & (uint32_t)CAN_InitFilterStruct->FilterMask_HighId) << 16) + | (0x0000FFFF & (uint32_t)CAN_InitFilterStruct->FilterMask_LowId); + } + + /* Filter Mode */ + if (CAN_InitFilterStruct->Filter_Mode == CAN_Filter_IdMaskMode) + { + /*Id/Mask mode for the filter*/ + CAN2->FM1 &= ~(uint32_t)filter_number_bit_pos; + } + else /* CAN_InitFilterStruct->Filter_Mode == CAN_Filter_IdListMode */ + { + /*Identifier list mode for the filter*/ + CAN2->FM1 |= (uint32_t)filter_number_bit_pos; + } + + /* Filter DATFIFO assignment */ + if (CAN_InitFilterStruct->Filter_FIFOAssignment == CAN_Filter_FIFO0) + { + /* DATFIFO 0 assignation for the filter */ + CAN2->FFA1 &= ~(uint32_t)filter_number_bit_pos; + } + + if (CAN_InitFilterStruct->Filter_FIFOAssignment == CAN_Filter_FIFO1) + { + /* DATFIFO 1 assignation for the filter */ + CAN2->FFA1 |= (uint32_t)filter_number_bit_pos; + } + + /* Filter activation */ + if (CAN_InitFilterStruct->Filter_Act == ENABLE) + { + CAN2->FA1 |= filter_number_bit_pos; + } + + /* Leave the initialisation mode for the filter */ + CAN2->FMC &= ~FMC_FINITM; +} + +/** + * @brief Fills each CAN_InitParam member with its default value. + * @param CAN_InitParam pointer to a CAN_InitType structure which + * will be initialized. + */ +void CAN_InitStruct(CAN_InitType* CAN_InitParam) +{ + /* Reset CAN init structure parameters values */ + + /* Initialize the time triggered communication mode */ + CAN_InitParam->TTCM = DISABLE; + + /* Initialize the automatic bus-off management */ + CAN_InitParam->ABOM = DISABLE; + + /* Initialize the automatic wake-up mode */ + CAN_InitParam->AWKUM = DISABLE; + + /* Initialize the no automatic retransmission */ + CAN_InitParam->NART = DISABLE; + + /* Initialize the receive DATFIFO locked mode */ + CAN_InitParam->RFLM = DISABLE; + + /* Initialize the transmit DATFIFO priority */ + CAN_InitParam->TXFP = DISABLE; + + /* Initialize the OperatingMode member */ + CAN_InitParam->OperatingMode = CAN_Normal_Mode; + + /* Initialize the RSJW member */ + CAN_InitParam->RSJW = CAN_RSJW_1tq; + + /* Initialize the TBS1 member */ + CAN_InitParam->TBS1 = CAN_TBS1_4tq; + + /* Initialize the TBS2 member */ + CAN_InitParam->TBS2 = CAN_TBS2_3tq; + + /* Initialize the BaudRatePrescaler member */ + CAN_InitParam->BaudRatePrescaler = 1; +} + +/** + * @brief Enables or disables the DBG Freeze for CAN. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param Cmd new state of the CAN peripheral. This parameter can + * be: ENABLE or DISABLE. + */ +void CAN_DebugFreeze(CAN_Module* CANx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable Debug Freeze */ + CANx->MCTRL |= MCTRL_DBGF; + } + else + { + /* Disable Debug Freeze */ + CANx->MCTRL &= ~MCTRL_DBGF; + } +} + +/** + * @brief Enables or disabes the CAN Time TriggerOperation communication mode. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param Cmd Mode new state , can be one of @ref FunctionalState. + * @note when enabled, Time stamp (TIME[15:0]) value is sent in the last + * two data bytes of the 8-byte message: TIME[7:0] in data byte 6 + * and TIME[15:8] in data byte 7 + * @note DLC must be programmed as 8 in order Time Stamp (2 bytes) to be + * sent over the CAN bus. + */ +void CAN_EnTTComMode(CAN_Module* CANx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the TTCM mode */ + CANx->MCTRL |= CAN_MCTRL_TTCM; + + /* Set TGT bits */ + CANx->sTxMailBox[0].TMDT |= ((uint32_t)CAN_TMDT0_TGT); + CANx->sTxMailBox[1].TMDT |= ((uint32_t)CAN_TMDT1_TGT); + CANx->sTxMailBox[2].TMDT |= ((uint32_t)CAN_TMDT2_TGT); + } + else + { + /* Disable the TTCM mode */ + CANx->MCTRL &= (uint32_t)(~(uint32_t)CAN_MCTRL_TTCM); + + /* Reset TGT bits */ + CANx->sTxMailBox[0].TMDT &= ((uint32_t)~CAN_TMDT0_TGT); + CANx->sTxMailBox[1].TMDT &= ((uint32_t)~CAN_TMDT1_TGT); + CANx->sTxMailBox[2].TMDT &= ((uint32_t)~CAN_TMDT2_TGT); + } +} +/** + * @brief Initiates the transmission of a message. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param TxMessage pointer to a structure which contains CAN Id, CAN + * DLC and CAN data. + * @return The number of the mailbox that is used for transmission + * or CAN_TxSTS_NoMailBox if there is no empty mailbox. + */ +uint8_t CAN_TransmitMessage(CAN_Module* CANx, CanTxMessage* TxMessage) +{ + uint8_t transmit_mailbox = 0; + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_ID(TxMessage->IDE)); + assert_param(IS_CAN_RTRQ(TxMessage->RTR)); + assert_param(IS_CAN_DLC(TxMessage->DLC)); + + /* Select one empty transmit mailbox */ + if ((CANx->TSTS & CAN_TSTS_TMEM0) == CAN_TSTS_TMEM0) + { + transmit_mailbox = 0; + } + else if ((CANx->TSTS & CAN_TSTS_TMEM1) == CAN_TSTS_TMEM1) + { + transmit_mailbox = 1; + } + else if ((CANx->TSTS & CAN_TSTS_TMEM2) == CAN_TSTS_TMEM2) + { + transmit_mailbox = 2; + } + else + { + transmit_mailbox = CAN_TxSTS_NoMailBox; + } + + if (transmit_mailbox != CAN_TxSTS_NoMailBox) + { + /* Set up the Id */ + CANx->sTxMailBox[transmit_mailbox].TMI &= TMIDxR_TXRQ; + if (TxMessage->IDE == CAN_Standard_Id) + { + assert_param(IS_CAN_STDID(TxMessage->StdId)); + CANx->sTxMailBox[transmit_mailbox].TMI |= ((TxMessage->StdId << 21) | TxMessage->RTR); + } + else + { + assert_param(IS_CAN_EXTID(TxMessage->ExtId)); + CANx->sTxMailBox[transmit_mailbox].TMI |= ((TxMessage->ExtId << 3) | TxMessage->IDE | TxMessage->RTR); + } + + /* Set up the DLC */ + TxMessage->DLC &= (uint8_t)0x0000000F; + CANx->sTxMailBox[transmit_mailbox].TMDT &= (uint32_t)0xFFFFFFF0; + CANx->sTxMailBox[transmit_mailbox].TMDT |= TxMessage->DLC; + + /* Set up the data field */ + CANx->sTxMailBox[transmit_mailbox].TMDL = + (((uint32_t)TxMessage->Data[3] << 24) | ((uint32_t)TxMessage->Data[2] << 16) + | ((uint32_t)TxMessage->Data[1] << 8) | ((uint32_t)TxMessage->Data[0])); + CANx->sTxMailBox[transmit_mailbox].TMDH = + (((uint32_t)TxMessage->Data[7] << 24) | ((uint32_t)TxMessage->Data[6] << 16) + | ((uint32_t)TxMessage->Data[5] << 8) | ((uint32_t)TxMessage->Data[4])); + /* Request transmission */ + CANx->sTxMailBox[transmit_mailbox].TMI |= TMIDxR_TXRQ; + } + return transmit_mailbox; +} + +/** + * @brief Checks the transmission of a message. + * @param CANx where x can be 1 or 2 to to select the + * CAN peripheral. + * @param TransmitMailbox the number of the mailbox that is used for + * transmission. + * @return CAN_TxSTS_Ok if the CAN driver transmits the message, CAN_TxSTS_Failed + * in an other case. + */ +uint8_t CAN_TransmitSTS(CAN_Module* CANx, uint8_t TransmitMailbox) +{ + uint32_t state = 0; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_TRANSMITMAILBOX(TransmitMailbox)); + + switch (TransmitMailbox) + { + case (CAN_TXMAILBOX_0): + state = CANx->TSTS & (CAN_TSTS_RQCPM0 | CAN_TSTS_TXOKM0 | CAN_TSTS_TMEM0); + break; + case (CAN_TXMAILBOX_1): + state = CANx->TSTS & (CAN_TSTS_RQCPM1 | CAN_TSTS_TXOKM1 | CAN_TSTS_TMEM1); + break; + case (CAN_TXMAILBOX_2): + state = CANx->TSTS & (CAN_TSTS_RQCPM2 | CAN_TSTS_TXOKM2 | CAN_TSTS_TMEM2); + break; + default: + state = CAN_TxSTS_Failed; + break; + } + switch (state) + { + /* transmit pending */ + case (0x0): + state = CAN_TxSTS_Pending; + break; + /* transmit failed */ + case (CAN_TSTS_RQCPM0 | CAN_TSTS_TMEM0): + state = CAN_TxSTS_Failed; + break; + case (CAN_TSTS_RQCPM1 | CAN_TSTS_TMEM1): + state = CAN_TxSTS_Failed; + break; + case (CAN_TSTS_RQCPM2 | CAN_TSTS_TMEM2): + state = CAN_TxSTS_Failed; + break; + /* transmit succeeded */ + case (CAN_TSTS_RQCPM0 | CAN_TSTS_TXOKM0 | CAN_TSTS_TMEM0): + state = CAN_TxSTS_Ok; + break; + case (CAN_TSTS_RQCPM1 | CAN_TSTS_TXOKM1 | CAN_TSTS_TMEM1): + state = CAN_TxSTS_Ok; + break; + case (CAN_TSTS_RQCPM2 | CAN_TSTS_TXOKM2 | CAN_TSTS_TMEM2): + state = CAN_TxSTS_Ok; + break; + default: + state = CAN_TxSTS_Failed; + break; + } + return (uint8_t)state; +} + +/** + * @brief Cancels a transmit request. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param Mailbox Mailbox number. + */ +void CAN_CancelTransmitMessage(CAN_Module* CANx, uint8_t Mailbox) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_TRANSMITMAILBOX(Mailbox)); + /* abort transmission */ + switch (Mailbox) + { + case (CAN_TXMAILBOX_0): + CANx->TSTS |= CAN_TSTS_ABRQM0; + break; + case (CAN_TXMAILBOX_1): + CANx->TSTS |= CAN_TSTS_ABRQM1; + break; + case (CAN_TXMAILBOX_2): + CANx->TSTS |= CAN_TSTS_ABRQM2; + break; + default: + break; + } +} + +/** + * @brief Receives a message. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param FIFONum Receive DATFIFO number, CAN_FIFO0 or CAN_FIFO1. + * @param RxMessage pointer to a structure receive message which contains + * CAN Id, CAN DLC, CAN datas and FMI number. + */ +void CAN_ReceiveMessage(CAN_Module* CANx, uint8_t FIFONum, CanRxMessage* RxMessage) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_FIFO(FIFONum)); + /* Get the Id */ + RxMessage->IDE = (uint8_t)0x04 & CANx->sFIFOMailBox[FIFONum].RMI; + if (RxMessage->IDE == CAN_Standard_Id) + { + RxMessage->StdId = (uint32_t)0x000007FF & (CANx->sFIFOMailBox[FIFONum].RMI >> 21); + } + else + { + RxMessage->ExtId = (uint32_t)0x1FFFFFFF & (CANx->sFIFOMailBox[FIFONum].RMI >> 3); + } + + RxMessage->RTR = (uint8_t)0x02 & CANx->sFIFOMailBox[FIFONum].RMI; + /* Get the DLC */ + RxMessage->DLC = (uint8_t)0x0F & CANx->sFIFOMailBox[FIFONum].RMDT; + /* Get the FMI */ + RxMessage->FMI = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONum].RMDT >> 8); + /* Get the data field */ + RxMessage->Data[0] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONum].RMDL; + RxMessage->Data[1] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONum].RMDL >> 8); + RxMessage->Data[2] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONum].RMDL >> 16); + RxMessage->Data[3] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONum].RMDL >> 24); + RxMessage->Data[4] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONum].RMDH; + RxMessage->Data[5] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONum].RMDH >> 8); + RxMessage->Data[6] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONum].RMDH >> 16); + RxMessage->Data[7] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONum].RMDH >> 24); + /* Release the DATFIFO */ + /* Release FIFO0 */ + if (FIFONum == CAN_FIFO0) + { + CANx->RFF0 |= CAN_RFF0_RFFOM0; + } + /* Release FIFO1 */ + else /* FIFONum == CAN_FIFO1 */ + { + CANx->RFF1 |= CAN_RFF1_RFFOM1; + } +} + +/** + * @brief Releases the specified DATFIFO. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param FIFONum DATFIFO to release, CAN_FIFO0 or CAN_FIFO1. + */ +void CAN_ReleaseFIFO(CAN_Module* CANx, uint8_t FIFONum) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_FIFO(FIFONum)); + /* Release FIFO0 */ + if (FIFONum == CAN_FIFO0) + { + CANx->RFF0 |= CAN_RFF0_RFFOM0; + } + /* Release FIFO1 */ + else /* FIFONum == CAN_FIFO1 */ + { + CANx->RFF1 |= CAN_RFF1_RFFOM1; + } +} + +/** + * @brief Returns the number of pending messages. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param FIFONum Receive DATFIFO number, CAN_FIFO0 or CAN_FIFO1. + * @return NbMessage : which is the number of pending message. + */ +uint8_t CAN_PendingMessage(CAN_Module* CANx, uint8_t FIFONum) +{ + uint8_t message_pending = 0; + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_FIFO(FIFONum)); + if (FIFONum == CAN_FIFO0) + { + message_pending = (uint8_t)(CANx->RFF0 & (uint32_t)0x03); + } + else if (FIFONum == CAN_FIFO1) + { + message_pending = (uint8_t)(CANx->RFF1 & (uint32_t)0x03); + } + else + { + message_pending = 0; + } + return message_pending; +} + +/** + * @brief Select the CAN Operation mode. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param CAN_OperatingMode CAN Operating Mode. This parameter can be one + * of @ref CAN_operating_mode enumeration. + * @return status of the requested mode which can be + * - CAN_ModeSTS_Failed CAN failed entering the specific mode + * - CAN_ModeSTS_Success CAN Succeed entering the specific mode + + */ +uint8_t CAN_OperatingModeReq(CAN_Module* CANx, uint8_t CAN_OperatingMode) +{ + uint8_t status = CAN_ModeSTS_Failed; + + /* Timeout for INAK or also for SLAK bits*/ + uint32_t timeout = INIAK_TIMEOUT; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_OPERATING_MODE(CAN_OperatingMode)); + + if (CAN_OperatingMode == CAN_Operating_InitMode) + { + /* Request initialisation */ + CANx->MCTRL = (uint32_t)((CANx->MCTRL & (uint32_t)(~(uint32_t)CAN_MCTRL_SLPRQ)) | CAN_MCTRL_INIRQ); + + /* Wait the acknowledge */ + while (((CANx->MSTS & CAN_MODE_MASK) != CAN_MSTS_INIAK) && (timeout != 0)) + { + timeout--; + } + if ((CANx->MSTS & CAN_MODE_MASK) != CAN_MSTS_INIAK) + { + status = CAN_ModeSTS_Failed; + } + else + { + status = CAN_ModeSTS_Success; + } + } + else if (CAN_OperatingMode == CAN_Operating_NormalMode) + { + /* Request leave initialisation and sleep mode and enter Normal mode */ + CANx->MCTRL &= (uint32_t)(~(CAN_MCTRL_SLPRQ | CAN_MCTRL_INIRQ)); + + /* Wait the acknowledge */ + while (((CANx->MSTS & CAN_MODE_MASK) != 0) && (timeout != 0)) + { + timeout--; + } + if ((CANx->MSTS & CAN_MODE_MASK) != 0) + { + status = CAN_ModeSTS_Failed; + } + else + { + status = CAN_ModeSTS_Success; + } + } + else if (CAN_OperatingMode == CAN_Operating_SleepMode) + { + /* Request Sleep mode */ + CANx->MCTRL = (uint32_t)((CANx->MCTRL & (uint32_t)(~(uint32_t)CAN_MCTRL_INIRQ)) | CAN_MCTRL_SLPRQ); + + /* Wait the acknowledge */ + while (((CANx->MSTS & CAN_MODE_MASK) != CAN_MSTS_SLPAK) && (timeout != 0)) + { + timeout--; + } + if ((CANx->MSTS & CAN_MODE_MASK) != CAN_MSTS_SLPAK) + { + status = CAN_ModeSTS_Failed; + } + else + { + status = CAN_ModeSTS_Success; + } + } + else + { + status = CAN_ModeSTS_Failed; + } + + return (uint8_t)status; +} + +/** + * @brief Enters the low power mode. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @return status: CAN_SLEEP_Ok if sleep entered, CAN_SLEEP_Failed in an + * other case. + */ +uint8_t CAN_EnterSleep(CAN_Module* CANx) +{ + uint8_t sleepstatus = CAN_SLEEP_Failed; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + /* Request Sleep mode */ + CANx->MCTRL = (((CANx->MCTRL) & (uint32_t)(~(uint32_t)CAN_MCTRL_INIRQ)) | CAN_MCTRL_SLPRQ); + + /* Sleep mode status */ + if ((CANx->MSTS & (CAN_MSTS_SLPAK | CAN_MSTS_INIAK)) == CAN_MSTS_SLPAK) + { + /* Sleep mode not entered */ + sleepstatus = CAN_SLEEP_Ok; + } + /* return sleep mode status */ + return (uint8_t)sleepstatus; +} + +/** + * @brief Wakes the CAN up. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @return status: CAN_WKU_Ok if sleep mode left, CAN_WKU_Failed in an + * other case. + */ +uint8_t CAN_WakeUp(CAN_Module* CANx) +{ + uint32_t wait_slak = SLPAK_TIMEOUT; + uint8_t wakeupstatus = CAN_WKU_Failed; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + /* Wake up request */ + CANx->MCTRL &= ~(uint32_t)CAN_MCTRL_SLPRQ; + + /* Sleep mode status */ + while (((CANx->MSTS & CAN_MSTS_SLPAK) == CAN_MSTS_SLPAK) && (wait_slak != 0x00)) + { + wait_slak--; + } + if ((CANx->MSTS & CAN_MSTS_SLPAK) != CAN_MSTS_SLPAK) + { + /* wake up done : Sleep mode exited */ + wakeupstatus = CAN_WKU_Ok; + } + /* return wakeup status */ + return (uint8_t)wakeupstatus; +} + +/** + * @brief Returns the CANx's last error code (LEC). + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @return CAN_ErrorCode: specifies the Error code : + * - CAN_ERRORCODE_NoErr No Error + * - CAN_ERRORCODE_StuffErr Stuff Error + * - CAN_ERRORCODE_FormErr Form Error + * - CAN_ERRORCODE_ACKErr Acknowledgment Error + * - CAN_ERRORCODE_BitRecessiveErr Bit Recessive Error + * - CAN_ERRORCODE_BitDominantErr Bit Dominant Error + * - CAN_ERRORCODE_CRCErr CRC Error + * - CAN_ERRORCODE_SoftwareSetErr Software Set Error + */ + +uint8_t CAN_GetLastErrCode(CAN_Module* CANx) +{ + uint8_t errorcode = 0; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + /* Get the error code*/ + errorcode = (((uint8_t)CANx->ESTS) & (uint8_t)CAN_ESTS_LEC); + + /* Return the error code*/ + return errorcode; +} +/** + * @brief Returns the CANx Receive Error Counter (REC). + * @note In case of an error during reception, this counter is incremented + * by 1 or by 8 depending on the error condition as defined by the CAN + * standard. After every successful reception, the counter is + * decremented by 1 or reset to 120 if its value was higher than 128. + * When the counter value exceeds 127, the CAN controller enters the + * error passive state. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @return CAN Receive Error Counter. + */ +uint8_t CAN_GetReceiveErrCounter(CAN_Module* CANx) +{ + uint8_t counter = 0; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + /* Get the Receive Error Counter*/ + counter = (uint8_t)((CANx->ESTS & CAN_ESTS_RXEC) >> 24); + + /* Return the Receive Error Counter*/ + return counter; +} + +/** + * @brief Returns the LSB of the 9-bit CANx Transmit Error Counter(TEC). + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @return LSB of the 9-bit CAN Transmit Error Counter. + */ +uint8_t CAN_GetLSBTransmitErrCounter(CAN_Module* CANx) +{ + uint8_t counter = 0; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + /* Get the LSB of the 9-bit CANx Transmit Error Counter(TEC) */ + counter = (uint8_t)((CANx->ESTS & CAN_ESTS_TXEC) >> 16); + + /* Return the LSB of the 9-bit CANx Transmit Error Counter(TEC) */ + return counter; +} + +/** + * @brief Enables or disables the specified CANx interrupts. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param CAN_INT specifies the CAN interrupt sources to be enabled or disabled. + * This parameter can be: + * - CAN_INT_TME, + * - CAN_INT_FMP0, + * - CAN_INT_FF0, + * - CAN_INT_FOV0, + * - CAN_INT_FMP1, + * - CAN_INT_FF1, + * - CAN_INT_FOV1, + * - CAN_INT_EWG, + * - CAN_INT_EPV, + * - CAN_INT_LEC, + * - CAN_INT_ERR, + * - CAN_INT_WKU or + * - CAN_INT_SLK. + * @param Cmd new state of the CAN interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void CAN_INTConfig(CAN_Module* CANx, uint32_t CAN_INT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_INT(CAN_INT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected CANx interrupt */ + CANx->INTE |= CAN_INT; + } + else + { + /* Disable the selected CANx interrupt */ + CANx->INTE &= ~CAN_INT; + } +} +/** + * @brief Checks whether the specified CAN flag is set or not. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param CAN_FLAG specifies the flag to check. + * This parameter can be one of the following flags: + * - CAN_FLAG_EWGFL + * - CAN_FLAG_EPVFL + * - CAN_FLAG_BOFFL + * - CAN_FLAG_RQCPM0 + * - CAN_FLAG_RQCPM1 + * - CAN_FLAG_RQCPM2 + * - CAN_FLAG_FFMP1 + * - CAN_FLAG_FFULL1 + * - CAN_FLAG_FFOVR1 + * - CAN_FLAG_FFMP0 + * - CAN_FLAG_FFULL0 + * - CAN_FLAG_FFOVR0 + * - CAN_FLAG_WKU + * - CAN_FLAG_SLAK + * - CAN_FLAG_LEC + * @return The new state of CAN_FLAG (SET or RESET). + */ +FlagStatus CAN_GetFlagSTS(CAN_Module* CANx, uint32_t CAN_FLAG) +{ + FlagStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_GET_FLAG(CAN_FLAG)); + + if ((CAN_FLAG & CAN_FLAGS_ESTS) != (uint32_t)RESET) + { + /* Check the status of the specified CAN flag */ + if ((CANx->ESTS & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + /* CAN_FLAG is set */ + bitstatus = SET; + } + else + { + /* CAN_FLAG is reset */ + bitstatus = RESET; + } + } + else if ((CAN_FLAG & CAN_FLAGS_MSTS) != (uint32_t)RESET) + { + /* Check the status of the specified CAN flag */ + if ((CANx->MSTS & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + /* CAN_FLAG is set */ + bitstatus = SET; + } + else + { + /* CAN_FLAG is reset */ + bitstatus = RESET; + } + } + else if ((CAN_FLAG & CAN_FLAGS_TSTS) != (uint32_t)RESET) + { + /* Check the status of the specified CAN flag */ + if ((CANx->TSTS & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + /* CAN_FLAG is set */ + bitstatus = SET; + } + else + { + /* CAN_FLAG is reset */ + bitstatus = RESET; + } + } + else if ((CAN_FLAG & CAN_FLAGS_RFF0) != (uint32_t)RESET) + { + /* Check the status of the specified CAN flag */ + if ((CANx->RFF0 & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + /* CAN_FLAG is set */ + bitstatus = SET; + } + else + { + /* CAN_FLAG is reset */ + bitstatus = RESET; + } + } + else /* If(CAN_FLAG & CAN_FLAGS_RFF1 != (uint32_t)RESET) */ + { + /* Check the status of the specified CAN flag */ + if ((uint32_t)(CANx->RFF1 & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + /* CAN_FLAG is set */ + bitstatus = SET; + } + else + { + /* CAN_FLAG is reset */ + bitstatus = RESET; + } + } + /* Return the CAN_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the CAN's pending flags. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param CAN_FLAG specifies the flag to clear. + * This parameter can be one of the following flags: + * - CAN_FLAG_RQCPM0 + * - CAN_FLAG_RQCPM1 + * - CAN_FLAG_RQCPM2 + * - CAN_FLAG_FFULL1 + * - CAN_FLAG_FFOVR1 + * - CAN_FLAG_FFULL0 + * - CAN_FLAG_FFOVR0 + * - CAN_FLAG_WKU + * - CAN_FLAG_SLAK + * - CAN_FLAG_LEC + */ +void CAN_ClearFlag(CAN_Module* CANx, uint32_t CAN_FLAG) +{ + uint32_t flagtmp = 0; + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_CLEAR_FLAG(CAN_FLAG)); + + if (CAN_FLAG == CAN_FLAG_LEC) /* ESTS register */ + { + /* Clear the selected CAN flags */ + CANx->ESTS = (uint32_t)RESET; + } + else /* MSTS or TSTS or RFF0 or RFF1 */ + { + flagtmp = CAN_FLAG & 0x000FFFFF; + + if ((CAN_FLAG & CAN_FLAGS_RFF0) != (uint32_t)RESET) + { + /* Receive Flags */ + CANx->RFF0 = (uint32_t)(flagtmp); + } + else if ((CAN_FLAG & CAN_FLAGS_RFF1) != (uint32_t)RESET) + { + /* Receive Flags */ + CANx->RFF1 = (uint32_t)(flagtmp); + } + else if ((CAN_FLAG & CAN_FLAGS_TSTS) != (uint32_t)RESET) + { + /* Transmit Flags */ + CANx->TSTS = (uint32_t)(flagtmp); + } + else /* If((CAN_FLAG & CAN_FLAGS_MSTS)!=(uint32_t)RESET) */ + { + /* Operating mode Flags */ + CANx->MSTS = (uint32_t)(flagtmp); + } + } +} + +/** + * @brief Checks whether the specified CANx interrupt has occurred or not. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param CAN_INT specifies the CAN interrupt source to check. + * This parameter can be one of the following flags: + * - CAN_INT_TME + * - CAN_INT_FMP0 + * - CAN_INT_FF0 + * - CAN_INT_FOV0 + * - CAN_INT_FMP1 + * - CAN_INT_FF1 + * - CAN_INT_FOV1 + * - CAN_INT_WKU + * - CAN_INT_SLK + * - CAN_INT_EWG + * - CAN_INT_EPV + * - CAN_INT_BOF + * - CAN_INT_LEC + * - CAN_INT_ERR + * @return The current state of CAN_INT (SET or RESET). + */ +INTStatus CAN_GetIntStatus(CAN_Module* CANx, uint32_t CAN_INT) +{ + INTStatus itstatus = RESET; + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_INT(CAN_INT)); + + /* check the enable interrupt bit */ + if ((CANx->INTE & CAN_INT) != RESET) + { + /* in case the Interrupt is enabled, .... */ + switch (CAN_INT) + { + case CAN_INT_TME: + /* Check CAN_TSTS_RQCPx bits */ + itstatus = CheckINTStatus(CANx->TSTS, CAN_TSTS_RQCPM0 | CAN_TSTS_RQCPM1 | CAN_TSTS_RQCPM2); + break; + case CAN_INT_FMP0: + /* Check CAN_RFF0_FFMP0 bit */ + itstatus = CheckINTStatus(CANx->RFF0, CAN_RFF0_FFMP0); + break; + case CAN_INT_FF0: + /* Check CAN_RFF0_FFULL0 bit */ + itstatus = CheckINTStatus(CANx->RFF0, CAN_RFF0_FFULL0); + break; + case CAN_INT_FOV0: + /* Check CAN_RFF0_FFOVR0 bit */ + itstatus = CheckINTStatus(CANx->RFF0, CAN_RFF0_FFOVR0); + break; + case CAN_INT_FMP1: + /* Check CAN_RFF1_FFMP1 bit */ + itstatus = CheckINTStatus(CANx->RFF1, CAN_RFF1_FFMP1); + break; + case CAN_INT_FF1: + /* Check CAN_RFF1_FFULL1 bit */ + itstatus = CheckINTStatus(CANx->RFF1, CAN_RFF1_FFULL1); + break; + case CAN_INT_FOV1: + /* Check CAN_RFF1_FFOVR1 bit */ + itstatus = CheckINTStatus(CANx->RFF1, CAN_RFF1_FFOVR1); + break; + case CAN_INT_WKU: + /* Check CAN_MSTS_WKUINT bit */ + itstatus = CheckINTStatus(CANx->MSTS, CAN_MSTS_WKUINT); + break; + case CAN_INT_SLK: + /* Check CAN_MSTS_SLAKINT bit */ + itstatus = CheckINTStatus(CANx->MSTS, CAN_MSTS_SLAKINT); + break; + case CAN_INT_EWG: + /* Check CAN_ESTS_EWGFL bit */ + itstatus = CheckINTStatus(CANx->ESTS, CAN_ESTS_EWGFL); + break; + case CAN_INT_EPV: + /* Check CAN_ESTS_EPVFL bit */ + itstatus = CheckINTStatus(CANx->ESTS, CAN_ESTS_EPVFL); + break; + case CAN_INT_BOF: + /* Check CAN_ESTS_BOFFL bit */ + itstatus = CheckINTStatus(CANx->ESTS, CAN_ESTS_BOFFL); + break; + case CAN_INT_LEC: + /* Check CAN_ESTS_LEC bit */ + itstatus = CheckINTStatus(CANx->ESTS, CAN_ESTS_LEC); + break; + case CAN_INT_ERR: + /* Check CAN_MSTS_ERRINT bit */ + itstatus = CheckINTStatus(CANx->MSTS, CAN_MSTS_ERRINT); + break; + default: + /* in case of error, return RESET */ + itstatus = RESET; + break; + } + } + else + { + /* in case the Interrupt is not enabled, return RESET */ + itstatus = RESET; + } + + /* Return the CAN_INT status */ + return itstatus; +} + +/** + * @brief Clears the CANx's interrupt pending bits. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param CAN_INT specifies the interrupt pending bit to clear. + * - CAN_INT_TME + * - CAN_INT_FF0 + * - CAN_INT_FOV0 + * - CAN_INT_FF1 + * - CAN_INT_FOV1 + * - CAN_INT_WKU + * - CAN_INT_SLK + * - CAN_INT_EWG + * - CAN_INT_EPV + * - CAN_INT_BOF + * - CAN_INT_LEC + * - CAN_INT_ERR + */ +void CAN_ClearINTPendingBit(CAN_Module* CANx, uint32_t CAN_INT) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_CLEAR_INT(CAN_INT)); + + switch (CAN_INT) + { + case CAN_INT_TME: + /* Clear CAN_TSTS_RQCPx (rc_w1)*/ + CANx->TSTS = CAN_TSTS_RQCPM0 | CAN_TSTS_RQCPM1 | CAN_TSTS_RQCPM2; + break; + case CAN_INT_FF0: + /* Clear CAN_RFF0_FFULL0 (rc_w1)*/ + CANx->RFF0 = CAN_RFF0_FFULL0; + break; + case CAN_INT_FOV0: + /* Clear CAN_RFF0_FFOVR0 (rc_w1)*/ + CANx->RFF0 = CAN_RFF0_FFOVR0; + break; + case CAN_INT_FF1: + /* Clear CAN_RFF1_FFULL1 (rc_w1)*/ + CANx->RFF1 = CAN_RFF1_FFULL1; + break; + case CAN_INT_FOV1: + /* Clear CAN_RFF1_FFOVR1 (rc_w1)*/ + CANx->RFF1 = CAN_RFF1_FFOVR1; + break; + case CAN_INT_WKU: + /* Clear CAN_MSTS_WKUINT (rc_w1)*/ + CANx->MSTS = CAN_MSTS_WKUINT; + break; + case CAN_INT_SLK: + /* Clear CAN_MSTS_SLAKINT (rc_w1)*/ + CANx->MSTS = CAN_MSTS_SLAKINT; + break; + case CAN_INT_EWG: + /* Clear CAN_MSTS_ERRINT (rc_w1) */ + CANx->MSTS = CAN_MSTS_ERRINT; + /* Note : the corresponding Flag is cleared by hardware depending + of the CAN Bus status*/ + break; + case CAN_INT_EPV: + /* Clear CAN_MSTS_ERRINT (rc_w1) */ + CANx->MSTS = CAN_MSTS_ERRINT; + /* Note : the corresponding Flag is cleared by hardware depending + of the CAN Bus status*/ + break; + case CAN_INT_BOF: + /* Clear CAN_MSTS_ERRINT (rc_w1) */ + CANx->MSTS = CAN_MSTS_ERRINT; + /* Note : the corresponding Flag is cleared by hardware depending + of the CAN Bus status*/ + break; + case CAN_INT_LEC: + /* Clear LEC bits */ + CANx->ESTS = RESET; + /* Clear CAN_MSTS_ERRINT (rc_w1) */ + CANx->MSTS = CAN_MSTS_ERRINT; + break; + case CAN_INT_ERR: + /*Clear LEC bits */ + CANx->ESTS = RESET; + /* Clear CAN_MSTS_ERRINT (rc_w1) */ + CANx->MSTS = CAN_MSTS_ERRINT; + /* Note : BOFF, EPVF and EWGF Flags are cleared by hardware depending + of the CAN Bus status*/ + break; + default: + break; + } +} + +/** + * @brief Checks whether the CAN interrupt has occurred or not. + * @param CAN_Reg specifies the CAN interrupt register to check. + * @param Int_Bit specifies the interrupt source bit to check. + * @return The new state of the CAN Interrupt (SET or RESET). + */ +static INTStatus CheckINTStatus(uint32_t CAN_Reg, uint32_t Int_Bit) +{ + INTStatus pendingbitstatus = RESET; + + if ((CAN_Reg & Int_Bit) != (uint32_t)RESET) + { + /* CAN_INT is set */ + pendingbitstatus = SET; + } + else + { + /* CAN_INT is reset */ + pendingbitstatus = RESET; + } + return pendingbitstatus; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_crc.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_crc.c new file mode 100644 index 0000000000..bc03ec0390 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_crc.c @@ -0,0 +1,228 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_crc.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_crc.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup CRC + * @brief CRC driver modules + * @{ + */ + +/** @addtogroup CRC_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CRC_Private_Defines + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CRC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CRC_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CRC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CRC_Private_Functions + * @{ + */ + +/** + * @brief Resets the CRC Data register (DAT). + */ +void CRC32_ResetCrc(void) +{ + /* Reset CRC generator */ + CRC->CRC32CTRL = CRC32_CTRL_RESET; +} + +/** + * @brief Computes the 32-bit CRC of a given data word(32-bit). + * @param Data data word(32-bit) to compute its CRC + * @return 32-bit CRC + */ +uint32_t CRC32_CalcCrc(uint32_t Data) +{ + CRC->CRC32DAT = Data; + + return (CRC->CRC32DAT); +} + +/** + * @brief Computes the 32-bit CRC of a given buffer of data word(32-bit). + * @param pBuffer pointer to the buffer containing the data to be computed + * @param BufferLength length of the buffer to be computed + * @return 32-bit CRC + */ +uint32_t CRC32_CalcBufCrc(uint32_t pBuffer[], uint32_t BufferLength) +{ + uint32_t index = 0; + + for (index = 0; index < BufferLength; index++) + { + CRC->CRC32DAT = pBuffer[index]; + } + return (CRC->CRC32DAT); +} + +/** + * @brief Returns the current CRC value. + * @return 32-bit CRC + */ +uint32_t CRC32_GetCrc(void) +{ + return (CRC->CRC32DAT); +} + +/** + * @brief Stores a 8-bit data in the Independent Data(ID) register. + * @param IDValue 8-bit value to be stored in the ID register + */ +void CRC32_SetIDat(uint8_t IDValue) +{ + CRC->CRC32IDAT = IDValue; +} + +/** + * @brief Returns the 8-bit data stored in the Independent Data(ID) register + * @return 8-bit value of the ID register + */ +uint8_t CRC32_GetIDat(void) +{ + return (CRC->CRC32IDAT); +} + +// CRC16 add +void __CRC16_SetLittleEndianFmt(void) +{ + CRC->CRC16CTRL = CRC16_CTRL_LITTLE | CRC->CRC16CTRL; +} +void __CRC16_SetBigEndianFmt(void) +{ + CRC->CRC16CTRL = CRC16_CTRL_BIG & CRC->CRC16CTRL; +} +void __CRC16_SetCleanEnable(void) +{ + CRC->CRC16CTRL = CRC16_CTRL_RESET | CRC->CRC16CTRL; +} +void __CRC16_SetCleanDisable(void) +{ + CRC->CRC16CTRL = CRC16_CTRL_NO_RESET & CRC->CRC16CTRL; +} + +uint16_t __CRC16_CalcCrc(uint8_t Data) +{ + CRC->CRC16DAT = Data; + return (CRC->CRC16D); +} + +void __CRC16_SetCrc(uint8_t Data) +{ + CRC->CRC16DAT = Data; +} + +uint16_t __CRC16_GetCrc(void) +{ + return (CRC->CRC16D); +} + +void __CRC16_SetLRC(uint8_t Data) +{ + CRC->LRC = Data; +} + +uint8_t __CRC16_GetLRC(void) +{ + return (CRC->LRC); +} + +uint16_t CRC16_CalcBufCrc(uint8_t pBuffer[], uint32_t BufferLength) +{ + uint32_t index = 0; + + CRC->CRC16D = 0x00; + // CRC16_SetCleanEnable(); + for (index = 0; index < BufferLength; index++) + { + CRC->CRC16DAT = pBuffer[index]; + } + return (CRC->CRC16D); +} + +uint16_t CRC16_CalcCRC(uint8_t Data) +{ + CRC->CRC16DAT = Data; + + return (CRC->CRC16D); +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_dac.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_dac.c new file mode 100644 index 0000000000..925adbd46e --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_dac.c @@ -0,0 +1,425 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_dac.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_dac.h" +#include "n32g4fr_rcc.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DAC + * @brief DAC driver modules + * @{ + */ + +/** @addtogroup DAC_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DAC_Private_Defines + * @{ + */ + +/* CTRL register Mask */ +#define CTRL_CLEAR_MASK ((uint32_t)0x00000FFE) + +/* DAC Dual Channels SWTRIG masks */ +#define DUAL_SWTRIG_SET ((uint32_t)0x00000003) +#define DUAL_SWTRIG_RESET ((uint32_t)0xFFFFFFFC) + +/* DCH registers offsets */ +#define DR12CH1_OFFSET ((uint32_t)0x00000008) +#define DR12CH2_OFFSET ((uint32_t)0x00000014) +#define DR12DCH_OFFSET ((uint32_t)0x00000020) + +/* DATO register offset */ +#define DATO1_OFFSET ((uint32_t)0x0000002C) +/** + * @} + */ + +/** @addtogroup DAC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DAC_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DAC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DAC_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the DAC peripheral registers to their default reset values. + */ +void DAC_DeInit(void) +{ + /* Enable DAC reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_DAC, ENABLE); + /* Release DAC from reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_DAC, DISABLE); +} + +/** + * @brief Initializes the DAC peripheral according to the specified + * parameters in the DAC_InitStruct. + * @param DAC_Channel the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_CHANNEL_1 DAC Channel1 selected + * @arg DAC_CHANNEL_2 DAC Channel2 selected + * @param DAC_InitStruct pointer to a DAC_InitType structure that + * contains the configuration information for the specified DAC channel. + */ +void DAC_Init(uint32_t DAC_Channel, DAC_InitType* DAC_InitStruct) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0; + /* Check the DAC parameters */ + assert_param(IS_DAC_TRIGGER(DAC_InitStruct->Trigger)); + assert_param(IS_DAC_GENERATE_WAVE(DAC_InitStruct->WaveGen)); + assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(DAC_InitStruct->LfsrUnMaskTriAmp)); + assert_param(IS_DAC_OUTPUT_BUFFER_STATE(DAC_InitStruct->BufferOutput)); + /*---------------------------- DAC CTRL Configuration --------------------------*/ + /* Get the DAC CTRL value */ + tmpreg1 = DAC->CTRL; + /* Clear BOFFx, TENx, TSELx, WAVEx and MAMPx bits */ + tmpreg1 &= ~(CTRL_CLEAR_MASK << DAC_Channel); + /* Configure for the selected DAC channel: buffer output, trigger, wave generation, + mask/amplitude for wave generation */ + /* Set TSELx and TENx bits according to Trigger value */ + /* Set WAVEx bits according to WaveGen value */ + /* Set MAMPx bits according to LfsrUnMaskTriAmp value */ + /* Set BOFFx bit according to BufferOutput value */ + tmpreg2 = (DAC_InitStruct->Trigger | DAC_InitStruct->WaveGen | DAC_InitStruct->LfsrUnMaskTriAmp + | DAC_InitStruct->BufferOutput); + /* Calculate CTRL register value depending on DAC_Channel */ + tmpreg1 |= tmpreg2 << DAC_Channel; + /* Write to DAC CTRL */ + DAC->CTRL = tmpreg1; +} + +/** + * @brief Fills each DAC_InitStruct member with its default value. + * @param DAC_InitStruct pointer to a DAC_InitType structure which will + * be initialized. + */ +void DAC_ClearStruct(DAC_InitType* DAC_InitStruct) +{ + /*--------------- Reset DAC init structure parameters values -----------------*/ + /* Initialize the Trigger member */ + DAC_InitStruct->Trigger = DAC_TRG_NONE; + /* Initialize the WaveGen member */ + DAC_InitStruct->WaveGen = DAC_WAVEGEN_NONE; + /* Initialize the LfsrUnMaskTriAmp member */ + DAC_InitStruct->LfsrUnMaskTriAmp = DAC_UNMASK_LFSRBIT0; + /* Initialize the BufferOutput member */ + DAC_InitStruct->BufferOutput = DAC_BUFFOUTPUT_ENABLE; +} + +/** + * @brief Enables or disables the specified DAC channel. + * @param DAC_Channel the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_CHANNEL_1 DAC Channel1 selected + * @arg DAC_CHANNEL_2 DAC Channel2 selected + * @param Cmd new state of the DAC channel. + * This parameter can be: ENABLE or DISABLE. + */ +void DAC_Enable(uint32_t DAC_Channel, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected DAC channel */ + DAC->CTRL |= (DAC_CTRL_CH1EN << DAC_Channel); + } + else + { + /* Disable the selected DAC channel */ + DAC->CTRL &= ~(DAC_CTRL_CH1EN << DAC_Channel); + } +} + +/** + * @brief Enables or disables the specified DAC channel DMA request. + * @param DAC_Channel the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_CHANNEL_1 DAC Channel1 selected + * @arg DAC_CHANNEL_2 DAC Channel2 selected + * @param Cmd new state of the selected DAC channel DMA request. + * This parameter can be: ENABLE or DISABLE. + */ +void DAC_DmaEnable(uint32_t DAC_Channel, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected DAC channel DMA request */ + DAC->CTRL |= (DAC_CTRL_DMA1EN << DAC_Channel); + } + else + { + /* Disable the selected DAC channel DMA request */ + DAC->CTRL &= ~(DAC_CTRL_DMA1EN << DAC_Channel); + } +} + +/** + * @brief Enables or disables the selected DAC channel software trigger. + * @param DAC_Channel the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_CHANNEL_1 DAC Channel1 selected + * @arg DAC_CHANNEL_2 DAC Channel2 selected + * @param Cmd new state of the selected DAC channel software trigger. + * This parameter can be: ENABLE or DISABLE. + */ +void DAC_SoftTrgEnable(uint32_t DAC_Channel, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable software trigger for the selected DAC channel */ + DAC->SOTTR |= (uint32_t)DAC_SOTTR_TR1EN << (DAC_Channel >> 4); + } + else + { + /* Disable software trigger for the selected DAC channel */ + DAC->SOTTR &= ~((uint32_t)DAC_SOTTR_TR1EN << (DAC_Channel >> 4)); + } +} + +/** + * @brief Enables or disables simultaneously the two DAC channels software + * triggers. + * @param Cmd new state of the DAC channels software triggers. + * This parameter can be: ENABLE or DISABLE. + */ +void DAC_DualSoftwareTrgEnable(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable software trigger for both DAC channels */ + DAC->SOTTR |= DUAL_SWTRIG_SET; + } + else + { + /* Disable software trigger for both DAC channels */ + DAC->SOTTR &= DUAL_SWTRIG_RESET; + } +} + +/** + * @brief Enables or disables the selected DAC channel wave generation. + * @param DAC_Channel the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_CHANNEL_1 DAC Channel1 selected + * @arg DAC_CHANNEL_2 DAC Channel2 selected + * @param DAC_Wave Specifies the wave type to enable or disable. + * This parameter can be one of the following values: + * @arg DAC_WAVE_NOISE noise wave generation + * @arg DAC_WAVE_TRIANGLE triangle wave generation + * @param Cmd new state of the selected DAC channel wave generation. + * This parameter can be: ENABLE or DISABLE. + */ +void DAC_WaveGenerationEnable(uint32_t DAC_Channel, uint32_t DAC_Wave, FunctionalState Cmd) +{ + /* Check the parameters */ + __IO uint32_t tmp = 0; + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_DAC_WAVE(DAC_Wave)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + tmp=DAC->CTRL; + tmp&=~(3<<(DAC_Channel+6)); + if (Cmd != DISABLE) + { + /* Enable the selected wave generation for the selected DAC channel */ + tmp |= DAC_Wave << DAC_Channel; + } + else + { + /* Disable the selected wave generation for the selected DAC channel */ + tmp &=~(3<<(DAC_Channel+6)); + } + DAC->CTRL = tmp; +} + +/** + * @brief Set the specified data holding register value for DAC channel1. + * @param DAC_Align Specifies the data alignment for DAC channel1. + * This parameter can be one of the following values: + * @arg DAC_ALIGN_R_8BIT 8bit right data alignment selected + * @arg DAC_ALIGN_L_12BIT 12bit left data alignment selected + * @arg DAC_ALIGN_R_12BIT 12bit right data alignment selected + * @param Data Data to be loaded in the selected data holding register. + */ +void DAC_SetCh1Data(uint32_t DAC_Align, uint16_t Data) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_ALIGN(DAC_Align)); + assert_param(IS_DAC_DATA(Data)); + + tmp = (uint32_t)DAC_BASE; + tmp += DR12CH1_OFFSET + DAC_Align; + + /* Set the DAC channel1 selected data holding register */ + *(__IO uint32_t*)tmp = Data; +} + +/** + * @brief Set the specified data holding register value for DAC channel2. + * @param DAC_Align Specifies the data alignment for DAC channel2. + * This parameter can be one of the following values: + * @arg DAC_ALIGN_R_8BIT 8bit right data alignment selected + * @arg DAC_ALIGN_L_12BIT 12bit left data alignment selected + * @arg DAC_ALIGN_R_12BIT 12bit right data alignment selected + * @param Data Data to be loaded in the selected data holding register. + */ +void DAC_SetCh2Data(uint32_t DAC_Align, uint16_t Data) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_ALIGN(DAC_Align)); + assert_param(IS_DAC_DATA(Data)); + + tmp = (uint32_t)DAC_BASE; + tmp += DR12CH2_OFFSET + DAC_Align; + + /* Set the DAC channel2 selected data holding register */ + *(__IO uint32_t*)tmp = Data; +} + +/** + * @brief Set the specified data holding register value for dual channel + * DAC. + * @param DAC_Align Specifies the data alignment for dual channel DAC. + * This parameter can be one of the following values: + * @arg DAC_ALIGN_R_8BIT 8bit right data alignment selected + * @arg DAC_ALIGN_L_12BIT 12bit left data alignment selected + * @arg DAC_ALIGN_R_12BIT 12bit right data alignment selected + * @param Data2 Data for DAC Channel2 to be loaded in the selected data + * holding register. + * @param Data1 Data for DAC Channel1 to be loaded in the selected data + * holding register. + */ +void DAC_SetDualChData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1) +{ + uint32_t data = 0, tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_ALIGN(DAC_Align)); + assert_param(IS_DAC_DATA(Data1)); + assert_param(IS_DAC_DATA(Data2)); + + /* Calculate and set dual DAC data holding register value */ + if (DAC_Align == DAC_ALIGN_R_8BIT) + { + data = ((uint32_t)Data2 << 8) | Data1; + } + else + { + data = ((uint32_t)Data2 << 16) | Data1; + } + + tmp = (uint32_t)DAC_BASE; + tmp += DR12DCH_OFFSET + DAC_Align; + + /* Set the dual DAC selected data holding register */ + *(__IO uint32_t*)tmp = data; +} + +/** + * @brief Returns the last data output value of the selected DAC channel. + * @param DAC_Channel the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_CHANNEL_1 DAC Channel1 selected + * @arg DAC_CHANNEL_2 DAC Channel2 selected + * @return The selected DAC channel data output value. + */ +uint16_t DAC_GetOutputDataVal(uint32_t DAC_Channel) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + + tmp = (uint32_t)DAC_BASE; + tmp += DATO1_OFFSET + ((uint32_t)DAC_Channel >> 2); + + /* Returns the DAC channel data output register value */ + return (uint16_t)(*(__IO uint32_t*)tmp); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_dbg.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_dbg.c new file mode 100644 index 0000000000..3d47cefffc --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_dbg.c @@ -0,0 +1,264 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_dbg.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_dbg.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DBG + * @brief DBG driver modules + * @{ + */ + +/** @addtogroup DBGMCU_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DBGMCU_Private_Defines + * @{ + */ + +#define IDCODE_DEVID_MASK ((uint32_t)0x00000FFF) +/** + * @} + */ + +/** @addtogroup DBGMCU_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DBGMCU_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DBGMCU_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DBGMCU_Private_Functions + * @{ + */ + +/** + * @brief Returns the UCID. + * @return UCID + */ + +void GetUCID(uint8_t *UCIDbuf) +{ + uint8_t num = 0; + uint32_t* ucid_addr = (uint32_t*)0; + uint32_t temp = 0; + + if (0xFFFFFFFF == *(uint32_t*)(0x1FFFF260)) + { + ucid_addr = (uint32_t*)UCID_BASE; + } + else + { + ucid_addr = (uint32_t*)(0x1FFFF260); + } + + for (num = 0; num < UCID_LENGTH;) + { + temp = *(__IO uint32_t*)(ucid_addr++); + UCIDbuf[num++] = (temp & 0xFF); + UCIDbuf[num++] = (temp & 0xFF00) >> 8; + UCIDbuf[num++] = (temp & 0xFF0000) >> 16; + UCIDbuf[num++] = (temp & 0xFF000000) >> 24; + } +} + +/** + * @brief Returns the UID. + * @return UID + */ + +void GetUID(uint8_t *UIDbuf) +{ + uint8_t num = 0; + uint32_t* uid_addr = (uint32_t*)0; + uint32_t temp = 0; + + if (0xFFFFFFFF == *(uint32_t*)(0x1FFFF270)) + { + uid_addr = (uint32_t*)UID_BASE; + } + else + { + uid_addr = (uint32_t*)(0x1FFFF270); + } + + for (num = 0; num < UID_LENGTH;) + { + temp = *(__IO uint32_t*)(uid_addr++); + UIDbuf[num++] = (temp & 0xFF); + UIDbuf[num++] = (temp & 0xFF00) >> 8; + UIDbuf[num++] = (temp & 0xFF0000) >> 16; + UIDbuf[num++] = (temp & 0xFF000000) >> 24; + } +} + +/** + * @brief Returns the DBGMCU_ID. + * @return DBGMCU_ID + */ + +void GetDBGMCU_ID(uint8_t *DBGMCU_IDbuf) +{ + uint8_t num = 0; + uint32_t* dbgid_addr = (uint32_t*)0; + uint32_t temp = 0; + + dbgid_addr = (uint32_t*)DBGMCU_ID_BASE; + for (num = 0; num < DBGMCU_ID_LENGTH;) + { + temp = *(__IO uint32_t*)(dbgid_addr++); + DBGMCU_IDbuf[num++] = (temp & 0xFF); + DBGMCU_IDbuf[num++] = (temp & 0xFF00) >> 8; + DBGMCU_IDbuf[num++] = (temp & 0xFF0000) >> 16; + DBGMCU_IDbuf[num++] = (temp & 0xFF000000) >> 24; + } +} + +/** + * @brief Returns the device revision number. + * @return Device revision identifier + */ +uint32_t DBG_GetRevNum(void) +{ + return (DBG->ID & 0x00FF); +} + +/** + * @brief Returns the device identifier. + * @return Device identifier + */ +uint32_t DBG_GetDevNum(void) +{ + uint32_t id = DBG->ID; + return ((id & 0x00F00000) >> 20) | ((id & 0xFF00) >> 4); +} + +/** + * @brief Configures the specified peripheral and low power mode behavior + * when the MCU under Debug mode. + * @param DBG_Periph specifies the peripheral and low power mode. + * This parameter can be any combination of the following values: + * @arg DBG_SLEEP Keep debugger connection during SLEEP mode + * @arg DBG_STOP Keep debugger connection during STOP mode + * @arg DBG_STDBY Keep debugger connection during STANDBY mode + * @arg DBG_IWDG_STOP Debug IWDG stopped when Core is halted + * @arg DBG_WWDG_STOP Debug WWDG stopped when Core is halted + * @arg DBG_TIM1_STOP TIM1 counter stopped when Core is halted + * @arg DBG_TIM2_STOP TIM2 counter stopped when Core is halted + * @arg DBG_TIM3_STOP TIM3 counter stopped when Core is halted + * @arg DBG_TIM4_STOP TIM4 counter stopped when Core is halted + * @arg DBG_CAN1_STOP Debug CAN2 stopped when Core is halted + * @arg DBG_I2C1SMBUS_TIMEOUT I2C1 SMBUS timeout mode stopped when Core is halted + * @arg DBG_I2C2SMBUS_TIMEOUT I2C2 SMBUS timeout mode stopped when Core is halted + * @arg DBG_TIM8_STOP TIM8 counter stopped when Core is halted + * @arg DBG_TIM5_STOP TIM5 counter stopped when Core is halted + * @arg DBG_TIM6_STOP TIM6 counter stopped when Core is halted + * @arg DBG_TIM7_STOP TIM7 counter stopped when Core is halted + * @arg DBG_CAN2_STOP Debug CAN2 stopped when Core is halted + + * @param Cmd new state of the specified peripheral in Debug mode. + * This parameter can be: ENABLE or DISABLE. + */ +void DBG_ConfigPeriph(uint32_t DBG_Periph, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_DBGMCU_PERIPH(DBG_Periph)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + DBG->CTRL |= DBG_Periph; + } + else + { + DBG->CTRL &= ~DBG_Periph; + } +} + +/** + * @brief Get FLASH size of this chip. + * + * @return FLASH size in bytes. + */ +uint32_t DBG_GetFlashSize(void) +{ + return (DBG->ID & 0x000F0000); +} + +/** + * @brief Get SRAM size of this chip. + * + * @return SRAM size in bytes. + */ +uint32_t DBG_GetSramSize(void) +{ + return (((DBG->ID & 0xF0000000) >> 28) + 1) << 14; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_dma.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_dma.c new file mode 100644 index 0000000000..46c531cdbc --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_dma.c @@ -0,0 +1,888 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_dma.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_dma.h" +#include "n32g4fr_rcc.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DMA + * @brief DMA driver modules + * @{ + */ + +/** @addtogroup DMA_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + +/** @addtogroup DMA_Private_Defines + * @{ + */ + +/* DMA1 Channelx interrupt pending bit masks */ +#define DMA1_CH1_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF1 | DMA_INTSTS_TXCF1 | DMA_INTSTS_HTXF1 | DMA_INTSTS_ERRF1)) +#define DMA1_CH2_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF2 | DMA_INTSTS_TXCF2 | DMA_INTSTS_HTXF2 | DMA_INTSTS_ERRF2)) +#define DMA1_CH3_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF3 | DMA_INTSTS_TXCF3 | DMA_INTSTS_HTXF3 | DMA_INTSTS_ERRF3)) +#define DMA1_CH4_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF4 | DMA_INTSTS_TXCF4 | DMA_INTSTS_HTXF4 | DMA_INTSTS_ERRF4)) +#define DMA1_CH5_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF5 | DMA_INTSTS_TXCF5 | DMA_INTSTS_HTXF5 | DMA_INTSTS_ERRF5)) +#define DMA1_CH6_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF6 | DMA_INTSTS_TXCF6 | DMA_INTSTS_HTXF6 | DMA_INTSTS_ERRF6)) +#define DMA1_CH7_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF7 | DMA_INTSTS_TXCF7 | DMA_INTSTS_HTXF7 | DMA_INTSTS_ERRF7)) +#define DMA1_CH8_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF8 | DMA_INTSTS_TXCF8 | DMA_INTSTS_HTXF8 | DMA_INTSTS_ERRF8)) + +/* DMA2 Channelx interrupt pending bit masks */ +#define DMA2_CH1_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF1 | DMA_INTSTS_TXCF1 | DMA_INTSTS_HTXF1 | DMA_INTSTS_ERRF1)) +#define DMA2_CH2_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF2 | DMA_INTSTS_TXCF2 | DMA_INTSTS_HTXF2 | DMA_INTSTS_ERRF2)) +#define DMA2_CH3_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF3 | DMA_INTSTS_TXCF3 | DMA_INTSTS_HTXF3 | DMA_INTSTS_ERRF3)) +#define DMA2_CH4_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF4 | DMA_INTSTS_TXCF4 | DMA_INTSTS_HTXF4 | DMA_INTSTS_ERRF4)) +#define DMA2_CH5_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF5 | DMA_INTSTS_TXCF5 | DMA_INTSTS_HTXF5 | DMA_INTSTS_ERRF5)) +#define DMA2_CH6_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF6 | DMA_INTSTS_TXCF6 | DMA_INTSTS_HTXF6 | DMA_INTSTS_ERRF6)) +#define DMA2_CH7_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF7 | DMA_INTSTS_TXCF7 | DMA_INTSTS_HTXF7 | DMA_INTSTS_ERRF7)) +#define DMA2_CH8_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF8 | DMA_INTSTS_TXCF8 | DMA_INTSTS_HTXF8 | DMA_INTSTS_ERRF8)) + +/* DMA registers Masks */ +#define CCR_CLEAR_Mask ((uint32_t)0xFFFF800F) + +/** + * @} + */ + +/** @addtogroup DMA_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DMA_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DMA_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DMA_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the DMAy Channelx registers to their default reset + * values. + * @param DMAyChx where y can be 1 or 2 to select the DMA and + * x can be 1 to 8 for DMA1 and 1 to 8 for DMA2 to select the DMA Channel. + */ +void DMA_DeInit(DMA_ChannelType* DMAyChx) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAyChx)); + + /* Disable the selected DMAy Channelx */ + DMAyChx->CHCFG &= (uint16_t)(~DMA_CHCFG1_CHEN); + + /* Reset DMAy Channelx control register */ + DMAyChx->CHCFG = 0; + + /* Reset DMAy Channelx remaining bytes register */ + DMAyChx->TXNUM = 0; + + /* Reset DMAy Channelx peripheral address register */ + DMAyChx->PADDR = 0; + + /* Reset DMAy Channelx memory address register */ + DMAyChx->MADDR = 0; + + if (DMAyChx == DMA1_CH1) + { + /* Reset interrupt pending bits for DMA1 Channel1 */ + DMA1->INTCLR |= DMA1_CH1_INT_MASK; + } + else if (DMAyChx == DMA1_CH2) + { + /* Reset interrupt pending bits for DMA1 Channel2 */ + DMA1->INTCLR |= DMA1_CH2_INT_MASK; + } + else if (DMAyChx == DMA1_CH3) + { + /* Reset interrupt pending bits for DMA1 Channel3 */ + DMA1->INTCLR |= DMA1_CH3_INT_MASK; + } + else if (DMAyChx == DMA1_CH4) + { + /* Reset interrupt pending bits for DMA1 Channel4 */ + DMA1->INTCLR |= DMA1_CH4_INT_MASK; + } + else if (DMAyChx == DMA1_CH5) + { + /* Reset interrupt pending bits for DMA1 Channel5 */ + DMA1->INTCLR |= DMA1_CH5_INT_MASK; + } + else if (DMAyChx == DMA1_CH6) + { + /* Reset interrupt pending bits for DMA1 Channel6 */ + DMA1->INTCLR |= DMA1_CH6_INT_MASK; + } + else if (DMAyChx == DMA1_CH7) + { + /* Reset interrupt pending bits for DMA1 Channel7 */ + DMA1->INTCLR |= DMA1_CH7_INT_MASK; + } + else if (DMAyChx == DMA1_CH8) + { + /* Reset interrupt pending bits for DMA1 Channel8 */ + DMA1->INTCLR |= DMA1_CH8_INT_MASK; + } + else if (DMAyChx == DMA2_CH1) + { + /* Reset interrupt pending bits for DMA2 Channel1 */ + DMA2->INTCLR |= DMA2_CH1_INT_MASK; + } + else if (DMAyChx == DMA2_CH2) + { + /* Reset interrupt pending bits for DMA2 Channel2 */ + DMA2->INTCLR |= DMA2_CH2_INT_MASK; + } + else if (DMAyChx == DMA2_CH3) + { + /* Reset interrupt pending bits for DMA2 Channel3 */ + DMA2->INTCLR |= DMA2_CH3_INT_MASK; + } + else if (DMAyChx == DMA2_CH4) + { + /* Reset interrupt pending bits for DMA2 Channel4 */ + DMA2->INTCLR |= DMA2_CH4_INT_MASK; + } + else if (DMAyChx == DMA2_CH5) + { + /* Reset interrupt pending bits for DMA2 Channel5 */ + DMA2->INTCLR |= DMA2_CH5_INT_MASK; + } + else if (DMAyChx == DMA2_CH6) + { + /* Reset interrupt pending bits for DMA2 Channel6 */ + DMA2->INTCLR |= DMA2_CH6_INT_MASK; + } + else if (DMAyChx == DMA2_CH7) + { + /* Reset interrupt pending bits for DMA2 Channel7 */ + DMA2->INTCLR |= DMA2_CH7_INT_MASK; + } + else + { + if (DMAyChx == DMA2_CH8) + { + /* Reset interrupt pending bits for DMA2 Channel8 */ + DMA2->INTCLR |= DMA2_CH8_INT_MASK; + } + } +} + +/** + * @brief Initializes the DMAy Channelx according to the specified + * parameters in the DMA_InitParam. + * @param DMAyChx where y can be 1 or 2 to select the DMA and + * x can be 1 to 8 for DMA1 and 1 to 8 for DMA2 to select the DMA Channel. + * @param DMA_InitParam pointer to a DMA_InitType structure that + * contains the configuration information for the specified DMA Channel. + */ +void DMA_Init(DMA_ChannelType* DMAyChx, DMA_InitType* DMA_InitParam) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAyChx)); + assert_param(IS_DMA_DIR(DMA_InitParam->Direction)); + assert_param(IS_DMA_BUF_SIZE(DMA_InitParam->BufSize)); + assert_param(IS_DMA_PERIPH_INC_STATE(DMA_InitParam->PeriphInc)); + assert_param(IS_DMA_MEM_INC_STATE(DMA_InitParam->DMA_MemoryInc)); + assert_param(IS_DMA_PERIPH_DATA_SIZE(DMA_InitParam->PeriphDataSize)); + assert_param(IS_DMA_MEMORY_DATA_SIZE(DMA_InitParam->MemDataSize)); + assert_param(IS_DMA_MODE(DMA_InitParam->CircularMode)); + assert_param(IS_DMA_PRIORITY(DMA_InitParam->Priority)); + assert_param(IS_DMA_M2M_STATE(DMA_InitParam->Mem2Mem)); + + /*--------------------------- DMAy Channelx CHCFG Configuration -----------------*/ + /* Get the DMAyChx CHCFG value */ + tmpregister = DMAyChx->CHCFG; + /* Clear MEM2MEM, PL, MSIZE, PSIZE, MINC, PINC, CIRC and DIR bits */ + tmpregister &= CCR_CLEAR_Mask; + /* Configure DMAy Channelx: data transfer, data size, priority level and mode */ + /* Set DIR bit according to Direction value */ + /* Set CIRC bit according to CircularMode value */ + /* Set PINC bit according to PeriphInc value */ + /* Set MINC bit according to DMA_MemoryInc value */ + /* Set PSIZE bits according to PeriphDataSize value */ + /* Set MSIZE bits according to MemDataSize value */ + /* Set PL bits according to Priority value */ + /* Set the MEM2MEM bit according to Mem2Mem value */ + tmpregister |= DMA_InitParam->Direction | DMA_InitParam->CircularMode | DMA_InitParam->PeriphInc + | DMA_InitParam->DMA_MemoryInc | DMA_InitParam->PeriphDataSize | DMA_InitParam->MemDataSize + | DMA_InitParam->Priority | DMA_InitParam->Mem2Mem; + + /* Write to DMAy Channelx CHCFG */ + DMAyChx->CHCFG = tmpregister; + + /*--------------------------- DMAy Channelx TXNUM Configuration ---------------*/ + /* Write to DMAy Channelx TXNUM */ + DMAyChx->TXNUM = DMA_InitParam->BufSize; + + /*--------------------------- DMAy Channelx PADDR Configuration ----------------*/ + /* Write to DMAy Channelx PADDR */ + DMAyChx->PADDR = DMA_InitParam->PeriphAddr; + + /*--------------------------- DMAy Channelx MADDR Configuration ----------------*/ + /* Write to DMAy Channelx MADDR */ + DMAyChx->MADDR = DMA_InitParam->MemAddr; +} + +/** + * @brief Fills each DMA_InitParam member with its default value. + * @param DMA_InitParam pointer to a DMA_InitType structure which will + * be initialized. + */ +void DMA_StructInit(DMA_InitType* DMA_InitParam) +{ + /*-------------- Reset DMA init structure parameters values ------------------*/ + /* Initialize the PeriphAddr member */ + DMA_InitParam->PeriphAddr = 0; + /* Initialize the MemAddr member */ + DMA_InitParam->MemAddr = 0; + /* Initialize the Direction member */ + DMA_InitParam->Direction = DMA_DIR_PERIPH_SRC; + /* Initialize the BufSize member */ + DMA_InitParam->BufSize = 0; + /* Initialize the PeriphInc member */ + DMA_InitParam->PeriphInc = DMA_PERIPH_INC_DISABLE; + /* Initialize the DMA_MemoryInc member */ + DMA_InitParam->DMA_MemoryInc = DMA_MEM_INC_DISABLE; + /* Initialize the PeriphDataSize member */ + DMA_InitParam->PeriphDataSize = DMA_PERIPH_DATA_SIZE_BYTE; + /* Initialize the MemDataSize member */ + DMA_InitParam->MemDataSize = DMA_MemoryDataSize_Byte; + /* Initialize the CircularMode member */ + DMA_InitParam->CircularMode = DMA_MODE_NORMAL; + /* Initialize the Priority member */ + DMA_InitParam->Priority = DMA_PRIORITY_LOW; + /* Initialize the Mem2Mem member */ + DMA_InitParam->Mem2Mem = DMA_M2M_DISABLE; +} + +/** + * @brief Enables or disables the specified DMAy Channelx. + * @param DMAyChx where y can be 1 or 2 to select the DMA and + * x can be 1 to 8 for DMA1 and 1 to 8 for DMA2 to select the DMA Channel. + * @param Cmd new state of the DMAy Channelx. + * This parameter can be: ENABLE or DISABLE. + */ +void DMA_EnableChannel(DMA_ChannelType* DMAyChx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAyChx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected DMAy Channelx */ + DMAyChx->CHCFG |= DMA_CHCFG1_CHEN; + } + else + { + /* Disable the selected DMAy Channelx */ + DMAyChx->CHCFG &= (uint16_t)(~DMA_CHCFG1_CHEN); + } +} + +/** + * @brief Enables or disables the specified DMAy Channelx interrupts. + * @param DMAyChx where y can be 1 or 2 to select the DMA and + * x can be 1 to 8 for DMA1 and 1 to 8 for DMA2 to select the DMA Channel. + * @param DMAInt specifies the DMA interrupts sources to be enabled + * or disabled. + * This parameter can be any combination of the following values: + * @arg DMA_INT_TXC Transfer complete interrupt mask + * @arg DMA_INT_HTX Half transfer interrupt mask + * @arg DMA_INT_ERR Transfer error interrupt mask + * @param Cmd new state of the specified DMA interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void DMA_ConfigInt(DMA_ChannelType* DMAyChx, uint32_t DMAInt, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAyChx)); + assert_param(IS_DMA_CONFIG_INT(DMAInt)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected DMA interrupts */ + DMAyChx->CHCFG |= DMAInt; + } + else + { + /* Disable the selected DMA interrupts */ + DMAyChx->CHCFG &= ~DMAInt; + } +} + +/** + * @brief Sets the number of data units in the current DMAy Channelx transfer. + * @param DMAyChx where y can be 1 or 2 to select the DMA and + * x can be 1 to 8 for DMA1 and 1 to 8 for DMA2 to select the DMA Channel. + * @param DataNumber The number of data units in the current DMAy Channelx + * transfer. + * @note This function can only be used when the DMAyChx is disabled. + */ +void DMA_SetCurrDataCounter(DMA_ChannelType* DMAyChx, uint16_t DataNumber) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAyChx)); + + /*--------------------------- DMAy Channelx TXNUM Configuration ---------------*/ + /* Write to DMAy Channelx TXNUM */ + DMAyChx->TXNUM = DataNumber; +} + +/** + * @brief Returns the number of remaining data units in the current + * DMAy Channelx transfer. + * @param DMAyChx where y can be 1 or 2 to select the DMA and + * x can be 1 to 8 for DMA1 and 1 to 8 for DMA2 to select the DMA Channel. + * @return The number of remaining data units in the current DMAy Channelx + * transfer. + */ +uint16_t DMA_GetCurrDataCounter(DMA_ChannelType* DMAyChx) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAyChx)); + /* Return the number of remaining data units for DMAy Channelx */ + return ((uint16_t)(DMAyChx->TXNUM)); +} + +/** + * @brief Checks whether the specified DMAy Channelx flag is set or not. + * @param DMAyFlag specifies the flag to check. + * This parameter can be one of the following values: + * @arg DMA1_FLAG_GL1 DMA1 Channel1 global flag. + * @arg DMA1_FLAG_TC1 DMA1 Channel1 transfer complete flag. + * @arg DMA1_FLAG_HT1 DMA1 Channel1 half transfer flag. + * @arg DMA1_FLAG_TE1 DMA1 Channel1 transfer error flag. + * @arg DMA1_FLAG_GL2 DMA1 Channel2 global flag. + * @arg DMA1_FLAG_TC2 DMA1 Channel2 transfer complete flag. + * @arg DMA1_FLAG_HT2 DMA1 Channel2 half transfer flag. + * @arg DMA1_FLAG_TE2 DMA1 Channel2 transfer error flag. + * @arg DMA1_FLAG_GL3 DMA1 Channel3 global flag. + * @arg DMA1_FLAG_TC3 DMA1 Channel3 transfer complete flag. + * @arg DMA1_FLAG_HT3 DMA1 Channel3 half transfer flag. + * @arg DMA1_FLAG_TE3 DMA1 Channel3 transfer error flag. + * @arg DMA1_FLAG_GL4 DMA1 Channel4 global flag. + * @arg DMA1_FLAG_TC4 DMA1 Channel4 transfer complete flag. + * @arg DMA1_FLAG_HT4 DMA1 Channel4 half transfer flag. + * @arg DMA1_FLAG_TE4 DMA1 Channel4 transfer error flag. + * @arg DMA1_FLAG_GL5 DMA1 Channel5 global flag. + * @arg DMA1_FLAG_TC5 DMA1 Channel5 transfer complete flag. + * @arg DMA1_FLAG_HT5 DMA1 Channel5 half transfer flag. + * @arg DMA1_FLAG_TE5 DMA1 Channel5 transfer error flag. + * @arg DMA1_FLAG_GL6 DMA1 Channel6 global flag. + * @arg DMA1_FLAG_TC6 DMA1 Channel6 transfer complete flag. + * @arg DMA1_FLAG_HT6 DMA1 Channel6 half transfer flag. + * @arg DMA1_FLAG_TE6 DMA1 Channel6 transfer error flag. + * @arg DMA1_FLAG_GL7 DMA1 Channel7 global flag. + * @arg DMA1_FLAG_TC7 DMA1 Channel7 transfer complete flag. + * @arg DMA1_FLAG_HT7 DMA1 Channel7 half transfer flag. + * @arg DMA1_FLAG_TE7 DMA1 Channel7 transfer error flag. + * @arg DMA1_FLAG_GL8 DMA1 Channel7 global flag. + * @arg DMA1_FLAG_TC8 DMA1 Channel7 transfer complete flag. + * @arg DMA1_FLAG_HT8 DMA1 Channel7 half transfer flag. + * @arg DMA1_FLAG_TE8 DMA1 Channel7 transfer error flag. + * @arg DMA2_FLAG_GL1 DMA2 Channel1 global flag. + * @arg DMA2_FLAG_TC1 DMA2 Channel1 transfer complete flag. + * @arg DMA2_FLAG_HT1 DMA2 Channel1 half transfer flag. + * @arg DMA2_FLAG_TE1 DMA2 Channel1 transfer error flag. + * @arg DMA2_FLAG_GL2 DMA2 Channel2 global flag. + * @arg DMA2_FLAG_TC2 DMA2 Channel2 transfer complete flag. + * @arg DMA2_FLAG_HT2 DMA2 Channel2 half transfer flag. + * @arg DMA2_FLAG_TE2 DMA2 Channel2 transfer error flag. + * @arg DMA2_FLAG_GL3 DMA2 Channel3 global flag. + * @arg DMA2_FLAG_TC3 DMA2 Channel3 transfer complete flag. + * @arg DMA2_FLAG_HT3 DMA2 Channel3 half transfer flag. + * @arg DMA2_FLAG_TE3 DMA2 Channel3 transfer error flag. + * @arg DMA2_FLAG_GL4 DMA2 Channel4 global flag. + * @arg DMA2_FLAG_TC4 DMA2 Channel4 transfer complete flag. + * @arg DMA2_FLAG_HT4 DMA2 Channel4 half transfer flag. + * @arg DMA2_FLAG_TE4 DMA2 Channel4 transfer error flag. + * @arg DMA2_FLAG_GL5 DMA2 Channel5 global flag. + * @arg DMA2_FLAG_TC5 DMA2 Channel5 transfer complete flag. + * @arg DMA2_FLAG_HT5 DMA2 Channel5 half transfer flag. + * @arg DMA2_FLAG_TE5 DMA2 Channel5 transfer error flag. + * @arg DMA2_FLAG_GL6 DMA1 Channel6 global flag. + * @arg DMA2_FLAG_TC6 DMA1 Channel6 transfer complete flag. + * @arg DMA2_FLAG_HT6 DMA1 Channel6 half transfer flag. + * @arg DMA2_FLAG_TE6 DMA1 Channel6 transfer error flag. + * @arg DMA2_FLAG_GL7 DMA1 Channel7 global flag. + * @arg DMA2_FLAG_TC7 DMA1 Channel7 transfer complete flag. + * @arg DMA2_FLAG_HT7 DMA1 Channel7 half transfer flag. + * @arg DMA2_FLAG_TE7 DMA1 Channel7 transfer error flag. + * @arg DMA2_FLAG_GL8 DMA1 Channel7 global flag. + * @arg DMA2_FLAG_TC8 DMA1 Channel7 transfer complete flag. + * @arg DMA2_FLAG_HT8 DMA1 Channel7 half transfer flag. + * @arg DMA2_FLAG_TE8 DMA1 Channel7 transfer error flag. + * @param DMAy DMA1 or DMA2. + * This parameter can be one of the following values: + * @arg DMA1 . + * @arg DMA2 . + * @return The new state of DMAyFlag (SET or RESET). + */ +FlagStatus DMA_GetFlagStatus(uint32_t DMAyFlag, DMA_Module* DMAy) +{ + FlagStatus bitstatus = RESET; + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_DMA_GET_FLAG(DMAyFlag)); + + /* Calculate the used DMAy */ + /* Get DMAy INTSTS register value */ + tmpregister = DMAy->INTSTS; + + /* Check the status of the specified DMAy flag */ + if ((tmpregister & DMAyFlag) != (uint32_t)RESET) + { + /* DMAyFlag is set */ + bitstatus = SET; + } + else + { + /* DMAyFlag is reset */ + bitstatus = RESET; + } + + /* Return the DMAyFlag status */ + return bitstatus; +} + +/** + * @brief Clears the DMAy Channelx's pending flags. + * @param DMAyFlag specifies the flag to clear. + * This parameter can be any combination (for the same DMA) of the following values: + * @arg DMA1_FLAG_GL1 DMA1 Channel1 global flag. + * @arg DMA1_FLAG_TC1 DMA1 Channel1 transfer complete flag. + * @arg DMA1_FLAG_HT1 DMA1 Channel1 half transfer flag. + * @arg DMA1_FLAG_TE1 DMA1 Channel1 transfer error flag. + * @arg DMA1_FLAG_GL2 DMA1 Channel2 global flag. + * @arg DMA1_FLAG_TC2 DMA1 Channel2 transfer complete flag. + * @arg DMA1_FLAG_HT2 DMA1 Channel2 half transfer flag. + * @arg DMA1_FLAG_TE2 DMA1 Channel2 transfer error flag. + * @arg DMA1_FLAG_GL3 DMA1 Channel3 global flag. + * @arg DMA1_FLAG_TC3 DMA1 Channel3 transfer complete flag. + * @arg DMA1_FLAG_HT3 DMA1 Channel3 half transfer flag. + * @arg DMA1_FLAG_TE3 DMA1 Channel3 transfer error flag. + * @arg DMA1_FLAG_GL4 DMA1 Channel4 global flag. + * @arg DMA1_FLAG_TC4 DMA1 Channel4 transfer complete flag. + * @arg DMA1_FLAG_HT4 DMA1 Channel4 half transfer flag. + * @arg DMA1_FLAG_TE4 DMA1 Channel4 transfer error flag. + * @arg DMA1_FLAG_GL5 DMA1 Channel5 global flag. + * @arg DMA1_FLAG_TC5 DMA1 Channel5 transfer complete flag. + * @arg DMA1_FLAG_HT5 DMA1 Channel5 half transfer flag. + * @arg DMA1_FLAG_TE5 DMA1 Channel5 transfer error flag. + * @arg DMA1_FLAG_GL6 DMA1 Channel6 global flag. + * @arg DMA1_FLAG_TC6 DMA1 Channel6 transfer complete flag. + * @arg DMA1_FLAG_HT6 DMA1 Channel6 half transfer flag. + * @arg DMA1_FLAG_TE6 DMA1 Channel6 transfer error flag. + * @arg DMA1_FLAG_GL7 DMA1 Channel7 global flag. + * @arg DMA1_FLAG_TC7 DMA1 Channel7 transfer complete flag. + * @arg DMA1_FLAG_HT7 DMA1 Channel7 half transfer flag. + * @arg DMA1_FLAG_TE7 DMA1 Channel7 transfer error flag. + * @arg DMA1_FLAG_GL8 DMA1 Channel8 global flag. + * @arg DMA1_FLAG_TC8 DMA1 Channel8 transfer complete flag. + * @arg DMA1_FLAG_HT8 DMA1 Channel8 half transfer flag. + * @arg DMA1_FLAG_TE8 DMA1 Channel8 transfer error flag. + * @arg DMA2_FLAG_GL1 DMA2 Channel1 global flag. + * @arg DMA2_FLAG_TC1 DMA2 Channel1 transfer complete flag. + * @arg DMA2_FLAG_HT1 DMA2 Channel1 half transfer flag. + * @arg DMA2_FLAG_TE1 DMA2 Channel1 transfer error flag. + * @arg DMA2_FLAG_GL2 DMA2 Channel2 global flag. + * @arg DMA2_FLAG_TC2 DMA2 Channel2 transfer complete flag. + * @arg DMA2_FLAG_HT2 DMA2 Channel2 half transfer flag. + * @arg DMA2_FLAG_TE2 DMA2 Channel2 transfer error flag. + * @arg DMA2_FLAG_GL3 DMA2 Channel3 global flag. + * @arg DMA2_FLAG_TC3 DMA2 Channel3 transfer complete flag. + * @arg DMA2_FLAG_HT3 DMA2 Channel3 half transfer flag. + * @arg DMA2_FLAG_TE3 DMA2 Channel3 transfer error flag. + * @arg DMA2_FLAG_GL4 DMA2 Channel4 global flag. + * @arg DMA2_FLAG_TC4 DMA2 Channel4 transfer complete flag. + * @arg DMA2_FLAG_HT4 DMA2 Channel4 half transfer flag. + * @arg DMA2_FLAG_TE4 DMA2 Channel4 transfer error flag. + * @arg DMA2_FLAG_GL5 DMA2 Channel5 global flag. + * @arg DMA2_FLAG_TC5 DMA2 Channel5 transfer complete flag. + * @arg DMA2_FLAG_HT5 DMA2 Channel5 half transfer flag. + * @arg DMA2_FLAG_TE5 DMA2 Channel5 transfer error flag. + * @arg DMA2_FLAG_GL6 DMA2 Channel6 global flag. + * @arg DMA2_FLAG_TC6 DMA2 Channel6 transfer complete flag. + * @arg DMA2_FLAG_HT6 DMA2 Channel6 half transfer flag. + * @arg DMA2_FLAG_TE6 DMA2 Channel6 transfer error flag. + * @arg DMA2_FLAG_GL7 DMA2 Channel7 global flag. + * @arg DMA2_FLAG_TC7 DMA2 Channel7 transfer complete flag. + * @arg DMA2_FLAG_HT7 DMA2 Channel7 half transfer flag. + * @arg DMA2_FLAG_TE7 DMA2 Channel7 transfer error flag. + * @arg DMA2_FLAG_GL8 DMA2 Channel8 global flag. + * @arg DMA2_FLAG_TC8 DMA2 Channel8 transfer complete flag. + * @arg DMA2_FLAG_HT8 DMA2 Channel8 half transfer flag. + * @arg DMA2_FLAG_TE8 DMA2 Channel8 transfer error flag. + * @param DMAy DMA1 or DMA2. + * This parameter can be one of the following values: + * @arg DMA1 . + * @arg DMA2 . + */ +void DMA_ClearFlag(uint32_t DMAyFlag, DMA_Module* DMAy) +{ + /* Check the parameters */ + assert_param(IS_DMA_CLEAR_FLAG(DMAyFlag)); + + /* Calculate the used DMAy */ + /* Clear the selected DMAy flags */ + DMAy->INTCLR = DMAyFlag; +} + +/** + * @brief Checks whether the specified DMAy Channelx interrupt has occurred or not. + * @param DMAy_IT specifies the DMAy interrupt source to check. + * This parameter can be one of the following values: + * @arg DMA1_INT_GLB1 DMA1 Channel1 global interrupt. + * @arg DMA1_INT_TXC1 DMA1 Channel1 transfer complete interrupt. + * @arg DMA1_INT_HTX1 DMA1 Channel1 half transfer interrupt. + * @arg DMA1_INT_ERR1 DMA1 Channel1 transfer error interrupt. + * @arg DMA1_INT_GLB2 DMA1 Channel2 global interrupt. + * @arg DMA1_INT_TXC2 DMA1 Channel2 transfer complete interrupt. + * @arg DMA1_INT_HTX2 DMA1 Channel2 half transfer interrupt. + * @arg DMA1_INT_ERR2 DMA1 Channel2 transfer error interrupt. + * @arg DMA1_INT_GLB3 DMA1 Channel3 global interrupt. + * @arg DMA1_INT_TXC3 DMA1 Channel3 transfer complete interrupt. + * @arg DMA1_INT_HTX3 DMA1 Channel3 half transfer interrupt. + * @arg DMA1_INT_ERR3 DMA1 Channel3 transfer error interrupt. + * @arg DMA1_INT_GLB4 DMA1 Channel4 global interrupt. + * @arg DMA1_INT_TXC4 DMA1 Channel4 transfer complete interrupt. + * @arg DMA1_INT_HTX4 DMA1 Channel4 half transfer interrupt. + * @arg DMA1_INT_ERR4 DMA1 Channel4 transfer error interrupt. + * @arg DMA1_INT_GLB5 DMA1 Channel5 global interrupt. + * @arg DMA1_INT_TXC5 DMA1 Channel5 transfer complete interrupt. + * @arg DMA1_INT_HTX5 DMA1 Channel5 half transfer interrupt. + * @arg DMA1_INT_ERR5 DMA1 Channel5 transfer error interrupt. + * @arg DMA1_INT_GLB6 DMA1 Channel6 global interrupt. + * @arg DMA1_INT_TXC6 DMA1 Channel6 transfer complete interrupt. + * @arg DMA1_INT_HTX6 DMA1 Channel6 half transfer interrupt. + * @arg DMA1_INT_ERR6 DMA1 Channel6 transfer error interrupt. + * @arg DMA1_INT_GLB7 DMA1 Channel7 global interrupt. + * @arg DMA1_INT_TXC7 DMA1 Channel7 transfer complete interrupt. + * @arg DMA1_INT_HTX7 DMA1 Channel7 half transfer interrupt. + * @arg DMA1_INT_ERR7 DMA1 Channel7 transfer error interrupt. + * @arg DMA1_INT_GLB8 DMA1 Channel8 global interrupt. + * @arg DMA1_INT_TXC8 DMA1 Channel8 transfer complete interrupt. + * @arg DMA1_INT_HTX8 DMA1 Channel8 half transfer interrupt. + * @arg DMA1_INT_ERR8 DMA1 Channel8 transfer error interrupt. + * @arg DMA2_INT_GLB1 DMA2 Channel1 global interrupt. + * @arg DMA2_INT_TXC1 DMA2 Channel1 transfer complete interrupt. + * @arg DMA2_INT_HTX1 DMA2 Channel1 half transfer interrupt. + * @arg DMA2_INT_ERR1 DMA2 Channel1 transfer error interrupt. + * @arg DMA2_INT_GLB2 DMA2 Channel2 global interrupt. + * @arg DMA2_INT_TXC2 DMA2 Channel2 transfer complete interrupt. + * @arg DMA2_INT_HTX2 DMA2 Channel2 half transfer interrupt. + * @arg DMA2_INT_ERR2 DMA2 Channel2 transfer error interrupt. + * @arg DMA2_INT_GLB3 DMA2 Channel3 global interrupt. + * @arg DMA2_INT_TXC3 DMA2 Channel3 transfer complete interrupt. + * @arg DMA2_INT_HTX3 DMA2 Channel3 half transfer interrupt. + * @arg DMA2_INT_ERR3 DMA2 Channel3 transfer error interrupt. + * @arg DMA2_INT_GLB4 DMA2 Channel4 global interrupt. + * @arg DMA2_INT_TXC4 DMA2 Channel4 transfer complete interrupt. + * @arg DMA2_INT_HTX4 DMA2 Channel4 half transfer interrupt. + * @arg DMA2_INT_ERR4 DMA2 Channel4 transfer error interrupt. + * @arg DMA2_INT_GLB5 DMA2 Channel5 global interrupt. + * @arg DMA2_INT_TXC5 DMA2 Channel5 transfer complete interrupt. + * @arg DMA2_INT_HTX5 DMA2 Channel5 half transfer interrupt. + * @arg DMA2_INT_ERR5 DMA2 Channel5 transfer error interrupt. + * @arg DMA2_INT_GLB6 DMA2 Channel6 global interrupt. + * @arg DMA2_INT_TXC6 DMA2 Channel6 transfer complete interrupt. + * @arg DMA2_INT_HTX6 DMA2 Channel6 half transfer interrupt. + * @arg DMA2_INT_ERR6 DMA2 Channel6 transfer error interrupt. + * @arg DMA2_INT_GLB7 DMA2 Channel7 global interrupt. + * @arg DMA2_INT_TXC7 DMA2 Channel7 transfer complete interrupt. + * @arg DMA2_INT_HTX7 DMA2 Channel7 half transfer interrupt. + * @arg DMA2_INT_ERR7 DMA2 Channel7 transfer error interrupt. + * @arg DMA2_INT_GLB8 DMA2 Channel8 global interrupt. + * @arg DMA2_INT_TXC8 DMA2 Channel8 transfer complete interrupt. + * @arg DMA2_INT_HTX8 DMA2 Channel8 half transfer interrupt. + * @arg DMA2_INT_ERR8 DMA2 Channel8 transfer error interrupt. + * @param DMAy DMA1 or DMA2. + * This parameter can be one of the following values: + * @arg DMA1 . + * @arg DMA2 . + * @return The new state of DMAy_IT (SET or RESET). + */ +INTStatus DMA_GetIntStatus(uint32_t DMAy_IT, DMA_Module* DMAy) +{ + INTStatus bitstatus = RESET; + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_DMA_GET_IT(DMAy_IT)); + + /* Calculate the used DMA */ + /* Get DMAy INTSTS register value */ + tmpregister = DMAy->INTSTS; + + /* Check the status of the specified DMAy interrupt */ + if ((tmpregister & DMAy_IT) != (uint32_t)RESET) + { + /* DMAy_IT is set */ + bitstatus = SET; + } + else + { + /* DMAy_IT is reset */ + bitstatus = RESET; + } + /* Return the DMAInt status */ + return bitstatus; +} + +/** + * @brief Clears the DMAy Channelx's interrupt pending bits. + * @param DMAy_IT specifies the DMAy interrupt pending bit to clear. + * This parameter can be any combination (for the same DMA) of the following values: + * @arg DMA1_INT_GLB1 DMA1 Channel1 global interrupt. + * @arg DMA1_INT_TXC1 DMA1 Channel1 transfer complete interrupt. + * @arg DMA1_INT_HTX1 DMA1 Channel1 half transfer interrupt. + * @arg DMA1_INT_ERR1 DMA1 Channel1 transfer error interrupt. + * @arg DMA1_INT_GLB2 DMA1 Channel2 global interrupt. + * @arg DMA1_INT_TXC2 DMA1 Channel2 transfer complete interrupt. + * @arg DMA1_INT_HTX2 DMA1 Channel2 half transfer interrupt. + * @arg DMA1_INT_ERR2 DMA1 Channel2 transfer error interrupt. + * @arg DMA1_INT_GLB3 DMA1 Channel3 global interrupt. + * @arg DMA1_INT_TXC3 DMA1 Channel3 transfer complete interrupt. + * @arg DMA1_INT_HTX3 DMA1 Channel3 half transfer interrupt. + * @arg DMA1_INT_ERR3 DMA1 Channel3 transfer error interrupt. + * @arg DMA1_INT_GLB4 DMA1 Channel4 global interrupt. + * @arg DMA1_INT_TXC4 DMA1 Channel4 transfer complete interrupt. + * @arg DMA1_INT_HTX4 DMA1 Channel4 half transfer interrupt. + * @arg DMA1_INT_ERR4 DMA1 Channel4 transfer error interrupt. + * @arg DMA1_INT_GLB5 DMA1 Channel5 global interrupt. + * @arg DMA1_INT_TXC5 DMA1 Channel5 transfer complete interrupt. + * @arg DMA1_INT_HTX5 DMA1 Channel5 half transfer interrupt. + * @arg DMA1_INT_ERR5 DMA1 Channel5 transfer error interrupt. + * @arg DMA1_INT_GLB6 DMA1 Channel6 global interrupt. + * @arg DMA1_INT_TXC6 DMA1 Channel6 transfer complete interrupt. + * @arg DMA1_INT_HTX6 DMA1 Channel6 half transfer interrupt. + * @arg DMA1_INT_ERR6 DMA1 Channel6 transfer error interrupt. + * @arg DMA1_INT_GLB7 DMA1 Channel7 global interrupt. + * @arg DMA1_INT_TXC7 DMA1 Channel7 transfer complete interrupt. + * @arg DMA1_INT_HTX7 DMA1 Channel7 half transfer interrupt. + * @arg DMA1_INT_ERR7 DMA1 Channel7 transfer error interrupt. + * @arg DMA1_INT_GLB8 DMA1 Channel8 global interrupt. + * @arg DMA1_INT_TXC8 DMA1 Channel8 transfer complete interrupt. + * @arg DMA1_INT_HTX8 DMA1 Channel8 half transfer interrupt. + * @arg DMA1_INT_ERR8 DMA1 Channel8 transfer error interrupt. + * @arg DMA2_INT_GLB1 DMA2 Channel1 global interrupt. + * @arg DMA2_INT_TXC1 DMA2 Channel1 transfer complete interrupt. + * @arg DMA2_INT_HTX1 DMA2 Channel1 half transfer interrupt. + * @arg DMA2_INT_ERR1 DMA2 Channel1 transfer error interrupt. + * @arg DMA2_INT_GLB2 DMA2 Channel2 global interrupt. + * @arg DMA2_INT_TXC2 DMA2 Channel2 transfer complete interrupt. + * @arg DMA2_INT_HTX2 DMA2 Channel2 half transfer interrupt. + * @arg DMA2_INT_ERR2 DMA2 Channel2 transfer error interrupt. + * @arg DMA2_INT_GLB3 DMA2 Channel3 global interrupt. + * @arg DMA2_INT_TXC3 DMA2 Channel3 transfer complete interrupt. + * @arg DMA2_INT_HTX3 DMA2 Channel3 half transfer interrupt. + * @arg DMA2_INT_ERR3 DMA2 Channel3 transfer error interrupt. + * @arg DMA2_INT_GLB4 DMA2 Channel4 global interrupt. + * @arg DMA2_INT_TXC4 DMA2 Channel4 transfer complete interrupt. + * @arg DMA2_INT_HTX4 DMA2 Channel4 half transfer interrupt. + * @arg DMA2_INT_ERR4 DMA2 Channel4 transfer error interrupt. + * @arg DMA2_INT_GLB5 DMA2 Channel5 global interrupt. + * @arg DMA2_INT_TXC5 DMA2 Channel5 transfer complete interrupt. + * @arg DMA2_INT_HTX5 DMA2 Channel5 half transfer interrupt. + * @arg DMA2_INT_ERR5 DMA2 Channel5 transfer error interrupt. + * @arg DMA2_INT_GLB6 DMA2 Channel6 global interrupt. + * @arg DMA2_INT_TXC6 DMA2 Channel6 transfer complete interrupt. + * @arg DMA2_INT_HTX6 DMA2 Channel6 half transfer interrupt. + * @arg DMA2_INT_ERR6 DMA2 Channel6 transfer error interrupt. + * @arg DMA2_INT_GLB7 DMA2 Channel7 global interrupt. + * @arg DMA2_INT_TXC7 DMA2 Channel7 transfer complete interrupt. + * @arg DMA2_INT_HTX7 DMA2 Channel7 half transfer interrupt. + * @arg DMA2_INT_ERR7 DMA2 Channel7 transfer error interrupt. + * @arg DMA2_INT_GLB8 DMA2 Channel8 global interrupt. + * @arg DMA2_INT_TXC8 DMA2 Channel8 transfer complete interrupt. + * @arg DMA2_INT_HTX8 DMA2 Channel8 half transfer interrupt. + * @arg DMA2_INT_ERR8 DMA2 Channel8 transfer error interrupt. + * @param DMAy DMA1 or DMA2. + * This parameter can be one of the following values: + * @arg DMA1 . + * @arg DMA2 . + */ +void DMA_ClrIntPendingBit(uint32_t DMAy_IT, DMA_Module* DMAy) +{ + /* Check the parameters */ + assert_param(IS_DMA_CLR_INT(DMAy_IT)); + + /* Calculate the used DMAy */ + /* Clear the selected DMAy interrupt pending bits */ + DMAy->INTCLR = DMAy_IT; +} + +/** + * @brief Set the DMAy Channelx's remap request. + * @param DMAy_REMAP specifies the DMAy request. + * This parameter can be set by the following values: + * @arg DMA1_REMAP_ADC1 DMA1 Request For ADC1. + * @arg DMA1_REMAP_UART5_TX DMA1 Request For UART5_TX. + * @arg DMA1_REMAP_I2C3_TX DMA1 Request For I2C3_TX. + * @arg DMA1_REMAP_TIM2_CH3 DMA1 Request For TIM2_CH3. + * @arg DMA1_REMAP_TIM4_CH1 DMA1 Request For TIM4_CH1. + * @arg DMA1_REMAP_USART3_TX DMA1 Request For USART3_TX. + * @arg DMA1_REMAP_I2C3_RX DMA1 Request For I2C3_RX. + * @arg DMA1_REMAP_TIM1_CH1 DMA1 Request For TIM1_CH1. + * @arg DMA1_REMAP_TIM2_UP DMA1 Request For TIM2_UP. + * @arg DMA1_REMAP_TIM3_CH3 DMA1 Request For TIM3_CH3. + * @arg DMA1_REMAP_SPI1_RX DMA1 Request For SPI1_RX. + * @arg DMA1_REMAP_USART3_RX DMA1 Request For USART3_RX. + * @arg DMA1_REMAP_TIM1_CH2 DMA1 Request For TIM1_CH2. + * @arg DMA1_REMAP_TIM3_CH4 DMA1 Request For TIM3_CH4. + * @arg DMA1_REMAP_TIM3_UP DMA1 Request For TIM3_UP. + * @arg DMA1_REMAP_SPI1_TX DMA1 Request For SPI1_TX. + * @arg DMA1_REMAP_USART1_TX DMA1 Request For USART1_TX. + * @arg DMA1_REMAP_TIM1_CH4 DMA1 Request For TIM1_CH4. + * @arg DMA1_REMAP_TIM1_TRIG DMA1 Request For TIM1_TRIG. + * @arg DMA1_REMAP_TIM1_COM DMA1 Request For TIM1_COM. + * @arg DMA1_REMAP_TIM4_CH2 DMA1 Request For TIM4_CH2. + * @arg DMA1_REMAP_SPI_I2S2_RX DMA1 Request For SPI_I2S2_RX. + * @arg DMA1_REMAP_I2C2_TX DMA1 Request For I2C2_TX. + * @arg DMA1_REMAP_USART1_RX DMA1 Request For USART1_RX. + * @arg DMA1_REMAP_TIM1_UP DMA1 Request For TIM1_UP. + * @arg DMA1_REMAP_SPI_I2S2_TX DMA1 Request For SPI_I2S2_TX. + * @arg DMA1_REMAP_TIM4_CH3 DMA1 Request For TIM4_CH3. + * @arg DMA1_REMAP_I2C2_RX DMA1 Request For I2C2_RX. + * @arg DMA1_REMAP_TIM2_CH1 DMA1 Request For TIM2_CH1. + * @arg DMA1_REMAP_USART2_RX DMA1 Request For USART2_RX. + * @arg DMA1_REMAP_TIM1_CH3 DMA1 Request For TIM1_CH3. + * @arg DMA1_REMAP_TIM3_CH1 DMA1 Request For TIM3_CH1. + * @arg DMA1_REMAP_TIM3_TRIG DMA1 Request For TIM3_TRIG. + * @arg DMA1_REMAP_I2C1_TX DMA1 Request For I2C1_TX. + * @arg DMA1_REMAP_USART2_TX DMA1 Request For USART2_TX. + * @arg DMA1_REMAP_TIM2_CH2 DMA1 Request For TIM2_CH2. + * @arg DMA1_REMAP_TIM2_CH4 DMA1 Request For TIM2_CH4. + * @arg DMA1_REMAP_TIM4_UP DMA1 Request For TIM4_UP. + * @arg DMA1_REMAP_I2C1_RX DMA1 Request For I2C1_RX. + * @arg DMA1_REMAP_ADC2 DMA1 Request For ADC2. + * @arg DMA1_REMAP_UART5_RX DMA1 Request For UART5_RX. + * @arg DMA2_REMAP_TIM5_CH4 DMA2 Request For TIM5_CH4. + * @arg DMA2_REMAP_TIM5_TRIG DMA2 Request For TIM5_TRIG. + * @arg DMA2_REMAP_TIM8_CH3 DMA2 Request For TIM8_CH3. + * @arg DMA2_REMAP_TIM8_UP DMA2 Request For TIM8_UP. + * @arg DMA2_REMAP_SPI_I2S3_RX DMA2 Request For SPI_I2S3_RX. + * @arg DMA2_REMAP_UART6_RX DMA2 Request For UART6_RX. + * @arg DMA2_REMAP_TIM8_CH4 DMA2 Request For TIM8_CH4. + * @arg DMA2_REMAP_TIM8_TRIG DMA2 Request For TIM8_TRIG. + * @arg DMA2_REMAP_TIM8_COM DMA2 Request For TIM8_COM. + * @arg DMA2_REMAP_TIM5_CH3 DMA2 Request For TIM5_CH3. + * @arg DMA2_REMAP_TIM5_UP DMA2 Request For TIM5_UP. + * @arg DMA2_REMAP_SPI_I2S3_TX DMA2 Request For SPI_I2S3_TX. + * @arg DMA2_REMAP_UART6_TX DMA2 Request For UART6_TX. + * @arg DMA2_REMAP_TIM8_CH1 DMA2 Request For TIM8_CH1. + * @arg DMA2_REMAP_UART4_RX DMA2 Request For UART4_RX. + * @arg DMA2_REMAP_TIM6_UP DMA2 Request For TIM6_UP. + * @arg DMA2_REMAP_DAC1 DMA2 Request For DAC1. + * @arg DMA2_REMAP_TIM5_CH2 DMA2 Request For TIM5_CH2. + * @arg DMA2_REMAP_SDIO DMA2 Request For SDIO. + * @arg DMA2_REMAP_TIM7_UP DMA2 Request For TIM7_UP. + * @arg DMA2_REMAP_DAC2 DMA2 Request For DAC2. + * @arg DMA2_REMAP_ADC3 DMA2 Request For ADC3. + * @arg DMA2_REMAP_TIM8_CH2 DMA2 Request For TIM8_CH2. + * @arg DMA2_REMAP_TIM5_CH1 DMA2 Request For TIM5_CH1. + * @arg DMA2_REMAP_UART4_TX DMA2 Request For UART4_TX. + * @arg DMA2_REMAP_QSPI_RX DMA2 Request For QSPI_RX. + * @arg DMA2_REMAP_I2C4_TX DMA2 Request For I2C4_TX. + * @arg DMA2_REMAP_UART7_RX DMA2 Request For UART7_RX. + * @arg DMA2_REMAP_QSPI_TX DMA2 Request For QSPI_TX. + * @arg DMA2_REMAP_I2C4_RX DMA2 Request For I2C4_RX. + * @arg DMA2_REMAP_UART7_TX DMA2 Request For UART7_TX. + * @arg DMA2_REMAP_ADC4 DMA2 Request For ADC4. + * @arg DMA2_REMAP_DVP DMA2 Request For DVP. + * @param DMAy DMA1 or DMA2. + * This parameter can be one of the following values: + * @arg DMA1 . + * @arg DMA2 . + * @param DMAyChx where y can be 1 or 2 to select the DMA and + * x can be 1 to 8 for DMA1 and 1 to 8 for DMA2 to select the DMA Channel. + * @param Cmd new state of the DMAy Channelx. + * This parameter can be: ENABLE or DISABLE. + */ +void DMA_RequestRemap(uint32_t DMAy_REMAP, DMA_Module* DMAy, DMA_ChannelType* DMAyChx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_DMA_REMAP(DMAy_REMAP)); + + if (Cmd != DISABLE) + { + /* Calculate the used DMAy */ + /* Set the selected DMAy remap request */ + DMAyChx->CHSEL = DMAy_REMAP; + DMAy->CHMAPEN = 1; + } + else + { + DMAy->CHMAPEN = 0; + } +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_dvp.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_dvp.c new file mode 100644 index 0000000000..7cf58fc32d --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_dvp.c @@ -0,0 +1,166 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_dvp.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_dvp.h" +#include "n32g4fr_rcc.h" + +/** + * @brief Deinitializes the DVP peripheral registers to their default reset values. + * @param None + * @retval None + */ +void DVP_ResetReg(void) +{ + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_DVP, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_DVP, DISABLE); +} + +/** + * @brief Initializes the DVP peripheral according to the specified + * parameters in the DVP_InitStruct . + * @param DVP_InitStruct pointer to a DVP_InitType structure + * that contains the configuration information for the specified DVP + * peripheral. + * @retval None + */ +void DVP_Init( DVP_InitType* DVP_InitStruct) +{ + uint32_t tmpregister = 0x00; + + /* Check the parameters */ + assert_param(IS_DVP_LINE_CAPTURE(DVP_InitStruct->LineCapture)); + assert_param(IS_DVP_BYTE_CAPTURE(DVP_InitStruct->ByteCapture)); + assert_param(IS_DVP_DATA_INVERT(DVP_InitStruct->DataInvert)); + assert_param(IS_DVP_PIXEL_POLARITY(DVP_InitStruct->PixelClkPolarity)); + assert_param(IS_DVP_VSYNC_POLARITY(DVP_InitStruct->VsyncPolarity)); + assert_param(IS_DVP_HSYNC_POLARITY(DVP_InitStruct->HsyncPolarity)); + assert_param(IS_DVP_CAPTURE_MODE(DVP_InitStruct->CaptureMode)); + assert_param(IS_DVP_FIFOWATERMARK(DVP_InitStruct->FifoWatermark)); + + /*---------------------------- DVP CTRL Configuration -----------------------*/ + tmpregister = 0; + tmpregister |= DVP_InitStruct->LineCapture | DVP_InitStruct->ByteCapture + | DVP_InitStruct->DataInvert | DVP_InitStruct->PixelClkPolarity + | DVP_InitStruct->VsyncPolarity | DVP_InitStruct->HsyncPolarity + | DVP_InitStruct->CaptureMode | DVP_InitStruct->FifoWatermark; + DVP->CTRL = tmpregister; + + /*---------------------------- DVP WST Configuration -----------------------*/ + if (DVP_InitStruct->RowStart) + DVP_InitStruct->RowStart--; + + if (DVP_InitStruct->ColumnStart) + DVP_InitStruct->ColumnStart--; + + DVP->WST = ( (((uint32_t)(DVP_InitStruct->RowStart)) << DVP_WST_VST_SHIFT) \ + | (((uint32_t)(DVP_InitStruct->ColumnStart))<< DVP_WST_HST_SHIFT) ); + + /*---------------------------- DVP WSIZE Configuration -----------------------*/ + DVP->WSIZE = ( (((uint32_t)(DVP_InitStruct->ImageHeight-1)) << DVP_WSIZE_VLINE_SHIFT) \ + | (((uint32_t)(DVP_InitStruct->ImageWidth-1)) << DVP_WSIZE_HCNT_SHIFT) ); +} + +/** + * @brief Fills DVP_InitStruct member with its default value. + * @param DVP_InitStruct pointer to a DVP_InitType structure + * which will be initialized. + * @retval None + */ +void DVP_DafaultInitParam(DVP_InitType* DVP_InitStruct) +{ + /* DVP_InitStruct members default value */ + DVP_InitStruct->FifoWatermark = DVP_WATER_MARK_1; + DVP_InitStruct->LineCapture = DVP_LINE_CAPTURE_ALL; + DVP_InitStruct->ByteCapture = DVP_BYTE_CAPTURE_ALL; + DVP_InitStruct->DataInvert = DVP_DATA_NOTINVERT; + DVP_InitStruct->PixelClkPolarity = DVP_PIXEL_POLARITY_FALLING; + DVP_InitStruct->VsyncPolarity = DVP_VSYNC_POLARITY_LOW; + DVP_InitStruct->HsyncPolarity = DVP_HSYNC_POLARITY_HIGH; + DVP_InitStruct->CaptureMode = DVP_CAPTURE_MODE_SINGLE; + DVP_InitStruct->RowStart = 0; + DVP_InitStruct->ColumnStart = 0; + DVP_InitStruct->ImageHeight = 240; + DVP_InitStruct->ImageWidth = 320; +} + +/** + * @brief Enables or disables the DVP DMA interface. + * @param Cmd New state of the DMA Request. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DVP_ConfigDma( FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* When DMA is enable, the FWM in CTRL1 should be set 1*/ + __DVP_SetFifoWatermark(DVP_WATER_MARK_1); + + __DVP_EnableDMA(); + } + else + { + __DVP_DisableDMA(); + } +} + +/** + * @brief Get the data length in FIFO. + * @param None. + * @retval Current date length in FIFO + */ +uint32_t DVP_GetFifoCount(void) +{ + if (__FIFOIsNotEmpty()) + return ((DVP->STS & DVP_STS_FCNT_MASK)>>DVP_STS_FCNT_SHIFT); + else + return 0; +} + +/** + * @brief Software Reset FIFO + * @param None. + * @retval None. + */ +void DVP_ResetFifo(void) +{ + __DVP_StopCapture(); + + DVP->CTRL |= DVP_FIFO_SOFT_RESET; + + while(DVP->CTRL & DVP_FIFO_SOFT_RESET); +} diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_exti.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_exti.c new file mode 100644 index 0000000000..e3ffaf50e0 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_exti.c @@ -0,0 +1,286 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_exti.c + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_exti.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup EXTI + * @brief EXTI driver modules + * @{ + */ + +/** @addtogroup EXTI_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup EXTI_Private_Defines + * @{ + */ + +#define EXTI_LINENONE ((uint32_t)0x00000) /* No interrupt selected */ + +/** + * @} + */ + +/** @addtogroup EXTI_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup EXTI_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup EXTI_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup EXTI_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the EXTI peripheral registers to their default reset values. + */ +void EXTI_DeInit(void) +{ + EXTI->IMASK = 0x00000000; + EXTI->EMASK = 0x00000000; + EXTI->RT_CFG = 0x00000000; + EXTI->FT_CFG = 0x00000000; + EXTI->PEND = 0x003FFFFF; +} + +/** + * @brief Initializes the EXTI peripheral according to the specified + * parameters in the EXTI_InitStruct. + * @param EXTI_InitStruct pointer to a EXTI_InitType structure + * that contains the configuration information for the EXTI peripheral. + */ +void EXTI_InitPeripheral(EXTI_InitType* EXTI_InitStruct) +{ + uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_EXTI_MODE(EXTI_InitStruct->EXTI_Mode)); + assert_param(IS_EXTI_TRIGGER(EXTI_InitStruct->EXTI_Trigger)); + assert_param(IS_EXTI_LINE(EXTI_InitStruct->EXTI_Line)); + assert_param(IS_FUNCTIONAL_STATE(EXTI_InitStruct->EXTI_LineCmd)); + + tmp = (uint32_t)EXTI_BASE; + + if (EXTI_InitStruct->EXTI_LineCmd != DISABLE) + { + /* Clear EXTI line configuration */ + EXTI->IMASK &= ~EXTI_InitStruct->EXTI_Line; + EXTI->EMASK &= ~EXTI_InitStruct->EXTI_Line; + + tmp += EXTI_InitStruct->EXTI_Mode; + + *(__IO uint32_t*)tmp |= EXTI_InitStruct->EXTI_Line; + + /* Clear Rising Falling edge configuration */ + EXTI->RT_CFG &= ~EXTI_InitStruct->EXTI_Line; + EXTI->FT_CFG &= ~EXTI_InitStruct->EXTI_Line; + + /* Select the trigger for the selected external interrupts */ + if (EXTI_InitStruct->EXTI_Trigger == EXTI_Trigger_Rising_Falling) + { + /* Rising Falling edge */ + EXTI->RT_CFG |= EXTI_InitStruct->EXTI_Line; + EXTI->FT_CFG |= EXTI_InitStruct->EXTI_Line; + } + else + { + tmp = (uint32_t)EXTI_BASE; + tmp += EXTI_InitStruct->EXTI_Trigger; + + *(__IO uint32_t*)tmp |= EXTI_InitStruct->EXTI_Line; + } + } + else + { + tmp += EXTI_InitStruct->EXTI_Mode; + + /* Disable the selected external lines */ + *(__IO uint32_t*)tmp &= ~EXTI_InitStruct->EXTI_Line; + } +} + +/** + * @brief Fills each EXTI_InitStruct member with its reset value. + * @param EXTI_InitStruct pointer to a EXTI_InitType structure which will + * be initialized. + */ +void EXTI_InitStruct(EXTI_InitType* EXTI_InitStruct) +{ + EXTI_InitStruct->EXTI_Line = EXTI_LINENONE; + EXTI_InitStruct->EXTI_Mode = EXTI_Mode_Interrupt; + EXTI_InitStruct->EXTI_Trigger = EXTI_Trigger_Falling; + EXTI_InitStruct->EXTI_LineCmd = DISABLE; +} + +/** + * @brief Generates a Software interrupt. + * @param EXTI_Line specifies the EXTI lines to be enabled or disabled. + * This parameter can be any combination of EXTI_Linex where x can be (0..19). + */ +void EXTI_TriggerSWInt(uint32_t EXTI_Line) +{ + /* Check the parameters */ + assert_param(IS_EXTI_LINE(EXTI_Line)); + + EXTI->SWIE |= EXTI_Line; +} + +/** + * @brief Checks whether the specified EXTI line flag is set or not. + * @param EXTI_Line specifies the EXTI line flag to check. + * This parameter can be: + * @arg EXTI_Linex External interrupt line x where x(0..19) + * @return The new state of EXTI_Line (SET or RESET). + */ +FlagStatus EXTI_GetStatusFlag(uint32_t EXTI_Line) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_GET_EXTI_LINE(EXTI_Line)); + + if ((EXTI->PEND & EXTI_Line) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the EXTI's line pending flags. + * @param EXTI_Line specifies the EXTI lines flags to clear. + * This parameter can be any combination of EXTI_Linex where x can be (0..19). + */ +void EXTI_ClrStatusFlag(uint32_t EXTI_Line) +{ + /* Check the parameters */ + assert_param(IS_EXTI_LINE(EXTI_Line)); + + EXTI->PEND = EXTI_Line; +} + +/** + * @brief Checks whether the specified EXTI line is asserted or not. + * @param EXTI_Line specifies the EXTI line to check. + * This parameter can be: + * @arg EXTI_Linex External interrupt line x where x(0..19) + * @return The new state of EXTI_Line (SET or RESET). + */ +INTStatus EXTI_GetITStatus(uint32_t EXTI_Line) +{ + INTStatus bitstatus = RESET; + uint32_t enablestatus = 0; + /* Check the parameters */ + assert_param(IS_GET_EXTI_LINE(EXTI_Line)); + + enablestatus = EXTI->IMASK & EXTI_Line; + if (((EXTI->PEND & EXTI_Line) != (uint32_t)RESET) && (enablestatus != (uint32_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the EXTI's line pending bits. + * @param EXTI_Line specifies the EXTI lines to clear. + * This parameter can be any combination of EXTI_Linex where x can be (0..19). + */ +void EXTI_ClrITPendBit(uint32_t EXTI_Line) +{ + /* Check the parameters */ + assert_param(IS_EXTI_LINE(EXTI_Line)); + + EXTI->PEND = EXTI_Line; +} + +/** + * @brief Select one of EXTI inputs to the RTC TimeStamp event. + * @param EXTI_TSSEL_Line specifies the EXTI lines to select. + * This parameter can be any combination of EXTI_TSSEL_Line where x can be (0..15). + */ +void EXTI_RTCTimeStampSel(uint32_t EXTI_TSSEL_Line) +{ + /* Check the parameters */ + assert_param(IS_EXTI_TSSEL_LINE(EXTI_TSSEL_Line)); + + EXTI->TSSEL &= EXTI_TSSEL_TSSEL_ALL; + EXTI->TSSEL |= EXTI_TSSEL_Line; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_flash.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_flash.c new file mode 100644 index 0000000000..fb9833dacc --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_flash.c @@ -0,0 +1,1123 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_flash.c + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_flash.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup FLASH + * @brief FLASH driver modules + * @{ + */ + +/** @addtogroup FLASH_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup FLASH_Private_Defines + * @{ + */ + +/* Flash Access Control Register bits */ +#define AC_LATENCY_MSK ((uint32_t)0x000000F8) +#define AC_PRFTBE_MSK ((uint32_t)0xFFFFFFEF) +#define AC_ICAHEN_MSK ((uint32_t)0xFFFFFF7F) + +/* Flash Access Control Register bits */ +#define AC_PRFTBS_MSK ((uint32_t)0x00000020) +#define AC_ICAHRST_MSK ((uint32_t)0x00000040) + +/* Flash Control Register bits */ +#define CTRL_Set_PG ((uint32_t)0x00000001) +#define CTRL_Reset_PG ((uint32_t)0x00003FFE) +#define CTRL_Set_PER ((uint32_t)0x00000002) +#define CTRL_Reset_PER ((uint32_t)0x00003FFD) +#define CTRL_Set_MER ((uint32_t)0x00000004) +#define CTRL_Reset_MER ((uint32_t)0x00003FFB) +#define CTRL_Set_OPTPG ((uint32_t)0x00000010) +#define CTRL_Reset_OPTPG ((uint32_t)0x00003FEF) +#define CTRL_Set_OPTER ((uint32_t)0x00000020) +#define CTRL_Reset_OPTER ((uint32_t)0x00003FDF) +#define CTRL_Set_START ((uint32_t)0x00000040) +#define CTRL_Set_LOCK ((uint32_t)0x00000080) +#define CTRL_Reset_SMPSEL ((uint32_t)0x00003EFF) +#define CTRL_SMPSEL_SMP1 ((uint32_t)0x00000000) +#define CTRL_SMPSEL_SMP2 ((uint32_t)0x00000100) + +/* FLASH Mask */ +#define RDPRTL1_MSK ((uint32_t)0x00000002) +#define RDPRTL2_MSK ((uint32_t)0x80000000) +#define OBR_USER_MSK ((uint32_t)0x0000001C) +#define WRP0_MSK ((uint32_t)0x000000FF) +#define WRP1_MSK ((uint32_t)0x0000FF00) +#define WRP2_MSK ((uint32_t)0x00FF0000) +#define WRP3_MSK ((uint32_t)0xFF000000) + +/* FLASH Keys */ +#define L1_RDP_Key ((uint32_t)0xFFFF00A5) +#define RDP_USER_Key ((uint32_t)0xFFF800A5) +#define L2_RDP_Key ((uint32_t)0xFFFF33CC) +#define FLASH_KEY1 ((uint32_t)0x45670123) +#define FLASH_KEY2 ((uint32_t)0xCDEF89AB) + +/* Delay definition */ +#define EraseTimeout ((uint32_t)0x000B0000) +#define ProgramTimeout ((uint32_t)0x00002000) +/** + * @} + */ + +/** @addtogroup FLASH_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup FLASH_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup FLASH_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup FLASH_Private_Functions + * @{ + */ + +/** + * @brief Sets the code latency value. + * @note This function can be used for N32G4FR devices. + * @param FLASH_Latency specifies the FLASH Latency value. + * This parameter can be one of the following values: + * @arg FLASH_LATENCY_0 FLASH Zero Latency cycle + * @arg FLASH_LATENCY_1 FLASH One Latency cycle + * @arg FLASH_LATENCY_2 FLASH Two Latency cycles + * @arg FLASH_LATENCY_3 FLASH Three Latency cycles + * @arg FLASH_LATENCY_4 FLASH Four Latency cycles + */ +void FLASH_SetLatency(uint32_t FLASH_Latency) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_FLASH_LATENCY(FLASH_Latency)); + + /* Read the AC register */ + tmpregister = FLASH->AC; + + /* Sets the Latency value */ + tmpregister &= AC_LATENCY_MSK; + tmpregister |= FLASH_Latency; + + /* Write the AC register */ + FLASH->AC = tmpregister; +} + +/** + * @brief Enables or disables the Prefetch Buffer. + * @note This function can be used for N32G4FR devices. + * @param FLASH_PrefetchBuf specifies the Prefetch buffer status. + * This parameter can be one of the following values: + * @arg FLASH_PrefetchBuf_EN FLASH Prefetch Buffer Enable + * @arg FLASH_PrefetchBuf_DIS FLASH Prefetch Buffer Disable + */ +void FLASH_PrefetchBufSet(uint32_t FLASH_PrefetchBuf) +{ + /* Check the parameters */ + assert_param(IS_FLASH_PREFETCHBUF_STATE(FLASH_PrefetchBuf)); + + /* Enable or disable the Prefetch Buffer */ + FLASH->AC &= AC_PRFTBE_MSK; + FLASH->AC |= FLASH_PrefetchBuf; +} + +/** + * @brief ICache Reset. + * @note This function can be used for N32G4FR devices. + */ +void FLASH_iCacheRST(void) +{ + /* ICache Reset */ + FLASH->AC |= FLASH_AC_ICAHRST; +} + +/** + * @brief Enables or disables the iCache. + * @note This function can be used for N32G4FR devices. + * @param FLASH_iCache specifies the iCache status. + * This parameter can be one of the following values: + * @arg FLASH_iCache_EN FLASH iCache Enable + * @arg FLASH_iCache_DIS FLASH iCache Disable + */ +void FLASH_iCacheCmd(uint32_t FLASH_iCache) +{ + /* Check the parameters */ + assert_param(IS_FLASH_ICACHE_STATE(FLASH_iCache)); + + /* Enable or disable the iCache */ + FLASH->AC &= AC_ICAHEN_MSK; + FLASH->AC |= FLASH_iCache; +} + +/** + * @brief Checks whether the FLASH SMPSEL is SMP1 or SMP2. + * @note This function can be used for N32G4FR devices. + * @param FLASH_smpsel FLASH_SMP1 or FLASH_SMP2 + * @return FLASH_SMPSEL_SMP1 or FLASH_SMPSEL_SMP2. + */ +void FLASH_SetSMPSELStatus(uint32_t FLASH_smpsel) +{ + /* Check the parameters */ + assert_param(IS_FLASH_SMPSEL_STATE(FLASH_smpsel)); + + /* SMP1 or SMP2 */ + FLASH->CTRL &= CTRL_Reset_SMPSEL; + FLASH->CTRL |= FLASH_smpsel; +} + +/** + * @brief Unlocks the FLASH Program Erase Controller. + * @note This function can be used for N32G4FR devices. + * - For N32G4FR devices this function unlocks Bank1. + * to FLASH_UnlockBank1 function.. + */ +void FLASH_Unlock(void) +{ + /* Authorize the FPEC of Bank1 Access */ + FLASH->KEY = FLASH_KEY1; + FLASH->KEY = FLASH_KEY2; +} + +/** + * @brief Locks the FLASH Program Erase Controller. + * @note This function can be used for N32G4FR devices. + * - For N32G4FR devices this function Locks Bank1. + * to FLASH_LockBank1 function. + */ +void FLASH_Lock(void) +{ + /* Set the Lock Bit to lock the FPEC and the CTRL of Bank1 */ + FLASH->CTRL |= CTRL_Set_LOCK; +} + +/** + * @brief Erases a specified FLASH page. + * @note This function can be used for N32G4FR devices. + * @param Page_Address The page address to be erased. + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_EraseOnePage(uint32_t Page_Address) +{ + FLASH_STS status = FLASH_COMPL; + /* Check the parameters */ + assert_param(IS_FLASH_ADDRESS(Page_Address)); + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* if the previous operation is completed, proceed to erase the page */ + FLASH->CTRL |= CTRL_Set_PER; + FLASH->ADD = Page_Address; + FLASH->CTRL |= CTRL_Set_START; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + /* Disable the PER Bit */ + FLASH->CTRL &= CTRL_Reset_PER; + } + + /* Return the Erase Status */ + return status; +} + +/** + * @brief Erases all FLASH pages. + * @note This function can be used for all N32G4FR devices. + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_MassErase(void) +{ + FLASH_STS status = FLASH_COMPL; + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* if the previous operation is completed, proceed to erase all pages */ + FLASH->CTRL |= CTRL_Set_MER; + FLASH->CTRL |= CTRL_Set_START; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + /* Disable the MER Bit */ + FLASH->CTRL &= CTRL_Reset_MER; + } + + /* Return the Erase Status */ + return status; +} + +/** + * @brief Erases the FLASH option bytes. + * @note This functions erases all option bytes except the Read protection (RDP). + * @note This function can be used for N32G4FR devices. + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV, FLASH_ERR_RDP2 or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_EraseOB(void) +{ + uint32_t rdptmp = L1_RDP_Key; + + FLASH_STS status = FLASH_COMPL; + + /* Get the actual read protection L2 Option Byte value */ + if (FLASH_GetReadOutProtectionL2STS() != RESET) + { + status = FLASH_ERR_RDP2; + return status; + } + + /* Get the actual read protection Option Byte value */ + if (FLASH_GetReadOutProtectionSTS() != RESET) + { + rdptmp = (L1_RDP_Key & FLASH_USER_USER); + } + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* Authorize the small information block programming */ + FLASH->OPTKEY = FLASH_KEY1; + FLASH->OPTKEY = FLASH_KEY2; + + /* if the previous operation is completed, proceed to erase the option bytes */ + FLASH->CTRL |= CTRL_Set_OPTER; + FLASH->CTRL |= CTRL_Set_START; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + + /* if the erase operation is completed, disable the OPTER Bit */ + FLASH->CTRL &= CTRL_Reset_OPTER; + + /* Enable the Option Bytes Programming operation */ + FLASH->CTRL |= CTRL_Set_OPTPG; + /* Restore the last read protection Option Byte value */ + OB->USER_RDP = (uint32_t)rdptmp; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + + if (status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CTRL &= CTRL_Reset_OPTPG; + } + } + else + { + if (status != FLASH_TIMEOUT) + { + /* Disable the OPTER Bit */ + FLASH->CTRL &= CTRL_Reset_OPTER; + } + } + } + /* Return the erase status */ + return status; +} + +/** + * @brief Programs a word at a specified address. + * @note This function can be used for N32G4FR devices. + * @param Address specifies the address to be programmed. + * @param Data specifies the data to be programmed. + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV, FLASH_ERR_ADD or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_ProgramWord(uint32_t Address, uint32_t Data) +{ + FLASH_STS status = FLASH_COMPL; + + /* Check the parameters */ + assert_param(IS_FLASH_ADDRESS(Address)); + + if((Address & (uint32_t)0x3) != 0) + { + /* The programming address is not a multiple of 4 */ + status = FLASH_ERR_ADD; + return status; + } + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + + if (status == FLASH_COMPL) + { + /* if the previous operation is completed, proceed to program the new word */ + FLASH->CTRL |= CTRL_Set_PG; + + *(__IO uint32_t*)Address = (uint32_t)Data; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + + /* Disable the PG Bit */ + FLASH->CTRL &= CTRL_Reset_PG; + } + + /* Return the Program Status */ + return status; +} + +/** + * @brief Programs a half word at a specified Option Byte Data address. + * @note This function can be used for N32G4FR devices. + * @param Address specifies the address to be programmed. + * This parameter can be 0x1FFFF804. + * @param Data specifies the data to be programmed(Data0 and Data1). + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV, FLASH_ERR_RDP2 or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_ProgramOBData(uint32_t Address, uint32_t Data) +{ + FLASH_STS status = FLASH_COMPL; + /* Check the parameters */ + assert_param(IS_OB_DATA_ADDRESS(Address)); + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + + /* Get the actual read protection L2 Option Byte value */ + if (FLASH_GetReadOutProtectionL2STS() != RESET) + { + status = FLASH_ERR_RDP2; + return status; + } + + if (status == FLASH_COMPL) + { + /* Authorize the small information block programming */ + FLASH->OPTKEY = FLASH_KEY1; + FLASH->OPTKEY = FLASH_KEY2; + /* Enables the Option Bytes Programming operation */ + FLASH->CTRL |= CTRL_Set_OPTPG; + *(__IO uint32_t*)Address = (uint32_t)Data; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + if (status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CTRL &= CTRL_Reset_OPTPG; + } + } + /* Return the Option Byte Data Program Status */ + return status; +} + +/** + * @brief Write protects the desired pages + * @note This function can be used for N32G4FR devices. + * @param FLASH_Pages specifies the address of the pages to be write protected. + * This parameter can be: + * @arg For @b N32G4FR_devices: value between FLASH_WRP_Pages0to1 and + * FLASH_WRP_Pages60to61 or FLASH_WRP_Pages62to255 + * @arg FLASH_WRP_AllPages + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV, FLASH_ERR_RDP2 or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_EnWriteProtection(uint32_t FLASH_Pages) +{ + uint16_t WRP0_Data = 0xFFFF, WRP1_Data = 0xFFFF, WRP2_Data = 0xFFFF, WRP3_Data = 0xFFFF; + + FLASH_STS status = FLASH_COMPL; + + /* Check the parameters */ + assert_param(IS_FLASH_WRP_PAGE(FLASH_Pages)); + + /* Get the actual read protection L2 Option Byte value */ + if (FLASH_GetReadOutProtectionL2STS() != RESET) + { + status = FLASH_ERR_RDP2; + return status; + } + + FLASH_Pages = (uint32_t)(~FLASH_Pages); + WRP0_Data = (uint16_t)(FLASH_Pages & WRP0_MSK); + WRP1_Data = (uint16_t)((FLASH_Pages & WRP1_MSK) >> 8); + WRP2_Data = (uint16_t)((FLASH_Pages & WRP2_MSK) >> 16); + WRP3_Data = (uint16_t)((FLASH_Pages & WRP3_MSK) >> 24); + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + + if (status == FLASH_COMPL) + { + /* Authorizes the small information block programming */ + FLASH->OPTKEY = FLASH_KEY1; + FLASH->OPTKEY = FLASH_KEY2; + FLASH->CTRL |= CTRL_Set_OPTPG; + + if ((WRP0_Data != 0xFF) || (WRP1_Data != 0xFF)) + { + OB->WRP1_WRP0 = (((uint32_t)WRP0_Data) | (((uint32_t)WRP1_Data) << 16)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + } + + if (((WRP2_Data != 0xFF) || (WRP3_Data != 0xFF)) && (status == FLASH_COMPL)) + { + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + + OB->WRP3_WRP2 = (((uint32_t)WRP2_Data) | (((uint32_t)WRP3_Data) << 16)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + } + + if (status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CTRL &= CTRL_Reset_OPTPG; + } + } + /* Return the write protection operation Status */ + return status; +} + +/** + * @brief Enables or disables the read out protection. + * @note If the user has already programmed the other option bytes before calling + * this function, he must re-program them since this function erases all option bytes. + * @note This function can be used for N32G4FR devices. + * @param Cmd new state of the ReadOut Protection. + * This parameter can be: ENABLE or DISABLE. + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV, FLASH_ERR_RDP2 or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_ReadOutProtectionL1(FunctionalState Cmd) +{ + uint32_t usertmp; + FLASH_STS status = FLASH_COMPL; + + usertmp = ((OBR_USER_MSK & FLASH->OBR) << 0x0E); + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Get the actual read protection L2 Option Byte value */ + if (FLASH_GetReadOutProtectionL2STS() != RESET) + { + status = FLASH_ERR_RDP2; + return status; + } + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* Authorizes the small information block programming */ + FLASH->OPTKEY = FLASH_KEY1; + FLASH->OPTKEY = FLASH_KEY2; + FLASH->CTRL |= CTRL_Set_OPTER; + FLASH->CTRL |= CTRL_Set_START; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + if (status == FLASH_COMPL) + { + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + + /* if the erase operation is completed, disable the OPTER Bit */ + FLASH->CTRL &= CTRL_Reset_OPTER; + /* Enable the Option Bytes Programming operation */ + FLASH->CTRL |= CTRL_Set_OPTPG; + if (Cmd != DISABLE) + { + OB->USER_RDP = (FLASH_USER_USER & usertmp); + } + else + { + OB->USER_RDP = ((L1_RDP_Key & FLASH_RDP_RDP1) | usertmp); + } + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CTRL &= CTRL_Reset_OPTPG; + } + } + else + { + if (status != FLASH_TIMEOUT) + { + /* Disable the OPTER Bit */ + FLASH->CTRL &= CTRL_Reset_OPTER; + } + } + } + /* Return the protection operation Status */ + return status; +} + +/** + * @brief Enables or disables the read out protection L2. + * @note If the user has already programmed the other option bytes before calling + * this function, he must re-program them since this function erases all option bytes. + * @note This function can be used for N32G4FR devices. + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV, FLASH_ERR_RDP2 or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_ReadOutProtectionL2_ENABLE(void) +{ + uint32_t usertmp; + FLASH_STS status = FLASH_COMPL; + + usertmp = ((OBR_USER_MSK & FLASH->OBR) << 0x0E); + + /* Get the actual read protection L1 Option Byte value */ + if (FLASH_GetReadOutProtectionSTS() == RESET) + { + usertmp |= (L1_RDP_Key & FLASH_RDP_RDP1); + } + /* Get the actual read protection L2 Option Byte value */ + if (FLASH_GetReadOutProtectionL2STS() != RESET) + { + status = FLASH_ERR_RDP2; + return status; + } + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* Authorizes the small information block programming */ + FLASH->OPTKEY = FLASH_KEY1; + FLASH->OPTKEY = FLASH_KEY2; + FLASH->CTRL |= CTRL_Set_OPTER; + FLASH->CTRL |= CTRL_Set_START; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + if (status == FLASH_COMPL) + { + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + + /* if the erase operation is completed, disable the OPTER Bit */ + FLASH->CTRL &= CTRL_Reset_OPTER; + /* Enable the Option Bytes Programming operation */ + FLASH->CTRL |= CTRL_Set_OPTPG; + + OB->USER_RDP = usertmp; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + + /* Enables the read out protection L2 */ + OB->RDP2 = L2_RDP_Key; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + } + + if (status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CTRL &= CTRL_Reset_OPTPG; + } + } + else + { + if (status != FLASH_TIMEOUT) + { + /* Disable the OPTER Bit */ + FLASH->CTRL &= CTRL_Reset_OPTER; + } + } + } + /* Return the protection operation Status */ + return status; +} + +/** + * @brief Programs the FLASH User Option Byte: IWDG_SW / RST_STOP / RST_STDBY. + * @note This function can be used for N32G4FR devices. + * @param OB_IWDG Selects the IWDG mode + * This parameter can be one of the following values: + * @arg OB_IWDG_SW Software IWDG selected + * @arg OB_IWDG_HW Hardware IWDG selected + * @param OB_STOP Reset event when entering STOP mode. + * This parameter can be one of the following values: + * @arg OB_STOP0_NORST No reset generated when entering in STOP + * @arg OB_STOP0_RST Reset generated when entering in STOP + * @param OB_STDBY Reset event when entering Standby mode. + * This parameter can be one of the following values: + * @arg OB_STDBY_NORST No reset generated when entering in STANDBY + * @arg OB_STDBY_RST Reset generated when entering in STANDBY + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV, FLASH_ERR_RDP2 or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_ConfigUserOB(uint16_t OB_IWDG, uint16_t OB_STOP, uint16_t OB_STDBY) +{ + uint32_t rdptmp = RDP_USER_Key; + + FLASH_STS status = FLASH_COMPL; + + /* Check the parameters */ + assert_param(IS_OB_IWDG_SOURCE(OB_IWDG)); + assert_param(IS_OB_STOP0_SOURCE(OB_STOP)); + assert_param(IS_OB_STDBY_SOURCE(OB_STDBY)); + + /* Get the actual read protection L2 Option Byte value */ + if (FLASH_GetReadOutProtectionL2STS() != RESET) + { + status = FLASH_ERR_RDP2; + return status; + } + + /* Get the actual read protection Option Byte value */ + if (FLASH_GetReadOutProtectionSTS() != RESET) + { + rdptmp = 0xFFF80000; + } + + /* Authorize the small information block programming */ + FLASH->OPTKEY = FLASH_KEY1; + FLASH->OPTKEY = FLASH_KEY2; + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* if the previous operation is completed, proceed to erase the option bytes */ + FLASH->CTRL |= CTRL_Set_OPTER; + FLASH->CTRL |= CTRL_Set_START; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + + /* if the erase operation is completed, disable the OPTER Bit */ + FLASH->CTRL &= CTRL_Reset_OPTER; + + /* Enable the Option Bytes Programming operation */ + FLASH->CTRL |= CTRL_Set_OPTPG; + /* Restore the last read protection Option Byte value */ + OB->USER_RDP = + (uint32_t)rdptmp + | ((uint32_t)(OB_IWDG | (uint32_t)(OB_STOP | (uint32_t)(OB_STDBY | ((uint32_t)0xF8)))) << 16); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + + if (status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CTRL &= CTRL_Reset_OPTPG; + } + } + else + { + if (status != FLASH_TIMEOUT) + { + /* Disable the OPTER Bit */ + FLASH->CTRL &= CTRL_Reset_OPTER; + } + } + } + + /* Return the Option Byte program Status */ + return status; +} + +/** + * @brief Returns the FLASH User Option Bytes values. + * @note This function can be used for N32G4FR devices. + * @return The FLASH User Option Bytes values:IWDG_SW(Bit0), RST_STOP(Bit1) + * and RST_STDBY(Bit2). + */ +uint32_t FLASH_GetUserOB(void) +{ + /* Return the User Option Byte */ + return (uint32_t)((FLASH->OBR << 27) >> 29); +} + +/** + * @brief Returns the FLASH Write Protection Option Bytes Register value. + * @note This function can be used for N32G4FR devices. + * @return The FLASH Write Protection Option Bytes Register value + */ +uint32_t FLASH_GetWriteProtectionOB(void) +{ + /* Return the Flash write protection Register value */ + return (uint32_t)(FLASH->WRP); +} + +/** + * @brief Checks whether the FLASH Read Out Protection Status is set or not. + * @note This function can be used for N32G4FR devices. + * @return FLASH ReadOut Protection Status(SET or RESET) + */ +FlagStatus FLASH_GetReadOutProtectionSTS(void) +{ + FlagStatus readoutstatus = RESET; + if ((FLASH->OBR & RDPRTL1_MSK) != (uint32_t)RESET) + { + readoutstatus = SET; + } + else + { + readoutstatus = RESET; + } + return readoutstatus; +} + +/** + * @brief Checks whether the FLASH Read Out Protection L2 Status is set or not. + * @note This function can be used for N32G4FR devices. + * @return FLASH ReadOut Protection L2 Status(SET or RESET) + */ +FlagStatus FLASH_GetReadOutProtectionL2STS(void) +{ + FlagStatus readoutstatus = RESET; + if ((FLASH->OBR & RDPRTL2_MSK) != (uint32_t)RESET) + { + readoutstatus = SET; + } + else + { + readoutstatus = RESET; + } + return readoutstatus; +} + +/** + * @brief Checks whether the FLASH Prefetch Buffer status is set or not. + * @note This function can be used for N32G4FR devices. + * @return FLASH Prefetch Buffer Status (SET or RESET). + */ +FlagStatus FLASH_GetPrefetchBufSTS(void) +{ + FlagStatus bitstatus = RESET; + + if ((FLASH->AC & AC_PRFTBS_MSK) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + /* Return the new state of FLASH Prefetch Buffer Status (SET or RESET) */ + return bitstatus; +} + +/** + * @brief Checks whether the FLASH SMPSEL is SMP1 or SMP2. + * @note This function can be used for N32G4FR devices. + * @return FLASH SMPSEL (FLASH_SMP1 or FLASH_SMP2). + */ +FLASH_SMPSEL FLASH_GetSMPSELStatus(void) +{ + FLASH_SMPSEL bitstatus = FLASH_SMP1; + + if ((FLASH->CTRL & CTRL_SMPSEL_SMP2) != (uint32_t)FLASH_SMP1) + { + bitstatus = FLASH_SMP2; + } + else + { + bitstatus = FLASH_SMP1; + } + /* Return the new state of FLASH SMPSEL (FLASH_SMP1 or FLASH_SMP2) */ + return bitstatus; +} + +/** + * @brief Enables or disables the specified FLASH interrupts. + * @note This function can be used for N32G4FR devices. + * @param FLASH_INT specifies the FLASH interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg FLASH_IT_ERROR FLASH Error Interrupt + * @arg FLASH_INT_FERR EVERR PVERR Interrupt + * @arg FLASH_INT_EOP FLASH end of operation Interrupt + * @param Cmd new state of the specified Flash interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void FLASH_INTConfig(uint32_t FLASH_INT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FLASH_INT(FLASH_INT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the interrupt sources */ + FLASH->CTRL |= FLASH_INT; + } + else + { + /* Disable the interrupt sources */ + FLASH->CTRL &= ~(uint32_t)FLASH_INT; + } +} + +/** + * @brief Checks whether the specified FLASH flag is set or not. + * @note This function can be used for N32G4FR devices. + * @param FLASH_FLAG specifies the FLASH flag to check. + * This parameter can be one of the following values: + * @arg FLASH_FLAG_BUSY FLASH Busy flag + * @arg FLASH_FLAG_PGERR FLASH Program error flag + * @arg FLASH_FLAG_PVERR FLASH Program Verify ERROR flag + * @arg FLASH_FLAG_WRPERR FLASH Write protected error flag + * @arg FLASH_FLAG_EOP FLASH End of Operation flag + * @arg FLASH_FLAG_EVERR FLASH Erase Verify ERROR flag + * @arg FLASH_FLAG_OBERR FLASH Option Byte error flag + * @return The new state of FLASH_FLAG (SET or RESET). + */ +FlagStatus FLASH_GetFlagSTS(uint32_t FLASH_FLAG) +{ + FlagStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_FLASH_GET_FLAG(FLASH_FLAG)); + if (FLASH_FLAG == FLASH_FLAG_OBERR) + { + if ((FLASH->OBR & FLASH_FLAG_OBERR) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + else + { + if ((FLASH->STS & FLASH_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + + /* Return the new state of FLASH_FLAG (SET or RESET) */ + return bitstatus; +} + +/** + * @brief Clears the FLASH's pending flags. + * @note This function can be used for N32G4FR devices. + * @param FLASH_FLAG specifies the FLASH flags to clear. + * This parameter can be any combination of the following values: + * @arg FLASH_FLAG_PGERR FLASH Program error flag + * @arg FLASH_FLAG_PVERR FLASH Program Verify ERROR flag + * @arg FLASH_FLAG_WRPERR FLASH Write protected error flag + * @arg FLASH_FLAG_EOP FLASH End of Operation flag + * @arg FLASH_FLAG_EVERR FLASH Erase Verify ERROR flag + */ +void FLASH_ClearFlag(uint32_t FLASH_FLAG) +{ + /* Check the parameters */ + assert_param(IS_FLASH_CLEAR_FLAG(FLASH_FLAG)); + + /* Clear the flags */ + FLASH->STS |= FLASH_FLAG; +} + +/** + * @brief Returns the FLASH Status. + * @note This function can be used for N32G4FR devices, it is equivalent + * to FLASH_GetBank1Status function. + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_GetSTS(void) +{ + FLASH_STS flashstatus = FLASH_COMPL; + + if ((FLASH->STS & FLASH_FLAG_BUSY) == FLASH_FLAG_BUSY) + { + flashstatus = FLASH_BUSY; + } + else + { + if ((FLASH->STS & FLASH_FLAG_PGERR) != 0) + { + flashstatus = FLASH_ERR_PG; + } + else + { + if ((FLASH->STS & FLASH_FLAG_PVERR) != 0) + { + flashstatus = FLASH_ERR_PV; + } + else + { + if ((FLASH->STS & FLASH_FLAG_WRPERR) != 0) + { + flashstatus = FLASH_ERR_WRP; + } + else + { + if ((FLASH->STS & FLASH_FLAG_EVERR) != 0) + { + flashstatus = FLASH_ERR_EV; + } + else + { + flashstatus = FLASH_COMPL; + } + } + } + } + } + + /* Return the Flash Status */ + return flashstatus; +} + +/** + * @brief Waits for a Flash operation to complete or a TIMEOUT to occur. + * @note This function can be used for N32G4FR devices, + * it is equivalent to FLASH_WaitForLastBank1Operation.. + * @param Timeout FLASH programming Timeout + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_WaitForLastOpt(uint32_t Timeout) +{ + FLASH_STS status = FLASH_COMPL; + + /* Check for the Flash Status */ + status = FLASH_GetSTS(); + /* Wait for a Flash operation to complete or a TIMEOUT to occur */ + while ((status == FLASH_BUSY) && (Timeout != 0x00)) + { + status = FLASH_GetSTS(); + Timeout--; + } + if (Timeout == 0x00) + { + status = FLASH_TIMEOUT; + } + /* Return the operation status */ + return status; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_gpio.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_gpio.c new file mode 100644 index 0000000000..ad17a3f93a --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_gpio.c @@ -0,0 +1,852 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_gpio.c + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_gpio.h" +#include "n32g4fr_rcc.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup GPIO + * @brief GPIO driver modules + * @{ + */ + +/** @addtogroup GPIO_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup GPIO_Private_Defines + * @{ + */ + +/* ------------ RCC registers bit address in the alias region ----------------*/ +#define AFIO_OFFSET (AFIO_BASE - PERIPH_BASE) + +/* --- Event control register -----*/ + +/* Alias word address of EVOE bit */ +#define EVCR_OFFSET (AFIO_OFFSET + 0x00) +#define EVOE_BitNumber ((uint8_t)0x07) +#define EVCR_EVOE_BB (PERIPH_BB_BASE + (EVCR_OFFSET * 32) + (EVOE_BitNumber * 4)) + +/* --- RMP_CFG Register ---*/ +/* Alias word address of MII_RMII_SEL bit */ +#define MAPR_OFFSET (AFIO_OFFSET + 0x04) +#define MII_RMII_SEL_BitNumber ((u8)0x17) +#define MAPR_MII_RMII_SEL_BB (PERIPH_BB_BASE + (MAPR_OFFSET * 32) + (MII_RMII_SEL_BitNumber * 4)) + +#define EVCR_PORTPINCONFIG_MASK ((uint16_t)0xFF80) +#define LSB_MASK ((uint16_t)0xFFFF) +#define DBGAFR_POSITION_MASK ((uint32_t)0x000F0000) +#define DBGAFR_SWJCFG_MASK ((uint32_t)0xF0FFFFFF) +#define DBGAFR_LOCATION_MASK ((uint32_t)0x00200000) +#define DBGAFR_NUMBITS_MASK ((uint32_t)0x00100000) +#define DBGAFR_NUMBITS_MAPR3_MASK ((uint32_t)0x40000000) +#define DBGAFR_NUMBITS_MAPR4_MASK ((uint32_t)0x20000000) +#define DBGAFR_NUMBITS_MAPR5_MASK ((uint32_t)0x10000000) +#define DBGAFR_NUMBITS_SPI1_MASK ((uint32_t)0x01000000) +#define DBGAFR_NUMBITS_USART2_MASK ((uint32_t)0x04000000) + +/** + * @} + */ + +/** @addtogroup GPIO_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup GPIO_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup GPIO_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup GPIO_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the GPIOx peripheral registers to their default reset values. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + */ +void GPIO_DeInit(GPIO_Module* GPIOx) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + if (GPIOx == GPIOA) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOA, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOA, DISABLE); + } + else if (GPIOx == GPIOB) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOB, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOB, DISABLE); + } + else if (GPIOx == GPIOC) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOC, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOC, DISABLE); + } + else if (GPIOx == GPIOD) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOD, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOD, DISABLE); + } + else if (GPIOx == GPIOE) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOE, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOE, DISABLE); + } + else + { + } +} + +/** + * @brief Deinitializes the Alternate Functions (remap, event control + * and EXTI configuration) registers to their default reset values. + */ +void GPIO_AFIOInitDefault(void) +{ + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_AFIO, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_AFIO, DISABLE); +} + +/** + * @brief Initializes the GPIOx peripheral according to the specified + * parameters in the GPIO_InitStruct. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @param GPIO_InitStruct pointer to a GPIO_InitType structure that + * contains the configuration information for the specified GPIO peripheral. + */ +void GPIO_InitPeripheral(GPIO_Module* GPIOx, GPIO_InitType* GPIO_InitStruct) +{ + uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00; + uint32_t tmpregister = 0x00, pinmask = 0x00; + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode)); + assert_param(IS_GPIO_PIN(GPIO_InitStruct->Pin)); + + /*---------------------------- GPIO Mode Configuration -----------------------*/ + currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F); + if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00) + { + /* Check the parameters */ + assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed)); + /* Output mode */ + currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed; + } + /*---------------------------- GPIO PL_CFG Configuration ------------------------*/ + /* Configure the eight low port pins */ + if (((uint32_t)GPIO_InitStruct->Pin & ((uint32_t)0x00FF)) != 0x00) + { + tmpregister = GPIOx->PL_CFG; + for (pinpos = 0x00; pinpos < 0x08; pinpos++) + { + pos = ((uint32_t)0x01) << pinpos; + /* Get the port pins position */ + currentpin = (GPIO_InitStruct->Pin) & pos; + if (currentpin == pos) + { + pos = pinpos << 2; + /* Clear the corresponding low control register bits */ + pinmask = ((uint32_t)0x0F) << pos; + tmpregister &= ~pinmask; + /* Write the mode configuration in the corresponding bits */ + tmpregister |= (currentmode << pos); + /* Reset the corresponding POD bit */ + if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) + { + GPIOx->PBC = (((uint32_t)0x01) << pinpos); + } + else + { + /* Set the corresponding POD bit */ + if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU) + { + GPIOx->PBSC = (((uint32_t)0x01) << pinpos); + } + } + } + } + GPIOx->PL_CFG = tmpregister; + } + /*---------------------------- GPIO PH_CFG Configuration ------------------------*/ + /* Configure the eight high port pins */ + if (GPIO_InitStruct->Pin > 0x00FF) + { + tmpregister = GPIOx->PH_CFG; + for (pinpos = 0x00; pinpos < 0x08; pinpos++) + { + pos = (((uint32_t)0x01) << (pinpos + 0x08)); + /* Get the port pins position */ + currentpin = ((GPIO_InitStruct->Pin) & pos); + if (currentpin == pos) + { + pos = pinpos << 2; + /* Clear the corresponding high control register bits */ + pinmask = ((uint32_t)0x0F) << pos; + tmpregister &= ~pinmask; + /* Write the mode configuration in the corresponding bits */ + tmpregister |= (currentmode << pos); + /* Reset the corresponding POD bit */ + if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) + { + GPIOx->PBC = (((uint32_t)0x01) << (pinpos + 0x08)); + } + /* Set the corresponding POD bit */ + if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU) + { + GPIOx->PBSC = (((uint32_t)0x01) << (pinpos + 0x08)); + } + } + } + GPIOx->PH_CFG = tmpregister; + } +} + +/** + * @brief Fills each GPIO_InitStruct member with its default value. + * @param GPIO_InitStruct pointer to a GPIO_InitType structure which will + * be initialized. + */ +void GPIO_InitStruct(GPIO_InitType* GPIO_InitStruct) +{ + /* Reset GPIO init structure parameters values */ + GPIO_InitStruct->Pin = GPIO_PIN_ALL; + GPIO_InitStruct->GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStruct->GPIO_Mode = GPIO_Mode_IN_FLOATING; +} + +/** + * @brief Reads the specified input port pin. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @param Pin specifies the port bit to read. + * This parameter can be GPIO_Pin_x where x can be (0..15). + * @return The input port pin value. + */ +uint8_t GPIO_ReadInputDataBit(GPIO_Module* GPIOx, uint16_t Pin) +{ + uint8_t bitstatus = 0x00; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GET_GPIO_PIN(Pin)); + + if ((GPIOx->PID & Pin) != (uint32_t)Bit_RESET) + { + bitstatus = (uint8_t)Bit_SET; + } + else + { + bitstatus = (uint8_t)Bit_RESET; + } + return bitstatus; +} + +/** + * @brief Reads the specified GPIO input data port. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @return GPIO input data port value. + */ +uint16_t GPIO_ReadInputData(GPIO_Module* GPIOx) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + return ((uint16_t)GPIOx->PID); +} + +/** + * @brief Reads the specified output data port bit. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @param Pin specifies the port bit to read. + * This parameter can be GPIO_Pin_x where x can be (0..15). + * @return The output port pin value. + */ +uint8_t GPIO_ReadOutputDataBit(GPIO_Module* GPIOx, uint16_t Pin) +{ + uint8_t bitstatus = 0x00; + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GET_GPIO_PIN(Pin)); + + if ((GPIOx->POD & Pin) != (uint32_t)Bit_RESET) + { + bitstatus = (uint8_t)Bit_SET; + } + else + { + bitstatus = (uint8_t)Bit_RESET; + } + return bitstatus; +} + +/** + * @brief Reads the specified GPIO output data port. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @return GPIO output data port value. + */ +uint16_t GPIO_ReadOutputData(GPIO_Module* GPIOx) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + return ((uint16_t)GPIOx->POD); +} + +/** + * @brief Sets the selected data port bits. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @param Pin specifies the port bits to be written. + * This parameter can be any combination of GPIO_Pin_x where x can be (0..15). + */ +void GPIO_SetBits(GPIO_Module* GPIOx, uint16_t Pin) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GPIO_PIN(Pin)); + + GPIOx->PBSC = Pin; +} +void GPIO_SetBitsHigh16(GPIO_Module* GPIOx, uint32_t Pin) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + // assert_param(IS_GPIO_PIN(Pin)); + + GPIOx->PBSC = Pin; +} + +/** + * @brief Clears the selected data port bits. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @param Pin specifies the port bits to be written. + * This parameter can be any combination of GPIO_Pin_x where x can be (0..15). + */ +void GPIO_ResetBits(GPIO_Module* GPIOx, uint16_t Pin) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GPIO_PIN(Pin)); + + GPIOx->PBC = Pin; +} + +/** + * @brief Sets or clears the selected data port bit. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @param Pin specifies the port bit to be written. + * This parameter can be one of GPIO_Pin_x where x can be (0..15). + * @param BitCmd specifies the value to be written to the selected bit. + * This parameter can be one of the Bit_OperateType enum values: + * @arg Bit_RESET to clear the port pin + * @arg Bit_SET to set the port pin + */ +void GPIO_WriteBit(GPIO_Module* GPIOx, uint16_t Pin, Bit_OperateType BitCmd) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GET_GPIO_PIN(Pin)); + assert_param(IS_GPIO_BIT_OPERATE(BitCmd)); + + if (BitCmd != Bit_RESET) + { + GPIOx->PBSC = Pin; + } + else + { + GPIOx->PBC = Pin; + } +} + +/** + * @brief Writes data to the specified GPIO data port. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @param PortVal specifies the value to be written to the port output data register. + */ +void GPIO_Write(GPIO_Module* GPIOx, uint16_t PortVal) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + GPIOx->POD = PortVal; +} + +/** + * @brief Locks GPIO Pins configuration registers. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @param Pin specifies the port bit to be written. + * This parameter can be any combination of GPIO_Pin_x where x can be (0..15). + */ +void GPIO_ConfigPinLock(GPIO_Module* GPIOx, uint16_t Pin) +{ + uint32_t tmp = 0x00010000; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GPIO_PIN(Pin)); + + tmp |= Pin; + /* Set LCKK bit */ + GPIOx->PLOCK_CFG = tmp; + /* Reset LCKK bit */ + GPIOx->PLOCK_CFG = Pin; + /* Set LCKK bit */ + GPIOx->PLOCK_CFG = tmp; + /* Read LCKK bit*/ + tmp = GPIOx->PLOCK_CFG; + /* Read LCKK bit*/ + tmp = GPIOx->PLOCK_CFG; +} + +/** + * @brief Selects the GPIO pin used as Event output. + * @param PortSource selects the GPIO port to be used as source + * for Event output. + * This parameter can be GPIO_PortSourceGPIOx where x can be (A..E). + * @param PinSource specifies the pin for the Event output. + * This parameter can be GPIO_PinSourcex where x can be (0..15). + */ +void GPIO_ConfigEventOutput(uint8_t PortSource, uint8_t PinSource) +{ + uint32_t tmpregister = 0x00; + /* Check the parameters */ + assert_param(IS_GPIO_EVENTOUT_PORT_SOURCE(PortSource)); + assert_param(IS_GPIO_PIN_SOURCE(PinSource)); + + tmpregister = AFIO->ECTRL; + /* Clear the PORT[6:4] and PIN[3:0] bits */ + tmpregister &= EVCR_PORTPINCONFIG_MASK; + tmpregister |= (uint32_t)PortSource << 0x04; + tmpregister |= PinSource; + AFIO->ECTRL = tmpregister; +} + +/** + * @brief Enables or disables the Event Output. + * @param Cmd new state of the Event output. + * This parameter can be: ENABLE or DISABLE. + */ +void GPIO_CtrlEventOutput(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)EVCR_EVOE_BB = (uint32_t)Cmd; +} + +/** + * @brief Changes the mapping of the specified pin. + * @param RmpPin selects the pin to remap. + * This parameter can be one of the following values: + * @arg GPIO_RMP_SPI1 SPI1 Alternate Function mapping + * @arg GPIO_RMP_I2C1 I2C1 Alternate Function mapping + * @arg GPIO_RMP_USART1 USART1 Alternate Function mapping + * @arg GPIO_RMP_USART2 USART2 Alternate Function mapping + * @arg GPIO_PART_RMP_USART3 USART3 Partial Alternate Function mapping + * @arg GPIO_ALL_RMP_USART3 USART3 Full Alternate Function mapping + * @arg GPIO_PART1_RMP_TIM1 TIM1 Partial Alternate Function mapping + * @arg GPIO_PART2_RMP_TIM1 TIM1 Partial Alternate Function mapping + * @arg GPIO_ALL_RMP_TIM1 TIM1 Full Alternate Function mapping + * @arg GPIO_PartialRemap1_TIM2 TIM2 Partial1 Alternate Function mapping + * @arg GPIO_PART2_RMP_TIM2 TIM2 Partial2 Alternate Function mapping + * @arg GPIO_ALL_RMP_TIM2 TIM2 Full Alternate Function mapping + * @arg GPIO_PART1_RMP_TIM3 TIM3 Partial Alternate Function mapping + * @arg GPIO_ALL_RMP_TIM3 TIM3 Full Alternate Function mapping + * @arg GPIO_RMP_TIM4 TIM4 Alternate Function mapping + * @arg GPIO_RMP1_CAN1 CAN1 Alternate Function mapping + * @arg GPIO_RMP2_CAN1 CAN1 Alternate Function mapping + * @arg GPIO_RMP3_CAN1 CAN1 Alternate Function mapping + * @arg GPIO_RMP_PD01 PD01 Alternate Function mapping + * @arg GPIO_RMP_TIM5CH4 LSI connected to TIM5 Channel4 input capture for calibration + * @arg GPIO_RMP_ADC1_ETRI ADC1 External Trigger Injected Conversion remapping + * @arg GPIO_RMP_ADC1_ETRR ADC1 External Trigger Regular Conversion remapping + * @arg GPIO_RMP_ADC2_ETRI ADC2 External Trigger Injected Conversion remapping + * @arg GPIO_RMP_ADC2_ETRR ADC2 External Trigger Regular Conversion remapping + * @arg GPIO_RMP_SW_JTAG_NO_NJTRST Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST + * @arg GPIO_RMP_SW_JTAG_SW_ENABLE JTAG-DP Disabled and SW-DP Enabled + * @arg GPIO_RMP_SW_JTAG_DISABLE Full SWJ Disabled (JTAG-DP + SW-DP) + * @arg GPIO_RMP_SDIO SDIO Alternate Function mapping + * @arg GPIO_RMP1_CAN2 CAN2 Alternate Function mapping + * @arg GPIO_RMP3_CAN2 CAN2 Alternate Function mapping + * @arg GPIO_RMP1_QSPI QSPI Alternate Function mapping + * @arg GPIO_RMP3_QSPI QSPI Alternate Function mapping + * @arg GPIO_RMP1_I2C2 I2C2 Alternate Function mapping + * @arg GPIO_RMP3_I2C2 I2C2 Alternate Function mapping + * @arg GPIO_RMP2_I2C3 I2C3 Alternate Function mapping + * @arg GPIO_RMP3_I2C3 I2C3 Alternate Function mapping + * @arg GPIO_RMP1_I2C4 I2C4 Alternate Function mapping + * @arg GPIO_RMP3_I2C4 I2C4 Alternate Function mapping + * @arg GPIO_RMP1_SPI2 SPI2 Alternate Function mapping + * @arg GPIO_RMP2_SPI2 SPI2 Alternate Function mapping + * @arg GPIO_RMP1_SPI3 SPI3 Alternate Function mapping + * @arg GPIO_RMP2_SPI3 SPI3 Alternate Function mapping + * @arg GPIO_RMP1_ETH ETH Alternate Function mapping + * @arg GPIO_RMP2_ETH ETH Alternate Function mapping + * @arg GPIO_RMP3_ETH ETH Alternate Function mapping + * @arg GPIO_RMP1_SPI1 SPI1 Alternate Function mapping + * @arg GPIO_RMP2_SPI1 SPI1 Alternate Function mapping + * @arg GPIO_RMP3_SPI1 SPI1 Alternate Function mapping + * @arg GPIO_RMP1_USART2 USART2 Alternate Function mapping + * @arg GPIO_RMP2_USART2 USART2 Alternate Function mapping + * @arg GPIO_RMP3_USART2 USART2 Alternate Function mapping + * @arg GPIO_RMP1_UART4 UART4 Alternate Function mapping + * @arg GPIO_RMP2_UART4 UART4 Alternate Function mapping + * @arg GPIO_RMP3_UART4 UART4 Alternate Function mapping + * @arg GPIO_RMP1_UART5 UART5 Alternate Function mapping + * @arg GPIO_RMP2_UART5 UART5 Alternate Function mapping + * @arg GPIO_RMP3_UART5 UART5 Alternate Function mapping + * @arg GPIO_RMP2_UART6 UART6 Alternate Function mapping + * @arg GPIO_RMP3_UART6 UART6 Alternate Function mapping + * @arg GPIO_RMP1_UART7 UART7 Alternate Function mapping + * @arg GPIO_RMP3_UART7 UART7 Alternate Function mapping + * @arg GPIO_RMP1_TIM8 TIM8 Alternate Function mapping + * @arg GPIO_RMP3_TIM8 TIM8 Alternate Function mapping + * @arg GPIO_RMP1_COMP1 COMP1 Alternate Function mapping + * @arg GPIO_RMP2_COMP1 COMP1 Alternate Function mapping + * @arg GPIO_RMP3_COMP1 COMP1 Alternate Function mapping + * @arg GPIO_RMP1_COMP2 COMP2 Alternate Function mapping + * @arg GPIO_RMP2_COMP2 COMP2 Alternate Function mapping + * @arg GPIO_RMP3_COMP2 COMP2 Alternate Function mapping + * @arg GPIO_RMP1_COMP3 COMP3 Alternate Function mapping + * @arg GPIO_RMP3_COMP3 COMP3 Alternate Function mapping + * @arg GPIO_RMP1_COMP4 COMP4 Alternate Function mapping + * @arg GPIO_RMP3_COMP4 COMP4 Alternate Function mapping + * @arg GPIO_RMP1_COMP5 COMP5 Alternate Function mapping + * @arg GPIO_RMP2_COMP5 COMP5 Alternate Function mapping + * @arg GPIO_RMP3_COMP5 COMP5 Alternate Function mapping + * @arg GPIO_RMP3_UART5 UART5 Alternate Function mapping + * @arg GPIO_RMP1_COMP6 COMP6 Alternate Function mapping + * @arg GPIO_RMP3_COMP6 COMP6 Alternate Function mapping + * @arg GPIO_RMP_COMP7 COMP7 Alternate Function mapping + * @arg GPIO_RMP_ADC3_ETRI ADC3_ETRGINJ Alternate Function mapping + * @arg GPIO_RMP_ADC3_ETRR ADC3_ETRGREG Alternate Function mapping + * @arg GPIO_RMP_ADC4_ETRI ADC4_ETRGINJ Alternate Function mapping + * @arg GPIO_RMP_ADC4_ETRR ADC4_ETRGREG Alternate Function mapping + * @arg GPIO_RMP_TSC_OUT_CTRL TSC_OUT_CTRL Alternate Function mapping + * @arg GPIO_RMP_QSPI_XIP_EN QSPI_XIP_EN Alternate Function mapping + * @arg GPIO_RMP1_DVP DVP Alternate Function mapping + * @arg GPIO_RMP3_DVP DVP Alternate Function mapping + * @arg GPIO_Remap_SPI1_NSS SPI1 NSS Alternate Function mapping + * @arg GPIO_Remap_SPI2_NSS SPI2 NSS Alternate Function mapping + * @arg GPIO_Remap_SPI3_NSS SPI3 NSS Alternate Function mapping + * @arg GPIO_Remap_QSPI_MISO QSPI MISO Alternate Function mapping + * @arg GPIO_Remap_DET_EN_EGB4 EGB4 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_EGB3 EGB3 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_EGB2 EGB2 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_EGB1 EGB1 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_EGBN4 EGBN4 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_EGBN3 EGBN3 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_EGBN2 EGBN2 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_EGBN1 EGBN1 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_ECLAMP4 ECLAMP4 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_ECLAMP3 ECLAMP3 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_ECLAMP2 ECLAMP2 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_ECLAMP1 ECLAMP1 Detect Alternate Function mapping + * @arg GPIO_Remap_RST_EN_EGB4 EGB4 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_EGB3 EGB3 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_EGB2 EGB2 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_EGB1 EGB1 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_EGBN4 EGBN4 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_EGBN3 EGBN3 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_EGBN2 EGBN2 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_EGBN1 EGBN1 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_ECLAMP4 ECLAMP4 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_ECLAMP3 ECLAMP3 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_ECLAMP2 ECLAMP2 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_ECLAMP1 ECLAMP1 Reset Alternate Function mapping + * @param Cmd new state of the port pin remapping. + * This parameter can be: ENABLE or DISABLE. + */ +void GPIO_ConfigPinRemap(uint32_t RmpPin, FunctionalState Cmd) +{ + uint32_t tmp = 0x00, tmp1 = 0x00, tmpregister = 0x00, tmpmask = 0x00, tmp2 = 0x00; + + /* Check the parameters */ + assert_param(IS_GPIO_REMAP(RmpPin)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Check RmpPin relate AFIO RMP_CFG */ + if ((RmpPin & 0x40000000) == 0x40000000) + { + tmpregister = AFIO->RMP_CFG3; + } + else if ((RmpPin & 0x20000000) == 0x20000000) + { + tmpregister = AFIO->RMP_CFG4; + } + else if ((RmpPin & 0x10000000) == 0x10000000) + { + tmpregister = AFIO->RMP_CFG5; + } + else + { + tmpregister = AFIO->RMP_CFG; + } + + tmpmask = (RmpPin & DBGAFR_POSITION_MASK) >> 16; + tmp = RmpPin & LSB_MASK; + + if ((RmpPin + & (DBGAFR_NUMBITS_MAPR5_MASK | DBGAFR_NUMBITS_MAPR4_MASK | DBGAFR_NUMBITS_MAPR3_MASK | DBGAFR_LOCATION_MASK + | DBGAFR_NUMBITS_MASK)) + == (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) + { + tmpregister &= DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG &= DBGAFR_SWJCFG_MASK; + } + else if ((RmpPin & DBGAFR_NUMBITS_MASK) == DBGAFR_NUMBITS_MASK) + { + if ((RmpPin & DBGAFR_LOCATION_MASK) == DBGAFR_LOCATION_MASK) + { + tmp1 = (((uint32_t)0x03) << tmpmask) << 16; + } + else + { + tmp1 = ((uint32_t)0x03) << tmpmask; + } + tmpregister &= ~tmp1; + if ((RmpPin & 0x70000000) == 0x00000000) + { + tmpregister |= ~DBGAFR_SWJCFG_MASK; + } + } + else + {/*configuration AFIO RMP_CFG*/ + if ((RmpPin & DBGAFR_NUMBITS_SPI1_MASK) == DBGAFR_NUMBITS_SPI1_MASK) + { + if ((RmpPin & 0x00000004) == 0x00000004) + { + if ((RmpPin & 0x02000000) == 0x02000000) // GPIO_RMP3_SPI1 + { + tmpregister &= ~(tmp << (((RmpPin & 0x00200000) >> 21) * 16)); + if (Cmd != DISABLE) + { + tmp2 = AFIO->RMP_CFG; + tmp2 |= 0x00000001; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_SPI1 ENABLE + } + else + { + tmp2 = AFIO->RMP_CFG; + tmp2 &= 0xFFFFFFFE; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_SPI1 DISABLE + } + } + else + { + tmpregister &= ~(tmp << (((RmpPin & 0x00200000) >> 21) * 16)); // GPIO_RMP2_SPI1 + + tmp2 = AFIO->RMP_CFG; + tmp2 &= 0xFFFFFFFE; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_SPI1 DISABLE + } + } + else + { + tmpregister &= ~((tmp | 0x00000004) << (((RmpPin & 0x00200000) >> 21) * 16)); // clear + if (Cmd != DISABLE) // GPIO_RMP1_SPI1 + { + tmp2 = AFIO->RMP_CFG; + tmp2 |= 0x00000001; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_SPI1 ENABLE + } + else + { + tmp2 = AFIO->RMP_CFG; + tmp2 &= 0xFFFFFFFE; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_SPI1 DISABLE + } + } + } + else if ((RmpPin & DBGAFR_NUMBITS_USART2_MASK) == DBGAFR_NUMBITS_USART2_MASK) + { + if ((RmpPin & 0x00000008) == 0x00000008) + { + if ((RmpPin & 0x02000000) == 0x02000000) // GPIO_RMP3_USART2 + { + tmpregister &= ~(tmp << (((RmpPin & 0x00200000) >> 21) * 16)); + if (Cmd != DISABLE) + { + tmp2 = AFIO->RMP_CFG; + tmp2 |= 0x00000008; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_USART2 ENABLE + } + else + { + tmp2 = AFIO->RMP_CFG; + tmp2 &= 0xFFFFFFF7; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_USART2 DISABLE + } + } + else + { + tmpregister &= ~(tmp << (((RmpPin & 0x00200000) >> 21) * 16)); // GPIO_RMP2_USART2 + + tmp2 = AFIO->RMP_CFG; + tmp2 &= 0xFFFFFFF7; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_USART2 DISABLE + } + } + else // GPIO_RMP1_USART2 + { + tmpregister &= ~((tmp | 0x00000008) << (((RmpPin & 0x00200000) >> 21) * 16)); // clear + if (Cmd != DISABLE) + { + tmp2 = AFIO->RMP_CFG; + tmp2 |= 0x00000008; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_USART2 ENABLE + } + else + { + tmp2 = AFIO->RMP_CFG; + tmp2 &= 0xFFFFFFF7; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_USART2 DISABLE + } + } + } + else + { + tmpregister &= ~(tmp << (((RmpPin & 0x00200000) >> 21) * 16)); + if ((RmpPin & 0x70000000) == 0x00000000) + { + tmpregister |= ~DBGAFR_SWJCFG_MASK; + } + } + } + + /*configuration AFIO RMP_CFG~RMP_CFG5*/ + if (Cmd != DISABLE) + { + tmpregister |= (tmp << (((RmpPin & 0x00200000) >> 21) * 16)); + } + + if ((RmpPin & 0x40000000) == 0x40000000) + { + AFIO->RMP_CFG3 = tmpregister; + } + else if ((RmpPin & 0x20000000) == 0x20000000) + { + AFIO->RMP_CFG4 = tmpregister; + } + else if ((RmpPin & 0x10000000) == 0x10000000) + { + AFIO->RMP_CFG5 = tmpregister; + } + else + { + AFIO->RMP_CFG = tmpregister; + } +} + +/** + * @brief Selects the GPIO pin used as EXTI Line. + * @param PortSource selects the GPIO port to be used as source for EXTI lines. + * This parameter can be GPIO_PortSourceGPIOx where x can be (A..G). + * @param PinSource specifies the EXTI line to be configured. + * This parameter can be GPIO_PinSourcex where x can be (0..15). + */ +void GPIO_ConfigEXTILine(uint8_t PortSource, uint8_t PinSource) +{ + uint32_t tmp = 0x00; + /* Check the parameters */ + assert_param(IS_GPIO_EXTI_PORT_SOURCE(PortSource)); + assert_param(IS_GPIO_PIN_SOURCE(PinSource)); + + tmp = ((uint32_t)0x0F) << (0x04 * (PinSource & (uint8_t)0x03)); + AFIO->EXTI_CFG[PinSource >> 0x02] &= ~tmp; + AFIO->EXTI_CFG[PinSource >> 0x02] |= (((uint32_t)PortSource) << (0x04 * (PinSource & (uint8_t)0x03))); +} + +/** + * @brief Selects the Ethernet media interface. + * @note This function applies only to N32G4FR Connectivity line devices. + * @param ETH_ConfigSel specifies the Media Interface mode. + * This parameter can be one of the following values: + * @arg GPIO_ETH_MII_CFG MII mode + * @arg GPIO_ETH_RMII_CFG RMII mode + */ +void GPIO_ETH_ConfigMediaInterface(uint32_t ETH_ConfigSel) +{ + assert_param(IS_GPIO_ETH_MEDIA_INTERFACE(ETH_ConfigSel)); + + AFIO->RMP_CFG &= (uint32_t)(~0x00800000); + AFIO->RMP_CFG |= ETH_ConfigSel; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_i2c.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_i2c.c new file mode 100644 index 0000000000..7cf6e23a5c --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_i2c.c @@ -0,0 +1,1324 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_i2c.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_i2c.h" +#include "n32g4fr_rcc.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup I2C + * @brief I2C driver modules + * @{ + */ + +/** @addtogroup I2C_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup I2C_Private_Defines + * @{ + */ + +/* I2C SPE mask */ +#define CTRL1_SPEN_SET ((uint16_t)0x0001) +#define CTRL1_SPEN_RESET ((uint16_t)0xFFFE) + +/* I2C START mask */ +#define CTRL1_START_SET ((uint16_t)0x0100) +#define CTRL1_START_RESET ((uint16_t)0xFEFF) + +/* I2C STOP mask */ +#define CTRL1_STOP_SET ((uint16_t)0x0200) +#define CTRL1_STOP_RESET ((uint16_t)0xFDFF) + +/* I2C ACK mask */ +#define CTRL1_ACK_SET ((uint16_t)0x0400) +#define CTRL1_ACK_RESET ((uint16_t)0xFBFF) + +/* I2C ENGC mask */ +#define CTRL1_GCEN_SET ((uint16_t)0x0040) +#define CTRL1_GCEN_RESET ((uint16_t)0xFFBF) + +/* I2C SWRST mask */ +#define CTRL1_SWRESET_SET ((uint16_t)0x8000) +#define CTRL1_SWRESET_RESET ((uint16_t)0x7FFF) + +/* I2C PEC mask */ +#define CTRL1_PEC_SET ((uint16_t)0x1000) +#define CTRL1_PEC_RESET ((uint16_t)0xEFFF) + +/* I2C ENPEC mask */ +#define CTRL1_PECEN_SET ((uint16_t)0x0020) +#define CTRL1_PECEN_RESET ((uint16_t)0xFFDF) + +/* I2C ENARP mask */ +#define CTRL1_ARPEN_SET ((uint16_t)0x0010) +#define CTRL1_ARPEN_RESET ((uint16_t)0xFFEF) + +/* I2C NOSTRETCH mask */ +#define CTRL1_NOEXTEND_SET ((uint16_t)0x0080) +#define CTRL1_NOEXTEND_RESET ((uint16_t)0xFF7F) + +/* I2C registers Masks */ +#define CTRL1_CLR_MASK ((uint16_t)0xFBF5) + +/* I2C DMAEN mask */ +#define CTRL2_DMAEN_SET ((uint16_t)0x0800) +#define CTRL2_DMAEN_RESET ((uint16_t)0xF7FF) + +/* I2C LAST mask */ +#define CTRL2_DMALAST_SET ((uint16_t)0x1000) +#define CTRL2_DMALAST_RESET ((uint16_t)0xEFFF) + +/* I2C FREQ mask */ +#define CTRL2_CLKFREQ_RESET ((uint16_t)0xFFC0) + +/* I2C ADD0 mask */ +#define OADDR1_ADDR0_SET ((uint16_t)0x0001) +#define OADDR1_ADDR0_RESET ((uint16_t)0xFFFE) + +/* I2C ENDUAL mask */ +#define OADDR2_DUALEN_SET ((uint16_t)0x0001) +#define OADDR2_DUALEN_RESET ((uint16_t)0xFFFE) + +/* I2C ADD2 mask */ +#define OADDR2_ADDR2_RESET ((uint16_t)0xFF01) + +/* I2C F/S mask */ +#define CLKCTRL_FSMODE_SET ((uint16_t)0x8000) + +/* I2C CHCFG mask */ +#define CLKCTRL_CLKCTRL_SET ((uint16_t)0x0FFF) + +/* I2C FLAG mask */ +#define FLAG_MASK ((uint32_t)0x00FFFFFF) + +/* I2C Interrupt Enable mask */ +#define INTEN_MASK ((uint32_t)0x07000000) + +/** + * @} + */ + +/** @addtogroup I2C_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup I2C_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup I2C_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup I2C_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the I2Cx peripheral registers to their default reset values. + * @param I2Cx where x can be 1,2 ,3 or 4 to select the I2C peripheral. + */ +void I2C_DeInit(I2C_Module* I2Cx) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + + if (I2Cx == I2C1) + { + /* Enable I2C1 reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_I2C1, ENABLE); + /* Release I2C1 from reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_I2C1, DISABLE); + } + else if (I2Cx == I2C2) + { + /* Enable I2C2 reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_I2C2, ENABLE); + /* Release I2C2 from reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_I2C2, DISABLE); + } + else if (I2Cx == I2C3) + { + /* Enable I2C3 reset state */ + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_I2C3, ENABLE); + /* Release I2C3 from reset state */ + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_I2C3, DISABLE); + } + else if (I2Cx == I2C4) + { + /* Enable I2C4 reset state */ + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_I2C4, ENABLE); + /* Release I2C4 from reset state */ + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_I2C4, DISABLE); + } + else + { + + } +} + +/** + * @brief Initializes the I2Cx peripheral according to the specified + * parameters in the I2C_InitStruct. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_InitStruct pointer to a I2C_InitType structure that + * contains the configuration information for the specified I2C peripheral. + */ +void I2C_Init(I2C_Module* I2Cx, I2C_InitType* I2C_InitStruct) +{ + uint16_t tmpregister = 0, freqrange = 0; + uint16_t result = 0x04; + uint32_t pclk = 8000000; + RCC_ClocksType rcc_clocks; + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_CLK_SPEED(I2C_InitStruct->ClkSpeed)); + assert_param(IS_I2C_BUS_MODE(I2C_InitStruct->BusMode)); + assert_param(IS_I2C_FM_DUTY_CYCLE(I2C_InitStruct->FmDutyCycle)); + assert_param(IS_I2C_OWN_ADDR1(I2C_InitStruct->OwnAddr1)); + assert_param(IS_I2C_ACK_STATE(I2C_InitStruct->AckEnable)); + assert_param(IS_I2C_ADDR_MODE(I2C_InitStruct->AddrMode)); + + /*---------------------------- I2Cx CTRL2 Configuration ------------------------*/ + /* Get the I2Cx CTRL2 value */ + tmpregister = I2Cx->CTRL2; + /* Clear frequency FREQ[5:0] bits */ + tmpregister &= CTRL2_CLKFREQ_RESET; + /* Get APB1/2 frequency value */ + RCC_GetClocksFreqValue(&rcc_clocks); + + if ((I2Cx == I2C1) || (I2Cx == I2C2)) + { + pclk = rcc_clocks.Pclk1Freq; + } + else if ((I2Cx == I2C3) || (I2Cx == I2C4)) + { + pclk = rcc_clocks.Pclk2Freq; + } + + /* Set frequency bits depending on pclk1 value */ + freqrange = (uint16_t)(pclk / 1000000); + if (freqrange > 36) + { + freqrange = 36; + } + /* Write to I2Cx CTRL2 */ + tmpregister |= freqrange; + I2Cx->CTRL2 = tmpregister; + + /*---------------------------- I2Cx CHCFG Configuration ------------------------*/ + /* Disable the selected I2C peripheral to configure TMRISE */ + I2Cx->CTRL1 &= CTRL1_SPEN_RESET; + /* Reset tmpregister value */ + /* Clear F/S, DUTY and CHCFG[11:0] bits */ + tmpregister = 0; + + /* Configure speed in standard mode */ + if (I2C_InitStruct->ClkSpeed <= 100000) + { + /* Standard mode speed calculate */ + result = (uint16_t)(pclk / (I2C_InitStruct->ClkSpeed << 1)); + /* Test if CHCFG value is under 0x4*/ + if (result < 0x04) + { + /* Set minimum allowed value */ + result = 0x04; + } + /* Set speed value for standard mode */ + tmpregister |= result; + /* Set Maximum Rise Time for standard mode */ + I2Cx->TMRISE = freqrange + 1; + } + /* Configure speed in fast mode */ + else + { + if (I2C_InitStruct->FmDutyCycle == I2C_FMDUTYCYCLE_2) + { + /* Fast mode speed calculate: Tlow/Thigh = 2 */ + result = (uint16_t)(pclk / (I2C_InitStruct->ClkSpeed * 3)); + } + else /*I2C_InitStruct->FmDutyCycle == I2C_FMDUTYCYCLE_16_9*/ + { + /* Fast mode speed calculate: Tlow/Thigh = 16/9 */ + result = (uint16_t)(pclk / (I2C_InitStruct->ClkSpeed * 25)); + /* Set DUTY bit */ + result |= I2C_FMDUTYCYCLE_16_9; + } + + /* Test if CHCFG value is under 0x1*/ + if ((result & CLKCTRL_CLKCTRL_SET) == 0) + { + /* Set minimum allowed value */ + result |= (uint16_t)0x0001; + } + /* Set speed value and set F/S bit for fast mode */ + tmpregister |= (uint16_t)(result | CLKCTRL_FSMODE_SET); + + /* Set Maximum Rise Time for fast mode */ + I2Cx->TMRISE = (uint16_t)(((freqrange * (uint16_t)300) / (uint16_t)1000) + (uint16_t)1); + } + /* Write to I2Cx CHCFG */ + I2Cx->CLKCTRL = tmpregister; + /* Enable the selected I2C peripheral */ + I2Cx->CTRL1 |= CTRL1_SPEN_SET; + + /*---------------------------- I2Cx CTRL1 Configuration ------------------------*/ + /* Get the I2Cx CTRL1 value */ + tmpregister = I2Cx->CTRL1; + /* Clear ACK, SMBTYPE and SMBUS bits */ + tmpregister &= CTRL1_CLR_MASK; + /* Configure I2Cx: mode and acknowledgement */ + /* Set SMBTYPE and SMBUS bits according to BusMode value */ + /* Set ACK bit according to AckEnable value */ + tmpregister |= (uint16_t)((uint32_t)I2C_InitStruct->BusMode | I2C_InitStruct->AckEnable); + /* Write to I2Cx CTRL1 */ + I2Cx->CTRL1 = tmpregister; + + /*---------------------------- I2Cx OADDR1 Configuration -----------------------*/ + /* Set I2Cx Own Address1 and acknowledged address */ + I2Cx->OADDR1 = (I2C_InitStruct->AddrMode | I2C_InitStruct->OwnAddr1); +} + +/** + * @brief Fills each I2C_InitStruct member with its default value. + * @param I2C_InitStruct pointer to an I2C_InitType structure which will be initialized. + */ +void I2C_InitStruct(I2C_InitType* I2C_InitStruct) +{ + /*---------------- Reset I2C init structure parameters values ----------------*/ + /* initialize the ClkSpeed member */ + I2C_InitStruct->ClkSpeed = 5000; + /* Initialize the BusMode member */ + I2C_InitStruct->BusMode = I2C_BUSMODE_I2C; + /* Initialize the FmDutyCycle member */ + I2C_InitStruct->FmDutyCycle = I2C_FMDUTYCYCLE_2; + /* Initialize the OwnAddr1 member */ + I2C_InitStruct->OwnAddr1 = 0; + /* Initialize the AckEnable member */ + I2C_InitStruct->AckEnable = I2C_ACKDIS; + /* Initialize the AddrMode member */ + I2C_InitStruct->AddrMode = I2C_ADDR_MODE_7BIT; +} + +/** + * @brief Enables or disables the specified I2C peripheral. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2Cx peripheral. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_Enable(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected I2C peripheral */ + I2Cx->CTRL1 |= CTRL1_SPEN_SET; + } + else + { + /* Disable the selected I2C peripheral */ + I2Cx->CTRL1 &= CTRL1_SPEN_RESET; + } +} + +/** + * @brief Enables or disables the specified I2C DMA requests. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C DMA transfer. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_EnableDMA(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected I2C DMA requests */ + I2Cx->CTRL2 |= CTRL2_DMAEN_SET; + } + else + { + /* Disable the selected I2C DMA requests */ + I2Cx->CTRL2 &= CTRL2_DMAEN_RESET; + } +} + +/** + * @brief Specifies if the next DMA transfer will be the last one. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C DMA last transfer. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_EnableDmaLastSend(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Next DMA transfer is the last transfer */ + I2Cx->CTRL2 |= CTRL2_DMALAST_SET; + } + else + { + /* Next DMA transfer is not the last transfer */ + I2Cx->CTRL2 &= CTRL2_DMALAST_RESET; + } +} + +/** + * @brief Generates I2Cx communication START condition. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C START condition generation. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_GenerateStart(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Generate a START condition */ + I2Cx->CTRL1 |= CTRL1_START_SET; + } + else + { + /* Disable the START condition generation */ + I2Cx->CTRL1 &= CTRL1_START_RESET; + } +} + +/** + * @brief Generates I2Cx communication STOP condition. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C STOP condition generation. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_GenerateStop(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Generate a STOP condition */ + I2Cx->CTRL1 |= CTRL1_STOP_SET; + } + else + { + /* Disable the STOP condition generation */ + I2Cx->CTRL1 &= CTRL1_STOP_RESET; + } +} + +/** + * @brief Enables or disables the specified I2C acknowledge feature. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C Acknowledgement. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_ConfigAck(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the acknowledgement */ + I2Cx->CTRL1 |= CTRL1_ACK_SET; + } + else + { + /* Disable the acknowledgement */ + I2Cx->CTRL1 &= CTRL1_ACK_RESET; + } +} + +/** + * @brief Configures the specified I2C own address2. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Address specifies the 7bit I2C own address2. + */ +void I2C_ConfigOwnAddr2(I2C_Module* I2Cx, uint8_t Address) +{ + uint16_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + + /* Get the old register value */ + tmpregister = I2Cx->OADDR2; + + /* Reset I2Cx Own address2 bit [7:1] */ + tmpregister &= OADDR2_ADDR2_RESET; + + /* Set I2Cx Own address2 */ + tmpregister |= (uint16_t)((uint16_t)Address & (uint16_t)0x00FE); + + /* Store the new register value */ + I2Cx->OADDR2 = tmpregister; +} + +/** + * @brief Enables or disables the specified I2C dual addressing mode. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C dual addressing mode. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_EnableDualAddr(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable dual addressing mode */ + I2Cx->OADDR2 |= OADDR2_DUALEN_SET; + } + else + { + /* Disable dual addressing mode */ + I2Cx->OADDR2 &= OADDR2_DUALEN_RESET; + } +} + +/** + * @brief Enables or disables the specified I2C general call feature. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C General call. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_EnableGeneralCall(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable generall call */ + I2Cx->CTRL1 |= CTRL1_GCEN_SET; + } + else + { + /* Disable generall call */ + I2Cx->CTRL1 &= CTRL1_GCEN_RESET; + } +} + +/** + * @brief Enables or disables the specified I2C interrupts. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_IT specifies the I2C interrupts sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg I2C_INT_BUF Buffer interrupt mask + * @arg I2C_INT_EVENT Event interrupt mask + * @arg I2C_INT_ERR Error interrupt mask + * @param Cmd new state of the specified I2C interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_ConfigInt(I2C_Module* I2Cx, uint16_t I2C_IT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + assert_param(IS_I2C_CFG_INT(I2C_IT)); + + if (Cmd != DISABLE) + { + /* Enable the selected I2C interrupts */ + I2Cx->CTRL2 |= I2C_IT; + } + else + { + /* Disable the selected I2C interrupts */ + I2Cx->CTRL2 &= (uint16_t)~I2C_IT; + } +} + +/** + * @brief Sends a data byte through the I2Cx peripheral. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Data Byte to be transmitted.. + */ +void I2C_SendData(I2C_Module* I2Cx, uint8_t Data) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + /* Write in the DAT register the data to be sent */ + I2Cx->DAT = Data; +} + +/** + * @brief Returns the most recent received data by the I2Cx peripheral. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @return The value of the received data. + */ +uint8_t I2C_RecvData(I2C_Module* I2Cx) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + /* Return the data in the DAT register */ + return (uint8_t)I2Cx->DAT; +} + +/** + * @brief Transmits the address byte to select the slave device. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Address specifies the slave address which will be transmitted + * @param I2C_Direction specifies whether the I2C device will be a + * Transmitter or a Receiver. This parameter can be one of the following values + * @arg I2C_DIRECTION_SEND Transmitter mode + * @arg I2C_DIRECTION_RECV Receiver mode + */ +void I2C_SendAddr7bit(I2C_Module* I2Cx, uint8_t Address, uint8_t I2C_Direction) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_DIRECTION(I2C_Direction)); + /* Test on the direction to set/reset the read/write bit */ + if (I2C_Direction != I2C_DIRECTION_SEND) + { + /* Set the address bit0 for read */ + Address |= OADDR1_ADDR0_SET; + } + else + { + /* Reset the address bit0 for write */ + Address &= OADDR1_ADDR0_RESET; + } + /* Send the address */ + I2Cx->DAT = Address; +} + +/** + * @brief Reads the specified I2C register and returns its value. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_Register specifies the register to read. + * This parameter can be one of the following values: + * @arg I2C_REG_CTRL1 CTRL1 register. + * @arg I2C_REG_CTRL2 CTRL2 register. + * @arg I2C_REG_OADDR1 OADDR1 register. + * @arg I2C_REG_OADDR2 OADDR2 register. + * @arg I2C_REG_DAT DAT register. + * @arg I2C_REG_STS1 STS1 register. + * @arg I2C_REG_STS2 STS2 register. + * @arg I2C_REG_CLKCTRL CHCFG register. + * @arg I2C_REG_TMRISE TMRISE register. + * @return The value of the read register. + */ +uint16_t I2C_GetRegister(I2C_Module* I2Cx, uint8_t I2C_Register) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_REG(I2C_Register)); + + tmp = (uint32_t)I2Cx; + tmp += I2C_Register; + + /* Return the selected register value */ + return (*(__IO uint16_t*)tmp); +} + +/** + * @brief Enables or disables the specified I2C software reset. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C software reset. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_EnableSoftwareReset(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Peripheral under reset */ + I2Cx->CTRL1 |= CTRL1_SWRESET_SET; + } + else + { + /* Peripheral not under reset */ + I2Cx->CTRL1 &= CTRL1_SWRESET_RESET; + } +} + +/** + * @brief Selects the specified I2C NACK position in master receiver mode. + * This function is useful in I2C Master Receiver mode when the number + * of data to be received is equal to 2. In this case, this function + * should be called (with parameter I2C_NACK_POS_NEXT) before data + * reception starts,as described in the 2-byte reception procedure + * recommended in Reference Manual in Section: Master receiver. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_NACKPosition specifies the NACK position. + * This parameter can be one of the following values: + * @arg I2C_NACK_POS_NEXT indicates that the next byte will be the last + * received byte. + * @arg I2C_NACK_POS_CURRENT indicates that current byte is the last + * received byte. + * + * @note This function configures the same bit (POS) as I2C_ConfigPecLocation() + * but is intended to be used in I2C mode while I2C_ConfigPecLocation() + * is intended to used in SMBUS mode. + * + */ +void I2C_ConfigNackLocation(I2C_Module* I2Cx, uint16_t I2C_NACKPosition) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_NACK_POS(I2C_NACKPosition)); + + /* Check the input parameter */ + if (I2C_NACKPosition == I2C_NACK_POS_NEXT) + { + /* Next byte in shift register is the last received byte */ + I2Cx->CTRL1 |= I2C_NACK_POS_NEXT; + } + else + { + /* Current byte in shift register is the last received byte */ + I2Cx->CTRL1 &= I2C_NACK_POS_CURRENT; + } +} + +/** + * @brief Drives the SMBusAlert pin high or low for the specified I2C. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_SMBusAlert specifies SMBAlert pin level. + * This parameter can be one of the following values: + * @arg I2C_SMBALERT_LOW SMBAlert pin driven low + * @arg I2C_SMBALERT_HIGH SMBAlert pin driven high + */ +void I2C_ConfigSmbusAlert(I2C_Module* I2Cx, uint16_t I2C_SMBusAlert) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_SMB_ALERT(I2C_SMBusAlert)); + if (I2C_SMBusAlert == I2C_SMBALERT_LOW) + { + /* Drive the SMBusAlert pin Low */ + I2Cx->CTRL1 |= I2C_SMBALERT_LOW; + } + else + { + /* Drive the SMBusAlert pin High */ + I2Cx->CTRL1 &= I2C_SMBALERT_HIGH; + } +} + +/** + * @brief Enables or disables the specified I2C PEC transfer. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C PEC transmission. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_SendPEC(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected I2C PEC transmission */ + I2Cx->CTRL1 |= CTRL1_PEC_SET; + } + else + { + /* Disable the selected I2C PEC transmission */ + I2Cx->CTRL1 &= CTRL1_PEC_RESET; + } +} + +/** + * @brief Selects the specified I2C PEC position. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_PECPosition specifies the PEC position. + * This parameter can be one of the following values: + * @arg I2C_PEC_POS_NEXT indicates that the next byte is PEC + * @arg I2C_PEC_POS_CURRENT indicates that current byte is PEC + * + * @note This function configures the same bit (POS) as I2C_ConfigNackLocation() + * but is intended to be used in SMBUS mode while I2C_ConfigNackLocation() + * is intended to used in I2C mode. + * + */ +void I2C_ConfigPecLocation(I2C_Module* I2Cx, uint16_t I2C_PECPosition) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_PEC_POS(I2C_PECPosition)); + if (I2C_PECPosition == I2C_PEC_POS_NEXT) + { + /* Next byte in shift register is PEC */ + I2Cx->CTRL1 |= I2C_PEC_POS_NEXT; + } + else + { + /* Current byte in shift register is PEC */ + I2Cx->CTRL1 &= I2C_PEC_POS_CURRENT; + } +} + +/** + * @brief Enables or disables the PEC value calculation of the transferred bytes. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2Cx PEC value calculation. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_ComputePec(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected I2C PEC calculation */ + I2Cx->CTRL1 |= CTRL1_PECEN_SET; + } + else + { + /* Disable the selected I2C PEC calculation */ + I2Cx->CTRL1 &= CTRL1_PECEN_RESET; + } +} + +/** + * @brief Returns the PEC value for the specified I2C. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @return The PEC value. + */ +uint8_t I2C_GetPec(I2C_Module* I2Cx) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + /* Return the selected I2C PEC value */ + return ((I2Cx->STS2) >> 8); +} + +/** + * @brief Enables or disables the specified I2C ARP. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2Cx ARP. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_EnableArp(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected I2C ARP */ + I2Cx->CTRL1 |= CTRL1_ARPEN_SET; + } + else + { + /* Disable the selected I2C ARP */ + I2Cx->CTRL1 &= CTRL1_ARPEN_RESET; + } +} + +/** + * @brief Enables or disables the specified I2C Clock stretching. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2Cx Clock stretching. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_EnableExtendClk(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd == DISABLE) + { + /* Enable the selected I2C Clock stretching */ + I2Cx->CTRL1 |= CTRL1_NOEXTEND_SET; + } + else + { + /* Disable the selected I2C Clock stretching */ + I2Cx->CTRL1 &= CTRL1_NOEXTEND_RESET; + } +} + +/** + * @brief Selects the specified I2C fast mode duty cycle. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param FmDutyCycle specifies the fast mode duty cycle. + * This parameter can be one of the following values: + * @arg I2C_FMDUTYCYCLE_2 I2C fast mode Tlow/Thigh = 2 + * @arg I2C_FMDUTYCYCLE_16_9 I2C fast mode Tlow/Thigh = 16/9 + */ +void I2C_ConfigFastModeDutyCycle(I2C_Module* I2Cx, uint16_t FmDutyCycle) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_FM_DUTY_CYCLE(FmDutyCycle)); + if (FmDutyCycle != I2C_FMDUTYCYCLE_16_9) + { + /* I2C fast mode Tlow/Thigh=2 */ + I2Cx->CLKCTRL &= I2C_FMDUTYCYCLE_2; + } + else + { + /* I2C fast mode Tlow/Thigh=16/9 */ + I2Cx->CLKCTRL |= I2C_FMDUTYCYCLE_16_9; + } +} + +/** + * @brief + **************************************************************************************** + * + * I2C State Monitoring Functions + * + **************************************************************************************** + * This I2C driver provides three different ways for I2C state monitoring + * depending on the application requirements and constraints: + * + * + * 1) Basic state monitoring: + * Using I2C_CheckEvent() function: + * It compares the status registers (STS1 and STS2) content to a given event + * (can be the combination of one or more flags). + * It returns SUCCESS if the current status includes the given flags + * and returns ERROR if one or more flags are missing in the current status. + * - When to use: + * - This function is suitable for most applications as well as for startup + * activity since the events are fully described in the product reference manual + * (RM0008). + * - It is also suitable for users who need to define their own events. + * - Limitations: + * - If an error occurs (ie. error flags are set besides to the monitored flags), + * the I2C_CheckEvent() function may return SUCCESS despite the communication + * hold or corrupted real state. + * In this case, it is advised to use error interrupts to monitor the error + * events and handle them in the interrupt IRQ handler. + * + * @note + * For error management, it is advised to use the following functions: + * - I2C_ConfigInt() to configure and enable the error interrupts (I2C_INT_ERR). + * - I2Cx_ER_IRQHandler() which is called when the error interrupt occurs. + * Where x is the peripheral instance (I2C1, I2C2 ...) + * - I2C_GetFlag() or I2C_GetIntStatus() to be called into I2Cx_ER_IRQHandler() + * in order to determine which error occured. + * - I2C_ClrFlag() or I2C_ClrIntPendingBit() and/or I2C_EnableSoftwareReset() + * and/or I2C_GenerateStop() in order to clear the error flag and source, + * and return to correct communication status. + * + * + * 2) Advanced state monitoring: + * Using the function I2C_GetLastEvent() which returns the image of both status + * registers in a single word (uint32_t) (Status Register 2 value is shifted left + * by 16 bits and concatenated to Status Register 1). + * - When to use: + * - This function is suitable for the same applications above but it allows to + * overcome the mentioned limitation of I2C_GetFlag() function. + * The returned value could be compared to events already defined in the + * library (n32g4fr_i2c.h) or to custom values defined by user. + * - This function is suitable when multiple flags are monitored at the same time. + * - At the opposite of I2C_CheckEvent() function, this function allows user to + * choose when an event is accepted (when all events flags are set and no + * other flags are set or just when the needed flags are set like + * I2C_CheckEvent() function). + * - Limitations: + * - User may need to define his own events. + * - Same remark concerning the error management is applicable for this + * function if user decides to check only regular communication flags (and + * ignores error flags). + * + * + * 3) Flag-based state monitoring: + * Using the function I2C_GetFlag() which simply returns the status of + * one single flag (ie. I2C_FLAG_RXDATNE ...). + * - When to use: + * - This function could be used for specific applications or in debug phase. + * - It is suitable when only one flag checking is needed (most I2C events + * are monitored through multiple flags). + * - Limitations: + * - When calling this function, the Status register is accessed. Some flags are + * cleared when the status register is accessed. So checking the status + * of one Flag, may clear other ones. + * - Function may need to be called twice or more in order to monitor one + * single event. + * + * For detailed description of Events, please refer to section I2C_Events in + * n32g4fr_i2c.h file. + * + */ + +/** + * @brief Checks whether the last I2Cx Event is equal to the one passed + * as parameter. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_EVENT specifies the event to be checked. + * This parameter can be one of the following values: + * @arg I2C_EVT_SLAVE_SEND_ADDR_MATCHED EV1 + * @arg I2C_EVT_SLAVE_RECV_ADDR_MATCHED EV1 + * @arg I2C_EVT_SLAVE_SEND_ADDR2_MATCHED EV1 + * @arg I2C_EVT_SLAVE_RECV_ADDR2_MATCHED EV1 + * @arg I2C_EVT_SLAVE_GCALLADDR_MATCHED EV1 + * @arg I2C_EVT_SLAVE_DATA_RECVD EV2 + * @arg (I2C_EVT_SLAVE_DATA_RECVD | I2C_FLAG_DUALFLAG) EV2 + * @arg (I2C_EVT_SLAVE_DATA_RECVD | I2C_FLAG_GCALLADDR) EV2 + * @arg I2C_EVT_SLAVE_DATA_SENDED EV3 + * @arg (I2C_EVT_SLAVE_DATA_SENDED | I2C_FLAG_DUALFLAG) EV3 + * @arg (I2C_EVT_SLAVE_DATA_SENDED | I2C_FLAG_GCALLADDR) EV3 + * @arg I2C_EVT_SLAVE_ACK_MISS EV3_2 + * @arg I2C_EVT_SLAVE_STOP_RECVD EV4 + * @arg I2C_EVT_MASTER_MODE_FLAG EV5 + * @arg I2C_EVT_MASTER_TXMODE_FLAG EV6 + * @arg I2C_EVT_MASTER_RXMODE_FLAG EV6 + * @arg I2C_EVT_MASTER_DATA_RECVD_FLAG EV7 + * @arg I2C_EVT_MASTER_DATA_SENDING EV8 + * @arg I2C_EVT_MASTER_DATA_SENDED EV8_2 + * @arg I2C_EVT_MASTER_MODE_ADDRESS10_FLAG EV9 + * + * @note: For detailed description of Events, please refer to section + * I2C_Events in n32g4fr_i2c.h file. + * + * @return An ErrorStatus enumeration value: + * - SUCCESS: Last event is equal to the I2C_EVENT + * - ERROR: Last event is different from the I2C_EVENT + */ +ErrorStatus I2C_CheckEvent(I2C_Module* I2Cx, uint32_t I2C_EVENT) +{ + uint32_t lastevent = 0; + uint32_t flag1 = 0, flag2 = 0; + ErrorStatus status = ERROR; + + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_EVT(I2C_EVENT)); + + /* Read the I2Cx status register */ + flag1 = I2Cx->STS1; + flag2 = I2Cx->STS2; + flag2 = flag2 << 16; + + /* Get the last event value from I2C status register */ + lastevent = (flag1 | flag2) & FLAG_MASK; + + /* Check whether the last event contains the I2C_EVENT */ + if ((lastevent & I2C_EVENT) == I2C_EVENT) + { + /* SUCCESS: last event is equal to I2C_EVENT */ + status = SUCCESS; + } + else + { + /* ERROR: last event is different from I2C_EVENT */ + status = ERROR; + } + /* Return status */ + return status; +} + +/** + * @brief Returns the last I2Cx Event. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * + * @note: For detailed description of Events, please refer to section + * I2C_Events in n32g4fr_i2c.h file. + * + * @return The last event + */ +uint32_t I2C_GetLastEvent(I2C_Module* I2Cx) +{ + uint32_t lastevent = 0; + uint32_t flag1 = 0, flag2 = 0; + + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + + /* Read the I2Cx status register */ + flag1 = I2Cx->STS1; + flag2 = I2Cx->STS2; + flag2 = flag2 << 16; + + /* Get the last event value from I2C status register */ + lastevent = (flag1 | flag2) & FLAG_MASK; + + /* Return status */ + return lastevent; +} + +/** + * @brief Checks whether the specified I2C flag is set or not. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg I2C_FLAG_DUALFLAG Dual flag (Slave mode) + * @arg I2C_FLAG_SMBHADDR SMBus host header (Slave mode) + * @arg I2C_FLAG_SMBDADDR SMBus default header (Slave mode) + * @arg I2C_FLAG_GCALLADDR General call header flag (Slave mode) + * @arg I2C_FLAG_TRF Transmitter/Receiver flag + * @arg I2C_FLAG_BUSY Bus busy flag + * @arg I2C_FLAG_MSMODE Master/Slave flag + * @arg I2C_FLAG_SMBALERT SMBus Alert flag + * @arg I2C_FLAG_TIMOUT Timeout or Tlow error flag + * @arg I2C_FLAG_PECERR PEC error in reception flag + * @arg I2C_FLAG_OVERRUN Overrun/Underrun flag (Slave mode) + * @arg I2C_FLAG_ACKFAIL Acknowledge failure flag + * @arg I2C_FLAG_ARLOST Arbitration lost flag (Master mode) + * @arg I2C_FLAG_BUSERR Bus error flag + * @arg I2C_FLAG_TXDATE Data register empty flag (Transmitter) + * @arg I2C_FLAG_RXDATNE Data register not empty (Receiver) flag + * @arg I2C_FLAG_STOPF Stop detection flag (Slave mode) + * @arg I2C_FLAG_ADDR10F 10-bit header sent flag (Master mode) + * @arg I2C_FLAG_BYTEF Byte transfer finished flag + * @arg I2C_FLAG_ADDRF Address sent flag (Master mode) "ADSL" + * Address matched flag (Slave mode)"ENDA" + * @arg I2C_FLAG_STARTBF Start bit flag (Master mode) + * @return The new state of I2C_FLAG (SET or RESET). + */ +FlagStatus I2C_GetFlag(I2C_Module* I2Cx, uint32_t I2C_FLAG) +{ + FlagStatus bitstatus = RESET; + __IO uint32_t i2creg = 0, i2cxbase = 0; + + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_GET_FLAG(I2C_FLAG)); + + /* Get the I2Cx peripheral base address */ + i2cxbase = (uint32_t)I2Cx; + + /* Read flag register index */ + i2creg = I2C_FLAG >> 28; + + /* Get bit[23:0] of the flag */ + I2C_FLAG &= FLAG_MASK; + + if (i2creg != 0) + { + /* Get the I2Cx STS1 register address */ + i2cxbase += 0x14; + } + else + { + /* Flag in I2Cx STS2 Register */ + I2C_FLAG = (uint32_t)(I2C_FLAG >> 16); + /* Get the I2Cx STS2 register address */ + i2cxbase += 0x18; + } + + if (((*(__IO uint32_t*)i2cxbase) & I2C_FLAG) != (uint32_t)RESET) + { + /* I2C_FLAG is set */ + bitstatus = SET; + } + else + { + /* I2C_FLAG is reset */ + bitstatus = RESET; + } + + /* Return the I2C_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the I2Cx's pending flags. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_FLAG specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg I2C_FLAG_SMBALERT SMBus Alert flag + * @arg I2C_FLAG_TIMOUT Timeout or Tlow error flag + * @arg I2C_FLAG_PECERR PEC error in reception flag + * @arg I2C_FLAG_OVERRUN Overrun/Underrun flag (Slave mode) + * @arg I2C_FLAG_ACKFAIL Acknowledge failure flag + * @arg I2C_FLAG_ARLOST Arbitration lost flag (Master mode) + * @arg I2C_FLAG_BUSERR Bus error flag + * + * @note + * - STOPF (STOP detection) is cleared by software sequence: a read operation + * to I2C_STS1 register (I2C_GetFlag()) followed by a write operation + * to I2C_CTRL1 register (I2C_Enable() to re-enable the I2C peripheral). + * - ADD10 (10-bit header sent) is cleared by software sequence: a read + * operation to I2C_STS1 (I2C_GetFlag()) followed by writing the + * second byte of the address in DAT register. + * - BTF (Byte Transfer Finished) is cleared by software sequence: a read + * operation to I2C_STS1 register (I2C_GetFlag()) followed by a + * read/write to I2C_DAT register (I2C_SendData()). + * - ADDR (Address sent) is cleared by software sequence: a read operation to + * I2C_STS1 register (I2C_GetFlag()) followed by a read operation to + * I2C_STS2 register ((void)(I2Cx->STS2)). + * - SB (Start Bit) is cleared software sequence: a read operation to I2C_STS1 + * register (I2C_GetFlag()) followed by a write operation to I2C_DAT + * register (I2C_SendData()). + */ +void I2C_ClrFlag(I2C_Module* I2Cx, uint32_t I2C_FLAG) +{ + uint32_t flagpos = 0; + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_CLR_FLAG(I2C_FLAG)); + /* Get the I2C flag position */ + flagpos = I2C_FLAG & FLAG_MASK; + /* Clear the selected I2C flag */ + I2Cx->STS1 = (uint16_t)~flagpos; +} + +/** + * @brief Checks whether the specified I2C interrupt has occurred or not. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_IT specifies the interrupt source to check. + * This parameter can be one of the following values: + * @arg I2C_INT_SMBALERT SMBus Alert flag + * @arg I2C_INT_TIMOUT Timeout or Tlow error flag + * @arg I2C_INT_PECERR PEC error in reception flag + * @arg I2C_INT_OVERRUN Overrun/Underrun flag (Slave mode) + * @arg I2C_INT_ACKFAIL Acknowledge failure flag + * @arg I2C_INT_ARLOST Arbitration lost flag (Master mode) + * @arg I2C_INT_BUSERR Bus error flag + * @arg I2C_INT_TXDATE Data register empty flag (Transmitter) + * @arg I2C_INT_RXDATNE Data register not empty (Receiver) flag + * @arg I2C_INT_STOPF Stop detection flag (Slave mode) + * @arg I2C_INT_ADDR10F 10-bit header sent flag (Master mode) + * @arg I2C_INT_BYTEF Byte transfer finished flag + * @arg I2C_INT_ADDRF Address sent flag (Master mode) "ADSL" + * Address matched flag (Slave mode)"ENDAD" + * @arg I2C_INT_STARTBF Start bit flag (Master mode) + * @return The new state of I2C_IT (SET or RESET). + */ +INTStatus I2C_GetIntStatus(I2C_Module* I2Cx, uint32_t I2C_IT) +{ + INTStatus bitstatus = RESET; + uint32_t enablestatus = 0; + + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_GET_INT(I2C_IT)); + + /* Check if the interrupt source is enabled or not */ + enablestatus = (uint32_t)(((I2C_IT & INTEN_MASK) >> 16) & (I2Cx->CTRL2)); + + /* Get bit[23:0] of the flag */ + I2C_IT &= FLAG_MASK; + + /* Check the status of the specified I2C flag */ + if (((I2Cx->STS1 & I2C_IT) != (uint32_t)RESET) && enablestatus) + { + /* I2C_IT is set */ + bitstatus = SET; + } + else + { + /* I2C_IT is reset */ + bitstatus = RESET; + } + /* Return the I2C_IT status */ + return bitstatus; +} + +/** + * @brief Clears the I2Cx's interrupt pending bits. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_IT specifies the interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg I2C_INT_SMBALERT SMBus Alert interrupt + * @arg I2C_INT_TIMOUT Timeout or Tlow error interrupt + * @arg I2C_INT_PECERR PEC error in reception interrupt + * @arg I2C_INT_OVERRUN Overrun/Underrun interrupt (Slave mode) + * @arg I2C_INT_ACKFAIL Acknowledge failure interrupt + * @arg I2C_INT_ARLOST Arbitration lost interrupt (Master mode) + * @arg I2C_INT_BUSERR Bus error interrupt + * + * @note + * - STOPF (STOP detection) is cleared by software sequence: a read operation + * to I2C_STS1 register (I2C_GetIntStatus()) followed by a write operation to + * I2C_CTRL1 register (I2C_Enable() to re-enable the I2C peripheral). + * - ADD10 (10-bit header sent) is cleared by software sequence: a read + * operation to I2C_STS1 (I2C_GetIntStatus()) followed by writing the second + * byte of the address in I2C_DAT register. + * - BTF (Byte Transfer Finished) is cleared by software sequence: a read + * operation to I2C_STS1 register (I2C_GetIntStatus()) followed by a + * read/write to I2C_DAT register (I2C_SendData()). + * - ADDR (Address sent) is cleared by software sequence: a read operation to + * I2C_STS1 register (I2C_GetIntStatus()) followed by a read operation to + * I2C_STS2 register ((void)(I2Cx->STS2)). + * - SB (Start Bit) is cleared by software sequence: a read operation to + * I2C_STS1 register (I2C_GetIntStatus()) followed by a write operation to + * I2C_DAT register (I2C_SendData()). + */ +void I2C_ClrIntPendingBit(I2C_Module* I2Cx, uint32_t I2C_IT) +{ + uint32_t flagpos = 0; + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_CLR_INT(I2C_IT)); + /* Get the I2C flag position */ + flagpos = I2C_IT & FLAG_MASK; + /* Clear the selected I2C flag */ + I2Cx->STS1 = (uint16_t)~flagpos; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_iwdg.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_iwdg.c new file mode 100644 index 0000000000..360e713fc7 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_iwdg.c @@ -0,0 +1,193 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_iwdg.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_iwdg.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup IWDG + * @brief IWDG driver modules + * @{ + */ + +/** @addtogroup IWDG_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup IWDG_Private_Defines + * @{ + */ + +/* ---------------------- IWDG registers bit mask ----------------------------*/ + +/* KEY register bit mask */ +#define KEY_ReloadKey ((uint16_t)0xAAAA) +#define KEY_EnableKey ((uint16_t)0xCCCC) + +/** + * @} + */ + +/** @addtogroup IWDG_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup IWDG_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup IWDG_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup IWDG_Private_Functions + * @{ + */ + +/** + * @brief Enables or disables write access to IWDG_PR and IWDG_RLR registers. + * @param IWDG_WriteAccess new state of write access to IWDG_PR and IWDG_RLR registers. + * This parameter can be one of the following values: + * @arg IWDG_WRITE_ENABLE Enable write access to IWDG_PR and IWDG_RLR registers + * @arg IWDG_WRITE_DISABLE Disable write access to IWDG_PR and IWDG_RLR registers + */ +void IWDG_WriteConfig(uint16_t IWDG_WriteAccess) +{ + /* Check the parameters */ + assert_param(IS_IWDG_WRITE(IWDG_WriteAccess)); + IWDG->KEY = IWDG_WriteAccess; +} + +/** + * @brief Sets IWDG Prescaler value. + * @param IWDG_Prescaler specifies the IWDG Prescaler value. + * This parameter can be one of the following values: + * @arg IWDG_PRESCALER_DIV4 IWDG prescaler set to 4 + * @arg IWDG_PRESCALER_DIV8 IWDG prescaler set to 8 + * @arg IWDG_PRESCALER_DIV16 IWDG prescaler set to 16 + * @arg IWDG_PRESCALER_DIV32 IWDG prescaler set to 32 + * @arg IWDG_PRESCALER_DIV64 IWDG prescaler set to 64 + * @arg IWDG_PRESCALER_DIV128 IWDG prescaler set to 128 + * @arg IWDG_PRESCALER_DIV256 IWDG prescaler set to 256 + */ +void IWDG_SetPrescalerDiv(uint8_t IWDG_Prescaler) +{ + /* Check the parameters */ + assert_param(IS_IWDG_PRESCALER_DIV(IWDG_Prescaler)); + IWDG->PREDIV = IWDG_Prescaler; +} + +/** + * @brief Sets IWDG Reload value. + * @param Reload specifies the IWDG Reload value. + * This parameter must be a number between 0 and 0x0FFF. + */ +void IWDG_CntReload(uint16_t Reload) +{ + /* Check the parameters */ + assert_param(IS_IWDG_RELOAD(Reload)); + IWDG->RELV = Reload; +} + +/** + * @brief Reloads IWDG counter with value defined in the reload register + * (write access to IWDG_PR and IWDG_RLR registers disabled). + */ +void IWDG_ReloadKey(void) +{ + IWDG->KEY = KEY_ReloadKey; +} + +/** + * @brief Enables IWDG (write access to IWDG_PR and IWDG_RLR registers disabled). + */ +void IWDG_Enable(void) +{ + IWDG->KEY = KEY_EnableKey; +} + +/** + * @brief Checks whether the specified IWDG flag is set or not. + * @param IWDG_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg IWDG_PVU_FLAG Prescaler Value Update on going + * @arg IWDG_CRVU_FLAG Reload Value Update on going + * @return The new state of IWDG_FLAG (SET or RESET). + */ +FlagStatus IWDG_GetStatus(uint16_t IWDG_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_IWDG_FLAG(IWDG_FLAG)); + if ((IWDG->STS & IWDG_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + /* Return the flag status */ + return bitstatus; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_pwr.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_pwr.c new file mode 100644 index 0000000000..7b5643333f --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_pwr.c @@ -0,0 +1,399 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_pwr.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_pwr.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup PWR + * @brief PWR driver modules + * @{ + */ + +/** @addtogroup PWR_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup PWR_Private_Defines + * @{ + */ + +/* --------- PWR registers bit address in the alias region ---------- */ +#define PWR_OFFSET (PWR_BASE - PERIPH_BASE) + +/* --- CTRL Register ---*/ + +/* Alias word address of DBKP bit */ +#define CTRL_OFFSET (PWR_OFFSET + 0x00) +#define DBKP_BITN 0x08 +#define CTRL_DBKP_BB (PERIPH_BB_BASE + (CTRL_OFFSET * 32) + (DBKP_BITN * 4)) + +/* Alias word address of PVDEN bit */ +#define PVDEN_BITN 0x04 +#define CTRL_PVDEN_BB (PERIPH_BB_BASE + (CTRL_OFFSET * 32) + (PVDEN_BITN * 4)) + +/* --- CTRLSTS Register ---*/ + +/* Alias word address of WKUPEN bit */ +#define CTRLSTS_OFFSET (PWR_OFFSET + 0x04) +#define WKUPEN_BITN 0x08 +#define CTRLSTS_WKUPEN_BB (PERIPH_BB_BASE + (CTRLSTS_OFFSET * 32) + (WKUPEN_BITN * 4)) + +/* ------------------ PWR registers bit mask ------------------------ */ + +/* CTRL register bit mask */ +#define CTRL_DS_MASK ((uint32_t)0xFFFFFFFC) +#define CTRL_PRS_MASK ((uint32_t)0xFFFFFD1F) + +/** + * @} + */ + +/** @addtogroup PWR_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup PWR_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup PWR_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup PWR_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the PWR peripheral registers to their default reset values. + */ +void PWR_DeInit(void) +{ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_PWR, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_PWR, DISABLE); +} + +/** + * @brief Enables or disables access to the RTC and backup registers. + * @param Cmd new state of the access to the RTC and backup registers. + * This parameter can be: ENABLE or DISABLE. + */ +void PWR_BackupAccessEnable(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)CTRL_DBKP_BB = (uint32_t)Cmd; +} + +/** + * @brief Enables or disables the Power Voltage Detector(PVD). + * @param Cmd new state of the PVD. + * This parameter can be: ENABLE or DISABLE. + */ +void PWR_PvdEnable(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)CTRL_PVDEN_BB = (uint32_t)Cmd; +} + +/** + * @brief Configures the voltage threshold detected by the Power Voltage Detector(PVD). + * @param PWR_PVDLevel specifies the PVD detection level + * This parameter can be one of the following values: + * @arg PWR_PVDRANGRE_2V2 PVD detection level set to 2.2V + * @arg PWR_PVDRANGRE_2V3 PVD detection level set to 2.3V + * @arg PWR_PVDRANGRE_2V4 PVD detection level set to 2.4V + * @arg PWR_PVDRANGRE_2V5 PVD detection level set to 2.5V + * @arg PWR_PVDRANGRE_2V6 PVD detection level set to 2.6V + * @arg PWR_PVDRANGRE_2V7 PVD detection level set to 2.7V + * @arg PWR_PVDRANGRE_2V8 PVD detection level set to 2.8V + * @arg PWR_PVDRANGRE_2V9 PVD detection level set to 2.9V + */ +void PWR_PvdRangeConfig(uint32_t PWR_PVDLevel) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_PWR_PVD_LEVEL(PWR_PVDLevel)); + tmpregister = PWR->CTRL; + /* Clear PRS[7:5] bits */ + tmpregister &= CTRL_PRS_MASK; + /* Set PRS[7:5] bits according to PWR_PVDLevel value */ + tmpregister |= PWR_PVDLevel; + /* Store the new value */ + PWR->CTRL = tmpregister; +} + +/** + * @brief Enables or disables the WakeUp Pin functionality. + * @param Cmd new state of the WakeUp Pin functionality. + * This parameter can be: ENABLE or DISABLE. + */ +void PWR_WakeUpPinEnable(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)CTRLSTS_WKUPEN_BB = (uint32_t)Cmd; +} + +/** + * @brief Enters SLEEP mode. + * @param SLEEPONEXIT specifies the SLEEPONEXIT state in SLEEP mode. + * This parameter can be one of the following values: + * @arg 0 SLEEP mode with SLEEPONEXIT disable + * @arg 1 SLEEP mode with SLEEPONEXIT enable + * @param PWR_STOPEntry specifies if SLEEP mode in entered with WFI or WFE instruction. + * This parameter can be one of the following values: + * @arg PWR_STOPENTRY_WFI enter SLEEP mode with WFI instruction + * @arg PWR_STOPENTRY_WFE enter SLEEP mode with WFE instruction + */ +void PWR_EnterSLEEPMode(uint8_t SLEEPONEXIT, uint8_t PWR_STOPEntry) +{ + // uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry)); + + /* CLEAR SLEEPDEEP bit of Cortex System Control Register */ + SCB->SCR &= (uint32_t) ~((uint32_t)SCB_SCR_SLEEPDEEP); + + /* Select SLEEPONEXIT mode entry --------------------------------------------------*/ + if (SLEEPONEXIT == 1) + { + /* the MCU enters Sleep mode as soon as it exits the lowest priority INTSTS */ + SCB->SCR |= SCB_SCR_SLEEPONEXIT; + } + else if (SLEEPONEXIT == 0) + { + /* Sleep-now */ + SCB->SCR &= (uint32_t) ~((uint32_t)SCB_SCR_SLEEPONEXIT); + } + + /* Select SLEEP mode entry --------------------------------------------------*/ + if (PWR_STOPEntry == PWR_STOPENTRY_WFI) + { + /* Request Wait For Interrupt */ + __WFI(); + } + else + { + /* Request Wait For Event */ + __SEV(); + __WFE(); + __WFE(); + } +} + +/** + * @brief Enters STOP mode. + * @param PWR_Regulator specifies the regulator state in STOP mode. + * This parameter can be one of the following values: + * @arg PWR_REGULATOR_ON STOP mode with regulator ON + * @arg PWR_REGULATOR_LOWPOWER STOP mode with regulator in low power mode + * @param PWR_STOPEntry specifies if STOP mode in entered with WFI or WFE instruction. + * This parameter can be one of the following values: + * @arg PWR_STOPENTRY_WFI enter STOP mode with WFI instruction + * @arg PWR_STOPENTRY_WFE enter STOP mode with WFE instruction + */ +void PWR_EnterStopState(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_PWR_REGULATOR(PWR_Regulator)); + assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry)); + + /* Select the regulator state in STOP mode ---------------------------------*/ + tmpregister = PWR->CTRL; + /* Clear PDS and LPS bits */ + tmpregister &= CTRL_DS_MASK; + /* Set LPS bit according to PWR_Regulator value */ + tmpregister |= PWR_Regulator; + /* Store the new value */ + PWR->CTRL = tmpregister; + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP; + + /* Select STOP mode entry --------------------------------------------------*/ + if (PWR_STOPEntry == PWR_STOPENTRY_WFI) + { + /* Request Wait For Interrupt */ + __WFI(); + } + else + { + /* Request Wait For Event */ + __SEV(); + __WFE(); + __WFE(); + } + + /* Reset SLEEPDEEP bit of Cortex System Control Register */ + SCB->SCR &= (uint32_t) ~((uint32_t)SCB_SCR_SLEEPDEEP); +} + +/** + * @brief Enters STOP2 mode. + * @param PWR_STOPEntry specifies if STOP2 mode in entered with WFI or WFE instruction. + * This parameter can be one of the following values: + * @arg PWR_STOPENTRY_WFI enter STOP2 mode with WFI instruction + * @arg PWR_STOPENTRY_WFE enter STOP2 mode with WFE instruction + */ +void PWR_EnterSTOP2Mode(uint8_t PWR_STOPEntry) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry)); + + /* Select the regulator state in STOP2 mode ---------------------------------*/ + tmpregister = PWR->CTRL; + /* Clear PDS and LPS bits */ + tmpregister &= CTRL_DS_MASK; + /* Store the new value */ + PWR->CTRL = tmpregister; + /*STOP2 sleep mode control-stop2s*/ + PWR->CTRL2 |= PWR_CTRL2_STOP2S; + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP; + // PWR_CTRL2.BIT0 STOP2S need? + /* Select STOP mode entry --------------------------------------------------*/ + if (PWR_STOPEntry == PWR_STOPENTRY_WFI) + { + /* Request Wait For Interrupt */ + __WFI(); + } + else + { + /* Request Wait For Event */ + __SEV(); + __WFE(); + __WFE(); + } + + /* Reset SLEEPDEEP bit of Cortex System Control Register */ + SCB->SCR &= (uint32_t) ~((uint32_t)SCB_SCR_SLEEPDEEP); +} + +/** + * @brief Enters STANDBY mode. + */ +void PWR_EnterStandbyState(void) +{ + /* Clear Wake-up flag */ + PWR->CTRL |= PWR_CTRL_CWKUP; + /* Clear PDS and LPS bits */ + PWR->CTRL &= CTRL_DS_MASK; + /* Select STANDBY mode */ + PWR->CTRL |= PWR_CTRL_PDS; + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP; +/* This option is used to ensure that store operations are completed */ +#if defined(__CC_ARM) + __force_stores(); +#endif + /* Request Wait For Interrupt */ + __WFI(); +} + +/** + * @brief Checks whether the specified PWR flag is set or not. + * @param PWR_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg PWR_WU_FLAG Wake Up flag + * @arg PWR_SB_FLAG StandBy flag + * @arg PWR_PVDO_FLAG PVD Output + * @arg PWR_VBATF_FLAG VBAT flag + * @return The new state of PWR_FLAG (SET or RESET). + */ +FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_PWR_GET_FLAG(PWR_FLAG)); + + if ((PWR->CTRLSTS & PWR_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + /* Return the flag status */ + return bitstatus; +} + +/** + * @brief Clears the PWR's pending flags. + * @param PWR_FLAG specifies the flag to clear. + * This parameter can be one of the following values: + * @arg PWR_WU_FLAG Wake Up flag + * @arg PWR_SB_FLAG StandBy and VBAT flag + */ +void PWR_ClearFlag(uint32_t PWR_FLAG) +{ + /* Check the parameters */ + assert_param(IS_PWR_CLEAR_FLAG(PWR_FLAG)); + + PWR->CTRL |= PWR_FLAG << 2; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_qspi.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_qspi.c new file mode 100644 index 0000000000..a3f27a775e --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_qspi.c @@ -0,0 +1,576 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_qspi.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_qspi.h" + +/** + * @brief Control QSPI function switch. + * @param cmd select enable or disable QSPI. + */ +void QSPI_Cmd(bool cmd) +{ + if (cmd != DISABLE) + { + QSPI->SLAVE_EN = QSPI_SLAVE_EN_SEN; + QSPI->EN = QSPI_EN_QEN; + } + else + { + QSPI->SLAVE_EN &= ~QSPI_SLAVE_EN_SEN; + QSPI->EN &= ~QSPI_EN_QEN; + } +} +/** + * @brief Control QSPI XIP function switch. + * @param cmd select enable or disable QSPI XIP. + */ +void QSPI_XIP_Cmd(bool cmd) +{ + if (cmd != DISABLE) + { + QSPI->XIP_SLAVE_EN = QSPI_XIP_SLAVE_EN_SEN; + } + else + { + QSPI->XIP_SLAVE_EN &= ~QSPI_XIP_SLAVE_EN_SEN; + } +} +/** + * @brief Deinitializes the QSPI peripheral registers to its default reset values. + */ +void QSPI_DeInit(void) +{ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_QSPI, ENABLE); + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_QSPI, DISABLE); +} +/** + * @brief Merge configuration from the buffer of QSPI para struct, then write it into related registers. + * @param QSPI_InitStruct pointer to buffer of QSPI para struct. + */ +void QspiInitConfig(QSPI_InitType* QSPI_InitStruct) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_QSPI_SPI_FRF(QSPI_InitStruct->SPI_FRF)); + assert_param(IS_QSPI_CFS(QSPI_InitStruct->CFS)); + assert_param(IS_QSPI_SSTE(QSPI_InitStruct->SSTE)); + assert_param(IS_QSPI_TMOD(QSPI_InitStruct->TMOD)); + assert_param(IS_QSPI_SCPOL(QSPI_InitStruct->SCPOL)); + assert_param(IS_QSPI_SCPH(QSPI_InitStruct->SCPH)); + assert_param(IS_QSPI_FRF(QSPI_InitStruct->FRF)); + assert_param(IS_QSPI_DFS(QSPI_InitStruct->DFS)); + assert_param(IS_QSPI_MWMOD(QSPI_InitStruct->MWMOD)); + assert_param(IS_QSPI_MC_DIR(QSPI_InitStruct->MC_DIR)); + assert_param(IS_QSPI_MHS_EN(QSPI_InitStruct->MHS_EN)); + assert_param(IS_QSPI_SES(QSPI_InitStruct->SES)); + assert_param(IS_QSPI_SDCN(QSPI_InitStruct->SDCN)); + + assert_param(IS_QSPI_ENH_CLK_STRETCH_EN(QSPI_InitStruct->ENHANCED_CLK_STRETCH_EN)); + assert_param(IS_QSPI_ENH_INST_DDR_EN(QSPI_InitStruct->ENHANCED_INST_DDR_EN)); + assert_param(IS_QSPI_ENH_SPI_DDR_EN(QSPI_InitStruct->ENHANCED_SPI_DDR_EN)); + assert_param(IS_QSPI_ENH_WAIT_CYCLES(QSPI_InitStruct->ENHANCED_WAIT_CYCLES)); + assert_param(IS_QSPI_ENH_INST_L(QSPI_InitStruct->ENHANCED_INST_L)); + assert_param(IS_QSPI_ENH_ADDR_LEN(QSPI_InitStruct->ENHANCED_ADDR_LEN)); + assert_param(IS_QSPI_ENH_TRANS_TYPE(QSPI_InitStruct->ENHANCED_TRANS_TYPE)); + + assert_param(IS_QSPI_XIP_MBL(QSPI_InitStruct->XIP_MBL)); + assert_param(IS_QSPI_XIP_CT_EN(QSPI_InitStruct->XIP_CT_EN)); + assert_param(IS_QSPI_XIP_INST_EN(QSPI_InitStruct->XIP_INST_EN)); + assert_param(IS_QSPI_INST_DDR_EN(QSPI_InitStruct->XIP_INST_DDR_EN)); + assert_param(IS_QSPI_DDR_EN(QSPI_InitStruct->XIP_DDR_EN)); + assert_param(IS_QSPI_XIP_DFS_HC(QSPI_InitStruct->XIP_DFS_HC)); + assert_param(IS_QSPI_XIP_WAIT_CYCLES(QSPI_InitStruct->XIP_WAIT_CYCLES)); + assert_param(IS_QSPI_XIP_MD_BIT_EN(QSPI_InitStruct->XIP_MD_BITS_EN)); + assert_param(IS_QSPI_XIP_INST_L(QSPI_InitStruct->XIP_INST_L)); + assert_param(IS_QSPI_XIP_ADDR_LEN(QSPI_InitStruct->XIP_ADDR_LEN)); + assert_param(IS_QSPI_XIP_TRANS_TYPE(QSPI_InitStruct->XIP_TRANS_TYPE)); + assert_param(IS_QSPI_XIP_FRF(QSPI_InitStruct->XIP_FRF)); + + assert_param(IS_QSPI_XIP_MODE(QSPI_InitStruct->XIP_MD_BITS)); + assert_param(IS_QSPI_XIP_INCR_TOC(QSPI_InitStruct->ITOC)); + assert_param(IS_QSPI_XIP_WRAP_TOC(QSPI_InitStruct->WTOC)); + assert_param(IS_QSPI_XIP_TOUT(QSPI_InitStruct->XTOUT)); + + assert_param(IS_QSPI_NDF(QSPI_InitStruct->NDF)); + assert_param(IS_QSPI_CLK_DIV(QSPI_InitStruct->CLK_DIV)); + assert_param(IS_QSPI_TXFT(QSPI_InitStruct->TXFT)); + assert_param(IS_QSPI_RXFT(QSPI_InitStruct->RXFT)); + assert_param(IS_QSPI_TXFN(QSPI_InitStruct->TXFN)); + assert_param(IS_QSPI_RXFN(QSPI_InitStruct->RXFN)); + assert_param(IS_QSPI_DDR_TXDE(QSPI_InitStruct->TXDE)); + + if((QSPI_InitStruct->SPI_FRF) == QSPI_CTRL0_SPI_FRF_STANDARD_FORMAT) + { + tmpregister = (uint32_t)(QSPI_InitStruct->SPI_FRF | QSPI_InitStruct->CFS | QSPI_InitStruct->SSTE | QSPI_InitStruct->TMOD + | QSPI_InitStruct->SCPOL | QSPI_InitStruct->SCPH | QSPI_InitStruct->FRF | QSPI_InitStruct->DFS); + QSPI->CTRL0 = tmpregister; + + tmpregister = 0; + tmpregister = (uint32_t)(QSPI_InitStruct->MWMOD | QSPI_InitStruct->MC_DIR | QSPI_InitStruct->MHS_EN); + QSPI->MW_CTRL = tmpregister; + + tmpregister = 0; + tmpregister = (uint32_t)(QSPI_InitStruct->SES | QSPI_InitStruct->SDCN); + QSPI->RS_DELAY = tmpregister; + } + else if((QSPI_InitStruct->SPI_FRF == QSPI_CTRL0_SPI_FRF_DUAL_FORMAT) || (QSPI_InitStruct->SPI_FRF == QSPI_CTRL0_SPI_FRF_QUAD_FORMAT)) + { + tmpregister = (uint32_t)(QSPI_InitStruct->SPI_FRF | QSPI_InitStruct->CFS | QSPI_InitStruct->SSTE | QSPI_InitStruct->TMOD + | QSPI_InitStruct->SCPOL | QSPI_InitStruct->SCPH | QSPI_InitStruct->FRF | QSPI_InitStruct->DFS); + QSPI->CTRL0 = tmpregister; + + tmpregister = 0; + tmpregister = (uint32_t)(QSPI_InitStruct->MWMOD | QSPI_InitStruct->MC_DIR | QSPI_InitStruct->MHS_EN); + QSPI->MW_CTRL = tmpregister; + + tmpregister = 0; + tmpregister = (uint32_t)(QSPI_InitStruct->SES | QSPI_InitStruct->SDCN); + QSPI->RS_DELAY = tmpregister; + + tmpregister = 0; + tmpregister = (uint32_t)(QSPI_InitStruct->ENHANCED_CLK_STRETCH_EN | QSPI_InitStruct->ENHANCED_INST_DDR_EN + | QSPI_InitStruct->ENHANCED_SPI_DDR_EN | QSPI_InitStruct->ENHANCED_WAIT_CYCLES | QSPI_InitStruct->ENHANCED_INST_L + | QSPI_InitStruct->ENHANCED_ADDR_LEN | QSPI_InitStruct->ENHANCED_TRANS_TYPE); + QSPI->ENH_CTRL0 = tmpregister; + + tmpregister = 0; + tmpregister = (uint32_t)(QSPI_InitStruct->XIP_MBL | QSPI_InitStruct->XIP_CT_EN | QSPI_InitStruct->XIP_INST_EN | QSPI_InitStruct->XIP_INST_DDR_EN + | QSPI_InitStruct->XIP_DDR_EN | QSPI_InitStruct->XIP_DFS_HC | QSPI_InitStruct->XIP_WAIT_CYCLES | QSPI_InitStruct->XIP_MD_BITS_EN + | QSPI_InitStruct->XIP_INST_L | QSPI_InitStruct->XIP_ADDR_LEN | QSPI_InitStruct->XIP_TRANS_TYPE | QSPI_InitStruct->XIP_FRF); + QSPI->XIP_CTRL = tmpregister; + + QSPI->XIP_MODE = QSPI_InitStruct->XIP_MD_BITS; + QSPI->XIP_INCR_TOC = QSPI_InitStruct->ITOC; + QSPI->XIP_WRAP_TOC = QSPI_InitStruct->WTOC; + QSPI->XIP_TOUT = QSPI_InitStruct->XTOUT; + } + QSPI->CTRL1 = QSPI_InitStruct->NDF; + QSPI->BAUD = QSPI_InitStruct->CLK_DIV; + QSPI->TXFT = QSPI_InitStruct->TXFT; + QSPI->RXFT = QSPI_InitStruct->RXFT; + QSPI->TXFN = QSPI_InitStruct->TXFN; + QSPI->RXFN = QSPI_InitStruct->RXFN; + QSPI->DDR_TXDE = QSPI_InitStruct->TXDE; +} +/** + * @brief Configure single GPIO port as GPIO_Mode_AF_PP. + * @param GPIOx x can be A to G to select the GPIO port. + * @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15. + */ +static void QSPI_SingleGpioConfig(GPIO_Module* GPIOx, uint16_t Pin) +{ + GPIO_InitType GPIO_InitStructure; + + GPIO_InitStructure.Pin = Pin; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure); +} +/** + * @brief Remap QSPI AFIO group by selecting the pin of NSS. + * @param qspi_nss_port_sel select the pin of NSS. + QSPI_NSS_PORTA_SEL:QSPI remap by PA4~PA7 and PC4~PC5. + QSPI_NSS_PORTC_SEL:QSPI remap by PC10~PC12 and PD0~PD2. + * @param IO1_Input IO1 Configure as input or not. + * @param IO3_Output IO3 Configure as output or not. + */ +void QSPI_GPIO(QSPI_NSS_PORT_SEL qspi_nss_port_sel, bool IO1_Input, bool IO3_Output) +{ + GPIO_InitType GPIO_InitStructure; + + switch (qspi_nss_port_sel) + { + case QSPI_NSS_PORTA_SEL: + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_GPIOC | RCC_APB2_PERIPH_AFIO, ENABLE); + RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_QSPI, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP3_QSPI, DISABLE); //clear two bits of qspi + + QSPI_SingleGpioConfig(GPIOA, GPIO_PIN_4); // NSS + QSPI_SingleGpioConfig(GPIOA, GPIO_PIN_5); // SCK + QSPI_SingleGpioConfig(GPIOA, GPIO_PIN_6); // IO0 + if (IO1_Input) + { + GPIO_InitStructure.Pin = GPIO_PIN_7; // IO1 + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_INPUT; + GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure); + } + else + { + QSPI_SingleGpioConfig(GPIOA, GPIO_PIN_7); // IO1 + } + + if (IO3_Output) + { + GPIO_InitStructure.Pin = GPIO_PIN_4 | GPIO_PIN_5; // IO2 and IO3 + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure); + + GPIOC->PBSC |= GPIO_PIN_4 | GPIO_PIN_5; + } + else + { + QSPI_SingleGpioConfig(GPIOC, GPIO_PIN_4); // IO2 + QSPI_SingleGpioConfig(GPIOC, GPIO_PIN_5); // IO3 + } + break; + case QSPI_NSS_PORTC_SEL: + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC | RCC_APB2_PERIPH_GPIOD | RCC_APB2_PERIPH_AFIO, ENABLE); + + RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_QSPI, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP3_QSPI, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP_QSPI_XIP_EN, ENABLE); + + QSPI_SingleGpioConfig(GPIOC, GPIO_PIN_10); // NSS + QSPI_SingleGpioConfig(GPIOC, GPIO_PIN_11); // SCK + QSPI_SingleGpioConfig(GPIOC, GPIO_PIN_12); // IO0 + if (IO1_Input) + { + GPIO_InitStructure.Pin = GPIO_PIN_0; // IO1 + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_INPUT; + GPIO_InitPeripheral(GPIOD, &GPIO_InitStructure); + } + else + { + QSPI_SingleGpioConfig(GPIOD, GPIO_PIN_0); // IO1 + } + + if (IO3_Output) + { + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2; // IO2 and IO3 + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitPeripheral(GPIOD, &GPIO_InitStructure); + + GPIOD->PBSC |= GPIO_PIN_1 | GPIO_PIN_2; + } + else + { + QSPI_SingleGpioConfig(GPIOD, GPIO_PIN_1); // IO2 + QSPI_SingleGpioConfig(GPIOD, GPIO_PIN_2); // IO3 + } + break; + default: + break; + } +} + +/** + * @brief Configuration of QSPI DMA. + * @param TxRx transmit or receive data. + QSPI_DMA_CTRL_TX_DMA_EN:transmit data + * @param TxDataLevel dma transmit data level. + */ +void QSPI_Tx_DMA_CTRL_Config(uint8_t Cmd,uint8_t TxDataLevel) +{ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + assert_param(IS_QSPI_DMATDL_CTRL(TxDataLevel)); + if (Cmd) + { + QSPI->DMATDL_CTRL = TxDataLevel; + QSPI->DMA_CTRL |= QSPI_DMA_CTRL_TX_DMA_EN; + } + else + { + QSPI->DMA_CTRL &= ~QSPI_DMA_CTRL_TX_DMA_EN; + } +} + +/** + * @brief Configuration of QSPI DMA. + * @param TxRx transmit or receive data. + QSPI_DMA_CTRL_RX_DMA_EN:receive data + * @param RxDataLevel dma receive data level. + */ +void QSPI_Rx_DMA_CTRL_Config(uint8_t Cmd, uint8_t RxDataLevel) +{ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + assert_param(IS_QSPI_DMARDL_CTRL(RxDataLevel)); + + if (Cmd) + { + QSPI->DMARDL_CTRL = RxDataLevel; + QSPI->DMA_CTRL |= QSPI_DMA_CTRL_RX_DMA_EN; + } + else + { + QSPI->DMA_CTRL &= ~QSPI_DMA_CTRL_RX_DMA_EN; + } +} +/** + * @brief Get the flag of interrupt status register. + * @param FLAG flag of related interrupt register. + */ +uint16_t QSPI_GetITStatus(uint16_t FLAG) +{ + uint16_t tmp = 0; + tmp = QSPI->ISTS & FLAG; + if (tmp) + return 1; + else + return 0; +} +/** + * @brief Clear the flag of related interrupt register. + * @param FLAG flag of related interrupt register. + */ +void QSPI_ClearITFLAG(uint16_t FLAG) +{ + if (FLAG == QSPI_ISTS_TXFOIS) + (void)QSPI->TXFOI_CLR; + else if (FLAG == QSPI_ISTS_RXFOIS) + (void)QSPI->RXFOI_CLR; + else if (FLAG == QSPI_ISTS_RXFUIS) + (void)QSPI->RXFUI_CLR; + else if (FLAG == QSPI_ISTS_MMCIS) + (void)QSPI->MMC_CLR; + else if (FLAG == QSPI_ISTS) + (void)QSPI->ICLR; + else + { + } +} +/** + * @brief Clear the flag of related interrupt register. + * @param FLAG flag of XRXFOIC interrupt register. + */ +void QSPI_XIP_ClearITFLAG(uint16_t FLAG) +{ + if (FLAG == QSPI_XIP_RXFOI_CLR_XRXFOIC) + (void)QSPI->XIP_RXFOI_CLR; +} +/** + * @brief Get QSPI status,busy or not. + * @return 1:QSPI busy;0:QSPI idle. + */ +bool GetQspiBusyStatus(void) +{ + if ((QSPI->STS & 0x01) == 0x01) + return 1; + return 0; +} +/** + * @brief Check transmit fifo full or not. + * @return 1: Transmit fifo full;0: Transmit fifo not full. + */ +bool GetQspiTxDataBusyStatus(void) +{ + if ((QSPI->STS & 0x02) == 0x00) + return 1; + return 0; +} +/** + * @brief Check transmit fifo empty or not. + * @return 1: Transmit fifo empty;0: Transmit fifo not empty. + */ +bool GetQspiTxDataEmptyStatus(void) +{ + if ((QSPI->STS & 0x04) == 0x04) + return 1; + return 0; +} +/** + * @brief Check receive fifo have data or not. + * @return 1:Receive fifo have data;0:Receive fifo empty. + */ +bool GetQspiRxHaveDataStatus(void) +{ + if ((QSPI->STS & 0x08) == 0x08) + return 1; + return 0; +} +/** + * @brief Check receive fifo full or not. + * @return 1: Receive fifo full;0: Receive fifo not full. + */ +bool GetQspiRxDataFullStatus(void) +{ + if ((QSPI->STS & 0x10) == 0x10) + return 1; + return 0; +} + +/** + * @brief Check data conflict error or not. + * @return 1: Data conflict error;0: No data conflict error. + */ +bool GetQspiDataConflictErrorStatus(void) +{ + if ((QSPI->STS & 0x40) == 0x40) + return 1; + return 0; +} +/** + * @brief Write one data direct to QSPI DAT0 register to send. + * @param SendData: data to be send. + */ +void QspiSendWord(uint32_t SendData) +{ + QSPI->DAT0 = SendData; +} +/** + * @brief Read one data from QSPI DAT0 register. + * @return the value of QSPI DAT0 register. + */ +uint32_t QspiReadWord(void) +{ + return QSPI->DAT0; +} +/** + * @brief Get Pointer of QSPI DAT0 register. + * @return the pointer of QSPI DAT0 register. + */ +uint32_t QspiGetDataPointer(void) +{ + return (uint32_t)&QSPI->DAT0; +} +/** + * @brief Read value from QSPI RXFN register which shows the number of the data from receive fifo. + * @return the number of the data from receive fifo. + */ +uint32_t QspiReadRxFifoNum(void) +{ + return QSPI->RXFN; +} +/** + * @brief Read DAT0 register to clear fifo. + */ +void ClrFifo(void) +{ + uint32_t timeout = 0; + + while (GetQspiRxHaveDataStatus()) + { + QspiReadWord(); + if(++timeout >= 200) + { + break; + } + } +} +/** + * @brief Get data from fifo. + * @param pData pointer to buffer of getting fifo data. + * @param Len length of getting fifo data. + */ +uint32_t GetFifoData(uint32_t* pData, uint32_t Len) +{ + uint32_t cnt; + for (cnt = 0; cnt < Len; cnt++) + { + if (GetQspiRxHaveDataStatus()) + { + *pData++ = QspiReadWord(); + } + else + { + return QSPI_NULL; + } + } + + return QSPI_SUCCESS; +} +/** + * @brief Send words out from source data buffer and get returned datas into destination data buffer. + * @param pSrcData pointer to buffer of sending datas. + * @param pDstData pointer to buffer of getting returned datas. + * @param cnt number of sending datas. + */ +void QspiSendAndGetWords(uint32_t* pSrcData, uint32_t* pDstData, uint32_t cnt) +{ + uint32_t num = 0; + uint32_t timeout = 0; + + while (num < cnt) + { + QspiSendWord(*(pSrcData++)); + num++; + } + while (!GetQspiRxHaveDataStatus()) + { + if(++timeout >= QSPI_TIME_OUT_CNT) + { + break; + } + } + timeout = 0; + while (QSPI->RXFN < cnt) + { + if(++timeout >= QSPI_TIME_OUT_CNT) + { + break; + } + } + num = 0; + while (num < cnt) + { + *(pDstData++) = QspiReadWord(); + num++; + } +} +/** + * @brief Send one word data and get returned words into destination data buffer. + * @param WrData one word to be sent. + * @param pRdData pointer to buffer of getting returned datas. + * @param LastRd whether go on to get returned datas. + 1:go on to get returned datas. + 0:end to get returned datas. + */ +uint32_t QspiSendWordAndGetWords(uint32_t WrData, uint32_t* pRdData, uint8_t LastRd) +{ + uint32_t timeout1 = 0; + + QspiSendWord(WrData); //trammit + *pRdData = QspiReadWord(); + if(LastRd != 0) + { + while(!GetQspiRxHaveDataStatus()) //wait for data + { + if(++timeout1 >= QSPI_TIME_OUT_CNT) + { + return QSPI_NULL; //time out + } + } + + *pRdData = QspiReadWord(); //read data + return QSPI_SUCCESS; + } + + return QSPI_NULL; +} + + diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_rcc.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_rcc.c new file mode 100644 index 0000000000..3e1bbebed7 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_rcc.c @@ -0,0 +1,1364 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_rcc.c + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_rcc.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup RCC + * @brief RCC driver modules + * @{ + */ + +/** @addtogroup RCC_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup RCC_Private_Defines + * @{ + */ + +/* ------------ RCC registers bit address in the alias region ----------- */ +#define RCC_OFFSET (RCC_BASE - PERIPH_BASE) + +/* --- CTRL Register ---*/ + +/* Alias word address of HSIEN bit */ +#define CTRL_OFFSET (RCC_OFFSET + 0x00) +#define HSIEN_BITN 0x00 +#define CTRL_HSIEN_BB (PERIPH_BB_BASE + (CTRL_OFFSET * 32) + (HSIEN_BITN * 4)) + +/* Alias word address of PLLEN bit */ +#define PLLEN_BITN 0x18 +#define CTRL_PLLEN_BB (PERIPH_BB_BASE + (CTRL_OFFSET * 32) + (PLLEN_BITN * 4)) + +/* Alias word address of CLKSSEN bit */ +#define CLKSSEN_BITN 0x13 +#define CTRL_CLKSSEN_BB (PERIPH_BB_BASE + (CTRL_OFFSET * 32) + (CLKSSEN_BITN * 4)) + +/* --- CFG Register ---*/ + +/* Alias word address of USBPRES bit */ +#define CFG_OFFSET (RCC_OFFSET + 0x04) + +#define USBPRES_BITN 0x16 +#define CFG_USBPRES_BB (PERIPH_BB_BASE + (CFG_OFFSET * 32) + (USBPRES_BITN * 4)) + +#define USBPRE_Bit1Number 0x17 +#define CFGR_USBPRE_BB_BIT1 (PERIPH_BB_BASE + (CFG_OFFSET * 32) + (USBPRE_Bit1Number * 4)) + +/* --- BDCTRL Register ---*/ + +/* Alias word address of RTCEN bit */ +#define BDCTRL_OFFSET (RCC_OFFSET + 0x20) +#define RTCEN_BITN 0x0F +#define BDCTRL_RTCEN_BB (PERIPH_BB_BASE + (BDCTRL_OFFSET * 32) + (RTCEN_BITN * 4)) + +/* Alias word address of BDSFTRST bit */ +#define BDSFTRST_BITN 0x10 +#define BDCTRL_BDSFTRST_BB (PERIPH_BB_BASE + (BDCTRL_OFFSET * 32) + (BDSFTRST_BITN * 4)) + +/* --- CTRLSTS Register ---*/ + +/* Alias word address of LSIEN bit */ +#define CTRLSTS_OFFSET (RCC_OFFSET + 0x24) +#define LSIEN_BITNUMBER 0x00 +#define CTRLSTS_LSIEN_BB (PERIPH_BB_BASE + (CTRLSTS_OFFSET * 32) + (LSIEN_BITNUMBER * 4)) + +/* ---------------------- RCC registers bit mask ------------------------ */ + +/* CTRL register bit mask */ +#define CTRL_HSEBP_RESET ((uint32_t)0xFFFBFFFF) +#define CTRL_HSEBP_SET ((uint32_t)0x00040000) +#define CTRL_HSEEN_RESET ((uint32_t)0xFFFEFFFF) +#define CTRL_HSEEN_SET ((uint32_t)0x00010000) +#define CTRL_HSITRIM_MASK ((uint32_t)0xFFFFFF07) + +/* CFG register bit mask */ +#define CFG_PLL_MASK ((uint32_t)0xF7C0FFFF) + +#define CFG_PLLMULFCT_MASK ((uint32_t)0x083C0000) +#define CFG_PLLSRC_MASK ((uint32_t)0x00010000) +#define CFG_PLLHSEPRES_MASK ((uint32_t)0x00020000) +#define CFG_SCLKSTS_MASK ((uint32_t)0x0000000C) +#define CFG_SCLKSW_MASK ((uint32_t)0xFFFFFFFC) +#define CFG_AHBPRES_RESET_MASK ((uint32_t)0xFFFFFF0F) +#define CFG_AHBPRES_SET_MASK ((uint32_t)0x000000F0) +#define CFG_APB1PRES_RESET_MASK ((uint32_t)0xFFFFF8FF) +#define CFG_APB1PRES_SET_MASK ((uint32_t)0x00000700) +#define CFG_APB2PRES_RESET_MASK ((uint32_t)0xFFFFC7FF) +#define CFG_APB2PRES_SET_MASK ((uint32_t)0x00003800) + +/* CFG2 register bit mask */ +#define CFG2_TIM18CLKSEL_SET_MASK ((uint32_t)0x20000000) +#define CFG2_TIM18CLKSEL_RESET_MASK ((uint32_t)0xDFFFFFFF) +#define CFG2_RNGCPRES_SET_MASK ((uint32_t)0x1F000000) +#define CFG2_RNGCPRES_RESET_MASK ((uint32_t)0xE0FFFFFF) +#define CFG2_ADC1MSEL_SET_MASK ((uint32_t)0x00000400) +#define CFG2_ADC1MSEL_RESET_MASK ((uint32_t)0xFFFFFBFF) +#define CFG2_ADC1MPRES_SET_MASK ((uint32_t)0x0000F800) +#define CFG2_ADC1MPRES_RESET_MASK ((uint32_t)0xFFFF07FF) +#define CFG2_ADCPLLPRES_SET_MASK ((uint32_t)0x000001F0) +#define CFG2_ADCPLLPRES_RESET_MASK ((uint32_t)0xFFFFFE0F) +#define CFG2_ADCHPRES_SET_MASK ((uint32_t)0x0000000F) +#define CFG2_ADCHPRES_RESET_MASK ((uint32_t)0xFFFFFFF0) + +/* CFG3 register bit mask */ +#define CFGR3_TRNG1MSEL_SET_MASK ((uint32_t)0x00020000) +#define CFGR3_TRNG1MSEL_RESET_MASK ((uint32_t)0xFFFDFFFF) +#define CFGR3_TRNG1MPRES_SET_MASK ((uint32_t)0x0000F800) +#define CFGR3_TRNG1MPRES_RESET_MASK ((uint32_t)0xFFFF07FF) + +/* CTRLSTS register bit mask */ +#define CSR_RMRSTF_SET ((uint32_t)0x01000000) +#define CSR_RMVF_Reset ((uint32_t)0xfeffffff) + +/* RCC Flag Mask */ +#define FLAG_MASK ((uint8_t)0x1F) + +/* CLKINT register byte 2 (Bits[15:8]) base address */ +#define CLKINT_BYTE2_ADDR ((uint32_t)0x40021009) + +/* CLKINT register byte 3 (Bits[23:16]) base address */ +#define CLKINT_BYTE3_ADDR ((uint32_t)0x4002100A) + +/* CFG register byte 4 (Bits[31:24]) base address */ +#define CFG_BYTE4_ADDR ((uint32_t)0x40021007) + +/* BDCTRL register base address */ +#define BDCTRL_ADDR (PERIPH_BASE + BDCTRL_OFFSET) + +/** + * @} + */ + +/** @addtogroup RCC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup RCC_Private_Variables + * @{ + */ + +static const uint8_t s_ApbAhbPresTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9}; +static const uint8_t s_AdcHclkPresTable[16] = {1, 2, 4, 6, 8, 10, 12, 16, 32, 32, 32, 32, 32, 32, 32, 32}; +static const uint16_t s_AdcPllClkPresTable[16] = {1, 2, 4, 6, 8, 10, 12, 16, 32, 64, 128, 256, 256, 256, 256, 256}; + +/** + * @} + */ + +/** @addtogroup RCC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup RCC_Private_Functions + * @{ + */ + +/** + * @brief Resets the RCC clock configuration to the default reset state. + */ +void RCC_DeInit(void) +{ + /* Set HSIEN bit */ + RCC->CTRL |= (uint32_t)0x00000001; + + /* Reset SW, HPRE, PPRE1, PPRE2 and MCO bits */ + RCC->CFG &= (uint32_t)0xF8FFC000; + + /* Reset HSEON, CLKSSEN and PLLEN bits */ + RCC->CTRL &= (uint32_t)0xFEF6FFFF; + + /* Reset HSEBYP bit */ + RCC->CTRL &= (uint32_t)0xFFFBFFFF; + + /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRES/OTGFSPRE bits */ + RCC->CFG &= (uint32_t)0xF700FFFF; + + /* Reset CFG2 register */ + RCC->CFG2 = 0x00003800; + + /* Reset CFG3 register */ + RCC->CFG3 = 0x00003840; + + /* Disable all interrupts and clear pending bits */ + RCC->CLKINT = 0x009F0000; +} + +/** + * @brief Configures the External High Speed oscillator (HSE). + * @note HSE can not be stopped if it is used directly or through the PLL as system clock. + * @param RCC_HSE specifies the new state of the HSE. + * This parameter can be one of the following values: + * @arg RCC_HSE_DISABLE HSE oscillator OFF + * @arg RCC_HSE_ENABLE HSE oscillator ON + * @arg RCC_HSE_BYPASS HSE oscillator bypassed with external clock + */ +void RCC_ConfigHse(uint32_t RCC_HSE) +{ + /* Check the parameters */ + assert_param(IS_RCC_HSE(RCC_HSE)); + /* Reset HSEON and HSEBYP bits before configuring the HSE ------------------*/ + /* Reset HSEON bit */ + RCC->CTRL &= CTRL_HSEEN_RESET; + /* Reset HSEBYP bit */ + RCC->CTRL &= CTRL_HSEBP_RESET; + /* Configure HSE (RC_HSE_DISABLE is already covered by the code section above) */ + switch (RCC_HSE) + { + case RCC_HSE_ENABLE: + /* Set HSEON bit */ + RCC->CTRL |= CTRL_HSEEN_SET; + break; + + case RCC_HSE_BYPASS: + /* Set HSEBYP and HSEON bits */ + RCC->CTRL |= CTRL_HSEBP_SET | CTRL_HSEEN_SET; + break; + + default: + break; + } +} + +/** + * @brief Waits for HSE start-up. + * @return An ErrorStatus enumuration value: + * - SUCCESS: HSE oscillator is stable and ready to use + * - ERROR: HSE oscillator not yet ready + */ +ErrorStatus RCC_WaitHseStable(void) +{ + __IO uint32_t StartUpCounter = 0; + ErrorStatus status = ERROR; + FlagStatus HSEStatus = RESET; + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC_GetFlagStatus(RCC_FLAG_HSERD); + StartUpCounter++; + } while ((StartUpCounter != HSE_STARTUP_TIMEOUT) && (HSEStatus == RESET)); + + if (RCC_GetFlagStatus(RCC_FLAG_HSERD) != RESET) + { + status = SUCCESS; + } + else + { + status = ERROR; + } + return (status); +} + +/** + * @brief Adjusts the Internal High Speed oscillator (HSI) calibration value. + * @param HSICalibrationValue specifies the calibration trimming value. + * This parameter must be a number between 0 and 0x1F. + */ +void RCC_SetHsiCalibValue(uint8_t HSICalibrationValue) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_CALIB_VALUE(HSICalibrationValue)); + tmpregister = RCC->CTRL; + /* Clear HSITRIM[4:0] bits */ + tmpregister &= CTRL_HSITRIM_MASK; + /* Set the HSITRIM[4:0] bits according to HSICalibrationValue value */ + tmpregister |= (uint32_t)HSICalibrationValue << 3; + /* Store the new value */ + RCC->CTRL = tmpregister; +} + +/** + * @brief Enables or disables the Internal High Speed oscillator (HSI). + * @note HSI can not be stopped if it is used directly or through the PLL as system clock. + * @param Cmd new state of the HSI. This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableHsi(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)CTRL_HSIEN_BB = (uint32_t)Cmd; +} + +/** + * @brief Configures the PLL clock source and multiplication factor. + * @note This function must be used only when the PLL is disabled. + * @param RCC_PLLSource specifies the PLL entry clock source. + * this parameter can be one of the following values: + * @arg RCC_PLL_SRC_HSI_DIV2 HSI oscillator clock divided by 2 selected as PLL clock entry + * @arg RCC_PLL_SRC_HSE_DIV1 HSE oscillator clock selected as PLL clock entry + * @arg RCC_PLL_SRC_HSE_DIV2 HSE oscillator clock divided by 2 selected as PLL clock entry + * @param RCC_PLLMul specifies the PLL multiplication factor. + * this parameter can be RCC_PLLMul_x where x:[2,32] + */ +void RCC_ConfigPll(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RCC_PLL_SRC(RCC_PLLSource)); + assert_param(IS_RCC_PLL_MUL(RCC_PLLMul)); + + tmpregister = RCC->CFG; + /* Clear PLLSRC, PLLXTPRE and PLLMUL[4:0] bits */ + tmpregister &= CFG_PLL_MASK; + /* Set the PLL configuration bits */ + tmpregister |= RCC_PLLSource | RCC_PLLMul; + /* Store the new value */ + RCC->CFG = tmpregister; +} + +/** + * @brief Enables or disables the PLL. + * @note The PLL can not be disabled if it is used as system clock. + * @param Cmd new state of the PLL. This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnablePll(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)CTRL_PLLEN_BB = (uint32_t)Cmd; +} + +/** + * @brief Configures the system clock (SYSCLK). + * @param RCC_SYSCLKSource specifies the clock source used as system clock. + * This parameter can be one of the following values: + * @arg RCC_SYSCLK_SRC_HSI HSI selected as system clock + * @arg RCC_SYSCLK_SRC_HSE HSE selected as system clock + * @arg RCC_SYSCLK_SRC_PLLCLK PLL selected as system clock + */ +void RCC_ConfigSysclk(uint32_t RCC_SYSCLKSource) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_SYSCLK_SRC(RCC_SYSCLKSource)); + tmpregister = RCC->CFG; + /* Clear SW[1:0] bits */ + tmpregister &= CFG_SCLKSW_MASK; + /* Set SW[1:0] bits according to RCC_SYSCLKSource value */ + tmpregister |= RCC_SYSCLKSource; + /* Store the new value */ + RCC->CFG = tmpregister; +} + +/** + * @brief Returns the clock source used as system clock. + * @return The clock source used as system clock. The returned value can + * be one of the following: + * - 0x00: HSI used as system clock + * - 0x04: HSE used as system clock + * - 0x08: PLL used as system clock + */ +uint8_t RCC_GetSysclkSrc(void) +{ + return ((uint8_t)(RCC->CFG & CFG_SCLKSTS_MASK)); +} + +/** + * @brief Configures the AHB clock (HCLK). + * @param RCC_SYSCLK defines the AHB clock divider. This clock is derived from + * the system clock (SYSCLK). + * This parameter can be one of the following values: + * @arg RCC_SYSCLK_DIV1 AHB clock = SYSCLK + * @arg RCC_SYSCLK_DIV2 AHB clock = SYSCLK/2 + * @arg RCC_SYSCLK_DIV4 AHB clock = SYSCLK/4 + * @arg RCC_SYSCLK_DIV8 AHB clock = SYSCLK/8 + * @arg RCC_SYSCLK_DIV16 AHB clock = SYSCLK/16 + * @arg RCC_SYSCLK_DIV64 AHB clock = SYSCLK/64 + * @arg RCC_SYSCLK_DIV128 AHB clock = SYSCLK/128 + * @arg RCC_SYSCLK_DIV256 AHB clock = SYSCLK/256 + * @arg RCC_SYSCLK_DIV512 AHB clock = SYSCLK/512 + */ +void RCC_ConfigHclk(uint32_t RCC_SYSCLK) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_SYSCLK_DIV(RCC_SYSCLK)); + tmpregister = RCC->CFG; + /* Clear HPRE[3:0] bits */ + tmpregister &= CFG_AHBPRES_RESET_MASK; + /* Set HPRE[3:0] bits according to RCC_SYSCLK value */ + tmpregister |= RCC_SYSCLK; + /* Store the new value */ + RCC->CFG = tmpregister; +} + +/** + * @brief Configures the Low Speed APB clock (PCLK1). + * @param RCC_HCLK defines the APB1 clock divider. This clock is derived from + * the AHB clock (HCLK). + * This parameter can be one of the following values: + * @arg RCC_HCLK_DIV1 APB1 clock = HCLK + * @arg RCC_HCLK_DIV2 APB1 clock = HCLK/2 + * @arg RCC_HCLK_DIV4 APB1 clock = HCLK/4 + * @arg RCC_HCLK_DIV8 APB1 clock = HCLK/8 + * @arg RCC_HCLK_DIV16 APB1 clock = HCLK/16 + */ +void RCC_ConfigPclk1(uint32_t RCC_HCLK) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_HCLK_DIV(RCC_HCLK)); + tmpregister = RCC->CFG; + /* Clear PPRE1[2:0] bits */ + tmpregister &= CFG_APB1PRES_RESET_MASK; + /* Set PPRE1[2:0] bits according to RCC_HCLK value */ + tmpregister |= RCC_HCLK; + /* Store the new value */ + RCC->CFG = tmpregister; +} + +/** + * @brief Configures the High Speed APB clock (PCLK2). + * @param RCC_HCLK defines the APB2 clock divider. This clock is derived from + * the AHB clock (HCLK). + * This parameter can be one of the following values: + * @arg RCC_HCLK_DIV1 APB2 clock = HCLK + * @arg RCC_HCLK_DIV2 APB2 clock = HCLK/2 + * @arg RCC_HCLK_DIV4 APB2 clock = HCLK/4 + * @arg RCC_HCLK_DIV8 APB2 clock = HCLK/8 + * @arg RCC_HCLK_DIV16 APB2 clock = HCLK/16 + */ +void RCC_ConfigPclk2(uint32_t RCC_HCLK) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_HCLK_DIV(RCC_HCLK)); + tmpregister = RCC->CFG; + /* Clear PPRE2[2:0] bits */ + tmpregister &= CFG_APB2PRES_RESET_MASK; + /* Set PPRE2[2:0] bits according to RCC_HCLK value */ + tmpregister |= RCC_HCLK << 3; + /* Store the new value */ + RCC->CFG = tmpregister; +} + +/** + * @brief Enables or disables the specified RCC interrupts. + * @param RccInt specifies the RCC interrupt sources to be enabled or disabled. + * + * this parameter can be any combination of the following values + * @arg RCC_INT_LSIRDIF LSI ready interrupt + * @arg RCC_INT_LSERDIF LSE ready interrupt + * @arg RCC_INT_HSIRDIF HSI ready interrupt + * @arg RCC_INT_HSERDIF HSE ready interrupt + * @arg RCC_INT_PLLRDIF PLL ready interrupt + * + * @param Cmd new state of the specified RCC interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_ConfigInt(uint8_t RccInt, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_RCC_INT(RccInt)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Perform Byte access to RCC_CLKINT bits to enable the selected interrupts */ + *(__IO uint8_t*)CLKINT_BYTE2_ADDR |= RccInt; + } + else + { + /* Perform Byte access to RCC_CLKINT bits to disable the selected interrupts */ + *(__IO uint8_t*)CLKINT_BYTE2_ADDR &= (uint8_t)~RccInt; + } +} + +/** + * @brief Configures the USB clock (USBCLK). + * @param RCC_USBCLKSource specifies the USB clock source. This clock is + * derived from the PLL output. + * This parameter can be one of the following values: + * @arg RCC_USBCLK_SRC_PLLCLK_DIV1_5 PLL clock divided by 1,5 selected as USB clock source + * @arg RCC_USBCLK_SRC_PLLCLK_DIV1 PLL clock selected as USB clock source + * @arg RCC_USBCLK_SRC_PLLCLK_DIV2 PLL clock divided by 2 selected as USB clock source + * @arg RCC_USBCLK_SRC_PLLCLK_DIV3 PLL clock divided by 3 selected as USB clock source + */ +void RCC_ConfigUsbClk(uint32_t RCC_USBCLKSource) +{ + /* Check the parameters */ + assert_param(IS_RCC_USBCLK_SRC(RCC_USBCLKSource)); + + *(__IO uint32_t*)CFG_USBPRES_BB = RCC_USBCLKSource; + *(__IO uint32_t*)CFGR_USBPRE_BB_BIT1 = RCC_USBCLKSource >> 1; +} + +/** + * @brief Configures the TIM1/8 clock (TIM1/8CLK). + * @param RCC_TIM18CLKSource specifies the TIM1/8 clock source. + * This parameter can be one of the following values: + * @arg RCC_TIM18CLK_SRC_TIM18CLK + * @arg RCC_TIM18CLKSource_AHBCLK + */ +void RCC_ConfigTim18Clk(uint32_t RCC_TIM18CLKSource) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_TIM18CLKSRC(RCC_TIM18CLKSource)); + + tmpregister = RCC->CFG2; + /* Clear TIMCLK_SEL bits */ + tmpregister &= CFG2_TIM18CLKSEL_RESET_MASK; + /* Set TIMCLK_SEL bits according to RCC_TIM18CLKSource value */ + tmpregister |= RCC_TIM18CLKSource; + + /* Store the new value */ + RCC->CFG2 = tmpregister; +} + +/** + * @brief Configures the RNGCCLK prescaler. + * @param RCC_RNGCCLKPrescaler specifies the RNGCCLK prescaler. + * This parameter can be one of the following values: + * @arg RCC_RNGCCLK_SYSCLK_DIV1 RNGCPRE[24:28] = 00000, SYSCLK Divided By 1 + * @arg RCC_RNGCCLK_SYSCLK_DIV2 RNGCPRE[24:28] = 00001, SYSCLK Divided By 2 + * @arg RCC_RNGCCLK_SYSCLK_DIV3 RNGCPRE[24:28] = 00002, SYSCLK Divided By 3 + * ... + * @arg RCC_RNGCCLK_SYSCLK_DIV31 RNGCPRE[24:28] = 11110, SYSCLK Divided By 31 + * @arg RCC_RNGCCLK_SYSCLK_DIV32 RNGCPRE[24:28] = 11111, SYSCLK Divided By 32 + */ +void RCC_ConfigRngcClk(uint32_t RCC_RNGCCLKPrescaler) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_RNGCCLKPRE(RCC_RNGCCLKPrescaler)); + + tmpregister = RCC->CFG2; + /* Clear RNGCPRE[3:0] bits */ + tmpregister &= CFG2_RNGCPRES_RESET_MASK; + /* Set RNGCPRE[3:0] bits according to RCC_RNGCCLKPrescaler value */ + tmpregister |= RCC_RNGCCLKPrescaler; + + /* Store the new value */ + RCC->CFG2 = tmpregister; +} + +/** + * @brief Configures the ADCx 1M clock (ADC1MCLK). + * @param RCC_ADC1MCLKSource specifies the ADC1M clock source. + * This parameter can be on of the following values: + * @arg RCC_ADC1MCLK_SRC_HSI + * @arg RCC_ADC1MCLK_SRC_HSE + * + * @param RCC_ADC1MPrescaler specifies the ADC1M clock prescaler. + * This parameter can be on of the following values: + * @arg RCC_ADC1MCLK_DIV1 ADC1M clock = RCC_ADC1MCLKSource_xxx/1 + * @arg RCC_ADC1MCLK_DIV2 ADC1M clock = RCC_ADC1MCLKSource_xxx/2 + * @arg RCC_ADC1MCLK_DIV3 ADC1M clock = RCC_ADC1MCLKSource_xxx/3 + * ... + * @arg RCC_ADC1MCLK_DIV31 ADC1M clock = RCC_ADC1MCLKSource_xxx/31 + * @arg RCC_ADC1MCLK_DIV32 ADC1M clock = RCC_ADC1MCLKSource_xxx/32 + */ +void RCC_ConfigAdc1mClk(uint32_t RCC_ADC1MCLKSource, uint32_t RCC_ADC1MPrescaler) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_ADC1MCLKSRC(RCC_ADC1MCLKSource)); + assert_param(IS_RCC_ADC1MCLKPRE(RCC_ADC1MPrescaler)); + + tmpregister = RCC->CFG2; + /* Clear ADC1MSEL and ADC1MPRE[4:0] bits */ + tmpregister &= CFG2_ADC1MSEL_RESET_MASK; + tmpregister &= CFG2_ADC1MPRES_RESET_MASK; + /* Set ADC1MSEL bits according to RCC_ADC1MCLKSource value */ + tmpregister |= RCC_ADC1MCLKSource; + /* Set ADC1MPRE[4:0] bits according to RCC_ADC1MPrescaler value */ + tmpregister |= RCC_ADC1MPrescaler; + + /* Store the new value */ + RCC->CFG2 = tmpregister; +} + +/** + * @brief Configures the ADCPLLCLK prescaler, and enable/disable ADCPLLCLK. + * @param RCC_ADCPLLCLKPrescaler specifies the ADCPLLCLK prescaler. + * This parameter can be on of the following values: + * @arg RCC_ADCPLLCLK_DISABLE ADCPLLCLKPRES[4:0] = 0xxxx, ADC Pll Clock Disable + * @arg RCC_ADCPLLCLK_DIV1 ADCPLLCLKPRES[4:0] = 10000, Pll Clock Divided By 1 + * @arg RCC_ADCPLLCLK_DIV2 ADCPLLCLKPRES[4:0] = 10001, Pll Clock Divided By 2 + * @arg RCC_ADCPLLCLK_DIV4 ADCPLLCLKPRES[4:0] = 10010, Pll Clock Divided By 4 + * @arg RCC_ADCPLLCLK_DIV6 ADCPLLCLKPRES[4:0] = 10011, Pll Clock Divided By 6 + * @arg RCC_ADCPLLCLK_DIV8 ADCPLLCLKPRES[4:0] = 10100, Pll Clock Divided By 8 + * @arg RCC_ADCPLLCLK_DIV10 ADCPLLCLKPRES[4:0] = 10101, Pll Clock Divided By 10 + * @arg RCC_ADCPLLCLK_DIV12 ADCPLLCLKPRES[4:0] = 10110, Pll Clock Divided By 12 + * @arg RCC_ADCPLLCLK_DIV16 ADCPLLCLKPRES[4:0] = 10111, Pll Clock Divided By 16 + * @arg RCC_ADCPLLCLK_DIV32 ADCPLLCLKPRES[4:0] = 11000, Pll Clock Divided By 32 + * @arg RCC_ADCPLLCLK_DIV64 ADCPLLCLKPRES[4:0] = 11001, Pll Clock Divided By 64 + * @arg RCC_ADCPLLCLK_DIV128 ADCPLLCLKPRES[4:0] = 11010, Pll Clock Divided By 128 + * @arg RCC_ADCPLLCLK_DIV256 ADCPLLCLKPRES[4:0] = 11011, Pll Clock Divided By 256 + * @arg RCC_ADCPLLCLK_DIV256 ADCPLLCLKPRES[4:0] = others, Pll Clock Divided By 256 + * + * @param Cmd specifies the ADCPLLCLK enable/disable selection. + * This parameter can be on of the following values: + * @arg ENABLE enable ADCPLLCLK + * @arg DISABLE disable ADCPLLCLK + */ +void RCC_ConfigAdcPllClk(uint32_t RCC_ADCPLLCLKPrescaler, FunctionalState Cmd) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_ADCPLLCLKPRE(RCC_ADCPLLCLKPrescaler)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + tmpregister = RCC->CFG2; + /* Clear ADCPLLPRES[4:0] bits */ + tmpregister &= CFG2_ADCPLLPRES_RESET_MASK; + + if (Cmd != DISABLE) + { + tmpregister |= RCC_ADCPLLCLKPrescaler; + } + else + { + tmpregister |= RCC_ADCPLLCLKPrescaler; + tmpregister &= RCC_ADCPLLCLK_DISABLE; + } + + /* Store the new value */ + RCC->CFG2 = tmpregister; +} + +/** + * @brief Configures the ADCHCLK prescaler. + * @param RCC_ADCHCLKPrescaler specifies the ADCHCLK prescaler. + * This parameter can be on of the following values: + * @arg RCC_ADCHCLK_DIV1 ADCHCLKPRE[3:0] = 0000, HCLK Clock Divided By 1 + * @arg RCC_ADCHCLK_DIV2 ADCHCLKPRE[3:0] = 0001, HCLK Clock Divided By 2 + * @arg RCC_ADCHCLK_DIV4 ADCHCLKPRE[3:0] = 0010, HCLK Clock Divided By 4 + * @arg RCC_ADCHCLK_DIV6 ADCHCLKPRE[3:0] = 0011, HCLK Clock Divided By 6 + * @arg RCC_ADCHCLK_DIV8 ADCHCLKPRE[3:0] = 0100, HCLK Clock Divided By 8 + * @arg RCC_ADCHCLK_DIV10 ADCHCLKPRE[3:0] = 0101, HCLK Clock Divided By 10 + * @arg RCC_ADCHCLK_DIV12 ADCHCLKPRE[3:0] = 0110, HCLK Clock Divided By 12 + * @arg RCC_ADCHCLK_DIV16 ADCHCLKPRE[3:0] = 0111, HCLK Clock Divided By 16 + * @arg RCC_ADCHCLK_DIV32 ADCHCLKPRE[3:0] = 1000, HCLK Clock Divided By 32 + * @arg RCC_ADCHCLK_DIV32 ADCHCLKPRE[3:0] = others, HCLK Clock Divided By 32 + */ +void RCC_ConfigAdcHclk(uint32_t RCC_ADCHCLKPrescaler) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_ADCHCLKPRE(RCC_ADCHCLKPrescaler)); + + tmpregister = RCC->CFG2; + /* Clear ADCHPRE[3:0] bits */ + tmpregister &= CFG2_ADCHPRES_RESET_MASK; + /* Set ADCHPRE[3:0] bits according to RCC_ADCHCLKPrescaler value */ + tmpregister |= RCC_ADCHCLKPrescaler; + + /* Store the new value */ + RCC->CFG2 = tmpregister; +} + +/** + * @brief Configures the TRNG 1M clock (TRNG1MCLK). + * @param RCC_TRNG1MCLKSource specifies the TRNG1M clock source. + * This parameter can be on of the following values: + * @arg RCC_TRNG1MCLK_SRC_HSI + * @arg RCC_TRNG1MCLK_SRC_HSE + * + * @param RCC_TRNG1MPrescaler specifies the TRNG1M prescaler. + * This parameter can be on of the following values: + * @arg RCC_TRNG1MCLKDiv_2 TRNG1M clock = RCC_TRNG1MCLKSource_xxx/2 + * @arg RCC_TRNG1MCLKDiv_4 TRNG1M clock = RCC_TRNG1MCLKSource_xxx/4 + * @arg RCC_TRNG1MCLKDiv_6 TRNG1M clock = RCC_TRNG1MCLKSource_xxx/6 + * ... + * @arg RCC_TRNG1MCLKDiv_30 TRNG1M clock = RCC_TRNG1MCLKSource_xxx/30 + * @arg RCC_TRNG1MCLKDiv_32 TRNG1M clock = RCC_TRNG1MCLKSource_xxx/32 + */ +void RCC_ConfigTrng1mClk(uint32_t RCC_TRNG1MCLKSource, uint32_t RCC_TRNG1MPrescaler) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_TRNG1MCLK_SRC(RCC_TRNG1MCLKSource)); + assert_param(IS_RCC_TRNG1MCLKPRE(RCC_TRNG1MPrescaler)); + + tmpregister = RCC->CFG3; + /* Clear TRNG1MSEL and TRNG1MPRE[4:0] bits */ + tmpregister &= CFGR3_TRNG1MSEL_RESET_MASK; + tmpregister &= CFGR3_TRNG1MPRES_RESET_MASK; + /* Set TRNG1MSEL bits according to RCC_TRNG1MCLKSource value */ + tmpregister |= RCC_TRNG1MCLKSource; + /* Set TRNG1MPRE[4:0] bits according to RCC_TRNG1MPrescaler value */ + tmpregister |= RCC_TRNG1MPrescaler; + + /* Store the new value */ + RCC->CFG3 = tmpregister; +} + +/** + * @brief Enable/disable TRNG clock (TRNGCLK). + * @param Cmd specifies the TRNGCLK enable/disable selection. + * This parameter can be on of the following values: + * @arg ENABLE enable TRNGCLK + * @arg DISABLE disable TRNGCLK + */ +void RCC_EnableTrng1mClk(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + RCC->CFG3 |= RCC_TRNG1MCLK_ENABLE; + } + else + { + RCC->CFG3 &= RCC_TRNG1MCLK_DISABLE; + } +} + +/** + * @brief Configures the External Low Speed oscillator (LSE). + * @param RCC_LSE specifies the new state of the LSE. + * This parameter can be one of the following values: + * @arg RCC_LSE_DISABLE LSE oscillator OFF + * @arg RCC_LSE_ENABLE LSE oscillator ON + * @arg RCC_LSE_BYPASS LSE oscillator bypassed with external clock + */ +void RCC_ConfigLse(uint8_t RCC_LSE) +{ + /* Check the parameters */ + assert_param(IS_RCC_LSE(RCC_LSE)); + /* Reset LSEON and LSEBYP bits before configuring the LSE ------------------*/ + /* Reset LSEON bit */ + *(__IO uint8_t*)BDCTRL_ADDR = RCC_LSE_DISABLE; + /* Reset LSEBYP bit */ + *(__IO uint8_t*)BDCTRL_ADDR = RCC_LSE_DISABLE; + /* Configure LSE (RCC_LSE_DISABLE is already covered by the code section above) */ + switch (RCC_LSE) + { + case RCC_LSE_ENABLE: + /* Set LSEON bit */ + *(__IO uint8_t*)BDCTRL_ADDR = RCC_LSE_ENABLE; + break; + + case RCC_LSE_BYPASS: + /* Set LSEBYP and LSEON bits */ + *(__IO uint8_t*)BDCTRL_ADDR = RCC_LSE_BYPASS | RCC_LSE_ENABLE; + break; + + default: + break; + } +} + +/** + * @brief Enables or disables the Internal Low Speed oscillator (LSI). + * @note LSI can not be disabled if the IWDG is running. + * @param Cmd new state of the LSI. This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableLsi(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)CTRLSTS_LSIEN_BB = (uint32_t)Cmd; +} + +/** + * @brief Configures the RTC clock (RTCCLK). + * @note Once the RTC clock is selected it can't be changed unless the Backup domain is reset. + * @param RCC_RTCCLKSource specifies the RTC clock source. + * This parameter can be one of the following values: + * @arg RCC_RTCCLK_SRC_LSE LSE selected as RTC clock + * @arg RCC_RTCCLK_SRC_LSI LSI selected as RTC clock + * @arg RCC_RTCCLK_SRC_HSE_DIV128 HSE clock divided by 128 selected as RTC clock + */ +void RCC_ConfigRtcClk(uint32_t RCC_RTCCLKSource) +{ + /* Check the parameters */ + assert_param(IS_RCC_RTCCLK_SRC(RCC_RTCCLKSource)); + + /* Clear the RTC clock source */ + RCC->BDCTRL &= (~0x00000300); + + /* Select the RTC clock source */ + RCC->BDCTRL |= RCC_RTCCLKSource; +} + +/** + * @brief Enables or disables the RTC clock. + * @note This function must be used only after the RTC clock was selected using the RCC_ConfigRtcClk function. + * @param Cmd new state of the RTC clock. This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableRtcClk(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)BDCTRL_RTCEN_BB = (uint32_t)Cmd; +} + +/** + * @brief Returns the frequencies of different on chip clocks. + * @param RCC_Clocks pointer to a RCC_ClocksType structure which will hold + * the clocks frequencies. + * @note The result of this function could be not correct when using + * fractional value for HSE crystal. + */ +void RCC_GetClocksFreqValue(RCC_ClocksType* RCC_Clocks) +{ + uint32_t tmp = 0, pllclk = 0, pllmull = 0, pllsource = 0, presc = 0; + + /* Get PLL clock source and multiplication factor ----------------------*/ + pllmull = RCC->CFG & CFG_PLLMULFCT_MASK; + pllsource = RCC->CFG & CFG_PLLSRC_MASK; + + if ((pllmull & RCC_CFG_PLLMULFCT_4) == 0) + { + pllmull = (pllmull >> 18) + 2; // PLLMUL[4]=0 + } + else + { + pllmull = ((pllmull >> 18) - 496) + 1; // PLLMUL[4]=1 + } + + if (pllsource == 0x00) + { /* HSI oscillator clock divided by 2 selected as PLL clock entry */ + pllclk = (HSI_VALUE >> 1) * pllmull; + } + else + { + /* HSE selected as PLL clock entry */ + if ((RCC->CFG & CFG_PLLHSEPRES_MASK) != (uint32_t)RESET) + { /* HSE oscillator clock divided by 2 */ + pllclk = (HSE_VALUE >> 1) * pllmull; + } + else + { + pllclk = HSE_VALUE * pllmull; + } + } + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFG & CFG_SCLKSTS_MASK; + + switch (tmp) + { + case 0x00: /* HSI used as system clock */ + RCC_Clocks->SysclkFreq = HSI_VALUE; + break; + case 0x04: /* HSE used as system clock */ + RCC_Clocks->SysclkFreq = HSE_VALUE; + break; + case 0x08: /* PLL used as system clock */ + RCC_Clocks->SysclkFreq = pllclk; + break; + + default: + RCC_Clocks->SysclkFreq = HSI_VALUE; + break; + } + + /* Compute HCLK, PCLK1, PCLK2 and ADCCLK clocks frequencies ----------------*/ + /* Get HCLK prescaler */ + tmp = RCC->CFG & CFG_AHBPRES_SET_MASK; + tmp = tmp >> 4; + presc = s_ApbAhbPresTable[tmp]; + /* HCLK clock frequency */ + RCC_Clocks->HclkFreq = RCC_Clocks->SysclkFreq >> presc; + /* Get PCLK1 prescaler */ + tmp = RCC->CFG & CFG_APB1PRES_SET_MASK; + tmp = tmp >> 8; + presc = s_ApbAhbPresTable[tmp]; + /* PCLK1 clock frequency */ + RCC_Clocks->Pclk1Freq = RCC_Clocks->HclkFreq >> presc; + /* Get PCLK2 prescaler */ + tmp = RCC->CFG & CFG_APB2PRES_SET_MASK; + tmp = tmp >> 11; + presc = s_ApbAhbPresTable[tmp]; + /* PCLK2 clock frequency */ + RCC_Clocks->Pclk2Freq = RCC_Clocks->HclkFreq >> presc; + + /* Get ADCHCLK prescaler */ + tmp = RCC->CFG2 & CFG2_ADCHPRES_SET_MASK; + presc = s_AdcHclkPresTable[tmp]; + /* ADCHCLK clock frequency */ + RCC_Clocks->AdcHclkFreq = RCC_Clocks->HclkFreq / presc; + /* Get ADCPLLCLK prescaler */ + tmp = RCC->CFG2 & CFG2_ADCPLLPRES_SET_MASK; + tmp = tmp >> 4; + presc = s_AdcPllClkPresTable[(tmp & 0xF)]; // ignore BIT5 + /* ADCPLLCLK clock frequency */ + RCC_Clocks->AdcPllClkFreq = pllclk / presc; +} + +/** + * @brief Enables or disables the AHB peripheral clock. + * @param RCC_AHBPeriph specifies the AHB peripheral to gates its clock. + * + * this parameter can be any combination of the following values: + * @arg RCC_AHB_PERIPH_DMA1 + * @arg RCC_AHB_PERIPH_DMA2 + * @arg RCC_AHB_PERIPH_SRAM + * @arg RCC_AHB_PERIPH_FLITF + * @arg RCC_AHB_PERIPH_CRC + * @arg RCC_AHB_PERIPH_RNGC + * @arg RCC_AHB_PERIPH_SDIO + * @arg RCC_AHB_PERIPH_SAC + * @arg RCC_AHB_PERIPH_ADC1 + * @arg RCC_AHB_PERIPH_ADC2 + * @arg RCC_AHB_PERIPH_ADC3 + * @arg RCC_AHB_PERIPH_ADC4 + * @arg RCC_AHB_PERIPH_ETHMAC + * @arg RCC_AHB_PERIPH_QSPI + * + * @note SRAM and FLITF clock can be disabled only during sleep mode. + * @param Cmd new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableAHBPeriphClk(uint32_t RCC_AHBPeriph, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB_PERIPH(RCC_AHBPeriph)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + RCC->AHBPCLKEN |= RCC_AHBPeriph; + } + else + { + RCC->AHBPCLKEN &= ~RCC_AHBPeriph; + } +} + +/** + * @brief Enables or disables the High Speed APB (APB2) peripheral clock. + * @param RCC_APB2Periph specifies the APB2 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_APB2_PERIPH_AFIO, RCC_APB2_PERIPH_GPIOA, RCC_APB2_PERIPH_GPIOB, + * RCC_APB2_PERIPH_GPIOC, RCC_APB2_PERIPH_GPIOD, RCC_APB2_PERIPH_GPIOE, + * RCC_APB2_PERIPH_TIM1, + * RCC_APB2_PERIPH_SPI1, RCC_APB2_PERIPH_TIM8, RCC_APB2_PERIPH_USART1, + * RCC_APB2_PERIPH_DVP, RCC_APB2_PERIPH_UART6, RCC_APB2_PERIPH_UART7, + * RCC_APB2_PERIPH_I2C3, RCC_APB2_PERIPH_I2C4 + * @param Cmd new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableAPB2PeriphClk(uint32_t RCC_APB2Periph, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + RCC->APB2PCLKEN |= RCC_APB2Periph; + } + else + { + RCC->APB2PCLKEN &= ~RCC_APB2Periph; + } +} + +/** + * @brief Enables or disables the Low Speed APB (APB1) peripheral clock. + * @param RCC_APB1Periph specifies the APB1 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_APB1_PERIPH_TIM2, RCC_APB1_PERIPH_TIM3, RCC_APB1_PERIPH_TIM4, + * RCC_APB1_PERIPH_TIM5, RCC_APB1_PERIPH_TIM6, RCC_APB1_PERIPH_TIM7, + * RCC_APB1_PERIPH_COMP, RCC_APB1_PERIPH_COMP_FILT, RCC_APB1_PERIPH_TSC, + * RCC_APB1_PERIPH_WWDG, RCC_APB1_PERIPH_SPI2, RCC_APB1_PERIPH_SPI3, + * RCC_APB1_PERIPH_USART2, RCC_APB1_PERIPH_USART3, RCC_APB1_PERIPH_UART4, + * RCC_APB1_PERIPH_UART5, RCC_APB1_PERIPH_I2C1, RCC_APB1_PERIPH_I2C2, + * RCC_APB1_PERIPH_USB, RCC_APB1_PERIPH_CAN1, RCC_APB1_PERIPH_CAN2, RCC_APB1_PERIPH_BKP, + * RCC_APB1_PERIPH_PWR, RCC_APB1_PERIPH_DAC, RCC_APB1_PERIPH_OPAMP + * + * @param Cmd new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableAPB1PeriphClk(uint32_t RCC_APB1Periph, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + RCC->APB1PCLKEN |= RCC_APB1Periph; + } + else + { + RCC->APB1PCLKEN &= ~RCC_APB1Periph; + } +} + +/** + * @brief Forces or releases AHB peripheral reset. + * @param RCC_AHBPeriph specifies the AHB peripheral to reset. + * This parameter can be any combination of the following values: + * @arg RCC_AHB_PERIPH_QSPI. + * RCC_AHB_PERIPH_ETHMAC. + * RCC_AHB_PERIPH_ADC4. + * RCC_AHB_PERIPH_ADC3. + * RCC_AHB_PERIPH_ADC2. + * RCC_AHB_PERIPH_ADC1. + * RCC_AHB_PERIPH_SAC. + * RCC_AHB_PERIPH_RNGC. + * @param Cmd new state of the specified peripheral reset. This parameter can be ENABLE or DISABLE. + */ +void RCC_EnableAHBPeriphReset(uint32_t RCC_AHBPeriph, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB_PERIPH(RCC_AHBPeriph)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + RCC->AHBPRST |= RCC_AHBPeriph; + } + else + { + RCC->AHBPRST &= ~RCC_AHBPeriph; + } +} + +/** + * @brief Forces or releases High Speed APB (APB2) peripheral reset. + * @param RCC_APB2Periph specifies the APB2 peripheral to reset. + * This parameter can be any combination of the following values: + * @arg RCC_APB2_PERIPH_AFIO, RCC_APB2_PERIPH_GPIOA, RCC_APB2_PERIPH_GPIOB, + * RCC_APB2_PERIPH_GPIOC, RCC_APB2_PERIPH_GPIOD, RCC_APB2_PERIPH_GPIOE, + * RCC_APB2_PERIPH_TIM1, + * RCC_APB2_PERIPH_SPI1, RCC_APB2_PERIPH_TIM8, RCC_APB2_PERIPH_USART1, + * RCC_APB2_PERIPH_DVP, RCC_APB2_PERIPH_UART6, RCC_APB2_PERIPH_UART7, + * RCC_APB2_PERIPH_I2C3, RCC_APB2_PERIPH_I2C4 + * @param Cmd new state of the specified peripheral reset. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableAPB2PeriphReset(uint32_t RCC_APB2Periph, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + RCC->APB2PRST |= RCC_APB2Periph; + } + else + { + RCC->APB2PRST &= ~RCC_APB2Periph; + } +} + +/** + * @brief Forces or releases Low Speed APB (APB1) peripheral reset. + * @param RCC_APB1Periph specifies the APB1 peripheral to reset. + * This parameter can be any combination of the following values: + * @arg RCC_APB1_PERIPH_TIM2, RCC_APB1_PERIPH_TIM3, RCC_APB1_PERIPH_TIM4, + * RCC_APB1_PERIPH_TIM5, RCC_APB1_PERIPH_TIM6, RCC_APB1_PERIPH_TIM7, + * RCC_APB1_PERIPH_TSC, RCC_APB1_PERIPH_WWDG, RCC_APB1_PERIPH_SPI2, + * RCC_APB1_PERIPH_SPI3, RCC_APB1_PERIPH_USART2, RCC_APB1_PERIPH_USART3, + * RCC_APB1_PERIPH_UART4, RCC_APB1_PERIPH_UART5, RCC_APB1_PERIPH_I2C1, + * RCC_APB1_PERIPH_I2C2, RCC_APB1_PERIPH_USB, RCC_APB1_PERIPH_CAN1, + * RCC_APB1_PERIPH_CAN2, RCC_APB1_PERIPH_BKP, RCC_APB1_PERIPH_PWR, + * RCC_APB1_PERIPH_DAC + * @param Cmd new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableAPB1PeriphReset(uint32_t RCC_APB1Periph, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + RCC->APB1PRST |= RCC_APB1Periph; + } + else + { + RCC->APB1PRST &= ~RCC_APB1Periph; + } +} + +/** + * @brief BOR reset enable. + * @param Cmd new state of the BOR reset. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableBORReset(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + RCC->CFG3 |= RCC_BOR_RST_ENABLE; + } + else + { + RCC->CFG3 &= ~RCC_BOR_RST_ENABLE; + } +} + +/** + * @brief Forces or releases the Backup domain reset. + * @param Cmd new state of the Backup domain reset. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableBackupReset(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)BDCTRL_BDSFTRST_BB = (uint32_t)Cmd; +} + +/** + * @brief Enables or disables the Clock Security System. + * @param Cmd new state of the Clock Security System.. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableClockSecuritySystem(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)CTRL_CLKSSEN_BB = (uint32_t)Cmd; +} + +/** + * @brief Configures the MCO PLL clock prescaler. + * @param RCC_MCOPLLCLKPrescaler specifies the MCO PLL clock prescaler. + * This parameter can be on of the following values: + * @arg RCC_MCO_PLLCLK_DIV2 MCOPRE[3:0] = 0010, PLL Clock Divided By 2 + * @arg RCC_MCO_PLLCLK_DIV3 MCOPRE[3:0] = 0011, PLL Clock Divided By 3 + * @arg RCC_MCO_PLLCLK_DIV4 MCOPRE[3:0] = 0100, PLL Clock Divided By 4 + * @arg RCC_MCO_PLLCLK_DIV5 MCOPRE[3:0] = 0101, PLL Clock Divided By 5 + * ... + * @arg RCC_MCO_PLLCLK_DIV13 MCOPRE[3:0] = 1101, PLL Clock Divided By 13 + * @arg RCC_MCO_PLLCLK_DIV14 MCOPRE[3:0] = 1110, PLL Clock Divided By 14 + * @arg RCC_MCO_PLLCLK_DIV15 MCOPRE[3:0] = 1111, PLL Clock Divided By 15 + */ +void RCC_ConfigMcoPllClk(uint32_t RCC_MCOPLLCLKPrescaler) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_MCOPLLCLKPRE(RCC_MCOPLLCLKPrescaler)); + + tmpregister = RCC->CFG; + /* Clear MCOPRE[3:0] bits */ + tmpregister &= ((uint32_t)0x0FFFFFFF); + /* Set MCOPRE[3:0] bits according to RCC_ADCHCLKPrescaler value */ + tmpregister |= RCC_MCOPLLCLKPrescaler; + + /* Store the new value */ + RCC->CFG = tmpregister; +} + +/** + * @brief Selects the clock source to output on MCO pin. + * @param RCC_MCO specifies the clock source to output. + * + * this parameter can be one of the following values: + * @arg RCC_MCO_NOCLK No clock selected + * @arg RCC_MCO_SYSCLK System clock selected + * @arg RCC_MCO_HSI HSI oscillator clock selected + * @arg RCC_MCO_HSE HSE oscillator clock selected + * @arg RCC_MCO_PLLCLK PLL clock divided by xx selected + * + */ +void RCC_ConfigMco(uint8_t RCC_MCO) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_MCO(RCC_MCO)); + + tmpregister = RCC->CFG; + /* Clear MCO[2:0] bits */ + tmpregister &= ((uint32_t)0xF8FFFFFF); + /* Set MCO[2:0] bits according to RCC_MCO value */ + tmpregister |= ((uint32_t)(RCC_MCO << 24)); + + /* Store the new value */ + RCC->CFG = tmpregister; +} + +/** + * @brief Checks whether the specified RCC flag is set or not. + * @param RCC_FLAG specifies the flag to check. + * + * this parameter can be one of the following values: + * @arg RCC_FLAG_HSIRD HSI oscillator clock ready + * @arg RCC_FLAG_HSERD HSE oscillator clock ready + * @arg RCC_FLAG_PLLRD PLL clock ready + * @arg RCC_FLAG_LSERD LSE oscillator clock ready + * @arg RCC_FLAG_LSIRD LSI oscillator clock ready + * @arg RCC_FLAG_BORRST BOR reset flag + * @arg RCC_FLAG_RETEMC Retention EMC reset flag + * @arg RCC_FLAG_BKPEMC BackUp EMC reset flag + * @arg RCC_FLAG_RAMRST RAM reset flag + * @arg RCC_FLAG_MMURST Mmu reset flag + * @arg RCC_FLAG_PINRST Pin reset + * @arg RCC_FLAG_PORRST POR/PDR reset + * @arg RCC_FLAG_SFTRST Software reset + * @arg RCC_FLAG_IWDGRST Independent Watchdog reset + * @arg RCC_FLAG_WWDGRST Window Watchdog reset + * @arg RCC_FLAG_LPWRRST Low Power reset + * + * @return The new state of RCC_FLAG (SET or RESET). + */ +FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG) +{ + uint32_t tmp = 0; + uint32_t statusreg = 0; + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_RCC_FLAG(RCC_FLAG)); + + /* Get the RCC register index */ + tmp = RCC_FLAG >> 5; + if (tmp == 1) /* The flag to check is in CTRL register */ + { + statusreg = RCC->CTRL; + } + else if (tmp == 2) /* The flag to check is in BDCTRL register */ + { + statusreg = RCC->BDCTRL; + } + else /* The flag to check is in CTRLSTS register */ + { + statusreg = RCC->CTRLSTS; + } + + /* Get the flag position */ + tmp = RCC_FLAG & FLAG_MASK; + if ((statusreg & ((uint32_t)1 << tmp)) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + /* Return the flag status */ + return bitstatus; +} + +/** + * @brief Clears the RCC reset flags. + * @note The reset flags are: RCC_FLAG_PINRST, RCC_FLAG_PORRST, RCC_FLAG_SFTRST, + * RCC_FLAG_IWDGRST, RCC_FLAG_WWDGRST, RCC_FLAG_LPWRRST + */ +void RCC_ClrFlag(void) +{ + /* Set RMVF bit to clear the reset flags */ + RCC->CTRLSTS |= CSR_RMRSTF_SET; + /* RMVF bit should be reset */ + RCC->CTRLSTS &= CSR_RMVF_Reset; +} + +/** + * @brief Checks whether the specified RCC interrupt has occurred or not. + * @param RccInt specifies the RCC interrupt source to check. + * + * this parameter can be one of the following values: + * @arg RCC_INT_LSIRDIF LSI ready interrupt + * @arg RCC_INT_LSERDIF LSE ready interrupt + * @arg RCC_INT_HSIRDIF HSI ready interrupt + * @arg RCC_INT_HSERDIF HSE ready interrupt + * @arg RCC_INT_PLLRDIF PLL ready interrupt + * + * @arg RCC_INT_CLKSSIF Clock Security System interrupt + * + * @return The new state of RccInt (SET or RESET). + */ +INTStatus RCC_GetIntStatus(uint8_t RccInt) +{ + INTStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_RCC_GET_INT(RccInt)); + + /* Check the status of the specified RCC interrupt */ + if ((RCC->CLKINT & RccInt) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + /* Return the RccInt status */ + return bitstatus; +} + +/** + * @brief Clears the RCC's interrupt pending bits. + * @param RccInt specifies the interrupt pending bit to clear. + * + * this parameter can be any combination of the + * following values: + * @arg RCC_INT_LSIRDIF LSI ready interrupt + * @arg RCC_INT_LSERDIF LSE ready interrupt + * @arg RCC_INT_HSIRDIF HSI ready interrupt + * @arg RCC_INT_HSERDIF HSE ready interrupt + * @arg RCC_INT_PLLRDIF PLL ready interrupt + * + * @arg RCC_INT_CLKSSIF Clock Security System interrupt + */ +void RCC_ClrIntPendingBit(uint8_t RccInt) +{ + /* Check the parameters */ + assert_param(IS_RCC_CLR_INT(RccInt)); + + /* Perform Byte access to RCC_CLKINT[23:16] bits to clear the selected interrupt + pending bits */ + *(__IO uint8_t*)CLKINT_BYTE3_ADDR = RccInt; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_rtc.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_rtc.c new file mode 100644 index 0000000000..40cd12df67 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_rtc.c @@ -0,0 +1,2006 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_rtc.c + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_rtc.h" +#include "n32g4fr_rcc.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup RTC + * @brief RTC driver modules + * @{ + */ + +/* Masks Definition */ +#define RTC_TR_RESERVED_MASK ((uint32_t)0x007F7F7F) +#define RTC_DATE_RESERVED_MASK ((uint32_t)0x00FFFF3F) + +#define RTC_RSF_MASK ((uint32_t)0xFFFFFFDF) +#define RTC_FLAGS_MASK \ + ((uint32_t)(RTC_FLAG_TISOVF | RTC_FLAG_TISF | RTC_FLAG_WTF | RTC_FLAG_ALBF | RTC_FLAG_ALAF | RTC_FLAG_INITF \ + | RTC_FLAG_RSYF | RTC_FLAG_INITSF | RTC_FLAG_WTWF | RTC_FLAG_ALBWF | RTC_FLAG_ALAWF | RTC_FLAG_RECPF \ + | RTC_FLAG_SHOPF)) + +#define INITMODE_TIMEOUT ((uint32_t)0x00002000) +#define SYNCHRO_TIMEOUT ((uint32_t)0x00008000) +#define RECALPF_TIMEOUT ((uint32_t)0x00001000) +#define SHPF_TIMEOUT ((uint32_t)0x00002000) + +static uint8_t RTC_ByteToBcd2(uint8_t Value); +static uint8_t RTC_Bcd2ToByte(uint8_t Value); + +/** @addtogroup RTC_Private_Functions + * @{ + */ + +/** @addtogroup RTC_Group1 Initialization and Configuration functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] This section provide functions allowing to initialize and configure the + RTC Prescaler (Synchronous and Asynchronous), RTC Hour format, disable + RTC registers Write protection, enter and exit the RTC initialization mode, + RTC registers synchronization check and reference clock detection enable. + (#) The RTC Prescaler is programmed to generate the RTC 1Hz time base. + It is split into 2 programmable prescalers to minimize power consumption. + (++) A 7-bit asynchronous prescaler and A 13-bit synchronous prescaler. + (++) When both prescalers are used, it is recommended to configure the + asynchronous prescaler to a high value to minimize consumption. + (#) All RTC registers are Write protected. Writing to the RTC registers + is enabled by writing a key into the Write Protection register, RTC_WRP. + (#) To Configure the RTC Calendar, user application should enter + initialization mode. In this mode, the calendar counter is stopped + and its value can be updated. When the initialization sequence is + complete, the calendar restarts counting after 4 RTCCLK cycles. + (#) To read the calendar through the shadow registers after Calendar + initialization, calendar update or after wakeup from low power modes + the software must first clear the RSYF flag. The software must then + wait until it is set again before reading the calendar, which means + that the calendar registers have been correctly copied into the + RTC_TSH and RTC_DATE shadow registers.The RTC_WaitForSynchro() function + implements the above software sequence (RSYF clear and RSYF check). + +@endverbatim + * @{ + */ + +/** + * @brief Deinitializes the RTC registers to their default reset values. + * @note This function doesn't reset the RTC Clock source + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC registers are deinitialized + * - ERROR: RTC registers are not deinitialized + */ +ErrorStatus RTC_DeInit(void) +{ + __IO uint32_t wutcounter = 0x00; + uint32_t wutwfstatus = 0x00; + ErrorStatus status = ERROR; + uint32_t i =0; + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Set Initialization mode */ + if (RTC_EnterInitMode() == ERROR) + { + status = ERROR; + } + else + { + /* Reset TSH, DAT and CTRL registers */ + RTC->TSH = (uint32_t)0x00000000; + RTC->DATE = (uint32_t)0x00002101; + + /* Reset All CTRL bits except CTRL[2:0] */ + RTC->CTRL &= (uint32_t)0x00000007; + + /* Wait till RTC WTWF flag is set and if Time out is reached exit */ + do + { + wutwfstatus = RTC->INITSTS & RTC_INITSTS_WTWF; + wutcounter++; + } while ((wutcounter != INITMODE_TIMEOUT) && (wutwfstatus == 0x00)); + + if ((RTC->INITSTS & RTC_INITSTS_WTWF) == RESET) + { + status = ERROR; + } + else + { + /* Reset all RTC CTRL register bits */ + RTC->CTRL &= (uint32_t)0x00000000; + RTC->WKUPT = (uint32_t)0x0000FFFF; + RTC->PRE = (uint32_t)0x007F00FF; + RTC->ALARMA = (uint32_t)0x00000000; + RTC->ALARMB = (uint32_t)0x00000000; + RTC->SCTRL = (uint32_t)0x00000000; + RTC->CALIB = (uint32_t)0x00000000; + RTC->ALRMASS = (uint32_t)0x00000000; + RTC->ALRMBSS = (uint32_t)0x00000000; + + /* Reset INTSTS register and exit initialization mode */ + RTC->INITSTS = (uint32_t)0x00000000; + + RTC->OPT = (uint32_t)0x00000000; + RTC->TSCWKUPCTRL = (uint32_t)0x00000008; + RTC->TSCWKUPCNT = (uint32_t)0x000002FE; + + /* Wait till the RTC RSYF flag is set */ + if (RTC_WaitForSynchro() == ERROR) + { + status = ERROR; + } + else + { + status = SUCCESS; + } + } + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + /* Delay for the RTC prescale effect */ + for(i=0;i<0x2FF;i++); + return status; +} + +/** + * @brief Initializes the RTC registers according to the specified parameters + * in RTC_InitStruct. + * @param RTC_InitStruct pointer to a RTC_InitType structure that contains + * the configuration information for the RTC peripheral. + * @note The RTC Prescaler register is write protected and can be written in + * initialization mode only. + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC registers are initialized + * - ERROR: RTC registers are not initialized + */ +ErrorStatus RTC_Init(RTC_InitType* RTC_InitStruct) +{ + ErrorStatus status = ERROR; + uint32_t i =0; + /* Check the parameters */ + assert_param(IS_RTC_HOUR_FORMAT(RTC_InitStruct->RTC_HourFormat)); + assert_param(IS_RTC_PREDIV_ASYNCH(RTC_InitStruct->RTC_AsynchPrediv)); + assert_param(IS_RTC_PREDIV_SYNCH(RTC_InitStruct->RTC_SynchPrediv)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Set Initialization mode */ + if (RTC_EnterInitMode() == ERROR) + { + status = ERROR; + } + else + { + /* Clear RTC CTRL HFMT Bit */ + RTC->CTRL &= ((uint32_t) ~(RTC_CTRL_HFMT)); + /* Set RTC_CTRL register */ + RTC->CTRL |= ((uint32_t)(RTC_InitStruct->RTC_HourFormat)); + + /* Configure the RTC PRE */ + RTC->PRE = (uint32_t)(RTC_InitStruct->RTC_SynchPrediv); + RTC->PRE |= (uint32_t)(RTC_InitStruct->RTC_AsynchPrediv << 16); + + /* Exit Initialization mode */ + RTC_ExitInitMode(); + + status = SUCCESS; + } + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + /* Delay for the RTC prescale effect */ + for(i=0;i<0x2FF;i++); + return status; +} + +/** + * @brief Fills each RTC_InitStruct member with its default value. + * @param RTC_InitStruct pointer to a RTC_InitType structure which will be + * initialized. + */ +void RTC_StructInit(RTC_InitType* RTC_InitStruct) +{ + /* Initialize the RTC_HourFormat member */ + RTC_InitStruct->RTC_HourFormat = RTC_24HOUR_FORMAT; + + /* Initialize the RTC_AsynchPrediv member */ + RTC_InitStruct->RTC_AsynchPrediv = (uint32_t)0x7F; + + /* Initialize the RTC_SynchPrediv member */ + RTC_InitStruct->RTC_SynchPrediv = (uint32_t)0xFF; +} + +/** + * @brief Enables or disables the RTC registers write protection. + * @note All the RTC registers are write protected except for RTC_INITSTS[13:8]. + * @note Writing a wrong key reactivates the write protection. + * @note The protection mechanism is not affected by system reset. + * @param Cmd new state of the write protection. + * This parameter can be: ENABLE or DISABLE. + */ +void RTC_EnableWriteProtection(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + } + else + { + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + } +} + +/** + * @brief Enters the RTC Initialization mode. + * @note The RTC Initialization mode is write protected, use the + * RTC_EnableWriteProtection(DISABLE) before calling this function. + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC is in Init mode + * - ERROR: RTC is not in Init mode + */ +ErrorStatus RTC_EnterInitMode(void) +{ + __IO uint32_t initcounter = 0x00; + ErrorStatus status = ERROR; + uint32_t initstatus = 0x00; + + /* Check if the Initialization mode is set */ + if ((RTC->INITSTS & RTC_INITSTS_INITF) == (uint32_t)RESET) + { + /* Set the Initialization mode */ + RTC->INITSTS = (uint32_t)RTC_INITSTS_INITM; + + /* Wait till RTC is in INIT state and if Time out is reached exit */ + do + { + initstatus = RTC->INITSTS & RTC_INITSTS_INITF; + initcounter++; + } while ((initcounter != INITMODE_TIMEOUT) && (initstatus == 0x00)); + + if ((RTC->INITSTS & RTC_INITSTS_INITF) != RESET) + { + status = SUCCESS; + } + else + { + status = ERROR; + } + } + else + { + status = SUCCESS; + } + + return (status); +} + +/** + * @brief Exits the RTC Initialization mode. + * @note When the initialization sequence is complete, the calendar restarts + * counting after 4 RTCCLK cycles. + * @note The RTC Initialization mode is write protected, use the + * RTC_EnableWriteProtection(DISABLE) before calling this function. + */ +void RTC_ExitInitMode(void) +{ + /* Exit Initialization mode */ + RTC->INITSTS &= (uint32_t)~RTC_INITSTS_INITM; +} + +/** + * @brief Waits until the RTC Time and Date registers (RTC_TSH and RTC_DATE) are + * synchronized with RTC APB clock. + * @note The RTC Resynchronization mode is write protected, use the + * RTC_EnableWriteProtection(DISABLE) before calling this function. + * @note To read the calendar through the shadow registers after Calendar + * initialization, calendar update or after wakeup from low power modes + * the software must first clear the RSYF flag. + * The software must then wait until it is set again before reading + * the calendar, which means that the calendar registers have been + * correctly copied into the RTC_TSH and RTC_DATE shadow registers. + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC registers are synchronised + * - ERROR: RTC registers are not synchronised + */ +ErrorStatus RTC_WaitForSynchro(void) +{ + __IO uint32_t synchrocounter = 0; + ErrorStatus status = ERROR; + uint32_t synchrostatus = 0x00; + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Clear RSYF flag */ + RTC->INITSTS &= (uint32_t)RTC_RSF_MASK; + + /* Wait the registers to be synchronised */ + do + { + synchrostatus = RTC->INITSTS & RTC_INITSTS_RSYF; + synchrocounter++; + } while ((synchrocounter != SYNCHRO_TIMEOUT) && (synchrostatus == 0x00)); + + if ((RTC->INITSTS & RTC_INITSTS_RSYF) != RESET) + { + status = SUCCESS; + } + else + { + status = ERROR; + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + + return (status); +} + + + +/** + * @brief Enables or Disables the Bypass Shadow feature. + * @note When the Bypass Shadow is enabled the calendar value are taken + * directly from the Calendar counter. + * @param Cmd new state of the Bypass Shadow feature. + * This parameter can be: ENABLE or DISABLE. + */ +void RTC_EnableBypassShadow(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + if (Cmd != DISABLE) + { + /* Set the BYPS bit */ + RTC->CTRL |= (uint8_t)RTC_CTRL_BYPS; + } + else + { + /* Reset the BYPS bit */ + RTC->CTRL &= (uint8_t)~RTC_CTRL_BYPS; + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @} + */ + +/** @addtogroup RTC_Group2 Time and Date configuration functions + * @brief Time and Date configuration functions + * +@verbatim + =============================================================================== + ##### Time and Date configuration functions ##### + =============================================================================== + [..] This section provide functions allowing to program and read the RTC + Calendar (Time and Date). + +@endverbatim + * @{ + */ + +/** + * @brief Set the RTC current time. + * @param RTC_Format specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN Binary data format. + * @arg RTC_FORMAT_BCD BCD data format. + * @param RTC_TimeStruct pointer to a RTC_TimeType structure that contains + * the time configuration information for the RTC. + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC Time register is configured + * - ERROR: RTC Time register is not configured + */ +ErrorStatus RTC_ConfigTime(uint32_t RTC_Format, RTC_TimeType* RTC_TimeStruct) +{ + uint32_t tmpregister = 0; + ErrorStatus status = ERROR; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(RTC_Format)); + + if (RTC_Format == RTC_FORMAT_BIN) + { + if ((RTC->CTRL & RTC_CTRL_HFMT) != (uint32_t)RESET) + { + assert_param(IS_RTC_12HOUR(RTC_TimeStruct->Hours)); + assert_param(IS_RTC_H12(RTC_TimeStruct->H12)); + } + else + { + RTC_TimeStruct->H12 = 0x00; + assert_param(IS_RTC_24HOUR(RTC_TimeStruct->Hours)); + } + assert_param(IS_RTC_MINUTES(RTC_TimeStruct->Minutes)); + assert_param(IS_RTC_SECONDS(RTC_TimeStruct->Seconds)); + } + else + { + if ((RTC->CTRL & RTC_CTRL_HFMT) != (uint32_t)RESET) + { + tmpregister = RTC_Bcd2ToByte(RTC_TimeStruct->Hours); + assert_param(IS_RTC_12HOUR(tmpregister)); + assert_param(IS_RTC_H12(RTC_TimeStruct->H12)); + } + else + { + RTC_TimeStruct->H12 = 0x00; + assert_param(IS_RTC_24HOUR(RTC_Bcd2ToByte(RTC_TimeStruct->Hours))); + } + assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(RTC_TimeStruct->Minutes))); + assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(RTC_TimeStruct->Seconds))); + } + + /* Check the input parameters format */ + if (RTC_Format != RTC_FORMAT_BIN) + { + tmpregister = (((uint32_t)(RTC_TimeStruct->Hours) << 16) | ((uint32_t)(RTC_TimeStruct->Minutes) << 8) + | ((uint32_t)RTC_TimeStruct->Seconds) | ((uint32_t)(RTC_TimeStruct->H12) << 16)); + } + else + { + tmpregister = + (uint32_t)(((uint32_t)RTC_ByteToBcd2(RTC_TimeStruct->Hours) << 16) + | ((uint32_t)RTC_ByteToBcd2(RTC_TimeStruct->Minutes) << 8) + | ((uint32_t)RTC_ByteToBcd2(RTC_TimeStruct->Seconds)) | (((uint32_t)RTC_TimeStruct->H12) << 16)); + } + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Set Initialization mode */ + if (RTC_EnterInitMode() == ERROR) + { + status = ERROR; + } + else + { + /* Set the RTC_TSH register */ + RTC->TSH = (uint32_t)(tmpregister & RTC_TR_RESERVED_MASK); + + /* Exit Initialization mode */ + RTC_ExitInitMode(); + + /* If RTC_CTRL_BYPS bit = 0, wait for synchro else this check is not needed */ + if ((RTC->CTRL & RTC_CTRL_BYPS) == RESET) + { + if (RTC_WaitForSynchro() == ERROR) + { + status = ERROR; + } + else + { + status = SUCCESS; + } + } + else + { + status = SUCCESS; + } + } + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + + return status; +} + +/** + * @brief Fills each RTC_TimeStruct member with its default value + * (Time = 00h:00min:00sec). + * @param RTC_TimeStruct pointer to a RTC_TimeType structure which will be + * initialized. + */ +void RTC_TimeStructInit(RTC_TimeType* RTC_TimeStruct) +{ + /* Time = 00h:00min:00sec */ + RTC_TimeStruct->H12 = RTC_AM_H12; + RTC_TimeStruct->Hours = 0; + RTC_TimeStruct->Minutes = 0; + RTC_TimeStruct->Seconds = 0; +} + +/** + * @brief Get the RTC current Time. + * @param RTC_Format specifies the format of the returned parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN Binary data format. + * @arg RTC_FORMAT_BCD BCD data format. + * @param RTC_TimeStruct pointer to a RTC_TimeType structure that will + * contain the returned current time configuration. + */ +void RTC_GetTime(uint32_t RTC_Format, RTC_TimeType* RTC_TimeStruct) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(RTC_Format)); + + /* Get the RTC_TSH register */ + tmpregister = (uint32_t)(RTC->TSH & RTC_TR_RESERVED_MASK); + + /* Fill the structure fields with the read parameters */ + RTC_TimeStruct->Hours = (uint8_t)((tmpregister & (RTC_TSH_HOT | RTC_TSH_HOU)) >> 16); + RTC_TimeStruct->Minutes = (uint8_t)((tmpregister & (RTC_TSH_MIT | RTC_TSH_MIU)) >> 8); + RTC_TimeStruct->Seconds = (uint8_t)(tmpregister & (RTC_TSH_SCT | RTC_TSH_SCU)); + RTC_TimeStruct->H12 = (uint8_t)((tmpregister & (RTC_TSH_APM)) >> 16); + + /* Check the input parameters format */ + if (RTC_Format == RTC_FORMAT_BIN) + { + /* Convert the structure parameters to Binary format */ + RTC_TimeStruct->Hours = (uint8_t)RTC_Bcd2ToByte(RTC_TimeStruct->Hours); + RTC_TimeStruct->Minutes = (uint8_t)RTC_Bcd2ToByte(RTC_TimeStruct->Minutes); + RTC_TimeStruct->Seconds = (uint8_t)RTC_Bcd2ToByte(RTC_TimeStruct->Seconds); + } +} + +/** + * @brief Gets the RTC current Calendar Subseconds value. + * @return RTC current Calendar Subseconds value. + */ +uint32_t RTC_GetSubSecond(void) +{ + uint32_t tmpregister = 0; + + /* Get subseconds values from the correspondent registers*/ + tmpregister = (uint32_t)(RTC->SUBS); + + return (tmpregister); +} + +/** + * @brief Set the RTC current date. + * @param RTC_Format specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN Binary data format. + * @arg RTC_FORMAT_BCD BCD data format. + * @param RTC_DateStruct pointer to a RTC_DateType structure that contains + * the date configuration information for the RTC. + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC Date register is configured + * - ERROR: RTC Date register is not configured + */ +ErrorStatus RTC_SetDate(uint32_t RTC_Format, RTC_DateType* RTC_DateStruct) +{ + uint32_t tmpregister = 0; + ErrorStatus status = ERROR; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(RTC_Format)); + + if ((RTC_Format == RTC_FORMAT_BIN) && ((RTC_DateStruct->Month & 0x10) == 0x10)) + { + RTC_DateStruct->Month = (RTC_DateStruct->Month & (uint32_t) ~(0x10)) + 0x0A; + } + if (RTC_Format == RTC_FORMAT_BIN) + { + assert_param(IS_RTC_YEAR(RTC_DateStruct->Year)); + assert_param(IS_RTC_MONTH(RTC_DateStruct->Month)); + assert_param(IS_RTC_DATE(RTC_DateStruct->Date)); + } + else + { + assert_param(IS_RTC_YEAR(RTC_Bcd2ToByte(RTC_DateStruct->Year))); + tmpregister = RTC_Bcd2ToByte(RTC_DateStruct->Month); + assert_param(IS_RTC_MONTH(tmpregister)); + tmpregister = RTC_Bcd2ToByte(RTC_DateStruct->Date); + assert_param(IS_RTC_DATE(tmpregister)); + } + assert_param(IS_RTC_WEEKDAY(RTC_DateStruct->WeekDay)); + + /* Check the input parameters format */ + if (RTC_Format != RTC_FORMAT_BIN) + { + tmpregister = ((((uint32_t)RTC_DateStruct->Year) << 16) | (((uint32_t)RTC_DateStruct->Month) << 8) + | ((uint32_t)RTC_DateStruct->Date) | (((uint32_t)RTC_DateStruct->WeekDay) << 13)); + } + else + { + tmpregister = (((uint32_t)RTC_ByteToBcd2(RTC_DateStruct->Year) << 16) + | ((uint32_t)RTC_ByteToBcd2(RTC_DateStruct->Month) << 8) + | ((uint32_t)RTC_ByteToBcd2(RTC_DateStruct->Date)) | ((uint32_t)RTC_DateStruct->WeekDay << 13)); + } + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Set Initialization mode */ + if (RTC_EnterInitMode() == ERROR) + { + status = ERROR; + } + else + { + /* Set the RTC_DATE register */ + RTC->DATE = (uint32_t)(tmpregister & RTC_DATE_RESERVED_MASK); + + /* Exit Initialization mode */ + RTC_ExitInitMode(); + + /* If RTC_CTRL_BYPS bit = 0, wait for synchro else this check is not needed */ + if ((RTC->CTRL & RTC_CTRL_BYPS) == RESET) + { + if (RTC_WaitForSynchro() == ERROR) + { + status = ERROR; + } + else + { + status = SUCCESS; + } + } + else + { + status = SUCCESS; + } + } + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + + return status; +} + +/** + * @brief Fills each RTC_DateStruct member with its default value + * (Monday, January 01 xx00). + * @param RTC_DateStruct pointer to a RTC_DateType structure which will be + * initialized. + */ +void RTC_DateStructInit(RTC_DateType* RTC_DateStruct) +{ + /* Monday, January 01 xx00 */ + RTC_DateStruct->WeekDay = RTC_WEEKDAY_MONDAY; + RTC_DateStruct->Date = 1; + RTC_DateStruct->Month = RTC_MONTH_JANUARY; + RTC_DateStruct->Year = 0; +} + +/** + * @brief Get the RTC current date. + * @param RTC_Format specifies the format of the returned parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN Binary data format. + * @arg RTC_FORMAT_BCD BCD data format. + * @param RTC_DateStruct pointer to a RTC_DateType structure that will + * contain the returned current date configuration. + */ +void RTC_GetDate(uint32_t RTC_Format, RTC_DateType* RTC_DateStruct) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(RTC_Format)); + + /* Get the RTC_TSH register */ + tmpregister = (uint32_t)(RTC->DATE & RTC_DATE_RESERVED_MASK); + + /* Fill the structure fields with the read parameters */ + RTC_DateStruct->Year = (uint8_t)((tmpregister & (RTC_DATE_YRT | RTC_DATE_YRU)) >> 16); + RTC_DateStruct->Month = (uint8_t)((tmpregister & (RTC_DATE_MOT | RTC_DATE_MOU)) >> 8); + RTC_DateStruct->Date = (uint8_t)(tmpregister & (RTC_DATE_DAT | RTC_DATE_DAU)); + RTC_DateStruct->WeekDay = (uint8_t)((tmpregister & (RTC_DATE_WDU)) >> 13); + + /* Check the input parameters format */ + if (RTC_Format == RTC_FORMAT_BIN) + { + /* Convert the structure parameters to Binary format */ + RTC_DateStruct->Year = (uint8_t)RTC_Bcd2ToByte(RTC_DateStruct->Year); + RTC_DateStruct->Month = (uint8_t)RTC_Bcd2ToByte(RTC_DateStruct->Month); + RTC_DateStruct->Date = (uint8_t)RTC_Bcd2ToByte(RTC_DateStruct->Date); + } +} + +/** + * @} + */ + +/** @addtogroup RTC_Group3 Alarms configuration functions + * @brief Alarms (Alarm A and Alarm B) configuration functions + * +@verbatim + =============================================================================== + ##### Alarms (Alarm A and Alarm B) configuration functions ##### + =============================================================================== + [..] This section provide functions allowing to program and read the RTC + Alarms. + +@endverbatim + * @{ + */ + +/** + * @brief Set the specified RTC Alarm. + * @note The Alarm register can only be written when the corresponding Alarm + * is disabled (Use the RTC_EnableAlarm(DISABLE)). + * @param RTC_Format specifies the format of the returned parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN Binary data format. + * @arg RTC_FORMAT_BCD BCD data format. + * @param RTC_Alarm specifies the alarm to be configured. + * This parameter can be one of the following values: + * @arg RTC_A_ALARM to select Alarm A. + * @arg RTC_B_ALARM to select Alarm B. + * @param RTC_AlarmStruct pointer to a RTC_AlarmType structure that + * contains the alarm configuration parameters. + */ +void RTC_SetAlarm(uint32_t RTC_Format, uint32_t RTC_Alarm, RTC_AlarmType* RTC_AlarmStruct) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(RTC_Format)); + assert_param(IS_RTC_ALARM_SEL(RTC_Alarm)); + assert_param(IS_ALARM_MASK(RTC_AlarmStruct->AlarmMask)); + assert_param(IS_RTC_ALARM_WEEKDAY_SEL(RTC_AlarmStruct->DateWeekMode)); + + if (RTC_Format == RTC_FORMAT_BIN) + { + if ((RTC->CTRL & RTC_CTRL_HFMT) != (uint32_t)RESET) + { + assert_param(IS_RTC_12HOUR(RTC_AlarmStruct->AlarmTime.Hours)); + assert_param(IS_RTC_H12(RTC_AlarmStruct->AlarmTime.H12)); + } + else + { + RTC_AlarmStruct->AlarmTime.H12 = 0x00; + assert_param(IS_RTC_24HOUR(RTC_AlarmStruct->AlarmTime.Hours)); + } + assert_param(IS_RTC_MINUTES(RTC_AlarmStruct->AlarmTime.Minutes)); + assert_param(IS_RTC_SECONDS(RTC_AlarmStruct->AlarmTime.Seconds)); + + if (RTC_AlarmStruct->DateWeekMode == RTC_ALARM_SEL_WEEKDAY_DATE) + { + assert_param(IS_RTC_ALARM_WEEKDAY_DATE(RTC_AlarmStruct->DateWeekValue)); + } + else + { + assert_param(IS_RTC_ALARM_WEEKDAY_WEEKDAY(RTC_AlarmStruct->DateWeekValue)); + } + } + else + { + if ((RTC->CTRL & RTC_CTRL_HFMT) != (uint32_t)RESET) + { + tmpregister = RTC_Bcd2ToByte(RTC_AlarmStruct->AlarmTime.Hours); + assert_param(IS_RTC_12HOUR(tmpregister)); + assert_param(IS_RTC_H12(RTC_AlarmStruct->AlarmTime.H12)); + } + else + { + RTC_AlarmStruct->AlarmTime.H12 = 0x00; + assert_param(IS_RTC_24HOUR(RTC_Bcd2ToByte(RTC_AlarmStruct->AlarmTime.Hours))); + } + + assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(RTC_AlarmStruct->AlarmTime.Minutes))); + assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(RTC_AlarmStruct->AlarmTime.Seconds))); + + if (RTC_AlarmStruct->DateWeekMode == RTC_ALARM_SEL_WEEKDAY_DATE) + { + tmpregister = RTC_Bcd2ToByte(RTC_AlarmStruct->DateWeekValue); + assert_param(IS_RTC_ALARM_WEEKDAY_DATE(tmpregister)); + } + else + { + tmpregister = RTC_Bcd2ToByte(RTC_AlarmStruct->DateWeekValue); + assert_param(IS_RTC_ALARM_WEEKDAY_WEEKDAY(tmpregister)); + } + } + + /* Check the input parameters format */ + if (RTC_Format != RTC_FORMAT_BIN) + { + tmpregister = + (((uint32_t)(RTC_AlarmStruct->AlarmTime.Hours) << 16) + | ((uint32_t)(RTC_AlarmStruct->AlarmTime.Minutes) << 8) | ((uint32_t)RTC_AlarmStruct->AlarmTime.Seconds) + | ((uint32_t)(RTC_AlarmStruct->AlarmTime.H12) << 16) | ((uint32_t)(RTC_AlarmStruct->DateWeekValue) << 24) + | ((uint32_t)RTC_AlarmStruct->DateWeekMode) | ((uint32_t)RTC_AlarmStruct->AlarmMask)); + } + else + { + tmpregister = (((uint32_t)RTC_ByteToBcd2(RTC_AlarmStruct->AlarmTime.Hours) << 16) + | ((uint32_t)RTC_ByteToBcd2(RTC_AlarmStruct->AlarmTime.Minutes) << 8) + | ((uint32_t)RTC_ByteToBcd2(RTC_AlarmStruct->AlarmTime.Seconds)) + | ((uint32_t)(RTC_AlarmStruct->AlarmTime.H12) << 16) + | ((uint32_t)RTC_ByteToBcd2(RTC_AlarmStruct->DateWeekValue) << 24) + | ((uint32_t)RTC_AlarmStruct->DateWeekMode) | ((uint32_t)RTC_AlarmStruct->AlarmMask)); + } + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Configure the Alarm register */ + if (RTC_Alarm == RTC_A_ALARM) + { + RTC->ALARMA = (uint32_t)tmpregister; + } + else + { + RTC->ALARMB = (uint32_t)tmpregister; + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Fills each RTC_AlarmStruct member with its default value + * (Time = 00h:00mn:00sec / Date = 1st day of the month/Mask = + * all fields are masked). + * @param RTC_AlarmStruct pointer to a @ref RTC_AlarmType structure which + * will be initialized. + */ +void RTC_AlarmStructInit(RTC_AlarmType* RTC_AlarmStruct) +{ + /* Alarm Time Settings : Time = 00h:00mn:00sec */ + RTC_AlarmStruct->AlarmTime.H12 = RTC_AM_H12; + RTC_AlarmStruct->AlarmTime.Hours = 0; + RTC_AlarmStruct->AlarmTime.Minutes = 0; + RTC_AlarmStruct->AlarmTime.Seconds = 0; + + /* Alarm Date Settings : Date = 1st day of the month */ + RTC_AlarmStruct->DateWeekMode = RTC_ALARM_SEL_WEEKDAY_DATE; + RTC_AlarmStruct->DateWeekValue = 1; + + /* Alarm Masks Settings : Mask = all fields are not masked */ + RTC_AlarmStruct->AlarmMask = RTC_ALARMMASK_NONE; +} + +/** + * @brief Get the RTC Alarm value and masks. + * @param RTC_Format specifies the format of the output parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN Binary data format. + * @arg RTC_FORMAT_BCD BCD data format. + * @param RTC_Alarm specifies the alarm to be read. + * This parameter can be one of the following values: + * @arg RTC_A_ALARM to select Alarm A. + * @arg RTC_B_ALARM to select Alarm B. + * @param RTC_AlarmStruct pointer to a RTC_AlarmType structure that will + * contains the output alarm configuration values. + */ +void RTC_GetAlarm(uint32_t RTC_Format, uint32_t RTC_Alarm, RTC_AlarmType* RTC_AlarmStruct) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(RTC_Format)); + assert_param(IS_RTC_ALARM_SEL(RTC_Alarm)); + + /* Get the RTC_ALARMx register */ + if (RTC_Alarm == RTC_A_ALARM) + { + tmpregister = (uint32_t)(RTC->ALARMA); + } + else + { + tmpregister = (uint32_t)(RTC->ALARMB); + } + + /* Fill the structure with the read parameters */ + RTC_AlarmStruct->AlarmTime.Hours = (uint32_t)((tmpregister & (RTC_ALARMA_HOT | RTC_ALARMA_HOU)) >> 16); + RTC_AlarmStruct->AlarmTime.Minutes = (uint32_t)((tmpregister & (RTC_ALARMA_MIT | RTC_ALARMA_MIU)) >> 8); + RTC_AlarmStruct->AlarmTime.Seconds = (uint32_t)(tmpregister & (RTC_ALARMA_SET | RTC_ALARMA_SEU)); + RTC_AlarmStruct->AlarmTime.H12 = (uint32_t)((tmpregister & RTC_ALARMA_APM) >> 16); + RTC_AlarmStruct->DateWeekValue = (uint32_t)((tmpregister & (RTC_ALARMA_DTT | RTC_ALARMA_DTU)) >> 24); + RTC_AlarmStruct->DateWeekMode = (uint32_t)(tmpregister & RTC_ALARMA_WKDSEL); + RTC_AlarmStruct->AlarmMask = (uint32_t)(tmpregister & RTC_ALARMMASK_ALL); + + if (RTC_Format == RTC_FORMAT_BIN) + { + RTC_AlarmStruct->AlarmTime.Hours = RTC_Bcd2ToByte(RTC_AlarmStruct->AlarmTime.Hours); + RTC_AlarmStruct->AlarmTime.Minutes = RTC_Bcd2ToByte(RTC_AlarmStruct->AlarmTime.Minutes); + RTC_AlarmStruct->AlarmTime.Seconds = RTC_Bcd2ToByte(RTC_AlarmStruct->AlarmTime.Seconds); + RTC_AlarmStruct->DateWeekValue = RTC_Bcd2ToByte(RTC_AlarmStruct->DateWeekValue); + } +} + +/** + * @brief Enables or disables the specified RTC Alarm. + * @param RTC_Alarm specifies the alarm to be configured. + * This parameter can be any combination of the following values: + * @arg RTC_A_ALARM to select Alarm A. + * @arg RTC_B_ALARM to select Alarm B. + * @param Cmd new state of the specified alarm. + * This parameter can be: ENABLE or DISABLE. + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC Alarm is enabled/disabled + * - ERROR: RTC Alarm is not enabled/disabled + */ +ErrorStatus RTC_EnableAlarm(uint32_t RTC_Alarm, FunctionalState Cmd) +{ + __IO uint32_t alarmcounter = 0x00; + uint32_t alarmstatus = 0x00; + ErrorStatus status = ERROR; + + /* Check the parameters */ + assert_param(IS_RTC_ALARM_ENABLE(RTC_Alarm)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Configure the Alarm state */ + if (Cmd != DISABLE) + { + RTC->CTRL |= (uint32_t)RTC_Alarm; + + status = SUCCESS; + } + else + { + /* Disable the Alarm in RTC_CTRL register */ + RTC->CTRL &= (uint32_t)~RTC_Alarm; + + /* Wait till RTC ALxWF flag is set and if Time out is reached exit */ + do + { + alarmstatus = RTC->INITSTS & (RTC_Alarm >> 8); + alarmcounter++; + } while ((alarmcounter != INITMODE_TIMEOUT) && (alarmstatus == 0x00)); + + if ((RTC->INITSTS & (RTC_Alarm >> 8)) == RESET) + { + status = ERROR; + } + else + { + status = SUCCESS; + } + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + + return status; +} + +/** + * @brief Configure the RTC AlarmA/B Subseconds value and mask.* + * @note This function is performed only when the Alarm is disabled. + * @param RTC_Alarm specifies the alarm to be configured. + * This parameter can be one of the following values: + * @arg RTC_A_ALARM to select Alarm A. + * @arg RTC_B_ALARM to select Alarm B. + * @param RTC_AlarmSubSecondValue specifies the Subseconds value. + * This parameter can be a value from 0 to 0x00007FFF. + * @param RTC_AlarmSubSecondMask specifies the Subseconds Mask. + * This parameter can be any combination of the following values: + * @arg RTC_SUBS_MASK_ALL All Alarm SS fields are masked. + * There is no comparison on sub seconds for Alarm. + * @arg RTC_SUBS_MASK_SS14_1 SS[14:1] are don't care in Alarm comparison. + * Only SS[0] is compared + * @arg RTC_SUBS_MASK_SS14_2 SS[14:2] are don't care in Alarm comparison. + * Only SS[1:0] are compared + * @arg RTC_SUBS_MASK_SS14_3 SS[14:3] are don't care in Alarm comparison. + * Only SS[2:0] are compared + * @arg RTC_SUBS_MASK_SS14_4 SS[14:4] are don't care in Alarm comparison. + * Only SS[3:0] are compared + * @arg RTC_SUBS_MASK_SS14_5 SS[14:5] are don't care in Alarm comparison. + * Only SS[4:0] are compared. + * @arg RTC_SUBS_MASK_SS14_6 SS[14:6] are don't care in Alarm comparison. + * Only SS[5:0] are compared. + * @arg RTC_SUBS_MASK_SS14_7 SS[14:7] are don't care in Alarm comparison. + * Only SS[6:0] are compared. + * @arg RTC_SUBS_MASK_SS14_8 SS[14:8] are don't care in Alarm comparison. + * Only SS[7:0] are compared. + * @arg RTC_SUBS_MASK_SS14_9 SS[14:9] are don't care in Alarm comparison. + * Only SS[8:0] are compared. + * @arg RTC_SUBS_MASK_SS14_10 SS[14:10] are don't care in Alarm comparison. + * Only SS[9:0] are compared. + * @arg RTC_SUBS_MASK_SS14_11 SS[14:11] are don't care in Alarm comparison. + * Only SS[10:0] are compared. + * @arg RTC_SUBS_MASK_SS14_12 SS[14:12] are don't care in Alarm comparison. + * Only SS[11:0] are compared. + * @arg RTC_SUBS_MASK_SS14_13 SS[14:13] are don't care in Alarm comparison. + * Only SS[12:0] are compared. + * @arg RTC_SUBS_MASK_SS14_14 SS[14] is don't care in Alarm comparison. + * Only SS[13:0] are compared. + * @arg RTC_SUBS_MASK_NONE SS[14:0] are compared and must match + * to activate alarm. + */ +void RTC_ConfigAlarmSubSecond(uint32_t RTC_Alarm, uint32_t RTC_AlarmSubSecondValue, uint32_t RTC_AlarmSubSecondMask) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RTC_ALARM_SEL(RTC_Alarm)); + assert_param(IS_RTC_ALARM_SUB_SECOND_VALUE(RTC_AlarmSubSecondValue)); + assert_param(IS_RTC_ALARM_SUB_SECOND_MASK_MODE(RTC_AlarmSubSecondMask)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Configure the Alarm A or Alarm B SubSecond registers */ + tmpregister = (uint32_t)(uint32_t)(RTC_AlarmSubSecondValue) | (uint32_t)(RTC_AlarmSubSecondMask); + + if (RTC_Alarm == RTC_A_ALARM) + { + /* Configure the AlarmA SubSecond register */ + RTC->ALRMASS = tmpregister; + } + else + { + /* Configure the Alarm B SubSecond register */ + RTC->ALRMBSS = tmpregister; + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Gets the RTC Alarm Subseconds value. + * @param RTC_Alarm specifies the alarm to be read. + * This parameter can be one of the following values: + * @arg RTC_A_ALARM to select Alarm A. + * @arg RTC_B_ALARM to select Alarm B. + * @return RTC Alarm Subseconds value. + */ +uint32_t RTC_GetAlarmSubSecond(uint32_t RTC_Alarm) +{ + uint32_t tmpregister = 0; + + /* Get the RTC_ALARMx register */ + if (RTC_Alarm == RTC_A_ALARM) + { + tmpregister = (uint32_t)((RTC->ALRMASS) & RTC_ALRMASS_SSV); + } + else + { + tmpregister = (uint32_t)((RTC->ALRMBSS) & RTC_ALRMBSS_SSV); + } + + return (tmpregister); +} + +/** + * @} + */ + +/** @addtogroup RTC_Group4 WakeUp Timer configuration functions + * @brief WakeUp Timer configuration functions + * +@verbatim + =============================================================================== + ##### WakeUp Timer configuration functions ##### + =============================================================================== + [..] This section provide functions allowing to program and read the RTC WakeUp. + +@endverbatim + * @{ + */ + +/** + * @brief Configures the RTC Wakeup clock source. + * @note The WakeUp Clock source can only be changed when the RTC WakeUp + * is disabled (Use the RTC_EnableWakeUp(DISABLE)). + * @param RTC_WakeUpClock Wakeup Clock source. + * This parameter can be one of the following values: + * @arg RTC_WKUPCLK_RTCCLK_DIV16 RTC Wakeup Counter Clock = RTCCLK/16. + * @arg RTC_WKUPCLK_RTCCLK_DIV8 RTC Wakeup Counter Clock = RTCCLK/8. + * @arg RTC_WKUPCLK_RTCCLK_DIV4 RTC Wakeup Counter Clock = RTCCLK/4. + * @arg RTC_WKUPCLK_RTCCLK_DIV2 RTC Wakeup Counter Clock = RTCCLK/2. + * @arg RTC_WKUPCLK_CK_SPRE_16BITS RTC Wakeup Counter Clock = CK_SPRE. + */ +void RTC_ConfigWakeUpClock(uint32_t RTC_WakeUpClock) +{ + /* Check the parameters */ + assert_param(IS_RTC_WKUP_CLOCK(RTC_WakeUpClock)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Clear the Wakeup Timer clock source bits in CTRL register */ + RTC->CTRL &= (uint32_t)~RTC_CTRL_WKUPSEL; + + /* Configure the clock source */ + RTC->CTRL |= (uint32_t)RTC_WakeUpClock; + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Configures the RTC Wakeup counter. + * @note The RTC WakeUp counter can only be written when the RTC WakeUp. + * is disabled (Use the RTC_EnableWakeUp(DISABLE)). + * @param RTC_WakeUpCounter specifies the WakeUp counter. + * This parameter can be a value from 0x0000 to 0xFFFF. + */ +void RTC_SetWakeUpCounter(uint32_t RTC_WakeUpCounter) +{ + /* Check the parameters */ + assert_param(IS_RTC_WKUP_COUNTER(RTC_WakeUpCounter)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Configure the Wakeup Timer counter */ + RTC->WKUPT = (uint32_t)RTC_WakeUpCounter; + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Returns the RTC WakeUp timer counter value. + * @return The RTC WakeUp Counter value. + */ +uint32_t RTC_GetWakeUpCounter(void) +{ + /* Get the counter value */ + return ((uint32_t)(RTC->WKUPT & RTC_WKUPT_WKUPT)); +} + +/** + * @brief Enables or Disables the RTC WakeUp timer. + * @param Cmd new state of the WakeUp timer. + * This parameter can be: ENABLE or DISABLE. + */ +ErrorStatus RTC_EnableWakeUp(FunctionalState Cmd) +{ + __IO uint32_t wutcounter = 0x00; + uint32_t wutwfstatus = 0x00; + ErrorStatus status = ERROR; + + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + if (Cmd != DISABLE) + { + /* Enable the Wakeup Timer */ + RTC->CTRL |= (uint32_t)RTC_CTRL_WTEN; + status = SUCCESS; + } + else + { + /* Disable the Wakeup Timer */ + RTC->CTRL &= (uint32_t)~RTC_CTRL_WTEN; + /* Wait till RTC WTWF flag is set and if Time out is reached exit */ + do + { + wutwfstatus = RTC->INITSTS & RTC_INITSTS_WTWF; + wutcounter++; + } while ((wutcounter != INITMODE_TIMEOUT) && (wutwfstatus == 0x00)); + + if ((RTC->INITSTS & RTC_INITSTS_WTWF) == RESET) + { + status = ERROR; + } + else + { + status = SUCCESS; + } + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + + return status; +} + +/** + * @} + */ + +/** @addtogroup RTC_Group5 Daylight Saving configuration functions + * @brief Daylight Saving configuration functions + * +@verbatim + =============================================================================== + ##### Daylight Saving configuration functions ##### + =============================================================================== + [..] This section provide functions allowing to configure the RTC DayLight Saving. + +@endverbatim + * @{ + */ + +/** + * @brief Adds or substract one hour from the current time. + * @param RTC_DayLightSaving the value of hour adjustment. + * This parameter can be one of the following values: + * @arg RTC_DAYLIGHT_SAVING_SUB1H Substract one hour (winter time). + * @arg RTC_DAYLIGHT_SAVING_ADD1H Add one hour (summer time). + * @param RTC_StoreOperation Specifies the value to be written in the BCK bit + * in CTRL register to store the operation. + * This parameter can be one of the following values: + * @arg RTC_STORE_OPERATION_RESET BCK Bit Reset. + * @arg RTC_STORE_OPERATION_SET BCK Bit Set. + */ +void RTC_ConfigDayLightSaving(uint32_t RTC_DayLightSaving, uint32_t RTC_StoreOperation) +{ + /* Check the parameters */ + assert_param(IS_RTC_DAYLIGHT_SAVING(RTC_DayLightSaving)); + assert_param(IS_RTC_STORE_OPERATION(RTC_StoreOperation)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Clear the bits to be configured */ + RTC->CTRL &= (uint32_t) ~(RTC_CTRL_BAKP); + /* Clear the SU1H and AD1H bits to be configured */ + RTC->CTRL &= (uint32_t) ~(RTC_CTRL_SU1H & RTC_CTRL_AD1H); + /* Configure the RTC_CTRL register */ + RTC->CTRL |= (uint32_t)(RTC_DayLightSaving | RTC_StoreOperation); + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Returns the RTC Day Light Saving stored operation. + * @return RTC Day Light Saving stored operation. + * - RTC_STORE_OPERATION_RESET + * - RTC_STORE_OPERATION_SET + */ +uint32_t RTC_GetStoreOperation(void) +{ + return (RTC->CTRL & RTC_CTRL_BAKP); +} + +/** + * @} + */ + +/** @addtogroup RTC_Group6 Output pin Configuration function + * @brief Output pin Configuration function + * +@verbatim + =============================================================================== + ##### Output pin Configuration function ##### + =============================================================================== + [..] This section provide functions allowing to configure the RTC Output source. + +@endverbatim + * @{ + */ + + + +/** + * @brief Configures the RTC output source (AFO_ALARM). + * @param RTC_Output Specifies which signal will be routed to the RTC output. + * This parameter can be one of the following values: + * @arg RTC_OUTPUT_DIS No output selected + * @arg RTC_OUTPUT_ALA signal of AlarmA mapped to output. + * @arg RTC_OUTPUT_ALB signal of AlarmB mapped to output. + * @arg RTC_OUTPUT_WKUP signal of WakeUp mapped to output. + * @param RTC_OutputPolarity Specifies the polarity of the output signal. + * This parameter can be one of the following: + * @arg RTC_OUTPOL_HIGH The output pin is high when the + * ALRAF/ALRBF/WUTF is high (depending on OSEL). + * @arg RTC_OUTPOL_LOW The output pin is low when the + * ALRAF/ALRBF/WUTF is high (depending on OSEL). + */ +void RTC_ConfigOutput(uint32_t RTC_Output, uint32_t RTC_OutputPolarity) +{ + /* Check the parameters */ + assert_param(IS_RTC_OUTPUT_MODE(RTC_Output)); + assert_param(IS_RTC_OUTPUT_POL(RTC_OutputPolarity)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Clear the bits to be configured */ + RTC->CTRL &= (uint32_t) ~(RTC_CTRL_OUTSEL | RTC_CTRL_OPOL); + + + /* Configure the output selection and polarity */ + RTC->CTRL |= (uint32_t)(RTC_Output | RTC_OutputPolarity); + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @} + */ + +/** @addtogroup RTC_Group7 Coarse and Smooth Calibrations configuration functions + * @brief Coarse and Smooth Calibrations configuration functions + * +@verbatim + =============================================================================== + ##### Coarse and Smooth Calibrations configuration functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the RTC clock to be output through the relative + * pin. + * @param Cmd new state of the coarse calibration Output. + * This parameter can be: ENABLE or DISABLE. + */ +void RTC_EnableCalibOutput(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + if (Cmd != DISABLE) + { + /* Enable the RTC clock output */ + RTC->CTRL |= (uint32_t)RTC_CTRL_COEN; + } + else + { + /* Disable the RTC clock output */ + RTC->CTRL &= (uint32_t)~RTC_CTRL_COEN; + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Configure the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz). + * @param RTC_CalibOutput Select the Calibration output Selection . + * This parameter can be one of the following values: + * @arg RTC_CALIB_OUTPUT_256HZ A signal has a regular waveform at 256Hz. + * @arg RTC_CALIB_OUTPUT_1HZ A signal has a regular waveform at 1Hz. + */ +void RTC_ConfigCalibOutput(uint32_t RTC_CalibOutput) +{ + /* Check the parameters */ + assert_param(IS_RTC_CALIB_OUTPUT(RTC_CalibOutput)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /*clear flags before config*/ + RTC->CTRL &= (uint32_t) ~(RTC_CTRL_CALOSEL); + + /* Configure the RTC_CTRL register */ + RTC->CTRL |= (uint32_t)RTC_CalibOutput; + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Configures the Smooth Calibration Settings. + * @param RTC_SmoothCalibPeriod Select the Smooth Calibration Period. + * This parameter can be can be one of the following values: + * @arg SMOOTH_CALIB_32SEC The smooth calibration periode is 32s. + * @arg SMOOTH_CALIB_16SEC The smooth calibration periode is 16s. + * @arg SMOOTH_CALIB_8SEC The smooth calibartion periode is 8s. + * @param RTC_SmoothCalibPlusPulses Select to Set or reset the CALP bit. + * This parameter can be one of the following values: + * @arg RTC_SMOOTH_CALIB_PLUS_PULSES_SET Add one RTCCLK puls every 2**11 pulses. + * @arg RTC_SMOOTH_CALIB_PLUS_PULSES__RESET No RTCCLK pulses are added. + * @param RTC_SmouthCalibMinusPulsesValue Select the value of CALM[8:0] bits. + * This parameter can be one any value from 0 to 0x000001FF. + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC Calib registers are configured + * - ERROR: RTC Calib registers are not configured + */ +ErrorStatus RTC_ConfigSmoothCalib(uint32_t RTC_SmoothCalibPeriod, + uint32_t RTC_SmoothCalibPlusPulses, + uint32_t RTC_SmouthCalibMinusPulsesValue) +{ + ErrorStatus status = ERROR; + uint32_t recalpfcount = 0; + + /* Check the parameters */ + assert_param(IS_RTC_SMOOTH_CALIB_PERIOD_SEL(RTC_SmoothCalibPeriod)); + assert_param(IS_RTC_SMOOTH_CALIB_PLUS(RTC_SmoothCalibPlusPulses)); + assert_param(IS_RTC_SMOOTH_CALIB_MINUS(RTC_SmouthCalibMinusPulsesValue)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* check if a calibration is pending*/ + if ((RTC->INITSTS & RTC_INITSTS_RECPF) != RESET) + { + /* wait until the Calibration is completed*/ + while (((RTC->INITSTS & RTC_INITSTS_RECPF) != RESET) && (recalpfcount != RECALPF_TIMEOUT)) + { + recalpfcount++; + } + } + + /* check if the calibration pending is completed or if there is no calibration operation at all*/ + if ((RTC->INITSTS & RTC_INITSTS_RECPF) == RESET) + { + /* Configure the Smooth calibration settings */ + RTC->CALIB = (uint32_t)((uint32_t)RTC_SmoothCalibPeriod | (uint32_t)RTC_SmoothCalibPlusPulses + | (uint32_t)RTC_SmouthCalibMinusPulsesValue); + + status = SUCCESS; + } + else + { + status = ERROR; + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + + return (ErrorStatus)(status); +} + +/** + * @} + */ + +/** @addtogroup RTC_Group8 TimeStamp configuration functions + * @brief TimeStamp configuration functions + * +@verbatim + =============================================================================== + ##### TimeStamp configuration functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Enables or Disables the RTC TimeStamp functionality with the + * specified time stamp pin stimulating edge. + * @param RTC_TimeStampEdge Specifies the pin edge on which the TimeStamp is + * activated. + * This parameter can be one of the following: + * @arg RTC_TIMESTAMP_EDGE_RISING the Time stamp event occurs on the rising + * edge of the related pin. + * @arg RTC_TIMESTAMP_EDGE_FALLING the Time stamp event occurs on the + * falling edge of the related pin. + * @param Cmd new state of the TimeStamp. + * This parameter can be: ENABLE or DISABLE. + */ +void RTC_EnableTimeStamp(uint32_t RTC_TimeStampEdge, FunctionalState Cmd) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RTC_TIMESTAMP_EDGE_MODE(RTC_TimeStampEdge)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Get the RTC_CTRL register and clear the bits to be configured */ + tmpregister = (uint32_t)(RTC->CTRL & (uint32_t) ~(RTC_CTRL_TSPOL | RTC_CTRL_TSEN)); + + /* Get the new configuration */ + if (Cmd != DISABLE) + { + tmpregister |= (uint32_t)(RTC_TimeStampEdge | RTC_CTRL_TSEN); + } + else + { + tmpregister |= (uint32_t)(RTC_TimeStampEdge); + } + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Configure the Time Stamp TSEDGE and Enable bits */ + RTC->CTRL = (uint32_t)tmpregister; + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Get the RTC TimeStamp value and masks. + * @param RTC_Format specifies the format of the output parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN Binary data format + * @arg RTC_FORMAT_BCD BCD data format + * @param RTC_StampTimeStruct pointer to a RTC_TimeType structure that will + * contains the TimeStamp time values. + * @param RTC_StampDateStruct pointer to a RTC_DateType structure that will + * contains the TimeStamp date values. + */ +void RTC_GetTimeStamp(uint32_t RTC_Format, RTC_TimeType* RTC_StampTimeStruct, RTC_DateType* RTC_StampDateStruct) +{ + uint32_t tmptime = 0, tmpdate = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(RTC_Format)); + + /* Get the TimeStamp time and date registers values */ + tmptime = (uint32_t)(RTC->TST & RTC_TR_RESERVED_MASK); + tmpdate = (uint32_t)(RTC->TSD & RTC_DATE_RESERVED_MASK); + + /* Fill the Time structure fields with the read parameters */ + RTC_StampTimeStruct->Hours = (uint8_t)((tmptime & (RTC_TSH_HOT | RTC_TSH_HOU)) >> 16); + RTC_StampTimeStruct->Minutes = (uint8_t)((tmptime & (RTC_TSH_MIT | RTC_TSH_MIU)) >> 8); + RTC_StampTimeStruct->Seconds = (uint8_t)(tmptime & (RTC_TSH_SCT | RTC_TSH_SCU)); + RTC_StampTimeStruct->H12 = (uint8_t)((tmptime & (RTC_TSH_APM)) >> 16); + + /* Fill the Date structure fields with the read parameters */ + RTC_StampDateStruct->Year = (uint8_t)((tmpdate & (RTC_DATE_YRT | RTC_DATE_YRU)) >> 16); + RTC_StampDateStruct->Month = (uint8_t)((tmpdate & (RTC_DATE_MOT | RTC_DATE_MOU)) >> 8); + RTC_StampDateStruct->Date = (uint8_t)(tmpdate & (RTC_DATE_DAT | RTC_DATE_DAU)); + RTC_StampDateStruct->WeekDay = (uint8_t)((tmpdate & (RTC_DATE_WDU)) >> 13); + + /* Check the input parameters format */ + if (RTC_Format == RTC_FORMAT_BIN) + { + /* Convert the Time structure parameters to Binary format */ + RTC_StampTimeStruct->Hours = (uint8_t)RTC_Bcd2ToByte(RTC_StampTimeStruct->Hours); + RTC_StampTimeStruct->Minutes = (uint8_t)RTC_Bcd2ToByte(RTC_StampTimeStruct->Minutes); + RTC_StampTimeStruct->Seconds = (uint8_t)RTC_Bcd2ToByte(RTC_StampTimeStruct->Seconds); + + /* Convert the Date structure parameters to Binary format */ + RTC_StampDateStruct->Month = (uint8_t)RTC_Bcd2ToByte(RTC_StampDateStruct->Month); + RTC_StampDateStruct->Date = (uint8_t)RTC_Bcd2ToByte(RTC_StampDateStruct->Date); + RTC_StampDateStruct->WeekDay = (uint8_t)RTC_Bcd2ToByte(RTC_StampDateStruct->WeekDay); + } +} + +/** + * @brief Get the RTC timestamp Subseconds value. + * @return RTC current timestamp Subseconds value. + */ +uint32_t RTC_GetTimeStampSubSecond(void) +{ + /* Get timestamp subseconds values from the correspondent registers */ + return (uint32_t)(RTC->TSSS); +} + +/** + * @} + */ + +/** @addtogroup RTC_Group11 Output Type Config configuration functions + * @brief Output Type Config configuration functions + * +@verbatim + =============================================================================== + ##### Output Type Config configuration functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Configures the RTC Output Pin mode. + * @param RTC_OutputType specifies the RTC Output (PC13) pin mode. + * This parameter can be one of the following values: + * @arg RTC_OUTPUT_OPENDRAIN RTC Output (PC13) is configured in + * Open Drain mode. + * @arg RTC_OUTPUT_PUSHPULL RTC Output (PC13) is configured in + * Push Pull mode. + */ +void RTC_ConfigOutputType(uint32_t RTC_OutputType) +{ + /* Check the parameters */ + assert_param(IS_RTC_OUTPUT_TYPE(RTC_OutputType)); + + RTC->OPT &= (uint32_t) ~(RTC_OPT_TYPE); + RTC->OPT |= (uint32_t)(RTC_OutputType); +} + +/** + * @} + */ + +/** @addtogroup RTC_Group12 Shift control synchronisation functions + * @brief Shift control synchronisation functions + * +@verbatim + =============================================================================== + ##### Shift control synchronisation functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Configures the Synchronization Shift Control Settings. + * @note When REFCKON is set, firmware must not write to Shift control register + * @param RTC_ShiftAdd1S Select to add or not 1 second to the time Calendar. + * This parameter can be one of the following values : + * @arg RTC_SHIFT_SUB1S_DISABLE Add one second to the clock calendar. + * @arg RTC_SHIFT_SUB1S_ENABLE No effect. + * @param RTC_ShiftAddFS Select the number of Second Fractions to Substitute. + * This parameter can be one any value from 0 to 0x7FFF. + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC Shift registers are configured + * - ERROR: RTC Shift registers are not configured + */ +ErrorStatus RTC_ConfigSynchroShift(uint32_t RTC_ShiftAddFS, uint32_t RTC_ShiftSub1s) +{ + ErrorStatus status = ERROR; + uint32_t shpfcount = 0; + + /* Check the parameters */ + assert_param(IS_RTC_SHIFT_ADFS(RTC_ShiftAddFS)); + assert_param(IS_RTC_SHIFT_SUB1S(RTC_ShiftSub1s)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Check if a Shift is pending*/ + if ((RTC->INITSTS & RTC_INITSTS_SHOPF) != RESET) + { + /* Wait until the shift is completed*/ + while (((RTC->INITSTS & RTC_INITSTS_SHOPF) != RESET) && (shpfcount != SHPF_TIMEOUT)) + { + shpfcount++; + } + } + + /* Check if the Shift pending is completed or if there is no Shift operation at all*/ + if ((RTC->INITSTS & RTC_INITSTS_SHOPF) == RESET) + { + + { + /* Configure the Shift settings */ + RTC->SCTRL = (uint32_t)(uint32_t)(RTC_ShiftAddFS) | (uint32_t)(RTC_ShiftSub1s); + + if (RTC_WaitForSynchro() == ERROR) + { + status = ERROR; + } + else + { + status = SUCCESS; + } + } + + } + else + { + status = ERROR; + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + + return (ErrorStatus)(status); +} + +/** + * @} + */ + +/** @addtogroup RTC_Group13 Interrupts and flags management functions + * @brief Interrupts and flags management functions + * +@verbatim + =============================================================================== + ##### Interrupts and flags management functions ##### + =============================================================================== + [..] All RTC interrupts are connected to the EXTI controller. + (+) To enable the RTC Alarm interrupt, the following sequence is required: + (+) Configure and enable the EXTI Line 17 in interrupt mode and select + the rising edge sensitivity using the EXTI_InitPeripheral() function. + (+) Configure and enable the RTC_Alarm IRQ channel in the NVIC using + the NVIC_Init() function. + (+) Configure the RTC to generate RTC alarms (Alarm A and/or Alarm B) + using the RTC_SetAlarm() and RTC_EnableAlarm() functions. + + (+) To enable the RTC Wakeup interrupt, the following sequence is required: + (+) Configure and enable the EXTI Line 20 in interrupt mode and select + the rising edge sensitivity using the EXTI_InitPeripheral() function. + (+) Configure and enable the RTC_WKUP IRQ channel in the NVIC using the + NVIC_Init() function. + (+) Configure the RTC to generate the RTC wakeup timer event using the + RTC_ConfigWakeUpClock(), RTC_SetWakeUpCounter() and RTC_EnableWakeUp() + functions. + + (+) To enable the RTC Tamper interrupt, the following sequence is required: + (+) Configure and enable the EXTI Line 19 in interrupt mode and select + the rising edge sensitivity using the EXTI_InitPeripheral() function. + (+) Configure and enable the TAMP_STAMP IRQ channel in the NVIC using + the NVIC_Init() function. + (+) Configure the RTC to detect the RTC tamper event using the + RTC_TamperTriggerConfig() and RTC_TamperCmd() functions. + + (+) To enable the RTC TimeStamp interrupt, the following sequence is + required: + (+) Configure and enable the EXTI Line 19 in interrupt mode and select + the rising edge sensitivity using the EXTI_InitPeripheral() function. + (+) Configure and enable the TAMP_STAMP IRQ channel in the NVIC using + the NVIC_Init() function. + (+) Configure the RTC to detect the RTC time-stamp event using the + RTC_EnableTimeStamp() functions. + +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the specified RTC interrupts. + * @param RTC_INT specifies the RTC interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg RTC_INT_WUT WakeUp Timer interrupt mask. + * @arg RTC_INT_ALRB Alarm B interrupt mask. + * @arg RTC_INT_ALRA Alarm A interrupt mask. + * @param Cmd new state of the specified RTC interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void RTC_ConfigInt(uint32_t RTC_INT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_RTC_CONFIG_INT(RTC_INT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + if (Cmd != DISABLE) + { + /* Configure the Interrupts in the RTC_CTRL register */ + RTC->CTRL |= RTC_INT ; + } + else + { + /* Configure the Interrupts in the RTC_CTRL register */ + RTC->CTRL &= (uint32_t) ~(RTC_INT); + } + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Checks whether the specified RTC flag is set or not. + * @param RTC_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg RTC_FLAG_RECPF RECALPF event flag. + * @arg RTC_FLAG_TISOVF Time Stamp OverFlow flag. + * @arg RTC_FLAG_TISF Time Stamp event flag. + * @arg RTC_FLAG_WTF WakeUp Timer flag. + * @arg RTC_FLAG_ALBF Alarm B flag. + * @arg RTC_FLAG_ALAF Alarm A flag. + * @arg RTC_FLAG_INITF Initialization mode flag. + * @arg RTC_FLAG_RSYF Registers Synchronized flag. + * @arg RTC_FLAG_INITSF Registers Configured flag. + * @arg RTC_FLAG_SHOPF Shift operation pending flag. + * @arg RTC_FLAG_WTWF WakeUp Timer Write flag. + * @arg RTC_FLAG_ALBWF Alarm B Write flag. + * @arg RTC_FLAG_ALAWF Alarm A write flag. + * @return The new state of RTC_FLAG (SET or RESET). + */ +FlagStatus RTC_GetFlagStatus(uint32_t RTC_FLAG) +{ + FlagStatus bitstatus = RESET; + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RTC_GET_FLAG(RTC_FLAG)); + + /* Get all the flags */ + tmpregister = (uint32_t)(RTC->INITSTS & RTC_FLAGS_MASK); + + /* Return the status of the flag */ + if ((tmpregister & RTC_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the RTC's pending flags. + * @param RTC_FLAG specifies the RTC flag to clear. + * This parameter can be any combination of the following values:. + * @arg RTC_FLAG_TISOVF Time Stamp Overflow flag. + * @arg RTC_FLAG_TISF Time Stamp event flag. + * @arg RTC_FLAG_WTF WakeUp Timer flag. + * @arg RTC_FLAG_ALBF Alarm B flag. + * @arg RTC_FLAG_ALAF Alarm A flag. + * @arg RTC_FLAG_RSYF Registers Synchronized flag. + */ +void RTC_ClrFlag(uint32_t RTC_FLAG) +{ + /* Check the parameters */ + assert_param(IS_RTC_CLEAR_FLAG(RTC_FLAG)); + + /* Clear the Flags in the RTC_INITSTS register */ + RTC->INITSTS = (uint32_t)( + (uint32_t)(~((RTC_FLAG | RTC_INITSTS_INITM) & 0x00011FFF) | (uint32_t)(RTC->INITSTS & RTC_INITSTS_INITM))); +} + +/** + * @brief Checks whether the specified RTC interrupt has occurred or not. + * @param RTC_INT specifies the RTC interrupt source to check. + * This parameter can be one of the following values: + * @arg RTC_INT_WUT WakeUp Timer interrupt. + * @arg RTC_INT_ALRB Alarm B interrupt. + * @arg RTC_INT_ALRA Alarm A interrupt. + * @return The new state of RTC_INT (SET or RESET). + */ +INTStatus RTC_GetITStatus(uint32_t RTC_INT) +{ + INTStatus bitstatus = RESET; + uint32_t tmpregister = 0, enablestatus = 0; + + /* Check the parameters */ + assert_param(IS_RTC_GET_INT(RTC_INT)); + + /* Get the Interrupt enable Status */ + enablestatus = (uint32_t)((RTC->CTRL & RTC_INT)); + + /* Get the Interrupt pending bit */ + tmpregister = (uint32_t)((RTC->INITSTS & (uint32_t)(RTC_INT >> 4))); + + /* Get the status of the Interrupt */ + if ((enablestatus != (uint32_t)RESET) && ((tmpregister & 0x0000FFFF) != (uint32_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the RTC's interrupt pending bits. + * @param RTC_INT specifies the RTC interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg RTC_INT_WUT WakeUp Timer interrupt + * @arg RTC_INT_ALRB Alarm B interrupt + * @arg RTC_INT_ALRA Alarm A interrupt + */ +void RTC_ClrIntPendingBit(uint32_t RTC_INT) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RTC_CLEAR_INT(RTC_INT)); + + /* Get the RTC_INITSTS Interrupt pending bits mask */ + tmpregister = (uint32_t)(RTC_INT >> 4); + + /* Clear the interrupt pending bits in the RTC_INITSTS register */ + RTC->INITSTS = (uint32_t)( + (uint32_t)(~((tmpregister | RTC_INITSTS_INITM) & 0x0000FFFF) | (uint32_t)(RTC->INITSTS & RTC_INITSTS_INITM))); +} + +/** + * @} + */ + +/** + * @brief Converts a 2 digit decimal to BCD format. + * @param Value Byte to be converted. + * @return Converted byte + */ +static uint8_t RTC_ByteToBcd2(uint8_t Value) +{ + uint8_t bcdhigh = 0; + + while (Value >= 10) + { + bcdhigh++; + Value -= 10; + } + + return ((uint8_t)(bcdhigh << 4) | Value); +} + +/** + * @brief Convert from 2 digit BCD to Binary. + * @param Value BCD value to be converted. + * @return Converted word + */ +static uint8_t RTC_Bcd2ToByte(uint8_t Value) +{ + uint8_t tmp = 0; + tmp = ((uint8_t)(Value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10; + return (tmp + (Value & (uint8_t)0x0F)); +} +/** + * @brief Enable wakeup tsc functionand wakeup by the set time + * @param count wakeup time. + */ +void RTC_EnableWakeUpTsc(uint32_t count) +{ + // Wait until bit RTC_TSCWKUPCTRL_WKUPOFF is 1 + while (!(RTC->TSCWKUPCTRL & RTC_TSCWKUPCTRL_WKUPOFF)) + { + } + // enter config wakeup cnt mode + RTC->TSCWKUPCTRL = RTC_TSCWKUPCTRL_WKUPCNF; + // config tsc wakeup cnt ,tsc wakeup module counting cycle = WAKUPCNT * LSE/LSI + RTC->TSCWKUPCNT = count; + // exit config wakeup cnt mode + RTC->TSCWKUPCTRL &= ~(RTC_TSCWKUPCTRL_WKUPCNF); + while (!(RTC->TSCWKUPCTRL & RTC_TSCWKUPCTRL_WKUPOFF)) + { + } + // TSC wakeup enable + RTC->TSCWKUPCTRL = RTC_TSCWKUPCTRL_WKUPEN; +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_sdio.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_sdio.c new file mode 100644 index 0000000000..7422019172 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_sdio.c @@ -0,0 +1,789 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_sdio.c + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_sdio.h" +#include "n32g4fr_rcc.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup SDIO + * @brief SDIO driver modules + * @{ + */ + +/** @addtogroup SDIO_Private_TypesDefinitions + * @{ + */ + +/* ------------ SDIO registers bit address in the alias region ----------- */ +#define SDIO_OFFSET (SDIO_BASE - PERIPH_BASE) + +/* --- CLKCTRL Register ---*/ + +/* Alias word address of CLKEN bit */ +#define CLKCTRL_OFFSET (SDIO_OFFSET + 0x04) +#define CLKEN_BIT_NUMBER 0x08 +#define CLKCTRL_CLKEN_BB (PERIPH_BB_BASE + (CLKCTRL_OFFSET * 32) + (CLKEN_BIT_NUMBER * 4)) + +/* --- CMDCTRL Register ---*/ + +/* Alias word address of SDIOSUSPEND bit */ +#define CMD_OFFSET (SDIO_OFFSET + 0x0C) +#define SDIO_SUSPEND_BIT_NUMBER 0x0B +#define CMD_SDIO_SUSPEND_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (SDIO_SUSPEND_BIT_NUMBER * 4)) + +/* Alias word address of ENCMDCOMPL bit */ +#define EN_CMD_COMPL_BIT_NUMBER 0x0C +#define EN_CMD_COMPL_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (EN_CMD_COMPL_BIT_NUMBER * 4)) + +/* Alias word address of NIEN bit */ +#define NIEN_BIT_NUMBER 0x0D +#define CMD_NIEN_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (NIEN_BIT_NUMBER * 4)) + +/* Alias word address of ATACMD bit */ +#define ATACMD_BIT_NUMBER 0x0E +#define CMD_ATACMD_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (ATACMD_BIT_NUMBER * 4)) + +/* --- DATCTRL Register ---*/ + +/* Alias word address of DMAEN bit */ +#define DCTRL_OFFSET (SDIO_OFFSET + 0x2C) +#define DMAEN_BIT_NUMBER 0x03 +#define DCTRL_DMAEN_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (DMAEN_BIT_NUMBER * 4)) + +/* Alias word address of RWSTART bit */ +#define RWSTART_BIT_NUMBER 0x08 +#define DCTRL_RWSTART_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWSTART_BIT_NUMBER * 4)) + +/* Alias word address of RWSTOP bit */ +#define RWSTOP_BIT_NUMBER 0x09 +#define DCTRL_RWSTOP_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWSTOP_BIT_NUMBER * 4)) + +/* Alias word address of RWMOD bit */ +#define RWMOD_BIT_NUMBER 0x0A +#define DCTRL_RWMOD_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWMOD_BIT_NUMBER * 4)) + +/* Alias word address of SDIOEN bit */ +#define SDIOEN_BIT_NUMBER 0x0B +#define DCTRL_SDIOEN_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (SDIOEN_BIT_NUMBER * 4)) + +/* ---------------------- SDIO registers bit mask ------------------------ */ + +/* --- CLKCTRL Register ---*/ + +/* CLKCTRL register clear mask */ +#define CLKCTRL_CLR_MASK ((uint32_t)0xFFFF8100) + +/* --- PWRCTRL Register ---*/ + +/* SDIO PWRCTRL Mask */ +#define POWER_PWRCTRL_MASK ((uint32_t)0xFFFFFFFC) + +/* --- DATCTRL Register ---*/ + +/* SDIO DATCTRL Clear Mask */ +#define DATCTRL_CLR_MASK ((uint32_t)0xFFFFFF08) + +/* --- CMDCTRL Register ---*/ + +/* CMDCTRL Register clear mask */ +#define CMD_CLR_MASK ((uint32_t)0xFFFFF800) + +/* SDIO RESP Registers Address */ +#define SDID_RESPONSE_ADDR ((uint32_t)(SDIO_BASE + 0x14)) + +/** + * @} + */ + +/** @addtogroup SDIO_Private_Defines + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SDIO_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SDIO_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SDIO_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SDIO_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the SDIO peripheral registers to their default reset values. + */ +void SDIO_DeInit(void) +{ + SDIO->PWRCTRL = 0x00000000; + SDIO->CLKCTRL = 0x00000000; + SDIO->CMDARG = 0x00000000; + SDIO->CMDCTRL = 0x00000000; + SDIO->DTIMER = 0x00000000; + SDIO->DATLEN = 0x00000000; + SDIO->DATCTRL = 0x00000000; + SDIO->INTCLR = 0x00C007FF; + SDIO->INTEN = 0x00000000; +} + +/** + * @brief Initializes the SDIO peripheral according to the specified + * parameters in the SDIO_InitStruct. + * @param SDIO_InitStruct pointer to a SDIO_InitType structure + * that contains the configuration information for the SDIO peripheral. + */ +void SDIO_Init(SDIO_InitType* SDIO_InitStruct) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_CLK_EDGE(SDIO_InitStruct->ClkEdge)); + assert_param(IS_SDIO_CLK_BYPASS(SDIO_InitStruct->ClkBypass)); + assert_param(IS_SDIO_CLK_POWER_SAVE(SDIO_InitStruct->ClkPwrSave)); + assert_param(IS_SDIO_BUS_WIDTH(SDIO_InitStruct->BusWidth)); + assert_param(IS_SDIO_HARDWARE_CLKCTRL(SDIO_InitStruct->HardwareClkCtrl)); + + /*---------------------------- SDIO CLKCTRL Configuration ------------------------*/ + /* Get the SDIO CLKCTRL value */ + tmpregister = SDIO->CLKCTRL; + + /* Clear CLKDIV, PWRSAV, BYPASS, WIDBUS, NEGEDGE, HWFC_EN bits */ + tmpregister &= CLKCTRL_CLR_MASK; + + /* Set CLKDIV bits according to ClkDiv value */ + /* Set PWRSAV bit according to ClkPwrSave value */ + /* Set BYPASS bit according to ClkBypass value */ + /* Set WIDBUS bits according to BusWidth value */ + /* Set NEGEDGE bits according to ClkEdge value */ + /* Set HWFC_EN bits according to HardwareClkCtrl value */ + tmpregister |= (SDIO_InitStruct->ClkDiv | SDIO_InitStruct->ClkPwrSave | SDIO_InitStruct->ClkBypass + | SDIO_InitStruct->BusWidth | SDIO_InitStruct->ClkEdge | SDIO_InitStruct->HardwareClkCtrl); + + /* Write to SDIO CLKCTRL */ + SDIO->CLKCTRL = tmpregister; +} + +/** + * @brief Fills each SDIO_InitStruct member with its default value. + * @param SDIO_InitStruct pointer to an SDIO_InitType structure which + * will be initialized. + */ +void SDIO_InitStruct(SDIO_InitType* SDIO_InitStruct) +{ + /* SDIO_InitStruct members default value */ + SDIO_InitStruct->ClkDiv = 0x00; + SDIO_InitStruct->ClkEdge = SDIO_CLKEDGE_RISING; + SDIO_InitStruct->ClkBypass = SDIO_ClkBYPASS_DISABLE; + SDIO_InitStruct->ClkPwrSave = SDIO_CLKPOWERSAVE_DISABLE; + SDIO_InitStruct->BusWidth = SDIO_BUSWIDTH_1B; + SDIO_InitStruct->HardwareClkCtrl = SDIO_HARDWARE_CLKCTRL_DISABLE; +} + +/** + * @brief Enables or disables the SDIO Clock. + * @param Cmd new state of the SDIO Clock. This parameter can be: ENABLE or DISABLE. + */ +void SDIO_EnableClock(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)CLKCTRL_CLKEN_BB = (uint32_t)Cmd; +} + +/** + * @brief Sets the power status of the controller. + * @param SDIO_PowerState new state of the Power state. + * This parameter can be one of the following values: + * @arg SDIO_POWER_CTRL_OFF + * @arg SDIO_POWER_CTRL_ON + */ +void SDIO_SetPower(uint32_t SDIO_PowerState) +{ + /* Check the parameters */ + assert_param(IS_SDIO_POWER_CTRL(SDIO_PowerState)); + + SDIO->PWRCTRL &= POWER_PWRCTRL_MASK; + SDIO->PWRCTRL |= SDIO_PowerState; +} + +/** + * @brief Gets the power status of the controller. + * @return Power status of the controller. The returned value can + * be one of the following: + * - 0x00: Power OFF + * - 0x02: Power UP + * - 0x03: Power ON + */ +uint32_t SDIO_GetPower(void) +{ + return (SDIO->PWRCTRL & (~POWER_PWRCTRL_MASK)); +} + +/** + * @brief Enables or disables the SDIO interrupts. + * @param SDIO_IT specifies the SDIO interrupt sources to be enabled or disabled. + * This parameter can be one or a combination of the following values: + * @arg SDIO_INT_CCRCERR Command response received (CRC check failed) interrupt + * @arg SDIO_INT_DCRCERR Data block sent/received (CRC check failed) interrupt + * @arg SDIO_INT_CMDTIMEOUT Command response timeout interrupt + * @arg SDIO_INT_DATTIMEOUT Data timeout interrupt + * @arg SDIO_INT_TXURERR Transmit DATFIFO underrun error interrupt + * @arg SDIO_INT_RXORERR Received DATFIFO overrun error interrupt + * @arg SDIO_INT_CMDRESPRECV Command response received (CRC check passed) interrupt + * @arg SDIO_INT_CMDSEND Command sent (no response required) interrupt + * @arg SDIO_INT_DATEND Data end (data counter, SDIDCOUNT, is zero) interrupt + * @arg SDIO_INT_SBERR Start bit not detected on all data signals in wide + * bus mode interrupt + * @arg SDIO_INT_DATBLKEND Data block sent/received (CRC check passed) interrupt + * @arg SDIO_INT_CMDRUN Command transfer in progress interrupt + * @arg SDIO_INT_TXRUN Data transmit in progress interrupt + * @arg SDIO_INT_RXRUN Data receive in progress interrupt + * @arg SDIO_INT_TFIFOHE Transmit DATFIFO Half Empty interrupt + * @arg SDIO_INT_RFIFOHF Receive DATFIFO Half Full interrupt + * @arg SDIO_INT_TFIFOF Transmit DATFIFO full interrupt + * @arg SDIO_INT_RFIFOF Receive DATFIFO full interrupt + * @arg SDIO_INT_TFIFOE Transmit DATFIFO empty interrupt + * @arg SDIO_INT_RFIFOE Receive DATFIFO empty interrupt + * @arg SDIO_INT_TDATVALID Data available in transmit DATFIFO interrupt + * @arg SDIO_INT_RDATVALID Data available in receive DATFIFO interrupt + * @arg SDIO_INT_SDIOINT SD I/O interrupt received interrupt + * @arg SDIO_INT_CEATAF CE-ATA command completion signal received for CMD61 interrupt + * @param Cmd new state of the specified SDIO interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void SDIO_ConfigInt(uint32_t SDIO_IT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_SDIO_INT(SDIO_IT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the SDIO interrupts */ + SDIO->INTEN |= SDIO_IT; + } + else + { + /* Disable the SDIO interrupts */ + SDIO->INTEN &= ~SDIO_IT; + } +} + +/** + * @brief Enables or disables the SDIO DMA request. + * @param Cmd new state of the selected SDIO DMA request. + * This parameter can be: ENABLE or DISABLE. + */ +void SDIO_DMACmd(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)DCTRL_DMAEN_BB = (uint32_t)Cmd; +} + +/** + * @brief Initializes the SDIO Command according to the specified + * parameters in the SDIO_CmdInitStruct and send the command. + * @param SDIO_CmdInitStruct pointer to a SDIO_CmdInitType + * structure that contains the configuration information for the SDIO command. + */ +void SDIO_SendCmd(SDIO_CmdInitType* SDIO_CmdInitStruct) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_CMD_INDEX(SDIO_CmdInitStruct->CmdIndex)); + assert_param(IS_SDIO_RESP(SDIO_CmdInitStruct->ResponseType)); + assert_param(IS_SDIO_WAIT(SDIO_CmdInitStruct->WaitType)); + assert_param(IS_SDIO_CPSM(SDIO_CmdInitStruct->CPSMConfig)); + + /*---------------------------- SDIO CMDARG Configuration ------------------------*/ + /* Set the SDIO Argument value */ + SDIO->CMDARG = SDIO_CmdInitStruct->CmdArgument; + + /*---------------------------- SDIO CMDCTRL Configuration ------------------------*/ + /* Get the SDIO CMDCTRL value */ + tmpregister = SDIO->CMDCTRL; + /* Clear CMDINDEX, WAITRESP, WAITINT, WAITPEND, CPSMEN bits */ + tmpregister &= CMD_CLR_MASK; + /* Set CMDINDEX bits according to CmdIndex value */ + /* Set WAITRESP bits according to ResponseType value */ + /* Set WAITINT and WAITPEND bits according to WaitType value */ + /* Set CPSMEN bits according to CPSMConfig value */ + tmpregister |= (uint32_t)SDIO_CmdInitStruct->CmdIndex | SDIO_CmdInitStruct->ResponseType + | SDIO_CmdInitStruct->WaitType | SDIO_CmdInitStruct->CPSMConfig; + + /* Write to SDIO CMDCTRL */ + SDIO->CMDCTRL = tmpregister; +} + +/** + * @brief Fills each SDIO_CmdInitStruct member with its default value. + * @param SDIO_CmdInitStruct pointer to an SDIO_CmdInitType + * structure which will be initialized. + */ +void SDIO_InitCmdStruct(SDIO_CmdInitType* SDIO_CmdInitStruct) +{ + /* SDIO_CmdInitStruct members default value */ + SDIO_CmdInitStruct->CmdArgument = 0x00; + SDIO_CmdInitStruct->CmdIndex = 0x00; + SDIO_CmdInitStruct->ResponseType = SDIO_RESP_NO; + SDIO_CmdInitStruct->WaitType = SDIO_WAIT_NO; + SDIO_CmdInitStruct->CPSMConfig = SDIO_CPSM_DISABLE; +} + +/** + * @brief Returns command index of last command for which response received. + * @return Returns the command index of the last command response received. + */ +uint8_t SDIO_GetCmdResp(void) +{ + return (uint8_t)(SDIO->CMDRESP); +} + +/** + * @brief Returns response received from the card for the last command. + * @param SDIO_RESP Specifies the SDIO response register. + * This parameter can be one of the following values: + * @arg SDIO_RESPONSE_1 Response Register 1 + * @arg SDIO_RESPONSE_2 Response Register 2 + * @arg SDIO_RESPONSE_3 Response Register 3 + * @arg SDIO_RESPONSE_4 Response Register 4 + * @return The Corresponding response register value. + */ +uint32_t SDIO_GetResp(uint32_t SDIO_RESP) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_RESPONSE(SDIO_RESP)); + + tmp = SDID_RESPONSE_ADDR + SDIO_RESP; + + return (*(__IO uint32_t*)tmp); +} + +/** + * @brief Initializes the SDIO data path according to the specified + * parameters in the SDIO_DataInitStruct. + * @param SDIO_DataInitStruct pointer to a SDIO_DataInitType structure that + * contains the configuration information for the SDIO command. + */ +void SDIO_ConfigData(SDIO_DataInitType* SDIO_DataInitStruct) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_DAT_LEN(SDIO_DataInitStruct->DatLen)); + assert_param(IS_SDIO_BLK_SIZE(SDIO_DataInitStruct->DatBlkSize)); + assert_param(IS_SDIO_TRANSFER_DIRECTION(SDIO_DataInitStruct->TransferDirection)); + assert_param(IS_SDIO_TRANS_MODE(SDIO_DataInitStruct->TransferMode)); + assert_param(IS_SDIO_DPSM(SDIO_DataInitStruct->DPSMConfig)); + + /*---------------------------- SDIO DATTIMEOUT Configuration ---------------------*/ + /* Set the SDIO Data TimeOut value */ + SDIO->DTIMER = SDIO_DataInitStruct->DatTimeout; + + /*---------------------------- SDIO DATLEN Configuration -----------------------*/ + /* Set the SDIO DataLength value */ + SDIO->DATLEN = SDIO_DataInitStruct->DatLen; + + /*---------------------------- SDIO DATCTRL Configuration ----------------------*/ + /* Get the SDIO DATCTRL value */ + tmpregister = SDIO->DATCTRL; + /* Clear DEN, DTMODE, DTDIR and DBCKSIZE bits */ + tmpregister &= DATCTRL_CLR_MASK; + /* Set DEN bit according to DPSMConfig value */ + /* Set DTMODE bit according to TransferMode value */ + /* Set DTDIR bit according to TransferDirection value */ + /* Set DBCKSIZE bits according to DatBlkSize value */ + tmpregister |= (uint32_t)SDIO_DataInitStruct->DatBlkSize | SDIO_DataInitStruct->TransferDirection + | SDIO_DataInitStruct->TransferMode | SDIO_DataInitStruct->DPSMConfig; + + if(SDIO_DataInitStruct->TransferDirection) + { + tmpregister &= ~(1<<12); + } + else + { + tmpregister |= 1<<12; + } + + /* Write to SDIO DATCTRL */ + SDIO->DATCTRL = tmpregister; +} + +/** + * @brief Fills each SDIO_DataInitStruct member with its default value. + * @param SDIO_DataInitStruct pointer to an SDIO_DataInitType structure which + * will be initialized. + */ +void SDIO_InitDataStruct(SDIO_DataInitType* SDIO_DataInitStruct) +{ + /* SDIO_DataInitStruct members default value */ + SDIO_DataInitStruct->DatTimeout = 0xFFFFFFFF; + SDIO_DataInitStruct->DatLen = 0x00; + SDIO_DataInitStruct->DatBlkSize = SDIO_DATBLK_SIZE_1B; + SDIO_DataInitStruct->TransferDirection = SDIO_TRANSDIR_TOCARD; + SDIO_DataInitStruct->TransferMode = SDIO_TRANSMODE_BLOCK; + SDIO_DataInitStruct->DPSMConfig = SDIO_DPSM_DISABLE; +} + +/** + * @brief Returns number of remaining data bytes to be transferred. + * @return Number of remaining data bytes to be transferred + */ +uint32_t SDIO_GetDataCountValue(void) +{ + return SDIO->DATCOUNT; +} + +/** + * @brief Read one data word from Rx DATFIFO. + * @return Data received + */ +uint32_t SDIO_ReadData(void) +{ + return SDIO->DATFIFO; +} + +/** + * @brief Write one data word to Tx DATFIFO. + * @param Data 32-bit data word to write. + */ +void SDIO_WriteData(uint32_t Data) +{ + SDIO->DATFIFO = Data; +} + +/** + * @brief Returns the number of words left to be written to or read from DATFIFO. + * @return Remaining number of words. + */ +uint32_t SDIO_GetFifoCounter(void) +{ + return SDIO->FIFOCOUNT; +} + +/** + * @brief Starts the SD I/O Read Wait operation. + * @param Cmd new state of the Start SDIO Read Wait operation. + * This parameter can be: ENABLE or DISABLE. + */ +void SDIO_EnableReadWait(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)DCTRL_RWSTART_BB = (uint32_t)Cmd; +} + +/** + * @brief Stops the SD I/O Read Wait operation. + * @param Cmd new state of the Stop SDIO Read Wait operation. + * This parameter can be: ENABLE or DISABLE. + */ +void SDIO_DisableReadWait(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)DCTRL_RWSTOP_BB = (uint32_t)Cmd; +} + +/** + * @brief Sets one of the two options of inserting read wait interval. + * @param SDIO_ReadWaitMode SD I/O Read Wait operation mode. + * This parameter can be: + * @arg SDIO_RDWAIT_MODE_CLK Read Wait control by stopping SDIOCLK + * @arg SDIO_RDWAIT_MODE_DAT2 Read Wait control using SDIO_DATA2 + */ +void SDIO_EnableSdioReadWaitMode(uint32_t SDIO_ReadWaitMode) +{ + /* Check the parameters */ + assert_param(IS_SDIO_RDWAIT_MODE(SDIO_ReadWaitMode)); + + *(__IO uint32_t*)DCTRL_RWMOD_BB = SDIO_ReadWaitMode; +} + +/** + * @brief Enables or disables the SD I/O Mode Operation. + * @param Cmd new state of SDIO specific operation. + * This parameter can be: ENABLE or DISABLE. + */ +void SDIO_EnableSdioOperation(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)DCTRL_SDIOEN_BB = (uint32_t)Cmd; +} + +/** + * @brief Enables or disables the SD I/O Mode suspend command sending. + * @param Cmd new state of the SD I/O Mode suspend command. + * This parameter can be: ENABLE or DISABLE. + */ +void SDIO_EnableSendSdioSuspend(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)CMD_SDIO_SUSPEND_BB = (uint32_t)Cmd; +} + +/** + * @brief Enables or disables the command completion signal. + * @param Cmd new state of command completion signal. + * This parameter can be: ENABLE or DISABLE. + */ +void SDIO_EnableCommandCompletion(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)EN_CMD_COMPL_BB = (uint32_t)Cmd; +} + +/** + * @brief Enables or disables the CE-ATA interrupt. + * @param Cmd new state of CE-ATA interrupt. This parameter can be: ENABLE or DISABLE. + */ +void SDIO_EnableCEATAInt(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)CMD_NIEN_BB = (uint32_t)((~((uint32_t)Cmd)) & ((uint32_t)0x1)); +} + +/** + * @brief Sends CE-ATA command (CMD61). + * @param Cmd new state of CE-ATA command. This parameter can be: ENABLE or DISABLE. + */ +void SDIO_EnableSendCEATA(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)CMD_ATACMD_BB = (uint32_t)Cmd; +} + +/** + * @brief Checks whether the specified SDIO flag is set or not. + * @param SDIO_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg SDIO_FLAG_CCRCERR Command response received (CRC check failed) + * @arg SDIO_FLAG_DCRCERR Data block sent/received (CRC check failed) + * @arg SDIO_FLAG_CMDTIMEOUT Command response timeout + * @arg SDIO_FLAG_DATTIMEOUT Data timeout + * @arg SDIO_FLAG_TXURERR Transmit DATFIFO underrun error + * @arg SDIO_FLAG_RXORERR Received DATFIFO overrun error + * @arg SDIO_FLAG_CMDRESPRECV Command response received (CRC check passed) + * @arg SDIO_FLAG_CMDSEND Command sent (no response required) + * @arg SDIO_FLAG_DATEND Data end (data counter, SDIDCOUNT, is zero) + * @arg SDIO_FLAG_SBERR Start bit not detected on all data signals in wide + * bus mode. + * @arg SDIO_FLAG_DATBLKEND Data block sent/received (CRC check passed) + * @arg SDIO_FLAG_CMDRUN Command transfer in progress + * @arg SDIO_FLAG_TXRUN Data transmit in progress + * @arg SDIO_FLAG_RXRUN Data receive in progress + * @arg SDIO_FLAG_TFIFOHE Transmit DATFIFO Half Empty + * @arg SDIO_FLAG_RFIFOHF Receive DATFIFO Half Full + * @arg SDIO_FLAG_TFIFOF Transmit DATFIFO full + * @arg SDIO_FLAG_RFIFOF Receive DATFIFO full + * @arg SDIO_FLAG_TFIFOE Transmit DATFIFO empty + * @arg SDIO_FLAG_RFIFOE Receive DATFIFO empty + * @arg SDIO_FLAG_TDATVALID Data available in transmit DATFIFO + * @arg SDIO_FLAG_RDATVALID Data available in receive DATFIFO + * @arg SDIO_FLAG_SDIOINT SD I/O interrupt received + * @arg SDIO_FLAG_CEATAF CE-ATA command completion signal received for CMD61 + * @return The new state of SDIO_FLAG (SET or RESET). + */ +FlagStatus SDIO_GetFlag(uint32_t SDIO_FLAG) +{ + FlagStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_SDIO_FLAG(SDIO_FLAG)); + + if ((SDIO->STS & SDIO_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the SDIO's pending flags. + * @param SDIO_FLAG specifies the flag to clear. + * This parameter can be one or a combination of the following values: + * @arg SDIO_FLAG_CCRCERR Command response received (CRC check failed) + * @arg SDIO_FLAG_DCRCERR Data block sent/received (CRC check failed) + * @arg SDIO_FLAG_CMDTIMEOUT Command response timeout + * @arg SDIO_FLAG_DATTIMEOUT Data timeout + * @arg SDIO_FLAG_TXURERR Transmit DATFIFO underrun error + * @arg SDIO_FLAG_RXORERR Received DATFIFO overrun error + * @arg SDIO_FLAG_CMDRESPRECV Command response received (CRC check passed) + * @arg SDIO_FLAG_CMDSEND Command sent (no response required) + * @arg SDIO_FLAG_DATEND Data end (data counter, SDIDCOUNT, is zero) + * @arg SDIO_FLAG_SBERR Start bit not detected on all data signals in wide + * bus mode + * @arg SDIO_FLAG_DATBLKEND Data block sent/received (CRC check passed) + * @arg SDIO_FLAG_SDIOINT SD I/O interrupt received + * @arg SDIO_FLAG_CEATAF CE-ATA command completion signal received for CMD61 + */ +void SDIO_ClrFlag(uint32_t SDIO_FLAG) +{ + /* Check the parameters */ + assert_param(IS_SDIO_CLR_FLAG(SDIO_FLAG)); + + SDIO->INTCLR = SDIO_FLAG; +} + +/** + * @brief Checks whether the specified SDIO interrupt has occurred or not. + * @param SDIO_IT specifies the SDIO interrupt source to check. + * This parameter can be one of the following values: + * @arg SDIO_INT_CCRCERR Command response received (CRC check failed) interrupt + * @arg SDIO_INT_DCRCERR Data block sent/received (CRC check failed) interrupt + * @arg SDIO_INT_CMDTIMEOUT Command response timeout interrupt + * @arg SDIO_INT_DATTIMEOUT Data timeout interrupt + * @arg SDIO_INT_TXURERR Transmit DATFIFO underrun error interrupt + * @arg SDIO_INT_RXORERR Received DATFIFO overrun error interrupt + * @arg SDIO_INT_CMDRESPRECV Command response received (CRC check passed) interrupt + * @arg SDIO_INT_CMDSEND Command sent (no response required) interrupt + * @arg SDIO_INT_DATEND Data end (data counter, SDIDCOUNT, is zero) interrupt + * @arg SDIO_INT_SBERR Start bit not detected on all data signals in wide + * bus mode interrupt + * @arg SDIO_INT_DATBLKEND Data block sent/received (CRC check passed) interrupt + * @arg SDIO_INT_CMDRUN Command transfer in progress interrupt + * @arg SDIO_INT_TXRUN Data transmit in progress interrupt + * @arg SDIO_INT_RXRUN Data receive in progress interrupt + * @arg SDIO_INT_TFIFOHE Transmit DATFIFO Half Empty interrupt + * @arg SDIO_INT_RFIFOHF Receive DATFIFO Half Full interrupt + * @arg SDIO_INT_TFIFOF Transmit DATFIFO full interrupt + * @arg SDIO_INT_RFIFOF Receive DATFIFO full interrupt + * @arg SDIO_INT_TFIFOE Transmit DATFIFO empty interrupt + * @arg SDIO_INT_RFIFOE Receive DATFIFO empty interrupt + * @arg SDIO_INT_TDATVALID Data available in transmit DATFIFO interrupt + * @arg SDIO_INT_RDATVALID Data available in receive DATFIFO interrupt + * @arg SDIO_INT_SDIOINT SD I/O interrupt received interrupt + * @arg SDIO_INT_CEATAF CE-ATA command completion signal received for CMD61 interrupt + * @return The new state of SDIO_IT (SET or RESET). + */ +INTStatus SDIO_GetIntStatus(uint32_t SDIO_IT) +{ + INTStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_SDIO_GET_INT(SDIO_IT)); + if ((SDIO->STS & SDIO_IT) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the SDIO's interrupt pending bits. + * @param SDIO_IT specifies the interrupt pending bit to clear. + * This parameter can be one or a combination of the following values: + * @arg SDIO_INT_CCRCERR Command response received (CRC check failed) interrupt + * @arg SDIO_INT_DCRCERR Data block sent/received (CRC check failed) interrupt + * @arg SDIO_INT_CMDTIMEOUT Command response timeout interrupt + * @arg SDIO_INT_DATTIMEOUT Data timeout interrupt + * @arg SDIO_INT_TXURERR Transmit DATFIFO underrun error interrupt + * @arg SDIO_INT_RXORERR Received DATFIFO overrun error interrupt + * @arg SDIO_INT_CMDRESPRECV Command response received (CRC check passed) interrupt + * @arg SDIO_INT_CMDSEND Command sent (no response required) interrupt + * @arg SDIO_INT_DATEND Data end (data counter, SDIDCOUNT, is zero) interrupt + * @arg SDIO_INT_SBERR Start bit not detected on all data signals in wide + * bus mode interrupt + * @arg SDIO_INT_SDIOINT SD I/O interrupt received interrupt + * @arg SDIO_INT_CEATAF CE-ATA command completion signal received for CMD61 + */ +void SDIO_ClrIntPendingBit(uint32_t SDIO_IT) +{ + /* Check the parameters */ + assert_param(IS_SDIO_CLR_INT(SDIO_IT)); + + SDIO->INTCLR = SDIO_IT; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_spi.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_spi.c new file mode 100644 index 0000000000..93b2ff2ef0 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_spi.c @@ -0,0 +1,862 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_spi.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_spi.h" +#include "n32g4fr_rcc.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup SPI + * @brief SPI driver modules + * @{ + */ + +/** @addtogroup SPI_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SPI_Private_Defines + * @{ + */ + +/* SPI SPE mask */ +#define CTRL1_SPIEN_ENABLE ((uint16_t)0x0040) +#define CTRL1_SPIEN_DISABLE ((uint16_t)0xFFBF) + +/* I2S I2SE mask */ +#define I2SCFG_I2SEN_ENABLE ((uint16_t)0x0400) +#define I2SCFG_I2SEN_DISABLE ((uint16_t)0xFBFF) + +/* SPI CRCNext mask */ +#define CTRL1_CRCNEXT_ENABLE ((uint16_t)0x1000) + +/* SPI CRCEN mask */ +#define CTRL1_CRCEN_ENABLE ((uint16_t)0x2000) +#define CTRL1_CRCEN_DISABLE ((uint16_t)0xDFFF) + +/* SPI SSOE mask */ +#define CTRL2_SSOEN_ENABLE ((uint16_t)0x0004) +#define CTRL2_SSOEN_DISABLE ((uint16_t)0xFFFB) + +/* SPI registers Masks */ +#define CTRL1_CLR_MASK ((uint16_t)0x3040) +#define I2SCFG_CLR_MASK ((uint16_t)0xF040) + +/* SPI or I2S mode selection masks */ +#define SPI_MODE_ENABLE ((uint16_t)0xF7FF) +#define I2S_MODE_ENABLE ((uint16_t)0x0800) + +/* I2S clock source selection masks */ +#define I2S2_CLKSRC ((uint32_t)(0x00020000)) +#define I2S3_CLKSRC ((uint32_t)(0x00040000)) +#define I2S_MUL_MASK ((uint32_t)(0x0000F000)) +#define I2S_DIV_MASK ((uint32_t)(0x000000F0)) + +/** + * @} + */ + +/** @addtogroup SPI_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SPI_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SPI_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SPI_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the SPIx peripheral registers to their default + * reset values (Affects also the I2Ss). + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + */ +void SPI_I2S_DeInit(SPI_Module* SPIx) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + + if (SPIx == SPI1) + { + /* Enable SPI1 reset state */ + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_SPI1, ENABLE); + /* Release SPI1 from reset state */ + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_SPI1, DISABLE); + } + else if (SPIx == SPI2) + { + /* Enable SPI2 reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_SPI2, ENABLE); + /* Release SPI2 from reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_SPI2, DISABLE); + } + else + { + if (SPIx == SPI3) + { + /* Enable SPI3 reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_SPI3, ENABLE); + /* Release SPI3 from reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_SPI3, DISABLE); + } + } +} + +/** + * @brief Initializes the SPIx peripheral according to the specified + * parameters in the SPI_InitStruct. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @param SPI_InitStruct pointer to a SPI_InitType structure that + * contains the configuration information for the specified SPI peripheral. + */ +void SPI_Init(SPI_Module* SPIx, SPI_InitType* SPI_InitStruct) +{ + uint16_t tmpregister = 0; + + /* check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + + /* Check the SPI parameters */ + assert_param(IS_SPI_DIR_MODE(SPI_InitStruct->DataDirection)); + assert_param(IS_SPI_MODE(SPI_InitStruct->SpiMode)); + assert_param(IS_SPI_DATASIZE(SPI_InitStruct->DataLen)); + assert_param(IS_SPI_CLKPOL(SPI_InitStruct->CLKPOL)); + assert_param(IS_SPI_CLKPHA(SPI_InitStruct->CLKPHA)); + assert_param(IS_SPI_NSS(SPI_InitStruct->NSS)); + assert_param(IS_SPI_BR_PRESCALER(SPI_InitStruct->BaudRatePres)); + assert_param(IS_SPI_FIRST_BIT(SPI_InitStruct->FirstBit)); + assert_param(IS_SPI_CRC_POLYNOMIAL(SPI_InitStruct->CRCPoly)); + + /*---------------------------- SPIx CTRL1 Configuration ------------------------*/ + /* Get the SPIx CTRL1 value */ + tmpregister = SPIx->CTRL1; + /* Clear BIDIMode, BIDIOE, RxONLY, SSM, SSI, LSBFirst, BR, MSTR, CPOL and CPHA bits */ + tmpregister &= CTRL1_CLR_MASK; + /* Configure SPIx: direction, NSS management, first transmitted bit, BaudRate prescaler + master/salve mode, CPOL and CPHA */ + /* Set BIDImode, BIDIOE and RxONLY bits according to DataDirection value */ + /* Set SSM, SSI and MSTR bits according to SpiMode and NSS values */ + /* Set LSBFirst bit according to FirstBit value */ + /* Set BR bits according to BaudRatePres value */ + /* Set CPOL bit according to CLKPOL value */ + /* Set CPHA bit according to CLKPHA value */ + tmpregister |= (uint16_t)((uint32_t)SPI_InitStruct->DataDirection | SPI_InitStruct->SpiMode + | SPI_InitStruct->DataLen | SPI_InitStruct->CLKPOL | SPI_InitStruct->CLKPHA + | SPI_InitStruct->NSS | SPI_InitStruct->BaudRatePres | SPI_InitStruct->FirstBit); + /* Write to SPIx CTRL1 */ + SPIx->CTRL1 = tmpregister; + + /* Activate the SPI mode (Reset I2SMOD bit in I2SCFG register) */ + SPIx->I2SCFG &= SPI_MODE_ENABLE; + + /*---------------------------- SPIx CRCPOLY Configuration --------------------*/ + /* Write to SPIx CRCPOLY */ + SPIx->CRCPOLY = SPI_InitStruct->CRCPoly; +} + +/** + * @brief Initializes the SPIx peripheral according to the specified + * parameters in the I2S_InitStruct. + * @param SPIx where x can be 2 or 3 to select the SPI peripheral + * (configured in I2S mode). + * @param I2S_InitStruct pointer to an I2S_InitType structure that + * contains the configuration information for the specified SPI peripheral + * configured in I2S mode. + * @note + * The function calculates the optimal prescaler needed to obtain the most + * accurate audio frequency (depending on the I2S clock source, the PLL values + * and the product configuration). But in case the prescaler value is greater + * than 511, the default value (0x02) will be configured instead. * + */ +void I2S_Init(SPI_Module* SPIx, I2S_InitType* I2S_InitStruct) +{ + uint16_t tmpregister = 0, i2sdiv = 2, i2sodd = 0, packetlength = 1; + uint32_t tmp = 0; + RCC_ClocksType RCC_Clocks; + uint32_t sourceclock = 0; + + /* Check the I2S parameters */ + assert_param(IS_SPI_2OR3_PERIPH(SPIx)); + assert_param(IS_I2S_MODE(I2S_InitStruct->I2sMode)); + assert_param(IS_I2S_STANDARD(I2S_InitStruct->Standard)); + assert_param(IS_I2S_DATA_FMT(I2S_InitStruct->DataFormat)); + assert_param(IS_I2S_MCLK_ENABLE(I2S_InitStruct->MCLKEnable)); + assert_param(IS_I2S_AUDIO_FREQ(I2S_InitStruct->AudioFrequency)); + assert_param(IS_I2S_CLKPOL(I2S_InitStruct->CLKPOL)); + + /*----------------------- SPIx I2SCFG & I2SPREDIV Configuration -----------------*/ + /* Clear I2SMOD, I2SE, MODCFG, PCMSYNC, STDSEL, CKPOL, TDATLEN and CHLEN bits */ + SPIx->I2SCFG &= I2SCFG_CLR_MASK; + SPIx->I2SPREDIV = 0x0002; + + /* Get the I2SCFG register value */ + tmpregister = SPIx->I2SCFG; + + /* If the default value has to be written, reinitialize i2sdiv and i2sodd*/ + if (I2S_InitStruct->AudioFrequency == I2S_AUDIO_FREQ_DEFAULT) + { + i2sodd = (uint16_t)0; + i2sdiv = (uint16_t)2; + } + /* If the requested audio frequency is not the default, compute the prescaler */ + else + { + /* Check the frame length (For the Prescaler computing) */ + if (I2S_InitStruct->DataFormat == I2S_DATA_FMT_16BITS) + { + /* Packet length is 16 bits */ + packetlength = 1; + } + else + { + /* Packet length is 32 bits */ + packetlength = 2; + } + + /* Get the I2S clock source mask depending on the peripheral number */ + if (((uint32_t)SPIx) == SPI2_BASE) + { + /* The mask is relative to I2S2 */ + tmp = I2S2_CLKSRC; + } + else + { + /* The mask is relative to I2S3 */ + tmp = I2S3_CLKSRC; + } + + /* I2S Clock source is System clock: Get System Clock frequency */ + RCC_GetClocksFreqValue(&RCC_Clocks); + + /* Get the source clock value: based on System Clock value */ + sourceclock = RCC_Clocks.SysclkFreq; + + /* Compute the Real divider depending on the MCLK output state with a floating point */ + if (I2S_InitStruct->MCLKEnable == I2S_MCLK_ENABLE) + { + /* MCLK output is enabled */ + tmp = (uint16_t)(((((sourceclock / 256) * 10) / I2S_InitStruct->AudioFrequency)) + 5); + } + else + { + /* MCLK output is disabled */ + tmp = (uint16_t)(((((sourceclock / (32 * packetlength)) * 10) / I2S_InitStruct->AudioFrequency)) + 5); + } + + /* Remove the floating point */ + tmp = tmp / 10; + + /* Check the parity of the divider */ + i2sodd = (uint16_t)(tmp & (uint16_t)0x0001); + + /* Compute the i2sdiv prescaler */ + i2sdiv = (uint16_t)((tmp - i2sodd) / 2); + + /* Get the Mask for the Odd bit (SPI_I2SPREDIV[8]) register */ + i2sodd = (uint16_t)(i2sodd << 8); + } + + /* Test if the divider is 1 or 0 or greater than 0xFF */ + if ((i2sdiv < 2) || (i2sdiv > 0xFF)) + { + /* Set the default values */ + i2sdiv = 2; + i2sodd = 0; + } + + /* Write to SPIx I2SPREDIV register the computed value */ + SPIx->I2SPREDIV = (uint16_t)(i2sdiv | (uint16_t)(i2sodd | (uint16_t)I2S_InitStruct->MCLKEnable)); + + /* Configure the I2S with the SPI_InitStruct values */ + tmpregister |= (uint16_t)( + I2S_MODE_ENABLE + | (uint16_t)(I2S_InitStruct->I2sMode + | (uint16_t)(I2S_InitStruct->Standard + | (uint16_t)(I2S_InitStruct->DataFormat | (uint16_t)I2S_InitStruct->CLKPOL)))); + + /* Write to SPIx I2SCFG */ + SPIx->I2SCFG = tmpregister; +} + +/** + * @brief Fills each SPI_InitStruct member with its default value. + * @param SPI_InitStruct pointer to a SPI_InitType structure which will be initialized. + */ +void SPI_InitStruct(SPI_InitType* SPI_InitStruct) +{ + /*--------------- Reset SPI init structure parameters values -----------------*/ + /* Initialize the DataDirection member */ + SPI_InitStruct->DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX; + /* initialize the SpiMode member */ + SPI_InitStruct->SpiMode = SPI_MODE_SLAVE; + /* initialize the DataLen member */ + SPI_InitStruct->DataLen = SPI_DATA_SIZE_8BITS; + /* Initialize the CLKPOL member */ + SPI_InitStruct->CLKPOL = SPI_CLKPOL_LOW; + /* Initialize the CLKPHA member */ + SPI_InitStruct->CLKPHA = SPI_CLKPHA_FIRST_EDGE; + /* Initialize the NSS member */ + SPI_InitStruct->NSS = SPI_NSS_HARD; + /* Initialize the BaudRatePres member */ + SPI_InitStruct->BaudRatePres = SPI_BR_PRESCALER_2; + /* Initialize the FirstBit member */ + SPI_InitStruct->FirstBit = SPI_FB_MSB; + /* Initialize the CRCPoly member */ + SPI_InitStruct->CRCPoly = 7; +} + +/** + * @brief Fills each I2S_InitStruct member with its default value. + * @param I2S_InitStruct pointer to a I2S_InitType structure which will be initialized. + */ +void I2S_InitStruct(I2S_InitType* I2S_InitStruct) +{ + /*--------------- Reset I2S init structure parameters values -----------------*/ + /* Initialize the I2sMode member */ + I2S_InitStruct->I2sMode = I2S_MODE_SlAVE_TX; + + /* Initialize the Standard member */ + I2S_InitStruct->Standard = I2S_STD_PHILLIPS; + + /* Initialize the DataFormat member */ + I2S_InitStruct->DataFormat = I2S_DATA_FMT_16BITS; + + /* Initialize the MCLKEnable member */ + I2S_InitStruct->MCLKEnable = I2S_MCLK_DISABLE; + + /* Initialize the AudioFrequency member */ + I2S_InitStruct->AudioFrequency = I2S_AUDIO_FREQ_DEFAULT; + + /* Initialize the CLKPOL member */ + I2S_InitStruct->CLKPOL = I2S_CLKPOL_LOW; +} + +/** + * @brief Enables or disables the specified SPI peripheral. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @param Cmd new state of the SPIx peripheral. + * This parameter can be: ENABLE or DISABLE. + */ +void SPI_Enable(SPI_Module* SPIx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected SPI peripheral */ + SPIx->CTRL1 |= CTRL1_SPIEN_ENABLE; + } + else + { + /* Disable the selected SPI peripheral */ + SPIx->CTRL1 &= CTRL1_SPIEN_DISABLE; + } +} + +/** + * @brief Enables or disables the specified SPI peripheral (in I2S mode). + * @param SPIx where x can be 2 or 3 to select the SPI peripheral. + * @param Cmd new state of the SPIx peripheral. + * This parameter can be: ENABLE or DISABLE. + */ +void I2S_Enable(SPI_Module* SPIx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_SPI_2OR3_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected SPI peripheral (in I2S mode) */ + SPIx->I2SCFG |= I2SCFG_I2SEN_ENABLE; + } + else + { + /* Disable the selected SPI peripheral (in I2S mode) */ + SPIx->I2SCFG &= I2SCFG_I2SEN_DISABLE; + } +} + +/** + * @brief Enables or disables the specified SPI/I2S interrupts. + * @param SPIx where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @param SPI_I2S_IT specifies the SPI/I2S interrupt source to be enabled or disabled. + * This parameter can be one of the following values: + * @arg SPI_I2S_INT_TE Tx buffer empty interrupt mask + * @arg SPI_I2S_INT_RNE Rx buffer not empty interrupt mask + * @arg SPI_I2S_INT_ERR Error interrupt mask + * @param Cmd new state of the specified SPI/I2S interrupt. + * This parameter can be: ENABLE or DISABLE. + */ +void SPI_I2S_EnableInt(SPI_Module* SPIx, uint8_t SPI_I2S_IT, FunctionalState Cmd) +{ + uint16_t itpos = 0, itmask = 0; + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + assert_param(IS_SPI_I2S_CONFIG_INT(SPI_I2S_IT)); + + /* Get the SPI/I2S IT index */ + itpos = SPI_I2S_IT >> 4; + + /* Set the IT mask */ + itmask = (uint16_t)1 << (uint16_t)itpos; + + if (Cmd != DISABLE) + { + /* Enable the selected SPI/I2S interrupt */ + SPIx->CTRL2 |= itmask; + } + else + { + /* Disable the selected SPI/I2S interrupt */ + SPIx->CTRL2 &= (uint16_t)~itmask; + } +} + +/** + * @brief Enables or disables the SPIx/I2Sx DMA interface. + * @param SPIx where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @param SPI_I2S_DMAReq specifies the SPI/I2S DMA transfer request to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg SPI_I2S_DMA_TX Tx buffer DMA transfer request + * @arg SPI_I2S_DMA_RX Rx buffer DMA transfer request + * @param Cmd new state of the selected SPI/I2S DMA transfer request. + * This parameter can be: ENABLE or DISABLE. + */ +void SPI_I2S_EnableDma(SPI_Module* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + assert_param(IS_SPI_I2S_DMA(SPI_I2S_DMAReq)); + if (Cmd != DISABLE) + { + /* Enable the selected SPI/I2S DMA requests */ + SPIx->CTRL2 |= SPI_I2S_DMAReq; + } + else + { + /* Disable the selected SPI/I2S DMA requests */ + SPIx->CTRL2 &= (uint16_t)~SPI_I2S_DMAReq; + } +} + +/** + * @brief Transmits a Data through the SPIx/I2Sx peripheral. + * @param SPIx where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @param Data Data to be transmitted. + */ +void SPI_I2S_TransmitData(SPI_Module* SPIx, uint16_t Data) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + + /* Write in the DAT register the data to be sent */ + SPIx->DAT = Data; +} + +/** + * @brief Returns the most recent received data by the SPIx/I2Sx peripheral. + * @param SPIx where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @return The value of the received data. + */ +uint16_t SPI_I2S_ReceiveData(SPI_Module* SPIx) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + + /* Return the data in the DAT register */ + return SPIx->DAT; +} + +/** + * @brief Configures internally by software the NSS pin for the selected SPI. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @param SPI_NSSInternalSoft specifies the SPI NSS internal state. + * This parameter can be one of the following values: + * @arg SPI_NSS_HIGH Set NSS pin internally + * @arg SPI_NSS_LOW Reset NSS pin internally + */ +void SPI_SetNssLevel(SPI_Module* SPIx, uint16_t SPI_NSSInternalSoft) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_SPI_NSS_LEVEL(SPI_NSSInternalSoft)); + if (SPI_NSSInternalSoft != SPI_NSS_LOW) + { + /* Set NSS pin internally by software */ + SPIx->CTRL1 |= SPI_NSS_HIGH; + } + else + { + /* Reset NSS pin internally by software */ + SPIx->CTRL1 &= SPI_NSS_LOW; + } +} + +/** + * @brief Enables or disables the SS output for the selected SPI. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @param Cmd new state of the SPIx SS output. + * This parameter can be: ENABLE or DISABLE. + */ +void SPI_SSOutputEnable(SPI_Module* SPIx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected SPI SS output */ + SPIx->CTRL2 |= CTRL2_SSOEN_ENABLE; + } + else + { + /* Disable the selected SPI SS output */ + SPIx->CTRL2 &= CTRL2_SSOEN_DISABLE; + } +} + +/** + * @brief Configures the data size for the selected SPI. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @param DataLen specifies the SPI data size. + * This parameter can be one of the following values: + * @arg SPI_DATA_SIZE_16BITS Set data frame format to 16bit + * @arg SPI_DATA_SIZE_8BITS Set data frame format to 8bit + */ +void SPI_ConfigDataLen(SPI_Module* SPIx, uint16_t DataLen) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_SPI_DATASIZE(DataLen)); + /* Clear DFF bit */ + SPIx->CTRL1 &= (uint16_t)~SPI_DATA_SIZE_16BITS; + /* Set new DFF bit value */ + SPIx->CTRL1 |= DataLen; +} + +/** + * @brief Transmit the SPIx CRC value. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + */ +void SPI_TransmitCrcNext(SPI_Module* SPIx) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + + /* Enable the selected SPI CRC transmission */ + SPIx->CTRL1 |= CTRL1_CRCNEXT_ENABLE; +} + +/** + * @brief Enables or disables the CRC value calculation of the transferred bytes. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @param Cmd new state of the SPIx CRC value calculation. + * This parameter can be: ENABLE or DISABLE. + */ +void SPI_EnableCalculateCrc(SPI_Module* SPIx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected SPI CRC calculation */ + SPIx->CTRL1 |= CTRL1_CRCEN_ENABLE; + } + else + { + /* Disable the selected SPI CRC calculation */ + SPIx->CTRL1 &= CTRL1_CRCEN_DISABLE; + } +} + +/** + * @brief Returns the transmit or the receive CRC register value for the specified SPI. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @param SPI_CRC specifies the CRC register to be read. + * This parameter can be one of the following values: + * @arg SPI_CRC_TX Selects Tx CRC register + * @arg SPI_CRC_RX Selects Rx CRC register + * @return The selected CRC register value.. + */ +uint16_t SPI_GetCRCDat(SPI_Module* SPIx, uint8_t SPI_CRC) +{ + uint16_t crcreg = 0; + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_SPI_CRC(SPI_CRC)); + if (SPI_CRC != SPI_CRC_RX) + { + /* Get the Tx CRC register */ + crcreg = SPIx->CRCTDAT; + } + else + { + /* Get the Rx CRC register */ + crcreg = SPIx->CRCRDAT; + } + /* Return the selected CRC register */ + return crcreg; +} + +/** + * @brief Returns the CRC Polynomial register value for the specified SPI. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @return The CRC Polynomial register value. + */ +uint16_t SPI_GetCRCPoly(SPI_Module* SPIx) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + + /* Return the CRC polynomial register */ + return SPIx->CRCPOLY; +} + +/** + * @brief Selects the data transfer direction in bi-directional mode for the specified SPI. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @param DataDirection specifies the data transfer direction in bi-directional mode. + * This parameter can be one of the following values: + * @arg SPI_BIDIRECTION_TX Selects Tx transmission direction + * @arg SPI_BIDIRECTION_RX Selects Rx receive direction + */ +void SPI_ConfigBidirectionalMode(SPI_Module* SPIx, uint16_t DataDirection) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_SPI_BIDIRECTION(DataDirection)); + if (DataDirection == SPI_BIDIRECTION_TX) + { + /* Set the Tx only mode */ + SPIx->CTRL1 |= SPI_BIDIRECTION_TX; + } + else + { + /* Set the Rx only mode */ + SPIx->CTRL1 &= SPI_BIDIRECTION_RX; + } +} + +/** + * @brief Checks whether the specified SPI/I2S flag is set or not. + * @param SPIx where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @param SPI_I2S_FLAG specifies the SPI/I2S flag to check. + * This parameter can be one of the following values: + * @arg SPI_I2S_TE_FLAG Transmit buffer empty flag. + * @arg SPI_I2S_RNE_FLAG Receive buffer not empty flag. + * @arg SPI_I2S_BUSY_FLAG Busy flag. + * @arg SPI_I2S_OVER_FLAG Overrun flag. + * @arg SPI_MODERR_FLAG Mode Fault flag. + * @arg SPI_CRCERR_FLAG CRC Error flag. + * @arg I2S_UNDER_FLAG Underrun Error flag. + * @arg I2S_CHSIDE_FLAG Channel Side flag. + * @return The new state of SPI_I2S_FLAG (SET or RESET). + */ +FlagStatus SPI_I2S_GetStatus(SPI_Module* SPIx, uint16_t SPI_I2S_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_SPI_I2S_GET_FLAG(SPI_I2S_FLAG)); + /* Check the status of the specified SPI/I2S flag */ + if ((SPIx->STS & SPI_I2S_FLAG) != (uint16_t)RESET) + { + /* SPI_I2S_FLAG is set */ + bitstatus = SET; + } + else + { + /* SPI_I2S_FLAG is reset */ + bitstatus = RESET; + } + /* Return the SPI_I2S_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the SPIx CRC Error (CRCERR) flag. + * @param SPIx where x can be + * - 1, 2 or 3 in SPI mode + * @param SPI_I2S_FLAG specifies the SPI flag to clear. + * This function clears only CRCERR flag. + * @note + * - OVR (OverRun error) flag is cleared by software sequence: a read + * operation to SPI_DAT register (SPI_I2S_ReceiveData()) followed by a read + * operation to SPI_STS register (SPI_I2S_GetStatus()). + * - UDR (UnderRun error) flag is cleared by a read operation to + * SPI_STS register (SPI_I2S_GetStatus()). + * - MODF (Mode Fault) flag is cleared by software sequence: a read/write + * operation to SPI_STS register (SPI_I2S_GetStatus()) followed by a + * write operation to SPI_CTRL1 register (SPI_Enable() to enable the SPI). + */ +void SPI_I2S_ClrCRCErrFlag(SPI_Module* SPIx, uint16_t SPI_I2S_FLAG) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_SPI_I2S_CLR_FLAG(SPI_I2S_FLAG)); + + /* Clear the selected SPI CRC Error (CRCERR) flag */ + SPIx->STS = (uint16_t)~SPI_I2S_FLAG; +} + +/** + * @brief Checks whether the specified SPI/I2S interrupt has occurred or not. + * @param SPIx where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @param SPI_I2S_IT specifies the SPI/I2S interrupt source to check. + * This parameter can be one of the following values: + * @arg SPI_I2S_INT_TE Transmit buffer empty interrupt. + * @arg SPI_I2S_INT_RNE Receive buffer not empty interrupt. + * @arg SPI_I2S_INT_OVER Overrun interrupt. + * @arg SPI_INT_MODERR Mode Fault interrupt. + * @arg SPI_INT_CRCERR CRC Error interrupt. + * @arg I2S_INT_UNDER Underrun Error interrupt. + * @return The new state of SPI_I2S_IT (SET or RESET). + */ +INTStatus SPI_I2S_GetIntStatus(SPI_Module* SPIx, uint8_t SPI_I2S_IT) +{ + INTStatus bitstatus = RESET; + uint16_t itpos = 0, itmask = 0, enablestatus = 0; + + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_SPI_I2S_GET_INT(SPI_I2S_IT)); + + /* Get the SPI/I2S IT index */ + itpos = 0x01 << (SPI_I2S_IT & 0x0F); + + /* Get the SPI/I2S IT mask */ + itmask = SPI_I2S_IT >> 4; + + /* Set the IT mask */ + itmask = 0x01 << itmask; + + /* Get the SPI_I2S_IT enable bit status */ + enablestatus = (SPIx->CTRL2 & itmask); + + /* Check the status of the specified SPI/I2S interrupt */ + if (((SPIx->STS & itpos) != (uint16_t)RESET) && enablestatus) + { + /* SPI_I2S_IT is set */ + bitstatus = SET; + } + else + { + /* SPI_I2S_IT is reset */ + bitstatus = RESET; + } + /* Return the SPI_I2S_IT status */ + return bitstatus; +} + +/** + * @brief Clears the SPIx CRC Error (CRCERR) interrupt pending bit. + * @param SPIx where x can be + * - 1, 2 or 3 in SPI mode + * @param SPI_I2S_IT specifies the SPI interrupt pending bit to clear. + * This function clears only CRCERR interrupt pending bit. + * @note + * - OVR (OverRun Error) interrupt pending bit is cleared by software + * sequence: a read operation to SPI_DAT register (SPI_I2S_ReceiveData()) + * followed by a read operation to SPI_STS register (SPI_I2S_GetIntStatus()). + * - UDR (UnderRun Error) interrupt pending bit is cleared by a read + * operation to SPI_STS register (SPI_I2S_GetIntStatus()). + * - MODF (Mode Fault) interrupt pending bit is cleared by software sequence: + * a read/write operation to SPI_STS register (SPI_I2S_GetIntStatus()) + * followed by a write operation to SPI_CTRL1 register (SPI_Enable() to enable + * the SPI). + */ +void SPI_I2S_ClrITPendingBit(SPI_Module* SPIx, uint8_t SPI_I2S_IT) +{ + uint16_t itpos = 0; + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_SPI_I2S_CLR_INT(SPI_I2S_IT)); + + /* Get the SPI IT index */ + itpos = 0x01 << (SPI_I2S_IT & 0x0F); + + /* Clear the selected SPI CRC Error (CRCERR) interrupt pending bit */ + SPIx->STS = (uint16_t)~itpos; +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_tim.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_tim.c new file mode 100644 index 0000000000..ddfe821c95 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_tim.c @@ -0,0 +1,3306 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_tim.c + * @author Nations + * @version v1.0.4 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_tim.h" +#include "n32g4fr_rcc.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup TIM + * @brief TIM driver modules + * @{ + */ + +/** @addtogroup TIM_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup TIM_Private_Defines + * @{ + */ + +/* ---------------------- TIM registers bit mask ------------------------ */ +#define SMCTRL_ETR_MASK ((uint16_t)0x00FF) +#define CAPCMPMOD_OFFSET ((uint16_t)0x0018) +#define CAPCMPEN_CCE_SET ((uint16_t)0x0001) +#define CAPCMPEN_CCNE_SET ((uint16_t)0x0004) + +/** + * @} + */ + +/** @addtogroup TIM_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup TIM_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup TIM_Private_FunctionPrototypes + * @{ + */ + +static void ConfigTI1(TIM_Module* TIMx, uint16_t IcPolarity, uint16_t IcSelection, uint16_t IcFilter); +static void ConfigTI2(TIM_Module* TIMx, uint16_t IcPolarity, uint16_t IcSelection, uint16_t IcFilter); +static void ConfigTI3(TIM_Module* TIMx, uint16_t IcPolarity, uint16_t IcSelection, uint16_t IcFilter); +static void ConfigTI4(TIM_Module* TIMx, uint16_t IcPolarity, uint16_t IcSelection, uint16_t IcFilter); +/** + * @} + */ + +/** @addtogroup TIM_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup TIM_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup TIM_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup TIM_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the TIMx peripheral registers to their default reset values. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + */ +void TIM_DeInit(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + + if (TIMx == TIM1) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_TIM1, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_TIM1, DISABLE); + } + else if (TIMx == TIM2) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM2, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM2, DISABLE); + } + else if (TIMx == TIM3) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM3, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM3, DISABLE); + } + else if (TIMx == TIM4) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM4, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM4, DISABLE); + } + else if (TIMx == TIM5) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM5, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM5, DISABLE); + } + else if (TIMx == TIM6) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM6, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM6, DISABLE); + } + else if (TIMx == TIM7) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM7, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM7, DISABLE); + } + else if (TIMx == TIM8) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_TIM8, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_TIM8, DISABLE); + } +} + +/** + * @brief Initializes the TIMx Time Base Unit peripheral according to + * the specified parameters in the TIM_TimeBaseInitStruct. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param TIM_TimeBaseInitStruct pointer to a TIM_TimeBaseInitType + * structure that contains the configuration information for the + * specified TIM peripheral. + */ +void TIM_InitTimeBase(TIM_Module* TIMx, TIM_TimeBaseInitType* TIM_TimeBaseInitStruct) +{ + uint32_t tmpcr1 = 0; + + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimCntMode(TIM_TimeBaseInitStruct->CntMode)); + assert_param(IsTimClkDiv(TIM_TimeBaseInitStruct->ClkDiv)); + + tmpcr1 = TIMx->CTRL1; + + if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) || (TIMx == TIM5)) + { + /* Select the Counter Mode */ + tmpcr1 &= (uint32_t)(~((uint32_t)(TIM_CTRL1_DIR | TIM_CTRL1_CAMSEL))); + tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->CntMode; + } + + if ((TIMx != TIM6) && (TIMx != TIM7)) + { + /* Set the clock division */ + tmpcr1 &= (uint32_t)(~((uint32_t)TIM_CTRL1_CLKD)); + tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->ClkDiv; + } + + TIMx->CTRL1 = tmpcr1; + + /* Set the Autoreload value */ + TIMx->AR = TIM_TimeBaseInitStruct->Period; + + /* Set the Prescaler value */ + TIMx->PSC = TIM_TimeBaseInitStruct->Prescaler; + + if ((TIMx == TIM1) || (TIMx == TIM8)) + { + /* Set the Repetition Counter value */ + TIMx->REPCNT = TIM_TimeBaseInitStruct->RepetCnt; + } + + /* Generate an update event to reload the Prescaler and the Repetition counter + values immediately */ + TIMx->EVTGEN = TIM_PSC_RELOAD_MODE_IMMEDIATE; + + /*channel input from comp or iom*/ + tmpcr1 = TIMx->CTRL1; + if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) || (TIMx == TIM5)) + { + if (TIM_TimeBaseInitStruct->CapCh1FromCompEn) + tmpcr1 |= (0x01L << 11); + else + tmpcr1 &= ~(0x01L << 11); + } + if ((TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) || (TIMx == TIM5)) + { + if (TIM_TimeBaseInitStruct->CapCh2FromCompEn) + tmpcr1 |= (0x01L << 12); + else + tmpcr1 &= ~(0x01L << 12); + if (TIM_TimeBaseInitStruct->CapCh3FromCompEn) + tmpcr1 |= (0x01L << 13); + else + tmpcr1 &= ~(0x01L << 13); + } + if ((TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4)) + { + if (TIM_TimeBaseInitStruct->CapCh4FromCompEn) + tmpcr1 |= (0x01L << 14); + else + tmpcr1 &= ~(0x01L << 14); + } + /*etr input from comp or iom*/ + if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4)) + { + if (TIM_TimeBaseInitStruct->CapEtrClrFromCompEn) + tmpcr1 |= (0x01L << 15); + else + tmpcr1 &= ~(0x01L << 15); + } + TIMx->CTRL1 = tmpcr1; + /*sel etr from iom or tsc*/ + tmpcr1 = TIMx->CTRL2; + if ((TIMx == TIM2) || (TIMx == TIM4)) + { + if (TIM_TimeBaseInitStruct->CapEtrSelFromTscEn) + tmpcr1 |= (0x01L << 8); + else + tmpcr1 &= ~(0x01L << 8); + } + TIMx->CTRL2 = tmpcr1; +} + +/** + * @brief Initializes the TIMx Channel1 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param TIM_OCInitStruct pointer to a OCInitType structure + * that contains the configuration information for the specified TIM peripheral. + */ +void TIM_InitOc1(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0; + uint32_t tmpccer = 0, tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimOcMode(TIM_OCInitStruct->OcMode)); + assert_param(IsTimOutputState(TIM_OCInitStruct->OutputState)); + assert_param(IsTimOcPolarity(TIM_OCInitStruct->OcPolarity)); + /* Disable the Channel 1: Reset the CC1E Bit */ + TIMx->CCEN &= (uint32_t)(~(uint32_t)TIM_CCEN_CC1EN); + /* Get the TIMx CCEN register value */ + tmpccer = TIMx->CCEN; + /* Get the TIMx CTRL2 register value */ + tmpcr2 = TIMx->CTRL2; + + /* Get the TIMx CCMOD1 register value */ + tmpccmrx = TIMx->CCMOD1; + + /* Reset the Output Compare Mode Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD1_OC1M)); + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD1_CC1SEL)); + + /* Select the Output Compare Mode */ + tmpccmrx |= TIM_OCInitStruct->OcMode; + + /* Reset the Output Polarity level */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC1P)); + /* Set the Output Compare Polarity */ + tmpccer |= TIM_OCInitStruct->OcPolarity; + + /* Set the Output State */ + tmpccer |= TIM_OCInitStruct->OutputState; + + if ((TIMx == TIM1) || (TIMx == TIM8)) + { + assert_param(IsTimOutputNState(TIM_OCInitStruct->OutputNState)); + assert_param(IsTimOcnPolarity(TIM_OCInitStruct->OcNPolarity)); + assert_param(IsTimOcnIdleState(TIM_OCInitStruct->OcNIdleState)); + assert_param(IsTimOcIdleState(TIM_OCInitStruct->OcIdleState)); + + /* Reset the Output N Polarity level */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC1NP)); + /* Set the Output N Polarity */ + tmpccer |= TIM_OCInitStruct->OcNPolarity; + + /* Reset the Output N State */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC1NEN)); + /* Set the Output N State */ + tmpccer |= TIM_OCInitStruct->OutputNState; + + /* Reset the Output Compare and Output Compare N IDLE State */ + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI1)); + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI1N)); + + /* Set the Output Idle state */ + tmpcr2 |= TIM_OCInitStruct->OcIdleState; + /* Set the Output N Idle state */ + tmpcr2 |= TIM_OCInitStruct->OcNIdleState; + } + /* Write to TIMx CTRL2 */ + TIMx->CTRL2 = tmpcr2; + + /* Write to TIMx CCMOD1 */ + TIMx->CCMOD1 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCDAT1 = TIM_OCInitStruct->Pulse; + + /* Write to TIMx CCEN */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Initializes the TIMx Channel2 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select + * the TIM peripheral. + * @param TIM_OCInitStruct pointer to a OCInitType structure + * that contains the configuration information for the specified TIM peripheral. + */ +void TIM_InitOc2(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0; + uint32_t tmpccer = 0, tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimOcMode(TIM_OCInitStruct->OcMode)); + assert_param(IsTimOutputState(TIM_OCInitStruct->OutputState)); + assert_param(IsTimOcPolarity(TIM_OCInitStruct->OcPolarity)); + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCEN &= (uint32_t)(~((uint32_t)TIM_CCEN_CC2EN)); + + /* Get the TIMx CCEN register value */ + tmpccer = TIMx->CCEN; + /* Get the TIMx CTRL2 register value */ + tmpcr2 = TIMx->CTRL2; + + /* Get the TIMx CCMOD1 register value */ + tmpccmrx = TIMx->CCMOD1; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD1_OC2M)); + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD1_CC2SEL)); + + /* Select the Output Compare Mode */ + tmpccmrx |= (uint16_t)(TIM_OCInitStruct->OcMode << 8); + + /* Reset the Output Polarity level */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC2P)); + /* Set the Output Compare Polarity */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OcPolarity << 4); + + /* Set the Output State */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OutputState << 4); + + if ((TIMx == TIM1) || (TIMx == TIM8)) + { + assert_param(IsTimOutputNState(TIM_OCInitStruct->OutputNState)); + assert_param(IsTimOcnPolarity(TIM_OCInitStruct->OcNPolarity)); + assert_param(IsTimOcnIdleState(TIM_OCInitStruct->OcNIdleState)); + assert_param(IsTimOcIdleState(TIM_OCInitStruct->OcIdleState)); + + /* Reset the Output N Polarity level */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC2NP)); + /* Set the Output N Polarity */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OcNPolarity << 4); + + /* Reset the Output N State */ + tmpccer &= (uint32_t)(~((uint16_t)TIM_CCEN_CC2NEN)); + /* Set the Output N State */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OutputNState << 4); + + /* Reset the Output Compare and Output Compare N IDLE State */ + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI2)); + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI2N)); + + /* Set the Output Idle state */ + tmpcr2 |= (uint32_t)(TIM_OCInitStruct->OcIdleState << 2); + /* Set the Output N Idle state */ + tmpcr2 |= (uint32_t)(TIM_OCInitStruct->OcNIdleState << 2); + } + /* Write to TIMx CTRL2 */ + TIMx->CTRL2 = tmpcr2; + + /* Write to TIMx CCMOD1 */ + TIMx->CCMOD1 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCDAT2 = TIM_OCInitStruct->Pulse; + + /* Write to TIMx CCEN */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Initializes the TIMx Channel3 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCInitStruct pointer to a OCInitType structure + * that contains the configuration information for the specified TIM peripheral. + */ +void TIM_InitOc3(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0; + uint32_t tmpccer = 0, tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcMode(TIM_OCInitStruct->OcMode)); + assert_param(IsTimOutputState(TIM_OCInitStruct->OutputState)); + assert_param(IsTimOcPolarity(TIM_OCInitStruct->OcPolarity)); + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCEN &= (uint32_t)(~((uint32_t)TIM_CCEN_CC3EN)); + + /* Get the TIMx CCEN register value */ + tmpccer = TIMx->CCEN; + /* Get the TIMx CTRL2 register value */ + tmpcr2 = TIMx->CTRL2; + + /* Get the TIMx CCMOD2 register value */ + tmpccmrx = TIMx->CCMOD2; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD2_OC3MD)); + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD2_CC3SEL)); + /* Select the Output Compare Mode */ + tmpccmrx |= TIM_OCInitStruct->OcMode; + + /* Reset the Output Polarity level */ + tmpccer &= (uint32_t)(~((uint16_t)TIM_CCEN_CC3P)); + /* Set the Output Compare Polarity */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OcPolarity << 8); + + /* Set the Output State */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OutputState << 8); + + if ((TIMx == TIM1) || (TIMx == TIM8)) + { + assert_param(IsTimOutputNState(TIM_OCInitStruct->OutputNState)); + assert_param(IsTimOcnPolarity(TIM_OCInitStruct->OcNPolarity)); + assert_param(IsTimOcnIdleState(TIM_OCInitStruct->OcNIdleState)); + assert_param(IsTimOcIdleState(TIM_OCInitStruct->OcIdleState)); + + /* Reset the Output N Polarity level */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC3NP)); + /* Set the Output N Polarity */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OcNPolarity << 8); + /* Reset the Output N State */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC3NEN)); + + /* Set the Output N State */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OutputNState << 8); + /* Reset the Output Compare and Output Compare N IDLE State */ + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI3)); + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI3N)); + /* Set the Output Idle state */ + tmpcr2 |= (uint32_t)(TIM_OCInitStruct->OcIdleState << 4); + /* Set the Output N Idle state */ + tmpcr2 |= (uint32_t)(TIM_OCInitStruct->OcNIdleState << 4); + } + /* Write to TIMx CTRL2 */ + TIMx->CTRL2 = tmpcr2; + + /* Write to TIMx CCMOD2 */ + TIMx->CCMOD2 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCDAT3 = TIM_OCInitStruct->Pulse; + + /* Write to TIMx CCEN */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Initializes the TIMx Channel4 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCInitStruct pointer to a OCInitType structure + * that contains the configuration information for the specified TIM peripheral. + */ +void TIM_InitOc4(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0; + uint32_t tmpccer = 0, tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcMode(TIM_OCInitStruct->OcMode)); + assert_param(IsTimOutputState(TIM_OCInitStruct->OutputState)); + assert_param(IsTimOcPolarity(TIM_OCInitStruct->OcPolarity)); + /* Disable the Channel 2: Reset the CC4E Bit */ + TIMx->CCEN &= (uint32_t)(~((uint32_t)TIM_CCEN_CC4EN)); + + /* Get the TIMx CCEN register value */ + tmpccer = TIMx->CCEN; + /* Get the TIMx CTRL2 register value */ + tmpcr2 = TIMx->CTRL2; + + /* Get the TIMx CCMOD2 register value */ + tmpccmrx = TIMx->CCMOD2; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD2_OC4MD)); + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD2_CC4SEL)); + + /* Select the Output Compare Mode */ + tmpccmrx |= (uint16_t)(TIM_OCInitStruct->OcMode << 8); + + /* Reset the Output Polarity level */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC4P)); + /* Set the Output Compare Polarity */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OcPolarity << 12); + + /* Set the Output State */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OutputState << 12); + + if ((TIMx == TIM1) || (TIMx == TIM8)) + { + assert_param(IsTimOcIdleState(TIM_OCInitStruct->OcIdleState)); + /* Reset the Output Compare IDLE State */ + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI4)); + /* Set the Output Idle state */ + tmpcr2 |= (uint32_t)(TIM_OCInitStruct->OcIdleState << 6); + } + /* Write to TIMx CTRL2 */ + TIMx->CTRL2 = tmpcr2; + + /* Write to TIMx CCMOD2 */ + TIMx->CCMOD2 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCDAT4 = TIM_OCInitStruct->Pulse; + + /* Write to TIMx CCEN */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Initializes the TIMx Channel5 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param TIM_OCInitStruct pointer to a OCInitType structure + * that contains the configuration information for the specified TIM peripheral. + */ +void TIM_InitOc5(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0; + uint32_t tmpccer = 0, tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcMode(TIM_OCInitStruct->OcMode)); + assert_param(IsTimOutputState(TIM_OCInitStruct->OutputState)); + assert_param(IsTimOcPolarity(TIM_OCInitStruct->OcPolarity)); + /* Disable the Channel 5: Reset the CC5E Bit */ + TIMx->CCEN &= (uint32_t)(~((uint32_t)TIM_CCEN_CC5EN)); + + /* Get the TIMx CCEN register value */ + tmpccer = TIMx->CCEN; + /* Get the TIMx CTRL2 register value */ + tmpcr2 = TIMx->CTRL2; + + /* Get the TIMx CCMOD3 register value */ + tmpccmrx = TIMx->CCMOD3; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD3_OC5MD)); + + /* Select the Output Compare Mode */ + tmpccmrx |= (uint16_t)(TIM_OCInitStruct->OcMode); + + /* Reset the Output Polarity level */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC5P)); + /* Set the Output Compare Polarity */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OcPolarity << 16); + + /* Set the Output State */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OutputState << 16); + + if ((TIMx == TIM1) || (TIMx == TIM8)) + { + assert_param(IsTimOcIdleState(TIM_OCInitStruct->OcIdleState)); + /* Reset the Output Compare IDLE State */ + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI5)); + /* Set the Output Idle state */ + tmpcr2 |= (uint32_t)(TIM_OCInitStruct->OcIdleState << 8); + } + /* Write to TIMx CTRL2 */ + TIMx->CTRL2 = tmpcr2; + + /* Write to TIMx CCMOD3 */ + TIMx->CCMOD3 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCDAT5 = TIM_OCInitStruct->Pulse; + + /* Write to TIMx CCEN */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Initializes the TIMx Channel6 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param TIM_OCInitStruct pointer to a OCInitType structure + * that contains the configuration information for the specified TIM peripheral. + */ +void TIM_InitOc6(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0; + uint32_t tmpccer = 0, tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcMode(TIM_OCInitStruct->OcMode)); + assert_param(IsTimOutputState(TIM_OCInitStruct->OutputState)); + assert_param(IsTimOcPolarity(TIM_OCInitStruct->OcPolarity)); + /* Disable the Channel 6: Reset the CC6E Bit */ + TIMx->CCEN &= (uint32_t)(~((uint32_t)TIM_CCEN_CC6EN)); + + /* Get the TIMx CCEN register value */ + tmpccer = TIMx->CCEN; + /* Get the TIMx CTRL2 register value */ + tmpcr2 = TIMx->CTRL2; + + /* Get the TIMx CCMOD3 register value */ + tmpccmrx = TIMx->CCMOD3; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD3_OC6MD)); + + /* Select the Output Compare Mode */ + tmpccmrx |= (uint16_t)(TIM_OCInitStruct->OcMode << 8); + + /* Reset the Output Polarity level */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC6P)); + /* Set the Output Compare Polarity */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OcPolarity << 20); + + /* Set the Output State */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OutputState << 20); + + if ((TIMx == TIM1) || (TIMx == TIM8)) + { + assert_param(IsTimOcIdleState(TIM_OCInitStruct->OcIdleState)); + /* Reset the Output Compare IDLE State */ + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI6)); + /* Set the Output Idle state */ + tmpcr2 |= (uint32_t)(TIM_OCInitStruct->OcIdleState << 10); + } + /* Write to TIMx CTRL2 */ + TIMx->CTRL2 = tmpcr2; + + /* Write to TIMx CCMOD3 */ + TIMx->CCMOD3 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCDAT6 = TIM_OCInitStruct->Pulse; + + /* Write to TIMx CCEN */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Initializes the TIM peripheral according to the specified + * parameters in the TIM_ICInitStruct. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param TIM_ICInitStruct pointer to a TIM_ICInitType structure + * that contains the configuration information for the specified TIM peripheral. + */ +void TIM_ICInit(TIM_Module* TIMx, TIM_ICInitType* TIM_ICInitStruct) +{ + /* Check the parameters */ + assert_param(IsTimCh(TIM_ICInitStruct->Channel)); + assert_param(IsTimIcSelection(TIM_ICInitStruct->IcSelection)); + assert_param(IsTimIcPrescaler(TIM_ICInitStruct->IcPrescaler)); + assert_param(IsTimInCapFilter(TIM_ICInitStruct->IcFilter)); + + if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) || (TIMx == TIM5)) + { + assert_param(IsTimIcPalaritySingleEdge(TIM_ICInitStruct->IcPolarity)); + } + else + { + assert_param(IsTimIcPolarityAnyEdge(TIM_ICInitStruct->IcPolarity)); + } + if (TIM_ICInitStruct->Channel == TIM_CH_1) + { + assert_param(IsTimList8Module(TIMx)); + /* TI1 Configuration */ + ConfigTI1(TIMx, TIM_ICInitStruct->IcPolarity, TIM_ICInitStruct->IcSelection, TIM_ICInitStruct->IcFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetInCap1Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler); + } + else if (TIM_ICInitStruct->Channel == TIM_CH_2) + { + assert_param(IsTimList6Module(TIMx)); + /* TI2 Configuration */ + ConfigTI2(TIMx, TIM_ICInitStruct->IcPolarity, TIM_ICInitStruct->IcSelection, TIM_ICInitStruct->IcFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetInCap2Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler); + } + else if (TIM_ICInitStruct->Channel == TIM_CH_3) + { + assert_param(IsTimList3Module(TIMx)); + /* TI3 Configuration */ + ConfigTI3(TIMx, TIM_ICInitStruct->IcPolarity, TIM_ICInitStruct->IcSelection, TIM_ICInitStruct->IcFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetInCap3Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler); + } + else + { + assert_param(IsTimList3Module(TIMx)); + /* TI4 Configuration */ + ConfigTI4(TIMx, TIM_ICInitStruct->IcPolarity, TIM_ICInitStruct->IcSelection, TIM_ICInitStruct->IcFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetInCap4Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler); + } +} + +/** + * @brief Configures the TIM peripheral according to the specified + * parameters in the TIM_ICInitStruct to measure an external PWM signal. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @param TIM_ICInitStruct pointer to a TIM_ICInitType structure + * that contains the configuration information for the specified TIM peripheral. + */ +void TIM_ConfigPwmIc(TIM_Module* TIMx, TIM_ICInitType* TIM_ICInitStruct) +{ + uint16_t icoppositepolarity = TIM_IC_POLARITY_RISING; + uint16_t icoppositeselection = TIM_IC_SELECTION_DIRECTTI; + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + /* Select the Opposite Input Polarity */ + if (TIM_ICInitStruct->IcPolarity == TIM_IC_POLARITY_RISING) + { + icoppositepolarity = TIM_IC_POLARITY_FALLING; + } + else + { + icoppositepolarity = TIM_IC_POLARITY_RISING; + } + /* Select the Opposite Input */ + if (TIM_ICInitStruct->IcSelection == TIM_IC_SELECTION_DIRECTTI) + { + icoppositeselection = TIM_IC_SELECTION_INDIRECTTI; + } + else + { + icoppositeselection = TIM_IC_SELECTION_DIRECTTI; + } + if (TIM_ICInitStruct->Channel == TIM_CH_1) + { + /* TI1 Configuration */ + ConfigTI1(TIMx, TIM_ICInitStruct->IcPolarity, TIM_ICInitStruct->IcSelection, TIM_ICInitStruct->IcFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetInCap1Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler); + /* TI2 Configuration */ + ConfigTI2(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->IcFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetInCap2Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler); + } + else + { + /* TI2 Configuration */ + ConfigTI2(TIMx, TIM_ICInitStruct->IcPolarity, TIM_ICInitStruct->IcSelection, TIM_ICInitStruct->IcFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetInCap2Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler); + /* TI1 Configuration */ + ConfigTI1(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->IcFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetInCap1Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler); + } +} + +/** + * @brief Configures the: Break feature, dead time, Lock level, the OSSI, + * the OSSR State and the AOE(automatic output enable). + * @param TIMx where x can be 1 or 8 to select the TIM + * @param TIM_BDTRInitStruct pointer to a TIM_BDTRInitType structure that + * contains the BKDT Register configuration information for the TIM peripheral. + */ +void TIM_ConfigBkdt(TIM_Module* TIMx, TIM_BDTRInitType* TIM_BDTRInitStruct) +{ + uint32_t tmp; + /* Check the parameters */ + assert_param(IsTimList2Module(TIMx)); + assert_param(IsTimOssrState(TIM_BDTRInitStruct->OssrState)); + assert_param(IsTimOssiState(TIM_BDTRInitStruct->OssiState)); + assert_param(IsTimLockLevel(TIM_BDTRInitStruct->LockLevel)); + assert_param(IsTimBreakInState(TIM_BDTRInitStruct->Break)); + assert_param(IsTimBreakPalarity(TIM_BDTRInitStruct->BreakPolarity)); + assert_param(IsTimAutoOutputState(TIM_BDTRInitStruct->AutomaticOutput)); + /* Set the Lock level, the Break enable Bit and the Ploarity, the OSSR State, + the OSSI State, the dead time value and the Automatic Output Enable Bit */ + TIMx->BKDT = (uint32_t)TIM_BDTRInitStruct->OssrState | TIM_BDTRInitStruct->OssiState | TIM_BDTRInitStruct->LockLevel + | TIM_BDTRInitStruct->DeadTime | TIM_BDTRInitStruct->Break | TIM_BDTRInitStruct->BreakPolarity + | TIM_BDTRInitStruct->AutomaticOutput; + + /*cofigure other break in*/ + tmp = TIMx->CTRL1; + /*IOMBKPEN 0 meaning iom as break enable*/ + if (TIM_BDTRInitStruct->IomBreakEn) + tmp &= ~(0x01L << 10); + else + tmp |= (0x01L << 10); + if (TIM_BDTRInitStruct->LockUpBreakEn) + tmp |= (0x01L << 16); + else + tmp &= ~(0x01L << 16); + if (TIM_BDTRInitStruct->PvdBreakEn) + tmp |= (0x01L << 17); + else + tmp &= ~(0x01L << 17); + TIMx->CTRL1 = tmp; +} + +/** + * @brief Fills each TIM_TimeBaseInitStruct member with its default value. + * @param TIM_TimeBaseInitStruct pointer to a TIM_TimeBaseInitType + * structure which will be initialized. + */ +void TIM_InitTimBaseStruct(TIM_TimeBaseInitType* TIM_TimeBaseInitStruct) +{ + /* Set the default configuration */ + TIM_TimeBaseInitStruct->Period = 0xFFFF; + TIM_TimeBaseInitStruct->Prescaler = 0x0000; + TIM_TimeBaseInitStruct->ClkDiv = TIM_CLK_DIV1; + TIM_TimeBaseInitStruct->CntMode = TIM_CNT_MODE_UP; + TIM_TimeBaseInitStruct->RepetCnt = 0x0000; + + TIM_TimeBaseInitStruct->CapCh1FromCompEn = false; + TIM_TimeBaseInitStruct->CapCh2FromCompEn = false; + TIM_TimeBaseInitStruct->CapCh3FromCompEn = false; + TIM_TimeBaseInitStruct->CapCh4FromCompEn = false; + TIM_TimeBaseInitStruct->CapEtrClrFromCompEn = false; + TIM_TimeBaseInitStruct->CapEtrSelFromTscEn = false; +} + +/** + * @brief Fills each TIM_OCInitStruct member with its default value. + * @param TIM_OCInitStruct pointer to a OCInitType structure which will + * be initialized. + */ +void TIM_InitOcStruct(OCInitType* TIM_OCInitStruct) +{ + /* Set the default configuration */ + TIM_OCInitStruct->OcMode = TIM_OCMODE_TIMING; + TIM_OCInitStruct->OutputState = TIM_OUTPUT_STATE_DISABLE; + TIM_OCInitStruct->OutputNState = TIM_OUTPUT_NSTATE_DISABLE; + TIM_OCInitStruct->Pulse = 0x0000; + TIM_OCInitStruct->OcPolarity = TIM_OC_POLARITY_HIGH; + TIM_OCInitStruct->OcNPolarity = TIM_OC_POLARITY_HIGH; + TIM_OCInitStruct->OcIdleState = TIM_OC_IDLE_STATE_RESET; + TIM_OCInitStruct->OcNIdleState = TIM_OCN_IDLE_STATE_RESET; +} + +/** + * @brief Fills each TIM_ICInitStruct member with its default value. + * @param TIM_ICInitStruct pointer to a TIM_ICInitType structure which will + * be initialized. + */ +void TIM_InitIcStruct(TIM_ICInitType* TIM_ICInitStruct) +{ + /* Set the default configuration */ + TIM_ICInitStruct->Channel = TIM_CH_1; + TIM_ICInitStruct->IcPolarity = TIM_IC_POLARITY_RISING; + TIM_ICInitStruct->IcSelection = TIM_IC_SELECTION_DIRECTTI; + TIM_ICInitStruct->IcPrescaler = TIM_IC_PSC_DIV1; + TIM_ICInitStruct->IcFilter = 0x00; +} + +/** + * @brief Fills each TIM_BDTRInitStruct member with its default value. + * @param TIM_BDTRInitStruct pointer to a TIM_BDTRInitType structure which + * will be initialized. + */ +void TIM_InitBkdtStruct(TIM_BDTRInitType* TIM_BDTRInitStruct) +{ + /* Set the default configuration */ + TIM_BDTRInitStruct->OssrState = TIM_OSSR_STATE_DISABLE; + TIM_BDTRInitStruct->OssiState = TIM_OSSI_STATE_DISABLE; + TIM_BDTRInitStruct->LockLevel = TIM_LOCK_LEVEL_OFF; + TIM_BDTRInitStruct->DeadTime = 0x00; + TIM_BDTRInitStruct->Break = TIM_BREAK_IN_DISABLE; + TIM_BDTRInitStruct->BreakPolarity = TIM_BREAK_POLARITY_LOW; + TIM_BDTRInitStruct->AutomaticOutput = TIM_AUTO_OUTPUT_DISABLE; +} + +/** + * @brief Enables or disables the specified TIM peripheral. + * @param TIMx where x can be 1 to 8 to select the TIMx peripheral. + * @param Cmd new state of the TIMx peripheral. + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_Enable(TIM_Module* TIMx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the TIM Counter */ + TIMx->CTRL1 |= TIM_CTRL1_CNTEN; + } + else + { + /* Disable the TIM Counter */ + TIMx->CTRL1 &= (uint32_t)(~((uint32_t)TIM_CTRL1_CNTEN)); + } +} + +/** + * @brief Enables or disables the TIM peripheral Main Outputs. + * @param TIMx where x can be 1, 8 to select the TIMx peripheral. + * @param Cmd new state of the TIM peripheral Main Outputs. + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_EnableCtrlPwmOutputs(TIM_Module* TIMx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimList2Module(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the TIM Main Output */ + TIMx->BKDT |= TIM_BKDT_MOEN; + } + else + { + /* Disable the TIM Main Output */ + TIMx->BKDT &= (uint16_t)(~((uint16_t)TIM_BKDT_MOEN)); + } +} + +/** + * @brief Enables or disables the specified TIM interrupts. + * @param TIMx where x can be 1 to 8 to select the TIMx peripheral. + * @param TIM_IT specifies the TIM interrupts sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg TIM_INT_UPDATE TIM update Interrupt source + * @arg TIM_INT_CC1 TIM Capture Compare 1 Interrupt source + * @arg TIM_INT_CC2 TIM Capture Compare 2 Interrupt source + * @arg TIM_INT_CC3 TIM Capture Compare 3 Interrupt source + * @arg TIM_INT_CC4 TIM Capture Compare 4 Interrupt source + * @arg TIM_INT_COM TIM Commutation Interrupt source + * @arg TIM_INT_TRIG TIM Trigger Interrupt source + * @arg TIM_INT_BREAK TIM Break Interrupt source + * @note + * - TIM6 and TIM7 can only generate an update interrupt. + * - TIM_INT_BREAK is used only with TIM1, TIM8. + * - TIM_INT_COM is used only with TIM1, TIM8. + * @param Cmd new state of the TIM interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_ConfigInt(TIM_Module* TIMx, uint16_t TIM_IT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimInt(TIM_IT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the Interrupt sources */ + TIMx->DINTEN |= TIM_IT; + } + else + { + /* Disable the Interrupt sources */ + TIMx->DINTEN &= (uint16_t)~TIM_IT; + } +} + +/** + * @brief Configures the TIMx event to be generate by software. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param TIM_EventSource specifies the event source. + * This parameter can be one or more of the following values: + * @arg TIM_EVT_SRC_UPDATE Timer update Event source + * @arg TIM_EVT_SRC_CC1 Timer Capture Compare 1 Event source + * @arg TIM_EVT_SRC_CC2 Timer Capture Compare 2 Event source + * @arg TIM_EVT_SRC_CC3 Timer Capture Compare 3 Event source + * @arg TIM_EVT_SRC_CC4 Timer Capture Compare 4 Event source + * @arg TIM_EVT_SRC_COM Timer COM event source + * @arg TIM_EVT_SRC_TRIG Timer Trigger Event source + * @arg TIM_EVT_SRC_BREAK Timer Break event source + * @note + * - TIM6 and TIM7 can only generate an update event. + * - TIM_EVT_SRC_COM and TIM_EVT_SRC_BREAK are used only with TIM1 and TIM8. + */ +void TIM_GenerateEvent(TIM_Module* TIMx, uint16_t TIM_EventSource) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimEvtSrc(TIM_EventSource)); + + /* Set the event sources */ + TIMx->EVTGEN = TIM_EventSource; +} + +/** + * @brief Configures the TIMx's DMA interface. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select + * the TIM peripheral. + * @param TIM_DMABase DMA Base address. + * This parameter can be one of the following values: + * @arg TIM_DMABase_CR, TIM_DMABASE_CTRL2, TIM_DMABASE_SMCTRL, + * TIM_DMABASE_DMAINTEN, TIM1_DMABase_SR, TIM_DMABASE_EVTGEN, + * TIM_DMABASE_CAPCMPMOD1, TIM_DMABASE_CAPCMPMOD2, TIM_DMABASE_CAPCMPEN, + * TIM_DMABASE_CNT, TIM_DMABASE_PSC, TIM_DMABASE_AR, + * TIM_DMABASE_REPCNT, TIM_DMABASE_CAPCMPDAT1, TIM_DMABASE_CAPCMPDAT2, + * TIM_DMABASE_CAPCMPDAT3, TIM_DMABASE_CAPCMPDAT4, TIM_DMABASE_BKDT, + * TIM_DMABASE_DMACTRL. + * @param TIM_DMABurstLength DMA Burst length. + * This parameter can be one value between: + * TIM_DMABURST_LENGTH_1TRANSFER and TIM_DMABURST_LENGTH_18TRANSFERS. + */ +void TIM_ConfigDma(TIM_Module* TIMx, uint16_t TIM_DMABase, uint16_t TIM_DMABurstLength) +{ + /* Check the parameters */ + assert_param(IsTimList4Module(TIMx)); + assert_param(IsTimDmaBase(TIM_DMABase)); + assert_param(IsTimDmaLength(TIM_DMABurstLength)); + /* Set the DMA Base and the DMA Burst Length */ + TIMx->DCTRL = TIM_DMABase | TIM_DMABurstLength; +} + +/** + * @brief Enables or disables the TIMx's DMA Requests. + * @param TIMx where x can be 1, 2, 3, 4, 5, 6, 7, 8 + * to select the TIM peripheral. + * @param TIM_DMASource specifies the DMA Request sources. + * This parameter can be any combination of the following values: + * @arg TIM_DMA_UPDATE TIM update Interrupt source + * @arg TIM_DMA_CC1 TIM Capture Compare 1 DMA source + * @arg TIM_DMA_CC2 TIM Capture Compare 2 DMA source + * @arg TIM_DMA_CC3 TIM Capture Compare 3 DMA source + * @arg TIM_DMA_CC4 TIM Capture Compare 4 DMA source + * @arg TIM_DMA_COM TIM Commutation DMA source + * @arg TIM_DMA_TRIG TIM Trigger DMA source + * @param Cmd new state of the DMA Request sources. + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_EnableDma(TIM_Module* TIMx, uint16_t TIM_DMASource, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimList9Module(TIMx)); + assert_param(IsTimDmaSrc(TIM_DMASource)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the DMA sources */ + TIMx->DINTEN |= TIM_DMASource; + } + else + { + /* Disable the DMA sources */ + TIMx->DINTEN &= (uint16_t)~TIM_DMASource; + } +} + +/** + * @brief Configures the TIMx internal Clock + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 + * to select the TIM peripheral. + */ +void TIM_ConfigInternalClk(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + /* Disable slave mode to clock the prescaler directly with the internal clock */ + TIMx->SMCTRL &= (uint16_t)(~((uint16_t)TIM_SMCTRL_SMSEL)); +} + +/** + * @brief Configures the TIMx Internal Trigger as External Clock + * @param TIMx where x can be 1, 2, 3, 4, 5 to select the TIM peripheral. + * @param TIM_InputTriggerSource Trigger source. + * This parameter can be one of the following values: + * @arg TIM_TRIG_SEL_IN_TR0 Internal Trigger 0 + * @arg TIM_TRIG_SEL_IN_TR1 Internal Trigger 1 + * @arg TIM_TRIG_SEL_IN_TR2 Internal Trigger 2 + * @arg TIM_TRIG_SEL_IN_TR3 Internal Trigger 3 + */ +void TIM_ConfigInternalTrigToExt(TIM_Module* TIMx, uint16_t TIM_InputTriggerSource) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimInterTrigSel(TIM_InputTriggerSource)); + /* Select the Internal Trigger */ + TIM_SelectInputTrig(TIMx, TIM_InputTriggerSource); + /* Select the External clock mode1 */ + TIMx->SMCTRL |= TIM_SLAVE_MODE_EXT1; +} + +/** + * @brief Configures the TIMx Trigger as External Clock + * @param TIMx where x can be 1, 2, 3, 4, 5 to select the TIM peripheral. + * @param TIM_TIxExternalCLKSource Trigger source. + * This parameter can be one of the following values: + * @arg TIM_EXT_CLK_SRC_TI1ED TI1 Edge Detector + * @arg TIM_EXT_CLK_SRC_TI1 Filtered Timer Input 1 + * @arg TIM_EXT_CLK_SRC_TI2 Filtered Timer Input 2 + * @param IcPolarity specifies the TIx Polarity. + * This parameter can be one of the following values: + * @arg TIM_IC_POLARITY_RISING + * @arg TIM_IC_POLARITY_FALLING + * @param ICFilter specifies the filter value. + * This parameter must be a value between 0x0 and 0xF. + */ +void TIM_ConfigExtTrigAsClk(TIM_Module* TIMx, uint16_t TIM_TIxExternalCLKSource, uint16_t IcPolarity, uint16_t ICFilter) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimExtClkSrc(TIM_TIxExternalCLKSource)); + assert_param(IsTimIcPalaritySingleEdge(IcPolarity)); + assert_param(IsTimInCapFilter(ICFilter)); + /* Configure the Timer Input Clock Source */ + if (TIM_TIxExternalCLKSource == TIM_EXT_CLK_SRC_TI2) + { + ConfigTI2(TIMx, IcPolarity, TIM_IC_SELECTION_DIRECTTI, ICFilter); + } + else + { + ConfigTI1(TIMx, IcPolarity, TIM_IC_SELECTION_DIRECTTI, ICFilter); + } + /* Select the Trigger source */ + TIM_SelectInputTrig(TIMx, TIM_TIxExternalCLKSource); + /* Select the External clock mode1 */ + TIMx->SMCTRL |= TIM_SLAVE_MODE_EXT1; +} + +/** + * @brief Configures the External clock Mode1 + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ExtTRGPrescaler The external Trigger Prescaler. + * This parameter can be one of the following values: + * @arg TIM_EXT_TRG_PSC_OFF ETRP Prescaler OFF. + * @arg TIM_EXT_TRG_PSC_DIV2 ETRP frequency divided by 2. + * @arg TIM_EXT_TRG_PSC_DIV4 ETRP frequency divided by 4. + * @arg TIM_EXT_TRG_PSC_DIV8 ETRP frequency divided by 8. + * @param TIM_ExtTRGPolarity The external Trigger Polarity. + * This parameter can be one of the following values: + * @arg TIM_EXT_TRIG_POLARITY_INVERTED active low or falling edge active. + * @arg TIM_EXT_TRIG_POLARITY_NONINVERTED active high or rising edge active. + * @param ExtTRGFilter External Trigger Filter. + * This parameter must be a value between 0x00 and 0x0F + */ +void TIM_ConfigExtClkMode1(TIM_Module* TIMx, + uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter) +{ + uint16_t tmpsmcr = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimExtPreDiv(TIM_ExtTRGPrescaler)); + assert_param(IsTimExtTrigPolarity(TIM_ExtTRGPolarity)); + assert_param(IsTimExtTrigFilter(ExtTRGFilter)); + /* Configure the ETR Clock source */ + TIM_ConfigExtTrig(TIMx, TIM_ExtTRGPrescaler, TIM_ExtTRGPolarity, ExtTRGFilter); + + /* Get the TIMx SMCTRL register value */ + tmpsmcr = TIMx->SMCTRL; + /* Reset the SMS Bits */ + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCTRL_SMSEL)); + /* Select the External clock mode1 */ + tmpsmcr |= TIM_SLAVE_MODE_EXT1; + /* Select the Trigger selection : ETRF */ + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCTRL_TSEL)); + tmpsmcr |= TIM_TRIG_SEL_ETRF; + /* Write to TIMx SMCTRL */ + TIMx->SMCTRL = tmpsmcr; +} + +/** + * @brief Configures the External clock Mode2 + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ExtTRGPrescaler The external Trigger Prescaler. + * This parameter can be one of the following values: + * @arg TIM_EXT_TRG_PSC_OFF ETRP Prescaler OFF. + * @arg TIM_EXT_TRG_PSC_DIV2 ETRP frequency divided by 2. + * @arg TIM_EXT_TRG_PSC_DIV4 ETRP frequency divided by 4. + * @arg TIM_EXT_TRG_PSC_DIV8 ETRP frequency divided by 8. + * @param TIM_ExtTRGPolarity The external Trigger Polarity. + * This parameter can be one of the following values: + * @arg TIM_EXT_TRIG_POLARITY_INVERTED active low or falling edge active. + * @arg TIM_EXT_TRIG_POLARITY_NONINVERTED active high or rising edge active. + * @param ExtTRGFilter External Trigger Filter. + * This parameter must be a value between 0x00 and 0x0F + */ +void TIM_ConfigExtClkMode2(TIM_Module* TIMx, + uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter) +{ + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimExtPreDiv(TIM_ExtTRGPrescaler)); + assert_param(IsTimExtTrigPolarity(TIM_ExtTRGPolarity)); + assert_param(IsTimExtTrigFilter(ExtTRGFilter)); + /* Configure the ETR Clock source */ + TIM_ConfigExtTrig(TIMx, TIM_ExtTRGPrescaler, TIM_ExtTRGPolarity, ExtTRGFilter); + /* Enable the External clock mode2 */ + TIMx->SMCTRL |= TIM_SMCTRL_EXCEN; +} + +/** + * @brief Configures the TIMx External Trigger (ETR). + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ExtTRGPrescaler The external Trigger Prescaler. + * This parameter can be one of the following values: + * @arg TIM_EXT_TRG_PSC_OFF ETRP Prescaler OFF. + * @arg TIM_EXT_TRG_PSC_DIV2 ETRP frequency divided by 2. + * @arg TIM_EXT_TRG_PSC_DIV4 ETRP frequency divided by 4. + * @arg TIM_EXT_TRG_PSC_DIV8 ETRP frequency divided by 8. + * @param TIM_ExtTRGPolarity The external Trigger Polarity. + * This parameter can be one of the following values: + * @arg TIM_EXT_TRIG_POLARITY_INVERTED active low or falling edge active. + * @arg TIM_EXT_TRIG_POLARITY_NONINVERTED active high or rising edge active. + * @param ExtTRGFilter External Trigger Filter. + * This parameter must be a value between 0x00 and 0x0F + */ +void TIM_ConfigExtTrig(TIM_Module* TIMx, + uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter) +{ + uint16_t tmpsmcr = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimExtPreDiv(TIM_ExtTRGPrescaler)); + assert_param(IsTimExtTrigPolarity(TIM_ExtTRGPolarity)); + assert_param(IsTimExtTrigFilter(ExtTRGFilter)); + tmpsmcr = TIMx->SMCTRL; + /* Reset the ETR Bits */ + tmpsmcr &= SMCTRL_ETR_MASK; + /* Set the Prescaler, the Filter value and the Polarity */ + tmpsmcr |= + (uint16_t)(TIM_ExtTRGPrescaler | (uint16_t)(TIM_ExtTRGPolarity | (uint16_t)(ExtTRGFilter << (uint16_t)8))); + /* Write to TIMx SMCTRL */ + TIMx->SMCTRL = tmpsmcr; +} + +/** + * @brief Configures the TIMx Prescaler. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param Prescaler specifies the Prescaler Register value + * @param TIM_PSCReloadMode specifies the TIM Prescaler Reload mode + * This parameter can be one of the following values: + * @arg TIM_PSC_RELOAD_MODE_UPDATE The Prescaler is loaded at the update event. + * @arg TIM_PSC_RELOAD_MODE_IMMEDIATE The Prescaler is loaded immediately. + */ +void TIM_ConfigPrescaler(TIM_Module* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimPscReloadMode(TIM_PSCReloadMode)); + /* Set the Prescaler value */ + TIMx->PSC = Prescaler; + /* Set or reset the UG Bit */ + TIMx->EVTGEN = TIM_PSCReloadMode; +} + +/** + * @brief Specifies the TIMx Counter Mode to be used. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param CntMode specifies the Counter Mode to be used + * This parameter can be one of the following values: + * @arg TIM_CNT_MODE_UP TIM Up Counting Mode + * @arg TIM_CNT_MODE_DOWN TIM Down Counting Mode + * @arg TIM_CNT_MODE_CENTER_ALIGN1 TIM Center Aligned Mode1 + * @arg TIM_CNT_MODE_CENTER_ALIGN2 TIM Center Aligned Mode2 + * @arg TIM_CNT_MODE_CENTER_ALIGN3 TIM Center Aligned Mode3 + */ +void TIM_ConfigCntMode(TIM_Module* TIMx, uint16_t CntMode) +{ + uint32_t tmpcr1 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimCntMode(CntMode)); + tmpcr1 = TIMx->CTRL1; + /* Reset the CMS and DIR Bits */ + tmpcr1 &= (uint32_t)(~((uint32_t)(TIM_CTRL1_DIR | TIM_CTRL1_CAMSEL))); + /* Set the Counter Mode */ + tmpcr1 |= CntMode; + /* Write to TIMx CTRL1 register */ + TIMx->CTRL1 = tmpcr1; +} + +/** + * @brief Selects the Input Trigger source + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @param TIM_InputTriggerSource The Input Trigger source. + * This parameter can be one of the following values: + * @arg TIM_TRIG_SEL_IN_TR0 Internal Trigger 0 + * @arg TIM_TRIG_SEL_IN_TR1 Internal Trigger 1 + * @arg TIM_TRIG_SEL_IN_TR2 Internal Trigger 2 + * @arg TIM_TRIG_SEL_IN_TR3 Internal Trigger 3 + * @arg TIM_TRIG_SEL_TI1F_ED TI1 Edge Detector + * @arg TIM_TRIG_SEL_TI1FP1 Filtered Timer Input 1 + * @arg TIM_TRIG_SEL_TI2FP2 Filtered Timer Input 2 + * @arg TIM_TRIG_SEL_ETRF External Trigger input + */ +void TIM_SelectInputTrig(TIM_Module* TIMx, uint16_t TIM_InputTriggerSource) +{ + uint16_t tmpsmcr = 0; + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimTrigSel(TIM_InputTriggerSource)); + /* Get the TIMx SMCTRL register value */ + tmpsmcr = TIMx->SMCTRL; + /* Reset the TS Bits */ + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCTRL_TSEL)); + /* Set the Input Trigger source */ + tmpsmcr |= TIM_InputTriggerSource; + /* Write to TIMx SMCTRL */ + TIMx->SMCTRL = tmpsmcr; +} + +/** + * @brief Configures the TIMx Encoder Interface. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_EncoderMode specifies the TIMx Encoder Mode. + * This parameter can be one of the following values: + * @arg TIM_ENCODE_MODE_TI1 Counter counts on TI1FP1 edge depending on TI2FP2 level. + * @arg TIM_ENCODE_MODE_TI2 Counter counts on TI2FP2 edge depending on TI1FP1 level. + * @arg TIM_ENCODE_MODE_TI12 Counter counts on both TI1FP1 and TI2FP2 edges depending + * on the level of the other input. + * @param TIM_IC1Polarity specifies the IC1 Polarity + * This parameter can be one of the following values: + * @arg TIM_IC_POLARITY_FALLING IC Falling edge. + * @arg TIM_IC_POLARITY_RISING IC Rising edge. + * @param TIM_IC2Polarity specifies the IC2 Polarity + * This parameter can be one of the following values: + * @arg TIM_IC_POLARITY_FALLING IC Falling edge. + * @arg TIM_IC_POLARITY_RISING IC Rising edge. + */ +void TIM_ConfigEncoderInterface(TIM_Module* TIMx, + uint16_t TIM_EncoderMode, + uint16_t TIM_IC1Polarity, + uint16_t TIM_IC2Polarity) +{ + uint16_t tmpsmcr = 0; + uint16_t tmpccmr1 = 0; + uint32_t tmpccer = 0; + + /* Check the parameters */ + assert_param(IsTimList5Module(TIMx)); + assert_param(IsTimEncodeMode(TIM_EncoderMode)); + assert_param(IsTimIcPalaritySingleEdge(TIM_IC1Polarity)); + assert_param(IsTimIcPalaritySingleEdge(TIM_IC2Polarity)); + + /* Get the TIMx SMCTRL register value */ + tmpsmcr = TIMx->SMCTRL; + + /* Get the TIMx CCMOD1 register value */ + tmpccmr1 = TIMx->CCMOD1; + + /* Get the TIMx CCEN register value */ + tmpccer = TIMx->CCEN; + + /* Set the encoder Mode */ + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCTRL_SMSEL)); + tmpsmcr |= TIM_EncoderMode; + + /* Select the Capture Compare 1 and the Capture Compare 2 as input */ + tmpccmr1 &= (uint16_t)(((uint16_t) ~((uint16_t)TIM_CCMOD1_CC1SEL)) & (uint16_t)(~((uint16_t)TIM_CCMOD1_CC2SEL))); + tmpccmr1 |= TIM_CCMOD1_CC1SEL_0 | TIM_CCMOD1_CC2SEL_0; + + /* Set the TI1 and the TI2 Polarities */ + tmpccer &= (uint32_t)(((uint32_t) ~((uint32_t)TIM_CCEN_CC1P)) & ((uint32_t) ~((uint32_t)TIM_CCEN_CC2P))); + tmpccer |= (uint32_t)(TIM_IC1Polarity | (uint16_t)(TIM_IC2Polarity << (uint16_t)4)); + + /* Write to TIMx SMCTRL */ + TIMx->SMCTRL = tmpsmcr; + /* Write to TIMx CCMOD1 */ + TIMx->CCMOD1 = tmpccmr1; + /* Write to TIMx CCEN */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Forces the TIMx output 1 waveform to active or inactive level. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param TIM_ForcedAction specifies the forced Action to be set to the output waveform. + * This parameter can be one of the following values: + * @arg TIM_FORCED_ACTION_ACTIVE Force active level on OC1REF + * @arg TIM_FORCED_ACTION_INACTIVE Force inactive level on OC1REF. + */ +void TIM_ConfigForcedOc1(TIM_Module* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimForceActive(TIM_ForcedAction)); + tmpccmr1 = TIMx->CCMOD1; + /* Reset the OC1M Bits */ + tmpccmr1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_OC1M); + /* Configure The Forced output Mode */ + tmpccmr1 |= TIM_ForcedAction; + /* Write to TIMx CCMOD1 register */ + TIMx->CCMOD1 = tmpccmr1; +} + +/** + * @brief Forces the TIMx output 2 waveform to active or inactive level. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @param TIM_ForcedAction specifies the forced Action to be set to the output waveform. + * This parameter can be one of the following values: + * @arg TIM_FORCED_ACTION_ACTIVE Force active level on OC2REF + * @arg TIM_FORCED_ACTION_INACTIVE Force inactive level on OC2REF. + */ +void TIM_ConfigForcedOc2(TIM_Module* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimForceActive(TIM_ForcedAction)); + tmpccmr1 = TIMx->CCMOD1; + /* Reset the OC2M Bits */ + tmpccmr1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_OC2M); + /* Configure The Forced output Mode */ + tmpccmr1 |= (uint16_t)(TIM_ForcedAction << 8); + /* Write to TIMx CCMOD1 register */ + TIMx->CCMOD1 = tmpccmr1; +} + +/** + * @brief Forces the TIMx output 3 waveform to active or inactive level. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ForcedAction specifies the forced Action to be set to the output waveform. + * This parameter can be one of the following values: + * @arg TIM_FORCED_ACTION_ACTIVE Force active level on OC3REF + * @arg TIM_FORCED_ACTION_INACTIVE Force inactive level on OC3REF. + */ +void TIM_ConfigForcedOc3(TIM_Module* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimForceActive(TIM_ForcedAction)); + tmpccmr2 = TIMx->CCMOD2; + /* Reset the OC1M Bits */ + tmpccmr2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_OC3MD); + /* Configure The Forced output Mode */ + tmpccmr2 |= TIM_ForcedAction; + /* Write to TIMx CCMOD2 register */ + TIMx->CCMOD2 = tmpccmr2; +} + +/** + * @brief Forces the TIMx output 4 waveform to active or inactive level. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ForcedAction specifies the forced Action to be set to the output waveform. + * This parameter can be one of the following values: + * @arg TIM_FORCED_ACTION_ACTIVE Force active level on OC4REF + * @arg TIM_FORCED_ACTION_INACTIVE Force inactive level on OC4REF. + */ +void TIM_ConfigForcedOc4(TIM_Module* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimForceActive(TIM_ForcedAction)); + tmpccmr2 = TIMx->CCMOD2; + /* Reset the OC2M Bits */ + tmpccmr2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_OC4MD); + /* Configure The Forced output Mode */ + tmpccmr2 |= (uint16_t)(TIM_ForcedAction << 8); + /* Write to TIMx CCMOD2 register */ + TIMx->CCMOD2 = tmpccmr2; +} + +/** + * @brief Forces the TIMx output 5 waveform to active or inactive level. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param TIM_ForcedAction specifies the forced Action to be set to the output waveform. + * This parameter can be one of the following values: + * @arg TIM_FORCED_ACTION_ACTIVE Force active level on OC5REF + * @arg TIM_FORCED_ACTION_INACTIVE Force inactive level on OC5REF. + */ +void TIM_ConfigForcedOc5(TIM_Module* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr3 = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimForceActive(TIM_ForcedAction)); + tmpccmr3 = TIMx->CCMOD3; + /* Reset the OC2M Bits */ + tmpccmr3 &= (uint16_t) ~((uint16_t)TIM_CCMOD3_OC5MD); + /* Configure The Forced output Mode */ + tmpccmr3 |= (uint16_t)(TIM_ForcedAction); + /* Write to TIMx CCMOD2 register */ + TIMx->CCMOD3 = tmpccmr3; +} + +/** + * @brief Forces the TIMx output 6 waveform to active or inactive level. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param TIM_ForcedAction specifies the forced Action to be set to the output waveform. + * This parameter can be one of the following values: + * @arg TIM_FORCED_ACTION_ACTIVE Force active level on OC6REF + * @arg TIM_FORCED_ACTION_INACTIVE Force inactive level on OC6REF. + */ +void TIM_ConfigForcedOc6(TIM_Module* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr3 = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimForceActive(TIM_ForcedAction)); + tmpccmr3 = TIMx->CCMOD3; + /* Reset the OC2M Bits */ + tmpccmr3 &= (uint16_t) ~((uint16_t)TIM_CCMOD3_OC6MD); + /* Configure The Forced output Mode */ + tmpccmr3 |= (uint16_t)(TIM_ForcedAction << 8); + /* Write to TIMx CCMOD2 register */ + TIMx->CCMOD3 = tmpccmr3; +} + +/** + * @brief Enables or disables TIMx peripheral Preload register on AR. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param Cmd new state of the TIMx peripheral Preload register + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_ConfigArPreload(TIM_Module* TIMx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Set the AR Preload Bit */ + TIMx->CTRL1 |= TIM_CTRL1_ARPEN; + } + else + { + /* Reset the AR Preload Bit */ + TIMx->CTRL1 &= (uint32_t) ~((uint32_t)TIM_CTRL1_ARPEN); + } +} + +/** + * @brief Selects the TIM peripheral Commutation event. + * @param TIMx where x can be 1, 8 to select the TIMx peripheral + * @param Cmd new state of the Commutation event. + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_SelectComEvt(TIM_Module* TIMx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimList2Module(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Set the COM Bit */ + TIMx->CTRL2 |= TIM_CTRL2_CCUSEL; + } + else + { + /* Reset the COM Bit */ + TIMx->CTRL2 &= (uint32_t) ~((uint32_t)TIM_CTRL2_CCUSEL); + } +} + +/** + * @brief Selects the TIMx peripheral Capture Compare DMA source. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select + * the TIM peripheral. + * @param Cmd new state of the Capture Compare DMA source + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_SelectCapCmpDmaSrc(TIM_Module* TIMx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimList4Module(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Set the CCDS Bit */ + TIMx->CTRL2 |= TIM_CTRL2_CCDSEL; + } + else + { + /* Reset the CCDS Bit */ + TIMx->CTRL2 &= (uint32_t) ~((uint32_t)TIM_CTRL2_CCDSEL); + } +} + +/** + * @brief Sets or Resets the TIM peripheral Capture Compare Preload Control bit. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 + * to select the TIMx peripheral + * @param Cmd new state of the Capture Compare Preload Control bit + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_EnableCapCmpPreloadControl(TIM_Module* TIMx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimList5Module(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Set the CCPC Bit */ + TIMx->CTRL2 |= TIM_CTRL2_CCPCTL; + } + else + { + /* Reset the CCPC Bit */ + TIMx->CTRL2 &= (uint32_t) ~((uint32_t)TIM_CTRL2_CCPCTL); + } +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCDAT1. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param TIM_OCPreload new state of the TIMx peripheral Preload register + * This parameter can be one of the following values: + * @arg TIM_OC_PRE_LOAD_ENABLE + * @arg TIM_OC_PRE_LOAD_DISABLE + */ +void TIM_ConfigOc1Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimOcPreLoadState(TIM_OCPreload)); + tmpccmr1 = TIMx->CCMOD1; + /* Reset the OC1PE Bit */ + tmpccmr1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_OC1PEN); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr1 |= TIM_OCPreload; + /* Write to TIMx CCMOD1 register */ + TIMx->CCMOD1 = tmpccmr1; +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCDAT2. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select + * the TIM peripheral. + * @param TIM_OCPreload new state of the TIMx peripheral Preload register + * This parameter can be one of the following values: + * @arg TIM_OC_PRE_LOAD_ENABLE + * @arg TIM_OC_PRE_LOAD_DISABLE + */ +void TIM_ConfigOc2Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimOcPreLoadState(TIM_OCPreload)); + tmpccmr1 = TIMx->CCMOD1; + /* Reset the OC2PE Bit */ + tmpccmr1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_OC2PEN); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr1 |= (uint16_t)(TIM_OCPreload << 8); + /* Write to TIMx CCMOD1 register */ + TIMx->CCMOD1 = tmpccmr1; +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCDAT3. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCPreload new state of the TIMx peripheral Preload register + * This parameter can be one of the following values: + * @arg TIM_OC_PRE_LOAD_ENABLE + * @arg TIM_OC_PRE_LOAD_DISABLE + */ +void TIM_ConfigOc3Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcPreLoadState(TIM_OCPreload)); + tmpccmr2 = TIMx->CCMOD2; + /* Reset the OC3PE Bit */ + tmpccmr2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_OC3PEN); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr2 |= TIM_OCPreload; + /* Write to TIMx CCMOD2 register */ + TIMx->CCMOD2 = tmpccmr2; +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCDAT4. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCPreload new state of the TIMx peripheral Preload register + * This parameter can be one of the following values: + * @arg TIM_OC_PRE_LOAD_ENABLE + * @arg TIM_OC_PRE_LOAD_DISABLE + */ +void TIM_ConfigOc4Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcPreLoadState(TIM_OCPreload)); + tmpccmr2 = TIMx->CCMOD2; + /* Reset the OC4PE Bit */ + tmpccmr2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_OC4PEN); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr2 |= (uint16_t)(TIM_OCPreload << 8); + /* Write to TIMx CCMOD2 register */ + TIMx->CCMOD2 = tmpccmr2; +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCDAT5. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param TIM_OCPreload new state of the TIMx peripheral Preload register + * This parameter can be one of the following values: + * @arg TIM_OC_PRE_LOAD_ENABLE + * @arg TIM_OC_PRE_LOAD_DISABLE + */ +void TIM_ConfigOc5Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr3 = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcPreLoadState(TIM_OCPreload)); + tmpccmr3 = TIMx->CCMOD3; + /* Reset the OC5PE Bit */ + tmpccmr3 &= (uint16_t) ~((uint16_t)TIM_CCMOD3_OC5PEN); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr3 |= (uint16_t)(TIM_OCPreload); + /* Write to TIMx CCMOD3 register */ + TIMx->CCMOD3 = tmpccmr3; +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCDAT6. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param TIM_OCPreload new state of the TIMx peripheral Preload register + * This parameter can be one of the following values: + * @arg TIM_OC_PRE_LOAD_ENABLE + * @arg TIM_OC_PRE_LOAD_DISABLE + */ +void TIM_ConfigOc6Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr3 = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcPreLoadState(TIM_OCPreload)); + tmpccmr3 = TIMx->CCMOD3; + /* Reset the OC6PE Bit */ + tmpccmr3 &= (uint16_t) ~((uint16_t)TIM_CCMOD3_OC6PEN); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr3 |= (uint16_t)(TIM_OCPreload << 8); + /* Write to TIMx CCMOD3 register */ + TIMx->CCMOD3 = tmpccmr3; +} + +/** + * @brief Configures the TIMx Output Compare 1 Fast feature. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param TIM_OCFast new state of the Output Compare Fast Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OC_FAST_ENABLE TIM output compare fast enable + * @arg TIM_OC_FAST_DISABLE TIM output compare fast disable + */ +void TIM_ConfigOc1Fast(TIM_Module* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimOcFastState(TIM_OCFast)); + /* Get the TIMx CCMOD1 register value */ + tmpccmr1 = TIMx->CCMOD1; + /* Reset the OC1FE Bit */ + tmpccmr1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_OC1FEN); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr1 |= TIM_OCFast; + /* Write to TIMx CCMOD1 */ + TIMx->CCMOD1 = tmpccmr1; +} + +/** + * @brief Configures the TIMx Output Compare 2 Fast feature. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select + * the TIM peripheral. + * @param TIM_OCFast new state of the Output Compare Fast Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OC_FAST_ENABLE TIM output compare fast enable + * @arg TIM_OC_FAST_DISABLE TIM output compare fast disable + */ +void TIM_ConfigOc2Fast(TIM_Module* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimOcFastState(TIM_OCFast)); + /* Get the TIMx CCMOD1 register value */ + tmpccmr1 = TIMx->CCMOD1; + /* Reset the OC2FE Bit */ + tmpccmr1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_OC2FEN); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr1 |= (uint16_t)(TIM_OCFast << 8); + /* Write to TIMx CCMOD1 */ + TIMx->CCMOD1 = tmpccmr1; +} + +/** + * @brief Configures the TIMx Output Compare 3 Fast feature. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCFast new state of the Output Compare Fast Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OC_FAST_ENABLE TIM output compare fast enable + * @arg TIM_OC_FAST_DISABLE TIM output compare fast disable + */ +void TIM_ConfigOc3Fast(TIM_Module* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcFastState(TIM_OCFast)); + /* Get the TIMx CCMOD2 register value */ + tmpccmr2 = TIMx->CCMOD2; + /* Reset the OC3FE Bit */ + tmpccmr2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_OC3FEN); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr2 |= TIM_OCFast; + /* Write to TIMx CCMOD2 */ + TIMx->CCMOD2 = tmpccmr2; +} + +/** + * @brief Configures the TIMx Output Compare 4 Fast feature. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCFast new state of the Output Compare Fast Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OC_FAST_ENABLE TIM output compare fast enable + * @arg TIM_OC_FAST_DISABLE TIM output compare fast disable + */ +void TIM_ConfigOc4Fast(TIM_Module* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcFastState(TIM_OCFast)); + /* Get the TIMx CCMOD2 register value */ + tmpccmr2 = TIMx->CCMOD2; + /* Reset the OC4FE Bit */ + tmpccmr2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_OC4FEN); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr2 |= (uint16_t)(TIM_OCFast << 8); + /* Write to TIMx CCMOD2 */ + TIMx->CCMOD2 = tmpccmr2; +} + +/** + * @brief Configures the TIMx Output Compare 5 Fast feature. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param TIM_OCFast new state of the Output Compare Fast Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OC_FAST_ENABLE TIM output compare fast enable + * @arg TIM_OC_FAST_DISABLE TIM output compare fast disable + */ +void TIM_ConfigOc5Fast(TIM_Module* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr3 = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcFastState(TIM_OCFast)); + /* Get the TIMx CCMOD2 register value */ + tmpccmr3 = TIMx->CCMOD3; + /* Reset the OC4FE Bit */ + tmpccmr3 &= (uint16_t) ~((uint16_t)TIM_CCMOD3_OC5FEN); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr3 |= (uint16_t)(TIM_OCFast); + /* Write to TIMx CCMOD3 */ + TIMx->CCMOD3 = tmpccmr3; +} + +/** + * @brief Configures the TIMx Output Compare 6 Fast feature. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param TIM_OCFast new state of the Output Compare Fast Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OC_FAST_ENABLE TIM output compare fast enable + * @arg TIM_OC_FAST_DISABLE TIM output compare fast disable + */ +void TIM_ConfigOc6Fast(TIM_Module* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr3 = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcFastState(TIM_OCFast)); + /* Get the TIMx CCMOD2 register value */ + tmpccmr3 = TIMx->CCMOD3; + /* Reset the OC4FE Bit */ + tmpccmr3 &= (uint16_t) ~((uint16_t)TIM_CCMOD3_OC6FEN); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr3 |= (uint16_t)(TIM_OCFast << 8); + /* Write to TIMx CCMOD3 */ + TIMx->CCMOD3 = tmpccmr3; +} + +/** + * @brief Clears or safeguards the OCREF1 signal on an external event + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCClear new state of the Output Compare Clear Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OC_CLR_ENABLE TIM Output clear enable + * @arg TIM_OC_CLR_DISABLE TIM Output clear disable + */ +void TIM_ClrOc1Ref(TIM_Module* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcClrState(TIM_OCClear)); + + tmpccmr1 = TIMx->CCMOD1; + + /* Reset the OC1CE Bit */ + tmpccmr1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_OC1CEN); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr1 |= TIM_OCClear; + /* Write to TIMx CCMOD1 register */ + TIMx->CCMOD1 = tmpccmr1; +} + +/** + * @brief Clears or safeguards the OCREF2 signal on an external event + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCClear new state of the Output Compare Clear Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OC_CLR_ENABLE TIM Output clear enable + * @arg TIM_OC_CLR_DISABLE TIM Output clear disable + */ +void TIM_ClrOc2Ref(TIM_Module* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcClrState(TIM_OCClear)); + tmpccmr1 = TIMx->CCMOD1; + /* Reset the OC2CE Bit */ + tmpccmr1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_OC2CEN); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr1 |= (uint16_t)(TIM_OCClear << 8); + /* Write to TIMx CCMOD1 register */ + TIMx->CCMOD1 = tmpccmr1; +} + +/** + * @brief Clears or safeguards the OCREF3 signal on an external event + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCClear new state of the Output Compare Clear Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OC_CLR_ENABLE TIM Output clear enable + * @arg TIM_OC_CLR_DISABLE TIM Output clear disable + */ +void TIM_ClrOc3Ref(TIM_Module* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcClrState(TIM_OCClear)); + tmpccmr2 = TIMx->CCMOD2; + /* Reset the OC3CE Bit */ + tmpccmr2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_OC3CEN); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr2 |= TIM_OCClear; + /* Write to TIMx CCMOD2 register */ + TIMx->CCMOD2 = tmpccmr2; +} + +/** + * @brief Clears or safeguards the OCREF4 signal on an external event + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCClear new state of the Output Compare Clear Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OC_CLR_ENABLE TIM Output clear enable + * @arg TIM_OC_CLR_DISABLE TIM Output clear disable + */ +void TIM_ClrOc4Ref(TIM_Module* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcClrState(TIM_OCClear)); + tmpccmr2 = TIMx->CCMOD2; + /* Reset the OC4CE Bit */ + tmpccmr2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_OC4CEN); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr2 |= (uint16_t)(TIM_OCClear << 8); + /* Write to TIMx CCMOD2 register */ + TIMx->CCMOD2 = tmpccmr2; +} + +/** + * @brief Clears or safeguards the OCREF5 signal on an external event + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param TIM_OCClear new state of the Output Compare Clear Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OC_CLR_ENABLE TIM Output clear enable + * @arg TIM_OC_CLR_DISABLE TIM Output clear disable + */ +void TIM_ClrOc5Ref(TIM_Module* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr3 = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcClrState(TIM_OCClear)); + tmpccmr3 = TIMx->CCMOD3; + /* Reset the OC4CE Bit */ + tmpccmr3 &= (uint16_t) ~((uint16_t)TIM_CCMOD3_OC5CEN); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr3 |= (uint16_t)(TIM_OCClear); + /* Write to TIMx CCMOD3 register */ + TIMx->CCMOD3 = tmpccmr3; +} + +/** + * @brief Clears or safeguards the OCREF6 signal on an external event + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param TIM_OCClear new state of the Output Compare Clear Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OC_CLR_ENABLE TIM Output clear enable + * @arg TIM_OC_CLR_DISABLE TIM Output clear disable + */ +void TIM_ClrOc6Ref(TIM_Module* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr3 = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcClrState(TIM_OCClear)); + tmpccmr3 = TIMx->CCMOD3; + /* Reset the OC4CE Bit */ + tmpccmr3 &= (uint16_t) ~((uint16_t)TIM_CCMOD3_OC6CEN); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr3 |= (uint16_t)(TIM_OCClear << 8); + /* Write to TIMx CCMOD3 register */ + TIMx->CCMOD3 = tmpccmr3; +} + +/** + * @brief Configures the TIMx channel 1 polarity. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param OcPolarity specifies the OC1 Polarity + * This parameter can be one of the following values: + * @arg TIM_OC_POLARITY_HIGH Output Compare active high + * @arg TIM_OC_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc1Polarity(TIM_Module* TIMx, uint16_t OcPolarity) +{ + uint32_t tmpccer = 0; + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimOcPolarity(OcPolarity)); + tmpccer = TIMx->CCEN; + /* Set or Reset the CC1P Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC1P); + tmpccer |= OcPolarity; + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configures the TIMx Channel 1N polarity. + * @param TIMx where x can be 1, 8 to select the TIM peripheral. + * @param OcNPolarity specifies the OC1N Polarity + * This parameter can be one of the following values: + * @arg TIM_OCN_POLARITY_HIGH Output Compare active high + * @arg TIM_OCN_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc1NPolarity(TIM_Module* TIMx, uint16_t OcNPolarity) +{ + uint32_t tmpccer = 0; + /* Check the parameters */ + assert_param(IsTimList2Module(TIMx)); + assert_param(IsTimOcnPolarity(OcNPolarity)); + + tmpccer = TIMx->CCEN; + /* Set or Reset the CC1NP Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC1NP); + tmpccer |= OcNPolarity; + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configures the TIMx channel 2 polarity. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @param OcPolarity specifies the OC2 Polarity + * This parameter can be one of the following values: + * @arg TIM_OC_POLARITY_HIGH Output Compare active high + * @arg TIM_OC_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc2Polarity(TIM_Module* TIMx, uint16_t OcPolarity) +{ + uint32_t tmpccer = 0; + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimOcPolarity(OcPolarity)); + tmpccer = TIMx->CCEN; + /* Set or Reset the CC2P Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC2P); + tmpccer |= (uint32_t)(OcPolarity << 4); + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configures the TIMx Channel 2N polarity. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param OcNPolarity specifies the OC2N Polarity + * This parameter can be one of the following values: + * @arg TIM_OCN_POLARITY_HIGH Output Compare active high + * @arg TIM_OCN_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc2NPolarity(TIM_Module* TIMx, uint16_t OcNPolarity) +{ + uint32_t tmpccer = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcnPolarity(OcNPolarity)); + + tmpccer = TIMx->CCEN; + /* Set or Reset the CC2NP Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC2NP); + tmpccer |= (uint32_t)(OcNPolarity << 4); + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configures the TIMx channel 3 polarity. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param OcPolarity specifies the OC3 Polarity + * This parameter can be one of the following values: + * @arg TIM_OC_POLARITY_HIGH Output Compare active high + * @arg TIM_OC_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc3Polarity(TIM_Module* TIMx, uint16_t OcPolarity) +{ + uint32_t tmpccer = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcPolarity(OcPolarity)); + tmpccer = TIMx->CCEN; + /* Set or Reset the CC3P Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC3P); + tmpccer |= (uint32_t)(OcPolarity << 8); + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configures the TIMx Channel 3N polarity. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param OcNPolarity specifies the OC3N Polarity + * This parameter can be one of the following values: + * @arg TIM_OCN_POLARITY_HIGH Output Compare active high + * @arg TIM_OCN_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc3NPolarity(TIM_Module* TIMx, uint16_t OcNPolarity) +{ + uint32_t tmpccer = 0; + + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcnPolarity(OcNPolarity)); + + tmpccer = TIMx->CCEN; + /* Set or Reset the CC3NP Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC3NP); + tmpccer |= (uint32_t)(OcNPolarity << 8); + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configures the TIMx channel 4 polarity. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param OcPolarity specifies the OC4 Polarity + * This parameter can be one of the following values: + * @arg TIM_OC_POLARITY_HIGH Output Compare active high + * @arg TIM_OC_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc4Polarity(TIM_Module* TIMx, uint16_t OcPolarity) +{ + uint32_t tmpccer = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcPolarity(OcPolarity)); + tmpccer = TIMx->CCEN; + /* Set or Reset the CC4P Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC4P); + tmpccer |= (uint32_t)(OcPolarity << 12); + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configures the TIMx channel 5 polarity. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param OcPolarity specifies the OC5 Polarity + * This parameter can be one of the following values: + * @arg TIM_OC_POLARITY_HIGH Output Compare active high + * @arg TIM_OC_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc5Polarity(TIM_Module* TIMx, uint16_t OcPolarity) +{ + uint32_t tmpccer = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcPolarity(OcPolarity)); + tmpccer = TIMx->CCEN; + /* Set or Reset the CC5P Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC5P); + tmpccer |= (uint32_t)(OcPolarity << 16); + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configures the TIMx channel 6 polarity. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param OcPolarity specifies the OC6 Polarity + * This parameter can be one of the following values: + * @arg TIM_OC_POLARITY_HIGH Output Compare active high + * @arg TIM_OC_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc6Polarity(TIM_Module* TIMx, uint16_t OcPolarity) +{ + uint32_t tmpccer = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcPolarity(OcPolarity)); + tmpccer = TIMx->CCEN; + /* Set or Reset the CC6P Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC6P); + tmpccer |= (uint32_t)(OcPolarity << 20); + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Enables or disables the TIM Capture Compare Channel x. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param Channel specifies the TIM Channel + * This parameter can be one of the following values: + * @arg TIM_CH_1 TIM Channel 1 + * @arg TIM_CH_2 TIM Channel 2 + * @arg TIM_CH_3 TIM Channel 3 + * @arg TIM_CH_4 TIM Channel 4 + * @param TIM_CCx specifies the TIM Channel CCxE bit new state. + * This parameter can be: TIM_CAP_CMP_ENABLE or TIM_CAP_CMP_DISABLE. + */ +void TIM_EnableCapCmpCh(TIM_Module* TIMx, uint16_t Channel, uint32_t TIM_CCx) +{ + uint16_t tmp = 0; + + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimCh(Channel)); + assert_param(IsTimCapCmpState(TIM_CCx)); + + tmp = CAPCMPEN_CCE_SET << Channel; + + /* Reset the CCxE Bit */ + TIMx->CCEN &= (uint32_t)~tmp; + + /* Set or reset the CCxE Bit */ + TIMx->CCEN |= (uint32_t)(TIM_CCx << Channel); +} + +/** + * @brief Enables or disables the TIM Capture Compare Channel xN. + * @param TIMx where x can be 1, 8 to select the TIM peripheral. + * @param Channel specifies the TIM Channel + * This parameter can be one of the following values: + * @arg TIM_CH_1 TIM Channel 1 + * @arg TIM_CH_2 TIM Channel 2 + * @arg TIM_CH_3 TIM Channel 3 + * @param TIM_CCxN specifies the TIM Channel CCxNE bit new state. + * This parameter can be: TIM_CAP_CMP_N_ENABLE or TIM_CAP_CMP_N_DISABLE. + */ +void TIM_EnableCapCmpChN(TIM_Module* TIMx, uint16_t Channel, uint32_t TIM_CCxN) +{ + uint16_t tmp = 0; + + /* Check the parameters */ + assert_param(IsTimList2Module(TIMx)); + assert_param(IsTimComplementaryCh(Channel)); + assert_param(IsTimCapCmpNState(TIM_CCxN)); + + tmp = CAPCMPEN_CCNE_SET << Channel; + + /* Reset the CCxNE Bit */ + TIMx->CCEN &= (uint32_t)~tmp; + + /* Set or reset the CCxNE Bit */ + TIMx->CCEN |= (uint32_t)(TIM_CCxN << Channel); +} + +/** + * @brief Selects the TIM Output Compare Mode. + * @note This function disables the selected channel before changing the Output + * Compare Mode. + * User has to enable this channel using TIM_EnableCapCmpCh and TIM_EnableCapCmpChN functions. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param Channel specifies the TIM Channel + * This parameter can be one of the following values: + * @arg TIM_CH_1 TIM Channel 1 + * @arg TIM_CH_2 TIM Channel 2 + * @arg TIM_CH_3 TIM Channel 3 + * @arg TIM_CH_4 TIM Channel 4 + * @param OcMode specifies the TIM Output Compare Mode. + * This parameter can be one of the following values: + * @arg TIM_OCMODE_TIMING + * @arg TIM_OCMODE_ACTIVE + * @arg TIM_OCMODE_TOGGLE + * @arg TIM_OCMODE_PWM1 + * @arg TIM_OCMODE_PWM2 + * @arg TIM_FORCED_ACTION_ACTIVE + * @arg TIM_FORCED_ACTION_INACTIVE + */ +void TIM_SelectOcMode(TIM_Module* TIMx, uint16_t Channel, uint16_t OcMode) +{ + uint32_t tmp = 0; + uint16_t tmp1 = 0; + + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimCh(Channel)); + assert_param(IsTimOc(OcMode)); + + tmp = (uint32_t)TIMx; + tmp += CAPCMPMOD_OFFSET; + + tmp1 = CAPCMPEN_CCE_SET << (uint16_t)Channel; + + /* Disable the Channel: Reset the CCxE Bit */ + TIMx->CCEN &= (uint16_t)~tmp1; + + if ((Channel == TIM_CH_1) || (Channel == TIM_CH_3)) + { + tmp += (Channel >> 1); + + /* Reset the OCxM bits in the CCMRx register */ + *(__IO uint32_t*)tmp &= (uint32_t) ~((uint32_t)TIM_CCMOD1_OC1M); + + /* Configure the OCxM bits in the CCMRx register */ + *(__IO uint32_t*)tmp |= OcMode; + } + else + { + tmp += (uint16_t)(Channel - (uint16_t)4) >> (uint16_t)1; + + /* Reset the OCxM bits in the CCMRx register */ + *(__IO uint32_t*)tmp &= (uint32_t) ~((uint32_t)TIM_CCMOD1_OC2M); + + /* Configure the OCxM bits in the CCMRx register */ + *(__IO uint32_t*)tmp |= (uint16_t)(OcMode << 8); + } +} + +/** + * @brief Enables or Disables the TIMx Update event. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param Cmd new state of the TIMx UDIS bit + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_EnableUpdateEvt(TIM_Module* TIMx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Set the Update Disable Bit */ + TIMx->CTRL1 |= TIM_CTRL1_UPDIS; + } + else + { + /* Reset the Update Disable Bit */ + TIMx->CTRL1 &= (uint32_t) ~((uint32_t)TIM_CTRL1_UPDIS); + } +} + +/** + * @brief Configures the TIMx Update Request Interrupt source. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param TIM_UpdateSource specifies the Update source. + * This parameter can be one of the following values: + * @arg TIM_UPDATE_SRC_REGULAr Source of update is the counter overflow/underflow + or the setting of UG bit, or an update generation + through the slave mode controller. + * @arg TIM_UPDATE_SRC_GLOBAL Source of update is counter overflow/underflow. + */ +void TIM_ConfigUpdateRequestIntSrc(TIM_Module* TIMx, uint16_t TIM_UpdateSource) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimUpdateSrc(TIM_UpdateSource)); + if (TIM_UpdateSource != TIM_UPDATE_SRC_GLOBAL) + { + /* Set the URS Bit */ + TIMx->CTRL1 |= TIM_CTRL1_UPRS; + } + else + { + /* Reset the URS Bit */ + TIMx->CTRL1 &= (uint32_t) ~((uint32_t)TIM_CTRL1_UPRS); + } +} + +/** + * @brief Enables or disables the TIMx's Hall sensor interface. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param Cmd new state of the TIMx Hall sensor interface. + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_SelectHallSensor(TIM_Module* TIMx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Set the TI1S Bit */ + TIMx->CTRL2 |= TIM_CTRL2_TI1SEL; + } + else + { + /* Reset the TI1S Bit */ + TIMx->CTRL2 &= (uint32_t) ~((uint32_t)TIM_CTRL2_TI1SEL); + } +} + +/** + * @brief Selects the TIMx's One Pulse Mode. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param TIM_OPMode specifies the OPM Mode to be used. + * This parameter can be one of the following values: + * @arg TIM_OPMODE_SINGLE + * @arg TIM_OPMODE_REPET + */ +void TIM_SelectOnePulseMode(TIM_Module* TIMx, uint16_t TIM_OPMode) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimOpMOde(TIM_OPMode)); + /* Reset the OPM Bit */ + TIMx->CTRL1 &= (uint32_t) ~((uint32_t)TIM_CTRL1_ONEPM); + /* Configure the OPM Mode */ + TIMx->CTRL1 |= TIM_OPMode; +} + +/** + * @brief Selects the TIMx Trigger Output Mode. + * @param TIMx where x can be 1, 2, 3, 4, 5, 6, 7, 8 to select the TIM peripheral. + * @param TIM_TRGOSource specifies the Trigger Output source. + * This paramter can be one of the following values: + * + * - For all TIMx + * @arg TIM_TRGO_SRC_RESET The UG bit in the TIM_EVTGEN register is used as the trigger output (TRGO). + * @arg TIM_TRGO_SRC_ENABLE The Counter Enable CEN is used as the trigger output (TRGO). + * @arg TIM_TRGO_SRC_UPDATE The update event is selected as the trigger output (TRGO). + * + * - For all TIMx except TIM6 and TIM7 + * @arg TIM_TRGO_SRC_OC1 The trigger output sends a positive pulse when the CC1IF flag + * is to be set, as soon as a capture or compare match occurs (TRGO). + * @arg TIM_TRGO_SRC_OC1REF OC1REF signal is used as the trigger output (TRGO). + * @arg TIM_TRGO_SRC_OC2REF OC2REF signal is used as the trigger output (TRGO). + * @arg TIM_TRGO_SRC_OC3REF OC3REF signal is used as the trigger output (TRGO). + * @arg TIM_TRGO_SRC_OC4REF OC4REF signal is used as the trigger output (TRGO). + * + */ +void TIM_SelectOutputTrig(TIM_Module* TIMx, uint16_t TIM_TRGOSource) +{ + /* Check the parameters */ + assert_param(IsTimList7Module(TIMx)); + assert_param(IsTimTrgoSrc(TIM_TRGOSource)); + /* Reset the MMS Bits */ + TIMx->CTRL2 &= (uint32_t) ~((uint32_t)TIM_CTRL2_MMSEL); + /* Select the TRGO source */ + TIMx->CTRL2 |= TIM_TRGOSource; +} + + +/** + * @brief Selects the TIMx Ext Source. + * @param Source: 0:selection external ETR(from IOM) signal.1:selection internal ETR(fromo TSC) signal. + * @retval None + */ +void TIM_SelectExtSignalSource(TIM_Module* TIMx, uint16_t ExtSigalSource) +{ + /* Select Ext Signal Source Bits */ + TIMx->CTRL2 &= (uint32_t)~((uint32_t)TIM_ETR_Seletct_innerTsc); + /* Select the TRGO source */ + TIMx->CTRL2 |= ExtSigalSource; +} + + +/** + * @brief Selects the TIMx Slave Mode. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @param TIM_SlaveMode specifies the Timer Slave Mode. + * This parameter can be one of the following values: + * @arg TIM_SLAVE_MODE_RESET Rising edge of the selected trigger signal (TRGI) re-initializes + * the counter and triggers an update of the registers. + * @arg TIM_SLAVE_MODE_GATED The counter clock is enabled when the trigger signal (TRGI) is high. + * @arg TIM_SLAVE_MODE_TRIG The counter starts at a rising edge of the trigger TRGI. + * @arg TIM_SLAVE_MODE_EXT1 Rising edges of the selected trigger (TRGI) clock the counter. + */ +void TIM_SelectSlaveMode(TIM_Module* TIMx, uint16_t TIM_SlaveMode) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimSlaveMode(TIM_SlaveMode)); + /* Reset the SMS Bits */ + TIMx->SMCTRL &= (uint16_t) ~((uint16_t)TIM_SMCTRL_SMSEL); + /* Select the Slave Mode */ + TIMx->SMCTRL |= TIM_SlaveMode; +} + +/** + * @brief Sets or Resets the TIMx Master/Slave Mode. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @param TIM_MasterSlaveMode specifies the Timer Master Slave Mode. + * This parameter can be one of the following values: + * @arg TIM_MASTER_SLAVE_MODE_ENABLE synchronization between the current timer + * and its slaves (through TRGO). + * @arg TIM_MASTER_SLAVE_MODE_DISABLE No action + */ +void TIM_SelectMasterSlaveMode(TIM_Module* TIMx, uint16_t TIM_MasterSlaveMode) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimMasterSlaveMode(TIM_MasterSlaveMode)); + /* Reset the MSM Bit */ + TIMx->SMCTRL &= (uint16_t) ~((uint16_t)TIM_SMCTRL_MSMD); + + /* Set or Reset the MSM Bit */ + TIMx->SMCTRL |= TIM_MasterSlaveMode; +} + +/** + * @brief Sets the TIMx Counter Register value + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param Counter specifies the Counter register new value. + */ +void TIM_SetCnt(TIM_Module* TIMx, uint16_t Counter) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + /* Set the Counter Register value */ + TIMx->CNT = Counter; +} + +/** + * @brief Sets the TIMx Autoreload Register value + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param Autoreload specifies the Autoreload register new value. + */ +void TIM_SetAutoReload(TIM_Module* TIMx, uint16_t Autoreload) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + /* Set the Autoreload Register value */ + TIMx->AR = Autoreload; +} + +/** + * @brief Sets the TIMx Capture Compare1 Register value + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param Compare1 specifies the Capture Compare1 register new value. + */ +void TIM_SetCmp1(TIM_Module* TIMx, uint16_t Compare1) +{ + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + /* Set the Capture Compare1 Register value */ + TIMx->CCDAT1 = Compare1; +} + +/** + * @brief Sets the TIMx Capture Compare2 Register value + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @param Compare2 specifies the Capture Compare2 register new value. + */ +void TIM_SetCmp2(TIM_Module* TIMx, uint16_t Compare2) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + /* Set the Capture Compare2 Register value */ + TIMx->CCDAT2 = Compare2; +} + +/** + * @brief Sets the TIMx Capture Compare3 Register value + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param Compare3 specifies the Capture Compare3 register new value. + */ +void TIM_SetCmp3(TIM_Module* TIMx, uint16_t Compare3) +{ + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + /* Set the Capture Compare3 Register value */ + TIMx->CCDAT3 = Compare3; +} + +/** + * @brief Sets the TIMx Capture Compare4 Register value + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param Compare4 specifies the Capture Compare4 register new value. + */ +void TIM_SetCmp4(TIM_Module* TIMx, uint16_t Compare4) +{ + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + /* Set the Capture Compare4 Register value */ + TIMx->CCDAT4 = Compare4; +} + +/** + * @brief Sets the TIMx Capture Compare5 Register value + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param Compare5 specifies the Capture Compare5 register new value. + */ +void TIM_SetCmp5(TIM_Module* TIMx, uint16_t Compare5) +{ + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + /* Set the Capture Compare4 Register value */ + TIMx->CCDAT5 = Compare5; +} + +/** + * @brief Sets the TIMx Capture Compare4 Register value + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param Compare6 specifies the Capture Compare6 register new value. + */ +void TIM_SetCmp6(TIM_Module* TIMx, uint16_t Compare6) +{ + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + /* Set the Capture Compare4 Register value */ + TIMx->CCDAT6 = Compare6; +} + +/** + * @brief Sets the TIMx Input Capture 1 prescaler. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param TIM_ICPSC specifies the Input Capture1 prescaler new value. + * This parameter can be one of the following values: + * @arg TIM_IC_PSC_DIV1 no prescaler + * @arg TIM_IC_PSC_DIV2 capture is done once every 2 events + * @arg TIM_IC_PSC_DIV4 capture is done once every 4 events + * @arg TIM_IC_PSC_DIV8 capture is done once every 8 events + */ +void TIM_SetInCap1Prescaler(TIM_Module* TIMx, uint16_t TIM_ICPSC) +{ + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimIcPrescaler(TIM_ICPSC)); + /* Reset the IC1PSC Bits */ + TIMx->CCMOD1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_IC1PSC); + /* Set the IC1PSC value */ + TIMx->CCMOD1 |= TIM_ICPSC; +} + +/** + * @brief Sets the TIMx Input Capture 2 prescaler. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @param TIM_ICPSC specifies the Input Capture2 prescaler new value. + * This parameter can be one of the following values: + * @arg TIM_IC_PSC_DIV1 no prescaler + * @arg TIM_IC_PSC_DIV2 capture is done once every 2 events + * @arg TIM_IC_PSC_DIV4 capture is done once every 4 events + * @arg TIM_IC_PSC_DIV8 capture is done once every 8 events + */ +void TIM_SetInCap2Prescaler(TIM_Module* TIMx, uint16_t TIM_ICPSC) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimIcPrescaler(TIM_ICPSC)); + /* Reset the IC2PSC Bits */ + TIMx->CCMOD1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_IC2PSC); + /* Set the IC2PSC value */ + TIMx->CCMOD1 |= (uint16_t)(TIM_ICPSC << 8); +} + +/** + * @brief Sets the TIMx Input Capture 3 prescaler. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ICPSC specifies the Input Capture3 prescaler new value. + * This parameter can be one of the following values: + * @arg TIM_IC_PSC_DIV1 no prescaler + * @arg TIM_IC_PSC_DIV2 capture is done once every 2 events + * @arg TIM_IC_PSC_DIV4 capture is done once every 4 events + * @arg TIM_IC_PSC_DIV8 capture is done once every 8 events + */ +void TIM_SetInCap3Prescaler(TIM_Module* TIMx, uint16_t TIM_ICPSC) +{ + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimIcPrescaler(TIM_ICPSC)); + /* Reset the IC3PSC Bits */ + TIMx->CCMOD2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_IC3PSC); + /* Set the IC3PSC value */ + TIMx->CCMOD2 |= TIM_ICPSC; +} + +/** + * @brief Sets the TIMx Input Capture 4 prescaler. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ICPSC specifies the Input Capture4 prescaler new value. + * This parameter can be one of the following values: + * @arg TIM_IC_PSC_DIV1 no prescaler + * @arg TIM_IC_PSC_DIV2 capture is done once every 2 events + * @arg TIM_IC_PSC_DIV4 capture is done once every 4 events + * @arg TIM_IC_PSC_DIV8 capture is done once every 8 events + */ +void TIM_SetInCap4Prescaler(TIM_Module* TIMx, uint16_t TIM_ICPSC) +{ + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimIcPrescaler(TIM_ICPSC)); + /* Reset the IC4PSC Bits */ + TIMx->CCMOD2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_IC4PSC); + /* Set the IC4PSC value */ + TIMx->CCMOD2 |= (uint16_t)(TIM_ICPSC << 8); +} + +/** + * @brief Sets the TIMx Clock Division value. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select + * the TIM peripheral. + * @param TIM_CKD specifies the clock division value. + * This parameter can be one of the following value: + * @arg TIM_CLK_DIV1 TDTS = Tck_tim + * @arg TIM_CLK_DIV2 TDTS = 2*Tck_tim + * @arg TIM_CLK_DIV4 TDTS = 4*Tck_tim + */ +void TIM_SetClkDiv(TIM_Module* TIMx, uint16_t TIM_CKD) +{ + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimClkDiv(TIM_CKD)); + /* Reset the CKD Bits */ + TIMx->CTRL1 &= (uint32_t) ~((uint32_t)TIM_CTRL1_CLKD); + /* Set the CKD value */ + TIMx->CTRL1 |= TIM_CKD; +} + +/** + * @brief Gets the TIMx Input Capture 1 value. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @return Capture Compare 1 Register value. + */ +uint16_t TIM_GetCap1(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + /* Get the Capture 1 Register value */ + return TIMx->CCDAT1; +} + +/** + * @brief Gets the TIMx Input Capture 2 value. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @return Capture Compare 2 Register value. + */ +uint16_t TIM_GetCap2(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + /* Get the Capture 2 Register value */ + return TIMx->CCDAT2; +} + +/** + * @brief Gets the TIMx Input Capture 3 value. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @return Capture Compare 3 Register value. + */ +uint16_t TIM_GetCap3(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + /* Get the Capture 3 Register value */ + return TIMx->CCDAT3; +} + +/** + * @brief Gets the TIMx Input Capture 4 value. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @return Capture Compare 4 Register value. + */ +uint16_t TIM_GetCap4(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + /* Get the Capture 4 Register value */ + return TIMx->CCDAT4; +} + +/** + * @brief Gets the TIMx Input Capture 5 value. + * @param TIMx where x can be 1 8 to select the TIM peripheral. + * @return Capture Compare 5 Register value. + */ +uint16_t TIM_GetCap5(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + /* Get the Capture 5 Register value */ + return TIMx->CCDAT5; +} + +/** + * @brief Gets the TIMx Input Capture 6 value. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @return Capture Compare 6 Register value. + */ +uint16_t TIM_GetCap6(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + /* Get the Capture 6 Register value */ + return TIMx->CCDAT6; +} + +/** + * @brief Gets the TIMx Counter value. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @return Counter Register value. + */ +uint16_t TIM_GetCnt(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + /* Get the Counter Register value */ + return TIMx->CNT; +} + +/** + * @brief Gets the TIMx Prescaler value. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @return Prescaler Register value. + */ +uint16_t TIM_GetPrescaler(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + /* Get the Prescaler Register value */ + return TIMx->PSC; +} + +/** + * @brief Gets the TIMx Prescaler value. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @return Prescaler Register value. + */ +uint16_t TIM_GetAutoReload(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + /* Get the Prescaler Register value */ + return TIMx->AR; +} + +/** + * @brief Checks whether the specified TIM flag is set or not. + * @param TIMx where x can be 1 to 5 , 8 to select the TIM peripheral. + * @param TIM_CCEN specifies the Bit to check. + * This parameter can be one of the following values: + * @arg TIM_CC1EN CC1EN Bit + * @arg TIM_CC1NEN CC1NEN Bit + * @arg TIM_CC2EN CC2EN Bit + * @arg TIM_CC2NEN CC2NEN Bit + * @arg TIM_CC3EN CC3EN Bit + * @arg TIM_CC3NEN CC3NEN Bit + * @arg TIM_CC4EN CC4EN Bit + * @arg TIM_CC5EN CC5EN Bit + * @arg TIM_CC6EN CC6EN Bit + * @note + * - TIM_CC1NEN TIM_CC2NEN TIM_CC3NEN is used only with TIM1, TIM8. + * @return The new state of TIM_FLAG (SET or RESET). + */ +FlagStatus TIM_GetCCENStatus(TIM_Module* TIMx, uint32_t TIM_CCEN) +{ + INTStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + + if(TIMx==TIM1 || TIMx==TIM8) + { + assert_param(IsAdvancedTimCCENFlag(TIM_CCEN)); + if ((TIMx->CCEN & TIM_CCEN) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + else if(TIMx==TIM2 || TIMx==TIM3 || TIMx==TIM4 || TIMx==TIM5 ) + { + assert_param(IsGeneralTimCCENFlag(TIM_CCEN)); + if ((TIMx->CCEN & TIM_CCEN) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + + return bitstatus; +} + +/** + * @brief Checks whether the specified TIM flag is set or not. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param TIM_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg TIM_FLAG_UPDATE TIM update Flag + * @arg TIM_FLAG_CC1 TIM Capture Compare 1 Flag + * @arg TIM_FLAG_CC2 TIM Capture Compare 2 Flag + * @arg TIM_FLAG_CC3 TIM Capture Compare 3 Flag + * @arg TIM_FLAG_CC4 TIM Capture Compare 4 Flag + * @arg TIM_FLAG_COM TIM Commutation Flag + * @arg TIM_FLAG_TRIG TIM Trigger Flag + * @arg TIM_FLAG_BREAK TIM Break Flag + * @arg TIM_FLAG_CC1OF TIM Capture Compare 1 overcapture Flag + * @arg TIM_FLAG_CC2OF TIM Capture Compare 2 overcapture Flag + * @arg TIM_FLAG_CC3OF TIM Capture Compare 3 overcapture Flag + * @arg TIM_FLAG_CC4OF TIM Capture Compare 4 overcapture Flag + * @arg TIM_FLAG_CC5 TIM Capture Compare 5 Flag + * @arg TIM_FLAG_CC6 TIM Capture Compare 6 Flag + * @note + * - TIM6 and TIM7 can have only one update flag. + * - TIM_FLAG_BREAK is used only with TIM1, TIM8. + * - TIM_FLAG_COM is used only with TIM1, TIM8. + * @return The new state of TIM_FLAG (SET or RESET). + */ +FlagStatus TIM_GetFlagStatus(TIM_Module* TIMx, uint32_t TIM_FLAG) +{ + INTStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimGetFlag(TIM_FLAG)); + + if ((TIMx->STS & TIM_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the TIMx's pending flags. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param TIM_FLAG specifies the flag bit to clear. + * This parameter can be any combination of the following values: + * @arg TIM_FLAG_UPDATE TIM update Flag + * @arg TIM_FLAG_CC1 TIM Capture Compare 1 Flag + * @arg TIM_FLAG_CC2 TIM Capture Compare 2 Flag + * @arg TIM_FLAG_CC3 TIM Capture Compare 3 Flag + * @arg TIM_FLAG_CC4 TIM Capture Compare 4 Flag + * @arg TIM_FLAG_COM TIM Commutation Flag + * @arg TIM_FLAG_TRIG TIM Trigger Flag + * @arg TIM_FLAG_BREAK TIM Break Flag + * @arg TIM_FLAG_CC1OF TIM Capture Compare 1 overcapture Flag + * @arg TIM_FLAG_CC2OF TIM Capture Compare 2 overcapture Flag + * @arg TIM_FLAG_CC3OF TIM Capture Compare 3 overcapture Flag + * @arg TIM_FLAG_CC4OF TIM Capture Compare 4 overcapture Flag + * @note + * - TIM6 and TIM7 can have only one update flag. + * - TIM_FLAG_BREAK is used only with TIM1, TIM8. + * - TIM_FLAG_COM is used only with TIM1, TIM8. + */ +void TIM_ClearFlag(TIM_Module* TIMx, uint32_t TIM_FLAG) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimClrFlag(TIM_FLAG)); + + /* Clear the flags */ + TIMx->STS = (uint32_t)~TIM_FLAG; +} + +/** + * @brief Checks whether the TIM interrupt has occurred or not. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param TIM_IT specifies the TIM interrupt source to check. + * This parameter can be one of the following values: + * @arg TIM_INT_UPDATE TIM update Interrupt source + * @arg TIM_INT_CC1 TIM Capture Compare 1 Interrupt source + * @arg TIM_INT_CC2 TIM Capture Compare 2 Interrupt source + * @arg TIM_INT_CC3 TIM Capture Compare 3 Interrupt source + * @arg TIM_INT_CC4 TIM Capture Compare 4 Interrupt source + * @arg TIM_INT_COM TIM Commutation Interrupt source + * @arg TIM_INT_TRIG TIM Trigger Interrupt source + * @arg TIM_INT_BREAK TIM Break Interrupt source + * @note + * - TIM6 and TIM7 can generate only an update interrupt. + * - TIM_INT_BREAK is used only with TIM1, TIM8. + * - TIM_INT_COM is used only with TIM1, TIM8. + * @return The new state of the TIM_IT(SET or RESET). + */ +INTStatus TIM_GetIntStatus(TIM_Module* TIMx, uint32_t TIM_IT) +{ + INTStatus bitstatus = RESET; + uint32_t itstatus = 0x0, itenable = 0x0; + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimGetInt(TIM_IT)); + + itstatus = TIMx->STS & TIM_IT; + + itenable = TIMx->DINTEN & TIM_IT; + if ((itstatus != (uint32_t)RESET) && (itenable != (uint32_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the TIMx's interrupt pending bits. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param TIM_IT specifies the pending bit to clear. + * This parameter can be any combination of the following values: + * @arg TIM_INT_UPDATE TIM1 update Interrupt source + * @arg TIM_INT_CC1 TIM Capture Compare 1 Interrupt source + * @arg TIM_INT_CC2 TIM Capture Compare 2 Interrupt source + * @arg TIM_INT_CC3 TIM Capture Compare 3 Interrupt source + * @arg TIM_INT_CC4 TIM Capture Compare 4 Interrupt source + * @arg TIM_INT_COM TIM Commutation Interrupt source + * @arg TIM_INT_TRIG TIM Trigger Interrupt source + * @arg TIM_INT_BREAK TIM Break Interrupt source + * @note + * - TIM6 and TIM7 can generate only an update interrupt. + * - TIM_INT_BREAK is used only with TIM1, TIM8. + * - TIM_INT_COM is used only with TIM1, TIM8. + */ +void TIM_ClrIntPendingBit(TIM_Module* TIMx, uint32_t TIM_IT) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimInt(TIM_IT)); + /* Clear the IT pending Bit */ + TIMx->STS = (uint32_t)~TIM_IT; +} + +/** + * @brief Configure the TI1 as Input. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param IcPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_IC_POLARITY_RISING + * @arg TIM_IC_POLARITY_FALLING + * @param IcSelection specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_IC_SELECTION_DIRECTTI TIM Input 1 is selected to be connected to IC1. + * @arg TIM_IC_SELECTION_INDIRECTTI TIM Input 1 is selected to be connected to IC2. + * @arg TIM_IC_SELECTION_TRC TIM Input 1 is selected to be connected to TRC. + * @param IcFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + */ +static void ConfigTI1(TIM_Module* TIMx, uint16_t IcPolarity, uint16_t IcSelection, uint16_t IcFilter) +{ + uint16_t tmpccmr1 = 0; + uint32_t tmpccer = 0; + /* Disable the Channel 1: Reset the CC1E Bit */ + TIMx->CCEN &= (uint32_t) ~((uint32_t)TIM_CCEN_CC1EN); + tmpccmr1 = TIMx->CCMOD1; + tmpccer = TIMx->CCEN; + /* Select the Input and set the filter */ + tmpccmr1 &= (uint16_t)(((uint16_t) ~((uint16_t)TIM_CCMOD1_CC1SEL)) & ((uint16_t) ~((uint16_t)TIM_CCMOD1_IC1F))); + tmpccmr1 |= (uint16_t)(IcSelection | (uint16_t)(IcFilter << (uint16_t)4)); + + if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) || (TIMx == TIM5)) + { + /* Select the Polarity and set the CC1E Bit */ + tmpccer &= (uint32_t) ~((uint32_t)(TIM_CCEN_CC1P)); + tmpccer |= (uint32_t)(IcPolarity | (uint32_t)TIM_CCEN_CC1EN); + } + else + { + /* Select the Polarity and set the CC1E Bit */ + tmpccer &= (uint32_t) ~((uint32_t)(TIM_CCEN_CC1P | TIM_CCEN_CC1NP)); + tmpccer |= (uint32_t)(IcPolarity | (uint32_t)TIM_CCEN_CC1EN); + } + + /* Write to TIMx CCMOD1 and CCEN registers */ + TIMx->CCMOD1 = tmpccmr1; + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configure the TI2 as Input. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @param IcPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_IC_POLARITY_RISING + * @arg TIM_IC_POLARITY_FALLING + * @param IcSelection specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_IC_SELECTION_DIRECTTI TIM Input 2 is selected to be connected to IC2. + * @arg TIM_IC_SELECTION_INDIRECTTI TIM Input 2 is selected to be connected to IC1. + * @arg TIM_IC_SELECTION_TRC TIM Input 2 is selected to be connected to TRC. + * @param IcFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + */ +static void ConfigTI2(TIM_Module* TIMx, uint16_t IcPolarity, uint16_t IcSelection, uint16_t IcFilter) +{ + uint16_t tmpccmr1 = 0; + uint32_t tmpccer = 0, tmp = 0; + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCEN &= (uint32_t) ~((uint32_t)TIM_CCEN_CC2EN); + tmpccmr1 = TIMx->CCMOD1; + tmpccer = TIMx->CCEN; + tmp = (uint32_t)(IcPolarity << 4); + /* Select the Input and set the filter */ + tmpccmr1 &= (uint16_t)(((uint16_t) ~((uint16_t)TIM_CCMOD1_CC2SEL)) & ((uint16_t) ~((uint16_t)TIM_CCMOD1_IC2F))); + tmpccmr1 |= (uint16_t)(IcFilter << 12); + tmpccmr1 |= (uint16_t)(IcSelection << 8); + + if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) || (TIMx == TIM5)) + { + /* Select the Polarity and set the CC2E Bit */ + tmpccer &= (uint32_t) ~((uint32_t)(TIM_CCEN_CC2P)); + tmpccer |= (uint32_t)(tmp | (uint32_t)TIM_CCEN_CC2EN); + } + else + { + /* Select the Polarity and set the CC2E Bit */ + tmpccer &= (uint32_t) ~((uint32_t)(TIM_CCEN_CC2P | TIM_CCEN_CC2NP)); + tmpccer |= (uint32_t)(IcPolarity | (uint32_t)TIM_CCEN_CC2EN); + } + + /* Write to TIMx CCMOD1 and CCEN registers */ + TIMx->CCMOD1 = tmpccmr1; + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configure the TI3 as Input. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param IcPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_IC_POLARITY_RISING + * @arg TIM_IC_POLARITY_FALLING + * @param IcSelection specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_IC_SELECTION_DIRECTTI TIM Input 3 is selected to be connected to IC3. + * @arg TIM_IC_SELECTION_INDIRECTTI TIM Input 3 is selected to be connected to IC4. + * @arg TIM_IC_SELECTION_TRC TIM Input 3 is selected to be connected to TRC. + * @param IcFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + */ +static void ConfigTI3(TIM_Module* TIMx, uint16_t IcPolarity, uint16_t IcSelection, uint16_t IcFilter) +{ + uint16_t tmpccmr2 = 0; + uint32_t tmpccer = 0, tmp = 0; + /* Disable the Channel 3: Reset the CC3E Bit */ + TIMx->CCEN &= (uint32_t) ~((uint32_t)TIM_CCEN_CC3EN); + tmpccmr2 = TIMx->CCMOD2; + tmpccer = TIMx->CCEN; + tmp = (uint32_t)(IcPolarity << 8); + /* Select the Input and set the filter */ + tmpccmr2 &= (uint16_t)(((uint16_t) ~((uint16_t)TIM_CCMOD2_CC3SEL)) & ((uint16_t) ~((uint16_t)TIM_CCMOD2_IC3F))); + tmpccmr2 |= (uint16_t)(IcSelection | (uint16_t)(IcFilter << (uint16_t)4)); + + if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) || (TIMx == TIM5)) + { + /* Select the Polarity and set the CC3E Bit */ + tmpccer &= (uint32_t) ~((uint32_t)(TIM_CCEN_CC3P)); + tmpccer |= (uint32_t)(tmp | (uint32_t)TIM_CCEN_CC3EN); + } + else + { + /* Select the Polarity and set the CC3E Bit */ + tmpccer &= (uint32_t) ~((uint32_t)(TIM_CCEN_CC3P | TIM_CCEN_CC3NP)); + tmpccer |= (uint32_t)(IcPolarity | (uint32_t)TIM_CCEN_CC3EN); + } + + /* Write to TIMx CCMOD2 and CCEN registers */ + TIMx->CCMOD2 = tmpccmr2; + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configure the TI4 as Input. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param IcPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_IC_POLARITY_RISING + * @arg TIM_IC_POLARITY_FALLING + * @param IcSelection specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_IC_SELECTION_DIRECTTI TIM Input 4 is selected to be connected to IC4. + * @arg TIM_IC_SELECTION_INDIRECTTI TIM Input 4 is selected to be connected to IC3. + * @arg TIM_IC_SELECTION_TRC TIM Input 4 is selected to be connected to TRC. + * @param IcFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + */ +static void ConfigTI4(TIM_Module* TIMx, uint16_t IcPolarity, uint16_t IcSelection, uint16_t IcFilter) +{ + uint16_t tmpccmr2 = 0; + uint32_t tmpccer = 0, tmp = 0; + + /* Disable the Channel 4: Reset the CC4E Bit */ + TIMx->CCEN &= (uint32_t) ~((uint32_t)TIM_CCEN_CC4EN); + tmpccmr2 = TIMx->CCMOD2; + tmpccer = TIMx->CCEN; + tmp = (uint32_t)(IcPolarity << 12); + /* Select the Input and set the filter */ + tmpccmr2 &= (uint16_t)((uint16_t)(~(uint16_t)TIM_CCMOD2_CC4SEL) & ((uint16_t) ~((uint16_t)TIM_CCMOD2_IC4F))); + tmpccmr2 |= (uint16_t)(IcSelection << 8); + tmpccmr2 |= (uint16_t)(IcFilter << 12); + + if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) || (TIMx == TIM5)) + { + /* Select the Polarity and set the CC4E Bit */ + tmpccer &= (uint32_t) ~((uint32_t)(TIM_CCEN_CC4P)); + tmpccer |= (uint32_t)(tmp | (uint32_t)TIM_CCEN_CC4EN); + } + else + { + /* Select the Polarity and set the CC4E Bit */ + tmpccer &= (uint32_t) ~((uint32_t)(TIM_CCEN_CC4P)); + tmpccer |= (uint32_t)(IcPolarity | (uint32_t)TIM_CCEN_CC4EN); + } + /* Write to TIMx CCMOD2 and CCEN registers */ + TIMx->CCMOD2 = tmpccmr2; + TIMx->CCEN = tmpccer; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_tsc.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_tsc.c new file mode 100644 index 0000000000..985602474b --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_tsc.c @@ -0,0 +1,500 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_tsc.c + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr.h" +#include "n32g4fr_tsc.h" + +/** + * @brief Init TSC config for hardware detect mode. + * @param TSC_Def Pointer of TSC register. + * @param CtrlCfg configurations. + */ +TSC_ErrorTypeDef TSC_Init(TSC_Module* TSC_Def, TSC_InitType* CtrlCfg) +{ + uint32_t tempreg,timeout; + + assert_param(IS_TSC_FILTER(CtrlCfg->TSC_FilterCount)); + assert_param(IS_TSC_DET_PERIOD(CtrlCfg->TSC_DetPeriod)); + + if(TSC_Def != TSC) + return TSC_ERROR_PARAMETER; + + /* waiting tsc hw for idle status.*/ + timeout = 0; + do + { + __TSC_HW_DISABLE(); + + if(++timeout > TSC_TIMEOUT) + return TSC_ERROR_HW_MODE; + }while (__TSC_GET_HW_MODE()); + + /*TSC_CTRL config*/ + tempreg = 0; + if(CtrlCfg->TSC_DetIntEnable) + tempreg |= TSC_IT_DET_ENABLE; + + if(CtrlCfg->TSC_GreatEnable) + tempreg |= TSC_DET_TYPE_GREAT; + + if(CtrlCfg->TSC_LessEnable) + tempreg |= TSC_DET_TYPE_LESS; + + tempreg |= CtrlCfg->TSC_FilterCount; + tempreg |= CtrlCfg->TSC_DetPeriod; + + TSC_Def->CTRL = tempreg; + + return TSC_ERROR_OK; +} + +/** + * @brief Config the clock source of TSC + * @param TSC_ClkSource specifies the clock source of TSC + * This parameter can be one of the following values: + * @arg TSC_CLK_SRC_LSI: TSC clock source is LSI(default) + * @arg TSC_CLK_SRC_LSE: TSC clock source is LSE,and LSE is oscillator + * @arg TSC_CLK_SRC_LSE_BYPASS: TSC clock source is LSE,and LSE is extennal clock + * @retval TSC error code + */ +TSC_ErrorTypeDef TSC_ClockConfig(uint32_t TSC_ClkSource) +{ + uint32_t timeout; + + /*Enable PWR peripheral Clock*/ + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_PWR,ENABLE); + + if(TSC_CLK_SRC_LSI == TSC_ClkSource) + { + /*enable LSI clock*/ + RCC_EnableLsi(ENABLE); + + /*Wait LSI stable*/ + timeout = 0; + while(RCC_GetFlagStatus(RCC_FLAG_LSIRD) == RESET) + { + if(++timeout >TSC_TIMEOUT) + return TSC_ERROR_CLOCK; + } + } + else if((TSC_CLK_SRC_LSE_BYPASS==TSC_ClkSource)||(TSC_CLK_SRC_LSE==TSC_ClkSource)) + { + if(RCC_GetFlagStatus(RCC_FLAG_LSERD)==RESET) + { + // Set bit 8 of PWR_CTRL1.Open PWR DBP. + PWR_BackupAccessEnable(ENABLE); + RCC_ConfigLse(TSC_ClkSource); + timeout = 0; + while(RCC_GetFlagStatus(RCC_FLAG_LSERD) == RESET) + { + if(++timeout >TSC_TIMEOUT) + return TSC_ERROR_CLOCK; + } + } + } + else + return TSC_ERROR_PARAMETER; + + /*Enable TSC clk*/ + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TSC,ENABLE); + + return TSC_ERROR_OK; +} + +/** + * @brief Configure internal charge resistor for some channels + * @param TSC_Def Pointer of TSC register. + * @param res: internal resistor selecte + * This parameter can be one of the following values: + * @arg TSC_RESR_CHN_RESIST_0: 1M OHM + * @arg TSC_RESR_CHN_RESIST_1: 882K OHM + * @arg TSC_RESR_CHN_RESIST_2: 756K OHM + * @arg TSC_RESR_CHN_RESIST_3: 630K OHM + * @arg TSC_RESR_CHN_RESIST_4: 504K OHM + * @arg TSC_RESR_CHN_RESIST_5: 378K OHM + * @arg TSC_RESR_CHN_RESIST_6: 252K OHM + * @arg TSC_RESR_CHN_RESIST_7: 126K OHM + * @param Channels: channels to be configed, as TSC_CHNEN defined + * This parameter:bit[0:23] used,bit[24:31] must be 0 + * bitx: TSC channel x + * @return: none + */ +TSC_ErrorTypeDef TSC_ConfigInternalResistor(TSC_Module* TSC_Def,uint32_t Channels, uint32_t res ) +{ + uint32_t i,chn,timeout,*pReg,nPos; + + assert_param(IS_TSC_CHN(Channels)); + assert_param(IS_TSC_RESISTOR_VALUE(res)); + + if(TSC_Def != TSC) + return TSC_ERROR_PARAMETER; + + /*Check charge resistor value */ + if(res > TSC_RESR_CHN_RESIST_125K) + return TSC_ERROR_PARAMETER; + + /* waiting tsc hw for idle status.*/ + timeout = 0; + do + { + __TSC_HW_DISABLE(); + + if(++timeout > TSC_TIMEOUT) + return TSC_ERROR_HW_MODE; + }while (__TSC_GET_HW_MODE()); + + /* Mask invalie bits*/ + chn = Channels & TSC_CHNEN_CHN_SEL_MASK; + + /* Set resistance for each channel one by one*/ + for (i = 0; iRESR0)); + pReg += (i/8); + nPos = (i & 0x7UL)*4; + MODIFY_REG(*pReg,TSC_RESR_CHN_RESIST_MASK<>= 1; + } + + return TSC_ERROR_OK; +} + +/** + * @brief Configure threshold value for some channels + * @param TSC_Def Pointer of TSC register. + * @param Channels: channels to be configed, as TSC_CHNEN defined + * This parameter:bit[0:23] used,bit[24:31] must be 0 + * bitx: TSC channel x + * @param base: base value of threshold, 0-MAX_TSC_THRESHOLD_BASE + * @param delta: delta value of threshold,0-MAX_TSC_THRESHOLD_DELRA + * @return: None + */ +TSC_ErrorTypeDef TSC_ConfigThreshold( TSC_Module* TSC_Def, uint32_t Channels, uint32_t base, uint32_t delta) +{ + uint32_t i, chn,timeout,*pReg; + + assert_param(IS_TSC_CHN(Channels)); + assert_param(IS_TSC_THRESHOLD_BASE(base)); + assert_param(IS_TSC_THRESHOLD_DELTA(delta)); + + if(TSC_Def != TSC) + return TSC_ERROR_PARAMETER; + + /*Check the base and delta value*/ + if( (base>MAX_TSC_THRESHOLD_BASE)||(delta>MAX_TSC_THRESHOLD_DELTA)) + return TSC_ERROR_PARAMETER; + + /* waiting tsc hw for idle status.*/ + timeout = 0; + do + { + __TSC_HW_DISABLE(); + + if(++timeout > TSC_TIMEOUT) + return TSC_ERROR_HW_MODE; + }while (__TSC_GET_HW_MODE()); + + pReg = (uint32_t *)(&(TSC_Def->THRHD0)); + + /*Mask invalie bits*/ + chn = Channels & TSC_CHNEN_CHN_SEL_MASK; + + /* Set the base and delta for each channnel one by one*/ + for (i = 0; i>= 1; + } + + return TSC_ERROR_OK; +} + + +/** + * @brief Get parameters of one channel. + * @param TSC_Def Pointer of TSC register. + * @param ChnCfg: Pointer of TSC_ChnCfg structure. + * @param Channels: channels to be configed, as TSC_CHNEN defined + * This parameter:bit[0:23] used,bit[24:31] must be 0 + * bitx: TSC channel x + * @return: None + */ +TSC_ErrorTypeDef TSC_GetChannelCfg( TSC_Module* TSC_Def, TSC_ChnCfg* ChnCfg, uint32_t Channels) +{ + uint32_t i,chn, *pReg; + + if(TSC_Def != TSC) + return TSC_ERROR_PARAMETER; + + /*Check channel number*/ + if(!(IS_TSC_CHN(Channels))) + return TSC_ERROR_PARAMETER; + + chn = Channels & TSC_CHNEN_CHN_SEL_MASK; + + for (i = 0; iTHRHD0)); + pReg += i; + ChnCfg->TSC_Base = (uint16_t)(((*pReg) & TSC_THRHD_BASE_MASK) >> TSC_THRHD_BASE_SHIFT); + ChnCfg->TSC_Delta = (uint8_t)(((*pReg) & TSC_THRHD_DELTA_MASK)>> TSC_THRHD_DELTA_SHIFT); + + pReg = (uint32_t *)(&(TSC->RESR0)); + pReg += (i/8); + ChnCfg->TSC_ResisValue = (uint8_t)(((*pReg) >> ((i & 0x7UL)*4)) & TSC_RESR_CHN_RESIST_MASK); + break; + } + + chn >>= 1; + } + + return TSC_ERROR_OK; +} + + +/** + * @brief Get TSC status value. + * @param TSC_Def Pointer of TSC register. + * @param type TSC status type. + */ +uint32_t TSC_GetStatus(TSC_Module* TSC_Def, uint32_t type) +{ + uint32_t value = 0; + + if(TSC_Def != TSC) + return 0; + + switch (type) + { + case TSC_GET_STS_CNTVALUE: + value = __TSC_GET_CHN_CNT(); + break; + + case TSC_GET_STS_LESS_DET: + value = __TSC_GET_HW_DET_TYPE(TSC_FLAG_LESS_DET); + break; + + case TSC_GET_STS_GREAT_DET: + value = __TSC_GET_HW_DET_TYPE(TSC_FLAG_GREAT_DET); + break; + + case TSC_GET_STS_CHN_NUM: + value = __TSC_GET_CHN_NUMBER(); + break; + + case TSC_GET_STS_DET_ST: + value = __TSC_GET_HW_MODE(); + break; + + default: + break; + } + + return value; +} + +/** + * @brief Enable/Disable hardware detection. + * @param TSC_Def Pointer of TSC register. + * @param Channels: channels to be configed, as TSC_CHNEN defined + * This parameter:bit[0:23] used,bit[24:31] must be 0 + * bitx: TSC channel x + * @param Cmd ENABLE:Enable hardware detection,DISALBE:Disable hardware detection. + * @note You can only output one channel at a time. + */ +TSC_ErrorTypeDef TSC_Cmd(TSC_Module* TSC_Def, uint32_t Channels, FunctionalState Cmd) +{ + uint32_t timeout; + + if(TSC_Def != TSC) + return TSC_ERROR_PARAMETER; + + if (Cmd != DISABLE) + { + // enable tsc channel + Channels &= TSC_CHNEN_CHN_SEL_MASK; + __TSC_CHN_CONFIG(Channels ); + + /* Enable the TSC */ + __TSC_HW_ENABLE(); + } + else + { + /* Disable the TSC */ + timeout = 0; + do + { + __TSC_HW_DISABLE(); + + if(++timeout > TSC_TIMEOUT) + return TSC_ERROR_HW_MODE; + }while (__TSC_GET_HW_MODE()); + + __TSC_CHN_CONFIG(0); + } + + return TSC_ERROR_OK; +} + +/** + * @brief Toggle channels to output to TIMER2/TIMER4 by software mode. + * @param TSC_Def Pointer of TSC register. + * @param Channels: channels to be configed, as TSC_CHNEN defined + * This parameter:bit[0:23] used,bit[24:31] must be 0 + * bitx: TSC channel x + * @param TIMx Select timer. + * @param Cmd ENABLE:Enable hardware detection,DISALBE:Disable hardware detection. + * @note It can only output to TIMER2/TIMER4 by software mode.Other channels are not valid. + */ +TSC_ErrorTypeDef TSC_SW_SwtichChn(TSC_Module* TSC_Def, uint32_t Channel, TIM_Module* TIMx, FunctionalState Cmd) +{ + uint32_t i, timeout; + + if(TSC_Def != TSC) + return TSC_ERROR_PARAMETER; + + if ((TIMx != TIM2) && (TIMx != TIM4)) + return TSC_ERROR_PARAMETER; + + + /* Disable the TSC HW MODE */ + timeout = 0; + do + { + __TSC_HW_DISABLE(); + + if(++timeout > TSC_TIMEOUT) + return TSC_ERROR_HW_MODE; + }while (__TSC_GET_HW_MODE()); + + if (Cmd == DISABLE) // Close output by software mode + { + __TSC_OUT_CONFIG(TSC_OUT_PIN); + __TSC_SW_DISABLE(); + } + else + { + for (i = 0; i < MAX_TSC_HW_CHN; i++) + { + if (Channel & 0x00000001) + { + __TSC_SW_CHN_NUM_CONFIG(i); + break; + } + + Channel >>= 1; + } + + // Select to output to specified TIMER. + if (TIMx == TIM4) + { + __TSC_OUT_CONFIG(TSC_OUT_TIM4_ETR); + } + else + { + __TSC_OUT_CONFIG(TSC_OUT_TIM2_ETR); + } + + __TSC_SW_ENABLE(); + } + + // delay time for tsc channel stabilize output + for (i = 0; i < 2000; i++) + { + } + + return TSC_ERROR_OK; +} + +/** + * @brief Configure analog signal parameters. + * @param TSC_Def Pointer of TSC register. + * @param AnaoCfg Pointer of analog parameter structure. + */ +TSC_ErrorTypeDef TSC_SetAnaoCfg(TSC_Module* TSC_Def, TSC_AnaoCfg* AnaoCfg) +{ + if(TSC_Def != TSC) + return TSC_ERROR_PARAMETER; + + if(AnaoCfg == 0) + return TSC_ERROR_PARAMETER; + + assert_param(IS_TSC_PAD_OPTION(AnaoCfg->TSC_AnaoptrResisOption)); + assert_param(IS_TSC_PAD_SPEED(AnaoCfg->TSC_AnaoptrSpeedOption)); + + __TSC_PAD_OPT_CONFIG(AnaoCfg->TSC_AnaoptrResisOption); + __TSC_PAD_SPEED_CONFIG(AnaoCfg->TSC_AnaoptrSpeedOption); + + return TSC_ERROR_OK; +} + +/** + * @brief Configure channel parameters by channel or operation.Support configure several channels at the same time. + * @param TSC_Def Pointer of TSC register. + * @param ChnCfg Channel parameters. + * @param Channels: channels to be configed, as TSC_CHNEN defined + * This parameter:bit[0:23] used,bit[24:31] must be 0 + * bitx: TSC channel x + */ +TSC_ErrorTypeDef TSC_SetChannelCfg(TSC_Module* TSC_Def, TSC_ChnCfg* ChnCfg, uint32_t Channels) +{ + TSC_ErrorTypeDef err; + + if(TSC_Def != TSC) + return TSC_ERROR_PARAMETER; + + if(0 == ChnCfg) + return TSC_ERROR_PARAMETER; + + // Set resistance + err = TSC_ConfigInternalResistor(TSC_Def, Channels, ChnCfg->TSC_ResisValue); + if(err != TSC_ERROR_OK) + return err; + + // Set the threshold of base and delta. + err = TSC_ConfigThreshold(TSC_Def, Channels, ChnCfg->TSC_Base, ChnCfg->TSC_Delta); + return err; +} + + diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_usart.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_usart.c new file mode 100644 index 0000000000..daccbc4076 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_usart.c @@ -0,0 +1,974 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_usart.c + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_usart.h" +#include "n32g4fr_rcc.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup USART + * @brief USART driver modules + * @{ + */ + +/** @addtogroup USART_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup USART_Private_Defines + * @{ + */ + +#define CTRL1_UEN_SET ((uint16_t)0x2000) /*!< USART Enable Mask */ +#define CTRL1_UEN_RESET ((uint16_t)0xDFFF) /*!< USART Disable Mask */ + +#define CTRL1_WUM_MASK ((uint16_t)0xF7FF) /*!< USART WakeUp Method Mask */ + +#define CTRL1_RCVWU_SET ((uint16_t)0x0002) /*!< USART mute mode Enable Mask */ +#define CTRL1_RCVWU_RESET ((uint16_t)0xFFFD) /*!< USART mute mode Enable Mask */ +#define CTRL1_SDBRK_SET ((uint16_t)0x0001) /*!< USART Break Character send Mask */ +#define CTRL1_CLR_MASK ((uint16_t)0xE9F3) /*!< USART CTRL1 Mask */ +#define CTRL2_ADDR_MASK ((uint16_t)0xFFF0) /*!< USART address Mask */ + +#define CTRL2_LINMEN_SET ((uint16_t)0x4000) /*!< USART LIN Enable Mask */ +#define CTRL2_LINMEN_RESET ((uint16_t)0xBFFF) /*!< USART LIN Disable Mask */ + +#define CTRL2_LINBDL_MASK ((uint16_t)0xFFDF) /*!< USART LIN Break detection Mask */ +#define CTRL2_STPB_CLR_MASK ((uint16_t)0xCFFF) /*!< USART CTRL2 STOP Bits Mask */ +#define CTRL2_CLOCK_CLR_MASK ((uint16_t)0xF0FF) /*!< USART CTRL2 Clock Mask */ + +#define CTRL3_SCMEN_SET ((uint16_t)0x0020) /*!< USART SC Enable Mask */ +#define CTRL3_SCMEN_RESET ((uint16_t)0xFFDF) /*!< USART SC Disable Mask */ + +#define CTRL3_SCNACK_SET ((uint16_t)0x0010) /*!< USART SC NACK Enable Mask */ +#define CTRL3_SCNACK_RESET ((uint16_t)0xFFEF) /*!< USART SC NACK Disable Mask */ + +#define CTRL3_HDMEN_SET ((uint16_t)0x0008) /*!< USART Half-Duplex Enable Mask */ +#define CTRL3_HDMEN_RESET ((uint16_t)0xFFF7) /*!< USART Half-Duplex Disable Mask */ + +#define CTRL3_IRDALP_MASK ((uint16_t)0xFFFB) /*!< USART IrDA LowPower mode Mask */ +#define CTRL3_CLR_MASK ((uint16_t)0xFCFF) /*!< USART CTRL3 Mask */ + +#define CTRL3_IRDAMEN_SET ((uint16_t)0x0002) /*!< USART IrDA Enable Mask */ +#define CTRL3_IRDAMEN_RESET ((uint16_t)0xFFFD) /*!< USART IrDA Disable Mask */ +#define GTP_LSB_MASK ((uint16_t)0x00FF) /*!< Guard Time Register LSB Mask */ +#define GTP_MSB_MASK ((uint16_t)0xFF00) /*!< Guard Time Register MSB Mask */ +#define INT_MASK ((uint16_t)0x001F) /*!< USART Interrupt Mask */ + +/** + * @} + */ + +/** @addtogroup USART_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup USART_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup USART_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup USART_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the USARTx peripheral registers to their default reset values. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + */ +void USART_DeInit(USART_Module* USARTx) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + + if (USARTx == USART1) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_USART1, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_USART1, DISABLE); + } + else if (USARTx == USART2) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_USART2, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_USART2, DISABLE); + } + else if (USARTx == USART3) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_USART3, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_USART3, DISABLE); + } + else if (USARTx == UART4) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_UART4, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_UART4, DISABLE); + } + else if (USARTx == UART5) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_UART5, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_UART5, DISABLE); + } + else if (USARTx == UART6) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_UART6, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_UART6, DISABLE); + } + else + { + if (USARTx == UART7) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_UART7, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_UART7, DISABLE); + } + } +} + +/** + * @brief Initializes the USARTx peripheral according to the specified + * parameters in the USART_InitStruct . + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param USART_InitStruct pointer to a USART_InitType structure + * that contains the configuration information for the specified USART + * peripheral. + */ +void USART_Init(USART_Module* USARTx, USART_InitType* USART_InitStruct) +{ + uint32_t tmpregister = 0x00, apbclock = 0x00; + uint32_t integerdivider = 0x00; + uint32_t fractionaldivider = 0x00; + uint32_t usartxbase = 0; + RCC_ClocksType RCC_ClocksStatus; + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_BAUDRATE(USART_InitStruct->BaudRate)); + assert_param(IS_USART_WORD_LENGTH(USART_InitStruct->WordLength)); + assert_param(IS_USART_STOPBITS(USART_InitStruct->StopBits)); + assert_param(IS_USART_PARITY(USART_InitStruct->Parity)); + assert_param(IS_USART_MODE(USART_InitStruct->Mode)); + assert_param(IS_USART_HARDWARE_FLOW_CONTROL(USART_InitStruct->HardwareFlowControl)); + /* The hardware flow control is available only for USART1, USART2 and USART3 */ + if (USART_InitStruct->HardwareFlowControl != USART_HFCTRL_NONE) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + + usartxbase = (uint32_t)USARTx; + + /*---------------------------- USART CTRL2 Configuration -----------------------*/ + tmpregister = USARTx->CTRL2; + /* Clear STOP[13:12] bits */ + tmpregister &= CTRL2_STPB_CLR_MASK; + /* Configure the USART Stop Bits, Clock, CPOL, CPHA and LastBit ------------*/ + /* Set STOP[13:12] bits according to StopBits value */ + tmpregister |= (uint32_t)USART_InitStruct->StopBits; + + /* Write to USART CTRL2 */ + USARTx->CTRL2 = (uint16_t)tmpregister; + + /*---------------------------- USART CTRL1 Configuration -----------------------*/ + tmpregister = USARTx->CTRL1; + /* Clear M, PCE, PS, TE and RE bits */ + tmpregister &= CTRL1_CLR_MASK; + /* Configure the USART Word Length, Parity and mode ----------------------- */ + /* Set the M bits according to WordLength value */ + /* Set PCE and PS bits according to Parity value */ + /* Set TE and RE bits according to Mode value */ + tmpregister |= (uint32_t)USART_InitStruct->WordLength | USART_InitStruct->Parity | USART_InitStruct->Mode; + /* Write to USART CTRL1 */ + USARTx->CTRL1 = (uint16_t)tmpregister; + + /*---------------------------- USART CTRL3 Configuration -----------------------*/ + tmpregister = USARTx->CTRL3; + /* Clear CTSE and RTSE bits */ + tmpregister &= CTRL3_CLR_MASK; + /* Configure the USART HFC -------------------------------------------------*/ + /* Set CTSE and RTSE bits according to HardwareFlowControl value */ + tmpregister |= USART_InitStruct->HardwareFlowControl; + /* Write to USART CTRL3 */ + USARTx->CTRL3 = (uint16_t)tmpregister; + + /*---------------------------- USART PBC Configuration -----------------------*/ + /* Configure the USART Baud Rate -------------------------------------------*/ + RCC_GetClocksFreqValue(&RCC_ClocksStatus); + if ((usartxbase == USART1_BASE) || (usartxbase == UART6_BASE) || (usartxbase == UART7_BASE)) + { + apbclock = RCC_ClocksStatus.Pclk2Freq; + } + else + { + apbclock = RCC_ClocksStatus.Pclk1Freq; + } + + /* Determine the integer part */ + integerdivider = ((25 * apbclock) / (4 * (USART_InitStruct->BaudRate))); + tmpregister = (integerdivider / 100) << 4; + + /* Determine the fractional part */ + fractionaldivider = (((((integerdivider - (100 * (tmpregister >> 4))) * 16) + 50) / 100)); + + /*Determine whether the fractional part needs to carried*/ + if((fractionaldivider >> 4) == 1){ + tmpregister = ((integerdivider / 100) + 1) << 4; + } + + /* Implement the fractional part in the register */ + tmpregister |= fractionaldivider & ((uint8_t)0x0F); + + /* Write to USART PBC */ + USARTx->BRCF = (uint16_t)tmpregister; +} + +/** + * @brief Fills each USART_InitStruct member with its default value. + * @param USART_InitStruct pointer to a USART_InitType structure + * which will be initialized. + */ +void USART_StructInit(USART_InitType* USART_InitStruct) +{ + /* USART_InitStruct members default value */ + USART_InitStruct->BaudRate = 9600; + USART_InitStruct->WordLength = USART_WL_8B; + USART_InitStruct->StopBits = USART_STPB_1; + USART_InitStruct->Parity = USART_PE_NO; + USART_InitStruct->Mode = USART_MODE_RX | USART_MODE_TX; + USART_InitStruct->HardwareFlowControl = USART_HFCTRL_NONE; +} + +/** + * @brief Initializes the USARTx peripheral Clock according to the + * specified parameters in the USART_ClockInitStruct . + * @param USARTx where x can be 1, 2, 3 to select the USART peripheral. + * @param USART_ClockInitStruct pointer to a USART_ClockInitType + * structure that contains the configuration information for the specified + * USART peripheral. + * @note The Smart Card and Synchronous modes are not available for UART4/UART5/UART6/UART7. + */ +void USART_ClockInit(USART_Module* USARTx, USART_ClockInitType* USART_ClockInitStruct) +{ + uint32_t tmpregister = 0x00; + /* Check the parameters */ + assert_param(IS_USART_123_PERIPH(USARTx)); + assert_param(IS_USART_CLOCK(USART_ClockInitStruct->Clock)); + assert_param(IS_USART_CPOL(USART_ClockInitStruct->Polarity)); + assert_param(IS_USART_CPHA(USART_ClockInitStruct->Phase)); + assert_param(IS_USART_LASTBIT(USART_ClockInitStruct->LastBit)); + + /*---------------------------- USART CTRL2 Configuration -----------------------*/ + tmpregister = USARTx->CTRL2; + /* Clear CLKEN, CPOL, CPHA and LBCL bits */ + tmpregister &= CTRL2_CLOCK_CLR_MASK; + /* Configure the USART Clock, CPOL, CPHA and LastBit ------------*/ + /* Set CLKEN bit according to Clock value */ + /* Set CPOL bit according to Polarity value */ + /* Set CPHA bit according to Phase value */ + /* Set LBCL bit according to LastBit value */ + tmpregister |= (uint32_t)USART_ClockInitStruct->Clock | USART_ClockInitStruct->Polarity + | USART_ClockInitStruct->Phase | USART_ClockInitStruct->LastBit; + /* Write to USART CTRL2 */ + USARTx->CTRL2 = (uint16_t)tmpregister; +} + +/** + * @brief Fills each USART_ClockInitStruct member with its default value. + * @param USART_ClockInitStruct pointer to a USART_ClockInitType + * structure which will be initialized. + */ +void USART_ClockStructInit(USART_ClockInitType* USART_ClockInitStruct) +{ + /* USART_ClockInitStruct members default value */ + USART_ClockInitStruct->Clock = USART_CLK_DISABLE; + USART_ClockInitStruct->Polarity = USART_CLKPOL_LOW; + USART_ClockInitStruct->Phase = USART_CLKPHA_1EDGE; + USART_ClockInitStruct->LastBit = USART_CLKLB_DISABLE; +} + +/** + * @brief Enables or disables the specified USART peripheral. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param Cmd new state of the USARTx peripheral. + * This parameter can be: ENABLE or DISABLE. + */ +void USART_Enable(USART_Module* USARTx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected USART by setting the UE bit in the CTRL1 register */ + USARTx->CTRL1 |= CTRL1_UEN_SET; + } + else + { + /* Disable the selected USART by clearing the UE bit in the CTRL1 register */ + USARTx->CTRL1 &= CTRL1_UEN_RESET; + } +} + +/** + * @brief Enables or disables the specified USART interrupts. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_INT specifies the USART interrupt sources to be enabled or disabled. + * This parameter can be one of the following values: + * @arg USART_INT_CTSF CTS change interrupt (not available for UART4 and UART5) + * @arg USART_INT_LINBD LIN Break detection interrupt + * @arg USART_INT_TXDE Transmit Data Register empty interrupt + * @arg USART_INT_TXC Transmission complete interrupt + * @arg USART_INT_RXDNE Receive Data register not empty interrupt + * @arg USART_INT_IDLEF Idle line detection interrupt + * @arg USART_INT_PEF Parity Error interrupt + * @arg USART_INT_ERRF Error interrupt(Frame error, noise error, overrun error) + * @param Cmd new state of the specified USARTx interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void USART_ConfigInt(USART_Module* USARTx, uint16_t USART_INT, FunctionalState Cmd) +{ + uint32_t usartreg = 0x00, itpos = 0x00, itmask = 0x00; + uint32_t usartxbase = 0x00; + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_CFG_INT(USART_INT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + /* The CTS interrupt is not available for UART4/UART5/UART6/UART7 */ + if (USART_INT == USART_INT_CTSF) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + + usartxbase = (uint32_t)USARTx; + + /* Get the USART register index */ + usartreg = (((uint8_t)USART_INT) >> 0x05); + + /* Get the interrupt position */ + itpos = USART_INT & INT_MASK; + itmask = (((uint32_t)0x01) << itpos); + + if (usartreg == 0x01) /* The IT is in CTRL1 register */ + { + usartxbase += 0x0C; + } + else if (usartreg == 0x02) /* The IT is in CTRL2 register */ + { + usartxbase += 0x10; + } + else /* The IT is in CTRL3 register */ + { + usartxbase += 0x14; + } + if (Cmd != DISABLE) + { + *(__IO uint32_t*)usartxbase |= itmask; + } + else + { + *(__IO uint32_t*)usartxbase &= ~itmask; + } +} + +/** + * @brief Enables or disables the USART's DMA interface. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_DMAReq specifies the DMA request. + * This parameter can be any combination of the following values: + * @arg USART_DMAREQ_TX USART DMA transmit request + * @arg USART_DMAREQ_RX USART DMA receive request + * @param Cmd new state of the DMA Request sources. + * This parameter can be: ENABLE or DISABLE. + */ +void USART_EnableDMA(USART_Module* USARTx, uint16_t USART_DMAReq, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_DMAREQ(USART_DMAReq)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the DMA transfer for selected requests by setting the DMAT and/or + DADDR bits in the USART CTRL3 register */ + USARTx->CTRL3 |= USART_DMAReq; + } + else + { + /* Disable the DMA transfer for selected requests by clearing the DMAT and/or + DADDR bits in the USART CTRL3 register */ + USARTx->CTRL3 &= (uint16_t)~USART_DMAReq; + } +} + +/** + * @brief Sets the address of the USART node. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_Addr Indicates the address of the USART node. + */ +void USART_SetAddr(USART_Module* USARTx, uint8_t USART_Addr) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_ADDRESS(USART_Addr)); + + /* Clear the USART address */ + USARTx->CTRL2 &= CTRL2_ADDR_MASK; + /* Set the USART address node */ + USARTx->CTRL2 |= USART_Addr; +} + +/** + * @brief Selects the USART WakeUp method. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_WakeUpMode specifies the USART wakeup method. + * This parameter can be one of the following values: + * @arg USART_WUM_IDLELINE WakeUp by an idle line detection + * @arg USART_WUM_ADDRMASK WakeUp by an address mark + */ +void USART_ConfigWakeUpMode(USART_Module* USARTx, uint16_t USART_WakeUpMode) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_WAKEUP(USART_WakeUpMode)); + + USARTx->CTRL1 &= CTRL1_WUM_MASK; + USARTx->CTRL1 |= USART_WakeUpMode; +} + +/** + * @brief Determines if the USART is in mute mode or not. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param Cmd new state of the USART mute mode. + * This parameter can be: ENABLE or DISABLE. + */ +void USART_EnableRcvWakeUp(USART_Module* USARTx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the USART mute mode by setting the RWU bit in the CTRL1 register */ + USARTx->CTRL1 |= CTRL1_RCVWU_SET; + } + else + { + /* Disable the USART mute mode by clearing the RWU bit in the CTRL1 register */ + USARTx->CTRL1 &= CTRL1_RCVWU_RESET; + } +} + +/** + * @brief Sets the USART LIN Break detection length. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_LINBreakDetectLength specifies the LIN break detection length. + * This parameter can be one of the following values: + * @arg USART_LINBDL_10B 10-bit break detection + * @arg USART_LINBDL_11B 11-bit break detection + */ +void USART_ConfigLINBreakDetectLength(USART_Module* USARTx, uint16_t USART_LINBreakDetectLength) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_LIN_BREAK_DETECT_LENGTH(USART_LINBreakDetectLength)); + + USARTx->CTRL2 &= CTRL2_LINBDL_MASK; + USARTx->CTRL2 |= USART_LINBreakDetectLength; +} + +/** + * @brief Enables or disables the USART's LIN mode. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param Cmd new state of the USART LIN mode. + * This parameter can be: ENABLE or DISABLE. + */ +void USART_EnableLIN(USART_Module* USARTx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the LIN mode by setting the LINEN bit in the CTRL2 register */ + USARTx->CTRL2 |= CTRL2_LINMEN_SET; + } + else + { + /* Disable the LIN mode by clearing the LINEN bit in the CTRL2 register */ + USARTx->CTRL2 &= CTRL2_LINMEN_RESET; + } +} + +/** + * @brief Transmits single data through the USARTx peripheral. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param Data the data to transmit. + */ +void USART_SendData(USART_Module* USARTx, uint16_t Data) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_DATA(Data)); + + /* Transmit Data */ + USARTx->DAT = (Data & (uint16_t)0x01FF); +} + +/** + * @brief Returns the most recent received data by the USARTx peripheral. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @return The received data. + */ +uint16_t USART_ReceiveData(USART_Module* USARTx) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + + /* Receive Data */ + return (uint16_t)(USARTx->DAT & (uint16_t)0x01FF); +} + +/** + * @brief Transmits break characters. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + */ +void USART_SendBreak(USART_Module* USARTx) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + + /* Send break characters */ + USARTx->CTRL1 |= CTRL1_SDBRK_SET; +} + +/** + * @brief Sets the specified USART guard time. + * @param USARTx where x can be 1, 2 or 3 to select the USART peripheral. + * @param USART_GuardTime specifies the guard time. + * @note The guard time bits are not available for UART4/UART5/UART6/UART7. + */ +void USART_SetGuardTime(USART_Module* USARTx, uint8_t USART_GuardTime) +{ + /* Check the parameters */ + assert_param(IS_USART_123_PERIPH(USARTx)); + + /* Clear the USART Guard time */ + USARTx->GTP &= GTP_LSB_MASK; + /* Set the USART guard time */ + USARTx->GTP |= (uint16_t)((uint16_t)USART_GuardTime << 0x08); +} + +/** + * @brief Sets the system clock prescaler. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_Prescaler specifies the prescaler clock. + * @note The function is used for IrDA mode with UART4 and UART5. + */ +void USART_SetPrescaler(USART_Module* USARTx, uint8_t USART_Prescaler) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + + /* Clear the USART prescaler */ + USARTx->GTP &= GTP_MSB_MASK; + /* Set the USART prescaler */ + USARTx->GTP |= USART_Prescaler; +} + +/** + * @brief Enables or disables the USART's Smart Card mode. + * @param USARTx where x can be 1, 2 or 3 to select the USART peripheral. + * @param Cmd new state of the Smart Card mode. + * This parameter can be: ENABLE or DISABLE. + * @note The Smart Card mode is not available for UART4/UART5/UART6/UART7. + */ +void USART_EnableSmartCard(USART_Module* USARTx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_USART_123_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the SC mode by setting the SCEN bit in the CTRL3 register */ + USARTx->CTRL3 |= CTRL3_SCMEN_SET; + } + else + { + /* Disable the SC mode by clearing the SCEN bit in the CTRL3 register */ + USARTx->CTRL3 &= CTRL3_SCMEN_RESET; + } +} + +/** + * @brief Enables or disables NACK transmission. + * @param USARTx where x can be 1, 2 or 3 to select the USART peripheral. + * @param Cmd new state of the NACK transmission. + * This parameter can be: ENABLE or DISABLE. + * @note The Smart Card mode is not available for UART4/UART5/UART6/UART7. + */ +void USART_SetSmartCardNACK(USART_Module* USARTx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_USART_123_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the NACK transmission by setting the NACK bit in the CTRL3 register */ + USARTx->CTRL3 |= CTRL3_SCNACK_SET; + } + else + { + /* Disable the NACK transmission by clearing the NACK bit in the CTRL3 register */ + USARTx->CTRL3 &= CTRL3_SCNACK_RESET; + } +} + +/** + * @brief Enables or disables the USART's Half Duplex communication. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param Cmd new state of the USART Communication. + * This parameter can be: ENABLE or DISABLE. + */ +void USART_EnableHalfDuplex(USART_Module* USARTx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the Half-Duplex mode by setting the HDSEL bit in the CTRL3 register */ + USARTx->CTRL3 |= CTRL3_HDMEN_SET; + } + else + { + /* Disable the Half-Duplex mode by clearing the HDSEL bit in the CTRL3 register */ + USARTx->CTRL3 &= CTRL3_HDMEN_RESET; + } +} + +/** + * @brief Configures the USART's IrDA interface. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_IrDAMode specifies the IrDA mode. + * This parameter can be one of the following values: + * @arg USART_IRDAMODE_LOWPPWER + * @arg USART_IRDAMODE_NORMAL + */ +void USART_ConfigIrDAMode(USART_Module* USARTx, uint16_t USART_IrDAMode) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_IRDA_MODE(USART_IrDAMode)); + + USARTx->CTRL3 &= CTRL3_IRDALP_MASK; + USARTx->CTRL3 |= USART_IrDAMode; +} + +/** + * @brief Enables or disables the USART's IrDA interface. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param Cmd new state of the IrDA mode. + * This parameter can be: ENABLE or DISABLE. + */ +void USART_EnableIrDA(USART_Module* USARTx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the IrDA mode by setting the IREN bit in the CTRL3 register */ + USARTx->CTRL3 |= CTRL3_IRDAMEN_SET; + } + else + { + /* Disable the IrDA mode by clearing the IREN bit in the CTRL3 register */ + USARTx->CTRL3 &= CTRL3_IRDAMEN_RESET; + } +} + +/** + * @brief Checks whether the specified USART flag is set or not. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg USART_FLAG_CTSF CTS Change flag (not available for UART4 and UART5) + * @arg USART_FLAG_LINBD LIN Break detection flag + * @arg USART_FLAG_TXDE Transmit data register empty flag + * @arg USART_FLAG_TXC Transmission Complete flag + * @arg USART_FLAG_RXDNE Receive data register not empty flag + * @arg USART_FLAG_IDLEF Idle Line detection flag + * @arg USART_FLAG_OREF OverRun Error flag + * @arg USART_FLAG_NEF Noise Error flag + * @arg USART_FLAG_FEF Framing Error flag + * @arg USART_FLAG_PEF Parity Error flag + * @return The new state of USART_FLAG (SET or RESET). + */ +FlagStatus USART_GetFlagStatus(USART_Module* USARTx, uint16_t USART_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_FLAG(USART_FLAG)); + /* The CTS flag is not available for UART4/UART5/UART6/UART7 */ + if (USART_FLAG == USART_FLAG_CTSF) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + + if ((USARTx->STS & USART_FLAG) != (uint16_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the USARTx's pending flags. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_FLAG specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg USART_FLAG_CTSF CTS Change flag (not available for UART4 and UART5). + * @arg USART_FLAG_LINBD LIN Break detection flag. + * @arg USART_FLAG_TXC Transmission Complete flag. + * @arg USART_FLAG_RXDNE Receive data register not empty flag. + * + * @note + * - PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun + * error) and IDLE (Idle line detected) flags are cleared by software + * sequence: a read operation to USART_SR register (USART_GetFlagStatus()) + * followed by a read operation to USART_DR register (USART_ReceiveData()). + * - RXNE flag can be also cleared by a read to the USART_DR register + * (USART_ReceiveData()). + * - TC flag can be also cleared by software sequence: a read operation to + * USART_SR register (USART_GetFlagStatus()) followed by a write operation + * to USART_DR register (USART_SendData()). + * - TXE flag is cleared only by a write to the USART_DR register + * (USART_SendData()). + */ +void USART_ClrFlag(USART_Module* USARTx, uint16_t USART_FLAG) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_CLEAR_FLAG(USART_FLAG)); + /* The CTS flag is not available for UART4/UART5/UART6/UART7 */ + if ((USART_FLAG & USART_FLAG_CTSF) == USART_FLAG_CTSF) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + + USARTx->STS = (uint16_t)~USART_FLAG; +} + +/** + * @brief Checks whether the specified USART interrupt has occurred or not. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_INT specifies the USART interrupt source to check. + * This parameter can be one of the following values: + * @arg USART_INT_CTSF CTS change interrupt (not available for UART4 and UART5) + * @arg USART_INT_LINBD LIN Break detection interrupt + * @arg USART_INT_TXDE Tansmit Data Register empty interrupt + * @arg USART_INT_TXC Transmission complete interrupt + * @arg USART_INT_RXDNE Receive Data register not empty interrupt + * @arg USART_INT_IDLEF Idle line detection interrupt + * @arg USART_INT_OREF OverRun Error interrupt + * @arg USART_INT_NEF Noise Error interrupt + * @arg USART_INT_FEF Framing Error interrupt + * @arg USART_INT_PEF Parity Error interrupt + * @return The new state of USART_INT (SET or RESET). + */ +INTStatus USART_GetIntStatus(USART_Module* USARTx, uint16_t USART_INT) +{ + uint32_t bitpos = 0x00, itmask = 0x00, usartreg = 0x00; + INTStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_GET_INT(USART_INT)); + /* The CTS interrupt is not available for UART4/UART5/UART6/UART7 */ + if (USART_INT == USART_INT_CTSF) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + + /* Get the USART register index */ + usartreg = (((uint8_t)USART_INT) >> 0x05); + /* Get the interrupt position */ + itmask = USART_INT & INT_MASK; + itmask = (uint32_t)0x01 << itmask; + + if (usartreg == 0x01) /* The IT is in CTRL1 register */ + { + itmask &= USARTx->CTRL1; + } + else if (usartreg == 0x02) /* The IT is in CTRL2 register */ + { + itmask &= USARTx->CTRL2; + } + else /* The IT is in CTRL3 register */ + { + itmask &= USARTx->CTRL3; + } + + bitpos = USART_INT >> 0x08; + bitpos = (uint32_t)0x01 << bitpos; + bitpos &= USARTx->STS; + if ((itmask != (uint16_t)RESET) && (bitpos != (uint16_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/** + * @brief Clears the USARTx's interrupt pending bits. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_INT specifies the interrupt pending bit to clear. + * This parameter can be one of the following values: + * @arg USART_INT_CTSF CTS change interrupt (not available for UART4 and UART5) + * @arg USART_INT_LINBD LIN Break detection interrupt + * @arg USART_INT_TXC Transmission complete interrupt. + * @arg USART_INT_RXDNE Receive Data register not empty interrupt. + * + * @note + * - PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun + * error) and IDLE (Idle line detected) pending bits are cleared by + * software sequence: a read operation to USART_SR register + * (USART_GetIntStatus()) followed by a read operation to USART_DR register + * (USART_ReceiveData()). + * - RXNE pending bit can be also cleared by a read to the USART_DR register + * (USART_ReceiveData()). + * - TC pending bit can be also cleared by software sequence: a read + * operation to USART_SR register (USART_GetIntStatus()) followed by a write + * operation to USART_DR register (USART_SendData()). + * - TXE pending bit is cleared only by a write to the USART_DR register + * (USART_SendData()). + */ +void USART_ClrIntPendingBit(USART_Module* USARTx, uint16_t USART_INT) +{ + uint16_t bitpos = 0x00, itmask = 0x00; + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_CLR_INT(USART_INT)); + /* The CTS interrupt is not available for UART4/UART5/UART6/UART7 */ + if (USART_INT == USART_INT_CTSF) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + + bitpos = USART_INT >> 0x08; + itmask = ((uint16_t)0x01 << (uint16_t)bitpos); + USARTx->STS = (uint16_t)~itmask; +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_wwdg.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_wwdg.c new file mode 100644 index 0000000000..49a9ebad4a --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_std_periph_driver/src/n32g4fr_wwdg.c @@ -0,0 +1,223 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file n32g4fr_wwdg.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g4fr_wwdg.h" +#include "n32g4fr_rcc.h" + +/** @addtogroup N32G4FR_StdPeriph_Driver + * @{ + */ + +/** @addtogroup WWDG + * @brief WWDG driver modules + * @{ + */ + +/** @addtogroup WWDG_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup WWDG_Private_Defines + * @{ + */ + +/* ----------- WWDG registers bit address in the alias region ----------- */ +#define WWDG_OFFADDR (WWDG_BASE - PERIPH_BASE) + +/* Alias word address of EWI bit */ +#define CFG_OFFADDR (WWDG_OFFADDR + 0x04) +#define EWINT_BIT 0x09 +#define CFG_EWINT_BB (PERIPH_BB_BASE + (CFG_OFFADDR * 32) + (EWINT_BIT * 4)) + +/* --------------------- WWDG registers bit mask ------------------------ */ + +/* CTRL register bit mask */ +#define CTRL_ACTB_SET ((uint32_t)0x00000080) + +/* CFG register bit mask */ +#define CFG_TIMERB_MASK ((uint32_t)0xFFFFFE7F) +#define CFG_W_MASK ((uint32_t)0xFFFFFF80) +#define BIT_MASK ((uint8_t)0x7F) + +/** + * @} + */ + +/** @addtogroup WWDG_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup WWDG_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup WWDG_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup WWDG_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the WWDG peripheral registers to their default reset values. + */ +void WWDG_DeInit(void) +{ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_WWDG, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_WWDG, DISABLE); +} + +/** + * @brief Sets the WWDG Prescaler. + * @param WWDG_Prescaler specifies the WWDG Prescaler. + * This parameter can be one of the following values: + * @arg WWDG_PRESCALER_DIV1 WWDG counter clock = (PCLK1/4096)/1 + * @arg WWDG_PRESCALER_DIV2 WWDG counter clock = (PCLK1/4096)/2 + * @arg WWDG_PRESCALER_DIV4 WWDG counter clock = (PCLK1/4096)/4 + * @arg WWDG_PRESCALER_DIV8 WWDG counter clock = (PCLK1/4096)/8 + */ +void WWDG_SetPrescalerDiv(uint32_t WWDG_Prescaler) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_WWDG_PRESCALER_DIV(WWDG_Prescaler)); + /* Clear WDGTB[1:0] bits */ + tmpregister = WWDG->CFG & CFG_TIMERB_MASK; + /* Set WDGTB[1:0] bits according to WWDG_Prescaler value */ + tmpregister |= WWDG_Prescaler; + /* Store the new value */ + WWDG->CFG = tmpregister; +} + +/** + * @brief Sets the WWDG window value. + * @param WindowValue specifies the window value to be compared to the downcounter. + * This parameter value must be lower than 0x80. + */ +void WWDG_SetWValue(uint8_t WindowValue) +{ + __IO uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_WWDG_WVALUE(WindowValue)); + /* Clear W[6:0] bits */ + + tmpregister = WWDG->CFG & CFG_W_MASK; + + /* Set W[6:0] bits according to WindowValue value */ + tmpregister |= WindowValue & (uint32_t)BIT_MASK; + + /* Store the new value */ + WWDG->CFG = tmpregister; +} + +/** + * @brief Enables the WWDG Early Wakeup interrupt(EWI). + */ +void WWDG_EnableInt(void) +{ + *(__IO uint32_t*)CFG_EWINT_BB = (uint32_t)ENABLE; +} + +/** + * @brief Sets the WWDG counter value. + * @param Counter specifies the watchdog counter value. + * This parameter must be a number between 0x40 and 0x7F. + */ +void WWDG_SetCnt(uint8_t Counter) +{ + /* Check the parameters */ + assert_param(IS_WWDG_CNT(Counter)); + /* Write to T[6:0] bits to configure the counter value, no need to do + a read-modify-write; writing a 0 to WDGA bit does nothing */ + WWDG->CTRL = Counter & BIT_MASK; +} + +/** + * @brief Enables WWDG and load the counter value. + * @param Counter specifies the watchdog counter value. + * This parameter must be a number between 0x40 and 0x7F. + */ +void WWDG_Enable(uint8_t Counter) +{ + /* Check the parameters */ + assert_param(IS_WWDG_CNT(Counter)); + WWDG->CTRL = CTRL_ACTB_SET | Counter; +} + +/** + * @brief Checks whether the Early Wakeup interrupt flag is set or not. + * @return The new state of the Early Wakeup interrupt flag (SET or RESET) + */ +FlagStatus WWDG_GetEWINTF(void) +{ + return (FlagStatus)(WWDG->STS); +} + +/** + * @brief Clears Early Wakeup interrupt flag. + */ +void WWDG_ClrEWINTF(void) +{ + WWDG->STS = (uint32_t)RESET; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_core.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_core.h new file mode 100644 index 0000000000..0447ebfec6 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_core.h @@ -0,0 +1,264 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file usb_core.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __USB_CORE_H__ +#define __USB_CORE_H__ + +#include "n32g4fr.h" + +/** + * @addtogroup N32G4FR_USB_Driver + * @brief N32G4FR USB low level driver + * @{ + */ + +typedef enum _CONTROL_STATE +{ + WaitSetup, /* 0 */ + SettingUp, /* 1 */ + InData, /* 2 */ + OutData, /* 3 */ + LastInData, /* 4 */ + LastOutData, /* 5 */ + WaitStatusIn, /* 7 */ + WaitStatusOut, /* 8 */ + Stalled, /* 9 */ + Pause /* 10 */ +} USB_ControlState; /* The state machine states of a control pipe */ + +typedef struct OneDescriptor +{ + uint8_t* Descriptor; + uint16_t Descriptor_Size; +} USB_OneDescriptor, *PONE_DESCRIPTOR; +/* All the request process routines return a value of this type + If the return value is not SUCCESS or NOT_READY, + the software will STALL the correspond endpoint */ +typedef enum _RESULT +{ + Success = 0, /* Process successfully */ + Error, + UnSupport, + Not_Ready /* The process has not been finished, endpoint will be + NAK to further request */ +} USB_Result; + +/*-*-*-*-*-*-*-*-*-*-* Definitions for endpoint level -*-*-*-*-*-*-*-*-*-*-*-*/ +typedef struct _ENDPOINT_INFO +{ + /* When send data out of the device, + CopyData() is used to get data buffer 'Length' bytes data + if Length is 0, + CopyData() returns the total length of the data + if the request is not supported, returns 0 + (NEW Feature ) + if CopyData() returns -1, the calling routine should not proceed + further and will resume the SETUP process by the class device + if Length is not 0, + CopyData() returns a pointer to indicate the data location + Usb_wLength is the data remain to be sent, + Usb_wOffset is the Offset of original data + When receive data from the host, + CopyData() is used to get user data buffer which is capable + of Length bytes data to copy data from the endpoint buffer. + if Length is 0, + CopyData() returns the available data length, + if Length is not 0, + CopyData() returns user buffer address + Usb_rLength is the data remain to be received, + Usb_rPointer is the Offset of data buffer + */ + uint16_t Usb_wLength; + uint16_t Usb_wOffset; + uint16_t PacketSize; + uint8_t* (*CopyData)(uint16_t Length); +} USB_EndpointMess; + +/*-*-*-*-*-*-*-*-*-*-*-* Definitions for device level -*-*-*-*-*-*-*-*-*-*-*-*/ + +typedef struct _DEVICE +{ + uint8_t TotalEndpoint; /* Number of endpoints that are used */ + uint8_t TotalConfiguration; /* Number of configuration available */ +} USB_Device; + +typedef union +{ + uint16_t w; + struct BW + { + uint8_t bb1; + uint8_t bb0; + } bw; +} uint16_t_uint8_t; + +typedef struct _DEVICE_INFO +{ + uint8_t bmRequestType; /* bmRequestType */ + uint8_t bRequest; /* bRequest */ + uint16_t_uint8_t wValues; /* wValue */ + uint16_t_uint8_t wIndexs; /* wIndex */ + uint16_t_uint8_t wLengths; /* wLength */ + + uint8_t CtrlState; /* of type USB_ControlState */ + uint8_t CurrentFeature; + uint8_t CurrentConfiguration; /* Selected configuration */ + uint8_t CurrentInterface; /* Selected interface of current configuration */ + uint8_t CurrentAlternateSetting; /* Selected Alternate Setting of current + interface*/ + + USB_EndpointMess Ctrl_Info; +} USB_DeviceMess; + +typedef struct _DEVICE_PROP +{ + void (*Init)(void); /* Initialize the device */ + void (*Reset)(void); /* Reset routine of this device */ + + /* Device dependent process after the status stage */ + void (*Process_Status_IN)(void); + void (*Process_Status_OUT)(void); + + /* Procedure of process on setup stage of a class specified request with data stage */ + /* All class specified requests with data stage are processed in Class_Data_Setup + Class_Data_Setup() + responses to check all special requests and fills USB_EndpointMess + according to the request + If IN tokens are expected, then wLength & wOffset will be filled + with the total transferring bytes and the starting position + If OUT tokens are expected, then rLength & rOffset will be filled + with the total expected bytes and the starting position in the buffer + + If the request is valid, Class_Data_Setup returns SUCCESS, else UNSUPPORT + + CAUTION: + Since GET_CONFIGURATION & GET_INTERFACE are highly related to + the individual classes, they will be checked and processed here. + */ + USB_Result (*Class_Data_Setup)(uint8_t RequestNo); + + /* Procedure of process on setup stage of a class specified request without data stage */ + /* All class specified requests without data stage are processed in Class_NoData_Setup + Class_NoData_Setup + responses to check all special requests and perform the request + + CAUTION: + Since SET_CONFIGURATION & SET_INTERFACE are highly related to + the individual classes, they will be checked and processed here. + */ + USB_Result (*Class_NoData_Setup)(uint8_t RequestNo); + + /*Class_Get_Interface_Setting + This function is used by the file usb_core.c to test if the selected Interface + and Alternate Setting (uint8_t Interface, uint8_t AlternateSetting) are supported by + the application. + This function is writing by user. It should return "SUCCESS" if the Interface + and Alternate Setting are supported by the application or "UNSUPPORT" if they + are not supported. */ + + USB_Result (*Class_Get_Interface_Setting)(uint8_t Interface, uint8_t AlternateSetting); + + uint8_t* (*GetDeviceDescriptor)(uint16_t Length); + uint8_t* (*GetConfigDescriptor)(uint16_t Length); + uint8_t* (*GetStringDescriptor)(uint16_t Length); + + /* This field is not used in current library version. It is kept only for + compatibility with previous versions */ + void* RxEP_buffer; + + uint8_t MaxPacketSize; + +} DEVICE_PROP; + +typedef struct _USER_STANDARD_REQUESTS +{ + void (*User_GetConfiguration)(void); /* Get Configuration */ + void (*User_SetConfiguration)(void); /* Set Configuration */ + void (*User_GetInterface)(void); /* Get Interface */ + void (*User_SetInterface)(void); /* Set Interface */ + void (*User_GetStatus)(void); /* Get Status */ + void (*User_ClearFeature)(void); /* Clear Feature */ + void (*User_SetEndPointFeature)(void); /* Set Endpoint Feature */ + void (*User_SetDeviceFeature)(void); /* Set Device Feature */ + void (*User_SetDeviceAddress)(void); /* Set Device Address */ +} USER_STANDARD_REQUESTS; + +#define Type_Recipient (pInformation->bmRequestType & (REQUEST_TYPE | RECIPIENT)) + +#define Usb_rLength Usb_wLength +#define Usb_rOffset Usb_wOffset + +#define USBwValue wValues.w +#define USBwValue0 wValues.bw.bb0 +#define USBwValue1 wValues.bw.bb1 +#define USBwIndex wIndexs.w +#define USBwIndex0 wIndexs.bw.bb0 +#define USBwIndex1 wIndexs.bw.bb1 +#define USBwLength wLengths.w +#define USBwLength0 wLengths.bw.bb0 +#define USBwLength1 wLengths.bw.bb1 + +uint8_t USB_ProcessSetup0(void); +uint8_t USB_ProcessPost0(void); +uint8_t USB_ProcessOut0(void); +uint8_t USB_ProcessIn0(void); + +USB_Result Standard_SetEndPointFeature(void); +USB_Result Standard_SetDeviceFeature(void); + +uint8_t* Standard_GetConfiguration(uint16_t Length); +USB_Result Standard_SetConfiguration(void); +uint8_t* Standard_GetInterface(uint16_t Length); +USB_Result Standard_SetInterface(void); +uint8_t* Standard_GetDescriptorData(uint16_t Length, PONE_DESCRIPTOR pDesc); + +uint8_t* Standard_GetStatus(uint16_t Length); +USB_Result Standard_ClearFeature(void); +void USB_SetDeviceAddress(uint8_t); +void USB_ProcessNop(void); + +extern DEVICE_PROP Device_Property; +extern USER_STANDARD_REQUESTS User_Standard_Requests; +extern USB_Device Device_Table; +extern USB_DeviceMess Device_Info; + +/* cells saving status during interrupt servicing */ +extern __IO uint16_t SaveRState; +extern __IO uint16_t SaveTState; + +/** + * @} + */ + +#endif /* __USB_CORE_H__ */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_def.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_def.h new file mode 100644 index 0000000000..baf9f79b28 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_def.h @@ -0,0 +1,98 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file usb_def.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __USB_DEF_H__ +#define __USB_DEF_H__ + +/** + * @addtogroup N32G4FR_USB_Driver + * @{ + */ + +typedef enum _RECIPIENT_TYPE +{ + DEVICE_RECIPIENT, /* Recipient device */ + INTERFACE_RECIPIENT, /* Recipient interface */ + ENDPOINT_RECIPIENT, /* Recipient endpoint */ + OTHER_RECIPIENT +} RECIPIENT_TYPE; + +typedef enum _STANDARD_REQUESTS +{ + GET_STATUS = 0, + CLR_FEATURE, + RESERVED1, + SET_FEATURE, + RESERVED2, + SET_ADDRESS, + GET_DESCRIPTOR, + SET_DESCRIPTOR, + GET_CONFIGURATION, + SET_CONFIGURATION, + GET_INTERFACE, + SET_INTERFACE, + TOTAL_SREQUEST, /* Total number of Standard request */ + SYNCH_FRAME = 12 +} STANDARD_REQUESTS; + +/* Definition of "USBwValue" */ +typedef enum _DESCRIPTOR_TYPE +{ + DEVICE_DESCRIPTOR = 1, + CONFIG_DESCRIPTOR, + STRING_DESCRIPTOR, + INTERFACE_DESCRIPTOR, + ENDPOINT_DESCRIPTOR +} DESCRIPTOR_TYPE; + +/* Feature selector of a SET_FEATURE or CLR_FEATURE */ +typedef enum _FEATURE_SELECTOR +{ + ENDPOINT_STALL, + DEVICE_REMOTE_WAKEUP +} FEATURE_SELECTOR; + +/* Definition of "bmRequestType" */ +#define REQUEST_TYPE 0x60 /* Mask to get request type */ +#define STANDARD_REQUEST 0x00 /* Standard request */ +#define CLASS_REQUEST 0x20 /* Class request */ +#define VENDOR_REQUEST 0x40 /* Vendor request */ + +#define RECIPIENT 0x1F /* Mask to get recipient */ + +/** + * @} + */ + +#endif /* __USB_DEF_H__ */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_init.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_init.h new file mode 100644 index 0000000000..e3cfc77bc8 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_init.h @@ -0,0 +1,71 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file usb_init.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __USB_INIT_H__ +#define __USB_INIT_H__ + +#include "n32g4fr.h" +#include "usb_core.h" + +/** + * @addtogroup N32G4FR_USB_Driver + * @{ + */ + +void USB_Init(void); + +/* The number of current endpoint, it will be used to specify an endpoint */ +extern uint8_t EPindex; +/* The number of current device, it is an index to the Device_Table */ +/*extern uint8_t Device_no; */ +/* Points to the USB_DeviceMess structure of current device */ +/* The purpose of this register is to speed up the execution */ +extern USB_DeviceMess* pInformation; +/* Points to the DEVICE_PROP structure of current device */ +/* The purpose of this register is to speed up the execution */ +extern DEVICE_PROP* pProperty; +/* Temporary save the state of Rx & Tx status. */ +/* Whenever the Rx or Tx state is changed, its value is saved */ +/* in this variable first and will be set to the EPRB or EPRA */ +/* at the end of interrupt process */ +extern USER_STANDARD_REQUESTS* pUser_Standard_Requests; + +extern uint16_t SaveState; +extern uint16_t wInterrupt_Mask; + +/** + * @} + */ + +#endif /* __USB_INIT_H__ */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_int.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_int.h new file mode 100644 index 0000000000..c5ab0ad180 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_int.h @@ -0,0 +1,50 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file usb_int.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __USB_INT_H__ +#define __USB_INT_H__ + +/** + * @addtogroup N32G4FR_USB_Driver + * @{ + */ + +void USB_CorrectTransferLp(void); +void USB_CorrectTransferHp(void); + +/** + * @} + */ + +#endif /* __USB_INT_H__ */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_lib.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_lib.h new file mode 100644 index 0000000000..3bd907dcac --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_lib.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file usb_lib.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __USB_LIB_H__ +#define __USB_LIB_H__ + +#include "usb_type.h" +#include "usb_regs.h" +#include "usb_def.h" +#include "usb_core.h" +#include "usb_init.h" +#include "usb_sil.h" +#include "usb_mem.h" +#include "usb_int.h" + +#endif /* __USB_LIB_H__ */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_mem.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_mem.h new file mode 100644 index 0000000000..3aec93557a --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_mem.h @@ -0,0 +1,52 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file usb_mem.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __USB_MEM_H__ +#define __USB_MEM_H__ + +#include "n32g4fr.h" + +/** + * @addtogroup N32G4FR_USB_Driver + * @{ + */ + +void USB_CopyUserToPMABuf(uint8_t* pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes); +void USB_CopyPMAToUserBuf(uint8_t* pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes); + +/** + * @} + */ + +#endif /*__USB_MEM_H__*/ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_regs.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_regs.h new file mode 100644 index 0000000000..16da6bb102 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_regs.h @@ -0,0 +1,715 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file usb_regs.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __USB_REGS_H__ +#define __USB_REGS_H__ + +#include "n32g4fr.h" + +/** + * @addtogroup N32G4FR_USB_Driver + * @{ + */ + +typedef enum _EP_DBUF_DIR +{ + /* double buffered endpoint direction */ + EP_DBUF_ERR, + EP_DBUF_OUT, + EP_DBUF_IN +} EP_DBUF_DIR; + +/* endpoint buffer number */ +enum EP_BUF_NUM +{ + EP_NOBUF, + EP_BUF0, + EP_BUF1 +}; + +#define RegBase (0x40005C00L) /* USB_IP Peripheral Registers base address */ +#define PMAAddr (0x40006000L) /* USB_IP Packet Memory Area base address */ + +/******************************************************************************/ +/* Special registers */ +/******************************************************************************/ +/* Pull up controller register */ +#define DP_CTRL ((__IO unsigned*)(0x40001820)) + +#define _EnPortPullup() (*DP_CTRL = (*DP_CTRL) | 0x10000000); +#define _DisPortPullup() (*DP_CTRL = (*DP_CTRL) & 0xEFFFFFFF); + +/******************************************************************************/ +/* General registers */ +/******************************************************************************/ + +/* Control register */ +#define USB_CTRL ((__IO unsigned*)(RegBase + 0x40)) +/* Interrupt status register */ +#define USB_STS ((__IO unsigned*)(RegBase + 0x44)) +/* Frame number register */ +#define USB_FN ((__IO unsigned*)(RegBase + 0x48)) +/* Device address register */ +#define USB_ADDR ((__IO unsigned*)(RegBase + 0x4C)) +/* Buffer Table address register */ +#define USB_BUFTAB ((__IO unsigned*)(RegBase + 0x50)) +/******************************************************************************/ +/* Endpoint registers */ +/******************************************************************************/ +#define EP0REG ((__IO unsigned*)(RegBase)) /* endpoint 0 register address */ + +/* Endpoint Addresses (w/direction) */ +#define EP0_OUT ((uint8_t)0x00) +#define EP0_IN ((uint8_t)0x80) +#define EP1_OUT ((uint8_t)0x01) +#define EP1_IN ((uint8_t)0x81) +#define EP2_OUT ((uint8_t)0x02) +#define EP2_IN ((uint8_t)0x82) +#define EP3_OUT ((uint8_t)0x03) +#define EP3_IN ((uint8_t)0x83) +#define EP4_OUT ((uint8_t)0x04) +#define EP4_IN ((uint8_t)0x84) +#define EP5_OUT ((uint8_t)0x05) +#define EP5_IN ((uint8_t)0x85) +#define EP6_OUT ((uint8_t)0x06) +#define EP6_IN ((uint8_t)0x86) +#define EP7_OUT ((uint8_t)0x07) +#define EP7_IN ((uint8_t)0x87) + +/* endpoints enumeration */ +#define ENDP0 ((uint8_t)0) +#define ENDP1 ((uint8_t)1) +#define ENDP2 ((uint8_t)2) +#define ENDP3 ((uint8_t)3) +#define ENDP4 ((uint8_t)4) +#define ENDP5 ((uint8_t)5) +#define ENDP6 ((uint8_t)6) +#define ENDP7 ((uint8_t)7) + +/******************************************************************************/ +/* USB_STS interrupt events */ +/******************************************************************************/ +#define STS_CTRS (0x8000) /* Correct TRansfer (clear-only bit) */ +#define STS_DOVR (0x4000) /* DMA OVeR/underrun (clear-only bit) */ +#define STS_ERROR (0x2000) /* ERRor (clear-only bit) */ +#define STS_WKUP (0x1000) /* WaKe UP (clear-only bit) */ +#define STS_SUSPD (0x0800) /* SUSPend (clear-only bit) */ +#define STS_RST (0x0400) /* RESET (clear-only bit) */ +#define STS_SOF (0x0200) /* Start Of Frame (clear-only bit) */ +#define STS_ESOF (0x0100) /* Expected Start Of Frame (clear-only bit) */ + +#define STS_DIR (0x0010) /* DIRection of transaction (read-only bit) */ +#define STS_EP_ID (0x000F) /* EndPoint IDentifier (read-only bit) */ + +#define CLR_CTRS (~STS_CTRS) /* clear Correct TRansfer bit */ +#define CLR_DOVR (~STS_DOVR) /* clear DMA OVeR/underrun bit*/ +#define CLR_ERROR (~STS_ERROR) /* clear ERRor bit */ +#define CLR_WKUP (~STS_WKUP) /* clear WaKe UP bit */ +#define CLR_SUSPD (~STS_SUSPD) /* clear SUSPend bit */ +#define CLR_RST (~STS_RST) /* clear RESET bit */ +#define CLR_SOF (~STS_SOF) /* clear Start Of Frame bit */ +#define CLR_ESOF (~STS_ESOF) /* clear Expected Start Of Frame bit */ + +/******************************************************************************/ +/* USB_CTRL control register bits definitions */ +/******************************************************************************/ +#define CTRL_CTRSM (0x8000) /* Correct TRansfer Mask */ +#define CTRL_DOVRM (0x4000) /* DMA OVeR/underrun Mask */ +#define CTRL_ERRORM (0x2000) /* ERRor Mask */ +#define CTRL_WKUPM (0x1000) /* WaKe UP Mask */ +#define CTRL_SUSPDM (0x0800) /* SUSPend Mask */ +#define CTRL_RSTM (0x0400) /* RESET Mask */ +#define CTRL_SOFM (0x0200) /* Start Of Frame Mask */ +#define CTRL_ESOFM (0x0100) /* Expected Start Of Frame Mask */ + +#define CTRL_RESUM (0x0010) /* RESUME request */ +#define CTRL_FSUSPD (0x0008) /* Force SUSPend */ +#define CTRL_LP_MODE (0x0004) /* Low-power MODE */ +#define CTRL_PD (0x0002) /* Power DoWN */ +#define CTRL_FRST (0x0001) /* Force USB RESet */ + +/******************************************************************************/ +/* USB_FN Frame Number Register bit definitions */ +/******************************************************************************/ +#define FN_RXDP (0x8000) /* status of D+ data line */ +#define FN_RXDM (0x4000) /* status of D- data line */ +#define FN_LCK (0x2000) /* LoCKed */ +#define FN_LSOF (0x1800) /* Lost SOF */ +#define FN_FNUM (0x07FF) /* Frame Number */ +/******************************************************************************/ +/* USB_ADDR Device ADDRess bit definitions */ +/******************************************************************************/ +#define ADDR_EFUC (0x80) +#define ADDR_ADDR (0x7F) +/******************************************************************************/ +/* Endpoint register */ +/******************************************************************************/ +/* bit positions */ +#define EP_CTRS_RX (0x8000) /* EndPoint Correct TRansfer RX */ +#define EP_DATTOG_RX (0x4000) /* EndPoint Data TOGGLE RX */ +#define EPRX_STS (0x3000) /* EndPoint RX STATus bit field */ +#define EP_SETUP (0x0800) /* EndPoint SETUP */ +#define EP_T_FIELD (0x0600) /* EndPoint TYPE */ +#define EP_KIND (0x0100) /* EndPoint KIND */ +#define EP_CTRS_TX (0x0080) /* EndPoint Correct TRansfer TX */ +#define EP_DATTOG_TX (0x0040) /* EndPoint Data TOGGLE TX */ +#define EPTX_STS (0x0030) /* EndPoint TX STATus bit field */ +#define EPADDR_FIELD (0x000F) /* EndPoint ADDRess FIELD */ + +/* EndPoint REGister INTEN (no toggle fields) */ +#define EPREG_MASK (EP_CTRS_RX | EP_SETUP | EP_T_FIELD | EP_KIND | EP_CTRS_TX | EPADDR_FIELD) + +/* EP_TYPE[1:0] EndPoint TYPE */ +#define EP_TYPE_MASK (0x0600) /* EndPoint TYPE Mask */ +#define EP_BULK (0x0000) /* EndPoint BULK */ +#define EP_CONTROL (0x0200) /* EndPoint CONTROL */ +#define EP_ISOCHRONOUS (0x0400) /* EndPoint ISOCHRONOUS */ +#define EP_INTERRUPT (0x0600) /* EndPoint INTERRUPT */ +#define EP_T_MASK (~EP_T_FIELD & EPREG_MASK) + +/* EP_KIND EndPoint KIND */ +#define EPKIND_MASK (~EP_KIND & EPREG_MASK) + +/* STAT_TX[1:0] STATus for TX transfer */ +#define EP_TX_DIS (0x0000) /* EndPoint TX DISabled */ +#define EP_TX_STALL (0x0010) /* EndPoint TX STALLed */ +#define EP_TX_NAK (0x0020) /* EndPoint TX NAKed */ +#define EP_TX_VALID (0x0030) /* EndPoint TX VALID */ +#define EPTX_DATTOG1 (0x0010) /* EndPoint TX Data TOGgle bit1 */ +#define EPTX_DATTOG2 (0x0020) /* EndPoint TX Data TOGgle bit2 */ +#define EPTX_DATTOGMASK (EPTX_STS | EPREG_MASK) + +/* STAT_RX[1:0] STATus for RX transfer */ +#define EP_RX_DIS (0x0000) /* EndPoint RX DISabled */ +#define EP_RX_STALL (0x1000) /* EndPoint RX STALLed */ +#define EP_RX_NAK (0x2000) /* EndPoint RX NAKed */ +#define EP_RX_VALID (0x3000) /* EndPoint RX VALID */ +#define EPRX_DATTOG1 (0x1000) /* EndPoint RX Data TOGgle bit1 */ +#define EPRX_DATTOG2 (0x2000) /* EndPoint RX Data TOGgle bit1 */ +#define EPRX_DATTOGMASK (EPRX_STS | EPREG_MASK) + +/* USB_SetCtrl */ +#define _SetCNTR(wRegValue) (*USB_CTRL = (uint16_t)wRegValue) + +/* USB_SetSts */ +#define _SetISTR(wRegValue) (*USB_STS = (uint16_t)wRegValue) + +/* USB_SetAddr */ +#define _SetDADDR(wRegValue) (*USB_ADDR = (uint16_t)wRegValue) + +/* USB_SetBuftab */ +#define _SetBTABLE(wRegValue) (*USB_BUFTAB = (uint16_t)(wRegValue & 0xFFF8)) + +/* USB_GetCtrl */ +#define _GetCNTR() ((uint16_t)*USB_CTRL) + +/* USB_GetSts */ +#define _GetISTR() ((uint16_t)*USB_STS) + +/* USB_GetFn */ +#define _GetFNR() ((uint16_t)*USB_FN) + +/* USB_GetAddr */ +#define _GetDADDR() ((uint16_t)*USB_ADDR) + +/* USB_GetBTABLE */ +#define _GetBTABLE() ((uint16_t)*USB_BUFTAB) + +/* USB_SetEndPoint */ +#define _SetENDPOINT(bEpNum, wRegValue) (*(EP0REG + bEpNum) = (uint16_t)wRegValue) + +/* USB_GetEndPoint */ +#define _GetENDPOINT(bEpNum) ((uint16_t)(*(EP0REG + bEpNum))) + +/******************************************************************************* + * Macro Name : USB_SetEpType + * Description : sets the type in the endpoint register(bits EP_TYPE[1:0]) + * Input : bEpNum: Endpoint Number. + * wType + * Output : None. + * Return : None. + *******************************************************************************/ +#define _SetEPType(bEpNum, wType) (_SetENDPOINT(bEpNum, ((_GetENDPOINT(bEpNum) & EP_T_MASK) | wType))) + +/******************************************************************************* + * Macro Name : USB_GetEpType + * Description : gets the type in the endpoint register(bits EP_TYPE[1:0]) + * Input : bEpNum: Endpoint Number. + * Output : None. + * Return : Endpoint Type + *******************************************************************************/ +#define _GetEPType(bEpNum) (_GetENDPOINT(bEpNum) & EP_T_FIELD) + +/******************************************************************************* + * Macro Name : SetEPTxStatus + * Description : sets the status for tx transfer (bits STAT_TX[1:0]). + * Input : bEpNum: Endpoint Number. + * wState: new state + * Output : None. + * Return : None. + *******************************************************************************/ +#define _SetEPTxStatus(bEpNum, wState) \ + { \ + register uint16_t _wRegVal; \ + _wRegVal = _GetENDPOINT(bEpNum) & EPTX_DATTOGMASK; \ + /* toggle first bit ? */ \ + if ((EPTX_DATTOG1 & wState) != 0) \ + _wRegVal ^= EPTX_DATTOG1; \ + /* toggle second bit ? */ \ + if ((EPTX_DATTOG2 & wState) != 0) \ + _wRegVal ^= EPTX_DATTOG2; \ + _SetENDPOINT(bEpNum, (_wRegVal | EP_CTRS_RX | EP_CTRS_TX)); \ + } /* _SetEPTxStatus */ + +/******************************************************************************* + * Macro Name : SetEPRxStatus + * Description : sets the status for rx transfer (bits STAT_TX[1:0]) + * Input : bEpNum: Endpoint Number. + * wState: new state. + * Output : None. + * Return : None. + *******************************************************************************/ +#define _SetEPRxStatus(bEpNum, wState) \ + { \ + register uint16_t _wRegVal; \ + \ + _wRegVal = _GetENDPOINT(bEpNum) & EPRX_DATTOGMASK; \ + /* toggle first bit ? */ \ + if ((EPRX_DATTOG1 & wState) != 0) \ + _wRegVal ^= EPRX_DATTOG1; \ + /* toggle second bit ? */ \ + if ((EPRX_DATTOG2 & wState) != 0) \ + _wRegVal ^= EPRX_DATTOG2; \ + _SetENDPOINT(bEpNum, (_wRegVal | EP_CTRS_RX | EP_CTRS_TX)); \ + } /* _SetEPRxStatus */ + +/******************************************************************************* + * Macro Name : SetEPRxTxStatus + * Description : sets the status for rx & tx (bits STAT_TX[1:0] & STAT_RX[1:0]) + * Input : bEpNum: Endpoint Number. + * wStaterx: new state. + * wStatetx: new state. + * Output : None. + * Return : None. + *******************************************************************************/ +#define _SetEPRxTxStatus(bEpNum, wStaterx, wStatetx) \ + { \ + register uint32_t _wRegVal; \ + \ + _wRegVal = _GetENDPOINT(bEpNum) & (EPRX_DATTOGMASK | EPTX_STS); \ + /* toggle first bit ? */ \ + if ((EPRX_DATTOG1 & wStaterx) != 0) \ + _wRegVal ^= EPRX_DATTOG1; \ + /* toggle second bit ? */ \ + if ((EPRX_DATTOG2 & wStaterx) != 0) \ + _wRegVal ^= EPRX_DATTOG2; \ + /* toggle first bit ? */ \ + if ((EPTX_DATTOG1 & wStatetx) != 0) \ + _wRegVal ^= EPTX_DATTOG1; \ + /* toggle second bit ? */ \ + if ((EPTX_DATTOG2 & wStatetx) != 0) \ + _wRegVal ^= EPTX_DATTOG2; \ + _SetENDPOINT(bEpNum, _wRegVal | EP_CTRS_RX | EP_CTRS_TX); \ + } /* _SetEPRxTxStatus */ +/******************************************************************************* + * Macro Name : USB_GetEpTxSts / USB_GetEpRxSts + * Description : gets the status for tx/rx transfer (bits STAT_TX[1:0] + * /STAT_RX[1:0]) + * Input : bEpNum: Endpoint Number. + * Output : None. + * Return : status . + *******************************************************************************/ +#define _GetEPTxStatus(bEpNum) ((uint16_t)_GetENDPOINT(bEpNum) & EPTX_STS) + +#define _GetEPRxStatus(bEpNum) ((uint16_t)_GetENDPOINT(bEpNum) & EPRX_STS) + +/******************************************************************************* + * Macro Name : USB_SetEpTxValid / USB_SetEpRxValid + * Description : sets directly the VALID tx/rx-status into the enpoint register + * Input : bEpNum: Endpoint Number. + * Output : None. + * Return : None. + *******************************************************************************/ +#define _SetEPTxValid(bEpNum) (_SetEPTxStatus(bEpNum, EP_TX_VALID)) + +#define _SetEPRxValid(bEpNum) (_SetEPRxStatus(bEpNum, EP_RX_VALID)) + +/******************************************************************************* + * Macro Name : USB_GetTxStallSts / USB_GetRxStallSts. + * Description : checks stall condition in an endpoint. + * Input : bEpNum: Endpoint Number. + * Output : None. + * Return : TRUE = endpoint in stall condition. + *******************************************************************************/ +#define _GetTxStallStatus(bEpNum) (_GetEPTxStatus(bEpNum) == EP_TX_STALL) +#define _GetRxStallStatus(bEpNum) (_GetEPRxStatus(bEpNum) == EP_RX_STALL) + +/******************************************************************************* + * Macro Name : USB_SetEpKind / USB_ClrEpKind. + * Description : set & clear EP_KIND bit. + * Input : bEpNum: Endpoint Number. + * Output : None. + * Return : None. + *******************************************************************************/ +#define _SetEP_KIND(bEpNum) \ + (_SetENDPOINT(bEpNum, (EP_CTRS_RX | EP_CTRS_TX | ((_GetENDPOINT(bEpNum) | EP_KIND) & EPREG_MASK)))) +#define _ClearEP_KIND(bEpNum) (_SetENDPOINT(bEpNum, (EP_CTRS_RX | EP_CTRS_TX | (_GetENDPOINT(bEpNum) & EPKIND_MASK)))) + +/******************************************************************************* + * Macro Name : USB_SetStsOut / USB_ClrStsOut. + * Description : Sets/clears directly STATUS_OUT bit in the endpoint register. + * Input : bEpNum: Endpoint Number. + * Output : None. + * Return : None. + *******************************************************************************/ +#define _Set_Status_Out(bEpNum) _SetEP_KIND(bEpNum) +#define _Clear_Status_Out(bEpNum) _ClearEP_KIND(bEpNum) + +/******************************************************************************* + * Macro Name : USB_SetEpDoubleBufer / USB_ClrEpDoubleBufer. + * Description : Sets/clears directly EP_KIND bit in the endpoint register. + * Input : bEpNum: Endpoint Number. + * Output : None. + * Return : None. + *******************************************************************************/ +#define _SetEPDoubleBuff(bEpNum) _SetEP_KIND(bEpNum) +#define _ClearEPDoubleBuff(bEpNum) _ClearEP_KIND(bEpNum) + +/******************************************************************************* + * Macro Name : USB_ClrEpCtrsRx / USB_ClrEpCtrsTx. + * Description : Clears bit CTR_RX / CTR_TX in the endpoint register. + * Input : bEpNum: Endpoint Number. + * Output : None. + * Return : None. + *******************************************************************************/ +#define _ClearEP_CTR_RX(bEpNum) (_SetENDPOINT(bEpNum, _GetENDPOINT(bEpNum) & 0x7FFF & EPREG_MASK)) +#define _ClearEP_CTR_TX(bEpNum) (_SetENDPOINT(bEpNum, _GetENDPOINT(bEpNum) & 0xFF7F & EPREG_MASK)) + +/******************************************************************************* + * Macro Name : USB_DattogRx / USB_DattogTx . + * Description : Toggles DTOG_RX / DTOG_TX bit in the endpoint register. + * Input : bEpNum: Endpoint Number. + * Output : None. + * Return : None. + *******************************************************************************/ +#define _ToggleDTOG_RX(bEpNum) \ + (_SetENDPOINT(bEpNum, EP_CTRS_RX | EP_CTRS_TX | EP_DATTOG_RX | (_GetENDPOINT(bEpNum) & EPREG_MASK))) +#define _ToggleDTOG_TX(bEpNum) \ + (_SetENDPOINT(bEpNum, EP_CTRS_RX | EP_CTRS_TX | EP_DATTOG_TX | (_GetENDPOINT(bEpNum) & EPREG_MASK))) + +/******************************************************************************* + * Macro Name : USB_ClrDattogRx / USB_ClrDattogTx. + * Description : Clears DTOG_RX / DTOG_TX bit in the endpoint register. + * Input : bEpNum: Endpoint Number. + * Output : None. + * Return : None. + *******************************************************************************/ +#define _ClearDTOG_RX(bEpNum) \ + if ((_GetENDPOINT(bEpNum) & EP_DATTOG_RX) != 0) \ + _ToggleDTOG_RX(bEpNum) +#define _ClearDTOG_TX(bEpNum) \ + if ((_GetENDPOINT(bEpNum) & EP_DATTOG_TX) != 0) \ + _ToggleDTOG_TX(bEpNum) +/******************************************************************************* + * Macro Name : USB_SetEpAddress. + * Description : Sets address in an endpoint register. + * Input : bEpNum: Endpoint Number. + * bAddr: Address. + * Output : None. + * Return : None. + *******************************************************************************/ +#define _SetEPAddress(bEpNum, bAddr) \ + _SetENDPOINT(bEpNum, EP_CTRS_RX | EP_CTRS_TX | (_GetENDPOINT(bEpNum) & EPREG_MASK) | bAddr) + +/******************************************************************************* + * Macro Name : USB_GetEpAddress. + * Description : Gets address in an endpoint register. + * Input : bEpNum: Endpoint Number. + * Output : None. + * Return : None. + *******************************************************************************/ +#define _GetEPAddress(bEpNum) ((uint8_t)(_GetENDPOINT(bEpNum) & EPADDR_FIELD)) + +#define _pEPTxAddr(bEpNum) ((uint32_t*)((_GetBTABLE() + bEpNum * 8) * 2 + PMAAddr)) +#define _pEPTxCount(bEpNum) ((uint32_t*)((_GetBTABLE() + bEpNum * 8 + 2) * 2 + PMAAddr)) +#define _pEPRxAddr(bEpNum) ((uint32_t*)((_GetBTABLE() + bEpNum * 8 + 4) * 2 + PMAAddr)) +#define _pEPRxCount(bEpNum) ((uint32_t*)((_GetBTABLE() + bEpNum * 8 + 6) * 2 + PMAAddr)) + +/******************************************************************************* + * Macro Name : USB_SetEpTxAddr / USB_SetEpRxAddr. + * Description : sets address of the tx/rx buffer. + * Input : bEpNum: Endpoint Number. + * wAddr: address to be set (must be word aligned). + * Output : None. + * Return : None. + *******************************************************************************/ +#define _SetEPTxAddr(bEpNum, wAddr) (*_pEPTxAddr(bEpNum) = ((wAddr >> 1) << 1)) +#define _SetEPRxAddr(bEpNum, wAddr) (*_pEPRxAddr(bEpNum) = ((wAddr >> 1) << 1)) + +/******************************************************************************* + * Macro Name : USB_GetEpTxAddr / USB_GetEpRxAddr. + * Description : Gets address of the tx/rx buffer. + * Input : bEpNum: Endpoint Number. + * Output : None. + * Return : address of the buffer. + *******************************************************************************/ +#define _GetEPTxAddr(bEpNum) ((uint16_t)*_pEPTxAddr(bEpNum)) +#define _GetEPRxAddr(bEpNum) ((uint16_t)*_pEPRxAddr(bEpNum)) + +/******************************************************************************* + * Macro Name : USB_SetEpCntRxReg. + * Description : Sets counter of rx buffer with no. of blocks. + * Input : pdwReg: pointer to counter. + * wCount: Counter. + * Output : None. + * Return : None. + *******************************************************************************/ +#define _BlocksOf32(dwReg, wCount, wNBlocks) \ + { \ + wNBlocks = wCount >> 5; \ + if ((wCount & 0x1f) == 0) \ + wNBlocks--; \ + *pdwReg = (uint32_t)((wNBlocks << 10) | 0x8000); \ + } /* _BlocksOf32 */ + +#define _BlocksOf2(dwReg, wCount, wNBlocks) \ + { \ + wNBlocks = wCount >> 1; \ + if ((wCount & 0x1) != 0) \ + wNBlocks++; \ + *pdwReg = (uint32_t)(wNBlocks << 10); \ + } /* _BlocksOf2 */ + +#define _SetEPCountRxReg(dwReg, wCount) \ + { \ + uint16_t wNBlocks; \ + if (wCount > 62) \ + { \ + _BlocksOf32(dwReg, wCount, wNBlocks); \ + } \ + else \ + { \ + _BlocksOf2(dwReg, wCount, wNBlocks); \ + } \ + } /* _SetEPCountRxReg */ + +#define _SetEPRxDblBuf0Count(bEpNum, wCount) \ + { \ + uint32_t* pdwReg = _pEPTxCount(bEpNum); \ + _SetEPCountRxReg(pdwReg, wCount); \ + } +/******************************************************************************* + * Macro Name : USB_SetEpTxCnt / USB_SetEpRxCnt. + * Description : sets counter for the tx/rx buffer. + * Input : bEpNum: endpoint number. + * wCount: Counter value. + * Output : None. + * Return : None. + *******************************************************************************/ +#define _SetEPTxCount(bEpNum, wCount) (*_pEPTxCount(bEpNum) = wCount) +#define _SetEPRxCount(bEpNum, wCount) \ + { \ + uint32_t* pdwReg = _pEPRxCount(bEpNum); \ + _SetEPCountRxReg(pdwReg, wCount); \ + } +/******************************************************************************* + * Macro Name : USB_GetEpTxCnt / USB_GetEpRxCnt. + * Description : gets counter of the tx buffer. + * Input : bEpNum: endpoint number. + * Output : None. + * Return : Counter value. + *******************************************************************************/ +#define _GetEPTxCount(bEpNum) ((uint16_t)(*_pEPTxCount(bEpNum)) & 0x3ff) +#define _GetEPRxCount(bEpNum) ((uint16_t)(*_pEPRxCount(bEpNum)) & 0x3ff) + +/******************************************************************************* + * Macro Name : USB_SetEpDblBuf0Addr / USB_SetEpDblBuf1Addr. + * Description : Sets buffer 0/1 address in a double buffer endpoint. + * Input : bEpNum: endpoint number. + * : wBuf0Addr: buffer 0 address. + * Output : None. + * Return : None. + *******************************************************************************/ +#define _SetEPDblBuf0Addr(bEpNum, wBuf0Addr) \ + { \ + _SetEPTxAddr(bEpNum, wBuf0Addr); \ + } +#define _SetEPDblBuf1Addr(bEpNum, wBuf1Addr) \ + { \ + _SetEPRxAddr(bEpNum, wBuf1Addr); \ + } + +/******************************************************************************* + * Macro Name : USB_SetEpDblBuferAddr. + * Description : Sets addresses in a double buffer endpoint. + * Input : bEpNum: endpoint number. + * : wBuf0Addr: buffer 0 address. + * : wBuf1Addr = buffer 1 address. + * Output : None. + * Return : None. + *******************************************************************************/ +#define _SetEPDblBuffAddr(bEpNum, wBuf0Addr, wBuf1Addr) \ + { \ + _SetEPDblBuf0Addr(bEpNum, wBuf0Addr); \ + _SetEPDblBuf1Addr(bEpNum, wBuf1Addr); \ + } /* _SetEPDblBuffAddr */ + +/******************************************************************************* + * Macro Name : USB_GetEpDblBuf0Addr / USB_GetEpDblBuf1Addr. + * Description : Gets buffer 0/1 address of a double buffer endpoint. + * Input : bEpNum: endpoint number. + * Output : None. + * Return : None. + *******************************************************************************/ +#define _GetEPDblBuf0Addr(bEpNum) (_GetEPTxAddr(bEpNum)) +#define _GetEPDblBuf1Addr(bEpNum) (_GetEPRxAddr(bEpNum)) + +/******************************************************************************* + * Macro Name : USB_SetEpDblBuferCnt / USB_SetEpDblBuf0Cnt / USB_SetEpDblBuf1Cnt. + * Description : Gets buffer 0/1 address of a double buffer endpoint. + * Input : bEpNum: endpoint number. + * : bDir: endpoint dir EP_DBUF_OUT = OUT + * EP_DBUF_IN = IN + * : wCount: Counter value + * Output : None. + * Return : None. + *******************************************************************************/ +#define _SetEPDblBuf0Count(bEpNum, bDir, wCount) \ + { \ + if (bDir == EP_DBUF_OUT) \ + /* OUT endpoint */ \ + { \ + _SetEPRxDblBuf0Count(bEpNum, wCount); \ + } \ + else if (bDir == EP_DBUF_IN) \ + /* IN endpoint */ \ + *_pEPTxCount(bEpNum) = (uint32_t)wCount; \ + } /* USB_SetEpDblBuf0Cnt*/ + +#define _SetEPDblBuf1Count(bEpNum, bDir, wCount) \ + { \ + if (bDir == EP_DBUF_OUT) \ + /* OUT endpoint */ \ + { \ + _SetEPRxCount(bEpNum, wCount); \ + } \ + else if (bDir == EP_DBUF_IN) \ + /* IN endpoint */ \ + *_pEPRxCount(bEpNum) = (uint32_t)wCount; \ + } /* USB_SetEpDblBuf1Cnt */ + +#define _SetEPDblBuffCount(bEpNum, bDir, wCount) \ + { \ + _SetEPDblBuf0Count(bEpNum, bDir, wCount); \ + _SetEPDblBuf1Count(bEpNum, bDir, wCount); \ + } /* _SetEPDblBuffCount */ + +/******************************************************************************* + * Macro Name : USB_GetEpDblBuf0Cnt / USB_GetEpDblBuf1Cnt. + * Description : Gets buffer 0/1 rx/tx counter for double buffering. + * Input : bEpNum: endpoint number. + * Output : None. + * Return : None. + *******************************************************************************/ +#define _GetEPDblBuf0Count(bEpNum) (_GetEPTxCount(bEpNum)) +#define _GetEPDblBuf1Count(bEpNum) (_GetEPRxCount(bEpNum)) + +extern __IO uint16_t wIstr; /* USB_STS register last read value */ + +void USB_SetCtrl(uint16_t /*wRegValue*/); +void USB_SetSts(uint16_t /*wRegValue*/); +void USB_SetAddr(uint16_t /*wRegValue*/); +void USB_SetBuftab(uint16_t /*wRegValue*/); +void USB_SetBuftab(uint16_t /*wRegValue*/); +uint16_t USB_GetCtrl(void); +uint16_t USB_GetSts(void); +uint16_t USB_GetFn(void); +uint16_t USB_GetAddr(void); +uint16_t USB_GetBTABLE(void); +void USB_SetEndPoint(uint8_t /*bEpNum*/, uint16_t /*wRegValue*/); +uint16_t USB_GetEndPoint(uint8_t /*bEpNum*/); +void USB_SetEpType(uint8_t /*bEpNum*/, uint16_t /*wType*/); +uint16_t USB_GetEpType(uint8_t /*bEpNum*/); +void SetEPTxStatus(uint8_t /*bEpNum*/, uint16_t /*wState*/); +void SetEPRxStatus(uint8_t /*bEpNum*/, uint16_t /*wState*/); +void USB_SetDouBleBuferEpStall(uint8_t /*bEpNum*/, uint8_t bDir); +uint16_t USB_GetEpTxSts(uint8_t /*bEpNum*/); +uint16_t USB_GetEpRxSts(uint8_t /*bEpNum*/); +void USB_SetEpTxValid(uint8_t /*bEpNum*/); +void USB_SetEpRxValid(uint8_t /*bEpNum*/); +uint16_t USB_GetTxStallSts(uint8_t /*bEpNum*/); +uint16_t USB_GetRxStallSts(uint8_t /*bEpNum*/); +void USB_SetEpKind(uint8_t /*bEpNum*/); +void USB_ClrEpKind(uint8_t /*bEpNum*/); +void USB_SetStsOut(uint8_t /*bEpNum*/); +void USB_ClrStsOut(uint8_t /*bEpNum*/); +void USB_SetEpDoubleBufer(uint8_t /*bEpNum*/); +void USB_ClrEpDoubleBufer(uint8_t /*bEpNum*/); +void USB_ClrEpCtrsRx(uint8_t /*bEpNum*/); +void USB_ClrEpCtrsTx(uint8_t /*bEpNum*/); +void USB_DattogRx(uint8_t /*bEpNum*/); +void USB_DattogTx(uint8_t /*bEpNum*/); +void USB_ClrDattogRx(uint8_t /*bEpNum*/); +void USB_ClrDattogTx(uint8_t /*bEpNum*/); +void USB_SetEpAddress(uint8_t /*bEpNum*/, uint8_t /*bAddr*/); +uint8_t USB_GetEpAddress(uint8_t /*bEpNum*/); +void USB_SetEpTxAddr(uint8_t /*bEpNum*/, uint16_t /*wAddr*/); +void USB_SetEpRxAddr(uint8_t /*bEpNum*/, uint16_t /*wAddr*/); +uint16_t USB_GetEpTxAddr(uint8_t /*bEpNum*/); +uint16_t USB_GetEpRxAddr(uint8_t /*bEpNum*/); +void USB_SetEpCntRxReg(uint32_t* /*pdwReg*/, uint16_t /*wCount*/); +void USB_SetEpTxCnt(uint8_t /*bEpNum*/, uint16_t /*wCount*/); +void USB_SetEpRxCnt(uint8_t /*bEpNum*/, uint16_t /*wCount*/); +uint16_t USB_GetEpTxCnt(uint8_t /*bEpNum*/); +uint16_t USB_GetEpRxCnt(uint8_t /*bEpNum*/); +void USB_SetEpDblBuf0Addr(uint8_t /*bEpNum*/, uint16_t /*wBuf0Addr*/); +void USB_SetEpDblBuf1Addr(uint8_t /*bEpNum*/, uint16_t /*wBuf1Addr*/); +void USB_SetEpDblBuferAddr(uint8_t /*bEpNum*/, uint16_t /*wBuf0Addr*/, uint16_t /*wBuf1Addr*/); +uint16_t USB_GetEpDblBuf0Addr(uint8_t /*bEpNum*/); +uint16_t USB_GetEpDblBuf1Addr(uint8_t /*bEpNum*/); +void USB_SetEpDblBuferCnt(uint8_t /*bEpNum*/, uint8_t /*bDir*/, uint16_t /*wCount*/); +void USB_SetEpDblBuf0Cnt(uint8_t /*bEpNum*/, uint8_t /*bDir*/, uint16_t /*wCount*/); +void USB_SetEpDblBuf1Cnt(uint8_t /*bEpNum*/, uint8_t /*bDir*/, uint16_t /*wCount*/); +uint16_t USB_GetEpDblBuf0Cnt(uint8_t /*bEpNum*/); +uint16_t USB_GetEpDblBuf1Cnt(uint8_t /*bEpNum*/); +EP_DBUF_DIR GetEPDblBufDir(uint8_t /*bEpNum*/); +void USB_FreeUserBuf(uint8_t bEpNum /*bEpNum*/, uint8_t bDir); +uint16_t USB_ToWord(uint8_t, uint8_t); +uint16_t USB_ByteSwap(uint16_t); + +/** + * @} + */ + +#endif /* __USB_REGS_H__ */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_sil.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_sil.h new file mode 100644 index 0000000000..7f8c98e039 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_sil.h @@ -0,0 +1,53 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file usb_sil.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __USB_SIL_H__ +#define __USB_SIL_H__ + +#include "n32g4fr.h" + +/** + * @addtogroup N32G4FR_USB_Driver + * @{ + */ + +uint32_t USB_SilInit(void); +uint32_t USB_SilWrite(uint8_t bEpAddr, uint8_t* pBufferPointer, uint32_t wBufferSize); +uint32_t USB_SilRead(uint8_t bEpAddr, uint8_t* pBufferPointer); + +/** + * @} + */ + +#endif /* __USB_SIL_H__ */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_type.h b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_type.h new file mode 100644 index 0000000000..764a8d4775 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/inc/usb_type.h @@ -0,0 +1,54 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file usb_type.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __USB_TYPE_H__ +#define __USB_TYPE_H__ + +#include "usb_conf.h" +#include + +/** + * @addtogroup N32G4FR_USB_Driver + * @{ + */ + +#ifndef NULL +#define NULL ((void*)0) +#endif + +/** + * @} + */ + +#endif /* __USB_TYPE_H__ */ diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_core.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_core.c new file mode 100644 index 0000000000..ee7f4e74ca --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_core.c @@ -0,0 +1,950 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file usb_core.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "usb_lib.h" + +#define ValBit(VAR, Place) (VAR & (1 << Place)) +#define SetBit(VAR, Place) (VAR |= (1 << Place)) +#define ClrBit(VAR, Place) (VAR &= ((1 << Place) ^ 255)) + +#define Send0LengthData() \ + { \ + _SetEPTxCount(ENDP0, 0); \ + vSetEPTxStatus(EP_TX_VALID); \ + } + +#define vSetEPRxStatus(st) (SaveRState = st) +#define vSetEPTxStatus(st) (SaveTState = st) + +#define USB_StatusIn() Send0LengthData() +#define USB_StatusOut() vSetEPRxStatus(EP_RX_VALID) + +#define StatusInfo0 StatusInfo.bw.bb1 /* Reverse bb0 & bb1 */ +#define StatusInfo1 StatusInfo.bw.bb0 + +uint16_t_uint8_t StatusInfo; + +bool Data_Mul_MaxPacketSize = false; + +static void DataStageOut(void); +static void DataStageIn(void); +static void NoData_Setup0(void); +static void Data_Setup0(void); + +/** + * @brief Return the current configuration variable address. + * Input : Length - How many bytes are needed. + * @return Return 1 , if the request is invalid when "Length" is 0. + * Return "Buffer" if the "Length" is not 0. + */ +uint8_t* Standard_GetConfiguration(uint16_t Length) +{ + if (Length == 0) + { + pInformation->Ctrl_Info.Usb_wLength = sizeof(pInformation->CurrentConfiguration); + return 0; + } + pUser_Standard_Requests->User_GetConfiguration(); + return (uint8_t*)&pInformation->CurrentConfiguration; +} + +/** + * @brief This routine is called to set the configuration value + * Then each class should configure device itself. + * @return + * - Success, if the request is performed. + * - UnSupport, if the request is invalid. + */ +USB_Result Standard_SetConfiguration(void) +{ + if ((pInformation->USBwValue0 <= Device_Table.TotalConfiguration) && (pInformation->USBwValue1 == 0) + && (pInformation->USBwIndex == 0)) /*call Back usb spec 2.0*/ + { + pInformation->CurrentConfiguration = pInformation->USBwValue0; + pUser_Standard_Requests->User_SetConfiguration(); + return Success; + } + else + { + return UnSupport; + } +} + +/** + * @brief Return the Alternate Setting of the current interface. + * Input : Length - How many bytes are needed. + * @return + * - NULL, if the request is invalid when "Length" is 0. + * - "Buffer" if the "Length" is not 0. + */ +uint8_t* Standard_GetInterface(uint16_t Length) +{ + if (Length == 0) + { + pInformation->Ctrl_Info.Usb_wLength = sizeof(pInformation->CurrentAlternateSetting); + return 0; + } + pUser_Standard_Requests->User_GetInterface(); + return (uint8_t*)&pInformation->CurrentAlternateSetting; +} + +/** + * @brief This routine is called to set the interface. + * Then each class should configure the interface them self. + * @return + * - Success, if the request is performed. + * - UnSupport, if the request is invalid. + */ +USB_Result Standard_SetInterface(void) +{ + USB_Result Re; + /*Test if the specified Interface and Alternate Setting are supported by + the application Firmware*/ + Re = (*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, pInformation->USBwValue0); + + if (pInformation->CurrentConfiguration != 0) + { + if ((Re != Success) || (pInformation->USBwIndex1 != 0) || (pInformation->USBwValue1 != 0)) + { + return UnSupport; + } + else if (Re == Success) + { + pUser_Standard_Requests->User_SetInterface(); + pInformation->CurrentInterface = pInformation->USBwIndex0; + pInformation->CurrentAlternateSetting = pInformation->USBwValue0; + return Success; + } + } + + return UnSupport; +} + +/** + * @brief Copy the device request data to "StatusInfo buffer". + * Input : - Length - How many bytes are needed. + * @return Return 0, if the request is at end of data block, + * or is invalid when "Length" is 0. + */ +uint8_t* Standard_GetStatus(uint16_t Length) +{ + if (Length == 0) + { + pInformation->Ctrl_Info.Usb_wLength = 2; + return 0; + } + + /* Reset Status Information */ + StatusInfo.w = 0; + + if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { + /*Get Device Status */ + uint8_t Feature = pInformation->CurrentFeature; + + /* Remote Wakeup enabled */ + if (ValBit(Feature, 5)) + { + SetBit(StatusInfo0, 1); + } + else + { + ClrBit(StatusInfo0, 1); + } + + /* Bus-powered */ + if (ValBit(Feature, 6)) + { + SetBit(StatusInfo0, 0); + } + else /* Self-powered */ + { + ClrBit(StatusInfo0, 0); + } + } + /*Interface Status*/ + else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) + { + return (uint8_t*)&StatusInfo; + } + /*Get EndPoint Status*/ + else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) + { + uint8_t Related_Endpoint; + uint8_t wIndex0 = pInformation->USBwIndex0; + + Related_Endpoint = (wIndex0 & 0x0f); + if (ValBit(wIndex0, 7)) + { + /* IN endpoint */ + if (_GetTxStallStatus(Related_Endpoint)) + { + SetBit(StatusInfo0, 0); /* IN Endpoint stalled */ + } + } + else + { + /* OUT endpoint */ + if (_GetRxStallStatus(Related_Endpoint)) + { + SetBit(StatusInfo0, 0); /* OUT Endpoint stalled */ + } + } + } + else + { + return NULL; + } + pUser_Standard_Requests->User_GetStatus(); + return (uint8_t*)&StatusInfo; +} + +/** + * @brief Clear or disable a specific feature. + * @return - Return Success, if the request is performed. + * - Return UnSupport, if the request is invalid. + */ +USB_Result Standard_ClearFeature(void) +{ + uint32_t Type_Rec = Type_Recipient; + uint32_t Status; + + if (Type_Rec == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { /*Device Clear Feature*/ + ClrBit(pInformation->CurrentFeature, 5); + return Success; + } + else if (Type_Rec == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) + { /*EndPoint Clear Feature*/ + USB_Device* pDev; + uint32_t Related_Endpoint; + uint32_t wIndex0; + uint32_t rEP; + + if ((pInformation->USBwValue != ENDPOINT_STALL) || (pInformation->USBwIndex1 != 0)) + { + return UnSupport; + } + + pDev = &Device_Table; + wIndex0 = pInformation->USBwIndex0; + rEP = wIndex0 & ~0x80; + Related_Endpoint = ENDP0 + rEP; + + if (ValBit(pInformation->USBwIndex0, 7)) + { + /*Get Status of endpoint & stall the request if the related_ENdpoint + is Disabled*/ + Status = _GetEPTxStatus(Related_Endpoint); + } + else + { + Status = _GetEPRxStatus(Related_Endpoint); + } + + if ((rEP >= pDev->TotalEndpoint) || (Status == 0) || (pInformation->CurrentConfiguration == 0)) + { + return UnSupport; + } + + if (wIndex0 & 0x80) + { + /* IN endpoint */ + if (_GetTxStallStatus(Related_Endpoint)) + { + USB_ClrDattogTx(Related_Endpoint); + SetEPTxStatus(Related_Endpoint, EP_TX_VALID); + } + } + else + { + /* OUT endpoint */ + if (_GetRxStallStatus(Related_Endpoint)) + { + if (Related_Endpoint == ENDP0) + { + /* After clear the STALL, enable the default endpoint receiver */ + USB_SetEpRxCnt(Related_Endpoint, Device_Property.MaxPacketSize); + _SetEPRxStatus(Related_Endpoint, EP_RX_VALID); + } + else + { + USB_ClrDattogRx(Related_Endpoint); + _SetEPRxStatus(Related_Endpoint, EP_RX_VALID); + } + } + } + pUser_Standard_Requests->User_ClearFeature(); + return Success; + } + + return UnSupport; +} + +/** + * @brief Set or enable a specific feature of EndPoint + * @return - Return Success, if the request is performed. + * - Return UnSupport, if the request is invalid. + */ +USB_Result Standard_SetEndPointFeature(void) +{ + uint32_t wIndex0; + uint32_t Related_Endpoint; + uint32_t rEP; + uint32_t Status; + + wIndex0 = pInformation->USBwIndex0; + rEP = wIndex0 & ~0x80; + Related_Endpoint = ENDP0 + rEP; + + if (ValBit(pInformation->USBwIndex0, 7)) + { + /* get Status of endpoint & stall the request if the related_ENdpoint + is Disabled*/ + Status = _GetEPTxStatus(Related_Endpoint); + } + else + { + Status = _GetEPRxStatus(Related_Endpoint); + } + + if (Related_Endpoint >= Device_Table.TotalEndpoint || pInformation->USBwValue != 0 || Status == 0 + || pInformation->CurrentConfiguration == 0) + { + return UnSupport; + } + else + { + if (wIndex0 & 0x80) + { + /* IN endpoint */ + _SetEPTxStatus(Related_Endpoint, EP_TX_STALL); + } + + else + { + /* OUT endpoint */ + _SetEPRxStatus(Related_Endpoint, EP_RX_STALL); + } + } + pUser_Standard_Requests->User_SetEndPointFeature(); + return Success; +} + +/** + * @brief Set or enable a specific feature of Device. + * @return - Return Success, if the request is performed. + * - Return UnSupport, if the request is invalid. + */ +USB_Result Standard_SetDeviceFeature(void) +{ + SetBit(pInformation->CurrentFeature, 5); + pUser_Standard_Requests->User_SetDeviceFeature(); + return Success; +} + +/** + * @brief Standard_GetDescriptorData is used for descriptors transfer. + * : This routine is used for the descriptors resident in Flash + * or RAM + * pDesc can be in either Flash or RAM + * The purpose of this routine is to have a versatile way to + * response descriptors request. It allows user to generate + * certain descriptors with software or read descriptors from + * external storage part by part. + * Input : - Length - Length of the data in this transfer. + * - pDesc - A pointer points to descriptor struct. + * The structure gives the initial address of the descriptor and + * its original size. + * @return Address of a part of the descriptor pointed by the Usb_ + * wOffset The buffer pointed by this address contains at least + * Length bytes. + */ +uint8_t* Standard_GetDescriptorData(uint16_t Length, USB_OneDescriptor* pDesc) +{ + uint32_t wOffset; + + wOffset = pInformation->Ctrl_Info.Usb_wOffset; + if (Length == 0) + { + pInformation->Ctrl_Info.Usb_wLength = pDesc->Descriptor_Size - wOffset; + return 0; + } + + return pDesc->Descriptor + wOffset; +} + +/** + * @brief Data stage of a Control Write Transfer. + */ +void DataStageOut(void) +{ + USB_EndpointMess* pEPinfo = &pInformation->Ctrl_Info; + uint32_t save_rLength; + + save_rLength = pEPinfo->Usb_rLength; + + if (pEPinfo->CopyData && save_rLength) + { + uint8_t* Buffer; + uint32_t Length; + + Length = pEPinfo->PacketSize; + if (Length > save_rLength) + { + Length = save_rLength; + } + + Buffer = (*pEPinfo->CopyData)(Length); + pEPinfo->Usb_rLength -= Length; + pEPinfo->Usb_rOffset += Length; + + USB_CopyPMAToUserBuf(Buffer, USB_GetEpRxAddr(ENDP0), Length); + } + + if (pEPinfo->Usb_rLength != 0) + { + vSetEPRxStatus(EP_RX_VALID); /* re-enable for next data reception */ + USB_SetEpTxCnt(ENDP0, 0); + vSetEPTxStatus(EP_TX_VALID); /* Expect the host to abort the data OUT stage */ + } + /* Set the next State*/ + if (pEPinfo->Usb_rLength >= pEPinfo->PacketSize) + { + pInformation->CtrlState = OutData; + } + else + { + if (pEPinfo->Usb_rLength > 0) + { + pInformation->CtrlState = LastOutData; + } + else if (pEPinfo->Usb_rLength == 0) + { + pInformation->CtrlState = WaitStatusIn; + USB_StatusIn(); + } + } +} + +/** + * @brief Data stage of a Control Read Transfer. + */ +void DataStageIn(void) +{ + USB_EndpointMess* pEPinfo = &pInformation->Ctrl_Info; + uint32_t save_wLength = pEPinfo->Usb_wLength; + uint32_t CtrlState = pInformation->CtrlState; + + uint8_t* DataBuffer; + uint32_t Length; + + if ((save_wLength == 0) && (CtrlState == LastInData)) + { + if (Data_Mul_MaxPacketSize == true) + { + /* No more data to send and empty packet */ + Send0LengthData(); + CtrlState = LastInData; + Data_Mul_MaxPacketSize = false; + } + else + { + /* No more data to send so STALL the TX Status*/ + CtrlState = WaitStatusOut; + vSetEPTxStatus(EP_TX_STALL); + } + + goto Expect_Status_Out; + } + + Length = pEPinfo->PacketSize; + CtrlState = (save_wLength <= Length) ? LastInData : InData; + + if (Length > save_wLength) + { + Length = save_wLength; + } + + DataBuffer = (*pEPinfo->CopyData)(Length); + + USB_CopyUserToPMABuf(DataBuffer, USB_GetEpTxAddr(ENDP0), Length); + + USB_SetEpTxCnt(ENDP0, Length); + + pEPinfo->Usb_wLength -= Length; + pEPinfo->Usb_wOffset += Length; + vSetEPTxStatus(EP_TX_VALID); + + USB_StatusOut(); /* Expect the host to abort the data IN stage */ + +Expect_Status_Out: + pInformation->CtrlState = CtrlState; +} + +/** + * @brief Proceed the processing of setup request without data stage. + */ +void NoData_Setup0(void) +{ + USB_Result Result = UnSupport; + uint32_t RequestNo = pInformation->bRequest; + uint32_t CtrlState; + + if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { + /* Device Request*/ + /* SET_CONFIGURATION*/ + if (RequestNo == SET_CONFIGURATION) + { + Result = Standard_SetConfiguration(); + } + + /*SET ADDRESS*/ + else if (RequestNo == SET_ADDRESS) + { + if ((pInformation->USBwValue0 > 127) || (pInformation->USBwValue1 != 0) || (pInformation->USBwIndex != 0) + || (pInformation->CurrentConfiguration != 0)) + /* Device Address should be 127 or less*/ + { + CtrlState = Stalled; + goto exit_NoData_Setup0; + } + else + { + Result = Success; + } + } + /*SET FEATURE for Device*/ + else if (RequestNo == SET_FEATURE) + { + if ((pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP) && (pInformation->USBwIndex == 0)) + { + Result = Standard_SetDeviceFeature(); + } + else + { + Result = UnSupport; + } + } + /*Clear FEATURE for Device */ + else if (RequestNo == CLR_FEATURE) + { + if (pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP && pInformation->USBwIndex == 0 + && ValBit(pInformation->CurrentFeature, 5)) + { + Result = Standard_ClearFeature(); + } + else + { + Result = UnSupport; + } + } + } + + /* Interface Request*/ + else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) + { + /*SET INTERFACE*/ + if (RequestNo == SET_INTERFACE) + { + Result = Standard_SetInterface(); + } + } + + /* EndPoint Request*/ + else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) + { + /*CLEAR FEATURE for EndPoint*/ + if (RequestNo == CLR_FEATURE) + { + Result = Standard_ClearFeature(); + } + /* SET FEATURE for EndPoint*/ + else if (RequestNo == SET_FEATURE) + { + Result = Standard_SetEndPointFeature(); + } + } + else + { + Result = UnSupport; + } + + if (Result != Success) + { + Result = (*pProperty->Class_NoData_Setup)(RequestNo); + if (Result == Not_Ready) + { + CtrlState = Pause; + goto exit_NoData_Setup0; + } + } + + if (Result != Success) + { + CtrlState = Stalled; + goto exit_NoData_Setup0; + } + + CtrlState = WaitStatusIn; /* After no data stage SETUP */ + + USB_StatusIn(); + +exit_NoData_Setup0: + pInformation->CtrlState = CtrlState; + return; +} + +/** + * @brief Proceed the processing of setup request with data stage. + */ +void Data_Setup0(void) +{ + uint8_t* (*CopyRoutine)(uint16_t); + USB_Result Result; + uint32_t Request_No = pInformation->bRequest; + + uint32_t Related_Endpoint, Reserved; + uint32_t wOffset, Status; + + CopyRoutine = NULL; + wOffset = 0; + + /*GET DESCRIPTOR*/ + if (Request_No == GET_DESCRIPTOR) + { + if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { + uint8_t wValue1 = pInformation->USBwValue1; + if (wValue1 == DEVICE_DESCRIPTOR) + { + CopyRoutine = pProperty->GetDeviceDescriptor; + } + else if (wValue1 == CONFIG_DESCRIPTOR) + { + CopyRoutine = pProperty->GetConfigDescriptor; + } + else if (wValue1 == STRING_DESCRIPTOR) + { + CopyRoutine = pProperty->GetStringDescriptor; + } /* End of GET_DESCRIPTOR */ + } + } + + /*GET STATUS*/ + else if ((Request_No == GET_STATUS) && (pInformation->USBwValue == 0) && (pInformation->USBwLength == 0x0002) + && (pInformation->USBwIndex1 == 0)) + { + /* GET STATUS for Device*/ + if ((Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) && (pInformation->USBwIndex == 0)) + { + CopyRoutine = Standard_GetStatus; + } + + /* GET STATUS for Interface*/ + else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) + { + if (((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == Success) + && (pInformation->CurrentConfiguration != 0)) + { + CopyRoutine = Standard_GetStatus; + } + } + + /* GET STATUS for EndPoint*/ + else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) + { + Related_Endpoint = (pInformation->USBwIndex0 & 0x0f); + Reserved = pInformation->USBwIndex0 & 0x70; + + if (ValBit(pInformation->USBwIndex0, 7)) + { + /*Get Status of endpoint & stall the request if the related_ENdpoint + is Disabled*/ + Status = _GetEPTxStatus(Related_Endpoint); + } + else + { + Status = _GetEPRxStatus(Related_Endpoint); + } + + if ((Related_Endpoint < Device_Table.TotalEndpoint) && (Reserved == 0) && (Status != 0)) + { + CopyRoutine = Standard_GetStatus; + } + } + } + + /*GET CONFIGURATION*/ + else if (Request_No == GET_CONFIGURATION) + { + if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { + CopyRoutine = Standard_GetConfiguration; + } + } + /*GET INTERFACE*/ + else if (Request_No == GET_INTERFACE) + { + if ((Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) && (pInformation->CurrentConfiguration != 0) + && (pInformation->USBwValue == 0) && (pInformation->USBwIndex1 == 0) && (pInformation->USBwLength == 0x0001) + && ((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == Success)) + { + CopyRoutine = Standard_GetInterface; + } + } + + if (CopyRoutine) + { + pInformation->Ctrl_Info.Usb_wOffset = wOffset; + pInformation->Ctrl_Info.CopyData = CopyRoutine; + /* sb in the original the cast to word was directly */ + /* now the cast is made step by step */ + (*CopyRoutine)(0); + Result = Success; + } + else + { + Result = (*pProperty->Class_Data_Setup)(pInformation->bRequest); + if (Result == Not_Ready) + { + pInformation->CtrlState = Pause; + return; + } + } + + if (pInformation->Ctrl_Info.Usb_wLength == 0xFFFF) + { + /* Data is not ready, wait it */ + pInformation->CtrlState = Pause; + return; + } + if ((Result == UnSupport) || (pInformation->Ctrl_Info.Usb_wLength == 0)) + { + /* Unsupported request */ + pInformation->CtrlState = Stalled; + return; + } + + if (ValBit(pInformation->bmRequestType, 7)) + { + /* Device ==> Host */ + __IO uint32_t wLength = pInformation->USBwLength; + + /* Restrict the data length to be the one host asks for */ + if (pInformation->Ctrl_Info.Usb_wLength > wLength) + { + pInformation->Ctrl_Info.Usb_wLength = wLength; + } + + else if (pInformation->Ctrl_Info.Usb_wLength < pInformation->USBwLength) + { + if (pInformation->Ctrl_Info.Usb_wLength < pProperty->MaxPacketSize) + { + Data_Mul_MaxPacketSize = false; + } + else if ((pInformation->Ctrl_Info.Usb_wLength % pProperty->MaxPacketSize) == 0) + { + Data_Mul_MaxPacketSize = true; + } + } + + pInformation->Ctrl_Info.PacketSize = pProperty->MaxPacketSize; + DataStageIn(); + } + else + { + pInformation->CtrlState = OutData; + vSetEPRxStatus(EP_RX_VALID); /* enable for next data reception */ + } + + return; +} + +/** + * @brief Get the device request data and dispatch to individual process. + * @return USB_ProcessPost0. + */ +uint8_t USB_ProcessSetup0(void) +{ + union + { + uint8_t* b; + uint16_t* w; + } pBuf; + + uint16_t offset = 1; + + pBuf.b = PMAAddr + (uint8_t*)(_GetEPRxAddr(ENDP0) * 2); /* *2 for 32 bits addr */ + + if (pInformation->CtrlState != Pause) + { + pInformation->bmRequestType = *pBuf.b++; /* bmRequestType */ + pInformation->bRequest = *pBuf.b++; /* bRequest */ + pBuf.w += offset; /* word not accessed because of 32 bits addressing */ + pInformation->USBwValue = USB_ByteSwap(*pBuf.w++); /* wValue */ + pBuf.w += offset; /* word not accessed because of 32 bits addressing */ + pInformation->USBwIndex = USB_ByteSwap(*pBuf.w++); /* wIndex */ + pBuf.w += offset; /* word not accessed because of 32 bits addressing */ + pInformation->USBwLength = *pBuf.w; /* wLength */ + } + + pInformation->CtrlState = SettingUp; + if (pInformation->USBwLength == 0) + { + /* Setup with no data stage */ + NoData_Setup0(); + } + else + { + /* Setup with data stage */ + Data_Setup0(); + } + return USB_ProcessPost0(); +} + +/** + * @brief Process the IN token on all default endpoint. + * @return USB_ProcessPost0. + */ +uint8_t USB_ProcessIn0(void) +{ + uint32_t CtrlState = pInformation->CtrlState; + + if ((CtrlState == InData) || (CtrlState == LastInData)) + { + DataStageIn(); + /* CtrlState may be changed outside the function */ + CtrlState = pInformation->CtrlState; + } + + else if (CtrlState == WaitStatusIn) + { + if ((pInformation->bRequest == SET_ADDRESS) && (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))) + { + USB_SetDeviceAddress(pInformation->USBwValue0); + pUser_Standard_Requests->User_SetDeviceAddress(); + } + (*pProperty->Process_Status_IN)(); + CtrlState = Stalled; + } + + else + { + CtrlState = Stalled; + } + + pInformation->CtrlState = CtrlState; + + return USB_ProcessPost0(); +} + +/** + * @brief Process the OUT token on all default endpoint. + * @return USB_ProcessPost0. + */ +uint8_t USB_ProcessOut0(void) +{ + uint32_t CtrlState = pInformation->CtrlState; + + if ((CtrlState == InData) || (CtrlState == LastInData)) + { + /* host aborts the transfer before finish */ + CtrlState = Stalled; + } + else if ((CtrlState == OutData) || (CtrlState == LastOutData)) + { + DataStageOut(); + CtrlState = pInformation->CtrlState; /* may be changed outside the function */ + } + + else if (CtrlState == WaitStatusOut) + { + (*pProperty->Process_Status_OUT)(); + CtrlState = Stalled; + } + + /* Unexpect state, STALL the endpoint */ + else + { + CtrlState = Stalled; + } + + pInformation->CtrlState = CtrlState; + + return USB_ProcessPost0(); +} + +/** + * @brief Stall the Endpoint 0 in case of error. + * @return + * - 0 if the control State is in Pause + * - 1 if not. + */ +uint8_t USB_ProcessPost0(void) +{ + USB_SetEpRxCnt(ENDP0, Device_Property.MaxPacketSize); + + if (pInformation->CtrlState == Stalled) + { + vSetEPRxStatus(EP_RX_STALL); + vSetEPTxStatus(EP_TX_STALL); + } + return (pInformation->CtrlState == Pause); +} + +/** + * @brief Set the device and all the used Endpoints addresses. + * @param Val device address. + */ +void USB_SetDeviceAddress(uint8_t Val) +{ + uint32_t i; + uint32_t nEP = Device_Table.TotalEndpoint; + + /* set address in every used endpoint */ + for (i = 0; i < nEP; i++) + { + _SetEPAddress((uint8_t)i, (uint8_t)i); + } /* for */ + _SetDADDR(Val | ADDR_EFUC); /* set device address and enable function */ +} + +/** + * @brief No operation function. + */ +void USB_ProcessNop(void) +{ +} diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_init.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_init.c new file mode 100644 index 0000000000..016aec225c --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_init.c @@ -0,0 +1,69 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file usb_init.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "usb_lib.h" + +/* The number of current endpoint, it will be used to specify an endpoint */ +uint8_t EPindex; +/* The number of current device, it is an index to the Device_Table */ +/* uint8_t Device_no; */ +/* Points to the USB_DeviceMess structure of current device */ +/* The purpose of this register is to speed up the execution */ +USB_DeviceMess* pInformation; +/* Points to the DEVICE_PROP structure of current device */ +/* The purpose of this register is to speed up the execution */ +DEVICE_PROP* pProperty; +/* Temporary save the state of Rx & Tx status. */ +/* Whenever the Rx or Tx state is changed, its value is saved */ +/* in this variable first and will be set to the EPRB or EPRA */ +/* at the end of interrupt process */ +uint16_t SaveState; +uint16_t wInterrupt_Mask; +USB_DeviceMess Device_Info; +USER_STANDARD_REQUESTS* pUser_Standard_Requests; + +/** + * @brief USB system initialization + */ +void USB_Init(void) +{ + pInformation = &Device_Info; + pInformation->CtrlState = 2; + pProperty = &Device_Property; + pUser_Standard_Requests = &User_Standard_Requests; + /* Initialize devices one by one */ + pProperty->Init(); + /*Pull up DP*/ + _EnPortPullup(); +} diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_int.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_int.c new file mode 100644 index 0000000000..66f8d4fe2a --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_int.c @@ -0,0 +1,179 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file usb_int.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "usb_lib.h" + +__IO uint16_t SaveRState; +__IO uint16_t SaveTState; + +extern void (*pEpInt_IN[7])(void); /* Handles IN interrupts */ +extern void (*pEpInt_OUT[7])(void); /* Handles OUT interrupts */ + +/** + * @brief Low priority Endpoint Correct Transfer interrupt's service routine. + */ +void USB_CorrectTransferLp(void) +{ + __IO uint16_t wEPVal = 0; + /* stay in loop while pending interrupts */ + while (((wIstr = _GetISTR()) & STS_CTRS) != 0) + { + /* extract highest priority endpoint number */ + EPindex = (uint8_t)(wIstr & STS_EP_ID); + if (EPindex == 0) + { + /* Decode and service control endpoint interrupt */ + /* calling related service routine */ + /* (USB_ProcessSetup0, USB_ProcessIn0, USB_ProcessOut0) */ + + /* save RX & TX status */ + /* and set both to NAK */ + + SaveRState = _GetENDPOINT(ENDP0); + SaveTState = SaveRState & EPTX_STS; + SaveRState &= EPRX_STS; + _SetEPRxTxStatus(ENDP0, EP_RX_NAK, EP_TX_NAK); + + /* DIR bit = origin of the interrupt */ + + if ((wIstr & STS_DIR) == 0) + { + /* DIR = 0 */ + + /* DIR = 0 => IN int */ + /* DIR = 0 implies that (EP_CTRS_TX = 1) always */ + + _ClearEP_CTR_TX(ENDP0); + USB_ProcessIn0(); + + /* before terminate set Tx & Rx status */ + + _SetEPRxTxStatus(ENDP0, SaveRState, SaveTState); + return; + } + else + { + /* DIR = 1 */ + + /* DIR = 1 & CTR_RX => SETUP or OUT int */ + /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */ + + wEPVal = _GetENDPOINT(ENDP0); + + if ((wEPVal & EP_SETUP) != 0) + { + _ClearEP_CTR_RX(ENDP0); /* SETUP bit kept frozen while CTR_RX = 1 */ + USB_ProcessSetup0(); + /* before terminate set Tx & Rx status */ + + _SetEPRxTxStatus(ENDP0, SaveRState, SaveTState); + return; + } + + else if ((wEPVal & EP_CTRS_RX) != 0) + { + _ClearEP_CTR_RX(ENDP0); + USB_ProcessOut0(); + /* before terminate set Tx & Rx status */ + + _SetEPRxTxStatus(ENDP0, SaveRState, SaveTState); + return; + } + } + } /* if(EPindex == 0) */ + else + { + /* Decode and service non control endpoints interrupt */ + + /* process related endpoint register */ + wEPVal = _GetENDPOINT(EPindex); + if ((wEPVal & EP_CTRS_RX) != 0) + { + /* clear int flag */ + _ClearEP_CTR_RX(EPindex); + + /* call OUT service function */ + (*pEpInt_OUT[EPindex - 1])(); + + } /* if((wEPVal & EP_CTRS_RX) */ + + if ((wEPVal & EP_CTRS_TX) != 0) + { + /* clear int flag */ + _ClearEP_CTR_TX(EPindex); + + /* call IN service function */ + (*pEpInt_IN[EPindex - 1])(); + } /* if((wEPVal & EP_CTRS_TX) != 0) */ + + } /* if(EPindex == 0) else */ + + } /* while(...) */ +} + +/** + * @brief High Priority Endpoint Correct Transfer interrupt's service routine. + */ +void USB_CorrectTransferHp(void) +{ + uint32_t wEPVal = 0; + + while (((wIstr = _GetISTR()) & STS_CTRS) != 0) + { + _SetISTR((uint16_t)CLR_CTRS); /* clear CTR flag */ + /* extract highest priority endpoint number */ + EPindex = (uint8_t)(wIstr & STS_EP_ID); + /* process related endpoint register */ + wEPVal = _GetENDPOINT(EPindex); + if ((wEPVal & EP_CTRS_RX) != 0) + { + /* clear int flag */ + _ClearEP_CTR_RX(EPindex); + + /* call OUT service function */ + (*pEpInt_OUT[EPindex - 1])(); + + } /* if((wEPVal & EP_CTRS_RX) */ + else if ((wEPVal & EP_CTRS_TX) != 0) + { + /* clear int flag */ + _ClearEP_CTR_TX(EPindex); + + /* call IN service function */ + (*pEpInt_IN[EPindex - 1])(); + + } /* if((wEPVal & EP_CTRS_TX) != 0) */ + + } /* while(...) */ +} diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_mem.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_mem.c new file mode 100644 index 0000000000..539a76b7cc --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_mem.c @@ -0,0 +1,81 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file usb_mem.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "usb_lib.h" +u8* EpOutDataPtrTmp; +u8* EpInDataPtrTmp; + +/** + * @brief Copy a buffer from user memory area to packet memory area (PMA) + * @param pbUsrBuf pointer to user memory area. + * @param wPMABufAddr address into PMA. + * @param wNBytes no. of bytes to be copied. + */ +void USB_CopyUserToPMABuf(uint8_t* pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes) +{ + uint32_t n = (wNBytes + 1) >> 1; /* n = (wNBytes + 1) / 2 */ + uint32_t i, temp1, temp2; + uint16_t* pdwVal; + pdwVal = (uint16_t*)(wPMABufAddr * 2 + PMAAddr); + for (i = n; i != 0; i--) + { + temp1 = (uint16_t)*pbUsrBuf; + pbUsrBuf++; + temp2 = temp1 | (uint16_t)*pbUsrBuf << 8; + *pdwVal++ = temp2; + pdwVal++; + pbUsrBuf++; + EpInDataPtrTmp = pbUsrBuf; + } +} + +/** + * @brief Copy a buffer from user memory area to packet memory area (PMA) + * @param pbUsrBuf pointer to user memory area. + * @param wPMABufAddr address into PMA. + * @param wNBytes no. of bytes to be copied. + */ +void USB_CopyPMAToUserBuf(uint8_t* pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes) +{ + uint32_t n = (wNBytes + 1) >> 1; /* /2*/ + uint32_t i; + uint32_t* pdwVal; + pdwVal = (uint32_t*)(wPMABufAddr * 2 + PMAAddr); + for (i = n; i != 0; i--) + { + *(uint16_t*)pbUsrBuf++ = *pdwVal++; + pbUsrBuf++; + EpOutDataPtrTmp = pbUsrBuf; + } +} diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_regs.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_regs.c new file mode 100644 index 0000000000..9dc97c4db7 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_regs.c @@ -0,0 +1,598 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file usb_regs.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "usb_lib.h" + +/** + * @brief Set the CTRL register value. + * @param wRegValue new register value. + */ +void USB_SetCtrl(uint16_t wRegValue) +{ + _SetCNTR(wRegValue); +} + +/** + * @brief returns the CTRL register value. + * @return CTRL register Value. + */ +uint16_t USB_GetCtrl(void) +{ + return (_GetCNTR()); +} + +/** + * @brief Set the STS register value. + * @param wRegValue new register value. + */ +void USB_SetSts(uint16_t wRegValue) +{ + _SetISTR(wRegValue); +} + +/** + * @brief Returns the STS register value. + * @return STS register Value + */ +uint16_t USB_GetSts(void) +{ + return (_GetISTR()); +} + +/** + * @brief Returns the FN register value. + * @return FN register Value + */ +uint16_t USB_GetFn(void) +{ + return (_GetFNR()); +} + +/** + * @brief Set the ADDR register value. + * @param wRegValue new register value. + */ +void USB_SetAddr(uint16_t wRegValue) +{ + _SetDADDR(wRegValue); +} + +/** + * @brief Returns the ADDR register value. + * @return ADDR register Value + */ +uint16_t USB_GetAddr(void) +{ + return (_GetDADDR()); +} + +/** + * @brief Set the BUFTAB. + * @param wRegValue New register value. + */ +void USB_SetBuftab(uint16_t wRegValue) +{ + _SetBTABLE(wRegValue); +} + +/** + * @brief Returns the BUFTAB register value. + * @return BUFTAB address. + */ +uint16_t USB_GetBTABLE(void) +{ + return (_GetBTABLE()); +} + +/** + * @brief Set the Endpoint register value. + * @param bEpNum Endpoint Number. + * @param wRegValue New register value. + */ +void USB_SetEndPoint(uint8_t bEpNum, uint16_t wRegValue) +{ + _SetENDPOINT(bEpNum, wRegValue); +} + +/** + * @brief Return the Endpoint register value. + * @param bEpNum Endpoint Number. + * @return Endpoint register value. + */ +uint16_t USB_GetEndPoint(uint8_t bEpNum) +{ + return (_GetENDPOINT(bEpNum)); +} + +/** + * @brief sets the type in the endpoint register. + * @param bEpNum Endpoint Number. + * @param wType type definition. + */ +void USB_SetEpType(uint8_t bEpNum, uint16_t wType) +{ + _SetEPType(bEpNum, wType); +} + +/** + * @brief Returns the endpoint type. + * @param bEpNum Endpoint Number. + * @return Endpoint Type + */ +uint16_t USB_GetEpType(uint8_t bEpNum) +{ + return (_GetEPType(bEpNum)); +} + +/** + * @brief Set the status of Tx endpoint. + * @param bEpNum Endpoint Number. + * @param wState new state. + */ +void SetEPTxStatus(uint8_t bEpNum, uint16_t wState) +{ + _SetEPTxStatus(bEpNum, wState); +} + +/** + * @brief Set the status of Rx endpoint. + * @param bEpNum Endpoint Number. + * @param wState new state. + */ +void SetEPRxStatus(uint8_t bEpNum, uint16_t wState) +{ + _SetEPRxStatus(bEpNum, wState); +} + +/** + * @brief sets the status for Double Buffer Endpoint to STALL + * @param bEpNum Endpoint Number. + * @param bDir Endpoint direction. + */ +void USB_SetDouBleBuferEpStall(uint8_t bEpNum, uint8_t bDir) +{ + uint16_t Endpoint_DTOG_Status; + Endpoint_DTOG_Status = USB_GetEndPoint(bEpNum); + if (bDir == EP_DBUF_OUT) + { /* OUT double buffered endpoint */ + _SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPRX_DATTOG1); + } + else if (bDir == EP_DBUF_IN) + { /* IN double buffered endpoint */ + _SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPTX_DATTOG1); + } +} + +/** + * @brief Returns the endpoint Tx status. + * @param bEpNum Endpoint Number. + * @return Endpoint TX Status + */ +uint16_t USB_GetEpTxSts(uint8_t bEpNum) +{ + return (_GetEPTxStatus(bEpNum)); +} + +/** + * @brief Returns the endpoint Rx status. + * @param bEpNum Endpoint Number. + * @return Endpoint RX Status + */ +uint16_t USB_GetEpRxSts(uint8_t bEpNum) +{ + return (_GetEPRxStatus(bEpNum)); +} + +/** + * @brief Valid the endpoint Tx Status. + * @param bEpNum Endpoint Number. + */ +void USB_SetEpTxValid(uint8_t bEpNum) +{ + _SetEPTxStatus(bEpNum, EP_TX_VALID); +} + +/** + * @brief Valid the endpoint Rx Status. + * @param bEpNum Endpoint Number. + */ +void USB_SetEpRxValid(uint8_t bEpNum) +{ + _SetEPRxStatus(bEpNum, EP_RX_VALID); +} + +/** + * @brief Clear the EP_KIND bit. + * @param bEpNum Endpoint Number. + */ +void USB_SetEpKind(uint8_t bEpNum) +{ + _SetEP_KIND(bEpNum); +} + +/** + * @brief set the EP_KIND bit. + * @param bEpNum Endpoint Number. + */ +void USB_ClrEpKind(uint8_t bEpNum) +{ + _ClearEP_KIND(bEpNum); +} +/** + * @brief Clear the Status Out of the related Endpoint + * @param bEpNum Endpoint Number. + */ +void USB_ClrStsOut(uint8_t bEpNum) +{ + _ClearEP_KIND(bEpNum); +} +/** + * @brief Set the Status Out of the related Endpoint + * @param bEpNum Endpoint Number. + */ +void USB_SetStsOut(uint8_t bEpNum) +{ + _SetEP_KIND(bEpNum); +} +/** + * @brief Enable the double buffer feature for the endpoint. + * @param bEpNum Endpoint Number. + */ +void USB_SetEpDoubleBufer(uint8_t bEpNum) +{ + _SetEP_KIND(bEpNum); +} +/** + * @brief Disable the double buffer feature for the endpoint. + * @param bEpNum Endpoint Number. + */ +void USB_ClrEpDoubleBufer(uint8_t bEpNum) +{ + _ClearEP_KIND(bEpNum); +} +/** + * @brief Returns the Stall status of the Tx endpoint. + * @param bEpNum Endpoint Number. + * @return Tx Stall status. + */ +uint16_t USB_GetTxStallSts(uint8_t bEpNum) +{ + return (_GetTxStallStatus(bEpNum)); +} +/** + * @brief Returns the Stall status of the Rx endpoint. + * @param bEpNum Endpoint Number. + * @return Rx Stall status. + */ +uint16_t USB_GetRxStallSts(uint8_t bEpNum) +{ + return (_GetRxStallStatus(bEpNum)); +} +/** + * @brief Clear the CTR_RX bit. + * @param bEpNum Endpoint Number. + */ +void USB_ClrEpCtrsRx(uint8_t bEpNum) +{ + _ClearEP_CTR_RX(bEpNum); +} +/** + * @brief Clear the CTR_TX bit. + * @param bEpNum Endpoint Number. + */ +void USB_ClrEpCtrsTx(uint8_t bEpNum) +{ + _ClearEP_CTR_TX(bEpNum); +} +/** + * @brief Toggle the DTOG_RX bit. + * @param bEpNum Endpoint Number. + */ +void USB_DattogRx(uint8_t bEpNum) +{ + _ToggleDTOG_RX(bEpNum); +} +/** + * @brief Toggle the DTOG_TX bit. + * @param bEpNum Endpoint Number. + */ +void USB_DattogTx(uint8_t bEpNum) +{ + _ToggleDTOG_TX(bEpNum); +} +/** + * @brief Clear the DTOG_RX bit. + * @param bEpNum Endpoint Number. + */ +void USB_ClrDattogRx(uint8_t bEpNum) +{ + _ClearDTOG_RX(bEpNum); +} +/** + * @brief Clear the DTOG_TX bit. + * @param bEpNum Endpoint Number. + */ +void USB_ClrDattogTx(uint8_t bEpNum) +{ + _ClearDTOG_TX(bEpNum); +} +/** + * @brief Set the endpoint address. + * @param bEpNum Endpoint Number. + * @param bAddr New endpoint address. + */ +void USB_SetEpAddress(uint8_t bEpNum, uint8_t bAddr) +{ + _SetEPAddress(bEpNum, bAddr); +} +/** + * @brief Get the endpoint address. + * @param bEpNum Endpoint Number. + * @return Endpoint address. + */ +uint8_t USB_GetEpAddress(uint8_t bEpNum) +{ + return (_GetEPAddress(bEpNum)); +} +/** + * @brief Set the endpoint Tx buffer address. + * @param bEpNum Endpoint Number. + * @param wAddr new address. + */ +void USB_SetEpTxAddr(uint8_t bEpNum, uint16_t wAddr) +{ + _SetEPTxAddr(bEpNum, wAddr); +} +/** + * @brief Set the endpoint Rx buffer address. + * @param bEpNum Endpoint Number. + * @param wAddr new address. + */ +void USB_SetEpRxAddr(uint8_t bEpNum, uint16_t wAddr) +{ + _SetEPRxAddr(bEpNum, wAddr); +} +/** + * @brief Returns the endpoint Tx buffer address. + * @param bEpNum Endpoint Number. + * @return Rx buffer address. + */ +uint16_t USB_GetEpTxAddr(uint8_t bEpNum) +{ + return (_GetEPTxAddr(bEpNum)); +} +/** + * @brief Returns the endpoint Rx buffer address. + * @param bEpNum Endpoint Number. + * @return Rx buffer address. + */ +uint16_t USB_GetEpRxAddr(uint8_t bEpNum) +{ + return (_GetEPRxAddr(bEpNum)); +} +/** + * @brief Set the Tx count. + * @param bEpNum Endpoint Number. + * @param wCount new count value. + */ +void USB_SetEpTxCnt(uint8_t bEpNum, uint16_t wCount) +{ + _SetEPTxCount(bEpNum, wCount); +} +/** + * @brief Set the Count Rx Register value. + * @param pdwReg point to the register. + * @param wCount the new register value. + */ +void USB_SetEpCntRxReg(uint32_t* pdwReg, uint16_t wCount) +{ + _SetEPCountRxReg(dwReg, wCount); +} +/** + * @brief Set the Rx count. + * @param bEpNum Endpoint Number. + * @param wCount the new count value. + */ +void USB_SetEpRxCnt(uint8_t bEpNum, uint16_t wCount) +{ + _SetEPRxCount(bEpNum, wCount); +} +/** + * @brief Get the Tx count. + * @param bEpNum Endpoint Number. + * @return Tx count value. + */ +uint16_t USB_GetEpTxCnt(uint8_t bEpNum) +{ + return (_GetEPTxCount(bEpNum)); +} +/** + * @brief Get the Rx count. + * @param bEpNum Endpoint Number. + * @return Rx count value. + */ +uint16_t USB_GetEpRxCnt(uint8_t bEpNum) +{ + return (_GetEPRxCount(bEpNum)); +} +/** + * @brief Set the addresses of the buffer 0 and 1. + * @param bEpNum Endpoint Number. + * @param wBuf0Addr new address of buffer 0. + * @param wBuf1Addr new address of buffer 1. + */ +void USB_SetEpDblBuferAddr(uint8_t bEpNum, uint16_t wBuf0Addr, uint16_t wBuf1Addr) +{ + _SetEPDblBuffAddr(bEpNum, wBuf0Addr, wBuf1Addr); +} +/** + * @brief Set the Buffer 1 address. + * @param bEpNum Endpoint Number + * @param wBuf0Addr new address. + */ +void USB_SetEpDblBuf0Addr(uint8_t bEpNum, uint16_t wBuf0Addr) +{ + _SetEPDblBuf0Addr(bEpNum, wBuf0Addr); +} +/** + * @brief Set the Buffer 1 address. + * @param bEpNum Endpoint Number + * @param wBuf1Addr new address. + */ +void USB_SetEpDblBuf1Addr(uint8_t bEpNum, uint16_t wBuf1Addr) +{ + _SetEPDblBuf1Addr(bEpNum, wBuf1Addr); +} +/** + * @brief Returns the address of the Buffer 0. + * @param bEpNum Endpoint Number. + */ +uint16_t USB_GetEpDblBuf0Addr(uint8_t bEpNum) +{ + return (_GetEPDblBuf0Addr(bEpNum)); +} +/** + * @brief Returns the address of the Buffer 1. + * @param bEpNum Endpoint Number. + * @return Address of the Buffer 1. + */ +uint16_t USB_GetEpDblBuf1Addr(uint8_t bEpNum) +{ + return (_GetEPDblBuf1Addr(bEpNum)); +} +/** + * @brief Set the number of bytes for a double Buffer endpoint. + * @param bEpNum + * @param bDir + * @param wCount + */ +void USB_SetEpDblBuferCnt(uint8_t bEpNum, uint8_t bDir, uint16_t wCount) +{ + _SetEPDblBuffCount(bEpNum, bDir, wCount); +} +/** + * @brief Set the number of bytes in the buffer 0 of a double Buffer endpoint. + * @param bEpNum + * @param bDir + * @param wCount + */ +void USB_SetEpDblBuf0Cnt(uint8_t bEpNum, uint8_t bDir, uint16_t wCount) +{ + _SetEPDblBuf0Count(bEpNum, bDir, wCount); +} +/** + * @brief Set the number of bytes in the buffer 0 of a double Buffer endpoint. + * @param bEpNum + * @param bDir + * @param wCount + */ +void USB_SetEpDblBuf1Cnt(uint8_t bEpNum, uint8_t bDir, uint16_t wCount) +{ + _SetEPDblBuf1Count(bEpNum, bDir, wCount); +} +/** + * @brief Returns the number of byte received in the buffer 0 of a double Buffer endpoint. + * @param bEpNum Endpoint Number. + * @return Endpoint Buffer 0 count + */ +uint16_t USB_GetEpDblBuf0Cnt(uint8_t bEpNum) +{ + return (_GetEPDblBuf0Count(bEpNum)); +} +/** + * @brief Returns the number of data received in the buffer 1 of a double Buffer endpoint. + * @param bEpNum Endpoint Number. + * @return Endpoint Buffer 1 count. + */ +uint16_t USB_GetEpDblBuf1Cnt(uint8_t bEpNum) +{ + return (_GetEPDblBuf1Count(bEpNum)); +} +/** + * @brief gets direction of the double buffered endpoint + * @param bEpNum Endpoint Number. + * @return EP_DBUF_OUT, EP_DBUF_IN, EP_DBUF_ERR if the endpoint counter not yet programmed. + */ +EP_DBUF_DIR GetEPDblBufDir(uint8_t bEpNum) +{ + if ((uint16_t)(*_pEPRxCount(bEpNum) & 0xFC00) != 0) + return (EP_DBUF_OUT); + else if (((uint16_t)(*_pEPTxCount(bEpNum)) & 0x03FF) != 0) + return (EP_DBUF_IN); + else + return (EP_DBUF_ERR); +} +/** + * @brief free buffer used from the application realizing it to the line toggles + * bit SW_BUF in the double buffered endpoint register + * @param bEpNum + * @param bDir + */ +void USB_FreeUserBuf(uint8_t bEpNum, uint8_t bDir) +{ + if (bDir == EP_DBUF_OUT) + { /* OUT double buffered endpoint */ + _ToggleDTOG_TX(bEpNum); + } + else if (bDir == EP_DBUF_IN) + { /* IN double buffered endpoint */ + _ToggleDTOG_RX(bEpNum); + } +} + +/** + * @brief merge two byte in a word. + * @param bh byte high + * @param bl bytes low. + * @return resulted word. + */ +uint16_t USB_ToWord(uint8_t bh, uint8_t bl) +{ + uint16_t wRet; + wRet = (uint16_t)bl | ((uint16_t)bh << 8); + return (wRet); +} +/** + * @brief Swap two byte in a word. + * @param wSwW word to Swap. + * @return resulted word. + */ +uint16_t USB_ByteSwap(uint16_t wSwW) +{ + uint8_t bTemp; + uint16_t wRet; + bTemp = (uint8_t)(wSwW & 0xff); + wRet = (wSwW >> 8) | ((uint16_t)bTemp << 8); + return (wRet); +} diff --git a/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_sil.c b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_sil.c new file mode 100644 index 0000000000..930e661c83 --- /dev/null +++ b/bsp/n32/libraries/N32G4FR_Firmware_Library/n32g4fr_usbfs_driver/src/usb_sil.c @@ -0,0 +1,83 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS 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. + * ****************************************************************************/ + +/** + * @file usb_sil.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "usb_lib.h" + +/** + * @brief Initialize the USB Device IP and the Endpoint 0. + * @return Status. + */ +uint32_t USB_SilInit(void) +{ + /* USB interrupts initialization */ + /* clear pending interrupts */ + _SetISTR(0); + wInterrupt_Mask = IMR_MSK; + /* set interrupts mask */ + _SetCNTR(wInterrupt_Mask); + return 0; +} + +/** + * @brief Write a buffer of data to a selected endpoint. + * @param bEpAddr The address of the non control endpoint. + * @param pBufferPointer The pointer to the buffer of data to be written to the endpoint. + * @param wBufferSize Number of data to be written (in bytes). + * @return Status. + */ +uint32_t USB_SilWrite(uint8_t bEpAddr, uint8_t* pBufferPointer, uint32_t wBufferSize) +{ + /* Use the memory interface function to write to the selected endpoint */ + USB_CopyUserToPMABuf(pBufferPointer, USB_GetEpTxAddr(bEpAddr & 0x7F), wBufferSize); + /* Update the data length in the control register */ + USB_SetEpTxCnt((bEpAddr & 0x7F), wBufferSize); + return 0; +} + +/** + * @brief Write a buffer of data to a selected endpoint. + * @param bEpAddr The address of the non control endpoint. + * @param pBufferPointer The pointer to which will be saved the received data buffer. + * @return Number of received data (in Bytes). + */ +uint32_t USB_SilRead(uint8_t bEpAddr, uint8_t* pBufferPointer) +{ + uint32_t DataLength = 0; + /* Get the number of received data on the selected Endpoint */ + DataLength = USB_GetEpRxCnt(bEpAddr & 0x7F); + /* Use the memory interface function to write to the selected endpoint */ + USB_CopyPMAToUserBuf(pBufferPointer, USB_GetEpRxAddr(bEpAddr & 0x7F), DataLength); + /* Return the number of received data */ + return DataLength; +} diff --git a/bsp/n32/libraries/n32_drivers/drv_adc.c b/bsp/n32/libraries/n32_drivers/drv_adc.c index abf0555adf..8d17f0d86f 100644 --- a/bsp/n32/libraries/n32_drivers/drv_adc.c +++ b/bsp/n32/libraries/n32_drivers/drv_adc.c @@ -64,7 +64,7 @@ static void n32_adc_init(struct n32_adc_config *config) ADC_DeInit((ADC_Module*)config->adc_periph); /* ADC configuration */ -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT; #endif @@ -137,7 +137,7 @@ int rt_hw_adc_init(void) int i = 0; int result = RT_EOK; -#if defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X) +#if defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X) || defined(SOC_N32G4FR) #ifdef BSP_USING_ADC RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC, ENABLE); diff --git a/bsp/n32/libraries/n32_drivers/drv_can.c b/bsp/n32/libraries/n32_drivers/drv_can.c index 138aa69f02..348494b20f 100644 --- a/bsp/n32/libraries/n32_drivers/drv_can.c +++ b/bsp/n32/libraries/n32_drivers/drv_can.c @@ -112,7 +112,7 @@ static void bxcan2_hw_init(void) /* baud calculation example: Tclk / ((ss + bs1 + bs2) * brp), 36 / ((1 + 8 + 3) * 3) = 1MHz*/ -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) /* APB1 36MHz(max) */ +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) /* APB1 36MHz(max) */ static const struct n32_baud_rate_tab can_baud_rate_tab[] = { N32_CAN_BAUD_DEF(CAN1MBaud, CAN_RSJW_1tq, CAN_TBS1_5tq, CAN_TBS2_3tq, 4), @@ -172,7 +172,7 @@ static rt_uint32_t get_can_baud_index(rt_uint32_t baud) static rt_err_t setfilter(struct n32_can *drv_can) { -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) if (drv_can->CANx == CAN1) { CAN1_InitFilter(&(drv_can->FilterConfig)); @@ -270,7 +270,7 @@ static rt_err_t configure(struct rt_can_device *can, struct can_configure *cfg) drv_can = (struct n32_can *)can->parent.user_data; pbxcan = drv_can->CANx; -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) if (pbxcan == CAN1) { #ifdef BSP_USING_CAN1 @@ -334,7 +334,7 @@ static rt_err_t control(struct rt_can_device *can, int cmd, void *arg) argval = (rt_uint32_t) arg; if (argval == RT_DEVICE_FLAG_INT_RX) { -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) if (CAN1 == drv_can->CANx) { NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn); @@ -384,7 +384,7 @@ static rt_err_t control(struct rt_can_device *can, int cmd, void *arg) } else if (argval == RT_DEVICE_CAN_INT_ERR) { -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) if (CAN1 == drv_can->CANx) { NVIC_DisableIRQ(CAN1_SCE_IRQn); @@ -420,7 +420,7 @@ static rt_err_t control(struct rt_can_device *can, int cmd, void *arg) CAN_INTConfig(drv_can->CANx, CAN_INT_FF1, ENABLE); /* DATFIFO 1 full Interrupt */ CAN_INTConfig(drv_can->CANx, CAN_INT_FOV1, ENABLE); /* DATFIFO 1 overrun Interrupt */ -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) if (CAN1 == drv_can->CANx) { CAN_NVIC_Config(USB_LP_CAN1_RX0_IRQn, 1, 0, ENABLE); @@ -445,7 +445,7 @@ static rt_err_t control(struct rt_can_device *can, int cmd, void *arg) { CAN_INTConfig(drv_can->CANx, CAN_INT_TME, ENABLE); /* Transmit mailbox empty Interrupt */ -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) if (CAN1 == drv_can->CANx) { CAN_NVIC_Config(USB_HP_CAN1_TX_IRQn, 1, 0, ENABLE); @@ -471,7 +471,7 @@ static rt_err_t control(struct rt_can_device *can, int cmd, void *arg) CAN_INTConfig(drv_can->CANx, CAN_INT_LEC, ENABLE); /* Last error code Interrupt */ CAN_INTConfig(drv_can->CANx, CAN_INT_ERR, ENABLE); /* Error Interrupt */ -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) if (CAN1 == drv_can->CANx) { CAN_NVIC_Config(CAN1_SCE_IRQn, 1, 0, ENABLE); diff --git a/bsp/n32/libraries/n32_drivers/drv_dac.c b/bsp/n32/libraries/n32_drivers/drv_dac.c index 2f5f0cc653..274c0e915a 100644 --- a/bsp/n32/libraries/n32_drivers/drv_dac.c +++ b/bsp/n32/libraries/n32_drivers/drv_dac.c @@ -56,7 +56,7 @@ static void n32_dac_init(struct n32_dac_config *config) DAC_InitStructure.LfsrUnMaskTriAmp = DAC_UNMASK_LFSRBIT0; DAC_InitStructure.BufferOutput = DAC_BUFFOUTPUT_ENABLE; -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) DAC_Init(config->dac_periph, &DAC_InitStructure); #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X) DAC_Init(&DAC_InitStructure); @@ -73,7 +73,7 @@ static rt_err_t n32_dac_enabled(struct rt_dac_device *device, rt_uint32_t channe { RT_ASSERT(device != RT_NULL); -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) DAC_Enable(channel, ENABLE); #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X) DAC_Enable(ENABLE); @@ -86,7 +86,7 @@ static rt_err_t n32_dac_disabled(struct rt_dac_device *device, rt_uint32_t chann { RT_ASSERT(device != RT_NULL); -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) DAC_Enable(channel, DISABLE); #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X) DAC_Enable(DISABLE); @@ -111,7 +111,7 @@ static rt_err_t n32_set_dac_value(struct rt_dac_device *device, rt_uint32_t chan set_value = 4096; } -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) /* Start DAC Channel conversion by software */ if (channel == DAC_CHANNEL_1) { diff --git a/bsp/n32/libraries/n32_drivers/drv_gpio.c b/bsp/n32/libraries/n32_drivers/drv_gpio.c index 967e446093..c352cd2359 100644 --- a/bsp/n32/libraries/n32_drivers/drv_gpio.c +++ b/bsp/n32/libraries/n32_drivers/drv_gpio.c @@ -255,7 +255,7 @@ static void n32_gpio_clock_enable(GPIO_Module* GPIOx) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE); } -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) else if (GPIOx == GPIOE) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE); @@ -296,7 +296,7 @@ static void n32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) /* Configure GPIO_InitStructure */ GPIO_InitStructure.Pin = index->pin; -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; #endif @@ -308,7 +308,7 @@ static void n32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) else if (mode == PIN_MODE_INPUT) { /* input setting: not pull. */ -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X) GPIO_InitStructure.GPIO_Pull = GPIO_No_Pull; @@ -318,7 +318,7 @@ static void n32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) else if (mode == PIN_MODE_INPUT_PULLUP) { /* input setting: pull up. */ -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X) GPIO_InitStructure.GPIO_Pull = GPIO_Pull_Up; @@ -328,7 +328,7 @@ static void n32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) else if (mode == PIN_MODE_INPUT_PULLDOWN) { /* input setting: pull down. */ -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X) GPIO_InitStructure.GPIO_Pull = GPIO_Pull_Down; @@ -340,7 +340,7 @@ static void n32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) /* output setting: od. */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; } -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) GPIO_InitPeripheral(index->gpio, &GPIO_InitStructure); #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X) GPIO_InitPeripheral(index->gpio, &GPIO_InitStructure); @@ -379,7 +379,7 @@ rt_inline rt_int32_t port2portsource(GPIO_Module* module) { return GPIOD_PORT_SOURCE; } -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) else if (module == GPIOE) { return GPIOE_PORT_SOURCE; diff --git a/bsp/n32/libraries/n32_drivers/drv_rtc.c b/bsp/n32/libraries/n32_drivers/drv_rtc.c index 1661536724..1bf01cec19 100644 --- a/bsp/n32/libraries/n32_drivers/drv_rtc.c +++ b/bsp/n32/libraries/n32_drivers/drv_rtc.c @@ -95,7 +95,7 @@ static rt_err_t rt_rtc_config(void) static rt_err_t n32_rtc_init(void) { /* Enable the PWR clock */ -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_PWR | RCC_APB1_PERIPH_BKP, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X) @@ -121,7 +121,7 @@ static rt_err_t n32_rtc_init(void) while (RCC_WaitHseStable() == ERROR) { } -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) rt_kprintf("rtc clock source is set hse/128!\n"); RCC_ConfigRtcClk(RCC_RTCCLK_SRC_HSE_DIV128); #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X) @@ -129,7 +129,7 @@ static rt_err_t n32_rtc_init(void) RCC_ConfigRtcClk(RCC_RTCCLK_SRC_HSE_DIV32); #endif -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) SynchPrediv = 0x1E8; // 8M/128 = 62.5KHz AsynchPrediv = 0x7F; // value range: 0-7F #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X) @@ -143,7 +143,7 @@ static rt_err_t n32_rtc_init(void) /* Enable the LSE OSC32_IN PC14 */ RCC_EnableLsi(DISABLE); // LSI is turned off here to ensure that only one clock is turned on -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) RCC_ConfigLse(RCC_LSE_ENABLE); while (RCC_GetFlagStatus(RCC_FLAG_LSERD) == RESET) { @@ -164,7 +164,7 @@ static rt_err_t n32_rtc_init(void) rt_kprintf("rtc clock source is set lsi!\n"); /* Enable the LSI OSC */ RCC_EnableLsi(ENABLE); -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) while (RCC_GetFlagStatus(RCC_FLAG_LSIRD) == RESET) { } @@ -175,7 +175,7 @@ static rt_err_t n32_rtc_init(void) #endif RCC_ConfigRtcClk(RCC_RTCCLK_SRC_LSI); -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) SynchPrediv = 0x136; // 39.64928KHz AsynchPrediv = 0x7F; // value range: 0-7F #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X) diff --git a/bsp/n32/libraries/n32_drivers/drv_spi.c b/bsp/n32/libraries/n32_drivers/drv_spi.c index 2a2f7ac0c3..4f0dc99f64 100644 --- a/bsp/n32/libraries/n32_drivers/drv_spi.c +++ b/bsp/n32/libraries/n32_drivers/drv_spi.c @@ -38,7 +38,7 @@ static rt_err_t configure(struct rt_spi_device* device, struct rt_spi_configurat spi_periph = (SPI_Module*)device->bus->parent.user_data; -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) if (spi_periph != SPI1 && spi_periph != SPI2 && spi_periph != SPI3) { return RT_EIO; @@ -273,7 +273,7 @@ int rt_hw_spi_init(void) result = rt_spi_bus_register(&spi_bus1, "spi1", &spi_ops); -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_SPI1, ENABLE); GPIO_InitStruct(&GPIO_InitStructure); @@ -307,7 +307,7 @@ int rt_hw_spi_init(void) result = rt_spi_bus_register(&spi_bus2, "spi2", &spi_ops); -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_SPI2, ENABLE); diff --git a/bsp/n32/libraries/n32_drivers/drv_usart.c b/bsp/n32/libraries/n32_drivers/drv_usart.c index f7d787754d..c14de578ad 100644 --- a/bsp/n32/libraries/n32_drivers/drv_usart.c +++ b/bsp/n32/libraries/n32_drivers/drv_usart.c @@ -21,7 +21,7 @@ /* n32 uart driver */ // Todo: compress uart info -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) struct n32_uart { USART_Module* uart_periph; //Todo: 3bits @@ -173,7 +173,7 @@ void UART7_IRQHandler(void) #endif /* BSP_USING_UART7 */ static const struct n32_uart uarts[] = { -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) #ifdef BSP_USING_USART1 { USART1, // uart peripheral index @@ -335,7 +335,7 @@ void n32_uart_gpio_init(struct n32_uart *uart, struct serial_configure *cfg) { GPIO_InitType GPIO_InitStructure; -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) /* enable USART clock */ RCC_EnableAPB2PeriphClk(uart->tx_gpio_clk | uart->rx_gpio_clk | RCC_APB2_PERIPH_AFIO, ENABLE); diff --git a/bsp/n32/libraries/n32_drivers/drv_wdt.c b/bsp/n32/libraries/n32_drivers/drv_wdt.c index 5d9a5ba94c..0b043d2ef4 100644 --- a/bsp/n32/libraries/n32_drivers/drv_wdt.c +++ b/bsp/n32/libraries/n32_drivers/drv_wdt.c @@ -39,7 +39,7 @@ static rt_err_t n32_wdt_open(rt_watchdog_t *wdt, rt_uint16_t oflag) RCC_EnableLsi(ENABLE); /* Wait till LSI is ready */ -#if defined(SOC_N32G45X) || defined(SOC_N32WB452) +#if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR) while (RCC_GetFlagStatus(RCC_FLAG_LSIRD) == RESET) { } diff --git a/bsp/n32/n32g4frml-stb/.config b/bsp/n32/n32g4frml-stb/.config new file mode 100644 index 0000000000..2cfd424ddc --- /dev/null +++ b/bsp/n32/n32g4frml-stb/.config @@ -0,0 +1,883 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=1000 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_HOOK_USING_FUNC_PTR=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=256 +# CONFIG_RT_USING_TIMER_SOFT is not set + +# +# kservice optimization +# +# CONFIG_RT_KSERVICE_USING_STDLIB is not set +# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set +# CONFIG_RT_USING_TINY_FFS is not set +# CONFIG_RT_KPRINTF_USING_LONGLONG is not set +CONFIG_RT_DEBUG=y +CONFIG_RT_DEBUG_COLOR=y +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +CONFIG_RT_USING_MEMHEAP=y +CONFIG_RT_MEMHEAP_FAST_MODE=y +# CONFIG_RT_MEMHEAP_BSET_MODE is not set +CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y +# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_SLAB_AS_HEAP is not set +# CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +# CONFIG_RT_USING_MEMTRACE is not set +# CONFIG_RT_USING_HEAP_ISR is not set +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="usart1" +CONFIG_RT_VER_NUM=0x40101 +CONFIG_ARCH_ARM=y +CONFIG_RT_USING_CPU_FFS=y +CONFIG_ARCH_ARM_CORTEX_M=y +CONFIG_ARCH_ARM_CORTEX_M4=y +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 +# CONFIG_RT_USING_LEGACY is not set +CONFIG_RT_USING_MSH=y +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_ARG_MAX=10 +# CONFIG_RT_USING_DFS is not set +# CONFIG_RT_USING_FAL is not set +# CONFIG_RT_USING_LWP is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_USING_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=64 +CONFIG_RT_USING_CAN=y +# CONFIG_RT_CAN_USING_HDR is not set +CONFIG_RT_USING_HWTIMER=y +# CONFIG_RT_USING_CPUTIME is not set +CONFIG_RT_USING_I2C=y +# CONFIG_RT_I2C_DEBUG is not set +CONFIG_RT_USING_I2C_BITOPS=y +# CONFIG_RT_I2C_BITOPS_DEBUG is not set +# CONFIG_RT_USING_PHY is not set +CONFIG_RT_USING_PIN=y +CONFIG_RT_USING_ADC=y +CONFIG_RT_USING_DAC=y +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +CONFIG_RT_USING_RTC=y +# CONFIG_RT_USING_ALARM is not set +# CONFIG_RT_USING_SOFT_RTC is not set +# CONFIG_RT_USING_SDIO is not set +CONFIG_RT_USING_SPI=y +# CONFIG_RT_USING_SPI_BITOPS is not set +# CONFIG_RT_USING_QSPI is not set +# CONFIG_RT_USING_SPI_MSD is not set +# CONFIG_RT_USING_SFUD is not set +# CONFIG_RT_USING_ENC28J60 is not set +# CONFIG_RT_USING_SPI_WIFI is not set +CONFIG_RT_USING_WDT=y +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB is not set +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# C/C++ and POSIX layer +# +CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 + +# +# POSIX (Portable Operating System Interface) layer +# +# CONFIG_RT_USING_POSIX_FS is not set +# CONFIG_RT_USING_POSIX_DELAY is not set +# CONFIG_RT_USING_POSIX_CLOCK is not set +# CONFIG_RT_USING_POSIX_TIMER is not set +# CONFIG_RT_USING_PTHREADS is not set +# CONFIG_RT_USING_MODULE is not set + +# +# Interprocess Communication (IPC) +# +# CONFIG_RT_USING_POSIX_PIPE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set + +# +# Socket is in the 'Network' category +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Network +# +# CONFIG_RT_USING_SAL is not set +# CONFIG_RT_USING_NETDEV is not set +# CONFIG_RT_USING_LWIP is not set +# CONFIG_RT_USING_AT is not set + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_VAR_EXPORT is not set +# CONFIG_RT_USING_RT_LINK is not set +# CONFIG_RT_USING_VBUS is not set + +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_LWIP is not set +# CONFIG_PKG_USING_LORAWAN_DRIVER is not set +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_MYMQTT is not set +# CONFIG_PKG_USING_KAWAII_MQTT is not set +# CONFIG_PKG_USING_BC28_MQTT is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_LIBMODBUS is not set +# CONFIG_PKG_USING_FREEMODBUS is not set +# CONFIG_PKG_USING_NANOPB is not set + +# +# Wi-Fi +# + +# +# Marvell WiFi +# +# CONFIG_PKG_USING_WLANMARVELL is not set + +# +# Wiced WiFi +# +# CONFIG_PKG_USING_WLAN_WICED is not set +# CONFIG_PKG_USING_RW007 is not set +# CONFIG_PKG_USING_COAP is not set +# CONFIG_PKG_USING_NOPOLL is not set +# CONFIG_PKG_USING_NETUTILS is not set +# CONFIG_PKG_USING_CMUX is not set +# CONFIG_PKG_USING_PPP_DEVICE is not set +# CONFIG_PKG_USING_AT_DEVICE is not set +# CONFIG_PKG_USING_ATSRV_SOCKET is not set +# CONFIG_PKG_USING_WIZNET is not set +# CONFIG_PKG_USING_ZB_COORDINATOR is not set + +# +# IoT Cloud +# +# CONFIG_PKG_USING_ONENET is not set +# CONFIG_PKG_USING_GAGENT_CLOUD is not set +# CONFIG_PKG_USING_ALI_IOTKIT is not set +# CONFIG_PKG_USING_AZURE is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_EZ_IOT_OS is not set +# CONFIG_PKG_USING_IOTSHARP_SDK is not set +# CONFIG_PKG_USING_NIMBLE is not set +# CONFIG_PKG_USING_LLSYNC_SDK_ADAPTER is not set +# CONFIG_PKG_USING_OTA_DOWNLOADER is not set +# CONFIG_PKG_USING_IPMSG is not set +# CONFIG_PKG_USING_LSSDP is not set +# CONFIG_PKG_USING_AIRKISS_OPEN is not set +# CONFIG_PKG_USING_LIBRWS is not set +# CONFIG_PKG_USING_TCPSERVER is not set +# CONFIG_PKG_USING_PROTOBUF_C is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# CONFIG_PKG_USING_WAYZ_IOTKIT is not set +# CONFIG_PKG_USING_MAVLINK is not set +# CONFIG_PKG_USING_BSAL is not set +# CONFIG_PKG_USING_AGILE_MODBUS is not set +# CONFIG_PKG_USING_AGILE_FTP is not set +# CONFIG_PKG_USING_EMBEDDEDPROTO is not set +# CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_LORA_PKT_FWD is not set +# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set +# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set +# CONFIG_PKG_USING_HM is not set +# CONFIG_PKG_USING_SMALL_MODBUS is not set +# CONFIG_PKG_USING_NET_SERVER is not set +# CONFIG_PKG_USING_ZFTP is not set + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_LIBSODIUM is not set +# CONFIG_PKG_USING_LIBHYDROGEN is not set +# CONFIG_PKG_USING_TINYCRYPT is not set +# CONFIG_PKG_USING_TFM is not set +# CONFIG_PKG_USING_YD_CRYPTO is not set + +# +# language packages +# + +# +# JSON: JavaScript Object Notation, a lightweight data-interchange format +# +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_LJSON is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_RAPIDJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PARSON is not set + +# +# XML: Extensible Markup Language +# +# CONFIG_PKG_USING_SIMPLE_XML is not set +# CONFIG_PKG_USING_EZXML is not set +# CONFIG_PKG_USING_LUATOS_SOC is not set +# CONFIG_PKG_USING_LUA is not set +# CONFIG_PKG_USING_JERRYSCRIPT is not set +# CONFIG_PKG_USING_MICROPYTHON is not set +# CONFIG_PKG_USING_PIKASCRIPT is not set +# CONFIG_PKG_USING_RTT_RUST is not set + +# +# multimedia packages +# + +# +# LVGL: powerful and easy-to-use embedded GUI library +# +# CONFIG_PKG_USING_LVGL is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set +# CONFIG_PKG_USING_GUI_GUIDER_DEMO is not set + +# +# u8g2: a monochrome graphic library +# +# CONFIG_PKG_USING_U8G2_OFFICIAL is not set +# CONFIG_PKG_USING_U8G2 is not set +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set +# CONFIG_PKG_USING_STEMWIN is not set +# CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_PDFGEN is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set +# CONFIG_PKG_USING_NUEMWIN is not set +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set +# CONFIG_PKG_USING_UGUI is not set + +# +# PainterEngine: A cross-platform graphics application framework written in C language +# +# CONFIG_PKG_USING_PAINTERENGINE is not set +# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_PERSIMMON is not set + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_SEGGER_RTT is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ULOG_FILE is not set +# CONFIG_PKG_USING_LOGMGR is not set +# CONFIG_PKG_USING_ADBD is not set +# CONFIG_PKG_USING_COREMARK is not set +# CONFIG_PKG_USING_DHRYSTONE is not set +# CONFIG_PKG_USING_MEMORYPERF is not set +# CONFIG_PKG_USING_NR_MICRO_SHELL is not set +# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set +# CONFIG_PKG_USING_LUNAR_CALENDAR is not set +# CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set +# CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_REGEX is not set +# CONFIG_PKG_USING_MEM_SANDBOX is not set +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set +# CONFIG_PKG_USING_FDT is not set +# CONFIG_PKG_USING_CBOX is not set +# CONFIG_PKG_USING_SNOWFLAKE is not set +# CONFIG_PKG_USING_HASH_MATCH is not set +# CONFIG_PKG_USING_FIRE_PID_CURVE is not set +# CONFIG_PKG_USING_ARMV7M_DWT_TOOL is not set +# CONFIG_PKG_USING_VOFA_PLUS is not set + +# +# system packages +# + +# +# enhanced kernel services +# +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set + +# +# acceleration: Assembly language or algorithmic acceleration packages +# +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set + +# +# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard +# +# CONFIG_PKG_USING_CMSIS_5 is not set +# CONFIG_PKG_USING_CMSIS_RTOS1 is not set +# CONFIG_PKG_USING_CMSIS_RTOS2 is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_UCOSII_WRAPPER is not set +# CONFIG_PKG_USING_UC_CRC is not set +# CONFIG_PKG_USING_UC_CLK is not set +# CONFIG_PKG_USING_UC_COMMON is not set +# CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_PKG_USING_FREERTOS_WRAPPER is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_PERF_COUNTER is not set +# CONFIG_PKG_USING_FLASHDB is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_THREAD_POOL is not set +# CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set +# CONFIG_PKG_USING_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set +# CONFIG_PKG_USING_EVENT_RECORDER is not set +# CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_MCUBOOT is not set +# CONFIG_PKG_USING_TINYUSB is not set +# CONFIG_PKG_USING_CHERRYUSB is not set +# CONFIG_PKG_USING_KMULTI_RTIMER is not set +# CONFIG_PKG_USING_TFDB is not set +# CONFIG_PKG_USING_QPC is not set +# CONFIG_PKG_USING_AGILE_UPGRADE is not set + +# +# peripheral libraries and drivers +# +# CONFIG_PKG_USING_SENSORS_DRIVERS is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_ADT74XX is not set +# CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_ESP_IDF is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_BUTTON is not set +# CONFIG_PKG_USING_PCF8574 is not set +# CONFIG_PKG_USING_SX12XX is not set +# CONFIG_PKG_USING_SIGNAL_LED is not set +# CONFIG_PKG_USING_LEDBLINK is not set +# CONFIG_PKG_USING_LITTLED is not set +# CONFIG_PKG_USING_LKDGUI is not set +# CONFIG_PKG_USING_NRF5X_SDK is not set +# CONFIG_PKG_USING_NRFX is not set +# CONFIG_PKG_USING_WM_LIBRARIES is not set + +# +# Kendryte SDK +# +# CONFIG_PKG_USING_K210_SDK is not set +# CONFIG_PKG_USING_KENDRYTE_SDK is not set +# CONFIG_PKG_USING_INFRARED is not set +# CONFIG_PKG_USING_MULTI_INFRARED is not set +# CONFIG_PKG_USING_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set +# CONFIG_PKG_USING_AT24CXX is not set +# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_AD7746 is not set +# CONFIG_PKG_USING_PCA9685 is not set +# CONFIG_PKG_USING_I2C_TOOLS is not set +# CONFIG_PKG_USING_NRF24L01 is not set +# CONFIG_PKG_USING_TOUCH_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# CONFIG_PKG_USING_AS608 is not set +# CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set +# CONFIG_PKG_USING_EMBARC_BSP is not set +# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set +# CONFIG_PKG_USING_MULTI_RTIMER is not set +# CONFIG_PKG_USING_MAX7219 is not set +# CONFIG_PKG_USING_BEEP is not set +# CONFIG_PKG_USING_EASYBLINK is not set +# CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set +# CONFIG_PKG_USING_LY68L6400 is not set +# CONFIG_PKG_USING_DM9051 is not set +# CONFIG_PKG_USING_SSD1306 is not set +# CONFIG_PKG_USING_QKEY is not set +# CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set +# CONFIG_PKG_USING_NES is not set +# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set +# CONFIG_PKG_USING_VDEVICE is not set +# CONFIG_PKG_USING_SGM706 is not set +# CONFIG_PKG_USING_STM32WB55_SDK is not set +# CONFIG_PKG_USING_RDA58XX is not set +# CONFIG_PKG_USING_LIBNFC is not set +# CONFIG_PKG_USING_MFOC is not set +# CONFIG_PKG_USING_TMC51XX is not set +# CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set +# CONFIG_PKG_USING_MCP23008 is not set +# CONFIG_PKG_USING_BLUETRUM_SDK is not set +# CONFIG_PKG_USING_MISAKA_AT24CXX is not set +# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set +# CONFIG_PKG_USING_BL_MCU_SDK is not set +# CONFIG_PKG_USING_SOFT_SERIAL is not set +# CONFIG_PKG_USING_MB85RS16 is not set +# CONFIG_PKG_USING_CW2015 is not set +# CONFIG_PKG_USING_RFM300 is not set +# CONFIG_PKG_USING_IO_INPUT_FILTER is not set +# CONFIG_PKG_USING_RASPBERRYPI_PICO_SDK is not set + +# +# AI packages +# +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_QUEST is not set +# CONFIG_PKG_USING_NAXOS is not set + +# +# miscellaneous packages +# + +# +# project laboratory +# + +# +# samples: kernel and components samples +# +# CONFIG_PKG_USING_KERNEL_SAMPLES is not set +# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set +# CONFIG_PKG_USING_NETWORK_SAMPLES is not set +# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set + +# +# entertainment: terminal games and other interesting software packages +# +# CONFIG_PKG_USING_CMATRIX is not set +# CONFIG_PKG_USING_SL is not set +# CONFIG_PKG_USING_CAL is not set +# CONFIG_PKG_USING_ACLOCK is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_COWSAY is not set +# CONFIG_PKG_USING_LIBCSV is not set +# CONFIG_PKG_USING_OPTPARSE is not set +# CONFIG_PKG_USING_FASTLZ is not set +# CONFIG_PKG_USING_MINILZO is not set +# CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_LZMA is not set +# CONFIG_PKG_USING_MULTIBUTTON is not set +# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set +# CONFIG_PKG_USING_CANFESTIVAL is not set +# CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_MINIZIP is not set +# CONFIG_PKG_USING_HEATSHRINK is not set +# CONFIG_PKG_USING_DSTR is not set +# CONFIG_PKG_USING_TINYFRAME is not set +# CONFIG_PKG_USING_KENDRYTE_DEMO is not set +# CONFIG_PKG_USING_DIGITALCTRL is not set +# CONFIG_PKG_USING_UPACKER is not set +# CONFIG_PKG_USING_UPARAM is not set +# CONFIG_PKG_USING_HELLO is not set +# CONFIG_PKG_USING_VI is not set +# CONFIG_PKG_USING_KI is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_DESIGN_PATTERN is not set +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set +# CONFIG_PKG_USING_MFBD is not set +# CONFIG_PKG_USING_SLCAN2RTT is not set +# CONFIG_PKG_USING_SOEM is not set +# CONFIG_PKG_USING_QPARAM is not set + +# +# Arduino libraries +# +# CONFIG_PKG_USING_RTDUINO is not set + +# +# Projects +# +# CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set +# CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set +# CONFIG_PKG_USING_ARDUINO_MATLAB_SUPPORT is not set + +# +# Sensors +# +# CONFIG_PKG_USING_ARDUINO_SEEED_BMP280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL375 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L0X is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LIS3DHTR is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_DHT is not set +# CONFIG_PKG_USING_ARDUINO_CAPACITIVESENSOR is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSOR is not set +# CONFIG_PKG_USING_ADAFRUIT_MAX31855 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31865 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31856 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90614 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS1 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AHTX0 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS0 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADT7410 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME680 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9808 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4728 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA219 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR390 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL345 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DHT is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9600 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM6DS is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO055 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX1704X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMC56X3 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90393 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90395 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ICM20X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DPS310 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTS221 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT4X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT31 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL343 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS726X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AMG88XX is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2320 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2315 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR329_LTR303 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP3XX is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MS8607 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3MDL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90640 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMA8451 is not set +# CONFIG_PKG_USING_ADAFRUIT_MSA301 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL115A2 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X_RVC is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS2MDL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303DLH_MAG is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LC709203F is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CAP1188 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CCS811 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_NAU7802 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS331 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS2X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS35HW is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303_ACCEL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3DH is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8591 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL3115A2 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPR121 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPRLS is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPU6050 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCT2075 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PM25AQI is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_EMC2101 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXAS21002C is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SCD30 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXOS8700 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HMC5883_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP30 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP006 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TLA202X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCS34725 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI7021 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI1145 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP40 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHTC3 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HDC1000 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU21DF is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS7341 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU31D is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA260 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP007_LIBRARY is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_L3GD20 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP117 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSC2007 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2561 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2591_LIBRARY is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VCNL4040 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6070 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6075 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML7700 is not set + +# +# Display +# +# CONFIG_PKG_USING_ARDUINO_U8G2 is not set + +# +# Timing +# +# CONFIG_PKG_USING_ARDUINO_MSTIMER2 is not set + +# +# Data Processing +# +# CONFIG_PKG_USING_ARDUINO_KALMANFILTER is not set +# CONFIG_PKG_USING_ARDUINO_ARDUINOJSON is not set + +# +# Data Storage +# + +# +# Communication +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PN532 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI4713 is not set + +# +# Device Control +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8574 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCA9685 is not set + +# +# Other +# + +# +# Signal IO +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BUSIO is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCA8418 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP23017 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADS1X15 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AW9523 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP3008 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4725 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BD3491FS is not set + +# +# Uncategorized +# +CONFIG_SOC_FAMILY_N32=y +CONFIG_SOC_SERIES_N32G45X=y + +# +# Hardware Drivers Config +# +CONFIG_SOC_N32G45X=y + +# +# Onboard Peripheral Drivers +# + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_USART1=y +# CONFIG_BSP_USING_USART2 is not set +# CONFIG_BSP_USING_USART3 is not set +# CONFIG_BSP_USING_UART4 is not set +# CONFIG_BSP_USING_UART5 is not set +# CONFIG_BSP_USING_UART6 is not set +# CONFIG_BSP_USING_UART7 is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_I2C1 is not set +# CONFIG_BSP_USING_RTC is not set +# CONFIG_BSP_USING_WDT is not set +# CONFIG_BSP_USING_HWTIMER is not set +# CONFIG_BSP_USING_ADC is not set +# CONFIG_BSP_USING_DAC is not set +# CONFIG_BSP_USING_CAN is not set + +# +# Board extended module Drivers +# diff --git a/bsp/n32/n32g4frml-stb/Kconfig b/bsp/n32/n32g4frml-stb/Kconfig new file mode 100644 index 0000000000..8cbc7b71a8 --- /dev/null +++ b/bsp/n32/n32g4frml-stb/Kconfig @@ -0,0 +1,21 @@ +mainmenu "RT-Thread Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../../.." + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" +source "../libraries/Kconfig" +source "board/Kconfig" diff --git a/bsp/n32/n32g4frml-stb/README.md b/bsp/n32/n32g4frml-stb/README.md new file mode 100644 index 0000000000..a0a58ca52f --- /dev/null +++ b/bsp/n32/n32g4frml-stb/README.md @@ -0,0 +1,115 @@ +# N32G4FRML-STB 开发板BSP 说明 + +## 简介 + +N32G4FRML-STB 是国民技术推出的一款N32G4FR系列的评估板,该开发板具有丰富的板载资源,开发板外观如下图所示: + +![](./figures/board.png) + + +该开发板常用 **板载资源** 如下: + +- N32G4FRML,主频 144MHz,512KB Flash、144KB SRAM +- 常用外设 + + - LED :3个,D1 (PA8),D2(PB4),D3(PB5) + - 按键:3个,S1(用户按键,PA4),S2(用户按键,PA5),S3(用户按键,PA5) + - General TM * 4、Advanced TM * 2、Basic TM * 2 + - 系统时钟 * 1 + - 看门狗 * 2 + - RTC * 1 + - USART * 3、UART * 4 + - I2C * 4、I2S * 2 + - SPI * 3 + - SDIO * 1 + - CAN2.0B * 2 + - USB2.0 * 1 + - DVP * 1 + - EXMC/SDRAM * 1 + - ADC * 2 + - DAC * 2 +- 调试接口:NS-Link,J-Link + + + +## 外设支持 + +本 BSP 目前对外设的支持情况如下: + +| **片上外设** | **支持情况** | **备注** | +| :----------- | :----------: | :------------------------------- | +| GPIO | 支持 | PA0, PA1... ---> PIN: 0, 1...143 | +| UART | 支持 | UART0 - UART7 | +| I2C | 支持 | I2C1 | +| SPI | 支持 | SPI0 - SPI2 | +| SPI FLASH | 支持 | | +| ADC | 支持 | ADC0 - ADC2 | +| **扩展模块** | **支持情况** | **备注** | +| 暂无 | 暂不支持 | 暂不支持 | + + + +## 使用说明 + +使用说明分为如下两个章节: + +- 快速上手 + + 本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。 + +- 进阶使用 + + 本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。 + +### 快速上手 + +本 BSP 为开发者提供MDK /IAR工程,并且支持 GCC 开发环境。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。 + +#### 硬件连接 + +使用数据线连接开发板到 PC,使用USB转232连接PA9(MCU TX)和PA10(MCU RX),打开电源开关。 + +#### 编译下载 + +双击 project.uvprojx 文件,打开 MDK5 工程,编译并下载程序到开发板。 + +> 工程默认配置使用 NS-Link 仿真器下载程序,在通过 NS-Link 连接开发板的基础上,点击下载按钮即可下载程序到开发板 + +#### 运行结果 + +下载程序成功之后,系统会自动运行,LED 闪烁。 + +连接开发板对应串口到 PC , 在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息: + +```bash + \ | / +- RT - Thread Operating System + / | \ 5.0.0 build Dec 24 2022 22:54:17 + 2006 - 2022 Copyright by RT-Thread team +msh > +``` + +### 进阶使用 + +此 BSP 默认只开启了 GPIO 和 串口0的功能,如果需使用高级功能,需要利用 ENV 工具对BSP 进行配置,步骤如下: + +1. 在 bsp 下打开 env 工具。 + +2. 输入`menuconfig`命令配置工程,配置好之后保存退出。 + +3. 输入`pkgs --update`命令更新软件包。 + +4. 输入`scons --target=mdk4/mdk5`/iar命令重新生成工程。 + +## 注意事项 + +暂无 + +## 联系人信息 + +维护人: + +- [BruceOu](https://github.com/Ouxiaolong/), 邮箱: + + + diff --git a/bsp/n32/n32g4frml-stb/SConscript b/bsp/n32/n32g4frml-stb/SConscript new file mode 100644 index 0000000000..20f7689c53 --- /dev/null +++ b/bsp/n32/n32g4frml-stb/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/n32/n32g4frml-stb/SConstruct b/bsp/n32/n32g4frml-stb/SConstruct new file mode 100644 index 0000000000..ef571d5871 --- /dev/null +++ b/bsp/n32/n32g4frml-stb/SConstruct @@ -0,0 +1,60 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +if rtconfig.PLATFORM == 'iar': + env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map') + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +n32_library = 'N32G4FR_Firmware_Library' +rtconfig.BSP_LIBRARY_TYPE = n32_library + +# include libraries +objs.extend(SConscript(os.path.join(libraries_path_prefix, n32_library, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'n32_drivers', 'SConscript'))) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/n32/n32g4frml-stb/applications/SConscript b/bsp/n32/n32g4frml-stb/applications/SConscript new file mode 100644 index 0000000000..9bb9abae89 --- /dev/null +++ b/bsp/n32/n32g4frml-stb/applications/SConscript @@ -0,0 +1,15 @@ +from building import * +import os + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +list = os.listdir(cwd) +for item in list: + if os.path.isfile(os.path.join(cwd, item, 'SConscript')): + group = group + SConscript(os.path.join(item, 'SConscript')) + +Return('group') diff --git a/bsp/n32/n32g4frml-stb/applications/main.c b/bsp/n32/n32g4frml-stb/applications/main.c new file mode 100644 index 0000000000..b5526c3eda --- /dev/null +++ b/bsp/n32/n32g4frml-stb/applications/main.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-12-19 BruceOu first version + */ + +#include +#include +#include + +/* defined the LED1 pin: PA8 */ +#define LED1_PIN GET_PIN(A, 8) + +int main (void) +{ + /* set LED1 pin mode to output */ + rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT); + + while (1) + { + rt_pin_write(LED1_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED1_PIN, PIN_LOW); + rt_thread_mdelay(500); + } +} diff --git a/bsp/n32/n32g4frml-stb/board/Kconfig b/bsp/n32/n32g4frml-stb/board/Kconfig new file mode 100644 index 0000000000..1b69f9179d --- /dev/null +++ b/bsp/n32/n32g4frml-stb/board/Kconfig @@ -0,0 +1,201 @@ +menu "Hardware Drivers Config" + +config SOC_SERIES_N32G4FR + bool + default y + +config SOC_N32G4FR + bool + select SOC_SERIES_N32G4FR + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +menu "Onboard Peripheral Drivers" + +endmenu + +menu "On-chip Peripheral Drivers" + + config BSP_USING_GPIO + bool "Enable GPIO" + select RT_USING_PIN + default y + + menuconfig BSP_USING_UART + bool "Enable UART" + default y + select RT_USING_SERIAL + if BSP_USING_UART + config BSP_USING_USART1 + bool "Enable USART1" + default y + + config BSP_USING_USART2 + bool "Enable USART2" + default n + + config BSP_USING_USART3 + bool "Enable USART3" + default n + + config BSP_USING_UART4 + bool "Enable UART4" + default n + + config BSP_USING_UART5 + bool "Enable UART5" + default n + + config BSP_USING_UART6 + bool "Enable UART6" + default n + + config BSP_USING_UART7 + bool "Enable UART7" + default n + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI BUS" + default n + select RT_USING_SPI + if BSP_USING_SPI + config BSP_USING_SPI1 + bool "Enable SPI1 BUS" + default n + + config BSP_USING_SPI2 + bool "Enable SPI2 BUS" + default n + + config BSP_USING_SPI3 + bool "Enable SPI3 BUS" + default n + + endif + + menuconfig BSP_USING_I2C1 + bool "Enable I2C1 BUS (software simulation)" + default n + select RT_USING_I2C + select RT_USING_I2C_BITOPS + select RT_USING_PIN + if BSP_USING_I2C1 + config BSP_I2C1_SCL_PIN + int "i2c1 scl pin number" + range 0 111 + default 22 + config BSP_I2C1_SDA_PIN + int "I2C1 sda pin number" + range 0 111 + default 23 + endif + + menuconfig BSP_USING_RTC + bool "Enable RTC" + select RT_USING_RTC + default n + if BSP_USING_RTC + choice + prompt "Select clock source" + default BSP_RTC_USING_LSE + + config BSP_RTC_USING_LSE + bool "RTC USING LSE" + + config BSP_RTC_USING_LSI + bool "RTC USING LSI" + endchoice + endif + + config BSP_USING_WDT + bool "Enable Watchdog Timer" + select RT_USING_WDT + default n + + menuconfig BSP_USING_HWTIMER + bool "Enable hwtimer" + default n + select RT_USING_HWTIMER + if BSP_USING_HWTIMER + config BSP_USING_HWTIMER1 + bool "using hwtimer1" + default n + config BSP_USING_HWTIMER2 + bool "using hwtimer2" + default n + config BSP_USING_HWTIMER3 + bool "using hwtimer3" + default n + config BSP_USING_HWTIMER4 + bool "using hwtimer4" + default n + config BSP_USING_HWTIMER5 + bool "using hwtimer5" + default n + config BSP_USING_HWTIMER6 + bool "using hwtimer6" + default n + config BSP_USING_HWTIMER7 + bool "using hwtimer7" + default n + config BSP_USING_HWTIMER8 + bool "using hwtimer8" + default n + endif + + menuconfig BSP_USING_ADC + bool "Enable ADC" + default n + select RT_USING_ADC + if BSP_USING_ADC + config BSP_USING_ADC1 + bool "using adc1" + default n + config BSP_USING_ADC2 + bool "using adc2" + default n + config BSP_USING_ADC3 + bool "using adc3" + default n + config BSP_USING_ADC4 + bool "using adc4" + default n + endif + + menuconfig BSP_USING_DAC + bool "Enable DAC" + default n + select RT_USING_DAC + if BSP_USING_DAC + config BSP_USING_DAC1 + bool "using dac1" + default n + config BSP_USING_DAC2 + bool "using dac2" + default n + endif + + menuconfig BSP_USING_CAN + bool "Enable CAN" + default n + select RT_USING_CAN + if BSP_USING_CAN + config BSP_USING_CAN1 + bool "using can1" + default n + config BSP_USING_CAN2 + bool "using can2" + default n + endif + + source "../libraries/n32_drivers/Kconfig" + +endmenu + +menu "Board extended module Drivers" + +endmenu + +endmenu diff --git a/bsp/n32/n32g4frml-stb/board/SConscript b/bsp/n32/n32g4frml-stb/board/SConscript new file mode 100644 index 0000000000..e10c8be8bc --- /dev/null +++ b/bsp/n32/n32g4frml-stb/board/SConscript @@ -0,0 +1,28 @@ +import os +import rtconfig +from building import * + +Import('SDK_LIB') + +cwd = GetCurrentDir() + +# add general drivers +src = Split(''' +board.c +''') + +path = [cwd] + +startup_path_prefix = SDK_LIB + +if rtconfig.PLATFORM in ['gcc']: + src += [startup_path_prefix + '/N32G4FR_Firmware_Library/CMSIS/device/startup/startup_n32g4fr_gcc.s'] +elif rtconfig.PLATFORM in ['armcc', 'armclang']: + src += [startup_path_prefix + '/N32G4FR_Firmware_Library/CMSIS/device/startup/startup_n32g4fr.s'] +elif rtconfig.PLATFORM in ['iccarm']: + src += [startup_path_prefix + '/N32G4FR_Firmware_Library/CMSIS/device/startup/startup_n32g4fr_EWARM.s'] + +CPPDEFINES = ['N32G4FR'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/n32/n32g4frml-stb/board/board.c b/bsp/n32/n32g4frml-stb/board/board.c new file mode 100644 index 0000000000..1949c34a73 --- /dev/null +++ b/bsp/n32/n32g4frml-stb/board/board.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-12-19 BruceOu first version + */ + +#include +#include +#include "board.h" + +/** + * @brief Configures Vector Table base location. + */ +void NVIC_Configuration(void) +{ +#ifdef VECT_TAB_RAM + /* Set the Vector Table base location at 0x20000000 */ + NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); +#else /* VECT_TAB_FLASH */ + /* Set the Vector Table base location at 0x08000000 */ + NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); +#endif +} + +/** + * @brief This is the timer interrupt service routine. + */ +void SysTick_Handler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * @brief This function will initial N32G45x board. + */ +void rt_hw_board_init() +{ + /* NVIC Configuration */ + NVIC_Configuration(); + + /* Configure the SysTick */ + SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + + /* Call components board initial (use INIT_BOARD_EXPORT()) */ +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + +#ifdef BSP_USING_SRAM + rt_system_heap_init((void *)EXT_SRAM_BEGIN, (void *)EXT_SRAM_END); +#else + rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); +#endif +} + diff --git a/bsp/n32/n32g4frml-stb/board/board.h b/bsp/n32/n32g4frml-stb/board/board.h new file mode 100644 index 0000000000..0bfe38ec59 --- /dev/null +++ b/bsp/n32/n32g4frml-stb/board/board.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-12-19 BruceOu first version + */ + +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "n32g4fr.h" +#include "drv_gpio.h" + +#define N32_FLASH_START_ADRESS ((uint32_t)0x08000000) +#define N32_FLASH_SIZE (512 * 1024) +#define N32_FLASH_END_ADDRESS ((uint32_t)(N32_FLASH_START_ADRESS + N32_FLASH_SIZE)) + +/* Internal SRAM memory size[Kbytes] <144>, Default: 144*/ +#define N32_SRAM_SIZE (144) +#define N32_SRAM_END (0x20000000 + N32_SRAM_SIZE * 1024) + +void rt_hw_board_init(void); + +#if defined(__ARMCC_VERSION) +extern int Image$$RW_IRAM1$$ZI$$Limit; +#define HEAP_BEGIN ((void *)&Image$$RW_IRAM1$$ZI$$Limit) +#elif __ICCARM__ +#pragma section="CSTACK" +#define HEAP_BEGIN (__segment_end("CSTACK")) +#else +extern int __bss_end; +#define HEAP_BEGIN ((void *)&__bss_end) +#endif + +#define HEAP_END N32_SRAM_END + + + + +#endif /* __BOARD_H__ */ + diff --git a/bsp/n32/n32g4frml-stb/board/linker_scripts/link.icf b/bsp/n32/n32g4frml-stb/board/linker_scripts/link.icf new file mode 100644 index 0000000000..4f961659c1 --- /dev/null +++ b/bsp/n32/n32g4frml-stb/board/linker_scripts/link.icf @@ -0,0 +1,40 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x08000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x0807FFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x20023FFF; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x1500; +define symbol __ICFEDIT_size_heap__ = 0x300; +/**** End of ICF editor section. ###ICF###*/ + +export symbol __ICFEDIT_region_RAM_end__; + +define symbol __region_RAM1_start__ = 0x10000000; +define symbol __region_RAM1_end__ = 0x1000FFFF; + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; +define region RAM1_region = mem:[from __region_RAM1_start__ to __region_RAM1_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +keep { section FSymTab }; +keep { section VSymTab }; +keep { section .rti_fn* }; +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; + +place in ROM_region { readonly }; +place in RAM_region { readwrite, + block CSTACK, block HEAP }; +place in RAM1_region { section .sram }; \ No newline at end of file diff --git a/bsp/n32/n32g4frml-stb/board/linker_scripts/link.lds b/bsp/n32/n32g4frml-stb/board/linker_scripts/link.lds new file mode 100644 index 0000000000..a96bb81398 --- /dev/null +++ b/bsp/n32/n32g4frml-stb/board/linker_scripts/link.lds @@ -0,0 +1,142 @@ +/* + * linker script for N32G4FR with GNU ld + * BruceOu 2022-12-18 + */ + +/* Program Entry, set to mark it as "used" and avoid gc */ +MEMORY +{ + CODE (rx) : ORIGIN = 0x08000000, LENGTH = 512k /* 512KB flash */ + DATA (rw) : ORIGIN = 0x20000000, LENGTH = 144k /* 144KB sram */ +} +ENTRY(Reset_Handler) +_system_stack_size = 0x1500; + +SECTIONS +{ + .text : + { + . = ALIGN(4); + _stext = .; + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + . = ALIGN(4); + _etext = .; + } > CODE = 0 + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + + /* This is used by the startup in order to initialize the .data secion */ + _sidata = .; + } > CODE + __exidx_end = .; + + /* .data section which is used for initialized data */ + + .data : AT (_sidata) + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _sdata = . ; + + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _edata = . ; + } >DATA + + .stack : + { + . = . + _system_stack_size; + . = ALIGN(4); + _estack = .; + } >DATA + + __bss_start = .; + .bss : + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; + + *(.bss) + *(.bss.*) + *(COMMON) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _ebss = . ; + + *(.bss.init) + } > DATA + __bss_end = .; + + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/n32/n32g4frml-stb/board/linker_scripts/link.sct b/bsp/n32/n32g4frml-stb/board/linker_scripts/link.sct new file mode 100644 index 0000000000..5333a7455c --- /dev/null +++ b/bsp/n32/n32g4frml-stb/board/linker_scripts/link.sct @@ -0,0 +1,15 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x08000000 0x00080000 { ; load region size_region + ER_IROM1 0x08000000 0x00080000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x20000000 0x00024000 { ; RW data + .ANY (+RW +ZI) + } +} + diff --git a/bsp/n32/n32g4frml-stb/figures/board.png b/bsp/n32/n32g4frml-stb/figures/board.png new file mode 100644 index 0000000000000000000000000000000000000000..93dbd6e22394a0af5c0dca9b74da0a485d2f975d GIT binary patch literal 1181447 zcmV)NK)1h%P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D|D{PpK~#8Nw7ms< zT*;L#uH7sp?=58MK+ z^^KkF_3fSY9fUH--5%DyXuyNp>$|jVA-#Z?gY;S-~*qKeF zOFQtgcaOjZ(%$71Hnvugj_#}@_@c1`*0;aFE)DQB*dOE_$ghI*4IWxVUf5XPT;JL~ z4u3iL#*Iy|zKbn*oygVgZ0~Gu?jS6|PukhNR(RI$!S?DZ{22IKeo5IZ(p7kw$W?q3 z@FlRiybOSkvckE^)I5*YmDZ<^o1y zwp%ZQW_uIXX53)oo$hxbqo`tT`5{5*j1}I;2_Invj%bM;q2w-BY+Ed_!wpe(x zNOS`wvMv(B8o~xGy-~=!SKJ&Xr5g$_fC<}4kLJo=8et~IwWpjJQ7r& z+$y^W+8q~V4kJcao0I}-^Qd(p&6cFHC24NrRkw&5Yl_0QNbb!x)%47C^pCq2a%}jj zlFklbE}9A3KNEKFTQMGfbUN(NE<;~XwyDe*i99|YacDf^$Tu+&erPs$U!bDFUswf& z3aqcLEzLj7W;!w~F5FsIUY#?)&V^Uy$TT~!$`JLKdeK?-25ibUI&W{Z+*;`gm*UR! zRS5>Ws+?ky?+{E6gk~q2$%b5ZpKX3fuYSZZ-^HozXhs{d!J2HmK`#3eHWc$ss>YgK z>BJ~?Bq;6?l=dXmBeL3^tZ^snZ3$|yxxBrGkzlWG&BScgUtZJNY;|AJrQ0vIUIQaT zx04F4qD8hu?G1wJCP`~U)ZC{SAJOE9*l(>ZL-ARjbV$Qy=_^46c8{{@Z^K0Rk(tm# zdt7~_Y+I25S)30$P#0s{6mnuX>~OdL;VJ(U6Je*}sng;6C!&5CR8qDCWqNya6Dk+{ z%H>4|tki{9?ZPj2=9Ri~8lCt}_r(>60 znQtj_fueGFX`QRDO`!^|QC0ox07Vx)ASi6`>gxpk4ZQw3(FAduXu3%=*^+g3Oaob_ z?Oj|Dc29HK7g`sfhJ&@$MO(5A%0Ac@m*iapQxTy5KB&02UFTSey|mW-Xa~&t7BEj| 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%0D{p9Cfbp=-NPR{AoPe+eVITg1Cf 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�Q`6wM2Q%7d);#&Gh8!uGM*>el}D>gq{by+o*C8yeM} z!}N-#SDBdS#q=jda<5`xE{YeEL+~x7zbt0oER@_TRI0ltZkF+%6j3=%y)PKLCrslD zj^zPS^$4%Oh}GOc>2DP)K#lg4qJD^1-$pCT+b7pe(1ykWan)wO5P_pdxqs9qoeeQ) zkhXhES7q-NMdd;18C`aE^8flLP<gYE(jgy|mN)B)gr#pf-9mbjtVT>p7`j7tXELwLSWw?Mc zepP0;jgy@#Ew3G!THApJzQZt>F0m)p;y&*UJMo2`o#&73-hOJ=7JC7E^RF>CfBY$k zlBtgl{L2A;7{kEP%Tb3%5vQNp+5Obc?x>wzf6T?4E5G;fFYQu~+chMfS_=89JnhMw zPyW*hJG;f=r=y8SRw9ngBpsfOzL+gy7b=F_L_-1GVGnlQYhIl@tIC62?Jlmofsr}E zl1a@T=T}^)JLm524AQQ5{BX4y3e) zF&ZK`)vsvfp8N_oZiTy`-c4BNE~-D6&wQ#8TfVFw;Ev<+>KbvC-kq}@x!Jq^i! z5nc8&mExF2dlOw$B`qJ+YA2P_S(U7xN3TW|R+Qw{Ad9QZiaV&JK^}WjA)Zq3r`5u4 z8E?{{n~*Tug{Ul-dn0nmqE7YF<@LRwbcMR=Sp?2G0WIsAVw-G5cp_h|o?cy>+J#(8 z1z{-O5(IUQPtDBEo2)hQCFGuk`QvtZn@rLkRaqUGfUM!JS0kKYEVSJJ=I*QjFA?QF0 zXmk{(27&SjRs{h100;eJ7#K&}f031as03PCGr_rj$(Vop+s6XM# zN5)LSlR-XTN;sx@^5d?Y$ALe#Lmao8%D!>$_v~5%4vl0!(gwhk`gr^gW7t^2vBjwU zH^&|xPdq!3aDFuONKf3+jl}aKiKkW)&(B4ln2kO;7j zwcX#f{^;D|37_pJxx24WTRyb)mxOi?x-C%D;md3D=2Uy}Ebfdp4|azKuMRjrz^wx~ z^J-jp&D^^Fy*+4YZF6{WDL9Sj6p(U1Fxv&M_8=%z$kHlenNt| zw4@r3YoL&uY2+3@b&&1z{;<@3_{}(b`if)WaFfPjh&m=5fBrWgpGu9nTS*$`hT* z6dcJD974&DV?k=AKaSS}N&%cgYEGlH;N=&1?U8*}eZ&F1005`whWKzIW`mb`D!GbvVVQ>4`tZ? zRFiMt{O@8vN`B3-WR9>vJK!X1c*|>kC2j(-62wP1M2fx!@H(IcUgw|#+5Wxc z#T88|<>OM>h(s_T=JoU00Ao_&gj_r#<~QKc^>}O_lL{?O-@JKyt)pYvERTHWfAehu zQ&xT}D*tkPseKmJo}hN1=&uqDmk5R{1W=tBzQmi(5)G#b+B-<~oj8(x9O`bViqkn4 ziZed;7_V-DEDaOK;&L4_aO3mPUw$Pgk2X_e-v*xg42J2)f~pC4{!*r`W7hp7f2cS z1kiqgQ5?o94q@aVV>^VB9YrgS1BZuJ+$a;D#IOeD)`8>S&tkX!V*p9;CIpYynqPy5 zFduBc6NVvJe84alMbmphtCzF|0PqaJ10-bPMo&o-U=`>9hP{$DgO^`>p#9;j2P;t@ ztP+1Py496k?FPUD)uO?TXLaXQy%Sf)ly|-sm_0>iH&GR=mI2twYjomvc+(o)vjs0R z7@i#IYntW`UH={>95vattXibc%ZRt$UtD_R>iAk#f~+Iw4GP4=0{*y6=zjHl$ZN02 z*KVoaFXl~J5G7}|;t2(BOvV`$awjDMXlBUK@#V(g^t@Kmtuxp=1yO~@>tWef6Oq?4 zDHkxZD`d@AMBN2IGLq>$*>o1K1qIq21onD7_Aya^4yQYTsl11RSB*VgtUH@0zK9Zi zi8EdFRLx@@E`|AYtVDbQsXT*Le1#NWE9IU<^N-;~C(yz(SjlO; z=p0dSo*?)FCHMjlyp$5Y2Z2(ZD3Kj45+2Iqeo??boX-O-czL8yaJYbfq?muWkbA6D zc&tPU4m*QV0h~lCPN9?lAU@ic2#=Q0`es&P6(^Vk|53m*uQm?y;E&s{Fl=jesWJK1 zXwp}M$@Wu;XC@F|{@a*B90#fWOycpG#FJAAUk)Z;9*R3ZnRqOOSD9$)eJ5!hgP>GP zXPLPTX>BSnH({&0kyUj?=GJUWr?I~01HGm|H`p)-i8?0~y<@b70YdX!Y4sqnWwOA~ z&Zz0}XKJ1j%(hu5jw%Y}S;N>yU!pvUZ;cijqlD@}S#`d#K1^KgCTMix*L$<9uk$%> z*{pZK?XjyJxlIp+*5|a^06cHLLTxL{NqGFAz%MYv@7;h!vCw5&o~YWGt=*Yz*q(3Q z-s*$a`*xvu2%DhBjAOM>rheo3@`iPK$;Bict3?hp(oiPh)X`bQ{%6Txct-?%q2M_yqz z|MZsy&x@MR70XYcjh|t)hY5z$NY%AGzFQLGdKBqwk^D2X@(4V_d`cpEA(P2fb$vEo)|QMb%G6h}6XuR#J+ z*Rujqptw0h(FA;KB18LD(DFgr`5+)8IHl-$461QxDJ%>BA)BhH>89`$9n(8m7pC8PvauQXh3#%75patNq*EcqywKb!9!OUSs_+mo?SY=7j zPUp-(d4IXS->e_98i#C^L$-=>n`EL^G-spijx<2Sb^To0gpA*1R6!d(k}|}qTr*cE zpVKj*h4vl=!-9=AGt)Y`gjNx5P)mkpS6`NjFBA0_DVCdP*^OkBS8R#Y);_cZQS`kP z!>#vX)OJ70hSpd2_NU&0ZK`7eRm^PcgoJuXZ|Q2S?HOzDL*^AvtnZA@tgZ58N{ab-9WsdYaPnfkM^%ZR|_S_u+pn#lDTc@ z8cuKqDH>i}fwp=+PAdBk0OV>5Q7534iGPD(yX}b%bJ54f;?8eG{;b&T_`M(5bwz$z zlXwP-{{nILztcY)Uyk`Q^|l=pcD^C`)=KEPbmxDp2z=!618oe=k9Gp*G&fwaw>|>=_0HBd zw6hJZtfFJ0s?h1pr2H;Yeh;71#bR|*aDxndqlmk=F;GP-nb2z&s-)98CbTj+*TCzP z7Pg6tyTk=n3c^N;nHw0miILc271t7px1zE43F<3!;}NXA8b@J2NZrWTf>KSn_#g8QNQfrXgqof)h596OS&ZU9O2ewithYEdD}A#0e<*%uvV| z3yIf9W9$c`j(lWTq^L5@I_S&mn1^+`+`&r4}x-@$CTblr|LRquqspA@Z`|UYWwICM{7;v zsd0J>x1mj6U!SOgHIZHl;8{tav~=cI#BePw)0;H2kzuQ_v@}oESk|f)wD_RVXAjXy z!O&jc_I!K4McJknbV@jlY*rnO(nKk0rWSY6iyCQ!dIGAIiD_b%PPSJEBSDH`p-%C!RB$s$>yWgcHS z-!=ukr&st02ScQTy!wU8iCtG(7t1(&=zU>eKG``gQ`fQRnS&c$f}FC^D2}06J9xZ+ zcMT~XS%a>Wicb{_+a_nB_4%oovr{qW$0N^xw(0dhGN1nM{*X_%a;{WIo+~ghM$DUn?|7_ygS<;3vr`X)5D3=+NBjh(H9xk`hvehx|$>53GPre$Gh6#A!6 ztnF=3{W5f>5O)$yJzJ(bm0jL3wHHFIjb-Z+IGPx?DvGIiM^X5ZO&_FnZSBzMOzzoy zN||LcL^bR#@A8!QcnLe)C2g+4L2$9X=Jv9Lb^jQV>PH}&C#O0W_PRILR%T%3=jA16 zegzuchK4txiShaCWpI7aJii33bd5!v9F6(uXw;>d(9_GAw=+ELv!5L8OnoBB_VfO0 zJNElajd@&R#eRe#4f3=plFXAMoteRF|QR6ZM#qrI`&M{?GlWk-nM^mF3oe7eZzg5(6>zZRY zI(G9+Ms+`;d@#;9h%imZYbWD0O986h6l>dsM{iu*1Ks>GmD;wj$n25n<=j%#_`<5( zWUHKB|G-r^$!kEqAI!77kv2OE;oBUry4yaz0G_g|oS9}vYK0HEvbVNtR<9otF|z&N zK6>Ed_|#cNB2<)?cF@UVQsIRt|YQqCKeu%;#Q zK@I7-bd^(iH5P_8`r#5*5Nx$?;OQbgXT@kNJFatE~0o?t#n(w!#iZeVowSoLL+ z`Wnf6xs+q~=ZwCwT|_!EBE9T!Cc!PaI47qpDxI8d8NL>|btT#4$JKD#Ce-b-+U99a z*VI!A?>0_+qfmUa&^9p(jc-5$V=J?ZyJJ&pCQIWZ_!gJ;mw2V9a`kM1>S!4~w|YEH zH;|!f4Aiv0)(-_}`*TEX(eerxK|kNn_cxLG?{Um`2{{C`NMmVKX`1WXM;0~#kEMq& zO#2f4h+(Yv+;^3KVaFXtjJ%|(MCcycP{G&rXq!vKeUQJlpv_evkm%-S^>i%`SqQ9PzqIU8{f?1*R+lI7D~ zqIm+_*dHutiB$C^$UBuCv++Ee7rVw^(0tD){#9_&v%p-gwk19rn_R*`(-b_ZZG0IT zSzJ%WsKa=s1ZqWq*bM7$@f)1rTOQSbTL&b2%&2l?*=SLZnp@(VZOnu$Vt0<_`(E0R24H0G|!e#iW9lqY^<6pSh%!*AX*rUp}4j z`boc1F{KoJcKHRDtvnf-eJ-@T74X^KSwd0A?eSNbuS~ZWR|687Lux)aWux= zNUYtDnCmOE5J>#s8Soq1OM?WYwW=Sv_AhRC z&Mh}jEp<=Kbxf^vEUtxvtX$a@BCn5B4~8gvf)(9DgVq%&)@n+r9BJC z0t^dID)dXjL}pUMQz>Ct^x&+rv2W!(8|^2P6aSeO65j+cY@6 zYF>g~QemZLccO|Svw-4p#j0?=l zG?!$WXDZVpnd+3zdR9Pj&F1-KC|x5f?f#hYDzerqQvXjsSKn|mJW9meO-9{|!9R{8 zJ&7mXM-c8LAnzvN?ndJtMxpOV7vGE|KufDMii$#4>C`oGDP)eU@oh-q!(im~;Ns5F z?Z+Q5cl=Wrn!&`{**N`Zv|%*dI1;5F2~rQfQ8d5ePtYZnUj&zVmoP4;XY-~P;wh5W zekhhGr&*?cUdsP}i0lhU4#>xG<1-8QPlvjtl!W zhW(#x2O|*ocDHt+cu{q_b?~jUcV>GpRM6JH4RwyMG!C!l@XT!xRH`uMR`rxw>f`Aa zkkS%rS{;j3fK>_d#zhDUC#hZ#jlSFlr{Ju>*o>DS(hTK2k(qcT+uSg?+OYxwCs*Dx zJ_|uDT^%`iVKJ5whZYC2D_wcDF9h%^!!LMMFwb~3&)Jm#&sa8isfz;{R9Gpz(xZfD z&|BJN+##)WP9xsX2Dbe$jL%E?SBnKVlQ5nc^art6hiK%}9Oi=z>VsUyi)_}*42DZK z`z=!LT`YG>V;|sUI*jKj3;@SeCTO1}(?RE666J0(j5|r>TL{X%WbDp7G`a=7iOK69 zS_aO0bPu|hRA8Tqeh`o97@d9`j(Qf7kE|ZU)sBl>#{HQU@0Ft=s%~-PEUK>4gWJy4 z_592?^Iaa{MJmb#rAZg-&26I<1EcK=&}XIUpAuAGp(P_b(DhQm$x`~{;ts5f@?CcP zHn!gh!;-}H#Z{A`^4_)er8HSxnX;-#*;1sf&r{cA8X8c>rXq8zrgJb>(3q@kORXQx zvdt!yPsCJAMO)`$4AYUi;UJp%g#C-im^{y*Y-?5T@+vev56v$^bF0w!CN#4FwJks+ zb6Z1GP!UEPS-^=caR)jloX{cr}ikDuAbK+rjd50MBUqQ$kqQyF~MI zyxOgdAB>UWOdZ;`sqWsX_SPY^y5TKW1iZ_me8#O*;+L;u@B8LP;Y5xZ$cH%$w_L7$ zbcsU(s%d2FXfek=Pkal3@=9eqh{iumro2caJW40u&tg2tVF5hJU_MW0zQ|<5$l|&e zN}O{Apz|z?1MoDH{SnWzxd4ut9H(sF^K{mWOwQ9(`ipEFv<1y=Z4A$EPt9zPE$oae zZjR5b_0B;plY2{RtB#qp4@vlUS=>N*Uy!`#gR1MTtj$;2>n<96A+%mdlQLw@|2wes zMGnTjsO(h^<|SV8rpW4m(>^IydlEF>GbtqoZ$*dht;M&A3qq(-xIQ?*xaWu^`R%mEX)c3@wM}j5o zw}P@fQ%j#DP%I5&Z;}gXTmzLNT3Unzf~wKMrN#xwgIAX-FeNBz-?FT)irB$9R74p& z6v+pdGRXR0@L@dXR>7VOv|M=YbU?L()dm0#G_apj%I^}5Pl>v|g*{tsqe!SU^)5Wb z$sF;Dt6>F?5qKx0^Z`zF1Fyb~(ci?W90>L(|L9(k9f}F|9H;#UuGQV(^z^@C}30*CR`Bhh<@FV1i;$R@u(1YxAVnh^)i^?4KK0Ms`a?S5HAkbJzSdRN1~Xu@0TimYqZ^ z?F%G5(|dqn$IIxG%e(M6{r|5sY=4}7oUkUleArje1@?pp+X^iGal)1Y!(bfGmLjUf zR}Mvp8bErRAgE(DPv$qwr`skI4WlWB(F}cGoW46+)}3PPe-xbjC_D|s3w7&A5RMv! z7DQ!Xk}^=KxunzrN@7|GqEvvF+2Yl3g6|@1_Tbq(3YdXe)P!Pgc&YdUy~>4E^@I=m zFgR9nzQ(~y76&8)$r)hS6NU{iEGP_-9vPG98yp^=eJ?QO83N;sRo>lSH}Do7UJT+E z$#5=Le7ab24J*BufbvSGKZ-;;B@C}@MwBu<6fMcn6fTL;nBdNH<$r#WcNyY+vk%R#_g`l5LM9<9azRoUnPNBG_ zP`xr(Z}Np6simr`*-OUdmyn zwEk1y>=+!GU*DtX+0l1Rcegbe`xe>;hubHhrWvSf4q6`FyHz4RiDFJH?R@=Q^0&JE zP8b#;vlZ43hl@rwASjw&BWoNI+j{AhL&frDaq~oks5VH_#IUyeb8E`V2huGwz%K#c*eCo=hzN-27)HQb7pyc z?>bRrnVN@iMHqBW8Y(e1$T#d>aL!|r@(#uHfMU8s)H>h|Ut#rE2>Sad`Ta!f+ce6v z2+XrY%Bw7@XDaqp4&{0r;YtGSD+KLAD&u@A{cJMzd>Z3S8vR@f?Eq(zC}&d`AZa_5 zLO;N{4ED)n8r-JP4{#!xb}Z#voKB>lPQ*@3?#)2Z@-j3&yi`B9uJ4+?6<2yZiFpKp zRQ3;j8HWAxT{6-(lxgTsmo`Nh`hqn>aoV9w{fMv3>Z%yv82f%6n4U=Ddm_q6Y=Nb! zqoK1;+dMtA0iDeeA47_+BZb{dTlS@rGf3vt+&V0A^xNKkCkzXh=s_+YBpg|SAOydq zXA8=t8Hd)O)+uNdzJJjez;9!lyA$}8-HQ;eYWx+|8lvt`Qg<~@Z-p|9&O}RuwDWmD zs!wp_i`NL7zQrF!D^)iK61C!i)lOJ33BvO=A^FVc99eiCD=3E(S|<6xt^i5c3vR8m zpuvMv>7K*?kVcOy!da`(=}yooMMbj<5a(ya*e z%{aV6Jl;M5e;I+lmQ1{Yz+XzlT}1o}E+r8GE+Pn*lSyAC;z0+r7ZPw66YvMP5QqIT z9>)1N4A_4*jsf~}3lPfEay<-NIkD@TNmjKk-HS$^jia4ULe)*pUJgcH@=YtMoX9L6 z$=3Dz%iH~xUH-C;cv)Ad!sa9DmFWBbDKI$#N4pW8do!QzoGU8Ox1_84kfydPx%_K| z^v5~0(Pij*ne=oS12Amon_CRO#qD>(urNtOQN@U_uw?;)niipn<<*JBjfvI0$$4mG zc4v4B>Y0TmHla9fU9PSRxc5YDf267}Sk(s{n4h@IN7VXNc=1iwz@X6N*M6BIu`MGH zlbDW4F6D+%wQsqG7`8QnrVij%M56eJBHsIKo>#u)O^(Q~Oc=iaC~bEx zk@4$rOveL&g5YTy{!s@0c^drkSqA<|8WsS=K7i*L#HSgATbUH6G~&|2o`@wa!-~bK zn((yJ61L7erR-H&k#}--@50`lh?3hM5P637INL;mVK~G*9;u&*H;lbCEIX@)pDzQ)P_FC2;C?|NoKc zM@y>FRU>|)R^Z`dB+dPRXA4Ue<4ZBTI)$X(EwDyfX( zTRf3M-#m_YCjWJw_!81 zadY39J!Zprz_Nj~%&nB;jbONC@tumK&&U-Z_j1gpzRMwbL}OpXQ{U&XT1J-p=Am4Y zczy?pDxtqg$9SboLSmi-GoAti`si98(JrN=OK3l?yKOE zuY$_@CLxc=lKa6q`4yAAw)w7k$cI(#qaKXX_L^EpXpLR2{03=7|L5;B-(v zOH#zVy4GIHU{BXNbRkE02rarn^4u0fufG7Z75gXSfnV=SJf5DYA~u6vZ4~DZ74Hzs+#(uxRwHaPj3BG ze(ijUZ7Q*RHqkVeY95c$kA#aGPv7;7j?Z#^pHp4eJG-zBYfi1KOl>Yr&n$u{Il2jT zY(pc9TZtl@2e-zJZF^NJ@y%s>WpKQ6Mcz4l-y-2#cx`jrGiI!SM}GhS|MW>jK~&un zPL(^u;+Dhski!lv;`~mkHx2zJw%98Q6_7#=&7}Dv(19tqpfv2eWP(Fz=A&%%!>lqdz_|>R zZz}Fp4&5Q2c`cu9U&?rrj0Sb_^^n|;xDk+hEim^=NS;GTfqhWk)u7xffjQTL^Xxsb*SCT_h@;zvzai0$G_NzW@V{QO( zaVF|hcro+XBcrj$zCT9dJ|B%fJ(qN-CHX~^sDj$C5G3v#-Gc)7mYKQjWeBqL3>0yV zfE>|6bAYH$($E*fHnW@Ni|fZzER!+1u_VJNs5cW;-5{BW(sa2-<-H4ub@IuqtsaQW zM6wjt3S%`%AgpT{Fn07+%x}7L%xOGzjI8Rlu+foQ|B_eZA*yyM;eW{I`egInbA@lR zc!9;@cMOXox6+AI??|bBNwYe!8r*SOzf$gpLiRhF1(5FmUqGP0vAEuYrmkIv!tzO8 zaoG4IEQ=@-Gh`aRvbDCSzkO(`e|D;WzNe|TLSMtBC`+*`??L| zF~^{(rmq?G>kQk2rsCn}od;9oK0eX>J~((rIT>@jE5$xsY|XD62;vW}Kv0mdEz30G z$7xK^jO3c9GIhQF(!O`nAz{s69KW1b-C0&SnOZ&`s~=6)j})p~Qnl@&s@^Dhr+Z|M zr+>J!Z%%XDWNLaDjUvPoM95-tK@pM2(__WPR7o{SVNR67KI~w8m@C8fl2z%!ul6kE z2j=qt!@P2YUfI0xJkIbYR6n(w$2X$uh65RfGE;}Jy34`Qe1b~dNn1Z-u(B{P;a$*o!Q3?6rM=^-p*rfFESkNg*NG*s$6vQQf zAKiZ)ek`W!1cux^ymKoV`68_J7EX7iMB-S$e*z+JKJ!wE_)C)RFh+Zns5ybP9K%|V z5Hv^enqzo)+Rq`h;y4kWHS`5i{&|_|RGFz|X3i&#{<=gKpHcEIy5xNVE+qk*-G?3 zZ$$p{+`bmk6g*Y-#B%g6mf@vbk4(m%20WRI`5gRoG5WKaxXISZu<>H-9voXXB1P6ejCA7LJkHIION zKUCEpEFbijbib4KAoRnJeIj4K4|aZ^ZK~*wOGC2d6{E9IK|Vg0s)-|NG87GOxNQiA zIZ9gX%Byh_!qZ7Sg!Q111pdrfSnDRJcv;AKm(BFfeD%aB^j%PFKvZ@f(KV*nDFO2+o!Znt4=wM7eTb~HwFr#8vZ_(M zzN4;lwxoINI0dHH0ghl*U*Od+_U8zlL@UoAjeQF%^IOpT*3Q5NR6n}Bw*ie0?uKWx zp2ZNGre^Hlqp!VB$JEayn8)G_eIe@JK+Ry7y6=Oc!&B1qMmEOR+CB-$Ph&`3Gf=sF zix-vzJfgU@9mmwF8W(?w<=A7S9c$2)BK~P4b9{bl3*S>=XQ1%?Cd(DzpD5B?3$h3K*FWrjQdULPl-?ez9qwPD&m)i?Cj=p?^VTIn@u}C z6a5RAVc+C)zn1Cm4klh)^#A*un}6RHbv*ycPZ|SmHD^8TeSNGk^IB`d>v{B(+yB|l z^)Kw4?Cjb~g3L*;+e44Gm$-~XU#m|%-xvI|h1gRSi7#X1^_j-bVD1R;Vd27>{&gso z*4n)dfwZh=a1X8O3=;LSY(t5{>W(Fd+%W4-tqNB3=4dLpt5&ujKe#lG>4 zck)dyuN_FuK|t&e4y1GtsWoN7mSSXlLYo~>sIvVwG2 zSmVU5ddx0&6#qB1tN~hP&GWT1{vCB)6slC zhT#NJ{W)HFjGzU6>u{OuC{_#bd6@#>1loA6#N55Mi|<~)MpP9vk9tZf@U64Tj#Zxo z@{{+)LuWL*lhDgi~Xo+w=coXMOXNiTE?^ z>5d(-H)moG`yaJy^F7uSd3z@6)Kb*X8&jW#3oV5;{jthLke=5~LjQb3{g;2LvQV{!ZRk`9#&P2;= zPK_g4{f1TbHkWCs=!%ZbE<>|+_BNsIWgqXrAOtotoe_|V*BD!jipm)znyi1B>l*d?S z1N5Uo+M!7OSg2vtTQmAv)Adz`gf6cB`&ra?@%7!I| z!9cFB3*^qzbX(5RoqzCOC6{lFJx*GP6gSxYs6pBae4geJhX0P;9+XRe9UOJ(xmtjL<}-H36+vc%+3J>q7~+%Qj$S@xLLavFFSI4m(J zvazylqH_StRKAQyxug)>5%?#OrH|6dx3P-zIQdzc=?uXL$aJul3BUopPU5vk%H$uz z<)KpPA&mSi#=NkvFzTF6o8N3ZC)wRq4 zr|72dj+3=^whdym4Nl5YG=Jmw|EDpeNc{6#lXjoT^Et!1#(w|g5`n3%p=aiLj_GCr zqh}McFX4XsQ$DfZL3=wp-nntVS9|MwUcC#)%|?F*LnE^kAns@hUZJGP<~ZEPzt zTFO-F0&QKc!J==e4rVrHnkUfBL&Y5f2~y~^=Wq;nJx>WmsW;;EU00rl`Guu8`6e{f z_s>mjEG(|gEN?F_FORLPPHe%$D?su-Kff8xv%2wX9XU1b+(wkXYq-0kqGd!!C^M4D zS~N@vd47n?R9E_t<*)d4iCA9$(DMBF65v|b@XCiAQdlZsa&%>=XKcJ{5D*1m zpJxa{b~?2ni;|bSPq-xDr8vl9upe*^FpOK8QJM(&mx@YDJ75?%AjU65A=N4QJS0`< z7GLTdU-B}c%p;ZPl7MxLE_2Lc-bE{c>pDZw1DwX|j-ix*Y5?#eIXEpy^N;K=4gk;0 zCh5+h&6^N3y9`Y)KttObLha~Zk>ah4qe`5G%?N=xQUcEr2MlwhR+1{ZwpQl@ z(ojkwRzoN0s01Ae&nV1uc6y5yR=Q3s}yjeAhyzPXWynfq9=r4$sBww6z+E zQ72X+Q(?xGr2x-_Am(NkC&du6vjDvSfr=9nu^B1!!UB-mi|}Q<()`lIgfc|hz7I<| zaDINSUU?a11<6@By6jaV>Qxf@RSMoU0p${pbWS3=Cz0+1=ig7IKFDT1%A!Baqyaq0 zpg!EkW3VTK`XHThfZMsuhsmg(p$(85&8@)0dJA|eXlA{>X;@t|b{j$J?H#=nNxTzB z$*h^ku=OTLYlEb%0a`fIM~Lb^a82%lcDAynDD7Ex-hij2Z$i;hTT#_m zfS`MLXCqwHk!9)$X4PbSzOx}%dJ*-&7*CTN!H<5(`cfqTii63 zp==G+4E(>;{RLnhNq+7P>n1mNlWcO6+|V1&Cc6VW%wV>_0^70-l5C+Z%eG`mwwRe2 zj}9|4GlQ6!nVGTQYMmLcXLs`^lk9%q-Jai+>$LjxX?Xe%-PKhQysqdHf=@`ScX)1l z*K}b?ZCYMsZZV>`8dqF{t;cclYe|_*a|KtQBx!|nNp715Qd_SdH48*YoTSTWlJKQ0 zJXJ{Lv#ER>ONOwHd9&MYvm0(v&w38ar#>yF0Rt9MMvX2cvRMi`o&}Z%@&Y0Q3aiV> z!W89EYf7<&1;97~0ip8p38jTVVZc$=WG3_h4)B8x+Y`XQn1&O&~{uBQLk`LK!Q1r$@n{| zb>maJVUZ=?ahQ;oxxvx-z7f?v(PdBLt9)XMhWf{@J+E|sUQ%P5%2f?#sm7vJ!%^xH zkWnT`2BXAn(b`$Is^dqG3+ouNR2)B<*<8w&Rf}7Zd<#a|QmyT;Gj_3>#(FnTE>-bA zsHIG;?41o?V3)!#ZThal{yP)cGI--oc29xAEM*NN(VVG0xNSwFrhiUi8|JsoRV%ui zM>aBew&#L2Nke};%UW+3%2ZFK7^lIN2hz!x;-OG}-y>0fyu2qMCf7GG%J)fbL(_P2 zPBn(EoL)ZY8(*-sjdk^`79enG)s%{QO$Le{R?ZA9V?Qlph7~a8)}Z13x#(hYcrImW z7i#U9c~L}oR!V+SN(e0_gp?8Pmtdb%F~UozFUpxAIpp9R`io*3jV0sKg}7=ox}c~& zH@_|$78$Cb0GXc;gas4^02->zg!2Fq9tl!QdSwo!G#6KxSDlt!o(}s^0I*@%sl`kT zxwMY@I0y4IAOE-z|ELK6qyQg~g9yw+-_NYSms00dNc2GSKPB+qB}+cUOFqLZ0G|_- z@8jg};gs*=Re�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 z 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 o`&An>Z;}^T+Qhs&Pkf&I8U3& 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