From 97ce760d688edf78d1c0b3a80e01b290ed5110d5 Mon Sep 17 00:00:00 2001 From: NationsHuanghanbin Date: Wed, 13 Jul 2022 19:56:14 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A6=96=E6=AC=A1=E6=B7=BB=E5=8A=A0n32=20bsp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/n32/libraries/Kconfig | 17 + .../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/n32g45x.h | 9049 +++++++++++++++++ .../CMSIS/device/n32g45x_conf.h | 88 + .../CMSIS/device/n32g45x_flash.ld | 182 + .../CMSIS/device/startup/startup_n32g45x.s | 432 + .../device/startup/startup_n32g45x_EWARM.s | 642 ++ .../device/startup/startup_n32g45x_gcc.s | 506 + .../CMSIS/device/system_n32g45x.c | 421 + .../CMSIS/device/system_n32g45x.h | 59 + .../N32G45x_Firmware_Library/SConscript | 68 + .../n32g45x_algo_lib/inc/n32g45x_aes.h | 126 + .../inc/n32g45x_algo_common.h | 154 + .../n32g45x_algo_lib/inc/n32g45x_des.h | 121 + .../n32g45x_algo_lib/inc/n32g45x_hash.h | 218 + .../n32g45x_algo_lib/inc/n32g45x_rng.h | 93 + .../n32g45x_std_periph_driver/inc/misc.h | 229 + .../inc/n32g45x_adc.h | 660 ++ .../inc/n32g45x_bkp.h | 182 + .../inc/n32g45x_can.h | 671 ++ .../inc/n32g45x_comp.h | 385 + .../inc/n32g45x_crc.h | 105 + .../inc/n32g45x_dac.h | 307 + .../inc/n32g45x_dbg.h | 124 + .../inc/n32g45x_dma.h | 569 ++ .../inc/n32g45x_dvp.h | 602 ++ .../inc/n32g45x_eth.h | 1608 +++ .../inc/n32g45x_exti.h | 206 + .../inc/n32g45x_flash.h | 375 + .../inc/n32g45x_gpio.h | 463 + .../inc/n32g45x_i2c.h | 672 ++ .../inc/n32g45x_iwdg.h | 145 + .../inc/n32g45x_opamp.h | 213 + .../inc/n32g45x_pwr.h | 179 + .../inc/n32g45x_qspi.h | 333 + .../inc/n32g45x_rcc.h | 708 ++ .../inc/n32g45x_rtc.h | 662 ++ .../inc/n32g45x_sdio.h | 494 + .../inc/n32g45x_spi.h | 471 + .../inc/n32g45x_tim.h | 1114 ++ .../inc/n32g45x_tsc.h | 576 ++ .../inc/n32g45x_usart.h | 398 + .../inc/n32g45x_wwdg.h | 122 + .../inc/n32xx_tsc_alg_api.h | 302 + .../n32g45x_std_periph_driver/src/misc.c | 229 + .../src/n32g45x_adc.c | 1495 +++ .../src/n32g45x_bkp.c | 252 + .../src/n32g45x_can.c | 1478 +++ .../src/n32g45x_comp.c | 297 + .../src/n32g45x_crc.c | 228 + .../src/n32g45x_dac.c | 425 + .../src/n32g45x_dbg.c | 263 + .../src/n32g45x_dma.c | 888 ++ .../src/n32g45x_dvp.c | 166 + .../src/n32g45x_eth.c | 3100 ++++++ .../src/n32g45x_exti.c | 286 + .../src/n32g45x_flash.c | 1123 ++ .../src/n32g45x_gpio.c | 870 ++ .../src/n32g45x_i2c.c | 1324 +++ .../src/n32g45x_iwdg.c | 193 + .../src/n32g45x_opamp.c | 201 + .../src/n32g45x_pwr.c | 399 + .../src/n32g45x_qspi.c | 612 ++ .../src/n32g45x_rcc.c | 1364 +++ .../src/n32g45x_rtc.c | 2007 ++++ .../src/n32g45x_sdio.c | 789 ++ .../src/n32g45x_spi.c | 862 ++ .../src/n32g45x_tim.c | 3307 ++++++ .../src/n32g45x_tsc.c | 500 + .../src/n32g45x_usart.c | 974 ++ .../src/n32g45x_wwdg.c | 223 + .../n32g45x_usbfs_driver/inc/usb_core.h | 264 + .../n32g45x_usbfs_driver/inc/usb_def.h | 98 + .../n32g45x_usbfs_driver/inc/usb_init.h | 71 + .../n32g45x_usbfs_driver/inc/usb_int.h | 50 + .../n32g45x_usbfs_driver/inc/usb_lib.h | 47 + .../n32g45x_usbfs_driver/inc/usb_mem.h | 52 + .../n32g45x_usbfs_driver/inc/usb_regs.h | 715 ++ .../n32g45x_usbfs_driver/inc/usb_sil.h | 53 + .../n32g45x_usbfs_driver/inc/usb_type.h | 54 + .../n32g45x_usbfs_driver/src/usb_core.c | 950 ++ .../n32g45x_usbfs_driver/src/usb_init.c | 69 + .../n32g45x_usbfs_driver/src/usb_int.c | 179 + .../n32g45x_usbfs_driver/src/usb_mem.c | 81 + .../n32g45x_usbfs_driver/src/usb_regs.c | 598 ++ .../n32g45x_usbfs_driver/src/usb_sil.c | 83 + bsp/n32/libraries/n32_drivers/Kconfig | 6 + bsp/n32/libraries/n32_drivers/SConscript | 53 + bsp/n32/libraries/n32_drivers/drv_adc.c | 188 + bsp/n32/libraries/n32_drivers/drv_adc.h | 59 + bsp/n32/libraries/n32_drivers/drv_can.c | 699 ++ bsp/n32/libraries/n32_drivers/drv_can.h | 115 + bsp/n32/libraries/n32_drivers/drv_dac.c | 180 + bsp/n32/libraries/n32_drivers/drv_dac.h | 59 + bsp/n32/libraries/n32_drivers/drv_gpio.c | 713 ++ bsp/n32/libraries/n32_drivers/drv_gpio.h | 73 + bsp/n32/libraries/n32_drivers/drv_hwtimer.c | 583 ++ bsp/n32/libraries/n32_drivers/drv_hwtimer.h | 60 + bsp/n32/libraries/n32_drivers/drv_i2c.c | 485 + bsp/n32/libraries/n32_drivers/drv_i2c.h | 49 + bsp/n32/libraries/n32_drivers/drv_rtc.c | 231 + bsp/n32/libraries/n32_drivers/drv_spi.c | 339 + bsp/n32/libraries/n32_drivers/drv_spi.h | 87 + bsp/n32/libraries/n32_drivers/drv_usart.c | 502 + bsp/n32/libraries/n32_drivers/drv_usart.h | 45 + bsp/n32/libraries/n32_drivers/drv_wdt.c | 197 + bsp/n32/libraries/n32_drivers/drv_wdt.h | 20 + bsp/n32/n32g45xvl-stb/.config | 701 ++ bsp/n32/n32g45xvl-stb/Kconfig | 21 + bsp/n32/n32g45xvl-stb/README.md | 124 + .../RTE/_rt-thread/RTE_Components.h | 21 + bsp/n32/n32g45xvl-stb/SConscript | 15 + bsp/n32/n32g45xvl-stb/SConstruct | 60 + bsp/n32/n32g45xvl-stb/applications/SConscript | 11 + bsp/n32/n32g45xvl-stb/applications/main.c | 30 + bsp/n32/n32g45xvl-stb/board/Kconfig | 190 + bsp/n32/n32g45xvl-stb/board/SConscript | 28 + bsp/n32/n32g45xvl-stb/board/board.c | 95 + bsp/n32/n32g45xvl-stb/board/board.h | 68 + .../board/linker_scripts/link.icf | 40 + .../board/linker_scripts/link.lds | 142 + .../board/linker_scripts/link.sct | 15 + bsp/n32/n32g45xvl-stb/figures/board.jpg | Bin 0 -> 1060611 bytes bsp/n32/n32g45xvl-stb/project.ewd | 2974 ++++++ bsp/n32/n32g45xvl-stb/project.ewp | 2418 +++++ bsp/n32/n32g45xvl-stb/project.eww | 10 + bsp/n32/n32g45xvl-stb/project.uvoptx | 1077 ++ bsp/n32/n32g45xvl-stb/project.uvprojx | 798 ++ bsp/n32/n32g45xvl-stb/rtconfig.h | 208 + bsp/n32/n32g45xvl-stb/rtconfig.py | 150 + bsp/n32/n32g45xvl-stb/settings/project.crun | 13 + bsp/n32/n32g45xvl-stb/settings/project.dbgdt | 4 + bsp/n32/n32g45xvl-stb/settings/project.dnx | 104 + .../settings/project.rt-thread.cspy.bat | 40 + .../settings/project.rt-thread.cspy.ps1 | 31 + .../settings/project.rt-thread.driver.xcl | 41 + .../settings/project.rt-thread.general.xcl | 15 + bsp/n32/n32g45xvl-stb/settings/project.wsdt | 385 + bsp/n32/n32g45xvl-stb/settings/template.crun | 13 + bsp/n32/n32g45xvl-stb/settings/template.dbgdt | 4 + bsp/n32/n32g45xvl-stb/settings/template.dnx | 58 + .../settings/template.rt-thread.cspy.bat | 40 + .../settings/template.rt-thread.cspy.ps1 | 31 + .../settings/template.rt-thread.driver.xcl | 19 + .../settings/template.rt-thread.general.xcl | 13 + bsp/n32/n32g45xvl-stb/settings/template.wsdt | 400 + bsp/n32/n32g45xvl-stb/template.ewp | 2114 ++++ bsp/n32/n32g45xvl-stb/template.eww | 10 + bsp/n32/n32g45xvl-stb/template.uvoptx | 185 + bsp/n32/n32g45xvl-stb/template.uvprojx | 413 + bsp/n32/tools/sdk_dist.py | 37 + 161 files changed, 85981 insertions(+) create mode 100644 bsp/n32/libraries/Kconfig create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/arm_common_tables.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/arm_const_structs.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/arm_math.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/cmsis_armcc.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/cmsis_armclang.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/cmsis_compiler.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/cmsis_gcc.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/cmsis_iccarm.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/cmsis_version.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/core_cm4.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/mpu_armv7.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/n32g45x.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/n32g45x_conf.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/n32g45x_flash.ld create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/startup/startup_n32g45x.s create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/startup/startup_n32g45x_EWARM.s create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/startup/startup_n32g45x_gcc.s create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/system_n32g45x.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/system_n32g45x.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/SConscript create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_aes.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_algo_common.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_des.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_hash.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_rng.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/misc.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_adc.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_bkp.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_can.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_comp.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_crc.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_dac.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_dbg.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_dma.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_dvp.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_eth.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_exti.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_flash.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_gpio.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_i2c.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_iwdg.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_opamp.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_pwr.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_qspi.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_rcc.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_rtc.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_sdio.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_spi.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_tim.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_tsc.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_usart.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_wwdg.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32xx_tsc_alg_api.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/misc.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_adc.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_bkp.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_can.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_comp.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_crc.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_dac.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_dbg.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_dma.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_dvp.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_eth.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_exti.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_flash.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_gpio.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_i2c.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_iwdg.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_opamp.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_pwr.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_qspi.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_rcc.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_rtc.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_sdio.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_spi.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_tim.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_tsc.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_usart.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_wwdg.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_core.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_def.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_init.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_int.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_lib.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_mem.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_regs.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_sil.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_type.h create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_core.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_init.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_int.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_mem.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_regs.c create mode 100644 bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_sil.c create mode 100644 bsp/n32/libraries/n32_drivers/Kconfig create mode 100644 bsp/n32/libraries/n32_drivers/SConscript create mode 100644 bsp/n32/libraries/n32_drivers/drv_adc.c create mode 100644 bsp/n32/libraries/n32_drivers/drv_adc.h create mode 100644 bsp/n32/libraries/n32_drivers/drv_can.c create mode 100644 bsp/n32/libraries/n32_drivers/drv_can.h create mode 100644 bsp/n32/libraries/n32_drivers/drv_dac.c create mode 100644 bsp/n32/libraries/n32_drivers/drv_dac.h create mode 100644 bsp/n32/libraries/n32_drivers/drv_gpio.c create mode 100644 bsp/n32/libraries/n32_drivers/drv_gpio.h create mode 100644 bsp/n32/libraries/n32_drivers/drv_hwtimer.c create mode 100644 bsp/n32/libraries/n32_drivers/drv_hwtimer.h create mode 100644 bsp/n32/libraries/n32_drivers/drv_i2c.c create mode 100644 bsp/n32/libraries/n32_drivers/drv_i2c.h create mode 100644 bsp/n32/libraries/n32_drivers/drv_rtc.c create mode 100644 bsp/n32/libraries/n32_drivers/drv_spi.c create mode 100644 bsp/n32/libraries/n32_drivers/drv_spi.h create mode 100644 bsp/n32/libraries/n32_drivers/drv_usart.c create mode 100644 bsp/n32/libraries/n32_drivers/drv_usart.h create mode 100644 bsp/n32/libraries/n32_drivers/drv_wdt.c create mode 100644 bsp/n32/libraries/n32_drivers/drv_wdt.h create mode 100644 bsp/n32/n32g45xvl-stb/.config create mode 100644 bsp/n32/n32g45xvl-stb/Kconfig create mode 100644 bsp/n32/n32g45xvl-stb/README.md create mode 100644 bsp/n32/n32g45xvl-stb/RTE/_rt-thread/RTE_Components.h create mode 100644 bsp/n32/n32g45xvl-stb/SConscript create mode 100644 bsp/n32/n32g45xvl-stb/SConstruct create mode 100644 bsp/n32/n32g45xvl-stb/applications/SConscript create mode 100644 bsp/n32/n32g45xvl-stb/applications/main.c create mode 100644 bsp/n32/n32g45xvl-stb/board/Kconfig create mode 100644 bsp/n32/n32g45xvl-stb/board/SConscript create mode 100644 bsp/n32/n32g45xvl-stb/board/board.c create mode 100644 bsp/n32/n32g45xvl-stb/board/board.h create mode 100644 bsp/n32/n32g45xvl-stb/board/linker_scripts/link.icf create mode 100644 bsp/n32/n32g45xvl-stb/board/linker_scripts/link.lds create mode 100644 bsp/n32/n32g45xvl-stb/board/linker_scripts/link.sct create mode 100644 bsp/n32/n32g45xvl-stb/figures/board.jpg create mode 100644 bsp/n32/n32g45xvl-stb/project.ewd create mode 100644 bsp/n32/n32g45xvl-stb/project.ewp create mode 100644 bsp/n32/n32g45xvl-stb/project.eww create mode 100644 bsp/n32/n32g45xvl-stb/project.uvoptx create mode 100644 bsp/n32/n32g45xvl-stb/project.uvprojx create mode 100644 bsp/n32/n32g45xvl-stb/rtconfig.h create mode 100644 bsp/n32/n32g45xvl-stb/rtconfig.py create mode 100644 bsp/n32/n32g45xvl-stb/settings/project.crun create mode 100644 bsp/n32/n32g45xvl-stb/settings/project.dbgdt create mode 100644 bsp/n32/n32g45xvl-stb/settings/project.dnx create mode 100644 bsp/n32/n32g45xvl-stb/settings/project.rt-thread.cspy.bat create mode 100644 bsp/n32/n32g45xvl-stb/settings/project.rt-thread.cspy.ps1 create mode 100644 bsp/n32/n32g45xvl-stb/settings/project.rt-thread.driver.xcl create mode 100644 bsp/n32/n32g45xvl-stb/settings/project.rt-thread.general.xcl create mode 100644 bsp/n32/n32g45xvl-stb/settings/project.wsdt create mode 100644 bsp/n32/n32g45xvl-stb/settings/template.crun create mode 100644 bsp/n32/n32g45xvl-stb/settings/template.dbgdt create mode 100644 bsp/n32/n32g45xvl-stb/settings/template.dnx create mode 100644 bsp/n32/n32g45xvl-stb/settings/template.rt-thread.cspy.bat create mode 100644 bsp/n32/n32g45xvl-stb/settings/template.rt-thread.cspy.ps1 create mode 100644 bsp/n32/n32g45xvl-stb/settings/template.rt-thread.driver.xcl create mode 100644 bsp/n32/n32g45xvl-stb/settings/template.rt-thread.general.xcl create mode 100644 bsp/n32/n32g45xvl-stb/settings/template.wsdt create mode 100644 bsp/n32/n32g45xvl-stb/template.ewp create mode 100644 bsp/n32/n32g45xvl-stb/template.eww create mode 100644 bsp/n32/n32g45xvl-stb/template.uvoptx create mode 100644 bsp/n32/n32g45xvl-stb/template.uvprojx create mode 100644 bsp/n32/tools/sdk_dist.py diff --git a/bsp/n32/libraries/Kconfig b/bsp/n32/libraries/Kconfig new file mode 100644 index 0000000000..c08c8d2b97 --- /dev/null +++ b/bsp/n32/libraries/Kconfig @@ -0,0 +1,17 @@ +config SOC_FAMILY_N32 + bool + +config SOC_SERIES_N32G45X + bool + select ARCH_ARM_CORTEX_M4 + select SOC_FAMILY_N32 + +config SOC_SERIES_N32G4FR + bool + select ARCH_ARM_CORTEX_M4 + select SOC_FAMILY_N32 + +config SOC_SERIES_N32WB452 + bool + select ARCH_ARM_CORTEX_M4 + select SOC_FAMILY_N32 diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/arm_common_tables.h b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/arm_common_tables.h new file mode 100644 index 0000000000..dfea7460e9 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_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/N32G45x_Firmware_Library/CMSIS/core/arm_const_structs.h b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/arm_const_structs.h new file mode 100644 index 0000000000..80a3e8bbe7 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_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/N32G45x_Firmware_Library/CMSIS/core/arm_math.h b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/arm_math.h new file mode 100644 index 0000000000..ea9dd26aa8 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_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/N32G45x_Firmware_Library/CMSIS/core/cmsis_armcc.h b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/cmsis_armcc.h new file mode 100644 index 0000000000..4d9d0645d3 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_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/N32G45x_Firmware_Library/CMSIS/core/cmsis_armclang.h b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/cmsis_armclang.h new file mode 100644 index 0000000000..162a400ea1 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_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/N32G45x_Firmware_Library/CMSIS/core/cmsis_compiler.h b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/cmsis_compiler.h new file mode 100644 index 0000000000..94212eb87a --- /dev/null +++ b/bsp/n32/libraries/N32G45x_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/N32G45x_Firmware_Library/CMSIS/core/cmsis_gcc.h b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/cmsis_gcc.h new file mode 100644 index 0000000000..2d9db15a5d --- /dev/null +++ b/bsp/n32/libraries/N32G45x_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/N32G45x_Firmware_Library/CMSIS/core/cmsis_iccarm.h b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/cmsis_iccarm.h new file mode 100644 index 0000000000..b82874d0e4 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_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/N32G45x_Firmware_Library/CMSIS/core/cmsis_version.h b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/cmsis_version.h new file mode 100644 index 0000000000..660f612aa3 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_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/N32G45x_Firmware_Library/CMSIS/core/core_cm4.h b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/core_cm4.h new file mode 100644 index 0000000000..7d56873532 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_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/N32G45x_Firmware_Library/CMSIS/core/mpu_armv7.h b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/core/mpu_armv7.h new file mode 100644 index 0000000000..01422033d0 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_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/N32G45x_Firmware_Library/CMSIS/device/n32g45x.h b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/n32g45x.h new file mode 100644 index 0000000000..43f69b5ce3 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/n32g45x.h @@ -0,0 +1,9049 @@ +/***************************************************************************** + * 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 n32g45x.h + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_H__ +#define __N32G45X_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup N32G45x_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 __N32G45X_STDPERIPH_VERSION_MAIN (0x00) /*!< [31:24] main version */ +#define __N32G45X_STDPERIPH_VERSION_SUB1 (0x04) /*!< [23:16] sub1 version */ +#define __N32G45X_STDPERIPH_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */ +#define __N32G45X_STDPERIPH_VERSION_RC (0x00) /*!< [7:0] release candidate */ + +/** + * @brief N32G45X Standard Peripheral Library version number + */ +#define __N32G45X_STDPERIPH_VERSION \ + ((__N32G45X_STDPERIPH_VERSION_MAIN << 24) | (__N32G45X_STDPERIPH_VERSION_SUB1 << 16) \ + | (__N32G45X_STDPERIPH_VERSION_SUB2 << 8) | (__N32G45X_STDPERIPH_VERSION_RC)) + +/* + * Configuration of the Cortex-M4 Processor and Core Peripherals + */ +#ifdef N32G45X +#define __MPU_PRESENT 1 /*!< N32G45X devices does not provide an MPU */ +#define __FPU_PRESENT 1 /*!< FPU present */ +#endif /* N32G45X */ +#define __NVIC_PRIO_BITS 4 /*!< N32G45X uses 4 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ + +/** + * @brief N32G45X 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 */ + + /****** N32G45X 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 */ + ADC3_4_IRQn = 47, /*!< ADC3 and ADC4 global Interrupt */ + RESERVE48_IRQn = 48, /*!< RESERVE */ + 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 */ + COMP_1_2_3_IRQn = 82, /*!< COMP1 & COMP2 & COMP3 global Interrupt */ + COMP_4_5_6_IRQn = 83, /*!< COMP4 & COMP5 & COMP6 global Interrupt */ + COMP7_IRQn = 84 /*!< COMP7 global Interrupt */ + +} IRQn_Type; + +#include "core_cm4.h" +#include "system_n32g45x.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; + +/* N32G45X 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 OPAMP + */ +typedef struct +{ + __IO uint32_t CS1; + __IO uint32_t RES1[3]; + __IO uint32_t CS2; + __IO uint32_t RES2[3]; + __IO uint32_t CS3; + __IO uint32_t RES3[3]; + __IO uint32_t CS4; + __IO uint32_t RES4[3]; + __IO uint32_t LOCK; +} OPAMP_Module; + +/** + * @brief COMP_Single + */ +typedef struct +{ + __IO uint32_t CTRL; + __IO uint32_t FILC; + __IO uint32_t FILP; + __IO uint32_t RES; +} COMP_SingleType; + +/** + * @brief COMP + */ +typedef struct +{ + __IO uint32_t RES4[4]; + COMP_SingleType Cmp[7]; + __IO uint32_t WINMODE; + __IO uint32_t LOCK; + __IO uint32_t RES; + __IO uint32_t INTEN; + __IO uint32_t INTSTS; + __IO uint32_t VREFSCL; +} COMP_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 Ethernet MAC + */ + +typedef struct +{ + __IO uint32_t MACCFG; + __IO uint32_t MACFFLT; + __IO uint32_t MACHASHHI; + __IO uint32_t MACHASHLO; + __IO uint32_t MACMIIADDR; + __IO uint32_t MACMIIDAT; + __IO uint32_t MACFLWCTRL; + __IO uint32_t MACVLANTAG; /* 8 */ + uint32_t RESERVED0[2]; + __IO uint32_t MACRMTWUFRMFLT; /* 11 */ + __IO uint32_t MACPMTCTRLSTS; + uint32_t RESERVED1[2]; + __IO uint32_t MACINTSTS; /* 15 */ + __IO uint32_t MACINTMSK; + __IO uint32_t MACADDR0HI; + __IO uint32_t MACADDR0LO; + __IO uint32_t MACADDR1HI; + __IO uint32_t MACADDR1LO; + __IO uint32_t MACADDR2HI; + __IO uint32_t MACADDR2LO; + __IO uint32_t MACADDR3HI; + __IO uint32_t MACADDR3LO; /* 24 */ + uint32_t RESERVED2[40]; + __IO uint32_t MMCCTRL; /* 65 */ + __IO uint32_t MMCRXINT; + __IO uint32_t MMCTXINT; + __IO uint32_t MMCRXINTMSK; + __IO uint32_t MMCTXINTMSK; /* 69 */ + uint32_t RESERVED3[14]; + __IO uint32_t MMCTXGFASCCNT; /* 84 */ + __IO uint32_t MMCTXGFAMSCCNT; + uint32_t RESERVED4[5]; + __IO uint32_t MMCTXGFCNT; + uint32_t RESERVED5[10]; + __IO uint32_t MMCRXFCECNT; + __IO uint32_t MMCRXFAECNT; + uint32_t RESERVED6[10]; + __IO uint32_t MMCRXGUFCNT; + uint32_t RESERVED7[14]; + __IO uint32_t MMCRXCOINTMSK; + uint32_t RESERVED8[319]; + __IO uint32_t PTPTSCTRL; + __IO uint32_t PTPSSINC; + __IO uint32_t PTPSEC; + __IO uint32_t PTPNS; + __IO uint32_t PTPSECUP; + __IO uint32_t PTPNSUP; + __IO uint32_t PTPTSADD; + __IO uint32_t PTPTTSEC; + __IO uint32_t PTPTTNS; + uint32_t RESERVED9[567]; + __IO uint32_t DMABUSMOD; + __IO uint32_t DMATXPD; + __IO uint32_t DMARXPD; + __IO uint32_t DMARXDLADDR; + __IO uint32_t DMATXDLADDR; + __IO uint32_t DMASTS; + __IO uint32_t DMAOPMOD; + __IO uint32_t DMAINTEN; + __IO uint32_t DMAMFBOCNT; + uint32_t RESERVED10[9]; + __IO uint32_t DMACHTXDESC; + __IO uint32_t DMACHRXDESC; + __IO uint32_t DMACHTXBADDR; + __IO uint32_t DMACHRXBADDR; +} ETH_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 IDCODE; + __IO uint32_t RESERVED; + __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 OPAMP_BASE (APB1PERIPH_BASE + 0x2000) +#define COMP_BASE (APB1PERIPH_BASE + 0x2400) +#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 GPIOF_BASE (APB2PERIPH_BASE + 0x1C00) +#define GPIOG_BASE (APB2PERIPH_BASE + 0x2000) +#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 ADC3_BASE (AHBPERIPH_BASE + 0x9800) +#define ADC4_BASE (AHBPERIPH_BASE + 0x9C00) +#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 ETH_BASE (AHBPERIPH_BASE + 0x10000) +#define ETH_MAC_BASE (ETH_BASE) +#define ETH_MMC_BASE (ETH_BASE + 0x0100) +#define ETH_PTP_BASE (ETH_BASE + 0x0700) +#define ETH_DMA_BASE (ETH_BASE + 0x1000) + +#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 OPAMP ((OPAMP_Module*)OPAMP_BASE) +#define COMP ((COMP_Module*)COMP_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 GPIOF ((GPIO_Module*)GPIOF_BASE) +#define GPIOG ((GPIO_Module*)GPIOG_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 ADC3 ((ADC_Module*)ADC3_BASE) +#define ADC4 ((ADC_Module*)ADC4_BASE) +#define FLASH ((FLASH_Module*)FLASH_R_BASE) +#define OB ((OB_Module*)OB_BASE) +#define CRC ((CRC_Module*)CRC_BASE) +#define ETH ((ETH_Module*)ETH_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_ADC3EN ((uint32_t)0x00004000) /*!< ADC3 clock enable */ +#define RCC_AHBPCLKEN_ADC4EN ((uint32_t)0x00008000) /*!< ADC4 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_ADC3RST ((uint32_t)0x00004000) /*!< ADC3 reset */ +#define RCC_AHBRST_ADC4RST ((uint32_t)0x00008000) /*!< ADC4 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/N32G45x_Firmware_Library/CMSIS/device/startup/startup_n32g45x.s b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/startup/startup_n32g45x.s new file mode 100644 index 0000000000..843a8e84a3 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/startup/startup_n32g45x.s @@ -0,0 +1,432 @@ +; **************************************************************************** +; 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 ADC3_4_IRQHandler ; ADC3 & ADC4 + DCD RESERVE48_IRQHandler ; + 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 ETH_IRQHandler ; Ethernet global interrupt + DCD ETH_WKUP_IRQHandler ; Ethernet Wakeup through EXTI line interrupt + 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 COMP_1_2_3_IRQHandler ; COMP1 & COMP2 & COMP3 + DCD COMP_4_5_6_IRQHandler ; COMP4 & COMP5 & COMP6 + DCD COMP7_IRQHandler ; COMP7 + 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 ADC3_4_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 ETH_IRQHandler [WEAK] + EXPORT ETH_WKUP_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 COMP_1_2_3_IRQHandler [WEAK] + EXPORT COMP_4_5_6_IRQHandler [WEAK] + EXPORT COMP7_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 +ADC3_4_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 +ETH_IRQHandler +ETH_WKUP_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 +COMP_1_2_3_IRQHandler +COMP_4_5_6_IRQHandler +COMP7_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/N32G45x_Firmware_Library/CMSIS/device/startup/startup_n32g45x_EWARM.s b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/startup/startup_n32g45x_EWARM.s new file mode 100644 index 0000000000..ae4330abef --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/startup/startup_n32g45x_EWARM.s @@ -0,0 +1,642 @@ +; **************************************************************************** +; 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 ADC3_4_IRQHandler ; ADC3 & ADC4 + 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 ETH_IRQHandler ; Ethernet global interrupt + DCD ETH_WKUP_IRQHandler ; Ethernet Wakeup through EXTI line interrupt + 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 COMP_1_2_3_IRQHandler ; COMP1 & COMP2 & COMP3 + DCD COMP_4_5_6_IRQHandler ; COMP4 & COMP5 & COMP6 + DCD COMP7_IRQHandler ; COMP7 + 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 ADC3_4_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ADC3_4_IRQHandler + B ADC3_4_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 ETH_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ETH_IRQHandler + B ETH_IRQHandler + + PUBWEAK ETH_WKUP_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ETH_WKUP_IRQHandler + B ETH_WKUP_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 COMP_1_2_3_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +COMP_1_2_3_IRQHandler + B COMP_1_2_3_IRQHandler + + PUBWEAK COMP_4_5_6_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +COMP_4_5_6_IRQHandler + B COMP_4_5_6_IRQHandler + + PUBWEAK COMP7_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +COMP7_IRQHandler + B COMP7_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/N32G45x_Firmware_Library/CMSIS/device/startup/startup_n32g45x_gcc.s b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/startup/startup_n32g45x_gcc.s new file mode 100644 index 0000000000..fa81b7cc64 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/startup/startup_n32g45x_gcc.s @@ -0,0 +1,506 @@ +/** + **************************************************************************** + 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. + **************************************************************************** + **/ + + .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 entry + 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 diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/system_n32g45x.c b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/system_n32g45x.c new file mode 100644 index 0000000000..64a14f0016 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/system_n32g45x.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_n32g45x.c + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x.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 = 0x00000000; + + /* Reset CFG3 register */ + RCC->CFG3 = 0x00000000; + + /* 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 n32g45x.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 N32G45X.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) +{ + volatile uint32_t rcc_cfgr = 0; + volatile bool HSEStatus = 0; + volatile 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/N32G45x_Firmware_Library/CMSIS/device/system_n32g45x.h b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/system_n32g45x.h new file mode 100644 index 0000000000..b94db8ba4c --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/CMSIS/device/system_n32g45x.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_n32g45x.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __SYSTEM_N32G45X_H__ +#define __SYSTEM_N32G45X_H__ + +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup N32G45X_System + * @{ + */ + +extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ + +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*__SYSTEM_N32G45X_H__ */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/SConscript b/bsp/n32/libraries/N32G45x_Firmware_Library/SConscript new file mode 100644 index 0000000000..f31797233c --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/SConscript @@ -0,0 +1,68 @@ +import rtconfig +Import('RTT_ROOT') +from building import * + +# get current directory +cwd = GetCurrentDir() + +# The set of source files associated with this SConscript file. + +src = Split(''' +CMSIS/device/system_n32g45x.c +n32g45x_std_periph_driver/src/n32g45x_gpio.c +n32g45x_std_periph_driver/src/n32g45x_rcc.c +n32g45x_std_periph_driver/src/n32g45x_exti.c +n32g45x_std_periph_driver/src/misc.c +''') + +if GetDepend(['RT_USING_SERIAL']): + src += ['n32g45x_std_periph_driver/src/n32g45x_usart.c'] + +if GetDepend(['RT_USING_I2C']): + src += ['n32g45x_std_periph_driver/src/n32g45x_i2c.c'] + +if GetDepend(['RT_USING_SPI']): + src += ['n32g45x_std_periph_driver/src/n32g45x_spi.c'] + +if GetDepend(['RT_USING_CAN']): + src += ['n32g45x_std_periph_driver/src/n32g45x_can.c'] + +if GetDepend(['BSP_USING_ETH']): + src += ['n32g45x_std_periph_driver/src/n32g45x_eth.c'] + +if GetDepend(['RT_USING_ADC']): + src += ['n32g45x_std_periph_driver/src/n32g45x_adc.c'] + +if GetDepend(['RT_USING_DAC']): + src += ['n32g45x_std_periph_driver/src/n32g45x_dac.c'] + +if GetDepend(['RT_USING_HWTIMER']): + src += ['n32g45x_std_periph_driver/src/n32g45x_tim.c'] + +if GetDepend(['RT_USING_RTC']): + src += ['n32g45x_std_periph_driver/src/n32g45x_rtc.c'] + src += ['n32g45x_std_periph_driver/src/n32g45x_pwr.c'] + +if GetDepend(['RT_USING_WDT']): + src += ['n32g45x_std_periph_driver/src/n32g45x_wwdg.c'] + src += ['n32g45x_std_periph_driver/src/n32g45x_iwdg.c'] + +if GetDepend(['RT_USING_SDIO']): + src += ['n32g45x_std_periph_driver/src/n32g45x_sdio.c'] + +if GetDepend(['RT_USING_BSP_USB']): + path += [cwd + '/n32g45x_usbfs_driver/inc'] + src += [cwd + '/n32g45x_usbfs_driver/src'] + +path = [ + cwd + '/CMSIS/device', + cwd + '/CMSIS/core', + cwd + '/n32g45x_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/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_aes.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_aes.h new file mode 100644 index 0000000000..427a5f7941 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_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 n32g45x_aes.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_AES_H__ +#define __N32G45X_AES_H__ + +#include +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_algo_common.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_algo_common.h new file mode 100644 index 0000000000..ebc78a2548 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_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 n32g45x_algo_common.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_ALGO_COMMON_H__ +#define __N32G45X_ALGO_COMMON_H__ + +#include +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_des.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_des.h new file mode 100644 index 0000000000..db80ec95c6 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_des.h @@ -0,0 +1,121 @@ +/***************************************************************************** + * 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 n32g45x_des.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_DES_H__ +#define __N32G45X_DES_H__ + +#include + +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_hash.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_hash.h new file mode 100644 index 0000000000..50e742f80e --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_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 n32g45x_hash.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_HASH_H__ +#define __N32G45X_HASH_H__ + +#include +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_rng.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_rng.h new file mode 100644 index 0000000000..d952485dea --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_algo_lib/inc/n32g45x_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 n32g45x_rng.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_RNG_H__ +#define __N32G45X_RNG_H__ + +#include + +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/misc.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/misc.h new file mode 100644 index 0000000000..543e4d1533 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/misc.h @@ -0,0 +1,229 @@ +/***************************************************************************** + * 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 "n32g45x.h" + +/** @addtogroup N32G45X_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 N32G45X Devices IRQ Channels list, please + refer to n32g45x.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) || ((SOURCE) == SysTick_CLKSource_HCLK_Div8)) +/** + * @} + */ + +/** + * @} + */ + +/** @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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_adc.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_adc.h new file mode 100644 index 0000000000..35b1167070 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_adc.h @@ -0,0 +1,660 @@ +/***************************************************************************** + * 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 n32g45x_adc.h + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_ADC_H__ +#define __N32G45X_ADC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" +#include + +/** @addtogroup N32G45X_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) || ((PERIPH) == ADC3) || ((PERIPH) == ADC4)) + +#define IsAdcDmaModule(PERIPH) (((PERIPH) == ADC1) || ((PERIPH) == ADC2) || ((PERIPH) == ADC3) || ((PERIPH) == ADC4)) + +/** @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 , ADC3 and ADC4 */ +#define ADC_EXT_TRIGCONV_NONE ((uint32_t)0x000E0000) /*!< For ADC1, ADC2 , ADC3 and ADC4 */ + +#define ADC_EXT_TRIGCONV_T3_CC1 ((uint32_t)0x00000000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIGCONV_T2_CC3 ((uint32_t)0x00020000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIGCONV_T8_CC1 ((uint32_t)0x00060000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIGCONV_T8_TRGO ((uint32_t)0x00080000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIGCONV_T5_CC1 ((uint32_t)0x000A0000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIGCONV_EXT_INT10_T5_CC3 ((uint32_t)0x000C0000) /*!< For ADC3 and ADC4 */ + +#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) \ + || ((REGTRIG) == ADC_EXT_TRIGCONV_T3_CC1) || ((REGTRIG) == ADC_EXT_TRIGCONV_T2_CC3) \ + || ((REGTRIG) == ADC_EXT_TRIGCONV_T8_CC1) || ((REGTRIG) == ADC_EXT_TRIGCONV_T8_TRGO) \ + || ((REGTRIG) == ADC_EXT_TRIGCONV_T5_CC1) || ((REGTRIG) == ADC_EXT_TRIGCONV_EXT_INT10_T5_CC3)) +/** + * @} + */ + +/** @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, ADC3 and ADC4 */ +#define ADC_EXT_TRIG_INJ_CONV_T1_CC4 ((uint32_t)0x00001000) /*!< For ADC1, ADC2, ADC3 and ADC4 */ +#define ADC_EXT_TRIG_INJ_CONV_NONE ((uint32_t)0x00007000) /*!< For ADC1, ADC2, ADC3 and ADC4 */ + +#define ADC_EXT_TRIG_INJ_CONV_T4_CC3 ((uint32_t)0x00002000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIG_INJ_CONV_T8_CC2 ((uint32_t)0x00003000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIG_INJ_CONV_T8_CC4 ((uint32_t)0x00004000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIG_INJ_CONV_T5_TRGO ((uint32_t)0x00005000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIG_INJ_CONV_EXT_INT14_T5_CC4 ((uint32_t)0x00006000) /*!< For ADC3 and ADC4 */ + +#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) \ + || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T4_CC3) || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T8_CC2) \ + || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T8_CC4) || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T5_TRGO) \ + || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_EXT_INT14_T5_CC4)) +/** + * @} + */ + +/** @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 ADC3_Channel_01_PB11 ((uint8_t)0x01) +#define ADC3_Channel_02_PE9 ((uint8_t)0x02) +#define ADC3_Channel_03_PE13 ((uint8_t)0x03) +#define ADC3_Channel_04_PE12 ((uint8_t)0x04) +#define ADC3_Channel_05_PB13 ((uint8_t)0x05) +#define ADC3_Channel_06_PE8 ((uint8_t)0x06) +#define ADC3_Channel_07_PD10 ((uint8_t)0x07) +#define ADC3_Channel_08_PD11 ((uint8_t)0x08) +#define ADC3_Channel_09_PD12 ((uint8_t)0x09) +#define ADC3_Channel_10_PD13 ((uint8_t)0x0A) +#define ADC3_Channel_11_PD14 ((uint8_t)0x0B) +#define ADC3_Channel_12_PB0 ((uint8_t)0x0C) +#define ADC3_Channel_13_PE7 ((uint8_t)0x0D) +#define ADC3_Channel_14_PE10 ((uint8_t)0x0E) +#define ADC3_Channel_15_PE11 ((uint8_t)0x0F) + +#define ADC4_Channel_01_PE14 ((uint8_t)0x01) +#define ADC4_Channel_02_PE15 ((uint8_t)0x02) +#define ADC4_Channel_03_PB12 ((uint8_t)0x03) +#define ADC4_Channel_04_PB14 ((uint8_t)0x04) +#define ADC4_Channel_05_PB15 ((uint8_t)0x05) +#define ADC4_Channel_06_PE8 ((uint8_t)0x06) +#define ADC4_Channel_07_PD10 ((uint8_t)0x07) +#define ADC4_Channel_08_PD11 ((uint8_t)0x08) +#define ADC4_Channel_09_PD12 ((uint8_t)0x09) +#define ADC4_Channel_10_PD13 ((uint8_t)0x0A) +#define ADC4_Channel_11_PD14 ((uint8_t)0x0B) +#define ADC4_Channel_12_PD8 ((uint8_t)0x0C) +#define ADC4_Channel_13_PD9 ((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 SampSecondStyle; +} 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 /*__N32G45X_ADC_H__ */ + +/** + * @} + */ +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_bkp.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_bkp.h new file mode 100644 index 0000000000..7b47b97337 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_bkp.h @@ -0,0 +1,182 @@ +/***************************************************************************** + * 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 n32g45x_bkp.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_BKP_H__ +#define __N32G45X_BKP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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 /* __N32G45X_BKP_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_can.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_can.h new file mode 100644 index 0000000000..ef4fc0080d --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_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 n32g45x_can.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_CAN_H__ +#define __N32G45X_CAN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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 /* __N32G45X_CAN_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_comp.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_comp.h new file mode 100644 index 0000000000..ae6079af33 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_comp.h @@ -0,0 +1,385 @@ +/***************************************************************************** + * 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 n32g45x_comp.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_COMP_H__ +#define __N32G45X_COMP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" +#include + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup COMP + * @{ + */ + +/** @addtogroup COMP_Exported_Constants + * @{ + */ +typedef enum +{ + COMP1 = 0, + COMP2 = 1, + COMP3 = 2, + COMP4 = 3, + COMP5 = 4, + COMP6 = 5, + COMP7 = 6 +} COMPX; + +// COMPx_CTRL +#define COMP1_CTRL_INPDAC_MASK (0x01L << 18) +#define COMP_CTRL_OUT_MASK (0x01L << 17) +#define COMP_CTRL_BLKING_MASK (0x07L << 14) +typedef enum +{ + COMP_CTRL_BLKING_NO = (0x0L << 14), + COMP_CTRL_BLKING_TIM1_OC5 = (0x1L << 14), + COMP_CTRL_BLKING_TIM8_OC5 = (0x2L << 14), +} COMP_CTRL_BLKING; +#define COMPx_CTRL_HYST_MASK (0x03L << 12) +typedef enum +{ + COMP_CTRL_HYST_NO = (0x0L << 12), + COMP_CTRL_HYST_LOW = (0x1L << 12), + COMP_CTRL_HYST_MID = (0x2L << 12), + COMP_CTRL_HYST_HIGH = (0x3L << 12), +} COMP_CTRL_HYST; + +#define COMP_POL_MASK (0x01L << 11) +#define COMP_CTRL_OUTSEL_MASK (0x0FL << 7) +typedef enum +{ + COMPX_CTRL_OUTSEL_NC = (0x0L << 7), + // comp1 out trig + COMP1_CTRL_OUTSEL_NC = (0x0L << 7), + COMP1_CTRL_OUTSEL_TIM1_BKIN = (0x1L << 7), + COMP1_CTRL_OUTSEL_TIM1_IC1 = (0x2L << 7), + COMP1_CTRL_OUTSEL_TIM1_OCrefclear = (0x3L << 7), + COMP1_CTRL_OUTSEL_TIM2_IC1 = (0x4L << 7), + COMP1_CTRL_OUTSEL_TIM2_OCrefclear = (0x5L << 7), + COMP1_CTRL_OUTSEL_TIM3_IC1 = (0x6L << 7), + COMP1_CTRL_OUTSEL_TIM3_OCrefclear = (0x7L << 7), + COMP1_CTRL_OUTSEL_TIM4_IC1 = (0x8L << 7), + COMP1_CTRL_OUTSEL_TIM4_OCrefclear = (0x9L << 7), + COMP1_CTRL_OUTSEL_TIM8_BKIN = (0xAL << 7), + COMP1_CTRL_OUTSEL_TIM1_BKIN_TIM8_BKIN = (0xBL << 7), + // comp2 out trig + COMP2_CTRL_OUTSEL_NC = (0x0L << 7), + COMP2_CTRL_OUTSEL_TIM1_BKIN = (0x1L << 7), + COMP2_CTRL_OUTSEL_TIM1_IC1 = (0x2L << 7), + COMP2_CTRL_OUTSEL_TIM1_OCrefclear = (0x3L << 7), + COMP2_CTRL_OUTSEL_TIM2_IC2 = (0x4L << 7), + COMP2_CTRL_OUTSEL_TIM2_OCrefclear = (0x5L << 7), + COMP2_CTRL_OUTSEL_TIM3_IC2 = (0x6L << 7), + COMP2_CTRL_OUTSEL_TIM3_OCrefclear = (0x7L << 7), + COMP2_CTRL_OUTSEL_TIM5_IC1 = (0x8L << 7), ////(0x9L << 7) + COMP2_CTRL_OUTSEL_TIM8_BKIN = (0xAL << 7), + COMP2_CTRL_OUTSEL_TIM1_BKIN_TIM8_BKIN = (0xBL << 7), + // comp3 out trig + COMP3_CTRL_OUTSEL_NC = (0x0L << 7), + COMP3_CTRL_OUTSEL_TIM1_BKIN = (0x1L << 7), + COMP3_CTRL_OUTSEL_TIM1_IC1 = (0x2L << 7), + COMP3_CTRL_OUTSEL_TIM1_OCrefclear = (0x3L << 7), + COMP3_CTRL_OUTSEL_TIM2_IC3 = (0x4L << 7), + COMP3_CTRL_OUTSEL_TIM2_OCrefclear = (0x5L << 7), + COMP3_CTRL_OUTSEL_TIM4_IC2 = (0x6L << 7), + COMP3_CTRL_OUTSEL_TIM4_OCrefclear = (0x7L << 7), + COMP3_CTRL_OUTSEL_TIM5_IC2 = (0x8L << 7), //(0x9L << 7) + COMP3_CTRL_OUTSEL_TIM8_BKIN = (0xAL << 7), + COMP3_CTRL_OUTSEL_TIM1_BKIN_TIM8_BKIN = (0xBL << 7), + // comp4 out trig + COMP4_CTRL_OUTSEL_NC = (0x0L << 7), + COMP4_CTRL_OUTSEL_TIM1_BKIN = (0x1L << 7), + COMP4_CTRL_OUTSEL_TIM3_IC3 = (0x2L << 7), + COMP4_CTRL_OUTSEL_TIM3_OCrefclear = (0x3L << 7), + COMP4_CTRL_OUTSEL_TIM4_IC3 = (0x4L << 7), + COMP4_CTRL_OUTSEL_TIM4_OCrefclear = (0x5L << 7), + COMP4_CTRL_OUTSEL_TIM5_IC3 = (0x6L << 7), //(0x7L << 7) + COMP4_CTRL_OUTSEL_TIM8_IC1 = (0x8L << 7), + COMP4_CTRL_OUTSEL_TIM8_OCrefclear = (0x9L << 7), + COMP4_CTRL_OUTSEL_TIM8_BKIN = (0xAL << 7), + COMP4_CTRL_OUTSEL_TIM1_BKIN_TIM8_BKIN = (0xBL << 7), + // comp5 out trig + COMP5_CTRL_OUTSEL_NC = (0x0L << 7), + COMP5_CTRL_OUTSEL_TIM1_BKIN = (0x1L << 7), + COMP5_CTRL_OUTSEL_TIM2_IC4 = (0x2L << 7), + COMP5_CTRL_OUTSEL_TIM2_OCrefclear = (0x3L << 7), + COMP5_CTRL_OUTSEL_TIM3_IC4 = (0x4L << 7), + COMP5_CTRL_OUTSEL_TIM3_OCrefclear = (0x5L << 7), + COMP5_CTRL_OUTSEL_TIM4_IC4 = (0x6L << 7), + COMP5_CTRL_OUTSEL_TIM4_OCrefclear = (0x7L << 7), + COMP5_CTRL_OUTSEL_TIM8_IC1 = (0x8L << 7), + COMP5_CTRL_OUTSEL_TIM8_OCrefclear = (0x9L << 7), + COMP5_CTRL_OUTSEL_TIM8_BKIN = (0xAL << 7), + COMP5_CTRL_OUTSEL_TIM1_BKIN_TIM8_BKIN = (0xBL << 7), + // comp6 out trig + COMP6_CTRL_OUTSEL_NC = (0x0L << 7), + COMP6_CTRL_OUTSEL_TIM1_BKIN = (0x1L << 7), + COMP6_CTRL_OUTSEL_TIM2_IC1 = (0x2L << 7), + COMP6_CTRL_OUTSEL_TIM2_OCrefclear = (0x3L << 7), + COMP6_CTRL_OUTSEL_TIM3_IC1 = (0x4L << 7), + COMP6_CTRL_OUTSEL_TIM3_OCrefclear = (0x5L << 7), + COMP6_CTRL_OUTSEL_TIM5_IC1 = (0x6L << 7), //(0x7L << 7) + COMP6_CTRL_OUTSEL_TIM8_IC1 = (0x8L << 7), + COMP6_CTRL_OUTSEL_TIM8_OCrefclear = (0x9L << 7), + COMP6_CTRL_OUTSEL_TIM8_BKIN = (0xAL << 7), + COMP6_CTRL_OUTSEL_TIM1_BKIN_TIM8_BKIN = (0xBL << 7), + // comp7 out trig + COMP7_CTRL_OUTSEL_NC = (0x0L << 7), + COMP7_CTRL_OUTSEL_TIM1_BKIN = (0x1L << 7), + COMP7_CTRL_OUTSEL_TIM2_IC1 = (0x2L << 7), + COMP7_CTRL_OUTSEL_TIM2_OCrefclear = (0x3L << 7), + COMP7_CTRL_OUTSEL_TIM3_IC1 = (0x4L << 7), + COMP7_CTRL_OUTSEL_TIM3_OCrefclear = (0x5L << 7), + COMP7_CTRL_OUTSEL_TIM5_IC1 = (0x6L << 7), //(0x7L << 7) + COMP7_CTRL_OUTSEL_TIM8_IC1 = (0x8L << 7), + COMP7_CTRL_OUTSEL_TIM8_OCrefclear = (0x9L << 7), + COMP7_CTRL_OUTSEL_TIM8_BKIN = (0xAL << 7), + COMP7_CTRL_OUTSEL_TIM1_BKIN_TIM8_BKIN = (0xBL << 7), +} COMP_CTRL_OUTTRIG; + +#define COMP_CTRL_INPSEL_MASK (0x07L<<4) +typedef enum { + COMPX_CTRL_INPSEL_RES = (0x7L << 4), + //comp1 inp sel + COMP1_CTRL_INPSEL_PA1 = (0x0L << 4), + COMP1_CTRL_INPSEL_PB10 = (0x1L << 4), + //comp2 inp sel, need recheck maybe wrong + COMP2_CTRL_INPSEL_PA1 = (0x0L << 4), + COMP2_CTRL_INPSEL_PB11 = (0x1L << 4), + COMP2_CTRL_INPSEL_PA7 = (0x2L << 4), + //comp3 inp sel + COMP3_CTRL_INPSEL_PB14 = (0x0L << 4), + COMP3_CTRL_INPSEL_PB0 = (0x1L << 4), + //comp4 inp sel, need recheck maybe wrong + COMP4_CTRL_INPSEL_PB14 = (0x0L << 4), + COMP4_CTRL_INPSEL_PB0 = (0x1L << 4), + COMP4_CTRL_INPSEL_PC9 = (0x2L << 4), + COMP4_CTRL_INPSEL_PB15 = (0x3L << 4), + //comp5 inp sel + COMP5_CTRL_INPSEL_PC4 = (0x0L << 4), + COMP5_CTRL_INPSEL_PC3 = (0x1L << 4), + COMP5_CTRL_INPSEL_PA3 = (0x2L << 4), + //comp6 inp sel, need recheck maybe wrong + COMP6_CTRL_INPSEL_PC4 = (0x0L << 4), + COMP6_CTRL_INPSEL_PC3 = (0x1L << 4), + COMP6_CTRL_INPSEL_PC5 = (0x2L << 4), + COMP6_CTRL_INPSEL_PD9 = (0x3L << 4), + //comp7 inp sel + COMP7_CTRL_INPSEL_PC1 = (0x0L << 4), +}COMP_CTRL_INPSEL; + +#define COMP_CTRL_INMSEL_MASK (0x07L<<1) +typedef enum { + COMPX_CTRL_INMSEL_RES = (0x7L << 1), + //comp1 inm sel + COMP1_CTRL_INMSEL_PA0 = (0x0L << 1), + COMP1_CTRL_INMSEL_DAC1_PA4 = (0x1L << 1), + COMP1_CTRL_INMSEL_DAC2_PA5 = (0x2L << 1), + COMP1_CTRL_INMSEL_VERF1 = (0x3L << 1), + COMP1_CTRL_INMSEL_VERF2 = (0x4L << 1), + //comp2 inm sel + COMP2_CTRL_INMSEL_PB1 = (0x0L << 1), + COMP2_CTRL_INMSEL_PE8 = (0x1L << 1), + COMP2_CTRL_INMSEL_DAC1_PA4 = (0x2L << 1), + COMP2_CTRL_INMSEL_DAC2_PA5 = (0x3L << 1), + COMP2_CTRL_INMSEL_VERF1 = (0x4L << 1), + COMP2_CTRL_INMSEL_VERF2 = (0x5L << 1), + //comp3 inm sel + COMP3_CTRL_INMSEL_PB12 = (0x0L << 1), + COMP3_CTRL_INMSEL_PE7 = (0x1L << 1), + COMP3_CTRL_INMSEL_DAC1_PA4 = (0x2L << 1), + COMP3_CTRL_INMSEL_DAC2_PA5 = (0x3L << 1), + COMP3_CTRL_INMSEL_VERF1 = (0x4L << 1), + COMP3_CTRL_INMSEL_VERF2 = (0x5L << 1), + //comp4 inm sel + COMP4_CTRL_INMSEL_PC4 = (0x0L << 1), + COMP4_CTRL_INMSEL_PB13 = (0x1L << 1), + COMP4_CTRL_INMSEL_DAC1_PA4 = (0x2L << 1), + COMP4_CTRL_INMSEL_DAC2_PA5 = (0x3L << 1), + COMP4_CTRL_INMSEL_VERF1 = (0x4L << 1), + COMP4_CTRL_INMSEL_VERF2 = (0x5L << 1), + //comp5 inm sel + COMP5_CTRL_INMSEL_PB10 = (0x0L << 1), + COMP5_CTRL_INMSEL_PD10 = (0x1L << 1), + COMP5_CTRL_INMSEL_DAC1_PA4 = (0x2L << 1), + COMP5_CTRL_INMSEL_DAC2_PA5 = (0x3L << 1), + COMP5_CTRL_INMSEL_VERF1 = (0x4L << 1), + COMP5_CTRL_INMSEL_VERF2 = (0x5L << 1), + //comp6 inm sel + COMP6_CTRL_INMSEL_PA7 = (0x0L << 1), + COMP6_CTRL_INMSEL_PD8 = (0x1L << 1), + COMP6_CTRL_INMSEL_DAC1_PA4 = (0x2L << 1), + COMP6_CTRL_INMSEL_DAC2_PA5 = (0x3L << 1), + COMP6_CTRL_INMSEL_VERF1 = (0x4L << 1), + COMP6_CTRL_INMSEL_VERF2 = (0x5L << 1), + //comp7 inm sel + COMP7_CTRL_INMSEL_PC0 = (0x0L << 1), + COMP7_CTRL_INMSEL_DAC1_PA4 = (0x1L << 1), + COMP7_CTRL_INMSEL_DAC2_PA5 = (0x2L << 1), + COMP7_CTRL_INMSEL_VERF1 = (0x3L << 1), + COMP7_CTRL_INMSEL_VERF2 = (0x4L << 1), +}COMP_CTRL_INMSEL; + +#define COMP_CTRL_EN_MASK (0x01L << 0) + +//COMPx_FILC +#define COMP_FILC_SAMPW_MASK (0x1FL<<6)//Low filter sample window size. Number of samples to monitor is SAMPWIN+1. +#define COMP_FILC_THRESH_MASK (0x1FL<<1)//For proper operation, the value of THRESH must be greater than SAMPWIN / 2. +#define COMP_FILC_FILEN_MASK (0x01L<<0)//Filter enable. + +//COMPx_FILCLKCR +#define COMP_FILCLKCR_CLKPSC_MASK (0xFFFFL<<0)//Low filter sample clock prescale. Number of system clocks between samples = CLK_PRE_CYCLE + 1, e.g. + +//COMP_WINMODE @addtogroup COMP_WINMODE_CMPMD +#define COMP_WINMODE_CMPMD_MSK (0x07L <<0) +#define COMP_WINMODE_CMP56MD (0x01L <<2)//1: Comparators 5 and 6 can be used in window mode. +#define COMP_WINMODE_CMP34MD (0x01L <<1)//1: Comparators 3 and 4 can be used in window mode. +#define COMP_WINMODE_CMP12MD (0x01L <<0)//1: Comparators 1 and 2 can be used in window mode. + +//COMPx_LOCK +#define COMP_LOCK_CMPLK_MSK (0x7FL <<0) +#define COMP_LOCK_CMP1LK_MSK (0x01L <<0)//1: COMx Lock bit +#define COMP_LOCK_CMP2LK_MSK (0x01L <<1)//1: COMx Lock bit +#define COMP_LOCK_CMP3LK_MSK (0x01L <<2)//1: COMx Lock bit +#define COMP_LOCK_CMP4LK_MSK (0x01L <<3)//1: COMx Lock bit +#define COMP_LOCK_CMP5LK_MSK (0x01L <<4)//1: COMx Lock bit +#define COMP_LOCK_CMP6LK_MSK (0x01L <<5)//1: COMx Lock bit +#define COMP_LOCK_CMP7LK_MSK (0x01L <<6)//1: COMx Lock bit + +// COMP_INTEN @addtogroup COMP_INTEN_CMPIEN +#define COMP_INTEN_CMPIEN_MSK (0x7FL << 0) +#define COMP_INTEN_CMP7IEN (0x01L << 6) // This bit control Interrput enable of COMP. +#define COMP_INTEN_CMP6IEN (0x01L << 5) +#define COMP_INTEN_CMP5IEN (0x01L << 4) +#define COMP_INTEN_CMP4IEN (0x01L << 3) +#define COMP_INTEN_CMP3IEN (0x01L << 2) +#define COMP_INTEN_CMP2IEN (0x01L << 1) +#define COMP_INTEN_CMP1IEN (0x01L << 0) + +// COMP_INTSTS @addtogroup COMP_INTSTS_CMPIS +#define COMP_INTSTS_INTSTS_MSK (0x7FL << 0) +#define COMP_INTSTS_CMP7IS (0x01L << 6) // This bit control Interrput enable of COMP. +#define COMP_INTSTS_CMP6IS (0x01L << 5) +#define COMP_INTSTS_CMP5IS (0x01L << 4) +#define COMP_INTSTS_CMP4IS (0x01L << 3) +#define COMP_INTSTS_CMP3IS (0x01L << 2) +#define COMP_INTSTS_CMP2IS (0x01L << 1) +#define COMP_INTSTS_CMP1IS (0x01L << 0) + +// COMP_VREFSCL @addtogroup COMP_VREFSCL +#define COMP_VREFSCL_VV2TRM_MSK (0x3FL << 8) // Vref2 Voltage scaler triming value. +#define COMP_VREFSCL_VV2EN_MSK (0x01L << 7) +#define COMP_VREFSCL_VV1TRM_MSK (0x3FL << 1) // Vref1 Voltage scaler triming value. +#define COMP_VREFSCL_VV1EN_MSK (0x01L << 0) +/** + * @} + */ + +/** + * @brief COMP Init structure definition + */ + +typedef struct +{ + // ctrl + bool InpDacConnect; // only COMP1 have this bit + + COMP_CTRL_BLKING Blking; /*see @ref COMP_CTRL_BLKING */ + + COMP_CTRL_HYST Hyst; + + bool PolRev; // out polarity reverse + + COMP_CTRL_OUTTRIG OutSel; + COMP_CTRL_INPSEL InpSel; + COMP_CTRL_INMSEL InmSel; + + bool En; + + // filter + uint8_t SampWindow; // 5bit + uint8_t Thresh; // 5bit ,need > SampWindow/2 + bool FilterEn; + + // filter psc + uint16_t ClkPsc; +} COMP_InitType; + +/** @addtogroup COMP_Exported_Functions + * @{ + */ + +void COMP_DeInit(void); +void COMP_StructInit(COMP_InitType* COMP_InitStruct); +void COMP_Init(COMPX COMPx, COMP_InitType* COMP_InitStruct); +void COMP_Enable(COMPX COMPx, FunctionalState en); +void COMP_SetInpSel(COMPX COMPx, COMP_CTRL_INPSEL VpSel); +void COMP_SetInmSel(COMPX COMPx, COMP_CTRL_INMSEL VmSel); +void COMP_SetOutTrig(COMPX COMPx, COMP_CTRL_OUTTRIG OutTrig); +void COMP_SetLock(uint32_t Lock); // see @COMP_LOCK_CMPLK +void COMP_SetIntEn(uint32_t IntEn); // see @COMP_INTEN_CMPIEN +uint32_t COMP_GetIntSts(void); // return see @COMP_INTSTS_CMPIS +void COMP_SetRefScl(uint8_t Vv2Trim, bool Vv2En, uint8_t Vv1Trim, bool Vv1En); // parma range see @COMP_VREFSCL +FlagStatus COMP_GetOutStatus(COMPX COMPx); +FlagStatus COMP_GetIntStsOneComp(COMPX COMPx); +void COMP_SetFilterPrescaler(COMPX COMPx , uint16_t FilPreVal); +void COMP_SetFilterControl(COMPX COMPx , uint8_t FilEn, uint8_t TheresNum , uint8_t SampPW); +void COMP_SetHyst(COMPX COMPx , COMP_CTRL_HYST HYST); +void COMP_SetBlanking(COMPX COMPx , COMP_CTRL_BLKING BLK); + + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G45X_ADC_H */ +/** + * @} + */ +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_crc.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_crc.h new file mode 100644 index 0000000000..0721f38cd4 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_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 n32g45x_crc.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_CRC_H__ +#define __N32G45X_CRC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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 /* __N32G45X_CRC_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_dac.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_dac.h new file mode 100644 index 0000000000..6542d3004e --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_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 n32g45x_dac.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_DAC_H__ +#define __N32G45X_DAC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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 /*__N32G45X_DAC_H__ */ + /** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_dbg.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_dbg.h new file mode 100644 index 0000000000..ca94b4a377 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_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 n32g45x_dbg.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_DBG_H__ +#define __N32G45X_DBG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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 /* __N32G45X_DBG_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_dma.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_dma.h new file mode 100644 index 0000000000..d1584fc83a --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_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 n32g45x_dma.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_DMA_H__ +#define __N32G45X_DMA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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 /*__N32G45X_DMA_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_dvp.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_dvp.h new file mode 100644 index 0000000000..e1aa6bc4e9 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_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 n32g45x_dvp.h + * @author Nations + * @version v1.0.4 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#ifndef __N32G45X_DVP_H__ +#define __N32G45X_DVP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_eth.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_eth.h new file mode 100644 index 0000000000..4ff243d0ac --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_eth.h @@ -0,0 +1,1608 @@ +/***************************************************************************** + * 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 Ethernet functions. + * @file n32g45x_eth.h + * @author Nations + * @version v1.0.0 + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __N32G45X_ETH_H__ +#define __N32G45X_ETH_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup ETH + * @{ + */ + +/** @addtogroup ETH_Exported_Types + * @{ + */ + +/** + * @brief ETH MAC Init structure definition + * @note The user should not configure all the ETH_InitType structure's fields. + * By calling the ETH_InitStruct function the structures fields are set to their default values. + * Only the parameters that will be set to a non-default value should be configured. + */ +typedef struct +{ + uint32_t AutoNegotiation; /*!< Selects or not the AutoNegotiation mode for the external PHY + The AutoNegotiation allows an automatic setting of the Speed (10/100Mbps) + and the mode (half/full-duplex). + This parameter can be a value of @ref AutoNegotiation */ + + uint32_t Watchdog; /*!< Selects or not the Watchdog timer + When enabled, the MAC allows no more then 2048 bytes to be received. + When disabled, the MAC can receive up to 16384 bytes. + This parameter can be a value of @ref ETH_watchdog */ + + uint32_t Jabber; /*!< Selects or not Jabber timer + When enabled, the MAC allows no more then 2048 bytes to be sent. + When disabled, the MAC can send up to 16384 bytes. + This parameter can be a value of @ref Jabber */ + + uint32_t InterFrameGap; /*!< Selects the minimum IFG between frames during transmission + This parameter can be a value of @ref ETH_Inter_Frame_Gap */ + + uint32_t CarrierSense; /*!< Selects or not the Carrier Sense + This parameter can be a value of @ref ETH_Carrier_Sense */ + + uint32_t SpeedMode; /*!< Sets the Ethernet speed: 10/100 Mbps + This parameter can be a value of @ref SpeedMode */ + + uint32_t RxOwn; /*!< Selects or not the ReceiveOwn + ReceiveOwn allows the reception of frames when the TX_EN signal is asserted + in Half-Duplex mode + This parameter can be a value of @ref ETH_Receive_Own */ + + uint32_t LoopbackMode; /*!< Selects or not the internal MAC MII Loopback mode + This parameter can be a value of @ref ETH_Loop_Back_Mode */ + + uint32_t DuplexMode; /*!< Selects the MAC duplex mode: Half-Duplex or Full-Duplex mode + This parameter can be a value of @ref ETH_Duplex_Mode */ + + uint32_t ChecksumOffload; /*!< Selects or not the IPv4 checksum checking for received frame payloads' TCP/UDP/ICMP + headers. This parameter can be a value of @ref ETH_Checksum_Offload */ + + uint32_t RetryTransmission; /*!< Selects or not the MAC attempt retries transmission, based on the settings of BL, + when a colision occurs (Half-Duplex mode) + This parameter can be a value of @ref ETH_Retry_Transmission */ + + uint32_t AutomaticPadCRCStrip; /*!< Selects or not the Automatic MAC Pad/CRC Stripping + This parameter can be a value of @ref ETH_Automatic_Pad_CRC_Strip */ + + uint32_t BackoffLimit; /*!< Selects the BackOff limit value + This parameter can be a value of @ref ETH_Back_Off_Limit + This parameer only valid in ETH_DUPLEX_MODE_HALF mode*/ + + uint32_t DeferralCheck; /*!< Selects or not the deferral check function (Half-Duplex mode) + This parameter can be a value of @ref ETH_Deferral_Check */ + + uint32_t RxAll; /*!< Selects or not all frames reception by the MAC (No fitering) + This parameter can be a value of @ref ETH_Receive_All */ + + uint32_t SrcAddrFilter; /*!< Selects the Source Address Filter mode + This parameter can be a value of @ref ETH_Source_Addr_Filter */ + + uint32_t PassCtrlFrames; /*!< Sets the forwarding mode of the control frames (including unicast and multicast Pause + frames) This parameter can be a value of @ref ETH_Pass_Control_Frames */ + + uint32_t BroadcastFramesReception; /*!< Selects or not the reception of Broadcast Frames + This parameter can be a value of @ref ETH_Broadcast_Frames_Reception */ + + uint32_t DestAddrFilter; /*!< Sets the destination filter mode for both unicast and multicast frames + This parameter can be a value of @ref ETH_Destination_Addr_Filter */ + + uint32_t PromiscuousMode; /*!< Selects or not the Promiscuous Mode + This parameter can be a value of @ref ETH_Promiscuous_Mode */ + + uint32_t MulticastFramesFilter; /*!< Selects the Multicast Frames filter mode: + None/HashTableFilter/PerfectFilter/PerfectHashTableFilter + This parameter can be a value of @ref ETH_Multicast_Frames_Filter */ + + uint32_t UnicastFramesFilter; /*!< Selects the Unicast Frames filter mode: + HashTableFilter/PerfectFilter/PerfectHashTableFilter + This parameter can be a value of @ref ETH_Unicast_Frames_Filter */ + + uint32_t HashTableHigh; /*!< This field holds the higher 32 bits of Hash table. */ + + uint32_t HashTableLow; /*!< This field holds the lower 32 bits of Hash table. */ + + uint32_t PauseTime; /*!< This field holds the value to be used in the Pause Time field in the + transmit control frame */ + + uint32_t ZeroQuantaPause; /*!< Selects or not the automatic generation of Zero-Quanta Pause Control frames + This parameter can be a value of @ref ETH_Zero_Quanta_Pause */ + + uint32_t PauseLowThreshold; /*!< This field configures the threshold of the Pause to be checked for + automatic retransmission of Pause Frame + This parameter can be a value of @ref ETH_Pause_Low_Threshold */ + + uint32_t UnicastPauseFrameDetect; /*!< Selects or not the MAC detection of the Pause frames (with MAC Address0 + unicast address and unique multicast address) + This parameter can be a value of @ref ETH_Unicast_Pause_Frame_Detect */ + + uint32_t RxFlowCtrl; /*!< Enables or disables the MAC to decode the received Pause frame and + disable its transmitter for a specified time (Pause Time) + This parameter can be a value of @ref ETH_Receive_Flow_Control */ + + uint32_t TxFlowCtrl; /*!< Enables or disables the MAC to transmit Pause frames (Full-Duplex mode) + or the MAC back-pressure operation (Half-Duplex mode) + This parameter can be a value of @ref ETH_Transmit_Flow_Control */ + + uint32_t VLANTagComparison; /*!< Selects the 12-bit VLAN identifier or the complete 16-bit VLAN tag for + comparison and filtering + This parameter can be a value of @ref ETH_VLAN_Tag_Comparison */ + + uint32_t VLANTagIdentifier; /*!< Holds the VLAN tag identifier for receive frames */ + + uint32_t DropTCPIPChecksumErrorFrame; /*!< Selects or not the Dropping of TCP/IP Checksum Error Frames + This parameter can be a value of @ref + ETH_Drop_TCP_IP_Checksum_Error_Frame */ + + uint32_t RxStoreForward; /*!< Enables or disables the Receive store and forward mode + This parameter can be a value of @ref ETH_Receive_Store_Forward */ + + uint32_t FlushRxFrame; /*!< Enables or disables the flushing of received frames + This parameter can be a value of @ref ETH_Flush_Received_Frame */ + + uint32_t TxStoreForward; /*!< Enables or disables Transmit store and forward mode + This parameter can be a value of @ref ETH_Transmit_Store_Forward */ + + uint32_t TxThresholdCtrl; /*!< Selects or not the Transmit Threshold Control + This parameter can be a value of @ref ETH_Transmit_Threshold_Control */ + + uint32_t ForwardErrorFrames; /*!< Selects or not the forward to the DMA of erroneous frames + This parameter can be a value of @ref ETH_Forward_Error_Frames */ + + uint32_t ForwardUndersizedGoodFrames; /*!< Enables or disables the Rx DATFIFO to forward Undersized frames (frames + with no Error and length less than 64 bytes) including pad-bytes and CRC) + This parameter can be a value of @ref + ETH_Forward_Undersized_Good_Frames */ + + uint32_t RxThresholdCtrl; /*!< Selects the threshold level of the Receive DATFIFO + This parameter can be a value of @ref ETH_Receive_Threshold_Control */ + + uint32_t SecondFrameOperate; /*!< Selects or not the Operate on second frame mode, which allows the DMA to process a + second frame of Transmit data even before obtaining the status for the first frame. + This parameter can be a value of @ref ETH_Second_Frame_Operate */ + + uint32_t AddrAlignedBeats; /*!< Enables or disables the Address Aligned Beats + This parameter can be a value of @ref ETH_Address_Aligned_Beats */ + + uint32_t FixedBurst; /*!< Enables or disables the AHB Master interface fixed burst transfers + This parameter can be a value of @ref ETH_Fixed_Burst */ + + uint32_t RxDMABurstLen; /*!< Indicates the maximum number of beats to be transferred in one Rx DMA transaction + This parameter can be a value of @ref ETH_Rx_DMA_Burst_Length */ + + uint32_t TxDMABurstLen; /*!< Indicates sthe maximum number of beats to be transferred in one Tx DMA transaction + This parameter can be a value of @ref ETH_Tx_DMA_Burst_Length */ + + uint32_t DescSkipLen; /*!< Specifies the number of word to skip between two unchained descriptors (Ring mode) */ + + uint32_t DMAArbitration; /*!< Selects the DMA Tx/Rx arbitration + This parameter can be a value of @ref ETH_DMA_Arbitration */ +} ETH_InitType; + +/** + * @brief ETH DMA Desciptors data structure definition + */ +typedef struct +{ + uint32_t Status; /*!< Status */ + uint32_t CtrlOrBufSize; /*!< Control and Buffer1, Buffer2 lengths */ + uint32_t Buf1Addr; /*!< Buffer1 address pointer */ + uint32_t Buf2OrNextDescAddr; /*!< Buffer2 or next descriptor address pointer */ +} ETH_DMADescType; + +/** + * @} + */ + +/** @addtogroup ETH_Exported_Constants + * @{ + */ + +/** + * @addtogroup ETH_PHY_Registers + * @{ + */ +#define PHY_BCR 0 /*!< Tranceiver Basic Control Register */ +#define PHY_BSR 1 /*!< Tranceiver Basic Status Register */ + +#define PHY_RESET ((u16)0x8000) /*!< PHY Reset */ +#define PHY_LOOPBACK ((u16)0x4000) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((u16)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((u16)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((u16)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((u16)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGO ((u16)0x1000) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGO ((u16)0x0200) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((u16)0x0800) /*!< Select the power down mode */ +#define PHY_ISOLATE ((u16)0x0400) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((u16)0x0020) /*!< Auto-Negotioation process completed */ +#define PHY_LINKED_STATUS ((u16)0x0004) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((u16)0x0002) /*!< Jabber condition detected */ + +#define PHY_READ_TO ((uint32_t)0x0004FFFF) +#define PHY_WRITE_TO ((uint32_t)0x0004FFFF) + +#define IS_ETH_PHY_ADDRESS(ADDRESS) ((ADDRESS) < 0x20) +#define IS_ETH_PHY_REG(REG) ((REG) < 0x20) +/** + * @} + */ + +/** @addtogroup ENET_Buffers_setting + * @{ + */ +#define ETH_MAX_PACKET_SIZE 1520 /*!< ETH_HEADER + ETH_EXTRA + ETH_MAX_PAYLOAD + ETH_CRC */ +#define ETH_HEADER 14 /*!< 6 byte Dest addr, 6 byte Src addr, 2 byte length/type */ +#define ETH_CRC 4 /*!< Ethernet CRC */ +#define ETH_EXTRA 2 /*!< Extra bytes in some cases */ +#define ETH_VLAN_TAG 4 /*!< optional 802.1q VLAN Tag */ +#define ETH_MIN_PAYLOAD 46 /*!< Minimum Ethernet payload size */ +#define ETH_MAX_PAYLOAD 1500 /*!< Maximum Ethernet payload size */ +#define ETH_JUMBO_FRAME_PAYLOAD 9000 /*!< Jumbo frame payload size */ + +/* + DMA Tx Desciptor + ----------------------------------------------------------------------------------------------- + TDES0 | OWN(31) | Reserved[30:18] | Status[17:0] | + ----------------------------------------------------------------------------------------------- + TDES1 | Ctrl[31:22] | Buffer2 ByteCount[21:11] | Buffer1 ByteCount[10:0] | + ----------------------------------------------------------------------------------------------- + TDES2 | Buffer1 Address [31:0] | + ----------------------------------------------------------------------------------------------- + TDES3 | Buffer2 Address [31:0] / Next Desciptor Address [31:0] | + ----------------------------------------------------------------------------------------------- +*/ + +/* + * Bit definition of TDES0 register: DMA Tx descriptor status register + */ +#define ETH_DMA_TX_DESC_OWN ((uint32_t)0x80000000) /*!< OWN bit: descriptor is owned by DMA engine */ +#define ETH_DMA_TX_DESC_TTSS ((uint32_t)0x00020000) /*!< Tx Time Stamp Status */ +#define ETH_DMA_TX_DESC_IHE ((uint32_t)0x00010000) /*!< IP Header Error */ +#define ETH_DMA_TX_DESC_ES \ + ((uint32_t)0x00008000) /*!< Error summary: OR of the following bits: UE || ED || EC || LCO || NC || LCA || FF || \ + JT */ +#define ETH_DMA_TX_DESC_JT ((uint32_t)0x00004000) /*!< Jabber Timeout */ +#define ETH_DMA_TX_DESC_FF ((uint32_t)0x00002000) /*!< Frame Flushed: DMA/MTL flushed the frame due to SW flush */ +#define ETH_DMA_TX_DESC_PCE ((uint32_t)0x00001000) /*!< Payload Checksum Error */ +#define ETH_DMA_TX_DESC_LOC ((uint32_t)0x00000800) /*!< Loss of Carrier: carrier lost during tramsmission */ +#define ETH_DMA_TX_DESC_NC ((uint32_t)0x00000400) /*!< No Carrier: no carrier signal from the tranceiver */ +#define ETH_DMA_TX_DESC_LC ((uint32_t)0x00000200) /*!< Late Collision: transmission aborted due to collision */ +#define ETH_DMA_TX_DESC_EC ((uint32_t)0x00000100) /*!< Excessive Collision: transmission aborted after 16 collisions \ + */ +#define ETH_DMA_TX_DESC_VF ((uint32_t)0x00000080) /*!< VLAN Frame */ +#define ETH_DMA_TX_DESC_CC ((uint32_t)0x00000078) /*!< Collision Count */ +#define ETH_DMA_TX_DESC_ED ((uint32_t)0x00000004) /*!< Excessive Deferral */ +#define ETH_DMA_TX_DESC_UF ((uint32_t)0x00000002) /*!< Underflow Error: late data arrival from the memory */ +#define ETH_DMA_TX_DESC_DB ((uint32_t)0x00000001) /*!< Deferred Bit */ + +/* + * Bit definition of TDES1 register + */ +#define ETH_DMA_TX_DESC_IC ((uint32_t)0x80000000) /*!< Interrupt on Completion */ +#define ETH_DMA_TX_DESC_LS ((uint32_t)0x40000000) /*!< Last Segment */ +#define ETH_DMA_TX_DESC_FS ((uint32_t)0x20000000) /*!< First Segment */ + +#define ETH_DMA_TX_DESC_CIC ((uint32_t)0x18000000) /*!< Checksum Insertion Control: 4 cases */ +#define ETH_DMA_TX_DESC_CIC_BYPASS ((uint32_t)0x00000000) /*!< Do Nothing: Checksum Engine is bypassed */ +#define ETH_DMA_TX_DESC_CIC_IPV4_HEADER ((uint32_t)0x08000000) /*!< IPV4 header Checksum Insertion */ +#define ETH_DMA_TX_DESC_CIC_TCPUDPICMP_SEGMENT \ + ((uint32_t)0x10000000) /*!< TCP/UDP/ICMP Checksum Insertion calculated over segment only */ +#define ETH_DMA_TX_DESC_CIC_TCPUDPICMP_FULL \ + ((uint32_t)0x18000000) /*!< TCP/UDP/ICMP Checksum Insertion fully calculated */ + +#define ETH_DMA_TX_DESC_DC ((uint32_t)0x04000000) /*!< Disable CRC */ +#define ETH_DMA_TX_DESC_TER ((uint32_t)0x02000000) /*!< Transmit End of Ring */ +#define ETH_DMA_TX_DESC_TCH ((uint32_t)0x01000000) /*!< Second Address Chained */ +#define ETH_DMA_TX_DESC_DP ((uint32_t)0x00800000) /*!< Disable Padding */ +#define ETH_DMA_TX_DESC_TTSE ((uint32_t)0x00400000) /*!< Transmit Time Stamp Enable */ +#define ETH_DMA_TX_DESC_TBS2 ((uint32_t)0x003FF800) /*!< Transmit Buffer2 Size */ +#define ETH_DMA_TX_DESC_TBS1 ((uint32_t)0x000007FF) /*!< Transmit Buffer1 Size */ + +/* + * Bit definition of TDES2 register + */ +#define ETH_DMA_TX_DESC_B1ADDR ((uint32_t)0xFFFFFFFF) /*!< Buffer1 Address Pointer */ + +/* + * Bit definition of TDES3 register + */ +#define ETH_DMA_TX_DESC_B2ADDR ((uint32_t)0xFFFFFFFF) /*!< Buffer2 Address Pointer */ + +/** + * @} + */ + +/** @addtogroup DMA_Rx_descriptor + * @{ + */ + +/* + DMA Rx Desciptor + -------------------------------------------------------------------------------------------------------------------- + RDES0 | OWN(31) | Status [30:0] | + --------------------------------------------------------------------------------------------------------------------- + RDES1 | CTRL(31) | Reserved[30:26] | CTRL[25:24] | Reserved[23:22] | Buffer2 ByteCnt[21:11] | Buffer1 ByteCnt[10:0] | + --------------------------------------------------------------------------------------------------------------------- + RDES2 | Buffer1 Address [31:0] | + --------------------------------------------------------------------------------------------------------------------- + RDES3 | Buffer2 Address [31:0] / Next Desciptor Address [31:0] | + --------------------------------------------------------------------------------------------------------------------- +*/ + +/* + * Bit definition of RDES0 register: DMA Rx descriptor status register + */ +#define ETH_DMA_RX_DESC_OWN ((uint32_t)0x80000000) /*!< OWN bit: descriptor is owned by DMA engine */ +#define ETH_DMA_RX_DESC_AFM ((uint32_t)0x40000000) /*!< DA Filter Fail for the rx frame */ +#define ETH_DMA_RX_DESC_FL ((uint32_t)0x3FFF0000) /*!< Receive descriptor frame length */ +#define ETH_DMA_RX_DESC_ES \ + ((uint32_t)0x00008000) /*!< Error summary: OR of the following bits: DE || OE || IPC || LC || RWT || RE || CE */ +#define ETH_DMA_RX_DESC_DE ((uint32_t)0x00004000) /*!< Desciptor error: no more descriptors for receive frame */ +#define ETH_DMA_RX_DESC_SAF ((uint32_t)0x00002000) /*!< SA Filter Fail for the received frame */ +#define ETH_DMA_RX_DESC_LE ((uint32_t)0x00001000) /*!< Frame size not matching with length field */ +#define ETH_DMA_RX_DESC_OE ((uint32_t)0x00000800) /*!< Overflow Error: Frame was damaged due to buffer overflow */ +#define ETH_DMA_RX_DESC_VLAN ((uint32_t)0x00000400) /*!< VLAN Tag: received frame is a VLAN frame */ +#define ETH_DMA_RX_DESC_FS ((uint32_t)0x00000200) /*!< First descriptor of the frame */ +#define ETH_DMA_RX_DESC_LS ((uint32_t)0x00000100) /*!< Last descriptor of the frame */ +#define ETH_DMA_RX_DESC_IPV4HCE ((uint32_t)0x00000080) /*!< IPC Checksum Error: Rx Ipv4 header checksum error */ +#define ETH_DMA_RX_DESC_LC ((uint32_t)0x00000040) /*!< Late collision occurred during reception */ +#define ETH_DMA_RX_DESC_FT ((uint32_t)0x00000020) /*!< Frame type - Ethernet, otherwise 802.3 */ +#define ETH_DMA_RX_DESC_RWT \ + ((uint32_t)0x00000010) /*!< Receive Watchdog Timeout: watchdog timer expired during reception */ +#define ETH_DMA_RX_DESC_RE ((uint32_t)0x00000008) /*!< Receive error: error reported by MII interface */ +#define ETH_DMA_RX_DESC_DBE ((uint32_t)0x00000004) /*!< Dribble bit error: frame contains non int multiple of 8 bits \ + */ +#define ETH_DMA_RX_DESC_CE ((uint32_t)0x00000002) /*!< CRC error */ +#define ETH_DMA_RX_DESC_RMAPCE \ + ((uint32_t)0x00000001) /*!< Rx MAC Address/Payload Checksum Error: Rx MAC address matched/ Rx Payload Checksum \ + Error */ + +/* + * Bit definition of RDES1 register + */ +#define ETH_DMA_RX_DESC_DIC ((uint32_t)0x80000000) /*!< Disable Interrupt on Completion */ +#define ETH_DMA_RX_DESC_RBS2 ((uint32_t)0x003FF800) /*!< Receive Buffer2 Size */ +#define ETH_DMA_RX_DESC_RER ((uint32_t)0x02000000) /*!< Receive End of Ring */ +#define ETH_DMA_RX_DESC_RCH ((uint32_t)0x01000000) /*!< Second Address Chained */ +#define ETH_DMA_RX_DESC_RBS1 ((uint32_t)0x000007FF) /*!< Receive Buffer1 Size */ + +/* + * Bit definition of RDES2 register + */ +#define ETH_DMA_RX_DESC_B1ADDR ((uint32_t)0xFFFFFFFF) /*!< Buffer1 Address Pointer */ + +/* + * Bit definition of RDES3 register + */ +#define ETH_DMA_RX_DESC_B2ADDR ((uint32_t)0xFFFFFFFF) /*!< Buffer2 Address Pointer */ + +/** + * @} + */ + +/** @addtogroup AutoNegotiation + * @{ + */ +#define ETH_AUTONEG_ENABLE ((uint32_t)0x00000001) +#define ETH_AUTONEG_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_AUTONEG(CMDCTRL) (((CMDCTRL) == ETH_AUTONEG_ENABLE) || ((CMDCTRL) == ETH_AUTONEG_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_watchdog + * @{ + */ +#define ETH_WATCHDOG_ENABLE ((uint32_t)0x00000000) +#define ETH_WATCHDOG_DISABLE ((uint32_t)0x00800000) +#define IS_ETH_WATCHDOG(CMDCTRL) (((CMDCTRL) == ETH_WATCHDOG_ENABLE) || ((CMDCTRL) == ETH_WATCHDOG_DISABLE)) + +/** + * @} + */ + +/** @addtogroup Jabber + * @{ + */ +#define ETH_JABBER_ENABLE ((uint32_t)0x00000000) +#define ETH_JABBER_DISABLE ((uint32_t)0x00400000) +#define IS_ETH_JABBER(CMDCTRL) (((CMDCTRL) == ETH_JABBER_ENABLE) || ((CMDCTRL) == ETH_JABBER_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Inter_Frame_Gap + * @{ + */ +#define ETH_INTER_FRAME_GAP_96BIT ((uint32_t)0x00000000) /*!< minimum IFG between frames during transmission is 96Bit \ + */ +#define ETH_INTER_FRAME_GAP_88BIT ((uint32_t)0x00020000) /*!< minimum IFG between frames during transmission is 88Bit \ + */ +#define ETH_INTER_FRAME_GAP_80BIT ((uint32_t)0x00040000) /*!< minimum IFG between frames during transmission is 80Bit \ + */ +#define ETH_INTER_FRAME_GAP_72BIT ((uint32_t)0x00060000) /*!< minimum IFG between frames during transmission is 72Bit \ + */ +#define ETH_INTER_FRAME_GAP_64BIT ((uint32_t)0x00080000) /*!< minimum IFG between frames during transmission is 64Bit \ + */ +#define ETH_INTER_FRAME_GAP_56BIT ((uint32_t)0x000A0000) /*!< minimum IFG between frames during transmission is 56Bit \ + */ +#define ETH_INTER_FRAME_GAP_48BIT ((uint32_t)0x000C0000) /*!< minimum IFG between frames during transmission is 48Bit \ + */ +#define ETH_INTER_FRAME_GAP_40BIT ((uint32_t)0x000E0000) /*!< minimum IFG between frames during transmission is 40Bit \ + */ +#define IS_ETH_INTER_FRAME_GAP(GAP) \ + (((GAP) == ETH_INTER_FRAME_GAP_96BIT) || ((GAP) == ETH_INTER_FRAME_GAP_88BIT) \ + || ((GAP) == ETH_INTER_FRAME_GAP_80BIT) || ((GAP) == ETH_INTER_FRAME_GAP_72BIT) \ + || ((GAP) == ETH_INTER_FRAME_GAP_64BIT) || ((GAP) == ETH_INTER_FRAME_GAP_56BIT) \ + || ((GAP) == ETH_INTER_FRAME_GAP_48BIT) || ((GAP) == ETH_INTER_FRAME_GAP_40BIT)) + +/** + * @} + */ + +/** @addtogroup ETH_Carrier_Sense + * @{ + */ +#define ETH_CARRIER_SENSE_ENABLE ((uint32_t)0x00000000) +#define ETH_CARRIER_SENSE_DISABLE ((uint32_t)0x00010000) +#define IS_ETH_CARRIER_SENSE(CMDCTRL) \ + (((CMDCTRL) == ETH_CARRIER_SENSE_ENABLE) || ((CMDCTRL) == ETH_CARRIER_SENSE_DISABLE)) + +/** + * @} + */ + +/** @addtogroup SpeedMode + * @{ + */ +#define ETH_SPEED_MODE_10M ((uint32_t)0x00000000) +#define ETH_SPEED_MODE_100M ((uint32_t)0x00004000) +#define IS_ETH_SPEED_MODE(SPEED) (((SPEED) == ETH_SPEED_MODE_10M) || ((SPEED) == ETH_SPEED_MODE_100M)) + +/** + * @} + */ + +/** @addtogroup ETH_Receive_Own + * @{ + */ +#define ETH_RX_OWN_ENABLE ((uint32_t)0x00000000) +#define ETH_RX_OWN_DISABLE ((uint32_t)0x00002000) +#define IS_ETH_RX_OWN(CMDCTRL) (((CMDCTRL) == ETH_RX_OWN_ENABLE) || ((CMDCTRL) == ETH_RX_OWN_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Loop_Back_Mode + * @{ + */ +#define ETH_LOOPBACK_MODE_ENABLE ((uint32_t)0x00001000) +#define ETH_LOOPBACK_MODE_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_LOOPBACK_MODE(CMDCTRL) \ + (((CMDCTRL) == ETH_LOOPBACK_MODE_ENABLE) || ((CMDCTRL) == ETH_LOOPBACK_MODE_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Duplex_Mode + * @{ + */ +#define ETH_DUPLEX_MODE_FULL ((uint32_t)0x00000800) +#define ETH_DUPLEX_MODE_HALF ((uint32_t)0x00000000) +#define IS_ETH_DUPLEX_MODE(MODE) (((MODE) == ETH_DUPLEX_MODE_FULL) || ((MODE) == ETH_DUPLEX_MODE_HALF)) + +/** + * @} + */ + +/** @addtogroup ETH_Checksum_Offload + * @{ + */ +#define ETH_CHECKSUM_OFFLOAD_ENABLE ((uint32_t)0x00000400) +#define ETH_CHECKSUM_OFFLOAD_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_CHECKSUM_OFFLOAD(CMDCTRL) \ + (((CMDCTRL) == ETH_CHECKSUM_OFFLOAD_ENABLE) || ((CMDCTRL) == ETH_CHECKSUM_OFFLOAD_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Retry_Transmission + * @{ + */ +#define ETH_RETRY_TRANSMISSION_ENABLE ((uint32_t)0x00000000) +#define ETH_RETRY_TRANSMISSION_DISABLE ((uint32_t)0x00000200) +#define IS_ETH_RETRY_TRANSMISSION(CMDCTRL) \ + (((CMDCTRL) == ETH_RETRY_TRANSMISSION_ENABLE) || ((CMDCTRL) == ETH_RETRY_TRANSMISSION_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Automatic_Pad_CRC_Strip + * @{ + */ +#define ETH_AUTO_PAD_CRC_STRIP_ENABLE ((uint32_t)0x00000080) +#define ETH_AUTO_PAD_CRC_STRIP_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_AUTO_PAD_CRC_STRIP(CMDCTRL) \ + (((CMDCTRL) == ETH_AUTO_PAD_CRC_STRIP_ENABLE) || ((CMDCTRL) == ETH_AUTO_PAD_CRC_STRIP_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Back_Off_Limit + * @{ + */ +#define ETH_BACKOFF_LIMIT_10 ((uint32_t)0x00000000) +#define ETH_BACKOFF_LIMIT_8 ((uint32_t)0x00000020) +#define ETH_BACKOFF_LIMIT_4 ((uint32_t)0x00000040) +#define ETH_BACKOFF_LIMIT_1 ((uint32_t)0x00000060) +#define IS_ETH_BACKOFF_LIMIT(LIMIT) \ + (((LIMIT) == ETH_BACKOFF_LIMIT_10) || ((LIMIT) == ETH_BACKOFF_LIMIT_8) || ((LIMIT) == ETH_BACKOFF_LIMIT_4) \ + || ((LIMIT) == ETH_BACKOFF_LIMIT_1)) + +/** + * @} + */ + +/** @addtogroup ETH_Deferral_Check + * @{ + */ +#define ETH_DEFERRAL_CHECK_ENABLE ((uint32_t)0x00000010) +#define ETH_DEFERRAL_CHECK_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_DEFERRAL_CHECK(CMDCTRL) \ + (((CMDCTRL) == ETH_DEFERRAL_CHECK_ENABLE) || ((CMDCTRL) == ETH_DEFERRAL_CHECK_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Receive_All + * @{ + */ +#define ETH_RX_ALL_ENABLE ((uint32_t)0x80000000) +#define ETH_RX_ALL_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_RX_ALL(CMDCTRL) (((CMDCTRL) == ETH_RX_ALL_ENABLE) || ((CMDCTRL) == ETH_RX_ALL_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Source_Addr_Filter + * @{ + */ +#define ETH_SRC_ADDR_FILTER_NORMAL_ENABLE ((uint32_t)0x00000200) +#define ETH_SRC_ADDR_FILTER_INVERSE_ENABLE ((uint32_t)0x00000300) +#define ETH_SRC_ADDR_FILTER_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_SRC_ADDR_FILTER(CMDCTRL) \ + (((CMDCTRL) == ETH_SRC_ADDR_FILTER_NORMAL_ENABLE) || ((CMDCTRL) == ETH_SRC_ADDR_FILTER_INVERSE_ENABLE) \ + || ((CMDCTRL) == ETH_SRC_ADDR_FILTER_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Pass_Control_Frames + * @{ + */ +#define ETH_PASS_CTRL_FRAMES_BLOCK_ALL \ + ((uint32_t)0x00000040) /*!< MAC filters all control frames from reaching the application */ +#define ETH_PASS_CTRL_FRAMES_FORWARD_ALL \ + ((uint32_t)0x00000080) /*!< MAC forwards all control frames to application even if they fail the Address Filter */ +#define ETH_PASS_CTRL_FRAMES_FORWARD_PASSED_ADDR_FILTER \ + ((uint32_t)0x000000C0) /*!< MAC forwards control frames that pass the Address Filter. */ +#define IS_ETH_PASS_CTRL_FRAMES(PASS) \ + (((PASS) == ETH_PASS_CTRL_FRAMES_BLOCK_ALL) || ((PASS) == ETH_PASS_CTRL_FRAMES_FORWARD_ALL) \ + || ((PASS) == ETH_PASS_CTRL_FRAMES_FORWARD_PASSED_ADDR_FILTER)) + +/** + * @} + */ + +/** @addtogroup ETH_Broadcast_Frames_Reception + * @{ + */ +#define ETH_BROADCAST_FRAMES_RECEPTION_ENABLE ((uint32_t)0x00000000) +#define ETH_BROADCAST_FRAMES_RECEPTION_DISABLE ((uint32_t)0x00000020) +#define IS_ETH_BROADCAST_FRAMES_RECEPTION(CMDCTRL) \ + (((CMDCTRL) == ETH_BROADCAST_FRAMES_RECEPTION_ENABLE) || ((CMDCTRL) == ETH_BROADCAST_FRAMES_RECEPTION_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Destination_Addr_Filter + * @{ + */ +#define ETH_DEST_ADDR_FILTER_NORMAL ((uint32_t)0x00000000) +#define ETH_DEST_ADDR_FILTER_INVERSE ((uint32_t)0x00000008) +#define IS_ETH_DEST_ADDR_FILTER(FILTER) \ + (((FILTER) == ETH_DEST_ADDR_FILTER_NORMAL) || ((FILTER) == ETH_DEST_ADDR_FILTER_INVERSE)) + +/** + * @} + */ + +/** @addtogroup ETH_Promiscuous_Mode + * @{ + */ +#define ETH_PROMISCUOUS_MODE_ENABLE ((uint32_t)0x00000001) +#define ETH_PROMISCUOUS_MODE_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_PROMISCUOUS_MODE(CMDCTRL) \ + (((CMDCTRL) == ETH_PROMISCUOUS_MODE_ENABLE) || ((CMDCTRL) == ETH_PROMISCUOUS_MODE_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Multicast_Frames_Filter + * @{ + */ +#define ETH_MULTICAST_FRAMES_FILTER_PERFECT_HASH_TABLE ((uint32_t)0x00000404) +#define ETH_MULTICAST_FRAMES_FILTER_HASH_TABLE ((uint32_t)0x00000004) +#define ETH_MULTICAST_FRAMES_FILTER_PERFECT ((uint32_t)0x00000000) +#define ETH_MULTICAST_FRAMES_FILTER_NONE ((uint32_t)0x00000010) +#define IS_ETH_MULTICAST_FRAMES_FILTER(FILTER) \ + (((FILTER) == ETH_MULTICAST_FRAMES_FILTER_PERFECT_HASH_TABLE) \ + || ((FILTER) == ETH_MULTICAST_FRAMES_FILTER_HASH_TABLE) || ((FILTER) == ETH_MULTICAST_FRAMES_FILTER_PERFECT) \ + || ((FILTER) == ETH_MULTICAST_FRAMES_FILTER_NONE)) + +/** + * @} + */ + +/** @addtogroup ETH_Unicast_Frames_Filter + * @{ + */ +#define ETH_UNICAST_FRAMES_FILTER_PERFECTHASHTABLE ((uint32_t)0x00000402) +#define ETH_UNICAST_FRAMES_FILTER_HASHTABLE ((uint32_t)0x00000002) +#define ETH_UNICAST_FRAMES_FILTER_PERFECT ((uint32_t)0x00000000) +#define IS_ETH_UNICAST_FRAMES_FILTER(FILTER) \ + (((FILTER) == ETH_UNICAST_FRAMES_FILTER_PERFECTHASHTABLE) || ((FILTER) == ETH_UNICAST_FRAMES_FILTER_HASHTABLE) \ + || ((FILTER) == ETH_UNICAST_FRAMES_FILTER_PERFECT)) + +/** + * @} + */ + +/** @addtogroup ETH_Pause_Time + * @{ + */ +#define IS_ETH_PAUSE_TIME(TIME) ((TIME) <= 0xFFFF) + +/** + * @} + */ + +/** @addtogroup ETH_Zero_Quanta_Pause + * @{ + */ +#define ETH_ZERO_QUANTA_PAUSE_ENABLE ((uint32_t)0x00000000) +#define ETH_ZERO_QUANTA_PAUSE_DISABLE ((uint32_t)0x00000080) +#define IS_ETH_ZERO_QUANTA_PAUSE(CMDCTRL) \ + (((CMDCTRL) == ETH_ZERO_QUANTA_PAUSE_ENABLE) || ((CMDCTRL) == ETH_ZERO_QUANTA_PAUSE_DISABLE)) +/** + * @} + */ + +/** @addtogroup ETH_Pause_Low_Threshold + * @{ + */ +#define ETH_PAUSE_LOW_THRESHOLD_MINUS4 ((uint32_t)0x00000000) /*!< Pause time minus 4 slot times */ +#define ETH_PAUSE_LOW_THRESHOLD_MINUS28 ((uint32_t)0x00000010) /*!< Pause time minus 28 slot times */ +#define ETH_PAUSE_LOW_THRESHOLD_MINUS144 ((uint32_t)0x00000020) /*!< Pause time minus 144 slot times */ +#define ETH_PAUSE_LOW_THRESHOLD_MINUS256 ((uint32_t)0x00000030) /*!< Pause time minus 256 slot times */ +#define IS_ETH_PAUSE_LOW_THRESHOLD(THRESHOLD) \ + (((THRESHOLD) == ETH_PAUSE_LOW_THRESHOLD_MINUS4) || ((THRESHOLD) == ETH_PAUSE_LOW_THRESHOLD_MINUS28) \ + || ((THRESHOLD) == ETH_PAUSE_LOW_THRESHOLD_MINUS144) || ((THRESHOLD) == ETH_PAUSE_LOW_THRESHOLD_MINUS256)) + +/** + * @} + */ + +/** @addtogroup ETH_Unicast_Pause_Frame_Detect + * @{ + */ +#define ETH_UNICAST_PAUSE_FRAME_DETECT_ENABLE ((uint32_t)0x00000008) +#define ETH_UNICAST_PAUSE_FRAME_DETECT_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_UNICAST_PAUSE_FRAME_DETECT(CMDCTRL) \ + (((CMDCTRL) == ETH_UNICAST_PAUSE_FRAME_DETECT_ENABLE) || ((CMDCTRL) == ETH_UNICAST_PAUSE_FRAME_DETECT_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Receive_Flow_Control + * @{ + */ +#define ETH_RX_FLOW_CTRL_ENABLE ((uint32_t)0x00000004) +#define ETH_RX_FLOW_CTRL_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_RX_FLOW_CTRL(CMDCTRL) (((CMDCTRL) == ETH_RX_FLOW_CTRL_ENABLE) || ((CMDCTRL) == ETH_RX_FLOW_CTRL_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Transmit_Flow_Control + * @{ + */ +#define ETH_TX_FLOW_CTRL_ENABLE ((uint32_t)0x00000002) +#define ETH_TX_FLOW_CTRL_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_TX_FLOW_CTRL(CMDCTRL) (((CMDCTRL) == ETH_TX_FLOW_CTRL_ENABLE) || ((CMDCTRL) == ETH_TX_FLOW_CTRL_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_VLAN_Tag_Comparison + * @{ + */ +#define ETH_VLAN_TAG_COMPARISON_12BIT ((uint32_t)0x00010000) +#define ETH_VLAN_TAG_COMPARISON_16BIT ((uint32_t)0x00000000) +#define IS_ETH_VLAN_TAG_COMPARISON(COMPARISON) \ + (((COMPARISON) == ETH_VLAN_TAG_COMPARISON_12BIT) || ((COMPARISON) == ETH_VLAN_TAG_COMPARISON_16BIT)) +#define IS_ETH_VLAN_TAG_IDENTIFIER(IDENTIFIER) ((IDENTIFIER) <= 0xFFFF) + +/** + * @} + */ + +/** @addtogroup ETH_MAC_Flags + * @{ + */ +#define ETH_MAC_FLAG_TST ((uint32_t)0x00000200) /*!< Time stamp trigger flag (on MAC) */ +#define ETH_MAC_FLAG_MMCTX ((uint32_t)0x00000040) /*!< MMC transmit flag */ +#define ETH_MAC_FLAG_MMCRX ((uint32_t)0x00000020) /*!< MMC receive flag */ +#define ETH_MAC_FLAG_MMC ((uint32_t)0x00000010) /*!< MMC flag (on MAC) */ +#define ETH_MAC_FLAG_PMT ((uint32_t)0x00000008) /*!< PMT flag (on MAC) */ +#define IS_ETH_MAC_GET_FLAG(FLAG) \ + (((FLAG) == ETH_MAC_FLAG_TST) || ((FLAG) == ETH_MAC_FLAG_MMCTX) || ((FLAG) == ETH_MAC_FLAG_MMCRX) \ + || ((FLAG) == ETH_MAC_FLAG_MMC) || ((FLAG) == ETH_MAC_FLAG_PMT)) +/** + * @} + */ + +/** @addtogroup ETH_MAC_Interrupts + * @{ + */ +#define ETH_MAC_INT_TST ((uint32_t)0x00000200) /*!< Time stamp trigger interrupt (on MAC) */ +#define ETH_MAC_INT_MMCTX ((uint32_t)0x00000040) /*!< MMC transmit interrupt */ +#define ETH_MAC_INT_MMCRX ((uint32_t)0x00000020) /*!< MMC receive interrupt */ +#define ETH_MAC_INT_MMC ((uint32_t)0x00000010) /*!< MMC interrupt (on MAC) */ +#define ETH_MAC_INT_PMT ((uint32_t)0x00000008) /*!< PMT interrupt (on MAC) */ +#define IS_ETH_MAC_INT(IT) ((((IT) & (uint32_t)0xFFFFFDF7) == 0x00) && ((IT) != 0x00)) +#define IS_ETH_MAC_GET_INT(IT) \ + (((IT) == ETH_MAC_INT_TST) || ((IT) == ETH_MAC_INT_MMCTX) || ((IT) == ETH_MAC_INT_MMCRX) \ + || ((IT) == ETH_MAC_INT_MMC) || ((IT) == ETH_MAC_INT_PMT)) +/** + * @} + */ + +/** @addtogroup ETH_MAC_addresses + * @{ + */ +#define ETH_MAC_ADDR0 ((uint32_t)0x00000000) +#define ETH_MAC_ADDR1 ((uint32_t)0x00000008) +#define ETH_MAC_ADDR2 ((uint32_t)0x00000010) +#define ETH_MAC_ADDR3 ((uint32_t)0x00000018) +#define IS_ETH_MAC_ADDR0123(ADDRESS) \ + (((ADDRESS) == ETH_MAC_ADDR0) || ((ADDRESS) == ETH_MAC_ADDR1) || ((ADDRESS) == ETH_MAC_ADDR2) \ + || ((ADDRESS) == ETH_MAC_ADDR3)) +#define IS_ETH_MAC_ADDR123(ADDRESS) \ + (((ADDRESS) == ETH_MAC_ADDR1) || ((ADDRESS) == ETH_MAC_ADDR2) || ((ADDRESS) == ETH_MAC_ADDR3)) +/** + * @} + */ + +/** @addtogroup ETH_MAC_addresses_filter_SA_DA_filed_of_received_frames + * @{ + */ +#define ETH_MAC_ADDR_FILTER_SA ((uint32_t)0x00000000) +#define ETH_MAC_ADDR_FILTER_DA ((uint32_t)0x00000008) +#define IS_ETH_MAC_ADDR_FILTER(FILTER) (((FILTER) == ETH_MAC_ADDR_FILTER_SA) || ((FILTER) == ETH_MAC_ADDR_FILTER_DA)) +/** + * @} + */ + +/** @addtogroup ETH_MAC_addresses_filter_Mask_bytes + * @{ + */ +#define ETH_MAC_ADDR_MASK_BYTE6 ((uint32_t)0x20000000) /*!< Mask MAC Address high reg bits [15:8] */ +#define ETH_MAC_ADDR_MASK_BYTE5 ((uint32_t)0x10000000) /*!< Mask MAC Address high reg bits [7:0] */ +#define ETH_MAC_ADDR_MASK_BYTE4 ((uint32_t)0x08000000) /*!< Mask MAC Address low reg bits [31:24] */ +#define ETH_MAC_ADDR_MASK_BYTE3 ((uint32_t)0x04000000) /*!< Mask MAC Address low reg bits [23:16] */ +#define ETH_MAC_ADDR_MASK_BYTE2 ((uint32_t)0x02000000) /*!< Mask MAC Address low reg bits [15:8] */ +#define ETH_MAC_ADDR_MASK_BYTE1 ((uint32_t)0x01000000) /*!< Mask MAC Address low reg bits [70] */ +#define IS_ETH_MAC_ADDR_MASK(INTEN) \ + (((INTEN) == ETH_MAC_ADDR_MASK_BYTE6) || ((INTEN) == ETH_MAC_ADDR_MASK_BYTE5) \ + || ((INTEN) == ETH_MAC_ADDR_MASK_BYTE4) || ((INTEN) == ETH_MAC_ADDR_MASK_BYTE3) \ + || ((INTEN) == ETH_MAC_ADDR_MASK_BYTE2) || ((INTEN) == ETH_MAC_ADDR_MASK_BYTE1)) + +/** + * @} + */ + +/** @addtogroup ETH_DMA_Tx_descriptor_flags + * @{ + */ +#define IS_ETH_DMATXDESC_GET_FLAG(FLAG) \ + (((FLAG) == ETH_DMA_TX_DESC_OWN) || ((FLAG) == ETH_DMA_TX_DESC_IC) || ((FLAG) == ETH_DMA_TX_DESC_LS) \ + || ((FLAG) == ETH_DMA_TX_DESC_FS) || ((FLAG) == ETH_DMA_TX_DESC_DC) || ((FLAG) == ETH_DMA_TX_DESC_DP) \ + || ((FLAG) == ETH_DMA_TX_DESC_TTSE) || ((FLAG) == ETH_DMA_TX_DESC_TER) || ((FLAG) == ETH_DMA_TX_DESC_TCH) \ + || ((FLAG) == ETH_DMA_TX_DESC_TTSS) || ((FLAG) == ETH_DMA_TX_DESC_IHE) || ((FLAG) == ETH_DMA_TX_DESC_ES) \ + || ((FLAG) == ETH_DMA_TX_DESC_JT) || ((FLAG) == ETH_DMA_TX_DESC_FF) || ((FLAG) == ETH_DMA_TX_DESC_PCE) \ + || ((FLAG) == ETH_DMA_TX_DESC_LOC) || ((FLAG) == ETH_DMA_TX_DESC_NC) || ((FLAG) == ETH_DMA_TX_DESC_LC) \ + || ((FLAG) == ETH_DMA_TX_DESC_EC) || ((FLAG) == ETH_DMA_TX_DESC_VF) || ((FLAG) == ETH_DMA_TX_DESC_CC) \ + || ((FLAG) == ETH_DMA_TX_DESC_ED) || ((FLAG) == ETH_DMA_TX_DESC_UF) || ((FLAG) == ETH_DMA_TX_DESC_DB)) + +/** + * @} + */ + +/** @addtogroup ETH_DMA_Tx_descriptor_segment + * @{ + */ +#define ETH_DMA_TX_DESC_LAST_SEGMENT ((uint32_t)0x40000000) /*!< Last Segment */ +#define ETH_DMA_TX_DESC_FIRST_SEGMENT ((uint32_t)0x20000000) /*!< First Segment */ +#define IS_ETH_DMA_TX_DESC_SEGMENT(SEGMENT) \ + (((SEGMENT) == ETH_DMA_TX_DESC_LAST_SEGMENT) || ((SEGMENT) == ETH_DMA_TX_DESC_FIRST_SEGMENT)) + +/** + * @} + */ + +/** @addtogroup ETH_DMA_Tx_descriptor_Checksum_Insertion_Control + * @{ + */ +#define ETH_DMA_TX_DESC_CHECKSUM_BYPASS ((uint32_t)0x00000000) /*!< Checksum engine bypass */ +#define ETH_DMA_TX_DESC_CHECKSUM_IPV4_HEADER ((uint32_t)0x08000000) /*!< IPv4 header checksum insertion */ +#define ETH_DMA_TX_DESC_CHECKSUM_TCPUDPICMP_SEGMENT \ + ((uint32_t)0x10000000) /*!< TCP/UDP/ICMP checksum insertion. Pseudo header checksum is assumed to be present */ +#define ETH_DMA_TX_DESC_CHECKSUM_TCPUDPICMP_FULL \ + ((uint32_t)0x18000000) /*!< TCP/UDP/ICMP checksum fully in hardware including pseudo header */ +#define IS_ETH_DMA_TX_DESC_CHECKSUM(CHECKSUM) \ + (((CHECKSUM) == ETH_DMA_TX_DESC_CHECKSUM_BYPASS) || ((CHECKSUM) == ETH_DMA_TX_DESC_CHECKSUM_IPV4_HEADER) \ + || ((CHECKSUM) == ETH_DMA_TX_DESC_CHECKSUM_TCPUDPICMP_SEGMENT) \ + || ((CHECKSUM) == ETH_DMA_TX_DESC_CHECKSUM_TCPUDPICMP_FULL)) + +#define IS_ETH_DMA_TX_DESC_BUFFER_SIZE(SIZE) ((SIZE) <= 0x1FFF) + +/** + * @} + */ + +/** @addtogroup ETH_DMA_Rx_descriptor_flags + * @{ + */ +#define IS_ETH_DMA_RX_DESC_GET_FLAG(FLAG) \ + (((FLAG) == ETH_DMA_RX_DESC_OWN) || ((FLAG) == ETH_DMA_RX_DESC_AFM) || ((FLAG) == ETH_DMA_RX_DESC_ES) \ + || ((FLAG) == ETH_DMA_RX_DESC_DE) || ((FLAG) == ETH_DMA_RX_DESC_SAF) || ((FLAG) == ETH_DMA_RX_DESC_LE) \ + || ((FLAG) == ETH_DMA_RX_DESC_OE) || ((FLAG) == ETH_DMA_RX_DESC_VLAN) || ((FLAG) == ETH_DMA_RX_DESC_FS) \ + || ((FLAG) == ETH_DMA_RX_DESC_LS) || ((FLAG) == ETH_DMA_RX_DESC_IPV4HCE) || ((FLAG) == ETH_DMA_RX_DESC_LC) \ + || ((FLAG) == ETH_DMA_RX_DESC_FT) || ((FLAG) == ETH_DMA_RX_DESC_RWT) || ((FLAG) == ETH_DMA_RX_DESC_RE) \ + || ((FLAG) == ETH_DMA_RX_DESC_DBE) || ((FLAG) == ETH_DMA_RX_DESC_CE) || ((FLAG) == ETH_DMA_RX_DESC_RMAPCE)) + +/** + * @} + */ + +/** @addtogroup ETH_DMA_Rx_descriptor_buffers_ + * @{ + */ +#define ETH_DMA_RX_DESC_BUFFER1 ((uint32_t)0x00000000) /*!< DMA Rx Desc Buffer1 */ +#define ETH_DMA_RX_DESC_BUFFER2 ((uint32_t)0x00000001) /*!< DMA Rx Desc Buffer2 */ +#define IS_ETH_DMA_RXDESC_BUFFER(BUFFER) \ + (((BUFFER) == ETH_DMA_RX_DESC_BUFFER1) || ((BUFFER) == ETH_DMA_RX_DESC_BUFFER2)) + +/** + * @} + */ + +/** @addtogroup ETH_Drop_TCP_IP_Checksum_Error_Frame + * @{ + */ +#define ETH_DROP_TCPIP_CHECKSUM_ERROR_FRAME_ENABLE ((uint32_t)0x00000000) +#define ETH_DROP_TCPIP_CHECKSUM_ERROR_FRAME_DISABLE ((uint32_t)0x04000000) +#define IS_ETH_DROP_TCPIP_CHECKSUM_FRAME(CMDCTRL) \ + (((CMDCTRL) == ETH_DROP_TCPIP_CHECKSUM_ERROR_FRAME_ENABLE) \ + || ((CMDCTRL) == ETH_DROP_TCPIP_CHECKSUM_ERROR_FRAME_DISABLE)) +/** + * @} + */ + +/** @addtogroup ETH_Receive_Store_Forward + * @{ + */ +#define ETH_RX_STORE_FORWARD_ENABLE ((uint32_t)0x02000000) +#define ETH_RX_STORE_FORWARD_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_RX_STORE_FORWARD(CMDCTRL) \ + (((CMDCTRL) == ETH_RX_STORE_FORWARD_ENABLE) || ((CMDCTRL) == ETH_RX_STORE_FORWARD_DISABLE)) +/** + * @} + */ + +/** @addtogroup ETH_Flush_Received_Frame + * @{ + */ +#define ETH_FLUSH_RX_FRAME_ENABLE ((uint32_t)0x00000000) +#define ETH_FLUSH_RX_FRAME_DISABLE ((uint32_t)0x01000000) +#define IS_ETH_FLUSH_RX_FRAME(CMDCTRL) \ + (((CMDCTRL) == ETH_FLUSH_RX_FRAME_ENABLE) || ((CMDCTRL) == ETH_FLUSH_RX_FRAME_DISABLE)) +/** + * @} + */ + +/** @addtogroup ETH_Transmit_Store_Forward + * @{ + */ +#define ETH_TX_STORE_FORWARD_ENABLE ((uint32_t)0x00200000) +#define ETH_TX_STORE_FORWARD_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_TX_STORE_FORWARD(CMDCTRL) \ + (((CMDCTRL) == ETH_TX_STORE_FORWARD_ENABLE) || ((CMDCTRL) == ETH_TX_STORE_FORWARD_DISABLE)) +/** + * @} + */ + +/** @addtogroup ETH_Transmit_Threshold_Control + * @{ + */ +#define ETH_TX_THRESHOLD_CTRL_64BYTES \ + ((uint32_t)0x00000000) /*!< threshold level of the MTL Transmit DATFIFO is 64 Bytes */ +#define ETH_TX_THRESHOLD_CTRL_128BYTES \ + ((uint32_t)0x00004000) /*!< threshold level of the MTL Transmit DATFIFO is 128 Bytes */ +#define ETH_TX_THRESHOLD_CTRL_192BYTES \ + ((uint32_t)0x00008000) /*!< threshold level of the MTL Transmit DATFIFO is 192 Bytes */ +#define ETH_TX_THRESHOLD_CTRL_256BYTES \ + ((uint32_t)0x0000C000) /*!< threshold level of the MTL Transmit DATFIFO is 256 Bytes */ +#define ETH_TX_THRESHOLD_CTRL_40BYTES \ + ((uint32_t)0x00010000) /*!< threshold level of the MTL Transmit DATFIFO is 40 Bytes */ +#define ETH_TX_THRESHOLD_CTRL_32BYTES \ + ((uint32_t)0x00014000) /*!< threshold level of the MTL Transmit DATFIFO is 32 Bytes */ +#define ETH_TX_THRESHOLD_CTRL_24BYTES \ + ((uint32_t)0x00018000) /*!< threshold level of the MTL Transmit DATFIFO is 24 Bytes */ +#define ETH_TX_THRESHOLD_CTRL_16BYTES \ + ((uint32_t)0x0001C000) /*!< threshold level of the MTL Transmit DATFIFO is 16 Bytes */ +#define IS_ETH_TX_THRESHOLD_CTRL(THRESHOLD) \ + (((THRESHOLD) == ETH_TX_THRESHOLD_CTRL_64BYTES) || ((THRESHOLD) == ETH_TX_THRESHOLD_CTRL_128BYTES) \ + || ((THRESHOLD) == ETH_TX_THRESHOLD_CTRL_192BYTES) || ((THRESHOLD) == ETH_TX_THRESHOLD_CTRL_256BYTES) \ + || ((THRESHOLD) == ETH_TX_THRESHOLD_CTRL_40BYTES) || ((THRESHOLD) == ETH_TX_THRESHOLD_CTRL_32BYTES) \ + || ((THRESHOLD) == ETH_TX_THRESHOLD_CTRL_24BYTES) || ((THRESHOLD) == ETH_TX_THRESHOLD_CTRL_16BYTES)) +/** + * @} + */ + +/** @addtogroup ETH_Forward_Error_Frames + * @{ + */ +#define ETH_FORWARD_ERROR_FRAMES_ENABLE ((uint32_t)0x00000080) +#define ETH_FORWARD_ERROR_FRAMES_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_FORWARD_ERROR_FRAMES(CMDCTRL) \ + (((CMDCTRL) == ETH_FORWARD_ERROR_FRAMES_ENABLE) || ((CMDCTRL) == ETH_FORWARD_ERROR_FRAMES_DISABLE)) +/** + * @} + */ + +/** @addtogroup ETH_Forward_Undersized_Good_Frames + * @{ + */ +#define ETH_FORWARD_UNDERSIZED_GOOD_FRAMES_ENABLE ((uint32_t)0x00000040) +#define ETH_FORWARD_UNDERSIZED_GOOD_FRAMES_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_FORWARD_UNDERSIZED_GOOD_FRAMES(CMDCTRL) \ + (((CMDCTRL) == ETH_FORWARD_UNDERSIZED_GOOD_FRAMES_ENABLE) \ + || ((CMDCTRL) == ETH_FORWARD_UNDERSIZED_GOOD_FRAMES_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Receive_Threshold_Control + * @{ + */ +#define ETH_RX_THRESHOLD_CTRL_64BYTES \ + ((uint32_t)0x00000000) /*!< threshold level of the MTL Receive DATFIFO is 64 Bytes */ +#define ETH_RX_THRESHOLD_CTRL_32BYTES \ + ((uint32_t)0x00000008) /*!< threshold level of the MTL Receive DATFIFO is 32 Bytes */ +#define ETH_RX_THRESHOLD_CTRL_96BYTES \ + ((uint32_t)0x00000010) /*!< threshold level of the MTL Receive DATFIFO is 96 Bytes */ +#define ETH_RX_THRESHOLD_CTRL_128BYTES \ + ((uint32_t)0x00000018) /*!< threshold level of the MTL Receive DATFIFO is 128 Bytes */ +#define IS_ETH_RX_THRESHOLD_CTRL(THRESHOLD) \ + (((THRESHOLD) == ETH_RX_THRESHOLD_CTRL_64BYTES) || ((THRESHOLD) == ETH_RX_THRESHOLD_CTRL_32BYTES) \ + || ((THRESHOLD) == ETH_RX_THRESHOLD_CTRL_96BYTES) || ((THRESHOLD) == ETH_RX_THRESHOLD_CTRL_128BYTES)) +/** + * @} + */ + +/** @addtogroup ETH_Second_Frame_Operate + * @{ + */ +#define ETH_SECOND_FRAME_OPERATE_ENABLE ((uint32_t)0x00000004) +#define ETH_SECOND_FRAME_OPERATE_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_SECOND_FRAME_OPERATE(CMDCTRL) \ + (((CMDCTRL) == ETH_SECOND_FRAME_OPERATE_ENABLE) || ((CMDCTRL) == ETH_SECOND_FRAME_OPERATE_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Address_Aligned_Beats + * @{ + */ +#define ETH_ADDR_ALIGNED_BEATS_ENABLE ((uint32_t)0x02000000) +#define ETH_ADDR_ALIGNED_BEATS_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_ADDR_ALIGNED_BEATS(CMDCTRL) \ + (((CMDCTRL) == ETH_ADDR_ALIGNED_BEATS_ENABLE) || ((CMDCTRL) == ETH_ADDR_ALIGNED_BEATS_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Fixed_Burst + * @{ + */ +#define ETH_FIXED_BURST_ENABLE ((uint32_t)0x00010000) +#define ETH_FIXED_BURST_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_FIXED_BURST(CMDCTRL) (((CMDCTRL) == ETH_FIXED_BURST_ENABLE) || ((CMDCTRL) == ETH_FIXED_BURST_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Rx_DMA_Burst_Length + * @{ + */ +#define ETH_RX_DMA_BURST_LEN_1BEAT \ + ((uint32_t)0x00020000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 1 */ +#define ETH_RX_DMA_BURST_LEN_2BEAT \ + ((uint32_t)0x00040000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 2 */ +#define ETH_RX_DMA_BURST_LEN_4BEAT \ + ((uint32_t)0x00080000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 4 */ +#define ETH_RX_DMA_BURST_LEN_8BEAT \ + ((uint32_t)0x00100000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 8 */ +#define ETH_RX_DMA_BURST_LEN_16BEAT \ + ((uint32_t)0x00200000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 16 */ +#define ETH_RX_DMA_BURST_LEN_32BEAT \ + ((uint32_t)0x00400000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 32 */ +#define ETH_RX_DMA_BURST_LEN_PBLX8_8BEAT \ + ((uint32_t)0x01020000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 4 */ +#define ETH_RX_DMA_BURST_LEN_PBLX8_16BEAT \ + ((uint32_t)0x01040000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 8 */ +#define ETH_RX_DMA_BURST_LEN_PBLX8_32BEAT \ + ((uint32_t)0x01080000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 16 */ +#define ETH_RX_DMA_BURST_LEN_PBLX8_64BEAT \ + ((uint32_t)0x01100000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 32 */ +#define ETH_RX_DMA_BURST_LEN_PBLX8_128BEAT \ + ((uint32_t)0x01200000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 64 */ +#define ETH_RX_DMA_BURST_LEN_PBLX8_256BEAT \ + ((uint32_t)0x01400000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 128 */ +#define IS_ETH_RX_DMA_BURST_LEN(LENGTH) \ + (((LENGTH) == ETH_RX_DMA_BURST_LEN_1BEAT) || ((LENGTH) == ETH_RX_DMA_BURST_LEN_2BEAT) \ + || ((LENGTH) == ETH_RX_DMA_BURST_LEN_4BEAT) || ((LENGTH) == ETH_RX_DMA_BURST_LEN_8BEAT) \ + || ((LENGTH) == ETH_RX_DMA_BURST_LEN_16BEAT) || ((LENGTH) == ETH_RX_DMA_BURST_LEN_32BEAT) \ + || ((LENGTH) == ETH_RX_DMA_BURST_LEN_PBLX8_8BEAT) || ((LENGTH) == ETH_RX_DMA_BURST_LEN_PBLX8_16BEAT) \ + || ((LENGTH) == ETH_RX_DMA_BURST_LEN_PBLX8_32BEAT) || ((LENGTH) == ETH_RX_DMA_BURST_LEN_PBLX8_64BEAT) \ + || ((LENGTH) == ETH_RX_DMA_BURST_LEN_PBLX8_128BEAT) || ((LENGTH) == ETH_RX_DMA_BURST_LEN_PBLX8_256BEAT)) + +/** + * @} + */ + +/** @addtogroup ETH_Tx_DMA_Burst_Length + * @{ + */ +#define ETH_TX_DMA_BURST_LEN_1BEAT \ + ((uint32_t)0x00000100) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 1 */ +#define ETH_TX_DMA_BURST_LEN_2BEAT \ + ((uint32_t)0x00000200) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 2 */ +#define ETH_TX_DMA_BURST_LEN_4BEAT \ + ((uint32_t)0x00000400) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 4 */ +#define ETH_TX_DMA_BURST_LEN_8BEAT \ + ((uint32_t)0x00000800) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 8 */ +#define ETH_TX_DMA_BURST_LEN_16BEAT \ + ((uint32_t)0x00001000) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 16 */ +#define ETH_TX_DMA_BURST_LEN_32BEAT \ + ((uint32_t)0x00002000) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 32 */ +#define ETH_TX_DMA_BURST_LEN_PBLX8_8BEAT \ + ((uint32_t)0x01000100) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 4 */ +#define ETH_TX_DMA_BURST_LEN_PBLX8_16BEAT \ + ((uint32_t)0x01000200) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 8 */ +#define ETH_TX_DMA_BURST_LEN_PBLX8_32BEAT \ + ((uint32_t)0x01000400) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 16 */ +#define ETH_TX_DMA_BURST_LEN_PBLX8_64BEAT \ + ((uint32_t)0x01000800) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 32 */ +#define ETH_TX_DMA_BURST_LEN_PBLX8_128BEAT \ + ((uint32_t)0x01001000) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 64 */ +#define ETH_TX_DMA_BURST_LEN_PBLX8_256BEAT \ + ((uint32_t)0x01002000) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 128 */ +#define IS_ETH_TX_DMA_BURST_LEN(LENGTH) \ + (((LENGTH) == ETH_TX_DMA_BURST_LEN_1BEAT) || ((LENGTH) == ETH_TX_DMA_BURST_LEN_2BEAT) \ + || ((LENGTH) == ETH_TX_DMA_BURST_LEN_4BEAT) || ((LENGTH) == ETH_TX_DMA_BURST_LEN_8BEAT) \ + || ((LENGTH) == ETH_TX_DMA_BURST_LEN_16BEAT) || ((LENGTH) == ETH_TX_DMA_BURST_LEN_32BEAT) \ + || ((LENGTH) == ETH_TX_DMA_BURST_LEN_PBLX8_8BEAT) || ((LENGTH) == ETH_TX_DMA_BURST_LEN_PBLX8_16BEAT) \ + || ((LENGTH) == ETH_TX_DMA_BURST_LEN_PBLX8_32BEAT) || ((LENGTH) == ETH_TX_DMA_BURST_LEN_PBLX8_64BEAT) \ + || ((LENGTH) == ETH_TX_DMA_BURST_LEN_PBLX8_128BEAT) || ((LENGTH) == ETH_TX_DMA_BURST_LEN_PBLX8_256BEAT)) + +#define IS_ETH_DMA_DESC_SKIP_LEN(LENGTH) ((LENGTH) <= 0x1F) + +/** + * @} + */ + +/** @addtogroup ETH_DMA_Arbitration + * @{ + */ +#define ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_1_1 ((uint32_t)0x00000000) +#define ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_2_1 ((uint32_t)0x00004000) +#define ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_3_1 ((uint32_t)0x00008000) +#define ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_4_1 ((uint32_t)0x0000C000) +#define ETH_DMA_ARBITRATION_RX_PRIOR_TX ((uint32_t)0x00000002) +#define IS_ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX(RATIO) \ + (((RATIO) == ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_1_1) || ((RATIO) == ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_2_1) \ + || ((RATIO) == ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_3_1) || ((RATIO) == ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_4_1) \ + || ((RATIO) == ETH_DMA_ARBITRATION_RX_PRIOR_TX)) +/** + * @} + */ + +/** @addtogroup ETH_DMA_Flags + * @{ + */ +#define ETH_DMA_FLAG_TST ((uint32_t)0x20000000) /*!< Time-stamp trigger interrupt (on DMA) */ +#define ETH_DMA_FLAG_PMT ((uint32_t)0x10000000) /*!< PMT interrupt (on DMA) */ +#define ETH_DMA_FLAG_MMC ((uint32_t)0x08000000) /*!< MMC interrupt (on DMA) */ +#define ETH_DMA_FLAG_DATA_TRANSFER_ERROR ((uint32_t)0x00800000) /*!< Error bits 0-Rx DMA, 1-Tx DMA */ +#define ETH_DMA_FLAG_READ_WRITE_ERROR ((uint32_t)0x01000000) /*!< Error bits 0-write trnsf, 1-read transfr */ +#define ETH_DMA_FLAG_ACCESS_ERROR ((uint32_t)0x02000000) /*!< Error bits 0-data buffer, 1-desc. access */ +#define ETH_DMA_FLAG_NIS ((uint32_t)0x00010000) /*!< Normal interrupt summary flag */ +#define ETH_DMA_FLAG_AIS ((uint32_t)0x00008000) /*!< Abnormal interrupt summary flag */ +#define ETH_DMA_FLAG_EARLY_RX ((uint32_t)0x00004000) /*!< Early receive flag */ +#define ETH_DMA_FLAG_FATAL_BUS_ERROR ((uint32_t)0x00002000) /*!< Fatal bus error flag */ +#define ETH_DMA_FLAG_EARLY_TX ((uint32_t)0x00000400) /*!< Early transmit flag */ +#define ETH_DMA_FLAG_RX_WDG_TIMEOUT ((uint32_t)0x00000200) /*!< Receive watchdog timeout flag */ +#define ETH_DMA_FLAG_RX_PROC_STOP ((uint32_t)0x00000100) /*!< Receive process stopped flag */ +#define ETH_DMA_FLAG_RX_BUF_UA ((uint32_t)0x00000080) /*!< Receive buffer unavailable flag */ +#define ETH_DMA_FLAG_RX ((uint32_t)0x00000040) /*!< Receive flag */ +#define ETH_DMA_FLAG_TX_UNDERFLOW ((uint32_t)0x00000020) /*!< Underflow flag */ +#define ETH_DMA_FLAG_RX_OVERFLOW ((uint32_t)0x00000010) /*!< Overflow flag */ +#define ETH_DMA_FLAG_TX_JABBER_TIMEOUT ((uint32_t)0x00000008) /*!< Transmit jabber timeout flag */ +#define ETH_DMA_FLAG_TX_BUF_UA ((uint32_t)0x00000004) /*!< Transmit buffer unavailable flag */ +#define ETH_DMA_FLAG_TX_PROC_STOP ((uint32_t)0x00000002) /*!< Transmit process stopped flag */ +#define ETH_DMA_FLAG_TX ((uint32_t)0x00000001) /*!< Transmit flag */ + +#define IS_ETH_DMA_FLAG(FLAG) ((((FLAG) & (uint32_t)0xFFFE1800) == 0x00) && ((FLAG) != 0x00)) +#define IS_ETH_DMA_GET_FLAG(FLAG) \ + (((FLAG) == ETH_DMA_FLAG_TST) || ((FLAG) == ETH_DMA_FLAG_PMT) || ((FLAG) == ETH_DMA_FLAG_MMC) \ + || ((FLAG) == ETH_DMA_FLAG_DATA_TRANSFER_ERROR) || ((FLAG) == ETH_DMA_FLAG_READ_WRITE_ERROR) \ + || ((FLAG) == ETH_DMA_FLAG_ACCESS_ERROR) || ((FLAG) == ETH_DMA_FLAG_NIS) || ((FLAG) == ETH_DMA_FLAG_AIS) \ + || ((FLAG) == ETH_DMA_FLAG_EARLY_RX) || ((FLAG) == ETH_DMA_FLAG_FATAL_BUS_ERROR) \ + || ((FLAG) == ETH_DMA_FLAG_EARLY_TX) || ((FLAG) == ETH_DMA_FLAG_RX_WDG_TIMEOUT) \ + || ((FLAG) == ETH_DMA_FLAG_RX_PROC_STOP) || ((FLAG) == ETH_DMA_FLAG_RX_BUF_UA) || ((FLAG) == ETH_DMA_FLAG_RX) \ + || ((FLAG) == ETH_DMA_FLAG_TX_UNDERFLOW) || ((FLAG) == ETH_DMA_FLAG_RX_OVERFLOW) \ + || ((FLAG) == ETH_DMA_FLAG_TX_JABBER_TIMEOUT) || ((FLAG) == ETH_DMA_FLAG_TX_BUF_UA) \ + || ((FLAG) == ETH_DMA_FLAG_TX_PROC_STOP) || ((FLAG) == ETH_DMA_FLAG_TX)) +/** + * @} + */ + +/** @addtogroup ETH_DMA_Interrupts + * @{ + */ +#define ETH_DMA_INT_TST ((uint32_t)0x20000000) /*!< Time-stamp trigger interrupt (on DMA) */ +#define ETH_DMA_INT_PMT ((uint32_t)0x10000000) /*!< PMT interrupt (on DMA) */ +#define ETH_DMA_INT_MMC ((uint32_t)0x08000000) /*!< MMC interrupt (on DMA) */ +#define ETH_DMA_INT_NIS ((uint32_t)0x00010000) /*!< Normal interrupt summary */ +#define ETH_DMA_INT_AIS ((uint32_t)0x00008000) /*!< Abnormal interrupt summary */ +#define ETH_DMA_INT_EARLY_RX ((uint32_t)0x00004000) /*!< Early receive interrupt */ +#define ETH_DMA_INT_FATAL_BUS_ERROR ((uint32_t)0x00002000) /*!< Fatal bus error interrupt */ +#define ETH_DMA_INT_EARLY_TX ((uint32_t)0x00000400) /*!< Early transmit interrupt */ +#define ETH_DMA_INT_RX_WDG_TIMEOUT ((uint32_t)0x00000200) /*!< Receive watchdog timeout interrupt */ +#define ETH_DMA_INT_RX_PROC_STOP ((uint32_t)0x00000100) /*!< Receive process stopped interrupt */ +#define ETH_DMA_INT_RX_BUF_UA ((uint32_t)0x00000080) /*!< Receive buffer unavailable interrupt */ +#define ETH_DMA_INT_RX ((uint32_t)0x00000040) /*!< Receive interrupt */ +#define ETH_DMA_INT_TX_UNDERFLOW ((uint32_t)0x00000020) /*!< Underflow interrupt */ +#define ETH_DMA_INT_RX_OVERFLOW ((uint32_t)0x00000010) /*!< Overflow interrupt */ +#define ETH_DMA_INT_TX_JABBER_TIMEOUT ((uint32_t)0x00000008) /*!< Transmit jabber timeout interrupt */ +#define ETH_DMA_INT_TX_BUF_UA ((uint32_t)0x00000004) /*!< Transmit buffer unavailable interrupt */ +#define ETH_DMA_INT_TX_PROC_STOP ((uint32_t)0x00000002) /*!< Transmit process stopped interrupt */ +#define ETH_DMA_INT_TX ((uint32_t)0x00000001) /*!< Transmit interrupt */ + +#define IS_ETH_DMA_INT(IT) ((((IT) & (uint32_t)0xFFFE1800) == 0x00) && ((IT) != 0x00)) +#define IS_ETH_DMA_GET_INT(IT) \ + (((IT) == ETH_DMA_INT_TST) || ((IT) == ETH_DMA_INT_PMT) || ((IT) == ETH_DMA_INT_MMC) || ((IT) == ETH_DMA_INT_NIS) \ + || ((IT) == ETH_DMA_INT_AIS) || ((IT) == ETH_DMA_INT_EARLY_RX) || ((IT) == ETH_DMA_INT_FATAL_BUS_ERROR) \ + || ((IT) == ETH_DMA_INT_EARLY_TX) || ((IT) == ETH_DMA_INT_RX_WDG_TIMEOUT) || ((IT) == ETH_DMA_INT_RX_PROC_STOP) \ + || ((IT) == ETH_DMA_INT_RX_BUF_UA) || ((IT) == ETH_DMA_INT_RX) || ((IT) == ETH_DMA_INT_TX_UNDERFLOW) \ + || ((IT) == ETH_DMA_INT_RX_OVERFLOW) || ((IT) == ETH_DMA_INT_TX_JABBER_TIMEOUT) \ + || ((IT) == ETH_DMA_INT_TX_BUF_UA) || ((IT) == ETH_DMA_INT_TX_PROC_STOP) || ((IT) == ETH_DMA_INT_TX)) + +/** + * @} + */ + +/** @addtogroup ETH_DMA_transmit_process_state_ + * @{ + */ +#define ETH_DMA_TX_PROC_STOPPED ((uint32_t)0x00000000) /*!< Stopped - Reset or Stop Tx Command issued */ +#define ETH_DMA_TX_PROC_FETCHING ((uint32_t)0x00100000) /*!< Running - fetching the Tx descriptor */ +#define ETH_DMA_TX_PROC_WAITING ((uint32_t)0x00200000) /*!< Running - waiting for status */ +#define ETH_DMA_TX_PROC_READING ((uint32_t)0x00300000) /*!< Running - reading the data from host memory */ +#define ETH_DMA_TX_PROC_SUSPENDED ((uint32_t)0x00600000) /*!< Suspended - Tx Desciptor unavailabe */ +#define ETH_DMA_TX_PROC_CLOSING ((uint32_t)0x00700000) /*!< Running - closing Rx descriptor */ + +/** + * @} + */ + +/** @addtogroup ETH_DMA_receive_process_state_ + * @{ + */ +#define ETH_DMA_RX_PROC_STOPPED ((uint32_t)0x00000000) /*!< Stopped - Reset or Stop Rx Command issued */ +#define ETH_DMA_RX_PROC_FETCHING ((uint32_t)0x00020000) /*!< Running - fetching the Rx descriptor */ +#define ETH_DMA_RX_PROC_WAITING ((uint32_t)0x00060000) /*!< Running - waiting for packet */ +#define ETH_DMA_RX_PROC_SUSPENDED ((uint32_t)0x00080000) /*!< Suspended - Rx Desciptor unavailable */ +#define ETH_DMA_RX_PROC_CLOSING ((uint32_t)0x000A0000) /*!< Running - closing descriptor */ +#define ETH_DMA_RX_PROC_QUEUING ((uint32_t)0x000E0000) /*!< Running - queuing the recieve frame into host memory */ + +/** + * @} + */ + +/** @addtogroup ETH_DMA_overflow_ + * @{ + */ +#define ETH_DMA_OVERFLOW_RX_FIFO_COUNTER ((uint32_t)0x10000000) /*!< Overflow bit for DATFIFO overflow counter */ +#define ETH_DMA_OVERFLOW_MISSED_FRAME_COUNTER ((uint32_t)0x00010000) /*!< Overflow bit for missed frame counter */ +#define IS_ETH_DMA_GET_OVERFLOW(OVERFLOW) \ + (((OVERFLOW) == ETH_DMA_OVERFLOW_RX_FIFO_COUNTER) || ((OVERFLOW) == ETH_DMA_OVERFLOW_MISSED_FRAME_COUNTER)) + +/** + * @} + */ + +/** @addtogroup ETH_PMT_Flags + * @{ + */ +#define ETH_PMT_FLAG_RWKUPFILTRST ((uint32_t)0x80000000) /*!< Wake-Up Frame Filter Register Poniter Reset */ +#define ETH_PMT_FLAG_RWKPRCVD ((uint32_t)0x00000040) /*!< Wake-Up Frame Received */ +#define ETH_PMT_FLAG_MGKPRCVD ((uint32_t)0x00000020) /*!< Magic Packet Received */ +#define IS_ETH_PMT_GET_FLAG(FLAG) (((FLAG) == ETH_PMT_FLAG_RWKPRCVD) || ((FLAG) == ETH_PMT_FLAG_MGKPRCVD)) + +/** + * @} + */ + +/** @addtogroup ETH_MMC_Tx_Interrupts + * @{ + */ +#define ETH_MMC_INT_TXGFRMIS ((uint32_t)0x00200000) /*!< When Tx good frame counter reaches half the maximum value */ +#define ETH_MMC_INT_TXMCOLGFIS \ + ((uint32_t)0x00008000) /*!< When Tx good multi col counter reaches half the maximum value */ +#define ETH_MMC_INT_TXSCOLGFIS \ + ((uint32_t)0x00004000) /*!< When Tx good single col counter reaches half the maximum value */ + +/** + * @} + */ + +/** @addtogroup ETH_MMC_Rx_Interrupts + * @{ + */ +#define ETH_MMC_INT_RXUCGFIS \ + ((uint32_t)0x10020000) /*!< When Rx good unicast frames counter reaches half the maximum value */ +#define ETH_MMC_INT_RXALGNERFIS \ + ((uint32_t)0x10000040) /*!< When Rx alignment error counter reaches half the maximum value */ +#define ETH_MMC_INT_RXCRCERFIS ((uint32_t)0x10000020) /*!< When Rx crc error counter reaches half the maximum value */ +#define IS_ETH_MMC_INT(IT) \ + (((((IT) & (uint32_t)0xFFDF3FFF) == 0x00) || (((IT) & (uint32_t)0xEFFDFF9F) == 0x00)) && ((IT) != 0x00)) +#define IS_ETH_MMC_GET_INT(IT) \ + (((IT) == ETH_MMC_INT_TXGFRMIS) || ((IT) == ETH_MMC_INT_TXMCOLGFIS) || ((IT) == ETH_MMC_INT_TXSCOLGFIS) \ + || ((IT) == ETH_MMC_INT_RXUCGFIS) || ((IT) == ETH_MMC_INT_RXALGNERFIS) || ((IT) == ETH_MMC_INT_RXCRCERFIS)) +/** + * @} + */ + +/** @addtogroup ETH_MMC_Registers + * @{ + */ +#define ETH_MMCCTRL ((uint32_t)0x00000100) /*!< MMC CTRL register */ +#define ETH_MMCRXINT ((uint32_t)0x00000104) /*!< MMC RIR register */ +#define ETH_MMCTXINT ((uint32_t)0x00000108) /*!< MMC TIR register */ +#define ETH_MMCRXINTMSK ((uint32_t)0x0000010C) /*!< MMC RIMR register */ +#define ETH_MMCTXINTMSK ((uint32_t)0x00000110) /*!< MMC TIMR register */ +#define ETH_MMCTXGFASCCNT ((uint32_t)0x0000014C) /*!< MMC TGFSCCR register */ +#define ETH_MMCTXGFAMSCCNT ((uint32_t)0x00000150) /*!< MMC TGFMSCCR register */ +#define ETH_MMCTXGFCNT ((uint32_t)0x00000168) /*!< MMC TGFCR register */ +#define ETH_MMCRXFCECNT ((uint32_t)0x00000194) /*!< MMC RFCECR register */ +#define ETH_MMCRXFAECNT ((uint32_t)0x00000198) /*!< MMC RFAECR register */ +#define ETH_MMCRXGUFCNT ((uint32_t)0x000001C4) /*!< MMC RGUFCR register */ + +#define IS_ETH_MMC_REGISTER(REG) \ + (((REG) == ETH_MMCCTRL) || ((REG) == ETH_MMCRXINT) || ((REG) == ETH_MMCTXINT) || ((REG) == ETH_MMCRXINTMSK) \ + || ((REG) == ETH_MMCTXINTMSK) || ((REG) == ETH_MMCTXGFASCCNT) || ((REG) == ETH_MMCTXGFAMSCCNT) \ + || ((REG) == ETH_MMCTXGFCNT) || ((REG) == ETH_MMCRXFCECNT) || ((REG) == ETH_MMCRXFAECNT) \ + || ((REG) == ETH_MMCRXGUFCNT)) + +/** + * @} + */ + +/** @addtogroup ETH_PTP_time_update_method + * @{ + */ +#define ETH_PTP_FINE_UPDATE ((uint32_t)0x00000001) /*!< Fine Update method */ +#define ETH_PTP_COARSE_UPDATE ((uint32_t)0x00000000) /*!< Coarse Update method */ +#define IS_ETH_PTP_UPDATE(UPDATE) (((UPDATE) == ETH_PTP_FINE_UPDATE) || ((UPDATE) == ETH_PTP_COARSE_UPDATE)) + +/** + * @} + */ + +/** @addtogroup ETH_PTP_Flags + * @{ + */ +#define ETH_PTP_FLAG_TSADDREG ((uint32_t)0x00000020) /*!< Addend Register Update */ +#define ETH_PTP_FLAG_TSTRIG ((uint32_t)0x00000010) /*!< Time Stamp Interrupt Trigger */ +#define ETH_PTP_FLAG_TSUPDT ((uint32_t)0x00000008) /*!< Time Stamp Update */ +#define ETH_PTP_FLAG_TSINIT ((uint32_t)0x00000004) /*!< Time Stamp Initialize */ +#define IS_ETH_PTP_GET_FLAG(FLAG) \ + (((FLAG) == ETH_PTP_FLAG_TSADDREG) || ((FLAG) == ETH_PTP_FLAG_TSTRIG) || ((FLAG) == ETH_PTP_FLAG_TSUPDT) \ + || ((FLAG) == ETH_PTP_FLAG_TSINIT)) + +#define IS_ETH_PTP_SUBSECOND_INCREMENT(SUBSECOND) ((SUBSECOND) <= 0xFF) + +/** + * @} + */ + +/** @addtogroup ETH_PTP_time_sign + * @{ + */ +#define ETH_PTP_POSITIVE_TIME ((uint32_t)0x00000000) /*!< Positive time value */ +#define ETH_PTP_NEGATIVE_TIME ((uint32_t)0x80000000) /*!< Negative time value */ +#define IS_ETH_PTP_TIME_SIGN(SIGN) (((SIGN) == ETH_PTP_POSITIVE_TIME) || ((SIGN) == ETH_PTP_NEGATIVE_TIME)) + +#define IS_ETH_PTP_TIME_STAMP_UPDATE_SUBSECOND(SUBSECOND) ((SUBSECOND) <= 0x7FFFFFFF) + +#define ETH_PTPTSCTRL ((uint32_t)0x00000700) /*!< PTP TSCR register */ +#define ETH_PTPSSINC ((uint32_t)0x00000704) /*!< PTP SSIR register */ +#define ETH_PTPSEC ((uint32_t)0x00000708) /*!< PTP TSHR register */ +#define ETH_PTPNS ((uint32_t)0x0000070C) /*!< PTP TSLR register */ +#define ETH_PTPSECUP ((uint32_t)0x00000710) /*!< PTP TSHUR register */ +#define ETH_PTPNSUP ((uint32_t)0x00000714) /*!< PTP TSLUR register */ +#define ETH_PTPTSADD ((uint32_t)0x00000718) /*!< PTP TSAR register */ +#define ETH_PTPTTSEC ((uint32_t)0x0000071C) /*!< PTP TTHR register */ +#define ETH_PTPTTNS ((uint32_t)0x00000720) /* PTP TTLR register */ +#define IS_ETH_PTP_REGISTER(REG) \ + (((REG) == ETH_PTPTSCTRL) || ((REG) == ETH_PTPSSINC) || ((REG) == ETH_PTPSEC) || ((REG) == ETH_PTPNS) \ + || ((REG) == ETH_PTPSECUP) || ((REG) == ETH_PTPNSUP) || ((REG) == ETH_PTPTSADD) || ((REG) == ETH_PTPTTSEC) \ + || ((REG) == ETH_PTPTTNS)) + +/** + * @} + */ + +/** + * @} + */ +/** @addtogroup ETH_Exported_Macros + * @{ + */ +/** + * @} + */ + +/* ETHERNET errors */ +#define ETH_ERROR ((uint32_t)0) +#define ETH_SUCCESS ((uint32_t)1) + +/** + * @brief the function prototype of initialize PHY. + * @param ETH_InitStruct init struct of ETH MAC peripheral. + * @return whether initialization succeed: + * - ETH_ERROR initialization fail + * - ETH_SUCCESS initialization succeed + */ +typedef uint32_t (*ETH_InitPHY)(ETH_InitType* ETH_InitStruct); + +/** @addtogroup ETH_Exported_Functions + * @{ + */ +void ETH_DeInit(void); + +uint32_t ETH_Init(ETH_InitType* ETH_InitStruct, ETH_InitPHY callable); +void ETH_InitStruct(ETH_InitType* ETH_InitStruct); +void ETH_SoftwareReset(void); +FlagStatus ETH_GetSoftwareResetStatus(void); +void ETH_EnableTxRx(void); +uint32_t ETH_TxPacket(u8* ppkt, u16 FrameLength); +uint32_t ETH_RxPacket(u8* ppkt, uint8_t checkErr); +uint32_t ETH_GetRxPacketSize(void); +void ETH_DropRxPacket(void); + +#define ETH_INTERFACE_RMII 0 +#define ETH_INTERFACE_MII 1 + +void ETH_ConfigGpio(uint8_t ETH_Interface, uint8_t remap); + +/* PHY */ +uint16_t ETH_ReadPhyRegister(u16 PHYAddress, u16 PHYReg); +uint32_t ETH_WritePhyRegister(u16 PHYAddress, u16 PHYReg, u16 PHYValue); +uint32_t ETH_EnablePhyLoopBack(u16 PHYAddress, FunctionalState Cmd); + +/* MAC */ +void ETH_EnableMacTx(FunctionalState Cmd); +void ETH_EnableMacRx(FunctionalState Cmd); +FlagStatus ETH_GetFlowCtrlBusyStatus(void); +void ETH_GeneratePauseCtrlFrame(void); +void ETH_EnableBackPressureActivation(FunctionalState Cmd); +FlagStatus ETH_GetMacFlagStatus(uint32_t ETH_MAC_FLAG); +INTStatus ETH_GetMacIntStatus(uint32_t ETH_MAC_IT); +void ETH_EnableMacInt(uint32_t ETH_MAC_IT, FunctionalState Cmd); +void ETH_SetMacAddr(uint32_t MacAddr, u8* Addr); +void ETH_GetMacAddr(uint32_t MacAddr, u8* Addr); +void ETH_EnableMacAddrPerfectFilter(uint32_t MacAddr, FunctionalState Cmd); +void ETH_ConfigMacAddrFilter(uint32_t MacAddr, uint32_t Filter); +void ETH_ConfigMacAddrMaskBytesFilter(uint32_t MacAddr, uint32_t MaskByte); + +/* DMA Tx/Rx descriptors */ +void ETH_ConfigDmaTxDescInChainMode(ETH_DMADescType* DMATxDescTab, u8* TxBuff, uint32_t BufSize, uint32_t TxBuffCount); +void ETH_ConfigDmaTxDescInRingMode(ETH_DMADescType* DMATxDescTab, + u8* TxBuff1, + u8* TxBuff2, + uint32_t BufSize, + uint32_t TxBuffCount); +FlagStatus ETH_GetDmaTxDescFlagStatus(ETH_DMADescType* DMATxDesc, uint32_t ETH_DMATxDescFlag); +uint32_t ETH_GetDmaTxDescCollisionCount(ETH_DMADescType* DMATxDesc); +void ETH_SetDmaTxDescOwn(ETH_DMADescType* DMATxDesc); +void ETH_EnableDmaTxDescTransmitInt(ETH_DMADescType* DMATxDesc, FunctionalState Cmd); +void ETH_ConfigDmaTxDescFrameSegment(ETH_DMADescType* DMATxDesc, uint32_t DMATxDesc_FrameSegment); +void ETH_ConfigDmaTxDescChecksumInsertion(ETH_DMADescType* DMATxDesc, uint32_t DMATxDesc_Checksum); +void ETH_EnableDmaTxDescCrc(ETH_DMADescType* DMATxDesc, FunctionalState Cmd); +void ETH_EnableDmaTxDescEndOfRing(ETH_DMADescType* DMATxDesc, FunctionalState Cmd); +void ETH_EnableDmaTxDescSecondAddrChained(ETH_DMADescType* DMATxDesc, FunctionalState Cmd); +void ETH_EnableDmaTxDescShortFramePadding(ETH_DMADescType* DMATxDesc, FunctionalState Cmd); +void ETH_EnableDmaTxDescTimeStamp(ETH_DMADescType* DMATxDesc, FunctionalState Cmd); +void ETH_ConfigDmaTxDescBufSize(ETH_DMADescType* DMATxDesc, uint32_t BufferSize1, uint32_t BufferSize2); +void ETH_ConfigDmaRxDescInChainMode(ETH_DMADescType* DMARxDescTab, u8* RxBuff, uint32_t BufSize, uint32_t RxBuffCount); +void ETH_ConfigDmaRxDescInRingMode(ETH_DMADescType* DMARxDescTab, + u8* RxBuff1, + u8* RxBuff2, + uint32_t BuffSize, + uint32_t RxBuffCount); +FlagStatus ETH_GetDmaRxDescFlagStatus(ETH_DMADescType* DMARxDesc, uint32_t ETH_DMARxDescFlag); +void ETH_SetDmaRxDescOwn(ETH_DMADescType* DMARxDesc); +uint32_t ETH_GetDmaRxDescFrameLen(__IO ETH_DMADescType* DMARxDesc); +void ETH_EnableDmaRxDescReceiveInt(ETH_DMADescType* DMARxDesc, FunctionalState Cmd); +void ETH_EnableDmaRxDescEndOfRing(ETH_DMADescType* DMARxDesc, FunctionalState Cmd); +void ETH_EnableDmaRxDescSecondAddrChained(ETH_DMADescType* DMARxDesc, FunctionalState Cmd); +uint32_t ETH_GetDmaRxDescBufSize(ETH_DMADescType* DMARxDesc, uint32_t DMARxDesc_Buffer); + +/* DMA */ +FlagStatus ETH_GetDmaFlagStatus(uint32_t ETH_DMA_FLAG); +void ETH_ClrDmaFlag(uint32_t ETH_DMA_FLAG); +INTStatus ETH_GetDmaIntStatus(uint32_t ETH_DMA_IT); +void ETH_ClrDmaIntPendingBit(uint32_t ETH_DMA_IT); +uint32_t ETH_GetTxProcState(void); +uint32_t ETH_GetRxProcState(void); +void ETH_FlushTxFifo(void); +FlagStatus ETH_GetFlushTxFifoStatus(void); +void ETH_EnableDmaTx(FunctionalState Cmd); +void ETH_EnableDmaRx(FunctionalState Cmd); +void ETH_EnableDmaInt(uint32_t ETH_DMA_IT, FunctionalState Cmd); +FlagStatus ETH_GetDmaOverflowStatus(uint32_t ETH_DMA_Overflow); +uint32_t ETH_GetRxOverflowMissedFrameCounter(void); +uint32_t ETH_GetBufUnavailableMissedFrameCounter(void); +uint32_t ETH_GetCurrentTxDescAddr(void); +uint32_t ETH_GetCurrentRxDescAddr(void); +uint32_t ETH_GetCurrentTxBufAddr(void); +uint32_t ETH_GetCurrentRxBufAddr(void); +void ETH_ResumeDmaTx(void); +void ETH_ResumeDmaRx(void); + +/* PMT */ +void ETH_ResetWakeUpFrameFilter(void); +void ETH_SetWakeUpFrameFilter(uint32_t* Buffer); +void ETH_EnableGlobalUnicastWakeUp(FunctionalState Cmd); +FlagStatus ETH_GetPmtFlagStatus(uint32_t ETH_PMT_FLAG); +void ETH_EnableWakeUpFrameDetection(FunctionalState Cmd); +void ETH_EnableMagicPacketDetection(FunctionalState Cmd); +void ETH_EnablePowerDown(FunctionalState Cmd); + +/* MMC */ +void ETH_EnableMmcCounterFreeze(FunctionalState Cmd); +void ETH_EnableMmcResetOnRead(FunctionalState Cmd); +void ETH_EnableMmcCounterRollover(FunctionalState Cmd); +void ETH_ResetMmcCounters(void); +void ETH_EnableMmcInt(uint32_t ETH_MMC_IT, FunctionalState Cmd); +INTStatus ETH_GetMmcIntStatus(uint32_t ETH_MMC_IT); +uint32_t ETH_GetMmcRegisterValue(uint32_t ETH_MMCReg); + +/* PTP */ +uint32_t ETH_TxPtpPacket(u8* ppkt, u16 FrameLength, uint32_t* PTPTxTab); +uint32_t ETH_RxPtpPacket(u8* ppkt, uint32_t* PTPRxTab); +void ETH_ConfigDmaPtpTxDescInChainMode(ETH_DMADescType* DMATxDescTab, + ETH_DMADescType* DMAPTPTxDescTab, + u8* TxBuff, + uint32_t TxBuffCount); +void ETH_ConfigDmaPtpRxDescInChainMode(ETH_DMADescType* DMARxDescTab, + ETH_DMADescType* DMAPTPRxDescTab, + u8* RxBuff, + uint32_t RxBuffCount); +void ETH_UpdatePtpTimeStampAddend(void); +void ETH_EnablePtpTimeStampIntTrigger(void); +void ETH_UpdatePtpTimeStamp(void); +void ETH_InitPtpTimeStamp(void); +void ETH_ConfigPtpUpdateMethod(uint32_t UpdateMethod); +void ETH_StartPTPTimeStamp(FunctionalState Cmd); +FlagStatus ETH_GetPtpFlagStatus(uint32_t ETH_PTP_FLAG); +void ETH_SetPtpSubSecondInc(uint32_t SubSecondValue); +void ETH_SetPtpTimeStampUpdate(uint32_t Sign, uint32_t SecondValue, uint32_t SubSecondValue); +void ETH_SetPtpTimeStampAddend(uint32_t Value); +void ETH_SetPtpTargetTime(uint32_t HighValue, uint32_t LowValue); +uint32_t ETH_GetPtpRegisterValue(uint32_t ETH_PTPReg); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G45X_ETH_H__ */ +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_exti.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_exti.h new file mode 100644 index 0000000000..88c1bb7c28 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_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 n32g45x_exti.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_EXTI_H__ +#define __N32G45X_EXTI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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 /* __N32G45X_EXTI_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_flash.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_flash.h new file mode 100644 index 0000000000..c2771fd97d --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_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 n32g45x_flash.h + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_FLASH_H__ +#define __N32G45X_FLASH_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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 N32G45X devices */ +#define FLASH_WRP_Pages0to1 \ + ((uint32_t)0x00000001) /*!< N32G45X devices: \ + Write protection of page 0 to 1 */ +#define FLASH_WRP_Pages2to3 \ + ((uint32_t)0x00000002) /*!< N32G45X devices: \ + Write protection of page 2 to 3 */ +#define FLASH_WRP_Pages4to5 \ + ((uint32_t)0x00000004) /*!< N32G45X devices: \ + Write protection of page 4 to 5 */ +#define FLASH_WRP_Pages6to7 \ + ((uint32_t)0x00000008) /*!< N32G45X devices: \ + Write protection of page 6 to 7 */ +#define FLASH_WRP_Pages8to9 \ + ((uint32_t)0x00000010) /*!< N32G45X devices: \ + Write protection of page 8 to 9 */ +#define FLASH_WRP_Pages10to11 \ + ((uint32_t)0x00000020) /*!< N32G45X devices: \ + Write protection of page 10 to 11 */ +#define FLASH_WRP_Pages12to13 \ + ((uint32_t)0x00000040) /*!< N32G45X devices: \ + Write protection of page 12 to 13 */ +#define FLASH_WRP_Pages14to15 \ + ((uint32_t)0x00000080) /*!< N32G45X devices: \ + Write protection of page 14 to 15 */ +#define FLASH_WRP_Pages16to17 \ + ((uint32_t)0x00000100) /*!< N32G45X devices: \ + Write protection of page 16 to 17 */ +#define FLASH_WRP_Pages18to19 \ + ((uint32_t)0x00000200) /*!< N32G45X devices: \ + Write protection of page 18 to 19 */ +#define FLASH_WRP_Pages20to21 \ + ((uint32_t)0x00000400) /*!< N32G45X devices: \ + Write protection of page 20 to 21 */ +#define FLASH_WRP_Pages22to23 \ + ((uint32_t)0x00000800) /*!< N32G45X devices: \ + Write protection of page 22 to 23 */ +#define FLASH_WRP_Pages24to25 \ + ((uint32_t)0x00001000) /*!< N32G45X devices: \ + Write protection of page 24 to 25 */ +#define FLASH_WRP_Pages26to27 \ + ((uint32_t)0x00002000) /*!< N32G45X devices: \ + Write protection of page 26 to 27 */ +#define FLASH_WRP_Pages28to29 \ + ((uint32_t)0x00004000) /*!< N32G45X devices: \ + Write protection of page 28 to 29 */ +#define FLASH_WRP_Pages30to31 \ + ((uint32_t)0x00008000) /*!< N32G45X devices: \ + Write protection of page 30 to 31 */ +#define FLASH_WRP_Pages32to33 \ + ((uint32_t)0x00010000) /*!< N32G45X devices: \ + Write protection of page 32 to 33 */ +#define FLASH_WRP_Pages34to35 \ + ((uint32_t)0x00020000) /*!< N32G45X devices: \ + Write protection of page 34 to 35 */ +#define FLASH_WRP_Pages36to37 \ + ((uint32_t)0x00040000) /*!< N32G45X devices: \ + Write protection of page 36 to 37 */ +#define FLASH_WRP_Pages38to39 \ + ((uint32_t)0x00080000) /*!< N32G45X devices: \ + Write protection of page 38 to 39 */ +#define FLASH_WRP_Pages40to41 \ + ((uint32_t)0x00100000) /*!< N32G45X devices: \ + Write protection of page 40 to 41 */ +#define FLASH_WRP_Pages42to43 \ + ((uint32_t)0x00200000) /*!< N32G45X devices: \ + Write protection of page 42 to 43 */ +#define FLASH_WRP_Pages44to45 \ + ((uint32_t)0x00400000) /*!< N32G45X devices: \ + Write protection of page 44 to 45 */ +#define FLASH_WRP_Pages46to47 \ + ((uint32_t)0x00800000) /*!< N32G45X devices: \ + Write protection of page 46 to 47 */ +#define FLASH_WRP_Pages48to49 \ + ((uint32_t)0x01000000) /*!< N32G45X devices: \ + Write protection of page 48 to 49 */ +#define FLASH_WRP_Pages50to51 \ + ((uint32_t)0x02000000) /*!< N32G45X devices: \ + Write protection of page 50 to 51 */ +#define FLASH_WRP_Pages52to53 \ + ((uint32_t)0x04000000) /*!< N32G45X devices: \ + Write protection of page 52 to 53 */ +#define FLASH_WRP_Pages54to55 \ + ((uint32_t)0x08000000) /*!< N32G45X devices: \ + Write protection of page 54 to 55 */ +#define FLASH_WRP_Pages56to57 \ + ((uint32_t)0x10000000) /*!< N32G45X devices: \ + Write protection of page 56 to 57 */ +#define FLASH_WRP_Pages58to59 \ + ((uint32_t)0x20000000) /*!< N32G45X devices: \ + Write protection of page 58 to 59 */ +#define FLASH_WRP_Pages60to61 \ + ((uint32_t)0x40000000) /*!< N32G45X devices: \ + Write protection of page 60 to 61 */ +#define FLASH_WRP_Pages62to127 \ + ((uint32_t)0x80000000) /*!< N32G45X - 256KB devices: Write protection of page 62 to 127 */ +#define FLASH_WRP_Pages62to255 \ + ((uint32_t)0x80000000) /*!< N32G45X - 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 N32G45X 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 /* __N32G45X_FLASH_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_gpio.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_gpio.h new file mode 100644 index 0000000000..cac3cb5f01 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_gpio.h @@ -0,0 +1,463 @@ +/***************************************************************************** + * 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 n32g45x_gpio.h + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_GPIO_H__ +#define __N32G45X_GPIO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup GPIO + * @{ + */ + +/** @addtogroup GPIO_Exported_Types + * @{ + */ + +#define IS_GPIO_ALL_PERIPH(PERIPH) \ + (((PERIPH) == GPIOA) || ((PERIPH) == GPIOB) || ((PERIPH) == GPIOC) || ((PERIPH) == GPIOD) || ((PERIPH) == GPIOE) \ + || ((PERIPH) == GPIOF) || ((PERIPH) == GPIOG)) + +/** + * @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 GPIOF_PORT_SOURCE ((uint8_t)0x05) +#define GPIOG_PORT_SOURCE ((uint8_t)0x06) +#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) \ + || ((PORTSOURCE) == GPIOF_PORT_SOURCE) || ((PORTSOURCE) == GPIOG_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 /* __N32G45X_GPIO_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_i2c.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_i2c.h new file mode 100644 index 0000000000..b543d66e18 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_i2c.h @@ -0,0 +1,672 @@ +/***************************************************************************** + * 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 n32g45x_i2c.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_I2C_H__ +#define __N32G45X_I2C_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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, MSMODE and STARTBF 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, MSMODE, ADDRF, TXDATE and TRF flags */ +#define I2C_EVT_MASTER_RXMODE_FLAG ((uint32_t)0x00030002) /* BUSY, MSMODE and ADDRF flags */ +/* --EV9 */ +#define I2C_EVT_MASTER_MODE_ADDRESS10_FLAG ((uint32_t)0x00030008) /* BUSY, MSMODE and ADD10RF 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 BSF 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, MSMODE and RXDATNE 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) /* TRF, BUSY, MSMODE, TXDATE flags */ +/* --EV8_2 */ +#define I2C_EVT_MASTER_DATA_SENDED ((uint32_t)0x00070084) /* TRF, BUSY, MSMODE, TXDATE and BSF 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 ADDRF flags */ +#define I2C_EVT_SLAVE_SEND_ADDR_MATCHED ((uint32_t)0x00060082) /* TRF, BUSY, TXDATE and ADDRF 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, TRF, BUSY and TXDATE 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 BSF 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 RXDATNE 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) /* TRF, BUSY, TXDATE and BSF flags */ +#define I2C_EVT_SLAVE_DATA_SENDING ((uint32_t)0x00060080) /* TRF, BUSY and TXDATE 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) \ + || ((EVENT) == I2C_EVT_MASTER_SFT_DATA_RECVD_FLAG) || ((EVENT) == I2C_EVT_SLAVE_DATA_RECVD_NOBUSY)) +/** + * @} + */ + +/** @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 (n32g45x_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 /*__N32G45X_I2C_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_iwdg.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_iwdg.h new file mode 100644 index 0000000000..9ace2b5b29 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_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 n32g45x_iwdg.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_IWDG_H__ +#define __N32G45X_IWDG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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 /* __N32G45X_IWDG_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_opamp.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_opamp.h new file mode 100644 index 0000000000..8273c7d16e --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_opamp.h @@ -0,0 +1,213 @@ +/***************************************************************************** + * 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 n32g45x_opamp.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_OPAMPMP_H__ +#define __N32G45X_OPAMPMP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" +#include + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup OPAMP + * @{ + */ + +/** @addtogroup OPAMP_Exported_Constants + * @{ + */ +typedef enum +{ + OPAMP1 = 0, + OPAMP2 = 4, + OPAMP3 = 8, + OPAMP4 = 12, +} OPAMPX; + +// OPAMP_CS +typedef enum +{ + OPAMP1_CS_VPSSEL_PA1 = (0x00L << 19), + OPAMP1_CS_VPSSEL_PA3 = (0x01L << 19), + OPAMP1_CS_VPSSEL_DAC2_PA5 = (0x02L << 19), + OPAMP1_CS_VPSSEL_PA7 = (0x03L << 19), + OPAMP2_CS_VPSSEL_PA7 = (0x00L << 19), + OPAMP2_CS_VPSSEL_PB0 = (0x01L << 19), + OPAMP2_CS_VPSSEL_PE8 = (0x02L << 19), + OPAMP3_CS_VPSSEL_PC9 = (0x00L << 19), + OPAMP3_CS_VPSSEL_PA1 = (0x01L << 19), + OPAMP3_CS_VPSSEL_DAC2_PA5 = (0x02L << 19), + OPAMP3_CS_VPSSEL_PC3 = (0x03L << 19), + OPAMP4_CS_VPSSEL_PC3 = (0x00L << 19), + OPAMP4_CS_VPSSEL_DAC1_PA4 = (0x01L << 19), + OPAMP4_CS_VPSSEL_PC5 = (0x02L << 19), +} OPAMP_CS_VPSSEL; +typedef enum +{ + OPAMP1_CS_VMSSEL_PA3 = (0x00L << 17), + OPAMP1_CS_VMSSEL_PA2 = (0x01L << 17), + OPAMPx_CS_VMSSEL_FLOAT = (0x03L << 17), + OPAMP2_CS_VMSSEL_PA2 = (0x00L << 17), + OPAMP2_CS_VMSSEL_PA5 = (0x01L << 17), + OPAMP3_CS_VMSSEL_PC4 = (0x00L << 17), + OPAMP3_CS_VMSSEL_PB10 = (0x01L << 17), + OPAMP4_CS_VMSSEL_PB10 = (0x00L << 17), + OPAMP4_CS_VMSSEL_PC9 = (0x01L << 17), + OPAMP4_CS_VMSSEL_PD8 = (0x02L << 17), +} OPAMP_CS_VMSSEL; + +typedef enum +{ + OPAMP1_CS_VPSEL_PA1 = (0x00L << 8), + OPAMP1_CS_VPSEL_PA3 = (0x01L << 8), + OPAMP1_CS_VPSEL_DAC2_PA5 = (0x02L << 8), + OPAMP1_CS_VPSEL_PA7 = (0x03L << 8), + OPAMP2_CS_VPSEL_PA7 = (0x00L << 8), + OPAMP2_CS_VPSEL_PB0 = (0x01L << 8), + OPAMP2_CS_VPSEL_PE8 = (0x02L << 8), + OPAMP3_CS_VPSEL_PC9 = (0x00L << 8), + OPAMP3_CS_VPSEL_PA1 = (0x01L << 8), + OPAMP3_CS_VPSEL_DAC2_PA5 = (0x02L << 8), + OPAMP3_CS_VPSEL_PC3 = (0x03L << 8), + OPAMP4_CS_VPSEL_PC3 = (0x00L << 8), + OPAMP4_CS_VPSEL_DAC1_PA4 = (0x01L << 8), + OPAMP4_CS_VPSEL_PC5 = (0x02L << 8), +} OPAMP_CS_VPSEL; +typedef enum +{ + OPAMP1_CS_VMSEL_PA3 = (0x00L << 6), + OPAMP1_CS_VMSEL_PA2 = (0x01L << 6), + OPAMPx_CS_VMSEL_FLOAT = (0x03L << 6), + OPAMP2_CS_VMSEL_PA2 = (0x00L << 6), + OPAMP2_CS_VMSEL_PA5 = (0x01L << 6), + OPAMP3_CS_VMSEL_PC4 = (0x00L << 6), + OPAMP3_CS_VMSEL_PB10 = (0x01L << 6), + OPAMP4_CS_VMSEL_PB10 = (0x00L << 6), + OPAMP4_CS_VMSEL_PC9 = (0x01L << 6), + OPAMP4_CS_VMSEL_PD8 = (0x02L << 6), +} OPAMP_CS_VMSEL; +typedef enum +{ + OPAMP_CS_PGA_GAIN_2 = (0x00 << 3), + OPAMP_CS_PGA_GAIN_4 = (0x01 << 3), + OPAMP_CS_PGA_GAIN_8 = (0x02 << 3), + OPAMP_CS_PGA_GAIN_16 = (0x03 << 3), + OPAMP_CS_PGA_GAIN_32 = (0x04 << 3), +} OPAMP_CS_PGA_GAIN; +typedef enum +{ + OPAMP_CS_EXT_OPAMP = (0x00 << 1), + OPAMP_CS_PGA_EN = (0x02 << 1), + OPAMP_CS_FOLLOW = (0x03 << 1), +} OPAMP_CS_MOD; + +// bit mask +#define OPAMP_CS_EN_MASK (0x01L << 0) +#define OPAMP_CS_MOD_MASK (0x03L << 1) +#define OPAMP_CS_PGA_GAIN_MASK (0x07L << 3) +#define OPAMP_CS_VMSEL_MASK (0x03L << 6) +#define OPAMP_CS_VPSEL_MASK (0x07L << 8) +#define OPAMP_CS_CALON_MASK (0x01L << 11) +#define OPAMP_CS_TSTREF_MASK (0x01L << 13) +#define OPAMP_CS_CALOUT_MASK (0x01L << 14) +#define OPAMP_CS_RANGE_MASK (0x01L << 15) +#define OPAMP_CS_TCMEN_MASK (0x01L << 16) +#define OPAMP_CS_VMSEL_SECOND_MASK (0x03L << 17) +#define OPAMP_CS_VPSEL_SECOND_MASK (0x07L << 19) +/** @addtogroup OPAMP_LOCK + * @{ + */ +#define OPAMP_LOCK_1 0x01L +#define OPAMP_LOCK_2 0x02L +#define OPAMP_LOCK_3 0x04L +#define OPAMP_LOCK_4 0x08L +/** + * @} + */ +/** + * @} + */ + +/** + * @brief OPAMP Init structure definition + */ + +typedef struct +{ + FunctionalState TimeAutoMuxEn; /*call ENABLE or DISABLE */ + + FunctionalState HighVolRangeEn; /*call ENABLE or DISABLE ,low range VDDA < 2.4V,high range VDDA >= 2.4V*/ + + OPAMP_CS_PGA_GAIN Gain; /*see @EM_PGA_GAIN */ + + OPAMP_CS_MOD Mod; /*see @EM_OPAMP_MOD*/ +} OPAMP_InitType; + +/** @addtogroup OPAMP_Exported_Functions + * @{ + */ + +void OPAMP_DeInit(void); +void OPAMP_StructInit(OPAMP_InitType* OPAMP_InitStruct); +void OPAMP_Init(OPAMPX OPAMPx, OPAMP_InitType* OPAMP_InitStruct); +void OPAMP_Enable(OPAMPX OPAMPx, FunctionalState en); +void OPAMP_SetPgaGain(OPAMPX OPAMPx, OPAMP_CS_PGA_GAIN Gain); +void OPAMP_SetVpSecondSel(OPAMPX OPAMPx, OPAMP_CS_VPSSEL VpSSel); +void OPAMP_SetVmSecondSel(OPAMPX OPAMPx, OPAMP_CS_VMSSEL VmSSel); +void OPAMP_SetVpSel(OPAMPX OPAMPx, OPAMP_CS_VPSEL VpSel); +void OPAMP_SetVmSel(OPAMPX OPAMPx, OPAMP_CS_VMSEL VmSel); +bool OPAMP_IsCalOutHigh(OPAMPX OPAMPx); +void OPAMP_CalibrationEnable(OPAMPX OPAMPx, FunctionalState en); +void OPAMP_SetLock(uint32_t Lock); // see @OPAMP_LOCK +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G45X_ADC_H */ + /** + * @} + */ + /** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_pwr.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_pwr.h new file mode 100644 index 0000000000..7ee2e964a3 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_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 n32g45x_pwr.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_PWR_H__ +#define __N32G45X_PWR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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 /* __N32G45X_PWR_H__ */ + /** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_qspi.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_qspi.h new file mode 100644 index 0000000000..914e426d7d --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_qspi.h @@ -0,0 +1,333 @@ +/***************************************************************************** + * 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 n32g45x_qspi.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_QSPI_H__ +#define __N32G45X_QSPI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" +#include +/** @addtogroup N32G45X_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_MD_BIT_EN; + 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_XIP_DFS_HC; + uint32_t ENHANCED_XIP_INST_EN; + uint32_t ENHANCED_XIP_CT_EN; + uint32_t ENHANCED_XIP_MBL; + 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_XIP_MBL(ENH_XIP_MBL) \ + (((ENH_XIP_MBL) == QSPI_ENH_CTRL0_XIP_MBL_2_BIT) || ((ENH_XIP_MBL) == QSPI_ENH_CTRL0_XIP_MBL_4_BIT) || \ + ((ENH_XIP_MBL) == QSPI_ENH_CTRL0_XIP_MBL_8_BIT) || ((ENH_XIP_MBL) == QSPI_ENH_CTRL0_XIP_MBL_16_BIT)) + +#define IS_QSPI_ENH_XIP_CT_EN(ENH_XIP_CT_EN) (((ENH_XIP_CT_EN) == QSPI_ENH_CTRL0_XIP_CT_EN) || ((ENH_XIP_CT_EN) == 0)) + +#define IS_QSPI_ENH_XIP_INST_EN(ENH_XIP_INST_EN) (((ENH_XIP_INST_EN) == QSPI_ENH_CTRL0_XIP_INST_EN) || ((ENH_XIP_INST_EN) == 0)) + +#define IS_QSPI_ENH_XIP_DFS_HC(ENH_XIP_DFS_HC) (((ENH_XIP_DFS_HC) == QSPI_ENH_CTRL0_XIP_DFS_HC) || ((ENH_XIP_DFS_HC) == 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_MD_BIT_EN(ENH_MD_BIT_EN) (((ENH_MD_BIT_EN) == QSPI_ENH_CTRL0_MD_BIT_EN) || ((ENH_MD_BIT_EN) == 0)) + +#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_DMA_CTRL_Config(uint8_t TxRx,uint8_t TxDataLevel,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 GetQspiTransmitErrorStatus(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 /*__N32G45X_QSPI_H__ */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_rcc.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_rcc.h new file mode 100644 index 0000000000..3552074e69 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_rcc.h @@ -0,0 +1,708 @@ +/***************************************************************************** + * 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 n32g45x_rcc.h + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_RCC_H__ +#define __N32G45X_RCC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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_GPIOF ((uint32_t)0x00000080) +#define RCC_APB2_PERIPH_GPIOG ((uint32_t)0x00000100) +#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 /* __N32G45X_RCC_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_rtc.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_rtc.h new file mode 100644 index 0000000000..8e8d94a810 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_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 n32g45x_rtc.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_RTC_H__ +#define __N32G45X_RTC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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 /*__N32G45X_RTC_H__ */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_sdio.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_sdio.h new file mode 100644 index 0000000000..c70eb58b8b --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_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 n32g45x_sdio.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_SDIO_H__ +#define __N32G45X_SDIO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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 /* __N32G45X_SDIO_H__ */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_spi.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_spi.h new file mode 100644 index 0000000000..401fbe65a4 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_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 n32g45x_spi.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_SPI_H__ +#define __N32G45X_SPI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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 /*__N32G45X_SPI_H__ */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_tim.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_tim.h new file mode 100644 index 0000000000..5da1c9c564 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_tim.h @@ -0,0 +1,1114 @@ +/***************************************************************************** + * 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 n32g45x_tim.h + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_TIM_H__ +#define __N32G45X_TIM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" +#include "stdbool.h" + +/** @addtogroup N32G45X_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 TIM_DMABASE_CAPCMPMOD3 ((uint16_t)0x0013) +#define TIM_DMABASE_CAPCMPDAT5 ((uint16_t)0x0014) +#define TIM_DMABASE_CAPCMPDAT6 ((uint16_t)0x0015) + +#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_CAPCMPMOD3) \ + || ((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_CAPCMPDAT5) || ((BASE) == TIM_DMABASE_CAPCMPDAT6) || ((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 /*__N32G45X_TIM_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_tsc.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_tsc.h new file mode 100644 index 0000000000..ad009b82c2 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_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 n32g45x_tsc.h + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_TSC_H__ +#define __N32G45X_TSC_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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 /* __N32G45X_USART_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_wwdg.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_wwdg.h new file mode 100644 index 0000000000..6f7d32b91d --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32g45x_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 n32g45x_wwdg.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_WWDG_H__ +#define __N32G45X_WWDG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_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 /* __N32G45X__WWDG_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32xx_tsc_alg_api.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/inc/n32xx_tsc_alg_api.h new file mode 100644 index 0000000000..a0bc723d76 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_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) //´¥¿ØÃ¿Í¨µÀµÄ²Î¿¼´óС£¬Êµ¼Ê´óСÒÔ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Êý¾Ý¿Õ¼äΪNULL»ò²»ÔÚ16K 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ģʽϱ£´æ´¥¿Ø»½Ðѹ¦ÄÜÏà¹ØµÄTSCÊý¾ÝBUF¡£ */ + uint16_t Stop2DataSize; /* ÓÃÓÚÔÚSTOP2ģʽϱ£´æ´¥¿Ø»½Ðѹ¦ÄÜÏà¹ØµÄTSCÊý¾ÝBUF´óС¡£µ¥Î»(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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/misc.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/misc.c new file mode 100644 index 0000000000..274a8058cb --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/misc.c @@ -0,0 +1,229 @@ +/***************************************************************************** + * 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 N32G45X_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_Div8 AHB clock divided by 8 selected as SysTick clock source. + * @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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_adc.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_adc.c new file mode 100644 index 0000000000..d0b34c004d --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_adc.c @@ -0,0 +1,1495 @@ +/***************************************************************************** + * 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 n32g45x_adc.c + * @author Nations + * @version v1.0.4 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_adc.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_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 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 ,3 or 4 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); + } + else if (ADCx == ADC3) + { + /* Enable ADC2 reset state */ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ADC3, ENABLE); + /* Release ADC2 from reset state */ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ADC3, DISABLE); + } + else + { + if (ADCx == ADC4) + { + /* Enable ADC3 reset state */ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ADC4, ENABLE); + /* Release ADC3 from reset state */ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ADC4, DISABLE); + } + } +} + +/** + * @brief Initializes the ADCx peripheral according to the specified parameters + * in the ADC_InitStruct. + * @param ADCx where x can be 1, 2 ,3 or 4 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 OR last ADC3 and ADC4 conversion result data in dual mode. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @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)ADC3->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 and ADC3) + * @arg ADC_EXT_TRIG_INJ_CONV_T1_CC4 Timer1 capture compare4 selected (for ADC1, ADC2 and ADC3) + * @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) + * @arg ADC_EXT_TRIG_INJ_CONV_T4_CC3 Timer4 capture compare3 selected (for ADC3 only) + * @arg ADC_EXT_TRIG_INJ_CONV_T8_CC2 Timer8 capture compare2 selected (for ADC3 only) + * @arg ADC_EXT_TRIG_INJ_CONV_T8_CC4 Timer8 capture compare4 selected (for ADC3 only) + * @arg ADC_EXT_TRIG_INJ_CONV_T5_TRGO Timer5 TRGO event selected (for ADC3 only) + * @arg ADC_EXT_TRIG_INJ_CONV_T5_CC4 Timer5 capture compare4 selected (for ADC3 only) + * @arg ADC_EXT_TRIG_INJ_CONV_NONE Injected conversion started by software and not + * by external trigger (for ADC1, ADC2 and ADC3) + */ +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 ,3 or 4 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->SampSecondStyle) + 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 ,3 or 4 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); + ADC_AHB_Clock_Mode_Config(ADC3); + ADC_AHB_Clock_Mode_Config(ADC4); + } + else + { + RCC_ConfigAdcPllClk(RCC_ADCHCLKPrescaler, ENABLE); + RCC_ConfigAdcHclk(RCC_ADCHCLK_DIV1); + ADC_PLL_Clock_Mode_Config(ADC1); + ADC_PLL_Clock_Mode_Config(ADC2); + ADC_PLL_Clock_Mode_Config(ADC3); + ADC_PLL_Clock_Mode_Config(ADC4); + } +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_bkp.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_bkp.c new file mode 100644 index 0000000000..5c8a983be0 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_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 n32g45x_bkp.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_bkp.h" + +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_can.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_can.c new file mode 100644 index 0000000000..6ec9f947e9 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_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 n32g45x_can.c + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_can.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_comp.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_comp.c new file mode 100644 index 0000000000..f8e0c53b12 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_comp.c @@ -0,0 +1,297 @@ +/***************************************************************************** + * 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 n32g45x_comp.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_comp.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup COMP + * @brief COMP driver modules + * @{ + */ + +/** @addtogroup COMP_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup COMP_Private_Defines + * @{ + */ + +/** + * @} + */ + +/** @addtogroup COMP_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup COMP_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup COMP_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup COMP_Private_Functions + * @{ + */ +#define SetBitMsk(reg, bit, msk) ((reg) = ((reg) & ~(msk) | (bit))) +#define ClrBit(reg, bit) ((reg) &= ~(bit)) +#define SetBit(reg, bit) ((reg) |= (bit)) +#define GetBit(reg, bit) ((reg) & (bit)) +/** + * @brief Deinitializes the COMP peripheral registers to their default reset values. + */ +void COMP_DeInit(void) +{ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_COMP, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_COMP, DISABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_COMP_FILT, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_COMP_FILT, DISABLE); +} +void COMP_StructInit(COMP_InitType* COMP_InitStruct) +{ + COMP_InitStruct->InpDacConnect = false; // only COMP1 have this bit + + COMP_InitStruct->Blking = COMP_CTRL_BLKING_NO; /*see @ref COMP_CTRL_BLKING */ + + COMP_InitStruct->Hyst = COMP_CTRL_HYST_NO; // see @COMPx_CTRL_HYST_MASK + + COMP_InitStruct->PolRev = false; // out polarity reverse + + COMP_InitStruct->OutSel = COMPX_CTRL_OUTSEL_NC; + COMP_InitStruct->InpSel = COMPX_CTRL_INPSEL_RES; + COMP_InitStruct->InmSel = COMPX_CTRL_INMSEL_RES; + COMP_InitStruct->FilterEn=false; + COMP_InitStruct->ClkPsc=0; + COMP_InitStruct->SampWindow=0; + COMP_InitStruct->Thresh=0; + COMP_InitStruct->En = false; +} +void COMP_Init(COMPX COMPx, COMP_InitType* COMP_InitStruct) +{ + COMP_SingleType* pCS = &COMP->Cmp[COMPx]; + __IO uint32_t tmp; + + // filter + tmp = pCS->FILC; + SetBitMsk(tmp, COMP_InitStruct->SampWindow << 6, COMP_FILC_SAMPW_MASK); + SetBitMsk(tmp, COMP_InitStruct->Thresh << 1, COMP_FILC_THRESH_MASK); + SetBitMsk(tmp, COMP_InitStruct->FilterEn << 0, COMP_FILC_FILEN_MASK); + pCS->FILC = tmp; + // filter psc + pCS->FILP = COMP_InitStruct->ClkPsc; + + // ctrl + tmp = pCS->CTRL; + if (COMPx == COMP1) + { + if (COMP_InitStruct->InpDacConnect) + SetBit(tmp, COMP1_CTRL_INPDAC_MASK); + else + ClrBit(tmp, COMP1_CTRL_INPDAC_MASK); + } + SetBitMsk(tmp, COMP_InitStruct->Blking, COMP_CTRL_BLKING_MASK); + SetBitMsk(tmp, COMP_InitStruct->Hyst, COMPx_CTRL_HYST_MASK); + if (COMP_InitStruct->PolRev) + SetBit(tmp, COMP_POL_MASK); + else + ClrBit(tmp, COMP_POL_MASK); + SetBitMsk(tmp, COMP_InitStruct->OutSel, COMP_CTRL_OUTSEL_MASK); + SetBitMsk(tmp, COMP_InitStruct->InpSel, COMP_CTRL_INPSEL_MASK); + SetBitMsk(tmp, COMP_InitStruct->InmSel, COMP_CTRL_INMSEL_MASK); + if (COMP_InitStruct->En) + SetBit(tmp, COMP_CTRL_EN_MASK); + else + ClrBit(tmp, COMP_CTRL_EN_MASK); + pCS->CTRL = tmp; +} +void COMP_Enable(COMPX COMPx, FunctionalState en) +{ + if (en) + SetBit(COMP->Cmp[COMPx].CTRL, COMP_CTRL_EN_MASK); + else + ClrBit(COMP->Cmp[COMPx].CTRL, COMP_CTRL_EN_MASK); +} + +void COMP_SetInpSel(COMPX COMPx, COMP_CTRL_INPSEL VpSel) +{ + __IO uint32_t tmp = COMP->Cmp[COMPx].CTRL; + SetBitMsk(tmp, VpSel, COMP_CTRL_INPSEL_MASK); + COMP->Cmp[COMPx].CTRL = tmp; +} +void COMP_SetInmSel(COMPX COMPx, COMP_CTRL_INMSEL VmSel) +{ + __IO uint32_t tmp = COMP->Cmp[COMPx].CTRL; + SetBitMsk(tmp, VmSel, COMP_CTRL_INMSEL_MASK); + COMP->Cmp[COMPx].CTRL = tmp; +} +void COMP_SetOutTrig(COMPX COMPx, COMP_CTRL_OUTTRIG OutTrig) +{ + __IO uint32_t tmp = COMP->Cmp[COMPx].CTRL; + SetBitMsk(tmp, OutTrig, COMP_CTRL_OUTSEL_MASK); + COMP->Cmp[COMPx].CTRL = tmp; +} +// Lock see @COMP_LOCK +void COMP_SetLock(uint32_t Lock) +{ + COMP->LOCK = Lock; +} +// IntEn see @COMP_INTEN_CMPIEN +void COMP_SetIntEn(uint32_t IntEn) +{ + COMP->INTEN = IntEn; +} +// return see @COMP_INTSTS_CMPIS +uint32_t COMP_GetIntSts(void) +{ + return COMP->INTSTS; +} +// parma range see @COMP_VREFSCL +// Vv2Trim,Vv1Trim max 63 +void COMP_SetRefScl(uint8_t Vv2Trim, bool Vv2En, uint8_t Vv1Trim, bool Vv1En) +{ + __IO uint32_t tmp = 0; + + SetBitMsk(tmp, Vv2Trim << 8, COMP_VREFSCL_VV2TRM_MSK); + SetBitMsk(tmp, Vv2En << 7, COMP_VREFSCL_VV2EN_MSK); + SetBitMsk(tmp, Vv1Trim << 1, COMP_VREFSCL_VV1TRM_MSK); + SetBitMsk(tmp, Vv1En << 0, COMP_VREFSCL_VV1EN_MSK); + + COMP->VREFSCL = tmp; +} +// SET when comp out 1 +// RESET when comp out 0 +FlagStatus COMP_GetOutStatus(COMPX COMPx) +{ + return (COMP->Cmp[COMPx].CTRL & COMP_CTRL_OUT_MASK) ? SET : RESET; +} +// get one comp interrupt flags +FlagStatus COMP_GetIntStsOneComp(COMPX COMPx) +{ + return (COMP_GetIntSts() & (0x01 << COMPx)) ? SET : RESET; +} + +/** + * @brief Set the COMP filter clock Prescaler value. + * @param COMPx where x can be 1 to 7 to select the COMP peripheral. + * @param FilPreVal Prescaler Value,Div clock = FilPreVal+1. + * @return void + */ +void COMP_SetFilterPrescaler(COMPX COMPx , uint16_t FilPreVal) +{ + COMP->Cmp[COMPx].FILP=FilPreVal; +} + +/** + * @brief Set the COMP filter control value. + * @param COMPx where x can be 1 to 7 to select the COMP peripheral. + * @param FilEn 1 for enable ,0 or disable + * @param TheresNum num under this value is noise + * @param SampPW total sample number in a window + * @return void + */ +void COMP_SetFilterControl(COMPX COMPx , uint8_t FilEn, uint8_t TheresNum , uint8_t SampPW) +{ + COMP->Cmp[COMPx].FILC=(FilEn&COMP_FILC_FILEN_MASK)+((TheresNum<<1)&COMP_FILC_THRESH_MASK)+((SampPW<<6)&COMP_FILC_SAMPW_MASK); +} + +/** + * @brief Set the COMP Hyst value. + * @param COMPx where x can be 1 to 7 to select the COMP peripheral. + * @param HYST specifies the HYST level. + * This parameter can be one of the following values: +* @arg COMP_CTRL_HYST_NO Hyst disable +* @arg COMP_CTRL_HYST_LOW Hyst level 5.1mV +* @arg COMP_CTRL_HYST_MID Hyst level 15mV +* @arg COMP_CTRL_HYST_HIGH Hyst level 25mV + * @return void + */ +void COMP_SetHyst(COMPX COMPx , COMP_CTRL_HYST HYST) +{ + uint32_t tmp=COMP->Cmp[COMPx].CTRL; + tmp&=~COMP_CTRL_HYST_HIGH; + tmp|=HYST; + COMP->Cmp[COMPx].CTRL=tmp; +} + +/** + * @brief Set the COMP Blanking source . + * @param COMPx where x can be 1 to 7 to select the COMP peripheral. + * @param BLK specifies the blanking source . + * This parameter can be one of the following values: +* @arg COMP_CTRL_BLKING_NO Blanking disable +* @arg COMP_CTRL_BLKING_TIM1_OC5 Blanking source TIM1_OC5 +* @arg COMP_CTRL_BLKING_TIM8_OC5 Blanking source TIM8_OC5 + * @return void + */ +void COMP_SetBlanking(COMPX COMPx , COMP_CTRL_BLKING BLK) +{ + uint32_t tmp=COMP->Cmp[COMPx].CTRL; + tmp&=~(7<<14); + tmp|=BLK; + COMP->Cmp[COMPx].CTRL=tmp; +} + + +/** + * @} + */ +/** + * @} + */ +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_crc.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_crc.c new file mode 100644 index 0000000000..e4a9200105 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_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 n32g45x_crc.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_crc.h" + +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_dac.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_dac.c new file mode 100644 index 0000000000..ce1b0635ed --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_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 n32g45x_dac.c + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_dac.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_dbg.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_dbg.c new file mode 100644 index 0000000000..743295129e --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_dbg.c @@ -0,0 +1,263 @@ +/***************************************************************************** + * 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 n32g45x_dbg.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_dbg.h" + +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_dma.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_dma.c new file mode 100644 index 0000000000..a4bf607049 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_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 n32g45x_dma.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_dma.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_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 CHCFGx registers Masks, MEM2MEM, PL, MSIZE, PSIZE, MINC, PINC, CIRC and DIR bits */ +#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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_dvp.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_dvp.c new file mode 100644 index 0000000000..3672816dfa --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_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 n32g45x_dvp.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_dvp.h" +#include "n32g45x_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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_eth.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_eth.c new file mode 100644 index 0000000000..ec645eee40 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_eth.c @@ -0,0 +1,3100 @@ +/***************************************************************************** + * 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 n32g45x_eth.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_eth.h" +#include "n32g45x_gpio.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup ETH + * @brief ETH driver modules + * @{ + */ + +/** + * @brief Initialize GPIO pins for MII/RMII interface. + * + * @param ETH_Interface specifies the interface, can be the following values: + * @arg ETH_INTERFACE_RMII Reduced media-independent interface + * @arg ETH_INTERFACE_MII Media-independent interface + * @param remap remap mode, can be 0~3 + */ +void ETH_ConfigGpio(uint8_t ETH_Interface, uint8_t remap) +{ + GPIO_InitType GPIO_InitStructure; + uint32_t ETH_PA_O; + uint32_t ETH_PA_I; + uint32_t ETH_PB_O; + uint32_t ETH_PB_I; + uint32_t ETH_PC_O; + uint32_t ETH_PC_I; + uint32_t ETH_PD_O; + uint32_t ETH_PD_I; + if (ETH_Interface == ETH_INTERFACE_MII) + { + switch (remap) + { + case 0: + ETH_PA_O = GPIO_PIN_2; + ETH_PA_I = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_7; + ETH_PB_O = GPIO_PIN_8 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; + ETH_PB_I = GPIO_PIN_10 | GPIO_PIN_0 | GPIO_PIN_1; + ETH_PC_O = GPIO_PIN_1 | GPIO_PIN_2; + ETH_PC_I = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5; + ETH_PD_O = 0; + ETH_PD_I = 0; + break; + case 1: + ETH_PA_O = GPIO_PIN_2; + ETH_PA_I = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3; + ETH_PB_O = GPIO_PIN_8 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; + ETH_PB_I = GPIO_PIN_10; + ETH_PC_O = GPIO_PIN_1 | GPIO_PIN_2; + ETH_PC_I = GPIO_PIN_3; + ETH_PD_O = 0; + ETH_PD_I = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; + GPIO_ConfigPinRemap(GPIO_RMP1_ETH, ENABLE); + break; + case 2: + ETH_PA_O = GPIO_PIN_2; + ETH_PA_I = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_7; + ETH_PB_O = GPIO_PIN_7 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; + ETH_PB_I = GPIO_PIN_10 | GPIO_PIN_0 | GPIO_PIN_1; + ETH_PC_O = GPIO_PIN_1 | GPIO_PIN_2; + ETH_PC_I = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5; + ETH_PD_O = 0; + ETH_PD_I = 0; + GPIO_ConfigPinRemap(GPIO_RMP2_ETH, ENABLE); + break; + case 3: + ETH_PA_O = GPIO_PIN_2; + ETH_PA_I = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3; + ETH_PB_O = GPIO_PIN_7 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; + ETH_PB_I = GPIO_PIN_10 | GPIO_PIN_0 | GPIO_PIN_1; + ETH_PC_O = GPIO_PIN_1 | GPIO_PIN_2; + ETH_PC_I = GPIO_PIN_3; + ETH_PD_O = 0; + ETH_PD_I = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10; + GPIO_ConfigPinRemap(GPIO_RMP3_ETH, ENABLE); + break; + default: + while (1) + ; + } + } + else /* RMII */ + { + switch (remap) + { + case 0: + case 2: + ETH_PA_O = GPIO_PIN_2; + ETH_PA_I = GPIO_PIN_1 | GPIO_PIN_7; + ETH_PB_O = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; + ETH_PB_I = 0; + ETH_PC_O = GPIO_PIN_1; + ETH_PC_I = GPIO_PIN_4 | GPIO_PIN_5; + ETH_PD_O = 0; + ETH_PD_I = 0; + break; + case 1: + case 3: + ETH_PA_O = GPIO_PIN_2; + ETH_PA_I = GPIO_PIN_1; + ETH_PB_O = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; + ETH_PB_I = 0; + ETH_PC_O = GPIO_PIN_1; + ETH_PC_I = 0; + ETH_PD_O = 0; + ETH_PD_I = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10; + GPIO_ConfigPinRemap(GPIO_RMP1_ETH, ENABLE); + break; + default: + while (1) + ; + } + } + if (ETH_PA_O) + { + /* Configure Ethernet PA and PA8 (MCO) as alternate function push-pull */ + GPIO_InitStructure.Pin = ETH_PA_O; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure); + } + if (ETH_PB_O) + { + /* Configure Ethernet PB and PB5 (PPS) as alternate function push-pull */ + GPIO_InitStructure.Pin = ETH_PB_O; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure); + } + if (ETH_PC_O) + { + /* Configure Ethernet PC as alternate function push-pull */ + GPIO_InitStructure.Pin = ETH_PC_O; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure); + } + if (ETH_PD_O) + { + /* Configure Ethernet PD as alternate function push-pull */ + GPIO_InitStructure.Pin = ETH_PD_O; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitPeripheral(GPIOD, &GPIO_InitStructure); + } + + if (ETH_PA_I) + { + /* Configure Ethernet PA as input */ + GPIO_InitStructure.Pin = ETH_PA_I; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure); + } + if (ETH_PB_I) + { + /* Configure Ethernet PB as input */ + GPIO_InitStructure.Pin = ETH_PB_I; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure); + } + if (ETH_PC_I) + { + /* Configure Ethernet PC as input */ + GPIO_InitStructure.Pin = ETH_PC_I; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure); + } + if (ETH_PD_I) + { + /* Configure Ethernet PD as input */ + GPIO_InitStructure.Pin = ETH_PD_I; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitPeripheral(GPIOD, &GPIO_InitStructure); + } +} + +/** @addtogroup ETH_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + +/** @addtogroup ETH_Private_Defines + * @{ + */ +/* Global pointers on Tx and Rx descriptor used to track transmit and receive descriptors */ +__IO ETH_DMADescType* DMATxDescToSet; +__IO ETH_DMADescType* DMARxDescToGet; +__IO ETH_DMADescType* DMAPTPTxDescToSet; +__IO ETH_DMADescType* DMAPTPRxDescToGet; + +/* ETHERNET MAC address offsets */ +#define ETH_MAC_ADDR_HBASE (ETH_MAC_BASE + 0x40) /* ETHERNET MAC address high offset */ +#define ETH_MAC_ADDR_LBASE (ETH_MAC_BASE + 0x44) /* ETHERNET MAC address low offset */ + +/* ETHERNET MACMIIADDR register Mask */ +#define MACMIIAR_CR_MASK ((uint32_t)0xFFFFFFE3) + +/* ETHERNET MACCFG register Mask */ +#define MACCR_CLR_MASK ((uint32_t)0xFF20810F) + +/* ETHERNET MACFLWCTRL register Mask */ +#define MACFCR_CLR_MASK ((uint32_t)0x0000FF41) + +/* ETHERNET DMAOPMOD register Mask */ +#define DMAOMR_CLR_MASK ((uint32_t)0xF8DE3F23) + +/* ETHERNET Remote Wake-up frame register length */ +#define ETH_WAKEUP_REG_LEN 8 + +/* ETHERNET Missed frames counter Shift */ +#define ETH_DMA_RX_OVERFLOW_MISSEDFRAMES_COUNTER_SHIFT 17 + +/* ETHERNET DMA Tx descriptors Collision Count Shift */ +#define ETH_DMA_TX_DESC_COLLISION_COUNTER_SHIFT 3 + +/* ETHERNET DMA Tx descriptors Buffer2 Size Shift */ +#define ETH_DMA_TX_DESC_BUF2_SIZE_SHIFT 11 + +/* ETHERNET DMA Rx descriptors Frame Length Shift */ +#define ETH_DMA_RX_DESC_FRAME_LEN_SHIFT 16 + +/* ETHERNET DMA Rx descriptors Buffer2 Size Shift */ +#define ETH_DMA_RX_DESC_BUF2_SIZE_SHIFT 11 + +/** + * @} + */ + +/** @addtogroup ETH_Private_Macros + * @{ + */ +/** + * @} + */ + +/** @addtogroup ETH_Private_Variables + * @{ + */ +/** + * @} + */ + +/** @addtogroup ETH_Private_FunctionPrototypes + * @{ + */ +/** + * @} + */ + +/** @addtogroup ETH_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the ETHERNET peripheral registers to their default reset values. + */ +void ETH_DeInit(void) +{ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ETHMAC, ENABLE); + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ETHMAC, DISABLE); +} +/** + * @brief Initializes the ETHERNET peripheral according to the specified + * parameters in the ETH_InitStruct . + * @param ETH_InitStruct pointer to a ETH_InitType structure that contains + * the configuration information for the specified ETHERNET peripheral. + * @param callable a function pointer of @ref ETH_InitPHY + * @return ETH_ERROR: Ethernet initialization failed + * ETH_SUCCESS: Ethernet successfully initialized + */ +uint32_t ETH_Init(ETH_InitType* ETH_InitStruct, ETH_InitPHY callable) +{ + uint32_t tmpregister = 0; + RCC_ClocksType rcc_clocks; + uint32_t hclk = 60000000; + /* Check the parameters */ + /* MAC --------------------------*/ + assert_param(IS_ETH_AUTONEG(ETH_InitStruct->AutoNegotiation)); + assert_param(IS_ETH_WATCHDOG(ETH_InitStruct->Watchdog)); + assert_param(IS_ETH_JABBER(ETH_InitStruct->Jabber)); + assert_param(IS_ETH_INTER_FRAME_GAP(ETH_InitStruct->InterFrameGap)); + assert_param(IS_ETH_CARRIER_SENSE(ETH_InitStruct->CarrierSense)); + assert_param(IS_ETH_SPEED_MODE(ETH_InitStruct->SpeedMode)); + assert_param(IS_ETH_RX_OWN(ETH_InitStruct->RxOwn)); + assert_param(IS_ETH_LOOPBACK_MODE(ETH_InitStruct->LoopbackMode)); + assert_param(IS_ETH_DUPLEX_MODE(ETH_InitStruct->DuplexMode)); + assert_param(IS_ETH_CHECKSUM_OFFLOAD(ETH_InitStruct->ChecksumOffload)); + assert_param(IS_ETH_RETRY_TRANSMISSION(ETH_InitStruct->RetryTransmission)); + assert_param(IS_ETH_AUTO_PAD_CRC_STRIP(ETH_InitStruct->AutomaticPadCRCStrip)); + assert_param(IS_ETH_BACKOFF_LIMIT(ETH_InitStruct->BackoffLimit)); + assert_param(IS_ETH_DEFERRAL_CHECK(ETH_InitStruct->DeferralCheck)); + assert_param(IS_ETH_RX_ALL(ETH_InitStruct->RxAll)); + assert_param(IS_ETH_SRC_ADDR_FILTER(ETH_InitStruct->SrcAddrFilter)); + assert_param(IS_ETH_PASS_CTRL_FRAMES(ETH_InitStruct->PassCtrlFrames)); + assert_param(IS_ETH_BROADCAST_FRAMES_RECEPTION(ETH_InitStruct->BroadcastFramesReception)); + assert_param(IS_ETH_DEST_ADDR_FILTER(ETH_InitStruct->DestAddrFilter)); + assert_param(IS_ETH_PROMISCUOUS_MODE(ETH_InitStruct->PromiscuousMode)); + assert_param(IS_ETH_MULTICAST_FRAMES_FILTER(ETH_InitStruct->MulticastFramesFilter)); + assert_param(IS_ETH_UNICAST_FRAMES_FILTER(ETH_InitStruct->UnicastFramesFilter)); + assert_param(IS_ETH_PAUSE_TIME(ETH_InitStruct->PauseTime)); + assert_param(IS_ETH_ZERO_QUANTA_PAUSE(ETH_InitStruct->ZeroQuantaPause)); + assert_param(IS_ETH_PAUSE_LOW_THRESHOLD(ETH_InitStruct->PauseLowThreshold)); + assert_param(IS_ETH_UNICAST_PAUSE_FRAME_DETECT(ETH_InitStruct->UnicastPauseFrameDetect)); + assert_param(IS_ETH_RX_FLOW_CTRL(ETH_InitStruct->RxFlowCtrl)); + assert_param(IS_ETH_TX_FLOW_CTRL(ETH_InitStruct->TxFlowCtrl)); + assert_param(IS_ETH_VLAN_TAG_COMPARISON(ETH_InitStruct->VLANTagComparison)); + assert_param(IS_ETH_VLAN_TAG_IDENTIFIER(ETH_InitStruct->VLANTagIdentifier)); + /* DMA --------------------------*/ + assert_param(IS_ETH_DROP_TCPIP_CHECKSUM_FRAME(ETH_InitStruct->DropTCPIPChecksumErrorFrame)); + assert_param(IS_ETH_RX_STORE_FORWARD(ETH_InitStruct->RxStoreForward)); + assert_param(IS_ETH_FLUSH_RX_FRAME(ETH_InitStruct->FlushRxFrame)); + assert_param(IS_ETH_TX_STORE_FORWARD(ETH_InitStruct->TxStoreForward)); + assert_param(IS_ETH_TX_THRESHOLD_CTRL(ETH_InitStruct->TxThresholdCtrl)); + assert_param(IS_ETH_FORWARD_ERROR_FRAMES(ETH_InitStruct->ForwardErrorFrames)); + assert_param(IS_ETH_FORWARD_UNDERSIZED_GOOD_FRAMES(ETH_InitStruct->ForwardUndersizedGoodFrames)); + assert_param(IS_ETH_RX_THRESHOLD_CTRL(ETH_InitStruct->RxThresholdCtrl)); + assert_param(IS_ETH_SECOND_FRAME_OPERATE(ETH_InitStruct->SecondFrameOperate)); + assert_param(IS_ETH_ADDR_ALIGNED_BEATS(ETH_InitStruct->AddrAlignedBeats)); + assert_param(IS_ETH_FIXED_BURST(ETH_InitStruct->FixedBurst)); + assert_param(IS_ETH_RX_DMA_BURST_LEN(ETH_InitStruct->RxDMABurstLen)); + assert_param(IS_ETH_TX_DMA_BURST_LEN(ETH_InitStruct->TxDMABurstLen)); + assert_param(IS_ETH_DMA_DESC_SKIP_LEN(ETH_InitStruct->DescSkipLen)); + assert_param(IS_ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX(ETH_InitStruct->DMAArbitration)); + /*-------------------------------- MAC Config ------------------------------*/ + /*---------------------- ETHERNET MACMIIADDR Configuration -------------------*/ + /* Get the ETHERNET MACMIIADDR value */ + tmpregister = ETH->MACMIIADDR; + /* Clear CTRLSTS Clock Range CTRL[2:0] bits */ + tmpregister &= MACMIIAR_CR_MASK; + /* Get hclk frequency value */ + RCC_GetClocksFreqValue(&rcc_clocks); + hclk = rcc_clocks.HclkFreq; + /* Set CTRL bits depending on hclk value */ + if (/*(hclk >= 20000000) && */ (hclk < 35000000)) + { + /* CTRLSTS Clock Range between 20-35 MHz */ + tmpregister |= (uint32_t)ETH_MACMIIADDR_CR_DIV16; + } + else if ((hclk >= 35000000) && (hclk < 60000000)) + { + /* CTRLSTS Clock Range between 35-60 MHz */ + tmpregister |= (uint32_t)ETH_MACMIIADDR_CR_DIV26; + } + else if ((hclk >= 60000000) && (hclk <= 72000000)) + { + /* CTRLSTS Clock Range between 60-72 MHz */ + tmpregister |= (uint32_t)ETH_MACMIIADDR_CR_DIV42; + } + /* Write to ETHERNET MAC MIIAR: Configure the ETHERNET CTRLSTS Clock Range */ + ETH->MACMIIADDR = (uint32_t)tmpregister; + /*-------------------- PHY initialization and configuration ----------------*/ + if (ETH_ERROR == callable(ETH_InitStruct)) + { + return ETH_ERROR; + } + + /*------------------------ ETHERNET MACCFG Configuration --------------------*/ + /* Get the ETHERNET MACCFG value */ + tmpregister = ETH->MACCFG; + /* Clear WD, PCE, PS, TE and RE bits */ + tmpregister &= MACCR_CLR_MASK; + /* Set the WD bit according to Watchdog value */ + /* Set the JD: bit according to Jabber value */ + /* Set the IFG bit according to InterFrameGap value */ + /* Set the DCRS bit according to CarrierSense value */ + /* Set the FES bit according to SpeedMode value */ + /* Set the DO bit according to RxOwn value */ + /* Set the LM bit according to LoopbackMode value */ + /* Set the DM bit according to DuplexMode value */ + /* Set the IPC bit according to ChecksumOffload value */ + /* Set the DAT bit according to RetryTransmission value */ + /* Set the ACS bit according to AutomaticPadCRCStrip value */ + /* Set the BL bit according to BackoffLimit value */ + /* Set the DC bit according to DeferralCheck value */ + tmpregister |= (uint32_t)( + ETH_InitStruct->Watchdog | ETH_InitStruct->Jabber | ETH_InitStruct->InterFrameGap | ETH_InitStruct->CarrierSense + | ETH_InitStruct->SpeedMode | ETH_InitStruct->RxOwn | ETH_InitStruct->LoopbackMode | ETH_InitStruct->DuplexMode + | ETH_InitStruct->ChecksumOffload | ETH_InitStruct->RetryTransmission | ETH_InitStruct->AutomaticPadCRCStrip + | ETH_InitStruct->BackoffLimit | ETH_InitStruct->DeferralCheck); + /* Write to ETHERNET MACCFG */ + ETH->MACCFG = (uint32_t)tmpregister; + + /*----------------------- ETHERNET MACFFLT Configuration --------------------*/ + /* Set the RA bit according to RxAll value */ + /* Set the SAF and SAIF bits according to SrcAddrFilter value */ + /* Set the PCF bit according to PassCtrlFrames value */ + /* Set the DBF bit according to BroadcastFramesReception value */ + /* Set the DAIF bit according to DestAddrFilter value */ + /* Set the PEND bit according to PromiscuousMode value */ + /* Set the PM, HMC and HPF bits according to MulticastFramesFilter value */ + /* Set the HUC and HPF bits according to UnicastFramesFilter value */ + /* Write to ETHERNET MACFFLT */ + ETH->MACFFLT = (uint32_t)(ETH_InitStruct->RxAll | ETH_InitStruct->SrcAddrFilter | ETH_InitStruct->PassCtrlFrames + | ETH_InitStruct->BroadcastFramesReception | ETH_InitStruct->DestAddrFilter + | ETH_InitStruct->PromiscuousMode | ETH_InitStruct->MulticastFramesFilter + | ETH_InitStruct->UnicastFramesFilter); + /*--------------- ETHERNET MACHASHHI and MACHASHLO Configuration ---------------*/ + /* Write to ETHERNET MACHASHHI */ + ETH->MACHASHHI = (uint32_t)ETH_InitStruct->HashTableHigh; + /* Write to ETHERNET MACHASHLO */ + ETH->MACHASHLO = (uint32_t)ETH_InitStruct->HashTableLow; + /*----------------------- ETHERNET MACFLWCTRL Configuration --------------------*/ + /* Get the ETHERNET MACFLWCTRL value */ + tmpregister = ETH->MACFLWCTRL; + /* Clear xx bits */ + tmpregister &= MACFCR_CLR_MASK; + + /* Set the PT bit according to PauseTime value */ + /* Set the DZPQ bit according to ZeroQuantaPause value */ + /* Set the PLT bit according to PauseLowThreshold value */ + /* Set the UP bit according to UnicastPauseFrameDetect value */ + /* Set the RFE bit according to RxFlowCtrl value */ + /* Set the TFE bit according to TxFlowCtrl value */ + tmpregister |= (uint32_t)((ETH_InitStruct->PauseTime << 16) | ETH_InitStruct->ZeroQuantaPause + | ETH_InitStruct->PauseLowThreshold | ETH_InitStruct->UnicastPauseFrameDetect + | ETH_InitStruct->RxFlowCtrl | ETH_InitStruct->TxFlowCtrl); + /* Write to ETHERNET MACFLWCTRL */ + ETH->MACFLWCTRL = (uint32_t)tmpregister; + /*----------------------- ETHERNET MACVLANTAG Configuration -----------------*/ + /* Set the ETV bit according to VLANTagComparison value */ + /* Set the VL bit according to VLANTagIdentifier value */ + ETH->MACVLANTAG = (uint32_t)(ETH_InitStruct->VLANTagComparison | ETH_InitStruct->VLANTagIdentifier); + + /*-------------------------------- DMA Config ------------------------------*/ + /*----------------------- ETHERNET DMAOPMOD Configuration --------------------*/ + /* Get the ETHERNET DMAOPMOD value */ + tmpregister = ETH->DMAOPMOD; + /* Clear xx bits */ + tmpregister &= DMAOMR_CLR_MASK; + + /* Set the DT bit according to DropTCPIPChecksumErrorFrame value */ + /* Set the RSYF bit according to RxStoreForward value */ + /* Set the DFF bit according to FlushRxFrame value */ + /* Set the TSF bit according to TxStoreForward value */ + /* Set the TTC bit according to TxThresholdCtrl value */ + /* Set the FEF bit according to ForwardErrorFrames value */ + /* Set the FUF bit according to ForwardUndersizedGoodFrames value */ + /* Set the RTC bit according to RxThresholdCtrl value */ + /* Set the OSF bit according to SecondFrameOperate value */ + tmpregister |= + (uint32_t)(ETH_InitStruct->DropTCPIPChecksumErrorFrame | ETH_InitStruct->RxStoreForward + | ETH_InitStruct->FlushRxFrame | ETH_InitStruct->TxStoreForward | ETH_InitStruct->TxThresholdCtrl + | ETH_InitStruct->ForwardErrorFrames | ETH_InitStruct->ForwardUndersizedGoodFrames + | ETH_InitStruct->RxThresholdCtrl | ETH_InitStruct->SecondFrameOperate); + /* Write to ETHERNET DMAOPMOD */ + ETH->DMAOPMOD = (uint32_t)tmpregister; + + /*----------------------- ETHERNET DMABUSMOD Configuration --------------------*/ + /* Set the AAL bit according to AddrAlignedBeats value */ + /* Set the FB bit according to FixedBurst value */ + /* Set the RPBL and 4*PBL bits according to RxDMABurstLen value */ + /* Set the PBL and 4*PBL bits according to TxDMABurstLen value */ + /* Set the DSL bit according to ETH_DesciptorSkipLength value */ + /* Set the PEND and DA bits according to DMAArbitration value */ + ETH->DMABUSMOD = + (uint32_t)(ETH_InitStruct->AddrAlignedBeats | ETH_InitStruct->FixedBurst | ETH_InitStruct->RxDMABurstLen + | /* !! if 4xPBL is selected for Tx or Rx it is applied for the other */ + ETH_InitStruct->TxDMABurstLen | (ETH_InitStruct->DescSkipLen << 2) | ETH_InitStruct->DMAArbitration + | ETH_DMABUSMOD_USP); /* Enable use of separate PBL for Rx and Tx */ + + /* Disable all MMC interrupt */ + ETH->MMCRXINTMSK = 0xffffffffUL; + ETH->MMCTXINTMSK = 0xffffffffUL; + ETH->MMCRXCOINTMSK = 0xffffffffUL; + + /* Return Ethernet configuration success */ + return ETH_SUCCESS; +} + +/** + * @brief Fills each ETH_InitStruct member with its default value. + * @param ETH_InitStruct pointer to a ETH_InitType structure which will be initialized. + */ +void ETH_InitStruct(ETH_InitType* ETH_InitStruct) +{ + /* ETH_InitStruct members default value */ + /*------------------------ MAC -----------------------------------*/ + ETH_InitStruct->AutoNegotiation = ETH_AUTONEG_DISABLE; + ETH_InitStruct->Watchdog = ETH_WATCHDOG_ENABLE; + ETH_InitStruct->Jabber = ETH_JABBER_ENABLE; + ETH_InitStruct->InterFrameGap = ETH_INTER_FRAME_GAP_96BIT; + ETH_InitStruct->CarrierSense = ETH_CARRIER_SENSE_ENABLE; + ETH_InitStruct->SpeedMode = ETH_SPEED_MODE_10M; + ETH_InitStruct->RxOwn = ETH_RX_OWN_ENABLE; + ETH_InitStruct->LoopbackMode = ETH_LOOPBACK_MODE_DISABLE; + ETH_InitStruct->DuplexMode = ETH_DUPLEX_MODE_HALF; + ETH_InitStruct->ChecksumOffload = ETH_CHECKSUM_OFFLOAD_DISABLE; + ETH_InitStruct->RetryTransmission = ETH_RETRY_TRANSMISSION_ENABLE; + ETH_InitStruct->AutomaticPadCRCStrip = ETH_AUTO_PAD_CRC_STRIP_DISABLE; + ETH_InitStruct->BackoffLimit = ETH_BACKOFF_LIMIT_10; + ETH_InitStruct->DeferralCheck = ETH_DEFERRAL_CHECK_DISABLE; + ETH_InitStruct->RxAll = ETH_RX_ALL_DISABLE; + ETH_InitStruct->SrcAddrFilter = ETH_SRC_ADDR_FILTER_DISABLE; + ETH_InitStruct->PassCtrlFrames = ETH_PASS_CTRL_FRAMES_BLOCK_ALL; + ETH_InitStruct->BroadcastFramesReception = ETH_BROADCAST_FRAMES_RECEPTION_DISABLE; + ETH_InitStruct->DestAddrFilter = ETH_DEST_ADDR_FILTER_NORMAL; + ETH_InitStruct->PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE; + ETH_InitStruct->MulticastFramesFilter = ETH_MULTICAST_FRAMES_FILTER_PERFECT; + ETH_InitStruct->UnicastFramesFilter = ETH_UNICAST_FRAMES_FILTER_PERFECT; + ETH_InitStruct->HashTableHigh = 0x0; + ETH_InitStruct->HashTableLow = 0x0; + ETH_InitStruct->PauseTime = 0x0; + ETH_InitStruct->ZeroQuantaPause = ETH_ZERO_QUANTA_PAUSE_DISABLE; + ETH_InitStruct->PauseLowThreshold = ETH_PAUSE_LOW_THRESHOLD_MINUS4; + ETH_InitStruct->UnicastPauseFrameDetect = ETH_UNICAST_PAUSE_FRAME_DETECT_DISABLE; + ETH_InitStruct->RxFlowCtrl = ETH_RX_FLOW_CTRL_DISABLE; + ETH_InitStruct->TxFlowCtrl = ETH_TX_FLOW_CTRL_DISABLE; + ETH_InitStruct->VLANTagComparison = ETH_VLAN_TAG_COMPARISON_16BIT; + ETH_InitStruct->VLANTagIdentifier = 0x0; + /*------------------------ DMA -----------------------------------*/ + ETH_InitStruct->DropTCPIPChecksumErrorFrame = ETH_DROP_TCPIP_CHECKSUM_ERROR_FRAME_DISABLE; + ETH_InitStruct->RxStoreForward = ETH_RX_STORE_FORWARD_ENABLE; + ETH_InitStruct->FlushRxFrame = ETH_FLUSH_RX_FRAME_DISABLE; + ETH_InitStruct->TxStoreForward = ETH_TX_STORE_FORWARD_ENABLE; + ETH_InitStruct->TxThresholdCtrl = ETH_TX_THRESHOLD_CTRL_64BYTES; + ETH_InitStruct->ForwardErrorFrames = ETH_FORWARD_ERROR_FRAMES_DISABLE; + ETH_InitStruct->ForwardUndersizedGoodFrames = ETH_FORWARD_UNDERSIZED_GOOD_FRAMES_ENABLE; + ETH_InitStruct->RxThresholdCtrl = ETH_RX_THRESHOLD_CTRL_64BYTES; + ETH_InitStruct->SecondFrameOperate = ETH_SECOND_FRAME_OPERATE_DISABLE; + ETH_InitStruct->AddrAlignedBeats = ETH_ADDR_ALIGNED_BEATS_ENABLE; + ETH_InitStruct->FixedBurst = ETH_FIXED_BURST_DISABLE; + ETH_InitStruct->RxDMABurstLen = ETH_RX_DMA_BURST_LEN_1BEAT; + ETH_InitStruct->TxDMABurstLen = ETH_TX_DMA_BURST_LEN_1BEAT; + ETH_InitStruct->DescSkipLen = 0x0; + ETH_InitStruct->DMAArbitration = ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_1_1; +} + +/** + * @brief Enables ENET MAC and DMA reception/transmission + */ +void ETH_EnableTxRx(void) +{ + /* Enable transmit state machine of the MAC for transmission on the MII */ + ETH_EnableMacTx(ENABLE); + /* Flush Transmit DATFIFO */ + ETH_FlushTxFifo(); + /* Enable receive state machine of the MAC for reception from the MII */ + ETH_EnableMacRx(ENABLE); + + /* Start DMA transmission */ + ETH_EnableDmaTx(ENABLE); + /* Start DMA reception */ + ETH_EnableDmaRx(ENABLE); +} + +/** + * @brief Transmits a packet, from application buffer, pointed by ppkt. + * @param ppkt pointer to the application's packet buffer to transmit. + * @param FrameLength Tx Packet size. + * @return ETH_ERROR: in case of Tx desc owned by DMA + * ETH_SUCCESS: for correct transmission + */ +uint32_t ETH_TxPacket(uint8_t* ppkt, uint16_t FrameLength) +{ + uint32_t send_len = 0; + + while (send_len < FrameLength) + { + uint32_t offset = 0; + + /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */ + if ((DMATxDescToSet->Status & ETH_DMA_TX_DESC_OWN) != (uint32_t)RESET) + { + /* Return ERROR: OWN bit set */ + return ETH_ERROR; + } + + uint16_t block_len = FrameLength - send_len; + if (block_len > ETH_DMA_TX_DESC_TBS1) + { + block_len = ETH_DMA_TX_DESC_TBS1; + } + /* Copy the frame to be sent into memory pointed by the current ETHERNET DMA Tx descriptor */ + for (offset = 0; offset < block_len; offset++) + { + (*(__IO uint8_t*)((DMATxDescToSet->Buf1Addr) + offset)) = (*(ppkt + offset + send_len)); + } + + /* Setting the Frame Length: bits[10:0] */ + DMATxDescToSet->CtrlOrBufSize &= (~ETH_DMA_TX_DESC_TBS1); + DMATxDescToSet->CtrlOrBufSize |= block_len; + /* Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) */ + if (send_len == 0) + { + DMATxDescToSet->CtrlOrBufSize |= ETH_DMA_TX_DESC_FS; + } + send_len += block_len; + if (send_len == FrameLength) + { + DMATxDescToSet->CtrlOrBufSize |= ETH_DMA_TX_DESC_LS; + } + + /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ + DMATxDescToSet->Status |= ETH_DMA_TX_DESC_OWN; + /* When Tx Buffer unavailable flag is set: clear it and resume transmission */ + if ((ETH->DMASTS & ETH_DMASTS_TU) != (uint32_t)RESET) + { + /* Clear TBUS ETHERNET DMA flag */ + ETH->DMASTS = ETH_DMASTS_TU; + /* Resume DMA transmission*/ + ETH->DMATXPD = 0; + } + + /* Update the ETHERNET DMA global Tx descriptor with next Tx decriptor */ + /* Chained Mode */ + if ((DMATxDescToSet->CtrlOrBufSize & ETH_DMA_TX_DESC_TCH) != (uint32_t)RESET) + { + /* Selects the next DMA Tx descriptor list for next buffer to send */ + DMATxDescToSet = (ETH_DMADescType*)(DMATxDescToSet->Buf2OrNextDescAddr); + } + else /* Ring Mode */ + { + if ((DMATxDescToSet->CtrlOrBufSize & ETH_DMA_TX_DESC_TER) != (uint32_t)RESET) + { + /* Selects the first DMA Tx descriptor for next buffer to send: last Tx descriptor was used */ + DMATxDescToSet = (ETH_DMADescType*)(ETH->DMATXDLADDR); + } + else + { + /* Selects the next DMA Tx descriptor list for next buffer to send */ + DMATxDescToSet = + (ETH_DMADescType*)((uint32_t)DMATxDescToSet + 0x10 + ((ETH->DMABUSMOD & ETH_DMABUSMOD_DSL))); + } + } + } + /* Return SUCCESS */ + return ETH_SUCCESS; +} + +/** + * @brief Receives a packet and copies it to memory pointed by ppkt. + * @param ppkt pointer to the application packet receive buffer. + * @param checkErr whether check error + * @return ETH_ERROR: if there is error in reception + * framelength: received packet size if packet reception is correct + */ +uint32_t ETH_RxPacket(uint8_t* ppkt, uint8_t checkErr) +{ + uint32_t offset = 0, framelength = 0; + /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */ + if ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_OWN) != (uint32_t)RESET) + { + /* Return error: OWN bit set */ + return ETH_ERROR; + } + + if (((checkErr && ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_ES) == (uint32_t)RESET)) || !checkErr) + && ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_LS) != (uint32_t)RESET) + && ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_FS) != (uint32_t)RESET)) + { + /* Get the Frame Length of the received packet */ + framelength = ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_FL) >> ETH_DMA_RX_DESC_FRAME_LEN_SHIFT); + /* Copy the received frame into buffer from memory pointed by the current ETHERNET DMA Rx descriptor */ + for (offset = 0; offset < framelength; offset++) + { + (*(ppkt + offset)) = (*(__IO uint8_t*)((DMARxDescToGet->Buf1Addr) + offset)); + } + } + else + { + /* Return ERROR */ + framelength = ETH_ERROR; + } + /* Set Own bit of the Rx descriptor Status: gives the buffer back to ETHERNET DMA */ + DMARxDescToGet->Status = ETH_DMA_RX_DESC_OWN; + + /* When Rx Buffer unavailable flag is set: clear it and resume reception */ + if ((ETH->DMASTS & ETH_DMASTS_RU) != (uint32_t)RESET) + { + /* Clear RBUS ETHERNET DMA flag */ + ETH->DMASTS = ETH_DMASTS_RU; + /* Resume DMA reception */ + ETH->DMARXPD = 0; + } + + /* Update the ETHERNET DMA global Rx descriptor with next Rx decriptor */ + /* Chained Mode */ + if ((DMARxDescToGet->CtrlOrBufSize & ETH_DMA_RX_DESC_RCH) != (uint32_t)RESET) + { + /* Selects the next DMA Rx descriptor list for next buffer to read */ + DMARxDescToGet = (ETH_DMADescType*)(DMARxDescToGet->Buf2OrNextDescAddr); + } + else /* Ring Mode */ + { + if ((DMARxDescToGet->CtrlOrBufSize & ETH_DMA_RX_DESC_RER) != (uint32_t)RESET) + { + /* Selects the first DMA Rx descriptor for next buffer to read: last Rx descriptor was used */ + DMARxDescToGet = (ETH_DMADescType*)(ETH->DMARXDLADDR); + } + else + { + /* Selects the next DMA Rx descriptor list for next buffer to read */ + DMARxDescToGet = + (ETH_DMADescType*)((uint32_t)DMARxDescToGet + 0x10 + ((ETH->DMABUSMOD & ETH_DMABUSMOD_DSL))); + } + } + + /* Return Frame Length/ERROR */ + return (framelength); +} + +/** + * @brief Get the size of received the received packet. + * @return framelength: received packet size + */ +uint32_t ETH_GetRxPacketSize(void) +{ + uint32_t frameLength = 0; + if (((DMARxDescToGet->Status & ETH_DMA_RX_DESC_OWN) == (uint32_t)RESET) + && ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_ES) == (uint32_t)RESET) + && ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_LS) != (uint32_t)RESET) + && ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_FS) != (uint32_t)RESET)) + { + /* Get the size of the packet: including 4 bytes of the CRC */ + frameLength = ETH_GetDmaRxDescFrameLen(DMARxDescToGet); + } + + /* Return Frame Length */ + return frameLength; +} + +/** + * @brief Drop a Received packet (too small packet, etc...) + */ +void ETH_DropRxPacket(void) +{ + /* Set Own bit of the Rx descriptor Status: gives the buffer back to ETHERNET DMA */ + DMARxDescToGet->Status = ETH_DMA_RX_DESC_OWN; + /* Chained Mode */ + if ((DMARxDescToGet->CtrlOrBufSize & ETH_DMA_RX_DESC_RCH) != (uint32_t)RESET) + { + /* Selects the next DMA Rx descriptor list for next buffer read */ + DMARxDescToGet = (ETH_DMADescType*)(DMARxDescToGet->Buf2OrNextDescAddr); + } + else /* Ring Mode */ + { + if ((DMARxDescToGet->CtrlOrBufSize & ETH_DMA_RX_DESC_RER) != (uint32_t)RESET) + { + /* Selects the next DMA Rx descriptor list for next buffer read: this will + be the first Rx descriptor in this case */ + DMARxDescToGet = (ETH_DMADescType*)(ETH->DMARXDLADDR); + } + else + { + /* Selects the next DMA Rx descriptor list for next buffer read */ + DMARxDescToGet = + (ETH_DMADescType*)((uint32_t)DMARxDescToGet + 0x10 + ((ETH->DMABUSMOD & ETH_DMABUSMOD_DSL))); + } + } +} + +/*--------------------------------- PHY ------------------------------------*/ +/** + * @brief Read a PHY register + * @param PHYAddress PHY device address, is the index of one of supported 32 PHY devices. + * This parameter can be one of the following values: 0,..,31 + * @param PHYReg PHY register address, is the index of one of the 32 PHY register. + * This parameter can be one of the following values: + * @arg PHY_BCR Tranceiver Basic Control Register + * @arg PHY_BSR Tranceiver Basic Status Register + * @arg PHY_SR Tranceiver Status Register + * @arg More PHY register could be read depending on the used PHY + * @return ETH_ERROR: in case of timeout + * MAC MIIDR register value: Data read from the selected PHY register (correct read ) + */ +uint16_t ETH_ReadPhyRegister(uint16_t PHYAddress, uint16_t PHYReg) +{ + uint32_t tmpregister = 0; + __IO uint32_t timeout = 0; + /* Check the parameters */ + assert_param(IS_ETH_PHY_ADDRESS(PHYAddress)); + assert_param(IS_ETH_PHY_REG(PHYReg)); + + /* Get the ETHERNET MACMIIADDR value */ + tmpregister = ETH->MACMIIADDR; + /* Keep only the CTRLSTS Clock Range CTRL[2:0] bits value */ + tmpregister &= ~MACMIIAR_CR_MASK; + /* Prepare the MII address register value */ + tmpregister |= (((uint32_t)PHYAddress << 11) & ETH_MACMIIADDR_PA); /* Set the PHY device address */ + tmpregister |= (((uint32_t)PHYReg << 6) & ETH_MACMIIADDR_MR); /* Set the PHY register address */ + tmpregister &= ~ETH_MACMIIADDR_MW; /* Set the read mode */ + tmpregister |= ETH_MACMIIADDR_MB; /* Set the MII Busy bit */ + /* Write the result value into the MII Address register */ + ETH->MACMIIADDR = tmpregister; + /* Check for the Busy flag */ + do + { + timeout++; + tmpregister = ETH->MACMIIADDR; + } while ((tmpregister & ETH_MACMIIADDR_MB) && (timeout < (uint32_t)PHY_READ_TO)); + /* Return ERROR in case of timeout */ + if (timeout == PHY_READ_TO) + { + return (uint16_t)ETH_ERROR; + } + + /* Return data register value */ + uint16_t ret = (uint16_t)(ETH->MACMIIDAT); + return ret; +} + +/** + * @brief Write to a PHY register + * @param PHYAddress PHY device address, is the index of one of supported 32 PHY devices. + * This parameter can be one of the following values: 0,..,31 + * @param PHYReg PHY register address, is the index of one of the 32 PHY register. + * This parameter can be one of the following values: + * @arg PHY_BCR Tranceiver Control Register + * @arg More PHY register could be written depending on the used PHY + * @param PHYValue the value to write + * @return ETH_ERROR: in case of timeout + * ETH_SUCCESS: for correct write + */ +uint32_t ETH_WritePhyRegister(uint16_t PHYAddress, uint16_t PHYReg, uint16_t PHYValue) +{ + uint32_t tmpregister = 0; + __IO uint32_t timeout = 0; + /* Check the parameters */ + assert_param(IS_ETH_PHY_ADDRESS(PHYAddress)); + assert_param(IS_ETH_PHY_REG(PHYReg)); + + /* Get the ETHERNET MACMIIADDR value */ + tmpregister = ETH->MACMIIADDR; + /* Keep only the CTRLSTS Clock Range CTRL[2:0] bits value */ + tmpregister &= ~MACMIIAR_CR_MASK; + /* Prepare the MII register address value */ + tmpregister |= (((uint32_t)PHYAddress << 11) & ETH_MACMIIADDR_PA); /* Set the PHY device address */ + tmpregister |= (((uint32_t)PHYReg << 6) & ETH_MACMIIADDR_MR); /* Set the PHY register address */ + tmpregister |= ETH_MACMIIADDR_MW; /* Set the write mode */ + tmpregister |= ETH_MACMIIADDR_MB; /* Set the MII Busy bit */ + /* Give the value to the MII data register */ + ETH->MACMIIDAT = PHYValue; + /* Write the result value into the MII Address register */ + ETH->MACMIIADDR = tmpregister; + /* Check for the Busy flag */ + do + { + timeout++; + tmpregister = ETH->MACMIIADDR; + } while ((tmpregister & ETH_MACMIIADDR_MB) && (timeout < (uint32_t)PHY_WRITE_TO)); + /* Return ERROR in case of timeout */ + if (timeout == PHY_WRITE_TO) + { + return ETH_ERROR; + } + + /* Return SUCCESS */ + return ETH_SUCCESS; +} + +/** + * @brief Enables or disables the PHY loopBack mode. + * @note: Don't be confused with ETH_MACLoopBackCmd function which enables internal + * loopback at MII level + * @param PHYAddress PHY device address, is the index of one of supported 32 PHY devices. + * This parameter can be one of the following values: + * @param Cmd new state of the PHY loopBack mode. + * This parameter can be: ENABLE or DISABLE. + * @return ETH_ERROR: in case of bad PHY configuration + * ETH_SUCCESS: for correct PHY configuration + */ +uint32_t ETH_EnablePhyLoopBack(uint16_t PHYAddress, FunctionalState Cmd) +{ + uint16_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_ETH_PHY_ADDRESS(PHYAddress)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Get the PHY configuration to update it */ + tmpregister = ETH_ReadPhyRegister(PHYAddress, PHY_BCR); + + if (Cmd != DISABLE) + { + /* Enable the PHY loopback mode */ + tmpregister |= PHY_LOOPBACK; + } + else + { + /* Disable the PHY loopback mode: normal mode */ + tmpregister &= (uint16_t)(~(uint16_t)PHY_LOOPBACK); + } + /* Update the PHY control register with the new configuration */ + if (ETH_WritePhyRegister(PHYAddress, PHY_BCR, tmpregister) != (uint32_t)RESET) + { + return ETH_SUCCESS; + } + else + { + /* Return SUCCESS */ + return ETH_ERROR; + } +} + +/*--------------------------------- MAC ------------------------------------*/ +/** + * @brief Enables or disables the MAC transmission. + * @param Cmd new state of the MAC transmission. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMacTx(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the MAC transmission */ + ETH->MACCFG |= ETH_MACCFG_TE; + } + else + { + /* Disable the MAC transmission */ + ETH->MACCFG &= ~ETH_MACCFG_TE; + } +} + +/** + * @brief Enables or disables the MAC reception. + * @param Cmd new state of the MAC reception. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMacRx(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the MAC reception */ + ETH->MACCFG |= ETH_MACCFG_RE; + } + else + { + /* Disable the MAC reception */ + ETH->MACCFG &= ~ETH_MACCFG_RE; + } +} + +/** + * @brief Checks whether the ETHERNET flow control busy bit is set or not. + * @return The new state of flow control busy status bit (SET or RESET). + */ +FlagStatus ETH_GetFlowCtrlBusyStatus(void) +{ + FlagStatus bitstatus = RESET; + /* The Flow Control register should not be written to until this bit is cleared */ + if ((ETH->MACFLWCTRL & ETH_MACFLWCTRL_FCB_BPA) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Initiate a Pause Control Frame (Full-duplex only). + */ +void ETH_GeneratePauseCtrlFrame(void) +{ + /* When Set In full duplex MAC initiates pause control frame */ + ETH->MACFLWCTRL |= ETH_MACFLWCTRL_FCB_BPA; +} + +/** + * @brief Enables or disables the MAC BackPressure operation activation (Half-duplex only). + * @param Cmd new state of the MAC BackPressure operation activation. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableBackPressureActivation(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Activate the MAC BackPressure operation */ + /* In Half duplex: during backpressure, when the MAC receives a new frame, + the transmitter starts sending a JAM pattern resulting in a collision */ + ETH->MACFLWCTRL |= ETH_MACFLWCTRL_FCB_BPA; + } + else + { + /* Desactivate the MAC BackPressure operation */ + ETH->MACFLWCTRL &= ~ETH_MACFLWCTRL_FCB_BPA; + } +} + +/** + * @brief Checks whether the specified ETHERNET MAC flag is set or not. + * @param ETH_MAC_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_MAC_FLAG_TST Time stamp trigger flag + * @arg ETH_MAC_FLAG_MMCTX MMC transmit flag + * @arg ETH_MAC_FLAG_MMCRX MMC receive flag + * @arg ETH_MAC_FLAG_MMC MMC flag + * @arg ETH_MAC_FLAG_PMT PMT flag + * @return The new state of ETHERNET MAC flag (SET or RESET). + */ +FlagStatus ETH_GetMacFlagStatus(uint32_t ETH_MAC_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_MAC_GET_FLAG(ETH_MAC_FLAG)); + if ((ETH->MACINTSTS & ETH_MAC_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Checks whether the specified ETHERNET MAC interrupt has occurred or not. + * @param ETH_MAC_IT specifies the interrupt source to check. + * This parameter can be one of the following values: + * @arg ETH_MAC_INT_TST Time stamp trigger interrupt + * @arg ETH_MAC_INT_MMCTX MMC transmit interrupt + * @arg ETH_MAC_INT_MMCRX MMC receive interrupt + * @arg ETH_MAC_INT_MMC MMC interrupt + * @arg ETH_MAC_INT_PMT PMT interrupt + * @return The new state of ETHERNET MAC interrupt (SET or RESET). + */ +INTStatus ETH_GetMacIntStatus(uint32_t ETH_MAC_IT) +{ + INTStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_MAC_GET_INT(ETH_MAC_IT)); + if ((ETH->MACINTSTS & ETH_MAC_IT) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Enables or disables the specified ETHERNET MAC interrupts. + * @param ETH_MAC_IT specifies the ETHERNET MAC interrupt sources to be + * enabled or disabled. + * This parameter can be any combination of the following values: + * @arg ETH_MAC_INT_TST Time stamp trigger interrupt + * @arg ETH_MAC_INT_PMT PMT interrupt + * @param Cmd new state of the specified ETHERNET MAC interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMacInt(uint32_t ETH_MAC_IT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_ETH_MAC_INT(ETH_MAC_IT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected ETHERNET MAC interrupts */ + ETH->MACINTMSK &= (~(uint32_t)ETH_MAC_IT); + } + else + { + /* Disable the selected ETHERNET MAC interrupts */ + ETH->MACINTMSK |= ETH_MAC_IT; + } +} + +/** + * @brief Configures the selected MAC address. + * @param MacAddr The MAC addres to configure. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDR0 MAC Address0 + * @arg ETH_MAC_ADDR1 MAC Address1 + * @arg ETH_MAC_ADDR2 MAC Address2 + * @arg ETH_MAC_ADDR3 MAC Address3 + * @param Addr Pointer on MAC address buffer data (6 bytes). + */ +void ETH_SetMacAddr(uint32_t MacAddr, uint8_t* Addr) +{ + uint32_t tmpregister; + /* Check the parameters */ + assert_param(IS_ETH_MAC_ADDR0123(MacAddr)); + + /* Calculate the selectecd MAC address high register */ + tmpregister = ((uint32_t)Addr[5] << 8) | (uint32_t)Addr[4]; + /* Load the selectecd MAC address high register */ + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + MacAddr)) = tmpregister; + /* Calculate the selectecd MAC address low register */ + tmpregister = ((uint32_t)Addr[3] << 24) | ((uint32_t)Addr[2] << 16) | ((uint32_t)Addr[1] << 8) | Addr[0]; + + /* Load the selectecd MAC address low register */ + (*(__IO uint32_t*)(ETH_MAC_ADDR_LBASE + MacAddr)) = tmpregister; +} + +/** + * @brief Get the selected MAC address. + * @param MacAddr The MAC addres to return. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDR0 MAC Address0 + * @arg ETH_MAC_ADDR1 MAC Address1 + * @arg ETH_MAC_ADDR2 MAC Address2 + * @arg ETH_MAC_ADDR3 MAC Address3 + * @param Addr Pointer on MAC address buffer data (6 bytes). + */ +void ETH_GetMacAddr(uint32_t MacAddr, uint8_t* Addr) +{ + uint32_t tmpregister; + /* Check the parameters */ + assert_param(IS_ETH_MAC_ADDR0123(MacAddr)); + + /* Get the selectecd MAC address high register */ + tmpregister = (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + MacAddr)); + + /* Calculate the selectecd MAC address buffer */ + Addr[5] = ((tmpregister >> 8) & (uint8_t)0xFF); + Addr[4] = (tmpregister & (uint8_t)0xFF); + /* Load the selectecd MAC address low register */ + tmpregister = (*(__IO uint32_t*)(ETH_MAC_ADDR_LBASE + MacAddr)); + /* Calculate the selectecd MAC address buffer */ + Addr[3] = ((tmpregister >> 24) & (uint8_t)0xFF); + Addr[2] = ((tmpregister >> 16) & (uint8_t)0xFF); + Addr[1] = ((tmpregister >> 8) & (uint8_t)0xFF); + Addr[0] = (tmpregister & (uint8_t)0xFF); +} + +/** + * @brief Enables or disables the Address filter module uses the specified + * ETHERNET MAC address for perfect filtering + * @param MacAddr specifies the ETHERNET MAC address to be used for prfect filtering. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDR1 MAC Address1 + * @arg ETH_MAC_ADDR2 MAC Address2 + * @arg ETH_MAC_ADDR3 MAC Address3 + * @param Cmd new state of the specified ETHERNET MAC address use. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMacAddrPerfectFilter(uint32_t MacAddr, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_ETH_MAC_ADDR123(MacAddr)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected ETHERNET MAC address for perfect filtering */ + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + MacAddr)) |= ETH_MACADDR1HI_AE; + } + else + { + /* Disable the selected ETHERNET MAC address for perfect filtering */ + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + MacAddr)) &= (~(uint32_t)ETH_MACADDR1HI_AE); + } +} + +/** + * @brief Set the filter type for the specified ETHERNET MAC address + * @param MacAddr specifies the ETHERNET MAC address + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDR1 MAC Address1 + * @arg ETH_MAC_ADDR2 MAC Address2 + * @arg ETH_MAC_ADDR3 MAC Address3 + * @param Filter specifies the used frame received field for comparaison + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDR_FILTER_SA MAC Address is used to compare with the + * SA fields of the received frame. + * @arg ETH_MAC_ADDR_FILTER_DA MAC Address is used to compare with the + * DA fields of the received frame. + */ +void ETH_ConfigMacAddrFilter(uint32_t MacAddr, uint32_t Filter) +{ + /* Check the parameters */ + assert_param(IS_ETH_MAC_ADDR123(MacAddr)); + assert_param(IS_ETH_MAC_ADDR_FILTER(Filter)); + + if (Filter != ETH_MAC_ADDR_FILTER_DA) + { + /* The selected ETHERNET MAC address is used to compare with the SA fields of the + received frame. */ + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + MacAddr)) |= ETH_MACADDR1HI_SA; + } + else + { + /* The selected ETHERNET MAC address is used to compare with the DA fields of the + received frame. */ + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + MacAddr)) &= (~(uint32_t)ETH_MACADDR1HI_SA); + } +} + +/** + * @brief Set the filter type for the specified ETHERNET MAC address + * @param MacAddr specifies the ETHERNET MAC address + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDR1 MAC Address1 + * @arg ETH_MAC_ADDR2 MAC Address2 + * @arg ETH_MAC_ADDR3 MAC Address3 + * @param MaskByte specifies the used address bytes for comparaison + * This parameter can be any combination of the following values: + * @arg ETH_MAC_ADDR_MASK_BYTE6 Mask MAC Address high reg bits [15:8]. + * @arg ETH_MAC_ADDR_MASK_BYTE5 Mask MAC Address high reg bits [7:0]. + * @arg ETH_MAC_ADDR_MASK_BYTE4 Mask MAC Address low reg bits [31:24]. + * @arg ETH_MAC_ADDR_MASK_BYTE3 Mask MAC Address low reg bits [23:16]. + * @arg ETH_MAC_ADDR_MASK_BYTE2 Mask MAC Address low reg bits [15:8]. + * @arg ETH_MAC_ADDR_MASK_BYTE1 Mask MAC Address low reg bits [7:0]. + */ +void ETH_ConfigMacAddrMaskBytesFilter(uint32_t MacAddr, uint32_t MaskByte) +{ + /* Check the parameters */ + assert_param(IS_ETH_MAC_ADDR123(MacAddr)); + assert_param(IS_ETH_MAC_ADDR_MASK(MaskByte)); + + /* Clear MBC bits in the selected MAC address high register */ + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + MacAddr)) &= (~(uint32_t)ETH_MACADDR1HI_MBC); + /* Set the selected Filetr mask bytes */ + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + MacAddr)) |= MaskByte; +} +/*------------------------ DMA Tx/Rx Desciptors -----------------------------*/ + +/** + * @brief Initializes the DMA Tx descriptors in chain mode. + * @param DMATxDescTab Pointer on the first Tx desc list + * @param TxBuff Pointer on the first TxBuffer list + * @param BuffSize Buffer size of each descriptor + * @param TxBuffCount Number of the used Tx desc in the list + */ +void ETH_ConfigDmaTxDescInChainMode(ETH_DMADescType* DMATxDescTab, + uint8_t* TxBuff, + uint32_t BuffSize, + uint32_t TxBuffCount) +{ + uint32_t i = 0; + ETH_DMADescType* DMATxDesc; + + /* Set the DMATxDescToSet pointer with the first one of the DMATxDescTab list */ + DMATxDescToSet = DMATxDescTab; + /* Fill each DMATxDesc descriptor with the right values */ + for (i = 0; i < TxBuffCount; i++) + { + /* Get the pointer on the ith member of the Tx Desc list */ + DMATxDesc = DMATxDescTab + i; + /* Set Second Address Chained bit */ + DMATxDesc->Status = 0; + DMATxDesc->CtrlOrBufSize = ETH_DMA_TX_DESC_TCH; + + /* Set Buffer1 address pointer */ + DMATxDesc->Buf1Addr = (uint32_t)(&TxBuff[i * BuffSize]); + + /* Initialize the next descriptor with the Next Desciptor Polling Enable */ + if (i < (TxBuffCount - 1)) + { + /* Set next descriptor address register with next descriptor base address */ + DMATxDesc->Buf2OrNextDescAddr = (uint32_t)(DMATxDescTab + i + 1); + } + else + { + /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ + DMATxDesc->Buf2OrNextDescAddr = (uint32_t)DMATxDescTab; + } + } + + /* Set Transmit Desciptor List Address Register */ + ETH->DMATXDLADDR = (uint32_t)DMATxDescTab; +} + +/** + * @brief Initializes the DMA Tx descriptors in ring mode. + * @param DMATxDescTab Pointer on the first Tx desc list + * @param TxBuff1 Pointer on the first TxBuffer1 list + * @param TxBuff2 Pointer on the first TxBuffer2 list + * @param BuffSize Buffer size of each descriptor + * @param TxBuffCount Number of the used Tx desc in the list + * Note: see decriptor skip length defined in ETH_DMA_InitStruct + * for the number of Words to skip between two unchained descriptors. + */ +void ETH_ConfigDmaTxDescInRingMode(ETH_DMADescType* DMATxDescTab, + uint8_t* TxBuff1, + uint8_t* TxBuff2, + uint32_t BuffSize, + uint32_t TxBuffCount) +{ + uint32_t i = 0; + ETH_DMADescType* DMATxDesc; + uint32_t dsl = (ETH->DMABUSMOD & ETH_DMABUSMOD_DSL) >> 2; + + /* Set the DMATxDescToSet pointer with the first one of the DMATxDescTab list */ + DMATxDescToSet = DMATxDescTab; + /* Fill each DMATxDesc descriptor with the right values */ + for (i = 0; i < TxBuffCount; i++) + { + /* Get the pointer on the ith member of the Tx Desc list */ + // DMATxDesc = DMATxDescTab + i; + DMATxDesc = (ETH_DMADescType*)((uint32_t)DMATxDescTab + i * (16 + 4 * dsl)); + /* Set Buffer1 address pointer */ + DMATxDesc->Buf1Addr = (uint32_t)(&TxBuff1[i * BuffSize]); + + /* Set Buffer2 address pointer */ + DMATxDesc->Buf2OrNextDescAddr = (uint32_t)(&TxBuff2[i * BuffSize]); + + /* Set Transmit End of Ring bit for last descriptor: The DMA returns to the base + address of the list, creating a Desciptor Ring */ + if (i == (TxBuffCount - 1)) + { + /* Set Transmit End of Ring bit */ + DMATxDesc->CtrlOrBufSize = ETH_DMA_TX_DESC_TER; + } + } + + /* Set Transmit Desciptor List Address Register */ + ETH->DMATXDLADDR = (uint32_t)DMATxDescTab; +} + +/** + * @brief Checks whether the specified ETHERNET DMA Tx Desc flag is set or not. + * @param DMATxDesc pointer on a DMA Tx descriptor + * @param ETH_DMATxDescFlag specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_DMA_TX_DESC_OWN OWN bit: descriptor is owned by DMA engine + * @arg ETH_DMA_TX_DESC_IC Interrupt on completetion + * @arg ETH_DMA_TX_DESC_LS Last Segment + * @arg ETH_DMA_TX_DESC_FS First Segment + * @arg ETH_DMA_TX_DESC_DC Disable CRC + * @arg ETH_DMA_TX_DESC_DP Disable Pad + * @arg ETH_DMA_TX_DESC_TTSE Transmit Time Stamp Enable + * @arg ETH_DMA_TX_DESC_TER Transmit End of Ring + * @arg ETH_DMA_TX_DESC_TCH Second Address Chained + * @arg ETH_DMA_TX_DESC_TTSS Tx Time Stamp Status + * @arg ETH_DMA_TX_DESC_IHE IP Header Error + * @arg ETH_DMA_TX_DESC_ES Error summary + * @arg ETH_DMA_TX_DESC_JT Jabber Timeout + * @arg ETH_DMA_TX_DESC_FF Frame Flushed: DMA/MTL flushed the frame due to SW flush + * @arg ETH_DMA_TX_DESC_PCE Payload Checksum Error + * @arg ETH_DMA_TX_DESC_LOC Loss of Carrier: carrier lost during tramsmission + * @arg ETH_DMA_TX_DESC_NC No Carrier: no carrier signal from the tranceiver + * @arg ETH_DMA_TX_DESC_LC Late Collision: transmission aborted due to collision + * @arg ETH_DMA_TX_DESC_EC Excessive Collision: transmission aborted after 16 collisions + * @arg ETH_DMA_TX_DESC_VF VLAN Frame + * @arg ETH_DMA_TX_DESC_CC Collision Count + * @arg ETH_DMA_TX_DESC_ED Excessive Deferral + * @arg ETH_DMA_TX_DESC_UF Underflow Error: late data arrival from the memory + * @arg ETH_DMA_TX_DESC_DB Deferred Bit + * @return The new state of ETH_DMATxDescFlag (SET or RESET). + */ +FlagStatus ETH_GetDmaTxDescFlagStatus(ETH_DMADescType* DMATxDesc, uint32_t ETH_DMATxDescFlag) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_DMATXDESC_GET_FLAG(ETH_DMATxDescFlag)); + + if ((DMATxDesc->Status & ETH_DMATxDescFlag) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Returns the specified ETHERNET DMA Tx Desc collision count. + * @param DMATxDesc pointer on a DMA Tx descriptor + * @return The Transmit descriptor collision counter value. + */ +uint32_t ETH_GetDmaTxDescCollisionCount(ETH_DMADescType* DMATxDesc) +{ + /* Return the Receive descriptor frame length */ + return ((DMATxDesc->Status & ETH_DMA_TX_DESC_CC) >> ETH_DMA_TX_DESC_COLLISION_COUNTER_SHIFT); +} + +/** + * @brief Set the specified DMA Tx Desc Own bit. + * @param DMATxDesc Pointer on a Tx desc + */ +void ETH_SetDmaTxDescOwn(ETH_DMADescType* DMATxDesc) +{ + /* Set the DMA Tx Desc Own bit */ + DMATxDesc->Status |= ETH_DMA_TX_DESC_OWN; +} + +/** + * @brief Enables or disables the specified DMA Tx Desc Transmit interrupt. + * @param DMATxDesc Pointer on a Tx desc + * @param Cmd new state of the DMA Tx Desc transmit interrupt. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaTxDescTransmitInt(ETH_DMADescType* DMATxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the DMA Tx Desc Transmit interrupt */ + DMATxDesc->CtrlOrBufSize |= ETH_DMA_TX_DESC_IC; + } + else + { + /* Disable the DMA Tx Desc Transmit interrupt */ + DMATxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_TX_DESC_IC); + } +} + +/** + * @brief Set the specified DMA Tx Desc frame segment. + * @param DMATxDesc Pointer on a Tx desc + * @param DMATxDesc_FrameSegment specifies is the actual Tx desc contain last or first segment. + * This parameter can be one of the following values: + * @arg ETH_DMA_TX_DESC_LAST_SEGMENT actual Tx desc contain last segment + * @arg ETH_DMA_TX_DESC_FIRST_SEGMENT actual Tx desc contain first segment + */ +void ETH_ConfigDmaTxDescFrameSegment(ETH_DMADescType* DMATxDesc, uint32_t DMATxDesc_FrameSegment) +{ + /* Check the parameters */ + assert_param(IS_ETH_DMA_TX_DESC_SEGMENT(DMATxDesc_FrameSegment)); + + /* Selects the DMA Tx Desc Frame segment */ + DMATxDesc->CtrlOrBufSize |= DMATxDesc_FrameSegment; +} + +/** + * @brief Selects the specified ETHERNET DMA Tx Desc Checksum Insertion. + * @param DMATxDesc pointer on a DMA Tx descriptor + * @param DMATxDesc_Checksum specifies is the DMA Tx desc checksum insertion. + * This parameter can be one of the following values: + * @arg ETH_DMA_TX_DESC_CHECKSUM_BYPASS Checksum bypass + * @arg ETH_DMA_TX_DESC_CHECKSUM_IPV4_HEADER IPv4 header checksum + * @arg ETH_DMA_TX_DESC_CHECKSUM_TCPUDPICMP_SEGMENT TCP/UDP/ICMP checksum. Pseudo header checksum is assumed to be + * present + * @arg ETH_DMA_TX_DESC_CHECKSUM_TCPUDPICMP_FULL TCP/UDP/ICMP checksum fully in hardware including pseudo header + */ +void ETH_ConfigDmaTxDescChecksumInsertion(ETH_DMADescType* DMATxDesc, uint32_t DMATxDesc_Checksum) +{ + /* Check the parameters */ + assert_param(IS_ETH_DMA_TX_DESC_CHECKSUM(DMATxDesc_Checksum)); + + /* Set the selected DMA Tx desc checksum insertion control */ + DMATxDesc->CtrlOrBufSize |= DMATxDesc_Checksum; +} + +/** + * @brief Enables or disables the DMA Tx Desc CRC. + * @param DMATxDesc pointer on a DMA Tx descriptor + * @param Cmd new state of the specified DMA Tx Desc CRC. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaTxDescCrc(ETH_DMADescType* DMATxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected DMA Tx Desc CRC */ + DMATxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_TX_DESC_DC); + } + else + { + /* Disable the selected DMA Tx Desc CRC */ + DMATxDesc->CtrlOrBufSize |= ETH_DMA_TX_DESC_DC; + } +} + +/** + * @brief Enables or disables the DMA Tx Desc end of ring. + * @param DMATxDesc pointer on a DMA Tx descriptor + * @param Cmd new state of the specified DMA Tx Desc end of ring. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaTxDescEndOfRing(ETH_DMADescType* DMATxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected DMA Tx Desc end of ring */ + DMATxDesc->CtrlOrBufSize |= ETH_DMA_TX_DESC_TER; + } + else + { + /* Disable the selected DMA Tx Desc end of ring */ + DMATxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_TX_DESC_TER); + } +} + +/** + * @brief Enables or disables the DMA Tx Desc second address chained. + * @param DMATxDesc pointer on a DMA Tx descriptor + * @param Cmd new state of the specified DMA Tx Desc second address chained. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaTxDescSecondAddrChained(ETH_DMADescType* DMATxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected DMA Tx Desc second address chained */ + DMATxDesc->CtrlOrBufSize |= ETH_DMA_TX_DESC_TCH; + } + else + { + /* Disable the selected DMA Tx Desc second address chained */ + DMATxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_TX_DESC_TCH); + } +} + +/** + * @brief Enables or disables the DMA Tx Desc padding for frame shorter than 64 bytes. + * @param DMATxDesc pointer on a DMA Tx descriptor + * @param Cmd new state of the specified DMA Tx Desc padding for frame shorter than 64 bytes. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaTxDescShortFramePadding(ETH_DMADescType* DMATxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected DMA Tx Desc padding for frame shorter than 64 bytes */ + DMATxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_TX_DESC_DP); + } + else + { + /* Disable the selected DMA Tx Desc padding for frame shorter than 64 bytes*/ + DMATxDesc->CtrlOrBufSize |= ETH_DMA_TX_DESC_DP; + } +} + +/** + * @brief Enables or disables the DMA Tx Desc time stamp. + * @param DMATxDesc pointer on a DMA Tx descriptor + * @param Cmd new state of the specified DMA Tx Desc time stamp. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaTxDescTimeStamp(ETH_DMADescType* DMATxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected DMA Tx Desc time stamp */ + DMATxDesc->CtrlOrBufSize |= ETH_DMA_TX_DESC_TTSE; + } + else + { + /* Disable the selected DMA Tx Desc time stamp */ + DMATxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_TX_DESC_TTSE); + } +} + +/** + * @brief Configures the specified DMA Tx Desc buffer1 and buffer2 sizes. + * @param DMATxDesc Pointer on a Tx desc + * @param BufferSize1 specifies the Tx desc buffer1 size. + * @param BufferSize2 specifies the Tx desc buffer2 size (put "0" if not used). + */ +void ETH_ConfigDmaTxDescBufSize(ETH_DMADescType* DMATxDesc, uint32_t BufferSize1, uint32_t BufferSize2) +{ + /* Check the parameters */ + assert_param(IS_ETH_DMA_TX_DESC_BUFFER_SIZE(BufferSize1)); + assert_param(IS_ETH_DMA_TX_DESC_BUFFER_SIZE(BufferSize2)); + + /* Set the DMA Tx Desc buffer1 and buffer2 sizes values */ + DMATxDesc->CtrlOrBufSize |= (BufferSize1 | (BufferSize2 << ETH_DMA_TX_DESC_BUF2_SIZE_SHIFT)); +} + +/** + * @brief Initializes the DMA Rx descriptors in chain mode. + * @param DMARxDescTab Pointer on the first Rx desc list + * @param RxBuff Pointer on the first RxBuffer list + * @param BuffSize the buffer size of each RxBuffer + * @param RxBuffCount Number of the used Rx desc in the list + */ +void ETH_ConfigDmaRxDescInChainMode(ETH_DMADescType* DMARxDescTab, + uint8_t* RxBuff, + uint32_t BuffSize, + uint32_t RxBuffCount) +{ + uint32_t i = 0; + ETH_DMADescType* DMARxDesc; + + /* Set the DMARxDescToGet pointer with the first one of the DMARxDescTab list */ + DMARxDescToGet = DMARxDescTab; + /* Fill each DMARxDesc descriptor with the right values */ + for (i = 0; i < RxBuffCount; i++) + { + /* Get the pointer on the ith member of the Rx Desc list */ + DMARxDesc = DMARxDescTab + i; + /* Set Own bit of the Rx descriptor Status */ + DMARxDesc->Status = ETH_DMA_RX_DESC_OWN; + + /* Set Buffer1 size and Second Address Chained bit */ + DMARxDesc->CtrlOrBufSize = ETH_DMA_RX_DESC_RCH | (uint32_t)(BuffSize & 0x1FFFUL); + /* Set Buffer1 address pointer */ + DMARxDesc->Buf1Addr = (uint32_t)(&RxBuff[i * BuffSize]); + + /* Initialize the next descriptor with the Next Desciptor Polling Enable */ + if (i < (RxBuffCount - 1)) + { + /* Set next descriptor address register with next descriptor base address */ + DMARxDesc->Buf2OrNextDescAddr = (uint32_t)(DMARxDescTab + i + 1); + } + else + { + /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ + DMARxDesc->Buf2OrNextDescAddr = (uint32_t)(DMARxDescTab); + } + } + + /* Set Receive Desciptor List Address Register */ + ETH->DMARXDLADDR = (uint32_t)DMARxDescTab; +} + +/** + * @brief Initializes the DMA Rx descriptors in ring mode. + * @param DMARxDescTab Pointer on the first Rx desc list + * @param RxBuff1 Pointer on the first RxBuffer1 list + * @param RxBuff2 Pointer on the first RxBuffer2 list + * @param BuffSize the buffer size of each RxBuffer + * @param RxBuffCount Number of the used Rx desc in the list + * Note: see decriptor skip length defined in ETH_DMA_InitStruct + * for the number of Words to skip between two unchained descriptors. + */ +void ETH_ConfigDmaRxDescInRingMode(ETH_DMADescType* DMARxDescTab, + uint8_t* RxBuff1, + uint8_t* RxBuff2, + uint32_t BuffSize, + uint32_t RxBuffCount) +{ + uint32_t i = 0; + ETH_DMADescType* DMARxDesc; + uint32_t dsl = (ETH->DMABUSMOD & ETH_DMABUSMOD_DSL) >> 2; + /* Set the DMARxDescToGet pointer with the first one of the DMARxDescTab list */ + DMARxDescToGet = DMARxDescTab; + /* Fill each DMARxDesc descriptor with the right values */ + for (i = 0; i < RxBuffCount; i++) + { + /* Get the pointer on the ith member of the Rx Desc list */ + // DMARxDesc = DMARxDescTab + i; + DMARxDesc = (ETH_DMADescType*)((uint32_t)DMARxDescTab + i * (16 + 4 * dsl)); + /* Set Own bit of the Rx descriptor Status */ + DMARxDesc->Status = ETH_DMA_RX_DESC_OWN; + /* Set Buffer1 size */ + DMARxDesc->CtrlOrBufSize = BuffSize; + /* Set Buffer1 address pointer */ + DMARxDesc->Buf1Addr = (uint32_t)(&RxBuff1[i * BuffSize]); + + /* Set Buffer2 address pointer */ + DMARxDesc->Buf2OrNextDescAddr = (uint32_t)(&RxBuff2[i * BuffSize]); + + /* Set Receive End of Ring bit for last descriptor: The DMA returns to the base + address of the list, creating a Desciptor Ring */ + if (i == (RxBuffCount - 1)) + { + /* Set Receive End of Ring bit */ + DMARxDesc->CtrlOrBufSize |= ETH_DMA_RX_DESC_RER; + } + } + + /* Set Receive Desciptor List Address Register */ + ETH->DMARXDLADDR = (uint32_t)DMARxDescTab; +} + +/** + * @brief Checks whether the specified ETHERNET Rx Desc flag is set or not. + * @param DMARxDesc pointer on a DMA Rx descriptor + * @param ETH_DMARxDescFlag specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_DMA_RX_DESC_OWN OWN bit: descriptor is owned by DMA engine + * @arg ETH_DMA_RX_DESC_AFM DA Filter Fail for the rx frame + * @arg ETH_DMA_RX_DESC_ES Error summary + * @arg ETH_DMA_RX_DESC_DE Desciptor error: no more descriptors for receive frame + * @arg ETH_DMA_RX_DESC_SAF SA Filter Fail for the received frame + * @arg ETH_DMA_RX_DESC_LE Frame size not matching with length field + * @arg ETH_DMA_RX_DESC_OE Overflow Error: Frame was damaged due to buffer overflow + * @arg ETH_DMA_RX_DESC_VLAN VLAN Tag: received frame is a VLAN frame + * @arg ETH_DMA_RX_DESC_FS First descriptor of the frame + * @arg ETH_DMA_RX_DESC_LS Last descriptor of the frame + * @arg ETH_DMA_RX_DESC_IPV4HCE IPC Checksum Error/Giant Frame: Rx Ipv4 header checksum error + * @arg ETH_DMA_RX_DESC_LC Late collision occurred during reception + * @arg ETH_DMA_RX_DESC_FT Frame type - Ethernet, otherwise 802.3 + * @arg ETH_DMA_RX_DESC_RWT Receive Watchdog Timeout: watchdog timer expired during reception + * @arg ETH_DMA_RX_DESC_RE Receive error: error reported by MII interface + * @arg ETH_DMA_RX_DESC_DE Dribble bit error: frame contains non int multiple of 8 bits + * @arg ETH_DMA_RX_DESC_CE CRC error + * @arg ETH_DMA_RX_DESC_RMAPCE Rx MAC Address/Payload Checksum Error: Rx MAC address matched/ Rx Payload Checksum + * Error + * @return The new state of ETH_DMARxDescFlag (SET or RESET). + */ +FlagStatus ETH_GetDmaRxDescFlagStatus(ETH_DMADescType* DMARxDesc, uint32_t ETH_DMARxDescFlag) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_DMA_RX_DESC_GET_FLAG(ETH_DMARxDescFlag)); + if ((DMARxDesc->Status & ETH_DMARxDescFlag) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Set the specified DMA Rx Desc Own bit. + * @param DMARxDesc Pointer on a Rx desc + */ +void ETH_SetDmaRxDescOwn(ETH_DMADescType* DMARxDesc) +{ + /* Set the DMA Rx Desc Own bit */ + DMARxDesc->Status |= ETH_DMA_RX_DESC_OWN; +} + +/** + * @brief Returns the specified DMA Rx Desc frame length. + * @param DMARxDesc pointer on a DMA Rx descriptor + * @return The Rx descriptor received frame length. + */ +uint32_t ETH_GetDmaRxDescFrameLen(__IO ETH_DMADescType* DMARxDesc) +{ + /* Return the Receive descriptor frame length */ + return ((DMARxDesc->Status & ETH_DMA_RX_DESC_FL) >> ETH_DMA_RX_DESC_FRAME_LEN_SHIFT); +} + +/** + * @brief Enables or disables the specified DMA Rx Desc receive interrupt. + * @param DMARxDesc Pointer on a Rx desc + * @param Cmd new state of the specified DMA Rx Desc interrupt. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaRxDescReceiveInt(ETH_DMADescType* DMARxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the DMA Rx Desc receive interrupt */ + DMARxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_RX_DESC_DIC); + } + else + { + /* Disable the DMA Rx Desc receive interrupt */ + DMARxDesc->CtrlOrBufSize |= ETH_DMA_RX_DESC_DIC; + } +} + +/** + * @brief Enables or disables the DMA Rx Desc end of ring. + * @param DMARxDesc pointer on a DMA Rx descriptor + * @param Cmd new state of the specified DMA Rx Desc end of ring. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaRxDescEndOfRing(ETH_DMADescType* DMARxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected DMA Rx Desc end of ring */ + DMARxDesc->CtrlOrBufSize |= ETH_DMA_RX_DESC_RER; + } + else + { + /* Disable the selected DMA Rx Desc end of ring */ + DMARxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_RX_DESC_RER); + } +} + +/** + * @brief Enables or disables the DMA Rx Desc second address chained. + * @param DMARxDesc pointer on a DMA Rx descriptor + * @param Cmd new state of the specified DMA Rx Desc second address chained. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaRxDescSecondAddrChained(ETH_DMADescType* DMARxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected DMA Rx Desc second address chained */ + DMARxDesc->CtrlOrBufSize |= ETH_DMA_RX_DESC_RCH; + } + else + { + /* Disable the selected DMA Rx Desc second address chained */ + DMARxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_RX_DESC_RCH); + } +} + +/** + * @brief Returns the specified ETHERNET DMA Rx Desc buffer size. + * @param DMARxDesc pointer on a DMA Rx descriptor + * @param DMARxDesc_Buffer specifies the DMA Rx Desc buffer. + * This parameter can be any one of the following values: + * @arg ETH_DMA_RX_DESC_BUFFER1 DMA Rx Desc Buffer1 + * @arg ETH_DMA_RX_DESC_BUFFER2 DMA Rx Desc Buffer2 + * @return The Receive descriptor frame length. + */ +uint32_t ETH_GetDmaRxDescBufSize(ETH_DMADescType* DMARxDesc, uint32_t DMARxDesc_Buffer) +{ + /* Check the parameters */ + assert_param(IS_ETH_DMA_RXDESC_BUFFER(DMARxDesc_Buffer)); + + if (DMARxDesc_Buffer != ETH_DMA_RX_DESC_BUFFER1) + { + /* Return the DMA Rx Desc buffer2 size */ + return ((DMARxDesc->CtrlOrBufSize & ETH_DMA_RX_DESC_RBS2) >> ETH_DMA_RX_DESC_BUF2_SIZE_SHIFT); + } + else + { + /* Return the DMA Rx Desc buffer1 size */ + return (DMARxDesc->CtrlOrBufSize & ETH_DMA_RX_DESC_RBS1); + } +} + +/*--------------------------------- DMA ------------------------------------*/ +/** + * @brief Resets all MAC subsystem internal registers and logic. + */ +void ETH_SoftwareReset(void) +{ + /* Set the SWR bit: resets all MAC subsystem internal registers and logic */ + /* After reset all the registers holds their respective reset values */ + ETH->DMABUSMOD |= ETH_DMABUSMOD_SWR; +} + +/** + * @brief Checks whether the ETHERNET software reset bit is set or not. + * @return The new state of DMA Bus Mode register STS bit (SET or RESET). + */ +FlagStatus ETH_GetSoftwareResetStatus(void) +{ + FlagStatus bitstatus = RESET; + if ((ETH->DMABUSMOD & ETH_DMABUSMOD_SWR) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Checks whether the specified ETHERNET DMA flag is set or not. + * @param ETH_DMA_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_DMA_FLAG_TST Time-stamp trigger flag + * @arg ETH_DMA_FLAG_PMT PMT flag + * @arg ETH_DMA_FLAG_MMC MMC flag + * @arg ETH_DMA_FLAG_DATA_TRANSFER_ERROR Error bits 0-data buffer, 1-desc. access + * @arg ETH_DMA_FLAG_READ_WRITE_ERROR Error bits 0-write trnsf, 1-read transfr + * @arg ETH_DMA_FLAG_ACCESS_ERROR Error bits 0-Rx DMA, 1-Tx DMA + * @arg ETH_DMA_FLAG_NIS Normal interrupt summary flag + * @arg ETH_DMA_FLAG_AIS Abnormal interrupt summary flag + * @arg ETH_DMA_FLAG_EARLY_RX Early receive flag + * @arg ETH_DMA_FLAG_FATAL_BUS_ERROR Fatal bus error flag + * @arg ETH_DMA_FLAG_EARLY_TX Early transmit flag + * @arg ETH_DMA_FLAG_RX_WDG_TIMEOUT Receive watchdog timeout flag + * @arg ETH_DMA_FLAG_RX_PROC_STOP Receive process stopped flag + * @arg ETH_DMA_FLAG_RX_BUF_UA Receive buffer unavailable flag + * @arg ETH_DMA_FLAG_RX Receive flag + * @arg ETH_DMA_FLAG_TX_UNDERFLOW Underflow flag + * @arg ETH_DMA_FLAG_RX_OVERFLOW Overflow flag + * @arg ETH_DMA_FLAG_TX_JABBER_TIMEOUT Transmit jabber timeout flag + * @arg ETH_DMA_FLAG_TX_BUF_UA Transmit buffer unavailable flag + * @arg ETH_DMA_FLAG_TX_PROC_STOP Transmit process stopped flag + * @arg ETH_DMA_FLAG_TX Transmit flag + * @return The new state of ETH_DMA_FLAG (SET or RESET). + */ +FlagStatus ETH_GetDmaFlagStatus(uint32_t ETH_DMA_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_DMA_GET_INT(ETH_DMA_FLAG)); + if ((ETH->DMASTS & ETH_DMA_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the ETHERNET's DMA pending flag. + * @param ETH_DMA_FLAG specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg ETH_DMA_FLAG_NIS Normal interrupt summary flag + * @arg ETH_DMA_FLAG_AIS Abnormal interrupt summary flag + * @arg ETH_DMA_FLAG_EARLY_RX Early receive flag + * @arg ETH_DMA_FLAG_FATAL_BUS_ERROR Fatal bus error flag + * @arg ETH_DMA_FLAG_ETI Early transmit flag + * @arg ETH_DMA_FLAG_RX_WDG_TIMEOUT Receive watchdog timeout flag + * @arg ETH_DMA_FLAG_RX_PROC_STOP Receive process stopped flag + * @arg ETH_DMA_FLAG_RX_BUF_UA Receive buffer unavailable flag + * @arg ETH_DMA_FLAG_RX Receive flag + * @arg ETH_DMA_FLAG_TX_UNDERFLOW Transmit Underflow flag + * @arg ETH_DMA_FLAG_RX_OVERFLOW Receive Overflow flag + * @arg ETH_DMA_FLAG_TX_JABBER_TIMEOUT Transmit jabber timeout flag + * @arg ETH_DMA_FLAG_TX_BUF_UA Transmit buffer unavailable flag + * @arg ETH_DMA_FLAG_TX_PROC_STOP Transmit process stopped flag + * @arg ETH_DMA_FLAG_TX Transmit flag + */ +void ETH_ClrDmaFlag(uint32_t ETH_DMA_FLAG) +{ + /* Check the parameters */ + assert_param(IS_ETH_DMA_FLAG(ETH_DMA_FLAG)); + + /* Clear the selected ETHERNET DMA FLAG */ + ETH->DMASTS = (uint32_t)ETH_DMA_FLAG; +} + +/** + * @brief Checks whether the specified ETHERNET DMA interrupt has occured or not. + * @param ETH_DMA_IT specifies the interrupt source to check. + * This parameter can be one of the following values: + * @arg ETH_DMA_INT_TST Time-stamp trigger interrupt + * @arg ETH_DMA_INT_PMT PMT interrupt + * @arg ETH_DMA_INT_MMC MMC interrupt + * @arg ETH_DMA_INT_NIS Normal interrupt summary + * @arg ETH_DMA_INT_AIS Abnormal interrupt summary + * @arg ETH_DMA_INT_EARLY_RX Early receive interrupt + * @arg ETH_DMA_INT_FATAL_BUS_ERROR Fatal bus error interrupt + * @arg ETH_DMA_INT_EARLY_TX Early transmit interrupt + * @arg ETH_DMA_INT_RX_WDG_TIMEOUT Receive watchdog timeout interrupt + * @arg ETH_DMA_INT_RX_PROC_STOP Receive process stopped interrupt + * @arg ETH_DMA_INT_RX_BUF_UA Receive buffer unavailable interrupt + * @arg ETH_DMA_INT_RX Receive interrupt + * @arg ETH_DMA_INT_TX_UNDERFLOW Underflow interrupt + * @arg ETH_DMA_INT_RX_OVERFLOW Overflow interrupt + * @arg ETH_DMA_INT_TX_JABBER_TIMEOUT Transmit jabber timeout interrupt + * @arg ETH_DMA_INT_TX_BUF_UA Transmit buffer unavailable interrupt + * @arg ETH_DMA_INT_TX_PROC_STOP Transmit process stopped interrupt + * @arg ETH_DMA_INT_TX Transmit interrupt + * @return The new state of ETH_DMA_IT (SET or RESET). + */ +INTStatus ETH_GetDmaIntStatus(uint32_t ETH_DMA_IT) +{ + INTStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_DMA_GET_INT(ETH_DMA_IT)); + if ((ETH->DMASTS & ETH_DMA_IT) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the ETHERNET's DMA IT pending bit. + * @param ETH_DMA_IT specifies the interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg ETH_DMA_INT_NIS Normal interrupt summary + * @arg ETH_DMA_INT_AIS Abnormal interrupt summary + * @arg ETH_DMA_INT_EARLY_RX Early receive interrupt + * @arg ETH_DMA_INT_FATAL_BUS_ERROR Fatal bus error interrupt + * @arg ETH_DMA_IT_ETI Early transmit interrupt + * @arg ETH_DMA_INT_RX_WDG_TIMEOUT Receive watchdog timeout interrupt + * @arg ETH_DMA_INT_RX_PROC_STOP Receive process stopped interrupt + * @arg ETH_DMA_INT_RX_BUF_UA Receive buffer unavailable interrupt + * @arg ETH_DMA_INT_RX Receive interrupt + * @arg ETH_DMA_INT_TX_UNDERFLOW Transmit Underflow interrupt + * @arg ETH_DMA_INT_RX_OVERFLOW Receive Overflow interrupt + * @arg ETH_DMA_INT_TX_JABBER_TIMEOUT Transmit jabber timeout interrupt + * @arg ETH_DMA_INT_TX_BUF_UA Transmit buffer unavailable interrupt + * @arg ETH_DMA_INT_TX_PROC_STOP Transmit process stopped interrupt + * @arg ETH_DMA_INT_TX Transmit interrupt + */ +void ETH_ClrDmaIntPendingBit(uint32_t ETH_DMA_IT) +{ + /* Check the parameters */ + assert_param(IS_ETH_DMA_INT(ETH_DMA_IT)); + + /* Clear the selected ETHERNET DMA IT */ + ETH->DMASTS = (uint32_t)ETH_DMA_IT; +} + +/** + * @brief Returns the ETHERNET DMA Transmit Process State. + * @return The new ETHERNET DMA Transmit Process State: + * This can be one of the following values: + * - ETH_DMA_TX_PROC_STOPPED : Stopped - Reset or Stop Tx Command issued + * - ETH_DMA_TX_PROC_FETCHING : Running - fetching the Tx descriptor + * - ETH_DMA_TX_PROC_WAITING : Running - waiting for status + * - ETH_DMA_TX_PROC_READING : unning - reading the data from host memory + * - ETH_DMA_TX_PROC_SUSPENDED : Suspended - Tx Desciptor unavailabe + * - ETH_DMA_TX_PROC_CLOSING : Running - closing Rx descriptor + */ +uint32_t ETH_GetTxProcState(void) +{ + return ((uint32_t)(ETH->DMASTS & ETH_DMASTS_TI)); +} + +/** + * @brief Returns the ETHERNET DMA Receive Process State. + * @return The new ETHERNET DMA Receive Process State: + * This can be one of the following values: + * - ETH_DMA_RX_PROC_STOPPED : Stopped - Reset or Stop Rx Command issued + * - ETH_DMA_RX_PROC_FETCHING : Running - fetching the Rx descriptor + * - ETH_DMA_RX_PROC_WAITING : Running - waiting for packet + * - ETH_DMA_RX_PROC_SUSPENDED : Suspended - Rx Desciptor unavailable + * - ETH_DMA_RX_PROC_CLOSING : Running - closing descriptor + * - ETH_DMA_RX_PROC_QUEUING : Running - queuing the recieve frame into host memory + */ +uint32_t ETH_GetRxProcState(void) +{ + return ((uint32_t)(ETH->DMASTS & ETH_DMASTS_RI)); +} + +/** + * @brief Clears the ETHERNET transmit DATFIFO. + */ +void ETH_FlushTxFifo(void) +{ + /* Set the Flush Transmit DATFIFO bit */ + ETH->DMAOPMOD |= ETH_DMAOPMOD_FTF; +} + +/** + * @brief Checks whether the ETHERNET transmit DATFIFO bit is cleared or not. + * @return The new state of ETHERNET flush transmit DATFIFO bit (SET or RESET). + */ +FlagStatus ETH_GetFlushTxFifoStatus(void) +{ + FlagStatus bitstatus = RESET; + if ((ETH->DMAOPMOD & ETH_DMAOPMOD_FTF) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Enables or disables the DMA transmission. + * @param Cmd new state of the DMA transmission. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaTx(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the DMA transmission */ + ETH->DMAOPMOD |= ETH_DMAOPMOD_ST; + } + else + { + /* Disable the DMA transmission */ + ETH->DMAOPMOD &= ~ETH_DMAOPMOD_ST; + } +} + +/** + * @brief Enables or disables the DMA reception. + * @param Cmd new state of the DMA reception. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaRx(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the DMA reception */ + ETH->DMAOPMOD |= ETH_DMAOPMOD_SR; + } + else + { + /* Disable the DMA reception */ + ETH->DMAOPMOD &= ~ETH_DMAOPMOD_SR; + } +} + +/** + * @brief Enables or disables the specified ETHERNET DMA interrupts. + * @param ETH_DMA_IT specifies the ETHERNET DMA interrupt sources to be + * enabled or disabled. + * This parameter can be any combination of the following values: + * @arg ETH_DMA_INT_NIS Normal interrupt summary + * @arg ETH_DMA_INT_AIS Abnormal interrupt summary + * @arg ETH_DMA_INT_EARLY_RX Early receive interrupt + * @arg ETH_DMA_INT_FATAL_BUS_ERROR Fatal bus error interrupt + * @arg ETH_DMA_INT_EARLY_TX Early transmit interrupt + * @arg ETH_DMA_INT_RX_WDG_TIMEOUT Receive watchdog timeout interrupt + * @arg ETH_DMA_INT_RX_PROC_STOP Receive process stopped interrupt + * @arg ETH_DMA_INT_RX_BUF_UA Receive buffer unavailable interrupt + * @arg ETH_DMA_INT_RX Receive interrupt + * @arg ETH_DMA_INT_TX_UNDERFLOW Underflow interrupt + * @arg ETH_DMA_INT_RX_OVERFLOW Overflow interrupt + * @arg ETH_DMA_INT_TX_JABBER_TIMEOUT Transmit jabber timeout interrupt + * @arg ETH_DMA_INT_TX_BUF_UA Transmit buffer unavailable interrupt + * @arg ETH_DMA_INT_TX_PROC_STOP Transmit process stopped interrupt + * @arg ETH_DMA_INT_TX Transmit interrupt + * @param Cmd new state of the specified ETHERNET DMA interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaInt(uint32_t ETH_DMA_IT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_ETH_DMA_INT(ETH_DMA_IT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected ETHERNET DMA interrupts */ + ETH->DMAINTEN |= ETH_DMA_IT; + } + else + { + /* Disable the selected ETHERNET DMA interrupts */ + ETH->DMAINTEN &= (~(uint32_t)ETH_DMA_IT); + } +} + +/** + * @brief Checks whether the specified ETHERNET DMA overflow flag is set or not. + * @param ETH_DMA_Overflow specifies the DMA overflow flag to check. + * This parameter can be one of the following values: + * @arg ETH_DMA_OVERFLOW_RX_FIFO_COUNTER Overflow for DATFIFO Overflow Counter + * @arg ETH_DMA_OVERFLOW_MISSED_FRAME_COUNTER Overflow for Missed Frame Counter + * @return The new state of ETHERNET DMA overflow Flag (SET or RESET). + */ +FlagStatus ETH_GetDmaOverflowStatus(uint32_t ETH_DMA_Overflow) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_DMA_GET_OVERFLOW(ETH_DMA_Overflow)); + + if ((ETH->DMAMFBOCNT & ETH_DMA_Overflow) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Get the ETHERNET DMA Rx Overflow Missed Frame Counter value. + * @return The value of Rx overflow Missed Frame Counter. + */ +uint32_t ETH_GetRxOverflowMissedFrameCounter(void) +{ + return ((uint32_t)((ETH->DMAMFBOCNT & ETH_DMAMFBOCNT_OVFFRMCNT) >> ETH_DMA_RX_OVERFLOW_MISSEDFRAMES_COUNTER_SHIFT)); +} + +/** + * @brief Get the ETHERNET DMA Buffer Unavailable Missed Frame Counter value. + * @return The value of Buffer unavailable Missed Frame Counter. + */ +uint32_t ETH_GetBufUnavailableMissedFrameCounter(void) +{ + return ((uint32_t)(ETH->DMAMFBOCNT) & ETH_DMAMFBOCNT_MISFRMCNT); +} + +/** + * @brief Get the ETHERNET DMA DMACHTXDESC register value. + * @return The value of the current Tx desc start address. + */ +uint32_t ETH_GetCurrentTxDescAddr(void) +{ + return ((uint32_t)(ETH->DMACHTXDESC)); +} + +/** + * @brief Get the ETHERNET DMA DMACHRXDESC register value. + * @return The value of the current Rx desc start address. + */ +uint32_t ETH_GetCurrentRxDescAddr(void) +{ + return ((uint32_t)(ETH->DMACHRXDESC)); +} + +/** + * @brief Get the ETHERNET DMA DMACHTXBADDR register value. + * @return The value of the current Tx buffer address. + */ +uint32_t ETH_GetCurrentTxBufAddr(void) +{ + return ((uint32_t)(ETH->DMACHTXBADDR)); +} + +/** + * @brief Get the ETHERNET DMA DMACHRXBADDR register value. + * @return The value of the current Rx buffer address. + */ +uint32_t ETH_GetCurrentRxBufAddr(void) +{ + return ((uint32_t)(ETH->DMACHRXBADDR)); +} + +/** + * @brief Resumes the DMA Transmission by writing to the DmaTxPollDemand register + * (the data written could be anything). This forces the DMA to resume transmission. + */ +void ETH_ResumeDmaTx(void) +{ + ETH->DMATXPD = 0; +} + +/** + * @brief Resumes the DMA Transmission by writing to the DmaRxPollDemand register + * (the data written could be anything). This forces the DMA to resume reception. + */ +void ETH_ResumeDmaRx(void) +{ + ETH->DMARXPD = 0; +} + +/*--------------------------------- PMT ------------------------------------*/ +/** + * @brief Reset Wakeup frame filter register pointer. + */ +void ETH_ResetWakeUpFrameFilter(void) +{ + /* Resets the Remote Wake-up Frame Filter register pointer to 0x0000 */ + ETH->MACPMTCTRLSTS |= ETH_MACPMTCTRLSTS_RWKUPFLTRST; +} + +/** + * @brief Populates the remote wakeup frame registers. + * @param Buffer Pointer on remote WakeUp Frame Filter Register buffer data (8 words). + */ +void ETH_SetWakeUpFrameFilter(uint32_t* Buffer) +{ + uint32_t i = 0; + + /* Fill Remote Wake-up Frame Filter register with Buffer data */ + for (i = 0; i < ETH_WAKEUP_REG_LEN; i++) + { + /* Write each time to the same register */ + ETH->MACRMTWUFRMFLT = Buffer[i]; + } +} + +/** + * @brief Enables or disables any unicast packet filtered by the MAC address + * recognition to be a wake-up frame. + * @param Cmd new state of the MAC Global Unicast Wake-Up. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableGlobalUnicastWakeUp(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the MAC Global Unicast Wake-Up */ + ETH->MACPMTCTRLSTS |= ETH_MACPMTCTRLSTS_GLBLUCAST; + } + else + { + /* Disable the MAC Global Unicast Wake-Up */ + ETH->MACPMTCTRLSTS &= ~ETH_MACPMTCTRLSTS_GLBLUCAST; + } +} + +/** + * @brief Checks whether the specified ETHERNET PMT flag is set or not. + * @param ETH_PMT_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_PMT_FLAG_RWKUPFILTRST Wake-Up Frame Filter Register Poniter Reset + * @arg ETH_PMT_FLAG_RWKPRCVD Wake-Up Frame Received + * @arg ETH_PMT_FLAG_MGKPRCVD Magic Packet Received + * @return The new state of ETHERNET PMT Flag (SET or RESET). + */ +FlagStatus ETH_GetPmtFlagStatus(uint32_t ETH_PMT_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_PMT_GET_FLAG(ETH_PMT_FLAG)); + + if ((ETH->MACPMTCTRLSTS & ETH_PMT_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Enables or disables the MAC Wake-Up Frame Detection. + * @param Cmd new state of the MAC Wake-Up Frame Detection. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableWakeUpFrameDetection(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the MAC Wake-Up Frame Detection */ + ETH->MACPMTCTRLSTS |= ETH_MACPMTCTRLSTS_RWKPKTEN; + } + else + { + /* Disable the MAC Wake-Up Frame Detection */ + ETH->MACPMTCTRLSTS &= ~ETH_MACPMTCTRLSTS_RWKPKTEN; + } +} + +/** + * @brief Enables or disables the MAC Magic Packet Detection. + * @param Cmd new state of the MAC Magic Packet Detection. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMagicPacketDetection(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the MAC Magic Packet Detection */ + ETH->MACPMTCTRLSTS |= ETH_MACPMTCTRLSTS_MGKPKTEN; + } + else + { + /* Disable the MAC Magic Packet Detection */ + ETH->MACPMTCTRLSTS &= ~ETH_MACPMTCTRLSTS_MGKPKTEN; + } +} + +/** + * @brief Enables or disables the MAC Power Down. + * @param Cmd new state of the MAC Power Down. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnablePowerDown(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the MAC Power Down */ + /* This puts the MAC in power down mode */ + ETH->MACPMTCTRLSTS |= ETH_MACPMTCTRLSTS_PWRDWN; + } + else + { + /* Disable the MAC Power Down */ + ETH->MACPMTCTRLSTS &= ~ETH_MACPMTCTRLSTS_PWRDWN; + } +} + +/*--------------------------------- MMC ------------------------------------*/ +/** + * @brief Enables or disables the MMC Counter Freeze. + * @param Cmd new state of the MMC Counter Freeze. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMmcCounterFreeze(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the MMC Counter Freeze */ + ETH->MMCCTRL |= ETH_MMCCTRL_CNTFREEZ; + } + else + { + /* Disable the MMC Counter Freeze */ + ETH->MMCCTRL &= ~ETH_MMCCTRL_CNTFREEZ; + } +} + +/** + * @brief Enables or disables the MMC Reset On Read. + * @param Cmd new state of the MMC Reset On Read. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMmcResetOnRead(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the MMC Counter reset on read */ + ETH->MMCCTRL |= ETH_MMCCTRL_RSTONRD; + } + else + { + /* Disable the MMC Counter reset on read */ + ETH->MMCCTRL &= ~ETH_MMCCTRL_RSTONRD; + } +} + +/** + * @brief Enables or disables the MMC Counter Stop Rollover. + * @param Cmd new state of the MMC Counter Stop Rollover. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMmcCounterRollover(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Disable the MMC Counter Stop Rollover */ + ETH->MMCCTRL &= ~ETH_MMCCTRL_CNTSTOPRO; + } + else + { + /* Enable the MMC Counter Stop Rollover */ + ETH->MMCCTRL |= ETH_MMCCTRL_CNTSTOPRO; + } +} + +/** + * @brief Resets the MMC Counters. + */ +void ETH_ResetMmcCounters(void) +{ + /* Resets the MMC Counters */ + ETH->MMCCTRL |= ETH_MMCCTRL_CNTRST; +} + +/** + * @brief Enables or disables the specified ETHERNET MMC interrupts. + * @param ETH_MMC_IT specifies the ETHERNET MMC interrupt sources to be enabled or disabled. + * This parameter can be any combination of Tx interrupt or + * any combination of Rx interrupt (but not both)of the following values: + * @arg ETH_MMC_INT_TXGFRMIS When Tx good frame counter reaches half the maximum value + * @arg ETH_MMC_INT_TXMCOLGFIS When Tx good multi col counter reaches half the maximum value + * @arg ETH_MMC_INT_TXSCOLGFIS When Tx good single col counter reaches half the maximum value + * @arg ETH_MMC_INT_RXUCGFIS When Rx good unicast frames counter reaches half the maximum value + * @arg ETH_MMC_INT_RXALGNERFIS When Rx alignment error counter reaches half the maximum value + * @arg ETH_MMC_INT_RXCRCERFIS When Rx crc error counter reaches half the maximum value + * @param Cmd new state of the specified ETHERNET MMC interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMmcInt(uint32_t ETH_MMC_IT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_ETH_MMC_INT(ETH_MMC_IT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if ((ETH_MMC_IT & (uint32_t)0x10000000) != (uint32_t)RESET) + { + /* Remove egister mak from IT */ + ETH_MMC_IT &= 0xEFFFFFFF; + + /* ETHERNET MMC Rx interrupts selected */ + if (Cmd != DISABLE) + { + /* Enable the selected ETHERNET MMC interrupts */ + ETH->MMCRXINTMSK &= (~(uint32_t)ETH_MMC_IT); + } + else + { + /* Disable the selected ETHERNET MMC interrupts */ + ETH->MMCRXINTMSK |= ETH_MMC_IT; + } + } + else + { + /* ETHERNET MMC Tx interrupts selected */ + if (Cmd != DISABLE) + { + /* Enable the selected ETHERNET MMC interrupts */ + ETH->MMCTXINTMSK &= (~(uint32_t)ETH_MMC_IT); + } + else + { + /* Disable the selected ETHERNET MMC interrupts */ + ETH->MMCTXINTMSK |= ETH_MMC_IT; + } + } +} + +/** + * @brief Checks whether the specified ETHERNET MMC IT is set or not. + * @param ETH_MMC_IT specifies the ETHERNET MMC interrupt. + * This parameter can be one of the following values: + * @arg ETH_MMC_IT_TxFCGC When Tx good frame counter reaches half the maximum value + * @arg ETH_MMC_IT_TxMCGC When Tx good multi col counter reaches half the maximum value + * @arg ETH_MMC_IT_TxSCGC When Tx good single col counter reaches half the maximum value + * @arg ETH_MMC_IT_RxUGFC When Rx good unicast frames counter reaches half the maximum value + * @arg ETH_MMC_IT_RxAEC When Rx alignment error counter reaches half the maximum value + * @arg ETH_MMC_IT_RxCEC When Rx crc error counter reaches half the maximum value + * @return The value of ETHERNET MMC IT (SET or RESET). + */ +INTStatus ETH_GetMmcIntStatus(uint32_t ETH_MMC_IT) +{ + INTStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_MMC_GET_INT(ETH_MMC_IT)); + + if ((ETH_MMC_IT & (uint32_t)0x10000000) != (uint32_t)RESET) + { + /* ETHERNET MMC Rx interrupts selected */ + /* Check if the ETHERNET MMC Rx selected interrupt is enabled and occured */ + if ((((ETH->MMCRXINT & ETH_MMC_IT) != (uint32_t)RESET)) && ((ETH->MMCRXINTMSK & ETH_MMC_IT) != (uint32_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + else + { + /* ETHERNET MMC Tx interrupts selected */ + /* Check if the ETHERNET MMC Tx selected interrupt is enabled and occured */ + if ((((ETH->MMCTXINT & ETH_MMC_IT) != (uint32_t)RESET)) && ((ETH->MMCRXINTMSK & ETH_MMC_IT) != (uint32_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + + return bitstatus; +} + +/** + * @brief Get the specified ETHERNET MMC register value. + * @param ETH_MMCReg specifies the ETHERNET MMC register. + * This parameter can be one of the following values: + * @arg ETH_MMCCTRL MMC CTRL register + * @arg ETH_MMCRXINT MMC RIR register + * @arg ETH_MMCTXINT MMC TIR register + * @arg ETH_MMCRXINTMSK MMC RIMR register + * @arg ETH_MMCTXINTMSK MMC TIMR register + * @arg ETH_MMCTXGFASCCNT MMC TGFSCCR register + * @arg ETH_MMCTXGFAMSCCNT MMC TGFMSCCR register + * @arg ETH_MMCTXGFCNT MMC TGFCR register + * @arg ETH_MMCRXFCECNT MMC RFCECR register + * @arg ETH_MMCRXFAECNT MMC RFAECR register + * @arg ETH_MMCRXGUFCNT MMC RGUFCRregister + * @return The value of ETHERNET MMC Register value. + */ +uint32_t ETH_GetMmcRegisterValue(uint32_t ETH_MMCReg) +{ + /* Check the parameters */ + assert_param(IS_ETH_MMC_REGISTER(ETH_MMCReg)); + + /* Return the selected register value */ + return (*(__IO uint32_t*)(ETH_MAC_BASE + ETH_MMCReg)); +} +/*--------------------------------- PTP ------------------------------------*/ + +/** + * @brief Updated the PTP block for fine correction with the Time Stamp Addend register value. + */ +void ETH_UpdatePtpTimeStampAddend(void) +{ + /* Enable the PTP block update with the Time Stamp Addend register value */ + ETH->PTPTSCTRL |= ETH_PTPTSCTRL_TSADDREG; +} + +/** + * @brief Enable the PTP Time Stamp interrupt trigger + */ +void ETH_EnablePtpTimeStampIntTrigger(void) +{ + /* Enable the PTP target time interrupt */ + ETH->PTPTSCTRL |= ETH_PTPTSCTRL_TSTRIG; +} + +/** + * @brief Updated the PTP system time with the Time Stamp Update register value. + */ +void ETH_UpdatePtpTimeStamp(void) +{ + /* Enable the PTP system time update with the Time Stamp Update register value */ + ETH->PTPTSCTRL |= ETH_PTPTSCTRL_TSUPDT; +} + +/** + * @brief Initialize the PTP Time Stamp + */ +void ETH_InitPtpTimeStamp(void) +{ + /* Initialize the PTP Time Stamp */ + ETH->PTPTSCTRL |= ETH_PTPTSCTRL_TSINIT; +} + +/** + * @brief Selects the PTP Update method + * @param UpdateMethod the PTP Update method + * This parameter can be one of the following values: + * @arg ETH_PTP_FINE_UPDATE Fine Update method + * @arg ETH_PTP_COARSE_UPDATE Coarse Update method + */ +void ETH_ConfigPtpUpdateMethod(uint32_t UpdateMethod) +{ + /* Check the parameters */ + assert_param(IS_ETH_PTP_UPDATE(UpdateMethod)); + + if (UpdateMethod != ETH_PTP_COARSE_UPDATE) + { + /* Enable the PTP Fine Update method */ + ETH->PTPTSCTRL |= ETH_PTPTSCTRL_TSCFUPDT; + } + else + { + /* Disable the PTP Coarse Update method */ + ETH->PTPTSCTRL &= (~(uint32_t)ETH_PTPTSCTRL_TSCFUPDT); + } +} + +/** + * @brief Enables or disables the PTP time stamp for transmit and receive frames. + * @param Cmd new state of the PTP time stamp for transmit and receive frames + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_StartPTPTimeStamp(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the PTP time stamp for transmit and receive frames */ + ETH->PTPTSCTRL |= ETH_PTPTSCTRL_TSENA; + } + else + { + /* Disable the PTP time stamp for transmit and receive frames */ + ETH->PTPTSCTRL &= (~(uint32_t)ETH_PTPTSCTRL_TSENA); + } +} + +/** + * @brief Checks whether the specified ETHERNET PTP flag is set or not. + * @param ETH_PTP_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_PTP_FLAG_TSADDREG Addend Register Update + * @arg ETH_PTP_FLAG_TSTRIG Time Stamp Interrupt Trigger Enable + * @arg ETH_PTP_FLAG_TSUPDT Time Stamp Update + * @arg ETH_PTP_FLAG_TSINIT Time Stamp Initialize + * @return The new state of ETHERNET PTP Flag (SET or RESET). + */ +FlagStatus ETH_GetPtpFlagStatus(uint32_t ETH_PTP_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_PTP_GET_FLAG(ETH_PTP_FLAG)); + + if ((ETH->PTPTSCTRL & ETH_PTP_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Sets the system time Sub-Second Increment value. + * @param SubSecondValue specifies the PTP Sub-Second Increment Register value. + */ +void ETH_SetPtpSubSecondInc(uint32_t SubSecondValue) +{ + /* Check the parameters */ + assert_param(IS_ETH_PTP_SUBSECOND_INCREMENT(SubSecondValue)); + /* Set the PTP Sub-Second Increment Register */ + ETH->PTPSSINC = SubSecondValue; +} + +/** + * @brief Sets the Time Stamp update sign and values. + * @param Sign specifies the PTP Time update value sign. + * This parameter can be one of the following values: + * @arg ETH_PTP_POSITIVE_TIME positive time value. + * @arg ETH_PTP_NEGATIVE_TIME negative time value. + * @param SecondValue specifies the PTP Time update second value. + * @param SubSecondValue specifies the PTP Time update sub-second value. + * This parameter is a 31 bit value, bit32 correspond to the sign. + */ +void ETH_SetPtpTimeStampUpdate(uint32_t Sign, uint32_t SecondValue, uint32_t SubSecondValue) +{ + /* Check the parameters */ + assert_param(IS_ETH_PTP_TIME_SIGN(Sign)); + assert_param(IS_ETH_PTP_TIME_STAMP_UPDATE_SUBSECOND(SubSecondValue)); + /* Set the PTP Time Update High Register */ + ETH->PTPSECUP = SecondValue; + + /* Set the PTP Time Update Low Register with sign */ + ETH->PTPNSUP = Sign | SubSecondValue; +} + +/** + * @brief Sets the Time Stamp Addend value. + * @param Value specifies the PTP Time Stamp Addend Register value. + */ +void ETH_SetPtpTimeStampAddend(uint32_t Value) +{ + /* Set the PTP Time Stamp Addend Register */ + ETH->PTPTSADD = Value; +} + +/** + * @brief Sets the Target Time registers values. + * @param HighValue specifies the PTP Target Time High Register value. + * @param LowValue specifies the PTP Target Time Low Register value. + */ +void ETH_SetPtpTargetTime(uint32_t HighValue, uint32_t LowValue) +{ + /* Set the PTP Target Time High Register */ + ETH->PTPTTSEC = HighValue; + /* Set the PTP Target Time Low Register */ + ETH->PTPTTNS = LowValue; +} + +/** + * @brief Get the specified ETHERNET PTP register value. + * @param ETH_PTPReg specifies the ETHERNET PTP register. + * This parameter can be one of the following values: + * @arg ETH_PTPTSCTRL Sub-Second Increment Register + * @arg ETH_PTPSSINC Sub-Second Increment Register + * @arg ETH_PTPSEC Time Stamp High Register + * @arg ETH_PTPNS Time Stamp Low Register + * @arg ETH_PTPSECUP Time Stamp High Update Register + * @arg ETH_PTPNSUP Time Stamp Low Update Register + * @arg ETH_PTPTSADD Time Stamp Addend Register + * @arg ETH_PTPTTSEC Target Time High Register + * @arg ETH_PTPTTNS Target Time Low Register + * @return The value of ETHERNET PTP Register value. + */ +uint32_t ETH_GetPtpRegisterValue(uint32_t ETH_PTPReg) +{ + /* Check the parameters */ + assert_param(IS_ETH_PTP_REGISTER(ETH_PTPReg)); + + /* Return the selected register value */ + return (*(__IO uint32_t*)(ETH_MAC_BASE + ETH_PTPReg)); +} + +/** + * @brief Initializes the DMA Tx descriptors in chain mode with PTP. + * @param DMATxDescTab Pointer on the first Tx desc list + * @param DMAPTPTxDescTab Pointer on the first PTP Tx desc list + * @param TxBuff Pointer on the first TxBuffer list + * @param TxBuffCount Number of the used Tx desc in the list + */ +void ETH_ConfigDmaPtpTxDescInChainMode(ETH_DMADescType* DMATxDescTab, + ETH_DMADescType* DMAPTPTxDescTab, + uint8_t* TxBuff, + uint32_t TxBuffCount) +{ + uint32_t i = 0; + ETH_DMADescType* DMATxDesc; + + /* Set the DMATxDescToSet pointer with the first one of the DMATxDescTab list */ + DMATxDescToSet = DMATxDescTab; + DMAPTPTxDescToSet = DMAPTPTxDescTab; + /* Fill each DMATxDesc descriptor with the right values */ + for (i = 0; i < TxBuffCount; i++) + { + /* Get the pointer on the ith member of the Tx Desc list */ + DMATxDesc = DMATxDescTab + i; + /* Set Second Address Chained bit and enable PTP */ + DMATxDesc->Status = 0; + DMATxDesc->CtrlOrBufSize = ETH_DMA_TX_DESC_TCH | ETH_DMA_TX_DESC_TTSE; + + /* Set Buffer1 address pointer */ + DMATxDesc->Buf1Addr = (uint32_t)(&TxBuff[i * ETH_MAX_PACKET_SIZE]); + + /* Initialize the next descriptor with the Next Desciptor Polling Enable */ + if (i < (TxBuffCount - 1)) + { + /* Set next descriptor address register with next descriptor base address */ + DMATxDesc->Buf2OrNextDescAddr = (uint32_t)(DMATxDescTab + i + 1); + } + else + { + /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ + DMATxDesc->Buf2OrNextDescAddr = (uint32_t)DMATxDescTab; + } + /* make DMAPTPTxDescTab points to the same addresses as DMATxDescTab */ + (&DMAPTPTxDescTab[i])->Buf1Addr = DMATxDesc->Buf1Addr; + (&DMAPTPTxDescTab[i])->Buf2OrNextDescAddr = DMATxDesc->Buf2OrNextDescAddr; + } + /* Store on the last DMAPTPTxDescTab desc status record the first list address */ + (&DMAPTPTxDescTab[i - 1])->Status = (uint32_t)DMAPTPTxDescTab; + + /* Set Transmit Desciptor List Address Register */ + ETH->DMATXDLADDR = (uint32_t)DMATxDescTab; +} + +/** + * @brief Initializes the DMA Rx descriptors in chain mode. + * @param DMARxDescTab Pointer on the first Rx desc list + * @param DMAPTPRxDescTab Pointer on the first PTP Rx desc list + * @param RxBuff Pointer on the first RxBuffer list + * @param RxBuffCount Number of the used Rx desc in the list + */ +void ETH_ConfigDmaPtpRxDescInChainMode(ETH_DMADescType* DMARxDescTab, + ETH_DMADescType* DMAPTPRxDescTab, + uint8_t* RxBuff, + uint32_t RxBuffCount) +{ + uint32_t i = 0; + ETH_DMADescType* DMARxDesc; + + /* Set the DMARxDescToGet pointer with the first one of the DMARxDescTab list */ + DMARxDescToGet = DMARxDescTab; + DMAPTPRxDescToGet = DMAPTPRxDescTab; + /* Fill each DMARxDesc descriptor with the right values */ + for (i = 0; i < RxBuffCount; i++) + { + /* Get the pointer on the ith member of the Rx Desc list */ + DMARxDesc = DMARxDescTab + i; + /* Set Own bit of the Rx descriptor Status */ + DMARxDesc->Status = ETH_DMA_RX_DESC_OWN; + + /* Set Buffer1 size and Second Address Chained bit */ + DMARxDesc->CtrlOrBufSize = ETH_DMA_RX_DESC_RCH | (uint32_t)ETH_MAX_PACKET_SIZE; + /* Set Buffer1 address pointer */ + DMARxDesc->Buf1Addr = (uint32_t)(&RxBuff[i * ETH_MAX_PACKET_SIZE]); + + /* Initialize the next descriptor with the Next Desciptor Polling Enable */ + if (i < (RxBuffCount - 1)) + { + /* Set next descriptor address register with next descriptor base address */ + DMARxDesc->Buf2OrNextDescAddr = (uint32_t)(DMARxDescTab + i + 1); + } + else + { + /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ + DMARxDesc->Buf2OrNextDescAddr = (uint32_t)(DMARxDescTab); + } + /* Make DMAPTPRxDescTab points to the same addresses as DMARxDescTab */ + (&DMAPTPRxDescTab[i])->Buf1Addr = DMARxDesc->Buf1Addr; + (&DMAPTPRxDescTab[i])->Buf2OrNextDescAddr = DMARxDesc->Buf2OrNextDescAddr; + } + /* Store on the last DMAPTPRxDescTab desc status record the first list address */ + (&DMAPTPRxDescTab[i - 1])->Status = (uint32_t)DMAPTPRxDescTab; + + /* Set Receive Desciptor List Address Register */ + ETH->DMARXDLADDR = (uint32_t)DMARxDescTab; +} + +/** + * @brief Transmits a packet, from application buffer, pointed by ppkt with Time Stamp values. + * @param ppkt pointer to application packet buffer to transmit. + * @param FrameLength Tx Packet size. + * @param PTPTxTab Pointer on the first PTP Tx table to store Time stamp values. + * @return ETH_ERROR: in case of Tx desc owned by DMA + * ETH_SUCCESS: for correct transmission + */ +uint32_t ETH_TxPtpPacket(uint8_t* ppkt, uint16_t FrameLength, uint32_t* PTPTxTab) +{ + uint32_t offset = 0, timeout = 0; + /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */ + if ((DMATxDescToSet->Status & ETH_DMA_TX_DESC_OWN) != (uint32_t)RESET) + { + /* Return ERROR: OWN bit set */ + return ETH_ERROR; + } + /* Copy the frame to be sent into memory pointed by the current ETHERNET DMA Tx descriptor */ + for (offset = 0; offset < FrameLength; offset++) + { + (*(__IO uint8_t*)((DMAPTPTxDescToSet->Buf1Addr) + offset)) = (*(ppkt + offset)); + } + /* Setting the Frame Length: bits[10:0] */ + DMATxDescToSet->CtrlOrBufSize &= (~ETH_DMA_TX_DESC_TBS1); + DMATxDescToSet->CtrlOrBufSize |= (FrameLength & ETH_DMA_TX_DESC_TBS1); + /* Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) */ + DMATxDescToSet->CtrlOrBufSize |= ETH_DMA_TX_DESC_LS | ETH_DMA_TX_DESC_FS; + /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ + DMATxDescToSet->Status |= ETH_DMA_TX_DESC_OWN; + /* When Tx Buffer unavailable flag is set: clear it and resume transmission */ + if ((ETH->DMASTS & ETH_DMASTS_TU) != (uint32_t)RESET) + { + /* Clear TBUS ETHERNET DMA flag */ + ETH->DMASTS = ETH_DMASTS_TU; + /* Resume DMA transmission*/ + ETH->DMATXPD = 0; + } + /* Wait for ETH_DMA_TX_DESC_TTSS flag to be set */ + do + { + timeout++; + } while (!(DMATxDescToSet->Status & ETH_DMA_TX_DESC_TTSS) && (timeout < 0xFFFF)); + /* Return ERROR in case of timeout */ + if (timeout == PHY_READ_TO) + { + return ETH_ERROR; + } + /* Clear the DMATxDescToSet status register TTSS flag */ + DMATxDescToSet->Status &= ~ETH_DMA_TX_DESC_TTSS; + *PTPTxTab++ = DMATxDescToSet->Buf1Addr; + *PTPTxTab = DMATxDescToSet->Buf2OrNextDescAddr; + /* Update the ENET DMA current descriptor */ + /* Chained Mode */ + if ((DMATxDescToSet->CtrlOrBufSize & ETH_DMA_TX_DESC_TCH) != (uint32_t)RESET) + { + /* Selects the next DMA Tx descriptor list for next buffer read */ + DMATxDescToSet = (ETH_DMADescType*)(DMAPTPTxDescToSet->Buf2OrNextDescAddr); + if (DMAPTPTxDescToSet->Status != 0) + { + DMAPTPTxDescToSet = (ETH_DMADescType*)(DMAPTPTxDescToSet->Status); + } + else + { + DMAPTPTxDescToSet++; + } + } + else /* Ring Mode */ + { + if ((DMATxDescToSet->CtrlOrBufSize & ETH_DMA_TX_DESC_TER) != (uint32_t)RESET) + { + /* Selects the next DMA Tx descriptor list for next buffer read: this will + be the first Tx descriptor in this case */ + DMATxDescToSet = (ETH_DMADescType*)(ETH->DMATXDLADDR); + DMAPTPTxDescToSet = (ETH_DMADescType*)(ETH->DMATXDLADDR); + } + else + { + /* Selects the next DMA Tx descriptor list for next buffer read */ + DMATxDescToSet = + (ETH_DMADescType*)((uint32_t)DMATxDescToSet + 0x10 + ((ETH->DMABUSMOD & ETH_DMABUSMOD_DSL))); + DMAPTPTxDescToSet = + (ETH_DMADescType*)((uint32_t)DMAPTPTxDescToSet + 0x10 + ((ETH->DMABUSMOD & ETH_DMABUSMOD_DSL))); + } + } + /* Return SUCCESS */ + return ETH_SUCCESS; +} + +/** + * @brief Receives a packet and copies it to memory pointed by ppkt with Time Stamp values. + * @param ppkt pointer to application packet receive buffer. + * @param PTPRxTab Pointer on the first PTP Rx table to store Time stamp values. + * @return ETH_ERROR: if there is error in reception + * framelength: received packet size if packet reception is correct + */ +uint32_t ETH_RxPtpPacket(uint8_t* ppkt, uint32_t* PTPRxTab) +{ + uint32_t offset = 0, framelength = 0; + /* Check if the descriptor is owned by the ENET or CPU */ + if ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_OWN) != (uint32_t)RESET) + { + /* Return error: OWN bit set */ + return ETH_ERROR; + } + if (((DMARxDescToGet->Status & ETH_DMA_RX_DESC_ES) == (uint32_t)RESET) + && ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_LS) != (uint32_t)RESET) + && ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_FS) != (uint32_t)RESET)) + { + /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */ + framelength = ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_FL) >> ETH_DMA_RX_DESC_FRAME_LEN_SHIFT) - 4; + /* Copy the received frame into buffer from memory pointed by the current ETHERNET DMA Rx descriptor */ + for (offset = 0; offset < framelength; offset++) + { + (*(ppkt + offset)) = (*(__IO uint8_t*)((DMAPTPRxDescToGet->Buf1Addr) + offset)); + } + } + else + { + /* Return ERROR */ + framelength = ETH_ERROR; + } + /* When Rx Buffer unavailable flag is set: clear it and resume reception */ + if ((ETH->DMASTS & ETH_DMASTS_RU) != (uint32_t)RESET) + { + /* Clear RBUS ETHERNET DMA flag */ + ETH->DMASTS = ETH_DMASTS_RU; + /* Resume DMA reception */ + ETH->DMARXPD = 0; + } + *PTPRxTab++ = DMARxDescToGet->Buf1Addr; + *PTPRxTab = DMARxDescToGet->Buf2OrNextDescAddr; + /* Set Own bit of the Rx descriptor Status: gives the buffer back to ETHERNET DMA */ + DMARxDescToGet->Status |= ETH_DMA_RX_DESC_OWN; + /* Update the ETHERNET DMA global Rx descriptor with next Rx decriptor */ + /* Chained Mode */ + if ((DMARxDescToGet->CtrlOrBufSize & ETH_DMA_RX_DESC_RCH) != (uint32_t)RESET) + { + /* Selects the next DMA Rx descriptor list for next buffer read */ + DMARxDescToGet = (ETH_DMADescType*)(DMAPTPRxDescToGet->Buf2OrNextDescAddr); + if (DMAPTPRxDescToGet->Status != 0) + { + DMAPTPRxDescToGet = (ETH_DMADescType*)(DMAPTPRxDescToGet->Status); + } + else + { + DMAPTPRxDescToGet++; + } + } + else /* Ring Mode */ + { + if ((DMARxDescToGet->CtrlOrBufSize & ETH_DMA_RX_DESC_RER) != (uint32_t)RESET) + { + /* Selects the first DMA Rx descriptor for next buffer to read: last Rx descriptor was used */ + DMARxDescToGet = (ETH_DMADescType*)(ETH->DMARXDLADDR); + } + else + { + /* Selects the next DMA Rx descriptor list for next buffer to read */ + DMARxDescToGet = + (ETH_DMADescType*)((uint32_t)DMARxDescToGet + 0x10 + ((ETH->DMABUSMOD & ETH_DMABUSMOD_DSL))); + } + } + /* Return Frame Length/ERROR */ + return (framelength); +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_exti.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_exti.c new file mode 100644 index 0000000000..fb77e69623 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_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 n32g45x_exti.c + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_exti.h" + +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_flash.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_flash.c new file mode 100644 index 0000000000..fc8b38ba38 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_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 n32g45x_flash.c + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_flash.h" + +/** @addtogroup N32G45X_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 N32G45X 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 N32G45X 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 N32G45X 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 N32G45X 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 N32G45X 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 N32G45X devices. + * - For N32G45X 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 N32G45X devices. + * - For N32G45X 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 N32G45X 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 N32G45X 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 N32G45X 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 N32G45X 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 N32G45X 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 N32G45X devices. + * @param FLASH_Pages specifies the address of the pages to be write protected. + * This parameter can be: + * @arg For @b N32G45X_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 N32G45X 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 N32G45X 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 N32G45X 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 N32G45X 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 N32G45X 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 N32G45X 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 N32G45x 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 N32G45X 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 N32G45X 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 N32G45X 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 N32G45X 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 N32G45X 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 N32G45X 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 N32G45X 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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_gpio.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_gpio.c new file mode 100644 index 0000000000..8c1f054396 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_gpio.c @@ -0,0 +1,870 @@ +/***************************************************************************** + * 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 n32g45x_gpio.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_gpio.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_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 if (GPIOx == GPIOF) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOF, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOF, DISABLE); + } + else if (GPIOx == GPIOG) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOG, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOG, 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 N32G45x 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) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ETH_MEDIA_INTERFACE(ETH_ConfigSel)); + + if (ETH_ConfigSel == GPIO_ETH_RMII_CFG) + { + *(__IO uint32_t*)MAPR_MII_RMII_SEL_BB = (uint32_t)1; + } + else + { + *(__IO uint32_t*)MAPR_MII_RMII_SEL_BB = (uint32_t)0; + } + +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_i2c.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_i2c.c new file mode 100644 index 0000000000..0e0d335b2d --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_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 n32g45x_i2c.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_i2c.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_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 or 2 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 I2C2 reset state */ + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_I2C3, ENABLE); + /* Release I2C2 from reset state */ + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_I2C3, DISABLE); + } + else if (I2Cx == I2C4) + { + /* Enable I2C4 reset state */ + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_I2C3, ENABLE); + /* Release I2C4 from reset state */ + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_I2C3, 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 (n32g45x_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 + * n32g45x_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 n32g45x_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 n32g45x_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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_iwdg.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_iwdg.c new file mode 100644 index 0000000000..36b2f4204a --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_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 n32g45x_iwdg.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_iwdg.h" + +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_opamp.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_opamp.c new file mode 100644 index 0000000000..d8dd50db71 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_opamp.c @@ -0,0 +1,201 @@ +/***************************************************************************** + * 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 n32g45x_opamp.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_opamp.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup OPAMP + * @brief OPAMP driver modules + * @{ + */ + +/** @addtogroup OPAMP_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup OPAMP_Private_Defines + * @{ + */ + +/** + * @} + */ + +/** @addtogroup OPAMP_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup OPAMP_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup OPAMP_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup OPAMP_Private_Functions + * @{ + */ +#define SetBitMsk(reg, bit, msk) ((reg) = ((reg) & ~(msk) | (bit))) +#define ClrBit(reg, bit) ((reg) &= ~(bit)) +#define SetBit(reg, bit) ((reg) |= (bit)) +#define GetBit(reg, bit) ((reg) & (bit)) +/** + * @brief Deinitializes the OPAMP peripheral registers to their default reset values. + */ +void OPAMP_DeInit(void) +{ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_OPAMP, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_OPAMP, DISABLE); +} + +void OPAMP_StructInit(OPAMP_InitType* OPAMP_InitStruct) +{ + OPAMP_InitStruct->Gain = OPAMP_CS_PGA_GAIN_2; + OPAMP_InitStruct->HighVolRangeEn = ENABLE; + OPAMP_InitStruct->TimeAutoMuxEn = DISABLE; + OPAMP_InitStruct->Mod = OPAMP_CS_PGA_EN; +} + +void OPAMP_Init(OPAMPX OPAMPx, OPAMP_InitType* OPAMP_InitStruct) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + __IO uint32_t tmp = *pCs; + + SetBitMsk(tmp, OPAMP_InitStruct->Gain, OPAMP_CS_PGA_GAIN_MASK); + + if(OPAMP_InitStruct->HighVolRangeEn==ENABLE) + SetBitMsk(tmp, OPAMP_CS_RANGE_MASK, OPAMP_CS_RANGE_MASK); + else + ClrBit(tmp,OPAMP_CS_RANGE_MASK); + + if(OPAMP_InitStruct->TimeAutoMuxEn==ENABLE) + SetBitMsk(tmp,OPAMP_CS_TCMEN_MASK, OPAMP_CS_TCMEN_MASK); + else + ClrBit(tmp,OPAMP_CS_TCMEN_MASK); + + SetBitMsk(tmp, OPAMP_InitStruct->Mod, OPAMP_CS_MOD_MASK); + *pCs = tmp; +} +void OPAMP_Enable(OPAMPX OPAMPx, FunctionalState en) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + if (en) + SetBit(*pCs, OPAMP_CS_EN_MASK); + else + ClrBit(*pCs, OPAMP_CS_EN_MASK); +} + +void OPAMP_SetPgaGain(OPAMPX OPAMPx, OPAMP_CS_PGA_GAIN Gain) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + __IO uint32_t tmp = *pCs; + SetBitMsk(tmp, Gain, OPAMP_CS_PGA_GAIN_MASK); + *pCs = tmp; +} +void OPAMP_SetVpSecondSel(OPAMPX OPAMPx, OPAMP_CS_VPSSEL VpSSel) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + __IO uint32_t tmp = *pCs; + SetBitMsk(tmp, VpSSel, OPAMP_CS_VPSEL_SECOND_MASK); + *pCs = tmp; +} +void OPAMP_SetVmSecondSel(OPAMPX OPAMPx, OPAMP_CS_VMSSEL VmSSel) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + __IO uint32_t tmp = *pCs; + SetBitMsk(tmp, VmSSel, OPAMP_CS_VMSEL_SECOND_MASK); + *pCs = tmp; +} +void OPAMP_SetVpSel(OPAMPX OPAMPx, OPAMP_CS_VPSEL VpSel) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + __IO uint32_t tmp = *pCs; + SetBitMsk(tmp, VpSel, OPAMP_CS_VPSEL_MASK); + *pCs = tmp; +} +void OPAMP_SetVmSel(OPAMPX OPAMPx, OPAMP_CS_VMSEL VmSel) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + __IO uint32_t tmp = *pCs; + SetBitMsk(tmp, VmSel, OPAMP_CS_VMSEL_MASK); + *pCs = tmp; +} +bool OPAMP_IsCalOutHigh(OPAMPX OPAMPx) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + return (GetBit(*pCs, OPAMP_CS_CALOUT_MASK)) ? true : false; +} +void OPAMP_CalibrationEnable(OPAMPX OPAMPx, FunctionalState en) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + if (en) + SetBit(*pCs, OPAMP_CS_CALON_MASK); + else + ClrBit(*pCs, OPAMP_CS_CALON_MASK); +} +// Lock see @OPAMP_LOCK +void OPAMP_SetLock(uint32_t Lock) +{ + OPAMP->LOCK = Lock; +} +/** + * @} + */ +/** + * @} + */ +/** + * @} + */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_pwr.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_pwr.c new file mode 100644 index 0000000000..c00be0efd3 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_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 n32g45x_pwr.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_pwr.h" + +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_qspi.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_qspi.c new file mode 100644 index 0000000000..e51b063b71 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_qspi.c @@ -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. + * ****************************************************************************/ + +/** + * @file n32g45x_qspi.c + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_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_XIP_MBL(QSPI_InitStruct->ENHANCED_XIP_MBL)); + assert_param(IS_QSPI_ENH_XIP_CT_EN(QSPI_InitStruct->ENHANCED_XIP_CT_EN)); + assert_param(IS_QSPI_ENH_XIP_INST_EN(QSPI_InitStruct->ENHANCED_XIP_INST_EN)); + assert_param(IS_QSPI_ENH_XIP_DFS_HC(QSPI_InitStruct->ENHANCED_XIP_DFS_HC)); + 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_MD_BIT_EN(QSPI_InitStruct->ENHANCED_MD_BIT_EN)); + 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_XIP_MBL | QSPI_InitStruct->ENHANCED_XIP_CT_EN + | QSPI_InitStruct->ENHANCED_XIP_INST_EN | QSPI_InitStruct->ENHANCED_XIP_DFS_HC | 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_MD_BIT_EN | 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. + QSPI_NSS_PORTF_SEL:QSPI remap by PF0~PF5. + * @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; + case QSPI_NSS_PORTF_SEL: + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOF | RCC_APB2_PERIPH_AFIO, ENABLE); + RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_QSPI, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP1_QSPI, ENABLE); + + QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_0); // NSS + QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_1); // SCK + QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_2); // IO0 + if (IO1_Input) + { + GPIO_InitStructure.Pin = GPIO_PIN_3; // IO1 + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_INPUT; + GPIO_InitPeripheral(GPIOF, &GPIO_InitStructure); + } + else + { + QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_3); // 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(GPIOF, &GPIO_InitStructure); + + GPIOF->PBSC |= GPIO_PIN_4 | GPIO_PIN_5; + } + else + { + QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_4); // IO2 + QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_5); // IO3 + } + break; + default: + break; + } +} +/** + * @brief Configuration of QSPI DMA. + * @param TxRx transmit or receive data. + QSPI_DMA_CTRL_TX_DMA_EN:transmit data + QSPI_DMA_CTRL_RX_DMA_EN:receive data + * @param TxDataLevel dma transmit data level. + * @param RxDataLevel dma receive data level. + */ +void QSPI_DMA_CTRL_Config(uint8_t TxRx,uint8_t TxDataLevel,uint8_t RxDataLevel) +{ + assert_param(IS_QSPI_DMA_CTRL(TxRx)); + assert_param(IS_QSPI_DMATDL_CTRL(TxDataLevel)); + assert_param(IS_QSPI_DMARDL_CTRL(RxDataLevel)); + + QSPI->DMA_CTRL = 0x00; + + if (TxRx & QSPI_DMA_CTRL_TX_DMA_EN) + { + QSPI->DMATDL_CTRL = TxDataLevel; + QSPI->DMA_CTRL |= QSPI_DMA_CTRL_TX_DMA_EN; + } + if (TxRx & QSPI_DMA_CTRL_RX_DMA_EN) + { + QSPI->DMARDL_CTRL = RxDataLevel; + 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) +{ + volatile uint16_t tmp = 0; + + if (FLAG == QSPI_ISTS_TXFOIS) + tmp = QSPI->TXFOI_CLR; + if (FLAG == QSPI_ISTS_RXFOIS) + tmp = QSPI->RXFOI_CLR; + if (FLAG == QSPI_ISTS_RXFUIS) + tmp = QSPI->RXFUI_CLR; + if (FLAG == QSPI_ISTS_MMCIS) + tmp = QSPI->MMC_CLR; + if (FLAG == QSPI_ISTS) + tmp = QSPI->ICLR; +} +/** + * @brief Clear the flag of related interrupt register. + * @param FLAG flag of XRXFOIC interrupt register. + */ +void QSPI_XIP_ClearITFLAG(uint16_t FLAG) +{ + volatile uint16_t tmp = 0; + + if (FLAG == QSPI_XIP_RXFOI_CLR_XRXFOIC) + tmp = 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 transmit error or not. + * @return 1: Transmit error;0: No transmit error. + */ +bool GetQspiTransmitErrorStatus(void) +{ + if ((QSPI->STS & 0x20) == 0x20) + 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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_rcc.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_rcc.c new file mode 100644 index 0000000000..8c1f892057 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_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 n32g45x_rcc.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_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_GPIOF, RCC_APB2_PERIPH_GPIOG, 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_GPIOF, RCC_APB2_PERIPH_GPIOG, 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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_rtc.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_rtc.c new file mode 100644 index 0000000000..8a65046ab8 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_rtc.c @@ -0,0 +1,2007 @@ +/***************************************************************************** + * 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 n32g45x_rtc.c + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_rtc.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_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; + + /* 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; + + 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; + /* Waits until the RTC Time and Date registers + (RTC_TSH and RTC_DATE) are synchronized with RTC APB clock. */ + status=RTC_WaitForSynchro(); + 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; + /* Waits until the RTC Time and Date registers + (RTC_TSH and RTC_DATE) are synchronized with RTC APB clock. */ + status=RTC_WaitForSynchro(); + 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) +{ + __IO uint32_t temp = 0; + /* 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. + * @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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_sdio.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_sdio.c new file mode 100644 index 0000000000..cff0be44fd --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_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 n32g45x_sdio.c + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_sdio.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_spi.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_spi.c new file mode 100644 index 0000000000..d069e7fe0c --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_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 n32g45x_spi.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_spi.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_tim.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_tim.c new file mode 100644 index 0000000000..41e441db65 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_tim.c @@ -0,0 +1,3307 @@ +/***************************************************************************** + * 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 n32g45x_tim.c + * @author Nations + * @version v1.0.4 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_tim.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_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_CAPCMPMOD3, TIM_DMABASE_CAPCMPDAT5, TIM_DMABASE_CAPCMPDAT6, + * 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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_tsc.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_tsc.c new file mode 100644 index 0000000000..dcdded30d3 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_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 n32g45x_tsc.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x.h" +#include "n32g45x_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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_usart.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_usart.c new file mode 100644 index 0000000000..a05c332d0c --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_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 n32g45x_usart.c + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_usart.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_wwdg.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_wwdg.c new file mode 100644 index 0000000000..6510972c3e --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_std_periph_driver/src/n32g45x_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 n32g45x_wwdg.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_wwdg.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_core.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_core.h new file mode 100644 index 0000000000..c2a9d3d07e --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_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 "n32g45x.h" + +/** + * @addtogroup N32G45X_USB_Driver + * @brief N32G45x 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/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_def.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_def.h new file mode 100644 index 0000000000..b981786024 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_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 N32G45X_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/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_init.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_init.h new file mode 100644 index 0000000000..6378061427 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_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 "n32g45x.h" +#include "usb_core.h" + +/** + * @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_int.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_int.h new file mode 100644 index 0000000000..77df5f0900 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_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 N32G45X_USB_Driver + * @{ + */ + +void USB_CorrectTransferLp(void); +void USB_CorrectTransferHp(void); + +/** + * @} + */ + +#endif /* __USB_INT_H__ */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_lib.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_lib.h new file mode 100644 index 0000000000..3bd907dcac --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_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/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_mem.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_mem.h new file mode 100644 index 0000000000..362ccc48e5 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_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 "n32g45x.h" + +/** + * @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_regs.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_regs.h new file mode 100644 index 0000000000..61cb75c82f --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_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 "n32g45x.h" + +/** + * @addtogroup N32G45X_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 << 11) | 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/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_sil.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_sil.h new file mode 100644 index 0000000000..68439223b1 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_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 "n32g45x.h" + +/** + * @addtogroup N32G45X_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/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_type.h b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/inc/usb_type.h new file mode 100644 index 0000000000..3187a1408c --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_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 N32G45X_USB_Driver + * @{ + */ + +#ifndef NULL +#define NULL ((void*)0) +#endif + +/** + * @} + */ + +#endif /* __USB_TYPE_H__ */ diff --git a/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_core.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_core.c new file mode 100644 index 0000000000..ee7f4e74ca --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_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/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_init.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_init.c new file mode 100644 index 0000000000..016aec225c --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_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/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_int.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_int.c new file mode 100644 index 0000000000..66f8d4fe2a --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_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/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_mem.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_mem.c new file mode 100644 index 0000000000..539a76b7cc --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_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/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_regs.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_regs.c new file mode 100644 index 0000000000..9dc97c4db7 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_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/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_sil.c b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_usbfs_driver/src/usb_sil.c new file mode 100644 index 0000000000..930e661c83 --- /dev/null +++ b/bsp/n32/libraries/N32G45x_Firmware_Library/n32g45x_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/Kconfig b/bsp/n32/libraries/n32_drivers/Kconfig new file mode 100644 index 0000000000..705f7be4b5 --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/Kconfig @@ -0,0 +1,6 @@ +if BSP_USING_USBD + config BSP_USBD_TYPE_FS + bool + # "USB Full Speed (FS) Core" +endif + diff --git a/bsp/n32/libraries/n32_drivers/SConscript b/bsp/n32/libraries/n32_drivers/SConscript new file mode 100644 index 0000000000..bb5f92d0f3 --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/SConscript @@ -0,0 +1,53 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() + +# add the general drivers. +src = Split(""" +""") + +if GetDepend(['RT_USING_PIN']): + src += ['drv_gpio.c'] + +if GetDepend(['RT_USING_SERIAL']): + if GetDepend(['RT_USING_SERIAL_V2']): + src += ['drv_usart_v2.c'] + else: + src += ['drv_usart.c'] + +if GetDepend(['RT_USING_HWTIMER']): + src += ['drv_hwtimer.c'] + +if GetDepend(['RT_USING_PWM']): + src += ['drv_pwm.c'] + +if GetDepend(['RT_USING_SPI']): + src += ['drv_spi.c'] + +if GetDepend(['RT_USING_I2C', 'RT_USING_I2C_BITOPS']): + if GetDepend('BSP_USING_I2C1') or GetDepend('BSP_USING_I2C2') or GetDepend('BSP_USING_I2C3') or GetDepend('BSP_USING_I2C4'): + src += ['drv_i2c.c'] + + +if GetDepend(['RT_USING_ADC']): + src += Glob('drv_adc.c') + +if GetDepend(['RT_USING_DAC']): + src += Glob('drv_dac.c') + +if GetDepend(['RT_USING_CAN']): + src += ['drv_can.c'] + + +if GetDepend(['BSP_USING_WDT']): + src += ['drv_wdt.c'] + +path = [cwd] +path += [cwd + '/config'] + +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) + +Return('group') + diff --git a/bsp/n32/libraries/n32_drivers/drv_adc.c b/bsp/n32/libraries/n32_drivers/drv_adc.c new file mode 100644 index 0000000000..648fb1f9d8 --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_adc.c @@ -0,0 +1,188 @@ +/***************************************************************************** + * 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 drv_adc.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "board.h" +#include "drv_adc.h" + +#ifdef RT_USING_ADC + +#if defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3) || defined(BSP_USING_ADC4) + /* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable ADC */ + + +static struct n32_adc_config adc_config[] = +{ +#ifdef BSP_USING_ADC1 + { + "adc1", + ADC1, + }, +#endif + +#ifdef BSP_USING_ADC2 + { + "adc2", + ADC2, + }, +#endif + +#ifdef BSP_USING_ADC3 + { + "adc3", + ADC3, + }, +#endif + +#ifdef BSP_USING_ADC4 + { + "adc4", + ADC4, + }, +#endif +}; + +static struct n32_adc adc_obj[sizeof(adc_config) / sizeof(adc_config[0])] = {0}; + +static void n32_adc_init(struct n32_adc_config *config) +{ + ADC_InitType ADC_InitStructure; + /* ADC configuration ------------------------------------------------------*/ + ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT; + ADC_InitStructure.MultiChEn = DISABLE; + ADC_InitStructure.ContinueConvEn = DISABLE; + ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE; + ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R; + ADC_InitStructure.ChsNumber = 1; + ADC_Init((ADC_Module*)config->adc_periph, &ADC_InitStructure); + + /* Enable ADC */ + ADC_Enable((ADC_Module*)config->adc_periph, ENABLE); + /* Check ADC Ready */ + while(ADC_GetFlagStatusNew((ADC_Module*)config->adc_periph, ADC_FLAG_RDY) == RESET) + ; + /* Start ADC calibration */ + ADC_StartCalibration((ADC_Module*)config->adc_periph); + /* Check the end of ADC calibration */ + while (ADC_GetCalibrationStatus((ADC_Module*)config->adc_periph)) + ; +} + +static rt_err_t n32_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled) +{ + if (channel > ADC_CH_18) + { + return RT_EINVAL; + } + return RT_EOK; +} + +static rt_err_t n32_adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value) +{ + struct n32_adc_config *config; + RT_ASSERT(device != RT_NULL); + + if (channel > ADC_CH_18) + { + return RT_EINVAL; + } + config = (struct n32_adc_config *)(device->parent.user_data); + + ADC_ConfigRegularChannel((ADC_Module*)config->adc_periph, channel, 1, ADC_SAMP_TIME_239CYCLES5); + + /* Start ADC Software Conversion */ + ADC_EnableSoftwareStartConv((ADC_Module*)config->adc_periph, ENABLE); + + while(ADC_GetFlagStatus((ADC_Module*)config->adc_periph, ADC_FLAG_ENDC)==0) + { + } + ADC_ClearFlag((ADC_Module*)config->adc_periph, ADC_FLAG_ENDC); + ADC_ClearFlag((ADC_Module*)config->adc_periph, ADC_FLAG_STR); + *value=ADC_GetDat((ADC_Module*)config->adc_periph); + + return RT_EOK; +} + +static struct rt_adc_ops n32_adc_ops = +{ + .enabled = n32_adc_enabled, + .convert = n32_adc_convert, +}; + +int rt_hw_adc_init(void) +{ + int i = 0; + int result = RT_EOK; + +#if defined(BSP_USING_ADC1) + RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC1, ENABLE); + /* Configure PC.00 PC.01 as analog input -------------------------*/ + GPIOInit(GPIOC, GPIO_Mode_AIN, GPIO_Speed_50MHz, GPIO_PIN_0 | GPIO_PIN_1); +#endif /* BSP_USING_ADC1 */ + +#if defined(BSP_USING_ADC2) + RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC2, ENABLE); + /* Configure PC.02 PC.03 as analog input -------------------------*/ + GPIOInit(GPIOC, GPIO_Mode_AIN, GPIO_Speed_50MHz, GPIO_PIN_2 | GPIO_PIN_3); + #endif /* BSP_USING_ADC2 */ + +#if defined(BSP_USING_ADC3) + RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC3, ENABLE); + /* Configure PD.10 PD.11 as analog input -------------------------*/ + GPIOInit(GPIOD, GPIO_Mode_AIN, GPIO_Speed_50MHz, GPIO_PIN_10 | GPIO_PIN_11); +#endif /* BSP_USING_ADC3 */ + +#if defined(BSP_USING_ADC4) + RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC4, ENABLE); + /* Configure PD.12 PD.13 as analog input -------------------------*/ + GPIOInit(GPIOD, GPIO_Mode_AIN, GPIO_Speed_50MHz, GPIO_PIN_12 | GPIO_PIN_13); +#endif /* BSP_USING_ADC4 */ + + /* RCC_ADCHCLK_DIV16*/ + ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV16); + + for (i = 0; i < sizeof(adc_obj) / sizeof(adc_obj[0]); i++) + { + adc_obj[i].config = &adc_config[i]; + n32_adc_init(&adc_config[i]); + rt_hw_adc_register(&adc_obj[i].adc_device, \ + adc_obj[i].config->name, &n32_adc_ops, adc_obj[i].config); + } + return result; +} + +INIT_DEVICE_EXPORT(rt_hw_adc_init); + +#endif /* defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3) || defined(BSP_USING_ADC4) */ +#endif /* RT_USING_ADC */ + diff --git a/bsp/n32/libraries/n32_drivers/drv_adc.h b/bsp/n32/libraries/n32_drivers/drv_adc.h new file mode 100644 index 0000000000..19d26b1165 --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_adc.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 drv_adc.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#ifndef __DRV_ADC__ +#define __DRV_ADC__ + +#include +#include +#include +#include "n32g45x.h" + +/* n32g45x config class */ +struct n32_adc_config +{ + const char *name; + ADC_Module* adc_periph; +}; + +struct n32_adc +{ + struct rt_adc_device adc_device; + struct n32_adc_config *config; +}; + +int rt_hw_adc_init(void); + +#endif diff --git a/bsp/n32/libraries/n32_drivers/drv_can.c b/bsp/n32/libraries/n32_drivers/drv_can.c new file mode 100644 index 0000000000..9f8edac5aa --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_can.c @@ -0,0 +1,699 @@ +/***************************************************************************** + * 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 drv_can.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#include +#include "board.h" + +#ifdef RT_USING_CAN + +#if defined(BSP_USING_CAN1) || defined(BSP_USING_CAN2) + /* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable ADC */ + + +CanRxMessage RxMessage; + +#ifdef BSP_USING_CAN1 +static struct n32_can drv_can1 = +{ + .name = "bxcan1", + .CanHandle.Instance = CAN1, +}; +#endif + +#ifdef BSP_USING_CAN2 +static struct n32_can drv_can2 = +{ + .name = "bxcan2", + .CanHandle.Instance = CAN2, +}; +#endif + +static rt_err_t setfilter(struct n32_can *pbxcan, CAN_FilterInitType *pconfig) +{ + CAN_FilterInitType CAN_FilterInitStruct; + + CAN_Module* CANx; + CANx = pbxcan->CanHandle.Instance; + + CAN_FilterInitStruct.Filter_Num = pconfig->Filter_Num; + CAN_FilterInitStruct.Filter_Mode = pconfig->Filter_Mode; + CAN_FilterInitStruct.Filter_Scale = pconfig->Filter_Scale; + CAN_FilterInitStruct.Filter_HighId = pconfig->Filter_HighId; + CAN_FilterInitStruct.Filter_LowId = pconfig->Filter_LowId; + CAN_FilterInitStruct.FilterMask_HighId = pconfig->FilterMask_HighId;; + CAN_FilterInitStruct.FilterMask_LowId = pconfig->FilterMask_LowId;; + CAN_FilterInitStruct.Filter_FIFOAssignment = pconfig->Filter_FIFOAssignment;; + CAN_FilterInitStruct.Filter_Act = pconfig->Filter_Act; + if(CANx == CAN1) + { + CAN1_InitFilter(&CAN_FilterInitStruct); + } + else + { + CAN2_InitFilter(&CAN_FilterInitStruct); + } + + return RT_EOK; +} + +static void bxcan_init(struct rt_can_device *can, struct can_configure *cfg) +{ + CAN_InitType CAN_InitStructure; + + struct n32_can *drv_can; + CAN_Module *pbxcan; + + drv_can = (struct n32_can *)can->parent.user_data; + pbxcan = drv_can->CanHandle.Instance; + + uint32_t bps ; + + /* CAN register init */ + CAN_DeInit(pbxcan); + + /* Struct init*/ + CAN_InitStruct(&CAN_InitStructure); + switch(cfg->baud_rate) + { + case CAN1MBaud: + bps = CAN_BAUDRATE_1M; + break; + case CAN500kBaud: + bps = CAN_BAUDRATE_500K; + break; + case CAN250kBaud: + bps = CAN_BAUDRATE_250K; + break; + case CAN125kBaud: + bps = CAN_BAUDRATE_125K; + break; + case CAN100kBaud: + bps = CAN_BAUDRATE_100K; + break; + case CAN50kBaud: + bps = CAN_BAUDRATE_50K; + break; + case CAN20kBaud: + bps = CAN_BAUDRATE_20K; + break; + case CAN10kBaud: + bps = CAN_BAUDRATE_10K; + break; + + default: + bps = CAN_BAUDRATE_100K; + break; + } + + CAN_InitStructure.BaudRatePrescaler = (uint32_t)(CAN_BTR_CALCULATE / bps); + + switch (cfg->mode) + { + case RT_CAN_MODE_NORMAL: + CAN_InitStructure.OperatingMode = CAN_Normal_Mode; + break; + case RT_CAN_MODE_LISEN: + CAN_InitStructure.OperatingMode = CAN_Silent_Mode; + break; + case RT_CAN_MODE_LOOPBACK: + CAN_InitStructure.OperatingMode = CAN_LoopBack_Mode; + break; + case RT_CAN_MODE_LOOPBACKANLISEN: + CAN_InitStructure.OperatingMode = CAN_Silent_LoopBack_Mode; + break; + + default: + CAN_InitStructure.OperatingMode = CAN_Normal_Mode; + break; + } + + CAN_InitStructure.TTCM = DISABLE; + CAN_InitStructure.ABOM = DISABLE; + CAN_InitStructure.AWKUM = DISABLE; + CAN_InitStructure.NART = DISABLE; + CAN_InitStructure.RFLM = DISABLE; + CAN_InitStructure.TXFP = ENABLE; + + CAN_InitStructure.RSJW = CAN_RSJW_1tq; + CAN_InitStructure.TBS1 = CAN_TBS1_3tq; + CAN_InitStructure.TBS2 = CAN_TBS2_2tq; + + /*Initializes the CAN */ + CAN_Init(pbxcan, &CAN_InitStructure); + + /* CAN filter init */ + setfilter(drv_can, &drv_can->FilterConfig); + +} + +#ifdef BSP_USING_CAN1 +static void bxcan1_hw_init(void) +{ + /* Enable CAN1 reset state */ + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_CAN1, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIOInit(GPIOD, GPIO_Mode_IPU, GPIO_Speed_50MHz, GPIO_PIN_8); + GPIOInit(GPIOD, GPIO_Mode_AF_PP, GPIO_Speed_50MHz, GPIO_PIN_9); + /* Remap CAN1 GPIOs */ + GPIO_ConfigPinRemap(GPIO_RMP1_CAN1, ENABLE); +} +#endif + +#ifdef BSP_USING_CAN2 +static void bxcan2_hw_init(void) +{ + /* Enable CAN2 reset state */ + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_CAN2, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIOInit(GPIOB, GPIO_Mode_IPU, GPIO_Speed_50MHz, GPIO_PIN_12); + GPIOInit(GPIOB, GPIO_Mode_AF_PP, GPIO_Speed_50MHz, GPIO_PIN_13); +} +#endif + +static rt_err_t configure(struct rt_can_device *can, struct can_configure *cfg) +{ + struct n32_can *drv_can; + CAN_Module *pbxcan; + + drv_can = (struct n32_can *)can->parent.user_data; + pbxcan = drv_can->CanHandle.Instance; + + if (pbxcan == CAN1) + { +#ifdef BSP_USING_CAN1 + bxcan1_hw_init(); + bxcan_init(&drv_can->device, &drv_can->device.config); +#endif + } + else if (pbxcan == CAN2) + { +#ifdef BSP_USING_CAN2 + bxcan2_hw_init(); + bxcan_init(&drv_can->device, &drv_can->device.config); +#endif + } + return RT_EOK; +} + +/** + * @brief Configures the NVIC for CAN. + */ +void CAN_NVIC_Config(IRQn_Type IRQn, uint8_t PreemptionPriority, uint8_t SubPriority,FunctionalState cmd) +{ + NVIC_InitType NVIC_InitStructure; + + NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); + + NVIC_InitStructure.NVIC_IRQChannel = IRQn; + NVIC_InitStructure.NVIC_IRQChannelCmd = cmd; + if(cmd) + { + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PreemptionPriority; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = SubPriority; + } + NVIC_Init(&NVIC_InitStructure); +} + +static rt_err_t control(struct rt_can_device *can, int cmd, void *arg) +{ + rt_uint32_t argval; + struct n32_can *drv_can; + struct rt_can_filter_config *filter_cfg; + + RT_ASSERT(can != RT_NULL); + drv_can = (struct n32_can *)can->parent.user_data; + RT_ASSERT(drv_can != RT_NULL); + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + argval = (rt_uint32_t) arg; + if (argval == RT_DEVICE_FLAG_INT_RX) + { + if (CAN1 == drv_can->CanHandle.Instance) + { + CAN_NVIC_Config(USB_LP_CAN1_RX0_IRQn, 1, 0, ENABLE); + CAN_NVIC_Config(CAN1_RX1_IRQn, 1, 0, ENABLE); + } +#ifdef CAN2 + if (CAN2 == drv_can->CanHandle.Instance) + { + CAN_NVIC_Config(CAN2_RX0_IRQn, 0, 0, DISABLE); + CAN_NVIC_Config(CAN2_RX1_IRQn, 0, 0, DISABLE); + } +#endif + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_FMP0, DISABLE); + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_FF0, DISABLE); + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_FOV0, DISABLE); + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_FMP1, DISABLE); + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_FF1, DISABLE); + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_FOV1, DISABLE); + } + else if (argval == RT_DEVICE_FLAG_INT_TX) + { + if (CAN1 == drv_can->CanHandle.Instance) + { + CAN_NVIC_Config(USB_HP_CAN1_TX_IRQn, 0, 0, DISABLE); + } +#ifdef CAN2 + if (CAN2 == drv_can->CanHandle.Instance) + { + CAN_NVIC_Config(CAN2_TX_IRQn, 0, 0, DISABLE); + } +#endif + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_TME, DISABLE); + } + else if (argval == RT_DEVICE_CAN_INT_ERR) + { + if (CAN1 == drv_can->CanHandle.Instance) + { + CAN_NVIC_Config(CAN1_SCE_IRQn, 0, 0, DISABLE); + + } +#ifdef CAN2 + if (CAN2 == drv_can->CanHandle.Instance) + { + CAN_NVIC_Config(CAN2_SCE_IRQn, 0, 0, DISABLE); + } +#endif + CAN_ClearFlag(drv_can->CanHandle.Instance, CAN_FLAG_EWGFL); + CAN_ClearFlag(drv_can->CanHandle.Instance, CAN_FLAG_EPVFL); + CAN_ClearFlag(drv_can->CanHandle.Instance, CAN_FLAG_BOFFL); + CAN_ClearFlag(drv_can->CanHandle.Instance, CAN_FLAG_LEC); + CAN_ClearINTPendingBit(drv_can->CanHandle.Instance, CAN_INT_ERR); + } + break; + case RT_DEVICE_CTRL_SET_INT: + argval = (rt_uint32_t) arg; + if (argval == RT_DEVICE_FLAG_INT_RX) + { + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_FMP0, ENABLE); + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_FF0, ENABLE); + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_FOV0, ENABLE); + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_FMP1, ENABLE); + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_FF1, ENABLE); + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_FOV1, ENABLE); + + if (CAN1 == drv_can->CanHandle.Instance) + { + CAN_NVIC_Config(USB_LP_CAN1_RX0_IRQn, 1, 0, ENABLE); + CAN_NVIC_Config(CAN1_RX1_IRQn, 1, 0, ENABLE); + } +#ifdef CAN2 + if (CAN2 == drv_can->CanHandle.Instance) + { + CAN_NVIC_Config(CAN2_RX0_IRQn, 1, 0, ENABLE); + CAN_NVIC_Config(CAN2_RX1_IRQn, 1, 0, ENABLE); + } +#endif + } + else if (argval == RT_DEVICE_FLAG_INT_TX) + { + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_TME, ENABLE); + + if (CAN1 == drv_can->CanHandle.Instance) + { + CAN_NVIC_Config(USB_HP_CAN1_TX_IRQn, 1, 0, ENABLE); + } +#ifdef CAN2 + if (CAN2 == drv_can->CanHandle.Instance) + { + CAN_NVIC_Config(CAN2_TX_IRQn, 1, 0, ENABLE); + } +#endif + } + else if (argval == RT_DEVICE_CAN_INT_ERR) + { + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_EWG, ENABLE); + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_EPV, ENABLE); + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_BOF, ENABLE); + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_LEC, ENABLE); + CAN_INTConfig(drv_can->CanHandle.Instance, CAN_INT_ERR, ENABLE); + + if (CAN1 == drv_can->CanHandle.Instance) + { + CAN_NVIC_Config(CAN1_SCE_IRQn, 1, 0, ENABLE); + } +#ifdef CAN2 + if (CAN2 == drv_can->CanHandle.Instance) + { + CAN_NVIC_Config(CAN2_SCE_IRQn, 1, 0, ENABLE); + } +#endif + } + break; + case RT_CAN_CMD_SET_FILTER: + if (RT_NULL == arg) + { + /* default filter config */ + setfilter(drv_can, &drv_can->FilterConfig); + } + else + { + filter_cfg = (struct rt_can_filter_config *)arg; + /* get default filter */ + for (int i = 0; i < filter_cfg->count; i++) + { + drv_can->FilterConfig.Filter_Num = filter_cfg->items[i].hdr; + drv_can->FilterConfig.Filter_HighId = (filter_cfg->items[i].id >> 13) & 0xFFFF; + drv_can->FilterConfig.Filter_LowId = ((filter_cfg->items[i].id << 3) | + (filter_cfg->items[i].ide << 2) | + (filter_cfg->items[i].rtr << 1)) & 0xFFFF; + drv_can->FilterConfig.FilterMask_HighId = (filter_cfg->items[i].mask >> 16) & 0xFFFF; + drv_can->FilterConfig.FilterMask_LowId = filter_cfg->items[i].mask & 0xFFFF; + drv_can->FilterConfig.Filter_Mode = filter_cfg->items[i].mode; + /* Filter conf */ + setfilter(drv_can, &drv_can->FilterConfig); + } + } + break; + case RT_CAN_CMD_SET_MODE: + argval = (rt_uint32_t) arg; + if (argval != RT_CAN_MODE_NORMAL && + argval != RT_CAN_MODE_LISEN && + argval != RT_CAN_MODE_LOOPBACK && + argval != RT_CAN_MODE_LOOPBACKANLISEN) + { + return -RT_ERROR; + } + if (argval != drv_can->device.config.mode) + { + drv_can->device.config.mode = argval; + return configure(&drv_can->device, &drv_can->device.config); + } + break; + case RT_CAN_CMD_SET_BAUD: + argval = (rt_uint32_t) arg; + if (argval != CAN1MBaud && + argval != CAN500kBaud && + argval != CAN250kBaud && + argval != CAN125kBaud && + argval != CAN100kBaud && + argval != CAN50kBaud && + argval != CAN20kBaud && + argval != CAN10kBaud) + { + return -RT_ERROR; + } + if (argval != drv_can->device.config.baud_rate) + { + drv_can->device.config.baud_rate = argval; + return configure(&drv_can->device, &drv_can->device.config); + } + break; + case RT_CAN_CMD_SET_PRIV: + argval = (rt_uint32_t) arg; + if (argval != RT_CAN_MODE_PRIV && + argval != RT_CAN_MODE_NOPRIV) + { + return -RT_ERROR; + } + if (argval != drv_can->device.config.privmode) + { + drv_can->device.config.privmode = argval; + return configure(&drv_can->device, &drv_can->device.config); + } + break; + case RT_CAN_CMD_GET_STATUS: + { + rt_uint32_t errtype; + errtype = drv_can->CanHandle.Instance->ESTS; + drv_can->device.status.rcverrcnt = errtype >> 24; + drv_can->device.status.snderrcnt = (errtype >> 16 & 0xFF); + drv_can->device.status.lasterrtype = errtype & 0x70; + drv_can->device.status.errcode = errtype & 0x07; + + rt_memcpy(arg, &drv_can->device.status, sizeof(drv_can->device.status)); + } + break; + } + + return RT_EOK; +} + +static int sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno) +{ + CAN_Module *pbxcan; + CanTxMessage TxMessage; + struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; + int i; + + pbxcan = ((struct n32_can *) can->parent.user_data)->CanHandle.Instance; + + if(pmsg->ide) + { + TxMessage.ExtId = pmsg->id; + TxMessage.StdId = 0; + } + else + { + TxMessage.StdId = pmsg->id; + TxMessage.ExtId = 0; + } + + TxMessage.RTR = pmsg->rtr; + TxMessage.IDE = pmsg->ide; + TxMessage.DLC = pmsg->len; + for( i=0; idata[i]; + } + CAN_TransmitMessage(pbxcan, &TxMessage); + + return RT_EOK; +} + +static int recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno) +{ + struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; + int i; + + pmsg->ide = (rt_uint32_t) RxMessage.IDE; + if(RxMessage.IDE == 1) + pmsg->id = RxMessage.ExtId; + else + pmsg->id = RxMessage.StdId; + pmsg->len = RxMessage.DLC; + pmsg->rtr = RxMessage.RTR; + pmsg->hdr = 0; + for(i= 0;i< RxMessage.DLC; i++) + { + pmsg->data[i] = RxMessage.Data[i]; + } + + + return RT_EOK; +} + +static const struct rt_can_ops canops = +{ + configure, + control, + sendmsg, + recvmsg, +}; + +#ifdef BSP_USING_CAN1 + +struct rt_can_device bxcan1; + +void n32_can1_irqhandler(void *param) +{ + CAN_Module* CANx; + + CANx = CAN1; + + /* receive data interrupt */ + if (CAN_GetIntStatus(CANx, CAN_INT_FMP0)) + { + CAN_ReceiveMessage(CANx, CAN_FIFO0, &RxMessage); + rt_hw_can_isr(&drv_can1.device, RT_CAN_EVENT_RX_IND); + CAN_ClearINTPendingBit(CANx, CAN_INT_FMP0); + rt_kprintf("\r\nCan1 int RX happened!\r\n"); + } + /* send data interrupt */ + else if (CAN_GetFlagSTS(CANx, CAN_FLAG_RQCPM0)) + { + rt_hw_can_isr(&drv_can1.device, RT_CAN_EVENT_TX_DONE | 0 << 8); + CAN_ClearFlag(CANx, CAN_FLAG_RQCPM0); + } + /* data overflow interrupt */ + else if (CAN_GetIntStatus(CANx, CAN_INT_FOV0)) + { + rt_hw_can_isr(&drv_can1.device, RT_CAN_EVENT_RXOF_IND); + rt_kprintf("\r\nCan1 int RX OF happened!\r\n"); + } +} + +void USB_HP_CAN1_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + n32_can1_irqhandler(&drv_can1.device); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +void USB_LP_CAN1_RX0_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + n32_can1_irqhandler(&drv_can1.device); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +#endif /*BSP_USING_CAN1*/ + +#ifdef BSP_USING_CAN2 +struct rt_can_device bxcan2; +void n32_can2_irqhandler(void *param) +{ + CAN_Module* CANx; + + CANx = CAN2; + + /* receive data interrupt */ + if (CAN_GetIntStatus(CANx, CAN_INT_FMP0)) + { + CAN_ReceiveMessage(CANx, CAN_FIFO0, &RxMessage); + rt_hw_can_isr(&drv_can2.device, RT_CAN_EVENT_RX_IND); + CAN_ClearINTPendingBit(CANx, CAN_INT_FMP0); + rt_kprintf("\r\nCan2 int RX happened!\r\n"); + } + /* send data interrupt */ + else if (CAN_GetFlagSTS(CANx, CAN_FLAG_RQCPM0)) + { + rt_hw_can_isr(&drv_can2.device, RT_CAN_EVENT_TX_DONE | 0 << 8); + CAN_ClearFlag(CANx, CAN_FLAG_RQCPM0); + } + /* data overflow interrupt */ + else if (CAN_GetIntStatus(CANx, CAN_INT_FOV0)) + { + rt_hw_can_isr(&drv_can2.device, RT_CAN_EVENT_RXOF_IND); + rt_kprintf("\r\nCan2 int RX OF happened!\r\n"); + } +} + +void CAN2_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + n32_can2_irqhandler(&drv_can2.device); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +void CAN2_RX0_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + n32_can2_irqhandler(&drv_can2.device); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +#endif /*BSP_USING_CAN2*/ + +#define CANCONFIG \ +{\ + CAN500kBaud,\ + RT_CANMSG_BOX_SZ,\ + RT_CANSND_BOX_NUM,\ + RT_CAN_MODE_LOOPBACK,\ +}; + +int rt_hw_can_init(void) +{ + struct can_configure config = CANCONFIG; + config.privmode = RT_CAN_MODE_NOPRIV; + config.ticks = 50; +#ifdef RT_CAN_USING_HDR + config.maxhdr = 14; +#ifdef CAN2 + config.maxhdr = 28; +#endif +#endif + /* config default filter */ + CAN_FilterInitType filterConf = {0}; + filterConf.Filter_HighId = 0x0000; + filterConf.Filter_LowId = 0x0000; + filterConf.FilterMask_HighId = 0x0000; + filterConf.FilterMask_LowId = 0x0000; + filterConf.Filter_FIFOAssignment = CAN_FIFO0; + filterConf.Filter_Num = CAN_FILTERNUM0; + filterConf.Filter_Mode = CAN_Filter_IdMaskMode; + filterConf.Filter_Scale = CAN_Filter_32bitScale; + filterConf.Filter_Act = ENABLE; + +#ifdef BSP_USING_CAN1 + filterConf.Filter_Num = 0; + + drv_can1.FilterConfig = filterConf; + drv_can1.device.config = config; + /* register CAN1 device */ + rt_hw_can_register(&drv_can1.device, + drv_can1.name, + &canops, + &drv_can1); +#endif /* BSP_USING_CAN1 */ + +#ifdef BSP_USING_CAN2 + filterConf.Filter_Num = 0; + + drv_can2.FilterConfig = filterConf; + drv_can2.device.config = config; + /* register CAN2 device */ + rt_hw_can_register(&drv_can2.device, + drv_can2.name, + &canops, + &drv_can2); +#endif /* BSP_USING_CAN2 */ + + return 0; +} + +INIT_BOARD_EXPORT(rt_hw_can_init); + +#endif /* defined(BSP_USING_CAN1) || defined(BSP_USING_CAN2) */ +#endif /*RT_USING_CAN*/ diff --git a/bsp/n32/libraries/n32_drivers/drv_can.h b/bsp/n32/libraries/n32_drivers/drv_can.h new file mode 100644 index 0000000000..bb435322ef --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_can.h @@ -0,0 +1,115 @@ +/***************************************************************************** + * 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 drv_can.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#ifndef __DRV_CAN_H__ +#define __DRV_CAN_H__ + +#include +#include +#include "n32g45x_can.h" + +#define CAN_BAUDRATE_1M ((uint32_t)1000) +#define CAN_BAUDRATE_500K ((uint32_t)500) +#define CAN_BAUDRATE_250K ((uint32_t)250) +#define CAN_BAUDRATE_125K ((uint32_t)125) +#define CAN_BAUDRATE_100K ((uint32_t)100) +#define CAN_BAUDRATE_50K ((uint32_t)50) +#define CAN_BAUDRATE_20K ((uint32_t)20) +#define CAN_BAUDRATE_10K ((uint32_t)10) +#define CAN_BTR_CALCULATE ((uint32_t)6000) + +#define CAN_TX_MAILBOX0 (0x00000001U) /*!< Tx Mailbox 0 */ +#define CAN_TX_MAILBOX1 (0x00000002U) /*!< Tx Mailbox 1 */ +#define CAN_TX_MAILBOX2 (0x00000004U) /*!< Tx Mailbox 2 */ + + +#define CAN_FILTERNUM0 ((uint8_t)0) + +/* attention !!! baud calculation example: Tclk / ((ss + bs1 + bs2) * brp) 36 / ((1 + 8 + 3) * 3) = 1MHz*/ + +/* Default config for serial_configure structure */ +#define RT_CAN_FILTER_CONFIG_DEFAULT \ +{ \ + BAUD_RATE_115200, /* 115200 bits/s */ \ + DATA_BITS_8, /* 8 databits */ \ + STOP_BITS_1, /* 1 stopbit */ \ + PARITY_NONE, /* No parity */ \ + HFC_CONTROL_NONE, /* No Hardwareflow control */ \ + TX_RX_MODE, /* Tx_Rx mode */ \ + RT_SERIAL_RB_BUFSZ, /* Buffer size */ \ + 0 \ +} + +struct n32_baud_rate_tab +{ + rt_uint32_t baud_rate; + rt_uint32_t config_data; +}; + +/** + * @brief CAN handle Structure definition + */ +typedef struct +{ + CAN_Module *Instance; /*!< Register base address */ + + CAN_InitType Init; /*!< CAN required parameters */ + + CanTxMessage* pTxMsg; /*!< Pointer to transmit structure */ + + CanRxMessage* pRxMsg; /*!< Pointer to reception structure for RX FIFO0 msg */ + + CanRxMessage* pRx1Msg; /*!< Pointer to reception structure for RX FIFO1 msg */ + + uint32_t State; /*!< CAN communication state */ + + FlagStatus Lock; /*!< CAN locking object */ + + uint32_t ErrorCode; /*!< CAN Error code */ + +}CAN_HandleTypeDef; + +/* n32 can device */ +struct n32_can +{ + char *name; + CAN_HandleTypeDef CanHandle; + CAN_FilterInitType FilterConfig; + struct rt_can_device device; /* inherit from can device */ +}; + +int rt_hw_can_init(void); + +#endif /* __DRV_CAN_H__ */ diff --git a/bsp/n32/libraries/n32_drivers/drv_dac.c b/bsp/n32/libraries/n32_drivers/drv_dac.c new file mode 100644 index 0000000000..1d2e50c914 --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_dac.c @@ -0,0 +1,180 @@ +/***************************************************************************** + * 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 drv_dac.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#include +#include "drv_dac.h" +#include "board.h" + +#ifdef RT_USING_DAC + +#if defined(BSP_USING_DAC1) || defined(BSP_USING_DAC2) + /* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable DAC */ + + +static struct n32_dac_config dac_config[] = +{ +#ifdef BSP_USING_DAC1 + { + "dac1", + DAC_CHANNEL_1, + }, +#endif + +#ifdef BSP_USING_DAC2 + { + "dac2", + DAC_CHANNEL_2, + }, +#endif +}; + + +static struct n32_dac dac_obj[sizeof(dac_config) / sizeof(dac_config[0])]; + +static void n32_dac_init(struct n32_dac_config *config) +{ + DAC_InitType DAC_InitStructure; + + /* DAC Periph clock enable */ + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_DAC, ENABLE); + /* DAC channel Configuration */ + DAC_InitStructure.Trigger = DAC_TRG_SOFTWARE; + DAC_InitStructure.WaveGen = DAC_WAVEGEN_NOISE; + DAC_InitStructure.LfsrUnMaskTriAmp = DAC_UNMASK_LFSRBIT0; + DAC_InitStructure.BufferOutput = DAC_BUFFOUTPUT_ENABLE; + DAC_Init(config->dac_periph, &DAC_InitStructure); +} + +static rt_err_t n32_dac_enabled(struct rt_dac_device *device, rt_uint32_t channel) +{ + RT_ASSERT(device != RT_NULL); + + DAC_Enable(channel, ENABLE); + + return RT_EOK; +} + +static rt_err_t n32_dac_disabled(struct rt_dac_device *device, rt_uint32_t channel) +{ + RT_ASSERT(device != RT_NULL); + + DAC_Enable(channel, DISABLE); + return RT_EOK; +} + + +static rt_err_t n32_set_dac_value(struct rt_dac_device *device, rt_uint32_t channel, rt_uint32_t *value) +{ + RT_ASSERT(device != RT_NULL); + rt_uint16_t set_value = 0; + set_value = (rt_uint16_t)*value; + + if(set_value > 4096) + { + set_value = 4096; + } + + /* Start DAC Channel conversion by software */ + if(channel == DAC_CHANNEL_1) + { + DAC_SetCh1Data(DAC_ALIGN_R_12BIT, set_value); + DAC_SoftTrgEnable(DAC_CHANNEL_1, ENABLE); + } + else + { + DAC_SetCh2Data(DAC_ALIGN_R_12BIT, set_value); + DAC_SoftTrgEnable(DAC_CHANNEL_2, ENABLE); + } + + return RT_EOK; +} + +static const struct rt_dac_ops n32_dac_ops = +{ + .disabled = n32_dac_disabled, + .enabled = n32_dac_enabled, + .convert = n32_set_dac_value, +}; + + +int rt_hw_dac_init(void) +{ + int result = RT_EOK; + /* save dac name */ + char name_buf[5] = {'d', 'a', 'c', '0', 0}; + int i = 0; + + for (i = 0; i < sizeof(dac_config) / sizeof(dac_config[0]); i++) + { + /* dac init */ + name_buf[3] = '0'; + dac_obj[i].config = &dac_config[i]; +#if defined(BSP_USING_DAC1) + if (dac_obj[i].config->dac_periph == DAC_CHANNEL_1) + { + name_buf[3] = '1'; + } + GPIOInit(GPIOA, GPIO_Mode_AIN, GPIO_Speed_50MHz, GPIO_PIN_4); +#endif +#if defined(BSP_USING_DAC2) + if (dac_obj[i].config->dac_periph == DAC_CHANNEL_2) + { + name_buf[3] = '2'; + } + GPIOInit(GPIOA, GPIO_Mode_AIN, GPIO_Speed_50MHz, GPIO_PIN_5); +#endif + + /* register dac device */ + for (i = 0; i < sizeof(dac_obj) / sizeof(dac_obj[0]); i++) + { + n32_dac_init(&dac_config[i]); + if (rt_hw_dac_register(&dac_obj[i].dac_device, name_buf, &n32_dac_ops, &dac_obj[i].config->dac_periph) == RT_EOK) + { + LOG_D("%s init success", name_buf); + } + else + { + LOG_E("%s register failed", name_buf); + result = -RT_ERROR; + } + } + } + + return result; +} +INIT_DEVICE_EXPORT(rt_hw_dac_init); + +#endif /* defined(BSP_USING_DAC1) || defined(BSP_USING_DAC2) */ +#endif /* RT_USING_DAC */ diff --git a/bsp/n32/libraries/n32_drivers/drv_dac.h b/bsp/n32/libraries/n32_drivers/drv_dac.h new file mode 100644 index 0000000000..c7c4cc267e --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_dac.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 drv_dac.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#ifndef __DRV_DAC__ +#define __DRV_DAC__ + +#include +#include +#include + +/* n32 config class */ +struct n32_dac_config +{ + const char *name; + rt_uint32_t dac_periph; +}; + +struct n32_dac +{ + struct rt_dac_device dac_device; + struct n32_dac_config *config; +}; + + +int rt_hw_dac_init(void); + +#endif diff --git a/bsp/n32/libraries/n32_drivers/drv_gpio.c b/bsp/n32/libraries/n32_drivers/drv_gpio.c new file mode 100644 index 0000000000..1b0ad232a1 --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_gpio.c @@ -0,0 +1,713 @@ +/***************************************************************************** + * 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 drv_gpio.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include +#include +#include "board.h" + +#ifdef RT_USING_PIN + +static const struct pin_index pins[] = +{ +#if defined(GPIOA) + __N32_PIN(0 , GPIOA, GPIO_PIN_0 ), + __N32_PIN(1 , GPIOA, GPIO_PIN_1 ), + __N32_PIN(2 , GPIOA, GPIO_PIN_2 ), + __N32_PIN(3 , GPIOA, GPIO_PIN_3 ), + __N32_PIN(4 , GPIOA, GPIO_PIN_4 ), + __N32_PIN(5 , GPIOA, GPIO_PIN_5 ), + __N32_PIN(6 , GPIOA, GPIO_PIN_6 ), + __N32_PIN(7 , GPIOA, GPIO_PIN_7 ), + __N32_PIN(8 , GPIOA, GPIO_PIN_8 ), + __N32_PIN(9 , GPIOA, GPIO_PIN_9 ), + __N32_PIN(10, GPIOA, GPIO_PIN_10), + __N32_PIN(11, GPIOA, GPIO_PIN_11), + __N32_PIN(12, GPIOA, GPIO_PIN_12), + __N32_PIN(13, GPIOA, GPIO_PIN_13), + __N32_PIN(14, GPIOA, GPIO_PIN_14), + __N32_PIN(15, GPIOA, GPIO_PIN_15), +#if defined(GPIOB) + __N32_PIN(16, GPIOB, GPIO_PIN_0), + __N32_PIN(17, GPIOB, GPIO_PIN_1), + __N32_PIN(18, GPIOB, GPIO_PIN_2), + __N32_PIN(19, GPIOB, GPIO_PIN_3), + __N32_PIN(20, GPIOB, GPIO_PIN_4), + __N32_PIN(21, GPIOB, GPIO_PIN_5), + __N32_PIN(22, GPIOB, GPIO_PIN_6), + __N32_PIN(23, GPIOB, GPIO_PIN_7), + __N32_PIN(24, GPIOB, GPIO_PIN_8), + __N32_PIN(25, GPIOB, GPIO_PIN_9), + __N32_PIN(26, GPIOB, GPIO_PIN_10), + __N32_PIN(27, GPIOB, GPIO_PIN_11), + __N32_PIN(28, GPIOB, GPIO_PIN_12), + __N32_PIN(29, GPIOB, GPIO_PIN_13), + __N32_PIN(30, GPIOB, GPIO_PIN_14), + __N32_PIN(31, GPIOB, GPIO_PIN_15), +#if defined(GPIOC) + __N32_PIN(32, GPIOC, GPIO_PIN_0), + __N32_PIN(33, GPIOC, GPIO_PIN_1), + __N32_PIN(34, GPIOC, GPIO_PIN_2), + __N32_PIN(35, GPIOC, GPIO_PIN_3), + __N32_PIN(36, GPIOC, GPIO_PIN_4), + __N32_PIN(37, GPIOC, GPIO_PIN_5), + __N32_PIN(38, GPIOC, GPIO_PIN_6), + __N32_PIN(39, GPIOC, GPIO_PIN_7), + __N32_PIN(40, GPIOC, GPIO_PIN_8), + __N32_PIN(41, GPIOC, GPIO_PIN_9), + __N32_PIN(42, GPIOC, GPIO_PIN_10), + __N32_PIN(43, GPIOC, GPIO_PIN_11), + __N32_PIN(44, GPIOC, GPIO_PIN_12), + __N32_PIN(45, GPIOC, GPIO_PIN_13), + __N32_PIN(46, GPIOC, GPIO_PIN_14), + __N32_PIN(47, GPIOC, GPIO_PIN_15), +#if defined(GPIOD) + __N32_PIN(48, GPIOD, GPIO_PIN_0), + __N32_PIN(49, GPIOD, GPIO_PIN_1), + __N32_PIN(50, GPIOD, GPIO_PIN_2), + __N32_PIN(51, GPIOD, GPIO_PIN_3), + __N32_PIN(52, GPIOD, GPIO_PIN_4), + __N32_PIN(53, GPIOD, GPIO_PIN_5), + __N32_PIN(54, GPIOD, GPIO_PIN_6), + __N32_PIN(55, GPIOD, GPIO_PIN_7), + __N32_PIN(56, GPIOD, GPIO_PIN_8), + __N32_PIN(57, GPIOD, GPIO_PIN_9), + __N32_PIN(58, GPIOD, GPIO_PIN_10), + __N32_PIN(59, GPIOD, GPIO_PIN_11), + __N32_PIN(60, GPIOD, GPIO_PIN_12), + __N32_PIN(61, GPIOD, GPIO_PIN_13), + __N32_PIN(62, GPIOD, GPIO_PIN_14), + __N32_PIN(63, GPIOD, GPIO_PIN_15), +#if defined(GPIOE) + __N32_PIN(64, GPIOE, GPIO_PIN_0), + __N32_PIN(65, GPIOE, GPIO_PIN_1), + __N32_PIN(66, GPIOE, GPIO_PIN_2), + __N32_PIN(67, GPIOE, GPIO_PIN_3), + __N32_PIN(68, GPIOE, GPIO_PIN_4), + __N32_PIN(69, GPIOE, GPIO_PIN_5), + __N32_PIN(70, GPIOE, GPIO_PIN_6), + __N32_PIN(71, GPIOE, GPIO_PIN_7), + __N32_PIN(72, GPIOE, GPIO_PIN_8), + __N32_PIN(73, GPIOE, GPIO_PIN_9), + __N32_PIN(74, GPIOE, GPIO_PIN_10), + __N32_PIN(75, GPIOE, GPIO_PIN_11), + __N32_PIN(76, GPIOE, GPIO_PIN_12), + __N32_PIN(77, GPIOE, GPIO_PIN_13), + __N32_PIN(78, GPIOE, GPIO_PIN_14), + __N32_PIN(79, GPIOE, GPIO_PIN_15), +#if defined(GPIOF) + __N32_PIN(80, GPIOF, GPIO_PIN_0), + __N32_PIN(81, GPIOF, GPIO_PIN_1), + __N32_PIN(82, GPIOF, GPIO_PIN_2), + __N32_PIN(83, GPIOF, GPIO_PIN_3), + __N32_PIN(84, GPIOF, GPIO_PIN_4), + __N32_PIN(85, GPIOF, GPIO_PIN_5), + __N32_PIN(86, GPIOF, GPIO_PIN_6), + __N32_PIN(87, GPIOF, GPIO_PIN_7), + __N32_PIN(88, GPIOF, GPIO_PIN_8), + __N32_PIN(89, GPIOF, GPIO_PIN_9), + __N32_PIN(90, GPIOF, GPIO_PIN_10), + __N32_PIN(91, GPIOF, GPIO_PIN_11), + __N32_PIN(92, GPIOF, GPIO_PIN_12), + __N32_PIN(93, GPIOF, GPIO_PIN_13), + __N32_PIN(94, GPIOF, GPIO_PIN_14), + __N32_PIN(95, GPIOF, GPIO_PIN_15), +#if defined(GPIOG) + __N32_PIN(96, GPIOG, GPIO_PIN_0), + __N32_PIN(97, GPIOG, GPIO_PIN_1), + __N32_PIN(98, GPIOG, GPIO_PIN_2), + __N32_PIN(99, GPIOG, GPIO_PIN_3), + __N32_PIN(100, GPIOG, GPIO_PIN_4), + __N32_PIN(101, GPIOG, GPIO_PIN_5), + __N32_PIN(102, GPIOG, GPIO_PIN_6), + __N32_PIN(103, GPIOG, GPIO_PIN_7), + __N32_PIN(104, GPIOG, GPIO_PIN_8), + __N32_PIN(105, GPIOG, GPIO_PIN_9), + __N32_PIN(106, GPIOG, GPIO_PIN_10), + __N32_PIN(107, GPIOG, GPIO_PIN_11), + __N32_PIN(108, GPIOG, GPIO_PIN_12), + __N32_PIN(109, GPIOG, GPIO_PIN_13), + __N32_PIN(110, GPIOG, GPIO_PIN_14), + __N32_PIN(111, GPIOG, GPIO_PIN_15), + +#endif /* defined(GPIOG) */ +#endif /* defined(GPIOF) */ +#endif /* defined(GPIOE) */ +#endif /* defined(GPIOD) */ +#endif /* defined(GPIOC) */ +#endif /* defined(GPIOB) */ +#endif /* defined(GPIOA) */ +}; + +static const struct pin_irq_map pin_irq_map[] = +{ + {GPIO_PIN_0, EXTI0_IRQn}, + {GPIO_PIN_1, EXTI1_IRQn}, + {GPIO_PIN_2, EXTI2_IRQn}, + {GPIO_PIN_3, EXTI3_IRQn}, + {GPIO_PIN_4, EXTI4_IRQn}, + {GPIO_PIN_5, EXTI9_5_IRQn}, + {GPIO_PIN_6, EXTI9_5_IRQn}, + {GPIO_PIN_7, EXTI9_5_IRQn}, + {GPIO_PIN_8, EXTI9_5_IRQn}, + {GPIO_PIN_9, EXTI9_5_IRQn}, + {GPIO_PIN_10, EXTI15_10_IRQn}, + {GPIO_PIN_11, EXTI15_10_IRQn}, + {GPIO_PIN_12, EXTI15_10_IRQn}, + {GPIO_PIN_13, EXTI15_10_IRQn}, + {GPIO_PIN_14, EXTI15_10_IRQn}, + {GPIO_PIN_15, EXTI15_10_IRQn}, +}; + +static struct rt_pin_irq_hdr pin_irq_hdr_tab[] = +{ + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, +}; +static uint32_t pin_irq_enable_mask=0; + +#define ITEM_NUM(items) sizeof(items) / sizeof(items[0]) +static const struct pin_index *get_pin(uint8_t pin) +{ + const struct pin_index *index; + + if (pin < ITEM_NUM(pins)) + { + index = &pins[pin]; + if (index->index == -1) + index = RT_NULL; + } + else + { + index = RT_NULL; + } + + return index; +}; + +static void n32_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) +{ + const struct pin_index *index; + + index = get_pin(pin); + if (index == RT_NULL) + { + return; + } + GPIO_WriteBit(index->gpio, index->pin, (Bit_OperateType)value); +} + +static int n32_pin_read(rt_device_t dev, rt_base_t pin) +{ + int value; + const struct pin_index *index; + + value = PIN_LOW; + + index = get_pin(pin); + if (index == RT_NULL) + { + return value; + } + + value = GPIO_ReadInputDataBit(index->gpio, index->pin); + + return value; +} + +static void n32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) +{ + const struct pin_index *index; + GPIO_InitType GPIO_InitStructure; + + index = get_pin(pin); + if (index == RT_NULL) + { + return; + } + + GPIO_InitStruct(&GPIO_InitStructure); + + /* Configure GPIO_InitStructure */ + GPIO_InitStructure.Pin = index->pin; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + + if (mode == PIN_MODE_OUTPUT) + { + /* output setting */ + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; + } + else if (mode == PIN_MODE_INPUT) + { + /* input setting: not pull. */ + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; + } + else if (mode == PIN_MODE_INPUT_PULLUP) + { + /* input setting: pull up. */ + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; + } + else if (mode == PIN_MODE_INPUT_PULLDOWN) + { + /* input setting: pull down. */ + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; + } + else if (mode == PIN_MODE_OUTPUT_OD) + { + /* output setting: od. */ + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; + } + GPIOInit(index->gpio, GPIO_InitStructure.GPIO_Mode, GPIO_InitStructure.GPIO_Speed, GPIO_InitStructure.Pin); +} + +rt_inline rt_int32_t bit2bitno(rt_uint32_t bit) +{ + int i; + for (i = 0; i < 32; i++) + { + if ((0x01 << i) == bit) + { + return i; + } + } + return -1; +} + +rt_inline rt_int32_t port2portsource(GPIO_Module* module) +{ + if(module == GPIOA) + { + return GPIOA_PORT_SOURCE; + } + else if(module == GPIOB) + { + return GPIOB_PORT_SOURCE; + } + else if(module == GPIOC) + { + return GPIOC_PORT_SOURCE; + } + else if(module == GPIOD) + { + return GPIOD_PORT_SOURCE; + } + else if(module == GPIOE) + { + return GPIOE_PORT_SOURCE; + } + else if(module == GPIOF) + { + return GPIOF_PORT_SOURCE; + } + else if(module == GPIOG) + { + return GPIOG_PORT_SOURCE; + } + else + { + return GPIOA_PORT_SOURCE; + } +} + +rt_inline const struct pin_irq_map *get_pin_irq_map(uint32_t pinbit) +{ + rt_int32_t mapindex = bit2bitno(pinbit); + if (mapindex < 0 || mapindex >= ITEM_NUM(pin_irq_map)) + { + return RT_NULL; + } + return &pin_irq_map[mapindex]; +}; + +static rt_err_t n32_pin_attach_irq(struct rt_device *device, rt_int32_t pin, + rt_uint32_t mode, void (*hdr)(void *args), void *args) +{ + const struct pin_index *index; + rt_base_t level; + rt_int32_t irqindex = -1; + + index = get_pin(pin); + if (index == RT_NULL) + { + return RT_ENOSYS; + } + irqindex = bit2bitno(index->pin); + if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) + { + return RT_ENOSYS; + } + + level = rt_hw_interrupt_disable(); + if (pin_irq_hdr_tab[irqindex].pin == pin && + pin_irq_hdr_tab[irqindex].hdr == hdr && + pin_irq_hdr_tab[irqindex].mode == mode && + pin_irq_hdr_tab[irqindex].args == args) + { + rt_hw_interrupt_enable(level); + return RT_EOK; + } + if (pin_irq_hdr_tab[irqindex].pin != -1) + { + rt_hw_interrupt_enable(level); + return RT_EBUSY; + } + pin_irq_hdr_tab[irqindex].pin = pin; + pin_irq_hdr_tab[irqindex].hdr = hdr; + pin_irq_hdr_tab[irqindex].mode = mode; + pin_irq_hdr_tab[irqindex].args = args; + rt_hw_interrupt_enable(level); + + return RT_EOK; +} + +static rt_err_t n32_pin_dettach_irq(struct rt_device *device, rt_int32_t pin) +{ + const struct pin_index *index; + rt_base_t level; + rt_int32_t irqindex = -1; + + index = get_pin(pin); + if (index == RT_NULL) + { + return RT_ENOSYS; + } + irqindex = bit2bitno(index->pin); + if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) + { + return RT_ENOSYS; + } + + level = rt_hw_interrupt_disable(); + if (pin_irq_hdr_tab[irqindex].pin == -1) + { + rt_hw_interrupt_enable(level); + return RT_EOK; + } + pin_irq_hdr_tab[irqindex].pin = -1; + pin_irq_hdr_tab[irqindex].hdr = RT_NULL; + pin_irq_hdr_tab[irqindex].mode = 0; + pin_irq_hdr_tab[irqindex].args = RT_NULL; + rt_hw_interrupt_enable(level); + + return RT_EOK; +} + +static rt_err_t n32_pin_irq_enable(struct rt_device *device, rt_base_t pin, + rt_uint32_t enabled) +{ + const struct pin_index *index; + const struct pin_irq_map *irqmap; + rt_base_t level; + rt_int32_t irqindex = -1; + GPIO_InitType GPIO_InitStructure; + EXTI_InitType EXTI_InitStructure; + + index = get_pin(pin); + if (index == RT_NULL) + { + return RT_ENOSYS; + } + + if (enabled == PIN_IRQ_ENABLE) + { + irqindex = bit2bitno(index->pin); + if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) + { + return RT_ENOSYS; + } + + level = rt_hw_interrupt_disable(); + + if (pin_irq_hdr_tab[irqindex].pin == -1) + { + rt_hw_interrupt_enable(level); + return RT_ENOSYS; + } + + irqmap = &pin_irq_map[irqindex]; + + /* Configure GPIO_InitStructure */ + GPIO_InitStruct(&GPIO_InitStructure); + GPIO_InitStructure.Pin = index->pin; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + switch (pin_irq_hdr_tab[irqindex].mode) + { + case PIN_IRQ_MODE_RISING: + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; + EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; + break; + case PIN_IRQ_MODE_FALLING: + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; + EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; + break; + case PIN_IRQ_MODE_RISING_FALLING: + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; + EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; + break; + } + GPIO_InitPeripheral(index->gpio, &GPIO_InitStructure); + + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + /* configure EXTI line */ + GPIO_ConfigEXTILine(port2portsource(index->gpio), irqindex); + + /*Configure key EXTI line*/ + EXTI_InitStructure.EXTI_Line = index->pin; + EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; + EXTI_InitStructure.EXTI_LineCmd = ENABLE; + EXTI_InitPeripheral(&EXTI_InitStructure); + + EXTI_ClrITPendBit(index->pin); + NVIC_SetPriority(irqmap->irqno, 5); + NVIC_EnableIRQ(irqmap->irqno); + pin_irq_enable_mask |= irqmap->pinbit; + + rt_hw_interrupt_enable(level); + } + else if (enabled == PIN_IRQ_DISABLE) + { + irqmap = get_pin_irq_map(index->pin); + if (irqmap == RT_NULL) + { + return RT_ENOSYS; + } + + level = rt_hw_interrupt_disable(); + + pin_irq_enable_mask &= ~irqmap->pinbit; + if (( irqmap->pinbit>=GPIO_PIN_5 )&&( irqmap->pinbit<=GPIO_PIN_9 )) + { + if(!(pin_irq_enable_mask&(GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9))) + { + NVIC_DisableIRQ(irqmap->irqno); + } + } + else if (( irqmap->pinbit>=GPIO_PIN_10 )&&( irqmap->pinbit<=GPIO_PIN_15 )) + { + if(!(pin_irq_enable_mask&(GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15))) + { + NVIC_DisableIRQ(irqmap->irqno); + } + } + else + { + NVIC_DisableIRQ(irqmap->irqno); + } + + rt_hw_interrupt_enable(level); + } + else + { + return -RT_ENOSYS; + } + + return RT_EOK; +} +const static struct rt_pin_ops _n32_pin_ops = +{ + n32_pin_mode, + n32_pin_write, + n32_pin_read, + n32_pin_attach_irq, + n32_pin_dettach_irq, + n32_pin_irq_enable, +}; + +int rt_hw_pin_init(void) +{ +#if defined(RCC_GPIOA_CLK_ENABLE) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); +#endif + +#if defined(RCC_GPIOB_CLK_ENABLE) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); +#endif + +#if defined(RCC_GPIOC_CLK_ENABLE) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); +#endif + +#if defined(RCC_GPIOD_CLK_ENABLE) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE); +#endif + +#if defined(RCC_GPIOE_CLK_ENABLE) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE); +#endif + +#if defined(RCC_GPIOF_CLK_ENABLE) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOF, ENABLE); +#endif + +#if defined(RCC_GPIOG_CLK_ENABLE) + __RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOG, ENABLE); +#endif + + return rt_device_pin_register("pin", &_n32_pin_ops, RT_NULL); +} + +INIT_BOARD_EXPORT(rt_hw_pin_init); + +rt_inline void pin_irq_hdr(int irqno) +{ + if (pin_irq_hdr_tab[irqno].hdr) + { + pin_irq_hdr_tab[irqno].hdr(pin_irq_hdr_tab[irqno].args); + } +} + +void N32_GPIO_EXTI_IRQHandler(rt_int8_t exti_line) +{ + if(RESET != EXTI_GetITStatus(1 << exti_line)) + { + pin_irq_hdr(exti_line); + EXTI_ClrITPendBit(1 << exti_line); + } +} + +void EXTI0_IRQHandler(void) +{ + rt_interrupt_enter(); + N32_GPIO_EXTI_IRQHandler(0); + rt_interrupt_leave(); +} +void EXTI1_IRQHandler(void) +{ + rt_interrupt_enter(); + N32_GPIO_EXTI_IRQHandler(1); + rt_interrupt_leave(); +} +void EXTI2_IRQHandler(void) +{ + rt_interrupt_enter(); + N32_GPIO_EXTI_IRQHandler(2); + rt_interrupt_leave(); +} +void EXTI3_IRQHandler(void) +{ + rt_interrupt_enter(); + N32_GPIO_EXTI_IRQHandler(3); + rt_interrupt_leave(); +} +void EXTI4_IRQHandler(void) +{ + rt_interrupt_enter(); + N32_GPIO_EXTI_IRQHandler(4); + rt_interrupt_leave(); +} +void EXTI9_5_IRQHandler(void) +{ + rt_interrupt_enter(); + N32_GPIO_EXTI_IRQHandler(5); + N32_GPIO_EXTI_IRQHandler(6); + N32_GPIO_EXTI_IRQHandler(7); + N32_GPIO_EXTI_IRQHandler(8); + N32_GPIO_EXTI_IRQHandler(9); + rt_interrupt_leave(); +} +void EXTI15_10_IRQHandler(void) +{ + rt_interrupt_enter(); + N32_GPIO_EXTI_IRQHandler(10); + N32_GPIO_EXTI_IRQHandler(11); + N32_GPIO_EXTI_IRQHandler(12); + N32_GPIO_EXTI_IRQHandler(13); + N32_GPIO_EXTI_IRQHandler(14); + N32_GPIO_EXTI_IRQHandler(15); + rt_interrupt_leave(); +} + +void GPIOInit(GPIO_Module* GPIOx, GPIO_ModeType mode, GPIO_SpeedType speed, uint16_t Pin) +{ + GPIO_InitType GPIO_InitStructure; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + /* Enable the GPIO Clock */ + if (GPIOx == GPIOA) + { + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); + } + else if (GPIOx == GPIOB) + { + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); + } + else if (GPIOx == GPIOC) + { + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); + } + else if (GPIOx == GPIOD) + { + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE); + } + else if (GPIOx == GPIOE) + { + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE); + } + else if (GPIOx == GPIOF) + { + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOF, ENABLE); + } + else + { + if (GPIOx == GPIOG) + { + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOG, ENABLE); + } + } + + /* Configure the GPIO pin */ + GPIO_InitStructure.Pin = Pin; + GPIO_InitStructure.GPIO_Mode = mode; + GPIO_InitStructure.GPIO_Speed = speed; + GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure); + +} + + +#endif /* RT_USING_PIN */ diff --git a/bsp/n32/libraries/n32_drivers/drv_gpio.h b/bsp/n32/libraries/n32_drivers/drv_gpio.h new file mode 100644 index 0000000000..53bd26f908 --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_gpio.h @@ -0,0 +1,73 @@ +/***************************************************************************** + * 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 drv_gpio.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#ifndef __DRV_GPIO_H__ +#define __DRV_GPIO_H__ + +#include "n32g45x.h" + +#define __N32_PORT(port) GPIO##port##_BASE + +#define GET_PIN(PORTx,PIN) (rt_base_t)((16 * ( ((rt_base_t)__N32_PORT(PORTx) - (rt_base_t)GPIOA_BASE)/(0x0400UL) )) + PIN) + +#define __N32_PIN(index, gpio, gpio_pin) \ + { \ + index, gpio, gpio_pin \ + } + +#define __N32_PIN_RESERVE \ + { \ + -1, 0, 0 \ + } + +/* GPIO driver */ +struct pin_index +{ + int index; + GPIO_Module *gpio; + uint32_t pin; +}; + +struct pin_irq_map +{ + uint16_t pinbit; + IRQn_Type irqno; +}; + +void GPIOInit(GPIO_Module* GPIOx, GPIO_ModeType mode, GPIO_SpeedType speed, uint16_t Pin); +int rt_hw_pin_init(void); + +#endif /* __DRV_GPIO_H__ */ + diff --git a/bsp/n32/libraries/n32_drivers/drv_hwtimer.c b/bsp/n32/libraries/n32_drivers/drv_hwtimer.c new file mode 100644 index 0000000000..e02b942595 --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_hwtimer.c @@ -0,0 +1,583 @@ +/***************************************************************************** + * 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 drv_hwtimer.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#include "drv_hwtimer.h" + +#ifdef RT_USING_HWTIMER + +#if defined(BSP_USING_HWTIMER1) || defined(BSP_USING_HWTIMER2) || defined(BSP_USING_HWTIMER3) \ + || defined(BSP_USING_HWTIMER4) || defined(BSP_USING_HWTIMER5) || defined(BSP_USING_HWTIMER6) \ + || defined(BSP_USING_HWTIMER7) || defined(BSP_USING_HWTIMER8) + /* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable HWTIMER */ + +static struct n32_hwtimer_config hwtimer_config[] = +{ +#ifdef BSP_USING_HWTIMER1 + { + "timer1", + TIM1, + TIM1_UP_IRQn, + }, +#endif +#ifdef BSP_USING_HWTIMER2 + { + "timer2", + TIM2, + TIM2_IRQn, + }, +#endif +#ifdef BSP_USING_HWTIMER3 + { + "timer3", + TIM3, + TIM3_IRQn, + }, +#endif +#ifdef BSP_USING_HWTIMER4 + { + "timer4", + TIM4, + TIM4_IRQn, + }, +#endif +#ifdef BSP_USING_HWTIMER5 + { + "timer5", + TIM5, + TIM5_IRQn, + }, +#endif +#ifdef BSP_USING_HWTIMER6 + { + "timer6", + TIM6, + TIM6_IRQn, + }, +#endif +#ifdef BSP_USING_HWTIMER7 + { + "timer7", + TIM7, + TIM7_IRQn, + }, +#endif +#ifdef BSP_USING_HWTIMER8 + { + "timer8", + TIM8, + TIM8_UP_IRQn, + }, +#endif +}; +uint8_t tim1_count = 0, tim2_count = 0, tim3_count = 0, tim4_count = 0,tim5_count = 0, tim6_count = 0, tim7_count = 0, tim8_count = 0; +static void caculate_tim_count() +{ + uint8_t count = 0; +#ifdef BSP_USING_HWTIMER1 + tim1_count = count; + count++; +#endif +#ifdef BSP_USING_HWTIMER2 + tim2_count = count; + count++; +#endif +#ifdef BSP_USING_HWTIMER3 + tim3_count = count; + count++; +#endif +#ifdef BSP_USING_HWTIMER4 + tim4_count = count; + count++; +#endif +#ifdef BSP_USING_HWTIMER5 + tim5_count = count; + count++; +#endif +#ifdef BSP_USING_HWTIMER6 + tim6_count = count; + count++; +#endif +#ifdef BSP_USING_HWTIMER7 + tim7_count = count; + count++; +#endif +#ifdef BSP_USING_HWTIMER8 + tim8_count = count; + count++; +#endif +} + +#define BITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end)))) +#define GET_BITS(regval, start, end) (((regval) & BITS((start),(end))) >> (start)) + +static struct n32_hwtimer hwtimer_obj[sizeof(hwtimer_config) / sizeof(hwtimer_config[0])] = {0}; + +static rt_err_t n32_hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args) +{ + rt_err_t err = RT_EOK; + struct n32_hwtimer_config *config; + RCC_ClocksType RCC_ClockFreq; + RT_ASSERT(timer != RT_NULL); + + config = (struct n32_hwtimer_config *)timer->parent.user_data; + + RCC_GetClocksFreqValue(&RCC_ClockFreq); + + switch (cmd) + { + case HWTIMER_CTRL_FREQ_SET: + { + uint32_t clk; + uint8_t clkpre; + uint32_t pre; + if (config->timer_periph != TIM1 && config->timer_periph != TIM8) + { + clk = RCC_ClockFreq.Pclk1Freq; + clkpre = GET_BITS(RCC->CFG, 8, 10); + } + else + { + clk = RCC_ClockFreq.Pclk2Freq; + clkpre = GET_BITS(RCC->CFG, 11, 13); + } + if (clkpre >= 4) + { + clk = clk * 2; + } + pre = (clk / * ((uint32_t *)args)) - 1; + TIM_ConfigPrescaler(config->timer_periph, pre, TIM_PSC_RELOAD_MODE_IMMEDIATE); + config->timer_periph->EVTGEN |= TIM_EVTGEN_UDGN; + } + break; + case HWTIMER_CTRL_STOP: + TIM_Enable(config->timer_periph, DISABLE); + break; + default: + err = -RT_ENOSYS; + break; + } + return err; +} + +static rt_uint32_t n32_hwtimer_count_get(rt_hwtimer_t *timer) +{ + rt_uint32_t CurrentTimer_Count; + struct n32_hwtimer_config *config; + RT_ASSERT(timer != RT_NULL); + + config = (struct n32_hwtimer_config *)timer->parent.user_data; + + CurrentTimer_Count = TIM_GetCnt(config->timer_periph); + + return CurrentTimer_Count; +} + +/** + * @brief Configures the NVIC for TIM. + */ +void TIM_NVIC_Config(IRQn_Type IRQn, uint8_t PreemptionPriority, uint8_t SubPriority,FunctionalState cmd) +{ + NVIC_InitType NVIC_InitStructure; + + NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); + + NVIC_InitStructure.NVIC_IRQChannel = IRQn; + NVIC_InitStructure.NVIC_IRQChannelCmd = cmd; + if(cmd) + { + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PreemptionPriority; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = SubPriority; + } + NVIC_Init(&NVIC_InitStructure); +} + + +static void n32_hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state) +{ + struct n32_hwtimer_config *config; + TIM_TimeBaseInitType TIM_TimeBaseStructure; + RCC_ClocksType RCC_ClockFreq; + RT_ASSERT(timer != RT_NULL); + config = (struct n32_hwtimer_config *)timer->parent.user_data; + + if (state == 1) + { + uint32_t clk; + uint8_t clkpre; + uint32_t pre; + + RCC_GetClocksFreqValue(&RCC_ClockFreq); + TIM_DeInit(config->timer_periph); + + if (config->timer_periph != TIM1 && config->timer_periph != TIM8) + { + clk = RCC_ClockFreq.Pclk1Freq; + clkpre = GET_BITS(RCC->CFG, 8, 10); + } + else + { + clk = RCC_ClockFreq.Pclk2Freq; + clkpre = GET_BITS(RCC->CFG, 11, 13); + } + if (clkpre >= 4) + { + clk = clk * 2; + } + pre = (clk / 10000) - 1; + + /* Time Base configuration */ + TIM_TimeBaseStructure.Prescaler = pre; + TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP; + TIM_TimeBaseStructure.Period = 10000 - 1; + TIM_TimeBaseStructure.ClkDiv = TIM_CLK_DIV1; + TIM_TimeBaseStructure.RepetCnt = 0; + + if (timer->info->cntmode == HWTIMER_CNTMODE_UP) + { + TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP; + } + else + { + TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_DOWN; + } + TIM_InitTimeBase(config->timer_periph, &TIM_TimeBaseStructure); + /* set the TIMx priority */ + TIM_NVIC_Config(config->irqn, 3, 0, ENABLE); + /* clear update flag */ + TIM_ClearFlag(config->timer_periph, TIM_FLAG_UPDATE); + } + else + { + TIM_Enable(config->timer_periph, DISABLE); + TIM_ConfigInt(config->timer_periph, TIM_INT_UPDATE, ENABLE); + TIM_NVIC_Config(config->irqn, 3, 0, DISABLE); + } +} + +static rt_err_t n32_hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode) +{ + struct n32_hwtimer_config *config; + RT_ASSERT(timer != RT_NULL); + config = (struct n32_hwtimer_config *)timer->parent.user_data; + + /* set tim cnt */ + TIM_SetCnt(config->timer_periph, 0); + /* set tim arr */ + TIM_SetAutoReload(config->timer_periph, cnt - 1); + + if (mode == HWTIMER_MODE_ONESHOT) + { + TIM_SelectOnePulseMode(config->timer_periph, TIM_OPMODE_SINGLE); + } + else + { + TIM_SelectOnePulseMode(config->timer_periph, TIM_OPMODE_REPET); + } + + /* start timer */ + TIM_ConfigInt(config->timer_periph, TIM_INT_UPDATE, ENABLE); + /* TIM counter enable */ + TIM_Enable(config->timer_periph, ENABLE); + + TIM_NVIC_Config(config->irqn, 3, 0, ENABLE); + + return RT_EOK; +} + +static void n32_hwtimer_stop(rt_hwtimer_t *timer) +{ + struct n32_hwtimer_config *config; + RT_ASSERT(timer != RT_NULL); + config = (struct n32_hwtimer_config *)timer->parent.user_data; + + TIM_Enable(config->timer_periph, DISABLE); + + TIM_NVIC_Config(config->irqn, 3, 0, DISABLE); +} + +static const struct rt_hwtimer_ops n32_hwtimer_ops = +{ + .init = n32_hwtimer_init, + .start = n32_hwtimer_start, + .stop = n32_hwtimer_stop, + .count_get = n32_hwtimer_count_get, + .control = n32_hwtimer_control, +}; + +static const struct rt_hwtimer_info n32_hwtimer_info = +{ + 1000000, /* the maximum count frequency can be set */ + 2000, /* the minimum count frequency can be set */ + 0xFFFF, + HWTIMER_CNTMODE_UP, +}; + +/** + * @brief This function handles TIM interrupts requests. + * @param htim TIM handle + * @retval None + */ +void TIM_IRQHandler(TIM_Module* timer_periph) +{ + /* Capture compare 1 event */ + if(TIM_GetFlagStatus(timer_periph, TIM_FLAG_CC1) != RESET) + { + if(TIM_GetIntStatus(timer_periph, TIM_INT_CC1) !=RESET) + { + { + TIM_ClrIntPendingBit(timer_periph, TIM_INT_CC1); + } + } + } + /* Capture compare 2 event */ + if(TIM_GetFlagStatus(timer_periph, TIM_FLAG_CC2) != RESET) + { + if(TIM_GetIntStatus(timer_periph, TIM_INT_CC2) !=RESET) + { + TIM_ClrIntPendingBit(timer_periph, TIM_INT_CC2); + } + } + /* Capture compare 3 event */ + if(TIM_GetFlagStatus(timer_periph, TIM_FLAG_CC3) != RESET) + { + if(TIM_GetIntStatus(timer_periph, TIM_INT_CC3) !=RESET) + { + TIM_ClrIntPendingBit(timer_periph, TIM_INT_CC3); + } + } + /* Capture compare 4 event */ + if(TIM_GetFlagStatus(timer_periph, TIM_FLAG_CC4) != RESET) + { + if(TIM_GetIntStatus(timer_periph, TIM_INT_CC4) !=RESET) + { + TIM_ClrIntPendingBit(timer_periph, TIM_INT_CC4); + } + } + /* TIM Update event */ + if(TIM_GetFlagStatus(timer_periph, TIM_FLAG_UPDATE) != RESET) + { + if(TIM_GetIntStatus(timer_periph, TIM_INT_UPDATE) !=RESET) + { + TIM_ClrIntPendingBit(timer_periph, TIM_INT_UPDATE); + } + } + /* TIM Break input event */ + if(TIM_GetFlagStatus(timer_periph, TIM_FLAG_BREAK) != RESET) + { + if(TIM_GetIntStatus(timer_periph, TIM_INT_BREAK) !=RESET) + { + TIM_ClrIntPendingBit(timer_periph, TIM_INT_BREAK); + } + } + /* TIM Trigger detection event */ + if(TIM_GetFlagStatus(timer_periph, TIM_FLAG_TRIG) != RESET) + { + if(TIM_GetIntStatus(timer_periph, TIM_INT_TRIG) !=RESET) + { + TIM_ClrIntPendingBit(timer_periph, TIM_INT_TRIG); + } + } + /* TIM commutation event */ + if(TIM_GetFlagStatus(timer_periph, TIM_FLAG_COM) != RESET) + { + if(TIM_GetIntStatus(timer_periph, TIM_INT_COM) !=RESET) + { + TIM_ClrIntPendingBit(timer_periph, TIM_INT_COM); + } + } +} + +#ifdef BSP_USING_HWTIMER1 + +void TIM1_UP_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); +// TIM_IRQHandler(hwtimer_obj[0].config->timer_periph); + + TIM_ClrIntPendingBit(hwtimer_obj[tim1_count].config->timer_periph, TIM_INT_UPDATE); + rt_device_hwtimer_isr(&hwtimer_obj[tim1_count].time_device); + /* leave interrupt */ + rt_interrupt_leave(); +} + +#endif + +#ifdef BSP_USING_HWTIMER2 + +void TIM2_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + TIM_ClrIntPendingBit(hwtimer_obj[tim2_count].config->timer_periph, TIM_INT_UPDATE); + rt_device_hwtimer_isr(&hwtimer_obj[tim2_count].time_device); + /* leave interrupt */ + rt_interrupt_leave(); +} + +#endif + +#ifdef BSP_USING_HWTIMER3 + +void TIM3_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + TIM_ClrIntPendingBit(hwtimer_obj[tim3_count].config->timer_periph, TIM_INT_UPDATE); + rt_device_hwtimer_isr(&hwtimer_obj[tim3_count].time_device); + /* leave interrupt */ + rt_interrupt_leave(); +} + +#endif + +#ifdef BSP_USING_HWTIMER4 + +void TIM4_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + TIM_ClrIntPendingBit(hwtimer_obj[tim4_count].config->timer_periph, TIM_INT_UPDATE); + rt_device_hwtimer_isr(&hwtimer_obj[tim4_count].time_device); + /* leave interrupt */ + rt_interrupt_leave(); +} + +#endif + +#ifdef BSP_USING_HWTIMER5 + +void TIM5_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + TIM_ClrIntPendingBit(hwtimer_obj[tim5_count].config->timer_periph, TIM_INT_UPDATE); + rt_device_hwtimer_isr(&hwtimer_obj[tim5_count].time_device); + /* leave interrupt */ + rt_interrupt_leave(); +} + +#endif + +#ifdef BSP_USING_HWTIMER6 + +void TIM6_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + TIM_ClrIntPendingBit(hwtimer_obj[tim6_count].config->timer_periph, TIM_INT_UPDATE); + rt_device_hwtimer_isr(&hwtimer_obj[tim6_count].time_device); + /* leave interrupt */ + rt_interrupt_leave(); +} + +#endif + +#ifdef BSP_USING_HWTIMER7 + +void TIM7_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + TIM_ClrIntPendingBit(hwtimer_obj[tim7_count].config->timer_periph, TIM_INT_UPDATE); + rt_device_hwtimer_isr(&hwtimer_obj[tim7_count].time_device); + /* leave interrupt */ + rt_interrupt_leave(); +} + +#endif + +#ifdef BSP_USING_HWTIMER8 + +void TIM8_UP_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + TIM_ClrIntPendingBit(hwtimer_obj[tim8_count].config->timer_periph, TIM_INT_UPDATE); + rt_device_hwtimer_isr(&hwtimer_obj[tim8_count].time_device); + /* leave interrupt */ + rt_interrupt_leave(); +} + +#endif + +int rt_hwtimer_init(void) +{ + int i = 0; + int result = RT_EOK; + +#ifdef BSP_USING_HWTIMER1 + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_TIM1, ENABLE); +#endif +#ifdef BSP_USING_HWTIMER2 + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM2, ENABLE); +#endif +#ifdef BSP_USING_HWTIMER3 + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM3, ENABLE); +#endif +#ifdef BSP_USING_HWTIMER4 + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM4, ENABLE); +#endif +#ifdef BSP_USING_HWTIMER5 + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM5, ENABLE); +#endif +#ifdef BSP_USING_HWTIMER6 + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM6, ENABLE); +#endif +#ifdef BSP_USING_HWTIMER7 + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM7, ENABLE); +#endif +#ifdef BSP_USING_HWTIMER8 + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_TIM8, ENABLE); +#endif + + caculate_tim_count(); + for (i = 0; i < sizeof(hwtimer_obj) / sizeof(hwtimer_obj[0]); i++) + { + hwtimer_obj[i].time_device.info = &n32_hwtimer_info; + hwtimer_obj[i].time_device.ops = &n32_hwtimer_ops; + hwtimer_obj[i].config = &hwtimer_config[i]; + rt_device_hwtimer_register(&hwtimer_obj[i].time_device, \ + hwtimer_obj[i].config->name, hwtimer_obj[i].config); + } + + return result; + +} + +INIT_DEVICE_EXPORT(rt_hwtimer_init); + +#endif /* defined(BSP_USING_HWTIMERx) */ +#endif /* RT_USING_HWTIMER */ diff --git a/bsp/n32/libraries/n32_drivers/drv_hwtimer.h b/bsp/n32/libraries/n32_drivers/drv_hwtimer.h new file mode 100644 index 0000000000..07eec64a96 --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_hwtimer.h @@ -0,0 +1,60 @@ +/***************************************************************************** + * 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 drv_hwtimer.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#ifndef __DRV_HWTIMER__ +#define __DRV_HWTIMER__ + +#include +#include +#include +#include "n32g45x.h" + +/* n32 config class */ +struct n32_hwtimer_config +{ + const char *name; + TIM_Module* timer_periph; + IRQn_Type irqn; +}; + +struct n32_hwtimer +{ + rt_hwtimer_t time_device; + struct n32_hwtimer_config *config; +}; + +int rt_hwtimer_init(void); + +#endif diff --git a/bsp/n32/libraries/n32_drivers/drv_i2c.c b/bsp/n32/libraries/n32_drivers/drv_i2c.c new file mode 100644 index 0000000000..5a4faf4b4a --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_i2c.c @@ -0,0 +1,485 @@ +/***************************************************************************** + * 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 drv_i2c.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#include +#include +#include "drv_i2c.h" +#include "board.h" + +#ifdef RT_USING_I2C + +#include + +#define DBG_TAG "drv.I2C" +#ifdef RT_I2C_DEBUG +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO +#endif +#include + +#define I2CT_FLAG_TIMEOUT ((uint32_t)0x1000) +#define I2CT_LONG_TIMEOUT ((uint32_t)(10 * I2CT_FLAG_TIMEOUT)) + + + +#ifdef RT_USING_I2C_BITOPS + +/*user can change this*/ +#define I2C_BUS_NAME "i2c1" + +/*user should change this to adapt specific board*/ +#define I2C_SCL_PIN GPIO_PIN_8 +#define I2C_SCL_PORT GPIOB +#define I2C_SCL_CLK RCC_APB2_PERIPH_GPIOB +#define I2C_SDA_PIN GPIO_PIN_9 +#define I2C_SDA_PORT GPIOB +#define I2C_SDA_CLK RCC_APB2_PERIPH_GPIOB + +struct n32_i2c_bit_data +{ + struct + { + rt_uint32_t clk; + GPIO_Module* port; + rt_uint32_t pin; + }scl, sda; +}; + +static void gpio_set_sda(void *data, rt_int32_t state) +{ + struct n32_i2c_bit_data* bd = data; + + if (state) + { + GPIO_SetBits((GPIO_Module*)bd->sda.port, bd->sda.pin); + } + else + { + GPIO_ResetBits((GPIO_Module*)bd->sda.port, bd->sda.pin); + } +} + +static void gpio_set_scl(void *data, rt_int32_t state) +{ + struct n32_i2c_bit_data* bd = data; + if (state) + { + GPIO_SetBits((GPIO_Module*)bd->scl.port, bd->scl.pin); + } + else + { + GPIO_ResetBits((GPIO_Module*)bd->scl.port, bd->scl.pin); + } +} + +static rt_int32_t gpio_get_sda(void *data) +{ + struct n32_i2c_bit_data* bd = data; + + return GPIO_ReadInputDataBit((GPIO_Module*)bd->sda.port, bd->sda.pin); +} + +static rt_int32_t gpio_get_scl(void *data) +{ + struct n32_i2c_bit_data* bd = data; + + return GPIO_ReadInputDataBit((GPIO_Module*)bd->scl.port, bd->scl.pin); +} + +static void gpio_udelay(rt_uint32_t us) +{ + RCC_ClocksType* RCC_Clocks = {0}; + RCC_GetClocksFreqValue(RCC_Clocks); + int i = ( RCC_Clocks->SysclkFreq / 4000000 * us); + while(i) + { + i--; + } +} + +static void drv_i2c_gpio_init(const struct n32_i2c_bit_data* bd) +{ + RCC_EnableAPB2PeriphClk(bd->sda.clk | bd->scl.clk, ENABLE); + GPIOInit((GPIO_Module*)bd->sda.port, GPIO_Mode_Out_OD, GPIO_Speed_10MHz, bd->sda.pin); + GPIOInit((GPIO_Module*)bd->scl.port, GPIO_Mode_Out_OD, GPIO_Speed_10MHz, bd->scl.pin); + + GPIO_SetBits((GPIO_Module*)bd->sda.port, bd->sda.pin); + GPIO_SetBits((GPIO_Module*)bd->scl.port, bd->scl.pin); +} + +#else /* use hardware i2c */ + +static uint32_t I2CTimeout = I2CT_LONG_TIMEOUT; + +static int rt_i2c_read(rt_uint32_t i2c_periph, rt_uint16_t slave_address, rt_uint8_t* p_buffer, rt_uint16_t data_byte) +{ + I2CTimeout = I2CT_LONG_TIMEOUT; + /* wait until I2C bus is idle */ + while(I2C_GetFlag((I2C_Module*)i2c_periph, I2C_FLAG_BUSY)) + { + if ((I2CTimeout--) == 0) + return 9; + }; + + I2C_ConfigAck((I2C_Module*)i2c_periph, ENABLE); + + /** Send START condition */ + I2C_GenerateStart((I2C_Module*)i2c_periph, ENABLE); + + I2CTimeout = I2CT_LONG_TIMEOUT; + /* wait until SBSEND bit is set */ + while (!I2C_CheckEvent((I2C_Module*)i2c_periph, I2C_EVT_MASTER_MODE_FLAG)) // EV5 + { + if ((I2CTimeout--) == 0) + return 10; + }; + + /* send slave address to I2C bus */ + I2C_SendAddr7bit((I2C_Module*)i2c_periph, slave_address, I2C_DIRECTION_RECV); + + I2CTimeout = I2CT_LONG_TIMEOUT; + while (!I2C_CheckEvent((I2C_Module*)i2c_periph, I2C_EVT_MASTER_RXMODE_FLAG)) // EV6 + { + if ((I2CTimeout--) == 0) + return 6; + }; + +// /* clear the ADDSEND bit */ +// I2C_ClrFlag((I2C_Module*)i2c_periph,I2C_FLAG_ADDRF); + +// if(1 == data_byte){ +// /* disable acknowledge */ +// I2C_ConfigAck((I2C_Module*)i2c_periph,DISABLE); +// /* send a stop condition to I2C bus */ +// I2C_GenerateStop(I2C1, ENABLE); +// } + + /* while there is data to be read */ + while(data_byte) + { + /* wait until the RBNE bit is set and clear it */ + if(I2C_GetFlag((I2C_Module*)i2c_periph, I2C_FLAG_RXDATNE)) + { + /* read a byte*/ + *p_buffer = I2C_RecvData((I2C_Module*)i2c_periph); + + /* point to the next location where the byte read will be saved */ + p_buffer++; + + /* decrement the read bytes counter */ + data_byte--; + if(1 == data_byte) + { + /* disable acknowledge */ + I2C_ConfigAck((I2C_Module*)i2c_periph, DISABLE); + /* send a stop condition to I2C bus */ + I2C_GenerateStop((I2C_Module*)i2c_periph, ENABLE); + } + } + } + + /* wait until the stop condition is finished */ + while(I2C_GetFlag((I2C_Module*)i2c_periph, I2C_FLAG_STOPF)) + { + if ((I2CTimeout--) == 0) + return 7; + }; + + /* enable acknowledge */ + I2C_ConfigAck((I2C_Module*)i2c_periph, ENABLE); + + I2C_ConfigNackLocation((I2C_Module*)i2c_periph,I2C_NACK_POS_CURRENT); + + return 0; +} + +static int rt_i2c_write(rt_uint32_t i2c_periph, uint16_t slave_address, uint8_t* p_buffer, uint16_t data_byte) +{ + uint8_t* sendBufferPtr = p_buffer; + I2CTimeout = I2CT_LONG_TIMEOUT; + while (I2C_GetFlag((I2C_Module*)i2c_periph, I2C_FLAG_BUSY)) + { + if ((I2CTimeout--) == 0) + return 4; + }; + + I2C_ConfigAck((I2C_Module*)i2c_periph, ENABLE); + I2C_GenerateStart((I2C_Module*)i2c_periph, ENABLE); + I2CTimeout = I2CT_LONG_TIMEOUT; + while (!I2C_CheckEvent((I2C_Module*)i2c_periph, I2C_EVT_MASTER_MODE_FLAG)) // EV5 + { + if ((I2CTimeout--) == 0) + return 5; + }; + + I2C_SendAddr7bit((I2C_Module*)i2c_periph, slave_address, I2C_DIRECTION_SEND); + I2CTimeout = I2CT_LONG_TIMEOUT; + while (!I2C_CheckEvent((I2C_Module*)i2c_periph, I2C_EVT_MASTER_TXMODE_FLAG)) // EV6 + { + if ((I2CTimeout--) == 0) + return 6; + }; + + // send data + while (data_byte-- > 0) + { + I2C_SendData((I2C_Module*)i2c_periph, *sendBufferPtr++); + I2CTimeout = I2CT_LONG_TIMEOUT; + while (!I2C_CheckEvent((I2C_Module*)i2c_periph, I2C_EVT_MASTER_DATA_SENDING)) // EV8 + { + if ((I2CTimeout--) == 0) + return 7; + }; + }; + + I2CTimeout = I2CT_LONG_TIMEOUT; + while (!I2C_CheckEvent((I2C_Module*)i2c_periph, I2C_EVT_MASTER_DATA_SENDED)) // EV8-2 + { + if ((I2CTimeout--) == 0) + return 8; + }; + I2C_GenerateStop((I2C_Module*)i2c_periph, ENABLE); + return 0; +} + + + +static rt_size_t rt_i2c_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num) +{ + struct rt_i2c_msg *msg; + rt_uint32_t i; + rt_err_t ret = RT_ERROR; + + struct rt_i2c_bus *rt_i2c = (struct rt_i2c_bus *)bus; + + for (i = 0; i < num; i++) + { + msg = &msgs[i]; + + if (msg->flags & RT_I2C_RD) + { + if (rt_i2c_read(rt_i2c->i2c_periph, msg->addr, msg->buf, msg->len) != 0) + { + LOG_E("i2c bus write failed,i2c bus stop!"); + goto out; + } + } + else + { + if (rt_i2c_write(rt_i2c->i2c_periph, msg->addr, msg->buf, msg->len) != 0) + { + LOG_E("i2c bus write failed,i2c bus stop!"); + goto out; + } + } + } + + ret = i; + return ret; + +out: + LOG_E("send stop condition\n"); + + return ret; +} + +static const struct rt_i2c_bus_device_ops i2c_ops = +{ + rt_i2c_xfer, + RT_NULL, + RT_NULL +}; + +#endif /* RT_USING_I2C_BITOPS */ + +int rt_hw_i2c_init(void) +{ +#ifdef RT_USING_I2C_BITOPS + { + static struct rt_i2c_bus_device i2c_device; + static const struct n32_i2c_bit_data _i2c_bdata = + { + /* SCL */ + { I2C_SCL_CLK, I2C_SCL_PORT, I2C_SCL_PIN}, + /* SDA */ + { I2C_SDA_CLK, I2C_SDA_PORT, I2C_SDA_PIN}, + }; + + static const struct rt_i2c_bit_ops _i2c_bit_ops = + { + (void*)&_i2c_bdata, + gpio_set_sda, + gpio_set_scl, + gpio_get_sda, + gpio_get_scl, + gpio_udelay, + 1, + 100 + }; + + drv_i2c_gpio_init(&_i2c_bdata); + + i2c_device.priv = (void *)&_i2c_bit_ops; + rt_i2c_bit_add_bus(&i2c_device, I2C_BUS_NAME); + } + +#else /* register hardware I2C */ + +#ifdef BSP_USING_I2C1 +#define I2C1_SPEED 400000 + + static struct rt_i2c_bus i2c_bus1; + I2C_InitType I2C_InitStructure; + + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP_I2C1, ENABLE); + /* connect PB8 to I2C1_SCL, PB9 to I2C1_SDA */ + GPIOInit(GPIOB, GPIO_Mode_AF_OD, GPIO_Speed_50MHz, GPIO_PIN_8 | GPIO_PIN_9); + + /* enable I2C clock */ + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_I2C1, ENABLE); + + I2C_DeInit(I2C1); + I2C_InitStructure.BusMode = I2C_BUSMODE_I2C; + I2C_InitStructure.FmDutyCycle = I2C_FMDUTYCYCLE_2; + I2C_InitStructure.OwnAddr1 = 0xff; + I2C_InitStructure.AckEnable = I2C_ACKEN; + I2C_InitStructure.AddrMode = I2C_ADDR_MODE_7BIT; + I2C_InitStructure.ClkSpeed = I2C1_SPEED; // 400000 400K + + I2C_Init(I2C1, &I2C_InitStructure); + + rt_memset((void *)&i2c_bus1, 0, sizeof(struct rt_i2c_bus)); + i2c_bus1.parent.ops = &i2c_ops; + i2c_bus1.i2c_periph = (rt_uint32_t)I2C1; + rt_i2c_bus_device_register(&i2c_bus1.parent, "i2c1"); +#endif + +#ifdef BSP_USING_I2C2 +#define I2C2_SPEED 100000 + + static struct rt_i2c_bus i2c_bus2; + I2C_InitType I2C_InitStructure; + + /* enable I2C clock */ + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_I2C2, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + + /* connect PB10 to I2C2_SCL, PB11 to I2C2_SDA */ + GPIOInit(GPIOB, GPIO_Mode_AF_OD, GPIO_Speed_50MHz, GPIO_PIN_10 | GPIO_PIN_11); + + I2C_DeInit(I2C2); + I2C_InitStructure.BusMode = I2C_BUSMODE_I2C; + I2C_InitStructure.FmDutyCycle = I2C_FMDUTYCYCLE_2; + I2C_InitStructure.OwnAddr1 = 0xff; + I2C_InitStructure.AckEnable = I2C_ACKEN; + I2C_InitStructure.AddrMode = I2C_ADDR_MODE_7BIT; + I2C_InitStructure.ClkSpeed = I2C2_SPEED; // 100000 100K + + I2C_Init(I2C2, &I2C_InitStructure); + + rt_memset((void *)&i2c_bus2, 0, sizeof(struct rt_i2c_bus)); + i2c_bus2.parent.ops = &i2c_ops; + i2c_bus2.i2c_periph = (rt_uint32_t)I2C2; + rt_i2c_bus_device_register(&i2c_bus2.parent, "i2c2"); +#endif + +#ifdef BSP_USING_I2C3 +#define I2C3_SPEED 100000 + + static struct rt_i2c_bus i2c_bus3; + I2C_InitType I2C_InitStructure; + + /* enable I2C clock */ + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_I2C3, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + + /* connect PC0 to I2C3_SCL, PC1 to I2C3_SDA */ + GPIOInit(GPIOC, GPIO_Mode_AF_OD, GPIO_Speed_50MHz, GPIO_PIN_0 | GPIO_PIN_1); + + I2C_DeInit(I2C3); + I2C_InitStructure.BusMode = I2C_BUSMODE_I2C; + I2C_InitStructure.FmDutyCycle = I2C_FMDUTYCYCLE_2; + I2C_InitStructure.OwnAddr1 = 0xff; + I2C_InitStructure.AckEnable = I2C_ACKEN; + I2C_InitStructure.AddrMode = I2C_ADDR_MODE_7BIT; + I2C_InitStructure.ClkSpeed = I2C3_SPEED; // 100000 100K + + I2C_Init(I2C3, &I2C_InitStructure); + + rt_memset((void *)&i2c_bus3, 0, sizeof(struct rt_i2c_bus)); + i2c_bus3.parent.ops = &i2c_ops; + i2c_bus3.i2c_periph = (rt_uint32_t)I2C3; + rt_i2c_bus_device_register(&i2c_bus3.parent, "i2c3"); +#endif + +#ifdef BSP_USING_I2C4 +#define I2C4_SPEED 100000 + + static struct rt_i2c_bus i2c_bus4; + I2C_InitType I2C_InitStructure; + + /* enable I2C clock */ + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_I2C4, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + + /* connect PC6 to I2C4_SCL, PC7 to I2C4_SDA */ + GPIOInit(GPIOC, GPIO_Mode_AF_OD, GPIO_Speed_50MHz, GPIO_PIN_6 | GPIO_PIN_7); + + I2C_DeInit(I2C4); + I2C_InitStructure.BusMode = I2C_BUSMODE_I2C; + I2C_InitStructure.FmDutyCycle = I2C_FMDUTYCYCLE_2; + I2C_InitStructure.OwnAddr1 = 0xff; + I2C_InitStructure.AckEnable = I2C_ACKEN; + I2C_InitStructure.AddrMode = I2C_ADDR_MODE_7BIT; + I2C_InitStructure.ClkSpeed = I2C4_SPEED; // 100000 100K + + I2C_Init(I2C4, &I2C_InitStructure); + + rt_memset((void *)&i2c_bus4, 0, sizeof(struct rt_i2c_bus)); + i2c_bus4.parent.ops = &i2c_ops; + i2c_bus4.i2c_periph = (rt_uint32_t)I2C4; + rt_i2c_bus_device_register(&i2c_bus4.parent, "i2c4"); +#endif + +#endif /* RT_USING_I2C_BITOPS */ + + return 0; +} +INIT_DEVICE_EXPORT(rt_hw_i2c_init); + +#endif +/* end of i2c driver */ diff --git a/bsp/n32/libraries/n32_drivers/drv_i2c.h b/bsp/n32/libraries/n32_drivers/drv_i2c.h new file mode 100644 index 0000000000..9433dd4083 --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_i2c.h @@ -0,0 +1,49 @@ +/***************************************************************************** + * 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 drv_i2c.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#ifndef __DRV_I2C__ +#define __DRV_I2C__ + +#include "i2c.h" + +struct rt_i2c_bus +{ + struct rt_i2c_bus_device parent; + rt_uint32_t i2c_periph; +}; + +int rt_hw_i2c_init(void); + +#endif diff --git a/bsp/n32/libraries/n32_drivers/drv_rtc.c b/bsp/n32/libraries/n32_drivers/drv_rtc.c new file mode 100644 index 0000000000..876cb4d9ae --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_rtc.c @@ -0,0 +1,231 @@ +/***************************************************************************** + * 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 drv_rtc.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include +#include +#include "board.h" +#include "time.h" +#include "rtdef.h" +#include "rtc.h" + +#ifdef BSP_USING_RTC + +uint32_t SynchPrediv, AsynchPrediv; + +static rt_err_t n32_rtc_get_timeval(struct timeval *tv) +{ + struct tm tm_new = {0}; + RTC_DateType RTC_DateStructure; + RTC_TimeType RTC_TimeStructure; + + RTC_GetTime(RTC_FORMAT_BIN, &RTC_TimeStructure); + RTC_GetDate(RTC_FORMAT_BIN, &RTC_DateStructure); + + tm_new.tm_sec = RTC_TimeStructure.Seconds; + tm_new.tm_min = RTC_TimeStructure.Minutes; + tm_new.tm_hour = RTC_TimeStructure.Hours; + tm_new.tm_wday = RTC_DateStructure.WeekDay; + tm_new.tm_mday = RTC_DateStructure.Date; + tm_new.tm_mon = RTC_DateStructure.Month - 1; + tm_new.tm_year = RTC_DateStructure.Year + 100; + + tv->tv_sec = timegm(&tm_new); + + return RT_EOK; +} + +static rt_err_t set_rtc_time_stamp(time_t time_stamp) +{ + struct tm time = {0}; + RTC_DateType RTC_DateStructure={0}; + RTC_TimeType RTC_TimeStructure={0}; + + gmtime_r(&time_stamp, &time); + if(time.tm_year < 100) + { + return -RT_ERROR; + } + + RTC_TimeStructure.Seconds = time.tm_sec ; + RTC_TimeStructure.Minutes = time.tm_min ; + RTC_TimeStructure.Hours = time.tm_hour; + RTC_DateStructure.Date = time.tm_mday; + RTC_DateStructure.Month = time.tm_mon + 1 ; + RTC_DateStructure.Year = time.tm_year - 100; + RTC_DateStructure.WeekDay = time.tm_wday + 1; + + if(RTC_SetDate(RTC_FORMAT_BIN, &RTC_DateStructure) != SUCCESS) + { + return -RT_ERROR; + } + + if(RTC_ConfigTime(RTC_FORMAT_BIN, &RTC_TimeStructure) != SUCCESS) + { + return -RT_ERROR; + } + + rt_kprintf("set rtc time.\n"); + + return RT_EOK; +} + +static rt_err_t rt_rtc_config(void) +{ + RTC_InitType RTC_InitStructure; + + /* Configure the RTC data register and RTC prescaler */ + RTC_InitStructure.RTC_AsynchPrediv = 128; + RTC_InitStructure.RTC_SynchPrediv = 128; + RTC_InitStructure.RTC_HourFormat = RTC_24HOUR_FORMAT; + + /* Check on RTC init */ + if(RTC_Init(&RTC_InitStructure) != SUCCESS) + { + return -RT_ERROR; + } + return RT_EOK; +} + +static rt_err_t n32_rtc_init(void) +{ + /* Enable the PWR clock */ + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_PWR | RCC_APB1_PERIPH_BKP, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + /* Allow access to RTC */ + PWR_BackupAccessEnable(ENABLE); + + /* Reset Backup */ + BKP_DeInit(); + + /* Disable RTC clock */ + RCC_EnableRtcClk(DISABLE); + +#ifdef BSP_RTC_USING_LSI + rt_kprintf("rtc clock source is set lsi!\n"); + /* Enable the LSI OSC */ + RCC_EnableLsi(ENABLE); + while(RCC_GetFlagStatus(RCC_FLAG_LSIRD) == RESET) + { + } + RCC_ConfigRtcClk(RCC_RTCCLK_SRC_LSI); + + SynchPrediv = 0x136; // 39.64928KHz + AsynchPrediv = 0x7F; // value range: 0-7F +#else + rt_kprintf("rtc clock source is set lse!\n"); + /* Enable the LSE OSC32_IN PC14 */ + RCC_EnableLsi(DISABLE); // LSI is turned off here to ensure that only one clock is turned on + RCC_ConfigLse(RCC_LSE_ENABLE); + while(RCC_GetFlagStatus(RCC_FLAG_LSERD) == RESET) + { + } + RCC_ConfigRtcClk(RCC_RTCCLK_SRC_LSE); + + SynchPrediv = 0xFF; // 32.768KHz + AsynchPrediv = 0x7F; // value range: 0-7F +#endif /* BSP_RTC_USING_LSI */ + + /* Enable the RTC Clock */ + RCC_EnableRtcClk(ENABLE); + RTC_WaitForSynchro(); + + if(rt_rtc_config() != RT_EOK) + { + rt_kprintf("rtc init failed.\n"); + return -RT_ERROR; + } + + return RT_EOK; +} + +static rt_err_t n32_rtc_get_secs(time_t *sec) +{ + struct timeval tv; + + n32_rtc_get_timeval(&tv); + *(time_t *) sec = tv.tv_sec; + + rt_kprintf("RTC: get rtc_time %d.\n", *sec); + + return RT_EOK; +} + +static rt_err_t n32_rtc_set_secs(time_t *sec) +{ + rt_err_t result = RT_EOK; + + if(set_rtc_time_stamp(*sec)) + { + result = -RT_ERROR; + } + + rt_kprintf("RTC: set rtc_time %d.\n", *sec); + + return result; +} + +static const struct rt_rtc_ops n32_rtc_ops = +{ + n32_rtc_init, + n32_rtc_get_secs, + n32_rtc_set_secs, + RT_NULL, + RT_NULL, + n32_rtc_get_timeval, + RT_NULL, +}; + +static rt_rtc_dev_t n32_rtc_dev; + +static int rt_hw_rtc_init(void) +{ + rt_err_t result; + + n32_rtc_dev.ops = &n32_rtc_ops; + result = rt_hw_rtc_register(&n32_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL); + if(result != RT_EOK) + { + rt_kprintf("rtc register error code: %d.\n", result); + return result; + } + else + { + rt_kprintf("rtc initialize success.\n"); + } + + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_rtc_init); +#endif /* BSP_USING_RTC */ + diff --git a/bsp/n32/libraries/n32_drivers/drv_spi.c b/bsp/n32/libraries/n32_drivers/drv_spi.c new file mode 100644 index 0000000000..d9168e9087 --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_spi.c @@ -0,0 +1,339 @@ +/***************************************************************************** + * 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 drv_spi.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#include "drv_spi.h" + +#if defined(RT_USING_SPI) && defined(RT_USING_PIN) +#include + +#if defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2) || \ + defined(BSP_USING_SPI3) + +/* #define DEBUG */ +#ifdef DEBUG +#define DEBUG_PRINTF(...) rt_kprintf(__VA_ARGS__) +#else +#define DEBUG_PRINTF(...) +#endif + +/* private rt-thread spi ops function */ + +static rt_err_t configure(struct rt_spi_device* device, struct rt_spi_configuration* configuration) +{ + SPI_InitType SPI_InitStructure; + RCC_ClocksType RCC_ClockFreq; + SPI_Module* spi_periph; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(configuration != RT_NULL); + + RCC_GetClocksFreqValue(&RCC_ClockFreq); + + spi_periph = (SPI_Module*)device->bus->parent.user_data; + + if(spi_periph != SPI1 && spi_periph != SPI2 && spi_periph != SPI3) + { + return RT_EIO; + } + if(configuration->data_width <= 8) + { + SPI_InitStructure.DataLen = SPI_DATA_SIZE_8BITS; + } + else if(configuration->data_width <= 16) + { + SPI_InitStructure.DataLen = SPI_DATA_SIZE_16BITS; + } + else + { + return RT_EIO; + } + + { + rt_uint32_t spi_apb_clock; + rt_uint32_t max_hz; + + max_hz = configuration->max_hz; + + DEBUG_PRINTF("sys freq: %d\n", RCC_ClockFreq.SysclkFreq); + DEBUG_PRINTF("CK_APB2 freq: %d\n", RCC_ClockFreq.Pclk2Freq); + DEBUG_PRINTF("max freq: %d\n", max_hz); + + if (spi_periph == SPI1) + { + spi_apb_clock = RCC_ClockFreq.Pclk2Freq; + } + else + { + spi_apb_clock = RCC_ClockFreq.Pclk1Freq; + } + + if(max_hz >= spi_apb_clock/2) + { + SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_2; + } + else if (max_hz >= spi_apb_clock/4) + { + SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_4; + } + else if (max_hz >= spi_apb_clock/8) + { + SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_8; + } + else if (max_hz >= spi_apb_clock/16) + { + SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_16; + } + else if (max_hz >= spi_apb_clock/32) + { + SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_32; + } + else if (max_hz >= spi_apb_clock/64) + { + SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_64; + } + else if (max_hz >= spi_apb_clock/128) + { + SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_128; + } + else + { + /* min prescaler 256 */ + SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_256; + } + } /* baudrate */ + + switch(configuration->mode & RT_SPI_MODE_3) + { + case RT_SPI_MODE_0: + SPI_InitStructure.CLKPOL = SPI_CLKPOL_LOW; + SPI_InitStructure.CLKPHA = SPI_CLKPHA_FIRST_EDGE; + break; + case RT_SPI_MODE_1: + SPI_InitStructure.CLKPOL = SPI_CLKPOL_LOW; + SPI_InitStructure.CLKPHA = SPI_CLKPHA_SECOND_EDGE; + break; + case RT_SPI_MODE_2: + SPI_InitStructure.CLKPOL = SPI_CLKPOL_HIGH; + SPI_InitStructure.CLKPHA = SPI_CLKPHA_FIRST_EDGE; + break; + case RT_SPI_MODE_3: + SPI_InitStructure.CLKPOL = SPI_CLKPOL_HIGH; + SPI_InitStructure.CLKPHA = SPI_CLKPHA_SECOND_EDGE; + break; + } + + /* MSB or LSB */ + if(configuration->mode & RT_SPI_MSB) + { + SPI_InitStructure.FirstBit = SPI_FB_MSB; + } + else + { + SPI_InitStructure.FirstBit = SPI_FB_LSB; + } + /*!< SPI configuration */ + SPI_InitStructure.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX; + SPI_InitStructure.SpiMode = SPI_MODE_MASTER; + SPI_InitStructure.CLKPHA = SPI_CLKPHA_SECOND_EDGE; + SPI_InitStructure.NSS = SPI_NSS_SOFT; + SPI_InitStructure.CRCPoly = 7; + + SPI_Init(spi_periph, &SPI_InitStructure); + + /*!< Enable the sFLASH_SPI */ + SPI_Enable(spi_periph, ENABLE); + + return RT_EOK; +} + +static rt_uint32_t xfer(struct rt_spi_device* device, struct rt_spi_message* message) +{ + struct n32_spi_cs *cs_pin = device->parent.user_data; + SPI_Module* spi_periph = (SPI_Module*)device->bus->parent.user_data; + struct rt_spi_configuration * config = &device->config; + + RT_ASSERT(device != NULL); + RT_ASSERT(message != NULL); + + /* take CS */ + if(message->cs_take) + { + rt_pin_write(cs_pin->GPIO_Pin, PIN_LOW); + DEBUG_PRINTF("spi take cs\n"); + } + + { + if(config->data_width <= 8) + { + const rt_uint8_t * send_ptr = message->send_buf; + rt_uint8_t * recv_ptr = message->recv_buf; + rt_uint32_t size = message->length; + + DEBUG_PRINTF("spi poll transfer start: %d\n", size); + + while(size--) + { + rt_uint8_t data = 0xA5; + + if(send_ptr != RT_NULL) + { + data = *send_ptr++; + } + + /*!< Loop while DAT register in not emplty */ + while (SPI_I2S_GetStatus(spi_periph, SPI_I2S_TE_FLAG) == RESET); + + // Send the byte + SPI_I2S_TransmitData(spi_periph, data); + + //Wait until a data is received + while(SPI_I2S_GetStatus(spi_periph, SPI_I2S_RNE_FLAG) == RESET); + + // Get the received data + data = SPI_I2S_ReceiveData(spi_periph); + + if(recv_ptr != RT_NULL) + { + *recv_ptr++ = data; + } + } + DEBUG_PRINTF("spi poll transfer finsh\n"); + } + else if(config->data_width <= 16) + { + const rt_uint16_t * send_ptr = message->send_buf; + rt_uint16_t * recv_ptr = message->recv_buf; + rt_uint32_t size = message->length; + + while(size--) + { + rt_uint16_t data = 0xFF; + + if(send_ptr != RT_NULL) + { + data = *send_ptr++; + } + + /*!< Loop while DAT register in not emplty */ + while (SPI_I2S_GetStatus(spi_periph, SPI_I2S_TE_FLAG) == RESET); + + // Send the byte + SPI_I2S_TransmitData(spi_periph, data); + + //Wait until a data is received + while(RESET == SPI_I2S_GetStatus(spi_periph, SPI_I2S_RNE_FLAG)); + + // Get the received data + data = SPI_I2S_ReceiveData(spi_periph); + + if(recv_ptr != RT_NULL) + { + *recv_ptr++ = data; + } + } + } + } + + /* release CS */ + if(message->cs_release) + { + rt_pin_write(cs_pin->GPIO_Pin, PIN_HIGH); + DEBUG_PRINTF("spi release cs\n"); + } + + return message->length; +} + +static struct rt_spi_ops spi_ops = +{ + configure, + xfer +}; + +int rt_hw_spi_init(void) +{ + int result = 0; + +#ifdef BSP_USING_SPI1 + static struct rt_spi_bus spi_bus1; + spi_bus1.parent.user_data = (void *)SPI1; + + result = rt_spi_bus_register(&spi_bus1, "spi1", &spi_ops); + + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_SPI1, ENABLE); + /* SPI1_SCK(PA5), SPI1_MISO(PA6) and SPI1_MOSI(PA7) GPIO pin configuration */ + GPIOInit(SPI1_SCK_GPIO_PORT, GPIO_Mode_AF_PP, GPIO_Speed_50MHz, SPI1_SCK_PIN); + GPIOInit(SPI1_MOSI_GPIO_PORT, GPIO_Mode_AF_PP, GPIO_Speed_50MHz, SPI1_MOSI_PIN); + GPIOInit(SPI1_MISO_GPIO_PORT, GPIO_Mode_IN_FLOATING, GPIO_Speed_50MHz, SPI1_MISO_PIN); + +#endif +#ifdef BSP_USING_SPI2 + static struct rt_spi_bus spi_bus2; + spi_bus2.parent.user_data = (void *)SPI2; + + result = rt_spi_bus_register(&spi_bus2, "spi2", &spi_ops); + + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_SPI2, ENABLE); + /* SPI2_SCK(PB13), SPI2_MISO(PB14) and SPI2_MOSI(PB15) GPIO pin configuration */ + GPIOInit(SPI2_SCK_GPIO_PORT, GPIO_Mode_AF_PP, GPIO_Speed_50MHz, SPI2_SCK_PIN); + GPIOInit(SPI2_MOSI_GPIO_PORT, GPIO_Mode_AF_PP, GPIO_Speed_50MHz, SPI2_MOSI_PIN); + GPIOInit(SPI2_MISO_GPIO_PORT, GPIO_Mode_IN_FLOATING, GPIO_Speed_50MHz, SPI2_MISO_PIN); + +#endif +#ifdef BSP_USING_SPI3 + static struct rt_spi_bus spi_bus3; + spi_bus3.parent.user_data = (void *)SPI3; + + result = rt_spi_bus_register(&spi_bus3, "spi3", &spi_ops); + + /* Enable AFIO clock */ + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + + GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_SW_ENABLE, ENABLE); + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_SPI3, ENABLE); + + /* SPI3_SCK(PB3), SPI3_MISO(PB4) and SPI3_MOSI(PB5) GPIO pin configuration */ + GPIOInit(SPI3_SCK_GPIO_PORT, GPIO_Mode_AF_PP, GPIO_Speed_50MHz, SPI3_SCK_PIN); + GPIOInit(SPI3_MOSI_GPIO_PORT, GPIO_Mode_AF_PP, GPIO_Speed_50MHz, SPI3_MOSI_PIN); + GPIOInit(SPI3_MISO_GPIO_PORT, GPIO_Mode_IN_FLOATING, GPIO_Speed_50MHz, SPI3_MISO_PIN); + +#endif + return result; +} +INIT_BOARD_EXPORT(rt_hw_spi_init); + +#endif /* defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2) || defined(BSP_USING_SPI3) */ +#endif diff --git a/bsp/n32/libraries/n32_drivers/drv_spi.h b/bsp/n32/libraries/n32_drivers/drv_spi.h new file mode 100644 index 0000000000..fec016adcd --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_spi.h @@ -0,0 +1,87 @@ +/***************************************************************************** + * 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 drv_spi.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#ifndef __DRV_SPI_H__ +#define __DRV_SPI_H__ + +#include +#include +#include + +struct n32_spi_cs +{ + GPIO_Module* GPIOx; + uint32_t GPIO_Pin; +}; + +#ifdef BSP_USING_SPI1 +#define SPI1_SCK_PIN GPIO_PIN_5 /* PA.05 */ +#define SPI1_SCK_GPIO_PORT GPIOA /* GPIOA */ +#define SPI1_SCK_GPIO_CLK RCC_APB2_PERIPH_GPIOA +#define SPI1_MISO_PIN GPIO_PIN_6 /* PA.06 */ +#define SPI1_MISO_GPIO_PORT GPIOA /* GPIOA */ +#define SPI1_MISO_GPIO_CLK RCC_APB2_PERIPH_GPIOA +#define SPI1_MOSI_PIN GPIO_PIN_7 /* PA.07 */ +#define SPI1_MOSI_GPIO_PORT GPIOA /* GPIOA */ +#define SPI1_MOSI_GPIO_CLK RCC_APB2_PERIPH_GPIOA +#endif /* RT_USING_SPI1 */ + +#ifdef BSP_USING_SPI2 +#define SPI2_SCK_PIN GPIO_PIN_13 /* PB.13 */ +#define SPI2_SCK_GPIO_PORT GPIOB /* GPIOB */ +#define SPI2_SCK_GPIO_CLK RCC_APB2_PERIPH_GPIOB +#define SPI2_MISO_PIN GPIO_PIN_14 /* PB.14 */ +#define SPI2_MISO_GPIO_PORT GPIOB /* GPIOB */ +#define SPI2_MISO_GPIO_CLK RCC_APB2_PERIPH_GPIOB +#define SPI2_MOSI_PIN GPIO_PIN_15 /* PB.15 */ +#define SPI2_MOSI_GPIO_PORT GPIOB /* GPIOB */ +#define SPI2_MOSI_GPIO_CLK RCC_APB2_PERIPH_GPIOB +#endif /* RT_USING_SPI2 */ + +#ifdef BSP_USING_SPI3 +#define SPI3_SCK_PIN GPIO_PIN_3 /* PB.03 */ +#define SPI3_SCK_GPIO_PORT GPIOB /* GPIOB */ +#define SPI3_SCK_GPIO_CLK RCC_APB2_PERIPH_GPIOB +#define SPI3_MISO_PIN GPIO_PIN_4 /* PB.04 */ +#define SPI3_MISO_GPIO_PORT GPIOB /* GPIOB */ +#define SPI3_MISO_GPIO_CLK RCC_APB2_PERIPH_GPIOB +#define SPI3_MOSI_PIN GPIO_PIN_5 /* PB.05 */ +#define SPI3_MOSI_GPIO_PORT GPIOB /* GPIOB */ +#define SPI3_MOSI_GPIO_CLK RCC_APB2_PERIPH_GPIOB +#endif /* RT_USING_SPI3 */ + +int rt_hw_spi_init(void); + +#endif /* __DRV_SPI_H__ */ diff --git a/bsp/n32/libraries/n32_drivers/drv_usart.c b/bsp/n32/libraries/n32_drivers/drv_usart.c new file mode 100644 index 0000000000..5171a16e98 --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_usart.c @@ -0,0 +1,502 @@ +/***************************************************************************** + * 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 drv_usart.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#include +#include "board.h" + +#ifdef RT_USING_SERIAL + +#if defined(BSP_USING_USART1) || defined(BSP_USING_USART2) || \ + defined(BSP_USING_USART3) || defined(BSP_USING_UART4) || \ + defined(BSP_USING_UART5) || defined(BSP_USING_UART6) || \ + defined(BSP_USING_UART7) + + +#include + +/* n32 uart driver */ +// Todo: compress uart info +struct n32_uart +{ + USART_Module* uart_periph; //Todo: 3bits + IRQn_Type irqn; //Todo: 7bits + uint32_t per_clk; //Todo: 5bits + uint32_t tx_gpio_clk; //Todo: 5bits + uint32_t rx_gpio_clk; //Todo: 5bits + GPIO_Module* tx_port; //Todo: 4bits + GPIO_ModeType tx_af; //Todo: 4bits + uint16_t tx_pin; //Todo: 4bits + GPIO_Module* rx_port; //Todo: 4bits + GPIO_ModeType rx_af; //Todo: 4bits + uint16_t rx_pin; //Todo: 4bits + + struct rt_serial_device * serial; + char *device_name; +}; + +static void uart_isr(struct rt_serial_device *serial); + +#if defined(BSP_USING_USART1) +struct rt_serial_device serial1; + +void USART1_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&serial1); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +#endif /* BSP_USING_USART1 */ + +#if defined(BSP_USING_USART2) +struct rt_serial_device serial2; + +void USART2_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&serial2); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +#endif /* BSP_USING_USART2 */ + +#if defined(BSP_USING_USART3) +struct rt_serial_device serial3; + +void USART3_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&serial3); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +#endif /* BSP_USING_USART3 */ + +#if defined(BSP_USING_UART4) +struct rt_serial_device serial4; + +void UART4_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&serial4); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +#endif /* BSP_USING_UART4 */ + +#if defined(BSP_USING_UART5) +struct rt_serial_device serial5; + +void UART5_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&serial5); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* BSP_USING_UART5 */ + +#if defined(BSP_USING_UART6) +struct rt_serial_device serial6; + +void UART6_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&serial6); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +#endif /* BSP_USING_UART6 */ + +#if defined(BSP_USING_UART7) +struct rt_serial_device serial7; + +void UART7_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&serial7); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +#endif /* BSP_USING_UART7 */ + +static const struct n32_uart uarts[] = { +#ifdef BSP_USING_USART1 + { + USART1, // uart peripheral index + USART1_IRQn, // uart iqrn + RCC_APB2_PERIPH_USART1, RCC_APB2_PERIPH_GPIOA, RCC_APB2_PERIPH_GPIOA, // periph clock, tx gpio clock, rt gpio clock + GPIOA, GPIO_Mode_AF_PP, GPIO_PIN_9, // tx port, tx alternate, tx pin + GPIOA, GPIO_Mode_IN_FLOATING, GPIO_PIN_10, // rx port, rx alternate, rx pin + &serial1, + "usart1", + }, +#endif + +#ifdef BSP_USING_USART2 + { + USART2, // uart peripheral index + USART2_IRQn, // uart iqrn + RCC_APB1_PERIPH_USART2, RCC_APB2_PERIPH_GPIOA, RCC_APB2_PERIPH_GPIOA, // periph clock, tx gpio clock, rt gpio clock + GPIOA, GPIO_Mode_AF_PP, GPIO_PIN_2, // tx port, tx alternate, tx pin + GPIOA, GPIO_Mode_IN_FLOATING, GPIO_PIN_3, // rx port, rx alternate, rx pin + &serial2, + "usart2", + }, +#endif + +#ifdef BSP_USING_USART3 + { + USART3, // uart peripheral index + USART3_IRQn, // uart iqrn + RCC_APB1_PERIPH_USART3, RCC_APB2_PERIPH_GPIOB, RCC_APB2_PERIPH_GPIOB, // periph clock, tx gpio clock, rt gpio clock + GPIOB, GPIO_Mode_AF_PP, GPIO_PIN_10, // tx port, tx alternate, tx pin + GPIOB, GPIO_Mode_IN_FLOATING, GPIO_PIN_11, // rx port, rx alternate, rx pin + &serial3, + "usart3", + }, +#endif + +#ifdef BSP_USING_UART4 + { + UART4, // uart peripheral index + UART4_IRQn, // uart iqrn + RCC_APB1_PERIPH_UART4, RCC_APB2_PERIPH_GPIOC, RCC_APB2_PERIPH_GPIOC, // periph clock, tx gpio clock, rt gpio clock + GPIOC, GPIO_Mode_AF_PP, GPIO_PIN_10, // tx port, tx alternate, tx pin + GPIOC, GPIO_Mode_IN_FLOATING, GPIO_PIN_11, // rx port, rx alternate, rx pin + &serial4, + "uart4", + }, +#endif + +#ifdef BSP_USING_UART5 + { + UART5, // uart peripheral index + UART5_IRQn, // uart iqrn + RCC_APB1_PERIPH_UART5, RCC_APB2_PERIPH_GPIOC, RCC_APB2_PERIPH_GPIOD, // periph clock, tx gpio clock, rt gpio clock + GPIOC, GPIO_Mode_AF_PP, GPIO_PIN_12, // tx port, tx alternate, tx pin + GPIOD, GPIO_Mode_IN_FLOATING, GPIO_PIN_2, // rx port, rx alternate, rx pin + &serial5, + "uart5", + }, +#endif + +#ifdef BSP_USING_UART6 + { + UART6, // uart peripheral index + UART6_IRQn, // uart iqrn + RCC_APB2_PERIPH_UART6, RCC_APB2_PERIPH_GPIOE, RCC_APB2_PERIPH_GPIOE, // periph clock, tx gpio clock, rt gpio clock + GPIOE, GPIO_Mode_AF_PP, GPIO_PIN_2, // tx port, tx alternate, tx pin + GPIOE, GPIO_Mode_IN_FLOATING, GPIO_PIN_3, // rx port, rx alternate, rx pin + &serial6, + "uart6", + }, +#endif + +#ifdef BSP_USING_UART7 + { + UART7, // uart peripheral index + UART7_IRQn, // uart iqrn + RCC_APB2_PERIPH_UART7, RCC_APB2_PERIPH_GPIOC, RCC_APB2_PERIPH_GPIOC, // periph clock, tx gpio clock, rt gpio clock + GPIOC, GPIO_Mode_AF_PP, GPIO_PIN_4, // tx port, tx alternate, tx pin + GPIOC, GPIO_Mode_IN_FLOATING, GPIO_PIN_5, // rx port, rx alternate, rx pin + &serial7, + "uart7", + }, +#endif +}; + + +/** +* @brief UART MSP Initialization +* This function configures the hardware resources used in this example: +* - Peripheral's clock enable +* - Peripheral's GPIO Configuration +* - NVIC configuration for UART interrupt request enable +* @param huart: UART handle pointer +* @retval None +*/ +void n32_uart_gpio_init(struct n32_uart *uart, struct serial_configure *cfg) +{ + /* enable USART clock */ + RCC_EnableAPB2PeriphClk(uart->tx_gpio_clk | uart->rx_gpio_clk | RCC_APB2_PERIPH_AFIO, ENABLE); + + if(uart->uart_periph == USART1 || uart->uart_periph == UART6 || uart->uart_periph == UART7) + { + RCC_EnableAPB2PeriphClk(uart->per_clk, ENABLE); + } + else + { + RCC_EnableAPB1PeriphClk(uart->per_clk, ENABLE); + } + + /* connect port to USARTx_Tx */ + GPIOInit(uart->tx_port, uart->tx_af, GPIO_Speed_50MHz, uart->tx_pin); + /* connect port to USARTx_Rx */ + GPIOInit(uart->tx_port, uart->rx_af, GPIO_Speed_50MHz, uart->rx_pin); + + NVIC_SetPriority(uart->irqn, 0); + NVIC_EnableIRQ(uart->irqn); +} + +static rt_err_t n32_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + struct n32_uart *uart; + USART_InitType USART_InitStructure; + + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(cfg != RT_NULL); + + uart = (struct n32_uart *)serial->parent.user_data; + + n32_uart_gpio_init(uart, cfg); + + USART_InitStructure.BaudRate = cfg->baud_rate; + + switch (cfg->data_bits) + { + case DATA_BITS_9: + USART_InitStructure.WordLength = USART_WL_9B; + break; + + default: + USART_InitStructure.WordLength = USART_WL_8B;; + break; + } + + switch (cfg->stop_bits) + { + case STOP_BITS_1: + USART_InitStructure.StopBits = USART_STPB_1; + break; + case STOP_BITS_2: + USART_InitStructure.StopBits = USART_STPB_0_5; + break; + case STOP_BITS_3: + USART_InitStructure.StopBits = USART_STPB_2; + break; + case STOP_BITS_4: + USART_InitStructure.StopBits = USART_STPB_1_5; + break; + default: + break; + } + + switch (cfg->parity) + { + case PARITY_ODD: + USART_InitStructure.Parity = USART_PE_ODD; + break; + case PARITY_EVEN: + USART_InitStructure.Parity = USART_PE_EVEN; + break; + case PARITY_NONE: + USART_InitStructure.Parity = USART_PE_NO; + break; + default: + break; + } + + switch (cfg->flowcontrol) + { + case RT_SERIAL_FLOWCONTROL_NONE: + USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE; + break; + case RT_SERIAL_FLOWCONTROL_CTSRTS: + USART_InitStructure.HardwareFlowControl = USART_HFCTRL_RTS_CTS; + break; + default: + USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE; + break; + } + + USART_InitStructure.Mode = USART_MODE_TX | USART_MODE_RX; + + USART_Init(uart->uart_periph, &USART_InitStructure); + + USART_Enable(uart->uart_periph, ENABLE); + + return RT_EOK; +} + +static rt_err_t n32_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + struct n32_uart *uart; + NVIC_InitType NVIC_InitStructure; + + /* Configure the NVIC Preemption Priority Bits */ + NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); + + RT_ASSERT(serial != RT_NULL); + uart = (struct n32_uart *)serial->parent.user_data; + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + /* disable rx irq */ + NVIC_InitStructure.NVIC_IRQChannel = uart->irqn; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE; + NVIC_Init(&NVIC_InitStructure); + /* disable interrupt */ + USART_ConfigInt(uart->uart_periph, USART_INT_RXDNE, DISABLE); + break; + case RT_DEVICE_CTRL_SET_INT: + /* enable rx irq */ + NVIC_InitStructure.NVIC_IRQChannel = uart->irqn; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + + /* enable interrupt */ + USART_ConfigInt(uart->uart_periph, USART_INT_RXDNE, ENABLE); + break; + } + + return RT_EOK; +} + +static int n32_putc(struct rt_serial_device *serial, char ch) +{ + struct n32_uart *uart; + + RT_ASSERT(serial != RT_NULL); + uart = (struct n32_uart *)serial->parent.user_data; + + USART_SendData(uart->uart_periph, ch); + while((USART_GetFlagStatus(uart->uart_periph, USART_FLAG_TXDE) == RESET)); + + return 1; +} + +static int n32_getc(struct rt_serial_device *serial) +{ + int ch; + struct n32_uart *uart; + + RT_ASSERT(serial != RT_NULL); + uart = (struct n32_uart *)serial->parent.user_data; + + ch = -1; + if (USART_GetFlagStatus(uart->uart_periph, USART_FLAG_RXDNE) != RESET) + ch = USART_ReceiveData(uart->uart_periph); + return ch; +} + +/** + * Uart common interrupt process. This need add to uart ISR. + * + * @param serial serial device + */ +static void uart_isr(struct rt_serial_device *serial) +{ + struct n32_uart *uart = (struct n32_uart *) serial->parent.user_data; + + RT_ASSERT(uart != RT_NULL); + + /* UART in mode Receiver -------------------------------------------------*/ + if (USART_GetIntStatus(uart->uart_periph, USART_INT_RXDNE) != RESET && + USART_GetFlagStatus(uart->uart_periph, USART_FLAG_RXDNE) != RESET) + { + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); + } + + if (USART_GetIntStatus(uart->uart_periph, USART_INT_TXDE) != RESET && + USART_GetFlagStatus(uart->uart_periph, USART_FLAG_TXDE) != RESET) + { + /* Write one byte to the transmit data register */ + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DONE); + + } +} + +static const struct rt_uart_ops n32_uart_ops = +{ + n32_configure, + n32_control, + n32_putc, + n32_getc, +}; + +int rt_hw_usart_init(void) +{ + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + int i; + + for (i = 0; i < sizeof(uarts) / sizeof(uarts[0]); i++) + { + uarts[i].serial->ops = &n32_uart_ops; + uarts[i].serial->config = config; + + /* register UART device */ + rt_hw_serial_register(uarts[i].serial, + uarts[i].device_name, + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + (void *)&uarts[i]); + } + + return 0; +} +INIT_BOARD_EXPORT(rt_hw_usart_init); + +#endif /* defined(BSP_USING_USARTx) */ +#endif /* BSP_USING_SERIAL */ diff --git a/bsp/n32/libraries/n32_drivers/drv_usart.h b/bsp/n32/libraries/n32_drivers/drv_usart.h new file mode 100644 index 0000000000..e5208e3a8e --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_usart.h @@ -0,0 +1,45 @@ +/***************************************************************************** + * 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 drv_usart.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#ifndef __USART_H__ +#define __USART_H__ + +#include +#include + +#define UART_ENABLE_IRQ(n) NVIC_EnableIRQ((n)) +#define UART_DISABLE_IRQ(n) NVIC_DisableIRQ((n)) + +#endif diff --git a/bsp/n32/libraries/n32_drivers/drv_wdt.c b/bsp/n32/libraries/n32_drivers/drv_wdt.c new file mode 100644 index 0000000000..2807dd5e4a --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_wdt.c @@ -0,0 +1,197 @@ +/***************************************************************************** + * 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 drv_wdt.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#include +#include +#include +#include "rtdevice.h" +#include "board.h" + +#ifdef RT_USING_WDT + +__IO uint32_t LsiFreq = 40000; + +static rt_err_t n32_wdt_close(rt_watchdog_t *wdt) +{ + rt_uint32_t level; + + level = rt_hw_interrupt_disable(); + /* Disable the LSI OSC */ + RCC_EnableLsi(DISABLE); + rt_hw_interrupt_enable(level); + + return RT_EOK; +} + +static rt_err_t n32_wdt_open(rt_watchdog_t *wdt, rt_uint16_t oflag) +{ + rt_uint32_t level; + + level = rt_hw_interrupt_disable(); + /* Enable the LSI OSC */ + RCC_EnableLsi(ENABLE); + + /* Wait till LSI is ready */ + while (RCC_GetFlagStatus(RCC_FLAG_LSIRD) == RESET) + { + } + /* Reload IWDG counter */ + IWDG_ReloadKey(); + /* Enable IWDG (the LSI oscillator will be enabled by hardware) */ + IWDG_Enable(); + rt_hw_interrupt_enable(level); + + return RT_EOK; +} + +static rt_err_t n32_wdt_init(rt_watchdog_t *wdt) +{ + return RT_EOK; +} + +static rt_err_t n32_wdt_refresh(rt_watchdog_t *wdt) +{ + rt_uint32_t level; + + level = rt_hw_interrupt_disable(); + /* Reload IWDG counter */ + IWDG_ReloadKey(); + rt_hw_interrupt_enable(level); + + return RT_EOK; +} + +/** + * @function control wdt + * + * @param + * wdt whick wdt used + * cmd control wdt options + * args argument of conrtol + * @retval rt_err_t the status of control result + * + * + */ +#define WDT_RELOAD_SECOND ((IWDG->RELV * LsiFreq) / IWDG->PREDIV) +static rt_err_t n32_wdt_control(rt_watchdog_t *wdt, int cmd, void *args) +{ + RT_ASSERT(wdt != NULL); + + uint16_t reload_value; + uint32_t relv, prediv; + static rt_tick_t last_tick = 0; + + relv = IWDG->RELV; + prediv = IWDG->PREDIV; + switch (cmd) + { + case RT_DEVICE_CTRL_WDT_GET_TIMEOUT: + { + *(uint16_t *)args = relv*LsiFreq/prediv; + } + break; + case RT_DEVICE_CTRL_WDT_SET_TIMEOUT: + { + RT_ASSERT(*(uint16_t *)args != 0); + reload_value = *(uint16_t *)args; + if(reload_value > 0xFFF * 32 *1000 / LsiFreq) + { + LOG_W("wdg set timeout parameter too large, please less than %d ms\n", 0xFFF * 32 *1000 / LsiFreq); + return -RT_EINVAL; + } + /* Enable write access to IWDG_PR and IWDG_RLR registers */ + IWDG_WriteConfig(IWDG_WRITE_ENABLE); + /* IWDG counter clock: LSI/32 */ + IWDG_SetPrescalerDiv(IWDG_PRESCALER_DIV32); + reload_value = ((uint32_t)reload_value * LsiFreq / 1000) / 32; + IWDG_CntReload(reload_value); + IWDG_WriteConfig(IWDG_WRITE_DISABLE); + } + break; + case RT_DEVICE_CTRL_WDT_GET_TIMELEFT: + *(uint16_t *)args = relv*LsiFreq/prediv - \ + (rt_tick_get() - last_tick) / RT_TICK_PER_SECOND; + + break; + case RT_DEVICE_CTRL_WDT_KEEPALIVE: + { + last_tick = rt_tick_get(); + n32_wdt_refresh(wdt); + } + break; + case RT_DEVICE_CTRL_WDT_START: + { + n32_wdt_open(wdt, *(rt_uint32_t *)args); + last_tick = rt_tick_get(); + } + break; + case RT_DEVICE_CTRL_WDT_STOP: + { + n32_wdt_close(wdt); + + } + break; + default: + return RT_EINVAL; + } + + return RT_EOK; +} + +static struct rt_watchdog_ops n32_wdt_ops = +{ + .init = n32_wdt_init, + .control = n32_wdt_control, +}; + +static struct rt_watchdog_device n32_wdt_device; + +int rt_hw_wdt_init(void) +{ + int result = RT_EOK; + + /* Disable the LSI OSC */ + RCC_EnableLsi(DISABLE); + n32_wdt_device.ops = &n32_wdt_ops; + /* register watchdog device */ + result = rt_hw_watchdog_register(&n32_wdt_device, "wdt", RT_DEVICE_FLAG_RDWR, (void *)IWDG); + + return result; +} + +INIT_DEVICE_EXPORT(rt_hw_wdt_init); + +#endif /* BSP_USING_WDT */ + diff --git a/bsp/n32/libraries/n32_drivers/drv_wdt.h b/bsp/n32/libraries/n32_drivers/drv_wdt.h new file mode 100644 index 0000000000..c7de38d535 --- /dev/null +++ b/bsp/n32/libraries/n32_drivers/drv_wdt.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2029-06-08 hqfang first implementation. + */ + +#ifndef __DRV_WDT__ +#define __DRV_WDT__ + +#include +#include +#include + +int rt_hw_wdt_init(void); + +#endif diff --git a/bsp/n32/n32g45xvl-stb/.config b/bsp/n32/n32g45xvl-stb/.config new file mode 100644 index 0000000000..40b6e6350d --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/.config @@ -0,0 +1,701 @@ +# +# 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 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 + +# +# 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_RTDUINO 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 + +# +# 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_RTT_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 +# 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 + +# +# 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_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_I2C 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/n32g45xvl-stb/Kconfig b/bsp/n32/n32g45xvl-stb/Kconfig new file mode 100644 index 0000000000..8cbc7b71a8 --- /dev/null +++ b/bsp/n32/n32g45xvl-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/n32g45xvl-stb/README.md b/bsp/n32/n32g45xvl-stb/README.md new file mode 100644 index 0000000000..b66ab9c590 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/README.md @@ -0,0 +1,124 @@ +# N32G45XVL-STB BSP 说明 + +## 简介 + +N32G45XVL-STB 是国民技术推出的一款N32G457系列的评估æ¿ï¼Œå…¶æ­è½½çš„MCU主è¦èµ„æºå‚数如下: + +| 硬件 | æè¿° | +| --------- | ------------- | +| èŠ¯ç‰‡åž‹å· | N32G457VEL7 | +| CPU | ARM Cortex M4 | +| 主频 | 144M | +| 片内SRAM | 144K | +| 片内FLASH | 512K | + +## 编译说明 + +N32G45XVL-STB æ¿çº§åŒ…支æŒMDK5å¼€å‘环境和GCC编译器,以下是具体版本信æ¯ï¼š + +| IDE/编译器 | 已测试版本 | +| ---------- | ---------------------------- | +| MDK5 | V5.34 | +| IAR | V8.50 | +| GCC | GCC 6.2.1 20161205 (release) | + +## æ¿è½½èµ„æº + +- MCU:N32G457VEL7,主频 144MHz,512KB FLASH +- 常用外设 + - LED :3个,LED1 (PA8),LED2(PB4),LED3(PB5) + - 按键:5个,RESET(NRST),WAKEUP(PA0),KEY1(PA4),KEY2(PA5),KEY3(PA6) + +- 常用接å£ï¼šUSB 接å£(J3) +- 调试接å£: æ¿è½½çš„ CMSIS-DAP SWD 下载(J4),JLINK + +## å¤–è®¾æ”¯æŒ + +本 BSP ç›®å‰å¯¹å¤–è®¾é©±åŠ¨çš„æ”¯æŒæƒ…况如下: + +| 驱动 | æ”¯æŒæƒ…况 | 备注 | +| --------- | -------- | ------------------------ | +| UART | æ”¯æŒ | USART1/2/3, UART4/5/6/7 | +| GPIO | æ”¯æŒ | PA0, PA1... PK15 ---> PIN: 0, 1...79 | +| I2C | æ”¯æŒ | I2C1/2/3/4 | +| SPI | æ”¯æŒ | SPI1/2/3 | +| ADC | æ”¯æŒ | ADC1/2/3/4 | +| CAN | æ”¯æŒ | CAN1/2 | +| DAC | æ”¯æŒ | DAC1/2 | +| HWTIMER | æ”¯æŒ | TIMER1/2/3/4/5/6/7/8 | +| WDT | æ”¯æŒ | IWDG | + +### IO在æ¿çº§æ”¯æŒåŒ…中的映射情况 + +| IOå· | æ¿çº§åŒ…中的定义 | +| ---- | -------------- | +| PA9 | USART1_TX | +| PA10 | USART1_RX | +| PA2 | USART2_TX | +| PA3 | USART2_RX | +| PB10 | USART3_TX | +| PB11 | USART3_RX | +| PC10 | USART4_TX | +| PC11 | USART4_RX | +| PC10 | USART5_TX | +| PD2 | USART5_RX | +| PE2 | USART6_TX | +| PE3 | USART6_RX | +| PC4 | USART7_TX | +| PC5 | USART7_RX | +| PA4 | SPI1_NSS | +| PA5 | SPI1_SCK | +| PA6 | SPI1_MISO | +| PA7 | SPI1_MOSI | +| PB12 | SPI2_NSS | +| PB13 | SPI2_SCK | +| PB14 | SPI2_MISO | +| PB15 | SPI2_MOSI | +| PB6 | I2C1_SCL | +| PB7 | I2C1_SDA | + +| PC0 | ADC1/2_IN10 | +| PC1 | ADC1/2_IN11 | +| PC2 | ADC1/2_IN12 | +| PC3 | ADC1/2_IN13 | + +## 使用说明 + + 本章节是为刚接触 RT-Thread 的新手准备的使用说明,éµå¾ªç®€å•的步骤å³å¯å°† RT-Thread æ“作系统è¿è¡Œåœ¨è¯¥å¼€å‘æ¿ä¸Šï¼Œçœ‹åˆ°å®žéªŒæ•ˆæžœ 。 + +### 快速上手 + +本 BSP 为开å‘者æä¾› MDK5工程,IARå·¥ç¨‹ï¼Œå¹¶ä¸”æ”¯æŒ GCC å¼€å‘环境。下é¢ä»¥ MDK5 å¼€å‘环境为例,介ç»å¦‚何将系统è¿è¡Œèµ·æ¥ã€‚ + +#### 硬件连接 + +使用数æ®çº¿è¿žæŽ¥å¼€å‘æ¿åˆ° PC,打开电æºå¼€å…³ã€‚ + +#### 编译下载 + +åŒå‡» project.uvprojx 文件,打开 MDK5 工程,编译并下载程åºåˆ°å¼€å‘æ¿ã€‚ + +#### è¿è¡Œç»“æžœ + +ä¸‹è½½ç¨‹åºæˆåŠŸä¹‹åŽï¼Œç³»ç»Ÿä¼šè‡ªåЍè¿è¡Œï¼Œè§‚å¯Ÿå¼€å‘æ¿ä¸Š LED çš„è¿è¡Œæ•ˆæžœï¼ŒLED3 会周期性闪çƒã€‚ + +è¿žæŽ¥å¼€å‘æ¿å¯¹åº”串å£åˆ° PC , 在终端工具里打开相应的串å£ï¼ˆ115200-8-1-N),å¤ä½è®¾å¤‡åŽï¼Œåœ¨ä¸²å£ä¸Šå¯ä»¥çœ‹åˆ° RT-Thread 的输出信æ¯: + +```bash + \ | / +- RT - Thread Operating System + / | \ 4.1.1 build Apr 24 2022 17:24:22 + 2006 - 2022 Copyright by RT-Thread team +msh > +``` + +## 注æ„事项 + +暂无 + +## è”ç³»äººä¿¡æ¯ + +维护人: + +- [LinYuanbo](https://github.com/Lim-LinYuanbo) +- [breo.com](https://github.com/breo-shenzhen) diff --git a/bsp/n32/n32g45xvl-stb/RTE/_rt-thread/RTE_Components.h b/bsp/n32/n32g45xvl-stb/RTE/_rt-thread/RTE_Components.h new file mode 100644 index 0000000000..b2528ce98c --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/RTE/_rt-thread/RTE_Components.h @@ -0,0 +1,21 @@ + +/* + * Auto generated Run-Time-Environment Configuration File + * *** Do not modify ! *** + * + * Project: 'project' + * Target: 'rt-thread' + */ + +#ifndef RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + + +/* + * Define the Device Header File: + */ +#define CMSIS_device_header "n32g45x.h" + + + +#endif /* RTE_COMPONENTS_H */ diff --git a/bsp/n32/n32g45xvl-stb/SConscript b/bsp/n32/n32g45xvl-stb/SConscript new file mode 100644 index 0000000000..20f7689c53 --- /dev/null +++ b/bsp/n32/n32g45xvl-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/n32g45xvl-stb/SConstruct b/bsp/n32/n32g45xvl-stb/SConstruct new file mode 100644 index 0000000000..d6b0922512 --- /dev/null +++ b/bsp/n32/n32g45xvl-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 = 'N32G45x_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/n32g45xvl-stb/applications/SConscript b/bsp/n32/n32g45xvl-stb/applications/SConscript new file mode 100644 index 0000000000..01eb940dfb --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/applications/SConscript @@ -0,0 +1,11 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = os.path.join(str(Dir('#')), 'applications') +src = Glob('*.c') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/n32/n32g45xvl-stb/applications/main.c b/bsp/n32/n32g45xvl-stb/applications/main.c new file mode 100644 index 0000000000..69f23c183e --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/applications/main.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ + +#include +#include +#include + +/* defined the LED3 pin: PB5 */ +#define LED3_PIN GET_PIN(B, 5) + +int main(void) +{ + /* set LED3 pin mode to output */ + rt_pin_mode(LED3_PIN, PIN_MODE_OUTPUT); + + while (1) + { + rt_pin_write(LED3_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED3_PIN, PIN_LOW); + rt_thread_mdelay(500); + } +} diff --git a/bsp/n32/n32g45xvl-stb/board/Kconfig b/bsp/n32/n32g45xvl-stb/board/Kconfig new file mode 100644 index 0000000000..0aac4afa40 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/board/Kconfig @@ -0,0 +1,190 @@ +menu "Hardware Drivers Config" + +config SOC_SERIES_N32G45X + bool + default y + +config SOC_N32G45X + bool + select SOC_SERIES_N32G45X + 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_I2C + bool "Enable I2C BUS" + default n + select RT_USING_I2C + if BSP_USING_I2C + config BSP_USING_I2C1 + bool "Enable I2C1" + default n + + config BSP_USING_I2C2 + bool "Enable I2C2" + default n + + config BSP_USING_I2C3 + bool "Enable I2C3" + default n + + config BSP_USING_I2C4 + bool "Enable I2C4" + default n + + 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/n32g45xvl-stb/board/SConscript b/bsp/n32/n32g45xvl-stb/board/SConscript new file mode 100644 index 0000000000..ac5283ad3b --- /dev/null +++ b/bsp/n32/n32g45xvl-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 == 'gcc': + src += [startup_path_prefix + '/N32G45x_Firmware_Library/CMSIS/device/startup/startup_n32g45x_gcc.s'] +elif rtconfig.PLATFORM in ['armcc', 'armclang']: + src += [startup_path_prefix + '/N32G45x_Firmware_Library/CMSIS/device/startup/startup_n32g45x.s'] +elif rtconfig.CROSS_TOOL == 'iar': + src += [startup_path_prefix + '/N32G45x_Firmware_Library/CMSIS/device/startup/startup_n32g45x_EWARM.s'] + +CPPDEFINES = ['N32G45X'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/n32/n32g45xvl-stb/board/board.c b/bsp/n32/n32g45xvl-stb/board/board.c new file mode 100644 index 0000000000..253cfab743 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/board/board.c @@ -0,0 +1,95 @@ +/***************************************************************************** + * 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 board.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#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/n32g45xvl-stb/board/board.h b/bsp/n32/n32g45xvl-stb/board/board.h new file mode 100644 index 0000000000..a5f8859272 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/board/board.h @@ -0,0 +1,68 @@ +/***************************************************************************** + * 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 board.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "n32g45x.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/n32g45xvl-stb/board/linker_scripts/link.icf b/bsp/n32/n32g45xvl-stb/board/linker_scripts/link.icf new file mode 100644 index 0000000000..4f961659c1 --- /dev/null +++ b/bsp/n32/n32g45xvl-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/n32g45xvl-stb/board/linker_scripts/link.lds b/bsp/n32/n32g45xvl-stb/board/linker_scripts/link.lds new file mode 100644 index 0000000000..caf3947f1a --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/board/linker_scripts/link.lds @@ -0,0 +1,142 @@ +/* + * linker script for N32G45x with GNU ld + * BruceOu 2021-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/n32g45xvl-stb/board/linker_scripts/link.sct b/bsp/n32/n32g45xvl-stb/board/linker_scripts/link.sct new file mode 100644 index 0000000000..5333a7455c --- /dev/null +++ b/bsp/n32/n32g45xvl-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/n32g45xvl-stb/figures/board.jpg b/bsp/n32/n32g45xvl-stb/figures/board.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cccc488312ede7744bcd86044947184026ec1d47 GIT binary patch literal 1060611 zcmV)HK)t_-P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L|D{PpK~#8NjQ!#Ehed-YY-bZ}(8nUOJnF(V@Lzl}^T;6IYFDY_F27#N>J-{=ggdj?QN z5x26tAC+B{&VE#P52ABu0u`OTsOacLd3!HP+Imsg+Kv2{Zsaz1A*ZPu*-c%@YV1^! z*`P^Qy+{YL8aj~O(50lNYY-hn<7gioN5|j<+UT|oNO%nG0~Cf^2S(8|JcUu7r^wjU zqH^VYMTRHll?;tj^e$zXGRWUEFs7GT^o#KKiAY#}t4MSIC`$QTO56KTLMi5NDr)UP zK}!$voB6w%L@>@9ys_HQ`GLBMSr-tqUH1`gnv1brXyxuLngA5O%zN-&?BU5N(dN1AD&OUSx zPhxmv5Yx35K<@@%;1?`a?Ziap9*m`J#%S6m^u+E!Q`j!lhU`R3*lu*j?m|n%9(2U) z!*J?$=G}>WB8A-h`>_t(eZ)hUx4rl&zS_-b~qonH>6awqrJT8}n>toSe~m9_Pte`HeK`?{WC-k)yXC#LZ} z6*FHk+g~B`=CcjT{mP@ry~=86M@C&cg7T~2n^gv{ta5l}mccEf6fP9!^invamcTK! z7-7XV@XM{l`{ZJLOew;<;$Dean+@%IH)#{x@@*U;ZYqjBlHF1p|6kW$Lu#``I5a*2{RNyT_6 zzbB~>uM$h}GNA;|;|uX3;TvAWf5Ypz0=$uMocO=tUF(_hMiwE(WCFynhN#`6l3$Upx+ZMZwB75;ktp zu%cMIMZwH15@xOpyF|f~eoMEnjQ_h=mTjKML_IJ)sT;t`AE z;`fN5#NrU^J?ze~dpu4sd{W|B<~Yk7V%Ww#3U&BM4BnbyXl5yxu5>7>C;3VaGd>%@> zhBW>Vo&I0Qe+V!F1XVpFxR+jt!;z`5k4VCvz-USojQzjD*e?Qxz7a6;4u=t4bH7OJ zbq|Gw*H;+1f59&P@Exup*y*TXXDPsN$gWSj{}!D%+E zGrUMAKPTa6U_6coCgC*wXM&P(EHDvA17hj&W(UUNF#U)8V{n8G_oyGkyx0eL3`?&F z>~jmn9@j8RICj(B?HY=m{5=Ld=N-;LFmMW@8?1ikCg%`r=I`0!5RA=^LD=TVc!syr zHDKHhhX8DM@Wa**zS#QS8{6M{VaHn^?0oGBgIAt-8xW4p)>fSJVIyWf3x`iIbMS%L zM=w}^^r3je>Vp@Ky9dIW@xOX}hS_@$TyXM2+Sk|U&)!Z5SP6`7z(Ru&#!`(j&CX^t z!vJHM+tCue8g)<)V$4E8c<8+dfhpUMsd})2 zP+VMw-qBf{_>_SCybq?l52j8O2XTY3pV!}zvfJ@9cJaRKVVZ%%XC>P|_`~310Pjs8 z@6BgylQ{8zlrZn@$IsYF*-hE?F$lX@pMj)11~P8|{Q)py*qHV2Wcps-XG6B@eU2g_ z*vn(>p)27%ENjFzZsy63%Hu146FU&^Xj~3X!fm!;8xOW`cXoJ8v!YnLYhvye&Wk3vcuZTcD_%9eiL@SX0A~%Wk!_Ls2c~pnX z`+tyS4oH}tq74;*om(tyna6@1svOsx=WD@pG^gJ}g(*CLb1DT>onMrNq*=2gx1isY zai*d)L|9f_Q=YT$6eyQnAQA=5Z`}->i6V z?Btki2e!;-MX}~@w{haL!24{?_HFs@6D;0&!}5(MoI^v=R$GUQ(mvjK!S1~mGjrF8oGvtjLWF~!tSKx0)9nz{5f2I9)>^g?Qg07|G7xv8*C#E@4 z=$bQb|3?a4W9Bn-2;;NBHbgLxXTn7C(cMp1@|aRA_$*oR{+ZD=;XO3f)n~ypbMf;S z77Sam4hy~T*)?@!o0WPA9_Dl{1weS7c5IhcJcfvwJe&ISbKtY_k!8g%$L6_7-R2)d z>4w1gBm2n@!PF#Wt*KM333fLAiLebwfK^}uYzQ&7?Ej8Lq~Z|eKzJ$+ekBaX=cA@~ z6yxNO|Ai>qf2^P~SWj8~!4JRiAzJa?4?ofU`7QnL{IHU;g8pA9tKa!!+ZkB+WW7u{{AZ^=J%c>(Bn6>rtKsI ztOxqnV4-Or#?lNikztC?c#f7Tx1l554AlX9k>hKKFHWWibGAg7g9Yk88(}ha6Grm( zA=lp;9bZf_N$3%Pna=vd5;H|tEH6{p8!(k4;3C$Vjmr8W;Tb~BQsqVr5}N9QO_gP4 zsdf`;;!Thla1hB}#z=DAhkWn-DDg2uTLjN7$r2q=d$Cx^j;facvoNOsW`3jxUsALA za8mK}LE6cCwu9GlEAR34cRmCUKkVQ=+{F-VfNcy5+(_K^w>&nFzmsvh2sS%; zY)KQ@CNA6gcGk0X8RPR5mYGq*y$LG2uLZIVh6 z6LwtEdG4baDhXpA9-E!#9?D)_+CIkbXXj^3zY#krBf7>6OIhid_o!oqsg8O-J2Vp! zrb(wP9i*9b#_TL5Y{HJxn0{l{V@$u4GvYC&E_23Ps7_WoZ&46m*!dA6bn)g6nrq3< z*^=oNtk;6+(veHYEgh%im(Jco^86`HI&h^tq<%@4vJ@-ETQRSd)XQ{BRaQHuIj@r_ zEKw{rl1^70o9WiNG9sd2ELoQgJ8d;mrN{_X+MqQ%Z(F*y0!u7s%XmA6MY%}Wj>_ z@B7llMUsDt(c666P~TF;d|mU3>_kfX|7_$LE70?p}rsRet7UefvKI!HBZw zJ)dL7Nt%?Ay7aE{^Z1554}im=WYIxgFdEPipz5` zRjG^hB?Lb?PnO#m9Q!MEAtPZVM*7D{gNfm)1K#WoX0rH!OaQR zNSttv!66PRWMHA%y?~1VH^I=7eiPbPP}9YmF3B?NU5d7#F zjDK?r#1Ae3_^YEoexUr73gxeFeelCuZ~XYm3qMnSeBp(kUU=e{=M2B_#;R97`01sW z3a@_Vg|$z;mAmq}H-4tO;+Z#AKA|vv75%H8`>3>)FMQ}{n02gR*_CufR3amDIKE?9lv0jutP!0LPNv4*np z&O1DD@kMV-6HZg%tp1(Aa_2oZ-g%1+x8GpX@2|hhhTAW(?$&d_xl8Y1rH9uyH^+M{jJnrMrb2s12}v!m(>2j*rJz|0JE;d6X8 zANUaLdQFgc<%{jF2p%sfyf-^uGR*t3i)|(=EdxUnv&sy*neA*d@6|TmgKfO#+n>?@ zRKh;k`@$bPd9Szfer#g;CdO^0yPb7yqikh;%Kw~j^Wqb>Fuaw=+Q#~}%JJA9R65UP zEB)JeF5;JTDYN6HA9k|bPPzt6+d(m)UtE!GJpZk){IKmc^SvhIybe^qZ71PcWC!E6 zGtS@*0f(|j@(`Z(h`b>L5x%9|PNwaWbapg*->}nr8;HG>J<4VH4Ld`|OZp!1za`|b zlQnwFj_)ly!Z#H0v-47EjN8NTZpQDSe<$PQ93*WY<0Wp-8+M-TkoT!Lsf!&k^NSer z7)Cta5yFxMJH>rGt|99-W@l|A$7MM=rWxxpVfp<`H)a`Q*0cXzsLHpG`3x!hVR#S~jOgCfL?4bk9A34B+VoAT% z!w;|{u-M*z4!gV0VEy|OnBRJYV|N}Sz~e5yeSO4%&rJ-ap2lMRO#+N7dK0WMo@;}- zDr+>x97C4RF{F4=To0na_Xv{Qjw96ZIKtkaKvT|jEcaWWm*89g`rQcWl;`;?Zd4}Kz zx6k-1!R0Sbgq9DV@NXQw{*4dI-(Gp+Z_hpP<5Lg(^vDfAQaS(l&o}|&0^tF!(8IK4PJi z*53Mv)i>W_)r~h;dF>@O+u}ZNvtkeFZ__zhkL&1?F=8C&mg*&=hqL{h7zm6mu9w z9(xh{(ilGXOyTp;99|DBQTJs#FuMgUY4-4YbO7bdGhe)c0HmKr5{S`2W=7V=sC6&m zZf2Ya!%SZ&T8D+v?MMy0fLuo-ELQ&wiz6qH6>|xmPi^4yz#6`{cOv2WE`0MeL<_;D zBl(B|nPr*h?uz7jOskR7RBs0Y;?k)=M0xsSH^E^ifno>YV;8~0fZ$<3;4~zpq@|@0 zyr(%Dh$5VL5?DO3MTBYFo)TgRFx#K_V26MVMWAIf>)FbBwh(}}(Z8K_Z6TEG5Qrh< z7!XLd(cQs#0j6z)Q3FZmc_@){Q6R(fV7vkSyWjXx2pX>mEU#IIfXXX>4N@ou0%DBY z!8|(!I0PW5SawrM?iTnEKV=Vpv$%WT1ybP(2z;ipB$!aC?)wnPkys!{QB3>DJXCT< z9C;flD-B0Zj)Vy+JQ<-GQUObvA=6YI#w&{p6{%QSWNJy`jj3#n7`LCwQ7k0N1g`u# zVHsm8Rk5&$h^4|(tQE{_!jZj+8uf+Y%BN`j%Fa(LDPmDFbN<7kAr=uEv1B+&_=}p# zQPV#hrJ1-ysOcXonI2{Mln%!B1U!gbSSj8oHXQLylkX|u1|T)#&& zMdsq8)O4DiOb@7d`l)EF>Dp4!NSsX7NPfv{E9Izs?AT%3QTZH@d3!1#J0I~!;wZz1 zJY`Bt%Ojn;y;m#_GG3;%j#B9z<%seC#h!}cuulRGQc>A6Y{#%Y70^M-5h{-(OglkE zbA;(fs7Q`5kE9)B`~hDI71lxKvt!&L$^rWADF>;jWNP~emC+&k?fn=}v11*FDC*eW zRI+ZNuxC54dFut+SMKl#3Py8fF|M->*t~Fu-Agyvy>P>U7p|~-<^sE?jyU$@J&rwm zi6i%);n2M&u>1WXj#Gj??;*nH1}dYkVKVzH7HS?~Y1|uq2{r^6GYsX}A;Rsh~|L zW`PucEzRU}8q9)HVIGvOTr=i1W!e1!Y1ki_1|!yO%KWM>|1`RqnD{fEb?jxlh~zb9 zIjPf%emTAw^O*&tt798cjHSGvND7QUC1F3?-+r%nn0Us+m{4KFc5KM!!idj@vBy{J z=d)qTc5TIH!znBUg@xs4u5RJrx(m}oBbXnbz~bZ-mZqlYPSc&i!t^v2CT1`@JcHq` z36xX~!at)0527n@A~X+2!!mI;ECXi!1`u zObTqm({M4q09~Wg|IiBa9bja!t4C2CHu^?k#it1T%_|f?cm&~RS9Y$1m=z9w_{%#V z{M#!p{2LX;U#Z~#MyOaz*+xaZl@POq9r~tMR0gj_ys?EHyO{EKu|wZQSL@^{?=^G# z9(K~(*g0?c=#On517YIK5#Wc<%JjbTLjXJC0PLmg6m$JMDu#D-#k^11`rZ$l-*H4M z=6ji9crPY;)6ZZ-0>6UbN?BgnN}zYJdE1t<7kaO zjLxry=#Srw+yE1NdTI@y$CjuJ-V03cL0hIhK0UTUu9G1a>$YJcQx7QmsUxwp=tWz| zJC(IbrOz^Mv1&7BM~)!c`7BD@c4DdiM~;#%AvO9Le4iae^b1?me%ge=_-&{UF+*dR zB{~w1p_O2@RByvk6#-^`Rs)#64g@7XcZjAl%zzzlg^4Be<~so;#=!}+jL$+>?) zaz+-0#wYQse-idm$r-tRQEOF1_Be-Pmy$3TIEP?|tbd`qli@v7ql(>4y6#`GoAG<7XvM!z z;;5MS(7%@*#9k^@i8E%0v7eoU5#2php5hu)G47`rQ#tNur(#Mm;RwZyO3jp`Bvblj zbY||$(Gta2;;1|=sOV%=XGTS4%Dj@_gnkn>+KXo#M{Xi2ot+0e3?uJEmZzU_`>8yQ z87HoZFFRwpX3Qt93B`#1{VH7(Gb&mo^qVMG!t8|TH<$91{q##+Qm2TK)TPcv^0Tw| zO<}%dtsZt>huC2sWrux)o!9|(uohI(7IZDy;aaf`So7Y>$kK`D#vd^(+UujEV@eB?|OL+;d zvhT7cxY!U}Y@WNo_K6d$9y`L80CVKwTf)n89JuoccDL`t`ubfQyzu~$z7LW1`4$Hm zcQBQC2JXyG&^Ma9z=QYQT9itu{?Yk?ODe7{O%|MUY+B>=>}%|N(5aLz${Hqp{=qC zmqW5)@tFf8-Xn7=e4C(5!bv8qDVHL%(cagNl!|tk`)3h4GGOMH4iiFv8O7W`oiLD& zeLl(9<&_9SAA*W6VS!?-@-h7rVS}!eGiLl=hK)p6e!r9zSD+-2d04**>oj6JkTes& zOhN|ZDEsL*@uOcCXY`3+LU#}AGL*Vi8uKw;&PhbdnMgX@%|5mvm5*UlwiRQZv%rh7 zJNp>7SQxnzTnH0}960QEiGnFbra`asIsF=+hrY%ZLdyVVM#eBpXqhFnh|CdO=0!Mg z6nL2zps%Z@ zar6?5jeH0MT>ee0Ee~C>?jaTNGY@QkMNlD}Y?SpMgb7(MvYv3Ui;DcHOEhkIC*v6# zh-+vL0-_2L99vAc2!7GUa0tu8Ro=J*9tkjXjvxhwV;dFK1}dEmE>t?~__tAEY@#Ar z$M9OluXPH=8Y-eSbXPkDW36Kd<3g~GN@*QOf9p8PTTgc_WexojUc=F*c$_sgF71LHQ?ibdxlB3YIPT{H!se3g?pOR;- z)G6h8J{#mXEVG_v*6G|0j-Ppb{ITwpC)Pf4#u@_5+PfdI?%oGAjdbI!8#-#raKSAE zo9}$U7Q)RYg3PAdZ?XCJH-s8O%&k}0e1i~k?HRUQeGCHvjM=4o@Opm|>N z{{u^1YcZ4a|DYws6scZ^k>O8(`C^C3jI9KXU(i)%iQqSO@O>iFN;`nbt>`a1gn*a! zh=0Bx)Ajo>DUd=ynNrh5;>tQ0ZQYAlVHC*d07n33xoHc=`|jY&yCbOcF~D-|&zK#u zN2vQv_&qy6%9zx64Bj}7fgZi)|SgN%rbj1R5ngwREzXQH0>^!L8 z_EM?u=ID1P!N7o{f*pj2odkiMjN8Tb@ijFaqZ8ve%+beo!od!X?l(JzQ@#)=|6aB` zuzfj3V2g7&Ht`;9;XT{N`@KzEw!iJpY;Vqy*upxtI!QQExmy`8evut~$PHYh*)F57 zg`)gy=i3-BaT4C)8l&QNxWqCX$8(N>fe7PwFy4Tj#%_-|{*E{mznktJ_jnEz;^~jY zE=l9)WG^4`z2fI+WjAG?m|gk68!~=3pP4=E01PQc3>$h7N<695*`XSFC1IauB6dr8 z@ly;%Jd;@`6uP{jVi+?z^)V&cQmrKGXr6%pu> zuo9-5vaIBjdQ4f)Ov*6MMCv6dNvEyqrV>%EzAWqA&tvUp8B>;#a{7FxOf#ogFwUHH zS*ZH7bPJ~2QCWy<&brM7Fz6THkn1k-0z1|!PM1elpN%d}phMyJ1Z1R6y{K!#bCf(*^jlCd$=U-`4yJ6_CtE#r#|!TOe2I<1X$~wc+2>e1 zc2Z*b&=Hmo9AI_-0}kGMgM)XT!RF=zSY5jd^DFmY!$DE7=L2L0-$Yl+RZM4|!cxmS zERFdRV9YU=V}q_#8^k*tMYQ8#6nr|1`2ssEwV%RR`z1uXoI}L>OK3{?9m_+9(Vawq zd36S%Z_i`8;1Cvyt#ttNr|Bcvain%05oq)acx4Ky(VoZsjJkwNh;=%LmW0zBq&+3T z_@F)A7Fm7=I7mB+p`;U-={$}4^!@OCc^tmZSK;U7g1Np5)u$+cnVCUnRTVyl=i_cz zF7Ab8;cjp)?uUI-;X90f994p#v{KxS%p>3sUIH|D+0SckB0|4F$v$59-Ms$$cyA4P z{S6ss%rupkA~0bWn900p*vm9Sx&kqhE>N+b;9)8-B-RqiACO7F(Evr@M_dIcbj80< z%2SMe1xN@!j5Ga|NywJ+5|;C0I@3%j#th5x1YQhzj`Dn%vM(`ZKVrf@#)y5DF=54+ zeVbaZ_AvyfsLLW_v(R1LfRWB#Oc7kB$0jg6K7pBuNex`4XRyHQxHvP*>#3JHEY4Es zpP!n+oQMLP3CvAQp|gDgF}Xds8&!deU-NN|*Y=`V!Mr)>VgF^ywkv}mYZ+7ovJWG` zScmah3s1+JoXUT=Bk8}5PA#Ibe;j5(Nm%I}fxmbWT-<~3S7(3xlY=k*^@9&~&|Sla z;D-lp_?hss=7|S3zVgDRH$GTHS^3HbD=3@Z$PSrsy#1Vkgyc%p6}O8`)> z1nVz7QBz2pExpBxmR`${WDrq4dMUhC_4{Ag}*UI(^g}y z=r0(lKa5C+!w7hG0Hr>=f$1F>DX~S+8+!!bH^*R>A*SWB;q#CqB?8Pq)GwGR{wt=MenoN62^0oh zLb2~r0?c6oOdOVHC)n96VWOuMUWr*$AXGALacbUl9|2)E+k*jR2Om5G0R*;7Uw8z{`eIe-+#eo-kZ(5PaEm3r)<)NxA0zW;yv3$|7HgQ4WVWu+uJ6( zn;lq|?k2`>6k%Okn6_0XTO0{Blr2sIJ5huh9@B|&$|c0m-RcyL&Eh%}WJFwIuw4oB z)7?t2+3qSLa1%#220Q8Q(us=W2x&K=W(VCZtZygF2($=j>?YjoQ~(sO@~e3I#T9VT zgNOji9uKih5m1=6%bl>|PS;HXAOV?OOxvYg4Q%!(XyNFR@jF?MxB@Z?W+a_q5mkoi zyH&adJPLX!dsw%`$?-J^lk?I*N&_SfrUZHfHUvNnnctXonhK0CUOHS8fff<*Q&|Xb z7%T7~FzMoqRat_Ss*mZqIt7F@K#@8GPPDr8#}km!z~m3O5tvb6Bz|33WIyvtJpwcW z83Hu|8B#_MC|W(@=O~hS%taU$sF8R94Jjk=BIja31*4#auH@0fj{-Fw(~_>#rK~K> zqd-Z@6MR%1a(v0B&rA4~U01S$#OkFFY&f_)^xPeG&)i`D*b(lIUI_3E#V3y-_iMa)H0IJ3cAD0|H#!;OFRqoS=88`Fa`MX_qmPa|+AdZde}i#8{>kCh~33 zo@R;9FMfsp%U@CQ`8*a1tgzgF8x!phk>YV4UFnxGTYeGCJx4H-egHwQP9f9#3>K;m zW1+~7fMP`vD~mu2VMc+A_(cdXYWj%j&A(!CJPhR#X9!E@(Ub8j`?yC~7=DSCWE&37 z4xyZV$#CK!%ynKtOR)ufye{B#zyrj`Mq;6_l6{Icg|tY;J6KnN{`Pi^^bcUPs{_M5 z0~qQaz%au@)JsFd}Sx zL|mpx{2rBu0K#^#-;eOaIAv`SfD!8p^9sCZbudg=$E!-CUr26 z8PmnJQSF6oRgSIV(qKWqv}5f#OHjM$_Os7a{VBmkri=FzTFj}VuDgFhQDy-qIy*2u zNPRszg2|C_OpZ<{>&xQwH2ddSP3A=A{!TDIkEOYJ4P+<_3T9?mc9t+RiK*c!2X7Mit^>bRI56Wa5ytakgCx!i=R@R0AoWlVKIY=i^H%t|bxbtKpYht!A5Y(S;mIoxJf}Q)?uKWt-0=Rj8=~CqpfY?f(6$yBCcq5H zE~3AnAljE#8hv0T_Xn99g`(o$d~0eUb2tTI8#3ub$7{!cJuiYO-%2@UacrgSP_>KVo6> z6%s=p!Q-9{(mt4BD1Id-bN&sJ9j6iR`x`#JJBL)~V?3uLSZ<5v!!gZnW*H;httiMX zMsj*3JE45U#bhBqt^iRn1qhEW!dJp>d}=i!6H5_AO8@vdib{`4pHL$(v60t(1Mh=? z%O>87O}y^{E+PUkTL>n~uZI``7ag=H>kWZfL5x6+#1U$?GA!UEkfT6{?Q$zS10@0_ zgqKY`_7-&xgeb}uwqJpm?aqW184zA}x@!4$ z^4LQJylzd(vu zY6M;+tm0X(9($od}d@ zfFrKJhX4-qQNak52*`*is|?dMP?54y7e}JHd}4J`)*I>Y#pU&pdIexC7-vSPwPgFW zd{2O3-)!~N0~U|mVM#gr(gA~|2^g;{z<6yQrW^7wQIpL3!;=*qf);oS2C5g%a89b?&6m@GPqrt~9lynO^tcTS-${5LFD5lW^W zV7%ob65M}d`I}g(JCCK-BbXtueEoP5B@q{}*mMYsC4`k48^VhoS}Zk?Q81&kz|;%G zn6gj1h{Z8)l!u-~g6k!o69H!UA?62fp(Vivxu1`tJ^mCXvyWi0|25jG?cnj@9Kt*v zAvZb@^W9~FE(%~4W~MRLR!?O-04&W?>B@kKaI?68WtqNSkSXjX%+4?1O=6|8zQ~l3 z-m0PiMkiu{5vz-&i70D|4oVcr@V<%VV;|d!SYX5wqpT{77ci0h%JL%lDKf33AV#Ky z{$zPElzIeS#PUKhrT=trE^H+a!vZogRV5&-K@98xj!qyT_^Pe@sqSD+%IhZYs5 z7l~)SWx9)mnT45o%ufrz%wUG~$h1;*^*A2H)Zo~cJY0>=!o#n*xbP{H&zx9c68KwW zXA+;0AU+FWX*kdRzh!VzZ7}*z0p?R_J$@jatHrv6mw)-_gMWJGg@1kNiN8H|!!K00 zzua@i>L>1m7caHTX4O+KrHnVd@W**}z?sSA7;Wjs)W9Idhet3zIHp|$UW^$5l<`SS z6INy>rbuNIm?xFV#hF*8DeXedPfTNupfk`ug!s%xoF#E?q@q|!h4QmN3l)x7O_XJX zisu&v3mU{|RvCehPz4eKCL%v8s1YC`xUj5dJ^2GVR!}5eK;jsPZ&>Qxj;YKaQI=?l$5)Tx?PVLZ25#jjX(c;^Rha6s$5#QECx=iUvXdRt zE-X~;N3z!;c;2=^?Wf(CD>qQDVqTGjyiHgf-i&V%=MnnY z0=*HN*+Kmki<7sJ8GZ*|cP)|cWJ-WpkLjWxFx-9sK2GQ0`tb~sJkPMBI|cM4^8wIy zA&qvoW1z7X%ag+#L3LravkB8ZU6|&GX|}5sbAx@D9~!{?Ko916yAY9@N`)Ma-EOf2 z2|@(HV?FPIK#Ty(2Hq3#>%#&q0yfGTqk|dc>L6w#fkpfhr+|fF@rwmU!U8v2*bykp zivk(3xk5cp=QtFQ6hKmKbG`p==S0jB6Z$g=sRi#B-M^rESc&T1B_3NHqOp$vV?_ThvA7UkL?pjhYBX>m&=5uha5M-ZR49ni;6;H3!^+yC10I19 zWkr!P0zULBYYibln^MxOEE2bmu(6Nv8jy(6PgC_sx&cMX?v-gGffIoeiUv_qR^UVc zM}rvw3^k3!dSvR!kmqJ3$6$Su&x{bDz=a*Jf(<1CFH{0l8b(ys3W8L;01V?442fuP zBjrTIuK-9y>Y%IYlylJK(IAFEpaT-|D=Umn1QHa;h+mgS;N@yawgL?;pBAqyB2-oa z90DsAj1!2_TVnJgaHgQ-PjPAriekgOR&+(QDW)`CKAwX>jpP%*F2CfnGTiIkY7+z4-(m+}i|% zvxs)QjJC9UK+82Owx7go`2i$*{EBa(3^yOga-D?+JoN;Zda=IHRp26iihB2pZc3@^ zcPtD$p(6MslHD$1u7m(H@&@x`&(M}~5Z^u@MNjq_OntM*e6J_ks%+u<}=uW%b|E;v$tY0cL5D0JDe>$+fTv%7S@7h5{1- z5&;;ozKGRD*1QNPNStPw(X1~bYC1^=9tvVqJ`G63q9Tx?tU6LwflHcNC$o>oF(Q~~ zdFT>QWZjF@A=VdT%6`^mPv8*%mT4pb6>-Hvq^vc%vH~{(=4#5E3S44i92_RP^>3rUhQ8n`PaQ+8w$`U|H0_ML=+oqJawm z@Xw+kMzhA~Eiwz!bJX{9n5BN79iKvJ^)Rk~t;V&OeE4M*AuPQDR_s#*VAL8m|0K0= z+A=H^M>1Q1?)@y~C(@y{44fE1r5{{Zk*jO{ zWkeuD#S6sf@-a@uiz{&|Pq;QUB;^HQbm>w?4=fU1MFpmZ8cEZOvbMZuI$iO9k7M3- ztaqJESBcfQyg~_bHpfu4C zFRmTKyQ{Y7`m!BM4vV))^ z78kM9=&dpWFlvg4@iJYct&@p^fonYLp`Yb<6JiYCM8V1_0sCA9RJ5rh0Th9kZIWLs zF#<7e5=XF6mKhCXlof?Apofgz?gSHo7ahbXVZ7d|qJ(~}oCYW|{iGK|0U2>U2suns z$IyX_fRBte_0vR}1xN!LLzYofNX%m>aRM}~L$kglz?5NQHwu5d3F8D{jG0%hZ_$Cq zeu9gb!v$g#C@Juu0^m7mmKP0BMD!4%*3mF5kRi~d2N(^0w0r^|0vG}uX7r1-MK5Ae z5irrijHz_83|lhaF)ArN+=!S{xrkN7LWzWRam*v@X#_?DKCE?XU#zKc^p+ZBk&!rx z0vDFCVLdifMzVHBM%VhaFWai=#9=PHB zOD7ChWnrSV8Y8W>=&mkBS5+B$Yb(%GS%`s#QYx?(ER6T^dFsblXA1_4zF@rU5_-N} zz<9|`_A6hoJmHGbR4Yt;JAmfQLvVk144^kHv}` zSg8ILb7hB6`1ugBK3(O&=pq)%jxy~4&}aoTSW|2WEc7d}Wmw_`ZYTrqc-|jS8bp9` zCBRf1p;({}{ZUUMF1rj@h1Xgpwr%Doa$p zV+5F);VvxCjAD5~*4$}n3UVZ$vcM2vlB!_;IS1B(gcyH;3O&5AZ4e&BuR#psR9HlV z8O>snioLu?`n4+xK*Wl|ylR?92|+_a3*kiohWFb@9ZT~40Wx~)i-=mVOR;1*bC#F1 z{S>Kxzb_$)ep8kaSK7KU2RnxBU-q-V+Qdn0W5MTmI8}V1C z5d5p7KmPTdFaG6~7yh4T?)cXSF8JGRNBnZn1se!2D@gP|%l73*9@z2R7mfjG=&xzP z%n-?KWCT;Aqa--7wrCe%f$*{hOX+}&^npsNXgycj7VisgoGr>k*cAgir zrJ)Zm!i$vR5OCS<8i@_O88TJ#GZm7+iol7oqA)A~qo4NC0EAFMS6M}rE07^mJ(@K} z{F>#3(4(6slKLb~U`6GTIF|cS#c389sauZo3(Lq<)vAvXnnmY5;e~aJU)J)h<2kPp zfYGgiQSXj<;EGju9I@(m2dujJ0h{UHe(xhz-*^j)-`}DkI|T!E<>+s$L04@RIx9=j zUt5gs@+>reOGe8#LSudsx{EU~P+f@j93QkN7z3>YhtYq+Qs*vAXa9uS6l1))dK4e8 z*`ZAUriOsivI%q3za!T36g(f=qE2=p_3XxCl>sUeY~lI46|!F$VzzDvCNi|G)7o2j zx2W|nVvW(lTQMtBNm<*mSh*47J*SZ1ege@i%rKU=iJi~CVrl9Eiev90;E_41KJCJ6 z70VWHA&K8Wkn?$VFlUkOcp6I$XV_6?v(c0C`6m{b@z#3GkN5Mz>ci3mM@&n6AlSjo z5rPF^Ci;3fTI^O2SxRBKwxZrML9IyA{5IO}vMj+0Mj*vyCDa7g6?R0y<4x>#3q03+59rtKq4NnK)nxya7=*sDnF|J@tLyjI4H6Mzx; z(V&A$LjXnx9(pT_fQwjOWDShCYU+sc2f)a*4#QL=%IYE_bx5253iF5vxcqqyj0QG; zz>9>%x?<0BkOjutl#^IoG|P)vW-O>cEUBmzu!tzg5NOeW!-}rJhXNT9Dl7#e0wz>~ zGF4c>01W6GCa|neFIJL zmoWP6HkOB@2r!-)Pcz3<(P6aa9EHa{4uYPZM|;{up!yKdMS$skjTnMPzW+V+Cfvj< z;bpe?FzO->BF^DDs=}{hGWR6rN|?Wqu+n6w7V4srAk#!?6qunXm+8Y!7%0Dsf`F4q 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≫Y}BM6F?D|k&Ch<07GzDo*JW{!ZLCpmgWdC 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 z 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

1OeMgv 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

mIohU|uVLxnS#w&f0R^@{S_7xM%=F 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�>WDQiJaMC##4&^? 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�yMr!GH)d&30sdJf>g+(q2D`2<02bA$=D zDV@4>+6={3MQk(VSgt|5<8EQQ4Z}xp{?ZLxzVQT`>!+3GLtsHaO{2g#?L34emQh+5IhOy1?W*h0)fL+p zDX#~J-`e1LWC}@ZpT`PXwE7wVY3-=%XBiDfeg_Ywfss&-nXjgZSVsdLEloR@R#(;6 z)2s*;vSt<@(GbY$$5RlI@N7fE~h{0um(rrQ2%|THS`Gu>%;L zJB^9sXE1r<4EE2R!4P4mabgyM^?R{+M=OCuz@;AVaa8;+!?!u25pa1cb(f02&5lL1 zGjFqf0UHqkm^XR+I?KO7aCwu^@&?cS4&!ez{FomVH$TN&_Pf?IJuqwdK=ElP38|lT9J6G_7?Ed@oF@NWez)vq2evc=Q z9wMT;1)oQzVOeB0jDnMK_4o`1<}Tyg;50b+#$vXk5kH>PK!(R+$h%0178n08;uB;! z^JP`i^4L8Oa>9!M%nI37z&8zso++^Pjz?QvBX&3TV6}HL9Qff}Pk>pw z>mWbCqcALD$FQRvHt7x6khz<`yA?46rPQnn6qnT_ZTA3zI!>ys1pH*Rk(xphXLU!^ zCXll9dR66qSdVkBeT}(!jXLN0Ds`pa{5Vp#YEoi@=en2=(k0H&3oLVyvF5$%gkBwu71 zuTczuZ=O7g+ozA??ujF~duk3(ubjox%a`!|ojaI2&;OF(A_lwyJ*vI{P%c3=tpa}D zF}QJf0ymG%;ljiiu8a@k+Q=}j4-ez}2M@8Q`v4q$(y`emLjjCvUp9EAW4(JC*14pp z9kCxCpT^b6gE-&27bm+qaiO;px27g=@A@qSg>HvK2!SP~5;neMQ%%4t-d zdBsDoDZxdi-BuLwe<|#y$UTw&O1oD^BK*$DIvzC zi~;Y%a^4?9ikddkl@pNBAV!-q5*rr0za1TGDSwBISPLJ{at+X?8}_${tG)&q=)vN8EBkLT5a z%kQE)Rxt9rh)s;t*8_}bNi@xirYTVnBIO7N0x;TCkOnadXjHp8(I2aNY?oyPM1I%Y zXdoi(N;w5Ry1D{15*H{D&`@bIeZ){{a&-07b_D_=e*hV=aZ#Y7>Il$iHZPU}EeuyF z55F>fq{YPs#$Ex;1U6RmVO`l?tm8Lgo$N-vdj!t^GXS%;vInoGl*%1ShN8T^mBDU^vkSrqED>%Vs7OmkT4

1`2j|MmPZ{N}S%g`J%ggJGv?| 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%0AMiz%*xZ((mR$5UkF>m=17%XSn^8E}CV6KGb z`(VPjq1hf7E!mA_7W?3B>xD~o4Y+o$9fQ@CxR{fPGf4?(Pfo%4kwWb|bd zD8v+`)2dt{oJiPBVCf-fbhGE&t+XwvxRjQNOUd!dskbvd5$6&ja5gpsZL#5K3JpMW zSO8k1we6OuV6?`DvP=}gCKmmfNf^wQ=^D@CDC5H@`` z1KmY7cyy~C4m)>Z)6D5OXgC|uJ1o!?;)eP_A6{#$u3R4aB^0d@kKLY`i#^UUSnC`M zOM>vo@Bl9LUc)B7Pb=KwvDzaME8G*Xig3M-&u}fpB|H=NZ;zwxvgAw0I=-U^Lo$^1 z=IO&n`1RROs5#e%-30V2mvkDKz#N3h(Bgad5R=(}(@o9j8@!GkJZ3;#I?w$!VscKx z+&)a1XU*AZTk05&rA`cOLvhqU8V|1xeU!VthOb2;a4pm1t-< ziHw{Q9M3C6L+1!=@=xLMqj3z4-NorELpXO~0B73<(0;xT9q0RT{^B6oFAw4R$QXtR zteZ1VYnl@U90DJj2*44@W<}scU`4l|aRo5~FoYjjZCXJK)0K9G zWfUYyND(uVex4ZxFcdK*X%4Sdi>yK|+86PIS(V*{-G!&I zBfSAD602Y#qma~Mjwi7`uLX^RxBq(|7`+MURgXAK)&b1l?ZVYCYMIb(ik|?30EK|d z?=$bJ(Lxk~4oy2F0HaG|V=ewAGJ)I6q1CKI&40qUz=`Y^4Tubn7KqUxLxUTAdA$}! z!3#fZ3VNh2ZVP;lm(^Avv?0t}BWPQ5a;T4|5i_-oo2O#|~%Yarx-% zuM>>krcC08`|Us(rY-e}hA17AdRNuPA$&7 zlugc9eb5t^Th1aNsRE`pX|RqPhYbP7DoQ4@y9H~B$KHk|L)mtW71jMc*r^$M#c5Y& z>Ai=eNq2E5Uh-bUSDxAUR0l93pXmHvzHv`f!+N%Mcduj6F!WE z`#i9SK(p{@AQn?3zQ86J3vIY<>4zm&{#tnG7#1G%#_B`faBvStVNwp7%PY`WQi#(T zY3LAV+>BK85&%R)(U+Tz{_G58(h<{6C!ywY65)g*J}p-WEnO)x0x20i87YL8ID$_s zPK5`eHpm|p$Gmae+Z_dNj>vbiL!N^@a_lJf6bCzG+uI^rLPrPWJKCVg)eco&PBQrbZ2EpCx(bfqr`vUiu(QO@Ip4t2;Cr|%o{q!D(_uOH zdz=Y$ri7r%+aeF2(Zr%I(o;kiaoHUiRD<9cwB`tv6U>b zZ=O^ItBgwA8o!Ctoj2H1tHx5MnI~4F;KXU*=cjna-g|IG8&)M9N86<<=wqX|lOM#G zvXg2lf$)M;Xl?7j<-Y6K7F~>z`euxejpGRGSP+&A)6iU)gvw%>BC_aZ7WPDE;m*(i zp4`5LCwK4Q;rKX42e08M&%L#^6&EjE#m0~V*sx>Kdae_W@ulc)JBzx8^H|I8QCVp< zdOEt*5MVX3%OMO4?L$yYNW9zCjeY#heX_$HA8mHRW-Dj(RaBszKv84wj~c>@0L+j_ z5Ppr7#TIikjYvkZHZ!g)9UybU2z2P-Bb)#en~DCT;W)l}H%{z2iiWM$C|N%L1C z{D(#Gp1BBqGv*`N#2l9oSmW1-WNo54HRG;85$n`XXcr?8Qvf7Vg3|G8ND68rE3hP* z4R%}&=0=rcPGlM8#Z+h@Kxh$%SmiX!_>Rna)ST%=XyF<7h33PNAnN233wy6P*my?6 znW3j|B8~+lA%e$ENXSN9LKX`6%v_7kU|YrsGYp z7*a;c>$ER&E&?ZNR1!le|I+7$AR=i3B??wp zMqowa3Umk~0xAL}FX2VDnMd!aE6%=pVA1=*C@qX=U$`w0BSWbLV0IN~03$vy%Tubb zoB(5y-GGC~+c0$J$$vi&i~x+S_`rC?6JTN$zLFLfFb~+;)D}D(1<4HErN=q zy-n~CXpu!9wQWj(z=w=d%2uYP$pN{TOwgG^k?lzgC;R6xJqJ?=D{7nZsZ5*3ywg}# zd~K$%&MAbKiGE_Dk<)@+gnOBZHqD?asNb~r%Wg)YbgoDNM5zj zrVe712>3Y1VUj}>CR>ML(vcv%eZUWI%gWRugqW#nX#o%A%)80*82Z}JBQ%x0w8JTI zNxTEwxO-|D0jtsB>Jm+W_I7YybJ#s_4P#6$s<`HDfj`|}cDg)>0Poko@95&AWh;;PCC4$H$ z84jJ9rW*ckLd%t`3<6DtGUZ$m?Tct$WVBHV0VX8@=M!Sl9v6+%(cw558idMYJ}7o~ zL!OHxA;l3HM;(x9YmW?@qe! z(HdySV~YO{fi63X@FJ$GLJSlY!zrO0OQXxwD$#vI{kYJ78|HB`C4IS?rB~*R(dLaQ z#}azI+YlvHCTVDiKg}0xzE2$H>hG*pXIGD5}Qk3!NCh^9Tu*=W(TH z7-KgG!u&9HUFpK;$Q|TYpTmP2H*w~|AeP8741^X#0*gUlHVgwZ)r#Ho_}kePk%K!U zgSdC&1|HuY$DOe;j1Awwk=Sy?6_nxj&@ieSE~53!MT`y)VQ*v(3d_sXVvptJEx2~2 z7iBfAFmZ||yhOr)-_`|uuNo>Vai@O(dwg^7(JoKCN2uQFa13Lur_mgmiYfsZmtZuy zhG5Vs06zyOXkZackO?7hh_*#0my@|!q69nyXb2m!rcqor9(g9>mYp9Sh9+RtDFm1H zxS(nMK~$M-Mxp6Ceqvj)Fs-SKpx94k;3D%llyB(8nR>9 z@W-;j<+C!7N$X_Dv}j*+W+MR`(Z&eOEFfsQ7uBPyrypY@*U{I14OhBH(bIbkT_Qb< zQ@VOb(c3e^XLFq}I}XRfb~TsG5;opzlPa+-xeD7-%dsh?5*w3`V*}xKeL@*FBphdW z9BcUw$r@Us0TPXiz{pFWP-%n!0TI0jbSN0n_90GL%_KphH23Zd(9^p#m3zjq+O|Y$#Ka0uR}z0}x%h z_^b%z%;o(tP}>?VUrJTL+<%d;BbTzi4A^5VaMi(Xy=jNS28{MDTR<0fk%Md9zZGLc<4K2km~nn^{Q zK~^TQ6FAXC@AL6ebE0eT1u$fvG9R(A6VU^XHuJ6qFtV(G=9sGig&t%y@X*rqW+lD+ z7hf2aM-zb-sYjWZ7}v~Bl2;R%NKZ^n;xnTlhV^RjldQJ?ILuo7Wz_jASYbZK#ivKo z1lr`<<=Vt-BtWAeM&;$Tdudu3F{^22qu(J$?=PbV7SXnd2(X9`jA&tA?x#%j&r~Cn zB$WITpF${^OsJXUOSmDd2=q*m5ljqaShmEc5`NxQY221FEI*m>@@@c+!E<_x*Q>NF zygy<#(tKSs^N^U2ByA$ERb&dUO_qTW;1RRZ89 zOgs{(IrJX%$0WkclzrZqw%ZF+_>taX>xZF>7Z97*i0L~+U>$h{Zpn8QuvigZY!eyR zt%u|!lB#K5Bu!~v67In=?hf1uF>zV9u`c8!{^^#0k6jY*PeRK-ofxOgv5&$0%`Pxr zXA2{{K+GnXo9^(0$?}7kx6=h*vl02XO%T4d4Z$q?aLggx{6J`#$?cg|L6~tQ0N)?- z$MpR^SYhMGo?#~1YU&Zmp74TQ_E@>@Fq$GF(M>4m6lYr*{+yLfa7n{uF%c17dYCRI zBJpFnlAet7iLq#njznExfYP#*dU>MI)g5`x9>{TUMwYz;vIs6&whn|BJ0u^mLh@lN zq#Us(lvpxu$+!TFHIfK2iQFI0wCH^Y5VdCy!guVX>_YhVoe18x6Ja~I6K-}R>Bs>B zk|Rz>2H{e26b5qB2q9StWQGg!70ifp??3^8hS1VS*cjkG1sr*qF9An1IFdeGT#WLN zNUZpBI*vQ9#m}QfsE;S$S${k^z2a0|<261v#q3SdMQD3~c%lhZk7)!^~nyExZ%1IuG;m_~qM z`c5`(ojpA`%LZ{Z8w_)%9dACbhW6gMbr(0s?;x_G70W{NQE~D#?h;&Xk6uSt-w@og z*~k)BR!0_MtIUrRcO2WIORzJh3>za$aUixBZRant+*w?_+=;T-a5BXoOBOEuYCZ1@`)l~5GX{$BIX@2^T;&+ zdhLtELzylBlURVK$C7Y|zqR{*@fbZCj4QjHac2D?oLajdCpH~Iso8c^EZTtHL-zRD zKU#wosaxumS$@M(2`_{tAHs_d0mq*J6Oe$X(b;g0ti-&SD%EHk%DP8t=(J`!QY%rv z97-(>eVv*u**?D(X(wBe%jY7J-+Tc%&F#oJ)q(WJHl&`UoM=N#?HSk?urXxAtc~I! zgs=`n1sMVoY={XIhVe{eXv9!VRYvMq;(sI1Ah4l9h(L_;Nuem1kdXO|#GzLgSK1j> z7tfjL%K2AUUSCdWSR}825Vtje(ZEMDKMAPtTy*ED&nM@vG$;(kY_x#Tp=nSw(SwZA zu;@h7zz|lX4z;a=7nc1!6bR8YHR9~6O?amPiZ;tH>mo!50I3m8EN94l+VE*jWSF+( z*8oNXAkn}mr(LOoWsM0g0xe1lqXQG=&?|Z6m@nfR$S6M<0Tw;Hr2P&rns!IbNCX&y zi>86m0A^>wX>3lfhZ#F77VO+EPuF~4widOZ`^F zkP$rs2^yS8K86$pDQtB0P@`#OePevgr?Tbz; zBhI~&riT{=GK39fV)D~8HR8yv^$rEsAJeB(5|uBD}AX=WPPm1YU#E#Bh5OuStWM3~eqLmJ@T5XkP?i z)Ott+hza~azil6hw~mHlqE)cc#7sIIfJw4Gl0b}@m3DbxGhyQD<;#dKY{a|k95DA_ zJdQ^7;#l@WHM6dL5`l%F;*$CR&MEicoGSh<_msn~Xl86;@8EFMEySgb<5I^s7Kaq! zL+5zHO9DP3xcrmx8MaX{UeCH$9mYJnAk1-%#QdFJFebbh?Q+65Ho^Fq=l0P-Km42W z6@le@e&oMq_^o9Cz9YDNLvZ`1L^*8dHK1zG^N~HXGo$)lvkm zo}&P!Bf^=0l+ROoQ%q?cB8zHpAihYg-fb3=hs4rGoWC%D^BqHIZXiY=VDbr26hri=KE%;wWiE{6JZ~hi#?%PYFPnU%ySNZ6Kj3r;hK0k_d=_5BGL$&M<>&Z3ZfE0pc#7KoMYe;I@l#k5eooBAgJUtc z4|5q+GCq&6Y7|utV~Q-| zX~^eh6kP#BK5Jt>OJhROJW1y>m5JyUQ3OVmmV^MHX2ca3AZ&Lg$*YTNP$Kp4T67|#l?>x~KI+(7em%&DNL&C%v^x?ih*9ZUT^hj1 zwgxzAh_!67=aFo0ub5ebqSPcBdWM9a3a^K z&POwei3UdIu~8$E7?=Fw;45XtgeKRj0EG~t0ETso?~BsR$TmZz;Zl$y8W?SMUIj4( z5v7&ket{V&KjD~OJHwFm2slmj%fUnfjFgk-qk#_rN5K-$hvmgz=N&m7uU(dD5L1!> zie^d@h!Jy=4qkWLITts+JWQhS;vHESdM7-@xfMM_QExtPwY(g=C z5Hr~_7*hmf4h3Sup#Z$S#|N7of^p+YH`2?_;G@m1_;9@oRvyhpM2Y60Yad5oNxTau z!irN8LyBzM#ofaGu!V1su|?7mE5s6JqV^v|*q*%z*|`_N+jqfl(-!z{ z*o5G1+Yq^D4-yX@K!v9RE+$1N9~sfcC@qYFlzhguZDmFhUm1ZJrVZ#OsXGyyfYsCI zAlGg=etA-h*4%i+ZkmszEk-CkybuAa=i$(tuW=^OhQO1rMo5WIkT?qu6cu5(vA8YS1LIi5hHP=H&V;lZ*K~ zT;`t%bILMy92W6+BrA;@xhG&DzcEYrTUpF+&|>#Qtn`e>Nm-X{vR!sz!X{(B~V2?qjj&@QTGH?^yH& zCs9%`NO&0~6kTO~*J3hpmGxYW$UtXQ9*Uxh;mzlcTny-cB1S;e> zN)y7m1e6T;>;*hDi1=MJUla{k^yVXdy#}fdftD(s56@d4#u3UGDnMd6Qyq*b^N^f_ zs!Ps8;x+2LL}Z^_n}`A#9$T-05fjn^!h~|lrRYNu1u~LPLgo|Eo13)JNE)n&C?6WR zCdtRR@|}@-2olQoMc_r?M1+Z35%Pj^Iogy*qXc*o*5~=`ZnxAMN*cdB-kw#u?sHJiK3mZ0R zp#Q?SXeczNT}hMt8f3_}nzo;!v@aCV#;7680x=B5k@i0c6aq5}eAvk9wJ0(foi?9~ zK#u0`B2c16E-7ds#K<;9%IHl_0wwx#0xy4Nujmy5i!wo}5lb52D7fK1wZgR=SAh%b zImUVfq~ts)0xSYyO3R|Z7YbOI#!x^+fr9S-$aSb0d=;>0T9w}&es$ub0~vn&H1m?c zp`;0<=(I38m=P$E?YI00H9CNKTjER?-xtxy=(RdZBSX=&Lxe1;OU{qyB>qJTR0t>n zC*te!7OzLIaS=_6gpya8l~fw*;QbWQX64lY<}KbsF(C=SOwa?2T_oNn#Jov}Q9d!U z$fIQlCL9UI>jwj|$u%5zd;8FOwj0i2d9dUM|0u6Fs(1)qxewu;_5glq_Yjc%0D;-} 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

p6u`&~w66qC_%1}g<@@@Y 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

ue3wW5BA=1?mNxrT~@O4C_ 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 z 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 U*;#1lWo!}xht4C$w4b&vFGbF&olxhH`XLu1; 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

*Yt3|2yA5;-O93jm`2lJUpL;r{}ukU%JyG$ zKtV~B3Z>E8JA|IzVf6G2qJx!ad)oloTKiC6-wAtK_=Xp~R9BGkqhR-J6t9l8PZs^^ofF#R}@MME0wq7r&K~S6Eo=P9zuC>Eu6yham+m#+t0W| z*DX=Cz<6X9u0ARN2u3OA2XBqn6T)*}VG9))AS zTdeY4ZhXl}%|O~mXg6YgX?WiY2l#&XUUq@WMOz%O^@Uqt2qwFm5uI2HgM+tVNPyAb zX$~D}fsts`21l?__Wq5M`B-uruE$oxJtPxJY56qzs|nd{h;E#~g{*FDAvnm?WK9gB5 z@iK%LnS#BO#>&wsO&5{?%*QSyljtJc$Zh%e0P~ChvpX;sf4k?0ukOnx||}wnBAvRv_?TzHcCsXv6hvK_<@lDynj5P@dYCQ;};l( zBQ7!6!9u1*N;U{7$5!7WtS7|iJ0~JEJP}O=%p)xc4aK?eQ!yZ#us5C(C*4RIkwLvC zQ4OTkS{R1OET$@cSQXF@D8U|*cCdd8N)n<`pB{&2?Numg8Nj{#K|cH;TqeAn&KbZ3 zuAfin#ERptSaj3@i;vl15oN_m2dp$B6qwoJ63Jd#0%S_-cB>#PKjVNERM;!dIC9w$ zx&)Z#qhkb^0W3Y|jGrlsY0>@2{Ss30@hdILl7?>hCzZe@IvdBF;;@9uAv?QNjZJFr z>8C~c9zH4MYSz!1%idUa$rDQm8v-y(C_fV(zE@*c98gwRj{b=k*uu*AYv%LmNnYo9 z2NjQM*JGIxO7(K)B>=OWAhVo#%CdA#32Z&~jDhxbKLs#f5`wIx@1BAaJ}G!XkZc>A zgP~6rF8jtKB02{V61OV58c_-PNKPw49KWa7#9~Cm=E0f@P4Ao+)|wM~3G))#AS;8w z^8P&mteel!2PYo-z%@J#E>RguoFX&uI7ntSrNSmO1NXUn+C35av`qDGvjV>Bhf9R! z$nJv-*@XRzHcv zChv4yi^$^ho<&AwAN0;TL+7FkEP4EC>mZmph2tvgjx!GfalxI2LqH-fJPyJsD?*_K z-}QNCm^en@fOP=+r3L2wZ}5$)U>OU*CAV;#=k{~V=M3S*(mELCgnRS*K`_4;gp-8L z?S#!O(pty=_u7ZTBQ#dU6jB3|?IUp5BV1YFdub3Iw(`dTD_@Ea_TTiuK9-q%*L|^< zWz+DSC$z8l!bE(8-1R|Dwsh0H$73r01Kf6$K(hOmFAmYjJ46Fu50BY?)d!~hmiFH8 z#V#JZQ;o;*#tz3wTKbW==|pRpp#AK{TUZ6<;3$oy{j3-F5cI0$Ud^a94AwzHU9~~Xh26qkITVD0x)k-*7X9$A<~6Z z2))2U=u3Y5Uq^)J&?ETlB+wl3&cY$9VC>;DGYd$@F}~{qm%Xry@M_BX;`mi}oVeOg`LGYvGpGfSWu(UI9-PbU!=-G^ zM35Uage4x*jlwZy5Z}w~!(-|br_vF)R1CwXW(p^hTcO2zMg?<}u_vLW1ekgSFfU)d zLD%Fn$}Bo59aBuFX3)*FXX+VxY2b9zP?7(;x!fb`{I8q;busOuG1SH7w(+OjcNYCK zJZ6U5r=N5Eg*vWl@~M(ef_Ud7g&fd5G0klh>YkBVX@On9)44aenA)bgon-8cK}0D5 zhK55-sip-+x{yLXj)5u04H~Hb7GR#gdWQqSdH4sdf^P^gKdV_to>+X-9m|{}@R?(b zii7kCEv&yfMB$)c8Ww1Arq+*OkwfCY#=v}H8;wt%gdvcX`RL3Xw)?N3e1)`cWD-ya+2`0wF1dy9XJxJnL@ogu32>@?cp)f z0wdi>61>qw9N&rGn1~t}h1cLHp(rdQ5zSc%7%3s(b=IJ|eF#^wdvP|aALj@!7L@ZW za2FE0vGjxsemY`zyoMNT1!C?4#H9kdn_lw2)qc) zNJ~vkX&t;{OYpsg9ezIJL_l!H52qbq?G=N03FEM^fVpRLc*X)}LrYLR>;}bTV4el` z)%;5oS9M_T!(al8bo~%uKETV5=UwpwD}f)*x!^kj%p#t*D8C%TQ*+RJ7>3Wp=gS#s zat&5vAU5!QtRlRupfX*pmYI+0M$)vzERsA4BR`*U!%rUu1^;N_qTuDTqfel9!wm-= z0Ijl719XPmLs{4wgPYS2GA2a_8CSbM@2tBzPh@7N>UwUO=t zXKZ=ohb=6(OZVTy&$PCJ(h8J69KYNqLPHvsx+JREZtv#jkVk-7OBh(`nuN`6aj<8F zvM(S9i=5)I*fAa}oD;B$N`5~fqqV6ASruK_O+~QUBNf}+lF?A#!bH(U9V&gDNB+>INH>ulx9L9c!!~~762wx=+FyAg)_o8F1A@VM=Man&VCG)FBUt2e zdl0s=;@9Cj*=%kL9SIysBSibS4Ym+8xAPjeusp70nO(u}e?9Mgvj9v~Cgz?$LmmM} z#xd=1h=cZJPps#+sY^w%^_mBC`5o_|F=KSq1NywjttaiUiFxgG3dJrOJbP(~bT>6A zKn%@kRNjnDxvvS!lre!xph@C?84$Ad&oRHV?tE?@*nG+bdJ<2G3T->fldE?a0p<;+ zXJ6w|Koa340ER51Iu{6jEZ^H$Hbt~q*0c!N63JSNAhqF=7fg74J7tCnzpJeD9Da}Q z;7XV}$h>#oB(M-tj4pXY?}8T%3NMxFGcSV+p1d|MXtBH-*@hBcqOgmAboGg!8Ur)? z{52ki<>Mfq{cgVR-J*2Qd%%>(?mF)YQy#a&lE+%QVCy9h9P&tp0k2D&ki3=U&oQMC zZ&`jLN`|n>GZP!VG6{}Z*hm20?3>MfB;`6~1J?y!Hu~mb!v}y7NHGb_!SJXi+V`Uj zX@SuIjKoA*E8R$3{@5M#u?0oa|LLJu12xjBquC~{G_owPB7maVMhH^Cq5&951xQr9 zBw1DfQ$T>JB&@zcdDk3_gK3R(yG~FM#L3;q{l#;yKG#LI(-=9-`#wzY-NW*HJSa&; zir>TXwwHB|$Zo#VU3|x;tj~-8Ne=1Fl7>eV+bL}9*-Q{ zFy3B|l(aJJ5;!?=1xCj&!}#bW7#_R;gMH^=bl?npy?n6a)FXUnbewh8LmZE&fJI^} zpJzArL^Wau^}|8xj$?`KFekVOm`LoS^Wt?^oYE0cRGQI+3j~#mJkF93bB1!7+fQd| z;N=40<#L_`a~x7F`L_y3{yUf>LFPf(B|9U}lJoAxB6ti=$aWRbm!)ui;Bz*xG zUi*pI@_zx0!G|$00x;MAPXP05;Vt&iD)@}n$+xWJeo_GAg{8M>J-cWC=5wbQe8GxX z;vyZU6}Iqn2AK_`Sn80BPwgV{iCr}QL5TU>CW=ZT7l{Q8SnEXSVTJlvT1$VTwX~X+ zTWM(nW`;*FHaLNyo>3&`)nS!w1lF^HOv)<9Xiq-|I{FcjS&l7)p-=Dn;uBuaC$yBr zsofthx#3T&)Kv@2iThZ5<{=6RFqNe>*d*OchXr7+X#i&5C46@95-`A5uvNVCzi} ztlW1WKU{LfkAz}VuVh?cS=6F(T}gOY;*x-?p{aOJ1yD$USx4|#OBoOqI zeKfW_jKnub9%At|XDo4yBNQd_IwW7&KM8036EXjE0zIPyn44kPN+oXmBnZYV^ST5_ zZN76YGeQfYQHx-^iHd&terv3wWvOpRn7HPKt*4(LEh$O0zyzl>Vv|4)?|&Pgsf?G> zVuh_uOJ0lbN}KCjX`ODC7+Ke;vjrIeJLUb@$UY3)_zkY$ds*=~3~Q)l*L$T>ai-%|c&eJhno~Cj1HJ<(XB)41LeDXR z=O!fFqSAJXfH5J)fMrDYlp{9NN;VQOc;JhjERXw{cWZqeB#u!)N)^jGL5T2TLdZ5| zYDh6qu;9gITGa#qEtXxQ`{G-Mh7!+b!gA^07K}HnIH#Y!#AyefllP*}XCq+-Bvz6x z^U)*BsFYBoOL)<~;)U&0W@5D)op-_Z(@sc9V0}0L8V&>xV*#lPJ}|lBgY7cYh;SzU zXT(FV0l~-c0+)F`J6Lz^=C`)<76FC(Sl;u*!)GjWb5V}Mjk47YD5)W|?q8MwXso;Qxta63wv-+j>)rYu)G`7Q0B zY-b&0WN8mQ8U{v$n0-!B*ugTdcg;zal>;m@#srm}cbu{Pi4W{O{qVH61?kyU*nZX; zh9@pT=jeHCJ4`uv9$Nd)!Q}8cgar6u?^#=XvdI*mY%!&=WsOS-O|YYZY7kb9ZK2gP zbZeBMEABh?P@l+fgro88IGNCa6G;`yb)x(F&u2~Im%B+J+CfBnY;X?z&H>U}{{7?2R zYLK9;;#=l5uBNwt2s0p4sig&`9H-(cVdS5sx{&ljatJp0FpMd}73MQL|8D?B0yb@7 zW&YLUKz#quA3xmj#t+v$v4jd?2?6E{hgbzLUpmLCDbp9jvPfDlkli?rCH6@Kmq`5G zCKCU!A?#3=&>~wwCHkqfzEJ-1C>VcXCHQw*a2ssHal}0i2Rst6pG3Tg@bVe0!@tvV zT16rji)A}2$i=k8{$b^dzgl_YFRV=e&W~Anf%D=4f6MxiyhB+YE$ z1$Y#ai|EX1*k`t2Uwkw6BsAk7VMkhDq%}sQ}d@J^mvJX&BvalWt zuf(yaYMhU6#O3rJ7Q8;3B*dJ_(R3l%m5#%i1@F7VcKGH137*#Umj@o>E9D2~iJD4% z_@=u87_l5puKQuB*<&m_WrGzKHduAq7Hjz7tUqs$4Hq1+{-P5>#tB=l(2~9C0)y+W z{6O7ca)XsVpV>~Pmpw!AFeDDAYy)xF+D|EpU9`sz^OE&71e*1%G^IJehA<^9 zFg^vHSix;;2}yFiK+JNc0zhW`Ha3~u#&U~$+@7EyO8rj=TFLM2tbY=f{S=|>6%`@h z3E^eugFsr`&M@Tj(j_2>f*09lZjV)jwlxVR*z#WuG{)y?&%cLX#{9r z_fbZLmVLMiKe17!z4Lfuf{{K!ON(&4mEbKiyNvGnK%e)mZ|MRP3wzX*m(wWx1^x-; z(4`_WWZBRca3kR8$zWfWF$oqa%Uh}7wQl*rkooBH9D3Y$8x@z8lRsX+l8^j6ClJ+2hyMcF2KQMS?$(B*ez%6A~GKnCY{PrQ~B)?OH&7{ZIWH?VR{fXP`ZS02Be z*Cg?Hq{ZMELFXW^WhcK8LxD9HLijyD=F98wNQ9nG7VH!A2{3a=sv3fhM<%pA)3L=f z4O-sm*hYvE(UC4C@v}qG^UG0UK=?5x2y7<^>>Kv`8vrTRuXG zh)khYgMUA)f81xIgb| zY=lH*A|NUa!7*6~q=ZE0AUq}qp-H)j$g4njb{XQ*@(`O>f|#OeB&6pfDU<)@6dd@0M=EpI7K$ z%lXH!&gj7Ym}WkYQZ-Ieh8Y-!RAM`I&8~y8`FyI)IWBWW9XQCjg~8OW74(g589O9bttq z4KKp(h+?KCFbylClwfCw{71;37>AZ&duR!Egcf55kJ--sjJb~?&uu^$G35CTczz?E z--P=ZbKRJ!3IBJ>ti>CClP_Mr!Hx6|74%VND@hlUX^f1O;j;?JhEYJKYJo9|EP!Ej zAui@L;3)y-#s3aqdZ-juI>ZxT0`R@Gz_3#Mo|L+n0JGFJ0-v*D`ph9l(*WN+i_;|ABeBh@D`)}y9h4QeI&6Z4ziH#<+3S{5x+1RfYAhd+)HrT!~Dei?m-r^ zL#f>q2_ev{iHAfvA+DnHBrN(6a+@ZQQPGbdkJu|Oyx$ODzM_0hfcaJc=FlS?;B#Mi z@q(4_JCxORprEo5#nmlbZbx}z2P#{-QQg*u>h@lh)^zltuCpKYU4v-q8bDJw)1E=J z^bMoAyB~uS;~0{D$iY!`P})^Gj_#o`3e({UbWvnmC)c|u9Rrj>ejEd%YKq?U^95WB z%fQYj{@6rIel4xpRaZ1EE=#F2r3+~}t;)rGKi?BTzOr;w03-17DHZUi(&}Q)_2YKX zvhuPCjg^&${IcGofu+S)w}A4@Aluv z;^Wp-$iC3N?THm!|LKA=esGM$G6KXBLdaqQ%u<4bz=yPqETLQpqB45+jFn#>mQ#@| zb&SJe%5wg04~{T$=5%qc<1QptxR$1Y=jtGT?D`&CudDS&a$YvVZxNUljdhvXN} zyqFUD4f#!NyX1@YEcXIa%RZcA1tDe)<)Tk4UOk^i@7O#{?ZUAA4i)=pN2T2LE$pCe zW`nH+g>5J8v5vsDmgRoiBR+pB>D8wQv4kBx*C^!V7b@Q>A=%9^df-nO5x+|~F)$;v z9KGj-GrqAn?GlQM5B+d~^~}k;Uby5PjT?TkxN0Aas|1h>1gg8NbB21msnmW!R#6LX zIfmnob0ls#Mc|fm1a7-T;jUXWZc}b>`wjPa+zC&^MfWJ?6Q;Z~UvvmVd@i5M`&XEs zdyB^eEHi?I8P9D=Xg_Toj5CDx3p8vl*apFZkassA3Ach0aDzsh72)BkT`=zYM4+y< zQ902|r6p@@N@*^lpr{@mOKEu1$?@&_Fium+mBxjW(DXR==ITe&D)^BMf0A2{tR=oPw`@Q7IV)eX4W$`y?udo zn8>{B%k@{!W>mCwS)ZGk#H;Bk%uP;UVt5c!-JK}NtHbsa50&R#U9;P)f2^R#RQtqD zm|EOKsGmRfpLf9LdPneI>rC+fS-cJZvB`u09F7wNk4=H)&;@mE&6NlB{-Y%G>^x!1* z%%0eG>`ZEbd(9-qrzCjiQy4{6V1HD(8W6jM(4Z~ji3lFy#SPTg^XMLZfkV`DT7(a2 z@z5ijh_gHK8za70v|Jx{fG9{aazVf)s{B?M|^7+D4lNXOC_6()#{MT3}dlEn}s%!Zi|~6J7*d{y~6|*+}+@1$-b2$Z8nD z_fHb>C&J6`o`m6#1eZThe*Yi@|8+kI|9L+c|8dVB|3Ogs4?>Ds7P-r1RwjQSu>Ah6 zAO4FK-G9=``@NMferM&4|G4Rm|DtmHPb$j)TZt?FZvx1FoO8hcI%9|bb?OQJfB{pcNRp{0B=vlHe? z?fh6P_>wF5z^nN3s`xM^C{-8IIa;Ul%0g1U5OIxu~~WR-IvmatN9}^a>_?hQ9UY}$MMr)dwjO{AwJ*t z5TEXSfKSDd-GN8=WWP1`@je#j=ONQO@!LODgjt!w`v2;u_7xA6@9|H5^!VpH3iF|| z1(n=C-@e1ItQ_9IV#V-s0dMDD@k3s~s~0c%fzM<9DL?R;XLvFFR5=rzWh$=AXZhb% z|1@mA=7n{a-LdY9ry8`of)KNu??zx|1)*j+w|^roFI2=|GX0ts>z4$P&rdnyAB2}p zx7=~WH5mFgys-WP^C7sb7l@Jcyc;%1D)1sLFdw>*R#Sl+5LEknx**Y#_uTZuisKKk z*TxU~Z3!@D53%)+BUPwSuM* z9QH}W(SS4@3CO_VfOMP)%D{<`ESLw2WWq8m8>c81q1mtu&%x>NTwJC_a62joU2SbD zs99FSAg;y~;%;IItm2p^6yZT)F&-oo!#1fDPRZqPOsj-#Y6WalO5vDU0k`Zb_~cb1 zo0jLhg*l8)%^`~G{?Qq<9BDDeWWz5a6<#4p@D5FfUsxub0}>FJQH&reMh_}UuY^3f z<(4Bfw-N)ry{e+GZ684}Ezz*J90W(x5@i}5pQ{D~$55F@a5*#~2hllYh{`WVY<>k2 z3u}->DXFMs#m`E8;T0+y`;bEgnp@F?{K_U2R5eji5}Z4FP*LBCin?Z0wD+Kluv|$6 zSxs1O>m5czOBY((I$6G6QK8JExvL+&qvPnK!tCf9#4sUxXhbt3YnakEIK;|#S_O;L z$P~uL#xTWgzrK5of3nQJeEAwPERRp8pR06cW>ypE@R=qsyC|2VnNN~`UU^|^`DrYexYXONWjHGg8Kj=eROmZ6XVmE;Qqs-V|YqsCZ20$di5-o z+|=YW&oQgIH{_doP55{=H;?D@3#@<_l&9QzKChPxua$qLmkZp+^fi^ROw*P?oHC>A z)$3PyM+L3M9Ps=6h4&@hV^V(JQ)x@VbsP54!fNf1xSzwsK>7zQK#F2*C?t8WaZ5imdOUfT4iG|O6z-2L@90PL2+Xb z3hKI0-`0bEmbcah88qLBjM6%!^Lxq5D@9>J6$)~zkef|dOe;o8av>6ua*d5PwMS(rvixSUcL6DAA^7$)4;fUxubfRS*G13E+1iXwx7 zWtugg2SqQOP{ws*f`?9MfoeUGFaR>vMwT@W@g$Y=Q$D1!Zbg)BFmFEq4BqxA2a|d9OHF zdPL)tdn7DeLvg|}2xlqf1x2VNz-+tbsR5Wn*VQmY6jTYrAd)kw*(9_Ers4J2MX)gyr%KYd z$!*)iWU3s6|Cx}O_eM3b05xDIm$ygBxR_?Oyd|gthto*Ur0w-ryiitLiK^C7XkB#2 zdRoTf#BR-bM{JO((v(%_ogiLwMajN<{Z{$O$SrC zMde7!FGgH$0phaq5TBWkxQu)RL`zd@wo-y_LFsS~N`(WT_hVYl4}21F$1@hU++%Ug zH4c~fj?dXg;Iv&hEbPKyW)p@Z4}xIj7=nqRVdW>|yjKd=6J9o4^-#|5*7AAFz}=M+ zVVdbu)dJ(L2LH;~mmki#;pYn;_>Rk;AGamEcwoOvAoOl|5mf#gT0R1dbR(@3IqR$f zMy@6Ntg+xTGPB2a%f}e)5%==%X%Y9Lq_Ppsz2e1o5Y_eVsHJkPq#~^qMJgh#Py-`q z5g8gq8x>aj&?JVauzsO}ougvx9-T%H*G0N1y;N9zlQZb266|L>I6Z>_${-cv5EbVz z)3KT7gebn71p+3O!UC1o#4{?^7ju}V5*6PYvmZoaGd-VsiRY5afNJLToRBb2MfZx< z=Kb$M3nBY{9i;`e}1L>Mg{sCkCSQFay@F9`Ks;A_n(pvx4jc< zS{z}$rSRP1Anz@oS?(yTH>^<<(e1x9K@QQ=lx6c=+`e^5V&WQ z#r>S`Y??qK@ck?Em**O0K`B@F5zvcEhE{~5);iXvQw9aMP`6SE9 z2+Pda@C2rY$1piMrKXHeNIE`)sqrap)2xs1{~^MeOa&hr9K}G-0ESrh`g@1a+u4tv z{vmWzsrGdDDeufZU4!Ujx$GwR^|W()`v6*-yV2Z81zgjHnuZS4G`FFZkXTdKj>4LD z11>V=<>T=JGvdHbhue&Ti;!8}pnNa&kIdtIOcjnt7Qr&A6qllk zahA&KTvQQGgcaa$Xd#Y-7veB2{X-#zI3HGsGvWEFJ~xlZ$FbH4hxQ;)+8TopA7>56rw`ag@fh=>b!pk~og)zT{V1Ga8owdd9^p4;&Q%iih=Mug?c^{9WY2ak` zsNlZ`D2I{+N?LJ@2JO+LRved>l#~vfOl^lnS{Ke{cH=^3AB}1Xp+v^FoX;F!+K-C_ zl`FXexRO7FOO$K*qqtQ#iaSMPxLY!Y+e{s*CXv@OgTnTwFp8i-&S#=a08!5D1Ux8F zr7aqO8GHfLNCFI@<}%-X0wFN9c>oE7K&$LJ!izYSBlLuo;bvM5(wcjaL}0W?s3Cwz zS5Y}GCelaVxV+U8nL9!)x9ZQ-PBSW&dh{F$~FN-h|wk5?sh`#LT}1n5kC;m1KPOI8e2~ zEFriox$TW*gqS6+k@(s<4xc&3s+mZCwTp%`EzI|?SSh@Ch5oS_^o~tYCebr8NsDU| z1N^xA$0jh$k6o;;;fX1XPEKKbn$`|0@yY3Dn0h*kX;wTlvoA2sO6VzQv=th{tHo+vO30h(NAk(|BpLuV- z>V)d@YBY9E;E=UHcHQxS$z69C-*tm2W#?U27~gTjO(%aWJe#IMTYwe8@YrK-9DU@2 zV~@PK>_zd#A+8^M;)6q6KVt2Pqt@OyVC{}Q4_vYLfgAQc@Pa;pLFb0MCg#jlALv~1 zhSpUtY$kYYB!sNK=&E8K{Y=0R=XF0=y5OhNF3Jn>r-9>zK23`{uB-V~tk^iJ}eov+R zixSPU5-PfP&u8(LO8+$#(_86|qrBnrYr@1UTJEn@GcuJH!DNnLBJzUe^7)hqE&7S4 zN@fT)Gc3n>JXTp@r!&G2HT<-55MmLpISJx0_5bd-k+o`Nt zXi0Xp^f9YcLXH-@Po2f7DP zLxomR*UfF6=%a$HqCzVs)V4KsqqDV}`46DJwiDG=t;o->LtcJ0(r8J>(BMceptYG( zj`Z|mWN^8FN->+2bXr;|(z42tR#J~7TB=C}HApF}Lvmp);tMK~kXOO90*U!mNXV@~ zY)%>CGAj_BS&Eo+T6bwB2udwMSaK;sBGM3&T!4V|G6aUFBUqLb3lPlZ(C8fa5TIQH zQ{bME2iKrvxceu97w@f}?jF+-S&n1*b8OEV%il!Nx5XwjPPNPb2D< zT@)@`hv1TD3?4EsE8AdPvk8U8!ys7N2EryZ1s);E%p(OhUWst@O~ezAc-*#&U`l9r zPQV?fC_M3u$8{Q5H@V+K8d>)U?>B71VNT=iw0k%%(NMa;y6~)ZFwQ*=!ucn`xb!#_ z7axV;63>58wm%5Q2`hh`a^p48Ks!g^KYKq2$8Y=Mgmh2&#KMe9@;K{KOYV32ZUFyh zdWUk;4`*-t!Tg3V4qW!Y&YNCpAnK_HfjE4Tb%A3PO#L!p;+qZ=?{pY>rNh`K1Nz=+ zN(_C{p-<6M>)bB?`DRkGpv`4183#kz#ys@>a@2Sj9Y2bHwi?8%=ac4QUZN zG{B*O5ow8$|D<(A12F$RAXom^jCm2*VJg$GnTNoNw9=?4(*i&r@)KZ@F*Xv4K=u)k zQTs79qNGq~x%hP+Xo;S>NSfw`$M{rvprg$88i^uS!ViG>} zGYG7k#+lR>jsF+Ifa)4jEhYT^OC>ntJX(k5urs=b+saWu0D1H7mBvV6T{`xB9xlb* zgp4v=O{zoh#F%p4DXn64!!tM-VCLp$dF(sf%Iem1MTPKx!jnl<2`u^E1z?mTI|7VBlmJXI zVXood1B{G;S?-*KFKmMFy>$Q<5nvYI@>Zb)7P~~@TLR3NPO%+j1LTBf>w=q<((K9<@%^vAE%6R+b|2_ zFs+sWrhT2g=xgsqZyPJ+rgpT{wxYSF6;0JmXsm2Nb#V>KSTPr|GR{dWMs8X@S}OQp z%WGhG%?qC$yMr%|-@%v1tq3u8-LfW_cL_mOdIGqxwRU}r)rOj&66u%I4D z?!u9jPV8fWwP4{q8Q+49m%LG1R*UAYDHvZNNbnk)Vwdu~&;gB4d5lUL*+6!dM}* zgLsU9inN++AiPMNqGcCcu=oPuf}kLSZNDIJd~@0rUs<@}TMHL_VdjMIc|H4`f^gEo zA4T~kn4f=(Gd`(UOBh zrvmg(#uJxt+zU*Gb#yN5VhUhOc@mum>zF(|jL5}3D!+T-*|^K)yWu&w9g&SYT(=6# zqU0#K9+HhKK^eFboQZ2(z8IW^b3s`+FA|uEGXWW}^iPMSZyGFoQ`NGWe;UliftFt? zj{B!j(r_Xm4M+KGjuG$<`=nsMcQOw7Bw@c#GWL6=V4qhK_Iank%rgmBspJk{cg88# zaNKc?zSUsUo30pmh#FcwNxcDFh$F6%|AIrfJ*Jzx*>yO=6U9r<4QssHXCJg&! zD(F1|tYa{a-|~VPLG>h+;1Rx)Lo5Tk#izO#rrEapO7NphxhR>)OM6 zH@WEvJw6v*eh>P*S0fSLn=!vRW1i21`|8UKGp>iEf$`?#A_ZYZSPJ7FXisvk4WhVv+`dPev_{5N>y~EQ#zC zVOiSAI?t5#uAzkujBXNQ_#K+E{M~uvjG@K~1@`*K?_%4Lb1*WyiY>d$vCiZKHXOc$ z4JWQ6z|R}|Zn6wr;kzZ69v~cEOKFC4{s5J5D~_|i7db+`Amb=c5M)jy5@rZC61eev zN;j@$5MI)IaWSnIm#HJJWcK2GMz5M-bUveB$wdK~>_J?jToivW3SvfayO>fmiif2W zu&`p?eagO?`Ox z`V|JI=3x=nsK!>wpx=_FQB*YdsIf@lRl_(QS%Xo6%`~5PQh67qr=~G9^HR<3l~_mu zEYg)Epdzg*0#j<1kxDf!F?UjG@nY^N=3l+T?d%T#!(${4)3Mk}93`x1u^!#R`gChh zCbU?8>qQl+E~I}8Fx>>0rG%6(Y=ZFvE4rTuFyhGW=UW6AS{L8&zprE#l2bH3w~vBv zx+b7l_uwpU^8ycfr((B95_Y;J!qhz;J6z(SPtY;qzNWM!_OTM)?-q@H?s3>j2r{Mx zWb7CXBZ|HQmznntiV4MtmeNjIL#DRjFnAn-jd%U9*2)W8?n&$yA8fYr#>N|>j9svb zmFV`XPAJXJMNI{PU-D1_m*X|*0T#kN{C_w9+sA!&Q}z;44yASB zXj%`BrFY{53*t#qwIvIs1qV#&$h-(bs|kKzS-287T=Av33%);P zk3IGQIP4e%Ek5V;^a4D8@fxRDp{^sqti9?^coD~U%!A6|D_+m%yuMFQIp81W_6lG= z=kjMK31?Ki2b_bj?Y2OR23Qold}wu%E+p~&BCRjWs4yhj_V-60z9zhU zw%ZEd?z@XEeE-^ay|H@VJuIc7`uqOeGFF8I$vcUO^L-an4fd1(GyL0N9A$!i6-iAY|u-*O(e zoO!72%y)$?^JgAw>>{z$(gr_We2kU0VOYU3zQ#Tr8>mb-?!Skvcc@73cu;xK!aHgW zJ&Hc>TbID5bIcZN_uglDc!vR z$aHN30*nFSW1G1X*0ZeYKMI8YJx}QHzikAG&HVO^2_xd$$cO->&$1}j^6`2MnXeJQ z7ek&?0A?${Q(c0T%%C#nw`IcbS!Pff@O|y3A!tgFGLhL+AMVA7_pCsSc^E4gNL!ig+V>92~x_g1x=#`9ho&qX~1eXM?cTI#gVPvC63f6FWjjLul{|0f0C^O(b zI7U=3!*6u0hky)I0*(0M((=y2IO^b@`FYuzelOzwOs?~-f;G$`1(Hx`VA94NT7#I=d$nIZ*c=M51S*KcH zIwhn=Xod0(lhfFuS_Trz`{0ybgOSm3Jb(EP=VKd@QQwUDxtH+G?Sex}F=nSGP}V*J zGaffI(v7bEDTL=%;o0moD%vKL0dd$m5PSHpcN1VuSr$wQrMoFRPuanU5Tkp81_IyZ zBPSn>x7H&gy;OBuYwfhaw*8j;4z6Im(J`zwI!vfJk05_<9K7L-<97+JcHuY~Q;iex zO}L%b4l|im6w`#`)Fnr`?Ia<_f_mhn08AnQCZ!AKr3Hri;*tOi(?GKKo%H0p?w zX4Qq%K0Jqg(RJ7>0Mk2&*Dqh=dP*x!MwhDS^{)sO57WBQJwA-l>3N(@Y{c2vQgrt8 zqO5HSmV}>?v2o=gKE1IIPiH65H~yUWSx-RGw7N*EkF>;m9LOtOS^_hg*hnR~ol=MA z1ell70+Zdv|25r92I0jx5nG0Rk@+mENm%Ebi1k4%^VHQ^kp(!PBV9=UZV>O(ODu7U z!)H%4EimE-=0{p{Khq*u!piO&LdVyHi?5tx6u<-sz`TFMLNkR84ypK>mHQVq;XFPZ z|9BjV??}9cPT>R^0t~@r0~O2Hv?@NkPb-6#$x)wp91lo>Szrnd`KMAjMB$VB!T6T2 zV!#Uar~4uJ(#j8C-*8jYc6V~ych|k~_ls`$JFWe{u=4)1xi$WH;vRl7zl*%IbktVV zu_E@w-wxl#-()7zfosYe?}`&Qkd%A7MoNxfl^( zjAIBfgqnj1txDv-J@KvBPjJ~Q)1^gN5M`SH%pMj-nT51JxdZzsdsEv9GTk^#h&fJ@ zK1G5yr-&aI0hpWlgD7g9LTXVDR+~HGXDX{7kJ#deqaPgFu|oUlge?wH=}5o)^z%2g zPDAiBVcWmHIGKvw9U5`Zs2W`SkPEi%^Mik&P0?e0YF3g`FIrBK^AXA*Zv4PJ# zB{^3);5y9;QM!+$^+kmY;D6t+0v2HTloh=aDx1%Ey`SH7M@e! zMKgGpDZxd?yvPisRa7dA%xv*372~&uA1Z+P{-8C!*nJmY?Z1P~cf6_iy|9=-^COkk zk5raR1WFtQAY!qU5Fyj|HEA?{VwqY*pjf2RC@iL^>HPvEOjolUucRy|Y%Ev6BI_SO zGgJ@ z*yIqZ##?PTa*q(@30*2qxfXrqAx;55iazr)WS;u!Kc<8jJ%N@JjU3Pz@q?012e`v-iX`u zP7v6b8q;XpNkdVK-^z#>pKH}sqTRE-UL^xR=kWI+YfXjM< ziv({JM|KKsmK6`sIWsZ1c}TUR@*JzJE^z+ljjVUJOsa!ZB$j z_s>Rfb}5oe`*0_|94}vtA*yshb-&fLG_wAiQ}Kt6ctqi(btrbT&M~F2WXf{0i%=;5 zv)#fL#w>q^SDbOrI|!pKwMfe-fzd^l#iQ4-#pDDw?K^|b2hU-t&R*#3IEL^59~`lA zg~fdjY`2fZq39ayi>bq{)HWQUKG`2ti(^brQJ*5-t#H$e~EhJ3PI*h{xBRXCSg}T0sE>6IEf=W0!&2v zGg##eK`XSB@FL*^q&1`z;UC7pbc|>KW)A_TwRZro7T&<6unVpQ5*2*{&j=SdtV=Z`|TZGy^(QoWPr}6FpjK*3>a1eatSdqmPWda zB+ijexMrHPh_uYyNUEhSnZ^QP$w~l5jl1E05hd6jRfN3)FrG-pBsk5&i!xJ)Sasqixz1TteUt%4C^4exhK9#XA;-BFuh9;ik z2n+TncLMMrIvq`Y!#q9@-`(+tZA=RK_`tfUkVA57u>4LiA;uMdJ!g-j1d^t^+q%q&vAUL=+2(@b}9-IRpABUb#tv~s-_2NFB5N43VZVJ|`E za7wrG{bHFp05ejwOsTe%R+!v=+$$J{4fkJm(h1)mexd;8r=!vWV~-^gvxrvo-fM1n zIXjEV*;g>S9Y{zc*svn~p6So5RDUwFK_l;XZvG9btJ^V2>ty2TJkEKi!67hS&1R@+ z>_tjuIg%(>JmRqYf+PH6GSpzvj=|?xdCm<1u^D(zE5|3RfdJ!zC9Kf*+WKR!Q!ut( z^TNiZ1Dh>1iU3;}4-L9*tE?5TQa^Rk*ApV5OEHsb!rbyv`5lR*E*S zdm~|T)nVpExZKS9U2D#L9{OS%0Ye?fd)ml-1zdD^Ejm;Z(z>&O_r3W%Vc; zK7y`5(8(vN#YX3(ErGy}03#4%hb;u5t<2Nlfef5^Aaf8k&TOKPQ z#5@#u$kclgf(3zE=cEI)2rC8;eW1hr1(vj#&ssjOZT#Mh355D*?FmeT9|bM;%u|z( z24VzWoUxgpp>@>_dJp|z$Z~8zDAHrz+GhzSkAkp`|H(0uhd$4%M9xdmV_NnNy;gl(EW195tq5rCSi*Gq z;$7qa-w-1Jvr(MeeemG>(a(!GyOVw77zH9907i8a$uj>Jz*#5Iqrm3BMOt7K=tv6; z0Y;a3MweCNmtWqZXOsXFR;gNLGV1G97>I=0VFXpQVSHu`(@z(0i}iQgSU*~ao?~Z7 z8FYC3PG0vOp6g&pF2?v@S;tcx56wnnXEUBZU%*wjY;3>g%=#!AM;-*K?xWqTt4s;0 zJNceX`M!3r+!&v*#szC9^wbn1DY=kk^*-O-EgBh@u-^DMHte><@?GXwX|Nyh!G1XN zzzdf5Saw)9?2W3#j;I(l`oD8eLS%SmmxCY!#Zo@5t$PF5_ z*E0KXRUn2UUV1I5L(Hig%#%8BQU?4=_mk+I2pNM}g0l(DxRTt7tArW5k})_`Ou)Hj z8t%0-stYNs^%-vF3_@GFa|jDEu0&=GMU@d?-Y=kQbRGw&=l1Y=>U#(xzrMqZS8wq0 z)k_t3Eu&@}w~`xaI8ULz|GAo$ZNNOX1rsnrN^v|&Lb(j!*SD|K*gYAf-!k-qpi`|{ zSJXKLVEzZNd`xAglFUN7mQ;fo<}UzqFSiFe1Q!Y9Xb@2b!>AJMiY~%>uSAx)WNZq` zPynM9Re&?;^_ZFaH(f}5Qv?{2ya3F14+F7?mF17Oys?N@$uhS{eCHac#=%G{%%`+2 zeLezA#}uuCRD8#e>?>B>pRqFk+oKSIM>ZA+Csp;msG)+LpPoT_!w`1xqkK9zgl98z zNX%_Oa7qd6qH|gCN8+e=9L7e6)l7-YywRPkv`0wVeLbV7DI@d@jle3h1fNl<{+$-+ zUrs&3A5T7@QWt&n67JVo8c5W7DWQ z?38gW;k8U%aWMNVn24 zlJvPu&4_Yog*ir;Ih#EMGeXP-67tRDE-Dpg6@mGuqqYzaywZ)d_=G)vpfzZE*%cBk zdVKaZ^lk*=2U?mxu;P=J2Wf#>#LBm&ssW|V!_dF#4SVkxym|8m&T$nAU|wD560`Agp4N~bD?fsu#5)rIFN-cn7m^FUKkJ4c&$_Bsov&GOuVJNp)Sg!ET~DlG zCBKH(u}+EWhp{gjfLVRU39Be8X$dW7C9;^xO9t#Nq5O34A-+Cfg$-2T5^iA0{yX@_ z>=Axo`CKerGy*IXsl282L&1bVg}{Zt#3O>s2U+@<@IhHZm=Q2pslY@7H3Byup=A;O zU(9r|?E9E`JdR`?7w~B7j6$#BGb2=NdZ#hfOHfP~omQ zWrO8AuMtS7C@uM#S;6mP0~P72gZHrL zq&1e&C|UZzAIk{_tM}c;+RNeq(O#1WpR3kk0@dLMsx@URpZmsr_ppJWu~q!X$XF0w zhc1Cgx`gyDxj^TlGjuL!0*tP?%J+Dh3Ygci<)#a?F4z-%9w<25c!1YNt9G+ES)_8% z=Dlv*cL!U}5+(?wI+j%8(v5ZEA@nHQ#IKLECP|A8L0c>|C+RJ5PGP9w2l#kn98^sfg$Nu6Clze>}-~nojaa1a-6Wu;t?T;$Mam` z08;0n2VukxMl6HI7B*CH_Siu&{vf7j9Mk|%fhogl?$~MLhdsC5aOkod_7UQD@R=ME zuda`2m9y+0;r8QK+;EKV;3U5nGm6D^PgvZPu}YrUf5{c69KvwgH58|K4`$XuI4ZL; z1JiLhFayVEc^>7rcEm4*X%de6rQ%pXIwcLqgVJ!4ViuGR3s&%_WV(NF2F`|L;!Ic; zB^T#I^SC`5r$VxEn(OBx3ScIIAw{@+GP)R-XjPwzE>Qsz#V3ov$U1_+I>L(b$jfzs z4cV>{ZVM#Da9O5RYr2sLBm@@OPt(F8Ei#&I3Us*d$L-SEB7mbM%RJxKpgbzZeCTsI zLICF1x9A;vt(3Jcx2M)M;Ge&}#f$k@n46P9?(-^u*-6aKzQDE6GVG$^wc`fglWPPH-4DcW8clo7IARCi`A*hZ zrsg)-e&R81+;PNULnTtvOJQRENaMiH>?+n1Ue@Rx!dg=^tlw{ekN_{7W_dbc<*Y(R z?2oB}ak%(-5kDrS(DlxPj!QZ=Ka7Aj>zn-qMvL$&T#9bQdFqO*XQ3>9`x*^h!zgO(M{H>~%;V~C zCcYXIGvjC-o~ND^S0d#&n_P`k@l|-7)rh&5GidI63cK_MG_?<4Zs9fV=X5~^@hYD$ zN_g&Y&8#F9CV-*M;Fp0cLtZ1-ARlCWO{)fQp6m13$JUw>+`TH4;C#BoJU?@vTcd0VW#0nH2;W z=|Y;sdZ#pePx}9c+odJuTUO|?+2t4~u{EbxX9#@Eo{t?X0%;IuHDQ*WQ;vJQ^6Cdb4+c1oFbtAp17e8O~$0w{* z|3*vnujaJYPu)jmQaT!{8nNBV51$;h!Y4BRMS?mWpyD`n2WbSD<4#cokZL|KiCt6; z6Q=s1q~?fPB|9T)v6moof(7R|3y1`76!*_EMn-}-?vNH5X|?$vJ3fRGkd~W|V`z5A z)Z=7g3(lr=;%0UqZsrccg0yW$IhQ@C0On%e5UwZnVBIMX0*f7fX5}gXvq-v+PTJwS zV>SdB7rYdJdHNd0H~BvJf&D~F?q^yJ%UF>vXQkRyUW&Y{@C zigqKxMFKQ#q-?$HfxO&OynOi{mwYqTl2(~b&UmQk@TrNa8@m^FSrY>jVe*?+ay3Y%`aE2a1Y zmHYQcAL6I`d=>-@DKp<#v+NKozInj(K`6exABwN52GY!TMT>p;8e9QFPy8-xt@*|gjx*LSWDwS>i`1zh67Tx#fHqG`W zOjq#y%N_({1+Qo6!(gnmCU6kqmp}B!(o@!0z5OyaTUhg%+F;B6YuLKyI<)rQfY!d7 z*u3W^OpZOknq9ZCgv;9>cw^f|!UdsXD*@xMM+~%i&J9QJVeN4%=n`JGSw4gjVZrdk zeHfW>*~}V-6cZ|CZSH4CWxvDP4?8Y6z~GDxjGcn8&np_o9<$OuZ;ulXyQ%1Vv^cI6eol`DIAREJj*Z8B#M!5gDJ4 zq~Z#s6;~lMyA)Y@mB`30Lw0Tja`MWNmtT$o@sU&BfXeD7W?nF~- zH)`wKP*KxNMbLxh_HMLuTT4?X+M3(Z!hKq~+|K&1x4jSjeM9K)9zX~88y+3S_{bQB zdiv4R+mH6{A$0J+&Ylm_#r3X!Dv4gyxAvmFllxFQdj~Nvz~lNxF)UNKDMN!}TpndQ zj=_Op^mDnlcUXzcit8O1K?j$+c>bQj5e$ycV2p}=VCoq{%6g#XFD)nnFjO9d7=aZT z+aj=`{J5xfff^Bk8cjEn`j1c|-AFRsS^cVZ?f(jwirq$qGiY6XX zKJ*AS;ib|7^9BPGZ?K1TvuZ(S!_BpP|Mf5>jOy+^kBvLcvGo{@;T>jJx@|AEnw~&-pbyT`D73gI zV`su}FtP&TaaYH`1lm3Y*yv7U&o&;5Xkh-pI&?Mb2pz{n?C~qW5$c^|VRf)1OjyRX z;6idIE~IxWfH_Gc_-K4H_EN9xlxN{rj7?5SSjPHh6+vjDYl@mdb|gZ)y|>_QY8z~F zx^X+b0|C_|xSu}^?XYqMFai}aby>#1yeGi)kG~|q@V*EzRjl_H)EF4*xQJrx3M*4S zU=9;l`bUQ`GV@0HvpF17iK@N<6ts;aw4@#H-z^}adK5+>Wr!_r#=Cc~;88lH#=MBL zIvt)*#=}Tgk_;9$A+$&fjDD!bVcn&KYD~>eVSeE)tg;C(vTpVZ}c~ z0Ol3SJEyV9IRig95^e-uC_fQk(hKS^JoXg(JxSnPZ{Y{rH}M>1o;jEt7(zkg0QPyL zV5MUezM+Nu6%~@MT?8Hlr{L-66t097A%c}$|G+r*IHq736-Zk{Gb);gu;ykUKEL3M zf1I|#-w7~_PCp{RWT2tC5xegA;q&8n@Y&JZ_{Xu^3Su@AV6u}lao#f?d!jV}qtAk- zA6yA-lCn`?Irj2p><=o%$#BwbOf9Y?x56U6jRmO{y9qJ^FgpceWO}r8H&J#7w1`8y zuo@W3OeX&#>LeD^JUw)+Ow z(5l^h-4);Lxr#4n(SK*5tF zkXF%zEb-StWtftZkAjMNq~%p0HKh>g=|yT=N@@|3lk!nr$^Cf#IBsk0?nQO2Oo6UI zQB5P-dInKZ-+}ysO5_(;qO`6FWo31!D63~$i&9EuWdj=OTG7(jfm$lkwze*`v%+a@ z>p@df7wTzgwe(VHieH?jc64?3pu2An-Bgx6REWJ)lD%EM7~nBO{X>*7^mg`OY=R1Q zVv^~k8n`z+GK$gBF^o|rM#nMEZR1=X9vDP_S06@cn2ZmNP;m_N8y?3rmGfBtAg0DA zF*(fj(Fu%DfsXK6rpCwBw(-GHObm@N9mfb2@krmWnle5@B|XY}pJZO+RPf@5XpBmE ziu+FSxMBW3Hav_;o_}U+5>Lg=0=G{xpJ~aD$BpuShIx-eodXzX@8L1M7-t?6yk5z7 zfcHJn-G{M3UL&tnU_x9qO!7V@-?70VOvpX)x_VmL(bgz4B3sbSXV^_h>2B^ta{~c| z+edky79St3nE_5`rOf>W;V`YRuGdVbchL!;uC37h0n8r3g0*7i@k!aM}s_RHvQnUi4 z3y8w)|LRWq05Z}NqX2~fp$R9TX=%~SRFZBaX@#M1yFiUho7SOd2TCdsqj8?6O9?KK zSV*riOn})RRt4RVd?eJ=;q|N6xS7-pL*{G5;{<&4cn8lzK}drbabMz zdlEYc2ku$r2@InZ|bCJm`3*P?yAF*Cl5dU9-m_*H9e1=Z~EhwrU)V zw7{60c#I1-?9ks>O^~gH!8se~Sl-44Q!@oI8xLQ=kNQWjeCuvR2l(J30p|1_XPD4n z*-OQ5LcL;0ogx6Ui2$?eNi=?D9r`T|$whYpY3zh!vtt5|5kf9`#N(=87VgGW;BitN zE+w}sfRUL>GIMEPEOkxkdX4hn+%x$K;Z?op;rFtzFptO56-0oM>CnojiwJf2 z4sJ81NH>%|*9`?=;%hMZbP_KY-r#mtw+3LOg@ypLlh495rWk9ylCaq)g=H!on`IC$ z-=%p*4W{Pa{yTtqr3Q|DZx@1}#19OuzMpS-W2u$5^2GZi0p}>EUE(6uSJ$GhV;Gxm2ji>DuK4_n9X_Fj`=iA} z)dJI4#TQP1`Sh5yz-YYjN;lF5^E(P~%-v#P8db#yU87t)ZzCyh@#e?nnhsr$Oc=3{ z?+q-%A->#maSbpd-5!b~2@_z{m>2~x4KRve!6q3?z%IRzDr^lPA$#RwjZ-Rgee1hm2&SC$f2pC#v;#4DT|%@2zG}G*vf19F9rk>G`L#D5WKMl$Lcsbb^Ws z+DEIbq`nyzKJhSkLTlr(AB>-PqOP(Q!;|wk>=cgOHh!!y+mTsA629S!O_zPJK>+58 z*9RfMT=76bPAMysUvSPpLldO&v@^as<$$kGIpP~yF<%j^*05qYx9KJVE2eMz9P7Mz5g!0+-rr;cHPEjrq{9dvWyiW;O)7N zFAv_u=Qlj?!-D{8Y;{|T9my#R7kX1Wh(wC0eOUqc!XB%D1l(4 zrw8M*EDD;6yNlLuHx*hJty)nK(mL4F(t{R0zg}(^g(cJbM`*E%!X0OYKh{UZOvO6N zbf|ZP$I>#UqG+ZxR?{LUywuPdsU+02H@5J&K`K%L0P`AS9>SBTk4w#0V8-e#$%}rr+H7a;){k#TJjj6#Xca8 z(I_QFv=|9j*%^f>%_~MuP8nhnsRR;p(OA>O=R&~Xa}lL22E>#=h`@umG@w!+=KWUH zbihA4Q^k)74vj}pcp}^gh|(pQoSKVHf{{Gq5rTzSw?jPtAf=Ch(BIDI%jeb8F@mV1 z61avXFppH&IQrwUZ2&G>x#QYnAH*l+DkVDHJZsLv>ZXa{kuc)~E96Xd6Lm>kyiFd^3%sCQ2#m zj;Nd#*oI}}*fj?nz4!#j&fDPFg(o41mv$GBsn#*Yeqkd${NpfkfrBt_ATW z-AF9yLR=Bk;tnL2_ae2d9eL$#gyUZL+@+jI_SUG-~NC z3RD2|hV{}L927Se+!jNCdGqcKE+#hfTBNmx$1xx2GIGx>QPGa;`=27GS@g>k@@mHk zDY?`$br@rPm`iYb@pOW9;25;MvY_Re41KR;>~@TX=|yMkxZ;3=&V(2%FYGyG3sW@) z<`K?awLxz^jg5>d=pDO<^@lECllf(=HaVeu!K^rN21|DwLv)}oZctaAx#z)pH4FzL zD^&NF1?&DD{#4}D1)E({v6^~q@hx8hNDwwWj)tyd63$Xj7Nw=5t)c=WgMF;$XK^R3 z3uh!$fDA#1Z>H{Pz<%nS-H|oeM;)`(DG}?O;?>NvO&(d$<2_w)PDEW{E?!Oa;N>L0 zOB$_rXeeuil|d_{NQuls3MnGMyd%I&&ErITBesVTdYaquX5kgi@_aHANM->EXh>Jj z-S~1$j1A-0x9^m{m+6T)SfzKU*h$jLC{d-~Qp6uuQ}+yx#?(=-YNktT!UhmvT8O{CeU0bSv$Sr;QC{1HgI=jvZySm+i8ehrgXr`MSdy~7wGPFn z)K&nWkgbo(4E#9;a+_SLR zJ_&{{Y0#HK;h7C%pIn@Zu2Z4W_p%_#Or*WB%?e;lqU)7^m~Ekz&<-Z$2A1)|Ex;_wJ3E(e=R*WH--2;)8V<|+X+Q!c4u*ko zFbd>r9zDWR@&3g#ynOo+&QZlGx!sZT{5(jL=cHW3+z+kDh;kS!g;;_}*h$(gdzh!S^63Q7q)3f*Ek3Ho2a4EsO`VW zfqxNIJl6ExLc`!4S~+)6J#ZIkZ8zYU(uiXODwE)J1)e+Iu3)cMIHJ=E(KSS+!QU$5 zxpjSP-=Vww|1ST(gR;KcDC@n2^4@!hs-3|x0;(>R&w-P^*zbA?+uTF2lTuvXsB$e7 z^xQ-tC9C5q^12q0*>M9olvLIsvwab1oj2iA!a?6B5!;MCu-VcZ8ywGLm5m?ty+Tpd zJb(f!z^u+2NN-=@_ZN`fb%WP%9T|KtljkS4-@ui|1z2bFVC%^cY%p}hkJhIl+jRWF z`8>QL)6vvBkF54)@tEDuNm8^v}lc_S@s1 zbxz_RwXN~pQ7;_w2t_pwsHnzye)k$Kb6~yHv_QGR=WPKOc?_nA@o=``CIT84q2rZ` zf82Eff4|!j|Ey<&&9>(d7?+Q-j(Nn&@3P+c-FHwp@BoQjcX64Pp_CO$xzcizWiG;# zW5PDa2>gS#1^&k#OZ?8r1?y~s5RqMr+-{c9c^i@Kw|UMY&a*y2Jof_Y5Xje3hjWxu zbsPuN2e9VEMf`)wDg4b5cl_;fU##7T-eCgFM?8G?85T4S#q*O)qe-@u zaHjz&_1MqzWH;)AJl8z011*D-Dzo*gm#;Cqu%wpw?n-MxY<(x5-KPQZXbD%Z-ox3F zagOs1*hhd7IY2o^J!R&_G1n&&$K&&Hg5%3^r$`vtU)BK3L_cck24Q&OJa!*(!VYs6 z?6UO2=0hj3$55`$tIF#B7 z?YL^}kFJ7oY%PN0E6`t8gD;P+18*Owy`4hZ?!dKr0WOm8uId`>s;TqYG7x?lLv~=+3$t#>@Ir|6$l7mG=wi3who>m^1N6$XO zhI&jdcK|_^eH>G!ag6#*hu_mx-V<59)Q7`4y*O9di_+d%0`zr+)X(A&4f}(61dy^m zWVcQbw6AgunSoc;xPp}Zx!u%>6oSjXyp`9vgeb~>z9&np^(j8(G(cZU42&iZ%r}6M zI2j`XjBVu*_GL7&Pu8<hX!E&JrB&im!GgRsR7?}VAl%O1n~;MtR=w6Zq(n$ zRNzlBCW1>D{y=c~7s~1@MQHDz#N(w`IA73BtGp8X`2HV5 z^Rb2U@WyR4jNHLb7Yp%+&|Lg3Bp3hdVlMvSd={+ZOYo8aUr=@2a*NpF2 zm+`SljLtv8rgJ&?U!Jk}2U;Hg!~P=vJ2E2RTF5}KeFQH8|(2IYzkOex3NjB1=N9fCvEEG#NSW?)*O ziGdLhj3lx>IP4pT$GjgkgEz6`bPB&C;F6|5M&M;9p+@qMjB>E}^5r*pWHhTK)2m&g z@DoAh_kog>d@S>SE+UA{ztpYDR3e4=FY-7E*%2IA#<9eqEtR}$x(IN!D zHy3yb!apAK$7aHd#Jv1qdIrC+kJC zaD;=;<PDU5uG8KgUrXSBaL#5@Vg7a7hT3Aj}Hmx3e4oYtIi?A)2#43|u{P%rU z_`9R7_!|>cms{Vg1e@5b*B zdE;*m+u?5v?D1cZx?%h2Xk4nB;&m^m!O)p?l9c9FEJN}dS+SjLs;{g3MzY(jX9LTL zXu{`FF4!U@ZfH0ic{En-7)sNr?799LeCU{>i`&TWmt$p4vpXxB++mrn9smk8wqane_!6iY!M!!vZ|`9qAL27bKM9#c2YF7w?HT`;la7^<}$CZV(qq zeAaRo`tfb}uLgvmqdr(oL&J#{@}>5>2xxym!|5(uSe`fg`)Pjne8+uUpaittQ`d5q z-#Op;0Abw^sKkb`CAC?3V7BodDOjQC5E=w*wx-K_ZGW9k%G3n*ep^|j^1V>h6w->9 zMS%^^m!rljquI#uTSi~`jxGU4HgnAE9#T_C51)R9dC@4x)eczXcj7FStWn;8X4;A8 z$#l~JmZL|pB*dJjk`1XDhBNQMKEl=Bj8+`ZY=UcE6a0!h;E==jXlU$CtbtBaE%qkY z^H>92zBZ03h3Tm{82CiNBBlV=L76yetMS0x9PdSC^#G2T2SV4#2|7mh*lp^HohQ7Z zb-)Tb#x}@GOMpjk3Y;z`;Ye5^Y$Xp&`7~kdmdXQjgnH&!@fe|F0ycc#wqgqQgfmm> zoeOalsL0L7i^VBCnVZ7xg+-j^J$Gkck-q36VLo zhj1jT4Z1Xzb#nz?2*%0-Gyd-b%!5~-NvAFN{z?wkT+(FXUE{9_;$6RziB|wd9iz*U zqX6bBMsB>s&e$e3ee_*KDSj7Tf*&pyp_>46_4adUi=qh0qvYcs2`}pjEcdT3qK?+^ zri=Ml8^YhC6)ZuR|2-%jf!Q^9^XwTsNNwJ!)p-Bp2|~*UU{0m*_|9F_(V|`Dmw|uw z5`ejazbCwW?+}c-@;U+x;X@d67Em!a>UfgK*QKaeI--7d<0UjO6UcM)GbjO_#k z3AEiKLQsg$tW^8iEZ%*BvDq7#ymlKEJ#)}wyGh;^$zXir-Ye`S?CJX^;U>RRH*y=> z2skd~R&Y$CU!Kr6P6WKqOn@ zn^#=LF_v+hV#fc?Scc>ia-$+T)qD@fQU>r(94!Cy{uB5o8-M60RKkuxX2S0n5yFn} zJfjtn>o8&cj4p%?zkK1+P>ehKCUJt}><{H~+~FqiWP zE+)K=qkPYTbvZ%hZ^5!o@_TNy>^&Op;6Owj{>KqF{M~U+?51_;z`<7%I;#9fO0KHk zmh&umzP${%RF>|%9=Rs3CiZy_z}g-u_@6pfSbH)EhoWi~ObT?Ub9p?$ww4@AvVol) z2X6g2ZH-*gXt zgb?xWnx}O_H?kVmgb+sptryD>Nb%?A0xte5=LE9ulEOjY=2F)ZF83_qeD@<<>{~(* z-#028!mbRNK58Wl5K7b(k{sKyjR3Qo0JCSsDtn48#FG*9VOpvDeT+Eu-Fg+yi@zZBdnjF!the7RhI%a+2UOgN&|4 z)wg7It2uRsHT8&N%{=ezb(Ql)j3}St5u9OtW2#0FSv892hDr7}=`%M~pK;~URhCuD z^T@vI&3owA{t$uPj}h4Oh_a;F6N#{TrR^qSdha1|@By+$AM^QJfUNA194xX5Njxx_ zgo&@8mnmOy@5M6izI=oGlshlq;@+z_c=%f6EgrpI=J6dKzgfnkxBUMNUoXGI(((tw z!+Sh?M+kby*Y7DjK7aR7{r`&c`u%$fj~_l#P#s|trEPwihx0Lsk53+CDFQ4&x z`4jw`78GPjtd1OwWH;(6wtH3!4$=VE&1=X0V&3brE&|LLp2`%`$A1H09=-mIgM1MF zcqJDfFFl1T z30yC{2)C(RA3s{cz55UF?9mIjlBR#~PsR6CyuWjg!0((xvD)b(YD%gxJ~R%K^BMSq z?Rosm$pBh5{`f~i%r2+%Xsm65TUr%6(^0O=5>#@wc-9~7w!$T ztUg5AcFG(;M|BHs54GX$ zKpS4pj-h`1HtG2eTsV+;aR74TpyJheALj`$dtFkomGH9NDVhL7AsFnSY;lf;r5^$2 z`Ey*o^9l#gq+%x_Me?!i;&C^DV6S%^dOAlCl+~zK_6Wd;XcHjLMC9St!acPj;lbS{ zwPK;JYYO{(B@1s7((>yOncq%0Nyc8EM8srOBeI~Kzrpi;QnBlF3gJbw0%;3jWT$%! zCWj{>TkoICqi@2xsi`Ct`x1-I?$Oxj z5=jLRf%Udw_>u4;tBp2$M`4d&ELNMH!tYE^W7VlBtUs58wSMt%yOgY^%zh^sXWfGd zQ-sjd@zCRR zPiJALe>#qGV6>^6h81B!6t&69`QjmvE$wZ1t|JwjojP7u7Qa~69<-3{N@ub0Tqbs0 zDaPS~ejFtiSNWjV5~zFjTLqtbO{{guKOq4E`2k^#@15M!1$2<^}k7^ipOAgxyu_E+(^ z$d0$-j&@)G0t=FqOQl5TdA^N=7aj#-yr|5NCbr|SxV-tS9h7o-zmx|_DSi(2EW?%cmb#zj zxpKbL$-9A8Ct*qyzDM;UPUa55gy-+c=!KE27Gyg}8@uv+4~n~#LlNK*55_41gEzrL z0SMd1zwH6ss}^vKidtW$ep!wspJ~mxgg0Kl2irqDGM=p0X~ISze>;%RuXvQ?`g~~# z`x5{h$_R6`rVnOt@J;XMpnHww5V&gi+dS8s@Z-ndJWZGgZ`>NbUf<~vvo+i{t8M16v zDLj7PoUne9_ep*;fJ!fr-IT!_dLes?j=O@KSfyIQ$!9tL;UayTJHDx zT+G0;agM*w@q&<|Rvr-!B<@9y;(d`RAkE68zXFTqNLc|HffEHW6!~8T1m_CKth`n$ zkTf0`0hP4QL45uBBObr_0?Wd2_4xsQCLR|77`618B48x|b3lF0vRJ?UN;)`}^T_(? zq%~tVWe;_Qwt!5M1icbqlIpRSvOk$ek(65Krq;qZx)i1yPYt~^SCxeYT#cF33V?R1Vf3b;4%*GqB8TVSl@>rb4ZFAC3`V zEIBUO@ELX@Si00*hkGOMFP|0Zk6!HKlC)0pzlcXyJ$rRG;3#7Q#ewfT@&3E=K6~;$ z`gAWm(O0|h3w`|J@)FwOT2n6dmO%0OWZ+#dHC`J z!ETnIC3Tgoy^_eTpJUSi4rMg+UN&NntU@a6z@Cy0*fxy+-vCTXJN|Gv2dfA$>n;eu zq-X#pp$x0ztFbz+S_SaRYNV_t4Zuv?ehJ-#W~?RDtcoVw5M+LcD#4YKPE>WxU`JFX zehe$Z4}_ZUuSlY>LNvAwM>`iUum{!0Z-m3eLuwfHbT zAVKCVb~^>3rM3~Csnr~WWly6C*z+N`ESciX9f5gvKMD#O&|X@G!Rl(v_4FdPaf(WC zT7iqo^`hcmrc^$dBWfj*EU8{O3fS;Fb_AOA+!hpMm!L4W6crWC2y2^%t5|;=w8RS| z$?Uv1P+Xx!wBI9@@DigSX0t;CHrYpDD?#Qb=O~!*`rbWzhU@p6%qS zgc#j3DL8aCLlg7D@9g4tzQN0S3B2`)!NkZke);7$1Q&H@PiCA+wmaxM1@eRX2I7-muWn`DP!ZM)();Zlc%KNu9xdR4-(UamGDVu{$ z#Wgq)Se&V>1Y86ZT&k&PsRV7s15+hl77iGqCZ^TueYb>OGOW|&dgTM|CZ2`}

ukXXx>gyusz!&np3fPJ*?Z3xe@q~DJ4;Y@`u@Z`eZmU_sv zkW6pLYY(y9DQ>LWDfYLcMbkKt){E8AbvQzWZ7V=kt|>>(_vCN85&%3X;&qaGIrDvS zU(3{q8wXBLw$IVRXt4TZ&Yr0 zSC%6y4jrrJc|9zH<(y`_`1Aa;1dnq(&yUZqFY6+T=XC2GHN9odHr7t)!j6EFYFB(@NrDab%fp{5^a2J4=pJ{w&vzzv0L4$?wWFoNu{@ zNGiVQ{wE0QeS*k79{ZLM&i~^^o-1#Rf6oIXj4mN#=mCzi-w3csT+H^2RyCz0KqJAu z--36QH-=y#@bYctk~WP`*%(qpeYOHJlDJMp;6y-1mQib_kh+oDp#hkuFTcWuMxi9P zll(A;D00*zxX5c+jbtFg*M=8dhS{w!AZQs-`5j7cq}1b3YCQ}@QZ&aS zeD7#_1L3|N#u;@uMls8%fn8iF?EGS2>VFx&i5a*pd0^^CaL6(c2ah=70Kr87MwiEZ zhi$OW%mH~BNjQHg4L|O+z&~s^z&djeoXl!LQa9U<#?h{^S-wwx3_|**KboCI<)C_3euO3AprL=DrpFh08!xx|U{LUyZkp%u8DD0;` zypo5tm$C>j>DWMk*?5i; zPk~29Oa(tHS1Xcs5N33v%b*ojqEfmG!2A$i zgjEqm*hj!IVHw7R9s!oUlA`@`K2}rKt2i0ik4X~h$lKNr0&$MYBU3<#&w zxyE7>0b#vM476mKwWB6$ua-+RRyjvwtxFWv^C+LMagOEZvNb^zRuiDs@cU~iT7;+7 zj{GhGMY8?=U>DAI41<=#6^spzthwYeYu$>cPC@4?Uf;<45*0c%gk zVXaRr))Hv6ydtp5J_zoyMexmO!|A#?HHDy`Ifx%4IT+=Sz=rT*N#$fM%9^hosjzL! z=HbBmBW`t9LWlzulz35WsVrrB!I=ZX{`@iQjBCZl=te4&aazRFuqc&WK%%5Iir6-DY|&%P)zKA!x2ZnXJ6t@2!x;mF1`gH*gRoX*%)^R(SITjvNWv^{o+CiH_zb!7J5GG>Yy$yi1vmsc-D^ZK-%-<2G8K4~ z0P|CPi`uc+mgk+M!geA|x$?Cm;nSV%<-_Mtycbdr@yKYrJYwnIf=m4^7#GdLfN-~k zhS%}pakhtC3(Mj?KgoOVM8hPoW*+Bxe*$>U8HrmV2#Lik^^%wxnKnCKFpWb=z1Ttc zmA0@EXq9^{LIvi<`|rp5b)|Vx1>pJ+eq=gG;~64^5Go}8$f{@pdsxQd9C4pZf8({V zJp`(pdA?umRh+M*@V*9e3^_vuCMo4lu`GcY@#xs`S&(z>O6Oo!Jf#wy$@wm94@v3Z z!~cWW=cJs__In8Ld4kx1XNVfmKukOVCWIEfZ|7a4PrpFs&=Mh`=PxlY0x;Uj`y$gy z8gS8wzzgAoV539m&;W`|7il2n+cIha8QCmS<&2TfWjQrJmno!!1ehcRFdx(o#SN2p zQ8~7NDkayI)J!a*cJc;g5p`3GYH4r7%mNyxZ=h+4$H@gW(HL$VzlIjRZk=90i>zXu zyoL@X*U>R`4V}~1mDj&#_6B-q7tlYqfWF!5=;!+*W7FvB>_ta!A0Et4p|rdg2QAJ* zUpz2JG#(fM7=f9?#&#&mNQEB(=I^%|^%QP+s)zn{mDFQMwHKUi?hqQL_z`Vn&*YDt4Jx{~E z7l#QBhJ}3uEXftqhr^UZ1PMt#rkrnhxmO7z}2iK;&&^a8~GXZAHm0bM9<4>&1mSD<-ENmy7Y$L$z2uj1Yv$C0BG=4f2i9Mc| zQD0Gqp}tWVv(A6CIgjsb&f&Y0XBEK6GV1pFW}LX3g`EjiFs_{7U_TFQKGcUe=pB=( zqLL})mKL|YMa49Z6JE?n!KNZq7z$i?lq|dkgc*sCFk*)@<)C3sfayBa;77jx-Z~7r z9#L3cT2jlX14*K;;RSFB&xcz?0X$@r#>gB*W>g@pun7)fx%?~-t~@$ZJR%F=9a9Xi zxFVd6FU6U}N(3aA<3dU$g41enDYFJ4nbio*s>hYAIz;6)Ae!aG6*VEDq!nqU?MN%{ zKxze#RUOEw?ZVT?kMZX}|AxrQUYLew;n?L&>^YU7;&EhpOQwhfT6X;fT;h~$BUEi8 zU~P0D6iJ>NUgsaoL-3u+d9}TOY%{R-_!<0@>1q6ndpLeP6AvxQ8UoxJpBSw2B3!v& z!Fs0une)g*J@M?0-jT=~z(l94jPvasan18ifmC#HDBoPE-&9 zl4F6&!cpL5MM;a>-GNsA!Q4scCU#p~l_AgOtUIIWI zoWwgMUKJ_Jll|pL@f?n14q*cUW`AZk%b9`+%Q?#5KT$9Q5B5=KUYj%PpsP!I7c87$P zx?6-Yf=5aZ%V~xo>n;!@*-nkqI$@UFgp(}$OvxDhc@NLAoKq}AJZ2IHBe60PCuBxA zFfEwmnAu67YJ~;+ifQ3Ej%E+Sh}U>5xfyQx1Mp_~p|mnXcujsB8%_&!a4e9(T=A4y zu|HZCPCz@UT>+~t6_**yG0z@`5&Mx%c0asny`P~3*379@MW+cc0xhTb+PCEnPB)3? zZdO6m(Y#SA%VFLt_B|etrgh;+Y&E>IyAeR^KY(=!Y+OJH$D+8Qr%EFFpCEDM8A5xX zAf)dhvPPERQ$4GuZWO>!RA8^HM9Pq9B+Yx`jrsQZH&2Yp`9eq$K#~6?=0!~{5n43U zNh?!I^1u3?W|}Crtsh^$e!!o9`4wNke!SwyBh-s9)@Z}H2AxA^(PvPRy$ro6@1cgrjCPV@irYkYb03ZGxS#HZ)a@#)1A zd{}zSarY5k+`WaI3My6S3pi-x0R1BlI3N&n*cQ5nY+ztyhqBBJoR2QV-|x4=e_gW| z|HpSb@Lx9SVE3sI8cEYQkR^%r2r=vv2Du{y84bi3v9Fu3|C@1aFymNbRXh!A_HAqG zq2q)XGyZSJ=hccJY(pI-Q{FQDES^jo_Cp6g?~W8P;Pj}gf(IXA{@!b~Bexyzn+{<> zyf3>64YDHWU|t_m+otgK)3Vx%!I^q&FQG>59?kE`5^C8+T4mDZYl%hKN6?USC9AG3 z0Y*SbeW!3hZBKBpU_h;KQn_FFef7CIS2k^wtpha4?Bp}a^CF*1S+Z00nW|B|c(p`; z`ADN_TC;CbVLzo82F3j}VuoRo-G*(F2WDk2B%R_;*f&WG%)bLLk6wM^!&r|W!*Y}d z<{Q9lltgxM#RM145^4b$3FK9KA+h5;e*Ok^L)TF~d=<6B^Qaw}M;%38*YUlYp*hrx z49}v0(!|eNMz5lE;wm~OuAyC$bdjLDCMcxmUQ%+;6p5I0-A5|!BSjC$G}9Q5qjTsR znMK#YB-(q&(9|`Ey4D^vH1%Mze*}XB7{h=R{N6eM-&voC+c{ z`uqi-MZSDh^5yGS4k%yo+pj;X7?`wX4vLpEpzWQYVsRuUM`CmSI$b0lmpJV5AkesL z;ANY06gJvNV69CUR#{)ccf8K6rxS4?Bm-KOe)yw_FTVFCsQ4#honNBzyl9<@!CJ!0 zYWFZ`xn9D0hajwT^oMU+8T=cj;oG*zcAtfQYCpCpfZ^ak<$N%60QwxXtRjFpq1(iR4B& zWcR|AO2vy7m^_!iYZA|pGZpN?d;&SIVLh)&pY3prgQjE%-NX9r4XeO$ zwvR2r#)Ashzmg!t>yRlVdxD;nCD&xd{}1P~?-TB}$F<@(uSpVh9Zc)S?uZKLUd)9} zS_{q)82kx0=V(QG5~##OrMya_>5m=3L$Jn0YxoaW-4a1Q4NtgHjP*^GSE)~Fr_xud| zOc1T&^E8M8>#k|0bO;|ZW#~ni5rDCvGTTl-+>_A-OO825a{Hl|*oOZ=^17AV`D7)Y)(Ip^I6bK?}0^1D@o)`(}m8m32WVe^+U2g2>Wp4&p7J4Cs5TniJI<7RCi6FqH~-wiOTkIl(deZuw?`}4Fkxm?L|gqC(7%3urN7; zm-p|Yuyz24d?R3Z(g*qmgck!l95_UP(YL|jBep2cNW%phi+{Vr6#xCFL-@N*`uHEa zO`&BUM4*&}spHfWqd3Ip^eFq1Od**N-j9{Zf{+=Qi?@Y+%bI;%V!||2O7qH_rdHHZ zXV}q@u;cUWKtsSmrj1(e!M*JsyxZ=o#HcPUw{dCU5ytPn!XpBVOv&se5bVq6_?1h5 z5pW=^B)1B{yvBsD#>@Q8&mET5y>45!zG==o|^=If3V7|YStpOM{g(Pt>N!Tbsyo8n? z)D%$#zKbqJdi?-?{zT%XvipU~@7GU4!k_V*3I>uuAj*5v@B4T7mDKx-2oG#JAz^5P{vO90T*r&xZtgg5sd;>GPd zczk^kcW38uZG1{)raf^foA45-;N_1t0r5``#=LK>Yte&LFMwA*Fx}^Qnkd#E^|W(Sr1lZDdb@|Q^!y#HI9TeOiNiiBY<=H27*T=i zQx2SshxLVcyx>FhD<9|w51(Lh@iuNR-ouT>J6Mp^<0{?wJzQP5joJB|Sh#)%*Kgdy z_3I0K{}$%2E?{Qvx=KYpHNS{ag5d~(ac1T^X88TtxdoNxe0FXT(|m7MQl9hm48c+U zpPHJ-u+BCd-5WuqM!aA8yl=Z`{TjwLz#_U5mMP7!;d{1O z!?f_n;lO+4%mG4{LW}1_R*jsbGT2W=v_HNLS`l?H;NX9N{a{agJG4V9pnWkP4(Tlj zsT_eTm5Uqittd3v4qui!ehbPyQaVRvI*jeC%SKVsIYU(Rz0l`t>&OZmiztO96_hKL zw-aI6o(jf|){{&neG3kDt-DDj%|1gYTOUqVo)@OgJtTL&=;fsaP4=;gbRu`Pa ztCK$lJ3_S^ugR75(X5~$P|-R&m_La_$=z7X^Yk*i2qOK^N$S9^uuAL+%)uen$&Qwp z3$MwC1FAO%RL^RbBe1}0lIxQdLi)L*IFQguNNl79IRHJ$GRijA2`$0F^I25-|ZocyeS_k^szM-h+)XO<2eFko%-V<+_{qY2T${?7ol(%cMql z5)wT*(4P`d7s1S@`YK$j7nKJ^0LFj-W0Wz7^}J8oX`O1yMJI)dG@=Td{R!0ss-uaG zaOdD1R6LBB+DTksUA$SAcw!{pNbZ>d;Z8593#$l;2MM?Oyrw<7!=mlg#_fip# zCN;s6gKlu~2;ys|5Xhq++gWxDmLN>=z!7)+L5^4g>4h1f<38cpJ@@*B8f)pj1M0WDoe!do1`4-eGpQ|Y( z{x6B?E;jVz^Vj$I^zmmzH_gMTq@T}PKm5ykafxG2aPE{@@`HIi~EcUS9 z>JSDbiJbx%KIgHm6Zk@adHM1K4X{}PWH)^4CeS!@3+-1Qpn3idG6t@}tYlDmMD%C~ zTqg8%UcZgOTlbOPzo3~~qF9%XpnUuW#_l{q&Gb#2EE~jrnI__A;%(7*UNjpx3bbgv zGy+VTDJZ|{Q9OV36i?rLi6iaVD z{o4TZdnQ?T)DGB(GTu1q0mwiEb$R4J0{`|;b8vVm_DouJ<{|s8YrqI#L2I`$fRqHSs zI>u1jHi|k*EvdMsMZ7D+sBarWZSx=+nt5y(L?t_VS#=LeDmqY5(t@nKdZc7kVyLYP z)5GI%jwr;Bb{Fu2T@b!!=aXrq-Od6q&9Dki!#@~%;cpC`vHnyfT&#pq@aDiKII%)#X_2Ll5ti$g2mB3lp~Alw`-m{4Ls3rcds2&{-V=8(Wk*$fON z5}mSJ;$j*XV39e9eN@g}-Tip>>K$Cd3tIm(Kq9d44#MnnTJ+X*n6?Zfed*?DXws2N1% zVyj~)ey|9@kEdg?CNNdy8(KrKS?v=Gty9s^au35g!pmBx3(#^nk2Q8@@uP(g_MbR~ z$lPiKv{Hc(B=#ovU|nP*6(k26TIHfpEE5`G8C`}G@wM>aKy^N|4Iu?xxRBRLi+YTN zPX#SXn##qchHUoVqzVoq zw1#BKt_ntFIRY@o>4Vr5R*O9Z7y&As)}l+Co-=N6>S5E zt&%L6vX9pd6?7_I7;$}zvfmObfwKcJ;B_4$JnRlH$JW4X>)A+&Ku1<%TKhk5x`7^$hgCKbP8kT(Qf33iTaWcwDeoE+$}jV%)z5SUzz!kP|_ z0fUGuVf$1NtOOdU@Qc}t# zX)MH5_QRb9gse!CIvEk}q;1yo-W=lnmUtT74K|dk@#yRtt9@VD8ofg4zUjBsHj2NxM_)urs+HyAoxIHUH;vXM8nw z#Fb-PR0)h?3NSIygYv3w=$|-?J;xoO@9YcR<1W~*XGMUqg3iGc$VpB>Xmmcl)3wEF z6EFPa9*JYgjR}RHHm2x8X;K5f}|< zyQ@}=`L*7~DFrWgm7Hq34ddqNMLJf(MomGx8J}lh5Jben+k5(ILEi z0~nb?ifA6k=TEQj;`Jvuu`YYrRz-vJ`1+$FmnpctL=1t7DlQ%VgSXCxP@30m{2}5XM<8|33h;kI$aNe*`ch-WC0j zJTU917&XhNQ?TJ|61EUvBzSkVih-%ZA7jdqT-&RrknSzLg-cd9Oh~hai8Xxis-Txx zMVhU^p_mHjb1>OQ;L(jP#X%hKWJ`=c~RoyZdGi6~OJCw5&a zfcE7)Xj6&oxs*c-E1T9@7PJG?vFBV0cKRh^r%w#_ct)VIxC--QlkkWsftF(kRy$lE z$VebB0mkLL+G@Z$Bm@6+)Ej@RXNTQ^v2biyz;43GPFn9el)W;Q#DVCbzzQvPStfmi zP$F=0gx0&PIFcpQhe~866Jdq_OU@CsD|N*jg-Vs3)Rdj{xLDS-KE<7H$<8W!Avu;` z!#wIr%33yM5`Tdk9oylpKB~78WvRK%a0ymX7M@nyyCHk562!i ze%Cb$d);M+;8^VSjDrr3+C1(dJnZB5bSaX&ZjVO{bObCs2pc@^a@Tx+uU7(LBOcoB zaq9bf1VZ>)+nw*bQCwM;XA;X#U^y&{=NPdr*JkJO+i!nHbmcI%pNhdwuN6;=cw+cl zJ6Wf1vcpZlB^q0tA_y*5u-+yVe=rNgR_|!&M`U7~LkNDb3C0@2u>^~+A-t^eOHiJd z4Xpb*j|i-D561=q%sR&)Xz@O-w(-MvW?tBC;)eLVYMgIhfMGf5or-8p1Qih#s~#1| z{-jPE=U{)7&|nr>jqvCKEROWx>hKU|h6fQ^*h+w*1AimgV!b?gp_VT9Rh9 zP@##k?}LHBM`R5SgcsvTXekH1Oxzl1!jq{U%*;+Bpn6KJ0CKEafN#@n7!^+AXxad_ z5`^|qk;t-PJt}*{q$U`MLJTW`c~m9pDr<3nY7n=^cwM7Ih@@36Q%M3t5?>(zb2N>X zG%a$&>>gg%5Dk=G97$-!-pi%Xj;O$~$SRcNmtwZ32@mFm(B0LK01jN@WjIGAE%``{ z3Gj#57F*+J#TE|3j4*DRJD~QKIYf{;AWAX13Momscren5clQ?X?7<^swaZGY8wldy zD@(YIvWKyaN_tmP2P}%lVM+tQG-Ck9RQUS|cKfL4k44uZB_S7&XNK_n_6=NLxJB!G z4&Lfs-GUJTMoo*!)DOYqB%ec5LX1gP4~(hs^<(N_5Z?$7g2z-_J(jPHV0mFeO(S?! zUspT+O5m$e-Z+jVcdPiIV;ro-GiQ-A2(z?y7!k$}5Eu>x%j7KxiM!)kp_kbUhterH5I$@OGUl1xIGWrHeJVwhlvc!N zSL4guS9tee5ntcEM#~s2bO9kMI$QQXYqqffq8Z!7l@Q=sG7Gn&3D~mSBPmTP%eYBW z8!p6U~Q`@6Fky!jN-1C+sM$f4}d=)#87W(6)1_p&Rq72DEUusvO3V8ko) zZL>$svS1+3!f=TE2N(G@ck)0xdaTdKAE@X(O3JQqxEpxVcc}zk83_2QOh!Fv$DRkB3yS&j>b8A3w$Cj~|fVw+P+T z2Bg-tVQ_Q`qhs@U`se}Py?%p>Rnsari~x)_b=7VfB-+WfYKgTZxzi@V?250%*2rQU ziY~-ZUpGo^HT?K?fgbA9cXCy~nX*zd6zqq7f382lLa>Fh5U2Fr^W) z&(PWW>u`|xNE)*zD+n=F^ROk%*wf&$XaA8U)$(jfT-Dj;n>a^!k-iW>5tvaiP81Km zmJ}SPWXeb&hWGiDe5XUQx<5c*&tsgITt5Ae5i#@xabwSrGVuZ~jaSt^NCFdkDYA?@ zyk&y0@ft4)0B*Hc)q6D~bNKD&59pbBgo5r_JXv~z*94VQ{JdiLI({Wk_Rl;$7`groN6SVDFq&zm0}{MTD3PflO}vZ-UKGIa zbN?y{p;*Gpw;$kH&$=e5A@C^(SN$doW^-*P5 zL(z&X#aa#`t7vup5L$pAE*D_cuy*04h7mTEApk>Ty`*9fMVbm-VipC@HMM)o}t$bP3i` zL9V9N{sR@?cPIU!?Q#Jv)s3*dn2EnPa>pu%KsXllDmUIiiEE+gmrX*ylvZmQtvq%* zQ+7DnLO>FKnX?005KJU{s3h((C&8Ll(E?*~)HUHjkzr(Rg|1 z9!9P{;X@RUeQvSXPng*65l?`L<9l&9=oy3K{)wk4i^}L@Oy`r$uGm-#9@No&jdfvx%b^%yp z?T6o)dSZu#2cq)o5!Q20c`No)5v_@+!x1VVi5EFWh%x7YeVi7xF)jY6@H{H9A-ugY zi5E9!5SH5vU&5uV;1P)N;C<7}8YRHAd zcs@0Nudkn=p#LVktFOV6Wd-tHTN0)W(g&bJCB0Wx+OQmpqA^%dQCnp8<5*e;j3et& zm6e0H^F5Sa+?W@Dkvt^V)$-)?Eq7s3Gz+8DKD9lE9u>2Bv8<9CgCzmvB$f72Dl)s6 zdW<*M;lr&Nyqz1srw3P&*>y{;ZgOW?;*LHBrIZ zE|?P<2J2bQ!YJO}8pG7sI06X_l6CkrEkl_aGtM4`VM;f4Bubzv>%nKmqF@5{ga^ms zF~S4kDz*U`>BV?9-hnUoXYu;wTO>4V+E=bga^gtv?augS=&&7ZsHClV@2qJA*b^Si z1sGGhU>x6yq?7`@nIFQ3CwJ7Qh~YFcylBnJl4?W3oe`l-VwH~M48Xa3miKE)t>ST@ zF=0#CI+EH2Z(7n1$2zgRIEt5ZgJ|lVRDrmsX-s(X`83QOBM@q!%)DR}ZY<|y;Ut_0 zA(_%^_SScBpAf+tNwcQDHfi z&A^36SGJRN?jYN)6aJ~yc=h-pz7T?bS$>T1#V7FLm~oCqjVzg!{6Bl*+HfdqKqW$R zqyl%K$VxUxj!DOPtwyQsNGfXvzI?#)U0Tj>mry%Qi=1@{Y=5X$$~okX@; zr+lgx;727X9!GCl{q}4t^VA*$B@|$3t_vS;PvPr*DxjOs5k2%Aal=nhIr*H#Szv~ri#omINoP9Vq$I*_a3~!aT+)RExRak+?`yHJxO&+cE(o`Agi&1 zdTkqxX#L0n4EA)OtfmKhXjmO|z5xBB&e(g*9(!%vvF3mU*6%uoti)J^B;>*EVlu45 z3vseYawW~+taw~_G-aPKXJ4>nAGa-=f)n+MOy9T&!0?`U)h{5l;|@aG?-KOy;3C1~ z44++pLd*HK`#2>4Bf;8jch%8Ng!kKr-<8CJ=X(h-B7J;LhMys3^aZkJULdUh5nc(+A`j4iN zWc~c=h2QX2+T9vIo4+lW^0y6AFfMVDbM z0cJyFId()A;dn|lY|`prmtN2BRH+q8Yr{*RLxt*|U59f;t+-Ov1K(28JIfci*-E8$ zG@%4r2{fxO=3+;1CY<=cM|zdog?Qb$3}~@VYkU*1W(8o@xn4$DQ59xK$KV!02(rJZ zmfU`C6QE*Yb~y*4T{7`r%El^M^~QWK#ic9(R01zLR5k}WAWQJ>VRkyn`yxxFk8)s> z?4`#9WC$^`Oj@(zXkM*IlI7LnZ80U-nDHnObDUyDkg?%ld8+LJyhzWI14aU{LMOJevYN37kKpKIa&ru-9D)>JspqE z?qTFMPAJbwOmaCM-(SMhr!Vp3=_}m4_Y4*n@~}rhiNAZmCke)<;xIp{0hpMIA?)`0 zHf6+myAfR6qLu7)jl?d>7W*qI$IB1q!T8QJ2-|%LU*YN4=n{%QSO??#^XymQ1z5}b zp%s{hjs8h$YH70oj7J!@dq-dkkL#QXF!q58VAc{~{`r_Yw5`1nQqqn~Jr8h@O8P)@ zC)P*QQ%Mgh%ifF%S}b8Z%887Agt4#P>#E1&p>{l-9ztAspIQy#U2}sNwoJ+lT^JL++-za96d$C1`1t6Ub8q6j3gTF~M> zk}-(=EJru33nz;wS(dDZqGF@6w&VX6grS^_65Q%(z>Us&jP(t`zh(}uEJLMxUW*g!>CV1uFJ=}xhsA`eZjM1N%sZVmQeV)7a;RL{YS zwAA4YTxKBxcv((NGs2jSpaM`Wk|3 zudC#4;$1Q-oFbI<(NN<3CLFjBjAYreHOq3XxT?G?4t(vB(u9`EYK*itVXUN>&U25fm@nxln#{Tg20zKZ%0 zDj|L*%h#ox6IpzwVp|BT{R9!V39n01(aXK`WnVqb@49kKI-k|7cHF-^HG`KA?;x*_ z;|T#VsQnQw{dqVOEVYxnaDoa`lJiO5mh|*Kyq6awnO*aJ)`<$A08&#~kM6cU%#BQ= zdi*hBhF&NSOgxpSenyvOibz%*5m>eh%BL-s2jcu?Ud%f0L;#$8th8Y$j*dn zKKGT_9#@H-aTVAeQ$|B84}+bpsH*M5o-;|%_71~-hX80B+GF<-8|*mliZyzc$WKi~ zWJ(cyLXvSZst9HT7+L8j%amm`nQ6(m8k3F{3=^_P+0Q3=Pp9Eme~mCL+fxwmTW{ea z0p%>8eMvg#OT)pd{)X}vdhk1v&cKntVJ84eJ>y|at6KJpBa z1elEJmxw3K=oJnt4~&j@y$CB|9PdAWe1qlXF9ZY{ZMl7@7@UP{$UJ`M6>6q#;>GLd zc=z@LGCJj69q`myn15h~jI@ciWqEWde!kMBO< zF_ot`3G9d99E6wDVdDBdn8r6?b8r@Ns$1}wC|2VS-t@jkX*mEFvZ>1&C&W_jjh*rfC4tQr^n|%~^5MFlJQTg+=cx1NP zMnK>33LY=q#`yeG=n!7CouifPap7yqQTHgkkllozy}{V{Jf1yzf{&lRQb7;l93Q}+ z-@U{9jfd#&nLu;bDE#Z6pFxpdXloq@qR~4oHT3XbMWInvhsn10CN; z!e}70Y|mlUiPQKWhECXRa|$8V0|=niqC@4XM=7qFY2@Ey_4?8MNS1Pmf z$<0VlEkIsY8LBIq5m`A7KPm)`g-Ycp9+-~^{6Dh z(mHV|vk@@`El8;D$7%K(`3)y3O3wR4cfG7`rR)V7Y(z0jIptRo$iBKT zGlzTAbC~Yz#niw!E;d|K

Cg;@X!z0+W*k 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

c%Igdr>Pyd9@m1`X|4F2 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

^j%B)xaJ0`2VH{|Sh2ebC*rng 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

IArCdzZeVu)9zLbASAAw>F^F*h6Uc8&Lq`G_ zSy(h&6youPkp)K3qBO5#uVyG|rjqK?45JVNbg0&GQ5yHT8BMBFAfw|cJ1al8-z45nuEiRj=W5m^c+>FN z-}ns;_x0j>`!JtF4O+WzVW4{uAEsY}W?*Rw_ZouCXQ!*tKhTB2zHxkTqJcnBh#$_^ z66lAKd!dW>r<@>Ch?Bg(vjo5$IW7E#%1}^y9rvg|4_9>BETR=hE0A7&or-=2_wU`q z!OGjVnBDS(GJKzN5%YwJnj1s-kk2f$qz=cbZevYqmE~EVQfli8-R_+rI2R*i$1$5( z8}@BHBELC|S2iC&LuD!YT3c-)S@VJU4ZN5v%;M+SS!ac@bz)?xq3AaV_qhL_bUnf6 zw-6(Ekzb79MJw>y^l7j4#S1VJ@9+@;W?lfZz;UgRBjrxBDm?M=p@%W}Ac$@(9_*Z+e_|u(O^2v_~{QGW%ezgbLr_bRRlB-!q?BWC| zzXcb!$c@(@#)g9UfoTZI3okZ&^xu47#5@_0XxzWFfJChzMXP_G^18HEsJ5K70i!8rJYYi?a+k9}f9# z1QJM=?>K=s;?Lo|WWMmJMR<)be$V}i0_*+IP*050v z(r^cr!;5T;Hf5IK6W;LEZ0JI%umm!%v(6pab=XmGf%JX>KjvS?t9(ddR1$wqFF-;` zJ>pHSBB4}@_JaM9(`Fh`;mHc);%-)ue!{3UUjok(4ZCbTjgT)=>?d%`cFNT3^4SIJjiDRBaGyZM3pM5gV`Y8?7dsB)>RJ2Ak|T)WJ@-zl);bollK9CgW8mUK zEz0M+i}1p@&01of0F}``D%l7^WNBSJ4)PfW@!lWHEk$ixH{uSQ!JackXzu98iufGX zFF4A;9}Z`rqq~cAeg$j4O2n$SHX?H4AtYzzBDeAio+4;I_xHodKU;{wk#YPftrWYm z^7&nk@>`t2Jm1H8eu!OzV|XQjy`_>$T5XL7DGakG*4I6OVk)zuikmo7(u@}mmmrD&dil~73=U7?&us8z zb*XO9PYx&X;qfZ0Idlf~RA&ERPphVB03ihDjTwc!&*M~*-F$Zl9*57Ov+XwT;{u=Y z4WyjCfPt=$ zTewH%Q)i$j$dOZJ*`)?5%)9tH_p-Byc) qghBc48`8~LraW+#+%0jFlK@A?3c(_ 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 + + 3 + + rt-thread + + ARM + + 1 + + C-SPY + 2 + + 32 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 1 + + + + + + + + CADI_ID + 2 + + 0 + 1 + 1 + + + + + + + + + CMSISDAP_ID + 2 + + 4 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 1 + + + + + + + + + + + IJET_ID + 2 + + 8 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 16 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + NULINK_ID + 2 + + 0 + 1 + 1 + + + + + + + PEMICRO_ID + 2 + + 3 + 1 + 1 + + + + + + + + STLINK_ID + 2 + + 7 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 1 + + + + + + + + TIFET_ID + 2 + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + XDS100_ID + 2 + + 8 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\FreeRtos\FreeRtosArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\HWRTOSplugin\HWRTOSplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin2.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\RemedyRtosViewer\RemedyRtosViewer.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8b.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8bBE.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\TargetAccessServer\TargetAccessServer.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + + + Release + + ARM + + 0 + + C-SPY + 2 + + 32 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 0 + + + + + + + + CADI_ID + 2 + + 0 + 1 + 0 + + + + + + + + + CMSISDAP_ID + 2 + + 4 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 0 + + + + + + + + + + + IJET_ID + 2 + + 8 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 16 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 0 + + + + + + + + + + NULINK_ID + 2 + + 0 + 1 + 0 + + + + + + + PEMICRO_ID + 2 + + 3 + 1 + 0 + + + + + + + + STLINK_ID + 2 + + 7 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 0 + + + + + + + + TIFET_ID + 2 + + 1 + 1 + 0 + + + + + + + + + + + + + + + + + + + XDS100_ID + 2 + + 8 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\FreeRtos\FreeRtosArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\HWRTOSplugin\HWRTOSplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin2.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\RemedyRtosViewer\RemedyRtosViewer.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8b.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8bBE.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\TargetAccessServer\TargetAccessServer.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + + diff --git a/bsp/n32/n32g45xvl-stb/project.ewp b/bsp/n32/n32g45xvl-stb/project.ewp new file mode 100644 index 0000000000..c5defb3a07 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/project.ewp @@ -0,0 +1,2418 @@ + + 3 + + rt-thread + + ARM + + 1 + + General + 3 + + 31 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 36 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 23 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + BILINK + 0 + + + + + Release + + ARM + + 0 + + General + 3 + + 31 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 36 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 0 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 23 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 0 + + + + + + + BILINK + 0 + + + + + Applications + + $PROJ_DIR$\applications\main.c + + + + Compiler + + $PROJ_DIR$\..\..\..\components\libc\compilers\common\stdlib.c + + + $PROJ_DIR$\..\..\..\components\libc\compilers\common\time.c + + + $PROJ_DIR$\..\..\..\components\libc\compilers\dlib\environ.c + + + $PROJ_DIR$\..\..\..\components\libc\compilers\dlib\syscall_close.c + + + $PROJ_DIR$\..\..\..\components\libc\compilers\dlib\syscall_lseek.c + + + $PROJ_DIR$\..\..\..\components\libc\compilers\dlib\syscall_mem.c + + + $PROJ_DIR$\..\..\..\components\libc\compilers\dlib\syscall_open.c + + + $PROJ_DIR$\..\..\..\components\libc\compilers\dlib\syscall_read.c + + + $PROJ_DIR$\..\..\..\components\libc\compilers\dlib\syscall_remove.c + + + $PROJ_DIR$\..\..\..\components\libc\compilers\dlib\syscall_write.c + + + $PROJ_DIR$\..\..\..\components\libc\compilers\dlib\syscalls.c + + + + CPU + + $PROJ_DIR$\..\..\..\libcpu\arm\common\backtrace.c + + + $PROJ_DIR$\..\..\..\libcpu\arm\common\div0.c + + + $PROJ_DIR$\..\..\..\libcpu\arm\common\showmem.c + + + $PROJ_DIR$\..\..\..\libcpu\arm\cortex-m4\context_iar.S + + + $PROJ_DIR$\..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + + DeviceDrivers + + $PROJ_DIR$\..\..\..\components\drivers\can\can.c + + + $PROJ_DIR$\..\..\..\components\drivers\hwtimer\hwtimer.c + + + $PROJ_DIR$\..\..\..\components\drivers\i2c\i2c-bit-ops.c + + + $PROJ_DIR$\..\..\..\components\drivers\i2c\i2c_core.c + + + $PROJ_DIR$\..\..\..\components\drivers\i2c\i2c_dev.c + + + $PROJ_DIR$\..\..\..\components\drivers\ipc\completion.c + + + $PROJ_DIR$\..\..\..\components\drivers\ipc\dataqueue.c + + + $PROJ_DIR$\..\..\..\components\drivers\ipc\pipe.c + + + $PROJ_DIR$\..\..\..\components\drivers\ipc\ringblk_buf.c + + + $PROJ_DIR$\..\..\..\components\drivers\ipc\ringbuffer.c + + + $PROJ_DIR$\..\..\..\components\drivers\ipc\waitqueue.c + + + $PROJ_DIR$\..\..\..\components\drivers\ipc\workqueue.c + + + $PROJ_DIR$\..\..\..\components\drivers\misc\adc.c + + + $PROJ_DIR$\..\..\..\components\drivers\misc\dac.c + + + $PROJ_DIR$\..\..\..\components\drivers\misc\pin.c + + + $PROJ_DIR$\..\..\..\components\drivers\serial\serial.c + + + $PROJ_DIR$\..\..\..\components\drivers\spi\spi_core.c + + + $PROJ_DIR$\..\..\..\components\drivers\spi\spi_dev.c + + + $PROJ_DIR$\..\..\..\components\drivers\watchdog\watchdog.c + + + + Drivers + + $PROJ_DIR$\..\libraries\N32G45x_Firmware_Library\CMSIS\device\startup\startup_n32g45x_EWARM.s + + + $PROJ_DIR$\board\board.c + + + $PROJ_DIR$\..\libraries\n32_drivers\drv_adc.c + + + $PROJ_DIR$\..\libraries\n32_drivers\drv_can.c + + + $PROJ_DIR$\..\libraries\n32_drivers\drv_dac.c + + + $PROJ_DIR$\..\libraries\n32_drivers\drv_gpio.c + + + $PROJ_DIR$\..\libraries\n32_drivers\drv_hwtimer.c + + + $PROJ_DIR$\..\libraries\n32_drivers\drv_spi.c + + + $PROJ_DIR$\..\libraries\n32_drivers\drv_usart.c + + + + Finsh + + $PROJ_DIR$\..\..\..\components\finsh\shell.c + + + $PROJ_DIR$\..\..\..\components\finsh\msh.c + + + $PROJ_DIR$\..\..\..\components\finsh\cmd.c + + + + Kernel + + $PROJ_DIR$\..\..\..\src\clock.c + + + $PROJ_DIR$\..\..\..\src\components.c + + + $PROJ_DIR$\..\..\..\src\device.c + + + $PROJ_DIR$\..\..\..\src\idle.c + + + $PROJ_DIR$\..\..\..\src\ipc.c + + + $PROJ_DIR$\..\..\..\src\irq.c + + + $PROJ_DIR$\..\..\..\src\kservice.c + + + $PROJ_DIR$\..\..\..\src\mem.c + + + $PROJ_DIR$\..\..\..\src\memheap.c + + + $PROJ_DIR$\..\..\..\src\mempool.c + + + $PROJ_DIR$\..\..\..\src\object.c + + + $PROJ_DIR$\..\..\..\src\scheduler.c + + + $PROJ_DIR$\..\..\..\src\thread.c + + + $PROJ_DIR$\..\..\..\src\timer.c + + + + Libraries + + $PROJ_DIR$\..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_usart.c + + + $PROJ_DIR$\..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_wwdg.c + + + $PROJ_DIR$\..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_exti.c + + + $PROJ_DIR$\..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_can.c + + + $PROJ_DIR$\..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\misc.c + + + $PROJ_DIR$\..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_spi.c + + + $PROJ_DIR$\..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_i2c.c + + + $PROJ_DIR$\..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_adc.c + + + $PROJ_DIR$\..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_gpio.c + + + $PROJ_DIR$\..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_iwdg.c + + + $PROJ_DIR$\..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_dac.c + + + $PROJ_DIR$\..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_tim.c + + + $PROJ_DIR$\..\libraries\N32G45x_Firmware_Library\CMSIS\device\system_n32g45x.c + + + $PROJ_DIR$\..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_rcc.c + + + + POSIX + + diff --git a/bsp/n32/n32g45xvl-stb/project.eww b/bsp/n32/n32g45xvl-stb/project.eww new file mode 100644 index 0000000000..c2cb02eb1e --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/project.eww @@ -0,0 +1,10 @@ + + + + + $WS_DIR$\project.ewp + + + + + diff --git a/bsp/n32/n32g45xvl-stb/project.uvoptx b/bsp/n32/n32g45xvl-stb/project.uvoptx new file mode 100644 index 0000000000..bcf63567f3 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/project.uvoptx @@ -0,0 +1,1077 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc; *.md + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 ) -FN1 -FC1000 -FD20000000 -FF0N32G45x -FL080000 -FS08000000 -FP0($$Device:N32G457VEL7$Flash\N32G45x.FLM) + + + 0 + CMSIS_AGDI + -X"Any" -UAny -O206 -S0 -C0 -P00000000 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0N32G45x.FLM -FS08000000 -FL080000 -FP0($$Device:N32G457VEL7$Flash\N32G45x.FLM) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + Applications + 1 + 0 + 0 + 0 + + 1 + 1 + 1 + 0 + 0 + 0 + applications\main.c + main.c + 0 + 0 + + + + + Compiler + 0 + 0 + 0 + 0 + + 2 + 2 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\armlibc\syscall_mem.c + syscall_mem.c + 0 + 0 + + + 2 + 3 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\armlibc\syscalls.c + syscalls.c + 0 + 0 + + + 2 + 4 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\stdlib.c + stdlib.c + 0 + 0 + + + 2 + 5 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\time.c + time.c + 0 + 0 + + + + + CPU + 0 + 0 + 0 + 0 + + 3 + 6 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\backtrace.c + backtrace.c + 0 + 0 + + + 3 + 7 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\div0.c + div0.c + 0 + 0 + + + 3 + 8 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\showmem.c + showmem.c + 0 + 0 + + + 3 + 9 + 2 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + context_rvds.S + 0 + 0 + + + 3 + 10 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + cpuport.c + 0 + 0 + + + + + DeviceDrivers + 0 + 0 + 0 + 0 + + 4 + 11 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\can\can.c + can.c + 0 + 0 + + + 4 + 12 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\hwtimer\hwtimer.c + hwtimer.c + 0 + 0 + + + 4 + 13 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\i2c\i2c-bit-ops.c + i2c-bit-ops.c + 0 + 0 + + + 4 + 14 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\i2c\i2c_core.c + i2c_core.c + 0 + 0 + + + 4 + 15 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\i2c\i2c_dev.c + i2c_dev.c + 0 + 0 + + + 4 + 16 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\completion.c + completion.c + 0 + 0 + + + 4 + 17 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\dataqueue.c + dataqueue.c + 0 + 0 + + + 4 + 18 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\pipe.c + pipe.c + 0 + 0 + + + 4 + 19 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\ringblk_buf.c + ringblk_buf.c + 0 + 0 + + + 4 + 20 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\ringbuffer.c + ringbuffer.c + 0 + 0 + + + 4 + 21 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\waitqueue.c + waitqueue.c + 0 + 0 + + + 4 + 22 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\workqueue.c + workqueue.c + 0 + 0 + + + 4 + 23 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\misc\adc.c + adc.c + 0 + 0 + + + 4 + 24 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\misc\dac.c + dac.c + 0 + 0 + + + 4 + 25 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\misc\pin.c + pin.c + 0 + 0 + + + 4 + 26 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\serial\serial.c + serial.c + 0 + 0 + + + 4 + 27 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\spi\spi_core.c + spi_core.c + 0 + 0 + + + 4 + 28 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\spi\spi_dev.c + spi_dev.c + 0 + 0 + + + 4 + 29 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\watchdog\watchdog.c + watchdog.c + 0 + 0 + + + + + Drivers + 0 + 0 + 0 + 0 + + 5 + 30 + 2 + 0 + 0 + 0 + ..\libraries\N32G45x_Firmware_Library\CMSIS\device\startup\startup_n32g45x.s + startup_n32g45x.s + 0 + 0 + + + 5 + 31 + 1 + 0 + 0 + 0 + board\board.c + board.c + 0 + 0 + + + 5 + 32 + 1 + 0 + 0 + 0 + ..\libraries\n32_drivers\drv_adc.c + drv_adc.c + 0 + 0 + + + 5 + 33 + 1 + 0 + 0 + 0 + ..\libraries\n32_drivers\drv_can.c + drv_can.c + 0 + 0 + + + 5 + 34 + 1 + 0 + 0 + 0 + ..\libraries\n32_drivers\drv_dac.c + drv_dac.c + 0 + 0 + + + 5 + 35 + 1 + 0 + 0 + 0 + ..\libraries\n32_drivers\drv_gpio.c + drv_gpio.c + 0 + 0 + + + 5 + 36 + 1 + 0 + 0 + 0 + ..\libraries\n32_drivers\drv_hwtimer.c + drv_hwtimer.c + 0 + 0 + + + 5 + 37 + 1 + 0 + 0 + 0 + ..\libraries\n32_drivers\drv_spi.c + drv_spi.c + 0 + 0 + + + 5 + 38 + 1 + 0 + 0 + 0 + ..\libraries\n32_drivers\drv_usart.c + drv_usart.c + 0 + 0 + + + + + Finsh + 0 + 0 + 0 + 0 + + 6 + 39 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\shell.c + shell.c + 0 + 0 + + + 6 + 40 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh.c + msh.c + 0 + 0 + + + 6 + 41 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\cmd.c + cmd.c + 0 + 0 + + + + + Kernel + 0 + 0 + 0 + 0 + + 7 + 42 + 1 + 0 + 0 + 0 + ..\..\..\src\clock.c + clock.c + 0 + 0 + + + 7 + 43 + 1 + 0 + 0 + 0 + ..\..\..\src\components.c + components.c + 0 + 0 + + + 7 + 44 + 1 + 0 + 0 + 0 + ..\..\..\src\device.c + device.c + 0 + 0 + + + 7 + 45 + 1 + 0 + 0 + 0 + ..\..\..\src\idle.c + idle.c + 0 + 0 + + + 7 + 46 + 1 + 0 + 0 + 0 + ..\..\..\src\ipc.c + ipc.c + 0 + 0 + + + 7 + 47 + 1 + 0 + 0 + 0 + ..\..\..\src\irq.c + irq.c + 0 + 0 + + + 7 + 48 + 1 + 0 + 0 + 0 + ..\..\..\src\kservice.c + kservice.c + 0 + 0 + + + 7 + 49 + 1 + 0 + 0 + 0 + ..\..\..\src\mem.c + mem.c + 0 + 0 + + + 7 + 50 + 1 + 0 + 0 + 0 + ..\..\..\src\memheap.c + memheap.c + 0 + 0 + + + 7 + 51 + 1 + 0 + 0 + 0 + ..\..\..\src\mempool.c + mempool.c + 0 + 0 + + + 7 + 52 + 1 + 0 + 0 + 0 + ..\..\..\src\object.c + object.c + 0 + 0 + + + 7 + 53 + 1 + 0 + 0 + 0 + ..\..\..\src\scheduler.c + scheduler.c + 0 + 0 + + + 7 + 54 + 1 + 0 + 0 + 0 + ..\..\..\src\thread.c + thread.c + 0 + 0 + + + 7 + 55 + 1 + 0 + 0 + 0 + ..\..\..\src\timer.c + timer.c + 0 + 0 + + + + + Libraries + 0 + 0 + 0 + 0 + + 8 + 56 + 1 + 0 + 0 + 0 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_usart.c + n32g45x_usart.c + 0 + 0 + + + 8 + 57 + 1 + 0 + 0 + 0 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_wwdg.c + n32g45x_wwdg.c + 0 + 0 + + + 8 + 58 + 1 + 0 + 0 + 0 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_exti.c + n32g45x_exti.c + 0 + 0 + + + 8 + 59 + 1 + 0 + 0 + 0 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_can.c + n32g45x_can.c + 0 + 0 + + + 8 + 60 + 1 + 0 + 0 + 0 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\misc.c + misc.c + 0 + 0 + + + 8 + 61 + 1 + 0 + 0 + 0 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_spi.c + n32g45x_spi.c + 0 + 0 + + + 8 + 62 + 1 + 0 + 0 + 0 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_i2c.c + n32g45x_i2c.c + 0 + 0 + + + 8 + 63 + 1 + 0 + 0 + 0 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_adc.c + n32g45x_adc.c + 0 + 0 + + + 8 + 64 + 1 + 0 + 0 + 0 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_gpio.c + n32g45x_gpio.c + 0 + 0 + + + 8 + 65 + 1 + 0 + 0 + 0 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_iwdg.c + n32g45x_iwdg.c + 0 + 0 + + + 8 + 66 + 1 + 0 + 0 + 0 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_dac.c + n32g45x_dac.c + 0 + 0 + + + 8 + 67 + 1 + 0 + 0 + 0 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_tim.c + n32g45x_tim.c + 0 + 0 + + + 8 + 68 + 1 + 0 + 0 + 0 + ..\libraries\N32G45x_Firmware_Library\CMSIS\device\system_n32g45x.c + system_n32g45x.c + 0 + 0 + + + 8 + 69 + 1 + 0 + 0 + 0 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_rcc.c + n32g45x_rcc.c + 0 + 0 + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/n32/n32g45xvl-stb/project.uvprojx b/bsp/n32/n32g45xvl-stb/project.uvprojx new file mode 100644 index 0000000000..e030d05dee --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/project.uvprojx @@ -0,0 +1,798 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 5060960::V5.06 update 7 (build 960)::.\ARMCC + 0 + + + N32G457VEL7 + Nationstech + Nationstech.N32G45x_DFP.1.0.1 + http://www.keil.com/pack/ + IRAM(0x20000000,0x24000) IROM(0x08000000,0x80000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0N32G45x -FS08000000 -FL080000 -FP0($$Device:N32G457VEL7$Flash\N32G45x.FLM)) + 0 + $$Device:N32G457VEL7$firmware\CMSIS\device\n32g45x.h + + + + + + + + + + $$Device:N32G457VEL7$svd\N32G457.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM4 + SARMCM3.DLL + + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x24000 + + + 1 + 0x8000000 + 0x80000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x80000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x24000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + N32G45X, USE_STDPERIPH_DRIVER, __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\extension;..\..\..\components\libc\compilers\common\extension\fcntl\octal;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\n32_drivers;..\libraries\n32_drivers\config;..\..\..\components\finsh;.;..\..\..\include;..\libraries\N32G45x_Firmware_Library\CMSIS\device;..\libraries\N32G45x_Firmware_Library\CMSIS\core;..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\inc;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\io\stdio;..\..\..\components\libc\posix\ipc + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\board\linker_scripts\link.sct + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + Compiler + + + syscall_mem.c + 1 + ..\..\..\components\libc\compilers\armlibc\syscall_mem.c + + + syscalls.c + 1 + ..\..\..\components\libc\compilers\armlibc\syscalls.c + + + stdlib.c + 1 + ..\..\..\components\libc\compilers\common\stdlib.c + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + CPU + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + + + DeviceDrivers + + + can.c + 1 + ..\..\..\components\drivers\can\can.c + + + hwtimer.c + 1 + ..\..\..\components\drivers\hwtimer\hwtimer.c + + + i2c-bit-ops.c + 1 + ..\..\..\components\drivers\i2c\i2c-bit-ops.c + + + i2c_core.c + 1 + ..\..\..\components\drivers\i2c\i2c_core.c + + + i2c_dev.c + 1 + ..\..\..\components\drivers\i2c\i2c_dev.c + + + completion.c + 1 + ..\..\..\components\drivers\ipc\completion.c + + + dataqueue.c + 1 + ..\..\..\components\drivers\ipc\dataqueue.c + + + pipe.c + 1 + ..\..\..\components\drivers\ipc\pipe.c + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\ipc\ringblk_buf.c + + + ringbuffer.c + 1 + ..\..\..\components\drivers\ipc\ringbuffer.c + + + waitqueue.c + 1 + ..\..\..\components\drivers\ipc\waitqueue.c + + + workqueue.c + 1 + ..\..\..\components\drivers\ipc\workqueue.c + + + adc.c + 1 + ..\..\..\components\drivers\misc\adc.c + + + dac.c + 1 + ..\..\..\components\drivers\misc\dac.c + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + spi_core.c + 1 + ..\..\..\components\drivers\spi\spi_core.c + + + spi_dev.c + 1 + ..\..\..\components\drivers\spi\spi_dev.c + + + watchdog.c + 1 + ..\..\..\components\drivers\watchdog\watchdog.c + + + + + Drivers + + + startup_n32g45x.s + 2 + ..\libraries\N32G45x_Firmware_Library\CMSIS\device\startup\startup_n32g45x.s + + + board.c + 1 + board\board.c + + + drv_adc.c + 1 + ..\libraries\n32_drivers\drv_adc.c + + + drv_can.c + 1 + ..\libraries\n32_drivers\drv_can.c + + + drv_dac.c + 1 + ..\libraries\n32_drivers\drv_dac.c + + + drv_gpio.c + 1 + ..\libraries\n32_drivers\drv_gpio.c + + + drv_hwtimer.c + 1 + ..\libraries\n32_drivers\drv_hwtimer.c + + + drv_spi.c + 1 + ..\libraries\n32_drivers\drv_spi.c + + + drv_usart.c + 1 + ..\libraries\n32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + clock.c + 1 + ..\..\..\src\clock.c + + + components.c + 1 + ..\..\..\src\components.c + + + device.c + 1 + ..\..\..\src\device.c + + + idle.c + 1 + ..\..\..\src\idle.c + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + irq.c + 1 + ..\..\..\src\irq.c + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + mem.c + 1 + ..\..\..\src\mem.c + + + memheap.c + 1 + ..\..\..\src\memheap.c + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + object.c + 1 + ..\..\..\src\object.c + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + thread.c + 1 + ..\..\..\src\thread.c + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + Libraries + + + n32g45x_usart.c + 1 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_usart.c + + + n32g45x_wwdg.c + 1 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_wwdg.c + + + n32g45x_exti.c + 1 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_exti.c + + + n32g45x_can.c + 1 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_can.c + + + misc.c + 1 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\misc.c + + + n32g45x_spi.c + 1 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_spi.c + + + n32g45x_i2c.c + 1 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_i2c.c + + + n32g45x_adc.c + 1 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_adc.c + + + n32g45x_gpio.c + 1 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_gpio.c + + + n32g45x_iwdg.c + 1 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_iwdg.c + + + n32g45x_dac.c + 1 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_dac.c + + + n32g45x_tim.c + 1 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_tim.c + + + system_n32g45x.c + 1 + ..\libraries\N32G45x_Firmware_Library\CMSIS\device\system_n32g45x.c + + + n32g45x_rcc.c + 1 + ..\libraries\N32G45x_Firmware_Library\n32g45x_std_periph_driver\src\n32g45x_rcc.c + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + template + 0 + 1 + + + + +
diff --git a/bsp/n32/n32g45xvl-stb/rtconfig.h b/bsp/n32/n32g45xvl-stb/rtconfig.h new file mode 100644 index 0000000000..607fa15f7f --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/rtconfig.h @@ -0,0 +1,208 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 1000 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_HOOK_USING_FUNC_PTR +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_SMALL_MEM +#define RT_USING_MEMHEAP +#define RT_MEMHEAP_FAST_MODE +#define RT_USING_SMALL_MEM_AS_HEAP +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "usart1" +#define RT_VER_NUM 0x40101 +#define ARCH_ARM +#define RT_USING_CPU_FFS +#define ARCH_ARM_CORTEX_M +#define ARCH_ARM_CORTEX_M4 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 +#define RT_USING_MSH +#define RT_USING_FINSH +#define FINSH_USING_MSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_CMD_SIZE 80 +#define MSH_USING_BUILT_IN_COMMANDS +#define FINSH_USING_DESCRIPTION +#define FINSH_ARG_MAX 10 + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 +#define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_CAN +#define RT_USING_HWTIMER +#define RT_USING_I2C +#define RT_USING_I2C_BITOPS +#define RT_USING_PIN +#define RT_USING_ADC +#define RT_USING_DAC +#define RT_USING_SPI +#define RT_USING_WDT + +/* Using USB */ + + +/* C/C++ and POSIX layer */ + +#define RT_LIBC_DEFAULT_TIMEZONE 8 + +/* POSIX (Portable Operating System Interface) layer */ + + +/* Interprocess Communication (IPC) */ + + +/* Socket is in the 'Network' category */ + + +/* Network */ + + +/* Utilities */ + + +/* RT-Thread Utestcases */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + +/* JSON: JavaScript Object Notation, a lightweight data-interchange format */ + + +/* XML: Extensible Markup Language */ + + +/* multimedia packages */ + +/* LVGL: powerful and easy-to-use embedded GUI library */ + + +/* u8g2: a monochrome graphic library */ + + +/* PainterEngine: A cross-platform graphics application framework written in C language */ + + +/* tools packages */ + + +/* system packages */ + +/* enhanced kernel services */ + + +/* acceleration: Assembly language or algorithmic acceleration packages */ + + +/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + +/* project laboratory */ + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + +#define SOC_FAMILY_N32 +#define SOC_SERIES_N32G45X + +/* Hardware Drivers Config */ + +#define SOC_N32G45X + +/* Onboard Peripheral Drivers */ + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_GPIO +#define BSP_USING_UART +#define BSP_USING_USART1 + +/* Board extended module Drivers */ + + +#endif diff --git a/bsp/n32/n32g45xvl-stb/rtconfig.py b/bsp/n32/n32g45xvl-stb/rtconfig.py new file mode 100644 index 0000000000..b745c1acf0 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/rtconfig.py @@ -0,0 +1,150 @@ +import os + +# toolchains options +ARCH='arm' +CPU='cortex-m4' +CROSS_TOOL='keil' + +# bsp lib config +BSP_LIBRARY_TYPE = None + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') + +# cross_tool provides the cross compiler +# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'C:\Users\XXYYZZ' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = r'C:/Keil_v5' +elif CROSS_TOOL == 'iar': + PLATFORM = 'iar' + EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.0' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + CXX = PREFIX + 'g++' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections' + CFLAGS = DEVICE + ' -Dgcc' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.lds' + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2 -g' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' + +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + CXX = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M4.fp ' + CFLAGS = '-c ' + DEVICE + ' --apcs=interwork --c99' + AFLAGS = DEVICE + ' --apcs=interwork ' + LFLAGS = DEVICE + ' --scatter "board\linker_scripts\link.sct" --info sizes --info totals --info unused --info veneers --list rtthread.map --strict' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCC/include' + LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCC/lib' + + CFLAGS += ' -D__MICROLIB ' + AFLAGS += ' --pd "__MICROLIB SETA 1" ' + LFLAGS += ' --library_type=microlib ' + EXEC_PATH += '/ARM/ARMCC/bin/' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iar': + # toolchains + CC = 'iccarm' + CXX = 'iccarm' + AS = 'iasmarm' + AR = 'iarchive' + LINK = 'ilinkarm' + TARGET_EXT = 'out' + + DEVICE = '-Dewarm' + + CFLAGS = DEVICE + CFLAGS += ' --diag_suppress Pa050' + CFLAGS += ' --no_cse' + CFLAGS += ' --no_unroll' + CFLAGS += ' --no_inline' + CFLAGS += ' --no_code_motion' + CFLAGS += ' --no_tbaa' + CFLAGS += ' --no_clustering' + CFLAGS += ' --no_scheduling' + CFLAGS += ' --endian=little' + CFLAGS += ' --cpu=Cortex-M4' + CFLAGS += ' -e' + CFLAGS += ' --fpu=VFPv4_sp' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' --silent' + + AFLAGS = DEVICE + AFLAGS += ' -s+' + AFLAGS += ' -w+' + AFLAGS += ' -r' + AFLAGS += ' --cpu Cortex-M4' + AFLAGS += ' --fpu VFPv4_sp' + AFLAGS += ' -S' + + if BUILD == 'debug': + CFLAGS += ' --debug' + CFLAGS += ' -On' + else: + CFLAGS += ' -Oh' + + LFLAGS = ' --config "board/linker_scripts/link.icf"' + LFLAGS += ' --entry __iar_program_start' + + CXXFLAGS = CFLAGS + + EXEC_PATH = EXEC_PATH + '/arm/bin/' + POST_ACTION = 'ielftool --bin $TARGET rtthread.bin' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/n32/n32g45xvl-stb/settings/project.crun b/bsp/n32/n32g45xvl-stb/settings/project.crun new file mode 100644 index 0000000000..d71ea555a9 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/settings/project.crun @@ -0,0 +1,13 @@ + + + 1 + + + * + * + * + 0 + 1 + + + diff --git a/bsp/n32/n32g45xvl-stb/settings/project.dbgdt b/bsp/n32/n32g45xvl-stb/settings/project.dbgdt new file mode 100644 index 0000000000..73e71f6e4c --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/settings/project.dbgdt @@ -0,0 +1,4 @@ + + + + diff --git a/bsp/n32/n32g45xvl-stb/settings/project.dnx b/bsp/n32/n32g45xvl-stb/settings/project.dnx new file mode 100644 index 0000000000..fd6b6a7601 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/settings/project.dnx @@ -0,0 +1,104 @@ + + + + 0 + 1 + 90 + 1 + 1 + 1 + main + 0 + 50 + + + 0 + D:\IAR Systems\Embedded Workbench 8.4\arm\CONFIG\debugger\Nations\N32G45x\N32G457xE.ddf + + + CMSIS-DAP-NSLink:0001A0000002 + + 0 + 0 + 0 + Software + + + 1 + + + 2407728773 + + + _ 0 + _ 0 + + + 0 + 1 + + + 4 + 0 + 0 + 0 + 0 + 0 + 4294967295 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + 0 + + + 0 + + + _ 0 + _ "" + + + _ 0 + _ "" + _ 0 + + + 0 + 0 + + + 0 + + + 1 + + + 8192 + 0 + 1600416118 + 1634086963 + 0 + 63 + 1 + 0 + $PROJ_DIR$\ITM.log + 1 + 1 + + diff --git a/bsp/n32/n32g45xvl-stb/settings/project.rt-thread.cspy.bat b/bsp/n32/n32g45xvl-stb/settings/project.rt-thread.cspy.bat new file mode 100644 index 0000000000..55f86849fd --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/settings/project.rt-thread.cspy.bat @@ -0,0 +1,40 @@ +@REM This batch file has been generated by the IAR Embedded Workbench +@REM C-SPY Debugger, as an aid to preparing a command line for running +@REM the cspybat command line utility using the appropriate settings. +@REM +@REM Note that this file is generated every time a new debug session +@REM is initialized, so you may want to move or rename the file before +@REM making changes. +@REM +@REM You can launch cspybat by typing the name of this batch file followed +@REM by the name of the debug file (usually an ELF/DWARF or UBROF file). +@REM +@REM Read about available command line parameters in the C-SPY Debugging +@REM Guide. Hints about additional command line parameters that may be +@REM useful in specific cases: +@REM --download_only Downloads a code image without starting a debug +@REM session afterwards. +@REM --silent Omits the sign-on message. +@REM --timeout Limits the maximum allowed execution time. +@REM + + +@echo off + +if not "%~1" == "" goto debugFile + +@echo on + +"D:\IAR Systems\Embedded Workbench 8.4\common\bin\cspybat" -f "D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\settings\project.rt-thread.general.xcl" --backend -f "D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\settings\project.rt-thread.driver.xcl" + +@echo off +goto end + +:debugFile + +@echo on + +"D:\IAR Systems\Embedded Workbench 8.4\common\bin\cspybat" -f "D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\settings\project.rt-thread.general.xcl" "--debug_file=%~1" --backend -f "D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\settings\project.rt-thread.driver.xcl" + +@echo off +:end \ No newline at end of file diff --git a/bsp/n32/n32g45xvl-stb/settings/project.rt-thread.cspy.ps1 b/bsp/n32/n32g45xvl-stb/settings/project.rt-thread.cspy.ps1 new file mode 100644 index 0000000000..9f43aeceb3 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/settings/project.rt-thread.cspy.ps1 @@ -0,0 +1,31 @@ +param([String]$debugfile = ""); + +# This powershell file has been generated by the IAR Embedded Workbench +# C - SPY Debugger, as an aid to preparing a command line for running +# the cspybat command line utility using the appropriate settings. +# +# Note that this file is generated every time a new debug session +# is initialized, so you may want to move or rename the file before +# making changes. +# +# You can launch cspybat by typing Powershell.exe -File followed by the name of this batch file, followed +# by the name of the debug file (usually an ELF / DWARF or UBROF file). +# +# Read about available command line parameters in the C - SPY Debugging +# Guide. Hints about additional command line parameters that may be +# useful in specific cases : +# --download_only Downloads a code image without starting a debug +# session afterwards. +# --silent Omits the sign - on message. +# --timeout Limits the maximum allowed execution time. +# + + +if ($debugfile -eq "") +{ +& "D:\IAR Systems\Embedded Workbench 8.4\common\bin\cspybat" -f "D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\settings\project.rt-thread.general.xcl" --backend -f "D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\settings\project.rt-thread.driver.xcl" +} +else +{ +& "D:\IAR Systems\Embedded Workbench 8.4\common\bin\cspybat" -f "D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\settings\project.rt-thread.general.xcl" --debug_file=$debugfile --backend -f "D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\settings\project.rt-thread.driver.xcl" +} diff --git a/bsp/n32/n32g45xvl-stb/settings/project.rt-thread.driver.xcl b/bsp/n32/n32g45xvl-stb/settings/project.rt-thread.driver.xcl new file mode 100644 index 0000000000..d98855c662 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/settings/project.rt-thread.driver.xcl @@ -0,0 +1,41 @@ +"--endian=little" + +"--cpu=Cortex-M4" + +"--fpu=VFPv4_SP" + +"-p" + +"D:\IAR Systems\Embedded Workbench 8.4\arm\CONFIG\debugger\Nations\N32G45x\N32G457xE.ddf" + +"--semihosting" + +"--device=N32G457VE" + +"--multicore_nr_of_cores=1" + +"--jet_probe=cmsisdap" + +"--jet_script_file=D:\IAR Systems\Embedded Workbench 8.4\arm\config\debugger\Nations\N32.ProbeScript" + +"--jet_standard_reset=9,0,0" + +"--reset_style=\"0,-,0,Disabled__no_reset_\"" + +"--reset_style=\"1,-,0,Software\"" + +"--reset_style=\"2,-,0,Hardware\"" + +"--reset_style=\"3,-,0,Core\"" + +"--reset_style=\"4,-,0,System\"" + +"--reset_style=\"9,ConnectUnderReset,1,Connect_during_reset\"" + +"--drv_interface=SWD" + +"--drv_catch_exceptions=0xff0" + + + + diff --git a/bsp/n32/n32g45xvl-stb/settings/project.rt-thread.general.xcl b/bsp/n32/n32g45xvl-stb/settings/project.rt-thread.general.xcl new file mode 100644 index 0000000000..fe36532f95 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/settings/project.rt-thread.general.xcl @@ -0,0 +1,15 @@ +"D:\IAR Systems\Embedded Workbench 8.4\arm\bin\armproc.dll" + +"D:\IAR Systems\Embedded Workbench 8.4\arm\bin\armJET.dll" + +"D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\build\iar\Exe\project.out" + +--plugin="D:\IAR Systems\Embedded Workbench 8.4\arm\bin\armbat.dll" + +--device_macro="D:\IAR Systems\Embedded Workbench 8.4\arm\config\debugger\Nations\N32G45x\N32G45x.dmac" + +--flash_loader="D:\IAR Systems\Embedded Workbench 8.4\arm\config\flashloader\Nations\N32G457xE\N32G457xE.board" + + + + diff --git a/bsp/n32/n32g45xvl-stb/settings/project.wsdt b/bsp/n32/n32g45xvl-stb/settings/project.wsdt new file mode 100644 index 0000000000..45f29f9829 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/settings/project.wsdt @@ -0,0 +1,385 @@ + + + + + project/rt-thread + + + + + + 21 + 1878 + 2 + + 0 + -1 + + + + 34001 + 0 + + + + + 57600 + 57601 + 57603 + 33024 + 0 + 57607 + 0 + 57635 + 57634 + 57637 + 0 + 57643 + 57644 + 0 + 33090 + 33057 + 57636 + 57640 + 57641 + 33026 + 33065 + 33063 + 33064 + 33053 + 33054 + 0 + 33035 + 33036 + 34399 + 0 + 33038 + 33039 + 0 + + + + + 173 + 30 + 30 + 30 + + + project + project/Applications + project/Drivers + project/Kernel + project/Kernel/components.c + + + + 4 + 0 + + + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 0300000005000C810000020000000E81000001000000148600000100000011860000010000004681000001000000 + + + 0000 + 0000 + + + 0 + 0A0000000A0000006E0000006E000000 + 00000000E603000080070000F9030000 + 4096 + 0 + 0 + 32767 + 0 + + + 1 + + + 34051 + 80F8FFFF17000000A2F9FFFFC8000000 + 000000000000000022010000B1000000 + 32768 + 0 + 0 + 32767 + 0 + + + 0 + + + + 4294967295 + 80F8FFFFEB02000000000000FD030000 + 00000000D402000080070000E6030000 + 4096 + 0 + 0 + 32767 + 0 + + + 1 + + + 34052 + 80F8FFFF17000000A2F9FFFFC8000000 + 04000000EC0200007C070000CC030000 + 32768 + 0 + 0 + 32767 + 0 + + + 1 + + + 24 + 1400 + 373 + 93 + 2 + D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\BuildLog.log + 0 + -1 + + + 34048 + 80F8FFFF17000000A2F9FFFFC8000000 + 04000000EC0200007C070000CC030000 + 4096 + 0 + 0 + 32767 + 0 + + + 1 + + + 34056 + 80F8FFFF17000000A2F9FFFFC8000000 + 04000000EC0200007C070000CC030000 + 4096 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34057 + 80F8FFFF17000000A2F9FFFFC8000000 + 04000000EC0200007C070000CC030000 + 4096 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34058 + 80F8FFFF17000000A2F9FFFFC8000000 + 04000000EC0200007C070000CC030000 + 4096 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34059 + 80F8FFFF17000000A2F9FFFFC8000000 + 04000000EC0200007C070000CC030000 + 4096 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34062 + 80F8FFFF17000000A2F9FFFFC8000000 + 04000000EC0200007C070000CC030000 + 4096 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34053 + 80F8FFFF1700000000FBFFFFA8000000 + 00000000000000008002000091000000 + 32768 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34054 + 80F8FFFF17000000A2F9FFFFC8000000 + 000000000000000022010000B1000000 + 32768 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34055 + 80F8FFFF17000000A2F9FFFFC8000000 + 000000000000000022010000B1000000 + 32768 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34060 + 80F8FFFF17000000A2F9FFFFC8000000 + 000000000000000022010000B1000000 + 32768 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34061 + 80F8FFFF1700000000FBFFFFA8000000 + 00000000000000008002000091000000 + 32768 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34063 + 80F8FFFF1700000086F9FFFF78010000 + 000000003200000006010000D0020000 + 4096 + 0 + 0 + 32767 + 0 + + + 1 + + + 0000000010000000000000000010000001000000FFFFFFFFFFFFFFFF06010000320000000A010000D00200000100000002000010040000000100000000000000000000000F85000000000000000000000000000000000000010000000F850000010000000F850000000000000080000000000000FFFFFFFFFFFFFFFF000000000000000004000000040000000000000001000000040000000100000000000000000000000D85000000000000000000000000000000000000010000000D850000010000000D850000000000000080000000000000FFFFFFFFFFFFFFFF000000000000000004000000040000000000000001000000040000000100000000000000000000000C85000000000000000000000000000000000000010000000C850000010000000C850000000000000080000000000000FFFFFFFFFFFFFFFF00000000000000000400000004000000000000000100000004000000010000000000000000000000078500000000000000000000000000000000000001000000078500000100000007850000000000000080000000000000FFFFFFFFFFFFFFFF00000000000000000400000004000000000000000100000004000000010000000000000000000000068500000000000000000000000000000000000001000000068500000100000006850000000000000080000000000000FFFFFFFFFFFFFFFF00000000000000000400000004000000000000000100000004000000010000000000000000000000058500000000000000000000000000000000000001000000058500000100000005850000000000000080000001000000FFFFFFFFFFFFFFFF00000000D002000080070000D40200000100000001000010040000000100000006FDFFFF6F000000FFFFFFFF07000000048500000085000008850000098500000A8500000B8500000E850000FFFF02000B004354616262656450616E65008000000100000080F8FFFFEB02000000000000FD03000000000000D402000080070000E6030000000000004080005607000000FFFEFF054200750069006C006400010000000485000001000000FFFFFFFFFFFFFFFFFFFEFF094400650062007500670020004C006F006700010000000085000001000000FFFFFFFFFFFFFFFFFFFEFF0C4400650063006C00610072006100740069006F006E007300000000000885000001000000FFFFFFFFFFFFFFFFFFFEFF0A5200650066006500720065006E00630065007300000000000985000001000000FFFFFFFFFFFFFFFFFFFEFF0D460069006E006400200069006E002000460069006C0065007300000000000A85000001000000FFFFFFFFFFFFFFFFFFFEFF1541006D0062006900670075006F0075007300200044006500660069006E006900740069006F006E007300000000000B85000001000000FFFFFFFFFFFFFFFFFFFEFF0B54006F006F006C0020004F0075007400700075007400000000000E85000001000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000001000000FFFFFFFF0485000001000000FFFFFFFF04850000000000000080000000000000FFFFFFFFFFFFFFFF00000000000000000400000004000000000000000100000004000000010000000000000000000000038500000000000000000000000000000000000001000000038500000100000003850000000000000000000000000000 + + + CMSIS-Pack + 00200000010000000100FFFF01001100434D4643546F6F6C426172427574746F6ED1840000000000000C000000FFFEFF00000000000000000000000000010000000100000000000000FFFEFF0A43004D005300490053002D005000610063006B0018000000 + + + 34049 + 0A0000000A0000006E0000006E000000 + FE020000000000002C0300001A000000 + 8192 + 0 + 0 + 24 + 0 + + + 1 + + + Main + 00200000010000002000FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000035000000FFFEFF000000000000000000000000000100000001000000018001E100000000000036000000FFFEFF000000000000000000000000000100000001000000018003E100000000040038000000FFFEFF0000000000000000000000000001000000010000000180008100000000000019000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF000000000000000000000000000100000001000000018007E10000000004003B000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF000000000000000000000000000100000001000000018023E10000000004003D000000FFFEFF000000000000000000000000000100000001000000018022E10000000004003C000000FFFEFF000000000000000000000000000100000001000000018025E10000000004003F000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF00000000000000000000000000010000000100000001802BE100000000040042000000FFFEFF00000000000000000000000000010000000100000001802CE100000000040043000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF000000000000000000000000000100000001000000FFFF01000D005061737465436F6D626F426F784281000000000400FFFFFFFFFFFEFF0000000000000000000100000000000000010000007800000002002050FFFFFFFFFFFEFF0096000000000000000000018021810000000004002C000000FFFEFF000000000000000000000000000100000001000000018024E10000000004003E000000FFFEFF000000000000000000000000000100000001000000018028E100000000040040000000FFFEFF000000000000000000000000000100000001000000018029E100000000040041000000FFFEFF000000000000000000000000000100000001000000018002810000000004001B000000FFFEFF0000000000000000000000000001000000010000000180298100000000040030000000FFFEFF000000000000000000000000000100000001000000018027810000000004002E000000FFFEFF000000000000000000000000000100000001000000018028810000000004002F000000FFFEFF00000000000000000000000000010000000100000001801D8100000000040028000000FFFEFF00000000000000000000000000010000000100000001801E8100000000040029000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF00000000000000000000000000010000000100000001800B810000000004001F000000FFFEFF00000000000000000000000000010000000100000001800C8100000000000020000000FFFEFF00000000000000000000000000010000000100000001805F8600000000000034000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF00000000000000000000000000010000000100000001800E8100000000000022000000FFFEFF00000000000000000000000000010000000100000001800F8100000000000023000000FFFEFF00000000000000000000000000010000000100000000000000FFFEFF044D00610069006E00E8020000 + + + 34050 + 0A0000000A0000006E0000006E000000 + 0000000000000000FE0200001A000000 + 8192 + 0 + 0 + 744 + 0 + + + 1 + + + + 34048 + 34049 + 34050 + 34051 + 34052 + 34053 + 34054 + 34055 + 34056 + 34057 + 34058 + 34059 + 34060 + 34061 + 34062 + 34063 + + + + 010000000300000001000000000000000000000001000000010000000200000000000000010000000100000000000000280000002800000001000000040000000000000001000000FFFEFF1C2400570053005F0044004900520024005C006100700070006C00690063006100740069006F006E0073005C006D00610069006E002E00630001000000FFFF010014004966436F6E74656E7453746F72616765496D706CFFFEFF00FFFEFFFF24013C003F0078006D006C002000760065007200730069006F006E003D00220031002E0030002200200065006E0063006F00640069006E0067003D0022005500540046002D00380022003F003E000A003C0052006F006F0074003E000A0020002000200020003C004E0075006D0052006F00770073003E0031003C002F004E0075006D0052006F00770073003E000A0020002000200020003C004E0075006D0043006F006C0073003E0031003C002F004E0075006D0043006F006C0073003E000A0020002000200020003C00580050006F0073003E0030003C002F00580050006F0073003E000A0020002000200020003C00590050006F0073003E0030003C002F00590050006F0073003E000A0020002000200020003C00530065006C00530074006100720074003E0030003C002F00530065006C00530074006100720074003E000A0020002000200020003C00530065006C0045006E0064003E0030003C002F00530065006C0045006E0064003E000A0020002000200020003C00580050006F00730032003E0030003C002F00580050006F00730032003E000A0020002000200020003C00590050006F00730032003E0030003C002F00590050006F00730032003E000A0020002000200020003C00530065006C005300740061007200740032003E003300350038003C002F00530065006C005300740061007200740032003E000A0020002000200020003C00530065006C0045006E00640032003E003300350038003C002F00530065006C0045006E00640032003E000A003C002F0052006F006F0074003E000A00FFFEFF066D00610069006E002E00630000000000FFFFFFFFFFFFFFFFFFFEFF2D44003A005C00720074005F007400680072006500610064005C0034002E0031002E0030005C00720074002D007400680072006500610064005C007300720063005C0063006F006D0070006F006E0065006E00740073002E006300010000000180FFFEFF00FFFEFFFF27013C003F0078006D006C002000760065007200730069006F006E003D00220031002E0030002200200065006E0063006F00640069006E0067003D0022005500540046002D00380022003F003E000A003C0052006F006F0074003E000A0020002000200020003C004E0075006D0052006F00770073003E0031003C002F004E0075006D0052006F00770073003E000A0020002000200020003C004E0075006D0043006F006C0073003E0031003C002F004E0075006D0043006F006C0073003E000A0020002000200020003C00580050006F0073003E0030003C002F00580050006F0073003E000A0020002000200020003C00590050006F0073003E0030003C002F00590050006F0073003E000A0020002000200020003C00530065006C00530074006100720074003E0030003C002F00530065006C00530074006100720074003E000A0020002000200020003C00530065006C0045006E0064003E0030003C002F00530065006C0045006E0064003E000A0020002000200020003C00580050006F00730032003E0030003C002F00580050006F00730032003E000A0020002000200020003C00590050006F00730032003E00310038003C002F00590050006F00730032003E000A0020002000200020003C00530065006C005300740061007200740032003E0031003200370031003C002F00530065006C005300740061007200740032003E000A0020002000200020003C00530065006C0045006E00640032003E0031003200370031003C002F00530065006C0045006E00640032003E000A003C002F0052006F006F0074003E000A00FFFEFF0C63006F006D0070006F006E0065006E00740073002E00630000000000FFFFFFFFFFFFFFFFFFFEFF132400570053005F0044004900520024005C007200740063006F006E006600690067002E006800010000000180FFFEFF00FFFEFFFF22013C003F0078006D006C002000760065007200730069006F006E003D00220031002E0030002200200065006E0063006F00640069006E0067003D0022005500540046002D00380022003F003E000A003C0052006F006F0074003E000A0020002000200020003C004E0075006D0052006F00770073003E0031003C002F004E0075006D0052006F00770073003E000A0020002000200020003C004E0075006D0043006F006C0073003E0031003C002F004E0075006D0043006F006C0073003E000A0020002000200020003C00580050006F0073003E0030003C002F00580050006F0073003E000A0020002000200020003C00590050006F0073003E0030003C002F00590050006F0073003E000A0020002000200020003C00530065006C00530074006100720074003E0030003C002F00530065006C00530074006100720074003E000A0020002000200020003C00530065006C0045006E0064003E0030003C002F00530065006C0045006E0064003E000A0020002000200020003C00580050006F00730032003E0030003C002F00580050006F00730032003E000A0020002000200020003C00590050006F00730032003E003100350033003C002F00590050006F00730032003E000A0020002000200020003C00530065006C005300740061007200740032003E0030003C002F00530065006C005300740061007200740032003E000A0020002000200020003C00530065006C0045006E00640032003E0030003C002F00530065006C0045006E00640032003E000A003C002F0052006F006F0074003E000A00FFFEFF0A7200740063006F006E006600690067002E00680000000000FFFFFFFFFFFFFFFFFFFEFF2744003A005C00720074005F007400680072006500610064005C0034002E0031002E0030005C00720074002D007400680072006500610064005C007300720063005C00690064006C0065002E006300010000000180FFFEFF00FFFEFFFF28013C003F0078006D006C002000760065007200730069006F006E003D00220031002E0030002200200065006E0063006F00640069006E0067003D0022005500540046002D00380022003F003E000A003C0052006F006F0074003E000A0020002000200020003C004E0075006D0052006F00770073003E0031003C002F004E0075006D0052006F00770073003E000A0020002000200020003C004E0075006D0043006F006C0073003E0031003C002F004E0075006D0043006F006C0073003E000A0020002000200020003C00580050006F0073003E0030003C002F00580050006F0073003E000A0020002000200020003C00590050006F0073003E0030003C002F00590050006F0073003E000A0020002000200020003C00530065006C00530074006100720074003E0030003C002F00530065006C00530074006100720074003E000A0020002000200020003C00530065006C0045006E0064003E0030003C002F00530065006C0045006E0064003E000A0020002000200020003C00580050006F00730032003E0030003C002F00580050006F00730032003E000A0020002000200020003C00590050006F00730032003E003100350033003C002F00590050006F00730032003E000A0020002000200020003C00530065006C005300740061007200740032003E0034003700330033003C002F00530065006C005300740061007200740032003E000A0020002000200020003C00530065006C0045006E00640032003E0034003700330033003C002F00530065006C0045006E00640032003E000A003C002F0052006F006F0074003E000A00FFFEFF06690064006C0065002E00630000000000FFFFFFFFFFFFFFFF0000000010000000C5D4F200FFDC7800BECEA100F0A0A100BCA8E1009CC1B600F7B88600D9ADC200A5C2D700B3A6BE00EAD6A300F6FA7D00B5E99D005FC3CF00C1838300CACAD5000100000001000000020000008AF9FFFF4900000000000000E7020000 + + + + diff --git a/bsp/n32/n32g45xvl-stb/settings/template.crun b/bsp/n32/n32g45xvl-stb/settings/template.crun new file mode 100644 index 0000000000..d71ea555a9 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/settings/template.crun @@ -0,0 +1,13 @@ + + + 1 + + + * + * + * + 0 + 1 + + + diff --git a/bsp/n32/n32g45xvl-stb/settings/template.dbgdt b/bsp/n32/n32g45xvl-stb/settings/template.dbgdt new file mode 100644 index 0000000000..73e71f6e4c --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/settings/template.dbgdt @@ -0,0 +1,4 @@ + + + + diff --git a/bsp/n32/n32g45xvl-stb/settings/template.dnx b/bsp/n32/n32g45xvl-stb/settings/template.dnx new file mode 100644 index 0000000000..1872e83f75 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/settings/template.dnx @@ -0,0 +1,58 @@ + + + + 0 + 0 + 1 + 0 + 1 + 0 + + + 0 + 0 + 1 + 0 + 1 + + + 0 + 1 + 90 + 1 + 1 + 1 + main + 0 + 50 + + + 0 + + + 0 + + + 1 + + + 1 + 0 + 1 + 0 + 1 + + + 0 + 1 + + + 0 + 0 + + + 10000000 + 0 + 1 + + diff --git a/bsp/n32/n32g45xvl-stb/settings/template.rt-thread.cspy.bat b/bsp/n32/n32g45xvl-stb/settings/template.rt-thread.cspy.bat new file mode 100644 index 0000000000..b74961d305 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/settings/template.rt-thread.cspy.bat @@ -0,0 +1,40 @@ +@REM This batch file has been generated by the IAR Embedded Workbench +@REM C-SPY Debugger, as an aid to preparing a command line for running +@REM the cspybat command line utility using the appropriate settings. +@REM +@REM Note that this file is generated every time a new debug session +@REM is initialized, so you may want to move or rename the file before +@REM making changes. +@REM +@REM You can launch cspybat by typing the name of this batch file followed +@REM by the name of the debug file (usually an ELF/DWARF or UBROF file). +@REM +@REM Read about available command line parameters in the C-SPY Debugging +@REM Guide. Hints about additional command line parameters that may be +@REM useful in specific cases: +@REM --download_only Downloads a code image without starting a debug +@REM session afterwards. +@REM --silent Omits the sign-on message. +@REM --timeout Limits the maximum allowed execution time. +@REM + + +@echo off + +if not "%~1" == "" goto debugFile + +@echo on + +"D:\IAR Systems\Embedded Workbench 8.4\common\bin\cspybat" -f "D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\settings\template.rt-thread.general.xcl" --backend -f "D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\settings\template.rt-thread.driver.xcl" + +@echo off +goto end + +:debugFile + +@echo on + +"D:\IAR Systems\Embedded Workbench 8.4\common\bin\cspybat" -f "D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\settings\template.rt-thread.general.xcl" "--debug_file=%~1" --backend -f "D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\settings\template.rt-thread.driver.xcl" + +@echo off +:end \ No newline at end of file diff --git a/bsp/n32/n32g45xvl-stb/settings/template.rt-thread.cspy.ps1 b/bsp/n32/n32g45xvl-stb/settings/template.rt-thread.cspy.ps1 new file mode 100644 index 0000000000..8f594cf656 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/settings/template.rt-thread.cspy.ps1 @@ -0,0 +1,31 @@ +param([String]$debugfile = ""); + +# This powershell file has been generated by the IAR Embedded Workbench +# C - SPY Debugger, as an aid to preparing a command line for running +# the cspybat command line utility using the appropriate settings. +# +# Note that this file is generated every time a new debug session +# is initialized, so you may want to move or rename the file before +# making changes. +# +# You can launch cspybat by typing Powershell.exe -File followed by the name of this batch file, followed +# by the name of the debug file (usually an ELF / DWARF or UBROF file). +# +# Read about available command line parameters in the C - SPY Debugging +# Guide. Hints about additional command line parameters that may be +# useful in specific cases : +# --download_only Downloads a code image without starting a debug +# session afterwards. +# --silent Omits the sign - on message. +# --timeout Limits the maximum allowed execution time. +# + + +if ($debugfile -eq "") +{ +& "D:\IAR Systems\Embedded Workbench 8.4\common\bin\cspybat" -f "D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\settings\template.rt-thread.general.xcl" --backend -f "D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\settings\template.rt-thread.driver.xcl" +} +else +{ +& "D:\IAR Systems\Embedded Workbench 8.4\common\bin\cspybat" -f "D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\settings\template.rt-thread.general.xcl" --debug_file=$debugfile --backend -f "D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\settings\template.rt-thread.driver.xcl" +} diff --git a/bsp/n32/n32g45xvl-stb/settings/template.rt-thread.driver.xcl b/bsp/n32/n32g45xvl-stb/settings/template.rt-thread.driver.xcl new file mode 100644 index 0000000000..58b33a4f0f --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/settings/template.rt-thread.driver.xcl @@ -0,0 +1,19 @@ +"--endian=little" + +"--cpu=Cortex-M4" + +"--fpu=VFPv4_SP" + +"-p" + +"D:\IAR Systems\Embedded Workbench 8.4\arm\CONFIG\debugger\Nations\N32G45x\N32G457xE.ddf" + +"--semihosting" + +"--device=N32G457VE" + +"--multicore_nr_of_cores=1" + + + + diff --git a/bsp/n32/n32g45xvl-stb/settings/template.rt-thread.general.xcl b/bsp/n32/n32g45xvl-stb/settings/template.rt-thread.general.xcl new file mode 100644 index 0000000000..b32b78d4e5 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/settings/template.rt-thread.general.xcl @@ -0,0 +1,13 @@ +"D:\IAR Systems\Embedded Workbench 8.4\arm\bin\armproc.dll" + +"D:\IAR Systems\Embedded Workbench 8.4\arm\bin\armsim2.dll" + +"D:\rt_thread\4.1.0\rt-thread\bsp\n32\n32g45xvl-stb\build\iar\Exe\project.out" + +--plugin="D:\IAR Systems\Embedded Workbench 8.4\arm\bin\armbat.dll" + +--device_macro="D:\IAR Systems\Embedded Workbench 8.4\arm\config\debugger\Nations\N32G45x\N32G45x.dmac" + + + + diff --git a/bsp/n32/n32g45xvl-stb/settings/template.wsdt b/bsp/n32/n32g45xvl-stb/settings/template.wsdt new file mode 100644 index 0000000000..e0c5d7e012 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/settings/template.wsdt @@ -0,0 +1,400 @@ + + + + + template/rt-thread + + + + + + 21 + 1878 + 2 + + 0 + -1 + + + + 34001 + 0 + + + + + 57600 + 57601 + 57603 + 33024 + 0 + 57607 + 0 + 57635 + 57634 + 57637 + 0 + 57643 + 57644 + 0 + 33090 + 33057 + 57636 + 57640 + 57641 + 33026 + 33065 + 33063 + 33064 + 33053 + 33054 + 0 + 33035 + 33036 + 34399 + 0 + 33038 + 33039 + 0 + + + + + 190 + 30 + 30 + 30 + + + + + 4 + 0 + + + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 000000000000 + + + 0000 + 0000 + + + 0 + 0A0000000A0000006E0000006E000000 + 00000000E603000080070000F9030000 + 4096 + 0 + 0 + 32767 + 0 + + + 1 + + + 34051 + 80F8FFFF17000000A2F9FFFFC8000000 + 000000000000000022010000B1000000 + 32768 + 0 + 0 + 32767 + 0 + + + 0 + + + + 4294967295 + 80F8FFFF17000000A2F9FFFFC8000000 + 000000003503000080070000E6030000 + 4096 + 0 + 0 + 32767 + 0 + + + 1 + + + 34052 + 80F8FFFF17000000A2F9FFFFC8000000 + 040000004D0300007C070000CC030000 + 32768 + 0 + 0 + 32767 + 0 + + + 1 + + + + 34048 + 80F8FFFF17000000A2F9FFFFC8000000 + 040000004D0300007C070000CC030000 + 4096 + 0 + 0 + 32767 + 0 + + + 1 + + + 34056 + 80F8FFFF17000000A2F9FFFFC8000000 + 040000004D0300007C070000CC030000 + 4096 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34057 + 80F8FFFF17000000A2F9FFFFC8000000 + 040000004D0300007C070000CC030000 + 4096 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34058 + 80F8FFFF17000000A2F9FFFFC8000000 + 040000004D0300007C070000CC030000 + 4096 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34059 + 80F8FFFF17000000A2F9FFFFC8000000 + 040000004D0300007C070000CC030000 + 4096 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34062 + 80F8FFFF17000000A2F9FFFFC8000000 + 040000004D0300007C070000CC030000 + 4096 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34053 + 80F8FFFF1700000000FBFFFFA8000000 + 00000000000000008002000091000000 + 32768 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34054 + 80F8FFFF17000000A2F9FFFFC8000000 + 000000000000000022010000B1000000 + 32768 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34055 + 80F8FFFF17000000A2F9FFFFC8000000 + 000000000000000022010000B1000000 + 32768 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34060 + 80F8FFFF17000000A2F9FFFFC8000000 + 000000000000000022010000B1000000 + 32768 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34061 + 80F8FFFF1700000000FBFFFFA8000000 + 00000000000000008002000091000000 + 32768 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34063 + 80F8FFFF17000000A2F9FFFFC8000000 + 000000000000000022010000B1000000 + 32768 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34064 + 80F8FFFF17000000A2F9FFFFC8000000 + 000000000000000022010000B1000000 + 32768 + 0 + 0 + 32767 + 0 + + + 0 + + + + 34065 + 80F8FFFF1700000086F9FFFF78010000 + 00000000320000000601000031030000 + 4096 + 0 + 0 + 32767 + 0 + + + 1 + + + 0000000014000000000000000010000001000000FFFFFFFFFFFFFFFF06010000320000000A01000031030000010000000200001004000000010000000000000000000000118500000000000000000000000000000000000001000000118500000100000011850000000000000080000000000000FFFFFFFFFFFFFFFF00000000000000000400000004000000000000000100001004000000010000000000000000000000108500000000000000000000000000000000000001000000108500000100000010850000000000000080000000000000FFFFFFFFFFFFFFFF000000000000000004000000040000000000000001000010040000000100000000000000000000000F85000000000000000000000000000000000000010000000F850000010000000F850000000000000080000000000000FFFFFFFFFFFFFFFF000000000000000004000000040000000000000001000010040000000100000000000000000000000D85000000000000000000000000000000000000010000000D850000010000000D850000000000000080000000000000FFFFFFFFFFFFFFFF000000000000000004000000040000000000000001000010040000000100000000000000000000000C85000000000000000000000000000000000000010000000C850000010000000C850000000000000080000000000000FFFFFFFFFFFFFFFF00000000000000000400000004000000000000000100001004000000010000000000000000000000078500000000000000000000000000000000000001000000078500000100000007850000000000000080000000000000FFFFFFFFFFFFFFFF00000000000000000400000004000000000000000100001004000000010000000000000000000000068500000000000000000000000000000000000001000000068500000100000006850000000000000080000000000000FFFFFFFFFFFFFFFF00000000000000000400000004000000000000000100001004000000010000000000000000000000058500000000000000000000000000000000000001000000058500000100000005850000000000000080000001000000FFFFFFFFFFFFFFFF00000000310300008007000035030000010000000100001004000000010000000000000000000000FFFFFFFF07000000048500000085000008850000098500000A8500000B8500000E850000FFFF02000B004354616262656450616E65008000000100000080F8FFFF17000000A2F9FFFFC8000000000000003503000080070000E6030000000000004080005607000000FFFEFF054200750069006C006400010000000485000001000000FFFFFFFFFFFFFFFFFFFEFF094400650062007500670020004C006F006700010000000085000001000000FFFFFFFFFFFFFFFFFFFEFF0C4400650063006C00610072006100740069006F006E007300000000000885000001000000FFFFFFFFFFFFFFFFFFFEFF0A5200650066006500720065006E00630065007300000000000985000001000000FFFFFFFFFFFFFFFFFFFEFF0D460069006E006400200069006E002000460069006C0065007300000000000A85000001000000FFFFFFFFFFFFFFFFFFFEFF1541006D0062006900670075006F0075007300200044006500660069006E006900740069006F006E007300000000000B85000001000000FFFFFFFFFFFFFFFFFFFEFF0B54006F006F006C0020004F0075007400700075007400000000000E85000001000000FFFFFFFFFFFFFFFF01000000000000000000000000000000000000000000000001000000FFFFFFFF0485000001000000FFFFFFFF04850000000000000080000000000000FFFFFFFFFFFFFFFF00000000000000000400000004000000000000000100001004000000010000000000000000000000038500000000000000000000000000000000000001000000038500000100000003850000000000000000000000000000 + + + CMSIS-Pack + 00200000010000000100FFFF01001100434D4643546F6F6C426172427574746F6ED1840000000000000C000000FFFEFF00000000000000000000000000010000000100000000000000FFFEFF0A43004D005300490053002D005000610063006B00FF7F0000 + + + 34049 + 0A0000000A0000006E0000006E000000 + FE020000000000002C0300001A000000 + 8192 + 0 + 0 + 32767 + 0 + + + 1 + + + Main + 00200000010000002000FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000035000000FFFEFF000000000000000000000000000100000001000000018001E100000000000036000000FFFEFF000000000000000000000000000100000001000000018003E100000000040038000000FFFEFF0000000000000000000000000001000000010000000180008100000000000019000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF000000000000000000000000000100000001000000018007E10000000004003B000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF000000000000000000000000000100000001000000018023E10000000004003D000000FFFEFF000000000000000000000000000100000001000000018022E10000000004003C000000FFFEFF000000000000000000000000000100000001000000018025E10000000004003F000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF00000000000000000000000000010000000100000001802BE100000000040042000000FFFEFF00000000000000000000000000010000000100000001802CE100000000040043000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF000000000000000000000000000100000001000000FFFF01000D005061737465436F6D626F426F784281000000000400FFFFFFFFFFFEFF0000000000000000000100000000000000010000007800000002002050FFFFFFFFFFFEFF0096000000000000000000018021810000000004002C000000FFFEFF000000000000000000000000000100000001000000018024E10000000004003E000000FFFEFF000000000000000000000000000100000001000000018028E100000000040040000000FFFEFF000000000000000000000000000100000001000000018029E100000000040041000000FFFEFF000000000000000000000000000100000001000000018002810000000004001B000000FFFEFF0000000000000000000000000001000000010000000180298100000000040030000000FFFEFF000000000000000000000000000100000001000000018027810000000004002E000000FFFEFF000000000000000000000000000100000001000000018028810000000004002F000000FFFEFF00000000000000000000000000010000000100000001801D8100000000040028000000FFFEFF00000000000000000000000000010000000100000001801E8100000000040029000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF00000000000000000000000000010000000100000001800B810000000004001F000000FFFEFF00000000000000000000000000010000000100000001800C8100000000000020000000FFFEFF00000000000000000000000000010000000100000001805F8600000000000034000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF00000000000000000000000000010000000100000001800E8100000000000022000000FFFEFF00000000000000000000000000010000000100000001800F8100000000000023000000FFFEFF00000000000000000000000000010000000100000000000000FFFEFF044D00610069006E00FF7F0000 + + + 34050 + 0A0000000A0000006E0000006E000000 + 0000000000000000FE0200001A000000 + 8192 + 0 + 0 + 32767 + 0 + + + 1 + + + + 34048 + 34049 + 34050 + 34051 + 34052 + 34053 + 34054 + 34055 + 34056 + 34057 + 34058 + 34059 + 34060 + 34061 + 34062 + 34063 + 34064 + 34065 + + + + 01000000030000000100000000000000000000000100000001000000FFFFFFFF00000000010000000100000000000000280000002800000000000000 + + + + diff --git a/bsp/n32/n32g45xvl-stb/template.ewp b/bsp/n32/n32g45xvl-stb/template.ewp new file mode 100644 index 0000000000..5c5e0f7184 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/template.ewp @@ -0,0 +1,2114 @@ + + + 3 + + rt-thread + + ARM + + 1 + + General + 3 + + 31 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 36 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 23 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + BILINK + 0 + + + + + Release + + ARM + + 0 + + General + 3 + + 31 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 36 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 0 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 23 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 0 + + + + + + + BILINK + 0 + + + + diff --git a/bsp/n32/n32g45xvl-stb/template.eww b/bsp/n32/n32g45xvl-stb/template.eww new file mode 100644 index 0000000000..bd036bb4c9 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/template.eww @@ -0,0 +1,10 @@ + + + + + $WS_DIR$\template.ewp + + + + + diff --git a/bsp/n32/n32g45xvl-stb/template.uvoptx b/bsp/n32/n32g45xvl-stb/template.uvoptx new file mode 100644 index 0000000000..4fae3b2177 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/template.uvoptx @@ -0,0 +1,185 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc; *.md + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 ) -FN1 -FC1000 -FD20000000 -FF0N32G45x -FL080000 -FS08000000 -FP0($$Device:N32G457VEL7$Flash\N32G45x.FLM) + + + 0 + CMSIS_AGDI + -X"Any" -UAny -O206 -S0 -C0 -P00000000 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0N32G45x.FLM -FS08000000 -FL080000 -FP0($$Device:N32G457VEL7$Flash\N32G45x.FLM) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/n32/n32g45xvl-stb/template.uvprojx b/bsp/n32/n32g45xvl-stb/template.uvprojx new file mode 100644 index 0000000000..63fec2b738 --- /dev/null +++ b/bsp/n32/n32g45xvl-stb/template.uvprojx @@ -0,0 +1,413 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 5060960::V5.06 update 7 (build 960)::.\ARMCC + 0 + + + N32G457VEL7 + Nationstech + Nationstech.N32G45x_DFP.1.0.1 + http://www.keil.com/pack/ + IRAM(0x20000000,0x24000) IROM(0x08000000,0x80000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0N32G45x -FS08000000 -FL080000 -FP0($$Device:N32G457VEL7$Flash\N32G45x.FLM)) + 0 + $$Device:N32G457VEL7$firmware\CMSIS\device\n32g45x.h + + + + + + + + + + $$Device:N32G457VEL7$svd\N32G457.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM4 + SARMCM3.DLL + + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x24000 + + + 1 + 0x8000000 + 0x80000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x80000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x24000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\board\linker_scripts\link.sct + + + + + + + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + template + 0 + 1 + + + + +
diff --git a/bsp/n32/tools/sdk_dist.py b/bsp/n32/tools/sdk_dist.py new file mode 100644 index 0000000000..9b2d5030c7 --- /dev/null +++ b/bsp/n32/tools/sdk_dist.py @@ -0,0 +1,37 @@ +import os +import sys +import shutil + +cwd_path = os.getcwd() +sys.path.append(os.path.join(os.path.dirname(cwd_path), 'rt-thread', 'tools')) + +def bsp_update_board_kconfig(dist_dir): + # change board/kconfig path + if not os.path.isfile(os.path.join(dist_dir, 'board/Kconfig')): + return + + with open(os.path.join(dist_dir, 'board/Kconfig'), 'r') as f: + data = f.readlines() + with open(os.path.join(dist_dir, 'board/Kconfig'), 'w') as f: + for line in data: + if line.find('../libraries/n32_drivers/Kconfig') != -1: + position = line.find('../libraries/n32_drivers/Kconfig') + line = line[0:position] + 'libraries/n32_drivers/Kconfig"\n' + f.write(line) + +# BSP dist function +def dist_do_building(BSP_ROOT, dist_dir): + from mkdist import bsp_copy_files + import rtconfig + + print("=> copy n32 bsp library") + library_dir = os.path.join(dist_dir, 'libraries') + library_path = os.path.join(os.path.dirname(BSP_ROOT), 'libraries') + bsp_copy_files(os.path.join(library_path, rtconfig.BSP_LIBRARY_TYPE), + os.path.join(library_dir, rtconfig.BSP_LIBRARY_TYPE)) + + print("=> copy bsp drivers") + bsp_copy_files(os.path.join(library_path, 'n32_drivers'), os.path.join(library_dir, 'n32_drivers')) + shutil.copyfile(os.path.join(library_path, 'Kconfig'), os.path.join(library_dir, 'Kconfig')) + + bsp_update_board_kconfig(dist_dir)