From 24575c44861eae1646d44bea2663cad7391d4659 Mon Sep 17 00:00:00 2001 From: luobeihai <83497188+luobeihai@users.noreply.github.com> Date: Thu, 5 Jan 2023 14:15:02 +0800 Subject: [PATCH] add apm32F0 serie MCU support (#6789) * add apm32F0 serie MCU support add apm32f072vb-miniboard bsp update F103/F407 bsp * replace apm32f072vb picture * Update action.yml --- .github/workflows/action.yml | 2 + bsp/apm32/apm32f072vb-miniboard/.config | 985 +++ bsp/apm32/apm32f072vb-miniboard/.gitignore | 42 + bsp/apm32/apm32f072vb-miniboard/Kconfig | 22 + bsp/apm32/apm32f072vb-miniboard/README.md | 116 + bsp/apm32/apm32f072vb-miniboard/SConscript | 15 + bsp/apm32/apm32f072vb-miniboard/SConstruct | 60 + .../applications/SConscript | 15 + .../apm32f072vb-miniboard/applications/main.c | 33 + bsp/apm32/apm32f072vb-miniboard/board/Kconfig | 213 + .../apm32f072vb-miniboard/board/SConscript | 36 + bsp/apm32/apm32f072vb-miniboard/board/board.c | 127 + bsp/apm32/apm32f072vb-miniboard/board/board.h | 81 + .../board/linker_scripts/link.icf | 28 + .../board/linker_scripts/link.lds | 163 + .../board/linker_scripts/link.sct | 15 + .../figures/APM32F072VB.png | Bin 0 -> 878748 bytes .../figures/JFlash_Leader_01.png | Bin 0 -> 47629 bytes .../figures/JFlash_Leader_02.png | Bin 0 -> 9973 bytes .../figures/JFlash_Leader_03.png | Bin 0 -> 3590 bytes .../figures/JFlash_Leader_04.png | Bin 0 -> 12434 bytes bsp/apm32/apm32f072vb-miniboard/project.ewp | 2399 +++++++ bsp/apm32/apm32f072vb-miniboard/project.eww | 10 + .../apm32f072vb-miniboard/project.uvoptx | 853 +++ .../apm32f072vb-miniboard/project.uvprojx | 697 ++ bsp/apm32/apm32f072vb-miniboard/rtconfig.h | 241 + bsp/apm32/apm32f072vb-miniboard/rtconfig.py | 184 + bsp/apm32/apm32f072vb-miniboard/template.ewp | 2144 +++++++ bsp/apm32/apm32f072vb-miniboard/template.eww | 10 + .../apm32f072vb-miniboard/template.uvoptx | 185 + .../apm32f072vb-miniboard/template.uvprojx | 405 ++ bsp/apm32/apm32f103xe-minibroard/.config | 368 +- .../board/linker_scripts/link.lds | 5 + .../apm32f103xe-minibroard/project.uvoptx | 739 ++- .../apm32f103xe-minibroard/project.uvprojx | 213 +- bsp/apm32/apm32f103xe-minibroard/rtconfig.h | 44 +- bsp/apm32/apm32f407ig-minibroard/.config | 366 +- .../apm32f407ig-minibroard/board/board.h | 1 + .../apm32f407ig-minibroard/project.uvoptx | 740 ++- .../apm32f407ig-minibroard/project.uvprojx | 214 +- bsp/apm32/apm32f407ig-minibroard/rtconfig.h | 44 +- .../inc/apm32f0xx_adc.h | 364 ++ .../inc/apm32f0xx_can.h | 413 ++ .../inc/apm32f0xx_cec.h | 231 + .../inc/apm32f0xx_comp.h | 185 + .../inc/apm32f0xx_crc.h | 136 + .../inc/apm32f0xx_crs.h | 171 + .../inc/apm32f0xx_dac.h | 237 + .../inc/apm32f0xx_dbg.h | 134 + .../inc/apm32f0xx_dma.h | 520 ++ .../inc/apm32f0xx_eint.h | 175 + .../inc/apm32f0xx_fmc.h | 339 + .../inc/apm32f0xx_gpio.h | 228 + .../inc/apm32f0xx_i2c.h | 405 ++ .../inc/apm32f0xx_iwdt.h | 143 + .../inc/apm32f0xx_misc.h | 112 + .../inc/apm32f0xx_ob.h | 180 + .../inc/apm32f0xx_pmu.h | 174 + .../inc/apm32f0xx_rcm.h | 483 ++ .../inc/apm32f0xx_rtc.h | 526 ++ .../inc/apm32f0xx_spi.h | 416 ++ .../inc/apm32f0xx_syscfg.h | 219 + .../inc/apm32f0xx_tmr.h | 752 +++ .../inc/apm32f0xx_usart.h | 473 ++ .../inc/apm32f0xx_wwdt.h | 111 + .../src/apm32f0xx_adc.c | 784 +++ .../src/apm32f0xx_can.c | 1170 ++++ .../src/apm32f0xx_cec.c | 418 ++ .../src/apm32f0xx_comp.c | 298 + .../src/apm32f0xx_crc.c | 284 + .../src/apm32f0xx_crs.c | 424 ++ .../src/apm32f0xx_dac.c | 595 ++ .../src/apm32f0xx_dbg.c | 196 + .../src/apm32f0xx_dma.c | 695 ++ .../src/apm32f0xx_eint.c | 231 + .../src/apm32f0xx_fmc.c | 1005 +++ .../src/apm32f0xx_gpio.c | 378 ++ .../src/apm32f0xx_i2c.c | 1177 ++++ .../src/apm32f0xx_iwdt.c | 184 + .../src/apm32f0xx_misc.c | 190 + .../src/apm32f0xx_ob.c | 152 + .../src/apm32f0xx_pmu.c | 335 + .../src/apm32f0xx_rcm.c | 1520 +++++ .../src/apm32f0xx_rtc.c | 1753 +++++ .../src/apm32f0xx_spi.c | 786 +++ .../src/apm32f0xx_syscfg.c | 316 + .../src/apm32f0xx_tmr.c | 2394 +++++++ .../src/apm32f0xx_usart.c | 1741 +++++ .../src/apm32f0xx_wwdt.c | 175 + .../CMSIS/Include/core_cm0plus.h | 793 +++ .../CMSIS/Include/core_cmFunc.h | 636 ++ .../CMSIS/Include/core_cmInstr.h | 688 ++ .../APM32F0xx_Library/CMSIS/LICENSE.txt | 176 + .../Geehy/APM32F0xx/Include/apm32f0xx.h | 5662 +++++++++++++++++ .../APM32F0xx/Include/system_apm32f0xx.h | 86 + .../APM32F0xx/Source/arm/startup_apm32f030.s | 239 + .../APM32F0xx/Source/arm/startup_apm32f051.s | 246 + .../APM32F0xx/Source/arm/startup_apm32f070.s | 243 + .../APM32F0xx/Source/arm/startup_apm32f071.s | 248 + .../APM32F0xx/Source/arm/startup_apm32f072.s | 251 + .../APM32F0xx/Source/arm/startup_apm32f091.s | 248 + .../APM32F0xx/Source/gcc/gcc_APM32F03xx6.ld | 162 + .../APM32F0xx/Source/gcc/gcc_APM32F03xx8.ld | 162 + .../APM32F0xx/Source/gcc/gcc_APM32F03xxC.ld | 162 + .../APM32F0xx/Source/gcc/gcc_APM32F05xx6.ld | 162 + .../APM32F0xx/Source/gcc/gcc_APM32F05xx8.ld | 162 + .../APM32F0xx/Source/gcc/gcc_APM32F07xx8.ld | 162 + .../APM32F0xx/Source/gcc/gcc_APM32F07xxB.ld | 162 + .../APM32F0xx/Source/gcc/gcc_APM32F09xxB.ld | 162 + .../APM32F0xx/Source/gcc/gcc_APM32F09xxC.ld | 162 + .../APM32F0xx/Source/gcc/startup_apm32f030.S | 247 + .../APM32F0xx/Source/gcc/startup_apm32f051.S | 254 + .../APM32F0xx/Source/gcc/startup_apm32f070.S | 252 + .../APM32F0xx/Source/gcc/startup_apm32f071.S | 261 + .../APM32F0xx/Source/gcc/startup_apm32f072.S | 264 + .../APM32F0xx/Source/gcc/startup_apm32f091.S | 261 + .../APM32F0xx/Source/iar/startup_apm32f030.s | 278 + .../APM32F0xx/Source/iar/startup_apm32f051.s | 289 + .../APM32F0xx/Source/iar/startup_apm32f070.s | 285 + .../APM32F0xx/Source/iar/startup_apm32f071.s | 299 + .../APM32F0xx/Source/iar/startup_apm32f072.s | 305 + .../APM32F0xx/Source/iar/startup_apm32f091.s | 299 + .../Geehy/APM32F0xx/Source/system_apm32f0xx.c | 444 ++ .../libraries/APM32F0xx_Library/SConscript | 49 + .../TSC_Device_Lib/inc/tsc.h | 135 + .../TSC_Device_Lib/inc/tsc_acq.h | 253 + .../TSC_Device_Lib/inc/tsc_check.h | 578 ++ .../TSC_Device_Lib/inc/tsc_config.h | 583 ++ .../TSC_Device_Lib/inc/tsc_dxs.h | 95 + .../TSC_Device_Lib/inc/tsc_ecs.h | 94 + .../TSC_Device_Lib/inc/tsc_filter.h | 90 + .../TSC_Device_Lib/inc/tsc_linrot.h | 273 + .../TSC_Device_Lib/inc/tsc_object.h | 126 + .../TSC_Device_Lib/inc/tsc_time.h | 87 + .../TSC_Device_Lib/inc/tsc_touchkey.h | 165 + .../TSC_Device_Lib/inc/tsc_types.h | 271 + .../TSC_Device_Lib/src/tsc.c | 88 + .../TSC_Device_Lib/src/tsc_acq.c | 1483 +++++ .../TSC_Device_Lib/src/tsc_dxs.c | 202 + .../TSC_Device_Lib/src/tsc_ecs.c | 329 + .../TSC_Device_Lib/src/tsc_filter.c | 109 + .../TSC_Device_Lib/src/tsc_linrot.c | 2073 ++++++ .../TSC_Device_Lib/src/tsc_object.c | 250 + .../TSC_Device_Lib/src/tsc_time.c | 224 + .../TSC_Device_Lib/src/tsc_touchkey.c | 1131 ++++ .../Class/CDC/inc/usbd_class_cdc.h | 85 + .../Class/CDC/src/usbd_class_cdc.c | 122 + .../Class/HID/inc/usbd_class_hid.h | 94 + .../Class/HID/src/usbd_class_hid.c | 114 + .../Class/MSC/inc/usbd_class_msc.h | 88 + .../Core_Device/Class/MSC/inc/usbd_msc_bot.h | 156 + .../Core_Device/Class/MSC/inc/usbd_msc_scsi.h | 183 + .../Class/MSC/src/usbd_class_msc.c | 130 + .../Core_Device/Class/MSC/src/usbd_msc_bot.c | 292 + .../Core_Device/Class/MSC/src/usbd_msc_scsi.c | 752 +++ .../Core_Device/Standard/inc/usbd_core.h | 366 ++ .../Core_Device/Standard/inc/usbd_init.h | 116 + .../Core_Device/Standard/inc/usbd_interrupt.h | 83 + .../Core_Device/Standard/inc/usbd_stdReq.h | 82 + .../Core_Device/Standard/src/usbd_core.c | 456 ++ .../Core_Device/Standard/src/usbd_init.c | 288 + .../Core_Device/Standard/src/usbd_interrupt.c | 384 ++ .../Core_Device/Standard/src/usbd_stdReq.c | 371 ++ .../Driver/inc/drv_usb_device.h | 939 +++ .../Driver/src/drv_usb_device.c | 432 ++ .../APM32F10x_ETH_Driver/inc/apm32f10x_eth.h | 1406 ++++ .../APM32F10x_ETH_Driver/src/apm32f10x_eth.c | 2203 +++++++ .../inc/apm32f10x_adc.h | 164 +- .../inc/apm32f10x_bakpr.h | 31 +- .../inc/apm32f10x_can.h | 263 +- .../inc/apm32f10x_crc.h | 32 +- .../inc/apm32f10x_dac.h | 105 +- .../inc/apm32f10x_dbgmcu.h | 31 +- .../inc/apm32f10x_dma.h | 53 +- .../inc/apm32f10x_dmc.h | 120 +- .../inc/apm32f10x_eint.h | 82 +- .../inc/apm32f10x_fmc.h | 218 +- .../inc/apm32f10x_gpio.h | 250 +- .../inc/apm32f10x_i2c.h | 124 +- .../inc/apm32f10x_iwdt.h | 48 +- .../inc/apm32f10x_misc.h | 66 +- .../inc/apm32f10x_pmu.h | 50 +- .../inc/apm32f10x_qspi.h | 224 +- .../inc/apm32f10x_rcm.h | 279 +- .../inc/apm32f10x_rtc.h | 53 +- .../inc/apm32f10x_sci2c.h | 291 +- .../inc/apm32f10x_sdio.h | 129 +- .../inc/apm32f10x_smc.h | 370 ++ .../inc/apm32f10x_spi.h | 78 +- .../inc/apm32f10x_tmr.h | 110 +- .../inc/apm32f10x_usart.h | 96 +- .../inc/apm32f10x_wwdt.h | 48 +- .../src/apm32f10x_adc.c | 119 +- .../src/apm32f10x_bakpr.c | 21 +- .../src/apm32f10x_can.c | 486 +- .../src/apm32f10x_crc.c | 17 +- .../src/apm32f10x_dac.c | 45 +- .../src/apm32f10x_dbgmcu.c | 17 +- .../src/apm32f10x_dma.c | 34 +- .../src/apm32f10x_dmc.c | 28 +- .../src/apm32f10x_eint.c | 27 +- .../src/apm32f10x_fmc.c | 35 +- .../src/apm32f10x_gpio.c | 69 +- .../src/apm32f10x_i2c.c | 337 +- .../src/apm32f10x_iwdt.c | 17 +- .../src/apm32f10x_misc.c | 77 +- .../src/apm32f10x_pmu.c | 51 +- .../src/apm32f10x_qspi.c | 25 +- .../src/apm32f10x_rcm.c | 570 +- .../src/apm32f10x_rtc.c | 28 +- .../src/apm32f10x_sci2c.c | 221 +- .../src/apm32f10x_sdio.c | 543 +- .../src/apm32f10x_smc.c | 747 +++ .../src/apm32f10x_spi.c | 191 +- .../src/apm32f10x_tmr.c | 424 +- .../src/apm32f10x_usart.c | 291 +- .../src/apm32f10x_wwdt.c | 77 +- .../CMSIS/Include/cmsis_gcc.h | 1662 ++--- .../Geehy/APM32F10x/Include/apm32f10x.h | 2418 ++++--- .../APM32F10x/Include/system_apm32f10x.h | 29 +- .../Source/arm/startup_apm32f10x_cl.s | 365 ++ .../Source/arm/startup_apm32f10x_hd.s | 6 +- .../Source/arm/startup_apm32f10x_md.s | 6 +- .../APM32F10x/Source/gcc/gcc_APM32F10xx4.ld | 164 + .../APM32F10x/Source/gcc/gcc_APM32F10xx6.ld | 164 + .../APM32F10x/Source/gcc/gcc_APM32F10xx8.ld | 164 + .../APM32F10x/Source/gcc/gcc_APM32F10xxB.ld | 164 + .../APM32F10x/Source/gcc/gcc_APM32F10xxC.ld | 164 + .../APM32F10x/Source/gcc/gcc_APM32F10xxD.ld | 164 + .../APM32F10x/Source/gcc/gcc_APM32F10xxE.ld | 164 + .../Source/gcc/startup_apm32f10x_cl.S | 397 ++ .../Source/gcc/startup_apm32f10x_hd.s | 649 +- .../Source/gcc/startup_apm32f10x_md.s | 543 +- .../Source/iar/startup_apm32f10x_cl.s | 492 ++ .../Source/iar/startup_apm32f10x_hd.s | 4 +- .../Source/iar/startup_apm32f10x_md.s | 4 +- .../Geehy/APM32F10x/Source/system_apm32f10x.c | 520 +- .../libraries/APM32F10x_Library/SConscript | 6 +- .../APM32F4xx_ETH_Driver/inc/apm32f4xx_eth.h | 1424 +++++ .../APM32F4xx_ETH_Driver/src/apm32f4xx_eth.c | 2303 +++++++ .../libraries/APM32F4xx_Library/SConscript | 7 +- bsp/apm32/libraries/Drivers/SConscript | 8 +- bsp/apm32/libraries/Drivers/drv_adc.c | 140 +- bsp/apm32/libraries/Drivers/drv_common.c | 2 +- bsp/apm32/libraries/Drivers/drv_dac.c | 64 +- bsp/apm32/libraries/Drivers/drv_eth.c | 766 +++ bsp/apm32/libraries/Drivers/drv_eth.h | 107 + bsp/apm32/libraries/Drivers/drv_gpio.c | 349 +- bsp/apm32/libraries/Drivers/drv_hwtimer.c | 349 +- bsp/apm32/libraries/Drivers/drv_log.h | 27 + bsp/apm32/libraries/Drivers/drv_pwm.c | 304 +- bsp/apm32/libraries/Drivers/drv_rtc.c | 114 +- bsp/apm32/libraries/Drivers/drv_soft_i2c.c | 44 +- bsp/apm32/libraries/Drivers/drv_spi.c | 340 +- bsp/apm32/libraries/Drivers/drv_spi.h | 14 + bsp/apm32/libraries/Drivers/drv_usart.c | 229 +- bsp/apm32/libraries/Drivers/drv_wdt.c | 24 +- bsp/apm32/libraries/Kconfig | 5 + 258 files changed, 85038 insertions(+), 6328 deletions(-) create mode 100644 bsp/apm32/apm32f072vb-miniboard/.config create mode 100644 bsp/apm32/apm32f072vb-miniboard/.gitignore create mode 100644 bsp/apm32/apm32f072vb-miniboard/Kconfig create mode 100644 bsp/apm32/apm32f072vb-miniboard/README.md create mode 100644 bsp/apm32/apm32f072vb-miniboard/SConscript create mode 100644 bsp/apm32/apm32f072vb-miniboard/SConstruct create mode 100644 bsp/apm32/apm32f072vb-miniboard/applications/SConscript create mode 100644 bsp/apm32/apm32f072vb-miniboard/applications/main.c create mode 100644 bsp/apm32/apm32f072vb-miniboard/board/Kconfig create mode 100644 bsp/apm32/apm32f072vb-miniboard/board/SConscript create mode 100644 bsp/apm32/apm32f072vb-miniboard/board/board.c create mode 100644 bsp/apm32/apm32f072vb-miniboard/board/board.h create mode 100644 bsp/apm32/apm32f072vb-miniboard/board/linker_scripts/link.icf create mode 100644 bsp/apm32/apm32f072vb-miniboard/board/linker_scripts/link.lds create mode 100644 bsp/apm32/apm32f072vb-miniboard/board/linker_scripts/link.sct create mode 100644 bsp/apm32/apm32f072vb-miniboard/figures/APM32F072VB.png create mode 100644 bsp/apm32/apm32f072vb-miniboard/figures/JFlash_Leader_01.png create mode 100644 bsp/apm32/apm32f072vb-miniboard/figures/JFlash_Leader_02.png create mode 100644 bsp/apm32/apm32f072vb-miniboard/figures/JFlash_Leader_03.png create mode 100644 bsp/apm32/apm32f072vb-miniboard/figures/JFlash_Leader_04.png create mode 100644 bsp/apm32/apm32f072vb-miniboard/project.ewp create mode 100644 bsp/apm32/apm32f072vb-miniboard/project.eww create mode 100644 bsp/apm32/apm32f072vb-miniboard/project.uvoptx create mode 100644 bsp/apm32/apm32f072vb-miniboard/project.uvprojx create mode 100644 bsp/apm32/apm32f072vb-miniboard/rtconfig.h create mode 100644 bsp/apm32/apm32f072vb-miniboard/rtconfig.py create mode 100644 bsp/apm32/apm32f072vb-miniboard/template.ewp create mode 100644 bsp/apm32/apm32f072vb-miniboard/template.eww create mode 100644 bsp/apm32/apm32f072vb-miniboard/template.uvoptx create mode 100644 bsp/apm32/apm32f072vb-miniboard/template.uvprojx create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_adc.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_can.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_cec.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_comp.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_crc.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_crs.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_dac.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_dbg.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_dma.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_eint.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_fmc.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_gpio.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_i2c.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_iwdt.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_misc.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_ob.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_pmu.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_rcm.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_rtc.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_spi.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_syscfg.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_tmr.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_usart.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_wwdt.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_adc.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_can.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_cec.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_comp.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_crc.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_crs.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_dac.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_dbg.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_dma.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_eint.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_fmc.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_gpio.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_i2c.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_iwdt.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_misc.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_ob.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_pmu.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_rcm.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_rtc.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_spi.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_syscfg.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_tmr.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_usart.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_wwdt.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/CMSIS/Include/core_cm0plus.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/CMSIS/Include/core_cmFunc.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/CMSIS/Include/core_cmInstr.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/CMSIS/LICENSE.txt create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Include/apm32f0xx.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Include/system_apm32f0xx.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f030.s create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f051.s create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f070.s create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f071.s create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f072.s create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f091.s create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F03xx6.ld create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F03xx8.ld create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F03xxC.ld create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F05xx6.ld create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F05xx8.ld create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F07xx8.ld create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F07xxB.ld create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F09xxB.ld create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F09xxC.ld create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f030.S create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f051.S create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f070.S create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f071.S create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f072.S create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f091.S create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f030.s create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f051.s create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f070.s create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f071.s create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f072.s create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f091.s create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/system_apm32f0xx.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/SConscript create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_acq.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_check.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_config.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_dxs.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_ecs.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_filter.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_linrot.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_object.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_time.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_touchkey.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_types.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_acq.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_dxs.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_ecs.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_filter.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_linrot.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_object.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_time.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_touchkey.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/CDC/inc/usbd_class_cdc.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/CDC/src/usbd_class_cdc.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/HID/inc/usbd_class_hid.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/HID/src/usbd_class_hid.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/inc/usbd_class_msc.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/inc/usbd_msc_bot.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/inc/usbd_msc_scsi.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/src/usbd_class_msc.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/src/usbd_msc_bot.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/src/usbd_msc_scsi.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/inc/usbd_core.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/inc/usbd_init.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/inc/usbd_interrupt.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/inc/usbd_stdReq.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/src/usbd_core.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/src/usbd_init.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/src/usbd_interrupt.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/src/usbd_stdReq.c create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Driver/inc/drv_usb_device.h create mode 100644 bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Driver/src/drv_usb_device.c create mode 100644 bsp/apm32/libraries/APM32F10x_Library/APM32F10x_ETH_Driver/inc/apm32f10x_eth.h create mode 100644 bsp/apm32/libraries/APM32F10x_Library/APM32F10x_ETH_Driver/src/apm32f10x_eth.c create mode 100644 bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_smc.h create mode 100644 bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_smc.c create mode 100644 bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/arm/startup_apm32f10x_cl.s create mode 100644 bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xx4.ld create mode 100644 bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xx6.ld create mode 100644 bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xx8.ld create mode 100644 bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xxB.ld create mode 100644 bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xxC.ld create mode 100644 bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xxD.ld create mode 100644 bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xxE.ld create mode 100644 bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/startup_apm32f10x_cl.S create mode 100644 bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/iar/startup_apm32f10x_cl.s create mode 100644 bsp/apm32/libraries/APM32F4xx_Library/APM32F4xx_ETH_Driver/inc/apm32f4xx_eth.h create mode 100644 bsp/apm32/libraries/APM32F4xx_Library/APM32F4xx_ETH_Driver/src/apm32f4xx_eth.c create mode 100644 bsp/apm32/libraries/Drivers/drv_eth.c create mode 100644 bsp/apm32/libraries/Drivers/drv_eth.h create mode 100644 bsp/apm32/libraries/Drivers/drv_log.h diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index e2b6d159d8..056ca614a2 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -37,6 +37,8 @@ jobs: - {RTT_BSP: "acm32/acm32f0x0-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "CME_M7", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "apm32/apm32f103xe-minibroard", RTT_TOOL_CHAIN: "sourcery-arm"} + - {RTT_BSP: "apm32/apm32f407ig-minibroard", RTT_TOOL_CHAIN: "sourcery-arm"} + - {RTT_BSP: "apm32/apm32f072vb-miniboard", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "apollo2", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "asm9260t", RTT_TOOL_CHAIN: "sourcery-arm"} # - {RTT_BSP: "ft2004", RTT_TOOL_CHAIN: "sourcery-arm"} diff --git a/bsp/apm32/apm32f072vb-miniboard/.config b/bsp/apm32/apm32f072vb-miniboard/.config new file mode 100644 index 0000000000..d187c9346e --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/.config @@ -0,0 +1,985 @@ +# +# 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_SMART 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=y +# CONFIG_RT_KSERVICE_USING_STDLIB_MEMORY 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 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_DM 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="uart1" +CONFIG_RT_VER_NUM=0x50000 +# CONFIG_RT_USING_CACHE is not set +# CONFIG_ARCH_ARM_BOOTWITH_FLUSH_CACHE is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set +# CONFIG_RT_USING_CPU_FFS is not set +CONFIG_ARCH_ARM=y +CONFIG_ARCH_ARM_CORTEX_M=y +CONFIG_ARCH_ARM_CORTEX_M0=y + +# +# 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 + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_UNAMED_PIPE_NUMBER=64 +# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set +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 is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_NULL is not set +# CONFIG_RT_USING_ZERO is not set +# CONFIG_RT_USING_RANDOM is not set +# 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_FDT is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_LCD 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_DEV_BUS is not set +# CONFIG_RT_USING_WIFI is not set +# CONFIG_RT_USING_VIRTIO 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_RYANMQTT 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 +# CONFIG_PKG_USING_WOL 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 + +# +# 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_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_ARMV7M_DWT_TOOL is not set +# CONFIG_PKG_USING_VOFA_PLUS is not set + +# +# system packages +# + +# +# enhanced kernel services +# +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set + +# +# acceleration: Assembly language or algorithmic acceleration packages +# +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set + +# +# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard +# +# CONFIG_PKG_USING_CMSIS_5 is not set +# CONFIG_PKG_USING_CMSIS_RTOS1 is not set +# CONFIG_PKG_USING_CMSIS_RTOS2 is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_UCOSII_WRAPPER is not set +# CONFIG_PKG_USING_UC_CRC is not set +# CONFIG_PKG_USING_UC_CLK is not set +# CONFIG_PKG_USING_UC_COMMON is not set +# CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_PKG_USING_FREERTOS_WRAPPER is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_PERF_COUNTER is not set +# CONFIG_PKG_USING_FLASHDB is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_THREAD_POOL is not set +# CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set +# CONFIG_PKG_USING_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set +# CONFIG_PKG_USING_EVENT_RECORDER is not set +# CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_MCUBOOT is not set +# CONFIG_PKG_USING_TINYUSB is not set +# CONFIG_PKG_USING_CHERRYUSB is not set +# CONFIG_PKG_USING_KMULTI_RTIMER is not set +# CONFIG_PKG_USING_TFDB is not set +# CONFIG_PKG_USING_QPC is not set +# CONFIG_PKG_USING_AGILE_UPGRADE is not set + +# +# peripheral libraries and drivers +# + +# +# sensors drivers +# +# CONFIG_PKG_USING_LSM6DSM is not set +# CONFIG_PKG_USING_LSM6DSL is not set +# CONFIG_PKG_USING_LPS22HB is not set +# CONFIG_PKG_USING_HTS221 is not set +# CONFIG_PKG_USING_LSM303AGR is not set +# CONFIG_PKG_USING_BME280 is not set +# CONFIG_PKG_USING_BME680 is not set +# CONFIG_PKG_USING_BMA400 is not set +# CONFIG_PKG_USING_BMI160_BMX160 is not set +# CONFIG_PKG_USING_SPL0601 is not set +# CONFIG_PKG_USING_MS5805 is not set +# CONFIG_PKG_USING_DA270 is not set +# CONFIG_PKG_USING_DF220 is not set +# CONFIG_PKG_USING_HSHCAL001 is not set +# CONFIG_PKG_USING_BH1750 is not set +# CONFIG_PKG_USING_MPU6XXX is not set +# CONFIG_PKG_USING_AHT10 is not set +# CONFIG_PKG_USING_AP3216C is not set +# CONFIG_PKG_USING_TSL4531 is not set +# CONFIG_PKG_USING_DS18B20 is not set +# CONFIG_PKG_USING_DHT11 is not set +# CONFIG_PKG_USING_DHTXX is not set +# CONFIG_PKG_USING_GY271 is not set +# CONFIG_PKG_USING_GP2Y10 is not set +# CONFIG_PKG_USING_SGP30 is not set +# CONFIG_PKG_USING_HDC1000 is not set +# CONFIG_PKG_USING_BMP180 is not set +# CONFIG_PKG_USING_BMP280 is not set +# CONFIG_PKG_USING_SHTC1 is not set +# CONFIG_PKG_USING_BMI088 is not set +# CONFIG_PKG_USING_HMC5883 is not set +# CONFIG_PKG_USING_MAX6675 is not set +# CONFIG_PKG_USING_TMP1075 is not set +# CONFIG_PKG_USING_SR04 is not set +# CONFIG_PKG_USING_CCS811 is not set +# CONFIG_PKG_USING_PMSXX is not set +# CONFIG_PKG_USING_RT3020 is not set +# CONFIG_PKG_USING_MLX90632 is not set +# CONFIG_PKG_USING_MLX90393 is not set +# CONFIG_PKG_USING_MLX90392 is not set +# CONFIG_PKG_USING_MLX90397 is not set +# CONFIG_PKG_USING_MS5611 is not set +# CONFIG_PKG_USING_MAX31865 is not set +# CONFIG_PKG_USING_VL53L0X is not set +# CONFIG_PKG_USING_INA260 is not set +# CONFIG_PKG_USING_MAX30102 is not set +# CONFIG_PKG_USING_INA226 is not set +# CONFIG_PKG_USING_LIS2DH12 is not set +# CONFIG_PKG_USING_HS300X is not set +# CONFIG_PKG_USING_ZMOD4410 is not set +# CONFIG_PKG_USING_ISL29035 is not set +# CONFIG_PKG_USING_MMC3680KJ is not set +# CONFIG_PKG_USING_QMP6989 is not set +# CONFIG_PKG_USING_BALANCE is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AD7746 is not set +# CONFIG_PKG_USING_ADT74XX is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_CW2015 is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_PAJ7620 is not set + +# +# touch drivers +# +# CONFIG_PKG_USING_GT9147 is not set +# CONFIG_PKG_USING_GT1151 is not set +# CONFIG_PKG_USING_GT917S is not set +# CONFIG_PKG_USING_GT911 is not set +# CONFIG_PKG_USING_FT6206 is not set +# CONFIG_PKG_USING_FT5426 is not set +# CONFIG_PKG_USING_FT6236 is not set +# CONFIG_PKG_USING_XPT2046_TOUCH is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_ESP_IDF is not set +# CONFIG_PKG_USING_BUTTON is not set +# CONFIG_PKG_USING_PCF8574 is not set +# CONFIG_PKG_USING_SX12XX is not set +# CONFIG_PKG_USING_SIGNAL_LED is not set +# CONFIG_PKG_USING_LEDBLINK is not set +# CONFIG_PKG_USING_LITTLED is not set +# CONFIG_PKG_USING_LKDGUI is not set +# CONFIG_PKG_USING_NRF5X_SDK is not set +# CONFIG_PKG_USING_NRFX is not set +# CONFIG_PKG_USING_WM_LIBRARIES is not set + +# +# Kendryte SDK +# +# CONFIG_PKG_USING_K210_SDK is not set +# CONFIG_PKG_USING_KENDRYTE_SDK is not set +# CONFIG_PKG_USING_INFRARED is not set +# CONFIG_PKG_USING_MULTI_INFRARED is not set +# CONFIG_PKG_USING_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set +# CONFIG_PKG_USING_AT24CXX is not set +# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_PCA9685 is not set +# CONFIG_PKG_USING_I2C_TOOLS is not set +# CONFIG_PKG_USING_NRF24L01 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_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_RFM300 is not set +# CONFIG_PKG_USING_IO_INPUT_FILTER is not set +# CONFIG_PKG_USING_RASPBERRYPI_PICO_SDK is not set +# CONFIG_PKG_USING_LRF_NV7LIDAR is not set +# CONFIG_PKG_USING_FINGERPRINT 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 + +# +# Signal Processing and Control Algorithm Packages +# +# CONFIG_PKG_USING_FIRE_PID_CURVE is not set +# CONFIG_PKG_USING_UKAL 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_CRCLIB is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_DESIGN_PATTERN is not set +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set +# CONFIG_PKG_USING_MFBD is not set +# CONFIG_PKG_USING_SLCAN2RTT is not set +# CONFIG_PKG_USING_SOEM is not set +# CONFIG_PKG_USING_QPARAM is not set +# CONFIG_PKG_USING_CorevMCU_CLI is not set + +# +# Arduino libraries +# +# CONFIG_PKG_USING_RTDUINO is not set + +# +# Projects +# +# CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set +# CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set +# CONFIG_PKG_USING_ARDUINO_MATLAB_SUPPORT is not set + +# +# Sensors +# +# CONFIG_PKG_USING_ARDUINO_SENSOR_DEVICE_DRIVERS is not set +# CONFIG_PKG_USING_ARDUINO_CAPACITIVESENSOR is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL375 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L0X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L1X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSOR is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL6180X is not set +# CONFIG_PKG_USING_ADAFRUIT_MAX31855 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31865 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31856 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX6675 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90614 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS1 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AHTX0 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS0 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADT7410 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME680 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9808 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4728 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA219 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR390 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL345 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DHT is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9600 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM6DS is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO055 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX1704X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMC56X3 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90393 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90395 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ICM20X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DPS310 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTS221 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT4X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT31 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL343 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS726X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AMG88XX is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2320 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2315 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR329_LTR303 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP3XX is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MS8607 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3MDL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90640 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMA8451 is not set +# CONFIG_PKG_USING_ADAFRUIT_MSA301 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL115A2 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X_RVC is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS2MDL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303DLH_MAG is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LC709203F is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CAP1188 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CCS811 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_NAU7802 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS331 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS2X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS35HW is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303_ACCEL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3DH is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8591 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL3115A2 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPR121 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPRLS is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPU6050 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCT2075 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PM25AQI is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_EMC2101 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXAS21002C is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SCD30 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXOS8700 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HMC5883_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP30 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP006 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TLA202X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCS34725 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI7021 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI1145 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP40 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHTC3 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HDC1000 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU21DF is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS7341 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU31D is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSORLAB is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA260 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP007_LIBRARY is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_L3GD20 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP117 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSC2007 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2561 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2591_LIBRARY is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VCNL4040 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6070 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6075 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML7700 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LIS3DHTR is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_DHT is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL335 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL345 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BME280 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BMP280 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_H3LIS331DL is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_MMA7660 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_TSL2561 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_PAJ7620 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_VL53L0X is not set +# CONFIG_PKG_USING_SEEED_ITG3200 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SHT31 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HP20X is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_DRV2605L is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BBM150 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HMC5883L is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LSM303DLH is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_TCS3414CS is not set +# CONFIG_PKG_USING_SEEED_MP503 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BMP085 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HIGHTEMP is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_VEML6070 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SI1145 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SHT35 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_AT42QT1070 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LSM6DS3 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HDC1000 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HM3301 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_MCP9600 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LTC2941 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LDC1612 is not set + +# +# Display +# +# CONFIG_PKG_USING_ARDUINO_U8G2 is not set +# CONFIG_PKG_USING_SEEED_TM1637 is not set + +# +# Timing +# +# CONFIG_PKG_USING_ARDUINO_MSTIMER2 is not set + +# +# Data Processing +# +# CONFIG_PKG_USING_ARDUINO_KALMANFILTER is not set +# CONFIG_PKG_USING_ARDUINO_ARDUINOJSON is not set + +# +# Data Storage +# + +# +# Communication +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PN532 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI4713 is not set + +# +# Device Control +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8574 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCA9685 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_PCF85063TP is not set + +# +# Other +# + +# +# Signal IO +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BUSIO is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCA8418 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP23017 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADS1X15 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AW9523 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP3008 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4725 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BD3491FS is not set + +# +# Uncategorized +# +CONFIG_SOC_FAMILY_APM32=y +CONFIG_SOC_SERIES_APM32F0=y + +# +# Hardware Drivers Config +# +CONFIG_SOC_APM32F072VB=y + +# +# Onboard Peripheral Drivers +# + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART1=y +# CONFIG_BSP_USING_UART2 is not set +# CONFIG_BSP_USING_ADC is not set +# CONFIG_BSP_USING_DAC is not set +# CONFIG_BSP_USING_ONCHIP_RTC is not set +# CONFIG_BSP_USING_I2C is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_TMR is not set +# CONFIG_BSP_USING_PWM is not set +# CONFIG_BSP_USING_WDT is not set + +# +# Board extended module Drivers +# diff --git a/bsp/apm32/apm32f072vb-miniboard/.gitignore b/bsp/apm32/apm32f072vb-miniboard/.gitignore new file mode 100644 index 0000000000..7221bde019 --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/.gitignore @@ -0,0 +1,42 @@ +*.pyc +*.map +*.dblite +*.elf +*.bin +*.hex +*.axf +*.exe +*.pdb +*.idb +*.ilk +*.old +build +Debug +documentation/html +packages/ +*~ +*.o +*.obj +*.out +*.bak +*.dep +*.lib +*.i +*.d +.DS_Stor* +.config 3 +.config 4 +.config 5 +Midea-X1 +*.uimg +GPATH +GRTAGS +GTAGS +.vscode +JLinkLog.txt +JLinkSettings.ini +DebugConfig/ +RTE/ +settings/ +*.uvguix* +cconfig.h diff --git a/bsp/apm32/apm32f072vb-miniboard/Kconfig b/bsp/apm32/apm32f072vb-miniboard/Kconfig new file mode 100644 index 0000000000..7a400db91f --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/Kconfig @@ -0,0 +1,22 @@ +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/apm32/apm32f072vb-miniboard/README.md b/bsp/apm32/apm32f072vb-miniboard/README.md new file mode 100644 index 0000000000..05c9bbfd5a --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/README.md @@ -0,0 +1,116 @@ +# APM32F072VB MINI BOARD BSP 说明 + +## 简介 + +本文档为 APM32F072VB MINI 开呿¿ï¼ˆMINI BOARD)的 BSP (æ¿çº§æ”¯æŒåŒ…) 说明。 + +主è¦å†…容如下: + +- 开呿¿èµ„æºä»‹ç» +- BSP 快速上手 + +通过阅读快速上手章节开å‘者å¯ä»¥å¿«é€Ÿåœ°ä¸Šæ‰‹è¯¥ BSP,将 RT-Thread è¿è¡Œåœ¨å¼€å‘æ¿ä¸Šã€‚ + +## 开呿¿ä»‹ç» + +APM32F072VB MINI BOARD,采用标准JTAG/SWD调试接å£ï¼Œå¼•出了全部的IOã€‚å¼€å‘æ¿å¤–观如下图所示: + +image-20221227141551541 + +- æœ‰å…³å¼€å‘æ¿å’ŒèŠ¯ç‰‡çš„è¯¦æƒ…å¯è‡³æžæµ·å®˜ç½‘查阅。[å®˜ç½‘å¼€å‘æ¿é“¾æŽ¥ ](https://www.geehy.com/support/apm32?id=192) + + +è¯¥å¼€å‘æ¿å¸¸ç”¨ **æ¿è½½èµ„æº** 如下: + +- MCU:APM32F072VBT6,主频 48MHz,128KB FLASH ,16KB RAM +- 外部 RAM:无 +- 外部 FLASH:无 +- 常用外设 + - LED:2个,(黄色,PE5/PE6) + - 按键:2个,K1(PA1),K2(PA0) +- 常用接å£ï¼šRS232转串å£ã€USB SLAVE +- 调试接å£ï¼šæ ‡å‡† JTAG/SWD + + + +## å¤–è®¾æ”¯æŒ + +本 BSP ç›®å‰å¯¹å¤–è®¾çš„æ”¯æŒæƒ…况如下: + +| **æ¿è½½å¤–设** | **æ”¯æŒæƒ…况** | **备注** | +| :----------- | :----------: | :------------------------------------ | +| RS232è½¬ä¸²å£ | æ”¯æŒ | 使用 UART1/ UART2(通过跳线选择) | +| **片上外设** | **æ”¯æŒæƒ…况** | **备注** | +| GPIO | æ”¯æŒ | PA0, PA1... PF10 ---> PIN: 0, 1...89 | +| UART | æ”¯æŒ | UART1/2 | +| ADC | æ”¯æŒ | ADC1 | +| DAC | æ”¯æŒ | DAC1 | +| RTC | æ”¯æŒ | 支æŒå¤–部晶振和内部低速时钟 | +| TMR | æ”¯æŒ | TMR1/2/3/6/7/14/15/16/17 | +| PWM | æ”¯æŒ | TMR3 ->CH1/2/3/4 | +| I2C | æ”¯æŒ | 软件I2C | +| SPI | æ”¯æŒ | SPI1/2 | +| WDT | æ”¯æŒ | IWDT | + +## 使用说明 + +本章节是为刚接触 RT-Thread 的新手准备的使用说明,éµå¾ªç®€å•的步骤å³å¯å°† RT-Thread æ“作系统è¿è¡Œåœ¨è¯¥å¼€å‘æ¿ä¸Šï¼Œçœ‹åˆ°å®žéªŒæ•ˆæžœ 。 + + +### 快速上手 + +本 BSP 为开å‘者æä¾›MDK5 工程。下é¢ä»¥ MDK5 å¼€å‘环境为例,介ç»å¦‚何将系统è¿è¡Œèµ·æ¥ã€‚ + +#### 硬件连接 + +使用数æ®çº¿è¿žæŽ¥å¼€å‘æ¿åˆ° PC,打开电æºå¼€å…³ã€‚ + +#### 编译下载 +- æ–¹å¼ä¸€ï¼šMDK + + åŒå‡» project.uvprojx 文件,打开 MDK5 工程,编译并下载程åºåˆ°å¼€å‘æ¿ã€‚ + +> 工程默认é…置使用 J-Link 仿真器下载程åºï¼Œåœ¨é€šè¿‡ J-Link è¿žæŽ¥å¼€å‘æ¿çš„基础上,点击下载按钮å³å¯ä¸‹è½½ç¨‹åºåˆ°å¼€å‘æ¿ + +- æ–¹å¼äºŒï¼šJ-Flash下载 + + 通过ENV工具的scons指令或MDK编译出bin文件åŽï¼Œå†ä½¿ç”¨J-Flash工具将binæ–‡ä»¶ä¸‹è½½è‡³å¼€å‘æ¿å³å¯ï¼Œå¤§è‡´æ­¥éª¤å¦‚下: + +##### 1ã€å»ºç«‹J-Flash工程 + +![board](figures/JFlash_Leader_01.png) + +**注æ„**:步骤4é€‰æ‹©èŠ¯ç‰‡åž‹å·æ—¶ï¼Œè¦æ ¹æ®è‡ªå·±çš„开呿¿æ‰€ç”¨çš„芯片型å·è¿›è¡Œé€‰æ‹©ã€‚æ¯”å¦‚æœ¬å¼€å‘æ¿ï¼Œåˆ™é€‰æ‹©å¯¹åº”çš„ **APM32F072VBT6** 。 + +##### 2ã€è¿žæŽ¥å¼€å‘æ¿ + +![board](figures/JFlash_Leader_02.png) +##### 3ã€å°†bin文件拖至工程,起始地å€è®¾ä¸º0x8000000 +![board](figures/JFlash_Leader_03.png) +##### 4ã€ç‚¹å‡»ä¸‹è½½ +![board](figures/JFlash_Leader_04.png) + +#### è¿è¡Œç»“æžœ + +ä¸‹è½½ç¨‹åºæˆåŠŸä¹‹åŽï¼Œç³»ç»Ÿä¼šè‡ªåЍè¿è¡Œï¼ŒLED é—ªçƒ + +è¿žæŽ¥å¼€å‘æ¿å¯¹åº”串å£åˆ° PC , 在终端工具里打开相应的串å£ï¼ˆ115200-8-1-N),å¤ä½è®¾å¤‡åŽï¼Œå¯ä»¥çœ‹åˆ° RT-Thread 的输出信æ¯: + +```bash + \ | / +- RT - Thread Operating System + / | \ 4.1.0 build Aug 20 2021 + 2006 - 2021 Copyright by rt-thread team +msh > +``` +## 注æ„事项 + +- å¯åœ¨æžæµ·å®˜æ–¹ç½‘站进行所需资料下载,如pack安装包和MINI开呿¿åŽŸç†å›¾ç­‰ï¼ˆwww.geehy.com); + +## è”ç³»äººä¿¡æ¯ + +-[abbbcc ](https://gitee.com/abbbcc) + +-[stevetong459 ](https://github.com/stevetong459) + +-[luobeihai](https://github.com/luobeihai) \ No newline at end of file diff --git a/bsp/apm32/apm32f072vb-miniboard/SConscript b/bsp/apm32/apm32f072vb-miniboard/SConscript new file mode 100644 index 0000000000..20f7689c53 --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/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/apm32/apm32f072vb-miniboard/SConstruct b/bsp/apm32/apm32f072vb-miniboard/SConstruct new file mode 100644 index 0000000000..5660242653 --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/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 = 'rt-thread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CFLAGS = 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 in ['iccarm']: + env.Replace(CCCOM = ['$CC $CFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map rt-thread.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) + +apm32_library = 'APM32F0xx_Library' +rtconfig.BSP_LIBRARY_TYPE = apm32_library + +# include libraries +objs.extend(SConscript(os.path.join(libraries_path_prefix, apm32_library, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'Drivers', 'SConscript'))) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/apm32/apm32f072vb-miniboard/applications/SConscript b/bsp/apm32/apm32f072vb-miniboard/applications/SConscript new file mode 100644 index 0000000000..9bb9abae89 --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/applications/SConscript @@ -0,0 +1,15 @@ +from building import * +import os + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +list = os.listdir(cwd) +for item in list: + if os.path.isfile(os.path.join(cwd, item, 'SConscript')): + group = group + SConscript(os.path.join(item, 'SConscript')) + +Return('group') diff --git a/bsp/apm32/apm32f072vb-miniboard/applications/main.c b/bsp/apm32/apm32f072vb-miniboard/applications/main.c new file mode 100644 index 0000000000..de1309f793 --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/applications/main.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-11-06 zylx first version + */ + +#include +#include +#include + +/* defined the LED2 pin: PE6 */ +#define LED2_PIN GET_PIN(E, 6) + +int main(void) +{ + int count = 1; + /* set LED2 pin mode to output */ + rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT); + + while (count++) + { + rt_pin_write(LED2_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED2_PIN, PIN_LOW); + rt_thread_mdelay(500); + } + + return RT_EOK; +} diff --git a/bsp/apm32/apm32f072vb-miniboard/board/Kconfig b/bsp/apm32/apm32f072vb-miniboard/board/Kconfig new file mode 100644 index 0000000000..42cbfabb9d --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/board/Kconfig @@ -0,0 +1,213 @@ +menu "Hardware Drivers Config" + +config SOC_APM32F072VB + bool + select SOC_SERIES_APM32F0 + 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_UART1 + bool "Enable UART1" + default y + config BSP_USING_UART2 + bool "Enable UART2" + 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 "Enable ADC1" + 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 "Enable DAC1" + default n + endif + + menuconfig BSP_USING_ONCHIP_RTC + bool "Enable RTC" + select RT_USING_RTC + default n + if BSP_USING_ONCHIP_RTC + choice + prompt "Select clock source" + default BSP_RTC_USING_LSE + + config BSP_RTC_USING_LSE + bool "RTC USING LSE" + + config BSP_RTC_USING_LSI + bool "RTC USING LSI" + endchoice + endif + + menuconfig BSP_USING_I2C + bool "Enable I2C BUS (software simulation)" + default n + select RT_USING_I2C + select RT_USING_I2C_BITOPS + select RT_USING_PIN + if BSP_USING_I2C + config BSP_USING_I2C1 + bool "Enable I2C1 BUS" + if BSP_USING_I2C1 + comment "Notice: PB10 --> 26; PB11 --> 27" + config BSP_I2C1_SCL_PIN + int "i2c1 scl pin number" + range 0 63 + default 26 + config BSP_I2C1_SDA_PIN + int "I2C1 sda pin number" + range 0 63 + default 27 + endif + config BSP_USING_I2C2 + bool "Enable I2C2 BUS" + if BSP_USING_I2C2 + comment "Notice: PA0 --> 0; PA1 --> 1" + config BSP_I2C2_SCL_PIN + int "i2c2 scl pin number" + range 0 63 + default 22 + config BSP_I2C2_SDA_PIN + int "I2C2 sda pin number" + range 0 63 + default 23 + endif + config BSP_USING_I2C3 + bool "Enable I2C3 BUS" + if BSP_USING_I2C3 + comment "Notice: PB0 --> 16; PB1 --> 17" + config BSP_I2C3_SCL_PIN + int "i2c3 scl pin number" + range 0 63 + default 8 + config BSP_I2C3_SDA_PIN + int "I2C3 sda pin number" + range 0 63 + default 41 + endif + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI" + default n + select RT_USING_SPI + if BSP_USING_SPI + config BSP_USING_SPI1 + bool "Enable SPI1" + default n + + config BSP_USING_SPI2 + bool "Enable SPI2" + default n + endif + + menuconfig BSP_USING_TMR + bool "Enable Timer" + default n + select RT_USING_HWTIMER + if BSP_USING_TMR + config BSP_USING_TMR1 + bool "Enable TMR1" + default n + + config BSP_USING_TMR2 + bool "Enable TMR2" + default n + + config BSP_USING_TMR3 + bool "Enable TMR3" + default n + + config BSP_USING_TMR6 + bool "Enable TMR6" + default n + + config BSP_USING_TMR7 + bool "Enable TMR7" + default n + + config BSP_USING_TMR14 + bool "Enable TMR14" + default n + + config BSP_USING_TMR15 + bool "Enable TMR15" + default n + + config BSP_USING_TMR16 + bool "Enable TMR16" + default n + + config BSP_USING_TMR17 + bool "Enable TMR17" + default n + endif + + menuconfig BSP_USING_PWM + bool "Enable PWM" + default n + select RT_USING_PWM + if BSP_USING_PWM + menuconfig BSP_USING_PWM3 + bool "Enable timer3 output PWM" + default n + if BSP_USING_PWM3 + config BSP_USING_PWM3_CH1 + bool "Enable PWM3 channel1" + default n + + config BSP_USING_PWM3_CH2 + bool "Enable PWM3 channel2" + default n + + config BSP_USING_PWM3_CH3 + bool "Enable PWM3 channel3" + default n + + config BSP_USING_PWM3_CH4 + bool "Enable PWM3 channel4" + default n + endif + endif + + config BSP_USING_WDT + bool "Enable Watchdog Timer" + select RT_USING_WDT + default n + +endmenu + +menu "Board extended module Drivers" + +endmenu + +endmenu diff --git a/bsp/apm32/apm32f072vb-miniboard/board/SConscript b/bsp/apm32/apm32f072vb-miniboard/board/SConscript new file mode 100644 index 0000000000..5dabcec176 --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/board/SConscript @@ -0,0 +1,36 @@ +import os +import rtconfig +from building import * + +Import('SDK_LIB') + +cwd = GetCurrentDir() + +# add general drivers +src = Split(''' +board.c +''') + +path = [cwd] + +startup_path_prefix = SDK_LIB + +if rtconfig.PLATFORM in ['armcc', 'armclang']: + src += [startup_path_prefix + '/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f072.s'] + +if rtconfig.PLATFORM in ['iccarm']: + src += [startup_path_prefix + '/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f072.s'] + +if rtconfig.PLATFORM in ['gcc']: + src += [startup_path_prefix + '/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f072.S'] + +# APM32F030x6 || APM32F030x8 || APM32F030xC +# APM32F051x6 || APM32F051x8 +# APM32F070xB +# APM32F071x8 || APM32F071xB +# APM32F072x8 || APM32F072xB +# APM32F091xB || APM32F091xC +# You can select chips from the list above +CPPDEFINES = ['APM32F072xB'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) +Return('group') diff --git a/bsp/apm32/apm32f072vb-miniboard/board/board.c b/bsp/apm32/apm32f072vb-miniboard/board/board.c new file mode 100644 index 0000000000..16ffd4f2b5 --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/board/board.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-12-21 zylx first version + */ + +#include "board.h" + +void apm32_usart_init(void) +{ + GPIO_Config_T GPIO_ConfigStruct; + +#ifdef BSP_USING_UART1 + RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA); + RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_USART1); + + /* Connect PXx to USARTx_Tx */ + GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_9, GPIO_AF_PIN1); + + /* Connect PXx to USARRX_Rx */ + GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_10, GPIO_AF_PIN1); + + /* Configure USART Tx/Rx as alternate function push-pull */ + GPIO_ConfigStruct.mode = GPIO_MODE_AF; + GPIO_ConfigStruct.pin = GPIO_PIN_9; + GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz; + GPIO_ConfigStruct.outtype = GPIO_OUT_TYPE_PP; + GPIO_ConfigStruct.pupd = GPIO_PUPD_PU; + GPIO_Config(GPIOA, &GPIO_ConfigStruct); + + GPIO_ConfigStruct.pin = GPIO_PIN_10; + GPIO_Config(GPIOA, &GPIO_ConfigStruct); +#endif + +#ifdef BSP_USING_UART2 + RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA); + RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_USART2); + + /* Connect PXx to USARTx_Tx */ + GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_2, GPIO_AF_PIN1); + + /* Connect PXx to USARRX_Rx */ + GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_3, GPIO_AF_PIN1); + + /* Configure USART Tx/Rx as alternate function push-pull */ + GPIO_ConfigStruct.mode = GPIO_MODE_AF; + GPIO_ConfigStruct.pin = GPIO_PIN_2; + GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz; + GPIO_ConfigStruct.outtype = GPIO_OUT_TYPE_PP; + GPIO_ConfigStruct.pupd = GPIO_PUPD_PU; + GPIO_Config(GPIOA, &GPIO_ConfigStruct); + + GPIO_ConfigStruct.pin = GPIO_PIN_3; + GPIO_Config(GPIOA, &GPIO_ConfigStruct); +#endif +} + +void apm32_msp_spi_init(void *Instance) +{ +#ifdef BSP_USING_SPI + GPIO_Config_T GPIO_InitStructure; + SPI_T *spi_x = (SPI_T *)Instance; + + if(spi_x == SPI1) + { + /* Enable related Clock */ + RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOE); + RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SPI1); + RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG); + + /* Config SPI PinAF */ + GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_15, GPIO_AF_PIN1); + GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_14, GPIO_AF_PIN1); + GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_13, GPIO_AF_PIN1); + + /* Config SPI GPIO*/ + GPIO_ConfigStructInit(&GPIO_InitStructure); + GPIO_InitStructure.pin = GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; + GPIO_InitStructure.speed = GPIO_SPEED_50MHz; + GPIO_InitStructure.mode = GPIO_MODE_AF; + GPIO_InitStructure.outtype = GPIO_OUT_TYPE_PP; + GPIO_InitStructure.pupd = GPIO_PUPD_NO; + GPIO_Config(GPIOE, &GPIO_InitStructure); + } +#endif +} + +void apm32_msp_timer_init(void *Instance) +{ +#ifdef BSP_USING_PWM + GPIO_Config_T gpio_config; + TMR_T *tmr_x = (TMR_T *)Instance; + + if (tmr_x == TMR3) + { + RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR3); + + /* TMR3 channel 1 gpio init */ + GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_6, GPIO_AF_PIN0); + gpio_config.pin = GPIO_PIN_6; + gpio_config.mode = GPIO_MODE_AF; + gpio_config.outtype = GPIO_OUT_TYPE_PP; + gpio_config.pupd = GPIO_PUPD_NO; + gpio_config.speed = GPIO_SPEED_50MHz; + GPIO_Config(GPIOC, &gpio_config); + + /* TMR3 channel 2 gpio init */ + GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_7, GPIO_AF_PIN0); + gpio_config.pin = GPIO_PIN_7; + GPIO_Config(GPIOC, &gpio_config); + + /* TMR3 channel 3 gpio init */ + GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_8, GPIO_AF_PIN0); + gpio_config.pin = GPIO_PIN_8; + GPIO_Config(GPIOC, &gpio_config); + + /* TMR3 channel 4 gpio init */ + GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_9, GPIO_AF_PIN0); + gpio_config.pin = GPIO_PIN_9; + GPIO_Config(GPIOC, &gpio_config); + } +#endif +} diff --git a/bsp/apm32/apm32f072vb-miniboard/board/board.h b/bsp/apm32/apm32f072vb-miniboard/board/board.h new file mode 100644 index 0000000000..8091e17298 --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/board/board.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 Abbcc first version + */ + +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include +#include + +#include "apm32f0xx_gpio.h" +#include "apm32f0xx_syscfg.h" +#include "apm32f0xx_rcm.h" +#include "apm32f0xx_misc.h" +#include "apm32f0xx_eint.h" +#include "apm32f0xx_usart.h" + +#if defined(RT_USING_ADC) + #include "apm32f0xx_adc.h" +#endif +#if defined(RT_USING_DAC) + #include "apm32f0xx_dac.h" +#endif +#if defined(RT_USING_RTC) + #include "apm32f0xx_rtc.h" + #include "apm32f0xx_pmu.h" +#endif +#if defined(RT_USING_SPI) + #include "apm32f0xx_spi.h" +#endif +#if defined(RT_USING_HWTIMER) || defined(RT_USING_PWM) + #include "apm32f0xx_tmr.h" +#endif +#if defined(RT_USING_WDT) + #include "apm32f0xx_iwdt.h" + #include "apm32f0xx_wwdt.h" +#endif + +#include "drv_common.h" +#include "drv_gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define APM32_FLASH_START_ADRESS ((uint32_t)0x08000000) +#define APM32_FLASH_SIZE (128 * 1024) +#define APM32_FLASH_END_ADDRESS ((uint32_t)(APM32_FLASH_START_ADRESS + APM32_FLASH_SIZE)) + +/* Internal SRAM memory size[Kbytes] <8-64>, Default: 64 */ +#define APM32_SRAM_SIZE 16 +#define APM32_SRAM_END (0x20000000 + APM32_SRAM_SIZE * 1024) + +#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 APM32_SRAM_END + +void SystemClock_Config(void); + +void apm32_usart_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __BOARD_H__ */ diff --git a/bsp/apm32/apm32f072vb-miniboard/board/linker_scripts/link.icf b/bsp/apm32/apm32f072vb-miniboard/board/linker_scripts/link.icf new file mode 100644 index 0000000000..7f352fc72a --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/board/linker_scripts/link.icf @@ -0,0 +1,28 @@ +/*###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__ = 0x0801FFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x20003FFF; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x0400; +define symbol __ICFEDIT_size_heap__ = 0x000; +/**** End of ICF editor section. ###ICF###*/ + +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 block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; + +place in ROM_region { readonly }; +place in RAM_region { readwrite, last block CSTACK}; diff --git a/bsp/apm32/apm32f072vb-miniboard/board/linker_scripts/link.lds b/bsp/apm32/apm32f072vb-miniboard/board/linker_scripts/link.lds new file mode 100644 index 0000000000..8f9c4fa1a8 --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/board/linker_scripts/link.lds @@ -0,0 +1,163 @@ +/* + * linker script for APM32F0xx with GNU ld + */ + +/* Program Entry, set to mark it as "used" and avoid gc */ +MEMORY +{ + ROM (rx) : ORIGIN = 0x08000000, LENGTH = 128K /* 128KB flash */ + RAM (rw) : ORIGIN = 0x20000000, LENGTH = 16K /* 16K sram */ +} +ENTRY(Reset_Handler) +_system_stack_size = 0x400; + +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 = .; + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + + . = ALIGN(4); + + PROVIDE(__ctors_start__ = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE(__ctors_end__ = .); + + . = ALIGN(4); + + _etext = .; + } > ROM = 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 = .; + _start_address_init_data = .; + } > ROM + __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 = . ; + _start_address_data = .; + + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + + + PROVIDE(__dtors_start__ = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(__dtors_end__ = .); + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _edata = . ; + _end_address_data = .; + } >RAM + + .stack : + { + . = ALIGN(4); + _sstack = .; + . = . + _system_stack_size; + . = ALIGN(4); + _estack = .; + _end_stack = .; + } >RAM + + __bss_start = .; + _start_address_bss = .; + .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) + } > RAM + __bss_end = .; + _end_address_bss = .; + + _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/apm32/apm32f072vb-miniboard/board/linker_scripts/link.sct b/bsp/apm32/apm32f072vb-miniboard/board/linker_scripts/link.sct new file mode 100644 index 0000000000..adff0c5912 --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/board/linker_scripts/link.sct @@ -0,0 +1,15 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x08000000 0x00020000 { ; load region size_region + ER_IROM1 0x08000000 0x00020000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x20000000 0x00004000 { ; RW data + .ANY (+RW +ZI) + } +} + diff --git a/bsp/apm32/apm32f072vb-miniboard/figures/APM32F072VB.png b/bsp/apm32/apm32f072vb-miniboard/figures/APM32F072VB.png new file mode 100644 index 0000000000000000000000000000000000000000..77aacffaeee291c5be0383a2679a1cc80d10c022 GIT binary patch literal 878748 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]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

0J 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

@;PVVm-8wA3A_UrFdQ5R31mw@EF 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�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 z zmOKL&W??JZz|PzgSA8~1Xrn*?bsKKVTMqEmBo+&b!`I(|PK^s)52OLNsQ^B(?O)`v zfq!qKNZS<0f^E^l!V}!ONQ^>tusyA8^vt&l>p{8pb^X{+6}Y z^D&O0H&bHiNEDJL1K3xYPQQeEf0*?SO_%E&&V84G9JOEnBHM3kx&Gs!#9L|T)A9Uy z)`#Z)XMe8yq$0o&fc{5cMDY$zr#zN4czF2rVngEe=Xd~jB#ow+P;q*ag8>8=8Wt;YAJ@ZT#jnzunuy!o#QF-@$4T(l zhCMOp`)qjYOvp`RTdzGTxHxNBBLT*oC)sx%84gHnDd+p{3a$Dod-RU1AS^hTQ&t_m zYlE+4a{Tac7d-1EwDEOw(-QQ_3%Ln^@%kKXhWcS{Mmn;y>kC}>|Z@?$Hm1p?E&dobG`u*9tYJ=cH5uD ztgL)Izw@?7dqDmrO#;xgt@H7KP9W&>=kN;AtTDY9;MU*O^$!Rq_tO(Weo2x658+E_ z^;2ddklV4IeQ0&~0vu+iR-VSZ;)J*6G*yLdz3uk;C7bThf!ZEtvAnD)(}Q!7{tk3U`&bvTM(m}s`fP$EkcS&DrWRwFiLI|uXtC@2pYOw;2xeZ z8y3DdX^27ybb#LwAr+g31_!E0Ntm{gv>+b>;RDv>KNw2#mtpv}3Q^<+z~G>c9{lSX z2}x7Aj*n0Avk(ojC6-iJfqKi*-eqxUx2d5{rMBpF8KPXZBp42brpx+9PMCmVM?F!9 zWM;DUDebZ~N~WM+MC53x0_z|}oq2H>ZXDXc3p7sLp*wV%L#JW!P_<+|`}i8Yz~wSi z)ZcHvvhmRSvzii-^ja255)mO7Gdxn87$pdo=A~w~E)lgJ>d#W$H_7tuvDhBk>aJ=H$8CdHlyASW9T9Ose5DV5V}~yCmyKTR4n}QUXh>xXX_X`qFrvDQeUx(^ z3&h~#Ftd0erIy71GLLKij>xxsnBx+2Ihc^+@})c z=>BOFp*g;G>-D~vk=EU-#b5W29J>F2pNo+{<;IVDp7-lm_gBll>oGtd-TD3SaEx2y zR?f;-KXs7bY9M+QFx&ubhUY*oWgIveHJyI;y_&b~Z#MEec^CFc=!Zi+uGr10qu1TJ z@y)+uzlYq&+DgO}-_*9TbEg|{)%&leF8BU=JX*fsd|dLmmm4njx>ziZ&j6{xpMf&><= zLMi7`knxTR&~1Z$7VYt0!-- z#|HdE(f41Coa`IYWzl3TW@P=>hTfCUsgd17^-q(1hyWw0R|bUs`bM?o73Ns|7kU@F zJ-v=zO1gWx(`;Ah-Qq2tfS4st^i=aItjefuPf<-oLP!*8{sk=RVM)>DNf57-)D%($SXyI|#Co({gm%dF{W`_Qe2}n6)rXg%j4e>}{`3R2-oN zJ-<=TLgkN@hp4{$56|_2He(D9`YPKX@nfmsj6S59Lh{G$H}s=L1E5yrO?2P%%%??w zUKm*Ie_1~A_qAw{w8c8F_ckO0lrs1yeaXK!h<2~ptbv)L^7)IrbKT+aqU&9N=%qoy z@d&|hUle+#%*?t$e12E!)MpG9CfaOrx|eCwq{!tN1y#em#-kyxLPyG2)t-_q@x3)Q z7aI=$E1u8w-YZk{*#o+$z4s!a9OM3XQ#q&6b-#dyowm)x<2@A>*wkyEb(^w$ObiV6 zj4mt(?cqsBmxckL*882bRn3zAIziFf%vv5;^#}sbm)yLvG;-s-m`?9S%it}9?&nt_ z`ps}I{aLcZ`u)QNq9&}u67*xoehW$1z7?X z_mK2?Ya;2Pd?`dadDZw%Oe}K${VNWwMvif(Na0hu{ET9y1Ipa+`NBOKyxo7|I`1m^LoXr z8e!ynDhr_QqDCHZq3zd?w99_8)B&HL(D*dnz?1tb+^=7IEPMjZeRtbNB)jqPxpgHF zpqNCzM8a@!^z?+m=3%7eh^l?<5^8DIVOKy-Lzt8mp~6&x@)|yVJy3)!-{S>+`q1hW zwwf;7YZIqJZSLT(Kr_0n&f92hU92j68=~)c|0*ANK47r9;Nu~4{@;%-tpju>`YI(g z75@YA*|!K2b@r{P6pdQd22QMXuJO@I-6pfmhX)$aQoZ@MiAiOQTKsYIeHA**=hdtd z$?hEgFa1M#@55&h=7xG(5GAImt|QD|vKqQ=UmqrHjH z1kqt;zUI~!|Li37MK=w-^m}b&emL)u{I_@S0<-LsEd^*~`0gpn^_Z7UNn~V%4gdO3 zYSxzUX7Fpw!QJ^dct>{SK1HBg{tz>R-c&gK9dWj_y4is9 zQ2h45$luHigeFyt9PoTET(kMR?+HkfY{f)Ca|0B*ep))43C>?L`9Q*jPp$(k=M*`- znw-?AFyGn^M(f@X#EA$Yq(ev>>MWy&sX_?*33GkBfPC&fhfWn)T>oPcQ-p_eRn_{D zxX+7jr1-i&wLmv(PrST`NM+ra?;g2zmJ6Ud0%f2p6w&`>8_1PMltKm}tVxw=(7Nfm z@ULzj(TCdho}QllV}_KtD>nz$k4P*}Ysr$$z!c5(%%6T-U>OJ|=U9Bpv+Q#$Zg1&@ zj*m1j(hhnjJikSj@g?@r*~$K+>#JQ|By17u;}}6ZXY`1garHv%c^r~t3Rzqv3^)b> z(iRnllz=Gh=pEYPg4NY03!GQf#p&Cf{LGk`*x2NEZ|;#qN79nB2vt$9HhW2+`Fjx< zJP}rHa3|fruy~|IiNzG%l*sVc!E$rT7Gw%UBU>Y|b7V^`5Z;IdL14w-GjKHX)eI`8 z!fQ4L`1}LC^{aeLRxA_-;7oBh5cYg4`Lw=(PU~9}`0op-{eI~<`}4n-jmyouXHJHy z3YO}v&&Mn6Kb_W^#(j)hmVmab>*7Vn6~T6|^Wba3g<`@O&#H7%2LtLDwqFlwPaExz zr?j~MfU(%xssim6@Ts}ZW_w8juD)60=klb!v59*?1i1$2@SqyE*&N^jgfn1x^A8Ka zy9)J9*!TiTU8AeDVPCx?{kakZuPZd>0Ai*pRpYc`W@cDtr4r3XgvRm$u3avxuzZg! zQ!*{x!GA>n(&fQ%7_IOV|~&pj0F#h(iRhvxksc4iK=p0{f#C$81lFzNyrhg zvgtN2FZsi4+8pSIbvj%UbY7lin_0&s(olNzZ)c74&1Yw}T3^6ZFSm(+X%oEI_QUwb zsu9gr8x(@45xssoC#)8d?YX_vFMhO@>EylhEi5!R(58>$Wf^OvwtDM%_VM4(J*L1( zV%*?qbT|qxx@AooBX(r<>j0r%6(wClWvdvBm;O~gORh#nMh0Sk!OTq;4XO2fht-0S z&$6#I2uY~{Ba29#B!bP`^(s_f&F(l2PGAC^{&lj&`AO$5IDJqUL^Qg&@-#5g1pkeM zACKEfB{D%y-KTPt!LNX|VMDDBdS6Fst7|^P<+l8aL8C$3u0vePoYi_a;Q;+>Z!G;H zg2JAt@CX|at3$6g6dK;<|zJWoE+|)0=wuAL_g0_z<5rPLyX3*KiMyICj zF;U=rd)aKf#4j!&S|y*wNj;Fy%teY3FI5{A5y?ZIWDnB@jeXndVaG#q+Z$U*Zl%s6 zVn8Ct#nF0c2!$daga>W*mu*?>ih&ma3nqIm)yN2T%6A4h#Iu1N3(iwss;r`>0~MeG zMC2+AfbBA>JWe934h#ao<^aH)$o2sl1t(O7j~;*R)Ojv@kAC%RGJ$J5GM|T;5?ouu zKr78UWX4Yg+tw;tvK4j*-rC-tdrZJksxD8%OL1`+uP-dvc>Cnz1oQ~IK&!<~ROZ?B zEk#2<^xE-|37usMf{twf8J`ZM2zjUFB=K~^@=3_Se8O%zqWz|b8z9w8PqmRxjeW<6 zdgFGooRSCsYUa8V>4}98i03zixi_Tvzb;gqV8=eoQ;v;LH0aaStJJ3l(&u+$-+8{( znRdar%}&>veo)-v^DfpcGC&~kop6m>YP$^hV4t(JRGoyjsQ~#qiLkRLAzGX8VxWwL zQ48PsmcCX#J3ZzuwM9doQyHFbvJxl-VZQwh8G9*z&(;OtrKuc}r&-e2HXVE%^_^v= z8bp9!K)QAvxe!uqxUho$#2abaavO7dw79$o-SWzguZb7CqYVIEyKVE9A0ny2-=WV)te@lZI7fm|(frwp%D&}kH)DcEWpPC|i0eybv9#9xj zx|c!da~$<1S{|C9MT7*=oIL$ZCC%!qPP9e{7%@c@;A&D2rl zf7^NiAIr|Z@#Dg=f&SrnX|Xl9{qh@^kLNK>EX=c4$rMK-T8;tE`N7&Uj7S=IUuZ{$ z%##>e>VeF;Yz?N%j7s+q)35v25mQHGfY}0&cL2`IZV3>ZJ#04uI=jx!Cabbr@TlH% zMl~S7P3UhWoiEmDTf9~zz(6k+2&U$+Iu405uQ1jPS{-ch#?(XhEknRo{x+P@j6zNoA zXpoQ;q#J3FjzMY=1f<`6AMf$}1M^|_-dC*kTj$BC1;p$N?vE&i?hgj!lElwG>uGlF ze60Od_mDgpd;-iZtPI%7GNbx=i6Zn4-;Y&@loGrSdWXAPW7=-^x0kZC4~XWM=xIt; zto-h{s15~Uu$^@^)W;vLAi27KHRcgSmOgq%7|Fp~N5d&DcUDha9+b4l=N0i>ex$6* zpE0V~46a;(E5y_5dkz#5-jQEm->_F>I~%@OWS)Q+FvS_Z;o z{zfo8_9GQ@{4ODqBlln@TuI4{{R{5(?OT?pi=|@FMBrfdY>>?}ylg*{F?CV~9St5V zl)XJNK6RhALKeDktcimr=)ShqiMj|F%T+ml>dk89)?tU|Qp3(OpBU6WryG_@`u_Pi z9NMInnV!57>WZ53}SVO z6?0BPaakQ6QR2L5*_4UbJK)$@Cf3irN8H?M@f6_WrN;I-w?KNXKe+6CX_Xv$NQ#tP zzQm8P#37N-RB05lw#~!O8{bh_!fp?#(1=)+8lSmt}K-gDs_PhtYm3 zi$Gug$SEcyWJ|uX%s!TsXTF`uu~soyT-3tgj(IN%VW#X*iuCP91_xeob=*pzsw$_= zP0kKlI(A=1)3lYYW-pg9fi!ZZ(K2PmehDZ2E7cXyq~Ww@=4~9}R={p}$-_7$AG4p^ zg9r~R{+^mBel{eAYAsPF9JG&f~vns z!mGytA@HB8g6sH={mr~53*K1xwmRBn(Ey<<3Ht}_O3S+Mm4x$~S|EU?=R1bFUc2h@ z9eAcCahnS>s4=;oe7u_kUjHYEUnB?($Gvd&6y|}O(;q?x-uHVg9T)U#S62Wmvg2=p zyGgz0uD#TGmiHm?zE42J!$k4l3>wu5c23rM`=9(T$-+q&iTJIU%H?8R1nc2s+YXIE zGcGaKuUnOD47_laS-yBr7$Y4}tsILDOGo%nF<2H2Y@_jN7+^AZFRh)cmZ6}{DwXdd3R|jx@p&c&}^hP zACUT7-|Ps=7bo;XHDH>LHYn_ns>L@c>w+6uUdEzB=jj_Bj@^TAODd}C9zpk}Qb|UE z-&<;1dx_btALr_^XA#fE0$Fl#!VKD74{$v*Gt-1U;Zx>s*Mz!( zCsxTtV#)s;Xy;U$eY*^6f}k_>P^-p|{kPUAJ;V&sA?51)r~BH|&mBofTO`|ruDpwjdM1V7z>9av%p4F> zYfRpZKsTAQeT(095XH$iVC~a=+^ID~Bn>HX#x29`pxAawmScfj1LF6P2!ufTYqS{} zXqemoHuNV=lh5DelK5dh>Oy9SVBL+%fQp%pkYTV-flukQz60cdTT67{x;~?$C`8D; zSXnhU6U^whd^vR)?R!kbSopKny?wR8@lf=OKFn!=Sl`nom$uGD42{{I6&E))%oZ-} znaq?q&Oc7Nm}54c{7xH-4}WS!&=pd=fnEfgcwu?=01dr=vwpX?(0yJ#8X5qk)6bXR zBn)h8w%_Ktn}-1C*o#{x)IAV1@2{+BJG%-&eeJO*R0R@p1YPH=oMsPapNNz&GWxh| zm(crmA3TlHf$vOF4u!!nKt%yPKPY;KU?x?;eY+q4`8wh$OjX(k^n`#a|Ep03v@};? zh_T9Z!{^~jQ@{a8s(mLFxJ3ev#4Q!p2~^(W1jQQ@peSTt5Ihf@r~o5p5$>^1*~)SA za$Yg?gSPrrDY5wJck9H!t(da>2Df{eg;l>F!)3X5Wwn00a|=!4 z-_F+BS+2AVZUM5-IqdA`)G=_d=F5Fa|+kxR{jJ4h#si!H9nJjms>GgdvdOnjMN)=d; z6d>B+hsrXDi!r1f;Y1OW#z7)NDQm4439;&N`<4UPbWJ4B7P zAd8P5_S7BwtgE$Ts*<9UTvwQ2k1^sK?HIN~e_ndb{U>RP5j@-*(S z4;$xQeJrmm5A!pDItip9A6_(2tLqZQ{u51J|z+X zIeY|6>xndQ6&pT4Ywsdtsqunz$K}JX_vk6Gi3p=e5&wDdEh0<3li-&J9q=%{cq<8 zPqo<5*g@n);(LFzgdgvuXcp#LYX2n?06Eg2ejp0*5^tf(GV((D4ES@vJf9^k`V)~v6+ zyZ7z}q)U_QfEV%d*f{uEY=aA;9f4)}yzFa@-WIc{03U3*qU`?P2z^RP-0QA?K(Exx z(SNfpA=)h9H+9>pCKNh;%ADvRP8WgT#zETI+dW>872I44NQvDZHQFIdu`Z?(qJel` zW3yZEzWeK7rpB+!w9t5-Smv)(6&>(7y!*^3qZcv$|DLaCSykzhIzQ8RkrG*HI7rUd zsQy07NVrsg;p0*b4<}!lK3^FX=Pjy@&KPDgXxQ(NPVuzjP;?+0S5K8^ppQncVXXd- zpNrS*P=%^D@CGT6!ff`a^x}0QtBGIO=_h!*YIwxzL|IqKr+UQZTB!;;m!=EXmuG&; zqTq!l@GRTd>8jlJQ4N+jm_~)c8)BwNSwVTirx8~1Du!G+67;(RiPqRJFe9FyH5lny zQ7|#)NQndBUVA=rp6AhU!*H@xCE4?rI%ql?&9J7mwOhsarHBvZDrCRT;Mo29-VCuD zxh;Cuo-`GE7rA+g#P6pTkLK?y1$Hm%g@*D|@6&{(BU;|D*f%`?dF*v8mRSMf6ABb! zkF`SO`(wR~EoLL&g%n*K`{dxd1|SBuryU#`qkmJ80Usyc__3Lx92`CtqcC*q)3O~d z*ZX)m7z%jCA5Ci)0{Nr7&#qT{T%nzh?{DL#5FFKq%k$QxOaJ7HWhbE9qM7|tac~vA z;wN-q++k&}jQiBgaSUcpehhXcVlT?1 ztmq=JBP`iuOVl$#?{-LVr`kfq!V^qNies>JOf~hAsmQ3TKIXi`g3_adgi(6&f@mPB z9g+h>Ee4smq;Y6R{b=C;3f9p5S@BsEQQ(*B{QX?#pB^t2Fw{{g-$v)@8b!y@JP_dy zpE*~P9AZ2ZLv)phpZ7Yrp}Q!Bjd1i(A_5jnuTGZh&yN5%!FK$NLaRqLKsGjtxdzHX zE~ZJ0Ig|qaq4@aWh{Pdjwm5`POKAArN=!;Gh%0=afd%>$E9NL-)Nu;b+$Mj9U|_&4 zSFzfWdm=F=@>t{BaZbJdZ;wdm*JmXGB%UY0%f;r%z?=HyyAJ${{T80*ieG;~K8Fz> zQsoF7ggDPpS+}q5rKiqllNU=XUt(gP$(zaN-yhj)Oll@XmjK_jo1^2qmHA`J+|VA3 zCu=SCS8iIG8uz6PWAonG&7T?+YRGmoos=H_DA5NWjtk}a3_JtK0P_;Q>#(DGt=ycP z+m-J772nRo(9h|)=komiLJ1w!h|aayO0)B2AYOI+9eC~sKo2Q!3z)b%ei(dm7aZy@ zJ@Fn<#~`A^!X3m*MyucNb8tzs>_jF3=irO9@Pu8gkuk#XC#cV6LvW-+magd|m3`Nv;oz>E-&Orb7B&j}a4U^CNzm zF;+mzE-P2!mad+kdyz_JDo2e?$c!w~1^hKxMOb;fc>MFCOUJjdd_J*ymw+%3CNW!9 z4@g-1YjC?=1_&R-Ufyq{digkhg}dZ+h-qf&slAA4QzfabOX0n5tNVlXgIe}`tT90N z2chtIb$8j~TS}hw2Z&ISicVyPX{_((qBOjLMO{Rw5gnJ-vU{CAN$JNXh_|(MofOB# za5NjMhpHoXPa_I1Qmc!< z6tcf7TdlFiOb!XPNGk}>{MFsN=P%&Yjt?}4c5aGsj zFzmV@O`qi9I*%_BIInw^fOLj zU`U0nF{UmtKeL_^`BeYhCBQ`Bik~+tnh{4(l=^mE1Th}iM`u31Wd|9|jsLNg`y;nK z-#raoc%=}T78n0g;I~=MRga-HF(@)C*Ewi?j9lTnGTRR5`43+ZNWWe~P~9%Lb?0nC@@q836zFS&IH_xkZ9KIx`v; zvy6ahlZY|9vT9=P(iL@*BAC#NCw+uFk$Jc|--qt)BO1g(?u*6>1aKfi=YW%Scdcpr z4FJ>IZ0Qc}AN%W7E2e>adpRDL7@${~k#QArDo6icFEwOJ=CHPP3t#pVY0FC9M^1xx zRfmY|tb8Mrx2m~z$UVgpOH(CES&y3OunON-18l`>?b4D1&($GA)@V>|J3-hui7f45 zF>Y`23?Y=K%!UIzF)=22o;4ZdH+hl}?Pk~*a6t=1u7T4x3b3T3?#u#RI%3{IS*cAx z9?FHWm{u-K{7G@GcH`N=z5o0-GS~aM1t<197a$p`4ZS~HyFa<&u;SJy(@9Rnovlw) zfi6_NZL+`mVJzr={gbkbi>C95^L*6{0(CuUoI(r13Q50cP)2+ORXCsB&<;0GA6+)i zF!w=+xsaI`!&zSpD_R<8pC&b&$y4FqIyqY!Y`)dI*>;?}^a?cP7uVKH!Sf=i`Gw=G z4#{OV?bGBc2E@c|$K*UqY8~UB02Erff}F!M{MuqkOeo_Bj>3bRzgiSa$yJYaX&D-y z`g2MdY=J!{ilyC!Ty^e85mA>jMQ9)47+O!3wRkyG(nzY|xm8QOs4N4_dFWr=d;825 zP+=jj%141WlCtr|gih|H;f=82OD~A(ejTGeSd@T?=ST5}k5&tOlyCd+jV+pMXooBo>20S-F7Vm|(!ZcpbAk|8>Phd@FYpcT?N>u_1Utp>JKT()%EO*s$wSr)KSXTY2X zH$)fNIH_m~wKYn&RkQU+bp=O!dHDN_kib|%9m1?ahGXubzM(u$J7RJ2nLIp3G`Hk~ zFBhn=cmACi65+&*AQO@arqY>Tnm70~^P*7)aHN^txQqx~Lze${d7-nWW^m2>%~-W1UEKG(wP5e6tva`l3f=2k?A4h$ za!g-Vpr@LJ^*l^YO~$_%tiPq`q76AKgWwg!3h$*6$(a%7^ZFtSb?oG%WdyHUEx74u zPct#*tBrlP6NCt(?|sUGP9Ja-OTgs;o<<>YQ^_G*-`ISujf5AD1YCUE-PgP9^Uwd9 zn}wRTh;`Q0{Y@_u-vzSGzrH%AO`DwWgkL*_?#s~!{Y=X@X;x*fLbS1Uz{qnSFOGdX z_WNJwXXoouL<4%h=WH%N8IosPiRY8-R595GZ35@_bR7&%mUwYvN+hCx;vT%S(#-0~ zRg7WoWzYIYa@31~27YHX1EX$H(>+@Pq|$6jZS6BRa{t^8l!E{dr4KK*4~iF4Ri zm6QIVF#&hy%tw%#pn?P~t{9!bkc|NRHZCg(ti?Vz?(-A~Kvc3>G+ePYDxq;PtFug) zhk-b_cBG-hTS7#nuyU7~3L`f?w<$cCWEyrvLoAz!JV=K^^I*sxLLCD#)~DSGPD5mW zUG{fUE>wi0S(j6FE6tfGW2T%}%y?a1a#JNvo!0OQREc!XhRf(+4Yjshw<`V^)1iPG z9%sd{Hv@$BcbY4!&E*K*;%ozetPQNp6r68--ny2=i%=d@RsqX2nxdl9(~ky~uCz(z zr3h?Hr||CVH(Bsx@fc~HbQs^vs;2$=T4#yV-95b-V4x~!^cl~7d`tWA`0uW4gs*XN z(d-ShyZgUBIO%lr@d_f7l&LU@u=&^5e#NpG8HS9IQ^vWPpMNa4xkl%Kv4OigAeI)m zXE27o(c9bQ(@q2`{^itE`HsSx2xO}xc>kKs!OHBLm76eCb~h$lUnXY%?bP9gXr5c` zg4pFEt6ST#4=A3!$QKHYfkV_UNpb~vDI9!UiykU|k4K7ecW--})LbtP^vFipt--=Qa%2 z+f>ck%ObbPoYvf;}`z- z$myj;ddPDmJ}8-Fy6Bk)b)y$#{HqIZ1Es^+OTvi30u%3xG++pP(K;#gkJ_uYe_ujP z5^ezd)r>9u!#*&O^)~O7h?3%4w36=BSi6&QgdFbpv?GQndQZq8KLd*BdIFTkv!9&( zpg80Y8bg)}xUg$zO{!l69BY2_MfK*a{{-!1MemnhgkB;;Lxx$U zE-DZRJ9~Tg)`y#g$8qB%(Sv$az@)K3RqlVGN*9~jLs7h16CPIlxWKC{wv4K#QEX#O z5Y!YID1)1NVUfYUKNLfT3HSC|GdfHYc8paVBui<4Vx!*FyuC_MYzo+s6IUM~MP^;xm*`>MPbCf{%Lj};FwtOuUEO9pE35pF* zHilt4N6ICNOkgF=L=y|dPM|ouI%>LH6TTmFKvi8F$6ZWM7+qb= zP>15O`{if@)v1RdNrcy<3H5gAUc7L1abR`l5!{b@juf|6n_v)HQKVLOtF(rY*frM5 zphNh16i8+2xG=Em{ER@-+&=zhwM$G8h{alOWFlN1Qpk|`mk>85Od3-sMY=y|Jid}C zVJkr%+_+}MUvlGv5~-zDSNh~CDf6&io}YEg!NxAg%OV9o) zS+y)&{}zyX8B~6_JTz=;6w8f95+>)=qy_=_iVC}i2_p@`07^FZe9XSesHqKjWx8$- zQ0CVW|78Km^1Wnzoe+F;hZh0W#Yb14)^69X+}1i?kU!I8Mgo{$qa=v~_~@&4z^~mY z7@vJv$QBMSO_$+Bvd?i<9Td&IvR2=o9?H!qE3+g2`SZ+Tk)Efq*yk;+Y(%R->3%MK zBKD7-x|!dQWPv_9M^b#=X|Rzi-NHw83sF1Jh5U|5EEqKA!2KFGjaCJe9JkB#hG85t z7l$QKny8}z>suDKmX;POYdvjJqX$pfAx@gYd%~U*Tdr7I!8JZ#z6d0u&XxX0v9dG@ zPm6Bt;?(@{!a4tDw(LK4>dH53BycMt%m3F`8**IP0t|AcNg zHutrk+sIwW@8SW4cK}bf9W_ zh9W5;B!Q&Sm{gA@vD$Kd;>r~DLx}F7+1I2EU<`4F`t3$hcGcAs*Q2AY#!@uW_;b_5 zS3W>84qWcCq?c~1R*7Tf6mll9Y z_eVvQBnqDaQ&Kn6Ng?F2+~vbZ$IHhP-JzF_s{d{lI#2e@S8v)Dx8q@oWx&l;1LhLQy7v&o$6UK(y;G7uAj zC<*d&x!1BNxMSc<<_XT{;?fW;I_7tzFUW7qJ39Tp+Co3>i6Kp#k2@#7nf`*eP7CqN zJSk>lv-*V35&kxVw$y=Rv9JQ&?u(j$YMjd;*x*k7IfmMMIJgg!M7oriSN{y-d z_c)>TUc?^N^#AhgC?Ti#0O%y5O@ud^NvZE*;9Fp=Ko05_kg1Ejes@+CwLBeX8W>Sp zzjSeDp-qm}+%=M(Iu{zr4B-)+5X(@O?+jT_n{io0_Qks*q7%TfxEeHu9i_z$aJd}u zqHvbP%S2I#HH||^WS;>WvmFhkfwU}xlA_*=ncAhv*Bm{mqA5oiHi9SlsZ6$vf2+^O z4Tk1Z_i)HyL>u4npU;5UNs8oT6=cw$BWX&YFp}7v?1(fR>$Kwiu`w6md_FgRu8<6P z^Thdo@+X8VYO>q@EiJ#cJkH#r3WT@T)p_inGBS@)ncAg6vg&7iN*fzt816QT6qcxp zIg-!m4k4Bgt|-4-oQJ)8WP$I)W6`01h}+5Lx>OJ<_$nbjo~H5l;;~pWO014vK95QI z6DK#n3P-UL7MhM1+gL;Zw`7-%UBIPz=w)0()qL$bkoLR!Z}tdKX&H8h1h4W>Ow+ck z*I(C&5mji(dz-$2I=-qXO%!WEar=}i5bzQBmvMNz*p=BGm_7F3(1E_!*H3FG<^3xa z>UQ+-E+@@S^EW%`)n6RwYh@8sYP?#%9zn=!ay((c=A! zTP?r4Z2;9dCKGzv^CY;AOAW;RgCCSFKk6SH4nX;Chm;9%-be0+`OH$S12 z=67wtI8{oCOt%!D*gC)Cp`7vK`R$rH(MJ|5*1{LtYLeF#NskYkQg_EVlE0oEhA*}UT=yio;|T;(_;MDH>ttrEuWtWoeWV-6n9^uj9NzhBLWFy@e%f(}#W74R zgKMS9-W^I|ezzs{H=y%V_tq`|3OR^jE#T+px2k$lA_q<_q;f|i`JNJkJi@5A!1i)D zNaYG`#1Kb@IyHB{f8Rnryz`!Iw)F zM3$Z_ynRVx+n(IF7#~lF7KT<#@i9ulg` z;-apxkS0sNWB(w&@3_lAJ0?HP6titiL*e0h0gAyD2#(UvNz>LGVMJf&vRSn*qZRsE z_}wAHNyY5qJb};Dc_D>6w4?_5yIBJNilxEL>WZ+_7QHO4ND~u^m5*EyCZ->PA1y7J zqemh)OzQl8ooIhj__!23^%)nEmsBsTTr>Ye|^!G?yQ*m6*c#&f`v z#+~+OExwl-AF~zFkD88J+wAi;B3~186fnM&%dlNST|vnh3RCMEK5q~Z_+7l$MTb&o zNN4ix;^n>@C)BS2jpe>sonI)?DO&6}DqNamiQm^p6SvaU)}V>F0xE^6WM8gZG; zeA`0+5!nbM(N(>W9)$#*=d9mIc}XyBWj7sO(l0Kch%Qf7D-mgFX&S3=bW!(WGW5W! zBWkNt#z>1#IFN^bfNAS70yQ~45pw`M$Ftqh%aav8-~+WC%?Q4|)KFL7SzvVT=&zE8 zODF30XHu`-n$^AmCQ05ah_}hi;2w;P{iUb#Z>@@La}#tiG0)hglzhCVc5B^?=bP}m z3S5INlWE=p!ZELLfrWC!6Gpu5V_NsnX#(?B_s0;-9X2yi^7Q5iloLBbrkgIZp$?oe zelR}zK8$C;?LQ8L_xX5tzzyF-wx~FtV6)BdpSHkzoRgcI3rsfA(Ya;s0f~8u&B!!^ zDw8I!pkIMWJ1#9mAO&330?(~j3Qk#YE`h-##7ccy%>894(-VAeJpx?WE{pGyM4moT zXrP@M0CznBlfy8#)^zw#WsLR%ytu5XFR{zuYHXVGIX!hqlFSf!&#TW}#)6`xVV z{d_EMA4>z8WH2a9I}(7?l4*%EVm=9b)k<`@aB(ZaOq7p1E%xNtq^H%C#URW?v_yma zYyWG*w;kh}GGA(N{-b`FXTBco#R8aPu%E+a;=ljSgx=<~qe(*nw31Qi{Q@d*I?i0z zU~ZT-FUaEY0rfC?H8A)oF(J|9Cb7kJEodP@>ei_2038DQCf;fQ(ZV0Af~>WtLmMuoDZX~FMLsE4kCPa$UpTn&27j6+FN*Yk3lu^oFK>C|%fgn6j z^g;5e94-G?K-#0Oe7fHY=?Ie&P5ypZpj5a%G+zyQ41Q8&)_8DtKKa8F zY$E8o%+JT?yFX78Of7fmu)pjB$D#!-V-|UR^R~r=g*h8{`E)X!ehB-;Be|6d-3h1J;uP_ z0Gkw0@3e=W=Wqh9LFU$}+Tl_T2>uSOphm;Mi!VE!_M7?(AQJrO{hRwWrlc`{WHtbf z{z_5!dl`DB7>hev>|muA$t@;E5H_o8>cX{`htc#knFQf^+}70YbIgI?5_10*(-0t_ z6*`6hmTAqrSJ03sizYNw&m;Q>C z@$RjOa?U#qtl{@Xjn#y{6L!XesxM<3V#cdm9^TsUl_#r-`JPbGn+G8Ca^!H?UwEFJ z&U!%&3a-cOp*?y=PgkSXxKbLJb0e;!qJZ&I#6jT|%eaOM_WNJIFus>~LFFNzgjLmi zFa=bI1MNxXcev$t!;-U{!Ja^b8=8*bK;H+;SGuXtQ84tUujm~*E)!rcZ?`A>Z4_dQ z;VwKbJMPl9Xt(z8@tKe2o~2!GcQ26pRTpw^nj;iV5?kDHe7W*?W{OJGXbhM`0B0w@ zJk5)YmX6~LV|R(iUP=>>o=USnv2Ut?3uf*0jgTz#eR!cqY;kGANItq6%4b4mo?ysc+!3W&%^E=*6Dr zdV2SZt-V|}5GyV>c}&YOT6oj)+8VP#(>G^cMWH6F)V-Aj2<Y(!!Q2n`6b#$fVY zF(>K6)e#yT+~VRlUw}b9pgZf)6*OLH-g&WEy$)Ot*Zi-)lof>BXyc z`lNgFC+@*J0K_W+mhlhAd#2;j{qaTt*}Z=~8Tx1J$ZK@3LB((lJ1$&~)rp^q>e;jV zhbP@FK~^u={su;{2nuFs(X0mzzj*TNu~5mp>;_PYteKlU6x4KVr9D2lKV~>n_Kr{j zk?R;#(4kV2cmqa?{x@7RBivjjA%5{xtAmSx#kIi?(n{zS-tYrun22L|TZRet@K0Q^ zyb)$vPJ=4pKYiOkc9n(2fDSgsv%PH%^r&uguDU~4nw9h$mvMTA?AlJ4QZkA{w3}_5xL! z=m>SkW~utn%Cmb#-g!=V?$4%h#x_(qdkjIkaL4e-iD^akp)YieYw%Zcs_V)XPw>ne^H*An0J2Vu=$yS4~Bi^ z6W=t;X8J_&2v{q*UNWzwYbU?p6G4!sU`L=8kF%fUjB$;q`>#bEtJcmby_y*Dtjv7R znA$U)Dy%jI-Q9Q}9Jy0Xf!!qP38t2Y_sUN2f9Y5>x9Kd;Gc87UIK`>_4$~t*52Mlh zAd!{7L?eeYvo~+- z-hDQr1x$RBD}eRLr!#e1#3BoUtJHFqmI!RA?A=;`FwF9Np1+cQ*p@pX^78?%mEcvLJL`Z}R3qDtMeC z_u^(JxnJaym8|`bHD)WLFU9Z=0o(y><(_eG<&9YxaaWenjSN%6`e|ha#Vm;vw6)te z&ifQx@$#%+2&73Gt3<~ttICr@gTT7#Z`J0rzbd#2$}o7w;y?T2jH|vk;I9OaVFH0X zth}H4IaMA8>9WJnt?{#*m5FpYS(15+rPaYjralqODy7>ggq)bxOyPTfu>}4Y)HFQn zVNuUK1kEW>zHpGl<@z&5UIB+kihR|eT7gqjAH`+*tK&r6$kE@N4iHh(w?6i)pjx+W zUkCo?8Kh|pzO9jHzmht6mlXQnOZgf<}V50@GH=}TLsTegaEky>-NjEBV^x|$k zgn|*I&4x%VugO8+v-5zXw08#OKgVdO@)T%i>rQTIet{mm=O9#?^cAhW$6%YqgdXu8t zXQQuBUZUomHvWpOarrcH_$c1UOACBOd58NQY_* zX{b9|yk=0Aq@^f2?Gd3oe9OLVW*xgH>yvL4YjD*J~x9mGka+KZlnWGD7-Omc$3yLs+Pn8obWqBn+G>6jR|;XbKX#dJANu zpHd?rk#YdORWj(`j-KW-TH1;n(N8j`3p_Y$yg!U?#6k+5ZR!F{W)#ae2UPe(&|FW3vA#adau< z*vhl#DQ?n0^*rRM9+)s9>~iYO<}EW6BdoyTe}t+QUdnDX&pi!mIB3m4Mi{}-nwRRa zSEDwd(x4Q>K1S}!`YsJN3^*QDOwgWHGi!`ADYjg0>UD6Q(}Zy&drLwgKD|1O803n^ z8i|>XF@I!FW{EQ4E$K$QQy^#7yN0H*V1m#*F$=#Jx;VRF93c~=!LlydGn#=xxc&bP z8wZ{M+sR4S?YMi$Hiq%Z`dv=DX6V*4)ML&SSxtHy12&5`ZB;W`@EY0^m z7G1bF-4KdLi;gfHOsbmRxff)^>MJnwy`SCL`SQsWKxUK$pt>KLYS%9hje$sBs9!Ho zTmTdjT0DXpdKtSJ(R6EP8yH-Y%u*#XDd&^$K*UQrqvAJG>O!Y5BACnqs%!mP?x z(E5ssik6m)sI!F6Ml)Wj#aOGpQp}j0y%)D7KfVYke*1A3sCwc=1ORoo+Q8LA*;8Ui zJ76T;XU%{8*k_?e0yqW?$Hv5T240poyvK!NKCNDJkflWfYa9ekh_xQpj9=zHqB`@B z8`N{H^jObjaoIp|AO?cU9dT@C5)v;#cg!epuc#nNo2H7)cSs%rX0c`(k@mq{*ivGl zYW2z@&TGY5knY?^;5q{vs|O~5AIIz^`NYNVnx#T-y%+BPuDiGW21Y?Rf|h<03TOmR zE7S(=@fEPMyDrvQhJ-wfyLZ_H1hgRlw7?i^lH|euW)b6U>v4f2o$W{vDSH3r<`>G2 zvpHKMU~gN07aYsYyq5;3Le=z^}2L3n=P6_-)N zjsRts)9^n-Hre?4O=b>!k`AH273gdP*%YM1X|T10dNeW{CR~S2E?le5br`Cc_ONO>hZR0H<<@k>UaSmV6C{vEzUYZj;eb4HzGM|WdynjNqNKdP_B`4#OI_R54oCBxIwz170t{hs?n zIX)pt49IJm@-X6)fl7WTLP02w0~DW_cp1={{!?Hfh!4~Eu(~_s*EZebY?;Kxf16&4 zl3T~w2q$pS)r&1zJ^A*kvK`d2``Ih)3fhjb^c6DoaIeF0ZNVbmqP9jK z@7t1+H*G)spn3L8#A}~~Bqr=hf9xD*FgTkkSjP{?o2;`%ld@W4Od!4ds%K2i$WJ+} zbeGSinp-B(oR5TEgx9BGmHw3<2{EIzB3Wvzu7`mbBs_al@@1BK_8}HO{>)b*HfDcWjCeMgIUnb8?NYyf3@?Jc z_3Q7}FWc5oqnE~Axw(fvV&~^DP*$9LqJ9>f>U-K79Vq{<2CfWr z{UZOWW0S}|GpFDd*Z};2HgLaw=;Q6W7^;I(6KG!2iI+1RE>zzRYlV!Z0=JF)hreY7 z9$UkMw2i}o>x2ixfbUIHb1n2S7>L>K?Cdb2Oyj}IIi)N}gPOOD9JbJl00PhuO_m;6 zNuDwd%+MqL51dI5xaGV9YOR5nMW>91IZf-R zPqx>96I=$G3%f7Heu_?F>{MvD^U2q!UQ5~AbaG-mzy5?h&bLuAWA$(MWk7Rf$}?FV z;=Minj{+|xwMJaBNG!gy%agoNnkXW=aZ&gY(+P`7OQ<8!Ua5RB`3bjv+<jRc4pU^lfeyU0(xc zTqy~OPN1yElq3!mugv}KiG=9tEw>kkQWrn}h%O`ft<&+ch$1I)LS+3nF%c1w>#sVX zFm?aNJh!2X@8U_Lpa&T*WYnFdypb6oy%$Ek?f<1L}ZUT@rDcscM zX!H?@j9y&v^R{divY{bG9Cu@5N2jOUAeKEUCWuFD*q)!FtjRa0-4jzWu;uVSQt-2* zmB|>O-1RMZFp(tuRrr!XsJqMS@Y0w(w}rpjHqN1yk@4Tkt#lVEYahx0w4ZPAChGA4 zR`7TSFx(SGPWIJace)G@E$$Slc!t4yaGpN3)uICrT~n1@L>!mo7^aHA$L?Q4u;-g7 zN*iR#T}(5mo$a1B&tXd*T%eQ4%v^&wA^ptw7KMz{kCYhFD=DNyR(XgCoe`dtx_>yi zVDTf$fulSOkeJ+2;@9qzA-wYGDQJhoR<{aOsPygrF z)(}!{-JkJ>pp5x{vj%u$gy}OCxU^-nT>*CF+F-mQkc_knsZPuk!HZiVGExy<@dEU( zARVy z9#(8=RK>y}&-tH0`tFb)AIw)hN7sPs+{3|K9)eFuEJv5{eRgS z9XXXzR^B;213OQnhDbbJ^njPb=>(aRuA(gdL>C3RFr{JU+rB&jSHandQGEp^V(^<< zvrd;KUTu%Hj|wSPo)as9en6Sgz4PLYy~J^qR_G1zH=nF^9s-2||Nc?)cbf%f6`V=P@j^>=rjDi#-|QD0@*s;Flgu!V3OJW*X4KT^%+X zWA?9|b{X-_4?3Qjp1l;(bPJ7nm#;>r8?z~g4Q>se+VWAAD?<$i=|fF){%IPqZ9HJ$ zphj0D31gyw5THEBdH}RKlJ7M z-|K;IU1Chqiu2NM7R4B}N>ZvqAx_zJRC?M$@za64Nav7E@PMLH3v0!p2(yr&s45WJ z=w?$Rd(RlYb0^w7%RzVKo=-;JD6D!-1+PD+SXHQ_7gaWbTn5g{acud%-kr*!FP6a-ka9nR2{HMXIl=Lnx&j?)mw- zk7elfsQLYbZ|x*cb*;6|^?sRm1Q5k1WNDr@Qd&HQW-2HIs2zt!8mQ~` z`lqdd{>GMj_SMJz*`LC{{a16I=B*8Gngo<-vJvDk!CfUK{Ci5*2O1!|RigLjCG@K| zZ8uEH;&%fo^`fHTJVx@pN9dn(P@E7>J8o?;_2DN0ww7 zN63TrJ8Ah};WJSL8dlk_2I@6e)&z5etWl0Aj}3Pvs`(1Cfi#yf7qM&Sz6t$^a964-zjx<+{z%ud2nPCjM9J{@3wO`9F8^V}$p&bx+Wt4dn_{B@qO7iRuvp zr~TpiN#<;ywL(kM)Ba>T$d3LN-9^9RCgbQ{;u2BGUHgEiJWP;DF?9v_t0d?`ewiPo z10Qq_81I;OBH$8vJ%=qm*H}5;r$0Eyyk>YZiW={8+Js##y@rr*?UwIPffFzQmc9*|xVyU`s;=*MEWD@2h*P6*T#6BNUr%1WrZrER7-CI?iVD ze1m~q%o%TluSF@kM0PTX2^X>dWP9Uk*0I6qpe{0}?dUz1Z}-8xUlLm-?dQ+U+Bl+K zEHv}0su%%c7>%3FYOCYFd*Jwa?|oCQ)BIU8?p>9ryqF^q^(%>*e#(E!=^R+8M?SOH z0>p!e;qkwsoppM&S}rYZ;aYn|iHDtr_$XwTXdH^vkfh<$(c~%XNNr@|6W=tvNXM+N-> z?~{)4R5`yY(>^g|zi;gJ7?#4g+% zW2o92$kRB&*gE2egMV8l(z=v~YdCGfTBNRZesF)qAd-_9VbBTb@&ZlEdK*X)Nq^PQ z=k?AF?5O(Xi+)~0Nfi)4XrabT=R6o>iwBZ+sK>D|{}<1Z%u(O9GgB#F@i~tLQ}s7c z-S=|ud*V6CXz#hRm7;%}E)KNQJcz$si2oN4@K|xq5#fCY)OEY(-JUJu#8BkRQazrOR{f9UOnB_N1SOypE+mF_s-XC(9YtR=>9;q(u!vAe#DaUY`IMr`Qr;NUo4VKlMpz@G>|s=M zI4RdUVff~u2%`j_78Hy)B)#h*oa!111Dok^F?|5JW?@oin0rD1%f+u*m{?~BVT zuOmprC@rUiD3M<{8yuJm{=tCIE4f@iCbFy?fq}=7w45E>V{`H`fgFVXhO6eLEv+)_ z+c)N9m7b}~hbLfc0rqO)4pCJsksrdCi*acDrco-TLh{hFzo1J>q)$Cw-sk9hFMr1X z{?M+l2f#Z43@SW0pS%@<0Lx_i6A*-LyEBi>Rpy?T9xA99Z&Mj<7S*oNKsg;$@!2o{ zP`3HfE8y`g>wiMVBeePW5y^7r=XKUAkZDRu;m~6C z;xnjh%{U1ZfSE}U2V5Ip7TZ^mbKB5qRiV>A29W&EnN>tK`dxuMrQ=GVC1M@c%(0r2 zrBH_32w|Rk;@x~vEFqsISmGGx$i3KVUMR{#^93CnKl+d*}FAM}gXd0UbC zEQhW$)?Uf?s-fK)8kzC)dg>BRc8^yQHq+mhDO=xZ2R>X zuo-7JQ^VfZPBd%K70P2O#FNs|bdx24OiU^1ex;53$V&e7iRNkuzh1rw)Ukbppp-ct zHGrwqZJvQod*ZWcX|vBE{IwTZ?pvo$6jcZV2J*Y`sOa;cqYjW{fjl;tKYj4Kb!2jF z`d>=IbR;Nab6Zq;c;bk4`DWL~uC69MGqR!K5E~)L+Z-W~kl7a2k|gpp^=DYYL=A(E z)=&XMPye${MJx)TshTz%zB$hHk0VN==%Dtj)_Gf(-n$7#D;S2MzR}C-xnb(%1ffGi zkAW^oy6oS05AOj{=jXe(er;bTt1z)abRob`!S?*L^X!Zpd^40`uRaa1cSgqEV!wLz zbjtj)k?Fh%SKb-l)YQ2v`bx{bDqTl4XUXp~pExGs1*9ba0PQ_6(=Dm^-fMu4Q%(47 zmz(OolAkPD0EtClTh1zzar=DJF7S^3v9Ro?@IO|SyGe21X$@s@6DzMKmI$~8RdzbC zjWTR+m(U(oR0&fpAR5a1MP;U=WhnRgzf7u?KB+FL9Xiz#NFNNn3J2q<)2# zU-1kl+vfPw!LkEeZ@RnbS^4FNOw^6=F;?tmkkQN|F$$U;H8>)-}g?QaqM$xW)}C*2R08E<-NR@Neue9DFPqj+Rg%A(iDH z5&gq)clyR^6Trc91!CbQUg=FNcNq*3smE^1ti=Sy*RCFXkBNFZ&VI0K+agh}f(tJn z$3}edK5{L(y6G%V)FeXxpvFr^<7Ih(geyjyw-WlCs}du{f?lfZ8Wn9_!>4pogxLjW zP3apIl8EA-f7nyxQ?QiOwPk=FWCUeO<#(j|qIJaUs`r!Jakl=*{2bG_g5RF;LYdHi#G!$AezKRNs+vecAg2X{MCLK_QNM^Fk3tW4L zQaA-F2th8*S1Y#}u2NX-= zL(bv+{L<1=0L?z*ebU%ou3+vs3eAFl&4a@o)JXC&)rs(3V6bg-N1U_?AKq{ z=4Ivc{xVRhw+>(udhFa;zT3+A2Hb@PUc6ye&%g}U<<=DYKDE$@>$?`L5r)%xo>WOlA5^RTBA<(8=U)4VQg-_Dw@YMaeP9fpap*KYZhVosznV%#Oric&% z#;4-tr&!tX_~R)X8L%xejF~DW-(kctqLea4TH&E|!pjAFi+%#d9x!y12v(*YDfD_- zq@B!ou$p2OoXtr&53h7!zI6D9sc>`pT%hE-8MpJ+AHE>-VcQo29LNBYru}#; z)xY_^9}!LOi(rF>7asI`fgDG&N-lDLJmsz1&&V#XKU5hfzfGKVpyaQqs^EkJ7Zz$@ zQ?nf#1BhHfNr|!=kSFML09atqWjgZ-?)@T0R_X3bo z7XPZ}&DE@dI1f*7OpNFTjQ+bYJX|Si;z7A`);j$*pXQOJ$jk4ifN&EsuZ_0)klj?o1{Pv{h=u4yxwo|2wbIFiN)lw zU)DFrKYpwOi|Eolz`*_iaJ@qtg32$nPP%{&@Pv3eil zyTilsS0<=eh68iE>)jf8QlQK^v}P>M81O6}U5KBCdxWyTk;BSI1D`!J`?}=<6rM%P zCEgHehl$?G_S-A_g=(`%=T3NkHQ2c8_P3rOh_2Afu%r}wBjQoCf?`7g64c-QU?7z`zGBPmM_%!Mca2|80f&dSmf9R#QV7S%_I z+W4xr<+v3wB~R)^YA0Ekz<$&J#z6eZAnw=d37Ub&32`mQkUx-t@LR_+I2B6`V&Go& z_!m9@PQ>FkAn?-c(s45I!$%_txG_Or^MO`0N0L>$KrODApK>)*5_PT zoEOHup#0pM1_6!Ic1nQ2iX_X)4WOb|1auB!V=PocG@0+5<9{5F(>ON(V}a}YKbkb2 zQ+;7CzmCS&KR9F6Y{n91>=#V#^~@!jl_KsgcXc5OAtIXXxivre;o?E269|Fz&R3O1~U?bY*QVNTT<{U`hnG*yj zh?)rom;90>k<^5M!H6|X&GQ*idZX%Pk^ydKo4i+g_)uvRy~S_X zp(AOE<_{=*-F`N6+kX-FFVdAvA~16klYVZO+oq#_-civZ+5Ixf>t;h6S8}g9mrK?$ zO4I+SIB4kQl9-=Kk}@AqbZ#JezewleMxN2xyo40RgHpoy-y%KWh36JCs(1pB27Elt9stcuK$&XfMU}uEG+!>lK5|d zJJaxhH}fEHPEOMaQoJeXn{}-*`q#4?j}!2Y9X~V=#_F{3SIjF+A{V`U5I}dm2Bb20R!p$}?2e8cF*ba-`$f+SE_l_R>?EmL8&ZcuQ))DOAL?d|R4=or@dJp7CzRt52P zu6EOb_$E6%Qb7B9&J_{e%(PDL6KXK({${(_0Nk*)e-&Mqu_&-Vd$q2NpTf|;M@K8E zsOaW@2LX_Iz;p=n0P5i0Uygr(LYcNxJ;qNebZV{}cQPlhx&fnB53m$ak%lQNBHJB{ z5EE-^GF-~BLYx_-m9MoCjnV1MWokIYKBtCL-l2~8&xuiNU;8OZlQmXN*I^JG$$w{^ zf2g~aP|z~3l@DW!%mL+Xk#CuCnSac!F?c2GnD!<&R$!1!N_C=#`$VIlLPv=?E&7C| z3yy7TYr|esfXUXe#?v-nx?k@hq3`O4}SmC}SjLeN_y`>9*YlO1}b`oktg!dCes(k+_hnZrrM(?-MP*Is} z>xsCBV@7(>sM`d&dwvPq9gfGb`pYjp%ubANE*bJ;{S9K@oF=pso+nQT&b`po{6JZg z)aPU$IiV&(m`=vX2O^J9C1T{E5q9xdyiQ{n$!+M!tQyZ?KGAM+nV-mr5fb#|>NUlZ z#QSv=Qk&3zJ%=#jAO(C(H#mL)hh025kLg!k9$FF}kginU0T@G-&#BGRZOjAbaE^2Z0{YU(MLq=CH8(h+%N)USVLAViYW z$wNp;NRl}-EUlFB(Z6>0y~4Hi%ssyGWzpzbz`~!WNL4pB z=i%4xv`)Muqv$vOh~3F9p`b=mg)|5=MN|%s{XoHKcm&I`14qzCR-1$4ui>cu+i{QR zpR+98skI*x%UoUfpX!}Rp(uFhddDTS-N<+W8Zu(@tM*vr&Ntg^0im|Cw3s1cj?z+A z`D}~HDE-Zc56JkM-z{sARV7{Sk_H;dJo%S!uy}hnF?_!T?%1JrfS^EX z^|?MI0xVkXyO{23oqcv`(XzJWobp!J>LMr@4X5Sl?~vQ^Txd}avptF`%cIDu=N?ba zbNSt~VfVK>bS|=~DtR+vz~&0G+{*Hj1>0!6HB;NRE9Ob-5u*8_hH@e4_U)UxekP(R z(RcckRy)i!m~j+(LDy&;_kCy@o);F@3ZVFg4JF^>^$W$CzH!_6>gDBSWJJfWq(%fM zpl8nwV(GrTaP!DOiXoQo@!r8*+xAlO*TcSJ8abcek-e2DPKPQ zrlw2DVb&b?p830{#yjCYvpFYgzkHuRFfK5yu&T?bp{T@YgKH&N7}t7_8+Cy-fRUZig^rHlw z%c!G*MdowCcc0T>K=rvZIo5i(|MzWCY2mzMMisgVL(5dRG7b))9aK`6Mlq5PZo&?lvP*oa#*ul|hl(X(f%;m`s3I|KjprAk1;OJzWQ8Cba(2-SKf% zstmvx@b2B;6I^4$vT9^YXLN)b`mheVbW!QWuzNK|3r%16ywqH+6fM=;f~cHEN}ZkL+Y3C4QNIN`k3gyldh1uR&49qcc(%wiQcc zjSA`Y92?%2tZsgdU=p=raeMrVN9O-tfH*EB#59wFt=P>(G7!{t)R92qRIDcv^jVD< zJzzlv2Og`FM>_~NbdI?;Q6o9)oL|HO!Pf?On8Dz9QAlwwGElrAA;$PHPZ>Z?FfTpv zjZ_9CTQHdDs}4roE~~oeUD&UGnVCUFmHt`Y;-rqOX^ATc>cB&cEBqs$V2mC}8GdvH ziBR>}@q5Tv6}!o-nJw3+?_v#iUJ((fa)Lr#mtH46L0$8lN9$%*4BQtM-5Ui8 z80lU~|CNxUutS&A;f=^Oyzz<14K;hkn+tUlg>)KWC5!c(>Fa1GON6j!U*d8H2>4I!}0v;iZy@xsJE12CV({}5?;Q#x~e|Z zcifungNC9H3qxJ7$Mkh{qT{lh3raxY^VSY>+X;iis0_jLl}v92|K_?(YRoH-9IJvN zlQc!h@wl7OS@^lN{?V}rI`L>|{IlACg+L2looQ+@oOC}v@`Jc?moJ@WBo?THgkIyA ztrvLuf)RmgIiZtna|>o*H)~;Tj)#GuuArpxz3;Oev%%zW(A79O;>X+W=6K~SgJD!1Y+dEjqy6zAi3=lI6xufh z&bHNsu(V9A{Z zFNMi$JUUP>S*yDisfJa&gF~Q@(BSYOnRCA3DwD%vQV?8fWP+`IyF)<+S<+QnUhvlN zC@26tFRds8l}}dx*DBd!UZJuZeZkCOE{q&ue98tQi|#-%GG8BN-kM<^WCD(3qA6j- z$u2YF2nPINRyla`3U@Ca7;;nCz z;IdO-@+EI({OEumbv>WGyAn3V8!^!niW;;sbgtr$%8jSK8ya7 zDeY>THeNNf0g*QLLZ$)vBvzFW)@|5~?Iex48+5Z7*VOuaaqKf%*>;gqZL}nQcO`C+ z4ZXVDn~YGOb%lNkheF4TxWh81=;{{fY+k*_JDhhRGBH6-+P>`_c7v6%{6Ny&$wI`F z(D9-X{r>0U$B#f>VyyMxXC&#HWC$JHY+_z}H8VRKA3ug8d_w47zvXphHH6T{wtL(v zSi7Gca6X__9JCVallmwOG@&r?&`S|VdZ>fhFyH3cc%=UzoY%%~D6#^{ag2MRCxmn4 z^A+e&=7At;ctGEYxuRrDi#v!cR4Lc;O1%e}i-h+3_F4`*g~X`21TyrbHLHe6Obu$O zYa@-QtF8{p zPR-g&WTKNycU#S|`gFVsl>LaUyjsr4_Uw+yssX-6->Va9y+v)28jl4pPuw2xO45o@ zGBUF1c=HG4yoxP4+M-k^yEtwNRYGR86*Lv;BD-HhyUxE#j}YrtX%v}El$Q=JTW+%K zWQWZaG_}23j}H$o|AsPVeB_$Ee-{)HGQ7l_%#5%-Z%S7HS~$6Rqu(OP@&LF4S{9Fx zI!ZN)HEUxM@>uYJT+W|ZLr>4w_};B6$IHzo3Yf8i@BKE;DD2x_<1=4LYxXxXZ1@@~ zZ?-7qtikZKwG+S+YRM510mJh}v-JbHhE`7a7<4rojEjxpjrrd=pS%|n5?GHjc}zS< zZe2!Sepw`7e;uvGkU-wf4Bg6_On$L^<%N#myn@}EnCYIYvtI$1S?2f9Pl8DE3Om6V z;4AYxVA^`>1qR!YZ&=DuP#oS!WoZ`9L_-FHIbH4W8}9_<*F6Ke-5g%Sm+Z|AT#Rm` z_yqSY@4u1I{+jHVUqk@MmzdU&ez+i}{eY3C5ANFhjFM8(tE&`9tY{{w>6EOxhlj$I z<{5WqIX{;VlJo2=%G(Cpy^kmbU)YVIyEUqfjB$}$p&`SO`*U+QCjPcf5LQ&$Q;NI! z_$|it_Cj`i6UcSH&ov|O+yk9Ot2wLu1|)^JMqiX>1Ox=Ro!{}Um)=0N2;gv#5HlMN zzGPP8c@SgD=0m~afu7rL$M*d<_!rM!;+HRVub;zi3lG;0Oo^DV0Yy{TT?#1+$X#$&-+hX5#j7mZW>t3y7pCCa1gwhN6?D zs(<})`4701sftW%ETyoL!V}vHrObT028#v2Y-8?aK}`_@hhx4WJH(X$3bSgwCG?H( z0}u&%=E#J2knJUR}Eb)$>~<|8lore`ks`As|H|1+eEL_I$oL z`!SU6AVCupH*Go4H~p1H2ZW`XZ!-W#-A!fE{#+&{Wfl_v8w~`pMdn@nEVYuQrY*~Z zu{Z|90vH;_8}1onZLorbVyQq>r4bim$fOzzRVLn*lUFP5B3VQf!GqFCkRazD=*xCv zA`5eKqW;fIgM)+jeOASjo{!;wXkNr~em$k)qLlO%sUz3m5UZW|>djs_JI{V`R!X?t z*eI+SQc+A_KYSc^a5k~^MMp-%)i=lQVrOT!W-qfrwgi*-?Te8BI1wPui^+CjQA6makk(^k&?OgmkWE>ULr%`HPNq<)n#jGI5< ztb{|#ItMwoi#2G_QV@Vj?p=AiDguZQhipnWsXulW#HGv$fGu(v7+l>~eQydQNp;9z znHMQEO+KEke0_q{Dxe>(-n2w)k=1ZEwfY1)nsJ$jYPx}q`uZ=Yc(xWWp$g>|_u&rC zt6AZ0AAUhJeO zaEEhjB36Otb+v~%gEXRSOoCue!y|w9+{-6EW;J9YHHehaN>eLczQ=XgVT6@M@>va@ zoCKqDvmYjtrRm=fxXyRoU{HtZ) zp&5y}m8dQQOCKbOgnxExhNyYuoq2qLCNaH<>=J6Q-idkHi@#rOdqx|qc`a?T&JA!N zb&|KXe<`poOlb=Ypq&s&NJwgSdaqj2$1f@luf7!?)@0ggiMs*)(nto4AGz83TN{2T zUJO@~LJ6DGbhX;>5M5bX0*ImT{pIExuN}#_3?>3En!H@bj-9R4nzRr2+>9h3XU{_y z1w0n1ucuM&ZC}Z4UdMwv*rdsP4EZI+AMm8mAv#(K@{_#$c%(lRxe+Y+mz^x!v||Ze3gE4>xzTmFm8o|PND=^M#)0cC-J>_+mh5QK*+=XwUN{a zNvF!L=ra$a$1}RH0@dA*v_OYO!m4}wK-`4Q9kKc&$wjF-%&Jhd5KInAsWsEr^=UU| zk2H{9+bbgEpOW&U4#M!{rsAyC!EsqTmQ?yC|-?Pq<+qj{;KdB{HT^i@L!8OD)iRBMnYQLG!dopG)zBA>o#P zVzOkZMcx>rjx6jYg2_$3=;(xVYbn`I!kMzN(>yQx;|5H9?k{zSl~@CVa6@1j85ytZ z)IcaMa4ytc>om;ID(RXO-=Vaa%hI~(dD^I21*8w zzs5#`(_)fPAh5}UX!V*lGe2^F!viRPXu+MpRi)lG!~ZtU-tSMlN3Yi9koegZXOe}v z{^u{+Up{AQCcxn_G~$l?Q>;7PdpyO=P#d^#6{1A(WLnyB+Wu@2G7^38O~~&?A>Qmb zF7NLFvFSZF%H;Fq_^QEgjia=5hLlV5%F5WYlpCuM!23w#Vpb>v&8o9XYKfWPNFmlv zGc??lhrcO+$;h=>IqUuwFpSQ{{jqDliuu&KKV4HZ`C}I(Rm?J)DgJOF{({9(E+6pg zRA1Vz{ogfd>uD%po<2ErYsxcTq$93Fm=!VzLBvp308CuTo==P~y~_555V2Ta{33Pq*?sfN560E zYQ8(pg>QHWin*Mo_ZFfol=ARs{F~VQTlmrZ0)x#=4Ho?jM>Wu4iB%Gs|EMAf9iStV zPT4Gc+sNF@OC60j@Z(}MdH8r>B`A~SPtn)(B6K4wuHR4fi_ga=)L#q?RJdK6^=fj% z!-bfLOW_#cDObwqZzA<$&1)vcMgS;?8|#B*S>1FmLwUS*0HvPi)ik={+1Th^VmuoI zzR5ZpJf5=_A76-Ru@(#V7SUMdgQ)PL2Nn;g>J<3-WL~@>l1Bhiiqotj{MxVAOB|^2 zW%C`sJz{&?6?QMEM}Rtn#9u4XhW$Y(Mdv}dH#CK%8lSHS(P;P52Sr>w^W;2Hf&sj? zP7F+*frSU*?q>A{?Zp2DEjgK_-$r-DSH~^g#szcqA#tv!sEACp?v@al z!FiB=C*UyGMxZP=GqoRqmHE1J*RX>PQ{i+Ie}20=&sVsPzQOrTh|etyUFdDc6lUUu zxf?rMespjRkps%wQeEDSC5B@7yc0@2>N^mvlRUB{epVjIr~uy42CWb>?+}4gM>(bh zbsRo^ATPubRUrUhBZ^U0j%1C=brM-)K3-!cu}9E2GagIK@p2{bbC)cl1iN!GuL?sN zTd<*4IEe||P^&UI(d1_yvQ_FkJo0(P0Z*R5fpscN#?%(9bO^b!n2;iLpZ0(xBIX87c(S5ef#UBm(#h^>#6_!Hv+Xi_3 z<`HOQrl-p*Id2b_=CLp(oaOlMb_1{3o7N*+z-;@H-+SBc`*br@1J4$7b@IGZU*`3` zIr5#YY_oQ?wKZ~Ff4oB>l}fNF!!K8J8g(6xp$+LG1^BOm<@L6!XQS@V&H9zjk3I5; z!hRdKq|e(}JEK{I6M*h;BK~VEuGwLIV<15VTb5oK13{$q4ft9UbXxU?nh(w&uOXta zq&1bBk)Dn^zU+N7r{p=*uzXGkG`RxqCux_hq)(J>JEtn`N5w!~qS>zPP9`~IH%?XO z=6L=o>fqn8n%PH>j8t$i0vr?zh$_$X0zT6v#LyR$@Nb3fW z5qWCN@qKXM_1kNGySg+-_O5+Bdi8={{63h!v_wh)lg<8i<>YRi#xvm}rpyPl@)V!4 zbi*SKRf2zN+pjAtD|_Ri92L?jq{^pXhW| zocanMXx)+1E!Gz+h7gZfhqt^{R~%G8{!yR;01$y^kdvK`xl;MFVt9BsTh!O-$^Lqk}X>2zWOZL-Y&Ex>i&F4(RT9+P?0PDkwK&jIfhu` zuP#c=8p<`Yc0MuSX~{;6_mmus2Df~gR`m#;ip)~g82HA7 z>+*>8Pg2N2n4b|;A%PGzs%=y?$>bTwszX&5bkUv@z*wuDS8p z+vgq;kKPNQAln={)&rEszvlcJaY7@)N6CtJMIn(w{$i!xyfEG9?NFS{1|{p zE<_BO=n>@OgU((7(;IMuDK0L0!=bn9>W!|N90)OvN`PA#*Zg+K7IO94TKCp}CnE6B z`}TR{kJxp`kiOeVE6{Dd))Bb+w7lxK7Wn;W!4uR!HhR_m^3aY;K^845r=3`sWI_D& zH>J%7fGz1YyS=F_2RA9=5lapx!$g@r)teXU1$ zq0W~_uhZV8CB=qGA-_j$jcBxBNq?(_-M}vS3uHrzw&7fEW>zSH+71XKHg`9q;bnMH zw)^aT*vT_6F05bdkeEzrA2{t~jlK7}l(X4L1%5v_x67krNo~Y&|q#RZGJ2C7{9)4X=Y~2#kcDw zQhrt;ewP5Ggv<1A`aTtZ#_RC37|?XpbAM;JMTP4WVL%D&F|hsmW(=EokmfRU-z3OVg5v5MeC zuX6DR=jXA6DGY~EI$9)M8gRUCrNhwAYAS(3h+x(Ys~H7oP&&Gx;?K;CQC3#Kf+l;N zu+>T{ZAby;W_7E$IHPkFMEByz)XIQ1f?F6V;DRZOfF?)Z$>~rh-mqax1vJk zS8w7bgY=s|Q+lRIp%tu>1wMfq0g%IWByA9%wp^EjTwkUH1aYu#o}{lUrvEvbmAiHi z#F1tlFFj64#sdS5zX`z)?_c1vqoYN30ReE<+7wt-I7AH`?_9u^2|zrVcY-|OMMaV> zY}{y_2yiDw`SIq=_BYZ!^{;#sPO`HJHsbk8V$_FG3#ZbTS)7~yYC&~>nkMI~u|j*D zf;AIv5($)*UR|H8Hn=$MEj2nPj-*Z+j?;WElZRTz2=Z{e^^X81E0n$-(*wE?dXc>6 zDG6;s#$Ts4%_E1n0q`yxHaQqZ>xYvkpy1){^WV3vH$V}ezo#c^fPSU_`BZ7A;b|>< zw%gj8*>qffw2&?xz8CkgjN5UYHsVgE^9qxGdPdH3zpR+s$wz}GTR%YFz^U+`E%Q6l zYp?qGd3w6a zUC$mHCEIB-U$c>A%R~M^t{b~d|)6Q&sbUgMF>SfUblhA zdJ=+5r|q`s)pc>m5zS%>Yn>6vsc?8ia|jd99fFH?B^XwFc0a6tu^2ze7I(Ju^AkHW z{c5!LRi&AU5xGmhfnCjEJkm9v7RcnAHGH~vGIxvp-F7vzsGQ@qv9y;Up-p6VIvO*0 zc%s576fo~;ybTzEmrT_&IOZC;$fwy!%XXHpy70Qp(5|zDT~Q}og_nDKoq04S7aNXl zxASogT(6+5$^yOSJiTWgPK&ngORlpQalhd30A!pZbMr=dB^%{z(fK`>KmX+8rE!=O z&JLG`@0@qS9lWe$B+HuEM7GQx-ezQEd2g^`bjUz zxQF9qL=51(q);W|5uvDQX9AcnWYYk(QI$zWCB%MVLuKsT(NOG!;2+N`OHpyKaqA+V z_#6GG>rCfCrCL-m4?`4?bd<`QIsitbofS+ zKIwD?acWJdwrY;~RA-&$~J!rZ6{kAA1FziZgY0i zOX0~!5M?4QnVYZt-wO~59O@j|23#Lxce1}^H*DIfkH{O}GSJiO%9M$v;l3()vh!bD zN~B+?v;NM8Q-qq)odhOoSoZTK#5357%(MZB7O5FL;}K+ z?fCTS1AWyAHk92?8dT}ff6~B&>LL9q_*Duw$Wj|D_3Cm%4-uQL?@v)i+NQ5XG-ACbJ|?D zB$Apqxe+n@0Z(wW9o2y9eVS$nInCS=y%B%f5%=z8*O!bDh7_{^87LhkrsjHABKax= zRf+WU^u5a_ZU~Ji){X|>z_ter9Nd}cOO@BuR)yap5W$D#E!%4MvJr|ktUk*wJx8P1 zE1YCj%%OmH=pqaTb4(XF#w4Qn@F%NryE`r|xY2^q2?#z$WbPY9!!{{1GI8albwZ?t zxP^u|>&>WB6{B@J&b=U-b(4EbJ{Ke0jD*`;-&GwtxzXw52f-{1!!lxN#OoLxGKv)b z{Rt6H8(IMY0TQE*iV^6;Zb8+*=v~AL632sbnF><&@Z3V z46RSLKMH(ToStwq`dC(VB)P~Kt?tcz&{SP46SAmR`<|1wkM{2{v|uJMEg?;Ug^e6{ z6+h3J4Q``Gb9C{M3EIDD<&8FkBN5hRMHS-Q!$e`P_LbqCEIqw!hDK8r(T}b7%+6yD zI04hcmo*&p2c?=xnL_-aGM1r-)t4~3kP~1ZrT68F$2O1seXzLCYTx}f@Yo``r(NIk z@p-(^Jgoz5xz9y3-b3O(Th?wBO!@l_D|h~sVvif{PYd>sXEaZL^8RTO5n<90FvOXL z;ckm15%Ko@_FcRND#4d$4cuFuj{z0l-Vfk2U;T6+86Iu90@#jIr5fd5RNx{x7nwA^ zlNra}e?;DJaI&)D#sAG-_V)WHu=14Re-)1Vvhy7jgsV)9r>C$)a|x7mq6M!MejIXz zV$`VN#iDcWPx0nsO4B03X~Clj?*oNo>QG3D02NxB_MHT2%?zU}jKr^;1k zu<}0ZNVQHc5%XH4Mpz))kZ_viuKHC&F1VH|yhOVf?dUg8!&}FXJqh z&&yNV54XZj8pA-%%jdU*f3!Y*vIo+6dFU&iW~J~V^!0S>pT1jV`dgW3JOPf`bV~5E z(8!N4l8pRs5APZVG4a$&_wQ+FymnVo+HHKkKF*oQX5T!LiUIeh^71z?yBU7F9f7`Z zhlitv80ITe^$LA$-*qhgTcCnL%rQdgv#wr_=D)_fJG+J&@3G@QDx!AV*x+)GB|qDu zNMimSTH6~xm?0J>m+~XY+H7{zwo#zU+2H8!cRUF^$vXN9&4<}cAVbmLCtgR^;*URY zvqZeFSqISq_(3>S;c2f;P%rBB-JIxhSulr2vqXa5qG{B`1i{?AmXG{)fNve8!`k{l ziO7h_Ww@oONy|-P=RFs7%OfxWFY;bF{Qj8<2>LGPQ)vRNcd~vj?tT`)(#wkLsF~^k zLe)r=?>wsPk0+O0G|fBOm@oT%3AoCIPKJK`xah7z^WJgO?9>>AC4y_$bu33j{Pp+n zlCSCdmBsZT0@5Q+uXKj0K~QwT-7DL3>vZXuaWx5COo*B`>h8R=#oI61_Ze>=M{FBb z7WUklp2WOn4{nBMyULUK1@_$mw~4_+)2Ef2m>i&mLtK8Put>51V4BRo+!yvGNB?Lk{A<(RJC)WeZzT$0? z9o>zADJhZP2#QGs=pB?7^>`f*0U>P0YI2sNw(#)z&|gh$&jSEJ!nM*{FDkBD!?8#{ z->P9Tn!Eb*oIw3nLb%j2Z*oL(xRvpNjOAWzeMP7#UgS|#G#8`<5j*px9-X#?4n4iF z3{C(vY``r={;>tXVOP%Alt%3O3sw?zW8-m;~4wR)?~JWLvS zyk{V8=)s?Fe3m`;EK`RdZL2B>Nog1qVc3xd`3*)CRsnBhU5F7uZaSWWKYk>AKBIX7 zHkw_RmxoyTr;qKoy9SC()40zaH&iW$YXa1Mm%wV$6#)t&5-QZM6d;ForVP`X(*jpl zh#GHnHDe{k&p7Dq9;dzMP~GeoK$xkju^3xA%iL+%=BxBO?R@Ju>)v+#%HE^9{jSuX zFk_BW1b9Q~UQ-EuWuIr^`MDn>)e1ujsu2(*2c9`&J;2&8k0dIPE#~zEH<7ZN6u|28saworTyc zVX7-J0dfHu1{NtEKDtifYaH7+!8FA~BVfAcpWLeXK&+_|0kbT#lf{uZC_)8=G31%4 z;RyW6{nga8@xfu#7YJZ4P~sSz29b`Aj=2r0OTOiN>;Ghp`*e!?)c;tomkn%Vp2Sa) zR?$F1*47}hjO}2W`YficGrn&(yjwQCVOA+JlAGY)O@x`0wGF*o=}E=w8vAxT;~ zb<6WrC1CQp^}ko4k#@27n$)dq*%$<0ey8!@=;#F805=*+8tu1`x6(aWktu!;4gMzw z2L6{q?ko4#?vJ%McH;-0JKB6ZVf7*c1lC_KdgyhF+?i@ETm5|xI;~|-XR<91#^;4& z@xw!H--g8){*R`sjB4_2;{yRHaWvA5Mo{UN+9(035h98-2&klVcZbMmMvsyj(%miH z0>Y%F8{X&t;r+}xJ1p+!zOG+B70;E<=w0V0yB+y-kG>7_?w+J&j#Q!R{|B2A`5`d+ zXilD`i!1OBJ@}Y`XF&EZ@bU7~0*Fi|Qp)G1D?S(o1@!r3p{zP{<?0%Uu*a`$h z``oYGza*uEvADi?@epVN*-MyE#v}CO-EFFV;x@W(%&C!{veMFwF9+p-e;X&j5fXfb zjp-{rPlL?+?5Tlcxv6nL$NGmnLB^o=RfqgTaKP!wFnd5S*vmu|Vqr zNoDblUdKcGfeILF$)01>;g|+;&Fie*PS}Up^w88~UPLJwu8JbW;pXVuHt26MooZSX zxnqeW{nhLi1{7pdstF1*JL3P^e;`2F+3~@6kw73}N)#WM@yma(V?jJ#1v~0BaaZ7jK=I=4N@&lz{so6mj^?{c=oili1N%J$ zU!}^|{uYDs8~z|@F$`;SAFY&rWfc2G7HoozZR9&w(8kl0K{s+k-$$zbFPTUHp}Ty| zF@1k1bGLPV-*yfpji28RdCTbNyUY=|*o~x%>#Nh^mT&V2_lwWaofw+CUnZPuFb8C# zxKi@7CtNi^APg6UKj>5Q-U3-~)^&ZB=glGKOUL`r_qQ1|?&V)889hG`4zz znE~sg5>$I~{Bsgnr0P3F?c+3K1M=$!=5-yr7IJy0bR1IWLE$YG8N#RXPeMlya+#++ zAEXHSRjOct9gR7)P8Esds&*x=#i}0)Nmvgi_Dm}+50REdj`_4Ikz~4F=AclppXFw) zGTw6*-z(Xe{topgCXW9U{rkmSlg~5b^t86P*dHYkWUKuRR&U`vKdG*2BYL+j&TzkK*2P%M!_5}DxiI^AnA8|NeU z)orHRv*~!L=$>^%`($1!NUmaK#bCu;3;u){kHbST$f1rCNkoJR=VIS?ZeXEkepkVz zO5Nl%(livZqfnCMvIKT_+EnF#^+>ihvB3diNzbJ44+QoCtMJ;jRd^GPh*Q6v zfRa8VfqoYsTO(MKZ zEMFP%>nH*gFP4JQToo-v6A^Ym5tIa1-8!i3X>j%i&cZXDVa*Zo@05##$hGDj=LTgV z`bU)QECoqTHgUWIDl}o5TDtUP$H~q4AQMxOmjxRtv&?kWh^DXrH>0x$J@zv+tg@Lo zk2-YW2i~R}g5DsqB-a9^Rr6VL+mW*$$=#l@o7gyt8KU3FBl5gRdBvtI)qni9Qm0op ziZFU9c-F}=5Pyw&4_rCQWD0^ko!-3@Zy zU!ATTFOe2;y<&Q+Q~h|=>|ExD=ghw6JCE~a>1(uoR_pHXcKc&V5QS{qn0>kKOOCEuCL3%;CpS?1{Qpx$bX)` z=Wd~CJAv=+L+C!uS2{i9+Fxk(HT&s)G}&K`8Re@eeX(gat!7B-D_ z71#Hi9VlBUv^jC;1t$?f6g{`R@yt}-HbBh*WrO3^LZUK&$+?{FQ(#f=k@T1D z=RiJRsZr)-ck8W@@DDtvYHRd;_OCpsa?oEQrU044i**Yv=LYE!_w4(U!D>g2TSzK^ z8}ay)rxg>kBA-NHHt7j~4v(L9zD!M4aF8-Ltx`}ld1aR_8;q z+@wXZ=gV5Em0S{?<9`a$GA|=r|3xl2=u;YOoD_4WO5A;tIq3ud>t%;JoZ$cT6<=a3 ztt^2!&F8+?Pv6}QwjMo28;e@I_MTE94yu1tUqPJhNJx|0BY>+A?PaRh!d$%yl+?7}urRy9LsqkB%|a5y;QWWV?~?@KMH=;pwTfKnP3&iYJ_f;)|4X zwz{1>7hq>9#LqUpmc>XRRes@PMMAig*Cr?76O(YAhfH7-dvEEB-+lUtgy12lO|4;C zW~Mf&fR;cJ`^AvjsGS3`oB=!}cUaEXgf0?LXYMc5y?-OBgcGK2#xn5i0@z2#PbP=P zE3!U-Kc}RGzlDoJ9JhWQ^;{{Aa|3PRtDO@SEfVber=CGw;R=10AFKx#3$t}l^W2g! ztZ{`ytjbKyezc>4hIthNhom5 z-TJIV$$9;=8p&L0^}WwvA8BCiJ~UHfNK!=p_c+Cj?V`z&8S5oZV`3-ck^hWmGbFRvf?*yq3>kenRX>u zEwk{TWGW*MJMq&MC^e9mo}+rBniM(ZA0eNts1pPi?5Q}MZOzEBXk0e~<2#pFAjSr8VJ+P8yUc6Q9M>(+H@OsYIt|tT0woRMdA@ey{%Au=NHpJPKItC;h>i8`-wt={V znnS}Q-8A2mlT*mUOVZ{&X=4<59rsRWeAjp0$Nq;u85kO!ve-E|%u2^gGULL(06<85 zP}qq0dWN$^MnN$Kvq>CrqbK{9~mI( z!&3@qYQ4w_y(86R56maiD#)R1~f8+-TX^&PKEv$Y?oB^s_!B{2-r z==%C_KW_GqSF=OeesWmt?iedeyu#7+tAQ0?3k#R^K;J7l5LblhPjM;Nn+xHYx6;6p zaa(M^uxa)ul<{i*XnVWj{t9T~z~qZApAa*vslPQg257I)8PRDwGhW2};U8OCJ`M&j z%cmie$Tm|a5x;YX>$APc$Vk1|@G!%9bGk+ty6Lgp!VpugS(_eXH5U^09G|8F%iqj# z8T)&8N)dXmim3(^TgoL1^83A;pjv38(Q`_v|IX%7(_pO~LjA`@-4-sh zC>_BG`ou>}0P|}~03vKdsV8bL84#^T%J-PWM|BXq{rJ?{EsFqVkY0DS3jL{~)$Kee zMH>xlMV#xEpf^9eex`DT`FUi0dl7HZ@IC|rY9CtM?dZ5{C?BZ8fl~>|v;r&9fp^7B zmKw(_N)D90>nx(A08Q$u9{|}$eb@i4Z)sU5PEf>j(g^xlSqZ50W_-2=-(yduIW%km zRWEnu+Q!~{wV$pLb+?Va*9UJ``y17^(VK;Qa-L`VMuvvspXdBD5*dJ*37gdWb7Fs& z`0GE-$7#7aHf+dgREG*89{_?{-Od*0cu8?nbf>I^=Ifm>n+4cy`LDh=owEde11!)q z--JAWSI5;0dwv?K=r`}+Db>Ef24$T$VF1c$yhxLtRO820A)FX1+ZeIV-`59l{b_FCQFhI; zAc$!TURnO^ zASe7Rw(H^nEazy6Y2Z3;?NW(lki;tjcp8JZZwXnvZq|L9Kiw|_-%So`JJx%by!Gno z!Q1ynckA~%_dfeh2fInqj_2$>n)%D%)y7He#zvFvjfD_o{;=a*gw0u?Z?l@In zX3ysPiu190qw8*I>Q|F{e-tgbmSJ+3f#|8V)cpH>R%Zuqb&9CH51h79(WF1sBwrSD z_)L@xe3ddZFfcGS1}c|XL*ejzn%5Z;wP-ZDstPj1Ez){a(%Ml9`-i;^whIry!D&l} zX3y*a9F{jgaR$U7K~Yyt z9Qhb-j9~FRvS4CQgde*)LPP!B``^&pix*E`b0mffdh&jNvLzBw`UsQ{09aAiI)A=H z#ZzvES>NCLoo=C3KaU1V7=e^%4MXD4&RDNMtSCa+mVfPykc&|tU^E287MlJ>RD|OC zu9Cbr?T>xNV(>8O;&#-qe(u^Ri|SL^4=m158u|JLwEUmttLZGVZsbXOXhHF4rsR3G z%r#L$O7NhA_}^2~;+RL+K36(fw-=l*>+KhsqLl_emO$v`<4rvr6NLQ?DWiHLFZ*Pj z@&cp;Oo(`TlcuMq_Xs$@>u@|O3!PTSBE=fZsfu{=fh(+ilrN4r#BPrAhZ_fGe%oQ; zMW3X7t%ajr;;h0DPfU6hSk72DCgRX~l8IO`jZTAw!!;Y{?rO(D%=ZlN4YCmpV$gfD ztLf)|(h3BQL^#jHL!b=eEK&R(`bic!kT4eZt+Oi0Z>-d2fg}XOj*rE-J;2KAwxy7% zJPmFj=R8Zodwb{oeGjmR=;_T2YECAmg2ea(3Mk+};1}lRs}!F9>gOo2FJX}wYBf)+ zuns`ox7bBtw(Zggh%Sw;=&5ha1?DQvBn3q)4d1_CsrO#k+$@rWcX0$XP~_l0z!*nu zJp#0dCFKokjjh+GoS9#5TIyOEKrjFK%K$}fD;GTn-klhk*Vl)(l%!e) zz~s;sT^k+TeT>o!l80V3XPRf3_adWwBc(an*D%Jb zS9s96a;%8=4Mp%Oc4fGm^g(&#;P-&%np^D;nQmtO0TEZ;PspTQPyPZ%#jh(Zw@@1L z`@NMrh7T#JnZ{SX?w%9YugbU8K0n4l7q^BHm)eM80u^O!0)n_8oJT??ih=DE_;y@& zZjFstjc?00dSpNBR<%dJ5J}>6DhZ>|` zM&=rQcFA9(WNLTy%340gKUL}be!d(g=6UeRw{zf-=FfmhgkXqACkZ+mhS8xr@tbdE>tLb+Og$J%?|TTZ9B!&R>R6!T4#2LpoU? zF}=0M?He1$T|g|&_I&u%)Vk~AX?3YDYd`r6bfR)sUj+FDja*l8ncB4_2DlDZ@v3Qp zApT(3CUuw77G|E|+L4%N1Fbz|-@0Rz;hUA0^-+C( zevx))=*N0KgX9m&Q!0ybloS*Wiwj2>P|i}LukqR_%ycQIs(7K3l?w9jDb`o}emvKN z4=eg5eY;B6Ms0_mt1~t+bk4DgAji@*hk%e0}UB(&3~<^^noqS%8tHp5fIiz#GvUn?)1bYsp4oYVrrnX9vmF}{@&*juzU1YTy147FV5p&$yG{M zqA1ycd`med_mg-UAU*Iw_DH=?>wEY&l%9G@3c3t9aXy^**R_oaxQ#qWyf8xP`(M|118-zAYIw|oUw#ZkUv-5 zkq<$SYvP%+-ux-G=dB$9R$L^K6;e|2QFeCc)QlWez+tHp&l@YJ7E*-YHL{K9hlhiS zdK2gtXG8e0{i0>Fx&FLOfP#k1p+b>eljcANp5%F zUYYvy2rlIqc|AB7ONpoN55-WO>anSjJYj$3Yb4Kh3hB^yDXi?{cL~a5InzIt5&|r3 zuo2hqiW-%%_P*`|814>rFkxiDIwpVI`=>iEbulGQS=+zDfj;`3}-@nImpGHQ$ zf*h>_PYZlt!LdA_89TR_o7na{`0U*vT?)Z zX407W@_`Z*~gD!qN4f~`N)D4{Q8+4@!rJ# zS(mxJHtiC!%hm7RkXi76S@w}i2##{8PSJvfsfa(XuHpD%^lsI?bqk_ zCXwG#jHTmK#_I|d2xUZ3f5+Rs>6xC-^lqfubY+yd`CIwzfnXq_@t`F*j)Z}y&mCK) z?uXYvabbC;m?Ct-#$sLsmt83VI~yCNynEVEgr9)4E==%+y#((=TmrZaZW)b8Dn~uG^i=JUsy1aFnay1(aF5l_XYO! zlge0*DZs;Z$=@w=(HClk*=zw6Tuoc*-=FWjmADTe0xmL%Ds`nOJcPsn@8)Z)rt@XV z0|v4)E6Y?G$>!ye4dV$9TlVP|+3_Id>|a~XdU|?*f*c6%&ynk>;`P!hEvvx(phcBY z^;X<mUQC{UYWN_4*nhKZ z!3P&E^SQ(LFak}*W~wSsZILT<4!OYBX_Bz9Aw}e_Ovj`Cg!*-JbJKh2eK{PN3Gg$&QlD(;R=W{O?q58zv zgR;}81X=%THD$^^DgRRH*W9++Lg&OojjsM(VSn(0Oo`);kiK=wirDh~&>d;8GmJ}~QQ)E9yc>`3|pRo1E7GB+cDq`vu}`R`gJ!hlV@ z7cMM~c1$uLU}pEjSIgTBkWWbXlmDtCulR2gz;pRDO>nOqCD(P)`2Gt7o)Mi)Xu18d zoKDf@uj_-ri!v=bAAgnFKW*>@FyF;_`j)#>8PChKl{n~5!#iW++x8O-|Iv38VI|m9=!plt{3szu);DF5WRU4SjMHU_A8*G?sK@kopQH4KF5iX`KOV5u$79 zHB|bR9zc)a^X8=vmXHo=sGYwz%Z_fuR+X zN2EWa2jq`3F&K#-Hq101RMWa6TZpF;&uzTs;*Q9B=ll7}#%j@VkpF-P zauj?#;;GLpo2@D8GULKV0DgleW-;>8Rn>;W$+zn-5uz=t(dazhK|pulwE;AQ<|u@Y z$lTuy4-eO0x-UGB2;QRoKATXRf@Cx0A^NU=n&jm4WUgwZqWNrIwDocr2!|+ts>K~a z=FiqWgoHris-CwVFC4U7 z$d;c7s@hd6&|#yE?j0I&C5(E;?m_|{VkBbAui`b0@M~ylO4m-+C`99mpqNP!V_&?@ z_*97h!xWP&{FSS#1(^xj)q7Y?@wKqV@R_*7!_+5M_w?|`(nbl80^w{W`>u|DJZ}VYAvquAxP_H!?S4LrGj)E;TzqWD_Lf0`i7xR={AEmu<&#@MM8OHbIlJh{PHDuvWC~#y!82UFzLI|lln=>zWg!!E@ z_?51pwsb&!L5br?aCJF}&MR@RgbL25rGzf|sw_h2C@oE9+4hF=SSA^V;5j?~-91{Y z1@X|NDMUh^LqLQY2e}ywz?O{RL<4H<`fm3?e3b1Q*8ztKx){YjG?dNjzo;8sc?HLY zOnMwAcHa2sXq#stb&mb$H1?4jUw`7FF6K>w~^kOV`B*ALk&@Po3{*iUhv1%B-DVJ9` zA%8dEFwBrl)+kK}V5X4khsFqthX4$YqzYL z89_izZvLO|^ux3KpA8M0URtiIDr?^SWgI&@biMj9qodCkU9b5>mw=S5(U+31?8eo5 zCV=qvW>gwSkV7F6GUo8&aB8RZ{1z4d;6J~~x%4^D-|~%(E$g+&wYJ=cfco)#ckW}4 z&L&MFo7`m8=V?)5yuj7ZPlbN%Y@Wh(MEMI=r;EyW4$ZY+r_FV{yT;5KRb}H+YZU5W z=*ge*VB6b2dUQUP#}5PTxi++L?QREN{+Q!C44V7^CC=fFz?RLx*uHsub({3d5I70L zGZl07HM*k11BdIk?>>F`!V)wo)Gm(DDBzCZ{-HB)7#Rk_9(tzyqL-n7H-$fm4if%^qaG16dp zJ$`n1oa0P|8m>ZKgioa9}k5j+rQRb)^#g`*n&~7B>)ac?m%lo7wJy7Lz@y`tHSLe|mgW1G{GuryfmB)uP!g=V?(9iZ=1*5HehDo%g_`hHsQBY1Uw5sM21w{Fw^}}Vqot7`48Yunt}Qo$D&8sX1YVT4@^8K;>#PjC6?7M;Oqe%)PytvDs=t`M7p(*FxvmJpk5w=RS9QD#~12}E!0zi zvNr-}JzCg_q{>xmz;qxGo%tyNOpKiO#eH}3qXKBMHJdErgXy5;iwLWQ_*q~3W?C$Y zzRCg->6sYH8eb)~Yik(_{zejRl=S5gj=k$67Jpk+6=s*ljh?Hk2alKTYYL5T+U^t* zZcKcB@H0MhuWM@BS&Pi7_q|_A?EmWOdN)?7zzxOBfo_t>{Np8cR1>ttDqVLkmU`iA ziho`0J`k)Q;>2?%0yd8tRdpO7$Ms3TAC0;CKM9!9va;xq&QIPLN%aXat7k+~z@j;^ z&G5;$&`qst{qV=GE6_Orn|AZkO5W(%q~h-_&`M%M67qB42toc14P~R!H0mV(o<5fH z091bm%%;8R5N1=uBXNw>RLf99vGg^*RyCerREUx5l2A_)Hd!9cpa!R90!jAeE9Q8D z#Xfh8soLOR<7;}E4@cr`7QKYBG1p7)3MYySzq!X6Mb(7)1z^XS8qb6oh&@jQ;k2D7 zk4^f|RlCvc&_&tBK7?=w1WQD6aYYo2Pm3v4TbplveGjY-=U2B&jjzdqY~a=B*BUQj z@Z2z`5%Jc_%9e%(Tf<6~=p=I#)-WmDopIz$Kx9>=hMoG)ZDhMF-&SghJTYpGJ`^0< zx!Tg~39L=iwi5iF0@&JGvev11ps;?QDjKdeO+KB+c6(|IB~KgAiRmJcBywHaQIqro zrFd+VO3yYZtUxbbg;@VV?G4AT&RT9iiF%HWLh)PDRZ+RiALH3oNETUs2dj|ArOZ{O z{QE+gOd#2<`5sSIu^j7gHxO#7Ve-69kg)qPpYI8a9`g)sC>7pYkwGtBJKs z7$JKnZ)?OQ$g41v8Hf&avbS{^Idf$r7-wNld0&c}Jwi+0=tSP+W(1*k*IjX{o^Zg3 z%6}wMqGxbo%{;QLO*fhX;t=)04i&u`dz~meN-xvV!+)KC*F2FyG8vTZK>L&*ueK;a zE&*x!m)YEbmraFmU?km&hK2OA!|G7>0@*D-O%ZPdVD1tXytq)3@c@`hDa5?(e;fXF zpo7*0M=?)Gif(>!AnJ`ZzhJI;Cx$J7xqI58!G@MiEddToSm0tuQjqhfURjY9BV{}%sl?25^7vsL9;OW!&5q%%rWw{A#K?2IRTA#SR;^9U>6FP!)e7f1Hm%>e%7 z*hfw`US-nJ?g)?|VWda}jJA<9w`6|2mP+iNfd&-dYSyZ^?1CrEnl8&FwyIkB`5)*S zvPBjHp6J^95{#icNt)|2R_UR!o;MeeFzU(bEg2eYJDZQ@pUFYvQN zOvwG&I$SeHp2cncb5PTjWgAV`CL8qC@B6Zs1k*e7*|RSy?m#Fc;sq|>1;##mw)ge- z-L2@-=gy5!Us-t;JJ}$d1|6dSqa2Y(1!}2)5e$G*pQ-gX5;RTKc8WH$t4fz( z+8aGAKFc2d#LYM%WG}1wa4^AMI>&&Oi%7mc1|Q58;be#YxKL#Dv_cvBY&{0GEPmb2 zogej!g-s=hMyIA3WVi4wkvRYw$Qj%mS*$h1#*Ox&x6V2+WJ<;^{Nv?3e~x8M z+a1(t(mQ77$0Os+01BEh3FRG`1U6EZKS*A$RUl=884LMG;+3hI0tmCXy}j)$A$@x? zk+{9Kw&ssgq=e{GFur+2BrmW)rNshOub1N`Jcz8~&EQB;E94h4Y{5ez|7N(g@D5tN z``RA*@}DPAtNFU%heKyeC{gjKfd_qxN+zZ%FlcSR@nIY+To~b-7q%2LH1FZSo!GcBZM5<)$tnK#zUTh-BfLigYij|j{}CAW z_8{xRU4w;8C<>MOX4Tz_+#b1pxv5iHs!F+vJZyN+bEmVhDsYK3~ClZ zq4Pio$`jEMLPaXRelkJ5Nxkins%`#ES15=}MHhz#4u&W8BqbER#3Z~r+h3BTw|ACc z2-j5qxU(bONIzFXsEpFSLeA_&hniUuR;nb#*Tf%Pdzf8;h#xdKMi3w2D1 zb2PL}BO+f#rqQLbut6pj74Tz@Lx`Oo6M=rGGsST1-U8Ti*3E^_I*nj`-kQ{>M|BQ2 zcju8E@6V%m@QY7^ouuevT8{S)f;g}VK|qZ{@T|Odx_s3$aRntpJad(SoM`M+K5PD! zkYAS2&5}~K1Q%R$L~ODm7P9}XI7?SokjgM+*YCZkm{b=kv^h!Ro3qx4S#4gH%7V5& zer{`QKMEjgAEb;Jua}lEo0c;-;?)Mn)38>3;V#>Nv+H(KB-A?ai$J3;TW~PEX@d>6 zvL@!VF(J1O=O==hjwh9@>xcLt1;Qxe=>z(Edz?7d@9PkQ+iC4@n{eYOeK(;gs@@?bs;>KX&)Q#OJ=AxHp0SlLx9t&(epxRIm`FDgu!Ev%)F zcX#J=KGxm;T*_sx?cvtTgZY!rR|ey2jYEa};&jJJZ7l67k3n22B#csCYZu|)zMb}4 z%ZFhHo!K}Q1iQs-VyMHu3Lu6?M=L7IUWX($AilnLFv{N?>9jK$s*V*emQ__VH&03u z3g#8+33nkMLLi>#)^Z6fbzYVd2{C?& z958)1i49`@?7I46WTZ#}?@mA-zda->Nt<;$UGg$Xhspco!-2PsD4?5ZKDfJn{&f@A z#W=L!Fay$+N7(Yuk~QU6Urh4KG{h#pFO?PhS01T@@Fnp zE4GO-d1HrU1wT5NQyW)rC^&+{zZ>yUkv^m2S){M%){ap&r|%=Jl@^iN;kh{L;UAIEXn z^P52+oNO$LYSXHR?kVu|1~_wIg>^r7z^>9@?>4v)5DA~-d|+ubxim)lK=2z#Q=NTu zXytO`bkyez=6SwfTtet15EMeQgA!klnvl$ABI$id!mxe*u+c5+57GTbNja)uLZd=Q zA09DYpa7-N=`?XT-f6JJw46;<>@77O7*fAGvOttD8N=Q8s z>b0dC9M^o_!Zm3<5Cqz8cG@kN;8tX|d>RF0Gr3TPrFM7cuRnb{;toB7k*4C=y@ntm zLvLrkoo9xN)``?r)Ux0V#mtd5Ue4iaQbgke;V}5hYU&d~Z2Sjje!AVRxv?t|V`n=m zU;*}JgjS$sM`?7F$yR8{3A3Cl6FJ9F)!UVvhG^%al`lGnIRBGp_Nk{ zEgb*;7*eBv0Gego0<7wBsq2fdeEn2+o=uLIqWgNdMihKbC@kH0QoE^)3TiAef|Q?O z;7X10AvN@b2<)4>S!UT=6?h_HU@cLP<7j?c(et9cRcvN#94-|&?m9gNKanyZ=^` zf)>8lvJzVQ&xKi>uv=Ij>_LaS8&L%@G+4ui(PmxMgg!2kt)s1;E~IH27Y9cm0wf?{!qLl0X0jTItH;!3*< zc+ZQE;;YMcu!WmZKtBsH#Pf~AdB)C8X3AkE&rTYTDo;?YSb3gK4R?I& z@g15*V+4BAu#{<0LT~ zF#n~;-tZ_ws^#HF^!b&k3RkZo1b$lm8lL`{t)9RM=>Xe_^P#a>$?aKFnID3pTq#V= z5PYaj*$<8tQf;hc;7ynKb~tjI2AT3FB%f_8v2(lV0ezW&ZlT0k>b$x~KZ+O)IO8V<@o$FbB+Qp`Qvywa<4 zCW@5o$?c#1EZ8==(|M`?}q_(5E= zlR7zwH-Hg5PUX*nGZN(y#xIXUD!iN+AfQ8x#e8tqbUa}zz!VqdcaUfa)SprfM; zp)>?ba!tBS9Jra4>e!|9uRW2+cYj9t+pdI@MJPk#AwxHXb~Ucg+5fcwgipLYuxlsY z)nMy{$Rb(udWd_DQgUwuhldGmHS(N-HucI;kYuaysu+hf)wsA54@GW&&_ z5!$htV_;|kJ=vJLb1|L>zb=xhg{Nlw1>F}+b{0njPiTH!JsLw}M{pH`LD%$Dy}N>x zEAH`mK|BLPnX|;@~>NyXFI#I$=)JlwShL9RdatH zgfRBtppQAo2wY(>ayEgYY+OD~e<<$8VIfdNL$G7(cnG5gB3V6Fj1At9f~ zY&r8laweV-TSD^@A{K@*itDwtr>wm(*!bkd-mbU@&3Roh@yezmqCJ>1#Y(VzFPQBtAcA+14&6C{`2B(E2#>5q|_w~0|WtDv$$FeQgo zN`lHO7*rQHdv2u=7*EqNKRbp2;wrIp_!%2y`7BJW<%DN`2LN77$9CfPN;I*)`1stF z3XVttVeAh7m9{!GmQ8GNwVAk%c)k-y|JreV;!lHEJUWV@ZvG2YGIknK!(1;&#}e0)b2hKpp68jA!5Web7e^`zLpSttgPs`u)^_eP0JV>vjq zut<;pRwDeuO^e{G5l>$_FT1~H0*EC$yRH(h^( zON_ZV(S$VYhA+Qpi(e)s${c3Bth~-k90KeKI}I#n7QGwCc)ug=F%hj7Yt*?ydit|p z!Z)U^!-njjobc}ZecC6?L453)yw}jKjn6NBY{**@b46I|R_^vCX}1C`jvh-sbu+L@ zA75q_Ap*2-bNS9$It+&mgz<{{B9Q?;?CB}s<7jd-75G5cqAMR2Mxo$5LfJA~Y1V(k zOMpOZH~0WS8HX+Bw|YxL%i@@y1jenI}6 zH5=^bCzVN=PsRPgQwP>?%CqVXj0p%u&ID5eaOw9MRaIAE}+A#KkKh2F1e+5xcrjLy|SO_UwVL5BZ6GotW~G036fKM2pOp-2WFvb zTZuRCjjW&+m|5I#95NmGj^O(G{QP`2%^Bfp{4fE%sEuH5<2j;e^cPWZ|^v^!*-ifLvRT%-`Lw9oZe5 zNB!sUgFs+#EV*nj0BVb>#2WI7Z=#C(zeqota!xgcY%XU@3Z|45d^@}wR(5=&936({Ij+m;r@-^`3I{?oMym}%kvjxoogLU5gyM*q%r9$7tt$X?koL& z{|*BRAp5$dv%3{{nM%)vh2^t`ncE?zyK$y>ZhJDt)}!AKzVKdaJDS|Z_Z{vG`M zD@Jnp4l(MrdHnuj?PjsVS%AOeJI~EPMbmNjbDujPp)aev=_vB}xSGFUZVqwYbS?U< zrBVdwlz27Q)`NZ@BP$${T8vQiEC(r~GMlR2KIdd3o4AT|p9W$?O6O`yw_LMLw5*t!Fxx!6-&rNkVt z!G`|hEHA(k$}kvKq<0BE*2X80t&a{8Xn4E)vm}1dHBZzT~20m#&Dn{EJ7~TH9tT9TJDbZJ=#`?WdxC(1v}wZ@3?qajN5GE5tuPVGcD8N z`kgNq_yYhYt@@Q-~ z(ncpICj+;aYgP@WhwhUEfFiw?-bexhBZ1h+P{zg4D3-32N!c%ym1)xV*!YAY#0%rk z#G7J>559~jsoUF<`f7N-p=ObSbC{}w3MV&V;xTV6KH%EE@r>P?yoL#b>Ev6pO@?0j4w zKbai}Ps)>_xgdk*ly9@yX#TvMbI--iqp)ko8JqRqNY@z)AXFEib#OmmXtb4pf1^ko zWY*Ny8pPs@aFjrV6!affsi}1-gT%^E4s{pDqsHR2BrE63=Pxe_Z%6q?IW_28@BOdA zCIW~>r_tsa;5@Ig_7=b&ya`Kfl+cBjfkwm!J$Ssdl5ojK&o=LVcQQ%rB_)O$O#qGe zD>t2KfKkf#D6x_HJ5{zP3S6pR01$qPJD|=rQ$=cj zeXkE-&pE_7zrRXpwQuDu&(gSfNFUt3Zrz?DB8r^3op3o{^c*b#JT92GXX%*M-?+eo zy)nvwB4cTgQy5Pz9i%Q(cWeF zgOKPKL;??`vz$|K$^uU}_ zEVt!Cnrcq!niAt00=SbYJqVkP-^i)o)-H&G)s!S$2cCFtxRc?wieR=J#Y5M8SrAR( zNs0sFeomgIi4!wIUsO;En3k<3ay+(kGf4;(Ik#FLyeY zB;BN3|GofO|3a=aXctcGxk~Jcg|w;h+a^b+jHj_-{zubUhDFu2ZFne2>28Kbx`&qT z9uP@Ex zgdZOkOa~*bLwFY{=mLY4tq~;j;ymw{zFfT^pL9H32mr=np011J|ITEyfp@OJ0&i<{ z$)hqYvIj|}6ultceIw43jyjVX639S+bhj`d*2uTQD*OyUPy@E2#)-P_hy>Q|R&)KH z4~=gDv#5~g%#=j2DlU$emOd!HC`r-^`;iN=|7%b<%&at08k1nzJ{Q;2a26Dfd8~;` z!%buQt8a5H1Q79Y^Kcc@jr-6E0ZbutJ$GLSiCX`bM$`H%U3a4n^t7 zG|Sk&km8szHYCL<7kYJje;H+FH(?5u$iO4t0Cxume+TcoG%zR8G%P(mTY+mW;1r-b z$_3m-U$U<>v>(<_tD@)YLENuG$*KbOgkQ(lyOii^T~!R>Ks@O!4!gePFeY4X(n#!I zguL8j9y6h1mWM5JHnoZ~WpLrv$pP=-_Y& z^R%i2c*J6`O0ozMQ2|PyzgsM5W!qdnnx>azf3B@TrVxRxjfBsn6v}OY6&S1#g1wL= zq7dG~Isycy4>!Unm+Cy$FLOK=0r&LN7S;N7CGd^J3ZDvko~f5k*BHtwa-sg@AlHnJ zpFHEFA2HKb;S$`7Fhq%Iptk@06<~sK@qQhIg!LOMe6M8^yrn8r3@&1_Qzy#|!wc_a zU^q44tMu;3xkt2oQ}i)KhIOPT{x$@Qi}bkCIs^MK{a2O+8)_+C9(n@lMo4lRk#X@ie?PU z_TtZyT2|ney=}G1qjMU7wymy?wA~!7l1O&c^S%PtjPDNiEk)>iJ;(TrUoTR-e1UQw zhTL!Lpfc{g!5-qChX+}x%G;tCnqK14SzZP1ukRqRLuRXlBmi^E+t)pw?RNqJ;K8S1 z)py@)t6OepsqP0;JFf(o%W1nBTA(qEWEF?s`~!GNuOFXlS;e3C)m|TOUmho3@AuYT zJ8zBe@4Ld^8(nOs@~Y5g0F;$%in3uR+Xdyqpw=K*35%k!E=|N5fT96FcU>EyWPv}Y z_ubl_Umt)$)b4bE`z+M>e!1dhx4SS-@Dz$?HL%H-PNJ?RzE$tgBtRYm_bYJt*tNIc z2d6~d!2Q%}-|>u!JeRJAGB4Ov##G>0Z^7)+Wb5<>e|(Qt;fe>* zDYUXhyhjAf5U5D(re&J%FhBtdSeBoJLPo(jhJ{uFQ0Xxnh||8VpJsdfCdS3m10)Dm0{MiQUA8d1% z;B-C<9L*YQI$782*4-srvHJ+MEVsEu@u#Uc*{!MKRHK^^VE0{^B7k4%u${LO^xlq_ zBd@EZDZbW+g1;f%h~ND^pTz@6!*WrzPaFX^>B6V2m$TI``#^xu5ulg3pRQU7ei<)K z!X}9?C<6=WQYXCsu`9KgW;oZi$k)?q4FcjODq3}BH6lq*;E4S{N*o07KqcYusBVHX zj`8?man>zcvtFXIfC*SJq{dx=yGVS^aF9v9vYTOPnQSWtO{Ag*XOQ3o7Ai1U+u6aH(5Mz1{2{vNi1?T;ru|JB6-UB&CW!0-|} z=Cq8o+Ny~v9A?f0v+*mqz!Gb22Sp}o6+HWjAZlvKZQiDmUFOinpqj8xKEH^hhWBmQ za;fZ-zqfeGLnN1AQ81Y6cn&vIg?VZHa&2+CXqT)+v87c@7`1`;5buw0o_$K8BD@R( zzWJpXr)GmR)VUWCLtdeHm2k^R(07^R=}(y0m%g{_ZNR9S((@O9KY3aAUkA271)b4W>&(LM|d=|JKm`p0U&Hy6?XJ`cpsE>-j)Rs>i2_znr>>zz4pSed_x- zI{Je`Y?&msO>OBJXc1yZED{y4uo(mgvY>u+r6c2KWebded2?3|Oam2tZ=q}*H>5my zw6fiHY%}Z_Hsg=VwAcyCa$5^Cv4&PG=$5*($!71|4CNxmTkxm*`z^F)xnyyeM-tMr zUEvEd#{R^IFL3Lw+$>A=7I8&{@RZq?~Ya?dz?x)Z4FJ4!H4do{g~&qk*#9l>N9F0GQ(DZLMeni zKij+6pXRJu=K4Lz5E<6Dc0R;7`d$Jz%fcQ<&D)z%z;aX<@cP0at$VkC=&t&H#7HiY zH~)N1*Nv@!xwwGo0G2|>f1F+4{5F+s=Kqd0=~Cx z0=}oyxi4Qf(7*t!i6BDQot0l@_Vl(3*dnTbkOu%i8sJ(k5R_0{A-Y8}0nlh3+l*hY z1AKteOUf!ZBq>4la2PSwTo35A)5=jrX^e|pj&?lW06}@_KUVb(HJ#Uysa;A%dh|I^lah)4P8BIU+AIeGQ%T+jRuPk*tCwVwr645YEpufq)s) zIt$Zww&&g(ix}x(0c8Z1_bYgEU6f=6fhD&f>yC5-_T*1m@|_Pszp$Ev^6x(PPbj z;2C(_f4>z7W&ql_8&>Gli!CN(57?Dn-|c@l`=ZL!L*MohN2x+cVlqoKpx}4mB>eU2 zCBi4ow8fr)X{<8m!?Al?w(0-`8KuLBqlk`$tE9w1`689|0>0MTS7`}(k37(V6;oRp z2qnRlF&Fps(JN&(iH6IdgkhUScQR#^M9}o7DSu`HC!W&<<4dk|z2^IzifIcNAAe~T zc0Z!t)pzW;1`0fo%h5XNqH^1@wM5{hW=0d8M>;Z1)Azc<_!4+!f7hQ^u#C@UwvVg- zk;zf2Vd0`?`8smU=<`1J8!FLHMBk1CrMDE2Oc7RzQO!`6X&D+R5&nd-GeQBF`6vm> z=oBAp+?he{T_79+ouK=J>{l93^%^NFT};;uK4FgvUY@OHy!|&#@wNdRqI90ZflxcJ#a;nj zg#pj-RHKKLDE8LvN=LuL-CbEIRJs#ZLiN;*JkfQwKM?!F$aSnC9KHk9?A4iG8!OrxWTCWXsd24J+T*%BEv6>syGLA8g7hbCS9>T909p&W;&B5GgsB>(rN$dfQS83tT)e#=`D2=Vjk}9yPZC#y0Z(2E{jAw{J+?Z(8{m15w!7z zZxFS$G~B&A-fuixm*)5$RtglNueZHCjIg(C@9&8o*N)^A!hpNUrYWiDRshtKq}jBL z6nOp_NY9S9otWr;hsU|=$-bW9NeoU;e`#C0t|Dsxi{v&ftv^b`@~^x!hcuJ3tJ&79 zIX_Ocxu&zFzW#FfUA5f-a04RCX7Kua8epv92~rQ-FUnD7BqP&L71`4}^*U{nvcaI2 zN@Cz=?n~0tNOIF6i&??s&|m}N=hVY|3;qpoAK%Ml-~N$AIad96*-u&v!KpWcuOEBi zPv&h~4;)e(vyxc~6`}QKmNly(h2UbNqT*{yk{u=L6_Tvk3MiM&Fav7Oy!lMBIDYLf z+~k-|jo~;TidLWrQoGgT!|*2Xz9qy6h&QNzryHu_ae&EABD&$Re#HcFCidFPtvl<^kWG~Y>r^ArUH?6Stj#sTh*rwx;?7np)_V#r8>_Og!A)B7IP;|6M~ z{7TJmkrD@m;+Rx1%x59E1T!MGN7oDw72j5TGxl)0A-eb>x1E&pGAN@3-C~|d zBSk&W$TuiCd;AUycJtsev14mBVE}^o^kiT-A6yph;yr+h(rt3(B6S%KTXPv< z8)ZIKx3em@nXhC<_<=t%YzPt-nD33VSJ+_lK~Upy#~*w7-mn;2T;Ir1>S>NyWuZ=K zaR7qb2DWGkxwV#sUiXp0?RKZ0b{Pm8xfJcaRDVKVF;tMzj_meHdj}p96o~J{OA0Vm zCl0P#LE8Amj6V(^-WlHy14fT~U|Cs4tY#MW=-{$zzwKlpjootYaJww=FmRil&ON`n ze|tD4br%QFpif98@*T64Q7#ttn(CWj6I$m1ybhZ2czxRTDvQm|QG5fG?Jdti_)WZ#QU|U{2~M*S_6*?4wl@B?d8~QO8?Mvt z$riT4V2O-s{b~G;YcAIS(ekQV9E?H6Z@17C5TJ)|zNj_%%Oo%muw*SXJ8xO>0{h3y z_T#H_F1-Ig4zYT#>HeXJp#m1U-*AwCgPEbOhcn~Ool0GYwdVabpOZEJ-SqL0Ure1_ z6uLzD!lbk2B*1-_rQvx&u5$duN(~8I*JY(+z$RWUaZEpl*SS)a?_qKZ(P#+~G@LmD zaYoN6he>FYus>?@LIPB|Qlr%!uas_MJ(C}e_|ev;ra`AVUTR79s~yK1Mfo(r^ugc# z#;i8~#BkiDxBa4HHr%0oEhbWw7wpKF@+k}T70&7ZR5;jTwJ9LFz&2EBxFbEepY%(3 zcaRx8xvP>XyXBmH@E2VYi1Pj3Q2&soM@N#cEFH;W!XUES5s#k3MEeMWYDlOflH-8A zsIkLwD+K+fS)-pS>o*Y)A_(LT z1dQ%p(abV$-k+lHS|u9uO-J2tUc`*Z_YU>fDG&@7(CuX~pfQFu*VYDwy8!{1+1`(7 zjHM+7@^bGrn9aEI1h~>oZ8G|K>+)IQ7L3*+_3sF68v>v=e%e104Xm3)4e z)>~lJNWWBXJ$><~DkifL@ieow<~$V1tSG5}tHfHfvw>!W@dIu`-M&@l@}RR4q3u8= zh%h>Z>IkDxDoUn4iYRGtv1kUDFIca)KFbCwdnhb{$6m(Q>&1W(NOF)Krkvq+!SCudp^%siMwC* z&Uc+(i~6`jp`QqT)@XMy)-6aZQx}vc*5w*-F7rx2-!DLrgQt0>$pq{^&&CBDIRf4M zlgHDpQ@(2d*($@h*a5fb_$)jNs;qEwG2gWB?XE-yPE)`%M=L`Nkg#OnXQPLYYw}Ii zQYiSHF-J^J#RFt3YLJ5Td+m_uv~)6%?^zq=>T}j!XE%+J`(ol+!0{`q(rZWC3BCd- zdadA!Uf6-C|PRYedW3wQX z@1{rYjMDX01JbI63#x7^>kegRbh>ee>V)!h2zfA!FexzirvWEHr}0dSNlJ*TLfo5g zK7?wk{>vVcXKP{L;1Wv5rTX*ffY%}M`@gT=n|K^gr|mg#CXeaD{Emw-7;|3~hrgyB zpk3Tq_nZgD)}dQzrjay=y$Vnhg>r=gFCsvHC>RWnT>;aCngfjCGKlLSUR?=s@t9Nn z?XM+LOPo*y}TE@@Ax&a$(j@}z; zM(4Kyuj#;zy8Z2m=!Ey&4iLN_YG=Ev<$>JC$N4|yhrMpS`cC-hJX9=?3!1sq&hwrF z7ZGvaL`-nOpS5MoYZ%$t>mi_l5hzvcC zsf>N@CUIQ6_b5Ct!&J`TD2@beM@X@gvdVgZys}WXs$*>wBCrap7$9gkQzJCA``2i{zyxM1_|eS%@+*= z0QQzeOq1T`iyBWB?FOge3ZFKt(hBWKfAR8i^Y>qMs@H~oI_>lu8L0@BQzsxK0bn5; zX?W2C3KAJf;8NmyK-jTn$sckHfG>(agqluXRjzZV#>>!yEnHG4nj(_P(cIm*?BiXUi+ciS=`7Kr2g<*~<_^KTV_ z6}O31JUl#esH(E+lIX9V`038)N5FO02@F(qh{(%`V}JjnPVg8tp@_y>!|l(O+T$#Z zY4T*oIbW=Mca!RK)|l7uuA8?%I|7veRP4|+lJ%Wa+kA2VT8`FiaBm(lDSWtAdrGy` zY)Qg`eT2KTA=G3?9R5dD6*x$$w9H}-t{bLB6VDV}AOQj+_9gw1t_DsQ{_b90`|)y= zqRto6qNKJO5{G!1Sy{~hC4t}W1F)+U2vmNTYCDxi%1-6KT6JfShm>r03=n=ZI|6HR zW_^EeM4+uVwJ5?&6R1e2u_XPGK=&6sGY)=f2}5wYl}hS(_&+}#oobTqqgTG_q9CD13pi~(ZBc@68)w~LpY9-bG_~fblXvIqH43!({(~NOup>K9=|?Lyi^}AH*xX6$Mpa9 zHV`I~h^H@y&jYd4oyXB+5@r1!t@s6F3Hv>Z&ffg@z}CNwb>u%=g21Y;A2ek4MKMwV z?zH2vYIe5R&&Pw{*X(r~pNfjA!%FiffKLq=YTG=H{f}x8012%;b8lMzwI?rWRMC{x zXNAyJ2Z0hn(irLb>HX{0RsR4G!<7bcoGnxrKc9)kf+B9fTyM_pxqVO6(ZS;7fvif6 zc}!W&aiuw*1Pd@uXjm(@6`y31-RsNXcbjE+!y)lJtce=g5N`O| zv^~r$#u{*v%P>4{JukhqTvjt>T(-wF4-d-1q1*0mX|G^=cQ_Eo`bC^+{7`Hx_WFcw zbW@v3DdGum{-_uVA|g=10+eyDr{b?sv;M~Mm{br?U`*tDWk%I@c+!@0xv~dz-T%9h z&|iPpovYMed%0=)uL*9Xr+0Gg4Q+}V2iz-CTh0_{zzG6~^M`x)5pb+@`aOomkWsXr zt_Q3?ywwW0>3SXZBFb!Tu5WicbpM2%(&2N9H+7l&+HNU!IiRH&Ze@{AY*sqmK*sT| zK^v9gtKeSI+xsb2G%35{5BJddQ3XSN2kUoRA2Y414VNZK#jv@Qe!+q0uu@rz5$wp` zb~t!=nM0&j>5x6CEy|4iEA%4lQd0_Hb2%C~IcY}^ASi*f7m#S0e0lD{kw~8Q>;!c->jU?FP)%(NBlMZrEP9G) zt#b(D<51<-GL>WP^n0m*>r|Apxp&noZ5|xN;^AcnUt|lX?AKe4uK`nn2I8q-?M&h* z*F_d?f|iWh3qrut*M(l9&a+6sn#s<=2HE@0rz-7(F~)&%(@NmF#v< z6G?4E7QmqMT6N3)w0nIxUuoRcS!L@pn&q0PH4Pk?*F|srJ-oeZNoMoWyb22RSc5>J zw@?}3MskQkmYylB;2>+Lpz;ktebF04u%?l1ejP6cj=hO(OnFPLYwp6y>TwLUT#8~- zN_gb%#Y6?3j1~*YA7uhuA8P3Jnxzi?f+uPG4~KExk)^}Amr90qJ7&sK0d@WzNp;5I z@Pl7p3vL0+kEqAG-vk!rB2U%fPBC8Y-Fv${jm8uw?_0I znL@7cCArIKXL-$=KI-WKAY1}BDz^al<^lk9 z-Id1`n9|Sfj%AuoYeOx~%|j&Ss*P_~ay?I6QwTjy7au3TVSx+wm9+7b*eq7y7Und0 zOeLe#(dvSD&tDOAj=Ey$Yw)BNYybQ#$HR%>=0Tt--(jzyb>xU-1Q)3z>O^eGq6T*3 z6sO_ye3FuhtmW*jh_RVXs|ZBv&cb#wHFYtF%XUrdhQvh~s#g1stGX2MCkO6s~9I+Yb%9&Z{by8^yN< za-IKnn~8h=Lk8X~_l+DkZH?OidNS~0uAAevn+^up3%+-gf3nvf*&!yMGVz{HPCNIq z9bX%=g*~dOZXE9)1jMfLu?&5O5`kl zOLS&-E{u?mV#{ggbtA;^<@R^?X{a1Ov?wh@6cI=zkX+`AtA3s(Bp~T{fZ2# zx*>|A6eafE$X;)Bdpz2ni7|d`Vl;MN+({L`%xMGKK!3Zd41IR@=I7sPuU<@U0OV<# zQ(8tRfY1kYqZA9eO^0zLBtF#zbejk|ZJTcI?~{P|xGNgZxf>C=H}qoL^2x5J3y`uR??e5D>3@UfwT}?ODbIYLo!fs-=3`hYVy-X4pEQ`qM<$8 zTvf?8+-w5njOkc3i4KPG-<#}-#J?L(FssKW{ABi5kN^oe#V?`m1GZfqEo%?=zgx8| z!Kp(xxk3$~Nt+p(9sw|ay=+__y3aevb}fe>h|yegDy}xpQ^Io6fsui~0T$eMq6sT1 zdJ6|4FGOuR9hm}bGy=D^$}0BKw2vX*YV%-(GR$s<`SQH2ij_jrv=!5UbYPGR`r2MnJ62<2 zLN8Fh`_Yn|v5Y1!4I+;CUglt`k<@b$soTC;2Rtx8#m}nf^03k1HBGuRP|SF54RhjY z3*O6X9{@I3Tj1He{_l7XyyHi4bUl#(PK8LoX-^O*Qv0aue+_#%U|C!N)v}DWjDnmA zN#7!d14;OVkwrSMJV)rW*D#`n9wOb}U^Wy6C1j(7cCapuX&N~4TxW_`920q;%1LC|FWsa~~01yJMq3wxtc zR47!~Y%|*nm`rW5JhD|!qj|=g{}n`q|7$%ItNZkOcW7uxx8q{3{WgqJ+;dt*-~k34 zOQ=LX?LqcVLtV%@f;Y{6Eqsly0Vb{dkL&A~=H$u;|?}27_9tQh# zOLAh8`TN+65~GhsC+;kCY1!ET{w$#VKs(jI_uQlNnL-kLO10YXxFr4(2p`CaeIo>o z9{X=E0&aBr8Ct<8gI0sg7mw=!Y*BaE86}@~v4d`NT3$B0UJl<17>ElChlM{U&rW&% zKrtVf%UwFX1*k`I{yXz)ou7V(0?P})xBVg{?s7%h1Z?IPY;A-)$=|>u1U}909%#g|GHi zl`w|UpF$KLC%GU4%rv;5L}!fd(W)Yr{%+(!Pt#PkWWBty3=)b2jWxX;t7qZH9FpNg z0_vcxfw+l@%C@rzB6f1Y4@nfqI+&j}Y7i z?uE|<&jTtBLF7pBq2Kc5(P)UjMevNm1#%B9B0D+=&=sYenT#C$a>|3n0(DfI|HI~# z5)vKG{Gj*?iwum=YMTC}ntu02F)&-z(%s$N+#Knv-J7*4z1gD)kc9NNU)@0`GA+x; zy$c|wcpl|?mj06SwcO`mM&i5C7v|dKyyQm3@eieR&c~)2kCe*{TJ~r~J)`3%;`(uk zD#%kwUrgqldXjMC>q3ceLi(H@RO~KlM;C8MwHHmzl?jsj68S$F+1kJvgvQkHJf^^d z8Fv4+GvNhsE?1zHNQ@@q1=0vEuD)B;?c8ms7HxJq3v%TkzJAPo4hv{`sSt<>8(2F(@i4qeDrIHo z075vUlxC7w1;BAG+PB)#JJ$)X!?FS&&0~w>Fu7S<>NPh6o<-jgwJ$o zNA4Y1j*orDtdZ(>Akg+tEjM6^)B`5NPXPf#FY>FGGeTP=0B`1z`b+>F&lQW7_d1h=qYI+oF)xd~f7>_$#ry8u3Z6VBHJ zXy>9XY;gw#Wvz|4yy~#`d^3tef!REsBA*2x3K0fQ;~2KqM@|U!6g12WHRH_ruH)LA ztV76DnG5?#-`*GeO~<3=1bq_%zT6~GJPAd-2fLy{p*Sg72b1FCi{|Fv4z?NKa0o>t zv>?Fx{BEVSiqRYIW=c?7vdLk!l~8{JI*VgEuCK8*uxMy?>5f+mJ7}(oaAJ!dq)|)& zj+&htZ>#r`mi|oTNb&1@ga7XOeV~gDoR**cy>!)P4G|wYHps@u?apmjUx?8n1s$9( zs&t;skr;XvE*OCcS-v*G!x~xwmu@=yDx@uox{#VZb-l^!(@Qs`nh2 z6)OS>|Gf$EQxRz*TC6uxs(02A{&c6=74m`k__g}8rxSNjzpjXXK9tpZ@}r~bF&!gFJ)F$0BL zBT4`%it`=0nETasd0(m6R&8G&-n)^g=a=%f)0Z_ZU>glVK>xP!T}E@0L00Coc}zwE zK22UhkOC_dv2E2z1Ajc<)lG2AV*pIyddDr0;{g88drvDzM+XN$46BhlNN_6qpY{d>SaPagE~=kWt92hA;;Sq* zNCX-@WEA;m=v5kF3e0ccAb@_haiSuhLX-8T%t=~lAU^^bih3i+`xw|+MdtS1wD2_I z)7w^0THP+)wBqEhx6qMg3u%NLYd=6geEfJ&jVZYS(0Wrn#EMb!Xp&5Zgr~|gyksKO zwFA4Eu_1-13AE~G$#C@8sFfrQ6;q)TItc)4?!APWB8t^YXv3|}du_xi=g-u!nA54D^9M7<8n9$oQ)XNEScb==*@|7nQ{%Hdf`aXuG zypZ%EAMCel0GHwp@Fsa)lC34-E>k13iT0h1z;BN=9K{&FsZ1l8>u;wn%UIk6vqkD< zAyr1YWuPe9MBu|rO|7JdE#8drc-bCYPNM=W^U+S3*dI3ZsU1>3`oDa^R2QUyXMA^6 z>uu&@TF}+{kW?yWKY5x-PXYSzC;a6$TqxMR2oLdm+_%%5!&;rYS; zfT=JWD{K3IEYPY6B9v0K+){(_8;n zm~q#^lj}rwcDC@B?Vpi3BF-1xFC7I6mA*8N8?jcT@FS%}HRrOW({0C%%Qq*B&rd*1 ztx>o$O#b=(Yqj{p20)iFTn zWhOJo(6HRT4BJe^<<99H2H@!hOQvu-D0>CYNVBPO@cAcIQ?aRYpIZqkb026M?tv0f z7t+$BYN_c8*yHhb(!g-=1z2CPM_`h@tyO>)P6!R#Y^z-@qH?8|y`Q+_wuhUG3nIiN z=DaCAyMG7F+4Tr_YgsG#s4(S3kJ#DRh>|%Zv2oDc_ks4}2B7RC$gM*7u zhNHKYFWUK0e~RQ5Fs0EKf0pE*4;3!fDX&Q2;QT48t+gB)>58v4stXUlZBNL&eMOA; znSTYWk(p|;M;wnpJw_ZRviL%imX=-l)8hR&C#QtZyV?na%B<3c*0gZD#27+-^yWFU zrrWCbEZgF3b<(anB`}nPXG|zG>yp|*BvM8B@#X|@sUOCPURxvIh3K&GC(u;9srl$OOALntui<`-QlZIB8c`k<|C3co zb>;ZW>((#i9N+z77EK&%42uQ>KjN`i3^3x5q6s1whf+d2-?|Y{h zR@e0AH^|qiv!K8GXCf#uRm-aFJb%(LJ)H^waAdHt9Sc9# zsS5)+>@1I9HcrfA-K27z;1=|H)OIkSPWdI&=uqv`Phu(Z@XrB^t@k@;@D&x~y3w4>|Z!-<{?7g&h^b+}bJ93FYJDcGNjyx}HI|rIK2OH#vcDA3ll=Ud< zhej|k(glPt#(nm(N?YN?}mG@uLppX38raEUy|M65Cfm z#-hU5X2n<4=Swd$jZ$gw`nCTiU7f(dpAAVO-e5Z^SE<&NmgCVbHV|dHt}fuVDPWqH zi{DMLCPIOrts}yy>0#FR@fz?PXS7yYo8m40JdhqtfWd^xF@mr0s9qP?n*43u1f^%9 zI9mVto%(b!ii?U06SJ110mG0I>mw5`aZ5#vqB8sQxA4*>{@B47zct^=+>IYM1#G40 zw_gH%oMZw3-1juSVe&z{7^_p?Eq&1kX6wD~Q%x~%mYij4>x@I9Y}*BAsmFj}M+0Y4 zii}H)fAO~3XG_WGAz_5Q!|v0k4JG53+d{e6EAK=s@e34cuhW6T^FNz^fIm)49iR@s z%e~)HTd((0VhVEQJ&JSax@^2YoO@@YX=q?X(>*kVN+JfFJw5 zH@hSa?Dr?b;PI=`(Sx3#Y+IG-85R4l&h9KV);^#wg5V-&Lmw*aKuCY@))WeexY@b@ zAtNn~c$Suo-hQ#YczPd237X7G9)>V78=h4(<#srC+iFPlG&(x7xv7Bj9zN`sUf=Oi z!kf&pd_z9axEJC3y+FO>OC4A-E8I4wPNl9a>xd>)OEHkiP9f?(TK{kZ<3~AUY^UA= z54$;;qamrFJvVXgW`J1>^C-6AaI#+=kkL1^syrfi;iCLxAbHN0U91m^WII5=L|O@@ zmzSme^v<@P^M*Ctrmw8jGLz&M*=m79-{LD$XOKdq{A?i@^q{V5{@(uovjEyqF3LD8 zDlwNAuf5a74$H%om`s5&2Gwm&8OYDQbJqzU%_d!KQTxq27()<;;YKg(g7gjdf`|Tq zY_iJ4VYsH^npX8Z8O9r~en1V##l@V$Qc>Gzr8~BN$#zF6NDozE1#$B6L7~a0?yTj! zeZ-MH1#cplTt4q|C+QsVs??)8DVs9)$Y^}YQW^zpQbH7M){)@oem}0w1_e719A|KC z6)lsXWp+lpT>V1fT)Znf2v~Xn|Yx~?vVuFG~lQr*mitnemCyp6oYIKr+*>rWa4iBTW z;MZCH_7dmg<0Fm9D52RyobeH$od5P-oZfvr|2iCTRMHB9d`}}?ko7N1)MT8SbE&1S zO!91IF6zDuREB~c=!%I-&$Sy(7@8tkjMnqF1J9hA`wVZpqZ$kkm;Polc;$_~OmMGc zFy<6Z%)k}{{o&iAL{oJ&v5#qmpA~noR4S3;7y9>;(9zU?u|^^62Fnu;E0p5+7olYe z*yp6B8BkzKLQ~dU6$_oWr2e_J0Txqn_ouX3oAI_@?yAFDrXx#OW-IG(0jop%`L2fH zyY9TMhv&yv+G1c5hx}Xv$2I!FyupwOtucf&E7qiT!cZpv8g427E8*~_0gmJeI2_xs zT0kR-00(9@%{vZ}P>iU6Y3Wc5?&A~`?6#^#P=LSJhbs7tE62k%UTyb=`aj+VJl;+O zoLoYo1Tq@XY#_9jDd6|a;KRj-O8o#v+>_ZT$#k?(Kw)>>ArP=%vfADCCigh?mi}CZ zI1Z4HU_bo^VjZfRnwwEjnHDgN=Nc(hBbJY-+d$!iB`={pQ0QQfkfRy&HyxZscv>>8 z%vpy~X;Jr$hL(}}>drZz>3v@*7w25Bv z9b_moyeel#I6~R6u*r|@U!6+lHPjWzhfT_=&pq3lJ<(95aE|`Cj8BY>Dyyj6_W&;L zelv9RPNs{Bn%$bO?HPP0$TV;o!+~yNZSp-Ub%Bz*#3)K&7x{m#yiMUKxR6u2y}kOP zN>;gHQX8pSSWsom@f#&V=eG{+N+xXR#FvH79%VWj@o(JnZVge*u$ zL&B0lm`q>{DD8#or5CeQT#gIB?vgpU&~bR5y8`z{SYh=sFzU@o7&Y48I0pOPVOrW%UipaMwHoF>XKJI9FW zR)35eu=bh$hYK17aLNBo9!E!m!M$mN@zVQWT0=NMyu~xe?y|pswYnYZ>dH<$om)Dt zHo93mqk=RQfiHq}WN~p3h$o6(o&6qF{%hx&e_TD^O1Rf9@86zJ;T;%={*`{$IqEZM z9Mqj*26yML5>ibm5$Nb2dcGiF!8;oL!W1>g+)t-40@H#*qldiK4;FqEX)c&DXOFCA zHynZOXnwI35U9=jh8M7~0`;YeXR!jMn)C6}UN=KssEl;s6kt3il=&+CpSUzV-5Mu? z862;$qB0d3D_8=Y{%k0}47bs!OC(cy?{cl{gMYM^{2M+^t#p{R!W?9?A?IqRgjqZ(m~nsP;~;~Kc`X}>pJChQm$c4L>; zdQlm%X(W_tn>2zOiYy?FwMNqTNqU%UA}>*nkICwu<{CS>-uG(8m-=0OqtdZ~A4oOM z|ADPmqlJN}q!z`%0`?z3V3uNA-NEntQK0DsX~IVge7xAkSd1e?T}!>k`V{N7Wni&s zJ+jawrvY7t2TG>ee2elEDJNOsfwdIq-9erxdbn|mD}NatKYYuQI5eo8itv-Axg$;t zQIr4p&LIoNB(E2u3aw=+l^#z-r`WsvLlgM%g@E=uaF>ItjYI+eFlr9|5G(-(sPT;$>Y;{9&IdzYlB)2L!H7jY@c%w) zMeAM69H>fx;U%DMl1@2K4X154_Y*!ZaV||u^8upgiqMMMEkh8}si7$4KnYGfAH7DW z$cLy}6kwHOW*GN0hniCj`h-Q!b(3(?xZrQCp$hH^qC&){4h_Fd^({B$M*PK}LY9*b z{_@ltab6btpS}pc%*IqL=eu%E$T8ZS=g~OiOaDvQjWC^)YVDr+SWem6C=&`{YQH_E z;X9q$fUNL#5|@v^G#pCarfiRP_a2W`2Zd+y+b^|T`l?3T^GxNSR8HxcRN{j;ACPeb z!N}pAW3YmDlm3+lcvFY<`Ax!$?<+2-I8$Mh>_3NuR2~xGm z`Y$u|juQIg6oK}b;o<+b&+%OA>SXi?^P6u^d?*8+BoYr00H=$|`q!3wH)Jevu{wX3 zt=+e*2GG@#Dx68>EOQMsCJ6XK)&N;+{Kp5cHmf+wrg%|;1kn{311hZ-E{F-^)nM#A^}M9`L2g*>R+8(4ZR&UVQct!O7Q}0%p8?Dk8Q6 zdgCqF!&*@lHP$dysKC~!T9aQhOFd`0uL7RN?ugLv6ud=MkHLrUw31|BaW!W5!zDJP zP@o$4qfh?{6knevUV%XUp1V*sa9uY7yzq9Ph_?NAHGcLx&cI{U(&!1$n2r#==mp~q z@So4Z**Z~v_%EHc5uzp?XjHoQy`Exip~+UY)cwq?GC5+X#*a%BUJ+N_hNRfU{&`7X)a9v5p$H>EJ>MJLfypNhoqubx);Db5z0WnFff*)7?v(0bSFjgN3MCfh7g#a ztpWAPzkYh!0B^xEeQV-rRBhFJLGRG{u_Azpo3#{Kg5(o=Q8;0A!1{i{;+!y;fCwT`$Cdw+zBvH1zm-*haj|3++c3=x#Ko=`vs-KL1 z5&fd|QX0Qu$IkZ{kAJKw6}hGY^e#IbK8peOrq3JIRQW!#9}M;0hxCL2cv;>d2od}a za?%Cj&`Z?5q-$b1!xAX0mlf8N(Ln)Y;U}pJcK)(;?&)RT;;`9VH32X@fO`0C&MNS{ zT9h!BGLW~3KHfO4HT%yOwqbN2gJQE5FcG_vM`AC7A#*t>M{bgCpuZhjNW0s9*ybr1 zS+yl&WiH^M$4OEiZtw4U*h$>3eYDofs34hN!Y+-UZRC30OYp@o9^Nsk7!NDR_(nGAX0Y+vx2FnXSLNE+#>Uu3*`s;;Wv-i@R9{SZ-ZgV`fc zNlrdpbw6~=eY)!OYim3eY&sgdV(_V`kb>&!AeAzOUmnh@Q9u;sCDOu3^VmI8(Sl11 z!z^tZz{;wsq*ufFZ@2p%#QDxhBp4K6fY`9>%A8}-YkaZm)hEE|-}!*0g$1;sY5??C z)H&fl^iv!gtH@n9t(f}R`y{g;*#p3B#%Z+3H1w`Ctm{61^q={KPGx;@>$V$d?( zn}i5CZ}#q1X5#Gs8DW3iBkW0J{3`EuHt(h|0SWaV(FA-D0a7U|73d^T5&%Braq5>0~G%JOS~r zuwie$nA7h%d9n^Cs8>YE{JdOW@=RA3RBm5QpfT^yRKbAr{{85;&jF}lY7NYS!Q`^| znoCotOgtz#+0HZuFny|M)$-eMmRL~cM5)Iva>|r8Z0YEiF)df~HeDmaBquHM8ooHd zIc;m#Gf4(;f_h;GK(M+Pn2@diaS1qVtmJqsPmLS6J{VR!WAE=BUGox_=|BfN*_c~f zxI9eBQ9U28ckZeEBSt!`&xi4LDRq^BP* zsFzXZ)muk{L!P$-so0{3tv8KI4GYA@hOdpZUkWc{>UrsS3@y~K1Ac?a1~lA1 z3-AciikFWG%^^IZ_BZ6Geki|EVBvqs^_b^-?Tk}?_>5`ZON>KGnV9)v<)vxSaUk$p zK_S>cnMBJ5Xb9@sE!N(5`B%K`Ra0$v>j2|%_F(vj*ZgM1$S1*#4cZn*kKcnqcaB^>1o_Kb=v0|IbcwaRF<4Y5IOkhtEx} zS3lsKWySdLUA_9>|7bePsHom9iVvL<0@Bi5LrAwYNJ|XeE#2K9-67pIpbP^dDcuN2 z3n<;)`QHDB7e2BUi(%d8x##S&&u`xWltgwePDOI6Ild1@^H%y%>Pxd327Ia$C@1*~ z+z5_18Vflt|Oo2hZSXtjV>K$rKEUq|BX?WPzjkoU?81fg`I zFGVrXNmtI8O`Z81zIRE?j${TXYwgPY^wQV4)TUU!2j8t}KO6|GzpNCwpLs@3U z7Q4b6Bg1^B6q@Coi9>BWNbzA#0>q!VnrOC_wS+WmOfYWl>9T;y#jhG%dF_Os}f&kzb-c<@uiAOT8TmnSz5LI>(|pwCX?xth8hJGQ40Q#i$@C?RbeL;cGuhG#KZaZr$?Z7a zs0&<$G{>D@ijG59 za5zqP3_(&Ki{F?lM7->SXX}9}h_bBk(Y3tK`+e82j)7Vyi$DU(S3)-@ThX@(PZjx>>uvqB|;px>%~} zhn4eJ4u%-ZQog3{V-(sUM8*qrIr1+lkxukW>sa6$7hD1@ra2cQC`9DF#-II=ChroH zr#ZWK=DK)_fYE{>S_S%JhY)$YF|=U|)4 z*>N~-&iyBfM65=nSr^5goH#+I@W$z>}+oS-aofD?|4}CM*y}#$GF}h<<(2X z4{?*!^`*z;t-P?u$KOeEqsRwk{t|kvT7h@Ax>e0wf|zcF5rQ58#I;Wd9~=S~sC!Qw zmtU$oW=+X--?x8I8G7&2O3KZ}?6&VsKAWe-U%H+XR%NncP=N=7@5j?Mu)r=z&Mq_L zPk1@OreN+lA!|*~GeTGd`Q|*xpcfNe!xpd}f%)x|;VD1*aFm$HJi7iXPuidUL?5SW zmi3K}h{Y+y0xnD9xZYmMlg|-N=s!*5+|(SM#a8JbqC2RiGt=QA=HM|d$Hm4}v5tPK z+!+G*kF^F?5^CuaDtN4Ku5TxNInW3kr1U;sYjN2fqLINY_P#tTM|*pF?EG}>%*(sz zn1-U4787O!>Q2=*^>af^)=RyzECJ%9JZmiI}8fY|q3N|6cH z0091b)^_~73Z$vF^e7UImZ(r1JsW71W_9XOHW*$V=yv?|oxC9optjyFi`9>i?|q(Z zU!VP;g%ooIPxcPb=T+M##dxcp|2}OA#9WMUsLG~@j~B~FkPCGf>e81?e|&6;!=UFj zibrQoEukbFd#UcGwMlWPuuZwfc$fbMf}LMd74z*lox_mc2BNp-$VQIhWG)SmX}<_K z*9%jgjOOI*Squ^fRK@RMp|9SNSSY!Icb%7iaMW-Le89)lil(N;15hf)uTGv^1nEyC z$EI`e_$pA(Uj7}4^>WnKc>Lqu&SN|Daht8qLsED>ESriQB{$5B3FSBKk#n|i>{wZ1 zwdOV?!eC5}H&!Rih>wt#-jdm>(egaUacF>VQ*1nwxKkcJ1Ww-E!f#q1h$pLi#r=UF zen;G+lR=Ek0ON^^-uBzm{q>F+wPss zhhNz{1q2v|zonp{$evqSTN80!4SRJkZ>PSK=Q%;7Ynak1Ix4K3#R=?*bzU|U-nGCT z=8ar_qR3NvT9OR5ta`Xt8}iG+=t|#5%9(i#?AhqlOaU|y5yjUQh_p32wW%+&vqoL# zHNp22uhtSaUL!=Cfx+O@VYOgZ_3cFoiCVtGfOCw(r<1~<z~ZC1$;Nl0xtjxQzM ztb->tW|LHTpF(5pD&+vYKQ2?e%Z-7X%_0w8ls@K)O!j(|n{>tf-wewR{z#r?)o&%N zN>t3f>_Y^-%@@4`QJpO`pH%-+SppQ$7@k6X-WxN2=8s_8Y0x; z!2`O$>d|k#@M1rq{X}Lw*p$wdE8pazkuKLXiz+Bs^>mmI+PZImI6&P?;v7^}SA!n7 zG|bv&Q`b>L@iQ3M&H}0FiCtIcqGHt%2n6M)GgB-z@nto}sDBqr$EhHrVIpgxt5S?cU0!=m-;IR$7!dX;jSGBAcnRW;8o4HhJ4N#B4i#nrm2IKa}avu}JY3 zijJqRiu#I(7y1)3WZM&!n%_(_S%|urh^B`yWLt!PO(q->tOS#f#b`fQyr;JYy9tC9VGDZ_&GG7KMCvfKb9 zx|b3Qn~Y91S29N$xAj?Aq=khA5YFiAFuQbar99I_5Or3k?|z-6!t9jyLF4W&l1qR= zEPl%ZN#7>^Oza!(oEfwE@23zod#k;usg}Q*w)}!AYj2_Ya_ofsPcl&?G$H?Pl?>%pA<|KQCQ_JttR$+@`_5x0qAJ$YX) zrn#z^NUPG0?9ZfFFDkU=cN>Qyj*B~ymn3p$@jr7WQn?o`k|Y*aRLCB*G7;sPy=7d z0?)2ejILwI>W_sJ(8Aaqz*^x{S8c{BGD(w<&WlTo31`;N6sFSgD zpxSkwOnENrZEJzPhOCihWlgk-lJMritl>|`@SPj=zM;jno1cSkRcoxmxF00G@mR8 zE|S#FZ|u!fy!$dbK;5o;5K7j-RqT{MLQM2*Cv zy~&Qxoa2OXo|Np73dW`cBNEFesugKazvpKD-R}EQ8&+RK0nQ8th8A z=DA~Zq%-}grOxx>%~;o6ra>RVTl@=AEhU!n52oj$H;KXuLEt221Fdh)g4Q&wVJ~4Z z)PGwvKa1U|$~h|yi=BJ-W_Js*o$Mvq52qksy4lk*>R`rj6miN_)q~Bh#3h~??>P(0 zl(aBI9>p@cqRj`?yZ6rR1_uXYj8Xxl)pcE~dt>{`UegRcaJ5I7Ef}5DYqO3WQs^;S zl2B23^Cy*r#9Ef}4%jC6W@fCD;9ZC&^?-j@sMmj$YnqVNkeNt<$>U_8BS_+-8^d={C!U>`+a*!In>m`jCEq~vEi3hgxMObENl z$S|U>Gau7CLABfRv#HU0K!m86P1CJ#Gm_t|Vx<-qt?<%Pi;35;_mNU0I&4?gu)8t$ zNk%9?HCv>RjhS~=4CgwSjGWwwj||8GS!wjO@b(s)G%FFxS$@O~zJ2Pu-31`J7oBWt z0>Z)wbpwL~Ak&NO4?V1`8OnAA1O(w<9OE4WJsqIN%4v=-&;Q=zh0~1nvAmuTS5R|Q3`UW~qID!s zCt;A;Dnu)k{=l#H1v*^sceA^DdVu5iG?oMNI{EX>?`kwu&N`Y^I{mvB1KW%~TGcck z^kc1lW(He1HQ$83cJfv}pK`*K6bZF-tKl333+wJ(1p&=|k6RDHNOI(MLeV=~Tgk*x zSJgWv@vB&Buw{OOM!Gevd}a)J+W0S9zwwHMc^Oyc_M&{xu0_1g7M&Qw<-9StiQ z{tkMx_ANYFqq+pI#f84?vBsgAzyIWea!&>?MMsTn-NG;Aqx#Iu4ip9Wy$(1LtMwNCt z5kQiO`o9{YLl^OhtB2_|Qag``UGb1o=A>vCFC#pl0atq~x-xVj#c&-qdd3l`iln<6 z84(-3c_|;Sg~q64%5%gm1hq;t@;y^p3)`FJ6EL~EaU|A(%8IRfh*`0!i zYXJ(+J{$2XJ4?|cfb=YM^&5**H29$zYVxox(8y<%8H$ReXZlNyK&1Q?Ylhb}I9^rs ztPG$#mJ()BFrZNdeAQG)7qJPn!A;(24J}FV;z2?GV-mi=yzd^aJ?8bZZP{x&G5v6W zWD4zd3I`%$eBl5!OiStZLi^X@Pkiz%CWnGsG_7kXY{?&>*OChL=&}fkT5_7Hu5{P| z`hWjgMUNHe9HH&=3@O0c+u8u|O|!RcQg%g-B%0Z;mDyKC)2d(cP&5ldGz2%%HEm(o z@nmYk=PDQ&!^)L}Aoq!QP){HZ;`_}Zq4c0AnqLF7O!;0EawZS=^E+b&p67~8FGm1N z_~5`HdWm5{tN#n!Jz&#wnCFui-*M3)q?MY1~&QbN^~KyJ?fm^ zco7r&@;J#b_V?;`xjEF}Zab!rN-a-p!%lDduT)c0H^ka*P=)>Wt0fA9r%(vSzft#D z!_1&YEkXJ2oS)4P4z03`?lT3tgc3{X72%jYU`V^qSx+QZ{d4z2FZ1gj^;D0csngRK z{!l>ZQL>X6Pc-`E{L+6k3%SaJO+L@Hba?`9^1$bdLZh#yp>THn=!QCo7*NH0S-Xc+ zYfBT3vZe|pCr?;PNI^wSR0HfEg)sUfR9p&JPCCpRBrVNpvS`BQAfl6E$J)tLp9j51 z8hgfNt#AbVS&b^JCif)oWw;%4LRjIkUF}p z9UaXV&yiA99gcG09Y{}7c&T)e)UR*jS-kZrWXObm*#`tzzI4XK_JTbWGn>;yKDEsV zqn7uA-}rJ87a(-X<9`-uls^wNs+JAJLqh&SVAQbJbZTmVFTvKUJbg~ZC{ndHx zIXd{prJ4}N;8q99k*bztfxhFZ9Ft^6a6bf18_IaN)ufz$${rSGl#gU6){Idq_Qd%K z{-&8%VTXqd?4taVD|Dau@~QPMvlqv|*V4iqIQ4@R?w5d;fUDQ+I9Xr>_wzJ&E77S% zV4KoJ8rDWMd2jG78wBP}#xC|OQr=3X3)<_?LPN7T{?qEd+KvM3d1oDln~`j{CX}86 zBZHN1?mKltu!kT1WC?Pmi`c!Vm%OS5O)h&TI-OtLwnh@j1%z$z0aOGDAu7vNeZ3|{ zQbHp7lZ=<+zmLO=ufXq;r^Xyrc8BcBDTVe{o8EA6@%nmqOOkVAo0?iunfznpux^c# zvqL?37TX#t2}F#>gDy6HREl#Ck&;d9RtCuac9Tua5c4%nKQ>${jL20tWK43ZZ{fO- z6e6AKU+I>{Qg*p=W<|>7HZPAmqNBiG9aWt%{5n;6)pdH9i5>F&6yPCJzFj@3+XUT` ziU~2nd*b?2hjt#KB|x$T zv@QfulkLN$vTX{aE1K%Sv?X35d-RlNV+fnfiTm(+(Gvy!e9ctf6DPsqzfU33%Gj7& z!!jUbj|qeltK9p#!@R!=yMddeQpKpK)bji-lsh9C=Nm~9&%t{>*48ria7bbu{5be| z(!_h3eX^qygdaa$m!U_38Nl>>Wk%xV?LB{R6&x_R`sNDwez&Yx)C-UY z2F(`cXWD{oZ-+{g$aV|G9k$~u>k>*|BmK9ruO{)db0p$L548+%6#W3BSHv%>t&NDm zdczU$GOJ71y#%NpP=n=_75~dAdAgp*yNkEM>#>4~rPR4fniOP9{u>Db*8sw-YyEqx z`*z2_SMos{2Wvq9OD%6p$If$XO5R|n;zOZMwe}3(LoXH8^I6g-#-4`Y4F}-lCJ&cu zGGBViAfpnpacVz5yn(6Z41(S9MHv)GF{=%t#HP`R^SHQ7)AD;pB?5}5l+_p|2&w0j zJcwvnU)7LYOqpb~7u=vzFJjXNf>P4Nz3lZ+K#G-O+(Ick^LW>%hurb#1`}+zw z1nO2T>in|@kY`@gA=u)DyQF$xu4R8_VJw+em_XpY>p~9fK=NMky}A7PQx4V&6t3WS zb~K}|&kbmvN|fGyPc3maiU2)JgMf662O;au{Fh7`}0 zV0o{W#YL*_P^q3RqFBmfP6=1SX&Hx;QN5VaIS7q|F!|U_8I#!+PD?-iq?EZjjFzFd zefOqPsbFW!_&s;V7G~d%Q%o7qX_K*bXK`NcNzdkH*|<^dEa2HLRTDXi4>$H!FW7OI zt8)+l%!J+(Y-Dj1LZKQ;W&r?PiSqkn$bT5=KP{bCPCEr(LL?S4zA&gRBWQGXTqqc(GClx6a~%J%#X0%b-4kWJ4wFN3&U7ab>E zJD*1z?uO(`!0MPH)gNZAqwDWZu_j*_u%+*e8Pzv7#{XN{w#oC|pVc*axYPnpOM|P_y%Lr<)&VIb3gWb!KA~ucol{fljFO`Y@{Qc3RPP^0 zK4i?)kB&xfWobYn@&ge^I^-akvx96zu=EwEn>le>)XJI(oRqoDM(1@_Qe3TH93gc3 z$%M$C3Pcd2#!65+Cz)q;7yM83dCfR@=FHK_m^CYlUBB_u(bCk^6uTM%w;hv`!@49( zn!ZDr`fi*lCIn%h8Ykv(;dXcXLjxzIk@|x>Tz=MJc2>me_rVpUquFCIl_~m$ORuSF zMxU35Cmw?TEutF>UzJ6>$ch~WoAvVeE|gnyDr>YH(lIwP(_wSc`Bmb$a4xPYi__r# ze6%*vG^p05v2Ww(Im^HnRst zuQ?wp<=@^Ny~jnU=~vFA0B)t#V{woR4loIN1hQ_Lb)Y)6v%>=!ug5;TA5;~ePL@J^*Ufo*_6<;o_8qPXyb5Q71 zlTKuGuXcL)q*SIN;losti;Ae!_o-~Y0hw|^JMSO9`Z>9;^ruIW3zKU*$HK~;FWc+}$QIh#}c)hQ)K zl$I8O1|#hiex!aP#4goAH#?fGye0#aHcIMm-sm(tb}tx+fvb7PT&|-2CLE=jFGiuW z`fDXJK1UYYfWa)Y^^kj(l`kH%MbmWlmT&I11_{I=(i>8pp6{M8UdTR zr}xH8zMAe#7!eSpg@=dt_V%u>5`mwgM6;Bk} z$8D9d$M6+j7*uCx&MK=FAts}kMBr==~IybF1gr}Vcele6uxu{2S*v8`n% zdm}N2!T|`t?F!y4js`4+?4OPxVf9l6Bs3+c)qjnkIxj83FORhbCLOoyaibabl{1}J za|Toae-TD4^BI_SDZpV>c`Qud=-!16TaAQcW5(pmIYHkIFhfJ{fRu!;?Qkj;zz_F0 zNSr9T9-{?>@^qX8P8M|duK_SEhNFq6o0S&7*?n)5AlcyHwMvPrhAiU%QX$O|+Q!Yn zNdquf%O@8XYrJ$yf>4W`6;`W~?uxk-B-coD#=n|E0I~39JWmJIJxy=lWmuq5UH%Ih=oD+b-9>d^m-hk$~-m#UwDYpnRi+J|ygnGtw79{sE!tfsMOK zTNWgFSUq%@ou>t%W34WV3uR1Q=!EGSQv1iftqwyd`}fOjFOr)xsp0k6dz$`h@)qeG zTOUhg{G8jW(nQG$2%M+WVY6s!lyQLR`MhU@Inib;`(NI;(~_f#hqpJ9D`C{b^(#1J z+zZy>JCnKgxZR>e141|*NFaB(su_3x2G^8BQr4m44Uy|-o{=Y9!eI;D_-U(1VhN%~ zwd-2S#}S&JS$XGVT4a2plsW;lK~dL72mAZhRIXT&&+?9s8Xhc4vFil*G?TEq_n&u065t7 zH10epxDns+-rxV>-mqXK!)pke-MD5@p__}om@aul_?!0K!seJ<0 z*(v>YiyPY8{X85E$&sFay63QBi3tHIPn$Tlo59O(OXD@xP9b=@9R= z6BwUJI#>sks$KOtzJbpm{UY(aJGZ;tc-+ZY9IAqnTzb|5kDOzfmudqiNx<02{e zaf5xlAn1JWOR(E0z;s=`pKDq59W=^sO4*?-kJnieKBzl7+IQu*dCzPIMc+iH3^^S| zM@Z*ph27nBKI9V(QaQUzN9fc##qS*)J^i;i3NZ6G{=UbV8nM*p=NEs@IA{ny4Mhv5 z2APJ=EVgP=0412o<9=3Go8Of(`ez}V3NU+$h0N^ye43RnY=z#XoE~BFkW6wB(Ck&DTyMMQg@g{lM8##i$pAAW**%X0h6gJS;=S+2f1OW8zAN(HB z?t8(&n)&|mKIGf_?dodhOYa~|(;o1vE#`iFkc(1wwd?;(1bpy91rO{x6_QXM&K4hX@l`F;1TBpVwarJ%ad;(g2rjltTD5PWLzz+UX(%SrQ z-A%{)YdKd`IARkg@v5U~&wxy+Va*3senv*JxotC&RY2Ik*x}Oqw!UBx?B}qgc+$GF z%0v~+gZ`iLki{kO_u6FD_2lV>WYGVK%wANNGY zHU6$Vije!jKR|Z$?V!u;$rmu(gfOW}wg!^V{K$eNZ$L&zK{XFs9{IQ>cW zupm#&X}J4O%LOoib=$mLxtF`iqLHu=MdGs#@rsCw>NL#y`}uD=)_c!JUmq!_0ZnLP zuTnWM6`2!K&n{CG;@p{&GMnXyCyE>yv_s;hM$$Xz0h>l?R$p#zsI?#DXLTGMIk)Z{ zw=FALtaUyqXL441f3%s%yE`l_?09)L={WnHcERqj>D#J_PadFcZWFgezCw-9Qc4tp z(d*Z7a037tfJuf?(B0P9SHJNkd+7Z=P*faS%mWRgtth>-9hw{()UssCHqURLW$p)a z;)L+U7$683Urf%^A6fc1%4~kC`P!A<2tYkrW8_fSf1_cKEuje$y}%djVN^vT=2FHOnMu zkt88ziNsQBLL(>|Upob(qG`g3lh=zIcS;E%Y%VB>{(*_emrh&#W@`t~P8M|QU-khh zLcnPuPlPy9iej)8hMAyFfTu3FJ0YUydd!Ykq;sT$mAxU@JONK@_5}1EHI?|JL-M!T z{6*=hb(91ox>eSAIYX?3I-eC1r0k9s5D}Qa`X-{Y>58w}GhA$Q-tNMw+AfaUINNv4 zEiN&b^1j;s>uEdb6hSW$j0d6;VO~c+094MWe?7j5)3|}V;lKmm3Wp@bxPLKFo`vKn zH07(y;I+%?A(YGB*rq=NOyQ)+3*uz=9C+dLSmlOb=R-l8#7*lY<=4j$s^`CG|5=86 zP_O_S{g0%8+g_2DBS@QBei^a?ox@C-Hb?k$sReYr;gjTNIXQV?41UfoFffFV6#=RO zF)Yg7f3}7V7l3zT*bz&4Qo}iM^$T_~9c_DKgl(3ljI>G1&G>S|7-b#1UnnV;r&w0}AI2mF7?Di#N!_6?(W;{Sm436IWnC1s2Kq=q zb1F>|9uf9?zRQ>ty|Br7)_0>f=6p>$ez;eyH-y=bJDK9y98;E_FeyUV^ILth;h64Q z%MV#(CYGZJvN=>D# z(Jj@={N;d&JfSVkNVhi61090?6*w!{wvWR=07c3)?3Zm?MKyO6!jL|z%FjBu8HKNf zcC{*|p@v)y8H304K^MMWC}%y!n?yZ|-P4tdDwzk29QBoxFNlBG(ry-DX9>B%^ zdq&M3swVgx5gE6Qd$htvJckzjrl|IhI@Gh;(4ODGdnM4j+z^;P&4hJ3{`qb-ItR@% z^q2yAGKs5LHC8Cpy%SkxD;m9uVk*^28CUdgkt`N5r=H+W=fjB;|FX$_5*M)FzSg$0 z`p^qjP32dz8$#*TAWFfY{v(&Ph&dmNRbMD4D;}mawiYnUOwX7Q>D;UdVn+3v5HdeM z-ckw>LRq4*z)q1pEi<`0-bBYV_{CD(HMU*mHv!F{5hFP0{z_L&`Tpk{Ipm{oo~cx# z;c~}RbmolybZd-|{(nT6O(6Vi24`(6{ZH|U8`&|-M>3D6VyO+Xjkc*}Rz2NZ&fGng zpHx(Bp>6(tR_R07n+vV&i;k(Kp>{}Pc?J&9xSo)l{P?`UI4*mOH+G>qe)cV9)(#gJ zlWl+ZZ%mA8Gv@1!+!w8MBh0etF}^`{9L(_a9hk_|1fFgy0N3$u^YW)!9i^T2yAMh% z1jq@)a!iUfvrB*r`l6-l$w-xBok9U9-5ZFLV-YaL#6QeFW`w|V2%MW>pJj=5pjCDyX#jen zljn{@3b5eLknpu94PDB#f@P=>7=ecFVvIC=OLH&zJF7{ zP~mj1Yl(Mu8e=ejh6-?SW8yi$A$Z7vfq_pQNc@v*<)=-Lgg=r2{d9`Ki+!em{MaGYO$AJirBvbsa=Lg1u)#<5j?=aufYC__E zeoy1Q!*#^rZ0qNBH zaktfnF?r{#vh>%;&h{BRE_gnzF@jGIg%3GR`6Uj+`LB6DmS<4mvmtA%Y#KTAkKoHH z^@?UBaHxOv@gf^ft=J*uMzN>^?FKmOR(1b|#{S<6&}xXk&-uW}ZRLyVbRzi8;z8BH z32sPAK{3X&{E4aeVbC!X|NEcCc5XZOY1yS{?ofX8nAY({Aps$LB^RPvUjW~ zOo`1$tsQ1hkp*(Keff%mO+ryf;yyuETFShCbmYLtm{vBkwkE;PKetEEi;4#O(`*pC zMjDDmF0HB5`Uf)$SHsMVZM=wec0{1_>I4I>;1sPd*n4L%+xPlqKPg=f_HYoX5s_HyQzxbC5&cr zphXdzJOX3J24lB9k($~2m)n0kd4fwsO9)gEnjS$1^G-oql)mN^ z7TTX@_&$!v>-b>A1xW2&DPX1$j<_UchjgqXZ4T2HD~Br(A@fq1Ev@l)NGY!wd+)?3(Q0 zsCYXvARfj#?b?KGmZl^kG5%cu8j3XnDwVWO^P2i$j3o# zUPq$4MM!Nwek2NQXY14gYI|_-{De`kuh~|Y;ms6mLUb8Zhh3C4s@gUCqLnNL$6a0u zkGf}2B51|xmzp#-c^675c3LqGF0nrdG;-{>< z4oAvzGUZL#QAmpRAXB)eVyfyV*l|7QQ5x(et^e>PbmQ*j?sF;gXA9(COSV>47^D`G z%uM3DA5vRp2_0fnGNf@CN~QrO=t78r7ncmFVVV zL`aJ2snefhFMp>eVrtP}PHQp;9DStWVc|RNJWUPOq!o~ZhV=-dWX$0qOIcrt`Co%V z=4y;0q#b~6>^1Uxe>oli#us>0P%wqbLT%}A8~0wvVwo1qM}2X%Bj zjJMA(w?7GzB<4Ogcnj|V>rw;}|9p1}iL*xX`Q#b1MAUz&LSpnj(@Ls{V1Sv+*)rU8 zbph)W36h8BJQEXBjO{>t4zz5=o*%yzyz>TAjE7fb8UkiPkr_~6!kmMcW~-0^0d3y( zt=n`|oxsX({bOZ)eZ3#_dQ(fSsHM`%iBq?|fSEYJ=OJ_1MEZP5-sq zL+2Dz`4mO$Yytv)3+*27wce&GkGPg|FZuwlevL22?9`)mQF)fp*3M7 z*4{(B$O=%^*(+zCr^6grFEb`xnpY}wVkvXb_Fm3^Lh`PdB~$w;UETa;yJ*KXJ!KH&W*F zUP`op}oSe%BP!3Go&Kne)FMd6sPySNw?&a z+g%4f^*Xg;Vq%Kx@i^-w5NPu$hS6~hGrG#Rl^Bi0x;HK=JV#$AP^AmsZv{SQe`GN? zrT$%%KE3LML)Os`~*n>B+)9`VA>lmg!7dbEnj7jxZs<(i?esz&F(lAhU_FEvb)2H z3P^7-kmCzBYs&GM@4>&$TD?{a-IWZ=~pX_jq8iiDQ}pRkn#?S0A6`8=Dxs~iU+ z(-Umr!Tl8}iyuO4RE%hSFf^Xcy#X}%K`&2T^>eH$$L$wf+2Vm7rH4`19R; zBepw^wulyEmwPia>|)0Y8-P|itXXXtX6iC<8Hq)#cVG_}1~o4`X-zGW=<0Pg<&LW| zF_ZvzNVz5{DJe?GcWuB^&n-+eC_%YR=#i5LfZ9{l>H4h-%tW+qj> zh%eZyZ2P{AlFBTfshmU)H{Gc>0w$L#--BOHqh67_+4NG=x*;Jw&APptbSwAFw8>-i z_dWqcR?Ke5L%nxb3xp#sIweWMl(A8Xlr+h1!wH5=N$-U@`|DR{@xNkHUR39F~+-89AZdjrBjR%!W_c^e1VE=FZ4hd2ZG2Mcj-z}6Z;WTuG@OQOXKxK)vmkdh?sWGG}0<{SKh%Q1_? z;JQK}pO>FMcjwdWC>MMg3JB2`0BwX%P|&IW^F|PmgUc;xi>O}GWhN&-H^-U*C~Vgj z^TuDS7l%$=V2h4$h{c8l8oNo*<<#KwnqYw#TfP*FOdQ<4e|t`-#(P#yUOu%9sWZ@P zGq3OSUN;ELimg)BqzY4cT(z`d`sYMPQZ8cGgKftI43Vzt{iapd1((kEGv!L9sIT)? z?Hu{ZHYs2$ZO#gI7SN9nyFpAMrHKGnN@T&gB9w20LPdx!^d78)KU2|Z`u4&Uno6sh zP~Xszf9RH$N+mkxFwL05r2HX09bN_URSMxkvS@f`B_FhN#d5~uZ9`p&M=2B;Ii+#d zrG;Qc9L|O?kfHgPV)*-*uU#_5oFu)#067kKoJ0xIsiErWS0O?UWF?%I2`Q zTdfR@|HD&A@(Q(su5G$`cB3DcOfAp!*u8Z#q?Dv)A$%WZv=!PZkV6*&c-&hdfFFUj zh&4k=KleZFW2RA*ij?wWn5d5ldu!ll5(+S)Ee$5C>69TU6-qP(#`^gnrvf+8dELCss$=%(dS8JV8u{_4YGF*%xO61Hu9VIktOUFkbwr_SB zNK)Fi+*lL8aR$5wI*{mM;6AcQr4OqTbQ?STteTa*bmT=6r6}KE+#$?YyhDV@EQ7Wg zoIqi}g)X{>jFG{DZPB;1loWwk)De=No-`uYP{9aI=vLM0Bc`R@*%43WWXNO`XH1NZ z`7&OCfk=Q{%rEVNLgi9T5htN1wM>snYO2VM6+|5wGN#IA#d{!_rNl7W$nizM#C=>s zWCD?r)2Q(ctVm&H!BWJG%?EOQa6XsBUg{xkbb$Tl$#}+FP2j3oPYf-F#mFlkC(drh#ns(J*TC z50Wx+Y<*v~KgZUQ^ua}jw>b=Spb(;{(COP>@4N1LdvOQLt8{8pN||x+{`M2U@Bm+; zqU~nAeirF;j9JQFRMbef^lP1~ohVpu5JBt@T!r6)P3TcUDyk}(BXHmq%`g6zWW%tc z38%;O<=G4hrz(0)kb)CW%d{g?aUpu4XcNk9KFA@IoA^JP&N{5g|9j&D5e5>YWQ4Gd z6p?P}F6kO6j1nZIl}4f*I#mVA%{DIA)4 z5-8)y4~a62^o@&28UJBqTjy%2b~^WCZJ9_jlrxl<;Vc5ypFJ=X^BiR7xEcz>Q=qIV z?$S1Y{2VL)KyvNmxy0sVK{~XRi1xxw=Gm@t3d~svqqJ$oqo0`bxZ{ssb(3)9XW{ja zD#d|)pEv&^eMfpf$w07^M*jsYlNh8K(*AuSPfE$>EoAd3tRvr7DJmm7`1_aTaTW9H z_}EO>?Gg|~al3##_Qi2|qyO&*45C+?jG#$c4H2)-uFIT@9$O%{SCXc8OM~61pi74w zU+Q&qAX7OVm*7OMUiOCN{+GIhr9o&2WWoLT`5>^hy!ah*eeHwR_c{Bw1hmP(JnbaL z{7(C|b(Z`qhpb!yuk1%{Y2`bsA_)Kc>*W`}JqBZ6tba>X7j0Uaa!~uZxR}he1>Dc4 zQHS_aFwmzBj2%dAA|{P-09Gg>vX%Kfb#T{nUc{hm#%Nc+Wl<2Lsl`OuIaJ&^k#!pq zHiX86O53%5S9_X%V(d`QJL7x72qaad>H|_TAaP~7D!}6&ud;pHyz=^@ym9Dik%9hh z@DbO^+1csY$>ffQqx%M0Kn`}_Nk)&>EgE!w`#!Om` zi(*MI4zczjh_{Bf5T*u?&*DMh!sy?B$I_5IO%hbl2i1Osg=t~(@?~(ers^`DC*fiG zbooF9uUQ9~D(HMmiMo~+uUmWu*Y+w?&4Ep^fCJ@9U8l6dbH*ZVlW7$Z)#+Id)lU^R z=J$1g6GAz|zT(B}l)@*d;DRh}7pQ_)_Oq}ae3ervS#y?6+Da`ru!uo77dB;JTLnpC*YJ#kfc00i%qFZSDS8_YS4 z>Rc|5)&MHzeBIkbZ2~Fry9;t)-OiBDCil?D;fs4&RvZekL&eQ&Pw`3vYL63202L}DL0MheyEpI)&rGusGOt*bLeeGlwZ2Wu{iv;9D%6RxI)j`w| zXZl~g_i0KW!~L#f$Lq!n)~uVn#Mw%JFfyOAPawb($J=5 zhOaJVV+w%~Y{;t&*Y7sz65JIwgCbNikvvv{w8>#Ha@#AksG-{OvHnld>j_^}Jx7N< zTXvzhF;8BAzaA|isj#`WII(aM?$b|Y^|)%QaqV~5qC*5i5oDGyIcqQQ^gmmHRS=P% z$_tx^J#g_4Z%txEwwv_$JN`Wa-0$-IW9^7t3 zA?S5n5M|0-60ehcKcHjd?TfV>7Mq{Ka_T4q3JdZ$9MsS}+&ZQO$uVX2i1!~JrA@lw z!w4S1gM#?!nCKlGRdvZr^>8yTBmzONB5`26AHUNNo{Q~0>~owu>6g6imK4AD8uecj zv8^t6+-oIa;HqN0@ zD`BGjQuLX#)xp+>A()5dhmjOxfxP(dx=T<}r=5~qZLOPXs`^W{Re2PSTD?Uzv{(Z&0>Hgwc@-Ou>{mPra-6Q}7)oO%#2l8~(6~#ejjZ~21bR!3v z8IB>LjA60SkCsVIgjhj6n~dMf<>!zsKaGX2it|HAzEov5-Sg$gwjTw4-8kC1yu4hp zjD2Vb#FldR{dom~4Zz4_veb*%1{LZ307FHi6(<$eeuzZiuuWO1%7zKj8&U|`#{r0avodco9eRMuUs%A$C zov+@XFLqonEc^KjLvJ_xB+Y=z@w({t$LcDX+`(rcyY&g>?GNi{F=rZ@= zi%{zPvBaT&nT)DrpQr4pU-HiM#W25j{&~SJT$8U=?YN`A-{$58PR8s6O99EF(}+$$ zFnRnlgm$VZ6>Ld3EgI_miOmx75dKw;RQ3ZN%5@2ElA!xLSjvhpK31BCy53Di6oOcz zL)yw}Qe71Hl7NH>qVt1En0tjjtMu1-npVn>zT`pg>q?lKyWEQ(|}!_anoQ>XB%Lo+8Wz+vB`j z^b$EPd7RyjX-M`&c)w4;@1Px;3SWEs?abp5?}PT}{pORJF(8s!!e{i~!c`d8&Fxv% z{MnMNv&GcVM;L8|<~9NghX=cmSb=ne>EQ!FJ5D?;ydDWgeU9Yah>DXnOj|Zh33EdR z{0tcVvM+Wh-GJr|qwqIbrbLL`90S52^cX=f5nt zmHZvOkEwv(%PTy+6mEV+vuz(a1TEn90j64MaxoDd)iu`%<<&|H z>XRlmV&6WfbSGwH(bpw1ua2aUe~m7I`%Max<4>8X+JelaWv5a@bF%&J8R~k;OHBLE-gKyyd_I6rg$bf2F3h%Ge=xf8yVcV8XOt->0anF^X=QG z2#;}mAM>qVeOn>%V`k)YYPpBRK|jHmW^wHGiw4yt332f(p&HYccZv*C_Ul>u&4A0C z`Fg))zhQSC81X49c`d#A0}OT;I?kp7veP#6K9?4+Q@x80U;8sEI%)X2K4Y3+fmaGA zr5}x`KKTPklMLJJtG2eb%&MqR+?eS)dJQFl2vA7r1+cmo$x6mzmpj#B)tLxCIi;8+ zlL8SLp=uUL|KLd++@rX;N&CPyK1kYuy zcb0`a5RqX`>kzx`xeAtli&(nNAjs_^!!ZOd8#BS(av!T>7KYN2k`e%m_H>X@(ZX}2 zS}xjPB7$9-a_emkD6pV}F&w6ap;Ve#fy-bZFr}Jj+Uap6eq%ZxC>Uw-pbx<)3I|7Y zxi+1Ws{#dt*B%=N$w9}@h-mD4D792mXvV!C+ZqIIpHQMAcT5{FC@3mDpR*bBG7!Oj z6^#~%8{&{&(?v5XY zUFxiC_eKYS5C19j!46$Lg6NWaw*n{?yv}N41+=qWR<3$`!z{GcDn>kJ?(O;iHD**m zA5fz?mK0^D*N}R83Q>{?{0q6-D!eI~wJfeoKcprP;amUusNs>nveJaFDQ){8GU)cB zo#`jPw$*%(bPUW6HmEqWGC2loN>xxCc?sRr(bDT2gUOK$d833Ps&+56h=B?1;qBS{ zeNM;GDA(=81eK4ULj|r$l^M?ev;fUkBTs4GRFt#|fkvA0*dWya3{rk<=MgYC_H#QV|wVOdjcijqXUH7=|Hg;OF z1ZgA5h^X;{Lqn~i(xi{AWWh8IWFEx&;dmdX1tGW)l*yA;1X&^vQv#Mnl<3bQpXW73 z9PdwCAb-Hp6%;rR@iq6U#{D)7U5Pj{zcCDzoH6o#ZN>#e@A4M7+=1+c!AW>3WWQj! z^`8L&q>%hr99%AXgh`W+tRIa^Sv>xT5kS9&X{)iE30^3LX9Lt<8YE?eWw(F%MnZv>5x zk6WaeJ{YuET2q8V+1^{*mHLKYg?$-wnN!=rZV7kEwwwchb^kHGHkfL9*M3g#F&VGX z@>SyW^kk4vF^1>NyY1>Q3XT(vLmJ~f&Xx|gw1UXg;EF3?BXSL0R~o3o62{ujt=L=% z%;Y;YFZ-*H*1Eb@04tC|h1uzE3|@od;@nnU>T`3!Hs9W^m9B*ala>iUqaWcw1Aa=H z%FIFw0-@-z1B(Sv2^%by@ih(T!X!3jywi3jwHtEf;#5Df2pmm%>Pfz5lU9DRRyAk= z8L1ZmOgcKvl$&GrSt5O8C@X#|=H3ZfwOR_MqEXgklh!I2v*MROlvw>Vk6Dy3ty15E z`X-^OuTvKBM3a>^{88L;>Mv3cHHm{m6%4Ys>vCtXAW@ctDj^y>_I}xk z&nVzvKI5Gvsg7U9as@=Rd)^x@Oa7ggRCjCUnH~01+fB2x7D(z(LdLsdgNE3Bky2Kg zXo!(IzIuV~M8;`imk4Cm=W#qFkEei+;Yri!Cah~9;+=`>Sh{VF1P$f)q0Fn>ZW76p z;A3+@MB!)7?Dge5caj&bE2D$vsX1Q@qq@6v7?JE4v%_H+EG6XO;5ci}8cEK%nrzz0 zo_SL*H3mh2s*kMExKW|SYy=>?dLwJ(8D0oK?X*y`cCg1FjD1NKombt?RL?^}1JSK2N_+^>FaK{oI^&Lcr0HNjB z?B{Ul;OxE9NOK%ms4^6%t3F42K=R>Z9t`$JIToF6b~d}G;ZhkwABsoKMJ;mIwG}wsLYV;gEEwTC_U+L;ua*V!9h&Eg!<>r}>b3 zRiBm!-qLj*+kaWU!0uFB+>}xRK%?=~L~{(H(2pJ+=lM`Yvgyjj#1GcU^l%Ke&J3xX zz?0xT5Xeucj7qf!9G4k{71(9!wZx{#xZ%3ry}D|pmmFforE5m@dQScIpU~<>A*`A_ zd3*BfoQqOk7MlkM_|u{|r9h7`JPs{{jHnK&RInVmhZ^;Db4a+^*7nPi=h$6&0mE@* zRgj>1XKWUx8f4ibc3kOE*HeKJ7+@i?Oi^HTc6UR$a6{GA)ZBSDp2Y?Zy(xc0_XQ&% zU%;UvK5%j}%G<|rdj}hJBOQA@905X1vuHg-0RMe*)i%iGGkRY!M|hugBt{e6;5=_( zIv-I=KyQd4`*EnCf0$>*qZxn+glTD~QCr%)eDx)g#mAdc90QH69cdmCY^`e8Ul`l< zB#~G}j+(Sg8zk53GjzS!YrS11SGQWX;Nis>a;rP*DHHoni^`+2++cH#UlMteNg?^S z*~$+MwMWX(@0dVjU$UvJTS*=x60P+;hD2cqi?ud6Ph_D`6=uP{DBYT~M+sAWU$JCc zP-YxhrjuWfBNATS(fj{2AR z<-U>CGyD4sBDL;YKuhyXvv8R^`goMEKDZPhi=r3{rW#ut~sU>FTxggJxF4|AgEoh67{u zNl4Ng;CJS@9$kqW?4{>FW0q687E>zG{bgT2m*v@L3>YZjKytjQL$tOmB#zN-w+U>| zj0ptKIm^eedkM*DzT-|X1Jpo<%pZ1^jP5lODxv@iKG8yOJ492ZaEuB{T>Q4v#bNLT%Y#MdnJig? zYn_DYj8em(jpFUk3HAZ)k17i*)jHM2`a7;qnUfYVK|wmD6x1jVuYFl2)N_b#yUR#@ z#%>LVuO7_~VLS;XD8*VC+!@iY#csD6od;d>aufv@I-7XQG*6o6NU-2!;y>i)HYF(f2^|p7#$SGO(5B18Co1HLmCb) z5z;}+C!vZlT#*?ju_k(JTEK>0q={p+RJ}+*(mZfw_;Gp|RQ7~tPQMJ;kjkK`*Salr zADTZ7Q_ZsUCMC_YLWZPAe=aTkFs8ZjEUYTBxO{+PP`;p)ox%6fyiQ`GoWe`uY)|D| zNpp=3F`xYq5^_7qx;(y~KKt4-s)(1^e6holS8V=c0W+u01~{v>mA_! zXlh;DO=J3XkzKE$P$Jdc5aJQu1=P1`QYKN-DY)1CeMf3ge(v#A@s18}>3$icN zPti+RYwI3oIr#m(Sq9U9o}@cp8Er` z=9Uerasi3(AtW=+rriMPb{4}2yJO14@h9=%*7IqaDbAgFKZ3MSJ0-~z-4_Y#+%;h7 zIg6lNuoCZ30uSoJ1c^07nm=ii<@I1OEuEaU>jSbVxn!lD8tf7w{j}oKs|pG}yubki zy|uwo-i9sImMk6B1HT@2hJn&Is%0O5y8;L+dJ^~Kr@i2H2oU+sgt9ykZM1JmoL@*? zY7$e3m78vMYOFeeVCEYU{kisMoKky1C&yop&ZTbB5jg(wg6*x5h)u{Nn3#W5^)}R}VsV+lU5wWTU zZkMDZRtPC6u^vnjd6|O~$T3JrE$)$6+Ti(SYC&>X;PJZHyQMzBRG2@?`zSD4L5JxK z?^bNky`NPU7&dFP6x`)h6`5zt>kfo;y#eP3)<1suiwsCVM5(F1(nVWF2L9;B)=UD4 znpGejo(C8H5IhRE_hH|!a7!Nq*^8#$z*vaJ`RDoOOfOL5YxQ$Bl5 z{uLG_D*2}WUaTu5Hk`Gs)ZI;J6(l+}rKGuJwy04*i zg_0}a?k$&LljRyf{sr9peOv)v-7^4+I;^)>Y!nv83H};a-8{MLE=py3a;2l;_ckS6 z^2WbAjH><5%EwWWT@4K{fJxcmw(&0+FeaM$RLCSO-|xKx0?OtiH^o!iuak7tCu`q# zhx;sDU>c#Qvsv35Av51YEk%YXT*ccvMaiqf`)^maswo^Eb|m8eerot#{q5*DzdJTN z-DXy0jnBu@CO_gq*6C|)X(oq16EB}cXvxaClLg5k$Go%=V0;N{vX>f>JQ!gr8BGUO zQ`WL7@)@aj+WsL@=xI??`I7ghujrg5)TJNxBx%49;X|^3j%P%5`F!u4*%A6ypX)4q z`C`3e(epY>@^)(!Dcqw4hKP_slnCLV&(bGLwUJ{%{zEw1*6Bp%OF7IhU?Z^q3l+2FISq#X-}I($xX-4bT~oA$%K9t%I8EiL`1 z@aqUz>u>A#>W1aVOu^986B^pX(#I4;c4TY9)r>(ok=QG;AkA-sN%>kxG~{WrJL=10 z4OK_k^-S6rg+=BkHHC|Nt6olyDJ{N$Mve!_=xV^i;mEX|hLVM{sf|$c@`Mf{*Ejus zs_s6^v37FZT3uMEWL{K1NUj%j;GYA4lA^Zp+&vJP%#4if^Xpp+l5IkgDXAF&=#(wk zp-YUpLy)2}**O>AI5?`ZI~WInAq#O)Gx0_}?<>Zd6BT9(G32kOmF10}8d2_`A`Sbl zOz;4LgeiD`_?|3Z{uaO;UM4^*Z@DJ=$$;NaWzB_kVX~^J&*y_S5lbf z@n=N;7Ke$3Bw6B@dkn{pmN2!1yO4+D3~41Pva|M6C-rWFJ<(Yjark zJ3obU42?!W3RAgWZ03f5-!3+L0Im_k+O4~F=exqiOyN~PFerAB>)}9R*m(96z}xEp z8P7m+Les`MK&%qkZ#Bqjy<44WyUUwRN3I3-K!f7IVa$UI$2kH2o)%^D3JEm=Eem6; z*iBc5*!`Z*p2*2p*`h)gF5&ypR1J;$z4HKAUVf~^_J?N@-%bxJ`hdaJ^?rbhjg4pT zhvW!4*9%I6)_dTOCx4z*re$O_?=M~B<^RbLaF9F*8f0u5m-;evVLC0nvexXgv1DAw1sr?p8ZZ?;IJ9g?L>{xWvbFlv1Eb&J-L zjB>Om!__*{#ezT7?V}C=HTxavS?3Ia-Y2Lzp_AQ5^4w;_mzRAovm0v9vrgbAK*b*g z^(@O|> z@yAG-sV^@Rx+)_3yKp(kf}|+MI%E1lrI`kSPqE9!mVoy-#B?-&V-Go}*UA`P2U-T8 z$@I6l*o=^*K-{lT2?_52r`I_e2q~!d_YY|459%RHBGNBu#(@-yWT?84$JY1b@7k^z z87>ci*Ydg`RYX`u^47Zbu>zjfCCi+0EhY#k*l4rQ4z0RNGr7d2C9V+1ye&hZ8&m#5 zRR;S54}qdA1*5|OS)l#L>h=_Yn{Md}ubpYW_*RdXfln!M&;k+)*rB=Z(RI1Z4sy2# z6!P*?onQoy{rd6yB_g`9xX`poolr~~#PVlem>noTa*&S2*j#^Flq^a9C*ClW5!`-c z6+JO_?#Hph^iazpG1+dtH!yHF7ZMWcaBwPY{F?h+14(hUse;yY z);_7=Ra8D3DjrQzdeTgYDwLl4<>Dn@EAGNh%xR~=dm29q*!OE&xkU1fgv(ro)l{= zj%l0a`$mR^|B`v`cKhxF9_xnbugave%rW?K*Hx)yE>x^{|-qSitay3Z*hTbVr7d}9-GQO3VCsP zDUajM$;#{ezFWRbzv8YJ*n%Y9U!3@0XP5n4E*zoZ`wzHo!1O51^k|Suza3<4tQ4Ov(#A?Sfng) zgE~)l7Udw$cZ(;<1ndd4Zdvm0?j`SF0!eedNjKlm%`&PaspGvbP9C zVdrCay}xe+**^UCOIa)ZdLn^VV9cu{FpzMwj4y!8A{=Z%n#RLYSxOIoxMO3T20c}d z_fs9RjFtu=*ajuQ05n3f>2J(DXUomezW@3Bz3Y@vJAn2Q`CFQV56*i!6WBEx-uUyRpYby2qKfOTrX_df0hVTesdF1!XuP(V}# z)BnE5pz)jgTBj&09now}X`G$zYn!U8dyz^yb}Dp3 z0E!4%nWV~Tc3RBv513gWj?lBks@1X=(~LLdVH$FGsBNDka!4pyj{w|K1!>fY5BrCk&8#pLs|-3 zoymo$XoVs&8f-EsPEp9Z0{M)425;Kdjy6n#A{p3pacRK3+-2jz6+AHPaNaHgCg=L{ z>iB0AE+bDtC5|b;?#`;Zl)yt|%d-VAg8zIeblco`U?@WKIA4Y|Lu@qm#h*$4Djbk1 z%jiNe8_h5a8G#FUERryffiR*%UA0%Mn$0`pZei%(1BC3`NczbGot7I8|n&gm9ZUDVqTWm>Wb z2V)Mk)j{aPporTbI08j8oboVVjEjMtI38@em-&`Q;bp|1o&sh`4nJi2P~E3!{W1%* zX@jNr+JH46Ojbl}yU+2srdX?{sDq`PKNl5|2jUC^L2RSyh9Abj;E#El-euBcXaUJ6 z{HF?#_&hd+d@Z5_oJDs~AUu!YQw4@W$g%nNDA&!^OnU=hMHSmUD*f*y6fHm__~mtA zcW1E?c+9|x5VQgU$m3wId}%vBEs)fjY|-M9^SvMN0*mjQ5A=GwINel56M;?5^8Pc0 zo}m#W4p?H{OOWnVG2bG^8ljyepKY5+uJg~!#-^w`$+l^bcmG-N(Au!H$W^NIokP`3 z?MV7U0`uZ{P+DiMq7|q2guGikh(JaK!|jD)DzGWo7hHJv$J~s+#ZA%1)Ge=VH!9s#SB*34 z4gWlAma9ohrw`Zd=0hs8gVqi4szs;IAUOpaepJZLmD!BE>r3HaZ=0!!2&~Cv<0zfH zk9MT|P+2vvtk6Ilo<%i<3OH$jWD4M@ zC5G~91YHP725bhSW>n;gJY7n4m>o(>mjNpic3X{WYmSCM^WDO67#}?{Mv>KW%qH;$ zAGiCSe@U%0?`UTmm;k^HX{cBt3GY6@Z5tjR1KL<+QKXSG651xS7=hh_0=*L4FUzzTiU_5_@>bNdT$d7Z?_txkDIxRdhLy zksF8Dh?j^(Fh@1ikY^f;r7!wQXZlnUCY?9I_>`lSTk;-Y5bZ=eHv`FIGg$q}24*5O zL`SV-PC}^Av0^kFwytsrFYvw$`XFh?8j%KF`@4)?@Ecy&Gi0p=K!->#J4pfzlgBjI z-^e=Cd(0|_@|qU2p=3h)6^Ky<6l9l1{hC(Q(@H-%6(NC0KDICXisJ=9pm?L`@Y--y%v>^?>rcmOUX1S+Z8Qep)Q01zHYe_` zhxUB)ojr+pGOtvjg!Y@ZhyW54#`g0 z)qQeq&yWpos7XZ~%1XJz(PQNV;ITyb`qwx1M#6g;%TxCC_&~~Z9<BytXXVL$9 z_xNMZ{Y~o3@=schhPjtkE`qT`@u(BHgH__<-oFu3CK-w-bUiemN|!;3d5Sd!g7Drq zsF=I{S38;h1#9n*J9Q+E7KEZhjogU?e= zSr_9Iz=A5H^eF$2-Fan`W-<>m+XunhrR%6DU_q)KL`oe2D=+7jqI-r0k&cVf;Xu=w zRVY+(r4W%yKRsd*z&M(v`fW5^uCz5ZeibQ57wvz#W1i(RBBIgKy1jER>t$w=$v_;z z6FOkfxa{Az`)-N8Xa84IbXcZaa#ey}FbHO7TTxHvWxusLlAh((VpHMq%wUhSb@{4i zdaBHT;j8Bp5Jj&YfZcoDARE^YQksqv&^y5V0`kVUPvvwS*JZzsq_oTMv*1S*l=`L! zu(B3ep6KbZ-cfJ1( z@D9*>Ues2$oi+E-`{Z%>)lTiXH@BHF?DXls8u_0Vpl%o12~preWo^kG+K0?*KIp`ye3&mHY{kz?Bfr^ zKcEbeSSB9qNRW-!dMIgLbvCFhce1ojrgC3ovf}9CJe^Yj!X80X0asqT)-2&Uxq}|A+?B;)jm#=kiw;9 zLNF^7p#BcXh#=~LWv*q9IzU1$~2kTV0^Y4Z*&`%A@O4C1Ax^Bjq z$#bothM|16irv{RnQ5DVa6M?Su&5~YC0BapLhBk&muIBjYTT7ANQpjx2|>3CB>ai5 zr){+EIy&EXGwjtjIW!z5G@81uk}6gjR(FY9-)umu=u zrcuAY@>FfN!0&W9XwHeCNjv$F+HtgQ>~#4XPr|O8TzMV6=JI|djH-3-w935M-P_aC z#&RnGC{=YvFT9giig@j}1$cA)J4$|LYvZ|a z^~soMw$r6x{E;o6hphGb!rI($-}h*R2ix?0KBrsq4kqY-nG+Xy3}TVfrFInp9#YL$ zZIRzsC&x8>kKDL?$Bxy_?(<%LVt77SI%Vg3{o?*=e%>i#)178`8Wro9o|e{MGi0Qr z2kd`fG6Lt;01%DWFv(i)3i_>-JvAMY)>Pg~!jt=5@^&KCb9i{K{@iRZwd&Wqds`E~ z;n7imO;+zP?YmwZFtg-TAx_WOroxZ0YMygaRPHsj?Pa}wG4ck{+MHu+f! z$FA7P!Gp*HfC_libISF;n|A47qO6KkNvAB^X{elHhv%gNmN=HuYijTZ1evzuaw0vx zxM=kfGY#rPUYe2M7k(W#Bq>0)hH_%fF z_WE2n=0L_C?@3zi!~&U$B@|I8Syb!m6UE|Y?bh;3OWuJz1f@ZeboD6Z*~*>+g(i<& zz4wrap)#>L+3gm z!kf9~YwR7GZ`3eg;3_>m%h_wtSjc&4Var|a)l})!zHi@r89QuTQR1f4p!JAugOGLO zv7YV@4!*ZwZ`zeuy`4UO&a3AjlrmZ{4}u_5Uag_gdf7{pb3XLOF+uD#U&WemD0j;8 z)86p9C}kP((s?Q=>K81CQn8>&fp2LbkkVurOTt_x78!CZ){X7~qZ;n`1&jlR+vm_v;Xg zYz;wIRP-a0>TR+L$|yOj3hP%6j`)b`8B|E{>Q{np*H2h$ZLzV*xP z*B&&(H9#!-NHfP^WI5O1ZB;;wG!IMY?_RDflWo6WKKpG#H+$#S$ZP=10C;8h&%FT( z+Y5%pqhHiTIdAVS1J2?}{8qU*eSy_`?A*|n&hqPb`sIdWdvz?$iTPu>Cv9v&{oJbA z)I%nOGyo}`894K#W*zdPikBG{ymy9y*Oc6QI4XI)#sy3w+!*_sW}76P=2pwL`vGq8 zA9>cBtI$tQfG6Y&PM}NnOsmc5 zcAE^_U@1RFH`)2yo4kpvc@bMj!D@FIh9SrUYOBYQWZZ!SfBP1nNukG(#*dk~6F+N- zSpF$Jk{3Y}=8xIgds`R1;AwFyT(pnIm4!sXxfz4yyYguKP8|$PZ!k0ajracYTG0x< zldG%gwr&4{fWq0w<@IQ)odvWW0qCsbOmTy%yYBt{ zMdyy&7}4$G=f?D>)|Z(ZVjDe)G4}%o9n;4D+E$s1uzmp}q22nb7MOEdz%53oH;F{z zMyhJYxXE?Rtju6^XawuCI&T*TLdAN+ijydg>96n^7Nw01T&34={NQjEmUn;x!^6L} zl>$_1SMy8vB7)5s#?RX?-HWHbP!u>9jxfOxop=twEZoQ$ykmsz5;GtSS;~v%>JtMX4kQ?!N`#a2X*Q^W}#HT zKB$mlpm(?~)bWtiWF1mGRVR@Y{9Be{SQ$%s(gfwZMqBZij7+m-aUEiQC~4*~@Pif5 zIZHY%e2ae&aQ$ML=reD)eG!i4dMS@S$naP0Qw7EyxN4xUbPs7hmh4 z%JRKjONFoe=jSB{+RWb}#J)S`9cu&6Bp0(bF-8NyN}%|-1j87mK>Xdb!ZJM_XL>0J z%mVi@ghb$z8qODW&vAb(ls0K{QCamgC~k5n&3D~{2ObqR@CylJ zK0I^rZ-;P)McDw~_lsB#ys4yGOLiQbXK|U}*bj&Y(t&@9_x;jeQ29}ch@w*5Q$yKZ z;<{tRwgDLV-LYiAf9Xy+IXSGn4%1?8KU2l^_b&VMKMs)w{UigC1=s6$Pg_P>Bgsk< z9%R-c4&4CkTR2e%DrMCFtQL>%>t55SxXo_H1BL+0V@u~w5k)H+FP8W=uB2h3c|LAZ zy(My%!9^F-~Tp{lrhzyVCmv7F>Yt0(IeS5!=^{!+6=Gey8Gx+Oy5Otoe zUB7k1m^}<3$6QmuET6rBNgFV*&zpH8h!-M_Oo_CMUW2~e-o=trJ4#o&l3bhafj<4h z%*{uhR~1|x%Jl5qL{C!q^xJWr+5Obfzf3^obj#qq3BN7r9{U+l$5rB+l*A@2x0f39L0M7$>#DBaG)*Khtq;HP%(;EIOiBg9dIp%)TNL$kjDk_4=s+HZw#k)1GfUQr< zH*;Xqm>O}I9@I;DL_#G zNSEd>cPzy~@=`{jf9-_3X!>x+5g9jwU-i+O>|;i>%=Y;pkc`yLYJ8E}T~FZntf-!M z>5m_QR+ivx5737=?dW)&qjUWTK95IL9!Sx?NWJC1p#h~i_|{&WqKR+?3x_vGbtrA+ z2ndr(QgI*q=LGLemsKc#l+sJn=+B3e07NXL!O_pM%I~agKgdV1t&>RTX27O$%884U zGgv8qERqNG3QdQ?iLw zJh;2G;CK-bLOa^v0U6EXuOq#=pPaFY9Kb*NQX|1nF~#d4nu$-5eBAa-xRFvld6Y2& zd#@n%Q#u5tRqPNc-tRv=nDRh*b0p1u|ckv*N=ol zmBTC|^^jIg0P`WSwmaG%(GgCIyrq*l5^xYG$RV_ESma}>1`*-a-j(|gNsOAkn-P2Et z)`bn%AS|^|-|;&Jkd!HP{8u&wAmO_G&y{)Od?FBPbDh(=+8Zn0ur^h7$A==tn$J=n z>i*9&2iRArKoR+WsBQ1IKHjhP`s~&>Lz8)W{2vUw``<3$+UwrmySvgeH|A-}o8K*8ayVUGT|ER&On)L6J}VvEuN|QyktskV z^pB4pKX$dEY|a{9?DcFgIz z`1oQa4|`U+WU7|SWGG7^@@VFI2I^=99Ex=0&Bc2^phmo{oCyc1)fqs`f5O|tW1oUE^XDDspn~JNkPu5R!A&KKWp0Wq+@rSYl^+i#*+8}5#p9X33N zt-bD=I<9YC3N87b+}rH7bw6(^_35Pa)XQ?;-)(Pnwynn=z=BgmrNleNSp`!=QG|#e zuZ}`SF{5I9^iUKzeW&382+7TKJPT9fhvCB^(qu3u0fLH@$%>J~!o*Vh{kG|wYR{}` zpW{C6-^ZyEr@L+%GbM8l70Xv)k4AIMU)&G2?6n`h5c>L819+4IF>yb~!sJKjBK(x&91$XM}B?E{QvlB>O< zL9QnUq&RfZ5pK0^5d(E<|54`!Xoz=#4`;by(m2nosNnQYo)%KSc%~=7sj8(WR=)a3 z_0^HJpoIukm_xnmgbt4zp?|XwD$urLnbjuhb16H{oBDY~P{wnqP(vS!3F2q)1ArO( zB~jgb0T_T2=iT0I>g3!_x(F}SzPm5_Kbp=mEULEc!b1o{NFzuyq?FR#Lx&&?NOzY= zgQUdJDbnDe2t#*+bPOrdEhQ~o0^feV<9PqV4;1$7`@XKV*14qbpTn9C8y2N+PMlsg zZ>CJzTh9mc#(0eGmf$-6aI1OxCV~q^{kL!uI~C?xyQZN@3*~`|KMZ2>+GDsHPVs>p z@NEmbp+X*i!dVDXjo*=@*?xY7qcLo*Rt18-x8Hs5ohaz|Bl^x=UW$T2Pau1R9YpnE z*}PfhS$L$XJmilcDalv-jLpAU1TttLl&~-9Nut;q?A#2ty+jans50YwTyt+uq0e>z zGP{DEvTg}*1|a7J%k`8j-;Ypy0w9EB3duXoC}Xr@b}v}{+3%d%af2g5o|a9Vot(ha z!^Tx&D;j*P|GGo3+?v15I=Q`Vy`1>+am)fgPy2((;Zik*jOF3D=*|J&%eJ*-C2xko zt%^V3*tOIF0l!HA;T~>KrKLM2_3o0C?qn^ZWFjnf%d8lkCPCz3;v!YNr48 zqyrSdn@*JxZ=yc-mSpZuX-bz*bBL7-!4d8{Az_4=y~+lq{Bb>o95U}nqGNiZ2$^sp zDs^2X$?xu4>T_L>|916YUmZtzrect4YFrp9IQe}e1TkWsaj4wBA}7Y_;;-ptCrS>< z1Y2AkncQ6-JOL>z*SYsR75=c}&L(w~l^C?NRPe};;s=qHk6j)T=AT`&5uHp%^bO?S zg=f3nFjBM!1!E2-WYDOobGpaUFj_Jj8XDgIl@7WF;H_98vcV!WPXQ;9Qja!##aq+d zG*HEeJo?3Ry==j76stKIG2{B_Fpxjb&CHw!8Z`d>GbH_yP}(xPe~$ukHvz)Sb&lSy zQ$_L3sD7JfyVav_eG!dq7u-|)5gy^nDAYahZZp}*e+&m$eN9{_;9KQD;b+@s3R~`n z;UT3&n)a>q|NIN>2O|C8g&%$KetPGEki?B^{``A<5MOmnR#d;Q?$Jv9#=`3rCw|%V zt?f0SA!{Xn#ks1=kDg^$0(XNRg;cdlx*#yx1gOj%^zSOZ38J#A}oO_KPEGX=_Jtq1DZlTOf zYHj~pbBTLy5|IY)EDA?bW|-tPNxwdH;cl0(qIRs6{3jP#kgfk=>*Wa(~%7#W)tE&G*;oA@ac&dWOC7CNz zGFPDhSMiVh9gSWeIVcTB)_@nCxVM-CvA2JV^V;_xVdtY{GKb>=#zKvB|J(Gf-@oNb zr%9692IWn}u%$kGa`r;!Q1>wmiL8dt~_ z9L-*+HZC4jmJv-IEFCnz_U#6GhymWG6M&%I0I=^ZUY1?~YozUsfUeUkCk66;#xouX32O zm$?1e8MrkdeX|Z^52Y_p68~#E>bMO5V^bqrV1`w^^|Eb--R~;h;<7vTfJ_#r+Ar&th)o%CEEhD`Qa81Ip}v$xg~lAMf~IYp3{Q z7@km>5sG2i)owJaUZHgGtj(UB#|LVCVGsB}H)^cC)hP?@A`$F+YYK&1n2O85ifnaMt+_5hH1_it1qfgHj2)nkC=bvs+u{3tzqmd-ukHve7%lmmq9K~+sn*Y`%QENhzI zg?UitaboD<>?_QH5F9NNL&J^@J0FHQ=N}L`b%Gq^Nl2F{>G7Mr&$2R;yn=+%>U#bP zlP%YXSd{y2;9SEYup9mT31SHI%Cq@$snfplMLsHlhX)w(Ft$^=5?Yoozw`uL9ahq` zwp5_~oiu5so4-*$;`5*n@SLpxz~XR6{NxPUR!Ypt-=B0S@n|*mjdNDK_6%y6XoQT$qQVm=x0I8y&O2Em2pT-%aB8 z8Hd6neVrvMGw@q4zn6k( zS7ZF*Le1&YUbeC%M<=~y-o1@hw)%zhab8MDJFYuU=;%%AG8TvdH~jJe9^T85q8AMc zCzB(Jf4({KR#Gsed~!>@k&46_7dITAW|}mFp&%o-9@z_VivI^5Iv`+1@xgE=f40Lj z9nG?%Lq%Q1lz7qk`CHk4Qhs(P%D35+A04w1jkV6|ZN*u&?H>U=WCQBT44DXYWWz$A zN@9TV_o?|N_YLmGrJu)@)|q%xwgw#=leB)EY(LgMqDC2)s03XjQ{Ki$SIuuQ`{BSjde>4`n=T6WXw)F@ zKn(qqC7HNio7WYXQ8ng8oKG#ut<()1l`Z=*5xoX~>wC?)G|lvP%&vQbZ)SsC>SNr3 zuUa2J9M(V6vcD8JIEw5kE>I$%$C~)G#S%{^Kquz=Utw_Y`6Mm0$zr4baIukT5~v8O z?6}=)y zrxHw*H&RQPO|E5E8AcnfXuux1ka&wR_q5+hD9Y+qL5)bKF1O zLjjfmM_gUxwYLJ+y5Eyc#)bxHA=;w&Bsx)yDLeD_0&=}T0i zepx<;00aH(#Km7g@M8oh-hKcSJfN6hil3+5bK~~H4A^~u1U$&(Z_d9<9s=Y8gST&y z$WxvC7M}TY2v{ziH;lxhzv5C50T>NTEsYypmltm80WA&~v^s-E??=7H+fCgZTPOqy zm3xiTVfeBzOZ@O0I1LCl$xak=G^dpFrMB}M2E_mYg?g@bjvYVOuV0Bi^lJ`10~}iO z)e7I7SK4lB>?AfO*5w~REPDaqvOz=07wO`wZpHRd=*O=AL(a@n&Qd1$I0 z#+&r5^xwbR8wEHpNBHyt2u_5PZTvEaogqm?sv7F&)e+Aey|7IA2Vws zIN+LZJYR%q2TqG7ljS`7pBLbB)^%hyF0NGnb`MA<#w}Y}{aPAeCPCvb!6Jvf`3R)s2{L>F!I$40 z1sV+luh*lZde#BJE2v;<*Z+8kk>NawGY&swOqAT_ccd{zGLBXumSxOulo-{ib^t$@ zVsz4uLE7J%&+X?nF9UWfgD!s93v{f7orzjO*_C=aZ?b)syk;fC2jR-^R!GPF4xP+8 z>zX{TOs?9tr}cLfI^0%QX8+yn>*?KU6y^1O`wp$ABxR9fX0XjV=*^a=?BZ2+?p0Hy z)RkinUzSe9jfyh7<(GsR!w0SET1KI%^nX|FArCJ07t)=H~saGC_>tm$5Jzw_R|sfH0G3IBw0qDFY#{!nZx|iUB)Z;D3U@rjiy!~n!j?V{l@7k2 z)^9(3J+Pt8>Bf8VySv*(y8Uq6^nSQK;7S$F=u0mVw_!d(fdhDdRZM8adB_CD&xk(6 zb*XQSW=0VSyUtywu}OdHta-ouz2ZM?XRz1!%)06$aN!EvDm9%pGibhCaMCX~ym+{3 zw-cd~zWu{e=SpUQnj_4HNK2P0e=Nv^{SD_@mV+1 zyj%}p7Fi0g7ga7p4(BW=R4?Ws_c&hGxEnySmaWWpEYI6DeOz5f%|$?ftr`s-VmqRc zw@9T9-D~k4>Hj$XeuoA_=A0LGbMji`3OFOATblmX=C4+}20i?lj3`+llSw1$FLckN zcvj}bTmpRuc}D)q?OnjnK|NyI|Ia6qS5mrx({ToHo#9bH^_iQys*`P zrIHE}CyO0RLahDr2xu|J$U?e`O@?MValYAaPg`R_s06uvraXDSoJxE9MhyJPPK{uD z)6=dT&^Bb|jFr3zQdQ^0Y;^~^HaneWE0ATZZrKD`Smw?TW;NMWM{F_iwZ$aKqMzIg zZy>0zO3KXdrZMvuq?%O9Bl~kP4&HE}Q_VPb@;Rz2K8r?T3l$N`B)y_btl<(rZaYi* zbJTkDKBur;Qzwsyot-T*%0P_-ok1QB56StP^~x{tt?#><(GS~($CNInSVsH<<g|5G|rpCSd{d8xLh7*jT z6pidpPl2-O$;6?7l4wNjEBt6Bc<;0*6i&J+I$kNx-T&#Z1D*uRjdi9dS+D!si}9A< zr$7R3r`=Q-^AREKx4v(Bl_lHxJ9RgDC--HH7wyjW3;>Z8d>J?d>rH?c#&oqeco8SF zR!ZH!hOi-eGhXE-ttExW3KVEV2#V0ga#UetBgapOV-Q+TtgeVG`*|=E8A#2S=n{*P z8#>;l)K9z}Sgcf*cIY@CiXJ)gs?Sy=m-AGnvf^W|4v@msX0gT5j=!{^OVwt^wEoWF zWg?s#Xf42|9IXuo583dD``RB~HoF_=#nE6U11_CTcl!XIYfC6+6Jf=zczJ7aS}6!IEl&`12TMlvFd^TaK+ z>>C&Q-(iJdrG~IqzvDK-S#=+vWy}9C9I$ehheQ??6&*Eg*j4)Wq0CNGKIa9FiDnDC zJnX&>@;|$B>j1`hPyfEVmAi-k-1z{e+|wX3X>_c7rFKUKYzq58o0$VuDQ;k(sZEvl z7!+x#`nyxR0z6iKF2=3!F4FVcZ4wstG(g8yd;1`pH z0%@baoM!G9cxKmOyCn{00oo@W9e`93AJXn<%i3FjB(c$oM+?bCowZHvhOgy%F!siY zUTcwY^Z#w^nTh*(bi1|ev-H3}5C=^dy4&mjPs1;wj@4u2-BjQe6!coXC(QHP-W|w) z_b*Q}0N}-aJp^iY5XW`mR1gGYSGV%B-H~8r(5TwOIm^mjP_WJ814a}9z2nvm%WMCd z^3tGX$ldNMjFwYSCnxzh(*^%#U6_|h<2=|6y?)&y>#Zc|Fo;()suHNEb7~8 z;*?2PnrZKygYv`5yf!C@UQE-)E*UpP^J%^G8!$%ZF=aR|iEnAv{nGF65Q>rQw|D~}+O zYn^Jg+t)+os2o?y#XmzIi8lsmnWT$0P_p;2Gb-+Ysgg5#-@-1weKx(lI(}$%t#olL zm~47~kYi;l@ow#h(c^Cy;0Q9yBaiTCP*q}u7#kP>Sv*Fpfw9@iYVr4f27h)#0A%4< zv~uh631btNJSN1oei4g+LP0y-rgf?u*<#;Vg{l4j4l?v zHs1vIrd!Cc{;rlEJ}8KOD@a1FU^=3Hb$KBD?=@h{2nc>RKOW?L2lUnl{)}e(u)nyP zXCmo@`nPuROJ@u$6?C4JxTSDu7wmn3Eq&dEO~3T8`mne-TW(}W2j#_Tou)3OvBts( zot8=bRUwCuuAEMHB0b+t-3SUbNgW3x``6SiOp|fQ_ZGe{Qr01nx{1xQ%EY84OAx%| zUPGvi+FRZcEHEtFoDT125%Z}M{{T#YhnLy%c>xEXLmV>e9S1)jM!hr%v8`QFret&q z`j!k-9=z*FWHUx=Rm#p`_Igy^XaWoZp_5*j=0d5@F zS*utunE2X(M;WntbRVir)t;mg(`K^y z#C3^g`F3P(>1{6o(#Dm(+nt(>^>2xB;;Lm=;B|B;4U~&$@O?~kKB(a`GBj-4&Pqg+ z^GFH}p$T5H)n@cYaRxFQx4OE(5>bF7A^?AY1a?YC4oNmD&tJWQY5_(<4M z;ZnIngQitF7@s_Gs7|UAJTY6`UQ#mo4i0C_^-O^WZE>2R_{KbhsV+-fYDU|w8c1iz z+|$!G{^S1v=jq*O%z>MBp4H!a`m(a?rW)_%7LRf9tI)ef?w94DFN9Lz6D~fw)1nQs z&&X@KFZ?Bsogi3H99iAPLrCx2gwnN-#dQnZMqmBRO7})a)bn_J~D!A-u;Mu$^VUB zOSVoJlq7H*qR6W##C)N`QTU2jYyMI{P(Fh1Tk2d3m^gkm)mJz^ZhdZz09RGnnQ$8V zSs@NgDfh~iyM! zT=%oM*@h&VjOI{K%THG$J;JK8H=%UWZ>?>NwE(}-8kb3)^zRS4a3 z=@DT9E*0yVphU)<5~L%hjFzl7q+7;&hpO{ulTY;G7f0h)#D#XTaE79y9yN8fm^$*9 zU1BCyD}@)jUXtyOuwWaT7$7KF^WIcRy3_SA6yuJ(ZpwjP)c@HAHZ9i_cB z;CBR+@s@E`w!L2k@FkZ=<9x!D=cpRbOq5CgnBQ?JQm$yN9V3AeqNvN)q21YuA7YS) zhA0O3YOa+&S2N`=oA;1Nu8)<(K={FeUk)@^g~QuV+1;{Q$1Ht$k^R{&8j(dqLr5#( zyZLAGrujzDX&dV0>RK_i8yCg&nU{UGi?kXungdS_ZzK&e5=~@o(@YN|4yEC(ipjdb z0$KB%F{*0-EN*EiKHyqh&{%D)<|rMpNfh7RY!>twxlYahcMUu?N5keJgHrw8-&qiw z!2F6oR!z+FW%6vUn-|BQNFKhd>0|5PGJ6PYL>p{HQ`U}%B$+VYUebsRM6bWlj^-kJ z!L5WwhXKU^5n$aTU?6*@QW&#dJ^LH@wpjev0s`t9{17xPZL&*}vg0gD49rX(2z z1&)hOT2|pm2$J07ZirnK%n>${8ei$I_+mHvXUCz-Yrh4Z*4zeo3_IFpgiewRp>yl)p0xbLNHhEG<>TdL z<~09t&`xXqL)~}hg|=#B4`4U~?xqiaZpK?5JFtUpP^~Q`d-A>02{Yq2qwPe)&9|RF?_{Skz$&fSGR*mWrE$^4Y*x0{ zW*!(3U>3j{eetNZbMZ*mi`I%+^PyMh-g%);R5AE`kaz&U03kOVKTA%+90jWEcJLV) zvl$2z(HKG(H8v8R7+-&yn@D=mAlc*FW%aVFo>glTCx&Nbz;{H z)-zqVL@Y*JbNN^%BAX)iFpw0MIvs*c?j29*URE@+2EYDw7LxTV-|{~=WYQ+HSnR#N z>B)fv%C+;p;nTygy+~a`YBa4VE2||G*>CfG>P2Zs1iUFuUoUdY_rv+0>W?8rnORM* zi)yG6`+Mf6J*0elia(fqx0NK9c=DB)k|C2(U{Fk<`~-sL0?d_VM{$T8{-j;PheIH66JR?#V&=Qvw?A{( zaoCW5>2GrE#7YM%?6N15tD9i8#)XtYaV!Khxk!na@a#qD?pgpud|m7+2kxk73~ws) z$plVD_0+EDj@0Qop_%8pLZ`b+Zd*|7sq+{bi9$WHjg&TVz{cQq&8YkmSbNFziGH>* zNVj2Bd@5Ff>MEfB@Gi$-;mu#h@%Pr*tgt6xSK3rtoHeMXGJwr`1ca$$sa@N;Yz&eq z#%xHwmMKcjWO{__l9ju|RMNPt$K2Co1{FiZih7@bUP1V>h(EdP105ZJtYjIdw@$=n zX<%tv=#g0)s_E~Y#6Cdz8fnRCXD?(5L^F7IuysMz=#xHX}# z%x?r{2H0`Geydl6@QnuDUiFLcc9O(n`l@Grk`fK!Mov{~s`=#5tPE6S8-y`sxfN?{ zq|mtGbKA%$c#YU%V1hJUu#(}3G3~#h)MA9ZYGtoQg4B}9WAW4gC3y5K2RyI+eQKe_ zi!+t;6cV0ccX+Wc+*=$)z%x>A5b!&CVA*T7y(?;u4u%gQvZzsNI-R{g%{m4oi{ z5%47ecky)v3d!3)d4LU14Ol?{O|z@>J2`iQmr+4}voD8F-g%EMG`1gBO8FfQRQ~JP zQLhicN^OxKWHf%)^~7o0_6z|_-vC@pXUR$e!^q4`$-65Jjn__bGl9kSt;^37A~z=C zCRiZ!H4&XBN<+)Q@=%4Wwu~rV`$;HUj#8;3oPc=Y@bWUsTjDJ9Ga$fw#Fhmvog|9; z`|f`Bc{osb`B2C|CUUqV-ISQ0xZDl@*Z5l9wAdVsNGEm-eI~(hbH*iICTU)#(b^PJz@A42{^*EA}FV+e&a>}D- zI<;0|b=03eTYw?e$*ZX$d{$P%_WV^^BxaN|Oru^Hf)44^y5g=1ar&BYto8`X5*%Ws zPzJ_+nGr_C_hYkOCbNoHb&B%3AqcDziHt>xr4vl_-0AmLg4@{RS#Bzd*8)?qCt-&k_ShpJK^&5U_wzR zP1CLz1y`oz+65KEC-xG+>1nrY`m)!YIgiW3Adi~cjL}d(O<6$0ng(6)dwx7OX(J<9 za$GLq%5|tW{kFm)7jLiJD4aRQ<^FI_;}0JaVPAx_Jh36wbHxZ|2w`=Dg_~9`y1X78 z8~ZfPaJwKwsnv8iL;v*iXF#qkYpF<}lLQ*t+`SHgm1N@-0Mt#VDu-uKk~kI#H>fgo zF9g^sCL!3#e$3V*ueCg^T&(V>c8pD}{l=CxcY5gmtvvyZ4Ac}e106wUr}&^1>>YdE zNY_STY3a^@V>(c@?C|@xs(0Z;R&~~TE?x`IZ8qN1u-NN@MsV4X)H7}pAJ)v1lG<){ z4G+_q@l-fa93J!M=Lf^XzZdGA^egiuJ+EIO(>L5X-JTpP06p=at-_SF5$|II$)kE? zD}jeRQ=>vC$If>|QS|1HgW*lOM#^p(D7z9}Tt9$`YeYxS--7(sU&PGBpY5~ zsbjTa(NdI4sGk1A&@QNptXDxN5y4I@AATC48l7>t^7{I(mHtMwu%>#$pL!7qd!dg0 zTopAv4167(@^E-Y@kTg%R}zmhwUeCghFoDWWlO;*j>SMpd-**-o5MNC7X z(gA^2)hxJ7pb}g}*l+7=8J4dqT-bf=lM~j?d}D}Wc=|UwiK^?bYCKKnKj+Jhj!|d$Ai&m` zr`P&a1O5Bx-bfoD!%?p11vCJe<_F~Gb|@6E0Vl8M9@8FQQ$qt$Mh|>g2I8F+??lBH z1w;C)97mU=A2zUSxe^_+lq@knNuVBX58WOYggbU?&}DHjX`aMabNQu|TmK1B8T{eg zgGrQ;>oFDptMwoz&n6`5X4qz$cO)UFJ`{GXXY)t?cBBZigZ=lGtw zs9?WVya%z?8QPZ?MA{^CDYFrv{hH|gmBMCezD+6TXpvYg80Y?Ux5H)4ecuAs3yzE& zC@9cwLEu7@DBCO1l9S6&`agQPFmykS*ettZYef|%8&I`!QO9#c%Z*?P@Bmx#^z`(A zc2{jO#$Q2SGy|(uO{O_H@7+a@yodh$85502)7@^TC%~Gy59mZMxsUJZnwagVZ~}c| zD6)B?#2DUE(VnRO>riugQu?Hu?coIPv1xXH+2^=j4TS>g#JrQ50Fjv5_4=q#+z0yv zO7`(qvz2M^w{hz-dLaV~m?Ctk(TC7} zA#kBkgeJ~bPlKWy0r(`c3|#c1a;fpLa=m>}+Z)60fwTSoE>Qx=K;nG?+)58UHVH|m zWmU_OF;Y9jJI+gWC$;(a2Ug~Fy>|Wme@Q&~d=M;tBA;=X2flcoIavA=S$aTp;@ssD z8sd2hrpR)fZGIkQY|be`i@$=1e;wQr^UBGA!=Q34UuI{~ST2SBk`C{R@gV-kupLe~ur?$%$bL{bgQ}Pb!83d?FJ^ zfZFvarcpmT{g7x~v}goYPs`JPuZ@M4Xvx5v- zw)%UEC;h=cN=jTy?Xl?tbaa#w=>&X#ic(lrJ%oTl2W|ZN=Y0j3u?_MV5&eHM?-TQ6k{v;P3d z^p(9j`h^FrMqwL@Zfjl8i_BKoIgy_TM=eB2D}o&u-Hr*9nqZp;eCThUn)?wBf{9$F zoPV*X-{e8zgT=kiBea-8P$qFNAl;h0+Jls^WqTSRbwCJO9;0pD+1Zf}I#lBKKGf^* z7#K5hYoC7KL$rGpbX-HxvG$~%&_Fz3nR>-{{`j%0kHTbdB#MA;gx__kV?B<4>~uq< zVwedJTWRCV23L&hT-5{c(%LqV>h#vw;%wEi+pz`IZZUCj06a8HPvHDMD?fkyZ07Wo zggC&Ae&d~hPf!ajm@!L@Dg?xc2Jcng1pWBQ*!SiQQIZO)51GtD6LVez0}0~`?Nb!L z9X>>)-%gz}{6Qh!rR5~KR+u#B zQA1SuT#b|iHYy4FSoe1Tl%;O!wLFAAth@^F7o6YRG~XTFPy0$FXh-|Kq8zC(<%ZN> zao%^Jhf~4|!E>R`Qf$1D665WanSYnqa%SoAflH}v{%XK6O`45^OyBXt5kF7cHKNPB zDrf`il_Ae?1ciiq(C8AduOZCgpDT!C=b*|~@~w$i8&T!+dt>EPOMa=!+!oen_5D4XiMlyxXd&Q%jlD2Do~*1aQ&ZEH>)&{p{PY+Q zF-s8ON^l$l%vtHc-|D}et1JwLO+W{PH5OgT*>c{sS*>&iKMoHMcLd(G6Z+*bvGX<> z0vfCl>|5Z%q&7V=UTc2L5ZtzQ||9JsyI90Sys>e>_ zGLC@KkKK|Rpf*T!U%2dHyRieu@f_Q+agkRM)^?o|3t-g#0jwW!pr~Guzlh8&hl`xl zePmBB2`it1R92WlU>!G8ehgDn`=D?VH zoW=@ws3L!(oU9iQDRGpwD1*ol%LjEu#&4dqeXQ%mbo?@l`Tgu6Ln3{mZziJ^`TblL z?ikSJ{#y9?`Jvp|{te~-JKB-D+pVE0MOsBY{iY0i4(w^|ydh7D7ji6w+n*LOVnJAC z6yS)bVxjmAQ92qJfg~Zsta2g(O_FnTd=3&L*t+l>4?mMx4g^D{74c|InF?fxKpQ^@e;L!!{J=qJf5u*H1W}VtQ1rf@}6Awo&s;Qyx|~D6sp$4Dd_J< zBcJ1y_KjpEJ3D>JtLE|LHb2yVYcJ@N2gk=-GI`bX51@upPaY7c<1?(>pV1bT3uHG8k)SLCb7XC)HlmJEi^~ z?twFY>!lg6XNENrZ&2 z5z;L+)=2m+Oy$qar@Ad(GJr&O03QRjurrwVS$TJWhjFymAyBUkIJAoNIL$u%wNEDp zv7^Ia8n0hh8VY&~hGe3tkj1|v zE#%_9P}<;IKLvr;_WcED>QCFsh5?&hZeCV`Ea<#xl)5t*#a*gbdE58$sBJr6>K1S? zwIdy$EH^n6_WJ%=>*_K$FFGF+1;uFRY!Jz^#3@>V=4!UCgME+h@=kw!54v|UyN~jD zY#)-NWWelPs!RjoSDKwbw;KViSnmkXRTm7nJz6h10vaXXt)Atbd3Pqb~;Yyu~GY#Juyy z7-8UdF;_xq1Xgk7-hj{QV)Z|wM(S&+=hRAQPyVv^ZnjfQ*ObwmDNvYvI8mUu!sZnB zIRb{#{m_rtgtSsQyt)2+C3ZP}{VRb1ZY}FY>%#^1Tg$EiA~c#B8e4wpHuFD!@>O%9 zQfM`<{25jAnjt7c8j%8|!S*lXI99~WW85qt9SDZT$FE3FqLp#SPwGLVWzwESamc8~ zfbiLI3VW=s%UNA88D&H(K!QL%U~p+cP@P%3WqAzvSICXBx*gZWLdMAf7R-BrXUUXS z>7teuNHO;UG&!&U4l}E@r5t|z;WuFV`n5uuO)pn-i=oV=?&8bI+Vsl7ZNZK+#l3RG z5cwq@$aC?APaJt3N_g2;g}}pki;JlYus~Xqv-OJFwxB9`%uHw1T9k`hUJ-;?##VLj z1*x?1M!vc38$Hlhc3B;aWVr~Jcf1US94l&5XJJL0Q=@y<=ucTKC+-jCkMj~G2Z z^5dsF=K$#ppr*fU7{{qYgnQCGi-w<9P5vo?k_c4OL6`5;s%%^iXqcY zddFCWpfHRk4)+D7M?fibndJ#Z%SvEtDE3 zV=qu@DGuy`6yWIE<@<8IllIQiBM0f9^)r?MfqJjSbF7bu2zXOJ2kF|Zc1S8Dvm}Sx zr`v%4aCiKs>_zk=GSXyt`wei(u*1K0D?V9V$hI^tlZUw%#XqY`;x!U7dak8GwofEy zb+$T3D%hI6-Q_ICT~9+mG)uO8^^?WxJpo6v`Fq4n6=G|ppNd!s_#a;$C(qI-{yL!@4gZJ(j|i^He5Tx5&*r5 zZj{y1Pyi=5yeoL!tfQ)_>bmZ`w2S}r$m8|gK!aQG-x$=(N;z)y^n67P&!VhKx7zL= z6;)vd5T`Q6w`91Va6t%(jP@oY)M&A^xOWf}{1q`+9PjcF@t2T{OvUuXqxs+~=dO0klnGUMev5@L0V#EfG*XsHRN@+!wg_9Y+t0;T?;6aRY@| zfj8rR_s`aZ_~mdLn5yJ^`xQyFA)1j!SxB#zqv&#rQF5X7$QrA~3=Vc;qN=B>j?~)l zC_?(IBaOyWOGkfKTP=FY8cUlY8-OB2ZVptY{ii)oDo_C8VYyi+0dZ^lQFnLPG?jz% z60tUd9ZkfxXt!k7yU}Ai({3eb(S`F~%Hs4Nd8o^8$;!Xd?;`eu znTwknuyThL(@A{*>w=z4I_%wqkV5lDN^wj|b%@RiR)vd4XQ)T5%%@sOJi5oSyPZuW z(B*zBa*#Za=+zX4P{@rYOtHQpZSJA6Ah%#OOAG{q*K+t>#VkG4(GXU|7S5Db18oH| z8m7bYRg2feN)TWSCH@gp(ul|TPDV0WQ- z_RKPlEvE|by90IEb^?^)#Zs!WJfn6p92=V72a_@Yw*D;aFfi9Ma8vFa8txeWqOJ*# znu~Avz=;bo)|! z7Kku&=^@!}F4dClE(DF(sJsC=$t^3$LM3V^f?YIHOoY}o$^2g6$xy5#oLH9|7DpC} zpD*-EMFHVAkm48ijYUS@v_XNKG4!TMt@ejNPOO~3-ApeNFU~jgqET|$g$z)!<8}^V zC@AT9YJ*fRA#w=ugKCbQ7iFBj)o}?GX!Q2>Z)vR(QSPwAWen#UkL(EzYl=&xkvyQe z%izAad)z7yuC@&_m3u4RxqZs{QhL9PA7Gz+=(%#ey+`qImcC)A*`Snjb99uTqfppC z=NGc|bF#5fU|c!BKhE{u&NTbCw6jn?10;{c+@Qn$b+$ndUsLI34=WVMyd_R2_Fx{L zAI83o-xcm)n&k)GIwVS*67fh)pl%qzJ*wC$iC_8Wgi?u!<8un zV-B9tNZht0uzxL1dDWfv;2>VVZOm&G>?mYiKr&2yxglLkY^Uqck;c+Z4 zMC=&l)3)Iz1oWEr3%555*K0B|5aZ5wHye%7e*T69BcA?_>iyc z=2AG|(Fz$-UJ~tO@Dma-rK|(rj1>K6a8zzgFC~bf$d_LEx``cpe#hyhJu*{!sqE8| zTT`Y~sGWSJSDqCxE57PCCTdqQ>~7S6k1Y>1cM3>_Hf5z@Q>(aiwf#K4iu$PYTGDHy zC_eUTWnct1MfG!p3=vugVHYIM8E5jx?6bbY2BjEA=D@-j4z8D#Z;=bbr&`oGJRa$< zzz&Ugipve&3XvZzRyaTt#%1(O(JI2J^W0yHR^EI)AhP&btV}k_sjYs31Gg{wt@lY* zFzhCZQ+5OPb4@AJMwx9>qW&?Y$cXnd;l9Z)=N~WDW4aT584Jlqs|z_s%okgCLq{P} z)o!4y@5@>PlylA2gn6z!MC5stimJ|4&$0)&I|nZbt2vysOxpbg z`2)-VXIU+KO|Ce7eIymg3Jin!nGxRJyEfkaDNOt?S~kXppWHU67o4Dv`(t zvG^ObQ@FTtmv@!W4>W`3t~8B z^SZGSMZ1RKWcwau2-X{iT08COH9om;ZX==2y*>R%BHi=8m;S`!j*TXbQ}>N8O%myn z%tdG*c8^zfQabtc*H`S(%dZT|>mwi*_LZac0zq{s1OjhpuVhr_w#?P$U%-YdR|f|8r^~)tmz zNS~#;Qc{@rTxy=T4Bd_f^_Oj2yk*jaXs0?*_nOOYfIyIK(>QHQU7Gp#S1P3vK!z!|lxOwR6GDqmPbCWT1$ZyAb3xIeAHFcb?Rgw7vLMaes5Zj ztaQ1bZlC>dPIcT<+3f1T|TD<`|d;uvC$&kN2zD znVF)V*YDDk{UR6j84$_^Llg$zPRuhIOmRsqQVdlS(BT4Q6!B9!?Vo~H@2EmtK1mn| zf0sYvEuckjiTj+MzVffAQQb$JLi%QCJZPnM(N9>>E#MmwI;jaD4^ay_1Fy5oKivq& z3EM66)hvMpcPIfsZ&xNgD~ut+Mxj#O>1AkB*jZdTLo*eG{=@|ux~I)VgsX@5;unvJ z!cU|9u?Q9qe}B_A`Q*O;+J7yLF@;&62_mE@L%QB>xSqu)~vEt$$^Zs)Jk%VCeS#@@} zi1`PlxI#XxoJryyaoa$dFoF!3Xt^nkJ=X6;)<&RPIVbbJ8}??(1IB=_uiic>V|1FjR@}}8QoS5%^kF7n$bM_~*6-KXevP1t74Dy-8?XA6 zx5(4~ClEJ?=+mf?kh?$zJ?)c*bJ-BFe^>^XDOOox#~Dm-m(r?|DZMCl2ti2YB*c$B zjPaT7thcMGmb3EFgRf{d-n_Bi$e&BmsO5?UAf%ho3ZZ@Qd7*^Gh{jHkf>?(q6!fh~0E z{nszf!yr9y8;GlJy{zOx1%aW;E89_zlmxNTX1Rf)*hE}}6;JY#b=ofb9anRj=l#&ueouLa-Nd~$D z25kFGv#amgeL`va*p*d|Z407J_!fmRK!_SB-^a z{+)Q*GyUL;wjEj#{wbg&R_RPar=p_ua?jPrzi#R|J^kwWK@oz|+F-jqKX+e{y4}1R=ok};m*!n{m5y$`4%s1u|?A))*+oeI$c-v#3UiReiWiJ5siP(R$Ll4kAQsfOLrOWXpj4f7C= zgTK=EC$CR!&-z}9x)1&SkMnT_Tq1HMG^gowK_58;G=8Z3(E0ctgkHZ4TOL-qHFA1~ zPvQqXWc%5Z^XlIhCNx$T8#47|J#T&Hnzv!`(`3A$x6(6u2z9YC2qe7~cwqijzLBcd z&J^f6n2Gqv@6V4<`i>Y)gWp`Tfc69YMd$#LZE<`Kh(Ql_Yvd?wC5H@Oo^a^06xf%V z9p=EnEiGhp_$=5dlSY}UA`BA6<5%`~EXToh2qvs28gnI&1?yUE5|Q){5->tk zH<4V~qqb$?U}M_1B_a0qWTKeQ^mdF(MSnUb2%Np@0ma=F^%l0NjEIY?1I#6lVQ zIw6-8-`(##f!qdvbp_Eba`kD&jkj$s5+&a|SZo4Gc$Gda zf9*>vhyV}6d0?tfh^q5axUy`n-a4O)86{>w(W8W!k5=ek5EE(l$!!vATfBvmr|v%e zg*g`PObkW{>l&lJPO>S@RM#MxqQG3qIi>Xm_IWjzWq1gEfq7uiNzUb$H-JJmP`+Pr zlZjzJn$3Sd*Wv;J%H zZNuKr&cQd+MTDlwQ4(TolX^`%c?k+(F(p>`Y^Znu7U%+Q$d+z(X&ht2| zd(xhPBXnqy{eE1opvPRly}i9(NjR`_f3@ayq;mOh|NeIMUBTMdl|}UiRZ9(%3b;}{ z+}up%3YJHXdMC)nSV`~_8u3D6KMVUV^W z=*a>*Sr9RVf4*LhkiVPdwp(fvAYFF~Pb9=Pfl~dR5h$ZeghgUbx>XOtL(Y0)%ErLX zW*H`+)|c&c=4kpJT*uW@sz|QtA`5;A_ySz2^SqZ7C8c=(J2-7izk|&8-qiFFx=T+$F8y-z+;7_Y@$Phe`vRa}?8envYGFku;o{_~ z#Z9=8Lm<^k64)@-E=Zts6y!9AMpX7Pr8ZbEs-UL34+jFYM)Q2R9>sriKSUwPHnX;5 zKChpk+M?=FP+8i|51P2T!3{jF=+2}Vn$*9z3G-t7K}@t*<>{bC&g#&#eZpoiw>Azb zpNyFA9G*?po}vv>PKkk@A*g90V@f5>B#M3DDWb*&b_RA|@Ub|UQGL&KGg37NY3(3bHG+47~LpNKr+Fdnw`@zHKPLJro|ELqN;yp|?f&}rY) zg-l+PV6C4XOeiWxg0VoeZP9zfanpWp&)ek0#MFpe9hxqYIX(~_04E61_HSObv7)3{ zNyZLOL&|s@1IWzRpPhuCt3Ca8-km>}bAC+a=(uYqpYpH{nbu_eqMOM-P9j4Ki>g0J z#Hm(a4?k1kfy9DK!9x^hRC_KgS2KqvUcPn|3!v)@&G)Wj0^DbUsgn?qOs%Y>Gb9SE z8fR@=$C>VY-a&La4$h2bMIU-Y^ZcH^UtV4U-v}M|(ZX?hI=#~*E4vcjb@)0%`-bC& z4>>s>7Bg6E?4xWvwrymiPE5IN-zB@E<6y#RCJM!1!YHJrD&fV_^#eoeqEHTL(1qlb zuYv`fy12Tj{CvkBS3d1^XMyt}`+>RD_gkHxG-vHu#7OzSW1Q&S*(!cG_Uh%2K$-|? zPBBck1kNs4fXT&TAL?hqKK=>Z%jBXf<@{sSJ~rXgC~@2S-$1CQBw2y#@2!u>&$AQz zT3&{#;P2$tW##D~x12mY)(NdUB_x51HOKs^BOrt-5nemL*X48iQ*UO47u;Yb`KhS- zFOY?R>RNG!Lzb!yT>;5GZ}wzs_ifGczrXEmz^0ypiAoVvTwMI}x?$hi;Wb;7;CE9D zSg-g2aA!q{A$W2DXtbZdX&Z9#^14s8 zL1U+gbF;Ff8y~{;uJ|n~be#}w`h@s4Vlrq2OW|eKh>Ktu>!|efuuI6lGmHCQ71#X3 z(ZuPrw45_eC%hy1#Yu%yQ8z1!ovvf|MmYK~p&lxQV1=NMIOp7v_(Vsn!+JAZDmRWj z^IaN8U00n7pC9%&fOHD0*nSh;_S}m5>iqf$t<`I`y-b$+L(!slDyAz`clIhYUfH0@ zg)aBf;^1KNc_v-7R`%oAv*b!=y1HBiGkYVgv8ekA<~_~I6S(k3#Cz#msxf4T!&L*T(RisZDwn%M z4Lx6Okw+XiyOnZ%4|iqW{FeXDKE^qE{_XZ{Y0=AcmXi%_AR#9Y+#@#f+ynHN&b#8i z5j7qi3{M`@nwBhx@9>4dSp^w{W84jZ6SHh~0x1~Nx624JG&`%NMo|L1X9T+N5UjLO z3L}-s$bJ9xaOw08t>U3n{qe{!rkzO1A#WOr8=j!Vs@4`QDRpdaP>~jdo1Og<7#Ivi z>rjWv#v=T4j@>7gK$7yUI|h&C-&jImlh5s@b^h}d zbv)lM!TThIk0MWp)c={hZtnH!i-hMo-?q4oA5NhEEfcla(Vs}fLrdMzk9Rk~miSA^^$!UEKiscAcrYZmKu622X;xK7J(O2DS+VLb*>(oom$y z4_Y(a^y%mckvv;8(B5bHqxg#Fxj!BYNe|HXb?UfH|F5_Q zz>5N27|Z_whZ|Bd94lqAOx(E*%?KVlq}>Y%4C7WneMD7lM$ZefX)nRs3ZYZwwxJ*M zKFJ92@l4n8E8_>Lk&%+>)|)+w1|BAJd)9hii{?E=rx<%*v$pa@Z2wDe0;)#5+EVxL z-;UisjHhD@(AK!|^)9#}4v6DmfoYN)`VjVr?Bx04>%>|{kM`@=1q#1Zg8q_3v5zyv zrL_np=^bcbXa{E2zTIC{7ZfPQm+Y!oz5YK75M8bHRmmqN>LvT6f-QG3t2*#ROc6Cg zval6pWJ>Uy)gKMJ6D*4)ga(?qnGlo#f}tvzZHxAeEf((0CCK{lEQi*AdW`ZZX-$AB}pgTVX`r>JaUFc$I{%L3-8DI_iA z(9bz?iytl{FO$eYIp~x%5-Bw;O_mS`Z8uSP$?A5q@^`Fc)S%k^mffG1`;Cs}Xk72A zE(e!69#~2^b!=0s3GpA5z-kz1r4DS}ZvhXS>Gq@VtKW0yt@GRufM?qaZ{Sb(#2nWI z;k$>U@*antmpk8`;D~FX?KW3v_SQ|AW2-Ta<$kn+rF9ew`Z0#g2VDdy3x>&7rD$7C zDRJ1HUG-H8ybtJ!u5wYxW$rXo>NQ^_JUGfLhz%f|ovjaYQj$_oRsQI0YJ&~Mt5c0i z&E%CHt;w=Do)Gb0K2iOBv@+k|^fEihR~+ThqPSt;b+qV$DtUmIpR~KOWG3zEyAot{ zuv^nS3_MLn4zLH!T{~V7B*1|{{XLgILJg1#Srn|)(g+}uWC0I-r-Ci+*1o#M{OtAi z%QrUwe=-03-!)|fIcZ1&B(|V(&7Mcm%HmVTBc}OAo85BRWVVvA+fZxI%O3e_UA4Rf zVuHvS-#HP8gJW*1-O|O@_9_3<>&0M$rE%LyLxQ2pm~qce_$S}h?bm0YR z?84lxvqShVlc>fQYsWT6wAuE%JKC#A`7j;I5)~ z3u&?v9`X9S-2SOr?{7({q1 zYk5ahbf7andVov`l4PL_yFFe`_@twW6MDMt$&;A>;wt2K|1H_-hXvfTk;ZCZZwf7yW`)*7?{*Cp$Ys&hSm;6~8%IQgcE zUdez(6CHWKrD_Jky|PW=0JG7oq9fPyDd4I?H_1xs++w80?bN>PFGw4y!)E(1jx~b# z;rYu~890a^LvmPm7G;-i^>8$bh|OmdIRG-cq`w4BkA!>OslHoxfHA$(A&|9!|Z zJsegNUt&gO_I%o0sHAgEh&AjlTjQEiUEa45aGPg=Xv?{^-J{$LfBoxG-uZm zUJFFkAtbB(+m6lG)w4F-&Hdj=*LyCGrv0w3#+82ZwK*^&k+_Xs;|9@YO3lEYvWvHGg4_>(y^^gr71- z-M#`9^*Uh@*!th&ucr+_CaPb%>uGVl)d3*9cRxiCJ8cB^q}2kEY5)7}=|bjTzgMk! zzs5ejz|g7ImQhv|xl%++^1wfqh|=JRafQf(;Y^1MOC%TR1hnm>{~AUSzOxC5wl_3f zR|~`Z>XOs5u5L$0eCHXf#ou`sI87i$AI&+&7;b8|b)X3wp4w`{p#3KwmGMMNf$!JEvcZ%vc{ zb&M%etn0Cf7@G}|um;hfPRRl-a0}hyvPr&Ynx*Qt=UnR^R~MJ;>zl)3jQp#$<>YY> zrE|ZR<82_|b|B9KWI6lz9>u|=cKdB79RIA*<-CXhNdeEV zcvh#$=5l`@4{Smhwi7a)vDiPu22Wf5OfM{Ui$2t_$5)mzB{%}1!M9bFk)#5!WQi51 zpvZT1?3|RsC_5EK%4)1$;&#Sg?Hk~jz%>|>azW+(wZV`-8;_{+TKmrV!yd?jL*qwNQ0wEQ%=I`=x1f&w$WzdC;+V9 z$3aO_LLf?yj`@!d0ku%SuZgkR8O75fsIQ0S@w#;;ed(wA&1N>dBg0UDxM~^Nx09-2 z)NwEJtmv58`SiDHB7^}$N$ZDLKm~-i`LJ!v4k^@iw0dA5Y_7XEx-?h2B1g+iPB$~2 zR4)CX85X{}7W=ku8!!g|iU4=r(Y}8A5CHGh^Ljh}>Ap{}#7q@rMs3Fs=@4FU_8J#g zG03!bd^_Pc69Eo7obko4BH*uVVB;m4?3|U9)Hlw$8{BoA`Gz!qXU->1JJmvk&54Mw z`Ie0P#DAJ67Csu4y0nW@^}g&gdOw%>0vlcX4yEpPRC6#j^(j0mKAF!7Kvu2+c3WLC zSq@ZJQ`Bm@>A-aT-*vuI&wclE{^~_+xVNS5fxjxQm3vsr`<5%Pq|P#{6ue}V{Z8}P zUbUt22f8Jr4sK^P4Y{$o03fNVUTPs}-$XR21@ynj#u^HKZ3#k!Mk=K7X=FJ}O=zen zK$?>7LD5v=eZ^T%)TBmKA)p+KL9~vvg2S!^_O(O{#9CPn;j}Dc`LUO6MU-O)UOE9y z;Tl>aT2Mtv07u_uYMoh=pXIUZ>0G5AL!pg4CyuGCCJzObRyx-&22dDgobB8_y91}rUayLF?Ul`Ue|eFYIzO(Z)?eP z?p13=n=dmb0ow5%@VXvB7dR| z$5Q(C7ifNYd3lUk9dHbMHJJfii#2!xI9li8090>l(#={*L9Mn|E)O~?*=tn=drO~? zAubU&XB?AN7k!e0FQ*PW5TQP9sjV9au0ks5mq6|qD3lCI;eiPz%n2Va-9?Bsqok6Z zy;7G7BY_wc(u&7q*^0(JSAxU#o6a&L^sgzYY`g?Hv*S3Ib}-dz4k#uJ%TPX!U2>yl zYO+r+TE|Im-5kb?zJ_hTT$WWb7{9gizV`xIh_v=XCK_2DK$Qi2PWGL%HVu{6eH!V! z{lQgv%Z}tNcF*zFybhB6Q=Rojo;>5OShSeQkd-H(zF*TRz@>bnyDuI+h)?b6j*mkq{RB8ZCZ? zzucLPaWJsoD_sX!qTXk=%m%?FccNgc!D9s#Xib1tmRh<~;@(w_#rFLuc&`n+Pc&Ip zDIMRkZnfK)l11#bncS13UJ~ubA zpn5w;T8f)=gjJ#T1cn zs3r6Ws8N@F%1ljL>O8HllZw^K{ja4rY#<4xgMerruPj~ zB^lC;-<2JQ>0kc$FeFU5pcx|c8i(KrZer7W?_fqs>dfTIpz97{^+*E;lT^CB_CK6q z;Q26^vKPg|&D*?BkFSFSUH3sY*XiytCJH7nH>21vef-~`ZD=U*TB+)wuWhyOV5#_M zq}hIVvEIe`6~KLr>dB16#sI(n0p4Bf6pxea@*RxGN^uzB3YM^LJCg@zApvZXeOWFS zLWzUi@y4qXQT! zD$|iRqvB*PZaA8{4*-HupTherD2QTiW#u2RVv)h9*7tn%hI$^v z@xkK5RvL@cPY+&MO4a6UG;oh|o+Afqnyk+K0m%E?2HuOGus{x*_PX> z=QKX^yQ62z`td!`*f?-{8R3y>3(WO=d@tLQHy)R6+R(^7X+NQeLy2z;E zgf`g3$C7wm6i$3mg`9fGKr)LfqB$~6$z>0ss0Rr$nST^H+jCv*u;l0BGzkiaD$&EP zx14405?T8;hRLFLY&t^fqYVIVwRv%|=*!sj$LCfjgTR4vKMH3Pu?5*)><@6Ct5HFM z?fNxV+p&W%n4}}W)Q1*M*sw5j2T@{cOp&<~@1Bl4q^JZbtJ9e)Q1}sH)dmtyh2pc5b`pGHzAxb2(8vTIrD`j8{d3d&HjjSw(HbMD17 z!!FY zvWHl?^^>@Nn>^WW$%s`}qz4F;#KG+H0M`~s;PMkJyywQabxoY23(jIY9OYvkAVkO{ zT$JZq=8Hl%pQXX&IUf124iBmz!%374zc+B8D2k(SC)5hU*+z)U%OXNo+IN*K$>Ka} z5*e?!6X7hXF3&pO$;qvi%T%;Nqc59{PS)a{*kFDd8;qITc5F;dT2uV|ZY-~pPJ#%I z$t<)(AybVd(T8Pk_9QA`T?6!)6BI^+jWtSULqk#VXQu>i>@`Xk(_nP-?o=O9%J2Ee z>FuUm1fb-8Fn=uL?J^ykvjkwS?(v{mc$#0Gp6pi>HxoAtCjiso@!vqgMz{aSZz z$KIWg9iZ#!5ts2!-wxdNC-2%Hc>6a^{(SA=831Ulo}T_}+wR8!U=P8XCE1!1^#*t* z6ROYk3>j+p*mPN4FmV%9ppW&WX_(a7a#R>$jIp{Wi^+}t{`55a^9{8_n)SAc)HFm9 z&Kv`Mrh)m61VJUTCY05#f4NwT7nk;sm@Q0Dto~;-4KsQ9I>wym>^Kr9Oe53=_aetd+g#Z z6jb!alfQp$1bNMsKFk{Qh&nZ0pWSyp$2oavj^* z`9=Vr^W^zJ!DiE`gmTAG(egnU-(F@V1vBy|)-NIl%hICR!=Zb~{I>ff! zp&5rV-^I%-hBs*^IhfFx*vM8dh8y1Y^@vfaw!C@Pe{bfBaeU#l$ib8%#JNfwBFHTl z)Ahbt(#q<n z%d(&#>adRM!}MipE6#aW72W!wOB8V5SFbhz#k&zw-#?I^jAPtM>3Ls#*iH9)+i(0Z zbYWsFUH4OJc@aW(BCjj+FJiTV^QW=#iJsTcgop_kFw!dK}M{;3babf_jMz-!wdhep`W}CcO%kSvn$NL2lc`KNFq2!l|Y)pLRC>Y6*xF7 z7QG0*XVL9688TwlBJKQ}=X;)iG}R=d2eA;#%g%Oa&F*ijB5ASP6;JcVlKmJD7~n%!r>`pel;-^ z0hGwM;z3V*yycY|BD;eOS_2e&7L?>T1m^#aKPW#u(2LBTPX@eP1@_!6^ClJxO|xQ9 zqY}o%Crn~Y-TE{(Zl0Z$yC43D4ih?u6P=32*rl3~BX5tpOT0DOse;eet&c7}N z)-CPFKZpqlzf2vS(Kc-=c-&CH!kr^;zTueSuH2ZzoKzHi);PpT%2}&KW}oIz1qM0B zZ%eJO#rJ)%?Zn;zKs(VW@Z}abRkm7Q9}rXtP2a(#KE1R7Ls;SF-6LR`UPFR5Jbdt< z4I3y(RwW3YdHLQMyhT&&c)K#U41OIDT1edVxow2f!)?5RoDFT zS&A`lT1)8* zKweoB*8y`sE-hH5MdEyz`TAWp#U?Bjdl*?+twJIZJC{|O*(E3yB&|Qq$qY_bKFyPa z0bzeffLH9Uj;v?Oz21*REG>i!`QBl}bp?MtLQhX`ZlOjwWbs@C!jmY2m9*3);xZ9C zKG4VUH%^Otm*ch6gdXC3k;PU0?^_?%zr?7nU~mmYC?wG_213Zs^vI77g3yxDq+VA zY(`Bfwk5L$ayeI%B7YEXl^45HVrp+X4yg?h5%mo4l*K`nbps(2H>29BgnIi@nj!UV zoSpD!sU?tUjv`9roy0&UpY*xgSj(WyaZXtt#fNpnKfX#WzXnplxE1V^21~+eg7L(x z5hTUO224Fq@2%wMev@#-6baD8V_{Y{RQ~$g3njhDoDS#)8bD|5&w$=*^m*&8`;-6C zwqyHILY(xtuPCqJx~)h1{N`x=rsGG$c1;+Mvo&OQc!hpXE48r(Q1nzv9gAL5B(=)) z1R$)&{fH1cn&#=KdLy-`eL2^E zYL&io2fkm30Im8n4~3GZYM=MA%|6Cv;9JO03^31AaB#4=*Djy;{#`%PK0iM~68LX0 zxfE!^9IA?Bq3;xKYpw-n%|)}F%B%?RP{T!Y5b!uMoSw}h+kUAKcNjkpVUFqRem=V& zQwcD8dxs8$<0i1hfBH^lo%`Q+01n)Q^t%ILs`%KZuoRkw#7aQm^H3N;_OB1)wQAM= zzi+0{OKhNC+w`v@;|b%s9R=gpt19E$Un+(^M~bZqQ>MTBkjw;z(3Ui$pof7dKi{LU zhft3YU=^rish+ci%Z5bDZrMx%fsME4X+eN2j2Jp6@baH5K-9uBvDj;Rng1J@Szca1jIyf)jlmFf-s|GE0O0sjk9+V08mH;sm6SbMK7?J1rJW(YRhI=$F&um+ddRBL^o7R zuU&6le6oQ_`+pW-nD^z7Ui9SN3M&cXhosH{O7v`b_v7vg_HkNRnxLm zBXb!Q10tYaFHi1a%2a|^y|W!?nzA@3x{W6_#p^tv#`@ z_`glWx<80VR%b<=Jjw{YrI5dkwj(aF8q^ic+P~a+_P9^IOTP;ifNoy{`*q;axtY0I z93Sx7y!>K{sh}+2=bp!ME4ZJ@Rwb-e`8B@8N_Ub?kjgC{#ciasCGM?j zUmrWxR9^^<3XCF19RJ0yP0W++z(+}i>1;uz{S0346NZt*{+jmuW8&(hWBd6``{VO3 zVY~CUQF;-N1+|gRy$Q|$*Malewu5#b4qI#6Gum_@W!34X#~sFPcd7XKv^!j>JZ0MS%qH) z=>mYL+q?iE+iSyf1NWWE+;vZaA$Y2~m;+*lex^DvGu_b!p=pFr7=Ace?-gJar;x6+ zKWSCFeH`myaAA<|b*H%WMe??#+wn{)Ep|Eg%poil9xAzr22z^@ul@ZJH@`wRq^5>b z-g(drOohUy)F4_lR>wdxx!n7B}zpX)XF<={8hU!1fJT*Es2 z=ZvdD$Q2DB%9iZOS?@i7$WDK^9r#vs2=#tlNKpxVY#2Z5c?*F01DAjqouN_O45?Vj z?AeLJVT6T}Yb+4>{N-lhrU$sM0Pa^Me1nT%%Mar*MQ>N%@;hzDiWEL}OG*O9#c}nt zh;N4A3C~`zy<`zMr$pD5oW0DKO?R(ELUHbhozEC#y0yhBv`jA9 zVtn%{uhGJi6IGLt3^T)QPa~{DVnG0bNvtukNtzvC-GUfwXirEN>7}j`G(q|V#j`a@ z_Q#Hquvk=R@A7c5bc-rO3geUiCCB!PO`#!89QIl3YT<;}SsEcT*sph|Nd^3CBuA1t z?~KGOEI}ud?OVlL34)PWrwzA`jBKbwq7cx>q`}U^Y-`G>#oz{AyQ=6F_}DR6^wHf7 z>I+pcd0S7Fq6EQ4{z5{Z#nNrsW(S_(yWvpOYYi3A>+J1UkK^>3{KuO&Blpq1zGo-n z%T14t(;UR0&ZI^gPpiA@{5NsWmTc=jZ<18NGwKWgD`YacEhv|Q=WmOmIx!}-e498i z2Hl}nM3V=Hhn+&xh@mjFP%veJLFRo)lU`gxz)AA$@wxCGsWppU=gK?BwWi1Wo}Np< zX(P3kOdx~8wc21l={C11f*dc)+NV8>g$%|u9~E|`QK3VWDT&U+`MSEx#Ax;9xTU72 z$vbkRzx?vFrFwIDXKPOu$;^kR9 zE=}!dRTz_lI_V(C(T;HZBrm^R`@OTEFg2mK#2OpXL=; za0lP5lVSp1WSN*5=@UFxZ=<{Cp@|zVe#8RM@2+VBiU?Q^fhBLB0S(}1_^dJ%J>V*; zJnl_w3k!z7NyXRJwsO_hQr8HlwA7G(5zR&|U4VeasNrYyq6CI$28bVX9lHW08?l2C z1qWo<#a#@Ck{RYQTE@1gNLr~JD_#}#sOkCpkBRft>bc+g`qprijqtN-m9IWw%zN&mHZlS{V_UY<&BV!$D;&-U$N9Lz@$F!{Y9AQB0{~tj3-$=F`x97YJ zCI5G^uI)F16^|Gx)hmOvC!Jagpzj8f^UcPRCHIp}xP-O#SAW$AXD(ki#z0D9w?Nq67C{V16yJ?`KRoR!zQAX^>!;vVUnClhq1^@J(Vzb*zm;Sr$kj3hGt6AO2!bo z<$JwkL?){G*gwI~GKA7ssdS|V zO-Yw?1Wt*B>dL}#K~$)8Ej>i~;y*dQesleZLVZ?-C$6+vhsO_5qN2dTsvY&c2_K+s zDx(3pO&y4vWRr}>KlgV2<{}~ZKV{d;yUAmZ?hbP@KGZLTxfA;YBIPD7Z zzWQF{x$O;QA0hKSD*cAn^?UaghKZ|sNZ^|tGeW*sx(`(HiA5`APOEE-lc3NNevYGF7=1;}J%ASs5I-@{k1Ur&!N~#OuWX24fJ07`*yP@n6*)%qzdg2HXUZ zr%2Q(v<;A2<(xM(@=EAaba1p75nR-@x$e6b&bqjo6rA;x44)&y);V>jp0D^JqX=4@ zfg0izZc`BfwSj=(JU8HJ{a3@y7VtFo2P_PkO4+=Ylr|P(3p969+}w>cZ54FnDjmEV zbt~_JY;0}1fl!n|kK-n^=fb;4QM2dnwzlhd^Ss^jv}=m3htijP*4w)5Y5IG~>$dT9 zFj2Za4bJQdaW05Y2G^C-3F!F6eCqZ(nzLLiu-FZJ`HkTY7Lkp5r*ry8{f|;U27SxGvrE!c* zr=bfq#3k%ANE&TdquyLlFm~o)3`(ZA(+vV40nG^mg5dBj)V^nVDoW&ROMw+58O_Nf z#@i!2l1wvAk57*$lSG&F{Fx?7=#_7ZR$6fR$w6QEuwhVQ)E$1EEOw4HU_I8p4=2AgGZt7O{5K~GOGV{G2sj`x5W)zFD z;J%wd9;BKG$Q8;rZOOcLV1Qzu8FYaMgp}vg^$O5YAwjwv=d{t$>J;jqcF;vnBFz(o z&xU|1RXpc(W=@XZn1YcDa1VSrRWN$W(lCN{Ss&;~De6HentKsU=L9gLa3sNrnV82L z95gO>V?_mwrliRrJHx^%9Y*ol^S6U1;yk~Ts5Dv-FA z3n~ynUiCyBIn`l1S&N0w= z1ztt~KE7qup3e<$CTOfSO0`!V8j*yO^-mTPtd7u^w>4mk(TatQggI)idj}MXwO{55 zooXvNoGk2?x1N&{{F)e|3&)n7ugL!X1mVPuB#sK3jQk{>0;CE(ik)K|DssQNe)f}k+z$fb-i58VBBpgoWW?x;4NqG@W?Ox%{BBf4)7-(7 zN*g(P3MhVn=G&PBzR_s)GvJ#BjM_)2AAeFzyAnOw686pIxM)ma7lzRH=)dXY(YF%_SSWYNa)Xkn{9M#4!T+9eg5x4h7~ zg`xD@hfTmOF8yMu4tC_y|0u2r%vxtk#(bxbFq>HOjq(2lk#!7cD zCI3Nk>q6V_xubD@lLZxc%d+B*ogPl-qAaH@WAHvkk^s2e-GCmTK_+&p)kt#D;vfh> zSplc?#*Pq7V)0IHQ`URQr|cf@*=?Y@k|_Ixl6Zn)ZgKvvF`K7K94U_^6>>CV*~i$s zuy9i}^x@58wI|PGO&?hIYyjDU>*~gBz_peCFp}-41)`v5Y2gnQD4ux24OPr>wK~Cw zKEy$O?#h5i3bvO!xu19zpY+rE5{yz$j=_IY=eq5F_H>JJ2laU)cReR{)P|hCPhdYV zu=}Rr;v!EZCo2m}v%pX&uYrXr$iU#m>OABEVKI^V#1ma)grj*PuU2OOOBJd43DXCO z7EV_7oS)wvFx6+7$DSv!FDq|7cTL}S)n1HjCL~P1%W?J4w~J>F*wglTe!9=?v37Er zc3(E`@wv@n)S#>JyBrF9zG!EdbAtECBo!%A_sqhCinHx=-!ynSC>BY2X z(WMs+&XQp(i@N!uf!lyf+hM)i@6p9{)pa`a1HH1>PB0=6fIO*_NEtkDH3{BNZ4;NI zyKw^+{EtA3cALM+d^oR>2?Fi(%)=4i@%kg+0>%_K+GiDa-kMU8#}0gUXwCJTBgUUF zHd%hw-va!lJ&#J1IHKK8zihe3u8U@Eq9ebf*fs0vUB+nvQEt7`kVx;mn8V*gZ>yWa zyAOLtcFsSpGc0R5kv`BVR+OaG*Rx~2oN_N4+!p6A9WTx)V8Miq65@y9s^=TI|M9e% z&e{~6SzcU);54`&FUiv$9iP9K8oh>9{qgg6rCorp;f*R7e(^yV+_VpY194zD2^RJ) zecCTx^pwl^q>ymg#2)4hm?n*#`yQzbzH6R6j|BQ(>u*mq0$xz8s7FFcBq_D`hj=nJ zcPuDYcGPM`zu7LMJmZnBS+s*NQQY*tLp)DN{HArS|JzJw@mN-R-ZaO26ab1G^<8Xp zI`QLg(5{C6urhM{JM>hhHy;DjX8V$e>(TZOjt`rv5z zfSB1TX|~uEXm724f3Fm?uy-?ngFzbmz^_74S?Z#k!R~%U4NPcjVm|#x7EpE8d8iC8 z&-GZlT{hmHpHG3d$xigtONF1lQ3$-I@9vu5Ftu!^Rb~OLw}8;84Da!D)-?I>(YUzy z($8}?vER~EFn?`$H96RlG_y1)sD;M;khW2$pz2e9FrDl^U8ZPP)8|yzVhn1yk7&uI zmz3tsKo!DtRSWAE#5m<*YQE^;2_yKxffl~Rw`?X!Ta-&y04tC{;N9}|qM~gIcE#QS z^pzD$v8b4(E(UQ6ubu(M2fA*xcZX>i_s#ve6$gf){VeO#dvQiZW^b>g^3R?&gR*=+ zmb#)!NhtVHO%rHvQ3{}0-!~vEF8Z*Wu;n^TIJH|7_%ePy-BWii;>%047x-^JAE${S zgi34fFExhf(@t`P|!wBx7xfNc0Qa>{bD%$qOK`9F+*bJ)HosXMR1jn&yjst3ANFSpWBU4V*6|=#;Wp zsLc0@C#CO}*Bzx6x?j76?^gDvdbSC#PHLP2M`DkBfslq+LD>Er*U|a;dcAoE=~R(f ze~C|5`y0$N`}NhI@qB-u)kB@Cp1=ZztI6!8+q?HUUccpX4M`jCa?+7$9f$5W7 zt;TG4t-u3k{?h{OHzU2;VYLOraEbdpH1Z!c^DLn`*TJO<G zMtKu6?jQb4Mr1hLkCJA=b2ZD(Rq!B<90LFt8iYZ*yFwW6pdtZBG%)w{kGZz)I z6`1ant2vYK*37jX#2OILnarS)CG30>MKCF7y*yG@lxMKjiFqRGys3~}O71?@tNn8H z_0uO|R9`fqcA;=N*=EP}nN4v{KrzdDOO_}k?5kC46bOtOR1QewXC|sLJv_d@&gT11 z!96-S$`W+jyKg##efib*O%cv@)LAXZ3DGDKkp1fAZh?j9N|y|w(IPoT(dTL;N-JGQ z>^Dq;>Eg4>z0pia98{n4bo))HneMFyB0Ljw;vm>+`by`|^hz-l8zg|<7?}pD+6pS^ ztc+6=#P2JT2ufpSL}&bkx1Teb-TP^?!=-;Jt{1T1kG*^kRB%2W=;{hiWzhyIK@0yg z>w7(mRkId{f=VhYA1Z)uuG>7nIHA8~U(-a}-T&Z4osGoj^K*;f3+rgAU&P^_3gT~X zzdr3)@3V5p^X{l@z=LSl7_?c8AiXbDrXVAuL!*4`=@xlj+7^HM$3Zlq6A3}uXZ%*sO!^7pL z-hQ20WN%0xpH4pp_M#Zev)CqSDA#id2`R&xfuxvVaW`{N-<{26bpFF5)7PAikF%xy z*!u2wrr~Qqvq8(6t3CWI(>iy<;VmobPzrufD7M%2m7*ti5OORKxE`DE zM1xpTxBqe@QqJS03IQ63yLOUBr4rQezh`e2sf@9^*qR9#+nW>w{tm{np2%5VpVtiK zY;?2f{|~fQW!z?WJv>|%0YD`Bh_3a4P{PGd4|nlwAQuaZ+L zOIdGz9B3^XrY6*g`3$3Vk;D~#-QJ+I9-UPm9aem_4*HOW{?WYcIw>e#H#{iQDb1oOvZgo-vkReg4tgtW+7qxjrWxg@zm+oF9uyJ4~Dm_xRUt-raolA%fU zAOttq49bA8+){HbktPrGx5I{Uf|lh8TQ&ETl0U!VD4Kj@b9j`hdV7BZtgMZI+fHYJ z-zC2j6SY|UoCe+Y>|cXa*$wYY`SWLfy22Wf4}3efzs%cf*Z4D?N18gTieKXw32q4J zzZDGXNL9(;1YRm}wO(@_m&L{AUYl;#=rKXn9WtTu;?H-sU%Re>_(J>5%AwU*j!~^9 zw#Y$&=xxqhAwIp+GKP&>@82j8g1*Sk&RE&Q{qDQnzOdRiBoxj~dZME18=A=_Hv`F| zKolgSE-^7UI5_|LXp!e8!w4Uss%4gBH0eb+WYPu^5?FiIA0)#N5Th?YR&jaun0t#= z{ND@k{1CABIQe++L%jRnLU)x;T~TG_$9od%$ETY1TqRb|VX+VTmv~@-ujuqO(E=T4 zqyAiv$^^sI5h3d30dbFNrwXB}LcdG4<3yWNn*@4fhypt2?Lv#xm^g6ZrsXAFT8CvC zNg`z8AG!koJ4>M8MFh>^b==LERlIC*o$LHh@y9=^fX#cqlubWMgqKw1R1|`{+>2hJ zS3CcF9v^4`KsW&G4Kva2%lwD6{~R%lt5&x86}7*%^EoD=eKH^kDRiGWiH!$f!uSCA zyoWE8!)iM&!mT(rpM5TfmkP|!;;c>ux6LX44Rgs+I=%^gSw(}s%j5m`K40K;0I=gd zrgt?uty{rdBPtk)t3|SO7nb4Ods+54!dGXCdYM8V@yYLm{*`7w15du{V!4=Xjizao zDQ;5M87eJAOBmB1Jw&?LsW&j%F+xMR2xfzem92Z~A-(dHFb>=)kb*>K;kb)+Y5xuHjCr+HsBOmn3Y%X=D?dUnqjQ`g+ zl^0ZyV>n;b5=5jm;K%1{GP@={c!mSTSSeKvPuPeLUbZYp!+K=>?jcwcOM0%pAGB(& zYbOj6!o}{B5|hOGP6$_HU7VC{{j?oAu4) z@ExcSeJ4_~R5f4BZRoe#-WUa?^LUnMWo6~z4FKH)K7_cb=qS31!rf|&z_U-36$?pm zaoDC$I}GCM>+`AmW4INz)h6^(k-R=&WafE#2z5kFV~EMnh2D4RogH!#qQbFQ6H6&H zY~8_sp~Lf)O~ARmo3q;CvpQwMC$yF$Y(43B(&_xSu{=&qO<2edaPsV4vS@2C=Z^7u z{4BxZ=!gi57vA%Tawwz^g6)hy2yGbSzI|6wRXRjS=QiTe#fZt=%M$4yvE;Z+IHZ^x zE5~M0Nx)wA4=G`YxJWn7+r6(pNLF z@m;$ob6gt8T;QklJSh5_ZvC#S}!vw7O4%oV+_uU}ePCXGOb zJ;Pd;id#Y@3cBNycZWO*TZAGeG`+3G~K9|jw0IT$B8ZW~VxUm7Is<(}9`x1dK z{W#)BqSc1&3w|$;my--)BMq_*f?Y08rDV>n=Vis%ll4`4$Hb(h1`VFC1ywiVV`7m^ z5=@$9BzlVSs5qi(YHF(Wn`y;V9)u6e?@9O`|mJ05p zqJ=|5Y&Z$*(Fd0fz(iq{CCmkVLCj;RcAZ+a`d|b1Ks9Qbs5A|#AoM<=(+S|gXVtKq z^DyezQf1Ux!N^LnHaPo+S|JITgSny0yFU96<=o%2e0@1YUivt9c#U);Zu0VU^RkGO z_taqgxOL0_TsLiljE(J|Hk0nddfvKn`Lw%PIl+UW_<5HXRx}J&b0}SK{XH$sk~|9^rj`C3{+- zHESLxv=yD-T~J$l`m)mocIifWc)9u^{_oBw-{5>Ji&mkbBWRfN1M`dx-)y7nY`(MD zA)rlA2W~!WKD2bNE5gE>Oi4XZs;s7dv*oU|9Vm`Necw z?GhK^;icaCi_n8G6sT$v9isc7p&>5i!k7NI}5teYsq2+G()aC4|`PwOKGO zI-$~g{})1AiI|tNYWeor#TO$iv1a0wsY1Sp7!{ty$HO)y@3Cm!oH{5&HSdU zXd;diASSjW1y=fVwo|=D=<{*SKK|*p)?m1*T1yLma1l`GCMH(eC%qTjCj{II0&(36 z3x1VdWm2Dho5|Dx*yp9GiY%j$5e8d`)Q$v1CYB>LJseRmT6w>xy-Vd#Kog6x!4@H< zgQwsppO1WsMu%GoX0_JM6_2X;zqxwf>f-sO?@mvD<=#BV6?0v5o(53j3m$lz`;SQD z2!(IN69l(7=#CcZcuz?lpljr+RtFH6YRc^MY8kl0@l^K8%wB9*yFJTNY~er0x@;%` zRP?GSjqGv9@z+KT>E+Z-PXUSuHq` z+T84d{o-3L43w}Rb~^%ST27s?G)u$v>y3@bWO|k7%lzlL&CLfOZe#gy<0yd{BKhx2 zY9*iJTI0uK-=1GNIMkb7`6!~Iq8krv`YphE;R%I1k!nu_O|)+)Jf#~yQxxrVKOY7I z=EQVefIQDXY0P<=1fZRc=XgNmh@n(~W%1))=2wj-^>Wb6B}-mq$w(R-85&y4?e%p_ z*7$3(h4`3P!uzp5Z~L%V0IM#a!_w5IxLW0W)_;DR1IPo%-@hlQY9JE(xLcf8t+dN^ z=GN6KrV5C;>xSFg#i*l^m`OCWrZrv~7b2^`JoSb`80eUvBn8dacS-L$CGgV=5#_16Cici{DY5+=AWQ`xoH7C_SE@VasmO+Gy-W|pNCf@O)E(Rt67V?Kp44eH?6w^upXCd&0?(MVFT1Qpd@@?0NxkErLrDb@yA9+ zR}nn+H;au-L#Fp#j1FN{B;ONm5h9H7)lU+4uUjO?_lcQG!E#k_35~3ZRRws|wrTqP zvVZiE`g@7dN>r4==BVN;41O&^1e?tJ7}N$BZ|&=5X&+|WE4@B&h~{R}Yu!8p(2z<4 z!lKCB7RpyJ|4AsRC*4NN(b_0b=G1Wgm&gbm+7CV4U8AqysRZcLh0I9A7}^+h z^J5?XMH>srMH6kN(2rQA8}jk;?l7K5Vv)b%wzguVCXr*`K^cey%kbLo=H_~69-SQU z@$eui1qD_6N1+m4ywi=LvqmEhFJN8>MM!j&a7VRG@WNe^LI;hZtYFkvATSft^lK;` zt7fwH6$Pak)Aj}L&WE$#AN|``&E@74;`?rO{Js4B*SQ(@4Wda&!6&6 zPV}n9cpKgPJGgv)?kMWH?C9(6iM}NxIgO%=FvEnZ@0#F>DGBiR3xK86nt!z>aafU~ zL&K5lm_ohDe6{hzXiQ9{HOK3WJpVMuGSexjGesfNNJ=8e%Ssvl*;ENr*T1H;| zB5txx?N^5!^EvSBc!}G+9a?}hW@OItzNWsoPNH>eBGm>u8Sk&{f5?U}R_XG4osi48 zOe`{Mf<*6!7g=>LdW@ah4SC%?uKb_uU&O2@Hp+K{@wyuC2PXr6|5sKe2~x$LS{+9ocxAkZ4Hng*-_zlj_{Ps;g<`HhW@^YbA*rSuwurV4e1Wc=F| z`&zx~?>`#L#T2Hg3u#>E?Hn)nV&zd7V`Jl!-6A~WD{h@Eyq6wmCy^kr@y&m)Yw!RN z`qRy7%LaV1UKz%03q&s1gguXz>U|odB+Fo-64h4r3st)B=~W4*s~9zw7?=u z!nK#H?fzWDN*EnmEcDk%yl#*v?_b|P`vEduSn>jUp z&V5Noi~h&bc0X=N*$DBp9%_9@_L_BKPzK1k*kAMfxWXwQmtQMoO-mLe@kkKM|PX{zcFAr9!i^qKUboEGj4o5rLTrLhj!a zQtSUG`lY35`3;Zt*yE6lvFPb+{>ZY_Zc&^JtiFnXbIo^@?Q8z|1UQPn^UpZo`LMQL zL^hFTMVOl-0|kN7^nO+$EJKLH=w=4k41YLO=F${{(><^~^N|W@li&}5u+QguTn*U< zp>PPSXdM|ug*-p-&&D^bjGeo=v3l~eA)Qw7h%9SKMbrXY{Xm8$RtF1~qrTg#b8qfR z)78TuL5t6B|hZ%o>GG(na;dUBj1^fy6{K01xEP%BR>bXD}} zFg8+nWrZ}Nn%o9s7l`z|mZae-1A&r@Fs$tchzbD+D(4Jt%b(?^BJ&+vQ#55h88(m* zX7G3IZo5Rmk(0U~SHxmPc3p+K8>A!@P*+`u&b%OZbNasv(mveY4C1Xys;JOCV#`hX zpe#Ss=3{@bCdr5kdR~O&Tj)GyVo%i&T1+q|A(On#1$j&#k2NkvtOO$$njFlsIolA+ za~|dQaI|L-c5p1!r*^)GrDnZoRK@d8RPJI3RuM6Sz+vh9Z*)ABw|cSt9@Q6+A%KCc z=<$KYM5f2~&^1s1|N3yD`p@5!=NrrPce&gi78ZBE<=)gR9yS1LZDA}^`{^ty(C2iy zT1)BeMxSJBclRcw+UN<_O^vOh$xaLZcEfKnN6-xz8*9H@F`&fP8eDGyYd(#`xCJ;O%_z~((DX}x0;r}G6eNd-$E&R_c+szL;%UX;LI0&4>VCWd{&oCf z0r=!k+HPwUznHm8VY9L#B{LiouO*h+g8#@T*TFw~|7=UxSJ(JmQDBq;Gg$Nh!aXv0bd9XPOM1V5k@`;E!sCNS6bTHf14@Kze(%iT=nDQ5>0&I z>BXthQ*=JK4Z7X9MeUoBkW#ufG)OHW@w)Kf@N^Rx6X{qSHaoU#__8E6ErP5bgO&g= zX0?`FxR?KNHW8aa>sdY{Z#1^x&X)7XC-Zy(j!CTcn6MNuoGNt6j*p1L$p55mAMqDJ zL;e@*{IOq{qc86H$5IlN*_J4r^C{5{aD=M1=o|r@DB37PaIABs2!apPit8{)P%ByCZ<=_7HQ0E5KwF{ZxD1$t=_u#hc&Vcr#%DLkh@>7 z;mM4I!v=x`;}YCM%SjPIVT&VU5A*6+kyn@TGe>8CQ2wJCEry)gs zQU5}L?TDX^tEmaid;29~z2BkwNu>6naok@aRm4odbqE;;5n5rpGTzLgjoe^Y}lrenRaRRyS7-qr&aq zt;ceLL$}9=hGMh%9oLqYryoX?cC0&_wmG5{l!ekFOGLYyTf$6UgMzSOjU5`p z3(z8|5HoEKQ;qMqt|sMW57hwUX z(a^&skm)TN8wX!ZPZuV{zvlCFSSKH*gU+qb&)URJ~b7( zX+Tn`#mManez|x2aP?kQP<4!4gJL>uTtDQXZ9ng_7iU9t;!EVF+vFdBMB-XJ&H4M{ zOM1Z9%F2e?KuIj&J`HEp}mz zlVX11U|G4LHvv2FQ{4HCSNHJ`CrYyw%+lqj9{}+a1LeQW3@nQ%AGh!l-mSWHr0B+U7cWpfyu>_=6b9UwK5X(z`pBW3akNt;l-$njy6sc8-2!+JDdMl|{o) z5)&lwed*sF9UkxYuo&z4{5TH0+>r_W1gli|0Jt$q89Gi{k#Gcl?TRo#^L+MnTQ+|(KK&Z92m8^N>VmyYw4&`);L(vIlY7@|7iB8#ZQ$yfOcoP9) z{MosMNC=uwo=y$cbYN_x;1j&uZAK+jtS2s8P7kRlg9pvOvy;-KMuKUo;e+siu8GAX z8fJd>=dv&=+-Lhc(x)Ey@tKTcaVL#$|k zyC*Xh5NqwzetBZKyv@WymKF}r174H)Pgg`TJDz5?SL&Wpd#PWyI<(CZU30jrnRpx6 zP@*^SE(KdEe*I))V&ue+D{E=l2XOb|H+PF&KwGZWk3ndUGO`bx*y%BMw0jb_V%~0$ z0U2M%P!9km)_a66q@uEqVUS?VOZC4JcCj1jm927XCi*dxgJ8z<73!dtin#PPsHC9o zcaUc?A_$zJ09*2}7(GWpx+yc?$ z(OEGIH!5lA(%5R%NT@yD$9OXBEUu{a!69{pOnrLbY7|*H+1m~4jX9?G2$yy!Aabg2 zHrig*>I#u%EnY>ckF%p`mepEGv@i|)!7cq~*D)74FOTbQU~l$}_xXqifC+%o;G&1C zR`Bm)_x+%p*nOnPB*)8yrJr)XPyg#~N(wR++=^07Q{4uu<2;_Pi^9xfZAj_^ieHjw zH56D3b92Y7q-7Y~y)@MA_`*AsvQ=t6+f@qgB@EEXpffv|YF+N1TH9x6!5!8+=*|_4 zENqy6vvT~FXovtxA|$8%DomS9_*B}wY>TFAsW6kXAVEmL6Z0Qfdu%JDFwXfJ4ZpE??YxR%Ab1XlkJz6pu=BuEFLN@KkexR6#bYKU}P^d@^- znn7pIp*D`OPl3W?&+IU|gJdyQK53;0C4{eP!R_2#M5vPMBC zFGVKX8I-|Ok)22YHbKJu1+ZWEo>D+;MyC7kN_#c(>QG>=R`sTvVxb8%f~VxsUwqM+ z&yPXVc)btEC}5ZEAr+)#`c7btS_;@n?r>s;hlVBdqNqR!DC$6!Wzxu=afoOajEDg6 zfnb24{I_V-L@^j{gdAScqqj1z+frgTAx;I}J&!;SH3;QZK?+yzfsD4L7*STh{piTi zJI8-c55@KHy3g(LrZ^!x8iuK~oKI#IAtuJQQN+4~5XL9uWnzSg3#s-)GXH%m;}l96 z7GWUN0wb!cv9VP`@ty5yoSWTAGcbDB&Plho^Zy$R3}2$jiex1#-SoROYc<7a6;3NXHa#uiH@IYT6O_a$5@=&BVmS-oL|$ zoI0=hXm5ec4*Lf<{!#8^gFgVCd_(CB791E5^N~T991|;RXt3`K#n?7~eOivm1jR7l zdT(k)X!)*_p@?-9unz&(P|EMXMe#8A+8m$>tZsJsA1)k6(BkF>trnTLx8=CO;&daY zFoJOznT7$(XzGA=R02W|U{eI#tDn*YSfL=qh=2ejZKHpmmK&@bH@nO&EUsF&;~st> zDbcHvwECPIcgSfr-{g|ZnipM+@*U0iZO*U1Ml9a$S4w9``VfqD=?#*=e(bu<{URaU z>@0k+J01+;bUx_-KBg-ms?~xwIK=WTaq>9kGZ10|1W zrCwefR0ssnyPsK6f<)TfZU2e}SFDK5c&mo|+8fKWly&ELae1thd%4>0W(pC2S`lDG z&<01d8rN<4fKAi7x;`r1;=^M%7H`asK3iWtPt6?5jL!K+2*~E3j3P2&x?rrteXl1p zilx?6Z**W8A3Goi3H8{N#w%in5%lr}@3kvTn<*m{h~n#Qly_=7(3B?%8-7HOAl}v2 zqt}8+ifrY=3>s6ymip>nO*vc|mkr!*{pCyQ;rgoxT8W5F!zW{5fhz8f7`$V^R(zSZ z;ri^N!5Tk3%-xUM9INa-8=S}k4k1sKZhvY;OrUY58%6ikO=F0Bk1UlXWcl;6N;WOJ z+3I(y6&zi!t!=v=+4u=&+ITe>vrG1!LvaOFyD_2 zy`G;2`19_*Z^z%3*J|6de#y_Yt1hm1B?Ec(yxpYqxti_-2=?73lIH%8nbv8wx()Z8 zFBcoYF>rmQ%viq$O&C{@mBbH{=4^M?e}aYtNw^owxtCN$ymR2fAzpX(x7+aP3q!*;-fjn}~p(H&Oz)a?nu)35GAP`Q2TZS=Xu`p6NflTwTt(3unV1)->>uI%`Ni8P@- zyI-uy(GlxJtTeP{vn5j~>S3kv6w;xFf-cDSDZs zYg2B9=QL?}M`JBqQ(}83m{|a7qE@*ef8#6#$+@%x;V>f9!IMBopQHFQ!oo-#%)d(*nr zMzAX)9RzO8;CG%l(rrj%^V^$I;sAulS;2k(vjmyiu9xS)#|!OlPi*Qu1~~aV9~E)sBN2BfgukZHMIbb^xIc{-uRlum=hT;?K0{}D}%Mp|& z7}ybK#3Yp31qC_8*4nXsTk+B_Re|-jJhL|b-wW`r?M-rq6f?RM>^Pr4`EDI#5k}0; zB+nj|#Doh|F;R`!fv2L(`{)N!M^$`ti8ykK@pv`$8Fj5X;sjefqb7QMa#%}j_e`F! z=#7FYGWcH&@e`&J2ZR&MlxC-`mzh@L#8@~ttiey4v#prNYlQW=rQw`BatgDc7n?6} z^(zJSq-7^ zL7wJ853xRo3l&xLnH2C_xy58JAGUvp-Pb;xioYbvQEL6trgS|^@AB^j)FE9U|9nS_ zfS-yksm)?2A<*b{ml&Sze=|!N2(<7vopxP*XHXW{TUyNdcwesl_=6y|5iv?kAqK^o zl}3`vy?LHzuc5gGmrff=3C{pggV5du99jGrGwlPa467h_m||L-m)(EI%DCpQ?l=ez zl{vCUv2wz?jy+?e+Ve-W#D5LNY)F+upixeglvJeu03ZPb>!-_t)Bvs!Epp^>Z7^DC z_?>frrdqwI_rJ0Irw~4DO9I+H2 zQ0p!4bngg`9_qB;+>RFVNC_zG68h6{c3)6x!iVd>Z-r6O2vTIiQa=TZRg~>ufW&U< z;x{}Wj9Z*n;X6LXg3pha9DoPI@a5(_9_M5Yj?V_MYpiUWaQ)q4OS{&)Td`07r$eNV|xzH z*d);cXpa}b2EDSn$Zz|zaWL9>qr-=1#RqwyHw_i_Ph?1n5Z^5KpkbaQgr?tovwaI~ zvvp?%Smn(w{h!yf9rpeIvc!wt-#NBC9T(LawLUKIj$0l2ZFWBXWO?2O+^)K9b_7)1 zSgCTc*XL2B7<>^$A|4kz1AeY|z@McP?O=x2ZYC@&#Nd7_a(NVGZsaz{0=NFvgLD(m z77rcxFn4#16aPxzUZ=Wr+zN{;3U1u{W0dzArp7FFa8%{)xo~_&K}p$w0*8k#_36vN zk54JRzZiKX(YoDaHC=r1P{_iUfori^?6FQ}=|(qIs#m{yb>+O)N-gw}5!nhE zfjz~lG3j9jL z)6Z?%=vWKa7%r2P;L4UOjG2iN;MKcx@v&GsF8sp2k4r3owx>C;-5AaVhZ-w~!H( z&orXa6*9g^-WKu3l}b*n#zX*FKSak`>%*DY+vOYzUcy-{v+}<&J9WyO=5AGVbaV*c ze#syrCieYeL^XUa*9*Y>6SbuD*hTEn)LXylEGx#w$y{-KxIF< zcE=E)bpbBmMRIgvc&H~|;vYM3Xc&291&@8oaAgnU7q;5h_LeI%cG$gqn+FM4PMavC zgZRjZ7TaRzx-)#ijDGu<9Us{L9A^u-m<2*O@wxo4Mq0RSl`Q*W28djY@a{cEx~ z(UXk0317NuAh=&|RY_NoC*lU0@7apH$?Dt(Vz0X8a}TJf6}DOQBR7uHwI8pGIQ*ZZ ziH!YS=v0CVxZZpYm)#rB{1GgTPCOqu(Pcslkn9Z4*W7Bwb~GI*6kwtdWOBi?h%(s5 z15A_B-vpzGMJjKu;#%)D(*&V{Izo&cuNnx?Q}$4n>uv*xWx4OBYE#=Ks43Xb+u1RE zWlrERMP=7>KLD~gdqCSwzqPnqFEF0tvHV-&Y~*_0)3X!ZbyIy9=oOGf+wP))K*07B zIW;IH6G!BXN*#7_yB45Lrx2a6nr=&)40z%Icn>8h`HKBbUafp#Cby5Gwe|jz4ow`f zRs!_}2?9tmd5(mDRzal8HQL%+ca9T93Jv_XDeG22PrM5Vd;P?Ibe%{urjK+|r?coEsHU8z=mfv^Alpc} zMd&=7xVs~RPIIF$d4#^M$YK@5epvBcbs~Luh~xag8JU6@j86R-%83Qq^ZA|o0<^sf z9u#~+6aL(c~o%7(_uHmFzHfUJP$y1~xa7=Up#HaR*zzJ?XyMgd;W zXY0yT8pVeBMpUJr#VUw2iJ;25L5=dY)W$#emNJpd!if^F19?p;YW%PA1d`ZN8rUA5 z{*CeP>~)uxly`;bJr~g>rv&ZSL2pBUb>gHAEqV4t-yHqz;29X?B$dlsmK6ofL-#X~ z@R>**IO`2NscHriKqFjO#0;NSj0AeXjjwF#=7p*1VeAY*inc|Nko8MJ4mdh4wdp|yK_xT^TFRj!1?WE zM=E_e#)WXZklg3+*Df$uPy#JR(tC`Epm&-+78Vxn?l63eX+I9hC@LRzg)C%t3FY2i zC^buc>|x8}uke@iFb@Ae@qv$*fIWQwy8Gp+`)T!uQ~PnVRfB1+SI1p(FGCTMly)d* z;3kU9FJ2V@sLcMeDA)}53sexL6L^K@e2NssGfHIM9?zU0mWcx&xuU_yDV>SAfFARR z9V1k{LIMyhc>KDSsu^sR11STQ>dxDt>HYwB<7BT#Q~s zU>~XB_6;~pT2-~>_D}QiDus|H0qSYMFNqz=0cK1zbIGN8tgu1aKE6^GiJV9TSmBji zj7>x4UXVOlEPuMKi6$7dxPY%8G;}a5??-dcNn};ITc6#g{_v7HO73BgvNc2cvzKUo z*o@wyo{l=DjhMCxNa2*uL; zj_bSOzQe!qtl}`+kYJ_u0GfX**nJ@=j^EB;ti5zbnn29abAw@`a-pIir{o<1LEXHK z<7TtDnX@xB+bdMbWJDzNij$@0r;OtGj}Q8rdiW@U>bnElfD8AIBjl`I9#8cMG za-U7eZm5C|$R%OT^TBfXTJKFwAR&4tMINE8O1k0l1qdLWQ3-V^O@g=uE{Gj6K~SiF z3eyik;vQlG(p`1zk$=c$QErdBu2&pH37CXW5%kCjWw38~0_^k%RWs@Ojf`OanD7p~ z#4>w1x72!#3-4TFvVL6oM77sc3-x(Fp3tb||J;OdE%xT2lW6RXWj?KLK3V~qB4D1C zQ}wybzR49AceWfu0Q>npeE!V_P+Owykujm^JsFfXuHGnXGENDI{ZPdg#>OHbSO0P2Ymy&W=MiaN%hdf_~8xMC+t;%^>^EE+!PR?>`scuyfsOF4bXF~&59+HW* zb-0_8xAy^{J^%$S@4vTy7ZMVh<+bI_2HF|h&WFeV9_e0=95Oci+!?L3je(13Y;Asi zghm}1z{?|9jpqsa-5e?Ep#%X)4Ttsn>-oldt8u-2TF)CEw`#3QZI*oDmrL>Q_fdfV z)zm1IthU?pc*O%ya^9C~==t#ERk{#aNuyH9qL%DW7InGi2u`UU> zL+ZUlVS--IV~HefA{u=bk-mZq|#kkbUthf^z&E13PIKR`$+*p|&b!Hk)0kl6y6&B`VX0`I7lbJZ3 z7~1T0kiONIw_{mrE{~X>2;xGVfzXMqD6BB^pKsu@y^iFW!hy`#^)=feMK{IIxpRi3 zR*%i+gsPBYIhJtst$)k@ZIdGo_0$Uq)qCe1@`aUbbx2trQHy@5O3-_Fy=|jhCA{snk~0 zxHiCj!;d{A!rjZuTDSTB%RH!u^*D_kH=TE-M(Q72mXRPxlOjn*m<-|D+E>}CFS)Xo z45eJv4)-y9LKU*f&6as2=9#*&PlQ3fN;kYs2^F`VNNpjynj(T=H$_RgJS<4$GrhxK zA3vHR7~@Z7!3nU;;dy<33m#reThMx)deeo)3$F`QWS!w zt1)J(s;XJ^wtrbt{{k!N#e16)TfihRUw}a8`N*xh%43Y{$JNbEQ@uzvEwGwy`=U7j zT8vNrzsnY<^{i3?)AD({3Ns%kbo?mjxhCid2qvwaJ&1o%Xi``4@B8%W6BZHs(aDL} zSJ2=KkjmrrZPi3+}&{# zRdJDXxGgV67;;<9SDT-opMlGt-{zAMV^r|-2J5Ia1UKK)(|vrS!E^ab`ZEwUc$%er z!2^-T)_H4ZN=H;UURh0KTtB_solFLvAAZgM=yYS`_TcL$G3{r3dL#l^9X`u_{?6bY zaMw?{-r-Uy`>&N=AxUedh>;y=t^9bETnSXwC#eSB@H}-sd2M)T7f(yX@~KJ^*QwAU zPuZLb@oh-ZPMcVGhY9!!a8FthQ;@JkB{b>fQc!So|E${lR=4bciG`>W$YJ?GBC9l! z8*wj8+R>+v<=R_t%#n^ZSSmBN+`f4pn&7QYpy45ZJWvYmI~zV=x&EH%bDia}V~}XQ z7hU24v42u3`O{qgYBV?l9b%Xniy%+$=^*S@=(q?5)m{02j$rdUonC{k&a*)Mxjd*Q z2&e7z3u3;2B%mGJaoq?7g48US(e9q^7P^F0!^?WZd0fzqm5+^@baoeNFgPSm6o&B? zN!FZ#>eLYhd&=sww6Hw$^V@xgy*T!-K+2F&J&_0o>4Zb!L-iG={?OjmA)d5$Itl3% zI&&DIjATmj*4sB(T3^^MKRNi+qQ)?nq$-+hnBQMj0gjIE1Q3eEx0S>yqdnYhs|m%9 zrF7qo&9mj>+gscF$Xf!Bg_#xbtX%Sz5Z)bQ$``ScW1dDNdXT

x+Vp~f;AH(Vpu^%Z-knJ4yq|jOQNit9rX<^mHf`@ zp~5WmG3n8~s=M4Q_0-7m5EL_0LJ&8mkQRI1ko`_;;dwKjS6uXrJy`BsI4TAusJW0x zZ>l~@gB`_lf6y@QGb61uU4~xu;DJK&z6#fyQbu}AfE}w68nlCpJcUevOdb0Q?pM&b zr2*v@Mn1?FD`u6J1GYKqQ`7K{$04%Xr%~e*gg!kz;ghB9nMS zkHr9JPnS}NVN@Lg)F3*S_1#||Hao4qlKm`QZ+lddtor?GCeYXHUvj#E`}EXVgw!*~ z%SA19=&Ap{us)yjLwHMfaZ8Jz>`N7!elq}QdaBIRe{1gBy$$2#CB6PcL?L89ar8vU z>iv(!=)XRI_LKX|pQ)<1H#hT#uPJ}#wtE`-PY+^#STf~c*jaB!3j~U|jyiAia&vPd zE0=X!93K`~y8cbN?N7+KSDcw4)Y+J%FVyR8{M-k$={&zZ{D8MV+Y)j+*Nk%lJ95U)xao1rIA_>5<(>b1GR)*oR}qZ}m>BLk;Z5E9`0 zX1+i1VpY%|_@vhbJlIj+X^dyh$(BBo@VqL+EE>QMaXxi;(W*^vbZow(uwuRFU{r!x zl+r4MAe&{wwtFl^_Vq~MAW?;rsq+KEgnB4i46 zUHk&Y`8+~&glQLlRIu5_aWrZOc!0-sO^+$p@3s1vV%(@N(9e zdkB&r)vj8qcU=7(O9t@F!Lt7mzIwySV?tHMpT+b zhLm85)C#|ur9Cw^q^;#+{bV-RhP6{qsdOee&ROABP4Kw(iA04=+_S$+915A?*J=RY%X=uvxP;D)pg zq;?%0|DhnsU9;W{2>e%hxHpl>!z%!EK)V6T#)04F!$;#&hdx#XU4)IBn--vH^>^VE zkhDE|v$Q@t`>>PDf+PI+EtBWo?|b`Aw)o2xu*>%#;jGjJ?C*_d1K6J3BVD(wZ9Ja) z2fv5=C70^7lg``6S=GP>W^X_{9k+73$yo-hVMhlJoYYhcKwhmA)swLh7Y-iz>#>(Y z(s|3SKzI^p0uKcw5AQ*|(R7h6i@_*@{}9VSLihht(657Y;;FF1#3NCWRz|cgZE+gSUQ2fTZC(m{B z1&y{Ddn|OZfE?cc%K%r3)3FS}uOcMT=#4NRnI%|WN)7q7Wfnadzmvu{i^Cur{P&pD z=vnc$tc_fVuQcA$qv^j^L$TuXQjT5oi|;#^E>=Fx1rAaxW5NM31exMTQBV?87#sKd zcOkN-s@mF?%1R@A!1R82Xxq6_c71iNq8zh&q2;J+`h-ATY`^DInR*)7BPA1Hx0@^` zzfe|f)IKE09vzY!O-Y`(q`4z}BRR#XtvTHz5o$r#fhe}h%T=Z`KecfPOUkv$_OkNk z4TAhmFmDyrbEz*-aC4DbT}4HZ@WlUA0tcx%&>~!K#QZf;48RPM$L!@rsrac-1g|#o znZYPSWVY=%je!p;myp7!B5Vftp#$I|i=ZlsZxk&nu^|yQzuk*M-mFwGw?{XMBFmi^ z4j8lEF`l%rgmc>ay$WZ@O(7 z&keneFpPE^sR>4a{){e4Rjo06AumH@gdVNc1QGV%wI`9M3;#sDxz z*CeK-YzG2y@-x8JX|{5eS6JAqlFj!T`*j;H+bC{?*XviTy7jcq1m@e@0Rf_Z$8Gz@ zlmQOgr7AL+-6tu@xo!mld_w2h*-oUS8@ZOcSytgdD=YA7ZC@|MnW0|q*J6jMI5@jL8QA3LX?v3 zZjeriLGs(ryVm#1e~N3Ez3=KBf`oJD(e>@%_FOjnt9xXckwzX4`myXnxWySsE>c3aBUI+0d1q4fEVEDmjcc@#OigU^s2lYI{oHcpyEAGQ6B{~sYdt3hpLf>aPf`m2Oj2shM9(LHb-^6o z{6|=zq9=^w*WW7T7TKKHIcsCx-d<)6>BFIlJma>%WhLW+PBr9}6(N1uk5M255GIfP z2fSUr03K)^Ge>{_?H>U#!^?$zRX4Kc0|!momeBs^jNABegHl(k@4KkXPE9+gF=@I@-xsub@P-+ z@HPFgnBSF-u3YUP;X-Em{CAjCL74X&jM;O@kCdZD(f46goTV(3<(QiiJ{o7VuLqrwoPFQq7 zWVz@4X9X(VXv)vzTzFE+$N>_qwy~3S*|om|+*utfftcC@_Fl9j|uBEZLQ=8Rk5|Y z1fcZ)`jI@7xcRzoQ5|s22aMB$OBTYxFVtSlZ!v+(ZmpFN4o#Lf%}!xTO3}Y(cWf(! z_?}O@vfb1#)?1zZ`0-=-aAC!L&#qjvVn!A>LBQ|E=>M|-I`Yf*v_Xrf2a8Mqex!VA z>D0n9|RA`2BcT@@CQa?N?fvZkz-&bCQ>3jIt0pd?ir{;ZOOp1C@G@ICW`R ziFr}%kBOQytB#JUS%C0zz5hQgfYh$aCOGrzX24p2`|?0P+d^EY4gHw>zuMuT)dUmc zHJM(O@k80;;g0R28#>c($)E($X|go1Y5QrT$fSee(Ll%j#n@T`(EzeE()RpG>_dr@ z8p_B-9O5Y^u~he$RBBS+WsJB%o+vPlSz~runjM`@v8B8fuL;h zp+;{UOg%v)=DI!*vX8I8U{yJsLLf)3|JE z0oShO8wqs4gs+1~R1+k;R^gkxaRO)J_P+{~`~HlEEgVlq$7SH{GSd`hrVXhw84M1qm`Zxx2j`Q*NM06U$$}*UuawUyCEY?Q7`7>K!(8>h zdL=QfsMi?u=AL0FdPt-izQRniVHOIM{*_bp5f)8%DwN|zlgqt%Y=#cLeEPb!E;XAx zb@D7yHVn}dt#ed6ES9y649z$r(Xyf-+vuBb%I1iuLLty3f?Lcl7&w^c6+-uRnah7J zz}ysvR6fk507q@C0#Ctj^}fAXFT~3@|MRM-f`~l>0s{UgGmQ~336kXFC{-oaq@|;k zJPV*p?^tPHl9Y_*EDWp6Z|CH5A=%g{)UFU(zQ{#G4bYF2DrMtD|E3qRI$X^6&8C-A z{w+d3BkglJ!Eijp((**fbR~b9wHKzoa0iaS5B~rDyk3d{-eXHogYM55lF`y9G8}X- z&y%XAnM}U`u?(A=5;RcX<%w9@xiZMK4zq3M0kVxY4V?SCN3(TqXrQTsUI~(YIJaA9 zIR?&_{9vNp!`-iYEc!t4Wf5w*J6>#;N$WluVwIqg$Ja2$E~YI%ex*y2Db+q0g;eD7 z4ZM4dTtlv&{35vf`IIMHz$UfyzqbANikoQbWp6Wk{s!u!^7WjBhm1hCEJ>4v0*z2)b;lXIb%j=gfi0CA) z0klwf{sHPf&{3H_)3N|{lW*w`FhUR>pJUvPYrt+ zYTY_-B46@*(Ab{qMZdEK_k7NDK}KoAH`3ox$299p2;qy%A|s5}%H+%!B;3q+t!n37 zNhqt0dU9Ci((|Vf#3jlR5>}`I@}_uP4q}Rz4KPVOkj{rWhWeuOL3EDRz+V10^MAlE zSL>M&Ad~`BYF+>%5@5JFXK=b&6Tld}d(UHAI?iS{;#QnH?tnONS0U?TQ(%?tA-D&e z%SM0-RBnr_8P?RK7~7pegHTlsA#H3-T%3Beho?J>9r35b?$GF$V(+2bbWz~4=|^D& zjTA72XemU`?av)jiW+_f)yWSnT>S}0iUmJa+VWL5LLp9_+!&6^=9|)#5(#|rm zheCST6+t>|XTa69J9dD-k(mXf70r~s`0Ll?QzJ=;l~!Zq^eT|(IC%ZR|f&w?5h;SMIog4`YoQl3T9PaFu_FVpx7PJop z5?o?4cDAwt&#JvTe)-J-R=}gqf{>6Un|AbTKm|l5eTUAYht+o)8$Fp86czNp2d)I3GO;@vXTt8hW$q&pGk}t~+s_P4?%`{0!^5)ToozXTrh)SWeK> z>hBNZ6AKMjW8Hp7V(7?$4&aMU*uJX{tm9`Bap?R-l_@nHny$xsX#x&hdNXrEEVMD9 z5Lx4@)DT7>o10AdOcnsdt^z4wbUSIn9iiwbPKV2x!uI%FgALu;o<($`=W5|2CfmUm z1V4u*eB0b69fhktl4HRmF$(l>U0X@>fDXW()uGhl=@~bjx1{ z&BwFNmcKUu5}aUxC^P&o#IuMF#es!^}XsESJM@b2MS;o)MxIMt@NT9@3gsy$%4 z8K6y_gptH**#8E=>Nm3%LFyA!g@t&?MPi*Pzo71x_6D<#JMw3>4-c!fBF;TLUwF9EULb6UJ~)544*hu?>qmMQ4Hy8l9)t zX=lLKV%XZNqN05`8xnG;S;F>F&i4H>Ae8z$1S^y?6Q991&VnsJ~(AuV0LcbRJ#ROTX+ghqEOeHhN-6lB(9$WP3M>8%jxFaC%&$R3;Lh z0LR_&4(`*fevBWRgPH~BOd#F{RpNp2u^m-9`a=G4Vl~+pKbZHhKgDDT2LYsDCqXLu z(Yd)M^X`{`Cc!%u@ce{9-?sm2$pV&bel=~(Syh#KIAMi-ZRl77T|lbtP*0|Fb5jD~ zvpWNpmH_Se!Cx{C0u%R>MmtGhjA}vhAI~<&E|K;oQy;C7C+u+Ph~dBYyX0@HgzcCd z$Vpuo2OInN>$VA~YR17Z6`$Y;JE@R9vB++sMC`Lo-fNGojAQA8QTgq|hLOhh+>p*S zVEbl$eQu}t>@;%xrW>GDZobrTTB)NgG=I<3_fkVLV66M8sr%S=;^b?OskoUMQ*^n0 z`+5xkGXoaylx-RdN6uP$76Vk;ypto6->zzE04>eHc%JuoM4WUx>6pPC89Bykl&il# zOuhd2?xeq3q4#FQ`}pDIhurk++jAS9SErLIG44Mj%PjvL9T*L5*&RP0+M6FQR+W#3 ztA?xwjpE$S)TAZ1{2|Uwx5c8v8zdRdHAUb4X32dOzAky}bG+Uir?;)|e~TIo1!I2< zA9)!3Abq>sLO2`L8T4?dbFr)I@V5OAI`4Y3H_&h3ILPIYCqqn`xXFqKib;-af43%Q zP9WvDSo;QGBzPW^6dB?!n38Q+j*3c-Sq!v4s^>Jw>VthIQ*3`av-+hh^?}39JW^Jj z3>0p_CQll@Oa_ONVE8=I`Ve|(EfL#4>bXB|%dJ)5KyGB!Y&(iw5)<;_a45G(iBr2_ z4SA;N9u0`j4$A;=(dcL`x*OP`)_NYE0pE0d{tUR9HNgi|=Fm=_kfoy}`x}fT)qVsF@$kcFkVR_U!=m^y{0Onwvj7HY2%h zryrgGgu9v89P#Vxo3r26+7)E&yzV_=P7Go7>9&(VpE@U~m+s-qW?iq!F?G!K=!u!L zbDU~Ylf$&{v6#!J=tx;6#0b9-Zd^jTKZF6?%gF$b5J1{kn(N;>#nA9oO*tS9?bX~O zQ;Wk%4HPLt>xwvRgZt8!5#dtW`?6d`+GNUO`&?DmDrN9vfRRP1$jhzlinseRho~X-qZRwSisXfC~ALnoCLi}vaT-(vY2r5MS60p{x zM1-PQo&~L=JJ7%Ai-YT^Fa|?pEzQjfD;g?Nr`zviI205VfRmZngL>xdw9^9jx6Ly` zsaDa_^e9pi<9#;!w`cKF_2_nV+p?dz@7A0RV(Nz9`@u_4k`abMOoD}9toR2wRiV|L z1Kl)C(F`AH>ff#X1iy~ZORaw>#@8Q^8F zc=g?%8q>flBGa3m7INupC5U$8Ulr;Pp!m;Cz`|4{H}D(m-TKk@hmclQPG$yMGxOk8 z`9T44E$jLhRkZ8iLxNWu&B};_o7$=0Q5=G;r5g1@U$`Kn{+$R!N<``3XCZ8lVH3M} zBv@pRrp%*=tk_isPYN?c19g?n`3XVrpU^HHOO!z>7Ils~7*$S|xwc_+)mlM-hrvfl zXUDbp5U)E@O-)NpJ_X}3P9jnI>W$d0loEe2&M6-Xym(jqMt<@5&9z${;dnk#0rkGE z7cwN3^2TKv&K2^y9NZ<8y4pde`7?x_06cKN-Lww(TbJH@0N__PMJ1I?A$hI^o^@eu zQ>Ean!Z=KX5K$V7s*ppVTK=P`qu!_?M5-GWHVstYN&C+h9Zgu$ ztbI6TiTolc4e8R)R>HX$^spb~aW~U`Db&lyTyc)9(0zrj*e3*#tRYL^y$JEIv}eTz zpJ!#+ zKiL(|PdA6?`D0~?!6EteOo14v9$mLuQlyOA3V!D!`cjy@)hDG-P=S(ovM^Kyz5*hc zJ)f$aoZX&;G`K|RnM*;;m@U>1{HbDEHVC)!6qR|fnKYPz6$R!o;k;^@FK~F3Xl^Nt z%4BQ2g37VtJ=_!e|M)n%vhq+s7<8iF@$Cq(8&lCbl&h@UBS!7X0qOk8!QK%CHQm6t zBQQwa2#=AqnyC%}zG+Ci4ou#z`mN6hlS{BaY(%_Pjo9SgtuzoVU zK5rP2xR^}B;d%bW*=Qwe<^1!)+wa|Ph|Sog2BbE-x)5z9UWUHiUhOwm?|%^i3`{LOS2TT~#b^O%X!f5)7a%q|5bg30ggmdl?8+S^zG=MzHe> z>T@&+D=sLORxe}(#mg@Rz@IWLVkMr3orDm!KK$nrR8&-)3g;kBEr!QpWGgwmvpsQp z8no6_6F7u3;=8i;kroKmKcJ6+sb1abN1$sJPVGG3>f}%~ebJSqfscRqjE z#ql*ptmNgFjJvynb6}MRw8}IT+fuiSX|XWgXE@R;WN4naY&w11Zmg(hFa~*Q%)Sv3 zqOoWatlp9ivqf57h$HIpg2gNhoP__pO?cV|307mZUMRGFVQE{$^;1`VD%qj98oSo! zceR@B%T8TgE?1l`&6ddEN1#n5WCJ{9N2!E_q-v@{cyPg{XJ_ZCuPBoYgx;Vjt%^xNJS>!}ITfBj?tP8BDiqU3cHongJj zP3$8=1Me;(#hO?D1o?2W)*q;Hn}3V4cM8-M3dqH34|dE89!(}cL} zv*wmIkAIOYVz^a$9LkA@;>~oLt^dg-n*7Y-ydiWF3ZbPagr>Q9 zQZgx%K*>&Ba^Bmj68J%7)pIRF(r1@-hy^55;ur!=@#I_c`2E!Cq9-V>=$eX>!G_j5IplUt`v&K3DPT5o_ zsE*LcnNgMJp~uYKD$a_7knwi*%^L9O`{jz%@u$@1A!T%bUTq@U^!5+-d`}X(OWJp< zO7cASD35(+3UKHgJ0m;;$&qz$@2Rmp@v=pjnb$<}v5WpD}SfQ5&@ z1(sXJ&TYD_weq-qv8H%`{ym^Cv{M%#AmY%R$Eaj&&!wiB_Vqs>nYjN`2ogx1$ER@Q zdD;=D6yv?}c~38@L!8hdakBb|P`dS4>ZWyTs+Xp9C%^4-9;g(_!}0M6s)O!7^rmqe ze>;z;tBa^UI^wJV=4{(OV~)bObNHmt_2(i3^}v)O=;~t-RLk<)@%>Hs$B&{e3}8>r z&La(AXWT^)@G{fY(q}eQfTGrb%zglj8pE{y9p>~?SjXSO@9#!94G34Mz?=n(M{Uwx zXhP6x9jbDg&(7^px|ujB$o5%3#2_9MhK)OnPg~%0M2tJ=f@9)@^~PSS5=5VpQgjE) ztWU}=E8HH;xfqp4AAVmE|M(Gmpb*agj*tEkmIH3-oV{luYpdu3T_JFtE@D^pduGhlN*@)sFVX%%myUwzy4FOQ1y8F&A<6mjq$ciDzH zfWaRc#r^GMO_AK@!l+8`%t{$z3{gHVu=F3s5?WzOq(alj z_Ch?wGL4*FwlA&3a;=(xtQqJBz}WCQoKKnNhr@cUAgNMpFg3?$JYy9NE;EY9Y#KT8)mMcxhV>c&QnbLPW24U1#L5EC>o7gz7SsQ$;r_hw1J;^*vTURSa{{Wg)Z3Z<|0#+upY5S--=6 zV{nYy!`gU^A$iPD@4b^H9I!Afn~@Db4S3-wp`LO}kLRU$NiUJ8 z3=6U~`Xh!xQ z&H0CD_=rxcg06lAExM{YYm6)dvre~Zwe7{7lfE9VEYIV`!}o_T7p$MjAR@O`9PcFk?0-_AqshG0!MN0b8O)3;a+ckf5pEA`ErI&W;c>tS zcpj=0SN&a@e?4H!sg@ffZ%@LXg=-Y6i5ob+J1?$*sLgtUrhDNFl_@Iv; z6(jju&SuDEA)%;X`?qjl^J;Bsnuj`=uiFP+{ct%`QgR716<0VuOom*nguOp`REzSft9xfY+p2I;EwcGNA@P_`2PS#Gw`R1K4d1){ZO9PQQAF z3{$xbcsq(3&OSU9<}|sTov6_B@Iqe|##2ZaldEy0=sN10fRBAix^%SJAK6ub0C5x`1b; zqqJk#M)&krKF6ZJu4R`rp2-We&z#_lIlrtoDPll4&(kBHvyv9aX2uSc-d7~aWM zHnr;y0LcHrbzoQ2QJ$=p5T0ri8%YLeGnqLdfSZP|?AwKg#SgnGu4*!q3I#5M8kf zIPAPd#TijAblEWRr`h#Hsyyt5!4od&0!xwfzUC#eh3&yIU9PuaaP|gBu8TFrL7R-b z5L%bauG@9lFO^71DFjw%z79!+Kx~0!qbTC`1IA!JNl7VWv|R)yqWGj_CY?&(5ZkVn z|JB746dcNVJs9{QeMkx`f`$k)HZCsc!B1NB&!$CMjlpSMT#!8gkFB{)qpN!L?_7lY zJB;Txl1zi|CBzDH*4x`F;uP4)^w!ZIz9xu201$Fp2~ldpY^-nA+w{TFlqfvg3J359 zO+0pnLNrEnW1eVlgwHTj1RskiiXCOq45G%xB*XjBwXFH<>=Q9)bX9%F*;?^g%vbxN z3~XnL5QELfzNX>y5I8%cnpF<*_=ke;PgXV%0-wR%!vmP;Npa-)Fu%dnlw*%HuW7r) z4(2iz7Eeq6#sGOv!=N#Jq;m@QbSnu+?u#4AvA)^X0|NmJ4 znOAy=^T*m@4UK9Op1c3%2N2Gk+Pl!xsy1mj`r5QFYCWH*PrnVLB5A6|%V%zv1#6pa@rM<~O6?5_ ztmyk5qiWi=s08|(a58CH-2RuS-TdlAZ<_c83PW~(y}s!9cE3{;n=9g+H`lNYM3j+v z54YPu5D`j(8>sTNpvMBHLyfcH2+ZHQu}^RKOVzIVqvJGs9{LA^2e}fJku+bsm;j>| zKq1RETe{<^{`whMzS~2~ZgC2gnDF9JGE?y5K`_rV!J#Kg2iaUV2Fj@kV2;)UmM8{W!|=F(^VSiQ^KQjwfdGp@VYy0% z%*O$zf>Iz-#S)7>vL{=5J6lI~$2Lp@rM=q>$KMzYZdQMU;0Xk@ZZ7dOzdKH12-QqpinJHKt;{kJV*-GsmHNPn7*B`1el;JOE22&DK- zN^22J+GQ=RNkd1c@!F`-)zyDA?qYcFq zoz)#v3DhJ5WZ)Qwvy7dv6w-hzi%4kF-(9IFM#7*mJRCB<%blB6SLtFY7(@ENnqB11{V z`BqtAjnm)Vwmxsk)17Yskpc-tjME5UVUcP*>546slp%eMkjiI=k$(vKH$W)8CDe-_ z`(n{`fzILL`dgDj&DYDcNhG=SU>l(SLlBhvf^VCbTVq41a1%0qNrLKAX_Ri z!Sq!AyXquZE)K}4%dvG0NU}~*B_+{&TQCRyYeBqd?a|Rd1Fk>4Oq)!$@kW`F=cDp~ z=d>f}q>^x}YJFU_h_;|XbNT5z2%sV@JZj0LK;QBGOQ{Sj!)Usk=pphr@jq@aI!&3u}vjJI^S0cV`pZ+@5;b_5%*4uzV z5q;qRPscir^p#Yd`0ggji1_hhMa{jkvvW-*ThT7}yhD09I}C~kDZPSfhN2m+jM|7) z=n%7Fns4BAm}ZSQTBDo;sGZE;;uT1*suLRn z>9nXq6cj6EVm+@kbkx+9GdLVfZ%(`MMT^iv<;c+}_EN^QV#8G7Z_mG<>3s!qbH{DR zM@C%Yd!-iG*f_vCWX4fw=@4ClEw#>33$>zPjRw-1e zPblToE-pgxR|W1#yG?WsdCbhoPL`cl+PRb)^8fX-EktL`D*Q%YLNnW zds z4ro~WMpyeV9uuy@8JHJX!?Swt)C7fWXbx+soB(Y zXzOrarn7>{PS`PB*vXi*wLqr~qV9O2Vqy_nDWM8m+RWOx*dnDAvQ!+ZFH0SL=wU(F zm>IZO=5R!4PTT2Ml6?l09897vx$abdo=eoar@O zY_+snjdkLPZ(rZo0HSAE;Ept=NT*J0^Q?TL1kGdIe2|%U=VHBv@-KfIaGa#)y>@!qh+UBxPo12!V zrYk^pe_FaDaC*=XU~@hL4s}gNvi{Ddbf8f1uk)%h^~A=p9k5Ih6Al2pYjIq9&L_2& z-SCB|;#W-Nk=rq`jbKzi$xk&u8G3pKC7R*GYK2EB$R8Astn0ua`=folF+U271PI*r z{2KHJIe3|Ot(M5o#+qM-$MKC7)pJLQ zu|OdYrnq=)_8rc+y3@*0JK-!d|;_^_irR91jSrf*9%uAxxXn0 zr$lTHjGO<9E+}eON^}Hp%K#ZQj=Oco%_jk11mKX}cHC{+EVZ@a`u-N*n zVQU^H`U7U3X-V7~3?n8`PEhv;@XXz@uC_Q4}=SZgDdbcrQT46}1?} z^2i1sCASb)*O&abh}KKZvd-hPb3*$5E2jYHVS3Ttl|aSjC9Z=Yx1jpB(2Uqp`xAC5 z;kUEr&eC_k(d~YQfB=qz2Z#XPS-RDil-%6o97%6PdjZdqX@kbl3_bg}R(q&jY=E&#Oj z1Ba=HH{hiD6&@4yR2oJFB25T5fq;Q6drjg$J&dl$4uq(3G?PvP55s$v!ROv%FD3b; zh6jT&weDiHhwODZ&I-jF;e?A1Zt`VgpOW)fN2sK%f4asHkW4onOBUDWe%ybAmblzqGM9 zEDW-goJYF#P|mVc1q3tzUB1{rLG_qQCRB0bGu3)jWu*P*uRz18!I{3%Na_nIGJ$!w z`n5P9%pkUT`?N7|>6#=~IuOXCRGKtYvqrW6!7t-xC*TPeizD}m8*!IgmtVDgX0;k- zivE`5bvT=1WtgySSmk+Ahy+H+G0w4lgB)&W45@yBO*ZtC=e zk??rA&2ORE2?!z6b^(1FWbX0&*Y7439CB5u!c52es%mSt>aec_)#r~f9~ z%wV@y4({&m!aWL#4?L}Qc+I7-JwAeGp1oM~AmS%7eZ+(4*Xf#tx`b3;vB@Mhl``CR zXMnZeeoY6rb5pF;*3`=F)*nDwhGl5PXpK*#i6VK|{R9vv6Dm<*;o|)uy+aj-B(8~~ zx|A@>m12Qm003TE4Pgk=bNCCu*mANRG4s(_Ix;Gyp8|q@&8QCgeP(z5++PfQp!J-` z9S`lmC}#NnWNt_=5XegcDU=R$8=a?@7e~Q0Xwd8vwiZ3+ljgL#1RBk3)#AfR2AQr4 z1qUDw`ns3O|ENfwZbmMB_jFzo2K0{> zNUh7uO8{Wquv`knwWe0r1l`OoAFLTdKiRS$g2*(!uh-8@J((Bxq^>-4um3gtLXG;n z(~(X$e8XA_c+an#1C^0tJ!d%g1+r|X`FQ?fv%kclDHHkDkWv>5n7>^0&3o(zKnzn; z+T9~aLX4^|KT6*M$$WEL%V<)^B*yXuFURkHn$@>V6%e54e3Pzha{Qh~y0AGPQxHfm zcVVhkJjDwa)Wa;$jB=}H#j9{y_UlcZv77lJSmaWqHPoBRsAE`HZqLa;8p^g9y;-=` z5Lf!MQpRdGW9bp0r1v?I;?pXB^VZ`016~(vk1|8;1xZnNAc%WFCbJ$96QznQUL6=uT60DRu?7^YEW`l8H-5B1YyXaxEuvIj5C4;` zx##zq@Y3Z;gbbrTi_qbSe-FG^^{pgi_(J6q9 z(^6y5?&$l_$QUcSKKW9E_SrL&c7LD5&rL>m4S>Eb@aE9(I?IF(USH~1F8?8n7$lPq z4RwoXdtgfQ4>Wh@9J0648eH(>rVso}LN`#qxqS2N_7~mJ)u7F=v%5!iz}q{nmc>ip zZ+?Q0um0jixk~MU01*$YQ!qO$IQF%l08Oh#cEhp0>`<$K^2Ahy-ont}u-YybC_NiY zggbEqxND$N!x zD%16|!|zE%`whc~ zS^GaW**-lce#dvkJON)bTJ|o&!7=y*)-t48Wc22)5Ilx3ey}x5Ay_G_N-v6%?Ra0Zm~X?urPd>R7QH8S(aUUPEe(a^vwRLK zlbcFk2??ygq~;@ip;T^~?T=EEz<(`mPXTG}tS8Vf zYtX7;QO3*`&U!eE=q5=qO=gN{H;)n^x?8!mC*K$MRh=wh)Mft z4ABt9aWsa7PK@z(?tgNPp?_H&*7g!#Tz`e9e9!g8c9NUkqe#h!scSQlR-YgYx?*hd z4REPWnJ$mHpDfCcuP4e47Dwm(aPCqinDjR+XN7(sDT3mIBOQ#LUs=8!VgiG1ARF>WjR{*odG-; zKL64>1jPkJoG>d@@WhDgC{x4IfI5Vak^xF1mgHF0txeqIM zM}~PqgCp7H0sa(+bH+~fugX4fXs%f>GMCx`rm9o&sK-o53iJc6PByHT1P9whWXAN| z-kwkCn+EhAw#3E8PVRdUQPNUNuAlr8Us|T8GjLEjPR1=(|G<$$D1}KzhT3Vv`Glv5 z01XbbE;uyQV!fOb0F{1_`mwlJ>1G8nDJPd>hm}4rrL!-x*!SsMmT`-O*Oy?>H`nX( zz{ZYgr$T3Jn&xx7obMV419#}8ZZZnrjRf6ON`E=Md1`uF7W8o1(UK`Yu&08sybLF% zRos8p&tRrICo|cqxoG#B*DZG&@RMA!NS&S+KaxUj8rH(T{;e&X$aaDUp9Fjw3WegeUzeq zyRm(LS|a_=PO^g90jyP&&p;3!LN*EiHJE$xjtMRZ4g<*;nj^itCpUqb_VUDt=#rlX zLIB6+{j4DWo@4ZTq@> z6W*4{s-#3CO%8)mIpzQEVaMTEZbBSry%$wq#7h7h#Re>6v;%IrVig z@zvyZE>fY1KcmAwPX4B+c%Pxg4t`-HpFj$e6)pEqPy$yV)T2d+)&pZuefbJ>(-eOM zzpQf385FT~VtnNc;2O%5mk+w{?C@V$Sa$7aW1;id+@clt^!k2x15Bj8?N_r8EaDtz z8)T7N?c$lv=10xn@DJUZe+RN31rvw1mQNq!|Gm!wl8a%WFvC;~H%Mix#Icxq($~2R z;MdLqeY7-V>IHBX7R!b9KN@j8oyBpEj)}-KyC|{`doP7$@BJ~1bDWBbd=0f71^&TV z;d3k`i|CLFhTHAsWTjI)46X!iUGG=hBmf)#2`ZR{sJBI8tNXIJg`KypDBd^sY#PPZ za&^o}Wf%_ZmsIix0n3X`O9J_r0_z5=KC=(WJJb**GfGO@l%}hcQ!4{K*;RwcX6739qYi_^k}hZ>!$e1 z{jiPnOFL2?MK;ZZSPd%T+^(;a$e}y1KfKo9`WdV^Jms$sh9H zo#fqamIMYa@E|b7=`Ql<;lbEBk6$JwP2ZXp`6&o#Lqg)a@)41`9&uRx^-4*b0ERX% zFY7<|r(zF)wFuaI`SjuMEe=oH=6LV3z+`O)u3}|kDCvpm7Mj9hV+oe?g!L@fzG+@; zJNxY0%-v;w3P;=7bf(h+@b5mH{mytKpqzNM>e05|5dMUw#bYx)kGswp)l`1#Y>HQr zgG&T-ccv*uOunuoEUUOwA36!|{_UH1aZ~=n2m?;3C+Fwqe#YW@Wi8 zvrSD?X(PjwYOlZ0AI>$Dm>X7b3GQJU9kDU~DbB3L)Ehe`Gma^5jj?}E0#Zr@)BB1u z7RHcxVXW4lqnNLe-Zc{Z@?@mHG2HFh2aYB{!Nq8$oe!PyiSFeb;E?wbq>bKKACQt^ zZMC6z6m+1-Xxhj$qmS5l2u1ZO2;zGxRJ1h9Ad$J+UCCf%&nMTxftiNbApn|1ar}iJ zj`gPO8rR8}z~%2oWDE1NKLsUf1h<`Q~j}FVir0m2)#c<_4l zLYxuyF<)V=j))LL3#VeBHVd>`pCc}?|I_^-^>+k{YU&kMo6flIHb%anF2cg_PcGZ( zyE!5-14uPt8}W%=0v`bxs85C)niwf3zB@r#j@s^gW(X~R^&!1N;bZleOYLZ-K71oq z?>~9+65Jv2_!x|;W^`ku>SN_pz=j>;0`NacRxdMJy;(|yl zW@eTbqJaZEZ`+ze`W?N-=EvI}?cT7lw{T*@+teDu9LMOi@ppj5Q zRJ-?lMp)7pvvc)yB`a^dD#f#KVo-y0-6#G{f_bw)+nNBZH?HJ_bQK&sT#*p`+bTCYOQWB{9X0*!86-N}Sqk_?y?kQaana9F{be1Pj$AG-`nQ?1 zM95-BVGp|6%7IViA=p}?_}5qs(vA~vYNXIY&OQUiR2ROvg!M*FBg>L`S63{}&I`i~ zph$b3j5z~2qQgQFXDNGk%T4Kk-20C;rrV8i@s`Q7?4m>25!l5biLu=(gR@bSC$IYTTdG!Zu!Ggj#BP{rTZIy6WmhqxD7p^Aq-( zpEenOJ5i7}LY0^oiD4XHP2ztX$j2L{9?l8eoyf=Gtw#QyVq~l;$(?^f&ywxESe{Zr zo<>e=fdPv6ufX=7skK97=X}1(x`7jrMpp>|To?4g+}SR`-A~P1u{W15bG;IMNZmUz zzQ5I;gJb5G`6?bJ^7YGO5OF*s;Z-%SBruQJ(>8yB4FZFNl~SXFy>+{Zlmtyl-h&5B z5}~xxf@x3=x%lVD0u97mQ<ns>SuT1Pv2|#pT=tgjwS7P8!IgcSfebv=|Enh5-Y)~U2fU=|+ zVfbttSM}Tn`0+f9GtIpA8!9&awh7#ReMac+wESGy=r%2tew!zd(ujljvGZn|4>{6; z4$&*8Hyzi1emyn0vdJP?AZB!fN0TFyD@nyW;Lzjd!gneDVwmxbA!(Rp zCD9v;c-A-84#dY2FyE)tDrcO9#VT|lUiOkwOgXGjBM_2W-|`~XHDr{t#E8No7?co- zjwD0AEkfbBBPKoOba)9XHjOeCe4(WlU&DaM&4(xsSqY^1|Iu{TQBij9*B?R{2^qR; z2$7I(q#G%fR63*t5v3cXTLI}VX%LZ4>5%Rgh8~a@n%{Ze^?v_%Em<@7ocmn++WWIZ zujs@4P4mY7gsbSP$sR2?Ddyd2X5BBoXu94KzHe1OIQpZNz#@rh5&mb=?(Agc{T<-i zyL6%avR{&s>-z^GK(Vi3u2GY#+Un=aOPFll7_`Mv`|C(3AJXr()a3Fi*=#da&>$~~ z+@mYM(YXh$EX<_k_)RKErf^@Z-V)xbo(e zA#A*8KT{bP6l|n}noCXJK*C+vNT++2F%@R98PJcOmRkMCh4-lRy3I1axLdi*I2jm! zta7z1A3Zw0S+S z)88^XS64BWTn(BdMZs*)_~XZEb)@7S_?ixZLl#V7hF^cX#H{>Fc`4O|*eR+<&fWpv z)7?6GJvUb!nztK-vbLsM&>f=H@ESJUfTL1gOD(| z%zCB*TJAq%;t@u%{a&&GFHOrM1AHZU8*R#o+!zhut(`eQhXiJCFHlIMGgurD+@JN> zSGIotcxXZ2uzmSf0vWr4YDLgA0jA8YY=XXh)O6mh?>*?C5bD{Vzn$C_EIn*I8L45* zs@?px;Mn%=_DWqP)%PA-O1XB@P_5^JAq-1;!|=!8p9#DlnF??-)}=1I?>daHq!exX zVAtCd-9whE1}@~#Ov3*8Z!H~Y0(qVK9GpD~bx$INEzznzJ|KKz!SpkCtRIRtnL|3s z*{|OffPHIxB#Wt%;DJ2##Ihz+^!IFGEW4B~jw6AiVaifC)-9jKxUpk(!3{S?xt~g$ zmWG1Z;k?acx$K_+e6tctk9MmyBLg^i>5CwnPsRl3^ZB1d7hj= zR;UdL4Gzw0CV0X`$y>_|I3JWPNi8sYRWuZ$lcgIU@=;r^Ce}_@_82VVy zX$>ad9h&W;gis}vv7kD;`a5Y^o>XpB>-u{@XXWa=E&aUtrJA0#ir6-R>*4(6TXNs* z!SD!8**M4g>w3TIdH_RMat(#*l^Z@mUk=qRJ(jw^-2zRZZEH6(ukG&+dhbt^ zfcfk6&Zn!ZOS1U;m%10Hoh^>yqiXgJNmd}Os9?M;J&(Nv>wtN<%KzlN_K2sKlx+QA z_dD~M*VdMGWG?3bdh^#2Dm+|9tryc5`vz z-ZZfU{1r_TQ`NMLqzc+en}4)$6Z^}o-#+;ywv-E9#+E+|=E=)rGDw2h1uAGI^5|vy zjC`i(V;#(qAv`q*xq{m>)6ERt#}+=ChwGUg#W%yXoyotRGVx~MpS_Vz>SiwBxZ84) zysQ*n{_jWaIl0B;b=z9kZ*S~!=uzosR4M)~GxP3p)XC>+=j|gJk=225L;Ek5w;}jx zpp5*-ghpC=dRajUYQ)P4TFZIcuj%_QvC{7>r6`M6p5cWUHe`BUKt0H%46aW?s8QB( z5+klL`_FH5pE7%ep2UNYB90T{iG;AJOxSc5-T8M|Jmdt&6A(~NHt6pcfF)rbSCii6+y&h?*`51CKmS~-4_AYn0!fp8*v-$!5=>Bd0u&{|+ z7k-fM3bT+qy|Xq$-LFU&;_ltBNMYS?pCBdf;oHp-XW>GFdp#6+Ap}bFE<+o!&z_?9 zn8H~3R6if0ys&sx#z6-3;PP!cUHZmqO&KFxL7Qz(Mm~&_klG@$*}LC>o067N^8Kpm zGy9lm4cDd?-%3qzUF>d%w9(Z%eODaJr|#%BJU27F|pAeh%g&a zlcxNB8rMXi#fjdaw(8dfFo5|XMvN@`uBCyV$3XL)>tii!+BPY6Iw}B)C#_AQlHiT> z(xa{QIGN-2>UV2v@c>1#^cU^e_s8`2X2YqUKvgz+7>>%9S=ekSQMhv4y2OLKJLElD zKdTV0WitmYf8tLOem>iI7S^v&Ra*ODeM}J+bx^QHXG4^HIgA zF^spL&pKACx@LWmCYq7?c^R6l#mj!}uRT`p%qPlpE!ZADaWC;c%zgWa$WS04h^7V> z)+TWmmAX>>Au-oB;ML_GX1fs!p7qIl13zE75-1P?z#HzkaD*9m0loWz||$CC$vH z?P|I#&M~-dK{O7YY>wZEdIvGoF&VWPwv1$bdPl%9%zLcn- z$IcLLxb%@OgNe<9AFV+pPgUqf%_Zoh{$ax!5jC}t-PT3nF!@yfXxlo$nR`ZZEW>Z zI=@H1hCzCtsu3e@Xx$b)=B$zrW~=3-5=@UI85jtG<$rW^*bCA8HP~MU9eZna0M0qc z;wx8a64~Ih?BO&k{>&&TMnSdL11y1WPg{Mi$Czo*%@=<(p9J>3iQ~=CK$zTZzMe7m zIV&CUIkPuDNd;POyqGq2wGcmR>C8s3DlV}#qpZEUHi_Fx%bAkY)o~YrR5}79QAJ(~ zCw_CwJ*Agg9*;`jQJRAa9rB7;viKt4Mcv0lS$``>$43xNk+qBK!=_j^G_pTfurUhp zNeACm40@51&)j&7VXLJkC%aujv;~OVFvC=y_>9z4oBD+_#oM0?NQx{9gX#}D@rV;# zmr}j*y1WoPD+9x?ED1RH`UZ4j3Gxs~$$-u?Lut(5hOuITI>SnlYby@j=ZOV!`9RKD zm8)FQbjY2SRfun@Vdm>eHIJ)(Uq8`$@N?lU!kR$*Y8zZx0pfi(el6z~`w>l>)!>PS zpKrObNy~@fBOCjYiPo#{dvw36Hfy z7!ZsXA{JwcheQOMSrh)NepvMAc+lns_#w|4EW};(-xzv=CPRK9q1GR>x~#z)(s;`G zcBaE)FMc#n9I)B~BVF2_II>)ZuZQ&^C8liH8a4x*muNwH@w37k=&OgX^!4fK(DNw& zmV#};zoRZ#xDFlbi_)odjury>SCwy--YpNIW1k-YHq1*7Jv{unumn!E!J2&(Hd9{S zdJuyb{nf2Zs+RHJQICZ)anXGNUjKAnf8&`4cMZ5oXGpke!#@?2PVvLP@pd?k^L1MKWUeVWgg%JRr!G94@o@Z$u#k2OI6tE;~~|3o6=rP!u&ZFJc03wsOriBGQ5r}jQslZgOp$crW~ z0Cmc6?!moVm-7qv=jX=-=LJK}PzS|cx{1C%I?O)7B386;$_|epS|Ba@an|B9@mhT+ zOOSR-ni{Bi^&>8BmY?!P^gZAGTgsHj<1ch-IB)mgO8U%(sH5i^*&dD6yw=v@bB2W- zk3fm0?9Sart`C$zcjSKUDBWq~cms7s+j%^&);n;w?C&QxB*-1HfAYE<9PtI}f1R7B z$*W`q3k7O#<%w6^=%EbK?Fj`>a1cRvvlkSyFOmxCT+PhPoNcQ)2ab=OH|-Q!ANljj z+ss;Uz5D91Y|D*L5N%mEN%4|oB)NbiQebScyqJ^_&Hf>zR)B>W(b?JgB0=9Gx5?kl z%+(AOY_OG1g`{=8TC*TxU&z5BFCnuR44E`C#`OONGK`1;b!y=XqlQM%hU#%eX{$SW zB9p}0lX{Kxt6DNBeykpbXdxOi{{l?RmmLH?Rbw_WQFy4vXUG;@mWZ2OJp!Xo!-9!} zum5Tc@HI&%4bqmAu6Gth(B)vRZh$vQmL$qU9&f0G*B~irWSA~}p~-39aKS+U2sWbj8vi2cdKh1BT%2u@6GkM4kKl&kfwaXcaA03q3pTetCUsoKzT% zPfazfE7?cryiv%6r64IOn$u-1FS@mDp&_=zEdOC7boD_n4EuKZ&rz7Mu|2T`7jEdc zqV8zLcjv1&AP464RT}!}dv#7@b4e7nG&ANiu0Rxfw$S%Zg55~E*OwwMdn1ZDArP#* zs>DALVNha<2GraTO=F#UoTiXw>*+Wlp$L?OAnRt8_KM5XGRI75DHT9{cp&qRQ$ zNJ(EL&~o75_TB)+BN2(?4I4+EjSHwV)=lFmmrmi(h*Y^8R^DHSei1l8{R2F;hs;)# z<5Z=LvA6|QFvDloc+7T1+XJ1co=~c!m`G z!MWM3@k&q_+5L8P0xEFH5)JWrDs6xn(@OYOgNd1Ax5&zf#TTgR^Zh|(j3(TfS}zN8 z^Epo~3CDIM0%lyZ19`-7<=6wy-mHawKpzho* zOLpV)@8=zxex(z3#OTz)o44_zBG~djepQ)%vGky14D5jqkB;8|_gH`Ew_2!wCw?1+ zXxrp+vaL^+yl?O`)Yl)XdDX@PPqO;YZaV?WVwJ#nO?h)@*aEDlr&{)wwr16wg9X18 z7|y1{AP{K23K9FCPjeJ%ENx-mSPZ!A%hL@L5u5Mom#}D}RP3TXEzPOF7?zr~i0Khm zhszL}{8|Ulv-!6B_I2~?%c6{B2f@mQt9hABsnb4-k;|N%HSpX_QFB?SC;TA{rLT4y zmGlYAZ3<_t4wY7Yphwrl8%pmyTir`LWixqw+c7Rn0BHtO$8?QAFyE+)=}*h3j`reZ zW2pXLv#AIjYT@#QUuK`2v|Q&~n)~o6v3Uf>Q`1uDsi?3BNgw2^kjeJdOnUuSNODH4 z_ipirr?2&0_&d#bM!vrTABIyCYim!K_##Mq2hcsWaD#uz7swizraUBo$P<0#iWypO zx!zW~+ua`SJ;#1P$rs$=WnDaD5BgtL>040GuE?SSRi7!~4Yl)0O5W|dn9LdPpIx^Y zCRx{U4!%I%f~nAFBGz}28!KEz7OEYq^&}+!J7EqL0h6L&0OO0IJ!Tc9kPyP^8RVy? zmdljO$64P0;+6dB&JM4)5Qx`u!<_2zM^@Zk2F72TGUppWX?96}$=cdli&v47q9TZT zr43uBvOv3smQqG;QA<+d!U)_p$BnCLt*)l3y^^;fA&RNP0`Ip`UP3A}6$WYKj^5_! zqVN5!Yjp-|a@jyUt1&}7%MgIm!7A`N=wD*kjDHoL4f|%nY1tA0- z!;lHiX$}oQ(}Jq-?m{V_&@aTHK4X5%c&1MRplsz!wx|=C%wz>^GKDqOtim}4WNcK- zN3V=r3Ops#{X+{9`v zo^ZjQN$OA5{n$Rm5{Ysmmau$*@Z0Ni${L_BwVlk*+$CoYA5lwWCYzM!SetY4(e0|T zKvN;IG%no|UJt4Iv8S2sC|)FeHZF$LEGp+4zExKN-0VYe% zi0Q7_*^3dkmRscg9X*({DF*}47*&X^@@N1DqQ%&0*v!5Vb@;l;(cIUub;1DCRGPXd zNFL7={)3La%O@<34s5RINr{2(O=IhnOsKHwq4aZv6j%{4g7~TjH8O~*`Dn#Fu8im_k@z@>-U(BZ!ASx z=H}?3RybSWb(4@^@ew%TM}f0ITwIuYXe1HQ{BN@;>$n-)_Yyj9Qy&n_kgxUOMXhvB z-^pt~-v#1@pQ4D~-p3GA02zPVwy&VclPp=OJmda1UPb=C`X2X>3`L!CYJsiTBHLM*=ateDa zEfd_$3QUDMD|Co7!J>H~z8b+9C`-OMVVd_T`_%ACZeaCu1 zyr3;JWvBJ-%ulOQIDwhVNG3R@i|@zN;|Dko(Q}neA5K$PYu}0b(=FOj;q~aV(1o`9 z{kuaUeXLC~QE1=7Fmo21N=Gagem;)ko&L7qcZ`e1+_EH&skA?h_BlhiK9-!BzE{gjhrv z*ig;qPdWSyF$58wIWS#y1YtKVIabcJAu`M9Z~kP_d;E>B;B@F5qpBrp5=TVw_Qdrx zQdq!?o>h3k;#Y&_y>cnkKWg+{T=3WgYJBCl`C^|-zygQM`9o}?AXOu|8>_G6MOfdl zeGO=jaxM<$;o~z*avV%T*yNb(NP?JmE|gJ#8h`1}RIz_pjHu^H{oQ7oreuQ)4+W&J z=WH+i#KZWxM$C%)hPt@hq4#g6j3t{%r>nJCKi5I7S{F41Ngfr&Bv?)oi$YsvC;21u zI0y^oN|`VVkBc;fPpAqTDj&|vBf$4zwlJEZibqOHSQt!Fn)J@yYa^l7rE`1d_$eI> zCJlDG>g4Hu^R`9cHsA*|IGkYW&Zi= zOB^rnv(KNW-pI1QB^nRW=aq_@_%V>AJsg?KDjnF9VM|^3x|QHLua&-hFoZ)k*KRaW zhucU%2!pJ$(F$_BY|m2ZwiuUsp_ugsO&7h8yP2C7eRz2IXNYeXo!LENPuNca8_ByR z0D-{Fv^tapukcAlU*eWZ{0%cN*O~XR#P0oo7xo7mt-U<}8ZOgS^gWkIz8R9u`}9KJ zu}A##k0@lIwWu02liiGz(`hQP(QqcWPFMCX?Dv|bM6I@(lf@A5nT1+d$l>DR)-QVY zj$~+p+@X``;VcLO6eRnB!B|4C4iozk(TlXHntj}4@8f)8&8sy6KmE!XtjqBW%hClC zwt>#VaJS{B3xT>pE_s)uiB_Romeg{p%A!lca?b!ap(F#)95r#Prkq_-aId>J1r z$k6cm+^zLCK+0<+IPByBe=Qa~C-o{&Pl&xUldH z67_cLtqE%39)y)*MR)SQ?45}b4v&l)q!q8a-{0MeyB?Cn*V)gs9u1KXkBpp)wRmft zUI$UwJ^ULKdr-|AxE;vEKF~N^2N|iJ>I$i*!*MR#f9FBEp=Vj|;I<=R7%tak*@PZbH?gQnwG_ z6pz&Rm8tjMo*x?Nzme@`;0yrQ{N5hcq@;N`pP*nO;<9Aa$5D3>fSE)eXMGr8Nj75r zCKeljK}7U9JpA}~fvbU-eG~!RgC51+@UYMJDn2}Y@%c$p*FnAsM4?r{n!&1KeE`N` z!po`BW^N3Z9a=dETG07wM-ch#R92-)TkFKm!F=8IynUtG3vmen@9uadfmFE-3nnXr z=M~>(>%6dG&PU4H8+;U}KtFC;)Fsk3_)xApI-YtMl*&QTJbHpIkdKM)Z{sga#Q35l zAc0+M?47RtLBw{K%*S~j<=k9#!nEQSgu1#=U^%MOr-=$XHz_8=Whi!e4k`032;;$} zY-wO7^7ns$2g4?W^0u@5n-Y+HjgEs}4aL-Ux@<4Ygh_{Ngy7YA%1Hxo-nMYY;f-Ib z?@4bhfy{v)EWlhteA|d8ME;Qiy{-ru8V)w^v?qf7RMsG1H64qB3C(Vw1Y(1)LE55a zI@dv3S~0UdH<-9qaNa&R)V^8HF4nE1L$v$q%mC|9es`+uE{u#Y!v)wwJ9mn*Qknbd z+wNlz8@%=qQF3O?|MLP!-T&^T^LgW9A>W;?Vjq5TNXjj`2PUXiL<^EOjlyYiFT{qY zFZ`%I;5OOVbMDFLv(2$yI;Q8Z21p-84{;cAQW`Bt+HtJ&krK*b#h3BYV8+dq8TgzJ znv6RL$w6&XJ@g7~#~mggFuOmESWJ{0wi_~Yb!{E9`LUp;pl$sAj@rQ8+13nE@famh zn}zXOwTw6ZuEX$L|KMn{9m1jZxJH*-qiN|s$rqFh)p?xoo}9Q$6Y<9}P>M^n3Ghi+ zK2Ipbx93xN1BC_FLx*nuo@Y=CIfz_-jmAD7!3+XQVk44WjTn`M&8L zO|5=J2~I#k-=KBgWd_ptxIL&XJtf5!UogIEVdrnq__s1+O@9e~Tnsh5SSG$67-9UH zeMO5#bW%;(w4>W}xsg}L1BBl#^-7h>zq03hebSR~zHZCoUt4u%+BH#6vFQhz+2r#V z4)|QON#GQLFa!DHmZ#r&76EQ96Y7&gwCmX_AEm0CJ3kd~1l zC8-{nOLO{fON;-#2>_S8DT`ybNYXK3)RK(?Crv#dQO`V}`(g?-G!6(+o zh12D)o6I(@u<0*0m)x9;zL^YB$ywHRQ&o}(t%89~#&5L+`|H{oqeY)6xFPpS)?M#R z+3Q8)5#STV(#`smitZkZIz#58YB7em$638mm`P5jpunSbj(4 z)vATSfTAE(!uJ_Mf8)y1&uTR9zKgn@!ifnPRoSy7;R5JUYy(TgOK!nsf^^Llvp9i; z-*AXysb0+pWvKQ(BUX|AN}A(o@@(+)T-=$?O}4yM{R`sfS`Un&=;nRWr@mNWUs!pw zv+$cy2d>odp&^EC)l4V%*Jo)`nUNC7%20U&vYIC})lrgP64KAAwC@NL3;5;5TxTI~j~2S`Hbd_`Pqv1O(m#wxj*6X3A~IYrH;8x2V0&?T{Ib-HgI zi?0??PZB%uEFW{Qik19#Wa7Qu_IO9j;Onxuy}H3ym4uL0>2~bcT@P~sbh0N;O`Z;} z=M!tV&xkL3cHs+)g0lw>d6R^JkoT7Co2f8bvYDRy!i@F@y~-MiF5NUSVkgL~N|c83 zEX%XCw>O}L?M2TYDck$DzT@P@R@0TQ;Y`b125(-!zl5O;xiolJ0hABCp^<8883h`4 z&yzrdDOC-`_yOgz*V!}tA$i4)r(tLGmoRyG^q`JzL#VPPz&!)Xx(3>M46V4<>Tke6 zqQ3##;q4X2yJb|X1#!k3qHY5U98Bxtsd3bO|Fy|cAV0A^$VlGB`rHtMmUMamoF|9% zC$0cTK(+nk6AK9<_Q64$m_VvZmBDtRTz6};ZP%tVMW*05a;uiH_aoIjFxYsFS2M2) zbeUNi8$xhP}UxBxDi zzO4PP{@q3N{d6^l#YkjWIftol~Q?{_fY8z-X{zHP*l!7|^9 zh=oW73bZ!&_u|&pC}KEKTs0meaEz~iAD_bA7p;1qr;Ytvy(MCd674%DgvGX28uILM zZlQq%u0a>UgYN5rpgV&XrS1`W!K$)>R+8WDW@~K2UtsHlX4Bo^btesNPZFx7T0c-zy5s%tz0wots5SrQVQ4_ zs+pMGhFt0|n=Xs2# zsJV@ZI~}zz-wA)EI#HraKkPI}#lilf&%FE5D_U{5!TfjkEO6dFX#O)hyFD}nR!>8| zDE_9sx_J#X`EwA{U09n-BIO>>1dv);ND_s6{f$CWyqn zuJimDH zz>5&^d#AvYORn29uhq9Jq-Jq$$CZ#7Gc*h?Au#!UYS&{8tS(;FZl+j6`-4wT7aLN($tbk3n{`C}@bF0Ud0l07 zxDl$)4x%U^q|RJS8Zzxc@=a58^DAJs6|L+&cvvKfoV2fK_&!I2?oaLbYwS8(&IC5; zs`HjIq7a9}1ds=$p?KfvWFU_cELGZOoPhIs#b+i_&zm6rDky+AsUj%>?EG?k@rl6cwwa?dUid47eg6QaT69{U;mIOQ2C%WVrOibsqLm$O9(@ zJsp+na%2_CxS1h`L8Ow{>>)%*OA+5;!_s(V=i4~l<(hnus4BJ5?X;@jEZ5Zb^+w~)35uP4J zISyffE{-Q#z`duUuSC79F1+rEsi}34JX8|XemI-6m$j!%P(eEa8k`*yK*S&X zD4xFVRg@9Cop(?mf`U1Ys)SQceXxLQm5)-HzFi-wIux%rc?!F4Gk4iW%iTs(8G;VKR_Zl0d5j<(Jv69*qr z$Q36%!W2&RW`Z+MeCY&cN?O|Gwl;h`qRChpnCb6<#E$D0uk%wc5V4e&>yqoT(oR(@ zobj+T|IizgA;$T~R7}>6`_s2B;LX`RYa|FrQA70f_Vk-JwXi|HynJcs3wT_twvF$u z&jr+o)7(wiP4m*%!fKpJ@z~MrdIK*0=`}Ym9Ng_iOL>n0{*?DW6&3Ty@!QoNq~9L( zO2yRPi1nyrQyPf+xIkHX)=N`AWpd@ za6{nffB@6t0SCFxnKHSV{GOU7DOJ(M`6R$DW_gG6K#FI{(d{e0f?ZNLC;GI$?7#i;x(;mF zv(zKG@->{@jSF0z1_rU zYu-$HJ?hzy8v|TFpZ0_y>#aT$^~;_MEvS{ODZW46v#arVYSQ84#PYev!G;D3+;G@e zjiPe36w&AEQNXO%f{HY0wp_hBGhFft^=GYCJ|EzyG;T0AH}kD#Q-ceDyGGXG$3`F{ z;c3W7K9a=*rp%lDw^Fs>&fr_G84?njIwDFhTRL{JGwL{3XOHTCOdG4LXX0`jlc8yK zX84(mjhCHGbND)&DIptE@vm;JXoLCpBv0SQpxj(t=2Ve?{kc5#2Pu!~>= z2Dr5UY3cm@UjGd-KoDodly)8geZ7dbHpW%j=FE^-#Y1bk;r2LM@F=|hSt>t># z7)8{}%-6Cna3cRQ_JItE|$R}#FQd=)h<-Z0n zgV;CtH@YvKje0h~0Cj`+yIQWk90L@de`VM@6NYy3AD&2$W0FZn*L{9_6nA@o)E1?zg*}2J*lsxWOErr=RT9^X>BTvpBLf zxi8<=uB?vG!y1u}g>%{d31>*mTGLX_8lRt%qaZ#_cED48Ae9!fTO*`)=_1Wl&(rN1 zG_SwC`Lzh;Eu)*m$^83=b~H^8zj?c6Gs;p~4oO-BXGS-D8kCnvv(|z`zzOB|+x;@L zm&p=S?&2VbPpn?9`*syHhh82DU& zwtj9tQaFV6H^BW3pnAq0zfj;RhI=H$56eIe;(NQtSjo0!? zW^&8Em9}|dQ4v_tNQpV$U=r@0kv|-gg`2SGQRtfw3?# z^bzgVZ13IqMYx5b)tSJmj+5+U4L{W!?NS@nKVUfsF^~_djne z<(KD_wLu?@=VA6NjxTU6woK=FI7vM$XtD8H$k9-^)%QN&mi!s==6qnF)yFHES3&z% zZk4ut7(*F{+-S4)NA;qn5Bu9MfA^z5+^Z9#u!v6xP9GF@_(o#zw*1*{jH34B9zJHy zi}KTJ42!r2ec!&9cj{phPFyW;ui#jylPGv3DL8WmLY76j z7eN_^kyobo2g~8Uw~{VFj23X9O5Ys*mu{{BpU?PUrquSC@9Aw;Goa&u5A7+OnYnp8 zA#x_FLKLxI>tJbeJD}Hk@XiV7-00zA8IH9Eu^YuJqi)D$CJG^&o>_=B42prJ=%$ZM z&iNPEQ$|U7IlJQh%ed5@;#H}j_tiOVvXSc!7(LtHNj2UAFTv^ZTaWp@a!xL86R<1{ zE;KBEG|n00;P)phE6c>t@Wa!{yzd{F6)df+6foHn*}ZH8>~~Cgc&mM#oe5#}j^e`} z_XBz+3pSJB_Mdv~cNeL-^u9&ws}~u!ShF25QUNce(+l%G)rHK*-O2sVn`XD)ji2@) ze>_&~gp@**V(6YV0+uYXQtVXPa9(eWBcS5BI-buSTL3m5IDX+o3g>5)ez%EwEgwDY z4yRwYx$TupEjE6tWn(mW-__HfZ@BQw*5z%%-scI46=2X@xvvMMkGDS@+g6HoDqD9q zxqsdK_B#=#2U1uve~k!lNX4(+O+8?X{cQySxQbevJRl3_P)REA$TYBLPn5s*uwX*|rr1!ZAH|^y%H@G>&+W8o;n^(j znZ{AsD+H^>uCwt?r?S;Fe#?3$*ye@|5KsdKt<*wkOZY_b46sXlK`7KqfigUCs=E2k z&KsvUzH^0KY3GM4xajb*p9|B92B{c<3>feI-K2vDPo+0?aH`&uC@96yfal}C+9axI zF$gSWv!EbPDON*s7_ZLIBlAqmNYC8@uQu`>%OKWwi`I*EwWg)Riwla{Zs*0lvltp5 zJ06Pd(B_&N(E13`GB>c;umB-*@a6}!RK4A-Y9aNB$8Jc;gCFnEAXvt^2ijf>i>%OP;2WVmS4 z2ve)W&#ij#Awv$&&G9V_wq}*49T#dE*lJ$Z@@tdSg@o)z?;aEP5$F^g4zw6s3e?>wwb!RGRANKy=!)|{|gW_a3dp~X`06Wn0QU83LcLX z+3rS2sMW#;%LP5+6T*q8HxN9XOK`hRur>%!Y9h`Y? zY*_3~t3w9?L?hfV?-+S^+XNu+fqoZGetr`Q!nYgu*ZmpduFp{Wh)glTlQjaLzXU6{ zCL_-fG-x8u=DU?r|L$+5LL~tabm3qbaF71WF>e&6wSt48Gr9Gq(wT@Wx#dCb%4YoD1BPjH9)R zwMm6R{hz*s&F-NTzjK-D*E{~_mAV2US#)%Rq*BtrFmR;#^@=Z7|N8Z#xfv6(d~KbV zQVq5UpqdIHAl3tONMZY10&WL{+SzwTv)0R)81C4?`A3Rst8xypPudY z^tv60?KPh~-FC%B-hPo%%tzfF(>pEK91nmddC-Njr2j%oQ_3mh*MOTv7zkMu*Y%(% zqXSIw&VI~3tRA{Yvod8Hr)02V+1o*>xrvbKRbv*1f5a#E*Cl+^d5}%YCyy3FlD!Hs zbR?cE)I}p@zBLl#iqn2iE`8a#`P>1<=x+QF^06r+zK-eEm%g7y()*}{DU_Hxyo%i9 z?_~f6HaJJ^{WcS>+S)RsOCHblonr@edL_{@W~Pfh2$OcdYaq{8IKQxH`yr$&(3Sib zm-8WC_D6M`qaOs%)o=9&8!$mjP6Zo!bg4kZM5J~F1-cuP z3=9=)aer#dIP0-9?)DecT|AQT$;gvxB$&XF_iL=U$ky;z?v&l5Iw519sYHNeOrEKr zU8p`e)hJT4lt94$Al-UERNWI_wBN)Hr+;d*AX$6Nz=GiMrG+|s5 z7o3`%UC{K}uU_ix z5p_jdK5D!wFx?-r;|*hRq3#GC0Z<9feNb3bTX}z41ZvST3xk9~Fkx!ujZV3)@6ATm zvhTH~Kn(f7gtGiU3Ac16PkGN7yGOV~R#L~I1=73{G zl$SRq5U6ITu2>0AU>0xQx8fc)x=R4PTQdf4^9@q1ZQG=Z^@tJas-l7Km~oO5lpiSk zwXJy!fuaqKa^3A@-Cg=!5ZwEkd*8G+A+PTUTJKXd{kDSqj*|xm2eAogRoVN&83-Se zW9q82`v-c@LGs7zyxh8UW(VG}gj&3A#~@(mDwG(85*8H}2D3ykVgBf$fDS52k z=`vlrK%(Ey@tf%D65L!*`CMp}Vhr>>L2~l^;+PnuUYtBmkPa)YK2`bTe-=2ZGgkPi}H%7+aC1NMDrJDaUAtH!^Qp0ogH9!qW>zg zzW?ScE;g8pog7M1_DOJf|euHf!!=-b%_9V)3 z%#^FbVX5)#XV#*1URa#`t1(JDHq3W1>}i50UArhktkM~{6SUgc2|_1 zTYWtRm=EHjDqfsYu|17RmBE7T{;0?gnpAaq$}$?di;m-Fe`Yn79xi?Eh1K?|o_@b& zWB_gs&3KDdH5~y2?sSfI5tRfAh}$8}i@TW2oJM2M{bQ5B7qB{h2Ep~C9tyOhO*#b& z{$R?uh-O&QsPDPU%g0405|4vAB}XH7QeI|y>~?=_F|@^>Qkr?>G}rvFkAbL4Z``YG z1(j((<>~jQVIw9hTJyQ@-hy!3;it-S=1+)j`OiEiez!%!@8+8Q?tSg?`LHW3U?g4p zUvUd?87=V9fv^coY9cYg4-|5lHLfv`K6z8kcJ$5v^8&mvHXf*5FOln=&)78N!a_s5 zX{*mK@4uKoj?W>hlD9;I=-0>?mcO#LE(CPWGps>1HIGbqpi9|DXXN71(Gl>S2g>(Q z9azj>uVO#`(Y%X453OcnRpUjweyS)cpfzg;>cI4o$i$VM3hm*2nI+S}VW!rpzdfA*R&w%Q?ScdWs$q#i z>{~kX-}AE+d1~v%m711X?-!EZf#1<&$;;>*-TDQt2zX6M)YS9G$OcgIkvi<#hFT3G z@I>@eAtFU0k{Vk)F~GVR~L<7$wqlaSwcqEYlN zit-d&n}o?c)9Ro=gQT~I>e%!hNlk;igC!vca9@E3NYeetw16l!wsN7`qPL6S*`ker zVu;eZ>c5j~Bx-1bnE1@_Q$fr4jw_mTR|tOBa83|5irRiu^11=6az=rKK7U|^%wS=U z$X!7SQ_J1@&dj@ST;T(htCVkCQhnG)OA>J@3KCVsS7hv)04Reg9(b zYkw90yIBF$xWa;on#`6g1t zSe~F?QUemLOjiHRtz!~~HqnKdZ2mVgU}P@byUM~)`QEjAxeA&eT4FEHCIPP5%YhU) zy+yH=^cX(~C+NxyUZOVdJL*EwMB#x1+jKB;6Bl@oq@vq1n7WQnjE!}ieLf2scUQ^% zP7&`AaJ9$e)+LiF{n>!1>J4OAvArtG&dMe_xyM8`QKbk zXY-nqd%_;}%P(Aaa6n%^S1vC^v2SZ1Bj3=dUj<$&O1-%n({yLP+yD5y2bAp8)VV%? z6M+Hj=Oj4VFZaj>+n{#^?8?`QAK*E^{Qv#ReeRE&Y4PXq&H13%q~4Nv;wgN8b5=7) z)h2~f$fjz!z?g`5?z}(i*dDiQDqkyMqXF-}C&$L3CX#{mbh?a{!jwj47YZd83@JQ< ziTJRjg4apI*??VP-oFkSa_rPVEX+HT})x=6wQIhU6Wto9MI}4UtZ#jp%d{P z&IuH2S0ol6TuhsFtr#>|Ic`RI`G*fN$xqugp)rjjus*sr);5y7O%=KQ5)lJQ7buG% zARzv4Y)mPwI9f(BtaB)t=_W^#NqL5S!p5XLRRQ)>AgZLKI7y&Pn;40G<~w;tZC*I! zCFDpg13br?H>uw`|GG88jDBiYxL&i>q-W&lb(uZ_UcHM|L-*fofq~B)KstLrs?9l| zWEh@sdL9O%it_xc*;SEN)(de}G6e#W(q?5s;b7mh>tvqpCv=4~k$1R5$0&I8DCr`j z8_y*{%|RQT|7(tH)5a$z1kc#y3nER|FZU;F;TE>erAxK4xu}(zF?9oV+;CL-H`UA+ zRR%2qHx0Q<2yf^1HTn?X_@@zd^WdaVQmMXQuM+>Bks$_5*yPTE-pIWOpatVchn!na2x%Js#vHpxE(5tfB5!%MK`S0wNW!? z$5#)iK>%2WbKvO8jc98;ike765TNQmUTsC_m*og}nc3KsYAfTWKS9_!s3|F7;_k?7 zF;|8pD?LF38ad0muZI>{du4exuJ156iPmv-^HQ22JqmVU8QH{yEN`mdGGhV?bh}x# z()nc?2qk+i1pmm=w@vnIB4Wp>P;WOawHDhhn<3md_(i%h`E-$~9#%hgDsDoPOM)D; z_1G#vTH*csoP04hb{vi-k^p~!|n%QU&Z~^(6SeTdsG$A+~j2CX02m8#8MX|dKIdYPg&^D|D!?J&jh@hf@w65$# ziAP90d3cU{i>>k_At|g1-()E2mC* zDpTAH4-O6iQnF>UAjJ#&Gfql(^8g4N3n;WG0R0sSW|&de+p$r_==p(cC+Eota&qm( zdl6L`rYJKe$cF>SOl}5w^_mmF%x@SMYF|5`5%n7LU7*7y1O@X*QFoAUgJXRp%+8uh znS+S1C&;GA`zM0_Ty8vdt*e!3l96d|F`3#g-h265Cg7iTB2SF~;MOgeBC%jd;On?x zy@mP8*{x7Ez~7aBJ+%|8QbIfUXSHYR53vRyJ3c1Bn6pdmkIp0iQ(X%KEIw)^{U#95 zv>h*AdTVQ|h$>s^U&f%vM1I5DH&7Prmd3__mH41B1}x}+Kw8p9{uehh*j`onJ4xs; zcAwGBiKvUo1_~G=Wop4U7PB+_-=V9ql%y0IJ8Fzg>AFLyavQyL8g9Cs=5NE(Y-yfx ze^b>qLK#BYshIkp&@(RVB(9!HRyJZ8-yGh|*p8uZWI9kYE0M>m6JTez9ieQSHct%{ zB`ZdHlvnq`K-b#eZdcUi<-k5VO+2`Q(tPoOg66foVGf(7Nem?wWtpafdSpaIgi3Y> zBZEB~Ouejm%dRP{?D{8WIQU z*1QcM1?t&ydjM~t^N`p0=RvVbN&9`|Tj0d8EZhVpHpEMS(XC^*%K7mDDb7KK%X++Y z(9m$m@?)^tPNL`aiFKS&yt`QV?B@~C^7T|Vc!_%M*dXR>=gC4D zlp9*Q?z0c_UVwTkK2bJCG-}q|H82$1b~H9-S^8EiQ90p*6Gzt$CIo3CGpYsvV#}IS z3owo%|2|~oy=D+}HdeERL2uwY0i0gG>oVm2ruJ30<;%6O6gfij-otq!5TWhKq7TVn z(r%G?q?}8srDm3TyvX&gBuqIo80$lxBu`!l+mDk9qAEoVCn&@A5_+UknGZfWIyh8b zL7s^f(+LYxm_=NPQ-qxGX1;WVa8jW=tsWzJVw(`dSqoQlsnVzqUB)-~ zppq5nad`jTGM#G=0OtZKpkso&uE&+GHK0H(a;ZMY4c=dJ9msM2_HB@r{XGW(-*;fjLWpW&z9VQo&3$6Axfo={rWwRayw!jaQsY&9UTMk z0&gq33|vZk^r;k*TPs8>5G|yf$#><40D7F1J-w>+w)-6CetEZx9r>FN{QL$$=I~q} z)iwzgT4Cf0vhuLvFb@;^q@dQDm2fVs#J)@V}!P6Wpah-A3_ zh+;Rs42Tj1SI?A;N#WlG#y)t7e+{_ zv4alMxA%Nym}5*~$W65}B-mm(nr2kvZRd5`h|GG!uzfVJcn_#O4?IAoGsRUiGu&^j zi?u+8>Ml!!uU&cMW|&nN?A^wThJb!*vp|3-@pmR4L6dB8u_|d?Rndn3f-o>38$G7<%#-A4?R!{&{<`Hl2!NydAL0o}>CO;IP!OJI3veGOZePG1IF`n~|C8%qN=_ zT57jc$2+fUA8X4)g{oem-R!U=!tGu@b5Oa_Y7S_fggM{{Cu<*{Qdq_9{b%Zx?ZNmW zU%qK7ukpc1_V@3}WO6LSWr?7$l-;H6_~(mbLu;|8MdJTG0psUo{vjX&+H<|k(2_=H zwpyh_z-uf{PWI!+EZ)Q%`*(HT z3MK3W7WC4X1Tk+&pcK01uY%d&(x%h zFRc84)R>!$Y)>b8x@Pyy& z<85T{dE)Kq!KA2UQ!rL2PbyDv-kAFH__?**FfJ$bmjc$;gsU>!6bP2AH4Er`J^WRI zC+4aAhACxzXHDM3PH z(rxk&B}bmJizWsqxK1q;AFp4do}as+3-D7we-Q$EPFJLRGvyZr%`*LqV>|(=?L_ns zS4=%$2~H1gg%hi21YFKX0Vy2<_Ldm)ebVhb6;kh;FVzB>dT@`KYHAn*1eQWk@V}O- z-Rp68xyinP-5TwKt|JdXnfRkn^wh_ZOYgh(+OpX`3qkxQ0a8Q{8E4?fxU#Fo2ESLO8vM5+*MNu~ z%3R%+X~j#L!8fukjw{nPv#R2s{b~AQ~j>Gfp}>%H~Sb_1`~^?>T}j>(}>>9}a}=_%g$B_$_ko zC-3qp%(14TfvM{C(f3pI$@UzeLkK9Ii9} z7)L9P9enNQ>1+9CT=-NfG~63QP1I_b0_w4j@&Pp!Up=I!P#y;jvMlZ^YYtEm+k7wg zMB51hx3-^CG?PBx-x|C2&+&ggD6Xh(I|Rf_uBN7vP`g+_^t$FfU(NmgrwKV>t5nr% z@DPPLT3;&zbcO-7pvlY54m%{{ckyzW5Ry&4YUWf3IH-};op%|sg0x4{%XE7ncjNh2iTLGG&t=eaPb`7hUz3)V*aARpLg%|5g6Z74>p!R8v~cuF z%!hg6Lz=|OEb%8UYo21>Rc!Qo+W~MeK^f7Qm3#zlFJWifl1HT?DVT> zx`c!=AAY7@zTHhJ#J6Er3d_lM%E=i9zp(Ttj6}|D>JkKNT_%GNAh79wDv7MGMwK0F zFYtY3K!k&?NleQfV$r}xt25{K74A6Tg-)~nfEC<%Zo@0EdNeONqpl@UN%C*{4qf3` zzl4!BAf!TY5HdhD@rs%A6f$}1VGv7oN>Xcs8^fVT3s*$S;bAi|O{fc~s z6IQWv0Dcx0iSmPVp<%E-S;!odh~|#ONzs=a0yG70_1P4Olf4*vk_q2sLy?#7jXjhi z*ui>4zx~OLNzg&irYQzxYck}`nW%0JFA1McP6u27897!Sq{s3H^F~RoGK!Tzx=NN; z#SigxH9LkByWarFJF7jdc1?SqxWvVuM+buhDXt2c-PT(&di65+A|fO?(p-wvx#7lb ze~cNa)0s!=X~5e8oyhfjYip#=@>;>rS0H#X_L3bvK^9Ss(6=Z6KE*-1_QuXl5j+8H z%uy>r7s;t!?JFmN*Y?I03l$^RsMF%4F*g%M`{^hOEGn&{iR#*96ftlc1p=g-DGCin z+2r++1|CD{k}&)~#nX~7rRgsoL^^(^dD5r_C=m0ppwGAdz*Ts42uO$eB9j4VC{SbP zc0A?Ur?R2~@Q^)zqsqpv zfaAYYvWTg(lJ?&@;r}!MGC#p9(SX0?w;PIBQ7E;{4AyL}0YLos#jxtr<)5ZW|s>*LZvP=mi8G-RQPGNt#f7sMx+@t;PsrE)8%$6NobV zu;20VrDPcM9YwGY-@J`=B(tjXWDh>kYy{0z{kQAnWEjck(}vv4+}zuB6hOer|9MyO z>^@mM`}_CrnVB*qSM{DVdy$bZCuR@!^i8vFdtc4)j9w@$Woz=9GXj?v&JLmXRqJ}{M?If$vDu9>qZV;;R^S7sz8^)=c_ zm;ChISSawJ4?yOQf&isLPrtka?klk?%_jY|dRvW*y+hOqqdA5wCNSl&;lO&bBpUk# z4c6C)2)ib$3c=YUZ!2Wl7PB@pXIxU~SA4_Uy_P=LF(W05ErGj-u7_x^+vR(12^6ThoeKD~Zs!~K!i^j0;8{gz6hbdsI|y*rdMxOn?8V64F3=8JW0p{XZ` z2n1Cg0-^P*%>_ijcMe7l6WHa>QP4qWdM}N(Wb9Ed%dupOe*V33o~kNcHmHTDQH*^r zLW5+gC$S4L*vW)J(_5q^Qb`)43e+Uyn5BtFKo{hb$Z_yR)lvz1k zydba5Be6;7m;MK}HhX&Pe0ud((yyjpLvX9AZ}ceAQ`-71D=ThuV)B#DddETzi<)A2 zgP{=Id-_+f%*vq5X4*>k95RHd56(I{U?g(sa}icgP~uKBMTYmMjMz5OYJaTldO9L7 z4)}u(7vSYxIlW>{9ogS^K^V2(=J-FKZ9Gpf7BaqRu099lj9%njd1~>z#A5qK+bdij zJSH_?-R8gwk|4Q3m5svckb^~PB7XI#D8#jK-K|G6&}9j@dRP`I&Jz+wQ#9%;gpIDn z5|M}c6nsKLN+-LtD|o4Y_p~$1=j&6}2%(qCZWdkQrSP@QErrG;0dE-z+ile`6Z zh&liOUiQx>yK;j-BtO3Mr%#{8q8Z|d!1z4Uq=ku`pp_qur+HkHcS2G}s3nEd!mesM`(}2!1OE#D&TQ1Mm0~InTG!EDKEBXF z+-0-_uGxcMAtD^7&feo9_6uv?Yr;W?JBzxC0pQnDeSLSkyXa>R%e(+eq*r{k<#tPv zgCUZ;yse>v!m2>h1KiNWyMqgeLQyT_;V^IA{?IV~dy!Z!UQ$)kNuwqZo0 zEy_z~bBF?wJ8R12pbnk=Gr=8-#clH=G36};%xo}JhiMTy^sC3D>Us>`?SeN_Oatn$ z*;WjBl;RQg$A;wuExiT;z~9Z;;ROplp6>Mh@XoS)VU>&Y6{4UKXzW@p#mB4SvWRVB zaHxu`Jh;76FncE~M79S=w1dt=={^BV_P}ERB=CybpfIx&c!28w7D83j^D0U4{qc3% zM*B4;&LvKhRpG*sHY?s)7Kn}8!_6)Gb@J_HCtHDlN<#`^Ws~Z0pj7B0^|h=8Bgs&d z$iyXJ@f3)AyHG_|0#vFFJNgViVs2dn9lF#<1xgECUSHw9_{l6>@~Jn18zlvwowcyw*GE|>Pw7wC2BJJG%qq563%9*7=MDB8*{jVzHg15e;XYE_3J9}?-2+1L-S zl~$vgf}0sCTGHSR7%xQ=2r>A6a(>ef6g~fL2&>Zc%BpKvP`;&I#KA%<_qt?|=(eU# zUkZJd-Nvi7B|=O^aEx$YFS3oZ!1P@=9&)ruov{XXyYD#w1~Zye?4DZ9#!S%Y_|ng< zY-$TZqHE01j{QE^)?$&~{Lu~E#?GpFLluX^wTYDhrcUn|16p2twY2!c)9+CrYKRa8 zALGTuG%aqJ+>9X?lUO1eo`_mrsHq;PQ9u85j*(hY4&8si&9X@ha~%w!k4~vmr0~*F zXqc=@f0L%>wi55Gngpe$e56|>$B2dBs)$_P(3ZRi8C~o9`-5v>dH<{UPdv0Bpv@=s zb={xLFUb+g&@{ultDDCqX!&mG=C(Evo0-J?2KHN&R?x38X>m9FAY22p#;>1ke9^Oc zbQLG)GTiu~2gxDu+_C*Je$DOjH*kTGfct6(C7}#6bXRAH`yBFz0cYSqHXBW=8tTt^ z3sfQhnRG3n^vRmvpD#Qu)`Jv)2tC8)kl&E@ofMNcQ6sDo~b`-PukM2?dNOxG*B$==V; zuQwnJ?fSfTJ)|r#HFpnu2az{Y8v3B+}5q$mx%r}u@ zxBt%8{n*m6hWA=ufTY!`m_EkSGz}EnX0(3+RmEm`%fPZc=a(Lx2vGQ(mVa`J$758y zaccQ?|5(js1w2h)`)$7v2kf2duqd&2U(^modw1Ov7+;T6#EEzU#{Y|^G7WA(f(J~u zBz3bsUZwtUySqUuO^o^Il$K?K_EmJQ>`D({t@1L`OW!W-*^`X1?+6KHY{JZDlzH{Ylmh{HY8H3>121#U`R2(!sY( zv076?d13B`G4_g-jH|Pm3_wH)aWqYnBu)oe+0}$TzM^p=4W5kt7>~htvpY-16L3c;Wm}&g#2G5aj5;JiXm*Dd zJQ)nnBhaNmr7T~tr!48j4tFm#TK{qA!ahnA!KCwY#dFFPO#vC$E$Qv@569@I_cO|g zRY&re<$A-190%x3$(|uBM!Ax1r2apBh0+S)Gr`|Q{5Hte(fU~m;wAVHXj-A2je+=R zURa0IU&>sGM5b=Jk=lH^k+(FDyxs+XEGPBp;;`Ed0s7Unw6q+6uvp`N;tX8!-ezWoL6gtR zI?sa{Q%&<3`b}Qt+y-J7F>>nqz06gnq@C&kuLX8$B1-Bx@7Gk1otiU@`h-g!md?8| zVl^oGr|jC5#=k{-kv?(~Qvn7J+`wmorJo5eHF(2*=*u-v8LVR(dGG z*aB>^$o7`?Bxq^}FbS5H zmL6qeqkE|65^_CW?CC+xx3TEIxEP7RqXwBg-VL*lChY&0Ut)LNc54KO$2QITp8QMW@de|9wIc$@JdI|TSWM)X574eyMWHb zq2&LC`Q#MaKPNLg2%rUb`j2{d{rT-om{$kRBQ!x6(Na=orwhKuG7>3&Gw*xi28AYs zUVk+rVIZ8e&$cY%Q`$tgk?u&{Z>}54R7yKo5nbb z3%jdP$$MfYJ~Z8T-H8Zp5eS(V zQ(_RxD|B$YMF%h zez;QG24TjG)ww!b&so6fj{;Bnq3^6q{lX=!sJs9i!c=zX%o9fPRxi!KT=M1O*nqy2 zd6ik;8x`gEmi2xaHM;)*l}mC({3zWGwBUv=dtY9*ThjQi@DF92qA#OQnf z5Fbg17o~|jjtunIP+wtTVU;#w#+DHVBgqkrE36!9C@?ugT+02qnkB&kar(!x4PT60 z5OjJUanJ=7@baKxb-E-r4Nyo7WshDS4~zQeE+XzT00nV7f6(o({9a&j^S>$QCH1^B zyt0bFT#s+)GD|et2j$PN%jioR)W!+s90Z(69x$c=6V?BTZvf7M90;FIjQ!zSrH1@% zY7Ym0hBAtam;+(cu4mgz=6=)+;TNyr{aaw%2&k7^xUrs{KNzY_3`BP&Bu=;MWNH%5 z`Ek)>yOYQiaikJp@=Q-L4px6Yp?=@_*VkV5>(c0-?LpNX5j_hTn1HfUyhCH)C-br4WDNkY#~mLRTR|gDP|ZFe;VGHO;-*uk9V1By3}+sJ zE%_Ne5&exHEmEYx7~q_4ZK;#=&oBES^sBT1$8jugPi0gma}@RU9j4ehIU6tJi`YDr|v_%%m=e*h<*%oG=w~ur< zCZMI&__(zSUFyq#^tSNF(hhZoE(l^I~m#Sv8r^ zp~HnM7Cee@R2Dnba{r_c4SLS;7Z>*4%oRE^&+WiGAoDl-Xxo|-Rt}E6VZ+E3^%Z7! z92j-`mmmiu)~{Fp!|po+l4@W%#qNF4Q9FNgpY6E9H|V;mifIv}kC5^;AXJC>2}KzC z`>GP=->RHcL(krt5UNvp{Bj#2%%`VbkxNF-HEX}TUVe^L`6tn1qKpeqRp{wC26CB` z!E&BBR@XDKed?h#3O^=aa5a#x2bl!rASv9I6*t`adRl)~e1v^2>FLn*t4`#?C_6`o z)N%|_NHAlUe9jdMDh)t`68#wRK_bkpFzvJ^*14jCx#sn$>yyx5{?a$7;*Dnb2z5-E zQw)Ja7b$oKsLY@DyPh_Ibl!B!P?eJHs2(buA|+Jt3=gC9ysQOhT(VzNr~5rVcsQzK z<^UHD&z95DmX9fsx13_i_i?|@Jm?%V=vU`tyrj6|1pd^Xo|Q7qpnR3K|LH&E>UkM8 zVA+wqLNy()CrN1RLrsb#1Xam{UY9{11D$<+Sw=BkX;9!u)FFtz77w547W6BeNi%%V`cqN%D>&C=8z!>z&{WmX^ z=YvqWc*IcD`NPAPW<7+;f-Z>^zl+T2mcaXq4lU>WqI8W0gi#Hw>SeU|IMsHCg|Aht zOrKwsmz|ZJWszYGe?5==tx%P=;_w^5z6HopEjFL>+8clJi1XJRwF1NedUe>&Jk?sN z--HD&m_Cn<$8KnmS^JMv``VvzVlZXQHhk#n{xd-mQ|k09=+%MC@m$8I-EzO?v}Lk* zcu!9eKUPEz7LRi+^97+;-5m$Ljgp6jg176B7>V_s=`6tjIB zfYW;}d^fSo9~4i*2uxw&HC_3dfmPD~J%nYpvUXUL&>;IfJsYDl5=)I@0!1oqdS*Q( zpF1Is7}aI{UWD!yWk!ye-nwH~&O*b*>Qn9*!n(s!$CX1@%f1S6D~KEzm#=$GA0iP< zC<%dbVsWCr;4=|_7!Vil@fYB_beM?g^$*6Q09s>=m2;6r#`qU;i&%+FOq6O)Wph=t zRZgC5Yy4k{Z;UF+_oS;n>%Y2B-X(DFoQ!QdLm+y~%Yz<6x!pbHhGaE9tZ_)3TF(j4 zdNE|es#pnq9j_;42R-9rBsk2)PsS28-1KDd%j2?MCoI06G$s-P7iR*in@A?{Ou@0=>Jr zYvzHgU5*VGK-JK@uAx9PGyTxBwKdI1K<9Ti!y#%tA(*W~&k*|b>(tYMA)nX)1Sd=i z3EZxh(M*w)$>P@MEsZKVqu7s<{f=Jy4;MsJz-Yl&NG>xJmcex(+J)Iu7nj~G2}xUi znTI+MTIf~v-rCab-xf{-tviIdvOJxXV2O@YJ*u3H1j-Nv5kphcB4ae93TYRofG`Mt zg_0Sujakms?b{am!-EOp96s+uWKo#Vcl$v5!_+7;q*?CtB#&*{2^8A{%lgdN{LQ={ zf^Hv-FkowSpYJo*uZmL`7)Zqu7(teM|B2AM8ifaAH@tyH70&*^0?D+ z_pP27#N>8YK<0X%-Z-uR74q?>5(`++gFd-W3(Jr>3JB#r66W6!;SvRFoQTj9Rg_cE zV=HQxmn z0iy7^xu)=NV5ZsHmxvkMH&sf_TJG>k+W?1=^+(Di3>*a@nTX%28u@gir)V5}*I3mx zHr6vbP*%F)pQlf*cxNhu6^r<``@~wcsT0UmRnhoJ66%-;Z4i&wuZV}}rQ0pZ#$_E0 zLhS!G$aL%eiUbwJ;NrVzF8KNo!G6^rYg%q*pLw;_MFOFoCSV%D!K}DkkGM-HoHNVme(`6cSL;+;HT9eV5~Zil5Isy0sO}p>Jql zFMIv)&@-OhozOu<-<1m1*^vIw886i{av~EE%$T3e^*Bb zu*PU{Sa-3WX_ zJ~!p-g~4sc2FJ~87#NVB3>Q>cXBF00#KxZLMRi&FO%;+6kzeWjd>#bEC~ujie1LQt zUT$s!l65EX);eU?Q_F3Ti~XD{u(Wc>XnFp-VtlnlP9qdxv(ii(tvGsgWS_|ooC_1j zLI35I*VmSncX*d8$i>3-vUPhTfc24>Y_(%INNc`4RXo(4Zkfb~$;XimpMG-$6A2y!uYsf8^ zPP~Y@=`HPbQB0^AK@v`n>n8vqxtqN6{64R?zW%PSZhPbTi2(GAxb9CX3x7M;obpUe z1fyG^t*fu*M~@sCtYP1_y$o`Wtn@PijBe7xHjdTcFK>Yzq0ds&Lg&_Q4VKI%?VK_< z4ekmt8XmOcfSP~p{Q03@5NTZhbNP8&{Lvkpo}O;1Vm&@aC+-#CYKdTuDvqpFCN=$Kbk#R2(qt8bZBYI0KX2{K#%>r#=Z88VPPHHdawaSnrPwSo z3|H&m%~4~olUiH9Y^NAkz>}G_eNky`m}qv{NBmKmSzV#^d!*0V|MDP>YW#=$RWrZu zmlbc;vWzBSl~`E`{)vCuj|ctg4vl{pets;uU3GU>VyT(eB&nmEFO&=#Y<2`*nm9bP zQ>t4yDccA9fS(pTYZmMetsJWY{|mvyW&NI>eG(s$^<6`A&Z(rKu~BY^ViDc?)s&*5 zV%HtpGZIMKd5lcHe(5J1)_Tu_oA#I#$UL#+*c8AuL_ne|zzSYDgxRmt9(bor3dDt~%>Gohq$(nb*(I zIstAxB~5xTy}K+S_o>ae_Of;wZawOjfKdITSDGHK_0$>ehm5|D21$Bij+fr^4p@oV zX7q|_G^~}?mHJ|nUE9bqST9tjFG-!pKl#m%N)zIl_zF`Fr8qVD*NR~dF}9MVL+4-r znUyDnAEA8LN#<3|7=~cvTCIS&yLCd8=6NloXK`~RmVS8dt)mD&Rld6%QBEFHX6JYX z*6R~o-ghP>5*+M7{ZasZ|5C^DKw9FwaC2Xp?hdLjeRLhsOYg28{&;^&P6p9PW&hy4 zr&O{cc-GB);Q>>h^q z&PqJwrR=)u9_1hhJ}Szq7cwszLlQ_R94cMmdJG9!o8hFYZrqKml-_W-wZh z)=rCEd5Ab8z(fp3ma_(&+gBWA<~F@9B8if~QfRDO7k4>_lnPzEp!D*yi~^!4@{uPsglkTzXz$M=tS zIwI-Mlv1kGd`vMK4*jCb-zS2AJYhhGs|_ZdDz=@U=hL(_HSNAZrF39a7z6kV*0P0D zz-(2B3a`asY4u1sThP62rp)UUh$vea2gcTZDDOt>ka338)Gf;6V|{&Lajzpw-97G4 zTD;rWqB%N!ZgbY+_IHLgfd5U;u_zwq3(!@Lx`H%l-JyPV+4wj9TTnkvE=!A`h^z(@)VDU9yv{AWUGiB_19glknWiu_Enb`(XY9R=ggjPTd(6h%;(GnR-($gu)v!ZVNlFKPFi#N_P$3GgR6`&9}RCphIKcLy$E!^9qxAq-#u6vC-woIMmsij#G z+auvaOXCb~Xj+>de`enMu3uLF5d%rkQuo${FJaj%(SOz7$NIqH-r8~z$oigD znHiC8P_g=;{#~#_+5*fwLHI-a+^!oV7}TSl_L^aUf(wUo(#StI6g?I0gt%@#TfZ^X z22X2$4DlkjHRt2pjpSh5wEi>Op*)_9qK;9vd{zolu(8WdLs|H+ zEg`A)GU2#{VaRLC%<-!UTO}&nbPpwcEnh-{o)q&ZAG__-uD>Eh7h@+P84Z-=ZK9q>qax zDfxXIyf@A&j3^%cppRC_~NO*XPkaM^WOk^o2=@pswkHT8xYDQVITtu zS>qa}?_P>E2gqO*Vp0BW2`r!*OsK&cl|Vv?%k_qd@jc~>*x65xS|~iO8uM9)@Q|5SA^(H4FL*MmX(Z= z$youa)$>9APxsT`ZiEcYT}}9ATJmF+Df@e}%U_&aAyc3}R(5wUo*y66_8mCh2}*&u z7gpOG4T3m-p0?>Mc!~-NlA3D_`dRw&@+sFWP~&16KMn>3m^?qJEZI_WE69z<1R0?(mG}EZhstFsZq; z#L3f(n1pYIVB7;qQtdHyQF~^e7V5_m*(SiISd5^lj*}GAZx=3 z#_Im3(jqJ@JlaEM-IG3B2>$_pMT4_)zSA*5+$w!k_Yy2xpq7l$Ynlr$F0tON9Cp)u z`hP9J!8U3w02}1wEhn{@%wiw{SM0L8^N@Q%oKH4 z8gTVClhjW2yHSPre-i)L3xknie`vRDUdWV~D?2#&ZZ=nz<(|*39s^HM|M0d(rG)AR zldNPa=8ypm`FUn`+!uDep8loF(lBIsPoi(}%J-$I2QkCti8`tM=}ByZ=@fpTI#h~S zBszrjU5t>|{_OlF*1&s3D{)l4d+e%jSh1fwwAAuQnVY9;#vJXI_HHN$C7XpXB#5|= zWL4t!`von+DF`k3)QjCKmK8+Kib+B4r|i42in7OG2?<*DbC0{LPbDjk z-p&-fkX0g7-DaLQ>SMR3PyL^RR)q6_LPI+pb(r8 zMuWOHZp#eeX&91T1SGTd$|P=LWJ$4pR)xtS_{09__6aMN<#J{WAFZ@Pu<~+fD&Fjw ztV^`c=DWwq(15vvo^Au5c^43evt_OI*vgv;yA$2c7pUIB%PklkLy?j}0>I1XHoLpcD`+#*El@utr0BbBp@CEg8iYiO% ze_SsIEke$ci0C5-HT%D?$gs1K>+f|XxkKf|ZfnO1AUkpe0w2xig)0O+(Efo*>i&Y2 zS-gbTM&BbUZSAOMJ{H2X$PlMt@IDd(TCvq54}U}?z$Ps28#^e7<_OsTuW%d;R#sI7 z7Lxz{3VD%H6bgw-3pR_t`I}=l8V)8-u(mg#jOMTZ%DT)zHq=_c4p3$RdizbIVo8Rk za6!`???;Lbjrku@Xk4;P<*!3rYGw>S8CjW{hX^9a;3OArA7y5-7hMGQ2^KJVo8Bx@ zFcCR^kg!D%(E6fiPr@`7JRNx}*+)`v*MX2rHk}m-m!#*B)=(vLen(N_%nxC z%7cBb%P%gz8Q!~#->-Mw1I20R#&hVwl5)zzCN}H%eF_z*G_$Qb)85$c_viapx_bJC zE4np8bLszNwkMTTR6e{#(h`CsqyE$@a@?2Y-j&Uis1jgEL!Az%9@2fGfW_(OpJL~C z@7{}Drcd|`D;ixaZVo=5IzPotUWIIZ;?#e~FwOzkM6&+uNW+*^timb_A`1`t!hqD} z8@t{q&SG6sEhUz0`QA+v9vaGyy(vM}G~zQF(c7ho?^$cWm;LVTbMH!cYn&@`JR7mz zcQI0adqo#?QNn*0`bJj91j|nF$Zi3|xKCt#yBvU>t_>1*%L#2u!vlNMuOaMQssimv$ z_Fa@^u^>`PXwNObeEHwJku}LK-=Op_>L}kErdKuQG2boB8=t*-S0hRUL^JgpdCNcs z*pMG5NGc#2Q}>Q({1DYm(K zFF3jwVLf*2b$R^k6A&)N>v`sJLdjbh^}9N}l)4bS+Qo7~R@80I{6_jD>n1qk<^{xV zPn1w3AcPT#ek8U$9!jH!OPQa$o#x_GPJexLsi~=nLGJd|3X1mJFz~W{qL1T8CH-4Y z;jkR_oXpPgzOeQ=nd3MQ^-2j7qUoBNn#z(eMd=+aVo;o|k6FHy$)dRtda%vEas)Oy z%AzQN`S{c;al`N;iLe?URK#1~!9PyZWIJ+eEyY+EsGV+FPD02jvKlXuM~m9`Y_~D3 zMbiR9a%i*xQRWk$6aiM-B|J@8NuQ5n#&YY8%kcuw4vx0Awn~Pm0fG7C6jL{#I3F&$ z6z+ZJM}`C|<#EVQ3k>AjVTLHYmM#&(i0$=$XPs%0<2_GLgiSfod@Z5EL`QycUtIit zq$!)x27X4>MeLqd=4i*hL-P^S?h_wGHy%R8OiWgd5Tv%Ro$Ikw;RsaY=6Ef8*&oZ0 zWE!F-IHbtWa|2jW#6NK}tCb6l?_W_nTC=nHMbX=M$s~@>T#4Vh}q*R(Ud)c)#(;xhZy1 zlXuv!p|IAh=OA~yk^vhr>~0so_6|g^0(h?GYi)boy|!9LoAwZ^55qWOSACsaTvgKQ z#xpVsVI0yeUaK^+kt3J)ewqc_2Ojq`PZ*;@$HE}~Uw74xE5F6nXmcxB%7NSXQ;!V9 zsUTkv0s*Ocv9n-3Ukqj}A8MC-+$z$Xr@5@uwF0k{2%+(~IfU{gWlTr{6>(2&451=} zyz#+7_}421YK7ODVSn&s$LqUd=5*QPve{8$u0M3&=(Sz`O*A~uZaQ{9IWY}lTX0ur zL_tE5Fz9Uz5puC@c_10RTe)s4K>R6bC(5u9HcHLa^%2dBvT94DuROMgg&MRx8(UN*uNGX`H2-GN8 zGZfUS=#EjBFQ_;Mmd|~)ujLI4{aq>>zEQ%uka23v&G4f5W6|HnvSHD~Reg=;&21+3 zx?uRVvw$P%w~2UNSzaJbr|YMd z3@wX}_HRGpg`VP;_l3+*CzI>(8eWYEcuhzHDhf<)84!55s<^0bo{T}P@b$hTYxTgs zQ(OD{ibTVEJkq|DK(KAy3u*O-z4C|81+z5)9uNrnBhcIhJX7z4Toy*(N)%yXhGBBh zO~%euan7XH)XZZlqcSFV90%o0{hS)iDxRc z_q~)jS;5yJ3E?rMv3C~&#j6qg2`i0gU>VHD%!%%JDtkvnmAB#desBW5nv$<;WHhL6 zi%S@;T+Pr$lUzu{A@m2qqU;g#m<(KY=TrKiLEE8Sy zJv%KJ-AN{sQ^E5z2DR7O&BfZ%-t_qdG~RB$FD+H<=PQ3%{UGl#dtVL4l)wbq zehmx^EG=Y0I1D}drO(d?IcBK!XMvqe_N{L~Hf}tvAP-MX#rW#nj?2Iw4NRv4nhpKG ze$_F$7DPUkEcjIj^lji_^DQb0c4_|iPPs%CF8pJVb@kW%;tH>Tz^}En4zator>~<& z2KMz&uYlgz=KYbT=Z!!y=y+(kXXm~V8})xm^mW@c0Fu3K0Ur0)RFvb+FEJd%9W1S zrOx~JgR!yrmyF0!IG$guo)o<kA9aR8$Qj?pHQ8B^kodi6H8H%sQ^e1xV&}gwhpoXAoqhRAXh+MS zzcs}n>I0%XQIdY=oUf;r%#gS(jpje~9wx8;Ib=l=n8i~m75QX1C1IgabE8?j#e?6i zQs53)8QzIFT&w~v{^?Oo51o-zoJYdRk3u1XNfh*zb}3t z!N_1@Rr}7|LhWJ&2mSHy_mkG^$1{PZ(Z@U^&(+nZLmeP@(d4;LL-EN#7ez|(fi(p0 zEJal)Edr^^SywB*4=E(K#2vkl`1Q+FPn;JYZC?3By;FrC>8}LihWc^}mV`_MjpbU5 zrZ1<%&#TjEiyT;`NkC&@rvc`C0?iy2saCs<2%+QTTH8gIA=K9(kCVyCSU|TP z$@xfu-h@wC6+%nP!e|z@45s3BdI#4OClE)b9_0u?SieXX1Tek8GH6mhSQkw<&4q~$ z^fe_PAqbi~ws$>FLQ~6ICW=hy(E`l`F^PkH|0ZPh1=`Kg%gzTV2e+WGkD;@7=UR&w z7h+}44w>T8;wfsbNkvFtGUZu{oa?69S^oH8HMnKF0T=ne(cck7e%cCD4)>~($%-F$ z%6OR`O)YhGO>HTse&B!hHLR<0zkW@9LZ$z`0}VKS9UTj<4(5kT4j;rV>bm|!jL8+m ztfEk^IxKOTQ|<%9Wudr#PKPnn+;dc*DUw2nSE$LUw=4~qOBF*EMQ?7oED@D&Ut?HU zGLlK>kz+UFxBNBkTSC51){KBfnF#(ki=$yE$vjy@x#znZ{yJ5NEHDsCi+fD!V3^4$ z{DbUrR)<{l#ygi7Nk1T3Hz|NFZ)*3ac+KR#%7q(;49WhJw1xsl-ew+PoU+JxJg}sj z3B59WIJEz@-JoN*n|6HZ#^?Fi1GGY!a%pmbeqK(q?OyYF9@vUGKizKAtOFe^13~1T zH-JA+U(bLr8W3%47aK3@ChZr~70+uYmXgPPxNfvq#IbEO1BZNJCjW>)U;=5^W3Ss} zowhs3vD>v!#yNaj_sf~^P*xp%f9Y_+H69dEZ_47X+dN+K)2J-oNv)f!s&7aFsU%_Le4~)MI z3n?`7CEoJ25D}S+R_wv{zG5Act`w=!(o4h%Qi0$q9aJZ+WF@IBB{_0f}vLoj>qMEAb#7lxl5LYRA zt_$|L?JTB(ZAn{h%ZQ4Uv?h5FeB|l2xW76CFoK;7r(_v-+f4O=K>sS~gOW>9Qrb(* zsH8)@LiVh0R=UZFc?)hypMt(U^R!uOBdP|7Y$5iMEJ)eW-{KDV4nO}1G@k6+(o3Lf zRFdZCHI>4RkL!y5r;Wo$^xbNaTJ+Wk<4Rj^b&sqH)-_$j18TWWex#7twJ6IzNPRvId~%Fs^G$ux*j985O@Q&Kuu7v%R#GIGfcMY7)Wt`TFq zFl!LdA@l!Stg}b+_w=fEA8lxIJ_c&29Blv$%?1G>B`-(*-0}52so!S&G))kNv()N+ zK@)(+N`zNg;;dZ<>xV2IU%&X0%}1Czmz%VFcwR%j-3NW6DIxtu8P49+DFjkO0;6}0 zf8A)&0jU#ibr?t8(uQ%!>?b$p#MQ5^vUl;&)xHtcJ1u%EIVWK0qyvfZl}}H}_gPYm zW@So7^MOm&tRgBy98p7TZDoS{G4RZ{eX$DW=9B?4VWyh)^wbnVwB?p^RTZx^%McqG z|H%#zvteOlb5ue!*48FyAY>(J>lz!~4sK5WeittkyUVd(Xf_8*S^E3sDIN;RV+zzo zDm7L8UsSI9k7?}7Rb3d{9Az*GG#sPK$-gtv^_L8y06Of&9u(Uy2Jb2OzoP7?uAU|Q z13302c4n=D+1F)O*4txXq{8c5_)+V>dqu@i0{sMs5J~}5EK&91m*d_oni@ zf8m-wOxe%BqiHS-{Sj6u8!5`c#RUiicx3`q#>?D~9mZ}BF?8LzKUk4>E~b7eMW1)# zj0k-3ys9d{>EUbh1a=DlshVDQTp6Al(SXfjXN_>Qb)75YVdEQM;GgQc&}ltO1o$4| z8Bd3!E$7R}rxA9|r#pD6B%}DujX9gtumXk1Lz^qGmM2I!UoFm8Fi=WGNW)!B zWx?X8@k>6`#D8bE>Y7pGD~A1ikwadjKt5qxQ1-thJ%7b>E`?gHWeBSIl~3sK9x`BK zi-8-}nQ)sn>Reojt{piGgJBjXRWWA7B}ec3KH{Y@m=i&G+uDenZuoSjpGUWu4%4TJ z{=s**nCWGC0|*wL)fCAqitNKAQyTRt7bO=oG&wzty(ad`2j6rBMjlX6T8xgHc$3K6 zlU)7#X}{fkD*Jg+TPx_b_~%p6jRvKZw)%LmA&z+P2~f8Skm3O*MjB%AQ0ZW~sm^L|bNZ=g!7VoX zuhe75@5$Y}$|hTftF!lIH%|y@hAXe`C6LxMODbI9^h#$m;?q73~yo@ za9}ojt&71d%R0&z3*wMX|L#wb*LARDhOcCMCF|my1_Ww@2w}&q3t&t98AmovrMGA2 z9f?r0_V&Dk=gHn+S)l61h}9d*pUNZdn7wa>ow*wBB^1GlsTkk+XOKkqMC?ZW#S%X=__$RUd~+A z3D`EcZN5KRw&!Rse*Yf$zw!$g_1^Uzc2t+1!zYvmMFksPKb*4>zs67&sho@m_!xUl zjx|9EjnVNPAT(r&s@c505F4G_id`N;;T=#eW zFb)Bol!}jDIjcp?{NE&fs8H2EB2%ZN&HH11`&P_BH~4y$7#kpsATtAqDnTbVyJwVZ zqtlZ2T7Lsc?LNVch$8|&pdLT=ie2^tS?wt&gV|SEjw5=aMZ{q!;`y~w6|>5Ve!c|Y zcZ|fHBQ(Oly`BL`rqR&wFa$DRgjfVNd{>Kh_dsb<6ZG7ID44_ZHnMH$P+OYO=;Wce z_59Etc-Qtraj-6pyO>1p=BPj+KVbQjT>offc`LchC`<^!7M;&6*T7B9>-gI9c(2$9 zVCYZ< z-J4RD@+FtiU$L680IHApRglz12s;_}n>R!W2}IY1KgZ1z4FtJ(9Dy^S>A1oD`3XhY zAoZ}Ekae=JNMY-=kU9p(f;lFMO4i-iK-Ow7jE4+U;4+w>&Wc7JS6Tk0@ro?wz=Q*i zGW}rYp$9g!s5B|o3EM4RSkrV-g!sq!)?4CH`=oI@C%KXr3oVuJ4pQh2qps(9KUxxz zOvKvoo(<;3G`yTxU*lDzV)XUSq`}p~<+RT2o7=+X>L$jF#uuVSb%OP(!WoN4o{jP? zB~eOnDr0fUva3yOsij`Jqxi|g4Wzy#W(BhFf9t@DO5jfz7L1bO$|Lza2NlL5-C0!` z6g`uW)znVl zyE>@GSa(-cAn%7~zb_XZ_iFV(rpJt(SmbKQG&Xj5yigPvVP$guuK&?E$r9U1z54#k zHcg->j_mK9jFJDo1-F0zQ+AGEy2}w-5V^aJg~eOYho%EgDGku^F9-y%3 zNwPdK!&4Gm!J>HF%UD7EHSCpuSWjt^fdAOOQ|X=E#XYo78J?7OEv?=Ktkcy|j}3MQ z)HQ{U2i3aism1FSNnQt0`OnYK0|H49F063!a4JXrB#T86%z?!rus9nV4u@^k$zbBb zp}ECHZ^xBp3BBQ6QV~fGj0E zzfn0v`C+1sSXI%<(N$L{*sdRLbj#)M&_&Wv1E5xgwuV%MUdU-GVpC^Wz1shYA#JKprFGbKPTV(7HL z{co79*{Fwu#Gja=UTr39D4M#qs8Eqv=G25KP|@*AKfUizcI1$40hwc4+EkHVM@@04 zlHGU7_=}Lz0w1cRH6bq7f%OxsH?k58`Mb%HS^454-|VE<<$0X*XoI1JmC)y7o&=kS z#Gw=eF-MRiQJZa>mxxiH{ZU$( z-)Cl);rN|A%G_vH`#XhNz;qm;95%Ex-1PxhTfBx!Pu=hQ`KG3P+3WdNfyz501H;Cn z##y?VIc}h_jKcFd;y7Mg(XN8P@d^c4V?r7C zQ*2LXnCHh#T`eBHz6pul4Cc?4qPw-q(@kC5|o%e{P(tNWZrQHO`Fo;w7!R+@^EvH_pe z2Y$;z2PxXKG`sPsoHaf|>G7`oS2%vzEPLaHldQ?zZj_D_zh|vX9DvW>TFGvz_5Zy9 zoj8XJ4UX1s0|6%yE)Qm5|3S&50p?;c+$H$-)vS@%<+M(Q<52^^uwHbrc@DU4v44KN z2O8k^=lHjuw#uIc3A(#go2vJmvT1QT@>vs^S~IsM=Xn_esVVUa=Mq97evZocw!l$}!0cOs{VsLTnx_2+689(d`&hT<UVw?-9xV2}kQ8C=!(ftSOd8fEGbOD1{T!-tWpvf5x~gF4H?L@tn2FI6FA2wQ4i z`a|c0@i@q)nN0)26S-e9O3XDTZabL_Wj2m6AeW^BCrf5SPQ$tvD$q#qhSZ8VbQpWn zI_4};Kp;JJJTvD;$0runktfXPM|KEgL}gSo-sG;_Gd<-fxdDw_4I*zFYu&_dW*jtS zxPG7=64!7HL#39J6Nl$I6>@XJ!z@h*>CZA#lKRt8+&QIQRgnAnpV4y9EU5luWJ(Q7 zr@KbrLe-IwF)V2^kd*U+MEP?iVq7T>4yh#|`&jI*s{X+3O7t3@)^_&(xn>q%e*unj z!M71a0E$s1?IY(GKfC#A=wia~^-MT|T+Gwv8HkH|^=xX!#sU*?YMqkmuyf0K09&Ok z8nF>n7=y7!g$Y{z?Xj9h4Ip?IeNzc8u2d?46u50f%W6(^fyIjvOD@l?mzPem^-hBc zYH=MH>bjpl0|s@t&{Y?H5YD^w3?tW3_mxdXc)FhOT^9%V6%}wSPhI%a7!gnfgD@@g z+ALHJh(3Nm3?#Hisnb!n)5=SUPz#1sSZQn|nJ6BgZA4?D)2J}zC8b?yy@)0wq@w+z zw-pU&fIBU{#L99rxdd2j10%8LBS_OuG%PCuXxy4_IyU_5Ob_lfN3a{YnxMW) zwct}$Qu4SRG-|!c4wcDKS7LHF+cBM-Gc!-Yv3#n|)D4PTwQefI_DAeQfugiBMJRtS zXOV2M6Wc8PoSZF2(3JQ;T`WBS=3UuGa5XKUx#EYkGZlRg`Ah%_xr}W78?Ivj-CPO% zfF+t~;7F>Ugx~x3J2A~0bAG5bKnlBm_wGeQRFc8>*J&`UOd3a(_&6znc{1Hwg&4IH zY4wdE6EIgVVRW2^Zh~B#Nf;9#C8@yq=?CgOuV?0yl>uquSlS(MIQzUdeB7Ib^Fz;k zFpk=uUdLk(vGEwnsiud`6Ac@yo1O12PLuGe zf%2)mE=9#beEb$_0tgr{)O%1f47nCuL2auOKbuS9P0(k_55g5h=RgqRe#!-T6Pa5* za|@;_&+oQt75-9Sw7%aD6g6)8fRYLs{*~&_!PuKTUKD?~^LvTj_7w>s zQU?;!w*ozpc(*$?G1VerOZzt*SRn5oSmH0_K8bfLNiNVK)gB(sr5eWTE|SvRuF!;L z(+s!n1}d((;#M4gyIyiLle9r?kG1c#CBTiF|4ixKd=2tWSPVyZ58*UF7t@rB{S|x8 z#xLf2J!cxU_~k=6Bg~llZOi`hu}43T4*r*(vCk5kUIfp7DcX4F(?X&@0^>VC-Bxs2 zy=-?Xhi=}!fv=|S*er51{n{Q%zSWfK!=@fcQInLZ_GU6tl|X?}(wrGv+oNs6&wZ#| z=$QX-NMMer>pJo01qT%O}zAR9nLeb-&-m1;sTLSmx72xDBo6Mi@+Wm9R=K6GQ zRA1ZL>Ua(CV$RJWN*DCW-B~W8H)`JP7Z(>31C@ySgUn=ZHWu7ynND!DBDMVbr;j@= zTr>=WPDsGu4<4z`3Sj7qhc(Rg$1T3bS8hhh>fbe$IZQ51r&|eF_k}d1TeA zO&4|SaaWZJ#_Zjp`)NEJprwI{C^$~q_KOovP-_e z&McP?1$=mAWn};fw*5+^$rPWVv4uVY-dXoFx0ntLI02AU}(7 z*6P|T@z$<$ea3;lCw(!|Bo0nldW3@kSvfy%_?w4Ih4I<^-Zpili2 z(1%m^}U)QQi7gvYw#$TR>e%&A4_VC#)G(rbaaF%fVfxkhWp~vO)qRRnsL<+!^ zArj?QHa%Bc=brf_xNUpD6~$vDDZ!&C&x5j1ZGOHLAD>5R-~7YD4J&@2^8BPT@?g>B z`Cy1eAft#ilfvT}V+0^s8q7A!@hs>gNx@yY-;!|Ju)Nv!9Vbbn8I1eLF7|_hrhw6O zP{X!YS;}~1iL-iLSp{r@uUSW{bR1OvB7R8 zMLRB5DX>d1=Kg-Z$Tz9Eec)7!GFGUU+@chh=w-VVCF0MlFd}fA6cCO(tD;cKu5fr_ z2i1(){SDd?cJw&=n06Q(M)=;OHf6}yf5amkw?mztz>@fdxVW@Ian6^&@Ts88m`bf6 zT##JaLcZb)Jw8_u2;y67{yRJFuRZD50$aMyQmu(YW{6pH?ZJjm(wm|cp}uxzWOwW`zZf>#!v=aoFvwCF@UjXUnnI>MTsl!gEthFvtSXAVw08ti`iXBLJz9 z3TysaX`5P82m*~nBjJWH!*O2__9k*ZzcEGEZEvcrc7544s2Tn!51!U^EC}pG%9@`= zqW)pBJq#n3ILR5`5d-M{@RSsE%$0`V{$N$lJ;_-7*Z?-Eyh$eADTkECCsAy+aYmy zRCjAeSC!wckCvP4f#d*=Xua+J6{18!SKpzZt~R7_U?7P7?R1)9ufXcAGy8S(25`-X z$IzIN-6tl4;qq-8YaMObkLhD%wZT=WX+e#H3Q<20|wvlS2Q89eWbRs5G6^?H73O@yzcqx2SIN+18BpIXk&8sAfqBKzis!3vx{D1v`phO1a&^m%p??97yGW+ zBFPd>f9h&)c9|XFDlRV2Q6)8o`A89zX;9rkSczAU|<-cIJqIlK@Fx$VKe$Z}al*+ZKL{8|= zN3JzoyZYVDCheK8A9fEaFrW0*cfgsXVJk$G_C zJ0o?~d&b znJMt)6@dHAA#jCo-q->AKHMfs?>5s}D1`6ts&{$&_t$s?`sc@Jm|#(%+m|m}Dqt_v zsvPy9xIHZ%2y-VPJ7&fy4MXwl4p87+{zBuKvOfpE3UiKswx;zs>u1o2O)4~fL;>*! z9)Co)n5iEA$%~fX!n^Hl`rs^JK#Q z#xE}%ANjV+UD+Z)+5NZ1o)M(tweS4xZho4)OQAueRaCej3=+5mcX6tEYTRd&f;T{* zzH>*SE`k?6?K~qYPw148&4;%hOerooAMiMmB4-=$^sWUcsgjQ+i?|9v-ehAK4KCC? zB0u)JfHK^tk?q~pJJ*ksj+jVW3+7^#gKa64qNJ z<@_oO!Is_p)R8oi>y22|2wpz6w)Hdn+XVaD($%|Cpk*n8LdY{4)`5vR|AS1uKchJr zC35Aou&K`4?I9W?^>jY(BOT1|Z*3(@Kr*IscUY}OY|ydD{ZOot{hsdpagBU1mJ6KK zT}1hXw_}~1II7*O0+nk-uvZ_f%o(%;;x^jncOOq8w7DOsBsp4X2|__i3L%sx3H?Kc zEL(`c@)`0LH-&kh9K@<-@H<=_u0Af8KhN;3cs)O^VS%Y>T{KYX{}YjbMa&aW)$%9= z&=IWXo(Fzis}xkto0)(JUZQ;h99W<9KbSx}`If!=Y$v;jA$VLx)_QzH`b6f|ivat0BbBFgP$WcZMC3YnTC@3`wFS4%hBg_U8;;3vxwkE)LAb{B1y}OxgmaBXP;q# zim~s8Wlb>=Tl7ZD8*3M3EN{;nhLlww%BQ3OaN^SABf`~E97?EQ_uACjH@zKgPS;`R z8kvM$n{d#9(7u?dr@p%0^@;9LM8t6JNEf0p5Q@Q<)#r_Ym+4f~Q?9uB>Bi(ONSLDK z{4WK>y(W}&yhTW+t8g@NNt_2m}|vA%8_m z%+au@?(!vz4Ubs5>e0!LRarv=L}060TDB~xUw^dlt@UnAGLu8o;O*rl$wl+HB0tq0rtCA0VI4AkREFFm5U?34d=} z`A-;X_NAbO>Q6~-zc;d=hI8+s%gWQ{;wzT#KhZt|qam?~a*OS@4=;HNZ49PB7YuU< za5$vqU#*EeGsb*n(5ez(<7YEYLXJ-H);mTFpS}Q(#wj^*y&vS1N7h2INqO6(NmXO( z@Ppv5E2qqWMAxZJipC=MEAOygJ*fjsjTo)2Y%7bQFWRbF*ufw<+J+CJM&Z=9lh)Rj zRd+cQk1hBN5g1#ze-iE69(BAnbyiLR*=?Y_xlIQm|5=?OZcBSeX{eoT%40u8;k}<{ zp#*g*F97_8jO;1@U9%?vX(=yo?_RRCZDiwk?fA9bD7KN!;S0P1YfggHWh?u(1G&V0 zp#&W%o0yF4-UV-+qKmrQ7{7n+3 zYyh+qY*O#yd))+yJ^d4lPC-xRwB8mbLv?{Y%=L-_gPCX%K-ridrS>KER|62FHg@4s zQji3lgf~H*^FJNB33bRt+-!gpBRa|~4|I%;14SaN+eQ$2S!~2bVlQ$6H2R%edS1<) z{)-ej+gW*h({i2Ywd>+}?_yb{%hJ3pCu&lZ0ziwCMOY#-?W}vCh2WyiLzl_w*YFxU zVN_p|^WjN7bl0X9?__XQJ}tczi$(Tc;RH>j@Y%}s(?mH?E?Nh`L<@s+$7gPEp4R@= zEjy>?`0y=#{|8i89yRWl=@~f<4xAk!n2Rf!2Q`#4Joa|u% zm<3e>Vj>}dUY@gpRvE04AB!sqe#!BwFGY!^A}9ebIb@-^HMz)%zFMH{4T#_%D~MvH z;@4twl_k}vD71?IIS5|$wMmi$`vw2COj$gq#Lw_ndNgsfG5!8+MJ0R`Eh;P-JAFnbAeN-KS|fxp&t7jjTq*6C*328`KTjkTd;#P8meP?n{5_wqXFqP?3MQ`W_5} z+Fo?A^B)%m2~5zMk{ZZN3eQE*$I3$>kA}x>p1bxdcL{u68`q*2m*rwv7LSHM=FN3f z=r0{d#WJ|1wKVsy-G{0xD<68j9vA@r_?!F36|PZXp)?hskLW}8$*`r;1AEOhn%iVtBKy z^_U)d9n6?V5FDEQb2#;xi0hnaF)`Ddk!iE36f#QR7zN(@hGC(#I)yjwbQtVsVW;ia zfD`XOf^NLJ1Ihv;f_<%ZrNM0sVVLS*@1X|l>}x{6gU_v0s>TOA7BnCjiyiUd}CNDrf za;z1WKa0@m(Xf18TuRRx3`)c8lqFfX<-^paJKBWaWPF_UQ{%-Ps>HUpSZ;emnM~^K zqRt`Z^TONU`ec~Royn2Wols5v%6;sMHb;W;B=XLCqeq0-Sp>zr{_4&vglQ1Y^C`pA z&bLTWEMqcX+JK>`0pnL_q8>Mx9QXkU#M6eV*yU1(U(@xG$oIAOrl?)X@@w~6|+TN+i0Z95TOP=>FF01GEqBlN& zzw?tvh7T=%6l)yP3Bk5#k8uBk_N(5S5i6c0m?MBVyAXsKwB`{5&6W>3y5kQVc?4f# zMtUqeuW=$iVV_I{zYne){>bba3M8W7|u5 zHJ+|~D=pTZ?9g0I2-+XS?D+~syB2ND3$VmmtyN6bHso^+E;5H6%fP3p%PN(35s5Hhk=YfQg)0bGLxIeJdlhcI4BkI`&iSZ03$ULD4C&_M zsBm)UPT?FBrhPChUENptQeV50KYb(DSa*hqV~%V{NU2>Ts_e3kep_1@|72s$Vab$H zqK?q&DvU6vfIyGPPk22um z`=OBLV2p(2r(aExb=c`?Z^n(-bGg?wzSt8!o7cQD0c@BX76bTdH;{vu35*y14kma8h;Nz&Kx z%g7|p@>gsmM+p!+*O#r$+iv=U2;XH6A+p!nvok5R(iYDfw86kw{d>QRopi$|w~GL` zy)Xx{wNL)}#XoI0)UM?$~7R##fw`D7=v*GgFpRzImSfnVoWS(WQh z{WbE~sXiH%p3&f_HsjjIS4Y14?!b+{f4)e7bc-D1z`%QWJ&>yin~7nT1!FIZaCl4 z%?V9pN!sUMce@3ncJOx>h*~S@syAw)peY|E7rx8#x540K9vsCFS=?_1KO1sExn8dM zs=T>(Dx~p7Sbs0&-R_^Zx8XRYD&LDwB_#!Rw-ng{?Z&v&piTvbV1)9IePP@nGREeCG}w z<%)*gXcISPjF%M}f;bRq&w*h{bTwRA(N^}R%y0Bsb@}d&$`hj z-I}`aSgfp@Pq4c6L+~BocyL0gWcQwrPbL244DY^1_ZA4nNQO9Zzol{lj|edA{ehDh zzn1q;)&i_9bIQTVzLw)n7-=K6DlPsa$C5PyEU_)k4-Wl~I=ogi8v<|TLChiIkN6U2R);yQx2%&UzOo);s zrtM;WZrzf@V6oAo!cHwaD8xTsZ8p59tSsF^Of5_3bcJovZ1K`2E&Dc!`Txm=c`A&iuu*p~^v z_j9%r-{B*fDgeZ3cJa`0<
mOLqcc@373++cpn&)8t3E~mn5T->Ui*Vt;11zKAg zI1S7!Wn~?~5j~t9+=V!awfXAkT8KR0ihc$V+9#7@m$5nHTfjde zCBuETDSxv6P20_^G`3QQa8cro$4>)GylrLlDm`LqMm5T~2%(oUxAx6YMdr^5-C2@B zZ9g_H%!HW+KH90KE$%xI>Npx3PO@X*)6lbz>m#)b;?uCvP@#*Vp~xBylL_BEwB0m3 zcPk}#(k1F!d```)WJztbTAZ;mlKPlin))`GC^6w_>uNDkCt);QkKzJDeqkyfvC3CN zyY54+9LtRXe@_ix)MpE=ujVdv+XO^94tY@1Mth#+h!VI#>=RrGhXy!;g@4`9zJBut z9YrUqcy9s_H55ZhNl9OZz7!|omovw}A@=~dZLHK(=-EG_2w4B`1yD-37U_fMq^40n zhU0HdZ8wlaWBkRXllOVa(~nL$Gwna3f!p|@w@vo2dh3m0qsl%JhblL+7Fvy&aoH@c zS(%&2*7u`>J2CfdF|U)3pr`%Br~M4T%$%CK4@8~FKU~ZV_eQz~26~@9ar;lv(<5hEiJ;V6I$E-|Zma``&E0a-6?b@jKs4L2 z1nl4GjM3AkEoqK=IrBir+FUeEYHI9q)AcKKKY&+o5%{tt!((6XwZ8N2%-26%K)=Ua z}%t5w-@TGuwY6sL0lM;)B(J2f+c3UGc$4O6oL( zf%z$0bzZ%{M^QNNLN`pAV&UWOR7?GumV6Vz-llNg$(l*PX8L|v`sVuFHLI4^zXX+D z0kp>Kc-k3Hb^S)vKh4PE#;c#`Gpw&fp0jeF9VRvl4Q%_ey_C#q(N2~iLthnV>$07Z z!iCbV#WEUaL1J;e5GKGrt_358M^XmDLVCK4Gqby3u%im^`7`V!s4#h=c?T7li08%J zsj1RMZC%S{<=}@~)#qLO7Q@XIK4t4;pw0Bx{nf#zm5Tb`>}ex_|MV+*%St9<0QhN* z?fnT2&SM9~LqSJoB#aq(c}bwa!1eVf%#Te0Aq6$XbfCo+_gS{bVk2<JkFlCxd%t z!91d66-*_x5NbEcf8(E4_>>AX*P}FEdduh8S#!x%IghR^2NLmnBZKRxNrZ{>R@pa=pu zs`H@NzizJ<0aa@-DBWv?Zi}SKkwDfVqQu!|wfRYnM#@+Ng4>4kN-$1qs<8OBE30g= z*wDj#(Hau%C_^ToiWnj=VMjwnN<43Z%V=uvZ0!@l1bOi_9p;G6s;D${wQ-#mhOmt} z-xct(vR>fmJDlc3{u)+di0yafCW`J1ig=h4dfNRn;b5R~G*y)1G-n5ya9S;w8 zTIwn-9skMs1xsFIvijd?p{*X@s7dzaldIa@FJ*WFE_N}eGXgH~4+vpJp_UnEIx|d?QAo$R^&EKW zIF44mPA9Hx$M%^9W;0yZkKB)MFABtJ8XJiukT8c}$S-p3QaGjX34s#wYg4haoVt}e z1*xwo^hDC-Mm);rvKcr3gpQl{hjw`)f8)nzvm7-%r#ITQa|cRDtvr8gJ59fS_>gk&&Z9J)GDaU)F8;#c)8m3vG)>su%7w5*K6FSu4J{s>~PyaYVN(7_%3A`T&&GCZx=nkbhk&Nf* z4oJnFV*S*~DnmP0MtRTl7Hx!xj^xGh!RKMH`0%~lzK2S)nPh=CUX9gqt)8CkV%MjX z0pRR<0Nx4a)jUsK6pyC^11dUWtI+Lbqr3G)6LkVo69fR+v45lSuz!DJ!z=m}Kh=b$7nJ{l9Oib!6ZFbQw#&!4_ zXk1FvASl`zj^)mVIjx$4Z47ssQvPJ{;6~%EADJ7Lu1FZVGr&jjY%?0&L(ERTl%rc4 zBnP2=YzK;PU0NRx?Q0?&qU=@1DiQ7CQW^>tl+>~jWB{F}$j>xM zADnp1?X>*r-(@m ze95{(j*V9PhCF6ldH28UEv~+ia(%sSxf{c(JJvv23cZ^aH5Trz; zQ@TOv?vCgDUpyNxf$QQL=bYbtf8%qgT0~^yeHuE{RL7}V)&SWSa`)SOJ!|Ic7XLw~ z`G*e&vYPTg#2#E0N3nC(eQ!au`Dkgkd5eEc>ao_heW>vcf9biax0e~rOgNH}jBc&c ze^4ch0{(ECB2Jm9vvu&rmJ~_}vbl2grIj~)!XyY}u=XQD(K?^wI)C9N<-;4w3gv^m z{k!=|Uh9qh)*lu$MZmf_C!oH_+y@^t0`ByJ*lKB~wjVyEqyQ%%jeOCU)?Sf|`H%DE ziL~NPO-(+(5&%zycU>ody3GMiH@$B7=B64Sfz&0lIkyhTI%}OlK*Tx(DD%WK3;dv+ z4h$q|yBq4j@Zn-{eb;$&;Ba1rhMB@>y#})9ubi+H%X&CEemdf?2(qAz!#Mg8;vxYq za$EEb>;t|y-Ur{3OFc&#DS&Khv&t01!C#Dd8iG5es~kE{sXP6SC9gYxNTqh;d^Onw zK_e$Nzo0IEUVav&7>!rgP-3f^_XOz9`J{O<<3E0mQH!l;ozmIxwd?d)A8s;zLg}}u(WDCuFnkp8q*NI4oim$j~f7LQ*4dp>&9z!j~R^~jC;3!Z^ig#T3Ec|K|a zE2N8nPZg!<1_nL}N|PbCbt`V5{HF_tyT=ZAe0dt8I+J38j10Z=HoG%;q;d9PPWmxl zBTqyyPp#cPl7I$wU7P&kcdD+-2xTpLmaa@-Z&7P){$p>$@nh-pVTNH_(dscFWRi&~ z39GsOpwSK2nIWR=jUr+DI4373Q(tBeKvOBM+rU|(Ay+?poD{kQfa{Cttf=D$SjidOY;9q6Vh~kh(bpmJ%Koto^}mb*b*|jR_c?pA?t(hD>W3R*4x| z$7tdIE5UL`pb;q}T!$%!U7Nm3w(j~bxp@)@aIXUHIEBtt_bjCb;_uF>t$C$QaE$}< z)$^)4|LLlZliM*1pWDs*>tnhErQ`oxIXlt8YuiBjmd^|L2iBv zf|oI^lL>&2UA!0@*`Ef%jrD5V{>I9*xop=0m~cb84{Lu__seLLlmG+6&C)zXIf>3( zJRk~F?bWm(!E5eg2@l{KxFzYcMsvhxXD+*uHOsv*Q;>7T#g8t@>q1WBl4!(z{%)`- z#4CRND*DdMWTgS3DY}rFjwt$g)KczST^-SHM@f(pm%N|=Vz)jrvm*2KjgM{e@qhhF zQ`zH;ya|Cb?|=u&G)@geLeEGaN9FviNLnbm5?i5BJVIG;eu`~JTdh!1mJ*glVT5_W z$dx{fcdLY+F=AsL-z}+{-gPR+8(Mf@&URc0rpydU z*y)qTU_tL8c8GGMiaiOcg~&?KmQuDK?WGMVP8-L$(CcX1uzxI4Fplp5Z|o^r8wh^s;e*Fw9?8?yHLTZHgz!L?D$^l4Q}18|D*>P+DTRoy{6OH9RY& zv;-Ubm+5=I-@v2jVl{9LC0Jg^k{>%A%_h`uoX*VmG4AP%`}wRPO`#+4imWvw&_&`h@Ok7D^Vc$d{A} zA-NKVe7`LYivTW$7qlCtbOSUww%hz5j|>4Gd=i-?wD822YiH zCBk0=zZ&5zKxJs>E&!*pTx>ELQ!*_El(G|%@yK<{?ZH7}&A??&b!Jm<$pLIe8TY4x zhBTYlt+V$^DX2YC7N7$EzsEEb0%_^w87mzB{EDB{8u}M8^koR%z^pp{4Pyji(yCWL zP`furJKoxUvz1!?VduFerlq0mLBkZY5ec>?YWY_y9&&;aY{|Tm7;IW6YAQ zsKq8mON&OQ#WJVb?|bZoeitdxvtw?6F8NJ(2Pibj#bSvw;`4M)tE2*g7p&su#Jv=P zjmpA_8Fqe`g0m7KCu=cj0IW!?v8}B>;Q9!dlm7DLssT2q@`eGbl$*d86v+7K;Ry)| zMb%H2KvaeT%>SlpO#1oZp%|S-OqRJ21;k4Kt1^uR7`|{$PwPV3Nq@f2PF`{oKgOfS zI1j6%f5aJD71TxN#d$2~7vNyB_MGT+w)Zl<#>XYdtlUo`?XnRX4zJDK+k{n(9xCKe zSpRJYrFtiGRaL7skO&1Q|7EX8&VK%`?!N>#@6kmOTIK3bigkU#t_C{;E%n%#9=T(^-(UuRpSk% z#Kf>1p|<_g1`7b)1(Np?dThO5n3MA&m`qXo#zZoTKNo+xD4w;eM}(G=1{lidTQnn02@pX*!}@p2_Bt;+ONLgIxXF? z8|J4Ifm)m2^b%#tWypyp%ubkm-RNp;dV?908QR||bY#Xq@^A%hf$`JPt}Qi6_->W( zpz6OlqqAtu$+I|KykCNnVl32x1}YNa?idgH>vt?qfUKH|UfkgY|p9*z_efxs^9KVcHf%#j3>1s?(^A4nx3V?)CWn zl)K>0B8nyZT2*8WaB>Oe64N?`?rbWN^$I6F;spiqS9=y*0sYzcKHVC+;0sXLwV_cfLFUXJ+#hNmKLcl#DybrbS8t&wC=JeV_ zbO~k7e#r#Aa8yFalX^?k{PyxgrRlp779NZ-24zqtp>`cY>ba#;%O7%1?28+lqYcq4);-*HLoXTV)gw&Rc3oVxrhMrw7 zWKi)0YlIA}VLlz6SzM($%tCN9OxvXv&o<1gdnhn*n{ka+)LfX=VuQXF_m13UEl}%- zcJ5`dsNtZDUP@OF4W(!1oT^T=)~_Wcan%zXN3Kf25rz=I`MuKAoY2L?`XEK*V9W6( z?%@HZ^vyAQsa$i*NM_iPH2V3qRdRsx7o7LSl>TDj#f9fX_s5&3VL%92MvjqZ*SN9v7 zRU68sPtrAfBk^P0PtCP#n6t=l`LGX}o{*>@>&DgN=a33RZ&(oIMFgrXRHePcU1!@u zbFsz`1u^3E7GaKOfQIAQXpH>QtZ9H(yL z8~uHMq3n^ZkSbbq&>GHO7bUXJ$me=y{=dGBxmv)Ee1+Y{2P^TQtw zx(ZAi5zgcyr8i`u$x9IGcr#LUg#w-hDxijan$r*kMEYj0pCy(FgeeQ3Hz#i`8ywib z#Zl@hbMvV_Ffub@Qji65@uPFlP8@ap}_XPvtl;kI@0=LuiX+QPyD zu%-X~PT!ao*Q^Z|v4Q=8?^u0&92AQ4^PhRLnw~l`8ouQDOEDjl{J>i{5f25^XT?_H zm~CakfaUWkLGqExJ81Av<4=YZloSd%`80l$|32$wFA#K}oh6<+0;=Ey^@VD&mAl8z z_<45mWn^ijZl7Ta=mo$Ozr=uTxG58T$bNfLf$meCG)&JU?_(#c@0N{DIAdU#Z7fNS zJk?+a4)+jcaM|H8;G8jex(X;FW%QAY(rFJNqn%`M_rq^F@pu z^!Vf-Zse%qItdYwI+{PI^KvNqXelXgM$`len%V5=Dq8Ls4a;4*WuQ`At+z(zn)|I! zOWRW9Ht{JVUsz)YKI*0Gb1|Zu{!7WUcM+YK_^5Y**xcMq*I8^*#sl!hH#>lR*HM5g zuD+pef`SqHCY$*mFHtYWq`;fWtD!t@JBQ-k2EcV;W(4a|L389wgQ5BKkwRVm;0(tS z{EmnjDae~vA%QOlg(j&f@b;#sGDI24b)>w($?;ZG*z~ACfV=x)G(gk)o@8PelkC+C zpQCLwV-hsxHHh33=FPaU+}TG#Q2RKEcGH8EB>PgP2KrVllqpA&Yd&<`!|+ZIuv zqxo@}@`L~r!ZG^wsP%~%$+g_q+7JxzTQ}rYMdFVe2n(((Ts2Q&43OL6)2Mrhquu87Q@^s5 z4$vGQv~w->xT^^mqpW$x>hw{N6-Xx5913lo3L==c9k8Q6=$TrTrF*jQuKu_gu?#k# zvKy1e;1j!zaQJ;g)<@|f1qTdgq|{zkbsGFWT&eb}zQ>KMC>z_RvQ^6L={m%Z#>`9#EJa#_~A)ODkI(^W>77 z(A4|mRZ{<)k4bmB-8XS?bp{4OCUFw!B!%GdarG71z0#8TD!{Y-8o=t_J#2UKP;h<& zSM;Z!vg-)(^U7L}#?>4M;F%X6_!8Tqaz%r80^^Tj<3n3sG<>#a;o?aN@q&L`pG6EQ zE%`I_3YE50ve4V<%J4u4I~}E7biw2Y1Uj!21X|qkLeC3fm{Sy$@sZxg&nN4QhVT47 z#o~}fdFyKSO+vOu0e|g}+5N@^4Q88XgP=#X9y`Ltsj?=)Nn>3)X+LWoii7!P^3*&D zZ+1a9))>!WJPzcIaXUuuL85yPhun_z%oHuXi782Zg0JdsZ`C(;c8k!_BlIiO8V~i{ zf;+z}uY2va2&V6n*Cqp%2Ez};NteMF87zYH|7s$)D@M4_1^WSdnzmBZ=)Y1e3~ijEs9=o zCow2}UTu+-iT2s9T;a$Yb;Bl@SRT)e{jTC$VT4qEdLbpBo#5b$TR>|5z5q9_->CJuWb*uA-6Xd82Q;l=gjNwFq;~9 z@86SO=ZOcDA^gFJESQQK!!|OH)z#5Yjfniq+))Z4uU2udf&};(jT<^oczVx%|IAhf zJTjBiI1W1wWHe^~@08+&JZ3vWhhK9^_fy~~Un3i#n7yS2|m;F-;SD^zC32pHgT}R#?2`)uYv+k&+qlM z-?Qcr&%@!~yPYU^|B3lY2dS(35TmOqKw1XYF0D<8Kjkoc+S(x7$H2Yrc%cQDdpEgP zf>ztnF!<@2Q7NwO)famy$Uc*mr=7MysQbN6Zo^gD1gTy*#nrP~PfR6LjneqF-fjv% zpK*6?D+hZWeyx)v1%o%5x27owwdbcu(&3c-^ozUq<h+V*bDI_fXGU_Xh^3HTjR@q3L47B8pN%)J4`}SOMgBf9A zWDG(1aDt-P$|lFXB0j90FuFG{hH3h)jCfdB9Jsy)L={j|7sq&Fni(XEvJQ%V!Uoaz z&Xw4|i!cZ3RKrL2tFofH*xoq*)+bVvl?kGhkZye7If*IMogBTMP4=C?{et2?!KrC6 z^OF|}kv0U>7Cur!?uoMZ?Uf2!Z%uYVEYH0YHaOy$WR=AUMp6TWO9$Xp$5GOwF1-_M z^ccR}?yC53Q)j4#q5}C&>lE1w*@0hv3LEh9{Pw52{pUjHVrI6*s@C9=N`d%67rld( zSf|+asM;Pr$@!|g}C)7SVr3$v^Gl% z3(i$%+ac@Zz)o1|V*HmqbJlpN;LAgXv|_#k8(7csG4jO2T?&Er1k#6M>^smimmDV8 ziHGJXE#&NR)+}h+ON?5*tS|B9GvGnF05T{R&#kj77k{WVYVv?gd0o&Je|`;uRtp`d z!ry1)^QJu|=lMXeyicvJ|5{b!$MS0*8jq7-?j3>jJqSde|6XM{2L91}gR%e;v?2=@ z(vyPh^}Y7jf}L@z*6{rv6Ec*&L76V-8)6WUy2ZKMFS>xMbHAx}AI?NfibW!4WMuU5 z{<_W0$*EGBqC(~EQKpsma=M*p?ugXwfV8ORjfysjxvIN4G5XO&k_w<_>FWaxwX^DO z1qzBp7HQZO?0i0b8Y|co3Cs{y7gqL8JzYnHk@<%*%yvPyi~Y5B@&@ljFDod=TVM$=@`Bx>ebK; z#AP&T!8s!r-_tDBcemvelP&!|-hC|x-}DBSWkaIvmNcVMe36W?OM&`g)H+WL%iFGX z`RJ?TP7yNgv~+z+8yZb!h0IiXS<5TQlsMrk#Hv7J=x=b7y6!A4Rq}e_#Cj2@L)r^) zC=;k+Fg3Ot;zT)+!-A%jQA*ym?%`NAxjXflInUtlFIHlk0=;HMO3HyQs5!|m*n1y0 z`i}fT2oIRgP9UY#kr{<|a&vRp&RFVkYLWr{B2yKF&x*`%tC1Q=7qMJ~#9$ig_sT;k zDhusQfR_<98LxzY=nPc`?Srxu5C5=>Wq+2sGIR-(VaUP??;9}tBiTKvzDMVydJn(0 z1;vt>&z3L8P8MEjxJBNg56jzNEQn7~^F1!!BIsY>h@#?A$cqGA(RjZcTAlqD*&2nk zQ9_|>hs7=z56+-2Sz6o>BBM`BBlz*AnZN#I`%HNDC*tMfblsO)hRlBqx2s^vou#J9 z;d&9$w%5!&*$r|K5xhLDHKlSk|9X3>bruQAxeS*!M>dE144zE~4c3?SS&>0Y?W;$9T_7~h-oK4? zeutWm8_zVE&Ar6XFv_Ej{S_dhwAyx1uNnhF>bMT*++OTBG!5A+Uuki>2bL#6L5}vR zhqg$bzNv>E;t2(zY_<$JS+i2-Rg01rm}09T+Z#O;K>NghV#y8QZ3OzA?2MzpRG?ck zp!d1b4Nlp*qiKC+9=Q$P zHN?}qwr!7lJ5&Jixyc(xlz*>DKS#_`ZCUJ1s76S^Adx}6%H*p_=(~t*zItx=t7fV1nR_?g96Aqg7 zeJoa{4MP19$gjX?OWN`ms9glMWJhyf+W>Ll`4M=UW|+ED;zYgCnWj^59;xPx^Eb$s zY`NpPS3{(5cc`jxa8nflkuTbH@pMq*1DshI7MUUz@fx}?Q z<55i#c%o87>Dt5fiA(xB#ADRHy%!Ua&UieI@g7Z3UTGBTtu87(PV&%Kkzt#Re^B#I z^yJbEJ6O@*y`7`HKktL1;-l?U>s@8gLEuCZCrmW(-AXiyD9%b9;*s1U5PnfCeu+*ZHFBz>8DxX^hPGu5wLqQ*I``Yo9i)g55@45?`3sIaZ(KC3J9g4ga zAt2agq`PoQAKq19&*0qd;0QIsuuJ&xRRsuq5j^E1YAb* z9%NniSWL*y!iWB}dZVNlC@U;pOy#>9eP}2g$eGcNH#w7sP1Dz42#XWSQ0OGj=hWNv z{X}_qCFrOswd$|m5644SH3C^hns`OjCydROLxI_@Od|SLR9yW?5s1vPrJlPUru^6q^)I!^ zrT6p{kzV$lp#-mB-DFJJd8idcZ3h{Tahr+qW8<`$_YVo#Y?ZlXRyt+Xv+kFnGZCN+ z)?hJIn)D$tpnMvY#o<~5iI+%6Ss+>oq-x)rF09a9WS6P4kt$x` z0>AGQaCHIwYj&EFmn4Kp-#|UXDq&DCRqUL=;nhoVx%hC|&I5f+tqkpyW)oW*{YV*B zR3&IEs1i-P2H9=#>;A>hUky%=8);)OcC<3J5y+9SjbU91sFFY3C(%_ogUxzZ{Y{_G zu>G!IfTg|tIEn=p)T<)idp#Z^Omen5bQGi_){{cd`#+w4 zuLK1sn-(Js+xN|-(;(I$w_uCV6b6i}5x`2upF7fVnc)5~>>z!A^DjxBXcSM2K6O}r zJyWpM=#w{p9K%}UsNN{Y)>-t|HhA3-knezsUuOWn&V~P+4 z%H?tCDk&O%+JOH;h5F@AlcM!U3lM}Ne+0ZLPrc&Z)fSieUQ$?2<@34nXduf1wpV|< z*g{Pfnd#>i7Gf27sS+~%fU@qgGzu{E`m2HP$kQYFA>eX_Kq4H~(-80Ug}sRiIRRIw zy#3z-XYBBwt`esKm9-8atsdAxy3}6+{XY_Bf7V~ybH&azAzK2T*qNDrJ^6V1nf*)P zQl3OM(k3ZnwINjW_UprAURa=t!$hk^u$OK;-9mdWo_VkHK77_!TyfN|X}o@;d6461 zjq;X=08J4IO;P!!LfE|aFjOqoDW05w^cSkPSM9%`)vA+3Yt&aFjFmsp<>K)SszgvrSX-#cUku6ZVv-#S3|ogz`!qNj%kzbT2v(RCI#AuW|^54CIjD&Rnm2 zva>3fZMg9-Yj8kgY)d}Gr~D|c7eT(5kzRePOFc52sB=e2(d9xzr=?(xM#57{OjtVX zsjdGL3(~arqg!H}u$1$KB0&lJBehIgLlj!#Lb-$LU@2`RoKOHl3HdhhO&yv5SG-Eo zt<1zzrr;bAFseWQosnARW&1YNOvM&6P&>ni2gat=9}(oZNy|hrPq_lm)QyeZiODPm zsA8fD)e*weI~p%IQAdbV#wu9v>2AkgmFIuxjZzi{1aWOq}|Nf+Z z2RPC-9tT~E1C0vGt7kL5OcUI%n9-2=5cDG3^6|`AnykXeDK;D~Jm&qNx9BY_Zt~tF zhC9g>P2z{A6TDy|(7qih2?&(9A9O6?w z=6%wri*IOvz{idQEOVh29$k>E5&z-|0wz6Md&QW-4f>*q`@oTfPFPpH-Ox;J`|3Dj zfY@V^g}Z>8mo?{so{P8xkr(X=jXnzh!zKL;C!?!QB5A^?fqBMuVor)TQr9*m;cJt& zkG5XlIBjeP0!wR^2%!GOSNj&vTQ+o$0ozXg{&%B`beX~-ZS&64XJSMzWVXz3Lg4_Z z<*+~3qx(hC!v1w^J$;em&k%&M35$}fB{Bf7-8E+vk(=3gW{N?#GF2b!myv;X6h`O>V^=o18C%OHqLa>YHzlmq1 zr!QKgAMmmA7|%YYE}_fj!bjB-3~`5ud;mx_B0a%%NgGPa%0HIhXW0EAtc2AuL@5>5 zVgY4!XL+%}5u|=6;P^YSVB`BWn95h}DzrqJqHDkA9kJt=MA75hAID`e@bQx*E~j)4 z-y15t#+khz7FCW|xtAErJy+Bo9vw|c8q4mq?5OA=5cD*@vR`x~fJ=u2uTczo`Z%|) z9wsIwG5G(g|IsdloC;yjoIUq1emCZ#pjRiH_wj7tU9%hiXNuzaBunQHI0Zydfs{%v zdlEs_QLh2xs$ZNt@t&q1zNc;%Q*zpXo98S$S}}PAjY*9X^a<^|20)99GO|@K^z<3R zcyALl9Lsi`s?A$yKorZE10B4j5+yVkUlzcJ3U9B?ia?aPh1Omi&{T+V25wTK{>R>i zD}VcLgkA|~PP#uBuPrRKm?H8|2q9nTHz$eyo4ejtu%fRdOOmBcc1yp>Z2MrdKu-&H6e6Us6=u$~% zibAMVo_l=S{S=0H+dk8F@kdod{NDvoE%qE|(Iydb7DXK#wCp`Q?JT&xG&~#+>0s^N znftyRhv@3=4bmE-X2zjG`m=1tpi(9{B{4Kyz1R%`rS8e3uFLGGk6Q9#i?u-t$)6THt732HkI`x^$ z^yBPaKm#WoEv?B{>(dW?w2ki83wfVmc4{&;d5m43>srsEr61N?z4z4<|F-*%PCH+g z=PhM#&mWcNnRGlrH-|DV@7pPi*~<$kB6xz!YO#h=1oH1c#ckto4q>C}03U3WzV0`bI={t!rzdAa+^b*R#GzTQs>|8^2uMILTj;IkQ(w`~?KTa3u>G)x zG+kd2FAM^yB>Mr@-Kq-}`zFh`F5d~K{I=C9t$UX$Z|9S2=AX;G#ur!#5+u_j7@Xs< z)%h_r>p%w7>3|nJvJDgz}R)sB-3~^0PSD!{Z<0JpSFA{mrHFB{F zZ4-Hw6c}e(Sj~nYR!#y`P(D#nUI_ucp@tZErOywy(g(npee8~4cGXIw6_|6$c&KO^p98&j9jWXL27X`J-Rp{RdPj*T((`k!s+$Ss0H7U7n$ zREX5oDwZM(6B9#|!AqeDEkk|BB#_4=rS4E|8O7k57Na*o%+>%|apwBsiA0!=V0F1K zozXDt!H)dd+M{?^>qrt14!~uoweA%yeySg2v&D7$nER6zz_cg#X1w@FJsA$Y(@?{N;`=f09LyTr1c!&>#!+>zaw8L3C zzRch>9%RU{V;$5Ydu7yG!eVbVO=C{N7AGPp`B?wC-PPazD)V0=8V3fNh5wx@zSK^^ zDgXnI!lnLM(uf7^eO3(+d5w;Y+TV{Y1Dl|{!wRqCCHOu5LQWyy&mKKeGQfAtM=a!g zVfJaZrWpXD<@m1L+EE_=c$Q+qDvXFVAS)KZNT0wJUMW(bdps$n`+n0-E$sfTVe2{y zKL&vn04VwHBFC59l7~}pcne3}&7aoj8A@B_h}bPXtrU-!e0>zZ#S8;y5sQ9G9a z(uEK1jx0k8QY?Ob^S*goa?_7iuCnOTKj<{|)qg_^L~Bvk&}>$RZVoH*@aw(3>x zA-<{o+fWSJx%a-DZA;ygB78(s``(E_0<(T8;Q0D*xxss%Ov_2g#Lk$n;aWp~upY#O zMDGPKBVe@#RS9F+7EzWV-;q2K3$9Ir6mqZ{C7a)|C|M&jt={;Q5nn?t401g!6G=em z`e25X1`LPVZ%T!vXj_g~&jZ#F4>;v18o|gu%0z@z)2a8Gw^j3TK|^Jt{yM6ZsX{cu zXgL{Aclp^A5wJibHewpakZ>xa*cBM6W7(8DAy+2dy`gK2`yhh^ZXoQXmj8wPr{d;e zY-XR*Yb>Tc45bj$Aeoa=Uk5c!06cA$%8dHngE$nAHTR9cyIVX18*_#2+%K6dV&Jl$ zdCTcptbescJn~c*D=%;yC#~IsS$T}y^UBp=^ISbrrYi5$K;f=HH!67ScegG$qk&*EQ zFEg^fy<*qI#6;Uxd0E->twjg5wHc55%F(i>y1FLdW(9De^YD4FVv@Y=fLX@2U;8`m z*uVYTwD3(oACn7grxwgLU+IG(MPUG0wxk| zg|>6p7vJN&+tHL)5KEds5vHKO}O(RdVtS|OeAr%aIJEv@Xl?(B9uI@O; zwIt8S7Kt#;whC*uRYLI+Um)Oyzw^q+mN+fH277P#eZWDiP>c!+sUC z31v&jj2BMnBAge|)m4x7DQBy&9AtPCj5g{j!(iuuqVs1Mil~2$SMMDji^WGl2b$|; z)QYq%2gMZFe`G8J5OG~2{z3djsyRlB4@yHdVJgP#-)j7E4LmN#U?4{!2UxEvh1tqh znbUIh2xcm#B{Y^=jPoFu4$4C_?_k_8-?p76-F_ul7yP?wG;pGln}Yh~VuQoj@%tbD zNb4ldOUrY8_T7X<^Ko$#G}JXiF8As5eu6TG$c z5?~cQjBjWo*1=);W>Uj>o-Cm}vZW>=x=lkg4SW_g%;2r}+?=8ERf6%Lvc0bh5}vHF zvduMGyzkX9Cg1xWFlOh$gGZ_?MtH@J2MOc|n-1p&hO>p<2mXyQAD&3HJG`(ZlXDiL zvY*o01&G$Z|p(Y*= z@Z@UVOy3q%*f3JJWjErM#mwygq!k((ZkHw{WA9aljJ*A|sF;~O{rV}&;@KWh!pd_z z-)7h)Nwr#yWC^a^2Y2$M@yXb@Ln(9MxibLK({KOyJtUFu^V%z$c_ zXAR+-s-Xad6Rz_P<-t9ww_VQL>A@@#dR9b^Tjw`ifV8#>}i1lrJH&g0%%UCY+sLnKp=b2x8AV zp@DABQiq&8WTqH@#kN~;YGC+C2_T3h8OqX1fe?pgP`i39Ml(Jw8Y(biuP}UgPklo-57jr@f z(zIPI=41cQACF2TV}tu}zGk;^B5<)a*x>~xW@&-?{*~+JZcy3ypb2Vz#*XqvCZowt z9*CZ&!S|k!w_1z&M}aFuX75_2OYOUB(LhXza>XZHdLuODGH(r(=pO#6Ry#t<6C2`5 zoSH8U8b%BWZ(Qw}^~JHLjqvm)2;prAaNi^8Wr#E%zhx2&X|&&2OF!>vjoy^=Z}!a6 z)@%|>EzL|h`rNHTR=U8opTMGcKO|t(W&g5wL0bCcU;dNpFUF+cBZy(!I&NLa5hUs0 zn>e*l_2W@zP{_ZGkrg?9{SlOUaF)LOW%;@xDT7SPxX7ZxC8H5fQv-GHO3nwrKW0lU zz$+ysCAhP1ICjs&(xeBOPh3141|M_vWGEUHzo@YG#8p%v_7c;)G?LpN|4RY}kILf4-HZd62DxR8%dvB=Y=l{`7P#eFwz!VtJ57iYVmrfW1aS zpAEk!*-8t9g%B`u_faU8a1L$149NMSrlt{}l;}3!Hot9LJTX^qr;4*a2UPuSW!m70 zAB+PsBOh7fLwm>#BRGnpcYDON$r`PY%dG9>D{c~DOV@qPJH?`xSO~)LQY`t%F8zZ~ z?7of8WehD!tf8UFuD9d;r}!avljgq9v`8+OS+7d~3m#uw)+=ZjOiXilf}z4A&+qGo zB0rIw0)1NV-2E_wPM*?6j%ujB1W6Pdq+laAbh4Ela{ps>xfcxgeJrxHLblz?JlJG^ z74mn3x^57^ennq!h)-t6M;vw2>_@I$$Al|SobN_Xer8@jwV-ClU{-kg>dScCk@l8Ku<3 zbWd#|kLAipl`V|xgNXD?u6sewq_0e-{!`0%L{aWPy6JDBN zCQ~fIt7v6CFgKBY=(r1-zUg)HPRR=*GU~T6b~;EOx0xsat{i%+ z+UHp0v#h)|+(Pm10Kh*BFMB@Xb|OtH6*Clk#c`QgYVf}_AKB84`3M{_*!C8WYdOH9ys-5{3zre%$rOm%JGN`#bJT!f-se&Vod- zc*0S@MS*L2)INJS9+px(EsWKjlFPrnMdEZh7u6@^wv;)nh4ed90r7}T8?-@~xSj<} zi2&6LQa-s(q2IW{BP7Jf``;_Yu7mY%)Gp&hGGs+g_tTWKAQ@1{=-z%gp-lIZnvR;9 z+GUFRP$R(8`K|HR))uYXbLliq?C^?1?t5`Q>ARicfUASr>AhTP_bfP^Ffv!XDQ$>G zyJ{XW%SY%oldX_gWtBY;K=YBOtM8*m_mzSo>PwwLLq!E$^341ws2D0ndXzX8`|!-{ zmho0D2AB++T}VMWXv-KC>6}wI<_n>_UM6&|TNLrqE@{zKCSr(vPF?oZIc2tNH6|sy zk|o*oz%DX{`?1J+iM4|8 z=%}p2_uRgs^lF-82P+K$-vybfiPO>$2pzAWQOLl*6!WM(6`QKNE9JFoCF!od7x!dx;I7Ico#} z#Y__U3xmVqz$VeZedh40$K*v-m(G|$XrNNBz<~4Lv$7X4c(&%2?S*VHJ)%^ZI!4_u z*|W@T1d;rNEXJTzW$Z;T)Ew3tRL6G4lJizi{Ya9u&r+d}pbvS59}- zeF4z%KvEvv(+z*8b~NuQU}Fic&(sEyZWdV{H}H}C*Y(=Ds$>ab=y`1_bgzFJsi8Z?^?~g42Ao2i3Br+KwP+(8GZG`wT}%*xQ&&6P0gD~A&Z2=~;}=B*D9Kku zRvVAoXmK~&`>s*JXriGQg^iO`hqNg^3U%Lxme&c9;J`5EZ1VQ1^(a{!Og9G5KSt|E{{l(<9 zo#Mof?dxkSM#SR9+>Bw~D%Jm*Tg2k0@zBmlcTE;isUaY+TB$2wv(%FB`c^4wOwJ53`P|4T031A5@f zEguPdY@6HYJ7k*}5o>E>;(~{6+zg-&+OLa?i;K)i>?V#)u~aDKGPa9tY>0}^M@6N1 zd4CQA=LP^7<=VV>zBS?^aQ?1tJIKx7zjf!jPpL1;^tFLs;Nm}dd3j4*|DvU$3Y>Jg z87UmIUL3bkm)pC`eR58t@niB78*g0MO|Y`ioQ8-0T^&jYzqneeB9b2V?~{+jky*dr zBF}J$#K-ex1(N5F%<}K$VfeAzA9PzYF>A=bh#piz=aH5u4Yih(?HB-C=&QV8I?BIC zmQkc5AjB?Cjumr$@&Q2;F?qBP)2v`(+k*2AaAa;P&g3H^ind>|F$ti|0B&{}M-!1> z6dY|PoUtGx%FZk>ii{_kHns+t{>0iq`MS4$w1{%IwXBlQQ6EL_wa+yR@yBl}TogBn zg?8q8JOxrUeJ>?YWYM4%VXzg463fbgtKVcBw8m;muHv1ngFlU{HP7v-AN0_)R_f>& z8ISeO3z7Qncc=dbudUerkEW{(in43NONYcRozfvGCDI5>cS?6I2uMkHr*t<+cS(bi z(%mK9-2&h9{`hA2Ma-}}`<&_4x=}tM>T2MtQbV?phXS7yUD@Cwu$Oog>4i-TU_13}4SJ2b=rv;#e;y_ODm3-8VQb$o?0Q;lJALW6Gy9a&6d1;scuWQX z%6)*mRX+qQqnMH7%$%$&=HV$%b~28}C`lb;coQ_uF9=qu(shY>0L;R}E_~CcHk~km zpq#}kZ2!{!K+0=ZvE5~)c56^Qz)_~0Y_2xV#nK8CkJqt8=BH+5W%GUz=HY2EdbzhE zOUul3T${c00^GL(O<&ZMp%Szy4+hl&+=9+a#Kj^FcKRC*f3K80`j`zbmR}$Bovf_h z%9YRJ8B4`v8n)dkQT0ni62`_vJ&u%v27a0@#{^>WTU{lyX1TT*RO`n5H0g_|_TC~L z^{6)(r|`L-1UiZzfCMVsIEL(nhoow+n>U8{fA8-XNZGx%fYeFT;vAoJhmotywB|3% zUr!q6y~P%2brql!d;w>6Hm|*WkbT>8Q`hUDR9uCG zoLO$~qnIDw3r56l%y(r=#J!H3)YKYcJ|mqcWU88)x_ln3jj7Quy*@QQLseX=(tn?z zvQpASLG)M|U!<1}-ZfLj;b#M9LQJoy1iX9{#_v?MM)+{PJW!PMSe!JOm;IqRGo4!! zB^m<5p}*r-2Pdn1yo53)IUZ8!kpLLF4FwpdrLgZWH-9A?_6Hj)(<*I!J;)4Fb<9W}^fFCC>a`VtaF$tXn^%9)bCY?!Aial~`kiB+3M7nAHnfAuJ6< zHTmY)VMHK{3YFQYgLz`T^eKcBLuQRfYa2GIMiu^UH#A7R2!?3cHcl2Na#LAA(g|tL z0-GQ57{dmd$|nL=9p`L~@nTsG1A=^F zVNsj{Ejo)ccvO|+?_y8TO59I=D^Em#R0cW;k){;~_52%}y-$s2vXJ3?k3?{Vk9(wo zSVk*dZXS-OOpEiQ_q~eC8nxN=-$)VXHTS*O^K=_YNuapmo}KsK<7f09PxT$iz?ZAJ zR~@JEbeq@l#+=9FJ&z8y0GpW%(zo92EFY7}OwSF@exAg1c|K+Q7xmq7n(6d%qr2X6 z9Y`_8`3le!d*S*@BRL|zCMN88abi;oqg3H_2d*aD&0Qy7_A;HudV71RLdhQtV2D|(~HrJlxnR`w~JrE z0>y4n_jA$qc%jz&DJBamci$ykPn*E=_7ou>0b2;Ft~0vXP35Frsj1uQwb+;9Rg*l+ z)^R;0J7h+ zwd{@L@V@3puFV47ZBN*S-s>pBZv6+A?f*tn*1tZHmx>4a=MKdb&HN@ZbeZsml~h}bKpPU*ju!r1+&KNfVQ=^%|P_N&%AIB@aFJ0%yF%~Fv6ftU__6yea z=3Uyjh8Y}U{Y=BHHb^>E!9@Qc8D$ zYlx!TjztdflZs3!NckPb@iHy>5q=h{i_~p6M?E707$xBak?Pt|M#TF)G9%d!;+E+5cqO7?=Gyr*(y1X4=%4yf zD_PJ!*e^Mb@`!j$mKNi62*bO>BftA&@&GqHU+p5k!h_bHfcZBnD(ZB#*&gOtHwz0Q%5sXS zBO12-sZAhJnGAI2jx}2Dj%HZmae>~WRiG~-&a*|(9w4Y7#RNVy^zkvm^IyWln)-vx z1P{@Z>!tR)nLHIB?_l^!e>S+V0xNlgVXbDN=|bAlpjgZ=$Em89w60Zeisgf0)FsrS zRUX`lWF$Pb{CMFB*w|qgv(dn4OIae#riQPXw~g^8mCyO~Pk9yp#XT;6Rts>sFaO8K z{|oz_?cvD7NZG2x>N{ILCVYpv2WM11J5nz%aTNXd*d7Gt7xRK87>{U?(OdW;RJ!}!@_8O zLu5vGhR?quO8?NAvTG&;o-3z;7=V7%S^N1ooMVTH&67SFH@P|dT0LyvenEd_D@{-k zG{P|~2$_L3`l*NDK!#f8CX@|^*S-z)Nl~~QcY5Q>C9}A11@DP;?tGQrf~rV3jyzzb z`T5CAzP@_jbzRf31BUf3j|)1Aij}(!LXp=#(lv)QK+7oP_A0K@+U9y9cv!LrxQklJ z1zZ8x!^ZbKkb=y8J5K3%X-DYG%1@xf?Q_m`0AUrt1Oo{y_Sy45rFoM$wm`-7!SO=N zvs2FVNE7+;(#b8cW#-F)lJ8-YuKhYM-woiU@!b6NFvh2ej5o8L*#oboa98G8$OJd3 zos9+3kk^++{qW;f0PQp$B`5si_$La8j`9<^ym6yg1K#YhLX>d-Q?VjJ1=u9f;J;Ie zs|5($KO)v2Pqwp=yulC7?p^Q>hh}j$=aE3aCL!d_`o~GnfRe(KK8B|Ef4GH108wiG zv4Gd0x;*$CplOhYo=e&NXFK|I^OOIG@4_#npy_tOBw0q42mfk>Vei3P> zH#XwOe$LyeND~#S-}%tP9%9t7*`Bik*J^Rj5Qr2@(V-D#`TLm;e^hE?dt32)q4Lf0 z@Ao=-kX>K3ZEKR2=w;w7(a>R{m?d@TDuh^LmX+HNO(v$qS>OC}T^|LUP60#uWEu(rkCi*2sTPMO8~v4H`3M3?#nD_^soTgE?`- zoorBNHUyZe%F~eY9e*887?ckOu= zP8LT>P7Yi;IdFd8pithm`y-8VP2h0v9T{2qlf-P-we{`w$oKVp)V|Z)?#Jt|u2prVeewO(H8JQJXsaBt4gV5aEi`_X9_> zQ3q&9UDm;uM~H%|K;pGl))>kQhj6|#hL*^sun1iQZ86-Q2;AAf-kzL!?KOAautNbL z)7$f?DGPXHeSlVsXMgPWuKA<&$F|qUUxXsQJ4uEfecF}-S{{3I)rP*uU!_99Z{4>y z+mk!ap3hz{8bw|P=~6nk^a-=R^#l`kJgrW1alu=#(6jIh@XA@6igI$$ILA1if7biD zGyB<4NLcvgVwi3D@_uVnQx2}=GWhiFY0Z(0%m(_q!}>){Q>@_Fi%4;@DhBM9zfrPk*6 z?^yn`aEF`2*(Z92^ihlCJ;2XhKA*vi{c*oWBXqBkUy99R=X}4!9fF08?ZTgh3-Flk z147lyN0lFq`c$OIZ-A<%AmuPrmE9~U_1*mS|BgH^DQXNV7VWyAv=lb|#{!$G(YgvA zZb2cTHkYF<=Fe6CCS$7}fUsu=KwlIS9c%EfC(^$C;fF%T2cN6Ma*Cg?dEGKnl&f3)T`+rP$?q?$ z1;-}d<%)g?lhvHSXCMUYF%>|%TcY^lRd@Bf=D##$o9o6~_HxTHd?fxDlCB;iy?g&A zUxU7ho|kd1xIhDoXTXd&FeE_0k0~fK^PLqY5m5S&a|^FbBgb$H&>1Zrtq`3A#*qhgIx9T{J_ zNVWmtmc9p+#(kso?5%T@|71#s7H3)$9z*r2y^GS3LJPv5Hl?d*Wm0hQgUe=-&`vam zz<={xZE0B~qKQoASg<);6Ox$Z@9JSV07Pwv10ersjIFZ!+QdqMrBk@Vh@uVUZi0_VMVR2=y~L6bOEH%O&0pNb=kkdN?R8 zHK-Q)@WBJrBZ*Q7D7#(w7cQ{1?V6f8ptND)8M&LE6%@XE3{Z0_avORrdA21X$yeoWW&$ z{(g?juJ+c}*3X<@1!aH8gj!Ys71}1Y_s>NuAl&=4)pkfVbUO~pooLPy_$}u9h&C<= z_|uUQ45?4OTFGm5d3c~)mfuEii(x?m#Us>Bka*)bhn35FO`}aBfsQda=Fe|C55w{a zV}uWh&bZDvp_cTo?#Tj|X~TmLu5D_`<{fJwT8V=jkC7D^*68S%qJmR ztyN+2{p+_ow}t0TAMxV_B99 zFVW?8I8;o3tFYGiSk-o_lV!PhGjI61|2vj4AKh&)j55=v8j8x|Jm;KgsY12Q` z-{madHFfNTC(wj|>BNSS>t#QBD}O)5kp4r)HQWtLP3u+%gO!ntfm{`8@X)`9tA5GQ z*H%v~Bp29t+*BoW`yC`S^WCf#q92X~64FeeLH8~!A9b6{o=FMrW^9>srcj1K z!{NsQeMQL5-%O|N0*7rQU;O}CI_js z$}C9BI74qqOGC>a6oiSXw6gIm8eH^vrOLv6amXJB^|k0fA!INlQ$ z66VLE1ZY@8;ODRZil0D!xK_rgmC%jC(;92AKPM$nWlkFa&Ng0O3}4T#uSYKN zhdU@RsbZp9^N)pYX4ZlulZ9U&7=&&YkaNsIyEL1?Fw54mJtbM6JrBES*G%47(Gv(t z-CGPM%zg!eO>S?FC>|CD*xux|-(mY&HR?or1cm_~2?7?a`Km-B-8`GDDjvQ}#Y))3y|hX1Dn47#x1(V-b=% zOBaAH)%}bu2B#onzn-y6??;&wh)7FO1v@CyPO1$nN>#19uC-Q3PtM)R2&azgI2rV3 znvuqgMBE#c!1|L&w&#b&x-QJY0&{2WKOe1r-6|Hjxk$UOSG{# z`w@AQBGnzfJpm8EoIyrG3cPKmvHXY9Shb6`tcJBFtF10$EoFZ}5DC0JD-YP^34q;3 z;4}ZQv@{{c+24sb&n~j9r5*Cg-jn`mZ(`rPk3YgwaQS~NfCPoIzh5Semn(t9#U?6FSJ9T{gLuVm>ktRAde9aDMN>z;QzWPctl$JJ=_yowN##d zG`Dk9&%QW}cTB4#)Yne~JBrWfdOLmpM~>RFgcSV`D=>ZED}@k`D*ZN1C;>}q^FzPF z@89AS5BpN{F9+BZUgMrI!l&-*_j|s4FTDwWlmqG*V==IoOL0uj+1wHQVCfBo7 zxud1ed4Vb@yW3r~`l&ND3w8bZyi#TRXoCL0NQF=ZEEwsK$7v>DRj z?q<3HS^^Jm(y6l_F1dhvjZg@vg^3#%dIUrxpvhR@zX>_d$CkU}8Luf_7513e6ps5; z&jx#uhCfYCylrSuq$_ockCVn~?@=|Slg_KLSqYUH z7%>jM#2{BSlesp34#%)jrNtV8N!TPGd~jkU$O@Uoue)qJv+uKb>vSW@D?<<(T%4#@ zmQzw`o=P*$f$G$QB0l#Q%Mw=ns|T4?7?bs=^!x;?E>2Q0DYZ@nNxEzMV{M>$E{v*J z(iEgl*~@r5=rze~BHhQN0zz)oWsKgT-DC(CvO8lKy+UPbqTw^y$>g-K!^B+F0kC(+ zv&_$;7N>U}Q1#@Ug?*xU+)d8grw#**08}dEGbdwLVuB7Iz?Cpdvg*Uz|K0LNIhiVP ztc7uCbE**Y`_f_%vz9Uq=zYCO{1IgUd?}T|P&<0&74Qkpd7NR071;~|W@GPT8Vc`| z_3V20VFHbJj}mRubLd%hK@*3B2cpZ?Y!TE;?2os_jXJ;GvkQLvG%wqIla!SFjw-4v z{yX%oPWs5nMIV@~SVKjz> z>8TKK0B$FMJXm*VGC0Biu>6Mq6DeY!NObqj_$xI=Zu z9+Z)DTI`yylAGIIJUoCLk%y5XhMa$EcO5CHfT{fRjn1j`lLQ~n>RS>LyAMb8(`uF- ze~&3%w?(i-yk-HeaQ$}fTNvgHa=kKX0KclrW&|57MVp_1cK9-%1$U_Kua4%rO$z6t z8Ee1ts0_Y;l)P>7B`p-nGK6B_qPzr8?MG{j&&NPT=5p=Sn$=S6yOqHpd=~V2@!u&h z{+(oZL?;aNQMPElm#H2Rrx7*jPAL~t@OPP{({~GWN#g-L3)NLJX{<1H?qM!?TW->` z&V7AA^*wkq|7x+-9}O%>nV&ljZTD7U$lHL@gd9OY?B1v&G=8PSDsVG1JtlaxGio8n z@@uR|sk-enM&QhDE}by*H3X2lCG$11Kj+^81}~t-)!w=x9dusCHEz&&STi{ZVJ3mP zP45Ds@lKWBi1`9~29pbzG9CZCQ53ug0{@+>)b+i}Ahl_1y;BS`3A1KS?(wZGImzIpAKvH?I;vp=UWtAEY*9T^)8BVb9_xS$N5(kS*sTVI1=U~ zv{G!5BzpTzg|EN{al64is7zE0-C_Pg>BmwyaqnE%iCPUzj zKIfxC!qc?f2>+N_gr+iGs$VYDBeXfAz=G9(5g(077nbERCH6DHQgSulE(iYWHKVR9 zJx^(XSF_gAKsa|c38kO)cuYU6Q#!WKkQX3LEmWk||NS9FMHxpOQ3}z7#0^h;81vw3 zVoA(9GPN&7wHhbcT10T39Zln$)t%FJ^DsW$MMy!3TaLoGJVGubDVvcMf%b=d8b~Q` zI!AAQ=2(3uh%b4JO0<8(%(wy?qxVN=u2-l5EvB|&6pwLJ9^X)-cP7t7i9zzis!{eV zNwh_WX7xO5I$>IPcmZQ|M2^Uxv87N3);1kqlVdpUgasF#iLk46brU!F)gmjyX1=bS zZw1iAKO3xH>*uNy^t{cd3Lr}hBN>(S7OZa3)5aFKt^q!QRe+i>n=^-1=cm#5TE`PT zAON=9<#z%)*LbFnZX)xEh)EXfEwT9sO&2=7Gt%?E`$c>_i}>YiA_f%~r%6ai5O6)V zZA|AtY>UU6!QHue1dx!`gC?8CC16ny=K38w@?UXUW!F=+n!&%nK*=O?;>}?JrXL3=D>cn?zsUs>?x53 zsL*8P3yf1wbf){>1(nr@=4j5W6&fwh+=gKELepad|-aQwGjG=@xvF}~{M#-kyi zCHG&P)LXundqSU!$ecHy#JI&>FSE11%}xS{)DzHz_EZ(Qra7D;0pWQVn0i;-eh=7X zs>>{adED}4bF0IrX9Q#hs|DU9o5d;f&-ynzIvp1CW|f+rn`jI<-nWaznU}xHKtNml z!!o<~!|-zR7yFrvjcFmvwZl}hw?xzW<{SC^d#bPgs310tgD_Bcgx$u`n+m`-YGNf@ zr^>;dgY)@Uz+qB1r#~2Zu(-vV)@NecQT0nsITO_~Ej?9&g?>=~$H2p}IVQwD&0-<3 z@`7W?XG2p(JmJ~)vauF0!pG{e6a$X~-L=bI#pdT|d#|f(9vilw8v!iCK)>7k5n*Ls zvQr^bBq3W+L}_6-Vv&C!12&WNJAq%C$yEO67-jCKv7T#_qncO1I|b+G)5YuC^RGP_ zK&WXG&Fg1D-O7@bMi5pxTwQj+$l>T{h*}Fz6=&*zB@{ZJ2{>_IG=e_qPo?CA535Oi8AkB0i2eaP_m|{WhHLQr zRm0?r_=|~2a+7k8xW_Xz{U0*fiT%%>`wUq2RC#ZiMhcQ(Fv^0FB59SkX~mEV z9osK}Cg8D4`kY@uf`2aKE>nRRU#4lGeUcpsl|<<>5KRO&XJu4EUFbeqQzN9V|b(M)~-TW81lft01!JJ92Bnbb0mYEJx)5F z(fb?`j6o$Q>ar9*sj6OvC3jP@CJ{t=Sd`}`&1c70FEvd1CJ;LW^c9;~&C*5h@;&XT zh$uDWz076TAP)w})+AiIV5LDG8F8+Zgp2w{b;qPd<(D^qg&5SP@(v4c9-%1w-MZYL z0a*{hVDJ>}vSkjR`)S)Myb1Yt$^a6vV6eq__A>xcUjhBk?H2WoU$=JC>McUS0pCFT zWQq!nv)(6X?6z9%R(buCP)sSBnvHZ&qwn7Sy_A5`+5o;%uT@e-{)0k0-md$< z_ABlKsYTIgDH?Tz= z-GC9{mQEDoEfB;5lVIjgO(&HWHnz4Y9LUNO-P<#Xf1cyO{!ox~=4YM!FzL40GK;`* z;iu!?1vmNAC`pUFVv3=xwwpO!LUsc|PR^+VXRY@`Ou@`h!CLG++$?i*n|2`bQB{2hig zbg&!7n)}8epWU&yBC5Z<1_aHK7NZU%QSYWM^Fty~N8(C0XM-n>Pwn^D@rK#t$tt98Ju}zaw1ZsBmFcvt=5*dcMDRSu-TMmuQ0~tY&~C?{a7O zDj&fQFi^eBR{K0}){nt=_q`z`_r9LQ7Ovs9GX*Vhk*N4itg&dJI93d}wU0P26uqSz z!F#s*E-|wb55b^9#5kOZrVOG<V^TNYtqdZ@0-(32Z!ksuaVZlwcN(nnXekG8%rL z-|at-mx)Iw-L)hMKG|`Y$T*+CUG$G*y~U2F<`V70C1IB{P|M|Y zPeVaMw!hx+l@#R6PtKYUM;&MIr(CMVlcmU$qCWx(t>Ewvbf9z*K}t={1ioy)wT3qq zF4=VNUN_|Pts$u|er+jfzmrD9(4wD_hw@ zTaNVRk`^q$uS~5k*FE(oWa8;<9ZsGAJf&$GF(#ZJ_GGNQc~(#^$qS5PqBgrza_E0^?<%y2%?G#ZR+bJs}-Z(1LdD)nz6#0Ts4Wpm|KYj67G;6 z#SFf{q)HBm1OTn^f%Ed#mg)2JGn89M2>*?==|{xq1&%o*Mmbj_L`PxDfX~?xs*G`{ zMXRvI8LVsULHWg6r-7zQ-FoiI`KR_PZJnX3s$}ncWj*C;(h2=E+IJwnJ)4`>J7I_O zwQ`D>WNTDWX_5_OWbds1KnwMQx zcx@ED4czF+6nHb#zreqMr1>O3VWPDQD*LI>O@5*?{=LsObKX+&*IG&H0 z?_le3zC)TJ%?#d>Fld^DobV!knqBJdCWz{vhTXG5LgG71j5rY}{Y?-&$3@inlw)j7 zYYX0d$M}Rw?-S$kcV7=O3&*Odtd8#H!HAjp~BRG-B! zNE2dV?jH;`R|!cCHrYtxH_zX1mt$X&w)@Zxr-km?*6)fN(4-tPV!*X~uXG)xii1m> ze~Ftoq!cC`B%MS!ajEE$N|7kaod}lEQ>2#Ge8LF-Jp;bIFTd+2R@d1tnP$Z4!%={m zBYP|mXK2Z-A=QSy2q|5JpqUyTB1;NbvDe|oo=sI(D=KcdV0XI^ZmS-%J1GX3B=4JRsF zVSYR2?hTuxm)MMwf%hb*R~{O~g~Tn`C5!V?QukPGRCf8Wozg`-@@%%NJ@N>NG} znAi^+m+e-~I$_D+=vtX{YZleGJr)y%{JgPno)bk&w|=X(*~H5TYB5epcX^MIkPVm9 zPGAUmxFW>B!oa}9MA-xq;%Jtr$DbabvYfO#HUoLhP>>(tj9@VIM&DRrhazsQ?x(3m zgggd~UsL~7sSU~b_+7(Wy$@7$&~-(l32Mw}IG*ljwFNdn{8dMr(?JzZ5hbFttKy*V z7D>-{>wskIu#b?}#2Fk`oSeQX8Xk-)-LSC>4jm1mLson13?k_-PRurt_9sYKVl4@j z(yWwMRA9P0r?~g9uD6U#NA_3Qdh=DY?EanSFCyf(QZ;y(0(Tx{ZA3%{*r2A7B(EZM+ zDW1AM19M$f=OdF1PYnY9YCa>G^iRM+p;Kuso;>JwCT?V-_A8MQi$tTY$bdKh+97SdqGTJkhYZSA1ui zX9qb^(lV;7N;nPmjW~W|QcSkH2QQw)#TJEri|vCyvywY6yu4yV_0PWpfq~*-D~HaA zg&BLi|L$&v4P8Yy9m|n<=6Z2e2QKv@0QAD+IM}EgJxG?PT%8kSgay?UCAmRH2-*;J z*c&6KW&t0}c}&YCZh02y{q2P}YFnMl7nGUeR^W5U-s>mIp#2l}shfIS`=guU^bBpt zj0C=@EDB;)OAt=2$N=!==I9g(HqTg1vxl? zs@^%B#u&d}f`CS=Q*mE=?Ob}XB34G z0#uwhUI2QXko~;8p7^QGcng{0ACQt`F`CZD$7fxMzq`4)S)p^_+7?b{I`|~L_rc7I zEK*eEV(2b|{Kr;WZ z3D!B$1l&GuD*D1=QN0r+`mvQo;L>a)G$p%+SPa~=53Lwd_NA! zK;{~+70559g6{zV)pWUqjWwF-&_vqs#@qHQ;jatEp{2$O9R@AeQ}(M);~nz`o?p_< zD>ch!ZC8Ds{u5Izr@5P%IUh_F+01v|5B`qLzFkv;_@}k4>b*mw?r|@&`?bV##J#1z z#rW~PF^(WLPQYSY^$pec=wqUYMf7d&g&O1ELU%7aKpnU`EjSTqwFj==zAKt)6j9^x zI#?u^MwqwmKZmq2G?3N%I+@ySw}E3>^SZ=DLvsIkj=!eTDeqAN9|?o3WF7Kt>;EK; ziv__n2skLhC-;d)o&MWXmEWL;ea~~GkPxbRYn=b4*>)KbB-6zsEyM7kpL()tb<5Iw z|9EFO<>ux_=wds;)YLTaSv*$ccDt2uE;=fvLHA_Y{&gA%K5hQ8nr@!7vXkDKn_FV1 z318cf9P|4Flp1PtkpG4qAShrnq)D=Uo+&@l!VUq$>bmU*zyTp?Hd~_c+mhNEdW0q( zQo^`0aei+7dbt+2*|TilbyYj?R^`(b>Fa~bxJa|z{OM{q&#Im9w^QNJw;ooT5ju39 z#}@-RKD!4mFFm&s%*w-h9jyvglAQR5!p)LitXM1KFiO}mHd>{ug2|oQ%D!f*Afo+?@OSjSZu5 zO5@hW_M0XVy^G(>pwx;*OMt;%U{GREq)>S9qdK6hCnLonkCKW8^WnLR*$%qbgO# zk8q?y;CG{AW22+SM7v$vhCa>wP|uKqV68cwyRXTpTlf{4RuioR5qS}jkr0u*b-%41 z*RokUnVVJ;DT*A3$A_8%Psl8+anV-OrtzTk9YjV|w^CiyjQ!1>BN6ssQ6m9kX)rZB zLm2#uX{rA>13U2H1C*LswODzY@^nc{6Z0}WPKN7Uf_ujMF`0iZVUR_ zTP)(==<4W*16OzLn^0Q(ZrXsRPiB)6aktKjI{#zg@ua~YE2N1)z1+-kUCg>9H_L&e z(eHn|fyWzdpzDNn^gywB840voV>T53x&1G`&0K~1-=ShCOT@~`5^*48E>Zt5YlFgA8V zL8GXopeYWql#~}Sv-6OnYRg*`ihmKL_Wwo!wP95-5;g3e!$}74be-N_KW;Yl&S~gksyJ*RZ<;jU` zKjFTYBDbEtbuE9DrX=r?FDkW39JL%-9){Jx$GPZ+?XdLZTT2|lf{#=b?Vj74QcEW> z9P~p|mktY5QAM0sO)+d-jsb!Edmi%tYq(I$a8R_+@a zUc_FmoKYQqMd?j5%ycQ;!%Dd!>xKUn1pYpV5{t+2uz?VlXBEu`-Xd$v?d_&|pRr$! z0s^tn*Wzg1QkP1W9Qm3YQ`d!lgbP5$V1ZLJ6+;D9QZ9>;!L~KN;_*?Uj2{+#5#m_F z_Zv@VufrDu6kV_J2*nw!h(mRM`Unl3m#kkog?NPc`IkiAbMvgK{y+lIsKM{3t;&ch zv&dSeyMV+PNH#oZ*gF&GS{}Muc>sfHW#Rz~H%!rYZ+RV{1-}~LtqR5lxLF|cT>v!{ zaiygPo12q8Jw2;!1FfsK*1#6`=Up+=gLK9`SdhBosrMVX_l(M3wkK93UY?&L`M_?T zR0CrFK73&@K2m{$xXYBGZu{2=1ex35>(nCRs-01@>e>3eqzR#7KQcoy+H5^SUM>eh*{O(e@ z{s7KJk|{DVKW|vB0noCfUU}s-0USiwUk~Hxw1Z4Uh}n&AghhMeHF7H@N4)363{*_v zfm8|BNwrUKQJmV^K?R1>Z+-mI#jJQyF`)DwIq2LO3gHDd+*YDm3UQwvUMBtc4bDms zI;2x3CJkk>jK~cJR;`DUUvoqI2ZlDbx6K?R9%FA;d}N^KR)I20v=Y0ha3m}(4(M%p zM#N-L9j|0cgUlmJ5;3f|`SRig#(k+_)$V7&KKyV|`_*Eoj=S7UJDKBZsqqLvU9+&O z7@=lIb6)_Le;84~+1VKas`S5ZggXYAGP2`gwx?4ddwUUZjVzGZM0sBh6~F&WBW5OB zZ5#fl0OuNs8;UpHyI{xk^eKKOCMsrE0$2%rU&4VdfVQ(1-N0CnOkMCMSfSk$#TnJW z5ABnfXjm9LoDMA>B_vUlh)&+)1)Yk?3&Ah_?I#X4HGg?A7YdCAoTLdnce4DRp>D?X zJd2qpwVd{V4!ZTN}yKTj|m0sQxFNFw2`svHwF|62rr1@RBpAU<;e zt(>?{vC!qWFV89;wkHs>*#l`-N(w@+D^3wg3$#?UJX8}mA&_%)_)i^^>eycf;lu9O zfOs;!wpG_LB#YpeYsC5cuJ~t4p+F^8l-ac-AmYZL>DU~Irs_QH@~t)9JFOq%k9=QV z_&XSvvy43DYW&r#Q3r5s0$H>6>khv$r$>SG;LHxMhszD|bTb`8WQrNKenvI|si%up zjSNk3Jgo=6ue{cM1zq`Uo-vftW*GG~Jaf4kohel1-oc&Wadd$}W{6Ozj0_}m5@{rF zpjAraNt!qYo^G(xoCBI3oO~wchpfU;ITRi~+;#UGxD}nOD^B!kT~8k6I$uWja(sn{ zr<$`I1VL_CBU2}MAya_{J~emkyALkS>$d~sy3N|681f+>zARnOBq)hIZ>x>&HhfB? z#K~QS8D9LRP*PL~-$?1Yo&{2Kt5@v~u=LwpSDQN@PGX;*1^~6syd5uYhV5FzL1}Te z$8Kry2it}3wBe|2D`=7IWay0<4}TKYoPg(i+uc8`Qu8RBA=_;?tqVPuhg*n;$EiQ+ zzbridf|IZQ&ULXRx8kBP`zfe* zDUHhl0|O(mL6cVXEhz_TUJ2Q3=)~w7$i^u>MhkV2@>1$E}p*Vkt_Uy;8&BFfM1z9g!p_| zwLytaPiixCXl>?!;|tD8mZ%|uI-isoTLf{L9%wW1`tu<|2;O~pl|VFg&wu=*I*u%f zl%_)yxsMVK?xUoX$TxRZ-stx9Aqkh~$k#fS+`v($i3R09RE@FSB%U@1@GCtGbQ(M| z>Rz{+Ysequ%6@LC3CraeIlN><=cJL8*9a1yKucq+=;`LCW~BRdVgBWEkS4ZL&mESm zAs-M{7!VX5F2hMrz)x1elf;L9>*IsU$ z!yQz90)1Gq)D>8LP`rSxjXuAKj7C+A9ykz+N>f;)CSlauA9G8OXzi!R}pynSwz>UGOfNNt#X^@}8+hEH2WfM19TXq2!$#M3Y`zXpMmS9pNvAxyH7MFVJe&=l^R<$M`Xd@VRUQcE z9S2V1D_FTS{7yco2W79LE-TG*Q(Ce`r8SfqEfd+0+`!^fU;iD<0tT5&VQ$@%yKIlkftTkMY@dx|mU1Facq^B~sGU5&UP@^^ zUkeN9`PwI$lBj2HD^@I)e5f?YufzMfaE}jPh7>jeztkozABu<8Z*&fWlEIa&Rr;0m zYej@h_uA5R-pD#n!X@~;`Q?^=(6ZwVB+xzorl{(Ac|3dFxCC6?fg9J`y$m8QZ~ax* zqfi;%nFq5*P|M()t=Po!?dHvve~CA6p6siBDxS~weJNfd&mjRKtzPT^X2Rdy%Eb3=4MJ!rkh6KCuU!X!EnO3PhckJCRRMHaUW4xTd(czZ?&~bv{ps zW4{UeR>gSvaJB1w5ot(9Mxt(5V>ho+{tP_)uuVsslU1M!Z92zb)wWS*bnc(`o*_U( zA|N2F3Id(9IY11J(A~eQbfLhV7DKUTzpwP@ORHtmnT?V~QepcY6vV_;nl=DEV$FRB zXdI-}G)T_3w+q953a%fx0?B^FTo%w`8OR1`WKJuqGN_vlU54^2D!(vCwng|iwsLj) z;vbAMsJR(?)6>)83Yp*Vt|l?d8nCH`IZYF|8;iU*->$=pRm{S&G?~ZS8g;%H8Bxkj z3w{H}Yorlk~vQd z10L*|lDjYKwObF3<9qI%=EF_g3gMKJRmPbPhX|(-B}kk&G#5^^CQ%^p-9vqtSz#3G z_qTO~tH=TI%<6La%K6ZH23b)!(6v3Ca?pF~(fn;~$s!Oc0wkp=m<}0>MIOQ%y@JKc zgN*zLgdZ3uY}2h5zi!=3;gmZYFmD78f8rMvRNKm-dt{>Qja60>{jB2_a-S9e57$Ff z(9e-6Ab5sdP7pNF&`{ zN_Ur}w19v#3eqrybiMcg;dL#)=>mr5x%ZrX_WA9M#&?oDJ+Qu-^);y?%`?$2BvQkp zRM?VFCqKIw1*spfqH$x9Qjq*eRG3)FRVbfPex9|fXLq*5>UG08`bpXMM4pI9e@-b; z=AkM9QgM@LDFgo?L8&gICqf(eRK}!wgW{Y+@Tc$N*T%H@432&5lqm%eX$ldppTQic zrMBw*u!w(B^V?WO849-qAtW!vUzji@Vs?LVjPgsx?y-0mPK6H2bPc>wxHPq6n1*+0 zSl|~08FOlMYLvg@k3Q36=)ds$XGDiV`6rh@f0a)qiv{v?j&dD0$;^Q$)h$0fWB^u& zPsw(=-2WAu%2S+-{1?sDL{_W~g**Z3X3$o_T_zwv006P1t&D-JVQbl z)Wr(kbER#Yc%*FuVue&Z{)5Y=!urPd*0rd_nZ2+v838KlvFXaJlvk=vi~N4fUD4AaKci zGQS_Ban5)6%pH9{y1W!1wF{f#c}vw-E6*6wbHgDhD9FjVV#AA+HgD_>gynpo?qawEgQT(0uSHc(>=+ zmk7NSO@3Y4!zCbGi1m?{r`24kmG?7e^1Cp1PR~ghVq_Z<)eesqp}@t*cRv}M-R6HM zXvr4G4L8+ko>mn)*sq&-Mn)kmi4?)%?tN2scz;XWDL%`E75z3Wv8;LjwQ13~%W*5c z6xnDwi>_RBh^%zJ2pV;P{Px+gpey6_cUb$Wh5Y2QwWHxeKN=(t{@d9(EKmcbbgoK~ z)C@unM-P?1oh2m3D3Z&U6knFGNk6cOzL%&;AOiO7L=YGAK!HV#HNp|37XWcfhK4=P^6?A3+Gg#tkKNLZ zGrRv;hP0C{_ds9b-K|OGY`$}c4Cvy-ggo4C326krgnZx~%9EqiuXugfxwXRDu#5J@ zCob1q>z6~<9a!N&w%WZ8c!2E|qC+61Nsoec^VLIFcZswoYrr5i{m--P$6@G}9nrY7 z5ZikmO}!CLG&>DawS_S9vaJuC`sB>a3MM4dsTG`+VI+~A7?503k_gWP&PSQ0C0|vb zL9VL3L6RmP_Z6d)8NWtHF{?8P61++zm(ItKU1dZ^htBGvXcT+HwB1ci94a(as`k^C zNa6xb>IIg~i7B}yAo=j1CJPc$SYmHQ9g8HF1&1vCql?DM9^$xLV*=^*qh}}(ygn)_ z#YW0>SOmx`15b;MWxeL%(=q*u^r9UwAxvgl4!FA}o;1-`$QZLUHm0I=Z&O`Wx5LmP zB7IKXHyYCS2Ob@RLu8E!v5R)8N!ZSl{xL0x69O|EjS8lyng5%u*CuV5`HZ;621--C zC2t#TLdPY(X7WcWoLU`9aGbs3Lo;<+6^7+8asMj6C@7vvM$(L%N9(Hv{R;|lt%PV= z=TjuO(BC(G>IM_fYhZSH@3Amr`~JS&&)D-f#$({&lz(Z%h`W|)*Cf=SfACul&g-NJl6XXz28gfBlM$>|JU(ovnDd>G_BgkH|_*l}5*waG{H!ox7-XlhxvQdRwTdG+!yJ(9dCkpMhHsn`T~7d#LRy zrSl|dj^cE;r$ybf|5GtoCp1vmGHl8Kv~H2}%Yvqdo!D7jBIWqRkNuH}LT^Ia@o~)v z6A*e$iwaZ!0EDpZc))nhHYq$j{9w`J-E!m1XN7pJp_Mb+3eB$@UKe?vv>jI3!_#iC zuIWR}jW1e34*RZ`%NA{}ggLAC+X8BR#UeytF1w#ap(_n0jU@8P$0xjg>QL4Ei-v(u z=E|5aS}gOi*t+-U>pWr)Fj1D1(b3goMr#mCNnG-;^|x&T%bnyHM+r#6+!9i!YDFKJ zg<<2;=$q^IZ2T;&4q!^zdAK;6N?imOP5tEW=A7`)pQCF1l=M{pq5QzAg1trDC1Z9$ z)Qf$&^J&W_<#4exJq8d-JO=gF$1PMMSdbi_LkF;!D_vnUZ54&-k^U<01x?f}M1xdz*7? zzs5rR7Jm<$7W>_ZMI;va_2!cWSn@}zB00vC_Ua|ML(hFYp5kdcow%+P9GVq zGaHE%FaY-gc2M6&eFHYJ%;Z@vmyQZcJc58g{ru^8$5GF< zz6g%!bvKxtUfo4sd_yFsaXxO+st%VUNVb z+U=6sauNkLX^V2+0TM#{`@6B{*_Zb3y<>z9o0Zr*>NUR#pZ%N87kvWdtGON$y%a(= zum211$~oVo@q`aEKNqB$f~bdtu+b6tmcz?*V @B`EwqRLIv-@ z8os~dRSBSnW`GWSDE!#=#cyf~&;g1LkA`c^H<<^mN!7g+F&|JyXM9A31x2-ut`H`L z$Aoz#X3Ko~n$HLZgHTfoiw!iYTNAVQ9Yz7DKa) zkIb*3JRZ2cfKY`Jsv{rd@8a)UvI z?COukETKnR!d@t)7T}D)6JFA9PkzR5{ z*hMy427)G^q-5Y7p}|*+KwTm>c41WgjP2}PqtXJC`8qfOEKeuS6*pBbOAUJT>(ag> zyl8_#>gV0LVUWc8M2viH<(K{H5uMbuso#Sdir&Xbe->652F1 z^G;CK(j$#mPh%jYrXk4s9n;4aQO;rIMN`8>-u$jr7$w^WxG-$qFHq$oee=+s7JT0| zG^-rHM$yZ zt{vKED88`A7+4Io7h*>sl1@}!`aoN0H3gtdp}_f!3I{$5NWO%A?ZcG*i;>#V)IJh4 z>M_;9zgOI9Vg)gktiePYHepg!n3L^X?=SObj6r^EEr^}L10KjZKwpEW!7|TVTI=LL zhk*rFu+%$JQR9^z8#500q*7Q|*TzfLJ9fmzfbd$!v%XfL^255+!`fqEyhTwv8otJ; zXrjU71*MsYEZ0OqCh&CpiC{5u`=?Rmb0pd+1*4`50MTTylTfRk>3GO+%A+<#!n;{zh+;pU*p!gKE8* zDzFt^uG&!TIveSn*gSm}7cR@4_`|#p4MW1`&sv&%>#||$Bn%Uyh*U%C5MAry;9C)9EKR0$d zVln)!U9QXNvKd9pZ(sfOz_pdSJNv__pjk?Hg|^jR<3XL(m>F_t4Seeb#Is$VqnuS< zH$p4p5=Nd*E+ua`h%)%!gS}X~+LfCCk<(E^Re^h*uG=#pGM;U$t7$Robr|^_eVajg zO$?3NCdV_40ZwpY@pjMXfNqt{qeo#OYfAO20!VQL`T>ImlROQ&c(sKVE_F{5p!4sn zt*z~p0EP~ViB?S*$f9*HsL)Qg97t76b{BesQq90Qpf&YwaGa9*Pu8l{`94^(b3c8o zPhtHJ%=i`FLEo|Nk}N3wmd!wb3n~bC^?tuHw1NWQSk$_)^?h(RN&z`kk##d3+{&~Xcd^V#~W!!eZXWWGt z;TppP2qVcp*@E-9SYOYZb4pz2ZPQQwJHhOJ{|X)&oz_DM_|ea-qI;VJxVUZ2K@7VU z*qpTD-tQY?c}8Sl-VMzl~Pa$elj+zJ`4DX!U1C!B)yN9|(yLsNNx=c;*l0*5fr{)VEs43#9rPn9Rx;2WTY5sAY222i<4vObtO zngZ(pm>2Z*#)=9G{2-QueDmnqTaF}tak$ySxe3?<>FMca=iV?iHMP6n_yM|C*-6a5 zn;5Rv4+8#lr!zx?;Qc~KKhM46!MlsIIjoiSFj`caBbHb}W`$QDtf}Gc`!JT zasox3{RYvjjOw}kw+iNIzT1QpPk<-x? zfZHZZwM4&+&dkVl3L&(yrUPa|Aw z`h=36puCN$nbnUonQ=se%kNm~R#>iHp3~!OO&qIc;-o7Pw&(B%OfJSekmm~lgk4DZ z`djo_&Fn4k#b)s4jAMx+A#fTqY2}2%w5?a`<~J`yIM`3RmkwO*JFhOD=bU6uPR3y! z8iNG9hpgAk39r`w%c1!%;9^4L;;qefO4m}rv`Uv4;PT@O-G&LXKl9nIF}^)XY4eEQ z@l-~InZY>a!MlCG6|mC$c6v4YCIkA#2=6n3BXHqm+{LqXr(Aj)<(!#WnU*T=?G#fY zNek+jmp?1Aem2R~o-vz} zFHs8>^0j^dplC|YW#995kAYu+tb2D@Y_J00fT+1DqtX2Los-)csoA!w9$gn5BVrdV z6Dn#=3t8?3RS)H{zQ0K7-kxrXExGT#Xj-cExj6hC_nTEIf;Kj@?Tbv<+lXPfE<$O# zwt(ObIdkiWsmD-+tnEdmpg1l~q27Nvo51onp3ziwv2PexY}2+}s`X#y*E|~j?c0k( z65T%?b;)5-E;5G^vIWKQ`8_S;m0ABy)_}39IAct^POpkTOu23zw>(yks59NXwwdey zUVzMW#drjVj@`^x%U9^Abt(yyq};^}#rNR1a&v9>;qFc$9pkCpJ{p)%Ep}!p(|$Q4 z4C$U__&AZ{xry? zEAxA{;>`mvzwZVXDV3BI|5thq9Xr8aUMI-`dr(g1h0^)z!z5UH`yJ9WF>jTV)#lEd zF$Q*2=#`S+Ez}N?5K1#QEc9UDICPzz&r#ega8F#$C8&x1EqS;yj@Cc>+>7rsU;Eb} zW14^U_GZHGK6t|a{Pe$6Bn%5{N6*!(Q|2T^geswJI-1O>5RG5hXz996CYcld1Lt@P zhjx}A;}aE>C}q6dmG+hp1U+M|)>Pj)*&Z~Ijh0?1Us{ikRC;6W?&!z&Ux#nl|8m_u zbQ+}}&NF!HijT_C&i0@|wZthxpl-LAk_&p|=28~lu0rvW)DlekU4N@Z^D7MuE2S74Y*dY79PENY)N=*~%FoRf*!l_RKu&usf5L0-r1p$4;JHWU=V?{)c~0|HoaRaK4K9v@;#e15`rvrZv? z+x3S}z!3c^SmR(9bDXaQ4zRB3dnDAFU<8$h@k$t>u-h?F3qBMoM;ciA7jCU1tt(gY zU;>2rsP8LLW=R<1JcqZr3sVeOhy9yEVEMG@5RlqINvmyl#-pI0rK+X8uYe3IWAjg$ zQW1GN!94Pm0g*%&woQZy`N#9htbjyQMEFr;s|z6vduOOto|9UXJmVmi>oDot;!J;D08*750uf${#+SLo6} zE`H;2(6kEZOsnger!@8HFVIPzk@GMFVn zwtpFpar6Y6BePY=`o&jXRzTf#@Y};q@xNKr)5Z%DIMygoA>dsfo3hfITMubUtJO18WB_$cjHt?;d9uFyG6oL^oHG2e) z0(i&fD&92N-|1r>i|#MA*g4ylY7RBp&nN#vkCVTQ0mDpCiT2~oJzSI-`;<4F@0JBP zZ^X%U-s4r_(12MRt zdBQg@ zA;I~5Hbt0`Q1g1Id(6lNp2c~C{#g|Fgy#d+DiVjiXWU0xv35U{yfWZ-f7f$9w{etQ z&NaVZ^)}P92L@JSnNNH@4_mgtxTnk^Ioof2olucK6;$>P{-+tX4W)lR^|Zxix}5J= zWpnvM!2YUPp{lH^ zZx>a=Mszct<1vtiJYAs=pAo=<*Cc0p*d&9nAbLGPE@8te3-H5zwCwet>%HFoW2$=kP*cu<;RX1I8KFH78IK;RA4I2G-6CRF-PDQ=e zP>?JqY^7IfKZQ9^b91GKQ>333Wk1tZ!|7!#k9`9P5gu+y2w)WORL9GAGv4f96$@HW}Np>(sT&c9j+v2>uyq*>;5R!TmQz7#^^@E3MNY`<+5_tDBL|tb; z8J(3Dup}{K9lE!TKasvH)uHs;DN4z{2#@8KGBJe_3qu5u^f9*z;@t|igns;z<(`mK zjbAV?q>nO2mf8;LOdh3@crcGjdBeC@#;@*=G-ZW_VDa-;Uoaz%9F+4C5;BZS&DBjI z$zc)M)37)Oz#j2{RdCe}J^IM*3n&t9GDfgq2!~7DmW;+mmc0hiD2+liCj-*m#-v;S z^V+KS(lLwL%eQ9l_H#cNomV&*Isc9IM}^STQbR(5VB)AQX3FtJUK)U0iuNNaHag&B zI!AQlhg1TBbKt+T!QXpk=3?1pE;O3_B8_|QNetW&PCW(;>1SX*?oE|Gw)y@0=W5l} zoBGM}xm_#@$L=3TV3*|uQ)!Z7gZ^`bjsV=_hLB@OU5~Vvm`EmpNM()kKhY}a)a`rkuWOHzNz3GQe(q1kD$L2fD9Z8v=+c< zQMe1X@0iuIQ*CQ{H5c|G!pR>0_!`~QP9)H37_9Dhts=YNKI%?Ygl-mKqNV9^L{?ECla??)VY zI~!R&FVUTrDRfm|UL{VeiPcSygDBo72eUjbP>Mjr#3_$T1t(JMG-@(0u6=rp+0y#U zDjAQ3{#Y`{hYK{nJ0M#v6+9Mm&K3Q!%Ks%?Z4%|P8;1Fg)H$zT6DS@5#J#np;XI0a9DH|G|1b#6+GZHgx6Jsy(D+QXsS$zV{nsJqU$vU= zt}eB>!s?`9)F$!8W1C=>Q-LGE;e*8JPQhfL@!ZTMV1@mAh;2dQHkFmmJ~JO}nYAz3 zs3#(bhe2V`yn>}KCK58u`T0gcf&bX3bAK`I%81Kg6kX6>FjF&L7}3hmguxUgp}d99 zw+gdcFO1%fb9PdhS7t43UHSVRtuMyn$0oYeUM$o_9mh0zvNN`fh;TnD8e{c%$?Z82 zB-X!wnh6yVvSgYkAdqnq?zHlKDlPPl2_26b689u)-RwJ6vbI5Pn{7s{*zQAOAjH%d zLNr8*(t&r1AFqzTCrwe&KpinjCa(3&J+*$phJnWE`6qnv zna}9o6k~0+e(z3t1ysgtkvd2&ujRL33@1Z^AXX*(n}4QbmIU)4Kc$}y=PESexf-ZL zfGK}FPa%Qf7F575H|+*}AF#wc53jZg7;WwBZo)UaP1wUL8J@=K z=9ONg5YLw&+W~-J>BXa&#UPLKC!CxBTzqWC_bZ7^LL}x1h;Uk$Zj>9iW{csh-5_m? zFn?io9g$4jv&te(!!m6}CtT`@7rN?Y^&np}nw)=p#g2+xMsy;O5=z%dagGk37M|Xg zdP7j;ObYS#_AYNYI5_Y+{0t3Su$|#iNQAv&(uv|#>@nL!*v#&oH8wV~D(O_{J&~!Q zse3nH>vz7~WaO~nMV3;)W9RN#-_S5K;O6$a?6qA~L%sX*0?xQt0Eo3(y*_Ue{g?M) zT=b^=+qXQV9}=soz17;&y1AreE8WgNCeWO&fKl^B3LUwfvSI4Z`%gllhaZFH3uNVK zsZo7o)fF&l$SkyaDhOUAu9h|u8aL$W>oL2A@MjKBLkpE&u0s zj#{60{kKHnv#B%h>M)Kr2DKJBbQqTIyB%(}!) z1l)fYv6=w=bXCW>{*?UU!UBUzy5ns-A#ibn?Wm=e2QKq#TvJ=V(+YzoZRWSgTT!2h zm!Ovfejt?K8Rjgn*&Q%-9&%Y}e@jOrPTi2VVCZN+DX4fTi5yyGs_KhYTbi$;sUWhw!@3*#(Ro%#{9GJ!K9uOk$6b1B71e0Ph&OiyrX z$Ku~ecMCbZU}DRYdi98mk3*gUy?_>i8GM`NmzoFl4wBTU;CGdvwW%<`b^fIe-3~Cc zvlIH`B1d8ee6Ait9-VWOFJsKZ)G3UUI?{)nSI>U>LmhP6F zOk{dBTd5}%DqJ_>%sP7VkNjdByRQ06LGyS9_0fjH9uqZ>MY~70xOIe30lhb_5jiV* z`Cg-&W|Jb*bTRU$d^#vk>gvp0-+j@xW0?<28_I<&evgTY zc73iuB(qXhlF=;ez(*Dc!101yT*5X}8;s2Ces^OE3GPd#pN{X)(5OLbV0tTVY7osx z9h7szg)-CC!{ZG6^>FK-HEA##Qq2?yV&zm)b8v`%yJP)Gm6jZ?na*I7US-&_^tZAr z;10lMl!~T6g#aZtU-3PS1_~dJWQ*4D={pcoiF{!oDlFV?xxCPEk#1f=^XfYG!PDd$ zH_m_HO;7-;WeXQ|bgYMxJNWwTkW<}k%PAFkj%<#BpYrm~?_$M$@u0xGKrUcMDdmm- z70M0O(bnL-fkZ(M8l3>+t}+%jPMaqY3_DAdQ6u%da{F?X@1$2AbdoTVX(T<*dn= z^OY?->I@2>t2aZ?(Ib92s#&DYj4_9N5Of!PGT{r{JA`19->7!u49I4J#0V+r?aU^p zM9UU=dFyHSm6ycx){|vbY=)P#w1QiK`o5(9Mx{P{04S!fE-U&4GjHwC_EP?Qtl(wy z01qQj)Tz1nYUMXh+l?F$3O)O$OOcOH>V>#4Cp~kp#AScp&>r#jTqt9_*O~Amw8vp* z`x1x#%Lnz*^PqDPX+OVptNr%rMTZU_0Pn8Q2T+OCo5Q|vLJ%|IJ9yy1ppb4=X~^Ue zLk=42Yw&N7$cg)ornZ}EHNR5L+KGqLq9-gm@JUcw&2_quN>Hr?Ttzg9UG1oCf#Of$ zc@_r%;hbG>Q+h1FDVr%)T|VaTx{_)6+2}Pg`(LPX?uW7IB0vbgHFP4 zhd0Us?&~zQcBn{z5cD9tQ&<&ncj=XVb>Ojjwb(ewGDo{RPX4sZK~n7gIV-WlH<|Pq^zCr) zNT|`3ywLv{aq`e;rj=ts)kQHUR>Ti3dg8aJxgL(Ma_;x7E*9*nbd3D}E?*?e%$ild zXD?s;@R{kIuO_`g&_h!oFYWN@5<0ub33IQ8^HU+-U49t?TGVgno`UF8T&SgO`YaWS z3j7q;m~c235yd=3Lc{E5-cXbT?^>kjja%&A_{k^%Hg~*2-Orb+i*x)=e+n(RRi?F^ zc_<+HX(9 zAH<1d#y0>Fi7ei9`9+jMu;#_QYfa&b4ip9M|gTur|NAj1k%xx{V@IIg$d-Es}v!Kge4 zX$;JoY8t6CI0=8{I&crB@z_kwe*31_Fjm)oHk$z;-q*KV4`;^@{+aKjXQ|DYV#vo3 z5%1Cw1G;u5p4Q)G`Gz!+BB&Jxa{;Gg{0>Xad6U*8<}5S2C|DH#VgrPmyiNxi8`D*y zIM8T*_Wxz8)uze+Hf9ii{j19VDiWKJfuqjF-qTaLHj^?oCI;M>iY=L&dWW^Ce}H@W zZj67GVnvWd4jzbGZtQdXkyxvgcQZK-4ff~Pwr&fNOLA~CIDbT(ZZAoN)U2E!Cs%Z_ zhBfc5Izf41Gm`v!GOn58K+q)x4gc4}aM``zypRJ($H_@#`FnT1deMR*6g!ha_&mny zeB1|D;a8q7Ler{Oy}r~}{c9p5xKBU9%sNFQT1B$10#kH1`^k|b!B`<~t2+_K*`paa zmctt+Gv{98v&F&LI9%$$(wBV?RhAQ>KVX|N8e$>h@RKJ3IlH}^X>i_)&>HGQ)XSb? z21YX)3on~ZuWDR#OFS1D@u%ab!VzZhA|CfBa$N`D48X+rNMMt5Qai1Y*LhPd8P}3kov$?MX-}nDuS|Ci8foTXn%LWrw}J z+41&rMfd{DH~i0Lih%80(MRqk^!~o<{w%y+kLp+Rysp7ltdq=#ru31!Pw=_GJ5jROP7NO18%qeY?E_$(a>d<*L zkVAE+G}l}?!q#S1_0s44Qnl%ES(V$xIdGM(yl)sLR1@{Np=_F1c;Cc5F7S3ZQ2}4< z_UHq?Xh_)jCv}+R(OTFe49wsyNpk>_i?mV;P3@pJJBF#_9r#Cin=orv3BK!)5UG=R zGJ*=_st&ZANE3Dm@ZX5j{8~R}Pl?ISKrTyXgK6b zuzgppS*Dd6#iIDPw5VgUb@~-h90F3>WXW&kitJDL2{;2K$`HiM-mtzmMsVkIWsA=r z%TZwGf3iGOUw?~&dZquhc{)fBAtj@*<;%eG+s@Um5aiRoSa~^kK>5C9)j>!Hpj z1$6Swd7U?IuOF`Oor~g&#xz@aE(%2yY%>UHH<^8f{fxS?T)xrp>~39skH^lv5bS5y9k*Ei0u?wOK!aMr6c zLhkL^IoMG>qXhj@Z*T81$Oa?4&h|P_Yiv9RO=G_kVqZu|$Yb$+(-}bjY@~hcT~k)@ z#l!xTJje4)ckVO^k~{y4JYj`DEP=$1lvt5KrcZ@*E?OJ)&*AcI&{p~ z|GRsmrYA;gf9mtPVG+)2e&ylg@;<2Y_v;S2S^S=ypDF_^y736GCV@ra+D#WLI%SRU zSaKSSWbeHEHyt3f8!6}adqfVH1pdR$8nxNqfpjk)@I$RUbR#KUk~hmhvv<2-$5%UU zwMbx~E4lq-M-&61P8pJJO^%qndJ>i&3;R=w8#b5ym3Nq_Uh@GbE*bUg?2$L2eUqqBR%-iXK&lbi_A=ZyQsXQP^#>g0jJL}aD%P%0rJN(PEJ z6e}rdYKwD4v;H;wBK$-+&6p-Etb8UillN&91U;%Tzkjlf*D1S1g91Bp1cxjI3Xz^+ z93!w~fI2114Cd#^a*W^%lzW=Oh9VSZ-J2X@zHE?be&8@KcVXU{C7ct_J2)pWv^BUN zAX7L0jv9RNj`6!eG-r%RFoeX<=&!);;bA(D(;xQAtE(*VNrBO46qVTh#;Z!4v>u+0+L zuvISN9&iLAUFVZ@Ug({8TgeT&%{>h3-i#REZ-OJGQG<$7SE$-;ePD(~JBFP9@OrOO zY@a(Py|(wULb?EQnsuZO7e(woJeD223d^kx4y=CWIewN@{K#KmDYrLxE1N}UxNm=c zZv}4o$lDl~Y#x$dn@t9qYU-((H>zZK=D3XcuXW$lUcl27i?}=vmtOiH|2jW_+!i-? zS62_W+Z#3i%OAb5Mptz?tNu6OcJo6fj{!E^*?e>cAokKg*mO$yBBWEP`y8Zd%FwAJ zSRoOfPw_5ZTk+FyK@)}4&_iT7S2_NCM7{svJ{vfo;AI)X8Ug!!F;1ow$hxAg^*Qog zb{kOJ$?TXA^aej2^nOtXMZEc_FGVH&Q~7O&v5c^z{JN}U-)Gr{#l^+RNzrDv5jJiQ zgOlrc;fbi46=Em)-Q+LN-V84h!7RCCsaVPA$ktv^<;62fJli8ouuj{bh-k1_o{dZX1ukNW_MgeA!~;GrAP z?Un(l-O5t*&v!a3%vq6pvD5G2Kgs&BMyxxxSVZlR%w44n-q)JmVUp_&w!4iae`IGv4}^UwnlD&sYHE5OJs`8% z>IsIB(FI@H%E~6ot8`mx^&C8r1&j+eC8PkRNBZnp%uQDJ_2DM}4e*ywuc(p)e+7^9l1O;T)Ai*twZq?gq?%%?;&zdR<&CSsB&gZ$Bh z1aFzvjD&^FV?**a=uFQB=zfA!RR8{dB7a3+mQxi-H<`f(iQng{i@_yXB2%t7eAV&c z;m4ZXAMsEkuSn5{!OU%SeZ=bEJ=o3znhaj*Xt-{H|2k&DmHZ34w^eN|o=sQhwWJ0(;QGF80C< z(%gt%SfbmlgrOr(IppL_p1!xwbn$+~vdkyk6}(zGN*Nj2k6lf@!&ad+ywZjkQx#kP zC#+=Obx`RLuy>PUcycgbcd@^{T|djE)G@z}L^|+IwQDx>9`Pk?Iw8L^x8dlB9iw0d#tyzZ?;Y+x?uf{hA%#d$Mb-TtH)`5;O=C> z*vdf3;h{qrzto7M1^k&1Bf zI7h9g;X3VeN~S$@<--ol@`<|5v)cwUPR`BJ2Kq~DpQQoM&nyo75uSiocLn$r%tyT| z+_L24#rnbU3=$khZEYJKCYebO^+8p!LLqRhuwf=z!jAjCAgqL9veNDqxNSI|4fmQV zR3J8V402%`ah85(XJ^p*FB+T;=HMeclSM-pJ)NKE(kZl9CKU^oz>v*2Kj_8pxBD}zSOuqn zSgFAv1A1X1`L?D^)+FBQc7ElT`*{t+dv~42aXBXR~Z_cV0Op+|M z_AfMRMPw)>qz$GI?Tc7BkZiLT71jK9?ndz`yfUX&(R_-D0uTdBJ|z?<`Z^8T z752-uMOAjbhLw%vC;OSF(VMyka*Ibl)W2$BejbmBasJxwJX6|v-0`1ZXga_zy?-mF zqGm=>FA(jU3XXiT@EF)(j88H4_5#?`t1ScesGoBAX6mVkdEki;4zaaSFVhBcSd(*q zscq383EgJH%0h*ORWWL6y>wJsQr^EG*OJk`=RZC*64!f^OUKRDo?o=>718!J_X@of z#4tk-bcc^gCV_o@*wolNsHi^sHDAD_m_v~xrfALAM=hw7=Ui|eL-Co_-!##lSv z#u!sx1X`j1pgbgJmIR?|X+jsqPdhKC z-gvB}6an24Aq|#Sw|1tB$A5X1>Y14f|0!1JiR`Tzx#!^I5s%ofwxz+WhC42jxiStf?pDYHhEX+Vwx^ zwg|8joz9>8s_O-dhhPSYOP`9pC-Op)M-OcO+TP_Y!|o;tUMuX|Cl#yI9K4D@l3M~vLMKmNs-xGmBfOC-{bJFK-ebAuVHta6& zmZAKeQeqDPcIzpGUD=G}FtbmzPAS-H&@a-8ptBp0-6hB5OIECTlqQW1XY0C+xc>Eh zAe!91b%z0B!w_ET3UNBNt73Ziua+^YwNUVLWsRY;Qz_C!4J0P+bOqMMm7_Ltol0G7 z+F4y%uFxrj-$4UCU2pGSO|QM=7XevfVqlj-6D-vXy1C6PEPwUCFW9i`&l<BJI?&NaP zJbt^blBUR1FIS77uxP5)Cfk0+93k=y#t7ya=N5`Bwvkg|k`m%tx8<+WT1+WT@8-AB z^4YTIIfanlL!#G2xN&IuH8QtaM!1ew0Pb<3<8+ox(ri!y9Tk1iUJjS@HH`s2&QzFt zZ$&%HlYuV=G-bU;EH~oF&Dpfv49Ny<3n(_aa4s}d50j`;{kJ9^-WW^*#e&BIcXp4i zD4u@7o!XbW>Vh=0g z3yvErF4k=*?Q_cNTnx_RFOe8LgOXVL-@0U_fl4oJ0pfTF85(GE1xe5^AV0EYUmx}L zl(uTR7A4_*8x7fp%frxzi=2rTH7ShU{wDFS9<`ar3Z0J_UnvsFfppz>JY=)d(A2jr z4VHUrYZsk2y-ET9?r=J=3?^|X|o zb``I*+U*%~OxE1h^9RYxv&2{I_v8IrSr5?yG03)uAfOhHE%;s3Tw8Oi)bYGX8C}ix z_x5{82X(<(BjBeUHi0}tyW}vQj4^>mRx>a#e9`-_H2&K+iGGP{Uf;Pdm^`!uGJM_m z-w@E$Z?qhBybQH{v^sCRW@hFL-LC$ofDEI-VwEhmKr}RR_SWqT0 z?u3|Dbofvm3(wvzz3erOn;hiJ4GX4mOuo`%!=&Iu1Zt=}L_d@yuXMUs=B_1^U6JY) zn?XlB9AyU1PQ5X_R4ge?UlCjGXl*xTsH_bS40_^o(TbJjq4UP&?67Uj*1@4^Hubyp z@(}7D4E0}1L^41y54Oso{8b$kR(U(mo22;m;qD@b*De_R8);Z)Q+k_6AsUgoj1N#E{yhD@an?q~9K4tyaw}w6+e!V7hw0<}l+^FM-LxP-=;DtndU2)J@zK1U*B89BkFI3C-RplS zp08`rfF3Sd){>3>Mo_f;r|>Y!^!ruAKCm?H!k|% zv-)rzBcvK|(9jQJTe?Jbw{C$(OO`_GZV%@C&vRTCfIWiC>(kIka!1=*O8^8KNku_1 zI)#hE*1pyQ_N%V`ajRvu_l5)ojWsR1`xw@aw|plfpEth0T`;h}I*=juJ1tC53tvBB zVeeWJ`(eyBeSOb+CR>-r17rxb^+7d(^JeqP=KW7C2`R=#|910r!sOcrn3zx4A+l*E zp-^$(!*A#!vFFdUxY$N!gg$;?(C`r;qJjTgiM))7Spc^PumaW+#yl)oiJdA~Ufl)U zI{ohX`2KxEcD7TJ;uyCM%jLHlyGt4rkS^&Sx{*%ll9mqX z?rtgRkgo53zO~-J{DNU-?!B+;Jdb0>3N)`v?5+8x*0Z*EBfb8V)oo+c`E{MYsvV)n zn>KMz8Du)TAg29OK|)XiCZ1|k6N^uu%$~~4lw4vo71*~H{ThqSo?K$Qpy8Ll-U386`*gB1OKcqbg{7cnO?j{H<67Ewqix! z;FARIwyMKmOztCdp$=b2B29YHkgj6pFo6j`jk)UE^D5JX4Pcu55QE4tOSdKyKo^D_ zIA;!23g+Mum!AYD=e=Wwe%gq4Z1k9ZMOa<$grQI;q6WeH+3D`mpk zuu3t~(2?UHj%Qc}i8DoqPE_%hie=a62GKDhm;ZC+NaZ8G0=_N`>Gf3x*4g7y_ra-tqF0gr{{ab{DIh0U{;;M;@!cdpQxr1+uu zYYeon^;RDg;>{t1lpAP2*`e2VGO_;Go9(>7GQgV0}iW z47l$_*GA)4zXU-bHkQl~4Ue_UPjP}iJwg6V`p+32?FXc7=MA$B57)V_tv-SL0xK%~ zP8%3W?!T_Ab$}vyx`0yVa>{o5n+Bau(X66$UYDqjb8Fu zpXEE_ynI#FJJ8iysCg^s&kkK=fz9z29!D|G_bT?*i^?J(zO*RN1pqC#w-cPp1l?AW z)yr^}k&%beiWH3T2hMWN$}~!#vH*w?usW>rRilv;Z{|BtP^X*ac=wPeQ*xm*LFlTs zvbrVb$z()LL+{*Ti*84?->S5KFA%YA2smikjgO5jNW<`(T^cqJp#IjS%z=S_$H6J@ z7$(yvI=;m=&=gr6?kxA-j9mP-azxaYQb@Y6^oKNA>$;GDxH+^=5DpBfu*vwUuBDP+ zAemn!#)7rf`^oKfk3=^AkZy_U2)%GjWpB35v#Q*{Rm7amg^&V~(pMBWzihrMM`o;r z9|0DXK%K9oR{A~6c?VmFA*&SyH;pP3VWO3P+(U?YXcWiuu?$A{5 z;L@#xLPuBBpW1nSNWy?a0EkkbA<-EG>H!TkWLqnyb9gz9YEK4*0CS2K4;Go;p#i;A zh-jm}Ef-NHkAoeJ(np(J@<&lnt(qZAN|p<%p{sktdHc0uHVzad#T{uTRLSKaJgN@w zniC!#hLgy0#HSsCg(evZ1u*=&zFgxR5>`8X5e7&|MyZsD)d@v1uD9zRGOu{6bjKuo)pK-W~?M0BQG@3p44d?RpJ?+~T3+S-UJ7zw@ zx}ybAoDSQphQkMrq7Q8Snuy)VsTL7>mTl2|^>0;pJFmI377v4GHq(KbwVxEYq3{EV z5C1S?55q8+Hj*Td>RmC=u>JAgG%W_kj*&(2T&O_%3&mK)uZvy}IMZ-l7_vES<_35W zK?AXNc37)_GtEVB=#R4g9*t~WcAJKUeXj)@?#jlZUq9aA*)9GG=VKIyxiu%}1xYQG zm)G@^BP+;AMlP{1qZr&b<=9{`jYtSL-1!~NmHmIfOKBBID!=-7UcjPexh<6a7heL3 zrPj)Ve;b^P{nhl)p;=EH3>OY22JRKx|~*V)F^F`S-V#QnaL z@JNSgrPpaSu8-q5F<<@>{^<1hvF3^NXH$sy#zD`DI2f5Q^v9M1vL|au~L z?}oQ+VbjEIets36(!R?TQvhFmtu}r?khT;CA~?k-Y!s2QX+jDak3e_lAJD9J(_|PI zI9po8W7ZS-d4?o%|JB1oC&&8wK;)rMLuJ4T1t%7ZZ0Mb&Ue5Q?y}z>_8Ej6^wo$32 zeSpsP6!_-hwp}<|Ai}&mr1WnAk|A#wxp(^JiBu{a_}_OJYuc^We%&Uiynd6B`QSa| za(CDD_EHeVQl?$e$@Zp^q+EmB3QCxeK_>_6o7PxE?=YrAv=mFjm{k?q^`oc^Hwb(l zTnV z*s#@h)FI-cx1{J$8B8U3Q+F}t0!$s$xxeY;D;4$!{)P>{hf(aQ!o;^2AQBKE1dMnY zd4~*=uTs~meeU4;%r<&xLjr1_Y!u{JXce67&^i3&M*G*x44nOwJoOLnj9$%X_BHH` zVj|C`CuO90w(5S11Qkqe7&r!5CPB+l$NSs!Cao#mN~D#JifyoT5f>solF5YD57o+D z$2ph)X=b|$c{KV}_t6|za?t8J+0kEOQ5y1?6Dg?=Vo!_~=Mq{H^2AB@eYK~tdZ2kd zT=Qu#d@v~9k`S+V6ptr#2z1r-0SOl$Nz7z_W5bwXY6sXO3cF3h@LzOF2F){cwpm4?P=C8#y_971G&vB&Q^DGw`D3z3Q{RXM7g0 zSnBt0qG0~?(_f+e9?Ru$YJ7C!n#uDkK5X^U5r-;-<`_b|Q^OkW?bj3DWS(0hae_NT zIcH}sT~3z|2f5dwtiejEu^}vz?=UI$ zjOid3Gp)XrwT4-gAadZ)3kP7U>nj+6X$QJCIw3M1;Q+W_O_L!70A6XHU(x0~KY5>b z-rWkEyL)($c%O8U+=Q|UKAqGHoY##a;AcJk!}hOe(z*k1=~neXVol^KAr5BBU*uI} z&sh&i&p3^X0oBRXwZXW?Vda-x2+Gjj0}#9b=phquaG8EDnYLX{6M8ZvZo9xNFxP#h zC3Oq%rJi8tK1(L<3n(vdr{~B5UeX$fdr%Qzd1O|Rw zKvb06@S?&7aiMUMgXcu$K8l)5BF0Soz%7LX!w0cx&(;qJOuW;}vln&p_Regya&-Jv zU+-dJA$cwv{ADKqfd&a=Cfhin&kGv>2I1SJR`a29ThO=$19gHd8IyoK^tp5vJQST3 zfkgI=iUp|>Suy2uS`z#tb@b&{*paBP9iEV^kpf;Fp|pLoS`V)Y*j@?;X~`@bW1T~` z4s%mAXD;}bB+;KD65xxShM1{G=~cBm{cWo3AJl8C zSYA0r#V3UoPxCI`6?Ol^;IG_z&cld=5i88w`*=ct49&ANlt9+YNy?wM)z+)CsD%D> zQP0xr|A{`G=ShRi0S;l~irE<=$UFd4sgL;#DdjN*Tyk|*8fgf9v03723QSLx z0omz^FPU>3@yw5!sDHc~=OyR#Qkv@X#opO8eIa%=i`qtK9nteWL;ZxSP(+Yej-e`3 z8WJKcldEb|8Wbpk3_IjLiY~UN%g>EU%aER@$wZ(4v;I{n0nVKzZ+jo81=T4Yr!UW;cW%h;^mhN;v^{PsJFKm4~&J&YFKp&%+#qXUX zL6xx5Zth-yDOAvo^w&3Bf+54U3bq&m1!a^qeLKF$!^BJgQ(`x7;UH(KsxJ59ENr@e z{D23?X|XR|-|`znU~I!hB_L?E3_)L%QVWYlmLg2isflScW84bnYZNJV71F%^+C-pfTrp+0t6O7zRZyVEn-MC_`z8?m9fVp1#Et4cp zb3lG?+UCdLc;;Ye4~NU85hZNU0r|$q0m<43^VL-W3{gNW{rY@pj&J;@@2&;;WlT1^fkijq0#YU61pP&71CnKwQrC<)#Y&%!FXaB5AH8!@}L+}itEzWC1>mH1Ah4C|2!zZJ zDoW~Q?CLFKX#1$v+|3IaRCw)!R?j*MRNvP#im@?VFEGqd{B#LJR*O-oy^x2OME^)0 z&)z+eM7ob~#(W~Rv;zH|62t65y{=rfqrlG7D8zCkOAaz+m+Z}Yil+P5hx+YHY8L3e zAbskbiEcMqjH-j=LrfTZaaVeDEQU@+V>iY-ViAjTXe9-fDdNKCTIBEY3G6A;)6>6j zY@67>hI_yS06*GuwzhP&NP{Np6{3M~;xQc>Y{h(z{+7hO0`j`2jwlx1x0AKtJD-QR z8k2osU{agT6+y?c+$H>Q4>-k^fjBQ3fPKU7NILlBX=>xhm|(ZY3+_*d7^@VrK5crc zE~I>iw+w8?ac3@IfyXWIpHh;icIhwrp6zl=2n5CRGrzvB&+ELj7gnwB8P@PrHU@CG z9bx==0<@fA$jOYjxAA++)orKzPCNGiGj`A^>i`2rkQ0OkMhZzc5N@jER={#r(x+iY zeIEoB21GRkD|MC%oN}>(S1!K3>%jG@VL>^a!?$_eW3+T34_viKioH>Wb`yFS@_0PFQgg#~HASDK;HAs>d7~>Br4^6&ySdMFXJ`aUzhRRL& z+F%?y7NIKYFH(E28VBcy+$)91ju>o!5&(6`C$6ITke??;5wsyqW$5!h@|GejR#`wC zw*w~6%E5eUInkXNM*bQUuo2#pM#>AZn~H?KBWgJm!=GH6dWIYci1`=aP9x zhqmJ*x}K=zZMlTXLQKgam(jAScAls@MC9;Yn+wcQIF7zn+%R-#0tjlO#u66MA1Az* z{1zZ)Fnq4VSnfe$V2-)+U%2QR`)X+n6o^rXqLyDZ(2Thwi{ z2KNWNr3~3xaynveAXrA|%y)Nt3*fbEOiOJ$N)JQ8P$n#|^QE@DQ(TwER=IbW!+nPFk>t7EZAQ;CROF8+|tUpq|#TDqo8F}r+ zsXRY^{=oh9*UiEQk2FCk_@z;xk@ecP`6LWZWIvt1m2c$d&K|hFpbtx$<;9_ zU?y}BNEl~9$@Ni|=}9d!#Z}|nB$e__t0oL5!cbvLWG$*|F_#-DNDS-vQ5KRu1rjOx2 zhS4&`MaB^2UHfga${7?^DPfCm;^;8-iGaptjJca2Acc=C%u$L34+`%gBC*?!4>qqX z_0A@hY)#gp&c~s!(sVc2x|g+;AFOQRq{Et+`1zpU_T_^{HoT;d<6xn96y1psCmZhp zLBDmnb&r|F#G1301Rgi^=$YvC{24>`s37raBWyfV-p=mgQ)dtm1Fz;-aN>Lbl7Hj@9Zo6hST{^4LHtx-qE9Yd)Jsf z-9i;0jgQ6fD+t-w*Z24D!i|G52-qq%e|+9s_4EkNiik+C!zl_IAJ>`IT;3^*Dq158(g16&G9sQOtL;;3I`rj_t^eL!HPaF%Eo7+6d=*jC&}TjXhB zQyxMpaf;xM_4Pkb-$)<-yPcWd}lg8`%6MZbhYt8 zqdgsz0}nsuO-l-npOU4Rc3~N08|H?_w{aCaXB3a>Fo`_;m<5XTwd_^^qGPP`$Jg`a zmN|iD&r4h22_SD*MLw|i%a{!4iNp-ij9c-sSjM>axJ)wZx2IKpj{T^+)JB{Dv9-sk zFzAK+mTJSv@>T=qBzT1y))lk41da*6r@wYA#`2^69Y+(aJ;CycBL z>Bc$EVJ9{66<+*w1!1v5^vXl@<$~am$t(RO>9E|LRw>QS^VDiYZvG`rzL@tI*B`jL zx`Mio6~0&Nb@0djx%Bl#%klcUVNgO0+@CS{FGMAhEzaf-@Hbq}jTm*R#380g{pqEf z#dpG^9FV#NEVcc*wHEmn{i=mJrl-eC+Ov+y4eM;Lee<}N?;rR7gJT1=17P3v=hvTD zufIi7;Uw-uxH``#`AB5qy?^3F@^MmfUk*6s5+xUk_3#F`z8Rq;QJ7FcSdHJ)vlQU4 ztwqb1q90vMQ3sEpMuvk3L`_7iXi{j$j9sgL2q0jJo!+?aqV#@|w*wP^{S2$$caHw=fU$M@|$Vki23SRkiOX`Q3>SGSr7#ZI|ZS+ULTQoO~{+7 z4*}KZ;WbnPmK&<#UUYaic$6HY?urWnqF6bIj7Tqh^RxuaF!EzhGc$1}=b>w1j z`G5wA0&M}UgoGh!%GAFn8F3#pjU;G!SsQ9v%V+=@;+)JwHGF zQnt0ru;y8JHpmgc#tg+}JW0o_tOdmvqhRh$Ao!yyi7@z-p$Zj3S4?dLR7<_1pj6nx zEy!S;TW=|p(pg@2Cksr+;Y4bSp}kl=`62>LZifx5!OO6~cU`~s@fTL;80H5PzZI&L z>2oYtM(hxVmibQ0vIBSEuUEUnPQ-8~#Dj7GDWtxl&1C~+ki_raIvlBa!)f(YO)>ZN zA8jFW*T14dqnxg*t6mk~t3R6$6CM~#{tmXM6ybjAee2%mLZGcIv=qToGhQzBVjJss z1^Afo63GXAQrhPxONgH&Y)zZ>Meu5wWquSq4F(L+9}qUi^}&+9f1iuyDlZAr)174h zh<`nXqp2yrP(bHOD@%j*4;I?jJpzO>7}3G*WL{u!M1icN-bRo`mHfaBJ=(8cC_Zx{ z#jRa{pf@(*cL952G%ivIHXIc5cTPm5%S4DaGnQ$1+QDZ6&u~vMliM&5j2`HnjT##0 z3p5&;oC?-riq9d&X(MX?H$VG=4G0zs3*i?UiqsTe&62XkyMT2f+BrLQ5T`aMn#T}mt0@>K)mu9j<&@?O635e7$`KoBSIb$G?ZltE4lyz z7MSQDz2C3{MDcIG*D_^nQ;lv+y?GBd9KPLbRFqfelvmK|OH?4eiwPW%4G0+Eh8^ug z;iTiJW0%hYX%kagC-5!}FrhfFuI)0vR<`6jX)yb!OEVuNO}yu8tBseI`d z(HXlk1xYd7x>3rXRP*=Ld$#^>#AbSGsCAYU3y9juFiV@p6Q8lTjlQ?;%G@?qRas5{ z$a*%%89p;(PU}dy|G3${Ub3GS4pXX+?6;6!21Q1ipl`X!MYTUYV*;nZvOSp^{QM#+ zZsk1oI|?g%o7`Vh3*|ExArgiq3P{uhzpdq&Yz#EoZA)W0dV4uY9(6ys1G7+UWiz%d z!m`JG+eAk8E@r5W5{5j}Ob<5iEo^)&VC;tsW&8K~T{7>hPE2zY@U_R&8x}__6{2zN z7EN`XfdQFXkSbFWqAdE}5%b@*SXr=`Lyk*q`>*zsR+fQtIo*jkgeC}^8pM4a%4j%b z%6RC3<{@>DA7;@sM}!k9t`?f6@?KhXgw3w(1AM=DN5Gr36-)6=2g18N`&H33cO%>E z_Z)I{;T!|1^f;@G5QvlZrGwnK;cpm3^!LT2yr!>})_rhj8CCD`&{jyB0-}>=IfQKs<+HDwnAa1MrkO66G70kHI*-sG;CpS ze>#%FIJQfO1ZW&&HlCU{u1Pj8Ne(8m-`3;&T&*1*kGoz!_@CCirg*&Fcyzg5&B=&7 zPOJDo);2c2Y+f#I-VA;63JG8_>U`Y(^mY?fV|c{_87M90L;FTc0wK&e9}w;KV5j}=%MvblJ zt7-Pp)C%@?4@<1M64~Blv-&jFE2_dQZOQfri*H7I!~}j7v}6@1g=WKg#->OR8Kjnym>>|0p{ZS zF~82}@ZjVb8(th-%>0b`hUzbJULMvww$h-FH>KKenjAW;SP8O-rU3;~JZ7AsGoxit zQN%HVabQZz;?Iz48?Kd1<#8rQFi^=mZ@tdh zF6{(VU;o+EJT{zu_k6%pa(TYLB#?k^zjN?3mw(tD#^yUFX(rP%Fc9+C?oEk_*>*$* zDNsw|5ynXe{&8*c*d0pX>D<0Ck_WKFC-dXB4t^Ko&1*ihe>qDgbA*~X(jAf6;b|rk z&6x)J!G&pa#1Wng4eWgkVOee47M32?*1W_@G=GZik6R%>lCMWbs@UFG zzs?mk?AhMw7XY5f73r$0>m_z~cc)2`Gg>rQHQ*uU|B=|kHn3F09kSGDlqgtC+|uGY*x`PF(E0V)DbN56_d{mq13=gU?XxhkA?8xlxo2w<(u@}(UN3!XG!UoHqYjqdZw#AX( zwBZPTUjL3et*E&1C-tLw8Ap4LNB#5EC#4=dHQR|kOCj+t)KUMU`+pr>fnakIOsD0i zvsn}v`i%Y8Ne&8{abNRr+Vu3$ZfNNjcx|ne@}{!u2_vl-3Qs*)exc8J&_vwF)JRt} zt&e>HvODy43}1xubtHxX6wdf&qNqaX$r_Qm~Ep|C_;>D zwmc*zmV=uWrEt@-VAMWE;8d1>IfUu<6FG$2AA9yeYSiu5)r#uRf+Cx*Ha*?d$SW(Y zl5YWT!PQJGwdjfLb{TO+ zzIWl2ch@)?k!_6g;&jXV>~-b$tjX%f_CU8jjSlp$)@%Zi0m9VpOJ6i>69ToDU-H;o zzIjfKcR`GM)2cddwa?5-dUKIPXWvc6kMe>#S$kW%x#42MgXUM7NMZ*2mc}v(3Nu;D z%bn9Q($|!B$;e$qA?$FC3m>*(dnkmpA`X6UTupT$$tv#1u}VgP zVFyZd!7Y^ix)K(TD>(Rlr5HxigH~YuXGcA@8E(4d+SjA-+P!26WXN*kou0gDg^O;% z5&ay`nxl;%>D%AjSF*Qpq*pPm{+US&RBFsp6Idx8bW8R^*!vW7ZA}6c6hWA`?jAUq zuOiP0n~&M74vYh~`#Hl3ImF}m@UAbpH5h&mo>-~k5uX-e8~L83&C*dL>;91)&wNtx z#Rv0x*X%QVP=jH5&enLV*1re^LfS(jQL$v0&SYMP-u36jpk0F4bXs?@o*(Oaf%`p* zEn6p|0Yh}l3NE9MU!~$dQ#dPsHS&-uwH5$_l08;a%hZ2{6y}S3BldLtmzg#$Iu2V{ zo*c_5ZpHdsU;MfFx`Uvcpa2GHQ6jB5kN&Ig@8{aZyRFa?Y^8xeFHd*j1h+Nk-y z3?zTHHZ|#TMLn3=KCRp~Dgh))vw?5CkX|?*;-%HhN&M?3`@p|jJ;98Of5e2w^r{V8 zi-%?o4UA2NI6d=rKBXcm7^Mc*KD+R(aP7`SZj~3 zA7H=;x8*CTJ~pd#cW=6@I@MsNzL@e}tEX2#B(oy7kcyz#&61}h#>N}L?hYVPf#5N| z^^v8B8o$M2{M<{%bmB+{oT~Zd3=VaW{Vc4184=>_522@-)vNXB^7rlK2%R?zzt5kG z9h8lDh|x#(V}AL_=gSB;E}6Gu4u4z?ZMbk6vCFkZX>jfM&M6*+!1zRt7Lc=jQqhv$ z-~Bq@2X-DYrjQ7g5C>5Pu^fOYu?obDbQnegoYJ9*oP|$e6h&DsSgNp^3DveQqOxTc zgRM$`fEORy;9xl~AB7B$;hP^YkdguxmoFol^Gn#v66-mg4~*#O6^j9<uR5*b@1vB7 z-OZZJZDY&j0Yby8HoP`?Q3~H#DYs47WQ`UZs{;43%qul-0HaU%`%ULjW*!fEqjtyb zwH7o7@5B6Ii@KH;FM#s3?YP7>?#MetuaHZ~Lxce{4WF?lxofaHfUX?EK@`(EN1Y%LOI&8w!Ltg~*H=b7H!V2u#xr$zR-0-Qg_QL|N>M3-{<^kW zn;0$bCnq6evFt}x*=DllcslWCKL)4N_kpP`IYnu5oz>5_v^bC%hPkV;;6Gl^Vu8}t zl*FNYmRdItiDR7)2@WqUxlb(w3>FYG?7JI&#X}zKU&QbzQwH-ebzk~>a-FqI{R6w# zz+%3kE4D2vZ|5R4f4{k}m688c1#RbuG9wV`E}43e=V7~$D%gS$N2tM|p642Q45!S` zqGt|za2Ir6VBv-dtFhhosWm&t^!02yJZo8bYDo#W-cjg_wRJdVJa> z;H_oQwu(FWyLp3MpKuWuNg6YIytTEuoCuTL?Wau}Cu{D?`g-SfSTOrsaF30py(Jqo zge$WdsMG?K#rzLPFxY_>Hmj*{T3YY{)wo&@Wd4uV!nfXCI$9~_`v@rH5ayv@k!7ez zGO6e!+&60IF>pk9bHj^JGOx|2&bz1151=Fde`CQekfo-?`amM~ff35@s1?iw^eCKu z>x;tA9h-M>6q0Z^p6{F?1JRlhwYF_yc!Cp&3EJv zt?eQIeC6Ho->aLrPd1yYVd%>y>acwJy0YK9>>~11FXDYTm0x}AtPDaNN~|xBpb{OD z!*pUJ28kMJ@hK!?%#D!`v#;sO=oEH{Q^e)C$A5q7W zO-^WS!XB>vta@pMfjvC7=9Ya}H-owSODS7^AM8BgrqyUqSzwa<5$-c?0a9>rvUq79 zQ&B9aqFjCU(grMUPwg&|O)GD&)1T(zE|nN}qoviTWLxZJL_1ur-;WGk;EC%e$ehz6 zmaL28l1y&Hv8~|>O?1zPMKqFMc{@d#H}QSz+;-&3ovb$Q;3tZ?CF6}(2f&(bZQgDq z?@u-z5Hod})ED58bTAu^ug+Xo+>DI+vl2@a!wY_0M8+c@x6%|;EAUy1TF{X3^c?%b zfYwCcf04CFOyR>D=M0i~9Baq%!seCNj6}vvFh{4zJ7`UZ0ZvkKMt}aus^}znK+>(J zOUb{FM@1Ns$n{MSaA+*-3UMX+a*EHQi;h{~VS)+A;n6h%;^(F$<9WeEwV8(L$Q0$D zwRHTT7~zd5nr^!R!~qG=ATw)ekVRP7Rv|eA#K6E$87iu%NwB)J#0-l`!!ecBr^Wke zBX{xML2?=h^s*JY#1jXt#t2@mjG@P{r3L0U3*0AAB7>wA%1TO@_%K03EEM|RDjwNF zV9{r9PHL~5QotqWC}>&M}onr%`F zhDV>=gLb7M{Mb4>$}$*?aEXtjax_W9X6#4-o!=_EQ(`aq;c+S$LZ+DTI;`sMfBO1@ z6Bq_s%R6@%&$t5%RfL}az^bVr;XB0Om*XdmBguaTqz~E!Z0VIoEzURQU3W4yZ3j2a z>rNIP9<6SBN6X(;{AYRm6-vzn96IkGN^<-j)1S`#XFa*}jEuaG{?b;ozOICKv9OVJ z-ZXLYz4d=0_T73#!u;Fof}d$s%ahr;SLHzRPNuk3w?Redrgyp|w)6GIfnW{}w7T?b zt!Z6giMLxyGN*}|1fMs-kChrP7_S;~O0P-a)R&?V$fZnKps8KbMYg zfiDxUoq!qD|2lKi`S&{>EcI33_n)zd>W2jhVsL7r%k!O*Z+G0S^JI_XN8Qf!Ujs>u z9r6VvjCED5OBw&&mqC>*pZ)ZbI1+FEy<~ovWd1N2vX|Y?l$#zK&wpiwKqcnk{4J2| z+g1+}+3QibL&wcU6l=~FG}Q%fKI`}kflSJ|r!-l$wb9`wvMfe#&9U`0D zMr_8WDsm+Cqq?G60T~&dFY1S+B41Hf;$U1eeISv`-y3nZI8jqnVK-IN3`Yl#@97<4 zw6^=*WeOYY2%u{#WoR)2s9rBhGRkV=#X4%tC~#+3kSZ5*uDvb@BqRd7X$BeXpU17O z;1nR$%@A5xXg`i&JJ;L$BLA%4g`*^QYOJIc z-64l4COcb6x{#EnQ+gRf*&@JPwBqFO!$FE}B(2iV*c!)wR)9vT1k{b1)KWq;q*PS) ztdJI7W1Qwoh5$vkou81mKJCBbGBNJ&f$4u(%#1mTi zY^Bb>o5L)YipLAB6g{Dvv(eNyVPSzl6@S0+JJ;`@uB$QFj%$Nn@pWS{CPp4~P($jM znL<487gk%V)0I7ZPu=kbzuh}MWd5kWo;MubY?#dX=*mpNcLVPTM7M#NP}1hx%ck$n z?q7|P37?&$Tz=QzJ<~S#z;YAG|5~8y`uQQM>#2?Gg?01IL%L8-h=^3^agOo3@$yRh zV^r7u=-a8tJyMNf=lzm-?&J2|%Tx>xNrqD9q|f7Z`QyxRlECWf+pve>kO;k zq0HOaX6I>BCcaX$o7odE$SP6p`nQ_|e5lT!*SSk{s=q$(JNVoSy*<2N_jvn2y^8&b zpFewohnwZ)*#D*GZDZ5>ZD1e;98_-!dY!IKLe6%@<%DrEspv46jqko`6}3T(etiw5 zUvL|jR1A^rx?+4gGTOWya^?5_JD0v}C!DDSfbKQ`#nJTBc}Gq8pAzAlLy_lj5ujbf zNUNN)vAVv#y81Ly<1>oidC?CrWNrAze{aX9Sx50^=sNCl*B)|c%xbFEo=3vr@LjmHY`@YUbo+ERzy!^^w98M$xfKL&o5wQ#4 zoQ(K|*Jy=C@WJCtRp{pa{#uQ~a1;j2ai z;#ZW{^~+4Gblj^Etv+5?O!*2xT86&*wo#7QNl{AS|L00WaNq0r;S@*Z=3LDD;3R(+QrIY z$xj?riC5dP*{%#2f2?44nFvCT3|KZKl?>!dQrI@kdf!KH4M2(e6d%2cL}u7;{_b68 z!LV~Y=|sz4KN!z80V^8^;1uS6r5@e>Am1RLiCE;w4_gh04TSn#wdMXWnSCXcY5z5{R zWRjFaZCGzXTSv>qzr=Uh&v^DmF+{ika<8oZs|XB*wr2T|^$I&};Gis1AHkm_DQ_C6 z?}X&tMdL3s7=&+&Uk`pY zio*+%4sCv+s|*bEI{BGFv9hqxXq&kz6T9ZOnm~D6F}d#iXWaJqY2zvt>2=(}H>8E= zy>$Khat|C22snv;ry3RL+9r|t+O)a&?#*u8+3514; zS`AS25x9Imh4|yRbxJ>M9ccv&xvEi-z@$8I+p#9&B!d>TO4BuXBbq04hfnrR0 zyquJ#Gs+~yB3iEx*Zc%a@Wh)OWvZTnU+8|_(b zDhov&3|MVs<&G94I{fP1BrA1`hembvkAjOs;q@`9l}X!K-VcMaldMd{Oc+XPWjD!#Fi3$;T7P^A{>GNA zoWux&15Hoppo>kP=ZXpHwQwR-M%lXvGOX{ss(6pW zI^93zwj-z@nyHkT^)l;%RQ{CM)7{76GDH(%@s${V5*{70LyuFADymEu{9ThsKf;$K z$!0Q$KWCesVBh>*>k9IeD2(RZ$`5w!Vo~DOtmgtX%(#n*vUXytz4wRVv~;;KU0s^d zRftEQ(!JT#zk?kGNoP5V?nm#giHb}^pnYkTI1*Uj!6#IDl4)r|UWN!TaFMBidUez_5Vz+zO`2y~VNhaLhfjPeWu$;EP$|q8Q)3C`m)57{Fcxw6sxngqy)9@{0RTm zJ?2VJ!i5|-FWUD@^t(7tsthMz^4FDO7R%2Ww};aux!;Z+{@NiT77kl%6w|)#EdSkL zI&j?|8^vca{I(Nejdu!hD?^<>5P9nd{2ohtQ8hnU+{(PK4yS=d&zqN<<>r4dOmo4< zU5(uPIob`!$zu=qrW(7iua|GPB@Ry`;ds|!bSEcvlsmK{m&4iF>rJ+8)drtFeKIn7 z8IpN5+B(cyxMn5xz8a>T%;IZn{3zshq!|q}vVksa+E=cQiD`-h7%dM6R&c{)K(>>t2oTeP0wUi(xC+JT?KkR2UrXX>b45IlN-W?f-9DWzB0b z`@Qh})+jKSSl$qJd(=cG=HRhsYRN09mq&FJ~lTcT5A!}PE??IS%C~A78!HOuU=$z1}kRqQ3|er970NTCU10T z>jpfL(-_9l-@OF~37ef)Vrg(`{{4<5>b7X6H!{*fVb#xtPHIB?A{UByNG$<)Qle#N zyCv=DBREIP7u>z->Krkq||=+>_@d;#B4`*Qp4l!z$u$B9&&QQM_vES1 z@P7W>1oRRS7qZ1ZuUvhr=L{f5cs3kOP*D6^{ESy`6s7oL7Lj)Rgb>hhQdQuLYYNps z3~;t_0Z#`zZyijqCM@DssO1ac>4tG1@5%`??(l0UJYv=(6LQ0)gv$T0tP7%Dsp3$&z zii~PX!9=+zMov^mv-5fLkbyBvosfm4p+|PYU2i>4tPX}7tJ$ytX=kTr<0Z4#2a{dS ze`f%mqbK0$Ciefk`*`$C`E+Ar!-kjmos7|<@h`{i7W2ujr*;27+cjREO=* z#4#IyrtDLPkEL*KF2C>5>(jaa-ps)33zEy3;g!oDC7x_yZ!2^2;ItY$yDSm!Tkp;T z?~LNI^48q~O+Lai+sJAe)^d{P@p?OLGe7xA)?FYWWul zGw0S(TYK4yHraJGQdImoa~V>}2HDNRRdlKK+)I8z`H~Te>}H>oIA-l#|M|MNeo&>$ zXFv6KvtpP|gdp)>f$+R%X;v%!C$D8>rGEk^Um}8&4c?q(?_1|BJBE zCseTS-Cmv{JAL%zU`dlWcilDDz-zE(q{nR`5}QA`G54)a@E?;-BD|GF=lD%vo@ihp z)KfRypT@*ubl~pzp@$sxP#}jvT~!NdGCM{ad+_FGr9wXeEMh4U|H<_obL2*k(i6f3U&Z+JBzfCbZ$XP~pQ*l)mOzs{H4`R^=^C55wdK)< z36S-A(we_~ydw2h69iGp|7E?Jorjje3qUfGdj;wKWW2rKd&J*ABX2G!3sIF@U}7l^ z7N-(G52SA8w$3*@5`}PS=`O_LT@Wr^f5sd=Hy{-wV{UBc%kgf`;>mV{+975jbW4T~ z&)Rq&5k=h-jmGgIhj-Lvrz+K;e zsgUoZ>zC`}Gq0EJ-_0M5yce@Q(g|ermz%FvRfyM@ekEqy+IAjQ{2xtM{YYou#*faK zc9@ByV|u#AVY-i;?i$mkb85PK+A&ObPPbvYr@Nc?etvlW0dd#&x<0vjRpDUBS_B^= zH;qcE{Or9wF1pC0k8bSXz~1Kp@cyhi)#;?%G5z^KVZ%6XEc*6^0HpCjVtR{Y=#aBS zY4L`Op3V2H;>ZMsLJw(mv&Wiv5m5Ud5Ef5vD_VtswZ9YHMZT|yCL1Uoo@hFSyW zb5Pz;vfJ)cR-?06yIh*0L@DU<>p&1zZlaw_T`fQ)bBOW1$aB@q`+1`f3GMYKfN$A; zRFQ2ZDh3&{Lb65ha;@D?Uxzi)U1GCIWbaNpTTdLQ0|37K738)F>I8$55D3x;t}ImOu_|e@vuO5@#gPLLhsnbnt`^ zmpLPnv+#n7|2;|^eH4Aqfy=a$iX=KVlkn=O|bj9Vp^ z8PVBx4?>s2X8>~wUf?0_WID+e8jZwwB5OJ6R`!oUrYpy^KaV2bdfFw2Q|C2)Zl%ph z!J13@v+Yz*Xa2d!C@P9BE+1+mMDz}#9WBOq;rhB&FNe%32d6%==spr@ao0#DpD9MDnAI#vPMV$b^C^ErPpObj`#6g zO$vL*`B{uuGY}{C{CHPkix3-DRI_({ykZIDFn<5e0+5NHTla7SXIw=nV$gyDg8G2E zHcRD9;U>OiFQ5yLmygfgy*}Kkl?$T^fLk7V7$~x$w4y1+d=Kw7PrO!FvqvrUX6q3z z_V4$fZbVKmr<7Nn#}C-_n}x}z1$J%WlzNt#^WmB*MKGCteZsfAI7O?u#7E@kPu3S9T-*MXuyg|7?(z5x# zcsn2L-{0SV6TPIS{iLUNMKd?jn$tou9zgI4Y<((I zpG`Ga09P-u^$$a@sLV*EcMk&coc?#^)Q5<~?%D_-P!n>Wyp~rJ(pAEjG+n$=WQ5qN zfz5J5o!VbtDV&d9SX41asFAs?(#^v1&et+1A2&7)cbh}g%9x}32~^XRZbmeqefg>) zU^@r>gJzrx5-IhudFvytSD?ng*4;!Y$@UN`h@X9fEZ+UUPvI=84u)g)4A+ zM?h_+jhP7hBtdT?%P$)(lh)AW4M~iLn~*zS2gmow(q*39OPPnF&-EkRea0{nkvUKx z1~GC|S6fSiq|c>BAY+P|3?vHx-lonB` zYB-#z*zo;t8Rp+zQO4+ga8{Kd({gL5JMqkAuw`i=?+kBpaS!`Jxi+qle?JfKfTU?T z&VHFfFU65seMt~=KdvDl;v0n}g_SHg@@q^K?O}HAAJWn|qkt^PI&TPEtqTB&5VJ*> zFw=6HS&Vy3+yhN_04fv4#q&FoA0L=xJ|Py21j{fB?9{f`Ul;aM<{Tf^*)O`jLkksU z{As!Hm3}~su!qiJ%`jb(Q9FKRxmd=(=xOKrWe?}c@5S@`9}YxL+F>S=DlVeOeq}ud zIXqdfFHBb?L>pHLy>)>KKXrs#a&nb-H9AFq2uJ4XnS|3g1MD_3L}s_J1j@>c%8Utx zW>>Sw1*aGCS8|qEn+@r_>U6DE=~m*9@1r1^SSgPQL!}q_hE^mRredACM-=k8=N)!J z;Ep_!>>u2w5s(FBpReV@Ps%P&mstvHH&}a#rg8cv5{{+Io+iyDC*yES~ba9`~bfBu;N6Ea##z z8S})=v-$fRsBx7^g+U!5yLK*(ALl8+S{+IDgk&8d_42HtKfoWk@ zf?4+Zi<*;QM3!a8)7${+_=pl6^h~uDrfA4=55D$EZ( z>uKiGzrryP{jVQM1hDm>DWJA}6?r=+{BS~7(od%JdD&X;bJ#~}qpPB?Bpn{)$AuqU z#lYq4t)OriWXs{)4X*>H>i>Q+uqzxfVYxjZ^1;x?dyl3z=Hv?PDv8 zBXWTpf5$9}gTFAn-okxFh?`;Yf$m>0)J0{s$)1M=ej98e6=kxnd34|) zs^d;23UPBuAyL)RrVV^VV*3Jz08L7m=&zXQPJ=XNI{P+dr+Bw;+;$g6ZkyrB5~uyW zT}TeX!=>C<@xul8)Q1JJ~Bv1|SO5^3p^g0$E*5c<$*VO0xuvo3TmH`uq~(aWq#Kfkpg7A<@9=uwT7{k0k3|at~BY5G8hG z7JWy{AH8YTBjplj6|t9Ae64f!^83kS;p?YAU6SA04_Z17`2041e|t@td{`%@`3lY9 z>y(e*3xnusRm{`MjqlSUdxz7V;p5V{mv0!UCd~CAZgKVO>g2X&+~>I8@33F=`78#A zhs^n$9vU9Y7z~yGI)DD_x0>%VI`vt-X*2YAl-Emf+lONw9yN6bgB%}w!mqBLPJG6_ z01w{a@{#>@&`)w{acF$?NhA}UWMwoO#K;1MMV*@VhIA zQ-Jb5Vt@T(JT}NpCZGR`48PPGD6{}I?iFR6bey#Jn%sxZeg{Ht$9?z0`(IP=H#XO2 zJD)oWrZ~FkKMWPJOzmN-yrvXw<;&=}vUhlbSKhSFT?-M@q$uq#ynMKbzc2Sd`rY&)btwW^^_hJ6lKEA5lvK3EkW=kS*q|_o0Grq*uuq3*0$v4nk{qk1i8vw4_X2`x(lPj&T z1<5fj1MMdEQx-|nTbUOg!ut!+;VskD&1MC`0}*B)ot@=AX=+m=n-LS-_$SfyB+2H% z7z@QMh#>^3MENeIYXv$8ohlfuG{frFc%TF3BGy9upn=scuqk?Ldp)l{EAE%(mPjbY zTXuLZuro0a#c<8vo=KyCW1B009c1>e=3>!2z>_U3>@N_DBZTw+Vz4Wiei*A84-*F& z(Q|2wIc~NO?hl!9WgQ@CmOYgac*&TE|k@QN(W)0jj_4nI+6 zwTVn*1oliZzpbGn>QpmK;Sx0aMHyns)+Y^x4H!gP=0^kt2Sp>c<(NVSDfKTj{`*$} zho2h#LvVq(`t5bc>3V(i9|z4zNkkUc^>0$(pdT#5;i*W}60-$~x}&6VWz6aGCY(1% zZAZ<$-r3E-9Uq$S6@d{Ed(~(Irlxnq7yTWVJzBn7k|b=I9ggb~O?4%gmTU3ih%PPD z@fp`O=;$-m5o(;6xi>hE{V1Pl@)~+&D?=_Hq`jt!5^Uh2l}v~cuLI|92$Q(;UZ*g$ z8n^`P7Dwh>h{&&Jes|VI6$hzR_kFeJ{VaB#_+?ssuIM7HC9-4V7jR zZ8sEoch3jdpO`CasYo>hi~0?xs~kJiY{b->t}t~f+E`kPzJL}sA*=1H z_r3bMYNmrt_I^8Q7z%jvJH{#m=LgHMH}hqVNSq#O84cbj_%n4rwySr1D^K+e?e8^b zfKoQ~lo8e*MrP_z@aA33&dZ?Kv$c`Uf|QUUmH3ovdXj+5*y7@%*u%IVFaFqdk>4|k zA16f&K>08VFd2^tIC&gaDeKSAm7oRH?2Pf)Z|>6~oU(>}Am_2a7^yNodI-X8++5s`Gb!2V?1#cV?F;ZF<25S>56#fH9s@AU4-@FAta zt)9~7lHiluTc`YK(-@!oH|@^{zLy_;&78e~-IqL%7V2=p=yY3fGL4xv*iIrM2+VubU6%%|Bdc5>dHa;s z7dd1+Tw!F22KNRFFLi%JqFYQHDwN;H-=bKXD)zx;tQdrIdQt#keXuo(>Hv?2e6tI!NR@J60c*$RdTf4fx zH=3JkJj8l(r2=n4bJ)~*evs^xVW;qr$WoJ`PY^@gjhWvk;t{(&`; z(4jz{5mv&W91P~Fk1*%boT8>wdeH2~m6obA#Umr77mOUI^NQB>vmZ$kt$@*hj@p>M z-1C=~%6>nUCqLY2nLe-B6hl3xUFO6Fm$qL>R3)=k{6$Givir zcFRkP-=#VqMe`RPiYT-s>QDTBXId{a-^A`ud}lqG@J5+`e_ivO1u|bYUq5!gm; ze%Wf8Ei|5TnaQf?tM+B`V`OV`2e5K@*<_E`}X4~A7JHW$Pu=&AkT+$ zP3GCIKCA$h+(j7~dR5WN-h1KGb-q6Wb=HiGRd?D?rdW~T z?eM-y4>TEzHcY+>{7OX4NmHl)QM*>i0#&Ud4GteOY&?DFcsc31JhlIrDpMmPCyEo= znK0;au|G5L7|Pc=rZAQzQk)lT#ysdXWAJYHQcHCT$ZUEIf9-op*>{PlcY4 zjy$4CsmyM8Q(O$K^bB+H(vXb*+JWzXON0j!#bAQ`0|e*h>PL-Kj*j0W<9*e!J!7X9 z91oY#jdlE$m+ul$L5qIJxo@5bqRKlsctHAAWJ?m+3t$dFFRm|O`0R50m$T?0>^ZEr z;skusF7E7XS-3yW+H>M_kMCS`%X+l8Xo-4g3g@P|>Zhnl1mmWn(^+T`{vllaD>6weVbpB0ad3IH`TqpD(nky z&bulen8=rno*$Cm(7)K)wpgc6TDcsQe;ef~tWdPRSa`4gs>gtEofsJztW0meNY#CO zJhr_(18k1}X+3nfbH-bW9_}3;`xtV(|A0bWvzmFx6zkLTWG@4d@X&$~Kn0n+m7nvB zi8fbOgo_iMoVtcQgz;1c?XjyWQ1vsss@{VT@!F2Fy~c7n*0d0jP>cF5H+r!w$1|G_ zDumjP-x|K$ZW= zANBn*tpNLo=1uvCB{xhfewJEe)FfKQRsV)5`ycmxd?#@Ln1)J*7^w{2Y?LM-q)VSC zBqX$X)(G$RUIC4K`T$0(Jj^&eK13k=LKc|Uu+G_1G!SVCjy$5OaxQ zn>*!176u#LZt;oyPWhqoMh*h=c@-IS;LNN}^sE>m0?;1_nZ0Bhj2PcR@zCJ=aouHA`LExnF;)}i-*8jK&t!v$-Mv&>gE&7z05ES&q_X8fJ;%eY*6DZq%zJTc z&M=uNp5N=t5a!cjv5R>zuScvZG9jFK9z~H79^i5%6W07!iIFA|6);aZUSz#c@c`7! zu%iY22$NANvC37P>VeA%)csB0mTPr`l(_T*;K+K&PTS8BN_Dd_fuprcTnRM9(vNn!Dnbqaj&-ky z-L8{8JNpf;IWx0>w7S?UebRqiwQb97N0Y~IR!&ht8Kc`af9sA!ZkB4=-PQmznULFI z(-Cmk=9VO+AyS9K(}}ll?-Oy*b9-|)CKF-_ApW!1VP=XZ5&EBT4;QX2*m*XaD>Ug7 z+Flas++(T_1rLxq`d4-`y$=4il-*O;H5VqEiM-Q`N71I@=mVP~MPqP8RlP+7he`et zK~mxxMkeT+Gp38Ac0*?|^LSkqz=enrJTT+j8y^RTVM z;raHOiK&LmZ}7%YPajwr##SC4MBLrgwY?&-j+r~z)ceb~IlG_h>^UMF~0W%C!Yr2svYS&jD+od1zTVzFC zdx+~z*YC<$%3|z=;qh#C`nSW%KKp<2KV}qRw5^nv4Aom#6<-jOkYqXA?+)dGq)@1e z(v0iAe9ko4$g9oPJjo2RNrb~SrjC!1K|lXGU9EKi#Tc}4KvM=?sLNsXrmdyYQSE5W zc;+WPv4+N4;j}|ijwH29DS?$098NY?Hk={&=L~E8Ai%3>vRznMc-J)Fb~Xl_xg-c} z7k?JZqC!s*z;UPva+(&N0WG=P2cjjhM<_t3K>>ra_Pc5thku?`Y-^kGWTWTrl~Fp+ zPr|h0lY=&fSStT}^zSZ6fQae$4IGtu5H2AxcO%!W!!&M)N#Pe+nELsMr#km7v-0@D z4z8tCt(lXXq1^4&V{5_D{7TN#35JnufixLY9$g0rd->stwg{=1}1tjWHbZDo}%zb+evUzLh5jg%Gnn>-mgpF!zr1DQNRh?-~%*jn+> zBx+pD@0!KXb8WY3xWoHIi<9m&px}K^@Nr9lno~ z41Q;ZZ7(D9&c&h+4GK~I5r5o{mX^93d=DC){yIDr-`zF&osZ?*pOc&b)TX!$0EF6M zgm;gHfN>e!g`q(;NvZY-L%j^~Ee)_4?{|IQiV|CI^mn2E4i^^q+V0eO+np_@z3ANLc3)g05hJqXH z1Bi#-OSE{(di~KwP*p`HUDYJEbu*CbOB4ozBzB*=;0c{noSiKKJye17@-cE0qjLmb ziYg$t?hBHCAq}aSwH_(iEC0XeQ4dXMAd%ORC9*`F0wmPw%w5;w5>w-;lmu!KBV#U> zI^ZO#%~j&9uvinGh3r(RiHA(MtetM-SXYO?Rr8G3pvB-E%T zWl#+%Dzk~7%?GB$c<49wBzJmo`Z(07TJIzKU{I+R+^|Ob#Tg`);n@ni&vu9yMA!?Fk0ZpCb|BBg%8GACOgD`BRtY=hMx==Tw(tsqW1cDk z)ZE_wDWl`=I&tF(sB`-*9#NWJs!iLck_H$Us-uE#JNQX=wHIJMm1???do~xw%+ENo*`EtPH&j z{3+3GJAcMf=Hp^kbq$0esX%H}aoUk8x@|>idWaw}JzZbB!Cny=Id4jkNUHNKlCUF| zkd}_#p(OIr!|G;nzuzSrpw+O4o)q3*|7lGez4W{F+@pK5u(MXvQ_DUxM(^(Zp@e}s zot2Lq%K}E7hszC)-!lhdW~zoY$(KLUD0Y5s=Ys}QK2%Y9ZMys2q_n%R3*GdcJRg7T zxSqJbupJk@I9xftC8})n~8w zK(&ohXf?laX908U2SOAT6ct$!tU&mDsi%?WR#8gF22kSNw3VziU+bp&Q)Dkk zP2`c}Jp7~8@{Wz$2Sr5mbi#04XC#HF$%qA7SqOD8O|t4r#Q#p8(m%wCtg-2+$~n+Nwc@-5ww`W63`~GSGafp>gL;QrZ1FioL& zs@^*8YOgrwC+hF|tUkiXyjnlZ59GJV7&ZQiuZUctUtR2%snsC)85mdMFFa$Ga`{$I-fDee7i$IwWc3}2dte1};g4?90&zHrY z?G|v9pvH(k&k-?HG+w=FU%#uX10K_o(DcOcPcYf|y;@Ri7Ay|c8C+ACM$vcop6em+ zGc5PElbux{ZFd%Mpn!xJn2wGVv8|oQlo=ALf8x9qJwyEyQ{pC>X4UXmWzfHeKq?c1Pzg>WJRTeu7 zZ)m>)s;|E;0!_#lfS>1~U(Bx;$n5XRd795@d%!Z}e|Vg4&NgtJnZd$}B>fC?-5o5L zW~TC3)uJTV{GB$rwoq0%uWk5oLaTkFh}~yzWwSrV;q&J)4eny)Y&mKQQSaT(jc%X- zy~)kZ)YJ2`rB@_ww)Z{;hpNugmF=4B-NU%$l)C!O?4{xGQ-pT z8*fV#&i!uzJqupCgxzcot#tTYK7yok){y2!H6aroa0Ln|R{pG>k-7T_OMbXO(7^@x* zJMQ=>MSoR0ZC_r<5SmIzCwxB~Mg>x}NfsRhq~ih?Vl1Mpw?%PPiAYF@O{2_V(bD-b zK8GDpJUne31Hj?5Na6V}4xqV@=Bi8q=r?302n`U2v=k>`R0;V$&XqT;+|Q5u0=C2r zhU1QxXNGK#z?x=!+_ULYbr>v5qy-R}yz-<%;#9^21tE%0TNyNE!=aLgBGu``rX5?{ z-^O+1-B%5w!g`4F>{Hm`wSGPIwi*XTbl2L6K_Pb`xEo_*N}4AOLH!tpF0AS>+InWx zx(FEw#R&L{YSdtjvTPXBu%me9W@0cHFG?IXX+|0m@66Vf_7_E#wlMV&?_ETm?ILie zwSISX%>>oAH0U3-z1E-QeMee?4u_yGxqf(0&B=_w$VIEVC(&Vq-szicNMEl()D=Ol zfe@CKm7!ET`d4bt+3g|8sN*vlQ7#q&bps9!70r95SMU#*rRh1g>BJZq)}KH78XG@v z^d2D%%lm80)|H|objBSl+FdO*y^`eukme`olo(dyW-TnJYZ}>wS6_YLCDHn)78u8g_mzRDY}gFuLW{7 zr;JGX@WTNP8bpQ8_BxChn)>0LJOjxZC6{4WtgfMq-%de(7S1a?Y z)AirO^1~piT#SE69j5`aKK%#T9_QizwR8xP^cw<+Q(`Z`I&rD|^3UOU+pqPYqJ^#P zpBjXDIPXArFX8S}0E9Yx+MXNTm`8|#tf60Ms+j^OboHUlLDc(p060bTJ086JPQ{*1 zU;8{?xIaCuzW6NGPZd>UY)=BnzpnOaJ0`Wk(uz&SS0PuQ0wIX{8^L^G`%uPVxOF<% zRBpjN$Evbd20qsU{E=vk;3MN)>th@|QtWRbH!tga&%c{4b}TI|(Sknc5FRd>afMSq zZWW8V0x&7i=h~Ljaxu2pv6Z3x>5Iw1h9)eLvu{Qct)lgQ2|PHnlU5CRmU?r#OX z|Ec?(k-Q-pQ@-w#T{!dLgUVta-py_Gi{5s;4E=Yt?rX#zxFP%B*FdrBdXa|pxTbR? zEmT*ZXMQ%L)wP<-$cFFk0QeU$T0iGg-VFc>P-3@#!o>xgJ-}2BC~I!f+FvN+-2wZr z*Tdp!c6?MQxBtRSIpjZ^RpnFkEby_uU9a@{j)tVSl-6Xwn7FaB!Uid&7w0|KqvaH& zQIJV4ab4VnM(>-CJpuUPW%@R1<1NDe%zn}9#ekm+F_T4|y=heZyH-Y`#9 zA_SIYZd{f^Gi)C2lcS?|Y^)0V(i-;dBuUlGlj;hbs1I`CU_7dM#BlUnWH>U!syABm zsW#`3CHYL;$G_qot#r1nQ}p84eb)Ja2|GXcH{4j2`1jO;!;jFsL6`1-z(-#+os^oI z#*JEgttJc@qt0$MmZ!~CA&{$gHY;&qMdUhWV+8P@1(^fYnylw+?nR_W6 zYLiQM?DR6Sv*CiueGdlZir&a}7yD!|ZsD^R(qmxW@@b?E#saLHU-(yZcwM zOxGdbN?-ffF6=oLk$txSTsujGQtI(wAUNtU6As<%c%Wg$3&r({=l_vJ$1K<{OMv(F zWPwet`j?kD{dL8GAh-RAm=iB2XI@DdJv54H`?SWkH#-i0aBB+4ipn;$Va1@?y0mJ^ zBVYLD3ChbniDNLfkdt*r#MaFtE|VMk)SzOhYU`tlB5u1b4cjxReqVL804MXl%TCR`II6i(N$#6W@it$;T*g-Gge&20S9mQ!)k}mmyGa^y=aHWNy?{5@MdAkr~AJR z&jZI}IGpV7-erk+)$g29QQ{M(Hm#YsSyUX+>!VjN<^UH3I8aT2dV0q9Qh-E)Hohwt zen7vq;xy++Wye|FDKT~zLK`1b(!(hG&fpa(Zr6i}xu>}b?7t|z%J%#8bw?xT3nLC~ zLoxT|tJzOqdWjAW4k+(-KXz=zMfGEC(C8vv;@$AR{;$HGUvS($z zEj7`fmAhRUOsMo*KG4+CipaaYit&X)7b}35G$B=-rw?F9xB8>?Db%%f4IUGKQAd3| zYdK?@o7-H~QNKaP@v+*pj0NokNVAQ3IqNSoxPw5V=Ob4Bv}3Tp36>GpC_f5HkrJc- zzZSr`fzP6lphgm+qOGIzb~GBOg`f9(Ip`1-60>~!9vEa4J|)cnVRPhCzDKjq%YX(q zt~aC?97LO@RD`KAdj-?dZ}a)`CaND586{!1P&gy~y(S&$->_KIx}JR?m;5B<1p637 zJ<#sb`Nw&pb-GB?k~V+3N{h=vIrp7?USf@#Q#A#(=*^)smi+Kalk=uM-aGGrZI*`A zx3nSC7iU(Aeh?F5V_9Ssp5Sc#A%b9dwX-Hw*nlT;1G~L5ay(2I0fCk=5`W}tF}^9; z_aQcyT(ATOjgC%|qW(8FP1sguBok=6lMCg-g;P(%H5gcL>bg2Ro2^YFqI#lV;Yzna zoVA&?9|-V5*>F`m(7{|Ov5cWIBW^lO^rN&Qv;aKKahE4fZ(*@LBrsXPToj}y_^Z|V zY@>bb_b)Fm!qMaXEHr;0;fSdx43v3fVAWU{RziE=^q0b{{zxo8D@>Mdek>~oJi7c_ zH4HTQ>vIc2Ae4#hr5ridNgR{$10qqleVXt{ApQHVvlQHme-yZ-@+VpS z4H|!aIbQmT51UvnTF!|tgP#KnSGj8EF0q@BYJP|q95?O?$6a4e77o|_qzis!LGG+W ztUpWrryvbqb*g@}cBQFNBuxR=*%T%he$HrD{8@$xQznX&&Ul;6rDRu*AM z1dcnft_FFUUyA6vnMIID{8@>(E7B8fD5(DU^3+$2i3LE>=n4DNpN{s+cp9(GHuuMT_o)8O z6hrqQmm~J}mnS_Ew$@|URZk21BLMN-wzPa1Y*}$Ve!N?^+Rk|b`b@SI`CwAUAwMcy z5=mH1oT8VnuW#Ecml|4|9d}Q=fI+La_BN~XWen}uZ*6U8e-h}4-|Nc&x|SZl8^5<& z{OaydX}i#I>-Q{NxY3ugD&7-$5edJ)-Bjk^iKj)@@CtaiXNB_ACEjG~zwGMaHd#xA zf3PDRr9wu;=hT@ijU2LYnS+ z@9qE}f2H^85I}OZ*6@89;r`vVm0~DLaZ*u1flbYSQqghN*K*P>)YsU+N8OX3LN4I4 zOU0d1X!uFn`|dm6^QfihROpaAUH^uUFLselmlGMY;2c#4bBjVO+XZEf-mIsyWAQ>uo8>0vZh6P4@ zbrMH>p#MB575$Y1S{M_xe`#8j!Ta~fAphQyMOk(GCsoM}T-J~CrBFn!-2N4HH>-qP z5hGNJIVn=BSq46T_}$5s)CQ!*8%88FRX|8ikk`kXJ7X`v5Ko^Fe$&ocmbPxBJ8Sjs zL!RurJkG^OlPHi{V#tjz54Wzq2(AR*3h?A0jV!z~NX@cM*VKWyf5V|zB0b3zY0)H< z+Rd}J?#i19mx!1+DTJtLB27|B%lQYh@muU}v7ux7T#{Yi{JAu|ivxi=+eb$l-=Plz z5{aF0`IT(vzj|VqJKUN@Lkj#wxrlPoB8w)du{U2-RH$hF9Qvs++Jz&_K=f@p-Ry&Gcyie{V|V}9oM#3 zW_cxAnT_5HfW&%v&_(NgA1mA=(Jk&D{ zj`bdiJ>OD>#6pqqLcuv=Pme(SksFlWDVG`l)rgriA@rO{r;kfEdTcyKU{upc`Kci$1o~shnqkyAzNusCWgvjL=%rAU069$v95%yB@6mNlZfQR_w*;0$?hq zfBrb>+)pk=*+_6zG4y~n)T301qQ1t`Mr(^p?xvDXyYvqJaW(JIllmZq?oX8xGw+-M zoriG$EDy`PzIJ%yMl{Vfd&;R=M=eUj9|i)O@F4&3B$43bPOWO_v7$gpO1y8y^HOtq zsxK~OP8e`wlr#=3A- z=ey!5ght6|P`$PcMZ;koA06jx!Fsc!9dnqfH66HbTkrB zjhLw3&V_*UZzxPgf{L{_1r|gz?gwh7{SXrP%>CYphyD2chUn<}`mn$xp{xKbk$R{E zBoT7-ddx}jNv_&Lmd<0RoZ4-L6;9nw4FNl@GBL?bOcCJ4m_mT%Ubs%u4 zFQQmTScKshPUVhZ=gQVvli^+!=1i;i<6L0nDU4~qgUDdCvZOc9YwP*lhxb=DU8f5j zH*Q|;0Z%|#hXiuI{77@C|5S7RK4PCj@x+2t z3HfFS6)x@^zp)@wFKeV{KzxnXVqSv5kkb9jji+@II69mu-#4+)jra)Bt&w8|JJ!F( zLvMz&upq4t0a+SB{TjkqO8d*CpLQ}Vgb;zTVFiv)g(r4#IkmXhLisrHO==DBZS<_J zdhVEUd5*fbUX%FkA&opvb1Sa^76~a;yH9hsJ1-kP?Q3AQFl#P~Na!T3Ty!~?QW-q9 z0C0^EAmBcBlZXPMv&X9yGYH)9{yZfz&*QWU4WZWl4OCax;C>dcoB%mGHtEf*EGD9E zkJ^hpb#<<$P_?LQ2=AzdxcG#Cr6XolTN5Hx^jm*$3MwXX{#4GqbFjO?ThND)wn$DD z&3g$|!eoB_ETy6hMHnoMKTTo86%ZE2TDey*_I|eYDtp%DCLgP{CoqL(BBJNkR%Iw1 zAW&JpCqV4J_E>Vs!bdPxB~%u>a#1C;I6O%I>Saq{FkR8m(x9hIACyL#u*R!M1H7o= zrNxyBmOtBtjuPfHfK=ZW8yXowm6_=BoM`A0zh$kW}u>^T`kIw zWtWx@$V(*l|N(NVd(LM;y)!cU~yk^Ak)v2zk~)x#)#}^1J{$8 zK_+w(&HzUp896R2Qf1k#>pk6_jgI$$7Ey>m0B(%5ZH)Xuz8Dz!6Y0h9=T`x_C_PZp$Ri{Yjkske7rR(eZh6bRO>F?~gz5dbye@9h& z`{yv4DsGP@lU@5iQvS^qTAG>+JM1O<=jZV<@B?cY48X^&a)Zj7*i}?x`AmpRoO(E2 ztUjZU_Tp~)NIl-4Ot8bqEC^1X<&5zNtdKtv^9(){SO^R;6&{9aLQQ_@3eyJp;l1C2 zqV46F$_--95rxB`7`%Mr9Y^*KVt|J4`ubX3Squea_&lTqD5+P!oUR$mUfvSCj+CZ- zF3q_wC19u^|8B8B9}50Eo-Nu@wT_t+pH3siWpyZa`QtUW5Iv=2LtWbygWq}a%QFq7 z{-;lgi5-3dV1GvHr={_yNAnbYHNwKXFKPNw)|=fZQm?8KXsL6FI{U#NLgw)}uRLoa za`W);g?8evi%1d0A&SiO`-78HnRN0$4$$Y7Mwz57EWNrvir&W!vk9&6T>0EAcW?lD zuk+0eJrZf|{N@UW_O0!h$8Rwdy87Ss1wGHx>TN3;&*gR^dV50#&71&70T7h(yT!|^ z2~EP-*>YIGZ!1ZwcdmEt=~nsi7FaQsm*3_HIMaty@c$C#jsUE!kM^EFDOJ1d91ipq!|+ zQd(2vk0UJrUe|8U55~{G*#a82{>!MH&{4R2x%%d(LWoi$&!kk8Flj}sx>zL7B=T^` zZFgTNJiYt4^a$uGKewKR0`8j{0Gg1+-*PmHT*9|y{Z-Y4vz?nOo61G_`bjg52QRj# zpdc|8q%J3=`mcsWyjnGCLW4vAOyw{Fou-uaN}@yZVuOZs;+5zwyf)#Lf1_7$j`%jU zPBif;iitYDOIN1EpUOX&ti~AO`@6Bln1EUtWZA^|(maR^et!k4oGK~KH&^|gL~58D zD+E{r5_B~rW)0lt3&rlnD04Eh=#Wn^57nE2{9mg0ik9bvwq(|dWf z!&BQ#&W*ej+y-KAWT&v`@fMv4VfJf5cFBjM`V*BsoDt60+sQRvvP}h%0$2Ev6x4$? zrK9sd=cyQodE~?3W?VjA>UJ?BG*pKPBml2mi^kQWfTuW!qL)EZ&&vli^+_hu*2~Pr znEwOe6~?A!wX3+l7GTxs!OzF#>RHGATnfS#Q9rktRt#Neo$`OM2}>B{sH-=@z!A(@@GQbZ z%Ph|^;&04*_mc~esyjAN1_&g9RenwK6fu+gdE8ISwuEID4{HU7r8h8whAAzBkQkL?0)2kIvZ}B_Qw7{jLb{*s zt8FWrw*F?&SufXfBFkcc=3jmIxztx`BRBbXA{D~TY!$T(Xd~?@c#lZd>TQA6x{+NkRsPxc>8n+7kItgVjWfuboCfe7pW(R7~SY`C45E_j%Rw1Bq|TO+ZS(7KPfkY5+k<#Jm;7G;EZGcP-M^L7g?^f; zR)eM56e)_Wb+r{5kR+gfG-opuSf~@?LeBBU6A*G|p7DkFg-Dd>eCYB^l%19iF(WEt z;td(2QACcl01uo(;IU+1%J_6>#NH3IWBQ{`eVpG!O$ZzACssc4_ur+@w#c#JurCvfaYZggRmMI=rxXT z7-Io8&{dStjhVGx|2-{+BFS8vLLEd>qwzF9I)8YX1?ChHx&Gh+33@k@$A!!J5IjPH zh|`Wzf$g@EX%CnR;grL;1EV6M2T@JM_COMiSx%Otv-z7Cl6fa zPjrzb`G1tYDlqcSd;LKYdJd^UfQvhVuE*u(*m%+rBuJa8&lfEC0E(E zHnx0gP$}H6*G8C8p{$qvVb;reSo~Z7tIb_pd$i^*nEm?$sV&kaXnpwfGzL&lszLnX zJK^*JTz4Nhd#kMOnkDM<6C!39(rxi1%Z2fQd&mVR5ICf{C zS*(NqYMfO9;ZC5uVW2`e(|Rk50ah@}LBxzt=}C6la%f3st15OyJ{IEcrO?1tljrFo zjJ1JUrboZ7XWg0e(<0DUrvd8R0&JECcD1)G)bqrkZ+^O#sDyWprz=w%#lVWnaWkfz zhw=D-(q4vt6_1)(3s`R2i)Y1T%*#2JPR+mRfpiLSQU#l^RFcu&jpy zABvG{-B?nPwIhL7E?p}Zh{{G5D=xwDlL2Ebe%T-Up2fUm3}z%kh?AEwoA|@}DwTP< z;R|kIY)BHZVbQ$r^~!($sT!nM787VFGDWAuUTdt>b-u)rbwLQSzli`xiLVc5VtH@! zSq}-co{~-K#stN=JRM|d+?ZRAns>{EaKIqN+Y8yYie1ZYC=gJ>?&(>;7WoO(b#fy3 zR2Ar%nDzPs$hdSPBP0HYK%G3+S|Xi34uGixolu$qhnhJO!lI(U+7$3bB--XkJ>xD< zd8ih%I`1x37N9N`1re|{RSyu+`aHvCsZEi*4I?Waw?|L{XQbhD!mo3g%t3f`-fo-c zTVL-#!ef8`DOQ9j!gO)02TCDh@rN6J!tzhgagk*1E;39q6;)^h)+h5Ylw4?n#u}|) z;oa|WDbPs%gG98pP~*E@_tfWzML2L8#?KH^-XM4(eqG#5xf_KV*kgs<=4-u-lxp}Ky)WKEa%K|Xm zp#aGS(Qxl9t2x zTbr;TW>sWQB9)zZ_Bq1a`u-}|)WHFbvU8mzn4flOa|0+}^KPtUI8e{0$x`?V+Thdw zrF{Ya%41zj74(Z5F%C{XJJdi(W4J?B4%cIkLRdi{_t%{r@zivhY#mvh3!UX&hR8D& zfnIc*?a6|GCdYV65(L*_`48Y}|KM2N?(OHky>~TB-RV0T^|M+G$g3uAuXS7>>S&v# zclt*)`CN=IRl)BLAs;DGApz55bT4e*GHZZ}yIrMQfVi!yb-Q;J+iz`y0NIs>(-0Ln$<91KFNp z_Ju$53l#iPhA4n7g=G1P8xn*C-yRz?1Y|3S8dY*woY0 zOG!~v|9>w4?A_VY&P?5C$WG^N)Bik6OGDk|Jiypf^~xO~fW93Hx+tNLQ!mTL7Lu{{ z)3ovB`V@yf=#Pz--Lo`bsoLGx+?;FlTF9gpkG9+SUHbY5n3Fu|xduZ#HgrdI+Uv{k zFRCG;4elREO+v6N`#DNQHyI_K=Ufmc-t{)@m+@G?s^O??tq%F$4=vb?aH2nV!|(|j zwj{jqL0lM_BJz77*@Ph`?8?$Z)|}%3M-w5w*GP$V*5hIda(0f!3^K18cx-!PM^C~bYI3|#r3C!$@`>ne$fyO z3qjIXTxAC*s0B@1&*!=p6wWydOo1g!V5n4tusQJy0c7K98@rR?q_F*LL> zQ-*oOv1rY&_^EH7%5Am&PzMMLGNdfY_Rh&qSm`<*g3A2|7#H))Rg&4;FN@P2zW3~S z!Gm~^7gb}m8U5YIq_q6CiKwLjvYef`H2zq)`m&KGNnr{HL|#^y|5c8o4d;Z6{(Nj2 ze`khF3vQ#-C>n71LwzCP(*kVE*!zFMiLygplg z67&zi7|?$jFqxi8R++2%2yWzc;pOGcmTdCg`)Bh>`s82c;>||f@WYFcv*5!RQ}K26 zBb!lja8xOqG&R&i!io4X^XY;OJY=T>{F&CSe4oQU6my}H8D(GdW=Luwlvk>O^l+(oDe zQeHSkqP2h$tvx4FwDX&J`m42O7y8F-{4xQi`Q_2DKy3}}PAqcl(}B@*RICy1-u)1?#!3%dNXVYhMLjO#rvRcqS?Tt);x<5#QaFsRirmBL#z0FOvYX z6q{!d6rGOcoD^|7I;yoQhP#j}$r>qC+dh@0V`I?h{PyizF}Eez=>|X?&bJSCu>hVh zh5(sR#Q?$L5XcEFVMj`mh0$2XGS(@*2lh97A(soaFXFUb0fCR59S4(X;I^t_4Sar` zGr*FN#m4=y0;P}>&c&AYx>MJXGky73U`v;inYlPW<2)zQ50;|=#`=Q9(}nm^jqzBd zlEysyWKZN{#)E-*X;F5KA)%Lsd8|AMm0aKzdnfCy*d)-g8CWxkW$?vo zkbHQoWp535fZX7OCA#-*Ejdt=81?>l^ry9;;r+wuY~-N{!m*N6@5>=~DDo3t(Ar){ zwfN>?#knws#~RWX+)`mz<>Y-M3LiUb9AwQY=boV(8* zwOVDvlsiMUXy&G7j;V=B#g>o?!hjcvE#wjCH>^xOIlR5@{O5Cj5Q3H?`Yrb_Fu_S4 zJy$G6{o%odKfoF0#^w$B*LMdU_`rbetIQj~RIhH#wn^gRFya86{Ej8gp6e5MM)_qJ zNvKu(pDFFq92L=07lX1x5a8IqKdZi@#0v({nwg`U_kBQ#N|P&qo%p-GkMT+W(PjE7 z#NFM!=FaXG$fHD#lvjynCKn`E?9K;@$S=uU70CEst`J1N+dS9@+@ehwmks%-o+p*H zFKiW4sC4Wjgf!SdOQt7}_Q@QoS6QaHfV`Y&Yp#_IVp^-sPf{D*=2e(y71vYPXCM(XaTEjntd4K5x!yLF3 zUV~e9TMgA#QvMU{f2+EGZlbA^zVX8^!xE*ST8V2tTO0eHj+g4xo(@I($e~hzT~;+{ z*4f8ox~BZeF#=YZaVW(?*hN8BhQe;ty+9yhC@8e*;1$trfoDSv33VM%kWcWN@d=;y zQs0;2G=isSPFy*5VMJI;5|Im(A2$`=TNt0ukxz$~stn@FUM4}5^Q6GVw5Cf=e?FA; z2VChucP1OrKV7kCSRrEAscxq29Pq%6EhC!yfzr1HKb+}xb+&!4o1A+U_RH$0*{%u7zd^H{N=m3iXEtH)+YXiemjZkrc@MN z5+P>|b!CXp*_)(%Gb3Aec_MMIe}5JdwPlT2-(jryjdl={Wg#se+N*6XK8_Kfa_7Yd zf#NJlDSj~T3UH7KKfz}idRCGGn^><7Yu-h^^wp`1zPY=fe%3=8W7svA)GmUCCdO2D3ENH!l*W|z$;fGF*1Ma z`+gB!tYJ6ng4%GJ*YzpI2+1|LE2rt35&;MNfM$;L6IRk5b_Wz+SIRFh`Q?HqGKxLd z7l$3b$8dyMy98fR%BxEyD`bQ^Y*mPi0D=|Ayb(@QSMGS8l63o7Vy~b)6b=8kZg#g$ z^n~edJmjj=)OE^4bzG<{6sQpqHetYibpK)XNIf9CpPcqf4jbZ`%XdI8B-7}U_p$gi z(<()sNX(Z1VTqVC#n9n14+0?zB1=!FQR8OPa3ZmDVi9m3Nso$h8zNw3`6cE;T~TlR zGWgc)=BjRh&(LGTbcGBL=Y5&DZh{;<)KCyqYR{raX&X;(qd?Qf@>*9Nj|`HMlrCo^ zbm1pq-o^bs%wT->Z=I=;J2_55S@~~z*9FmWdpb*Hmm}HU4Jsd{hmF2$m3^caYqVg3 zNKbVm%3?E-g&50pyapnbfTQnqZ`SGI?ZIL8mmC>jC<4NR@*^Mrh65Fbi&vG4S7V=~%^%BLc*?5m>xFbK}x>|*1&r7ZEbs8j^u-~2%$g3(+uIU z!%A3P1zE%D>GjEHkX|$|??{eR0F{+B@-Y9j?{>*t0gI`~OL^g-F8C-J+8~~0>=5ur zv^~3aI-m1%Ib;&Ae}Z(f{D)Y4Z!Xf1@+(dy(5%(}uH7^e3@SCyQakf}j~AZ40k4nu z^Y;p_sSbNB;|c<$`|l*oa5BNr9tW*!77k2mOIC5Lf9KW9H{f_RrH^~o2IU|-nQ&*` zV`M)!d}IE-JXaB2bN+Ax0DEbnGN_^|Z(T4Qpz!35$R%+xeZ<)g0>E^m@LYj0+@shXaDXR7m(Xfy;s2TaDeM!lA*{qXe0=iw=l0 z(CNS%++Qg3uIWLE!y@zgaGrL%)IAiqd|g#ej2>7Sd&C_v2ApD-zPlCWs*>pWuBD>Fam3tpYR?$AMy zZNoQb`ZVz6Sl|!D@w1C}(Q-?&FmXU53Y30WLzV@ZR1f>6`T#3H@Oaq=NH28k9{y?Z zeCI)t{^ZFM_)esS=p&3p7JR2%5ATQ{Y)J?s`23&ovtZVUE&)a8qcB8ew9t<*RA`}B ze;D^hl8$=aWgw0BU3)KUFMm89=$!zrIe_?)Y}y>T3Z5E`o^a1NH-)=DZBn*5Z}hkt zO1n4w3DbQkKDr4Nrv3Qk;5OG}uh+X3OHO-IP&bdGdDUX zR3t+(Vo(|Q9Eek==|0Ql#VSO4kAM3m^WF8mdyBDuf!k-?MkV9S_y-`D-vVD7%wtyZ zsJ~i3uk#=HRuIyp^E_2_$#Cezi(-h>g~;J?eDc#KqxHrZ?v9Ne$6@I~6fY7sKgH0@@2+*SQT8-GM3IrJLaBz*H%C3yLHmwM zk&$I;ei^z#{b9*hdR|Uszwk zyAzAsAHioMM2L%tp+`4SzJ7iRy**-a<3e#(BWx@j6*OI9sYo$AkQR)?ZkQ5c`Afvhr?z5XSc`(pHU8Ylhv7M-oaz(vvEfE6#zih7bHBZGvIA{|v^D3CZ>D~jzK-HnoMvWm8#$;rA1`!f%AWz1 zKPXooM4>;p{C<|!vL@(D#wS$F)3Ew2x)dek(4{h%1rXcIuxc* zba(~SbP|KHDHo64u^y$=J$XxlM4*VHC~(#|wt9jp3|~!|wVz`0$kr~eqJIo0^mls# zsC9Nk*Q1vauq}5KDuC$m`?Al11o5nj+Bl*+6Lh!;+xW=|e4L=#K zlP}!9HVCe!s6~?vTTYWFqZ}%^i$69CUWZM;K?TV~lw>GZnnZ_cIS31{fr^VZ3>`_w z#5El69?9mWv;tj|9k=ImbNjsgORi~-&rMP%Y22OMlcfE?$*!y@-6Dw4>OT!FLbAP> z(5??}V7_b-_B)SYXWyynQvP!iIfM_juq3Ac3m-KBj;ookovmWmN1UJTX45*~xgAMZ z(s++s)-(rPEFdv0o|}!z=|wF-Sxb!Bze_XU{bk3+yYr@;PTydEkBruX^GYKCAlGgh za#XF-4tI-sO<2tYo3fGX9Qz(zD*$uR@C!7{og`VWOklLc<(Gb~7<{63irKN{e2 zjvXH#Th@q4i)Rm0&sqF7tybf%oB7_=I-vpV==FOC1_nmWvS{tHhy3gG5_wcXADWf9 zTNs!bzhq~-G-U>hDCMRkpiq7cN)VnR7Wg88?23VyloVsXJ5BY~Ol;~yO4`WfgWCZ0 ze-`-9tqgWF}NszoU&t^3|O4u~;}ra2c;23%ah9*>sR zwvJ%8LuvBGmH^v2(@qJ=-RsNs$@Q`2<+P5!MNedI+-i*fbo$%_N7yZ}J1$r)7#~jt zUg6=B-lF`+%gbW}%puk!O@|Bq=Qo$(*B8JwqtTGj*u?Y$7^bSKqN`SR7$R+KX69WM zaI<#YGtI=i@es?Ku9pXKq|VDhD9cI&$!KXD^0+MuuBeNU%J;_X7ar)|yKHvi+l0BX>u^Sq%NFxeII zy2rwr=l4NJV+Bv1q(09HMR?WC#IE{!czC$EC8#kDxJ&0;1c_?+0YB;t2K|~C%O{!^ zgEqsN@A%;o(h{V3Y;^O2It~w5o9UYsRtjuqpM(6~aj{0*BMRCj$t*g}_fG#EkAA@1 zQgljZ)(qMD>Km4Y(X(WUE5huXbm;#WZnyH~K4wfTKk$}h9%;wNFMT~b9D=*?ASzxQ zgv*MPq~tznD39uR!Df*ieW;R8Wd*0aC`spI9%%^^NJJBmnope774-CU9D;HW1CWN* zqNCX|4+T<wY{x=T|GLkTxC0~18<YeYVL01H#ki`M04 znrDU7^7V*G%Ise0s;ZUePdV!1SU^PZNQ^`YrwlO@DP4eAZ@{A1YYb&0&ns0vJAGP2 z@GjZ4r|JmzJ@Aj(t|(F;{k6IeK@V>*SV3h)4JREaN5`C=*C0S1SU97-mWYsp-$=ct z>z~DM5qElQd8J7e-Gev&I(29Wi*jYYSKR{2E_STa@D4QR`5H{-Shgw@x^vNaVO!T1 z%Y|Ru6?nhU&UZh_H<03xSaE!^+%t`=Gc9LeVhp-D9=JGM92EzUS9@ax%w{I0kfpwL zn-R(fX6^pM@hwxW9mb+(FEXAKn=h@1ANC_&HyCo63!BbR#Vs1p9&-Cc%z$YWb@9V4MU?Lw~H?u3c=o(yj_X1*0aTu?2lQc_YTj0{zxyVn;7fX3=n#|U0t`+E*Ra4Yq=y?Ahyi@yOh{kh@! zfG3NA7?}_+>Dblloco);^*;ZmfYp5;-jUJl&cL(D&STLMZs>T^-I|eRPJ0#~5)e(| z^8!x(QijH@zVr4wo-%R;_FV;I0GkR`B}zZ~bNf15?%xqmDt&QxjgO*uMYwTu^CwCf zM#`Eov%S3yd^SI7D@1JpuNbqdmC4C77fitEuxOMWgOX)cLwpZ^=J1X7J%Dp5SY4g$ zu06c69nEnT*`-;4)rzN|O zSO9V9Go)BhV|;RQvb(!`KES7ZBCCYxg8An5{@>yKGINk4&BqSl?`8rS^m$CcVX~&Q zUc=d$gxA@Q!@Ttt>BkX##3zG>TiQR_YaDyC(Fw=MD~PTurB) z_kK~izpler-w;Z8(b>8>x>tNIM`oTe2XyNd7Y(-V?6$N%~d5S*?F++^7BQ7ZN>_-8+B(`HGlD(5SxbFmi1QX`V42peU!q zZ54C7=fr3kGyag9?%)5}O8WXyP#FQ<@PUWR@1m&pW%ZOLMYm*IfgQg8mVjFxG3yKD zDST*q-zZG1sCoWiWONjH+7~#b*^**xJ8!H(9rGa?tgX5YJhk+kGy1~|KBqf0faPN? zXcWDffkvgz#?(rlmJ44+^H*N}jU-ZnOs@9pnos#)+&6zxJxwtd+1&>MGOFANLEKM% zxS?RnVT1-fBP3a5R)E`YcqDL^i_k zIr#wC@nuo->B8wZ{9#pI)LVoC%<;TZO?~p+EOHc&TiA1{mcF#eqUo3>N<+6VK`W+A zbtx27L?Me-b$R$KKZ%;&v$5<^ENWFqqK_CfY3LPO-Ut@Wb!QkRo%|EFtITaV?<9(< zyeT&!MFt1&`PqE(eV6s<)%h^q;5m+WV@PiE8_(*WMB#d=gvx(bNW)(3$H-%!`IJ>R zcr1Ze#WY-^Cub!nu})e27MR;Vo6=1)U(hlpGa?%ez4&ZU@ORo8qy3tN!~vn85`4%{gQEBcenLV?86%k zeIlYy!6$YN#-_&EQ25~Ypyt-rovQ_G@#&zt{?E_j4xgAqfDw_@Tt96ZIpuYGIb)z| z|ARJEj#$`M;NRLd6gg$+y4VVhUv&{h*{PC|U9GQdEp6TG?40a5)x2FZd^L1(a}#Za z-^KYUry{KMJm^zs+BALOonSwW_!L}i@NumEEg5-bwI~EP7HR0fi@*(dHCSLcb-lwxS?y7s`%WcmY`NhVl5 zq8doJ8o9Pdp}32=H8JzNnto05ReCW6;X0fgcj29hTtncx75$T|GU0*mk-g>Dt*z?~M}58NTZu4LW<$ae05Y zL?rY3QIA6lxF-cZ@~js`XtL+P8y7i$I`jq~-8s+u=r6m8vwC+NA6+7i!KB>3pL$%h zE`qL%bk2xZzw#S1Z~s^*9g95V{6PxyqVY!dM=+^dM1-P9V8$8^0yv?ezi~gtafvl! z!}Kd`xN8lo5|#jmPDHcu%S1PZl8ePoFZbZolI^Xn=C!A|P*37m)F&n>x`9FczHZ#}(t1lX#Sr&-g(P4RZ+q?UqK#0ZvEo$BD>5$N&G_vVV;_2wvY zk<&7ThqtXJ^=?&TD)enTpmo!@(s{fxee3$(nOx+@9asIo7oZ4b5xvdv zAgt8nDT+oXRzRgJbKfg=P>rH@f-IB=QO~yx4mYx9VPRp7;o(8+LAAc>4ayP!_&vH2)5k#eDgF}*MXXi^B+v7s z-{>4{m@r@OyEvNf{uEa7NM}Mji_Q&ux6>=iVIsGuN_wS1=&0#k z=Hj&|ECK#CpHR%n$EDK5tXk%BEg9(WJ2gK#tG@rf+}(Y4=Cybcs#`RX&kS5`m~ZY5 zuWt+s-?P4T)T5&0XCq-UP`$2N57JKJlj?_s9&Kd0N`>5c{MLZA%^!I1a&nf0Y9ZV( z3cdQkwbl2s?GV}EKr9qr6+!{4uW0bcH(J{LdFCX7nf>ZnHLhEKENMr$ijHz)sCyqp zOH)WQ{0poBN*LkeLvaN-{o?Aa4-n4IY2Selghg85LxjCtFG=2U4%W&Ix7u)L z(20KhE(l2L3G{(izR|yV6S^*35XxVf*#LVc;sgYuj;urfZu3 zK>X(QG70>-8Aj1kM_fA5&pW~rV zD9~T^gh@?|U!*n+Nz+roNm|w->=#Dk4;M3wZw5I(RaZ^L+m|F@bsxxiUhqJDSogd! zXo%*j(0bNSu{WV2Ieer_yOFk`L z!ra`vg=>uz)Bphyqf=iXRAX==r1Yb=m__qYgf6A(FDEBW8Qvm7xqQdRn0TSim13fj zLiNg4A~3wyFw2vDg9-`axZXEEmrR!|HK5o9C{7Mt;(7XiT^zDBH1d^2yGRpNzo90V zMgOa{vIBDcEIsg;@yT@O-5IB54(~=x(}J(n)WzJscb&ogTnOfNNWVicvjiMY5{pq$ z9~~X3;^k|~+_w~vkqjxykGZ@#n8#GN-$}6QeTJ)&ZUZz)Alu&A$b2x^6~evv>ogn7 zvx1-ggvK1X@*t$ESVYZaSXi@f0tR!46FB&2g0P=uhUJ@+VCH`-KEKFI&}R&-2(Bmb zr1{922KP8FX>bT{l_M^vvU-P*fu;evGIF?zJ74+%E4-5OGnW>zJC-)FccR>v-#b=d zGa5B1#6LhIRkA2qDIaTC@%*t>ERu`Ei|)2aa}G#wfYwZPk?d=~6=1rR%B=WbA^3(K zXTGqa9jTWs6i^*zSq+@r9p!5eE7&^${dB>;T%?J5uAYYW*9leFDt{qG_qUYyFHn(f# zM6fUA3XtppZuDMHpg?DH+aD*9i^F-PdrxiPa(mwJZQ149ckCq)bf%sNYYHY5# z>V%W^M_t6AjaC^d)Ic0Dux;+fdG}{k*tysSC@w7PU zl-i~cqNEf#o&wyhJRVU0Ii1eJ|0A}F_WMrcwre{HmB`%nmiEyxm~$xNCHurw5N0A1|A&CE;PU(cF6-Q?R^#ls7bwhL}Jik<&UhyrNs?i z>W>Sx*cu_o{y@UY*|1Qp(VG<0}C@r&}w zhQRL*LlBp)4leBDj8n_p{!P_3hBqRiglZ5_Y|&-Wlx&Lm{2DsM%N%k7w))(7kbi|A z)E)Gq>j68y?HEg{AtNcv#*WA9Czj5&OzT0spM|f8VC-&3vFZXWa`D|iS=9z7-?<0s zItqIkd|a=I2<>~P8HdJ%kNA+E9-=H7DbTFJwqf7e)>a5k{WES)c66S%-7;G&_pv^5R_kP*E zD$Drt?h;%Pvj-VPb6Qakz^^T62p_kZnu$7qyF)3?i}a8nuKXni`h{0>U1|E7>JSLo zjFU)_H3&>rb~2{KJm2nfaSPlmE>G6|+h_K@8&Zr)ILCz$W0!#o7wzS(G5jp<<}O0G zf~#Wj;?(SKvDA@2!-tXM!^n#D{8YJ6hShq$INR^MeQ0=PL(CY~y9fftX?V=w*qoQs z%Av~30G*Q=z-c#$3;N8i!}pJ}5Q#q_Qrdv5r^5aEnO1#QY)=fIJm~Ik`nAN>gr;9K zcQ1c+!&Otg5`Sae)M;vz^2MC^SjSM5Y+-r}PFI+)XMA?4>bmS!NJ8tNDqJ1VG=J)_ z<{OrWot0hq8O(`AhnA9%Do6CC1lyD>uw&ypIRe-LV5xu_#25{*QaifG8AVq*wcg4e4<)gx4qzUgUtVXJ7k(PlK2Kxo$=uP@4HSyoQh1Yu<{%7rEg{Q?=fxTG); z7iHm&gO^*NzrULs+EXMH40-Aml-Bz1@Am5AzqmzGf!m{S=8nrLqs9BX9N?QNmH;xZ zo7roaHoYGsk|}G5AAi$pCLu(W5jL}NcN+k7$rQLVkR_(u-rfMhsbW5`zpeN=fR!b2 zhzJ$eToubmM(-o8y}$UVp;o2 zkwqz6k7OD$9PAWAcog8OJd_h~YI)*E{rFlAk6aF5_yjtAdcrtMKHQD_O6B~55Zvo8 zhpq%yIExF~!gBo8Ie3J!Wx|`Wna-;AA~_`~XuGaO($ta1*q7aQe%gtQ?e5=ww@CxJ{rym%E|=w}INLMk(S>pBTE_#81SJaJ!3{ z?Aji15h${JYYov5J%4hT+cvnXD6GIC#MO5?ydxG*==RPxr38}CfD39?8_pvFec_{G z_&#>bih48tBeopawL3KY8w5nJFNb&bFKK7Vc6VLr@A~aqz5G4CN$g!6bUhwsDdK`) z=G}aK|Mmfo*yMp6Uz_+Gw-Mrmpz>G+r;n|fRsUtCS(T3qJ?eSu_y{|qs8)%F^Y$@U zxln;zON3)yR&vpqFKIO>3x}z~P+wV4x^r^7trBT})l?}!r@F5eMHQ(gc~pnCIIy?m z>fK!|9zUE5`Zlz5_;!#88#$QhGJPp)K?a(YJir?-X_dh;_a$qp7NUL%{9D*&>SS>E z^xp&}p2M9BikJp&r`95qTTXw`ZOg|dWKIYztDSKXi&*hc(;>k|?BG)L+GDvDH+0o( z;v004LZttZ4ADD~ln1Fc=tlNhsy3v;cls_Bi1XAK(azJm(r1Q_=E0luKDXLBj_qPH zMEO5=cRLPg62YRo`=fVfIk)|;_ah^!NuZ?-j=wy`Rfm9QuxQ+fQ|9iNjd}40G{zxn zY|P881UvwX=6>eHs{9fmi_;=T|un3CpI$bmG`LO1%zcMw}g-A$C zi$qvpej-#S`y5=#4Q(=td5iiix4jDn)3_`3cPnITrks#KjxWE*&{6dPsKg%d55X&R z2OCta7{3B|CvwkRFm68WZzpN;26!L1-(G04G}vFfPb{T!ie+IG5>j7ea&w6He$eWlCG) zB3+1JsX}cU6-(GX&Npf*znlV@uZhM|ad$UoHs9s#LkDHp|BQ<9e$#?d_v{8&oaa+R zPL$U+@ct$TJ;_7xmTHj zTMg>J=+*PM^vQ7^GJ^FGf0g2S_W8=^UGyCVe(_wb4US7T9b&0t_K}WEu?7F3&2@FO z$@uB}2ZbN0+vS!txwhZ+@5=nEJG`p4dQ3P3YZ%g?yZ};T(wW0Pb7Ku#;kZzu*neIosJuge{hjn}>7MvsKY4+g zSXM>$p&~nN=FnMLwcx>m=&&-|mzT?7%Fkk4W1HR_0u##4y4uk%C4AhJ*%MegZ9SPf zaWFGMvV+5l+OzjzQQreoRY&gj%q@kI46Ue9xVZiRrtv-@-5vq^#N#l;kH8ZIfyXWA ztYV9k)ClrZ z-7sR8XOcq}AkYtGx5K-68a9ttV$vd5Wr&|nBAI+tL_|cpyJ!1G zO$p7)3U&4w>J5jj9lIfSoA(>X+hb1BhnOGOqVfSKmKvxfI2w!eaak-wpb`>*#kXl^ z;PJ}Z)b@_~Hf>Yyi^=LmOHh8ao%zeWPs@boM^=NS$8gm+y1%tz>mr=+n$ExhsFjX} zNG?|YPJ~Zw*A%3sqd4m%!t?@*eOpmhUbeb8QZru)pIO%(4u}YtC!sS$c#dqWtf)5> zPsE@g8%fTU@d+tOz=ixk3BQ5IP*o41UC9+(mHt`)#oAmr{%Tr%S11kvoAk(@s9%E@ zg&OX(azDWW1=Ko%pW($|4BSyQ?~}2cZVQ_Lb2db zT#9=s?g5IIVg(8mhvNR`dGEb5naP)Y$o%D;efD1Kw=n7)RpUg5C^X&jVhDMr-ozlv zZ>=ncTBoRWzqwh=6vAtgnm3rpDkTB63Z-PUu!u)li z^s#K9Jjhqq5Bvq@|C2Qfm*KUGEyzqS>ym;)=zqZ*F=Dh|x{Uic9NC9+lrV)Iyn7Os|?SAyl1b z%`Kv9IIFb){yp0kDU2gMOGZX7Wd(kK#Dc`z#E>=iJOBiK`_|bR%;{~`W?m_Au` zUR^BdM+nk9t)n_ zES~>aJe?=gxx~^m+%$&i?Gwx*utgUBr`|GLN9E16x(TQa!bg;gg9X z|A}nhAOv?$9XA^NBODGO%}p$fV?nRyKw_H2Qn3! z^Po+BRsBmF;g{_dDLzCDZ7lD-bY*LZH9g*-e=ZUtvCA@@$XeZjM?c2u%&gwvTp!Z4 z_C4s?+Q0q?VkVuVg^*+MFn8&-+o!yP*Qafr>E-hiU7N-8F{Boy=hhnNRJNe801%#q zZ|GrUXK~#4{c)GC*SHv|inB&QU#P+;b$PG8lb1h?@@WD85W>+s3MO$aAx*|wpsqD- z$FE?<;p~KaQqZ3PSu6<+-2v{NE#uMm8fbk(i?{a#r|1y|PP^;)%hJLGqN-O4JAR6ov`rWYfO zZ^Y3Q7lM@>vDzg}(1{@&!V!n@xj_bsx03YG&dXo$tRI}ndP9Ad=nCXjd@aYiCfW5> zfWioN6jaq5)=4~)NvD>=yvt+4hG4>vbT1%#$1RsUl%tm@moFH-!{@>PoPca!EQaAv z7g3}2S~Pv#0toynAzO1VVVKFpWQg+vhZ#}_pO{?aMc#|6A^pit>~pU7_v@XB%qo4* zBtnvHxm#&qjZ$w?eXMelTb}C~?@{;R1JCOiE5F;b&7qxT>xMIjn)!o^U)BwOJEvIX z$en@jWiWvHwJqR3k&%&C0UG$smIEoP#H=RBNFR}rB@ZY)C}P>ki{CC(Tl0v{M)k9f#f7t1II_q4B@cMb3oyjM;Uh5DT~@>~C2+{CK&LUXK~ zE|A6)VBsl6^BTwr=)nc@DaF#M*78NgC=irjoi9vKrctY|r(YT%J4)FE1` zaMT5et)3P{Rbid4Pw!JUqtzE^O30Jrg-QI>2mC6ugxDCt!B7rsdv#g8yx_VjUI;?*Dqx?^o4auO{cdW^@!OyrBw}=3hq_i@yZ3zhwnf`}Q6T@)GVqiFA%0D>Rth6jGV}e;mUMi(N zIk=Ye#$yXSRPa&ys&3j#BH{MKX#6aNQ0xoRBNfA-@diQ&w{pWR=6d)+#a_|=5?t`~ z4@p_wv5`D|c2evI8Gh5^eBxh)eyREPSHtkeh|fzEI7lrSCWpLu;f!G|=Y%r}#%x&8?+gvrYa1skb zHN+w&%&F{A`o-Isk(DTeptyLfB^%-pR<@JDHTL@DOm@TdOb*F!QWN40+(w(vuwVBiI(f zLp|pFS?2H$d5}6lNSCy2_U;z@2mje%cZVY%22zE7F21(|Pe6lcD+0e;tD!$siDMmO zg&WgBcD|H>OIUR zviQNX?;W~}y38s{OgBP0OC{bgjl_FiKo9QwL0Dl%yoD=7j2bY3OQ=)3pg!V(XN7@; zBwSSfJU3r3FYH408&3?4!E_MDpqkc&A-79;Jdo?D=04|Im=*;fBu?sNQs}^FMKyV zJsGxp!9Q<|oK8Kby1m`>y}gCI?ub-$z#z`l3T0GwgG7Orc-HmSuw%YGi6R2_UB>AsP;UOx=9IWv7Qcuh}8 zKZNuh^_9uw*G_~v5TU)!FU{Z)W1K}pouXwKXBz^Pz%y3(8f;j0n?`N6Ob!uFuG6)y zo}T5GQG%Di(~zC+V_x-Tejuatzh6!%!;}c~#x3IAccfM_W6y_+P$%U~8YF;*1!){K z((}tu^ZgePBgTA*z?c{m0^ghCYp%GEGen^MlEn*4byWryIV7XlB&KMcn&4$8^vME| z?zDG`SMh&ZfTuA;=t2)zKlwIC`bGF9q37l1^X-4xxi95!f)REqyn*6{1cq-{DcL&e zH~hZ)H_!emCosbwuOfKf;xLzu(({!5k2iFDQg3h$mhKUbeR0r$+!@F@aPDp_FlbMs zQaH|cN++xM=~IgyH!?*Aa|LSRk2i{!WLBSiPEH!wg4)yx4OuO5th5Z-7s(7riHv%} zvgL|F2%7G1KT~{{{JpC2{uCar32RwN$@m$i7}I#R&(T7&9=e#!YMJVGvo6MBNye(~ z4VQAP>Yyku*3Ka=G@tqVM?5a>mCOq=@191IZH4sZ=alleSnU@G~V=gxGktM((cmT8RF?wI4}uM zj8aLBWTu=C=$sheg|vx#F8$DHL*f7OhbJ{xIYozuq+fNMwupmcE2Zk!DQiR#5gSuhG{POLoukRYBMNIc+azGvD$Mt5+G@rYO7Xe5;1>JLg~tn4 zKq7T7P!9OT<~sjf-cBz1HDIpU^5sOAWqp82X@E}`;6g&VrlOTc8vdT|6cK#4dgS)i z?baX&It^mR4eOhme&VRx8FRxz9S)eSba~@Kv@PRVilj6AmHOBa{+l?Q-Dit_}zdwemvFhMG1}4j5EO|{COp| z1gJ>uSPBd8YwuyXhht4oO8-b#tH=R?QKnH^#;?#t}?w`23Y{oAA4bJxrD z`j9Ql)8q8Zs_^r_*F86HLfgnjj|2o#e#iK-vGaRUJkuNo4!_rk5UfAaEfOcL9_RyDMzM+t!DsYBV0wg4BPJ|eY+7l;H z{jQhMWz+Zmfzk@4|6z1>Y$8bA$%~Eh^++A`3H_=IX_-BXkA(Up_S$(hii^XZXABMo zDWr{M+zA#$tO8eSGJyT;vlqv46~yWdE6&2(i)*3=FuK_v@CjbaAtiTqhQI4G9qQqF z-C@nI9AE!~(>w0ooU92a2XK0SR>uXLpOqjSl4iCVK!cd2S3*#D{cSmBd0`9WWvw)dzDj{aSaSLNaOF?@5@%$}R zxn;V`^{e*+5yrhv=ZiQjJPINHJYKAk1wm-x`u7)e@WLGyV6Qo$$NKCwiu7w@B2goA zkT?irwbLTW0R#ogx-{>ev@C9)-+pv^wq4kKJgS+OQ;UaYeDLx4zClNRftase-aZjb zO;7cjd?4s6^UpUAJQh;tpl@xw`m6ye!GeB+>ycT@eE}$I4fMaOGpG=R%FbYh$9>@Q#=R>;mdUBKk3kY;pe4L4rml^WIJ?;Bp@iZpPFmC z-5)k_8TkCI=0lDF8O<%e0!0e1+uIz6?0gA-YY0sFBlf1XYjJL00u0Ohwk_6JZZyed zHT>Jov8ig*gnHp&S(0}hqf{xThbj&*&|U~vi9$fZkN3U6iBmP9E&&qqL&kDHd(GN& z96)x^RTJA>lHqBKsob(677AOQlvR$$@*t09{zXzrd>%fLW32p5)C3ng`ikA5LzBH@ zeUcKO+_p=Lw$|2dQeA<=*VwRI+MsNuQhW?~uZB9gQ4`0e7@4n$2(E)0B7EL#_Le18OSy%r#xm)~X$o!7*s1Nh!w;*0zBGewn^1`E8B#N-HQK-kk+d zZ_Yfuev<+C@vg=q*e1ht#L%V(OEe1|Uv1*7zA8F(@s2Uc9NWP^^q={(3hvH`4 z5;>lkOmNnH1IHo^(CiX>XXI}(nTC89$)hPc|L$uRGcVNQ%M7*8)>)@?qq&w=Xabts= z9bv(eD;!+F1NUk+yCq5NZ$YEzsz5ct=Q8mBOD|J=)Z2s6&1Xf7&FO zhvHb=*~MRT2UoS%!{J81EA@5Q<;E2C^bUG!m!BcY8@|*drQF<9#ZDwq*@Zg>smrq& z{(xcGTRDYvb|$7(H8j1eW_T$HwjwS=j0DvWqAZB0M_uzNYP2sYLm zMaHsK^pj7+3FjtCX=)NzaHKrQ?0Hn06MX7^c|66Q5W#o(&b(aogK3%#eqBWL_w;mn z!h9OWu3nQ!PJ1{sl$X%@b8_-~nk*XkhFLD~P`v;IQIrLupF7j?)U?B*43+K83W>|e zA=7NdGhYTHuw7&SW~%>o&;^>98Rs?bC{ySZ4uB?*$xgnPLwHdQ13loIHC@MRhg#$v z_10Qwu9W*`VN@xb)g?4b1c73BKMpbG+SDQEv`a%zxn!`d6UaT zuf_NRPcZ`L(iY5LyVy7MYxcg4MMM^*{vF8egV$eW#)q;FjNt|-FHi1sgS&6PI|z@z zmrF6l6}f}oHuP~d2dj&?bwk~1c2|WRgwGdL!|<+uD{Wc7>&e0NS5Wreq)%5f^J3T| zKglVqCdpF~#K-Zm#kDoZgfmfoma*l|T_k^ZIa{HcgUoO#0* zxpic!pOYZ8IU@+aT@0g8G;Gn_hg-qa32OF!>kMmrV3PK^D^btNlWE!#U%kw-bW$WB zAY~kmPtFnDab6WdY^{3Yp~;(Zt%47@W|ze(Omb(y-}((NOyX+7M|T}_Sam()R8ou) zU;?ZE3{+hJ3tu!F-OiF}mKA2a8ZNRm9`?9g(WF@-NsTvnCb{* zOJ#3iQ(6+iR`o{3KWeFpQc!5AsD~%Cl{)BnCSVanrbgS-tYbT-p2T|Dza539WvP6i zj?oNks&{WeW(!^ineC+F;Hk|wH;o{`N<5c5T3Z?UFj z#gq88e*itLVOAyEu(ff@%)q8dVvfh^JIT65eK!0Dn6O?S_3 z({C2SOGgit=H~(&b6tEkJEZev9%ON{07m-8q&IYzG$6d?BuWvQw2^XuCgNMo8WM`F z+z17UIe`?H+Tte?l(|U9Blroq(b%t}E{Cre<0qoWqG7>Bsoz!j-?Nzc-p~e5z1fmx zxYq#k3-rdTz^Erpi}UNIVJalO5V0hsG$xfTmG$Wzq{*K}lV2ZqZ17Kt#$d(@Fk`(e z2a0jTg_;}|(451L^`Jzo)ze`fxr>$dPvRr7FW7aD%u-&)?}c5Z1%pV6Il?%pzoFrd z7sbf7gO&p2tMj%+zMju=!S&N5VD?=!3N``;+zR?YbttI0e3{ql$1TnoL1FqAsXw^s zV9R8HZP>divp^u1JiCH1NOcCRAJyMAsR63j-PENAabf$jB*a5m8`$D7W}bH;VzikK zRSF4~k~o^+)LB#guy&Nco)<%F8U9IyU?&>Pps{fih3W&Ns{Ul$e=%4S{LJjtpR~0> zBFx_pg#^m_Wy}#Pn_qJ%vDZsdJmDz1-YDj>4cjA~xR$)SSRGFGD9ESiZyW{&12pKK6%9w!_af1N}59FzSk(m`d@c9uZLYs%0mf z`YjIMLpxQaBQlj^9{C_?^pI7$flnEa2%bCY$X zcPYwmb2KOq1hp0u6$CulB1NfhB>&N#n$E@&q4F1R+^UblarUm-20}xlA9U(++U*%p zoq{WEyH)_3^ST#r@fNsT8S!QOGQj9R zg!gj6E3f*PneEkS8H`3t$v96l_G$CzD3LF;5=;GDx(ONCPKnkQn!z3* z0VJvW8tRNw$8>I-8hZ~;rGU~*;%VMH2zc2r%@4^nk59xIY&w)zqaPvpDi8%}q?MSs ztDZSh44fn_GzsTut1kFE78k#3%~@;Oo2F2oll&fa^UP^#C6|j4yK7qus;fW$R zr+<#%DAk(`M%J%(J#+`&;E%i)XihFf8Q+Y=Udx)7a|oPAJkiZRG1XR}HAVs6giF7oB@=1?S}IUU@j#QCRI@{Pd*YFa+W z)sWmp@RNUsoXRmNGs1q}fiU}sBq2OjQ_CmL=GhgUfxEb7#jq6Z7=gJ)E`KlM|79@?C3ak5tQN@K>I##Ac#1jM^b97}slGawTG<3^G3Z@8u{R)tT;pky z{q$W-8w?fyayxKd9R5Bx3bic|1gRJe$Y2r(JdMYA8E?4XTI?~65`ShLWZ-&A8w;th zd`e~}M5zsKu{Czlsj{v;Ccq3Lug6)fDy}TB4`cf$FD|GYz;e*$y`DNP!z&3=`wrD* zHX+@wV*c#7aM9G{pY79S2C`peDS-a{4QbI6KIAk+!#%wj8E|l2H$p>>(q6u{qmkX1 z*PzG?W|}PlcCO>Ri^aKdVrOO?@re2uyL=$hj-Fzj(zpv^=vTfc0T@&nuvIc1;QMqf zz2VTqd9o_x*P|9wu{r5F_Rk@2`vGKIXDM!6CmY+c{JWNQ=Pu@7QiZo|6yvB;%bmi| z-`-%r(;iwItPEsbaLv%tAmnDo8BI-j^>{5?*JN74E6#6$s~>Gv0nS!FEVA*PB`rHA zJKaKW3C>@)m0=Et7Qoz+gmc#3@()`vovM7UVrH`!@_diRT7eaf)vYnBUzxj^(&9*W z08On(vwo|T2yu0#LLa$Is4N{&^eZo^V7WN=ipQE!t$tC`BQSm7W-xj8g+W1;? zm@r-WiIC|75Sk4l0NW5&GWBB^fCNnf&ru02q|5i<5Bj7$9uDezWMU=1$`hh-*V+jJIz?Hj0A%Y2r2*q|VXEx=Mg3{Y zGwG)D-S}4s1tbF5C)~Pn>|mUV@GEjBq?Dxndpx*5IIsxaS9|#*zHx_$`c0V*IeXqd z%z16AqN-(QVny9)_EYSZ58w79+Kbf7H=EtJTfQ^w`G|(#a7d`%e?IHm<)*!^wdRW$)1#q>cCHg8dV1N+H;!NJbR&t_gvx)5LjwtD)SbK^Vuc< z#H1&{H8xiAOYLt2o5(U3NT}bXe~xRl+NUX2=@OPQ88B-_NBh9{h0`Zh-E3P$c1Ph~ zpoJh~t{dhwt^F#iiV0tsE7gSkNwiSlJe5F-atF6?+28j|Xr#nP}9$ zc3F7nfSYtq$QeX4)N&Hxd+Uq|wd18sl!m_h7QaPF<;4`-7w6r9ALE}crKb_K%?hZFYl8<{mrR6nYFn;wK5*7kpl?53=|7-(qx3>nqSn zhj;}d+l2n5n5;#5XH>CLD)w=A=)i_(LL4mEuqh$=!IPBW@$xz?zPf* zp*wdrtsc9;WLE$kZfzjcK0rD%j*bqzrX+9zsJq4QyKzH&sbJR ziYf)Pj1W&Uhsgx8oXoZM!&=!j)ksDF%d5^cIIqDqAtMq489+8SU5H=ci*hK3fs|0w z23$QK*0;(DfB2L(yP==^_uNZ_aka&W}Vo_=1r$y2BvOd@FecYT3rs z-r72z)h*z$77==xKV-pO_$gML!W;y>z2U)_aXPd^K*3*e1(T@K!TC154uM$!ogks<~ZtcgDKy!=KC zwfuJ0ZfIFVaVtl8@h&7@zJ%T;U&qQbxy0OG)rCG8hU^&9OTSxn4G&vsh-}}Z>*WIg z+Oj84x2Gq}rg@9~Zc6er=Md(@y1E;fj;bWBRtx@V=vkI=4Q1E}_|ky(2moY?n0q^U z^zR>a22{BwLTBPrbp*zzh^``)V?m8z?cf>CRN4kd+fw5%B}IQF-mKKRwyhv+p5+LZ zg#SMfbXELRj*#M7C@Fe$5-4uE%78E16u}sZ6x2{3z#@Zk&=>+Nez)hfx_Br`3seR4 zC-$3#Sx|JyuGVek(b7gS1zGE-Fx~tGG*&_N*$C()@tTSZxLfe$y>PV@OGrq!(p@zn z2pIMF=F>6Cc^$`Wa08o@6~5d@A{G>@4*hm8JO|NVl&HSYaY0)*42ngyzGF2lZ(p2P=r>UxEi_^*AZ^f8VeL+$% zauk}wia7JGNdLUMgB>(!mA@(*NszF+`_@!hpewLLR9ZUp`SEUY@|CTtFeBjAfV)^; zmN8?NGWv;lBbieT{h%-xaM6G(*5NNYlCf$^$q<#SF;j%2i!VX^Ulb@Uky8I$h_oI} z%&XcQ;(R_^Zj&&-fr(GpxNn+>(CZ-5W$McE{MgQHSK1!*BW7Rwo_ccK6=ELF{dzT= zttM-2O7T-|LA;=}He8@AN|}lBL|H)IZZs4@aRi^Tg39lw4;*-|5#3zBHC<%=o8nn{!CZLRyXBWMJd__`+~ zJotH4aG16zcTI5L-FzFbizne71NRCmNbkr>s_r#$ojZGWekLT}A$@O}q0oXi(CfD& zp0oby5TMg6XaR+aM5o>REXu!i_bk>WWy8(5EsSbyn3xf0NgGVrE@~+mkfm93) zrwi$gGnf$p6oX7Dw0Xz}of3&2a*2&dWDd0sDd5A2cV!zFdprDX`T}_smhDf!BMFj5 zzHn&P>n$KaMA}8Y(RvFh2AvqP6<%wFEyMkY5?(s0T&=w~k8pnc12SQ@aoRfovv?#=4V5^ZEiA zBn=pzj7=!hF!U=jQ#S@++He)gJJtRCPmtE;oSYnRNgM=H%K<-grJwEyoR5OxvUo9+ zoopDgpp1s?*JY^Y?oN#<2%&qMXCpJ<*Bb+@^d-etga~d#q{Ry~=bYcVVyL<{a6xKY zisoCnO4A_2xw-BJP_plN?~Ry>?a&w#<&2u;3Tk@az#J;wR*RB`?#@tn-h7_S`^;qycw|lKpe{ipZ%1Y<93zX@N&SQ_iHHj}Oagb*8CPjz_!a zo~F~{uZZI5hQk_vfh4sY;n&QH---N*0)KNW1Xp!=&Whm4)9l)kE%47b=s9r%^}MJL z1-ZQiOiYJ8u(phXD5^Rf*j-?C`4*WRX(AP+k-vb!?pBjLJ=140{!A?X%^!asSfiQL z!jfJ4)OC8uEdNgn0Hj){35Kh)xlF-9J<1WE58A|uCpc6`e-!6(RkeRH1}Qi#;F$n_ zH6p42m9j}6fwrBQfmq>(YOqcAEAvf%bNJeHcSnLjVHd=wRs7-i6RU|Av;W+x+7jPY z57U>>447#2eQ^$qgNh5rR{>Pk*Dvk8NPUdhQPKLsG*%en|JwblFS2_oZyVMvLO@#i zl`_!*9A)cU}}93F$$ay=`}HmR}LxE$s2A0X?)AV_S7 zw%qthe*QO%OJE?i1GHZ+L9wK~2`f<14-mbd%a2@3FwmZx1go_DOSjK4>ETQE%J)D~ zsy3Y;7U4wcUNnnafk7;ejA|!00AT+c`JIJbfiRl5r82$PO0f^{=Oi;Tlfc~nIA`OY z<bPUUa4om{| zbE2U)_a5Ye>fMb8h*PF~yI1$R_6tl{SnK@1q+bML|<1=jKxXidK^d=v=8al-2S(Bcc{U#|3 zFoPxRWTF?9X$#A=r50XU%iu@I3G|pHMvi0Rt{)@;Zf_C&J^gZjSf;T8-wypLZA78^ z_$9b`v2)pVWb*82d12qH|K*cmOH!aBy*Z98hlo3M0s+3Cjg)xG*Y5PRwEVw1W$V*} zecgvsYvG^T7AEt`S22=r`9sgS@=G(W^6! zb-DKf-f9q6qfk25dVmSj!R-5wN4e0}ZAkVWV&J54g{SX*VKWPksxW5M6ll)XfiQ`C zEP&sx91}d95rpn=T72*5Sa($vp1;ISYgUe<2il|#glMg8$J$YnUz`$wSKkC9vFN!#X<7ZX%GeRTyfH;fAvR@9Lmb6qI=o+h2?@6+ zjLpH?p-gCTtA>i)PA!SNR|=`xN)=TmUiqx5I7%es<+?Km&M6EG>YckR+L(l0G4xA9 zDMZZ;0^8mviXaT9uN=Txc$VAHFcm<==64I~o8Sa|lo3=+GzxzcG9Wkul0jKrK_;X? zs8(zUm-jqLaWC|ld}LctV~$nod92ljood-Ymoy9H3W1y8NJ&zF(!{&6 z$TP{e+ZP7X)@O$H1-)mnA`0oJ1P{sh|C}VSUGkYdEOt197f;L%EJknc_Lv3QBqK^L z^`c}>)L%T3DPqE-qevxFCmJn(7^Gl*E(R2#t5QEsJ!#5DNIYX(V=51Zx7qCSGm43b zs&Us+ma0wD6e|m(fbGtnWQ|1L%r(o5Q^;c9LoIvv8CX+TruW7MBHQg@Nr5GbPd&r~bxlHy zv#nmsip9ng{hC9YK%45iYB>BN*fcMO08(swNKa1;4Xq)PW<6sEJSc`^2{xQuJZ?M$ z94Qeo6RzCreiw}8bLUeGH=inJb zM(ne=PJaE-`cCKOxkPe}Tv++=LL|fQT(|&9|NCaG_OuheG*u9!45%)FKqIw@)8c%} zvZ8>_60#tghwI-+*u{7f{OfWBj*5k2b0)+yPrh%QHna#37dil27qc6cls|x!D<=d2 zd^t9|K@tjn?&Xw;hV36e1p35y-QXG4x;TLP`pfTZ$jTiYT>w_Lu9Jnb)6YNo`Q)4B z#`+Ui-wk5vssi}j@SL7ILzu7NpYnS^pr}Tdp=*`k8_kj=rKpNl+fGk^2mD%B9370n zgkmNR`k3;4J;xc6vnKUavYAAQ3sjpg4ucr6AoE_tGF%tvB?ze{L87{l z-GjB6{t*+`!kte(*;xLQLy_p!XI4?=VXomz3B3GmDopB=oH*qHt$;QB5J_4`$ORW= z1rpW^lx_Zshp~KdvW9=b7lN-%&c!J#QU@)}$`hP3Ghy4+YZo)S_3=Ro^Mx>(O(qt9 z-QC?GTmjRMi*8Sg=j{cV+xvoM?^dh5-JMGRF8c@ny43E7=1xR0ZI;j^Y1 zMkEC20?&_NzQC!Pzu$3ve}s0exf)YhM!qAhhiGUo45`SS@GT$x=@_>tNw7eonXU4o zx75AdBAX%=!t`%m|GBYLkhzkNpc6VyE=8Q1rw`;UZCO#2&85NDO0<@Rih(&Ek&P+K zdmN;Z#R?>7p&!^dzuv!-w+cY9ptz)ZDp12w!zCdn5-6g^p~O&LI5{O?_4Du@VN`Hx z1_SzTC`jNWw2B`^Ix0Z%(AYRa!up{^m@M7a4C`qUaZq&qxJ>GAS8uk9=A)a3?epI! z-W7<2Cts8Gk7Hj-8l@i$nXYBAmy{-%RsGQNFxEt~TprEXNls5szbjE>F*TBBbtmeF zW7F~$-?2Iv0wM9Y^7owvU%q{&`u$p_Xc7{1_B$N`QVu2)rN-a59Tv{MgHS{NBG&Q& z-ud?$_zZkaBd5|FCN+0gS69{=S&Uqb1L`Lyo0CBmq_cCoul_!du|lA;%l-Ok#?9Jg z9cmV~B1uYrd?-B$#;i#_b2NX`k7XnKeECB*HcmUkV(;oHmM39C(RARDA6Vofq++U(9I8? ztU_PbpEO^^YZJx2bpr4uQhl&>v| z(pD9tb22kK*%@`lml1r=UA-d#>mMejLhb#4{(4z&S3cI0oQQRX;Cm?EdPx90))Eok zz?Q%69)0j=rUo!g(3hTYtdip_g zlCB@!XBm0iW*FsEF(vkD|C%mT0l97Wfc~Hn2PFuYB711e9c3fH&`COZwN0HXS=}yL z9Y(JKSf}T7^!Ii<%T@?=*u0}L07%(hhWgXAZw4hNMc75>po5Ze#>NVAS&?1J z`3h;X-KTRPv#y#>RhsCmA?(C5pTJ0tIw=Q`4#q?6S;@3+jo;1eFP|pU3ajJ5n>Am? z#`%a^&4423b;ngG6sGrJhm^%l^(LBqpU{lO#&PVOm>QlQ-7e8T-sSCsA#g(1K-=@i<>D^>k2OCl&gf z3(J=ZR8=pvH&VY~Dn@h0$@cUMT&zeelCxv_dxfHGtd|3`#Q~VVH4*}y;i))rVy9^i zwgrZa@Cl%qypk{{bi^sFwNcR`PQlZSL172H*@D0%?>AN>l=aXRrB9On;9(jk2sfog z=qrLcR|JhCn#&uVcWuLMHDRl-<7`SCks~H01;6h}uO8i~=&2s_o3N-i4;Zb?W(=ja z*M7u;89O~)S-f2Rw^vu)|2-eDcxVYdyPf&`|G%50Z<@-t_uE1r+CsO5L*BQo8971L zs3x2a`07#z-VIG*p}z0*mIUw#-^|nc90FE60z>wW#xUvX4T=UyBKn~YQvRk)l`UkT zQ)&MXdq+XkF$k5!6{IJY5m$CO>e}~mnuvMl%MG2~pw&D*G+{tuaxcl%Wc}38MzeWKsLTe8 zcdWH`UGpucTE`0LEh579mrF=RG@TV4^!+;dyIAq=MZR-It|A*u>24SA3nt}&#}W8b z#JcN>xVKl$Y2$+rPa(z`?!H@3A#Rh-=B+sziqFrdh|lBo>EqnStwn~d|Ls|~NuLCh z8WH-L+-}hQA8cEbrlO>gZS2-&f0){ucOFwiU_c@IPe&RUItFkYKjNPwEwOpupnjli zv(!6S;miH}{ma1fLnBuoL!vcX!JY%f zTVY{gP{-O4sFbfmxG6Vz?%XfYT*$)vsWH5h7k6|4jO)R_j|jD>DOPh@@jyb*!M1rD zD}4LhV^1B~wQ+0)MO+aCowAPQR29f8vUnzM#ZCPmRJkaUOad}oF&=V_PT%x#`^lHI z*mR~krSr4EC9(8XAKC$PRB7Ejp{+=LEW4w603!AerYPI%>L5n@Y!n}h@AS5j~#ywdGV6b`*b|mP) zDoDIxmFR>zqt8u7$1h+VdpN>GT0 zDE^gr=u_U3g>-D2IVfJ$={PfFKU3<3So%Elao5fKo%v&4&jqf8I7{ z=R3ofM@*@^u{S}RxS{u~7I#h3PoGbId}PubP4uWirHUgTw&#V7;mNz$=||6;^-=nZ z<<*;#8`KW1!Gz#3lNfxA2y?NWo%lt@{zJ}Txmw^$_BufV+m|V7yIxa&ljpKqawqkVsvKwL}Ii%DV~1y4#`diG~#YNxLL^ zsi<{G!B0#B(d__#u;Kk&^&!Upk~+wzlvW_seGf{6uEr8Q-V^<(TfV_$HBRrN1rBpB zWT29gCs2AXY0gt26R+$iW1Dm)9#6~4<;02js}srzKE`xppB6rSRNqfrM+bJt3o`8C z-DCux5_7M1&l9c)ge2szWz5$!Ko{jE;bvK}CO~2;LCYoB8X0}fJ|Gv)Y08@=OtHbUhr7xGa_s`O$pFfXklU}?{+WwZi>e9BR z&poou$FJ|@fV-4BNgyozkn?nPCFG&iFb?lsH@_8}{%Loz(Ip|hL7KkDp_MQ3>Tqap zf`9sA7CuQ85xeKVp662Te{d8sE7srt%;rSnp81+SiB$8OG8zYw^M^N{u#oA3%+CC- z*{IPj!L*!*pzN7UW4%m=q=k0uW`ihpCV^B`wPT4l%CWa&(=UH4x~~=mwLoHeQW|r! z5bIygt(3A%?O!eNVda$omzX}X$hU~7^VKp9$s0TM5{0QLpXq$bgcT_^_IR<1Af3Q( zEBW2eDal+e9i0J5c5Jg4wYvrfP_>%HEvv!5Rwvvcy=l*iFqR5#&1uVd4&I@8e!f_g{u_!;`ky2b{gGRT#E zxY(BqfiVE(YQ~*(*@>IIPukmN9x<@7i$59{;L+@;Lq1lV>q!hkjdg)1g=&lNSA^7nS?Q1iC|!mG!B!YAhL~q1 zy0dkyZJX%J;0RsNLtW2WgKU2rIecsKel$-9AsmyCV9e`8uCzb4a{ndNb}O$oqdv^c zCQ?}>eC7QI!J0%o z|Di|syExF-`K5G^aJ%pK3w6)QFSm3B1qGoGwV@XX?)KAG=shkXYo6|z;N^)``VRGF zdE=>TI$tWGaDhM31rN11;aRx&#3d2@w+7T#tf?q96 z8pS$DQ7VQ*;mlHclCk=)36KOo?=o=Z=H{2k*35Uv6WmNf$g#^I{YcyjV`j!Bsz!#< zL;#aEpt?RV>W5eF{A)h!Bpyh_4-*gF`-4{g9*y11L>cd7LUh*god|a1T;iNB)30`^ zF&fbAFj{F%)d_z$h1kK><6I+5_mMa}_~>qaWkECy3|X(=+Y@=#2A%X^SrfzHcqyhb zIpWQcMgv!uCsI5Vzkr|TR{1@t-@+W$jRH{UaBV>V7taB{p+mM~KrPJF*;m~6COh8x?2ONml ziUo1D(JiU!Y`aCg;{L36xgmOD+?l8JO@ZCEZG~1#z;WhYAP@F5&Y<6?M*4?K9lOET zPQM31HVfHAxMjEAynJ9skMf9#RYJV;?-H6bB=GzgM);rqYCZl%6p)A*MvDCb?X@rN z*x%ULbc)CaxdrkxKRdp118Syi8#z_lmq_R1BNEGmdh) z^3#}SgJz`O*L-=zl$IWkbL~QgnhBX^!jg&S6xQMy(_QE9k~R$uYSn-ex0aO#g^hPYA7VJDv$4> zZ*6V$_Ws#mgOU)bUd&WDQa+M=SV=oNQkbNcEqwJ0>unp#S~qnl;Cru@{SX6m)$oe= zW!Zi(1(MIhsSj$p+!t4ATUirHh$J(L1rzh-2#f2`Vpi>DJDX)jx`F)Y52-(`$>AAJ zx%;jy?e%Um5FKuMDT2zdF6+IYnzFW;8$MhD0-rOXqS>Q3yUdA7E0u{`UD#07OneRD z)rdePvR76NaAdh9L)kyJq3kB}4b8OXqx*aDJ%FF~t8daF;X($nYK*)=Zn-hY^rS*r z>>}^W=G9pRkt$t!oLPByXTxPo_%4bfI91->;M8s*qa?{~N;U`ig9@FvWw;vkKy-9S z{9ODv@idj!IjE>bWkiWCSG8dJTVe{#T5OuzANCV$h4^}M%S}}H_=BQfX3~!k&EJK5 zz;X`!n<5~@IA;KdbRZ-tUfJ=*cmu@*J{t=?6iq9>3ke&$KsOMS9^ul4QX9BEjSe%S z2@86<>+k>S_%?WbD#ph4VTUWM1s-SYa_qh8yKU@$^iy@}@?iC=XvKepIwl$AbxAf) zkm-7tqt{gCXqG42uFsn9P5V8|YI}RTJ&0cW@Guip)zNW=;5B|873ttLX{z$-uxE~! znc@SayHTtzPCdoWM8XzoBWPUr(t#9r5Z4k02i9XFyUH!DM{kKr?Hg>lN2qLFYpoqS zeSa2FvC!NXAYA)#@>SXyP498tQBAmm!KY7tb8*j2og{%mg;(!(NG`p824%Tqzg1$BUyLs6o9Z&&X)xp}1yeSUb;_c;U{J|vW>L?ReL zDY-|TfzPdk8~{^&;+cEw&|_vsm6wz`emFn~2O@!zM*6f}&M!X9lrV4z@e2RI5wbk~ zE&|C`D=Iv{GHe^Bw!lRM4pdWHV7eJ*>QQh7xpBhvW{&eYdg(H-L?I1HthRye1!?>c z)IxCKuaeC6??Ms9yPQFKV9}RxnXoS}{YIPTPBU#s-w=2Nq0}d+IOH?f25KzI1|kjh zhv7~J5;mV|o?$R?eEAN6@Y^3g<+2s&LNc&is6?pvLDAehS&$HE5Wl=i2IxEfQj&Hr zBggmKqlH>oITu>YyfGS`A@!VynjJ~gq#B8sEPV)nR|_1ei$q~IB+qitAs2?(-Xec) zBTSXjbt}CkYavTea@aCL0g_aaEEp%$D8C5y&{2~f4jDZCX@*iL$t(?0yqu{NzZF}% z5c9v@^>1ixudS=Q1We?AA5tB%FVxZ=w78qq5^GJS6J>gpe$nFq+gL5{+{Y_kPkv9w z)*eX!XKH{w-3x9tRD(f@HX>v}X~iOW0ZJda2N;aRwvsfL2#LP@O~@`G)c{?1EJR)_ zP0$rJ*kl@2#s&P`2X}EqHOqXe-e>jm5&yt0e`cv)un@3<(1%$4T8aL_wb*jfF ze_>v>)Szn56OdKI66ZE07iTLg?ePX}?G+*#1%>V#f%FTZcTwDF5fs~5s7XT7XXl(o z35yGg@fVTb`AX9@OaxdOILAn%_?Eix6uGXKxmXua#aFe50cE;)#R>Y%Nzqmns+WVh zhqpONt%c(W1oEaftjQxaTVx^GAF|dAMbA1AD!`5KHnqUCHHz{G@;{Z=t-s)TtBaaX z!952_Q-R5D!H%@Ajd*6J-(k5#jT8)eZy>SQ^OlrGri1cq^r0Oak*|%e;H5df*9#4* zYW{jcPF!@nWUVsNpIx*dR~Dj=N4w$@6dz7~hkZ+TKaQCAnRdjwDIYH`{$~pQpDDV& zzP|lbcz!w|BbKe2N#wyLmCJG9J(hd4sCrdJvD=tXv2;>aRBm;Xa7VsRN$1VQP^=X# zTRM6^`$vdj=0bsu@OxCrfU|kD^#$dZ1i4DsQqyA~YTU4Pqs|KWO1s#P>eh+0p9cd% z;HPWBOyY1^ex64A;c1QQC?5ELR6Qb+cmkHFbge54;wmj2QUK3$XO+-#1*5_OP8b&` z99|9PXBc?Isq0K2T_*g=gGM5Mk|$g#(l!MN?Pk@GoytZNkMM==g*n(@LLyj|U|rbV zjbj6!p+CvITCnk+k%8+2zM zD#aXH=l_n3sp~Wt>mN=A6f@w_Z*74nkOD;q;v~8zmz2OuL=@jZ#ATPE%^f77)AT+g zLqhZPwX`JfFkD5O0*R6bC#)yt%5BbDrD$Y%*~d_>@vD2TSa1N8c;P}FUvPIh%2y&z z8vAFvhT03Ts;1!;T$kjrmHlQg08w^A{S8DHikVAgSrTqR;8Buj#%GVtRjcQ2E083~ zfg)`VTaMvf+^WWmAvBl!KNo;B9Oa_UCNe1~d>Zwr>)d$>b``_MtMpE`^dN09%cbHF zGXP?5XE%(ffpRGdp=_Yw`J7GOy8IXMhxbz0=f?1+q9R-3%f{k#!{nEz5ya2T@~_bh z_&i+f49WHcxmZRhe~A`j3}90w#u>?!qsY8uZYWz>R*$Yj&17lul3g+Mpfa0`Y1p7e zO>;H3gg|3Q^_QEKo9KRT?vM2Hl2Licy!ml&ZA zdXhMtI5Pf@G7^C#ne>^V0yb_fCSasAq+)w5$jnQ3BS}WB?;F$aw~!0g`IBy189ZlS z-Xh7!VfNYLr=hsGH)@+*50-sTyMyL4Y<+R2k()MV2vflij1bjdj898Xc`-aUmrz$~ zsd$7J{#__ED}hlz#HRjw2O{w2(<{`0g@lo#qTb z4DqXMZ1KV!bRHdXz1voJ31pP8l){DGk94P0WTH2frcURkrjhBxl}2@_y=M}Qz2U|; zcaMIfw?Gg3Yfb!Nync?l^C^^SkGeD*{@L-g?cYWepb`{0^_hyW``~jiZKE>iQaQ8x z7rcHYTx|Jz`VYlb74cGb-3Sd%11Bd zF-z&0Bdk%HOHg^meS3G;Dak|DQ*^Nkdrpt z{u2f{h^v=enu{dJ%pMFfphE>~!!jdxs;Srt8|>Soi%WI;tPQiaKO0f8fh3h*43E#P zfwMAc>r`zsKIiJT)pYN^3NEHI1JvZsJZKEJQk)FoeYarDb;E1fw=7wOgwm{X-|yJp z#=^Dzlv0koq;ITX8^pSjetQm40vx>vbwXzl0;amz!w%ZR^ClN9oXW~QG5V~H$`u-k zNtrf57v;PT%a)chAVB$z4?#`Ck0wVd8A%Ti4I20(rJ(rOUBn^uUP0_Q{EZ}(V%d78 zo-BkjI9A45x#LRS-6>nO_5~~{hBXuf#WaHke&xxq;Kq-JfJX9;ZiWy-Ma|94r4=oJ zU7%x&ZBEcd;2*fT&Z<+7s@3R^W1QW_hQ^M&`pUg1&M`ki67klnTCd;X9J5U8iSV&AhO!sd1sHgA}y_guizIGL+iIbPOGncr& zoAX~Xe)!!<9&^3e@ah*-*ihFXI&kE(w_R(6EtjJG%gZn-s?2u3PMl*dTo+qsLfXJo z4|V-RY^6F8;g(9w@V)*i^yz}$m&B$!7U9yuQZjtdkMW#TYOkUwh?6r|Y9!Oe;onLk zUIg^1rw49{W~eL=NNJmc*|5weGFlr(<%GmVH4h&MWgmt!ZC@AxjGV^wPGlp@#HC4% z>hQr6!uf_b814extSw8EhppE7%l*`Y_C46bJt(OBmKznVUv{vQudw^7@s~Fds_%te z=Ta4fj0edn(QmoH4n#yK5h`4nCwBm?FV zSA>$D`6{2s&+a1_f78LaXMdPivLh^=4qv^=*iNGBSKEu6-j_p^e{Hp$^PE@gRZ-n^ z=%3{)hqEDbhYrwxPYlRXT3flPS?m&EbHR)!HyaY-$Du=Y=WQFxUg#-J zfm&^cVXkVqrq~>zHycKj^Cu3kl1Y%}H@-jj3dM zz*xVIR_LeE*7q{d$R+7O+W zL3^e@?^hWU!j(ouS2a}Ik9y4f--iyw%R$h}R1wiCZk?%1TS&S;E`P#}PE)f{xpy0; zI)!<$=O2Z$=*&RD+SGuNSbb0lC@{_H``1QZr?X=PsFiOiv9b^W%P=f7v~Q~j^^PQ4 zms{g)OaQ`9h(XBPST10o-v8uc60)_U{+3=?3cJO8euj5NbS01MOp3{c4we;+eE_d9 z%7!ri`~r?2ICCe441Pmj3GZ@uch?$4Ppd6}tt5;%0>LoBvc2N_c1sO&he-3IqiPU{ zm0FIt>)!h6C?`F1rumkh05{ZEMm>le-lF4wbK`Rpu{rm{)AOn}=TW7yq7>fo=Z>iN z62t#*{Bd?R%4-Z6>=M;*3pwZgRxhPRes-EDVcsP<%U9O(H|pkQWW@hq6NfYO4+1;Q zsvULQqz5I(wpRPWDLl@iKx|I5(SkDc=LLfIy)Ey zLNk}0T+q(nE6E}$h7IYyU>7RXN2O-^hWtsIJ_?x-g4i5nQi6{+e}7dtQp8S=$~bIq z#-JokEX&{f4`3jRKmF5LT!tmdq6SJl?tfVGe||hEqF`)Y!y>YT9AJ}Fl^S-F2#W8! zmIuPEs*uSU+Ab&GH?H}$;)x>=F@*8t!eOK{Op%!KA4%hq=}40~Wcjky+I#NK8IApp zUdOdR-mg9ZZd;5Jm!q_0heL>y&gZAy9RCworh~ZqQKVf(^G?oVt+C(UpRmSv0xoJ+ zW7%TB>$^GL4!*wa94|d4q)*h4xp?uHDlJ#$x}HN=&6-VE z>;A@{9tBb|(#*jEdwtn;`~nl&S8U5~J-65M_7_~h$pg?R6e{jZihR@~-H z1QGc`-OCm{Hj8y_KI;uj4peap7Z(?mosVw70D**ygsRQIn?D@3k?{$-=O=x??ZL&6 z+?}7HU@2&;XaKERTO50x0Tn?WM@p!wYa%yyJ^vQIwe`nXR#vef_3UN)Lir&k0$d#Q z*zOpb<>GOoYr@Q2BsVfj?@#38+w^a;$e{udFz{zK*mv&>_UekX5Ee^YR5H_ypL-Iw za1!vBhO?9g)Y~&ypdsf=D|om#AtSpyF)?zRm|T9$NsAvCtApA2SSy4Bh{a`N@n7ce z^J6l+GBPgw(Zr?xT-GoxR%u-%bQVa?e1KK-D6cVEP&uKWQ>L}G?{bf-KOvtXFplg>S z-)=3v>mlNRSNMs1Yo-e|2$bfdk8*k?E}n z216HN1)4mVSXyxb6c7vHmzg9I%xg$}97XOPRvtVV4N6R8w#i$|d|I@72(Z_R!T6P5 zz&+=WC%kRLtVgo=@PFH>#_wv$?ZV>T-ka#T*N^^??&5AA7@2Ckc$QdhVVSb~@o3&)yBH=^n6$X??Sk|dt)JR~vUU8C z*{}5ro%nb43393iB3mx@yozinF46TQ4wT61sWtMlTiV3N@8PigSq%(KPNeTe$>7lZyf$Iui4MEIWuj5juPd0c{OBEP&H_OyZ)vJGTfEl z1aK1-+j90gFdX1v%o%$4+UnC{NwZ|S7Y|&-MD=hY)!fH<;aO0BD^|^n$g$6)qSDXI zWP8;~KeaEb-9JX6So$ zhBA!doYL19atZ*TJLo}~4ozozs;XV0rLrrfSmj091)<)WD!4$DEi@Z z0AO*A%g*n?QnKI=o-7VvE?ilj8-!!Uht3ND z&`ofjeo0?%52$8~=dAEsMQJ2F4LTA5#)(|%5$Y< z7TSmc;tj(OPd8`sFiTG-;#Mzk-atZt71nXMc?p}zG}DDV|C(|4|5~`U+EKg8aJDNp zBb6>bv~B1krj*tx`A54mic5R)B^%q3SNCs->^F+|onU8Le z7J%@JS$)Q}FjR0NAHPO(2kV}oB882YvU9OYDJzDo2lBFabrhpZB4Oh^?jkLhPl9ns zZs--9_>+$XkfU?dO(iwbYMUqxiaycR9_j_Ai)~Y5vBc^x!oyzSZ-RxxGb9f&n1xNq9 z3YCP8c5Q&5>n5x-J%WbbP$>aG(QdSB*dE>z9_UPM9kg zJuYUFsMKbQ``#gj-#R)t^tVus;wb!_s5bviN|p+TA6(s)?v4Vs=?^*mn-dm`34# z4vmDlBW&-PyBh2tPtsWbeb+;c2eUbWyrt?YhLl4;)|1b`UmWCjQ#)h(BcLHpW5ZbL*eM?_~y-7ExjuoKMcW^K_-;7}S@%5mj$k^ws4;a<6v$KKq zPF2<4)te5o)+`cc`PV*lhmjJFbVKiqvRFl`@HHaC>iWse!y#pVJNa$N$%6;Nw?5s& zY%*YIpyaJqaS-rknb5EV+g&bl3qxfoF-(ZV?Qjx2$H`r ze7z}&nwIWXzyu@(BeVnK)44v*_}y4R9TNBTV^~Uc2eEq8R;Fq2LKUmw6j9dXAZ$rU z_`;WO3E2kB3nr+EgT03B4@|`eikkefgTfx#=Mlm~`weX58HBsGO)Qpc6G3X=HTnFZcI61$?fz z;!Pt$zf`IM19p_C_N+b}eo%tI;d3R@6BDLkN(4$4ontqhIw~q}_+zB1bx=VrmQf#2 z1&d!G!#|By1U5`2cyLTLki_#)pNXfX)q_s&`vQ^JDUr6aubkWRdFvGT@F%_ zs>xEuWrhBgugI*qirl;knAz!2bnNhfVsasoZVVCvp)lr{623zX5`&iq!e$ogTxNVS zT0x`x0{2tg5OwsEq_jev>yqFx;|TTagCkU*)R2HbmThLIefSf2Uj@K+g>S^t19uSA zBRr^Z8T^|@Q?HScN?>S3sD8_*O`fo>YpMzex7!_?b6YvQIceIA4e3MUYjgVZ@Ktn( zt&creGQ)Da>%8!Nsu{LIEVV{e6xrD8z3Y>YyficIbV`_PI1hZxE3~m0Z}CvRZ@8!X z@*#m_y8_K1g%@J zXSkrVO!}_^)HX2a=5F;cLiq(EcIDf-aenAP-~i3M%g|9@dMAx6$wdF1FfYsC6N?;w z@LqXaV0t9p4w!&AV!(IHmjzwRY_@?H^-_vIpxA4OKoXtn7YMpJG0+1Slc+1z`RaKq zxdgLw6!JTp3;{TD4feY`=$mIvbBA%ie;RdqT~@#C+>h}%iIG>R6uf(I8FO@S#Jg+X zF0`}|u4=jrlK3~;QXzg-@}d25a-V3I4TP3=h;^-^0Y-eBbST3 z9t^D^eX2}dK@L>tr?i7<`UG{`%~+y>x%J_q&Inv;-FM^2@W|7DD<*j9Z0NWHAQO;Lg!fuW->W)NlC@=3 z)tZ7NlUWnDBJoLVBDYH4N+arFPWJ=Zf!<@+3>SHex8CXVBeiX3StHUu4=6t(Ct~vJ z>&QcmRMq#IGG5^h`?CuY$ElD%GzvjYpa_*CebRh-Q|;gA)EnF=>L-#WAENscUK$r1 zfpRkpN%mn22m?r9dcFudesdBQ2tOhnX<~B#JRmxNBqo7uZox3dXKE&oDvvBVm#UX8 z3J>@Ggyfp{8~P0txIi=D>uu?-5rHAyic{yhTQNsZXJ0cczS_V@M2DKg1M>2Haq?+< zuMHE<^Ud}hA1UHZ97@yKC7lg^)(QbV#aK{ zK^{R7Kq|mlCEX~?5v!xlWrH?0D3hBH{m6v|F(w3I?o=e$LfMt6t6Y9b=V!TeuDwp< zCL{>KmnJI`%%W1u?9bUS8OICM!KEh0M)$wA@^|0g=xaUgIQ-##5*ujj^M^{Pushd( zJ6Y%7tr*3J4A{cb$}rm-4i4Z#v^Qvx4KVh+tR8IQ=9Q1EX2@@;fRj%QJW4$luB1{FT3z*SxFD|gyEHwzUKuOxj(&HkpNN&P(xX=bQ^e>dTEj|;7HEI_1B#+>h z8=Ua8AzyXKjO39s*6F$--X0OTtO@F%UahWF?=*t?i?$L>8YHfb!lj`B(K6)}+Qudq z{D&sY(<`e@`Qi&(%+%&1rJQVSE{NBy0%r$7$)}#2W!R4#aIpF7IA&xU1w(!_o|rAb z{`BaFu;=;W=I{Tc0v)ag)2=)OgCZi{WN!@^2KO-<`WylxQ-gRT$0j?dyFJU^mi zsfDn?!1T5O0{xCN)|$JLcha|X0xsZ=u!nfaQk zQm`}RRpKQE?MGHY)5wz^>qd4h?u%?@J?~o9AE4XaI$0dCaNZlwTQO9!cMrx0EMR0V zW_SHbDT@%o3kzB?#Cr-FvK$)!gS%>4O2`e^qJnmaUup3&T#r%-kIDjh^)4=Gl~(CZ zpZCS36^_VJ(PgIw>+JPqv}+}`NhC9sG4|(*J5IfKj~%{SgN^L?R5uIxFfapG%Gll6 zKG56{R?mO@Hz#=*outJQ?}}Tlg@AKiJYC+FII5k{t`1VKkkUrB^{TvIIIQScg%K1- zgu7OJqk{&Ee>+2=(XutdI1}7WdAVb=7q3ooLH(u>$^At+9 z0cKr_9s0q)OvYp1RjQQ-<#QjYSYUBrTcaJFgeHI1gPN25eeDX37qGIBBSHm%sOLd4 z*r4Q$?Sk-Jbhg5xAHF+9e&;M&nfTT4QryAa?d|QHuQ#pF!z|+5)VLqAnojoqBx8s_ zhjga;po@V!~_ zKAKPdFW=y>1-&Zi73x4UY7_Tu!q0pScfnk(!<1eyi8O7zidnS%k{T=#7=F$ysOei; zx$=qB`f{;%W{7F@s?5G3Z*McWoEPgUzxjtre~E7^>6S@QX`;oaMB37 z{(T)M_7p1M^E>P*&i|qd#rR>w|29+TJxOT~0IM)30%#Kw{?noV<5t9>+UMgVp99_; z=>V#V&NJYLy;1d8K3iWC{|C@`MV0*4yD`>oTqL~5GEaT?PG8<-uieh|%|F+elfTE} z-voDm#@s*rC3o5T!xR3D|NG)~wiqLbp$SM<=q@7vL_I^$rMZ;ky!!sPvm%IKM>ARK zEhbAO13**K@*OIKE;OIOa_Ku+ohurrTGKmDy9k5)?%j<>X-XboL4^c*fN z{7CIAo5qSS=kD?b3T43N<_T*#0U}<)w<2E)B+GFrw5s+!mRbprbxDD9gj)@CooEL= z`e7)g-54{W8FEb*9e>Z#!vjoz({HBBdH%5m{bSSBeGd;uQ191B#VZzxD_C%%;K&uOLm;fSxjV^%=pO@}Vbh7&8UaTatITPec z_-!yN`rh!1k#?K-Dw~Y6uPXGxy1cD5Z39>M>M^3_(%Hj-#hk8Qr-H2mVrQEs=u%Y_AV{Q`+2PM`FgIMQyv%T zRbxVO`ci{U2DGm6rlGO@m?-DpTOj?)9{^5s+V1}Gdn|wX?a{tJ+Jgb;*JqL|et7jz ztvU^tR{|s=tI;-}J4E_m-JlTnMQX>Tlk&ddY2aDn?fJL6PhL}PeklpHQ)~IDA-EF@$ z+bAVcqFoI{f^aK?;tom}ZMhTE3mRq^5-$j2)ajd21Ki3ec3t zDcDyi-&lo6jB_xkbD}CUGdI_^9*TemUs)g~{F~GB=#kR%g6xfUrT(0dGl)RG34inq zoPEUqt?9%_z%8Ac>vH>><;xR9Bx*{!MB`Kigk(Lbf)gFDX&WC8UT$icJAK2!8Qs5$ zFSDf9%^{Co#ojx;)80ODa&pq&-@n`Ww-1OrbWGbUHGZTdSXo?bar*OXbaZs{gQ&QG zMBAVK!?}-h*X|y(Z_9xv-PrrM-fA@KwzTtZZ`f*7{Qkk^c|~OPtmCHr^!av5f(9F1 z;(<}(Ae3PwHu_LL{1p;OV3kYV84a)Y z@bG&_??e6PgSXE-QNipSoQMzon-qDmk%mqh7$s~5uubV+_F1Y{su7C~i3QqA88Ebq zI&B4|XAQ@nFZ+_BU6nibi=%gIHXq>7kOgR1Dvhm_EQn=X+o}y(U7~Shr!fv>kqG20 zJgiE)n8Kr?qHv8{{aHYQJZ*UAWLM=Rs}bFklbVJQHL8jOFHy>D34ih6^~;^40={NN zKVsyh@*JV2u+d~4Bkl~9Hl4kj!}qD25PEo|LN8oWa+K|Nmo9Q#S=K~$>603vEWSoQ zzWLuM4gP?mUd-Jbk%G|PPaLs>D(OM7GqPzYVTy8iAI&-gzlYZv^IKyS9F`d~<#Y65 zOhh8)YFkz?=7-8ScNg9%1YianA+#fU&69s&pljE+!1ELp#MWnBC?C`)L6I+@*z`?@ z@2?lDH`P3tY%8^q85(HtP_$*DXVK(US+oQYibC5kJtN`ue%aWB@eX>cKjg(5(XZEQ zWoW%Y^!uOX@1H$J&WH@_Ou*}}rNo>Vc9&1_wCm?8U6zE`>zkUY+S_T&faTRG(6qX^ zT!i7$wA}Jn>gkDB)waigjpFO=H6c1Ew8E}?0Df8lKX?eiS`raax;m@$wcqXv%yeiu zt7tv-+{+8oRK8huxp8Ar^SO4(5%ayPOGk@U!lC=Xym@sM<<@!g;b~tYp2^N`cWyLC z!tH#k2Ty{JGDZlMw+PIdXT^Ol!_9FP4~0S?IJ=>#?`B6NrI67fmWyE-ts1Gb)yRDX z3>hWns`p5Q%d9U)z~LI*vOM&qYzcAchU^AkL(uoyy{|c@DH?Rbkrssn{u!XW(4Zq~ z=38UwgH~8}Ju1P9BQ4$%O_aWZ{>=Zw!X%SvIS=Zx5Pc=TMnwTy-i^ht(N%Ki#$9fp z7%}kDI{Grr;rFY;OilI#6)tuEm8yyZ z_r(Cp;sjemNVC$TpT8ivL6g&;%lB_f4x9v2VXDd{Co_S9p{xv}=n}174yL|;2D*C= z4^tnafYzTmJ|v`%_AZb1<3ybQ#wNfN4D7k_JH7cY)?sS!^2Yxe@1^hMgrooCA=%E3 zW9xClO~*}PV=_D+4}u*8B-TWc}y>NQoR{@08MB=tau%Cs2? zWQ%s))i0#Qib=gt(IIv7??<(T_+Ol@E#V4o#y1PcX7F5Flfh3UMAcc4VaWv%3lQk$ z_Wj_l6AW2xS+;7um*TbdYGd2BJz(m1+Hx`4>aOq;z}e>L~!|2YdJCSV0JEffoLDmEev|(mS9b+O;(Wy zzn&O@ii+|d-nYwuP19_g?~%D8f}ZDFaUe3$3tfk$0Rw{+P?rG|Js3EWnj-cY=v|+B zpG?#t$(iOJu!zv`+>@)&3i&e>s&QEhD{mImA(LL+IWYmleb%2lAMHUPxSzX6kNNen z8_&xR@~yb#y!v7S>s{<0hm52fhusg110%6Genu0Um%(l88h>XKlqkm1yZ3(QSu0H7 zK=wn$497&>$iJ)S#Gh;FY&_aI;L3Jqd!fhFFLvA+d5mWwty-gaz zA4Ojb&JASI9}8$0HX*s0oe#4TS#{P?CRK*J1PbF>WgS;7FsV`%p%G{-!GQJGn#Y=N zWBc_-fj2oSMa<53g{gNztIH2QQ+!i{OuN0*W)Rm*{X%(m$C+WalH z7?k%;tc3Iey9QWhWw8&wL5JB|`Keu9xIw6lhbN+j4niBbIM!f;G=ai;Q@*65iA1<9 zebv@cfxpXY{e4-nP71hxG%m104v96%(G49hvBXj}zKIGcZ>rbVAv~9@9vt3#VCs4D zv;Y1Znk=yv_a@Ia(#(-L_d$Te&8e)cM=0nopVU!;lFZUOBW{#$onOM&cYq{%n9wT- zl>m_>F?T(&Ilq8_&!5}f9N&{e6@xj*5;IpZ93DC2~9v@c>cSF^6gyqR_5HAaKnHos*At9mQJzNhzr1%@@ z-Kgxz8H^4EX2SN}#V(%)v089Ppr=&hG}qCZ%I$u~7V@;uTS;2VdQ4GV&Nqa}0ctQU zE5m->%J6sy^%iA%3HQ*XG;L8hFnU(5AUog;%QdfHc zl6h>HTLG$4WBVP9YRp*hxtAzTKy{cJG#&90!2yeP4ZMv?@f8h1XRGi0H{9tpm+b)z z`L>RZmw9-PnPkR3@ew14M1u&y!rAM`TjFKvh5FxSZZr4E#<$73S3msj_M^z&J^_{t z(5ZJ24zBt!Cx90)j>VU*=IwSoiA{ipsblOiGS+s}4mjZ%85un#O57#_gkA__n+R-W zI}%Ir`oY7)J-}hOR^PFG`%&Wg=_=~*{rmT{k9!J8bitA!_~2_IjQ6mqFOK75LPUZu zB!26bE{;7MjdfhTx$(U!HMYwbU!{&sIxa;VZy-Fz^OKvQ?XaTN`1x+B^9eBp2p@ojS}EBm zy7!$0dih zKk_;SpFcaK9h^^|$1^J6(hBjBW6#dc_W#rv9V~POT7tXD)R!H%J9EokOXVNL9;f>* z$Qs@WbpE{^Q<`mW{{sFDYqpoWlz8ZT4vbiR?zj=VdB8IE`76ah9dnKQQgq!+2*O)a zU(b&+z*e$g2i##%#t+Ez;x0v>v(&t}@Un4MRl@MKNSPWoUK^+>9!Z)zlEdM)TBWdX zR7_jt5EN5hA|?=67EUUt&eVxmppiT8)n$&e29fojQlXD|S%VOID@I*3|KyVKOYv(W z9pBoLnr&-daZrc|P@$N!Bof67rINOj$=$q>WR#vuppeW32eZ`&B6F8UVx6W928*t-{2=li$wJ`8_Hepfbg>&(QeTV1|=82+#bpF*^ z4!RZZ?(AYb8d)fpM}WVV44qt$-u1oToKO_)_)xEN!yZ{(5pOL>{n9|(1h(e+n+E8d za-OEw=xPYJv)UUl6}v8biHyZO&!_q4sMl6j^bHJ-aPH7u_a_U1zX1n52p$QPi6d8G zA;05#;LQ8291n*&UG7aVD#VplR1n6OXj*ylmm0hk@fpq!a_~&UZ2kSO@$MorcDHM} zomM@XOT-6dnL=_#fK4JzBwW8MlP15+j7_c|ejs+YX9Z}vN3kFnIxea{m>9pwF?hRhql@PaTCq$wABY z;M&Zbfs2V{AsjwoJ)QkZU8f#ir<7{}Y+@m!jpO_k1}sdpV`RTx&FDNwtv!^-M5Q(~ zHq!e2%UgTOUfah*XRs}PYKmwQ!R>ZQc)?Ya^u{F|6aYFIIV=<4Kb#TMsdS&R;{p-9 zCSlSD@221n=G>BlD%+#WXce+6l6~5?8+?oU9W59n)h)?Z^$LR}OHi=%TBJckz=cGM z^vx&7LrS}V7I-PXnc;$kEws7<{AHf@$o{k!t~urR-@y|F*7Cp?J)d+g+i()3{=m%b z44K=U*kbWN7kl2LeH;f^x6hZCQy(6uz5Nc}+^pDH2iG+>pIuIkWeHuJTk}!k?uM@~ z0c-zN?-R|CIKQJ!pi*4U{Sb|@$hm*mjiVN7Xsb(FJZ_(`{$j&j*aqmL7#@urff?fJ zYGk2l=+8WP)@M1iu#B@e${)$8B%`H7io6_ymuEX{C^L^uf{}u5=W~N>Unq4+mh0Ro zr~NpL=+A-q zN|EqEQLu%_Mv-@%1W`L25#Qy|a3X?AZpSpaGY?{gc)3lPNHQA|{g$xukkc6QkQpYv z0_)%3iGy|PDnk0-y#%SJ+wrAE06b$VIXU^b{Mh*3__@#Vp}+ItaqWKPzoKc)Ma{v< z896ZVQ=#+u{yB_MAr^SN#cr0d^lB_9aKkWkKC1l?y^WLj>&JV)nD`+_qVw)=kMUih z@!j^*vWbh`;dpnlRnFsG;d`?@Q84KLD(2j1rjeXVwCGLJoz~OKkN({`% zFBzD;>3ZO9g{+Q$n#vAs)MkqI`Zr#?W0ijYZl1>Ufs$S!a%x~`*k0$yW+fHC6UZwo zsT5Hb9aY0xoR37{3@#Iv$TBwg1V0q+KX^F!lv(TX+_!0zJh0e6GL_Y*p!M;AW@O-F zN@``t0R&iSm6w$PwLqRR&f=`5-F_*n?`k}RGLSEkspZv8X+^Ua*Pd~UYsng|573>8 zGBLJlCG5HKe34ThoitS=HB(`0F6fv$1l*Q=e0_aQ{W@%5R%0DUwHJVd>K$)Q9SKhc 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 Q5O7^Jx{fHnbnEf|0Txf-h5!Hn literal 0 HcmV?d00001 diff --git a/bsp/apm32/apm32f072vb-miniboard/figures/JFlash_Leader_01.png b/bsp/apm32/apm32f072vb-miniboard/figures/JFlash_Leader_01.png new file mode 100644 index 0000000000000000000000000000000000000000..5640216ae5b677bc49e77e3995cdf3a00688723b GIT binary patch literal 47629 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
6Zj^KRst6 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 literal 0 HcmV?d00001 diff --git a/bsp/apm32/apm32f072vb-miniboard/figures/JFlash_Leader_02.png b/bsp/apm32/apm32f072vb-miniboard/figures/JFlash_Leader_02.png new file mode 100644 index 0000000000000000000000000000000000000000..93984c1a901979cc09743b4acd016aafb96c1d6e GIT binary patch literal 9973 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 literal 0 HcmV?d00001 diff --git a/bsp/apm32/apm32f072vb-miniboard/figures/JFlash_Leader_03.png b/bsp/apm32/apm32f072vb-miniboard/figures/JFlash_Leader_03.png new file mode 100644 index 0000000000000000000000000000000000000000..6280b5d664164903c9e7c8b4203306b03918d7bf GIT binary patch literal 3590 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 Vb%!*Mdq_PTpe(NeseEA(`hWN36S@EZ literal 0 HcmV?d00001 diff --git a/bsp/apm32/apm32f072vb-miniboard/figures/JFlash_Leader_04.png b/bsp/apm32/apm32f072vb-miniboard/figures/JFlash_Leader_04.png new file mode 100644 index 0000000000000000000000000000000000000000..b133313482c10209e4b442e6affb6607cfc7d2c1 GIT binary patch literal 12434 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 + 3 + + rt-thread + + ARM + + 1 + + General + 3 + + 35 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 37 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 11 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + 0 + inputOutputBased + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 27 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + + Release + + ARM + + 0 + + General + 3 + + 35 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 37 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 11 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 0 + + + + + + + + + CUSTOM + 3 + + + + 0 + inputOutputBased + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 27 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 0 + + + + + + + + Applications + + $PROJ_DIR$\applications\main.c + + + + Compiler + + $PROJ_DIR$\..\..\..\components\libc\compilers\common\cctype.c + + + $PROJ_DIR$\..\..\..\components\libc\compilers\common\cstdio.c + + + $PROJ_DIR$\..\..\..\components\libc\compilers\common\cstdlib.c + + + $PROJ_DIR$\..\..\..\components\libc\compilers\common\cstring.c + + + $PROJ_DIR$\..\..\..\components\libc\compilers\common\ctime.c + + + $PROJ_DIR$\..\..\..\components\libc\compilers\common\cwchar.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-m0\context_iar.S + + + $PROJ_DIR$\..\..\..\libcpu\arm\cortex-m0\cpuport.c + + + + DeviceDrivers + + $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\pin.c + + + $PROJ_DIR$\..\..\..\components\drivers\serial\serial.c + + + + Drivers + + $PROJ_DIR$\board\board.c + + + $PROJ_DIR$\..\libraries\APM32F0xx_Library\Device\Geehy\APM32F0xx\Source\iar\startup_apm32f072.s + + + $PROJ_DIR$\..\libraries\Drivers\drv_common.c + + + $PROJ_DIR$\..\libraries\Drivers\drv_gpio.c + + + $PROJ_DIR$\..\libraries\Drivers\drv_usart.c + + + + Finsh + + $PROJ_DIR$\..\..\..\components\finsh\shell.c + + + $PROJ_DIR$\..\..\..\components\finsh\msh.c + + + $PROJ_DIR$\..\..\..\components\finsh\msh_parse.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\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\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_eint.c + + + $PROJ_DIR$\..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_misc.c + + + $PROJ_DIR$\..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_gpio.c + + + $PROJ_DIR$\..\libraries\APM32F0xx_Library\Device\Geehy\APM32F0xx\Source\system_apm32f0xx.c + + + $PROJ_DIR$\..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_usart.c + + + $PROJ_DIR$\..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_syscfg.c + + + $PROJ_DIR$\..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_rcm.c + + + + POSIX + + diff --git a/bsp/apm32/apm32f072vb-miniboard/project.eww b/bsp/apm32/apm32f072vb-miniboard/project.eww new file mode 100644 index 0000000000..c2cb02eb1e --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/project.eww @@ -0,0 +1,10 @@ + + + + + $WS_DIR$\project.ewp + + + + + diff --git a/bsp/apm32/apm32f072vb-miniboard/project.uvoptx b/bsp/apm32/apm32f072vb-miniboard/project.uvoptx new file mode 100644 index 0000000000..e551477e4b --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/project.uvoptx @@ -0,0 +1,853 @@ + + + + 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\keil\List\ + + + 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 + 4 + + + + + + + + + + + Segger\JL2CM3.dll + + + + 0 + JL2CM3 + -U -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0APM32F0xx_128.FLM -FS08000000 -FL020000 -FP0($$Device:APM32F072VB$Flash\APM32F0xx_128.FLM) + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0APM32F0xx_128 -FS08000000 -FL020000 -FP0($$Device:APM32F072VB$Flash\APM32F0xx_128.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 + 0 + 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\cctype.c + cctype.c + 0 + 0 + + + 2 + 5 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\cstdio.c + cstdio.c + 0 + 0 + + + 2 + 6 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\cstdlib.c + cstdlib.c + 0 + 0 + + + 2 + 7 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\cstring.c + cstring.c + 0 + 0 + + + 2 + 8 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\ctime.c + ctime.c + 0 + 0 + + + 2 + 9 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\cwchar.c + cwchar.c + 0 + 0 + + + + + CPU + 0 + 0 + 0 + 0 + + 3 + 10 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\div0.c + div0.c + 0 + 0 + + + 3 + 11 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\showmem.c + showmem.c + 0 + 0 + + + 3 + 12 + 2 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m0\context_rvds.S + context_rvds.S + 0 + 0 + + + 3 + 13 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m0\cpuport.c + cpuport.c + 0 + 0 + + + + + DeviceDrivers + 1 + 0 + 0 + 0 + + 4 + 14 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\completion.c + completion.c + 0 + 0 + + + 4 + 15 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\dataqueue.c + dataqueue.c + 0 + 0 + + + 4 + 16 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\pipe.c + pipe.c + 0 + 0 + + + 4 + 17 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\ringblk_buf.c + ringblk_buf.c + 0 + 0 + + + 4 + 18 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\ringbuffer.c + ringbuffer.c + 0 + 0 + + + 4 + 19 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\waitqueue.c + waitqueue.c + 0 + 0 + + + 4 + 20 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\workqueue.c + workqueue.c + 0 + 0 + + + 4 + 21 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\misc\pin.c + pin.c + 0 + 0 + + + 4 + 22 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\serial\serial.c + serial.c + 0 + 0 + + + + + Drivers + 1 + 0 + 0 + 0 + + 5 + 23 + 1 + 0 + 0 + 0 + board\board.c + board.c + 0 + 0 + + + 5 + 24 + 2 + 0 + 0 + 0 + ..\libraries\APM32F0xx_Library\Device\Geehy\APM32F0xx\Source\arm\startup_apm32f072.s + startup_apm32f072.s + 0 + 0 + + + 5 + 25 + 1 + 0 + 0 + 0 + ..\libraries\Drivers\drv_common.c + drv_common.c + 0 + 0 + + + 5 + 26 + 1 + 0 + 0 + 0 + ..\libraries\Drivers\drv_gpio.c + drv_gpio.c + 0 + 0 + + + 5 + 27 + 1 + 0 + 0 + 0 + ..\libraries\Drivers\drv_usart.c + drv_usart.c + 0 + 0 + + + + + Finsh + 0 + 0 + 0 + 0 + + 6 + 28 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\shell.c + shell.c + 0 + 0 + + + 6 + 29 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh.c + msh.c + 0 + 0 + + + 6 + 30 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh_parse.c + msh_parse.c + 0 + 0 + + + 6 + 31 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\cmd.c + cmd.c + 0 + 0 + + + + + Kernel + 0 + 0 + 0 + 0 + + 7 + 32 + 1 + 0 + 0 + 0 + ..\..\..\src\clock.c + clock.c + 0 + 0 + + + 7 + 33 + 1 + 0 + 0 + 0 + ..\..\..\src\components.c + components.c + 0 + 0 + + + 7 + 34 + 1 + 0 + 0 + 0 + ..\..\..\src\device.c + device.c + 0 + 0 + + + 7 + 35 + 1 + 0 + 0 + 0 + ..\..\..\src\idle.c + idle.c + 0 + 0 + + + 7 + 36 + 1 + 0 + 0 + 0 + ..\..\..\src\ipc.c + ipc.c + 0 + 0 + + + 7 + 37 + 1 + 0 + 0 + 0 + ..\..\..\src\irq.c + irq.c + 0 + 0 + + + 7 + 38 + 1 + 0 + 0 + 0 + ..\..\..\src\kservice.c + kservice.c + 0 + 0 + + + 7 + 39 + 1 + 0 + 0 + 0 + ..\..\..\src\mem.c + mem.c + 0 + 0 + + + 7 + 40 + 1 + 0 + 0 + 0 + ..\..\..\src\mempool.c + mempool.c + 0 + 0 + + + 7 + 41 + 1 + 0 + 0 + 0 + ..\..\..\src\object.c + object.c + 0 + 0 + + + 7 + 42 + 1 + 0 + 0 + 0 + ..\..\..\src\scheduler.c + scheduler.c + 0 + 0 + + + 7 + 43 + 1 + 0 + 0 + 0 + ..\..\..\src\thread.c + thread.c + 0 + 0 + + + 7 + 44 + 1 + 0 + 0 + 0 + ..\..\..\src\timer.c + timer.c + 0 + 0 + + + + + Libraries + 0 + 0 + 0 + 0 + + 8 + 45 + 1 + 0 + 0 + 0 + ..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_eint.c + apm32f0xx_eint.c + 0 + 0 + + + 8 + 46 + 1 + 0 + 0 + 0 + ..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_misc.c + apm32f0xx_misc.c + 0 + 0 + + + 8 + 47 + 1 + 0 + 0 + 0 + ..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_gpio.c + apm32f0xx_gpio.c + 0 + 0 + + + 8 + 48 + 1 + 0 + 0 + 0 + ..\libraries\APM32F0xx_Library\Device\Geehy\APM32F0xx\Source\system_apm32f0xx.c + system_apm32f0xx.c + 0 + 0 + + + 8 + 49 + 1 + 0 + 0 + 0 + ..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_usart.c + apm32f0xx_usart.c + 0 + 0 + + + 8 + 50 + 1 + 0 + 0 + 0 + ..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_syscfg.c + apm32f0xx_syscfg.c + 0 + 0 + + + 8 + 51 + 1 + 0 + 0 + 0 + ..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_rcm.c + apm32f0xx_rcm.c + 0 + 0 + + + + diff --git a/bsp/apm32/apm32f072vb-miniboard/project.uvprojx b/bsp/apm32/apm32f072vb-miniboard/project.uvprojx new file mode 100644 index 0000000000..14307eafbd --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/project.uvprojx @@ -0,0 +1,697 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 5060960::V5.06 update 7 (build 960)::.\ARMCC + 0 + + + APM32F072VB + Geehy + Geehy.APM32F0xx_DFP.1.0.7 + https://www.geehy.com/uploads/tool/ + IRAM(0x20000000,0x4000) IROM(0x08000000,0x20000) CPUTYPE("Cortex-M0+") CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0APM32F0xx_128 -FS08000000 -FL020000 -FP0($$Device:APM32F072VB$Flash\APM32F0xx_128.FLM)) + 0 + $$Device:APM32F072VB$Device\Device\Geehy\APM32F0xx\Include\apm32f0xx.h + + + + + + + + + + $$Device:APM32F072VB$SVD\APM32F072.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\keil\Obj\ + rt-thread + 1 + 0 + 0 + 1 + 1 + .\build\keil\List\ + 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 + DARMCM1.DLL + -pCM0+ + SARMCM3.DLL + + TARMCM1.DLL + -pCM0+ + + + + 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-M0+" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 0 + 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 + 0x4000 + + + 1 + 0x8000000 + 0x20000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x20000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x4000 + + + 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 + + + __STDC_LIMIT_MACROS, RT_USING_ARMLIBC, USE_STDPERIPH_DRIVER, RT_USING_LIBC, __CLK_TCK=RT_TICK_PER_SECOND, __RTTHREAD__, APM32F072xB + + ..\..\..\components\drivers\include;..\..\..\components\finsh;..\..\..\libcpu\arm\cortex-m0;..\..\..\components\drivers\include;..\..\..\components\libc\posix\io\poll;..\..\..\libcpu\arm\common;..\..\..\components\libc\posix\io\stdio;applications;..\..\..\components\libc\compilers\common\include;..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\inc;..\libraries\APM32F0xx_Library\Device\Geehy\APM32F0xx\Include;..\libraries\Drivers\config;..\..\..\components\libc\compilers\common\extension;.;..\..\..\include;..\..\..\components\drivers\include;..\libraries\APM32F0xx_Library\CMSIS\Include;..\..\..\components\libc\posix\ipc;..\libraries\Drivers;..\..\..\components\libc\compilers\common\extension\fcntl\octal;board + + + + 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 + + + cctype.c + 1 + ..\..\..\components\libc\compilers\common\cctype.c + + + cstdio.c + 1 + ..\..\..\components\libc\compilers\common\cstdio.c + + + cstdlib.c + 1 + ..\..\..\components\libc\compilers\common\cstdlib.c + + + cstring.c + 1 + ..\..\..\components\libc\compilers\common\cstring.c + + + ctime.c + 1 + ..\..\..\components\libc\compilers\common\ctime.c + + + cwchar.c + 1 + ..\..\..\components\libc\compilers\common\cwchar.c + + + + + CPU + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m0\context_rvds.S + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m0\cpuport.c + + + + + DeviceDrivers + + + 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 + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + Drivers + + + board.c + 1 + board\board.c + + + startup_apm32f072.s + 2 + ..\libraries\APM32F0xx_Library\Device\Geehy\APM32F0xx\Source\arm\startup_apm32f072.s + + + drv_common.c + 1 + ..\libraries\Drivers\drv_common.c + + + drv_gpio.c + 1 + ..\libraries\Drivers\drv_gpio.c + + + drv_usart.c + 1 + ..\libraries\Drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + msh_parse.c + 1 + ..\..\..\components\finsh\msh_parse.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 + + + 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 + + + apm32f0xx_eint.c + 1 + ..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_eint.c + + + apm32f0xx_misc.c + 1 + ..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_misc.c + + + apm32f0xx_gpio.c + 1 + ..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_gpio.c + + + system_apm32f0xx.c + 1 + ..\libraries\APM32F0xx_Library\Device\Geehy\APM32F0xx\Source\system_apm32f0xx.c + + + apm32f0xx_usart.c + 1 + ..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_usart.c + + + apm32f0xx_syscfg.c + 1 + ..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_syscfg.c + + + apm32f0xx_rcm.c + 1 + ..\libraries\APM32F0xx_Library\APM32F0xx_StdPeriphDriver\src\apm32f0xx_rcm.c + + + + + + + + + + + + + + + + + template + 1 + + + + +
diff --git a/bsp/apm32/apm32f072vb-miniboard/rtconfig.h b/bsp/apm32/apm32f072vb-miniboard/rtconfig.h new file mode 100644 index 0000000000..2bfb0b486a --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/rtconfig.h @@ -0,0 +1,241 @@ +#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_KSERVICE_USING_STDLIB +#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_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 "uart1" +#define RT_VER_NUM 0x50000 +#define ARCH_ARM +#define ARCH_ARM_CORTEX_M +#define ARCH_ARM_CORTEX_M0 + +/* 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_UNAMED_PIPE_NUMBER 64 +#define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_PIN + +/* 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 */ + +/* sensors drivers */ + + +/* touch drivers */ + + +/* Kendryte SDK */ + + +/* AI packages */ + + +/* Signal Processing and Control Algorithm Packages */ + + +/* miscellaneous packages */ + +/* project laboratory */ + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + + +/* Arduino libraries */ + + +/* Projects */ + + +/* Sensors */ + + +/* Display */ + + +/* Timing */ + + +/* Data Processing */ + + +/* Data Storage */ + +/* Communication */ + + +/* Device Control */ + + +/* Other */ + +/* Signal IO */ + + +/* Uncategorized */ + +#define SOC_FAMILY_APM32 +#define SOC_SERIES_APM32F0 + +/* Hardware Drivers Config */ + +#define SOC_APM32F072VB + +/* Onboard Peripheral Drivers */ + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_GPIO +#define BSP_USING_UART +#define BSP_USING_UART1 + +/* Board extended module Drivers */ + + +#endif diff --git a/bsp/apm32/apm32f072vb-miniboard/rtconfig.py b/bsp/apm32/apm32f072vb-miniboard/rtconfig.py new file mode 100644 index 0000000000..2fd6753c9b --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/rtconfig.py @@ -0,0 +1,184 @@ +import os + +# toolchains options +ARCH='arm' +CPU='cortex-m0' +CROSS_TOOL='gcc' + +# 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 = 'iccarm' + EXEC_PATH = r'D:/IAR' + +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-m0 -mthumb -ffunction-sections -fdata-sections' + CFLAGS = DEVICE + ' -Dgcc' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rt-thread.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-M0 ' + 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 rt-thread.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 == 'armclang': + # toolchains + CC = 'armclang' + CXX = 'armclang' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M0 ' + CFLAGS = ' --target=arm-arm-none-eabi -mcpu=cortex-m0 ' + CFLAGS += ' -mcpu=cortex-m0 ' + CFLAGS += ' -c -fno-rtti -funsigned-char -fshort-enums -fshort-wchar ' + CFLAGS += ' -gdwarf-3 -ffunction-sections ' + AFLAGS = DEVICE + ' --apcs=interwork ' + LFLAGS = DEVICE + ' --info sizes --info totals --info unused --info veneers ' + LFLAGS += ' --list rt-thread.map ' + LFLAGS += r' --strict --scatter "board\linker_scripts\link.sct" ' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCLANG/include' + LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCLANG/lib' + + EXEC_PATH += '/ARM/ARMCLANG/bin/' + + if BUILD == 'debug': + CFLAGS += ' -g -O1' # armclang recommend + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iccarm': + # 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-M0' + CFLAGS += ' -e' + CFLAGS += ' --fpu=None' + 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-M0' + AFLAGS += ' --fpu None' + 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/apm32/apm32f072vb-miniboard/template.ewp b/bsp/apm32/apm32f072vb-miniboard/template.ewp new file mode 100644 index 0000000000..5f559e1751 --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/template.ewp @@ -0,0 +1,2144 @@ + + + 3 + + rt-thread + + ARM + + 1 + + General + 3 + + 35 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 37 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 11 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + 0 + inputOutputBased + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 27 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + + Release + + ARM + + 0 + + General + 3 + + 35 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 37 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 11 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 0 + + + + + + + + + CUSTOM + 3 + + + + 0 + inputOutputBased + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 27 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 0 + + + + + + + diff --git a/bsp/apm32/apm32f072vb-miniboard/template.eww b/bsp/apm32/apm32f072vb-miniboard/template.eww new file mode 100644 index 0000000000..bd036bb4c9 --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/template.eww @@ -0,0 +1,10 @@ + + + + + $WS_DIR$\template.ewp + + + + + diff --git a/bsp/apm32/apm32f072vb-miniboard/template.uvoptx b/bsp/apm32/apm32f072vb-miniboard/template.uvoptx new file mode 100644 index 0000000000..5a29a67e0a --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/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\keil\List\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 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 + 4 + + + + + + + + + + + Segger\JL2CM3.dll + + + + 0 + JL2CM3 + -U -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0APM32F0xx_128.FLM -FS08000000 -FL020000 -FP0($$Device:APM32F072VB$Flash\APM32F0xx_128.FLM) + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0APM32F0xx_128 -FS08000000 -FL020000 -FP0($$Device:APM32F072VB$Flash\APM32F0xx_128.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 + + + + + + + + + + + + + Source Group 1 + 0 + 0 + 0 + 0 + + +
diff --git a/bsp/apm32/apm32f072vb-miniboard/template.uvprojx b/bsp/apm32/apm32f072vb-miniboard/template.uvprojx new file mode 100644 index 0000000000..09efb9ffc4 --- /dev/null +++ b/bsp/apm32/apm32f072vb-miniboard/template.uvprojx @@ -0,0 +1,405 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::ARMCC + 0 + + + APM32F072VB + Geehy + Geehy.APM32F0xx_DFP.1.0.7 + https://www.geehy.com/uploads/tool/ + IRAM(0x20000000,0x4000) IROM(0x08000000,0x20000) CPUTYPE("Cortex-M0+") CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0APM32F0xx_128 -FS08000000 -FL020000 -FP0($$Device:APM32F072VB$Flash\APM32F0xx_128.FLM)) + 0 + $$Device:APM32F072VB$Device\Device\Geehy\APM32F0xx\Include\apm32f0xx.h + + + + + + + + + + $$Device:APM32F072VB$SVD\APM32F072.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\keil\Obj\ + rt-thread + 1 + 0 + 0 + 1 + 1 + .\build\keil\List\ + 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 + DARMCM1.DLL + -pCM0+ + SARMCM3.DLL + + TARMCM1.DLL + -pCM0+ + + + + 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-M0+" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 0 + 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 + 0x4000 + + + 1 + 0x8000000 + 0x20000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x20000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x4000 + + + 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 + + + + + + + + + + + Source Group 1 + + + + + + + + + + + + + + + template + 1 + + + + +
diff --git a/bsp/apm32/apm32f103xe-minibroard/.config b/bsp/apm32/apm32f103xe-minibroard/.config index 49c1edd185..1d85696fbc 100644 --- a/bsp/apm32/apm32f103xe-minibroard/.config +++ b/bsp/apm32/apm32f103xe-minibroard/.config @@ -8,6 +8,7 @@ # CONFIG_RT_NAME_MAX=8 # CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMART is not set # CONFIG_RT_USING_SMP is not set CONFIG_RT_ALIGN_SIZE=4 # CONFIG_RT_THREAD_PRIORITY_8 is not set @@ -77,16 +78,19 @@ CONFIG_RT_USING_HEAP=y # CONFIG_RT_USING_DEVICE=y # CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_DM 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="uart1" -CONFIG_RT_VER_NUM=0x40101 -CONFIG_ARCH_ARM=y +CONFIG_RT_VER_NUM=0x50000 +# CONFIG_RT_USING_CACHE is not set +# CONFIG_ARCH_ARM_BOOTWITH_FLUSH_CACHE is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set CONFIG_RT_USING_CPU_FFS=y +CONFIG_ARCH_ARM=y CONFIG_ARCH_ARM_CORTEX_M=y CONFIG_ARCH_ARM_CORTEX_M3=y -# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set # # RT-Thread Components @@ -121,14 +125,16 @@ CONFIG_DFS_FD_MAX=16 # CONFIG_RT_USING_DFS_ELMFAT is not set # CONFIG_RT_USING_DFS_DEVFS is not set # CONFIG_RT_USING_DFS_ROMFS is not set +# CONFIG_RT_USING_DFS_CROMFS is not set # CONFIG_RT_USING_DFS_RAMFS is not set +# CONFIG_RT_USING_DFS_TMPFS 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_UNAMED_PIPE_NUMBER=64 # CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set CONFIG_RT_USING_SERIAL=y CONFIG_RT_USING_SERIAL_V1=y @@ -143,10 +149,14 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64 CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_ADC is not set # CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_NULL is not set +# CONFIG_RT_USING_ZERO is not set +# CONFIG_RT_USING_RANDOM is not set # 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_FDT is not set # CONFIG_RT_USING_RTC is not set # CONFIG_RT_USING_SDIO is not set # CONFIG_RT_USING_SPI is not set @@ -154,10 +164,13 @@ CONFIG_RT_USING_PIN=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_LCD 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_DEV_BUS is not set # CONFIG_RT_USING_WIFI is not set +# CONFIG_RT_USING_VIRTIO is not set # # Using USB @@ -302,6 +315,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # 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_RYANMQTT 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 @@ -309,6 +323,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_SMALL_MODBUS is not set # CONFIG_PKG_USING_NET_SERVER is not set # CONFIG_PKG_USING_ZFTP is not set +# CONFIG_PKG_USING_WOL is not set # # security packages @@ -399,7 +414,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # 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 @@ -433,8 +447,8 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_CBOX is not set # CONFIG_PKG_USING_SNOWFLAKE is not set # CONFIG_PKG_USING_HASH_MATCH is not set -# CONFIG_PKG_USING_FIRE_PID_CURVE is not set # CONFIG_PKG_USING_ARMV7M_DWT_TOOL is not set +# CONFIG_PKG_USING_VOFA_PLUS is not set # # system packages @@ -470,7 +484,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # 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_FREERTOS_WRAPPER is not set # CONFIG_PKG_USING_CAIRO is not set # CONFIG_PKG_USING_PIXMAN is not set @@ -505,19 +518,93 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_KMULTI_RTIMER is not set # CONFIG_PKG_USING_TFDB is not set # CONFIG_PKG_USING_QPC is not set +# CONFIG_PKG_USING_AGILE_UPGRADE is not set # # peripheral libraries and drivers # -# CONFIG_PKG_USING_SENSORS_DRIVERS is not set -# CONFIG_PKG_USING_REALTEK_AMEBA is not set + +# +# sensors drivers +# +# CONFIG_PKG_USING_LSM6DSM is not set +# CONFIG_PKG_USING_LSM6DSL is not set +# CONFIG_PKG_USING_LPS22HB is not set +# CONFIG_PKG_USING_HTS221 is not set +# CONFIG_PKG_USING_LSM303AGR is not set +# CONFIG_PKG_USING_BME280 is not set +# CONFIG_PKG_USING_BME680 is not set +# CONFIG_PKG_USING_BMA400 is not set +# CONFIG_PKG_USING_BMI160_BMX160 is not set +# CONFIG_PKG_USING_SPL0601 is not set +# CONFIG_PKG_USING_MS5805 is not set +# CONFIG_PKG_USING_DA270 is not set +# CONFIG_PKG_USING_DF220 is not set +# CONFIG_PKG_USING_HSHCAL001 is not set +# CONFIG_PKG_USING_BH1750 is not set +# CONFIG_PKG_USING_MPU6XXX is not set +# CONFIG_PKG_USING_AHT10 is not set +# CONFIG_PKG_USING_AP3216C is not set +# CONFIG_PKG_USING_TSL4531 is not set +# CONFIG_PKG_USING_DS18B20 is not set +# CONFIG_PKG_USING_DHT11 is not set +# CONFIG_PKG_USING_DHTXX is not set +# CONFIG_PKG_USING_GY271 is not set +# CONFIG_PKG_USING_GP2Y10 is not set +# CONFIG_PKG_USING_SGP30 is not set +# CONFIG_PKG_USING_HDC1000 is not set +# CONFIG_PKG_USING_BMP180 is not set +# CONFIG_PKG_USING_BMP280 is not set +# CONFIG_PKG_USING_SHTC1 is not set +# CONFIG_PKG_USING_BMI088 is not set +# CONFIG_PKG_USING_HMC5883 is not set +# CONFIG_PKG_USING_MAX6675 is not set +# CONFIG_PKG_USING_TMP1075 is not set +# CONFIG_PKG_USING_SR04 is not set +# CONFIG_PKG_USING_CCS811 is not set +# CONFIG_PKG_USING_PMSXX is not set +# CONFIG_PKG_USING_RT3020 is not set +# CONFIG_PKG_USING_MLX90632 is not set +# CONFIG_PKG_USING_MLX90393 is not set +# CONFIG_PKG_USING_MLX90392 is not set +# CONFIG_PKG_USING_MLX90397 is not set +# CONFIG_PKG_USING_MS5611 is not set +# CONFIG_PKG_USING_MAX31865 is not set +# CONFIG_PKG_USING_VL53L0X is not set +# CONFIG_PKG_USING_INA260 is not set +# CONFIG_PKG_USING_MAX30102 is not set +# CONFIG_PKG_USING_INA226 is not set +# CONFIG_PKG_USING_LIS2DH12 is not set +# CONFIG_PKG_USING_HS300X is not set +# CONFIG_PKG_USING_ZMOD4410 is not set +# CONFIG_PKG_USING_ISL29035 is not set +# CONFIG_PKG_USING_MMC3680KJ is not set +# CONFIG_PKG_USING_QMP6989 is not set +# CONFIG_PKG_USING_BALANCE is not set # CONFIG_PKG_USING_SHT2X is not set # CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AD7746 is not set # CONFIG_PKG_USING_ADT74XX is not set +# CONFIG_PKG_USING_MAX17048 is not set # CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_CW2015 is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_PAJ7620 is not set + +# +# touch drivers +# +# CONFIG_PKG_USING_GT9147 is not set +# CONFIG_PKG_USING_GT1151 is not set +# CONFIG_PKG_USING_GT917S is not set +# CONFIG_PKG_USING_GT911 is not set +# CONFIG_PKG_USING_FT6206 is not set +# CONFIG_PKG_USING_FT5426 is not set +# CONFIG_PKG_USING_FT6236 is not set +# CONFIG_PKG_USING_XPT2046_TOUCH is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set # CONFIG_PKG_USING_STM32_SDIO is not set # CONFIG_PKG_USING_ESP_IDF is not set -# CONFIG_PKG_USING_ICM20608 is not set # CONFIG_PKG_USING_BUTTON is not set # CONFIG_PKG_USING_PCF8574 is not set # CONFIG_PKG_USING_SX12XX is not set @@ -540,12 +627,9 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # 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 @@ -560,7 +644,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # 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 @@ -591,10 +674,11 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_BL_MCU_SDK is not set # CONFIG_PKG_USING_SOFT_SERIAL is not set # CONFIG_PKG_USING_MB85RS16 is not set -# CONFIG_PKG_USING_CW2015 is not set # CONFIG_PKG_USING_RFM300 is not set # CONFIG_PKG_USING_IO_INPUT_FILTER is not set # CONFIG_PKG_USING_RASPBERRYPI_PICO_SDK is not set +# CONFIG_PKG_USING_LRF_NV7LIDAR is not set +# CONFIG_PKG_USING_FINGERPRINT is not set # # AI packages @@ -609,6 +693,12 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_QUEST is not set # CONFIG_PKG_USING_NAXOS is not set +# +# Signal Processing and Control Algorithm Packages +# +# CONFIG_PKG_USING_FIRE_PID_CURVE is not set +# CONFIG_PKG_USING_UKAL is not set + # # miscellaneous packages # @@ -660,7 +750,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # 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 @@ -671,63 +760,212 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_SLCAN2RTT is not set # CONFIG_PKG_USING_SOEM is not set # CONFIG_PKG_USING_QPARAM is not set +# CONFIG_PKG_USING_CorevMCU_CLI is not set # -# Privated Packages of RealThread +# Arduino libraries # -# CONFIG_PKG_USING_CODEC is not set -# CONFIG_PKG_USING_PLAYER is not set -# CONFIG_PKG_USING_MPLAYER is not set -# CONFIG_PKG_USING_PERSIMMON_SRC is not set -# CONFIG_PKG_USING_JS_PERSIMMON is not set -# CONFIG_PKG_USING_JERRYSCRIPT_WIN32 is not set +# CONFIG_PKG_USING_RTDUINO is not set # -# Network Utilities +# Projects # -# CONFIG_PKG_USING_WICED is not set -# CONFIG_PKG_USING_CLOUDSDK is not set -# CONFIG_PKG_USING_POWER_MANAGER is not set -# CONFIG_PKG_USING_RT_OTA is not set -# CONFIG_PKG_USING_RTINSIGHT is not set -# CONFIG_PKG_USING_SMARTCONFIG is not set -# CONFIG_PKG_USING_RTX is not set -# CONFIG_RT_USING_TESTCASE is not set -# CONFIG_PKG_USING_NGHTTP2 is not set -# CONFIG_PKG_USING_AVS is not set -# CONFIG_PKG_USING_ALI_LINKKIT is not set -# CONFIG_PKG_USING_STS is not set -# CONFIG_PKG_USING_DLMS is not set -# CONFIG_PKG_USING_AUDIO_FRAMEWORK is not set -# CONFIG_PKG_USING_ZBAR is not set -# CONFIG_PKG_USING_MCF is not set -# CONFIG_PKG_USING_URPC is not set -# CONFIG_PKG_USING_DCM is not set -# CONFIG_PKG_USING_EMQ is not set -# CONFIG_PKG_USING_CFGM is not set -# CONFIG_PKG_USING_RT_CMSIS_DAP is not set -# CONFIG_PKG_USING_SMODULE is not set -# CONFIG_PKG_USING_SNFD is not set -# CONFIG_PKG_USING_UDBD is not set -# CONFIG_PKG_USING_BENCHMARK is not set -# CONFIG_PKG_USING_UBJSON is not set -# CONFIG_PKG_USING_DATATYPE is not set -# CONFIG_PKG_USING_FASTFS is not set -# CONFIG_PKG_USING_RIL is not set -# CONFIG_PKG_USING_WATCH_DCM_SVC is not set -# CONFIG_PKG_USING_WATCH_APP_FWK is not set -# CONFIG_PKG_USING_GUI_TEST is not set -# CONFIG_PKG_USING_PMEM is not set -# CONFIG_PKG_USING_LWRDP is not set -# CONFIG_PKG_USING_MASAN is not set -# CONFIG_PKG_USING_BSDIFF_LIB is not set -# CONFIG_PKG_USING_PRC_DIFF is not set +# CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set +# CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set +# CONFIG_PKG_USING_ARDUINO_MATLAB_SUPPORT is not set # -# RT-Thread Smart +# Sensors +# +# CONFIG_PKG_USING_ARDUINO_SENSOR_DEVICE_DRIVERS is not set +# CONFIG_PKG_USING_ARDUINO_CAPACITIVESENSOR is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL375 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L0X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L1X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSOR is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL6180X is not set +# CONFIG_PKG_USING_ADAFRUIT_MAX31855 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31865 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31856 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX6675 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90614 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS1 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AHTX0 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS0 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADT7410 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME680 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9808 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4728 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA219 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR390 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL345 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DHT is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9600 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM6DS is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO055 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX1704X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMC56X3 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90393 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90395 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ICM20X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DPS310 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTS221 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT4X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT31 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL343 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS726X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AMG88XX is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2320 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2315 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR329_LTR303 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP3XX is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MS8607 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3MDL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90640 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMA8451 is not set +# CONFIG_PKG_USING_ADAFRUIT_MSA301 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL115A2 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X_RVC is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS2MDL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303DLH_MAG is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LC709203F is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CAP1188 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CCS811 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_NAU7802 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS331 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS2X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS35HW is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303_ACCEL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3DH is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8591 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL3115A2 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPR121 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPRLS is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPU6050 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCT2075 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PM25AQI is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_EMC2101 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXAS21002C is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SCD30 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXOS8700 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HMC5883_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP30 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP006 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TLA202X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCS34725 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI7021 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI1145 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP40 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHTC3 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HDC1000 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU21DF is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS7341 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU31D is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSORLAB is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA260 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP007_LIBRARY is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_L3GD20 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP117 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSC2007 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2561 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2591_LIBRARY is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VCNL4040 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6070 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6075 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML7700 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LIS3DHTR is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_DHT is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL335 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL345 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BME280 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BMP280 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_H3LIS331DL is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_MMA7660 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_TSL2561 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_PAJ7620 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_VL53L0X is not set +# CONFIG_PKG_USING_SEEED_ITG3200 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SHT31 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HP20X is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_DRV2605L is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BBM150 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HMC5883L is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LSM303DLH is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_TCS3414CS is not set +# CONFIG_PKG_USING_SEEED_MP503 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BMP085 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HIGHTEMP is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_VEML6070 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SI1145 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SHT35 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_AT42QT1070 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LSM6DS3 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HDC1000 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HM3301 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_MCP9600 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LTC2941 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LDC1612 is not set + +# +# Display +# +# CONFIG_PKG_USING_ARDUINO_U8G2 is not set +# CONFIG_PKG_USING_SEEED_TM1637 is not set + +# +# Timing +# +# CONFIG_PKG_USING_ARDUINO_MSTIMER2 is not set + +# +# Data Processing +# +# CONFIG_PKG_USING_ARDUINO_KALMANFILTER is not set +# CONFIG_PKG_USING_ARDUINO_ARDUINOJSON is not set + +# +# Data Storage +# + +# +# Communication +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PN532 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI4713 is not set + +# +# Device Control +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8574 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCA9685 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_PCF85063TP is not set + +# +# Other +# + +# +# Signal IO +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BUSIO is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCA8418 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP23017 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADS1X15 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AW9523 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP3008 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4725 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BD3491FS is not set + +# +# Uncategorized # -# CONFIG_PKG_USING_UKERNEL is not set -# CONFIG_PKG_USING_TRACE_AGENT is not set CONFIG_SOC_FAMILY_APM32=y CONFIG_SOC_SERIES_APM32F1=y @@ -746,6 +984,8 @@ CONFIG_BSP_USING_UART1=y # CONFIG_BSP_USING_ADC is not set # CONFIG_BSP_USING_DAC is not set # CONFIG_BSP_USING_ONCHIP_RTC is not set +# CONFIG_BSP_RTC_USING_LSE is not set +# CONFIG_BSP_RTC_USING_LSI is not set # CONFIG_BSP_USING_I2C1 is not set # CONFIG_BSP_USING_SPI is not set # CONFIG_BSP_USING_TMR is not set diff --git a/bsp/apm32/apm32f103xe-minibroard/board/linker_scripts/link.lds b/bsp/apm32/apm32f103xe-minibroard/board/linker_scripts/link.lds index 592dad353f..5d1d12bbfb 100644 --- a/bsp/apm32/apm32f103xe-minibroard/board/linker_scripts/link.lds +++ b/bsp/apm32/apm32f103xe-minibroard/board/linker_scripts/link.lds @@ -57,6 +57,7 @@ SECTIONS /* This is used by the startup in order to initialize the .data secion */ _sidata = .; + _start_address_init_data = .; } > CODE __exidx_end = .; @@ -67,6 +68,7 @@ SECTIONS . = ALIGN(4); /* This is used by the startup in order to initialize the .data secion */ _sdata = . ; + _start_address_data = .; *(.data) *(.data.*) @@ -75,6 +77,7 @@ SECTIONS . = ALIGN(4); /* This is used by the startup in order to initialize the .data secion */ _edata = . ; + _end_address_data = .; } >DATA .stack : @@ -85,6 +88,7 @@ SECTIONS } >DATA __bss_start = .; + _start_address_bss = .; .bss : { . = ALIGN(4); @@ -102,6 +106,7 @@ SECTIONS *(.bss.init) } > DATA __bss_end = .; + _end_address_bss = .; _end = .; diff --git a/bsp/apm32/apm32f103xe-minibroard/project.uvoptx b/bsp/apm32/apm32f103xe-minibroard/project.uvoptx index 2b7d33fccd..a6526b52bd 100644 --- a/bsp/apm32/apm32f103xe-minibroard/project.uvoptx +++ b/bsp/apm32/apm32f103xe-minibroard/project.uvoptx @@ -10,7 +10,7 @@ *.s*; *.src; *.a* *.obj; *.o *.lib - *.txt; *.h; *.inc + *.txt; *.h; *.inc; *.md *.plm *.cpp 0 @@ -73,11 +73,11 @@ 0 - 0 + 1 0 1 - 0 + 255 0 1 @@ -171,15 +171,746 @@ + + 1 + 1 + 0 + 2 + 10000000 + - Source Group 1 + Applications 0 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\cctype.c + cctype.c + 0 + 0 + + + 2 + 5 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\cstdio.c + cstdio.c + 0 + 0 + + + 2 + 6 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\cstdlib.c + cstdlib.c + 0 + 0 + + + 2 + 7 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\cstring.c + cstring.c + 0 + 0 + + + 2 + 8 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\ctime.c + ctime.c + 0 + 0 + + + 2 + 9 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\cwchar.c + cwchar.c + 0 + 0 + + + + + CPU + 0 + 0 + 0 + 0 + + 3 + 10 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\div0.c + div0.c + 0 + 0 + + + 3 + 11 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\showmem.c + showmem.c + 0 + 0 + + + 3 + 12 + 2 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m3\context_rvds.S + context_rvds.S + 0 + 0 + + + 3 + 13 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m3\cpuport.c + cpuport.c + 0 + 0 + + + + + DeviceDrivers + 1 + 0 + 0 + 0 + + 4 + 14 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\completion.c + completion.c + 0 + 0 + + + 4 + 15 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\dataqueue.c + dataqueue.c + 0 + 0 + + + 4 + 16 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\pipe.c + pipe.c + 0 + 0 + + + 4 + 17 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\ringblk_buf.c + ringblk_buf.c + 0 + 0 + + + 4 + 18 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\ringbuffer.c + ringbuffer.c + 0 + 0 + + + 4 + 19 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\waitqueue.c + waitqueue.c + 0 + 0 + + + 4 + 20 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\workqueue.c + workqueue.c + 0 + 0 + + + 4 + 21 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\misc\pin.c + pin.c + 0 + 0 + + + 4 + 22 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\serial\serial.c + serial.c + 0 + 0 + + + + + Drivers + 1 + 0 + 0 + 0 + + 5 + 23 + 1 + 1 + 0 + 0 + board\board.c + board.c + 0 + 0 + + + 5 + 24 + 2 + 0 + 0 + 0 + ..\libraries\APM32F10x_Library\Device\Geehy\APM32F10x\Source\arm\startup_apm32f10x_hd.s + startup_apm32f10x_hd.s + 0 + 0 + + + 5 + 25 + 1 + 0 + 0 + 0 + ..\libraries\Drivers\drv_common.c + drv_common.c + 0 + 0 + + + 5 + 26 + 1 + 0 + 0 + 0 + ..\libraries\Drivers\drv_gpio.c + drv_gpio.c + 0 + 0 + + + 5 + 27 + 1 + 0 + 0 + 0 + ..\libraries\Drivers\drv_usart.c + drv_usart.c + 0 + 0 + + + + + Filesystem + 0 + 0 + 0 + 0 + + 6 + 28 + 1 + 0 + 0 + 0 + ..\..\..\components\dfs\src\dfs_posix.c + dfs_posix.c + 0 + 0 + + + 6 + 29 + 1 + 0 + 0 + 0 + ..\..\..\components\dfs\src\dfs_fs.c + dfs_fs.c + 0 + 0 + + + 6 + 30 + 1 + 0 + 0 + 0 + ..\..\..\components\dfs\src\dfs.c + dfs.c + 0 + 0 + + + 6 + 31 + 1 + 0 + 0 + 0 + ..\..\..\components\dfs\src\dfs_file.c + dfs_file.c + 0 + 0 + + + + + Finsh + 0 + 0 + 0 + 0 + + 7 + 32 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\shell.c + shell.c + 0 + 0 + + + 7 + 33 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh.c + msh.c + 0 + 0 + + + 7 + 34 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh_parse.c + msh_parse.c + 0 + 0 + + + 7 + 35 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\cmd.c + cmd.c + 0 + 0 + + + 7 + 36 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh_file.c + msh_file.c + 0 + 0 + + + + + Kernel + 0 + 0 + 0 + 0 + + 8 + 37 + 1 + 0 + 0 + 0 + ..\..\..\src\clock.c + clock.c + 0 + 0 + + + 8 + 38 + 1 + 0 + 0 + 0 + ..\..\..\src\components.c + components.c + 0 + 0 + + + 8 + 39 + 1 + 0 + 0 + 0 + ..\..\..\src\device.c + device.c + 0 + 0 + + + 8 + 40 + 1 + 0 + 0 + 0 + ..\..\..\src\idle.c + idle.c + 0 + 0 + + + 8 + 41 + 1 + 0 + 0 + 0 + ..\..\..\src\ipc.c + ipc.c + 0 + 0 + + + 8 + 42 + 1 + 0 + 0 + 0 + ..\..\..\src\irq.c + irq.c + 0 + 0 + + + 8 + 43 + 1 + 0 + 0 + 0 + ..\..\..\src\kservice.c + kservice.c + 0 + 0 + + + 8 + 44 + 1 + 0 + 0 + 0 + ..\..\..\src\mem.c + mem.c + 0 + 0 + + + 8 + 45 + 1 + 0 + 0 + 0 + ..\..\..\src\mempool.c + mempool.c + 0 + 0 + + + 8 + 46 + 1 + 0 + 0 + 0 + ..\..\..\src\object.c + object.c + 0 + 0 + + + 8 + 47 + 1 + 0 + 0 + 0 + ..\..\..\src\scheduler.c + scheduler.c + 0 + 0 + + + 8 + 48 + 1 + 0 + 0 + 0 + ..\..\..\src\thread.c + thread.c + 0 + 0 + + + 8 + 49 + 1 + 0 + 0 + 0 + ..\..\..\src\timer.c + timer.c + 0 + 0 + + + + + Libraries + 0 + 0 + 0 + 0 + + 9 + 50 + 1 + 0 + 0 + 0 + ..\libraries\APM32F10x_Library\Device\Geehy\APM32F10x\Source\system_apm32f10x.c + system_apm32f10x.c + 0 + 0 + + + 9 + 51 + 1 + 0 + 0 + 0 + ..\libraries\APM32F10x_Library\APM32F10x_StdPeriphDriver\src\apm32f10x_rcm.c + apm32f10x_rcm.c + 0 + 0 + + + 9 + 52 + 1 + 0 + 0 + 0 + ..\libraries\APM32F10x_Library\APM32F10x_StdPeriphDriver\src\apm32f10x_misc.c + apm32f10x_misc.c + 0 + 0 + + + 9 + 53 + 1 + 0 + 0 + 0 + ..\libraries\APM32F10x_Library\APM32F10x_StdPeriphDriver\src\apm32f10x_usart.c + apm32f10x_usart.c + 0 + 0 + + + 9 + 54 + 1 + 0 + 0 + 0 + ..\libraries\APM32F10x_Library\APM32F10x_StdPeriphDriver\src\apm32f10x_eint.c + apm32f10x_eint.c + 0 + 0 + + + 9 + 55 + 1 + 0 + 0 + 0 + ..\libraries\APM32F10x_Library\APM32F10x_StdPeriphDriver\src\apm32f10x_gpio.c + apm32f10x_gpio.c + 0 + 0 + diff --git a/bsp/apm32/apm32f103xe-minibroard/project.uvprojx b/bsp/apm32/apm32f103xe-minibroard/project.uvprojx index 0fee2a3843..2136f3fc49 100644 --- a/bsp/apm32/apm32f103xe-minibroard/project.uvprojx +++ b/bsp/apm32/apm32f103xe-minibroard/project.uvprojx @@ -1,43 +1,46 @@ + 2.1 +
### uVision Project, (C) Keil Software
+ rt-thread 0x4 ARM-ADS - 5060750::V5.06 update 6 (build 750)::ARMCC + 5060960::V5.06 update 7 (build 960)::.\ARMCC 0 APM32F103ZE Geehy - Geehy.APM32F1xx_DFP.1.0.8 + Geehy.APM32F1xx_DFP.1.0.9 https://www.geehy.com/uploads/tool/ IRAM(0x20000000,0x00020000) IROM(0x08000000,0x00080000) CPUTYPE("Cortex-M3") CLOCK(12000000) ELITTLE - - + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0APM32F10x_512 -FS08000000 -FL080000 -FP0($$Device:APM32F103ZE$Flash\APM32F10x_512.FLM)) 0 $$Device:APM32F103ZE$Device\Include\apm32f10x.h - - - - - - - - - + + + + + + + + + $$Device:APM32F103ZE$SVD\APM32F103xx.svd 0 0 - - - - - + + + + + 0 0 @@ -49,9 +52,9 @@ rtthread 1 0 - 0 + 1 1 - 0 + 1 .\build\keil\List\ 1 0 @@ -59,8 +62,8 @@ 0 0 - - + + 0 0 0 @@ -69,8 +72,8 @@ 0 0 - - + + 0 0 0 @@ -80,14 +83,14 @@ 1 0 fromelf --bin !L --output rtthread.bin - + 0 0 0 0 0 - + 0 @@ -101,8 +104,8 @@ 0 0 3 - - + + 1 @@ -111,7 +114,7 @@ DCM.DLL -pCM3 SARMCM3.DLL - + TCM.DLL -pCM3 @@ -135,11 +138,11 @@ 1 BIN\UL2CM3.DLL - - - - - + + + + + 0 @@ -172,7 +175,7 @@ 0 0 "Cortex-M3" - + 0 0 0 @@ -182,6 +185,7 @@ 0 0 0 + 0 0 0 8 @@ -305,7 +309,7 @@ 0x0 - + 1 @@ -332,10 +336,10 @@ 0 0 - - __STDC_LIMIT_MACROS, USE_STDPERIPH_DRIVER, RT_USING_LIBC, __CLK_TCK=RT_TICK_PER_SECOND, __RTTHREAD__, RT_USING_ARM_LIBC, APM32F10X_HD - - applications;..\..\..\components\libc\compilers\common\include;..\..\..\components\libc\compilers\common\extension;..\..\..\components\libc\compilers\common\extension\fcntl\octal;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m3;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\Drivers;..\libraries\Drivers\config;..\..\..\components\dfs\include;..\..\..\components\finsh;.;..\..\..\include;..\libraries\APM32F10x_Library\Device\Geehy\APM32F10x\Include;..\libraries\APM32F10x_Library\APM32F10x_StdPeriphDriver\inc;..\libraries\APM32F10x_Library\CMSIS\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\io\stdio;..\..\..\components\libc\posix\ipc + + __STDC_LIMIT_MACROS, RT_USING_ARMLIBC, USE_STDPERIPH_DRIVER, RT_USING_LIBC, __CLK_TCK=RT_TICK_PER_SECOND, __RTTHREAD__, APM32F10X_HD + + ..\..\..\components\finsh;..\..\..\components\libc\posix\io\poll;..\libraries\APM32F10x_Library\APM32F10x_StdPeriphDriver\inc;..\libraries\APM32F10x_Library\CMSIS\Include;..\libraries\Drivers;..\..\..\components\libc\compilers\common\extension\fcntl\octal;board;..\libraries\APM32F10x_Library\Device\Geehy\APM32F10x\Include;..\..\..\components\libc\compilers\common\include;..\..\..\libcpu\arm\cortex-m3;..\..\..\components\drivers\include;..\..\..\components\libc\posix\ipc;..\..\..\libcpu\arm\common;..\..\..\components\libc\posix\io\stdio;applications;..\..\..\components\dfs\include;..\libraries\Drivers\config;..\..\..\components\drivers\include;..\libraries\APM32F10x_Library\APM32F10x_ETH_Driver\inc;..\..\..\include;..\..\..\components\drivers\include;..\..\..\components\libc\compilers\common\extension;. @@ -348,12 +352,12 @@ 0 0 0 - 0 + 4 - - - - + + + + @@ -365,13 +369,13 @@ 0 0x08000000 0x20000000 - + .\board\linker_scripts\link.sct - - - - - + + + + + @@ -394,50 +398,36 @@ 1 ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - syscalls.c 1 ..\..\..\components\libc\compilers\armlibc\syscalls.c - - cctype.c 1 ..\..\..\components\libc\compilers\common\cctype.c - - cstdio.c 1 ..\..\..\components\libc\compilers\common\cstdio.c - - cstdlib.c 1 ..\..\..\components\libc\compilers\common\cstdlib.c - - cstring.c 1 ..\..\..\components\libc\compilers\common\cstring.c - - ctime.c 1 ..\..\..\components\libc\compilers\common\ctime.c - - cwchar.c 1 @@ -447,35 +437,22 @@ 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-m3\context_rvds.S - - cpuport.c 1 @@ -491,57 +468,41 @@ 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 - - pin.c 1 ..\..\..\components\drivers\misc\pin.c - - serial.c 1 @@ -557,29 +518,21 @@ 1 board\board.c - - startup_apm32f10x_hd.s 2 ..\libraries\APM32F10x_Library\Device\Geehy\APM32F10x\Source\arm\startup_apm32f10x_hd.s - - drv_common.c 1 ..\libraries\Drivers\drv_common.c - - drv_gpio.c 1 ..\libraries\Drivers\drv_gpio.c - - drv_usart.c 1 @@ -595,22 +548,16 @@ 1 ..\..\..\components\dfs\src\dfs_posix.c - - dfs_fs.c 1 ..\..\..\components\dfs\src\dfs_fs.c - - dfs.c 1 ..\..\..\components\dfs\src\dfs.c - - dfs_file.c 1 @@ -626,29 +573,21 @@ 1 ..\..\..\components\finsh\shell.c - - msh.c 1 ..\..\..\components\finsh\msh.c - - msh_parse.c 1 ..\..\..\components\finsh\msh_parse.c - - cmd.c 1 ..\..\..\components\finsh\cmd.c - - msh_file.c 1 @@ -664,85 +603,61 @@ 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 - - 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 @@ -758,36 +673,26 @@ 1 ..\libraries\APM32F10x_Library\Device\Geehy\APM32F10x\Source\system_apm32f10x.c - - apm32f10x_rcm.c 1 ..\libraries\APM32F10x_Library\APM32F10x_StdPeriphDriver\src\apm32f10x_rcm.c - - apm32f10x_misc.c 1 ..\libraries\APM32F10x_Library\APM32F10x_StdPeriphDriver\src\apm32f10x_misc.c - - apm32f10x_usart.c 1 ..\libraries\APM32F10x_Library\APM32F10x_StdPeriphDriver\src\apm32f10x_usart.c - - apm32f10x_eint.c 1 ..\libraries\APM32F10x_Library\APM32F10x_StdPeriphDriver\src\apm32f10x_eint.c - - apm32f10x_gpio.c 1 @@ -798,9 +703,11 @@ + - - - + + + +
diff --git a/bsp/apm32/apm32f103xe-minibroard/rtconfig.h b/bsp/apm32/apm32f103xe-minibroard/rtconfig.h index 621d91fdfd..51d71acfff 100644 --- a/bsp/apm32/apm32f103xe-minibroard/rtconfig.h +++ b/bsp/apm32/apm32f103xe-minibroard/rtconfig.h @@ -47,9 +47,9 @@ #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 128 #define RT_CONSOLE_DEVICE_NAME "uart1" -#define RT_VER_NUM 0x40101 -#define ARCH_ARM +#define RT_VER_NUM 0x50000 #define RT_USING_CPU_FFS +#define ARCH_ARM #define ARCH_ARM_CORTEX_M #define ARCH_ARM_CORTEX_M3 @@ -82,6 +82,7 @@ /* Device Drivers */ #define RT_USING_DEVICE_IPC +#define RT_UNAMED_PIPE_NUMBER 64 #define RT_USING_SERIAL #define RT_USING_SERIAL_V1 #define RT_SERIAL_USING_DMA @@ -170,6 +171,11 @@ /* peripheral libraries and drivers */ +/* sensors drivers */ + + +/* touch drivers */ + /* Kendryte SDK */ @@ -177,6 +183,9 @@ /* AI packages */ +/* Signal Processing and Control Algorithm Packages */ + + /* miscellaneous packages */ /* project laboratory */ @@ -187,13 +196,38 @@ /* entertainment: terminal games and other interesting software packages */ -/* Privated Packages of RealThread */ +/* Arduino libraries */ -/* Network Utilities */ +/* Projects */ -/* RT-Thread Smart */ +/* Sensors */ + + +/* Display */ + + +/* Timing */ + + +/* Data Processing */ + + +/* Data Storage */ + +/* Communication */ + + +/* Device Control */ + + +/* Other */ + +/* Signal IO */ + + +/* Uncategorized */ #define SOC_FAMILY_APM32 #define SOC_SERIES_APM32F1 diff --git a/bsp/apm32/apm32f407ig-minibroard/.config b/bsp/apm32/apm32f407ig-minibroard/.config index 158e36b2ff..b1bed341aa 100644 --- a/bsp/apm32/apm32f407ig-minibroard/.config +++ b/bsp/apm32/apm32f407ig-minibroard/.config @@ -8,6 +8,7 @@ # CONFIG_RT_NAME_MAX=8 # CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMART is not set # CONFIG_RT_USING_SMP is not set CONFIG_RT_ALIGN_SIZE=4 # CONFIG_RT_THREAD_PRIORITY_8 is not set @@ -77,16 +78,19 @@ CONFIG_RT_USING_HEAP=y # CONFIG_RT_USING_DEVICE=y # CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_DM 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="uart1" -CONFIG_RT_VER_NUM=0x40101 -CONFIG_ARCH_ARM=y +CONFIG_RT_VER_NUM=0x50000 +# CONFIG_RT_USING_CACHE is not set +# CONFIG_ARCH_ARM_BOOTWITH_FLUSH_CACHE is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set CONFIG_RT_USING_CPU_FFS=y +CONFIG_ARCH_ARM=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 @@ -121,14 +125,16 @@ CONFIG_DFS_FD_MAX=16 # CONFIG_RT_USING_DFS_ELMFAT is not set # CONFIG_RT_USING_DFS_DEVFS is not set # CONFIG_RT_USING_DFS_ROMFS is not set +# CONFIG_RT_USING_DFS_CROMFS is not set # CONFIG_RT_USING_DFS_RAMFS is not set +# CONFIG_RT_USING_DFS_TMPFS 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_UNAMED_PIPE_NUMBER=64 # CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set CONFIG_RT_USING_SERIAL=y CONFIG_RT_USING_SERIAL_V1=y @@ -143,10 +149,14 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64 CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_ADC is not set # CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_NULL is not set +# CONFIG_RT_USING_ZERO is not set +# CONFIG_RT_USING_RANDOM is not set # 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_FDT is not set # CONFIG_RT_USING_RTC is not set # CONFIG_RT_USING_SDIO is not set # CONFIG_RT_USING_SPI is not set @@ -154,10 +164,13 @@ CONFIG_RT_USING_PIN=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_LCD 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_DEV_BUS is not set # CONFIG_RT_USING_WIFI is not set +# CONFIG_RT_USING_VIRTIO is not set # # Using USB @@ -302,6 +315,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # 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_RYANMQTT 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 @@ -309,6 +323,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_SMALL_MODBUS is not set # CONFIG_PKG_USING_NET_SERVER is not set # CONFIG_PKG_USING_ZFTP is not set +# CONFIG_PKG_USING_WOL is not set # # security packages @@ -400,7 +415,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # 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 @@ -434,8 +448,8 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_CBOX is not set # CONFIG_PKG_USING_SNOWFLAKE is not set # CONFIG_PKG_USING_HASH_MATCH is not set -# CONFIG_PKG_USING_FIRE_PID_CURVE is not set # CONFIG_PKG_USING_ARMV7M_DWT_TOOL is not set +# CONFIG_PKG_USING_VOFA_PLUS is not set # # system packages @@ -471,7 +485,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # 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_FREERTOS_WRAPPER is not set # CONFIG_PKG_USING_CAIRO is not set # CONFIG_PKG_USING_PIXMAN is not set @@ -506,19 +519,93 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_KMULTI_RTIMER is not set # CONFIG_PKG_USING_TFDB is not set # CONFIG_PKG_USING_QPC is not set +# CONFIG_PKG_USING_AGILE_UPGRADE is not set # # peripheral libraries and drivers # -# CONFIG_PKG_USING_SENSORS_DRIVERS is not set -# CONFIG_PKG_USING_REALTEK_AMEBA is not set + +# +# sensors drivers +# +# CONFIG_PKG_USING_LSM6DSM is not set +# CONFIG_PKG_USING_LSM6DSL is not set +# CONFIG_PKG_USING_LPS22HB is not set +# CONFIG_PKG_USING_HTS221 is not set +# CONFIG_PKG_USING_LSM303AGR is not set +# CONFIG_PKG_USING_BME280 is not set +# CONFIG_PKG_USING_BME680 is not set +# CONFIG_PKG_USING_BMA400 is not set +# CONFIG_PKG_USING_BMI160_BMX160 is not set +# CONFIG_PKG_USING_SPL0601 is not set +# CONFIG_PKG_USING_MS5805 is not set +# CONFIG_PKG_USING_DA270 is not set +# CONFIG_PKG_USING_DF220 is not set +# CONFIG_PKG_USING_HSHCAL001 is not set +# CONFIG_PKG_USING_BH1750 is not set +# CONFIG_PKG_USING_MPU6XXX is not set +# CONFIG_PKG_USING_AHT10 is not set +# CONFIG_PKG_USING_AP3216C is not set +# CONFIG_PKG_USING_TSL4531 is not set +# CONFIG_PKG_USING_DS18B20 is not set +# CONFIG_PKG_USING_DHT11 is not set +# CONFIG_PKG_USING_DHTXX is not set +# CONFIG_PKG_USING_GY271 is not set +# CONFIG_PKG_USING_GP2Y10 is not set +# CONFIG_PKG_USING_SGP30 is not set +# CONFIG_PKG_USING_HDC1000 is not set +# CONFIG_PKG_USING_BMP180 is not set +# CONFIG_PKG_USING_BMP280 is not set +# CONFIG_PKG_USING_SHTC1 is not set +# CONFIG_PKG_USING_BMI088 is not set +# CONFIG_PKG_USING_HMC5883 is not set +# CONFIG_PKG_USING_MAX6675 is not set +# CONFIG_PKG_USING_TMP1075 is not set +# CONFIG_PKG_USING_SR04 is not set +# CONFIG_PKG_USING_CCS811 is not set +# CONFIG_PKG_USING_PMSXX is not set +# CONFIG_PKG_USING_RT3020 is not set +# CONFIG_PKG_USING_MLX90632 is not set +# CONFIG_PKG_USING_MLX90393 is not set +# CONFIG_PKG_USING_MLX90392 is not set +# CONFIG_PKG_USING_MLX90397 is not set +# CONFIG_PKG_USING_MS5611 is not set +# CONFIG_PKG_USING_MAX31865 is not set +# CONFIG_PKG_USING_VL53L0X is not set +# CONFIG_PKG_USING_INA260 is not set +# CONFIG_PKG_USING_MAX30102 is not set +# CONFIG_PKG_USING_INA226 is not set +# CONFIG_PKG_USING_LIS2DH12 is not set +# CONFIG_PKG_USING_HS300X is not set +# CONFIG_PKG_USING_ZMOD4410 is not set +# CONFIG_PKG_USING_ISL29035 is not set +# CONFIG_PKG_USING_MMC3680KJ is not set +# CONFIG_PKG_USING_QMP6989 is not set +# CONFIG_PKG_USING_BALANCE is not set # CONFIG_PKG_USING_SHT2X is not set # CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AD7746 is not set # CONFIG_PKG_USING_ADT74XX is not set +# CONFIG_PKG_USING_MAX17048 is not set # CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_CW2015 is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_PAJ7620 is not set + +# +# touch drivers +# +# CONFIG_PKG_USING_GT9147 is not set +# CONFIG_PKG_USING_GT1151 is not set +# CONFIG_PKG_USING_GT917S is not set +# CONFIG_PKG_USING_GT911 is not set +# CONFIG_PKG_USING_FT6206 is not set +# CONFIG_PKG_USING_FT5426 is not set +# CONFIG_PKG_USING_FT6236 is not set +# CONFIG_PKG_USING_XPT2046_TOUCH is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set # CONFIG_PKG_USING_STM32_SDIO is not set # CONFIG_PKG_USING_ESP_IDF is not set -# CONFIG_PKG_USING_ICM20608 is not set # CONFIG_PKG_USING_BUTTON is not set # CONFIG_PKG_USING_PCF8574 is not set # CONFIG_PKG_USING_SX12XX is not set @@ -541,12 +628,9 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # 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 @@ -561,7 +645,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # 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 @@ -592,10 +675,11 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_BL_MCU_SDK is not set # CONFIG_PKG_USING_SOFT_SERIAL is not set # CONFIG_PKG_USING_MB85RS16 is not set -# CONFIG_PKG_USING_CW2015 is not set # CONFIG_PKG_USING_RFM300 is not set # CONFIG_PKG_USING_IO_INPUT_FILTER is not set # CONFIG_PKG_USING_RASPBERRYPI_PICO_SDK is not set +# CONFIG_PKG_USING_LRF_NV7LIDAR is not set +# CONFIG_PKG_USING_FINGERPRINT is not set # # AI packages @@ -610,6 +694,12 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_QUEST is not set # CONFIG_PKG_USING_NAXOS is not set +# +# Signal Processing and Control Algorithm Packages +# +# CONFIG_PKG_USING_FIRE_PID_CURVE is not set +# CONFIG_PKG_USING_UKAL is not set + # # miscellaneous packages # @@ -661,7 +751,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # 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 @@ -672,63 +761,212 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_SLCAN2RTT is not set # CONFIG_PKG_USING_SOEM is not set # CONFIG_PKG_USING_QPARAM is not set +# CONFIG_PKG_USING_CorevMCU_CLI is not set # -# Privated Packages of RealThread +# Arduino libraries # -# CONFIG_PKG_USING_CODEC is not set -# CONFIG_PKG_USING_PLAYER is not set -# CONFIG_PKG_USING_MPLAYER is not set -# CONFIG_PKG_USING_PERSIMMON_SRC is not set -# CONFIG_PKG_USING_JS_PERSIMMON is not set -# CONFIG_PKG_USING_JERRYSCRIPT_WIN32 is not set +# CONFIG_PKG_USING_RTDUINO is not set # -# Network Utilities +# Projects # -# CONFIG_PKG_USING_WICED is not set -# CONFIG_PKG_USING_CLOUDSDK is not set -# CONFIG_PKG_USING_POWER_MANAGER is not set -# CONFIG_PKG_USING_RT_OTA is not set -# CONFIG_PKG_USING_RTINSIGHT is not set -# CONFIG_PKG_USING_SMARTCONFIG is not set -# CONFIG_PKG_USING_RTX is not set -# CONFIG_RT_USING_TESTCASE is not set -# CONFIG_PKG_USING_NGHTTP2 is not set -# CONFIG_PKG_USING_AVS is not set -# CONFIG_PKG_USING_ALI_LINKKIT is not set -# CONFIG_PKG_USING_STS is not set -# CONFIG_PKG_USING_DLMS is not set -# CONFIG_PKG_USING_AUDIO_FRAMEWORK is not set -# CONFIG_PKG_USING_ZBAR is not set -# CONFIG_PKG_USING_MCF is not set -# CONFIG_PKG_USING_URPC is not set -# CONFIG_PKG_USING_DCM is not set -# CONFIG_PKG_USING_EMQ is not set -# CONFIG_PKG_USING_CFGM is not set -# CONFIG_PKG_USING_RT_CMSIS_DAP is not set -# CONFIG_PKG_USING_SMODULE is not set -# CONFIG_PKG_USING_SNFD is not set -# CONFIG_PKG_USING_UDBD is not set -# CONFIG_PKG_USING_BENCHMARK is not set -# CONFIG_PKG_USING_UBJSON is not set -# CONFIG_PKG_USING_DATATYPE is not set -# CONFIG_PKG_USING_FASTFS is not set -# CONFIG_PKG_USING_RIL is not set -# CONFIG_PKG_USING_WATCH_DCM_SVC is not set -# CONFIG_PKG_USING_WATCH_APP_FWK is not set -# CONFIG_PKG_USING_GUI_TEST is not set -# CONFIG_PKG_USING_PMEM is not set -# CONFIG_PKG_USING_LWRDP is not set -# CONFIG_PKG_USING_MASAN is not set -# CONFIG_PKG_USING_BSDIFF_LIB is not set -# CONFIG_PKG_USING_PRC_DIFF is not set +# CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set +# CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set +# CONFIG_PKG_USING_ARDUINO_MATLAB_SUPPORT is not set # -# RT-Thread Smart +# Sensors +# +# CONFIG_PKG_USING_ARDUINO_SENSOR_DEVICE_DRIVERS is not set +# CONFIG_PKG_USING_ARDUINO_CAPACITIVESENSOR is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL375 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L0X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L1X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSOR is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL6180X is not set +# CONFIG_PKG_USING_ADAFRUIT_MAX31855 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31865 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31856 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX6675 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90614 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS1 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AHTX0 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS0 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADT7410 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME680 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9808 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4728 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA219 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR390 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL345 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DHT is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9600 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM6DS is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO055 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX1704X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMC56X3 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90393 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90395 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ICM20X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DPS310 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTS221 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT4X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT31 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL343 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS726X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AMG88XX is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2320 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2315 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR329_LTR303 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP3XX is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MS8607 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3MDL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90640 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMA8451 is not set +# CONFIG_PKG_USING_ADAFRUIT_MSA301 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL115A2 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X_RVC is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS2MDL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303DLH_MAG is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LC709203F is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CAP1188 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CCS811 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_NAU7802 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS331 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS2X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS35HW is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303_ACCEL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3DH is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8591 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL3115A2 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPR121 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPRLS is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPU6050 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCT2075 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PM25AQI is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_EMC2101 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXAS21002C is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SCD30 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXOS8700 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HMC5883_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP30 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP006 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TLA202X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCS34725 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI7021 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI1145 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP40 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHTC3 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HDC1000 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU21DF is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS7341 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU31D is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSORLAB is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA260 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP007_LIBRARY is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_L3GD20 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP117 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSC2007 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2561 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2591_LIBRARY is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VCNL4040 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6070 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6075 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML7700 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LIS3DHTR is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_DHT is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL335 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL345 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BME280 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BMP280 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_H3LIS331DL is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_MMA7660 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_TSL2561 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_PAJ7620 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_VL53L0X is not set +# CONFIG_PKG_USING_SEEED_ITG3200 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SHT31 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HP20X is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_DRV2605L is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BBM150 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HMC5883L is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LSM303DLH is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_TCS3414CS is not set +# CONFIG_PKG_USING_SEEED_MP503 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BMP085 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HIGHTEMP is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_VEML6070 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SI1145 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SHT35 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_AT42QT1070 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LSM6DS3 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HDC1000 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HM3301 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_MCP9600 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LTC2941 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LDC1612 is not set + +# +# Display +# +# CONFIG_PKG_USING_ARDUINO_U8G2 is not set +# CONFIG_PKG_USING_SEEED_TM1637 is not set + +# +# Timing +# +# CONFIG_PKG_USING_ARDUINO_MSTIMER2 is not set + +# +# Data Processing +# +# CONFIG_PKG_USING_ARDUINO_KALMANFILTER is not set +# CONFIG_PKG_USING_ARDUINO_ARDUINOJSON is not set + +# +# Data Storage +# + +# +# Communication +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PN532 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI4713 is not set + +# +# Device Control +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8574 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCA9685 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_PCF85063TP is not set + +# +# Other +# + +# +# Signal IO +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BUSIO is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCA8418 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP23017 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADS1X15 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AW9523 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP3008 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4725 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BD3491FS is not set + +# +# Uncategorized # -# CONFIG_PKG_USING_UKERNEL is not set -# CONFIG_PKG_USING_TRACE_AGENT is not set CONFIG_SOC_FAMILY_APM32=y CONFIG_SOC_SERIES_APM32F4=y diff --git a/bsp/apm32/apm32f407ig-minibroard/board/board.h b/bsp/apm32/apm32f407ig-minibroard/board/board.h index 94b48d16e6..6aa61cdc92 100644 --- a/bsp/apm32/apm32f407ig-minibroard/board/board.h +++ b/bsp/apm32/apm32f407ig-minibroard/board/board.h @@ -15,6 +15,7 @@ #include #include "apm32f4xx_gpio.h" +#include "apm32f4xx_syscfg.h" #include "apm32f4xx_rcm.h" #include "apm32f4xx_misc.h" #include "apm32f4xx_rcm.h" diff --git a/bsp/apm32/apm32f407ig-minibroard/project.uvoptx b/bsp/apm32/apm32f407ig-minibroard/project.uvoptx index 287920c063..dc86c0ab26 100644 --- a/bsp/apm32/apm32f407ig-minibroard/project.uvoptx +++ b/bsp/apm32/apm32f407ig-minibroard/project.uvoptx @@ -10,7 +10,7 @@ *.s*; *.src; *.a* *.obj; *.o *.lib - *.txt; *.h; *.inc + *.txt; *.h; *.inc; *.md *.plm *.cpp 0 @@ -175,11 +175,747 @@ - Source Group 1 + Applications 0 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\cctype.c + cctype.c + 0 + 0 + + + 2 + 5 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\cstdio.c + cstdio.c + 0 + 0 + + + 2 + 6 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\cstdlib.c + cstdlib.c + 0 + 0 + + + 2 + 7 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\cstring.c + cstring.c + 0 + 0 + + + 2 + 8 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\ctime.c + ctime.c + 0 + 0 + + + 2 + 9 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\cwchar.c + cwchar.c + 0 + 0 + + + + + CPU + 0 + 0 + 0 + 0 + + 3 + 10 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\div0.c + div0.c + 0 + 0 + + + 3 + 11 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\showmem.c + showmem.c + 0 + 0 + + + 3 + 12 + 2 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + context_rvds.S + 0 + 0 + + + 3 + 13 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + cpuport.c + 0 + 0 + + + + + DeviceDrivers + 0 + 0 + 0 + 0 + + 4 + 14 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\completion.c + completion.c + 0 + 0 + + + 4 + 15 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\dataqueue.c + dataqueue.c + 0 + 0 + + + 4 + 16 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\pipe.c + pipe.c + 0 + 0 + + + 4 + 17 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\ringblk_buf.c + ringblk_buf.c + 0 + 0 + + + 4 + 18 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\ringbuffer.c + ringbuffer.c + 0 + 0 + + + 4 + 19 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\waitqueue.c + waitqueue.c + 0 + 0 + + + 4 + 20 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\ipc\workqueue.c + workqueue.c + 0 + 0 + + + 4 + 21 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\misc\pin.c + pin.c + 0 + 0 + + + 4 + 22 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\serial\serial.c + serial.c + 0 + 0 + + + + + Drivers + 1 + 0 + 0 + 0 + + 5 + 23 + 1 + 0 + 0 + 0 + board\board.c + board.c + 0 + 0 + + + 5 + 24 + 2 + 0 + 0 + 0 + ..\libraries\APM32F4xx_Library\Device\Geehy\APM32F4xx\Source\arm\startup_apm32f40x.s + startup_apm32f40x.s + 0 + 0 + + + 5 + 25 + 1 + 0 + 0 + 0 + ..\libraries\Drivers\drv_common.c + drv_common.c + 0 + 0 + + + 5 + 26 + 1 + 0 + 0 + 0 + ..\libraries\Drivers\drv_gpio.c + drv_gpio.c + 0 + 0 + + + 5 + 27 + 1 + 0 + 0 + 0 + ..\libraries\Drivers\drv_usart.c + drv_usart.c + 0 + 0 + + + + + Filesystem + 0 + 0 + 0 + 0 + + 6 + 28 + 1 + 0 + 0 + 0 + ..\..\..\components\dfs\src\dfs_posix.c + dfs_posix.c + 0 + 0 + + + 6 + 29 + 1 + 0 + 0 + 0 + ..\..\..\components\dfs\src\dfs_fs.c + dfs_fs.c + 0 + 0 + + + 6 + 30 + 1 + 0 + 0 + 0 + ..\..\..\components\dfs\src\dfs.c + dfs.c + 0 + 0 + + + 6 + 31 + 1 + 0 + 0 + 0 + ..\..\..\components\dfs\src\dfs_file.c + dfs_file.c + 0 + 0 + + + + + Finsh + 0 + 0 + 0 + 0 + + 7 + 32 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\shell.c + shell.c + 0 + 0 + + + 7 + 33 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh.c + msh.c + 0 + 0 + + + 7 + 34 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh_parse.c + msh_parse.c + 0 + 0 + + + 7 + 35 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\cmd.c + cmd.c + 0 + 0 + + + 7 + 36 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh_file.c + msh_file.c + 0 + 0 + + + + + Kernel + 0 + 0 + 0 + 0 + + 8 + 37 + 1 + 0 + 0 + 0 + ..\..\..\src\clock.c + clock.c + 0 + 0 + + + 8 + 38 + 1 + 0 + 0 + 0 + ..\..\..\src\components.c + components.c + 0 + 0 + + + 8 + 39 + 1 + 0 + 0 + 0 + ..\..\..\src\device.c + device.c + 0 + 0 + + + 8 + 40 + 1 + 0 + 0 + 0 + ..\..\..\src\idle.c + idle.c + 0 + 0 + + + 8 + 41 + 1 + 0 + 0 + 0 + ..\..\..\src\ipc.c + ipc.c + 0 + 0 + + + 8 + 42 + 1 + 0 + 0 + 0 + ..\..\..\src\irq.c + irq.c + 0 + 0 + + + 8 + 43 + 1 + 0 + 0 + 0 + ..\..\..\src\kservice.c + kservice.c + 0 + 0 + + + 8 + 44 + 1 + 0 + 0 + 0 + ..\..\..\src\mem.c + mem.c + 0 + 0 + + + 8 + 45 + 1 + 0 + 0 + 0 + ..\..\..\src\mempool.c + mempool.c + 0 + 0 + + + 8 + 46 + 1 + 0 + 0 + 0 + ..\..\..\src\object.c + object.c + 0 + 0 + + + 8 + 47 + 1 + 0 + 0 + 0 + ..\..\..\src\scheduler.c + scheduler.c + 0 + 0 + + + 8 + 48 + 1 + 0 + 0 + 0 + ..\..\..\src\thread.c + thread.c + 0 + 0 + + + 8 + 49 + 1 + 0 + 0 + 0 + ..\..\..\src\timer.c + timer.c + 0 + 0 + + + + + Libraries + 1 + 0 + 0 + 0 + + 9 + 50 + 1 + 0 + 0 + 0 + ..\libraries\APM32F4xx_Library\APM32F4xx_StdPeriphDriver\src\apm32f4xx_usart.c + apm32f4xx_usart.c + 0 + 0 + + + 9 + 51 + 1 + 0 + 0 + 0 + ..\libraries\APM32F4xx_Library\APM32F4xx_StdPeriphDriver\src\apm32f4xx_syscfg.c + apm32f4xx_syscfg.c + 0 + 0 + + + 9 + 52 + 1 + 0 + 0 + 0 + ..\libraries\APM32F4xx_Library\APM32F4xx_StdPeriphDriver\src\apm32f4xx_rcm.c + apm32f4xx_rcm.c + 0 + 0 + + + 9 + 53 + 1 + 0 + 0 + 0 + ..\libraries\APM32F4xx_Library\APM32F4xx_StdPeriphDriver\src\apm32f4xx_eint.c + apm32f4xx_eint.c + 0 + 0 + + + 9 + 54 + 1 + 0 + 0 + 0 + ..\libraries\APM32F4xx_Library\APM32F4xx_StdPeriphDriver\src\apm32f4xx_misc.c + apm32f4xx_misc.c + 0 + 0 + + + 9 + 55 + 1 + 0 + 0 + 0 + ..\libraries\APM32F4xx_Library\APM32F4xx_StdPeriphDriver\src\apm32f4xx_gpio.c + apm32f4xx_gpio.c + 0 + 0 + + + 9 + 56 + 1 + 0 + 0 + 0 + ..\libraries\APM32F4xx_Library\Device\Geehy\APM32F4xx\Source\system_apm32f4xx.c + system_apm32f4xx.c + 0 + 0 + diff --git a/bsp/apm32/apm32f407ig-minibroard/project.uvprojx b/bsp/apm32/apm32f407ig-minibroard/project.uvprojx index 2b721ff537..3c06617113 100644 --- a/bsp/apm32/apm32f407ig-minibroard/project.uvprojx +++ b/bsp/apm32/apm32f407ig-minibroard/project.uvprojx @@ -1,43 +1,46 @@ + 2.1 +
### uVision Project, (C) Keil Software
+ rt-thread 0x4 ARM-ADS - 5060750::V5.06 update 6 (build 750)::ARMCC + 5060960::V5.06 update 7 (build 960)::.\ARMCC 0 APM32F407IG Geehy - Geehy.APM32F4xx_DFP.1.0.1 + Geehy.APM32F4xx_DFP.1.0.2 https://www.geehy.com/uploads/tool/ IRAM(0x20000000,0x00020000) IRAM2(0x10000000,0x00010000) IROM(0x08000000,0x00100000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE - - + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0APM32F4xx_1024 -FS08000000 -FL080000 -FP0($$Device:APM32F407IG$Flash\APM32F4xx_1024.FLM)) 0 - - - - - - - - - - + + + + + + + + + + $$Device:APM32F407IG$SVD\APM32F40x.svd 0 0 - - - - - + + + + + 0 0 @@ -59,8 +62,8 @@ 0 0 - - + + 0 0 0 @@ -69,8 +72,8 @@ 0 0 - - + + 0 0 0 @@ -80,14 +83,14 @@ 1 0 fromelf --bin !L --output rtthread.bin - + 0 0 0 0 0 - + 0 @@ -101,8 +104,8 @@ 0 0 3 - - + + 1 @@ -135,11 +138,11 @@ 1 BIN\UL2CM3.DLL - - - - - + + + + + 0 @@ -172,7 +175,7 @@ 0 0 "Cortex-M4" - + 0 0 0 @@ -182,6 +185,7 @@ 0 2 0 + 0 1 0 8 @@ -305,7 +309,7 @@ 0x10000 - + 1 @@ -332,10 +336,10 @@ 0 0 - - __STDC_LIMIT_MACROS, USE_STDPERIPH_DRIVER, RT_USING_LIBC, APM32F40X, __CLK_TCK=RT_TICK_PER_SECOND, __RTTHREAD__, RT_USING_ARM_LIBC - - applications;..\..\..\components\libc\compilers\common\include;..\..\..\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;board;..\libraries\Drivers;..\libraries\Drivers\config;..\..\..\components\dfs\include;..\..\..\components\finsh;.;..\..\..\include;..\libraries\APM32F4xx_Library\Device\Geehy\APM32F4xx\Include;..\libraries\APM32F4xx_Library\APM32F4xx_StdPeriphDriver\inc;..\libraries\APM32F4xx_Library\CMSIS\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\io\stdio;..\..\..\components\libc\posix\ipc + + __STDC_LIMIT_MACROS, RT_USING_ARMLIBC, USE_STDPERIPH_DRIVER, RT_USING_LIBC, APM32F40X, __CLK_TCK=RT_TICK_PER_SECOND, __RTTHREAD__ + + ..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;.;..\libraries\Drivers;..\..\..\components\libc\compilers\common\extension\fcntl\octal;..\..\..\components\finsh;..\..\..\components\libc\compilers\common\include;..\libraries\APM32F4xx_Library\CMSIS\Include;..\libraries\APM32F4xx_Library\Device\Geehy\APM32F4xx\Include;..\..\..\components\drivers\include;board;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\libc\posix\io\stdio;..\..\..\components\dfs\include;applications;..\libraries\Drivers\config;..\..\..\components\drivers\include;..\..\..\include;..\..\..\components\drivers\include;..\libraries\APM32F4xx_Library\APM32F4xx_ETH_Driver\inc;..\..\..\components\libc\compilers\common\extension;..\libraries\APM32F4xx_Library\APM32F4xx_StdPeriphDriver\inc @@ -348,12 +352,12 @@ 0 0 0 - 0 + 4 - - - - + + + + @@ -365,13 +369,13 @@ 0 0x08000000 0x20000000 - + .\board\linker_scripts\link.sct - - - - - + + + + + @@ -394,50 +398,36 @@ 1 ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - syscalls.c 1 ..\..\..\components\libc\compilers\armlibc\syscalls.c - - cctype.c 1 ..\..\..\components\libc\compilers\common\cctype.c - - cstdio.c 1 ..\..\..\components\libc\compilers\common\cstdio.c - - cstdlib.c 1 ..\..\..\components\libc\compilers\common\cstdlib.c - - cstring.c 1 ..\..\..\components\libc\compilers\common\cstring.c - - ctime.c 1 ..\..\..\components\libc\compilers\common\ctime.c - - cwchar.c 1 @@ -447,35 +437,22 @@ 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 @@ -491,57 +468,41 @@ 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 - - pin.c 1 ..\..\..\components\drivers\misc\pin.c - - serial.c 1 @@ -557,29 +518,21 @@ 1 board\board.c - - startup_apm32f40x.s 2 ..\libraries\APM32F4xx_Library\Device\Geehy\APM32F4xx\Source\arm\startup_apm32f40x.s - - drv_common.c 1 ..\libraries\Drivers\drv_common.c - - drv_gpio.c 1 ..\libraries\Drivers\drv_gpio.c - - drv_usart.c 1 @@ -595,22 +548,16 @@ 1 ..\..\..\components\dfs\src\dfs_posix.c - - dfs_fs.c 1 ..\..\..\components\dfs\src\dfs_fs.c - - dfs.c 1 ..\..\..\components\dfs\src\dfs.c - - dfs_file.c 1 @@ -626,29 +573,21 @@ 1 ..\..\..\components\finsh\shell.c - - msh.c 1 ..\..\..\components\finsh\msh.c - - msh_parse.c 1 ..\..\..\components\finsh\msh_parse.c - - cmd.c 1 ..\..\..\components\finsh\cmd.c - - msh_file.c 1 @@ -664,85 +603,61 @@ 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 - - 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 @@ -758,36 +673,31 @@ 1 ..\libraries\APM32F4xx_Library\APM32F4xx_StdPeriphDriver\src\apm32f4xx_usart.c - - + + apm32f4xx_syscfg.c + 1 + ..\libraries\APM32F4xx_Library\APM32F4xx_StdPeriphDriver\src\apm32f4xx_syscfg.c + apm32f4xx_rcm.c 1 ..\libraries\APM32F4xx_Library\APM32F4xx_StdPeriphDriver\src\apm32f4xx_rcm.c - - apm32f4xx_eint.c 1 ..\libraries\APM32F4xx_Library\APM32F4xx_StdPeriphDriver\src\apm32f4xx_eint.c - - apm32f4xx_misc.c 1 ..\libraries\APM32F4xx_Library\APM32F4xx_StdPeriphDriver\src\apm32f4xx_misc.c - - apm32f4xx_gpio.c 1 ..\libraries\APM32F4xx_Library\APM32F4xx_StdPeriphDriver\src\apm32f4xx_gpio.c - - system_apm32f4xx.c 1 @@ -798,9 +708,11 @@ + - - - + + + +
diff --git a/bsp/apm32/apm32f407ig-minibroard/rtconfig.h b/bsp/apm32/apm32f407ig-minibroard/rtconfig.h index 1cd86165d6..2ad4c524dd 100644 --- a/bsp/apm32/apm32f407ig-minibroard/rtconfig.h +++ b/bsp/apm32/apm32f407ig-minibroard/rtconfig.h @@ -47,9 +47,9 @@ #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 128 #define RT_CONSOLE_DEVICE_NAME "uart1" -#define RT_VER_NUM 0x40101 -#define ARCH_ARM +#define RT_VER_NUM 0x50000 #define RT_USING_CPU_FFS +#define ARCH_ARM #define ARCH_ARM_CORTEX_M #define ARCH_ARM_CORTEX_M4 @@ -82,6 +82,7 @@ /* Device Drivers */ #define RT_USING_DEVICE_IPC +#define RT_UNAMED_PIPE_NUMBER 64 #define RT_USING_SERIAL #define RT_USING_SERIAL_V1 #define RT_SERIAL_USING_DMA @@ -170,6 +171,11 @@ /* peripheral libraries and drivers */ +/* sensors drivers */ + + +/* touch drivers */ + /* Kendryte SDK */ @@ -177,6 +183,9 @@ /* AI packages */ +/* Signal Processing and Control Algorithm Packages */ + + /* miscellaneous packages */ /* project laboratory */ @@ -187,13 +196,38 @@ /* entertainment: terminal games and other interesting software packages */ -/* Privated Packages of RealThread */ +/* Arduino libraries */ -/* Network Utilities */ +/* Projects */ -/* RT-Thread Smart */ +/* Sensors */ + + +/* Display */ + + +/* Timing */ + + +/* Data Processing */ + + +/* Data Storage */ + +/* Communication */ + + +/* Device Control */ + + +/* Other */ + +/* Signal IO */ + + +/* Uncategorized */ #define SOC_FAMILY_APM32 #define SOC_SERIES_APM32F4 diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_adc.h b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_adc.h new file mode 100644 index 0000000000..7f4612556a --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_adc.h @@ -0,0 +1,364 @@ +/*! + * @file apm32f0xx_adc.h + * + * @brief This file contains all the functions prototypes for the ADC firmware library + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __APM32F0XX_ADC_H +#define __APM32F0XX_ADC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes */ +#include "apm32f0xx.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup ADC_Driver + @{ +*/ + +/** @defgroup ADC_Macros Macros + @{ +*/ + +/* ADC_channels */ +#define ADC_Channel_TempSensor ((uint32_t)ADC_CHANNEL_16) /*!< ADC TempSensor Channel definition */ +#define ADC_Channel_Vrefint ((uint32_t)ADC_CHANNEL_17) /*!< ADC Vrefint Channel definition */ +#define ADC_Channel_Vbat ((uint32_t)ADC_CHANNEL_18) /*!< ADC Vbat Channel definition */ + +/* ADC CFG mask */ +#define CFG1_CLEAR_MASK ((uint32_t)0xFFFFD203) + +/* Calibration time out */ +#define CALIBRATION_TIMEOUT ((uint32_t)0x0000F000) + +/**@} end of group ADC_Macros */ + +/** @defgroup ADC_Enumerations Enumerations + @{ +*/ + +/** + * @brief ADC conversion mode + */ +typedef enum +{ + ADC_CONVERSION_SINGLE = ((uint8_t)0), /*!< Single conversion mode */ + ADC_CONVERSION_CONTINUOUS = ((uint8_t)1), /*!< Continuous conversion mode */ +} ADC_CONVERSION_T; + +/** + * @brief ADC Jitter + */ +typedef enum +{ + ADC_JITTER_PCLKDIV2 = ((uint8_t)0x01), /*!< ADC clocked by PCLK div2 */ + ADC_JITTER_PCLKDIV4 = ((uint8_t)0x02), /*!< ADC clocked by PCLK div4 */ +} ADC_JITTER_T; + +/** + * @brief ADC clock mode + */ +typedef enum +{ + ADC_CLOCK_MODE_ASYNCLK = ((uint8_t)0x00), /*!< ADC Asynchronous clock mode */ + ADC_CLOCK_MODE_SYNCLKDIV2 = ((uint8_t)0x01), /*!< Synchronous clock mode divided by 2 */ + ADC_CLOCK_MODE_SYNCLKDIV4 = ((uint8_t)0x02), /*!< Synchronous clock mode divided by 4 */ +} ADC_CLOCK_MODE_T; + +/** + * @brief ADC data resolution + */ +typedef enum +{ + ADC_RESOLUTION_12B = ((uint8_t)0x00), /*!< ADC Resolution is 12 bits */ + ADC_RESOLUTION_10B = ((uint8_t)0x01), /*!< ADC Resolution is 10 bits */ + ADC_RESOLUTION_8B = ((uint8_t)0x02), /*!< ADC Resolution is 8 bits */ + ADC_RESOLUTION_6B = ((uint8_t)0x03), /*!< ADC Resolution is 6 bits */ +} ADC_RESOLUTION_T; + +/** + * @brief ADC data alignment + */ +typedef enum +{ + ADC_DATA_ALIGN_RIGHT = ((uint8_t)0), /*!< Data alignment right */ + ADC_DATA_ALIGN_LEFT = ((uint8_t)1), /*!< Data alignment left */ +} ADC_DATA_ALIGN_T; + +/** + * @brief ADC scan sequence direction + */ +typedef enum +{ + ADC_SCAN_DIR_UPWARD = ((uint8_t)0), /*!< from CHSEL0 to CHSEL17 */ + ADC_SCAN_DIR_BACKWARD = ((uint8_t)1), /*!< from CHSEL17 to CHSEL0 */ +} ADC_SCAN_DIR_T; + +/** + * @brief ADC DMA Mode + */ +typedef enum +{ + ADC_DMA_MODE_ONESHOUT = ((uint8_t)0), /*!< ADC DMA Mode Select one shot */ + ADC_DMA_MODE_CIRCULAR = ((uint8_t)1), /*!< ADC DMA Mode Select circular */ +} ADC_DMA_MODE_T; + +/** + * @brief ADC external conversion trigger edge selectio + */ +typedef enum +{ + ADC_EXT_TRIG_EDGE_NONE = ((uint8_t)0x00), /*!< ADC External Trigger Conversion mode disabled */ + ADC_EXT_TRIG_EDGE_RISING = ((uint8_t)0x01), /*!< ADC External Trigger Conversion mode rising edge */ + ADC_EXT_TRIG_EDGE_FALLING = ((uint8_t)0x02), /*!< ADC External Trigger Conversion mode falling edge */ + ADC_EXT_TRIG_EDGE_ALL = ((uint8_t)0x03), /*!< ADC External Trigger Conversion mode rising and falling edges */ +} ADC_EXT_TRIG_EDGE_T; + +/** + * @brief ADC external trigger sources selection + */ +typedef enum +{ + ADC_EXT_TRIG_CONV_TRG0 = ((uint8_t)0x00), /*!< ADC External Trigger Conversion timer1 TRG0 */ + ADC_EXT_TRIG_CONV_TRG1 = ((uint8_t)0x01), /*!< ADC External Trigger Conversion timer1 CC4 */ + ADC_EXT_TRIG_CONV_TRG2 = ((uint8_t)0x02), /*!< ADC External Trigger Conversion timer2 TRGO */ + ADC_EXT_TRIG_CONV_TRG3 = ((uint8_t)0x03), /*!< ADC External Trigger Conversion timer3 TRG0 */ + ADC_EXT_TRIG_CONV_TRG4 = ((uint8_t)0x04), /*!< ADC External Trigger Conversion timer15 TRG0 */ +} ADC_EXT_TRIG_CONV_T; + +/** + * @brief ADC analog watchdog channel selection + */ +typedef enum +{ + ADC_ANALG_WDT_CHANNEL_0 = ((uint8_t)0x00), /*!< AWD Channel 0 */ + ADC_ANALG_WDT_CHANNEL_1 = ((uint8_t)0x01), /*!< AWD Channel 1 */ + ADC_ANALG_WDT_CHANNEL_2 = ((uint8_t)0x02), /*!< AWD Channel 2 */ + ADC_ANALG_WDT_CHANNEL_3 = ((uint8_t)0x03), /*!< AWD Channel 3 */ + ADC_ANALG_WDT_CHANNEL_4 = ((uint8_t)0x04), /*!< AWD Channel 4 */ + ADC_ANALG_WDT_CHANNEL_5 = ((uint8_t)0x05), /*!< AWD Channel 5 */ + ADC_ANALG_WDT_CHANNEL_6 = ((uint8_t)0x06), /*!< AWD Channel 6 */ + ADC_ANALG_WDT_CHANNEL_7 = ((uint8_t)0x07), /*!< AWD Channel 7 */ + ADC_ANALG_WDT_CHANNEL_8 = ((uint8_t)0x08), /*!< AWD Channel 8 */ + ADC_ANALG_WDT_CHANNEL_9 = ((uint8_t)0x09), /*!< AWD Channel 9 */ + ADC_ANALG_WDT_CHANNEL_10 = ((uint8_t)0x0A), /*!< AWD Channel 10 */ + ADC_ANALG_WDT_CHANNEL_11 = ((uint8_t)0x0B), /*!< AWD Channel 11 */ + ADC_ANALG_WDT_CHANNEL_12 = ((uint8_t)0x0C), /*!< AWD Channel 12 */ + ADC_ANALG_WDT_CHANNEL_13 = ((uint8_t)0x0D), /*!< AWD Channel 13 */ + ADC_ANALG_WDT_CHANNEL_14 = ((uint8_t)0x0E), /*!< AWD Channel 14 */ + ADC_ANALG_WDT_CHANNEL_15 = ((uint8_t)0x0F), /*!< AWD Channel 15 */ + ADC_ANALG_WDT_CHANNEL_16 = ((uint8_t)0x10), /*!< AWD Channel 16 */ + ADC_ANALG_WDT_CHANNEL_17 = ((uint8_t)0x11), /*!< AWD Channel 17 */ + ADC_ANALG_WDT_CHANNEL_18 = ((uint8_t)0x12), /*!< AWD Channel 18 */ +} ADC_ANALG_WDT_CHANNEL_T; + +/** + * @brief ADC sampling times + */ +typedef enum +{ + ADC_SAMPLE_TIME_1_5 = ((uint8_t)0x00), /*!< 1.5 ADC clock cycles */ + ADC_SAMPLE_TIME_7_5 = ((uint8_t)0x01), /*!< 7.5 ADC clock cycles */ + ADC_SAMPLE_TIME_13_5 = ((uint8_t)0x02), /*!< 13.5 ADC clock cycles */ + ADC_SAMPLE_TIME_28_5 = ((uint8_t)0x03), /*!< 28.5 ADC clock cycles */ + ADC_SAMPLE_TIME_41_5 = ((uint8_t)0x04), /*!< 41.5 ADC clock cycles */ + ADC_SAMPLE_TIME_55_5 = ((uint8_t)0x05), /*!< 55.5 ADC clock cycles */ + ADC_SAMPLE_TIME_71_5 = ((uint8_t)0x06), /*!< 71.5 ADC clock cycles */ + ADC_SAMPLE_TIME_239_5 = ((uint8_t)0x07), /*!< 239.5 ADC clock cycles */ +} ADC_SAMPLE_TIME_T; + +/** + * @brief ADC channel selection + */ +typedef enum +{ + ADC_CHANNEL_0 = ((uint32_t)0x00000001), /*!< ADC Channel 0 */ + ADC_CHANNEL_1 = ((uint32_t)0x00000002), /*!< ADC Channel 1 */ + ADC_CHANNEL_2 = ((uint32_t)0x00000004), /*!< ADC Channel 2 */ + ADC_CHANNEL_3 = ((uint32_t)0x00000008), /*!< ADC Channel 3 */ + ADC_CHANNEL_4 = ((uint32_t)0x00000010), /*!< ADC Channel 4 */ + ADC_CHANNEL_5 = ((uint32_t)0x00000020), /*!< ADC Channel 5 */ + ADC_CHANNEL_6 = ((uint32_t)0x00000040), /*!< ADC Channel 6 */ + ADC_CHANNEL_7 = ((uint32_t)0x00000080), /*!< ADC Channel 7 */ + ADC_CHANNEL_8 = ((uint32_t)0x00000100), /*!< ADC Channel 8 */ + ADC_CHANNEL_9 = ((uint32_t)0x00000200), /*!< ADC Channel 9 */ + ADC_CHANNEL_10 = ((uint32_t)0x00000400), /*!< ADC Channel 10 */ + ADC_CHANNEL_11 = ((uint32_t)0x00000800), /*!< ADC Channel 11 */ + ADC_CHANNEL_12 = ((uint32_t)0x00001000), /*!< ADC Channel 12 */ + ADC_CHANNEL_13 = ((uint32_t)0x00002000), /*!< ADC Channel 13 */ + ADC_CHANNEL_14 = ((uint32_t)0x00004000), /*!< ADC Channel 14 */ + ADC_CHANNEL_15 = ((uint32_t)0x00008000), /*!< ADC Channel 15 */ + ADC_CHANNEL_16 = ((uint32_t)0x00010000), /*!< ADC Channel 16 */ + ADC_CHANNEL_17 = ((uint32_t)0x00020000), /*!< ADC Channel 17 */ + ADC_CHANNEL_18 = ((uint32_t)0x00040000), /*!< ADC Channel 18 (Not for APM32F030 devices) */ +} ADC_CHANNEL_T; + +/** + * @brief ADC interrupts definition + */ +typedef enum +{ + ADC_INT_ADRDY = ((uint8_t)0x01), /*!< ADC ready interrupt */ + ADC_INT_CSMP = ((uint8_t)0x02), /*!< End of sampling interrupt */ + ADC_INT_CC = ((uint8_t)0x04), /*!< End of conversion interrupt */ + ADC_INT_CS = ((uint8_t)0x08), /*!< End of sequence interrupt */ + ADC_INT_OVR = ((uint8_t)0x10), /*!< ADC overrun interrupt */ + ADC_INT_AWD = ((uint8_t)0x80), /*!< Analog watchdog interrupt */ +} ADC_INT_T; + +/** + * @brief ADC Interrupt flag + */ +typedef enum +{ + ADC_INT_FLAG_ADRDY = ((uint8_t)0x01), /*!< ADC ready interrupt flag */ + ADC_INT_FLAG_CSMP = ((uint8_t)0x02), /*!< End of sampling interrupt flag */ + ADC_INT_FLAG_CC = ((uint8_t)0x04), /*!< End of conversion interrupt flag */ + ADC_INT_FLAG_CS = ((uint8_t)0x08), /*!< End of sequence interrupt flag */ + ADC_INT_FLAG_OVR = ((uint8_t)0x10), /*!< ADC overrun interrupt flag */ + ADC_INT_FLAG_AWD = ((uint8_t)0x80), /*!< Analog watchdog interrupt flag */ +} ADC_INT_FLAG_T; + +/** + * @brief ADC flag + */ +typedef enum +{ + ADC_FLAG_ADCON = ((uint32_t)0x01000001), /*!< ADC enable flag */ + ADC_FLAG_ADCOFF = ((uint32_t)0x01000002), /*!< ADC disable flag */ + ADC_FLAG_ADCSTA = ((uint32_t)0x01000004), /*!< ADC start conversion flag */ + ADC_FLAG_ADCSTOP = ((uint32_t)0x01000010), /*!< ADC stop conversion flag */ + ADC_FLAG_ADCCAL = ((int) 0x81000000), /*!< ADC calibration flag */ + ADC_FLAG_ADRDY = ((uint8_t)0x01), /*!< ADC ready flag */ + ADC_FLAG_CSMP = ((uint8_t)0x02), /*!< End of sampling flag */ + ADC_FLAG_CC = ((uint8_t)0x04), /*!< End of conversion flag */ + ADC_FLAG_CS = ((uint8_t)0x08), /*!< End of sequence flag */ + ADC_FLAG_OVR = ((uint8_t)0x10), /*!< ADC overrun flag */ + ADC_FLAG_AWD = ((uint8_t)0x80), /*!< Analog watchdog flag */ +} ADC_FLAG_T; + +/**@} end of group ADC_Enumerations */ + +/** @defgroup ADC_Structures Structures + @{ +*/ + +/** + * @brief ADC Config struct definition + */ +typedef struct +{ + ADC_RESOLUTION_T resolution; /*!< Specifies the ADC data resolution */ + ADC_DATA_ALIGN_T dataAlign; /*!< Specifies the data alignment mode */ + ADC_SCAN_DIR_T scanDir; /*!< Specifies the scan mode */ + ADC_CONVERSION_T convMode; /*!< Specifies the conversion mode */ + ADC_EXT_TRIG_CONV_T extTrigConv; /*!< Specifies the external trigger sources */ + ADC_EXT_TRIG_EDGE_T extTrigEdge; /*!< Specifies the external conversion trigger edge */ +} ADC_Config_T; + +/**@} end of group ADC_Structures */ + +/** @defgroup ADC_Variables Variables + @{ + */ + +/**@} end of group ADC_Variables */ + +/** @defgroup ADC_Functions Functions + @{ +*/ + +/* ADC reset and configuration */ +void ADC_Reset(void); +void ADC_Config(ADC_Config_T* adcConfig); +void ADC_ConfigStructInit(ADC_Config_T* adcConfig); +void ADC_Enable(void); +void ADC_Disable(void); +void ADC_EnableAutoPowerOff(void); +void ADC_DisableAutoPowerOff(void); +void ADC_EnableWaitMode(void); +void ADC_DisableWaitMode(void); +void ADC_ConfigChannel(uint32_t channel, uint8_t sampleTime); +void ADC_EnableContinuousMode(void); +void ADC_DisableContinuousMode(void); +void ADC_EnableDiscMode(void); +void ADC_DisableDiscMode(void); +void ADC_EnableOverrunMode(void); +void ADC_DisableOverrunMode(void); +void ADC_StopConversion(void); +void ADC_StartConversion(void); +void ADC_DMARequestMode(ADC_DMA_MODE_T DMARequestMode); + +/* ADC clock and jitter */ +void ADC_ClockMode(ADC_CLOCK_MODE_T clockMode); +void ADC_EnableJitter(ADC_JITTER_T jitter); +void ADC_DisableJitter(ADC_JITTER_T jitter); + +/* ADC analog watchdog */ +void ADC_EnableAnalogWatchdog(void); +void ADC_DisableAnalogWatchdog(void); +void ADC_AnalogWatchdogLowThreshold(uint16_t lowThreshold); +void ADC_AnalogWatchdogHighThreshold(uint16_t highThreshold); +void ADC_AnalogWatchdogSingleChannel(uint32_t channel); +void ADC_EnableAnalogWatchdogSingleChannel(void); +void ADC_DisableAnalogWatchdogSingleChannel(void); + +/* ADC common configuration */ +void ADC_EnableTempSensor(void); +void ADC_DisableTempSensor(void); +void ADC_EnableVrefint(void); +void ADC_DisableVrefint(void); +void ADC_EnableVbat(void); /*!< Not for APM32F030 devices */ +void ADC_DisableVbat(void); /*!< Not for APM32F030 devices */ + +/* Read data */ +uint32_t ADC_ReadCalibrationFactor(void); +uint16_t ADC_ReadConversionValue(void); + +/* DMA */ +void ADC_EnableDMA(void); +void ADC_DisableDMA(void); + +/* Interrupt and flag */ +void ADC_EnableInterrupt(uint8_t interrupt); +void ADC_DisableInterrupt(uint8_t interrupt); +uint8_t ADC_ReadStatusFlag(ADC_FLAG_T flag); +void ADC_ClearStatusFlag(uint32_t flag); +uint8_t ADC_ReadIntFlag(ADC_INT_FLAG_T flag); +void ADC_ClearIntFlag(uint32_t flag); + +#ifdef __cplusplus +} +#endif + +#endif /* __APM32F0XX_ADC_H */ + +/**@} end of group ADC_Functions */ +/**@} end of group ADC_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_can.h b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_can.h new file mode 100644 index 0000000000..60f1057c8f --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_can.h @@ -0,0 +1,413 @@ +/*! + * @file apm32f0xx_can.h + * + * @brief This file contains all the functions prototypes for the CAN firmware library + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __APM32F0XX_CAN_H +#define __APM32F0XX_CAN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes */ +#include "apm32f0xx.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup CAN_Driver + @{ +*/ + +/** @defgroup CAN_Macros Macros + @{ +*/ + +/**@} end of group CAN_Macros */ + +/** @defgroup CAN_Enumerations Enumerations + @{ +*/ + +/** + * @brief CAN operating mode + */ +typedef enum +{ + CAN_OPERATING_MODE_INIT = ((uint8_t)00), /*!< Initialization mode */ + CAN_OPERATING_MODE_NORMAL = ((uint8_t)01), /*!< Normal mode */ + CAN_OPERATING_MODE_SLEEP = ((uint8_t)02), /*!< sleep mode */ +} CAN_OPERATING_MODE_T; + +/** + * @brief CAN test mode + */ +typedef enum +{ + CAN_MODE_NORMAL = ((uint8_t)00), /*!< normal mode */ + CAN_MODE_LOOPBACK = ((uint8_t)01), /*!< loopback mode */ + CAN_MODE_SILENT = ((uint8_t)02), /*!< silent mode */ + CAN_MODE_SILENT_LOOPBACK = ((uint8_t)03), /*!< loopback combined with silent mode */ +} CAN_MODE_T; + +/** + * @brief CAN filter mode + */ +typedef enum +{ + CAN_FILTER_MODE_IDMASK = ((uint8_t)00), /*!< identifier/mask mode */ + CAN_FILTER_MODE_IDLIST = ((uint8_t)01), /*!< identifier list mode */ +} CAN_FILTER_MODE_T; + +/** + * @brief CAN synchronisation jump width + */ +typedef enum +{ + CAN_SJW_1 = ((uint8_t)00), /*!< 1 time quantum */ + CAN_SJW_2 = ((uint8_t)01), /*!< 2 time quantum */ + CAN_SJW_3 = ((uint8_t)02), /*!< 3 time quantum */ + CAN_SJW_4 = ((uint8_t)03), /*!< 4 time quantum */ +} CAN_SJW_T; + +/** + * @brief CAN_time quantum in bit_segment_1 + */ +typedef enum +{ + CAN_TIME_SEGMENT1_1 = (uint8_t)0x00, /*!< 1 time quanta */ + CAN_TIME_SEGMENT1_2 = (uint8_t)0x01, /*!< 2 time quanta */ + CAN_TIME_SEGMENT1_3 = (uint8_t)0x02, /*!< 3 time quanta */ + CAN_TIME_SEGMENT1_4 = (uint8_t)0x03, /*!< 4 time quanta */ + CAN_TIME_SEGMENT1_5 = (uint8_t)0x04, /*!< 5 time quanta */ + CAN_TIME_SEGMENT1_6 = (uint8_t)0x05, /*!< 6 time quanta */ + CAN_TIME_SEGMENT1_7 = (uint8_t)0x06, /*!< 7 time quanta */ + CAN_TIME_SEGMENT1_8 = (uint8_t)0x07, /*!< 8 time quanta */ + CAN_TIME_SEGMENT1_9 = (uint8_t)0x08, /*!< 9 time quanta */ + CAN_TIME_SEGMENT1_10 = (uint8_t)0x09, /*!< 10 time quanta */ + CAN_TIME_SEGMENT1_11 = (uint8_t)0x0A, /*!< 11 time quanta */ + CAN_TIME_SEGMENT1_12 = (uint8_t)0x0B, /*!< 12 time quanta */ + CAN_TIME_SEGMENT1_13 = (uint8_t)0x0C, /*!< 13 time quanta */ + CAN_TIME_SEGMENT1_14 = (uint8_t)0x0D, /*!< 14 time quanta */ + CAN_TIME_SEGMENT1_15 = (uint8_t)0x0E, /*!< 15 time quanta */ + CAN_TIME_SEGMENT1_16 = (uint8_t)0x0F, /*!< 16 time quanta */ +} CAN_TIME_SEGMENT1_T; + +/** + * @brief CAN_time_quantum_in_bit_segment_2 + */ +typedef enum +{ + CAN_TIME_SEGMENT2_1 = (uint8_t)0x00, /*!< 1 time quanta */ + CAN_TIME_SEGMENT2_2 = (uint8_t)0x01, /*!< 2 time quanta */ + CAN_TIME_SEGMENT2_3 = (uint8_t)0x02, /*!< 3 time quanta */ + CAN_TIME_SEGMENT2_4 = (uint8_t)0x03, /*!< 4 time quanta */ + CAN_TIME_SEGMENT2_5 = (uint8_t)0x04, /*!< 5 time quanta */ + CAN_TIME_SEGMENT2_6 = (uint8_t)0x05, /*!< 6 time quanta */ + CAN_TIME_SEGMENT2_7 = (uint8_t)0x06, /*!< 7 time quanta */ + CAN_TIME_SEGMENT2_8 = (uint8_t)0x07, /*!< 8 time quanta */ +} CAN_TIME_SEGMENT2_T; + +/** + * @brief CAN_filter_scale + */ +typedef enum +{ + CAN_FILTER_SCALE_16BIT = ((uint8_t)0x00), /*!< Two 16-bit filters */ + CAN_FILTER_SCALE_32BIT = ((uint8_t)0x01), /*!< One 32-bit filter */ +} CAN_FILTER_SCALE_T; + +/** + * @brief CAN identifier type + */ +typedef enum +{ + CAN_TYPEID_STD = ((uint32_t)0x00000000), /*!< Standard Id */ + CAN_TYPEID_EXT = ((uint32_t)0x00000004), /*!< Extended Id */ +} CAN_TYPEID_T; + +/** + * @brief CAN_remote_transmission_request + */ +typedef enum +{ + CAN_RTXR_DATA = ((uint32_t)0x00000000), /*!< Data frame */ + CAN_RTXR_REMOTE = ((uint32_t)0x00000002), /*!< Remote frame */ +} CAN_RTXR_T; + +/** + * @brief CAN_transmit_constants + */ +typedef enum +{ + CAN_TX_FAILED = ((uint8_t)0x00), /*!< CAN transmission failed */ + CAN_TX_OK = ((uint8_t)0x01), /*!< CAN transmission succeeded */ + CAN_TX_WAITING = ((uint8_t)0x02), /*!< CAN waiting for transmission */ + CAN_TX_MAILBOX_FULL = ((uint8_t)0x04), /*!< CAN cell did not provide */ +} CAN_TX_T; + +/** + * @brief CAN sleep constants + */ +typedef enum +{ + CAN_SLEEP_FAILED = ((uint8_t)0x00), /*!< CAN did not enter the sleep mode */ + CAN_SLEEP_OK = ((uint8_t)0x01), /*!< CAN entered the sleep mode */ +} CAN_SLEEP_T; + +/** + * @brief CAN wake up constants + */ +typedef enum +{ + CAN_WAKEUP_FAILED = ((uint8_t)0x00), /*!< CAN did not leave the sleep mode */ + CAN_WAKEUP_OK = ((uint8_t)0x01), /*!< CAN leaved the sleep mode */ +} CAN_WUP_T; + +/** + * @brief CAN receive FIFO + */ +typedef enum +{ + CAN_FIFO_0 = ((uint8_t)0x00), /*!< CAN FIFO 0 used to receive */ + CAN_FIFO_1 = ((uint8_t)0x01), /*!< CAN FIFO 1 used to receive */ +} CAN_FIFO_T; + +/** + * @brief CAN_error_Code_constants + */ +typedef enum +{ + CAN_ERROR_CODE_NOERR = ((uint8_t)0x00), /*!< No Error */ + CAN_ERROR_CODE_STUFFERR = ((uint8_t)0x10), /*!< Stuff Error */ + CAN_ERROR_CODE_FORMERR = ((uint8_t)0x20), /*!< Form Error */ + CAN_ERROR_CODE_ACKERR = ((uint8_t)0x30), /*!< Acknowledgment Error */ + CAN_ERROR_CODE_BITRECESSIVEERR = ((uint8_t)0x40), /*!< Bit Recessive Error */ + CAN_ERROR_CODE_BITDOMINANTERR = ((uint8_t)0x50), /*!< Bit Dominant Error */ + CAN_ERROR_CODE_CRCERR = ((uint8_t)0x60), /*!< CRC Error */ + CAN_ERROR_CODE_SOFTWARESETERR = ((uint8_t)0x70), /*!< Software Set Error */ +} CAN_ERROR_CODE_T; + +/** + * @brief Flags + */ +typedef enum +{ + /* Error Flags */ + CAN_FLAG_EWF = ((uint32_t)0x10F00001), /*!< Error Warning Flag */ + CAN_FLAG_EPF = ((uint32_t)0x10F00002), /*!< Error Passive Flag */ + CAN_FLAG_BOF = ((uint32_t)0x10F00004), /*!< Bus-Off Flag */ + CAN_FLAG_LEC = ((uint32_t)0x30F00070), /*!< Last error code Flag */ + /* Operating Mode Flags */ + CAN_FLAG_WUP = ((uint32_t)0x31000008), /*!< Wake up Flag */ + CAN_FLAG_SLAK = ((uint32_t)0x31000012), /*!< Sleep acknowledge Flag */ + /* Transmit Flags */ + CAN_FLAG_RQCP0 = ((uint32_t)0x32000001), /*!< Request MailBox0 Flag */ + CAN_FLAG_RQCP1 = ((uint32_t)0x32000100), /*!< Request MailBox1 Flag */ + CAN_FLAG_RQCP2 = ((uint32_t)0x32010000), /*!< Request MailBox2 Flag */ + /* Receive Flags */ + CAN_FLAG_FMP0 = ((uint32_t)0x14000003), /*!< FIFO 0 Message Pending Flag */ + CAN_FLAG_FF0 = ((uint32_t)0x34000008), /*!< FIFO 0 Full Flag */ + CAN_FLAG_FOV0 = ((uint32_t)0x34000010), /*!< FIFO 0 Overrun Flag */ + CAN_FLAG_FMP1 = ((uint32_t)0x18000003), /*!< FIFO 1 Message Pending Flag */ + CAN_FLAG_FF1 = ((uint32_t)0x38000008), /*!< FIFO 1 Full Flag */ + CAN_FLAG_FOV1 = ((uint32_t)0x38000010), /*!< FIFO 1 Overrun Flag */ +} CAN_FLAG_T; + +/** + * @brief CAN interrupts + */ +typedef enum +{ + CAN_INT_TXME = BIT0, /*!< Transmit mailbox empty Interrupt */ + CAN_INT_F0MP = BIT1, /*!< FIFO 0 message pending Interrupt */ + CAN_INT_F0FUL = BIT2, /*!< FIFO 0 full Interrupt */ + CAN_INT_F0OVR = BIT3, /*!< FIFO 0 overrun Interrupt */ + CAN_INT_F1MP = BIT4, /*!< FIFO 1 message pending Interrupt */ + CAN_INT_F1FUL = BIT5, /*!< FIFO 1 full Interrupt */ + CAN_INT_F1OVR = BIT6, /*!< FIFO 1 overrun Interrupt */ + CAN_INT_EWIE = BIT8, /*!< Error warning Interrupt */ + CAN_INT_EPIE = BIT9, /*!< Error passive Interrupt */ + CAN_INT_BOIE = BIT10, /*!< Bus-off Interrupt */ + CAN_INT_LEC = BIT11, /*!< Last error code Interrupt */ + CAN_INT_ERR = BIT15, /*!< Error Interrupt */ + CAN_INT_WUP = BIT16, /*!< Wake-up Interrupt */ + CAN_INT_SLE = BIT17, /*!< Sleep acknowledge Interrupt */ +} CAN_INT_T; + +typedef enum +{ + CAN_FILTER_NUMBER_0 = 0, /*!< Number 0 of filters */ + CAN_FILTER_NUMBER_1, /*!< Number 1 of filters */ + CAN_FILTER_NUMBER_2, /*!< Number 2 of filters */ + CAN_FILTER_NUMBER_3, /*!< Number 3 of filters */ + CAN_FILTER_NUMBER_4, /*!< Number 4 of filters */ + CAN_FILTER_NUMBER_5, /*!< Number 5 of filters */ + CAN_FILTER_NUMBER_6, /*!< Number 6 of filters */ + CAN_FILTER_NUMBER_7, /*!< Number 7 of filters */ + CAN_FILTER_NUMBER_8, /*!< Number 8 of filters */ + CAN_FILTER_NUMBER_9, /*!< Number 9 of filters */ + CAN_FILTER_NUMBER_10, /*!< Number 10 of filters */ + CAN_FILTER_NUMBER_11, /*!< Number 11 of filters */ + CAN_FILTER_NUMBER_12, /*!< Number 12 of filters */ + CAN_FILTER_NUMBER_13, /*!< Number 13 of filters */ +} CAN_FILTER_NUMBER_T; + +typedef enum +{ + CAN_MAILBOX_0 = ((uint8_t)0x00), /*!< Tx mailbox0 */ + CAN_MAILBOX_1 = ((uint8_t)0x01), /*!< Tx mailbox1 */ + CAN_MAILBOX_2 = ((uint8_t)0x02), /*!< Tx mailbox2 */ +} CAN_MAILBOX_T; + +/**@} end of group CAN_Enumerations */ + +/** @defgroup CAN_Structures Structures + @{ +*/ + +/** + * @brief CAN config structure definition + */ +typedef struct +{ + uint8_t timeTrigComMode; /*!< Enable or disable the time triggered communication mode */ + uint8_t autoBusOffManage; /*!< Enable or disable the automatic bus-off management */ + uint8_t autoWakeUpMode; /*!< Enable or disable the automatic wake-up mode */ + uint8_t nonAutoRetran; /*!< Enable or disable the non-automatic retransmission mode */ + uint8_t rxFIFOLockMode; /*!< Enable or disable the Receive FIFO Locked mode */ + uint32_t txFIFOPriority; /*!< Enable or disable the transmit FIFO priority */ + CAN_MODE_T mode; /*!< Specifies the CAN operating mode */ + CAN_SJW_T syncJumpWidth; /*!< Specifies the maximum number of time quanta the CAN hardware + is allowed to lengthen or shorten a bit to perform resynchronization. */ + CAN_TIME_SEGMENT1_T timeSegment1; /*!< Specifies the number of time quanta in Bit Segment 1 */ + CAN_TIME_SEGMENT2_T timeSegment2; /*!< Specifies the number of time quanta in Bit Segment 2 */ + uint16_t prescaler; /*!< Specifies the length of a time quantum. It can be 1 to 1024 */ +} CAN_Config_T; + +/** + * @brief CAN filter config structure definition + */ +typedef struct +{ + uint16_t filterIdHigh; /*!< Specifies the filter identification number. */ + uint16_t filterIdLow; /*!< Specifies the filter identification number. */ + uint16_t filterMaskIdHigh; /*!< Specifies the filter mask number or identification number. */ + uint16_t filterMaskIdLow; /*!< Specifies the filter mask number or identification number. */ + CAN_FIFO_T filterFIFO; /*!< Specifies the FIFO which will be assigned to the filter. */ + CAN_FILTER_NUMBER_T filterNumber; /*!< Specifies the filter which will be configured. It ranges from 0 to 13. */ + CAN_FILTER_MODE_T filterMode; /*!< Specifies the filter mode to be configured. */ + CAN_FILTER_SCALE_T filterScale; /*!< Specifies the filter scale. */ + uint8_t filterActivation; /*!< Enable or disable the filter. */ +} CAN_FilterConfig_T; + +/** + * @brief CAN Tx message structure definition + */ +typedef struct +{ + uint32_t stanID; /*!< Specifies the standard identifier. */ + uint32_t extenID; /*!< Specifies the extended identifier. */ + CAN_TYPEID_T typeID; /*!< Specifies the type of identifier for the message. */ + CAN_RTXR_T remoteTxReq; /*!< Specifies the type of frame for the message. */ + uint8_t dataLengthCode; /*!< Specifies the length of the frame. It can be a value between 0 to 8. */ + uint8_t data[8]; /*!< Contains the data to be transmitted. It ranges from 0 to 0xFF. */ +} CAN_Tx_Message; + +/** + * @brief CAN Rx message structure definition + */ +typedef struct +{ + uint32_t stanID; /*!< Specifies the standard identifier. */ + uint32_t extenID; /*!< Specifies the extended identifier. */ + CAN_TYPEID_T typeID; /*!< Specifies the type of identifier for the message. */ + CAN_RTXR_T remoteTxReq; /*!< Specifies the type of frame for the message. */ + uint8_t dataLengthCode; /*!< Specifies the length of the frame. It can be a value between 0 to 8. */ + uint8_t data[8]; /*!< Contains the data to be transmitted. It ranges from 0 to 0xFF. */ + uint8_t filterMatchIndex; /*!< Specifies the index of the filter the message stored in the mailbox passes through. */ +} CAN_Rx_Message; + +/**@} end of group CAN_Structures */ + +/** @defgroup CAN_Variables Variables + @{ +*/ + +/**@} end of group CAN_Variables */ + +/** @defgroup CAN_Functions Functions + @{ +*/ + +/* CAN reset and configuration */ +void CAN_Reset(void); +uint8_t CAN_Config(CAN_Config_T* canConfig); +void CAN_ConfigFilter(CAN_FilterConfig_T* filterConfig); +void CAN_ConfigStructInit(CAN_Config_T* canConfig); +void CAN_StartBankSlave(uint8_t bankNumber); +void CAN_EnableDebugFreeze(void); +void CAN_DisableDebugFreeze(void); +void CAN_EnableTTComMode(void); +void CAN_DisableTTComMode(void); + +/* CAN frames transmission */ +uint8_t CAN_TxMessage(CAN_Tx_Message* TxMessage); +uint8_t CAN_TxMessageStatus(CAN_MAILBOX_T TxMailbox); +void CAN_CancelTx(CAN_MAILBOX_T TxMailbox); + +/* CAN frames reception */ +void CAN_RxMessage(uint8_t FIFONumber, CAN_Rx_Message* RxMessage); +void CAN_ReleaseFIFO(uint8_t FIFONumber); +uint8_t CAN_PendingMessage(uint8_t FIFONumber); + +/* CAN operation modes */ +uint8_t CAN_OperatingMode(CAN_OPERATING_MODE_T operatingMode); +uint8_t CAN_SleepMode(void); +uint8_t CAN_WakeUpMode(void); + +/* CAN bus error management */ +uint8_t CAN_ReadLastErrorCode(void); +uint8_t CAN_ReadRxErrorCounter(void); +uint8_t CAN_ReadLSBTxErrorCounter(void); + +/* CAN interrupt and flag */ +void CAN_EnableInterrupt(uint32_t interrupt); +void CAN_DisableInterrupt(uint32_t interrupt); +uint8_t CAN_ReadStatusFlag(CAN_FLAG_T CAN_FLAG); +void CAN_ClearStatusFlag(CAN_FLAG_T flag); +uint8_t CAN_ReadIntFlag(CAN_INT_T interrupt); +void CAN_ClearIntFlag(uint32_t interrupt); + +#ifdef __cplusplus +} +#endif + +#endif /* __APM32F0XX_CAN_H */ + +/**@} end of group CAN_Functions */ +/**@} end of group CAN_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_cec.h b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_cec.h new file mode 100644 index 0000000000..3bf007d3f5 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_cec.h @@ -0,0 +1,231 @@ +/*! + * @file apm32f0xx_cec.h + * + * @brief This file contains all the functions prototypes for the CEC firmware library + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __APM32F0XX_CEC_H +#define __APM32F0XX_CEC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes */ +#include "apm32f0xx.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup CEC_Driver + @{ +*/ + +/** @defgroup CEC_Macros Macros + @{ +*/ + +/**@} end of group CEC_Macros */ + +/** @defgroup CEC_Enumerations Enumerations + @{ +*/ + +/** + * @brief CEC_Signal_Free_Time + */ +typedef enum +{ + CEC_SINGANL_FREETIME_STANDARD = 0x00, /*!< none nominal data bit periods */ + CEC_SINGANL_FREETIME_1T = 0x01, /*!< 0.5 nominal data bit periods */ + CEC_SINGANL_FREETIME_2T = 0x02, /*!< 1.5 nominal data bit periods */ + CEC_SINGANL_FREETIME_3T = 0x03, /*!< 2.5 nominal data bit periods */ + CEC_SINGANL_FREETIME_4T = 0x04, /*!< 3.5 nominal data bit periods */ + CEC_SINGANL_FREETIME_5T = 0x05, /*!< 4.5 nominal data bit periods */ + CEC_SINGANL_FREETIME_6T = 0x06, /*!< 5.5 nominal data bit periods */ + CEC_SINGANL_FREETIME_7T = 0x07, /*!< 6.5 nominal data bit periods */ +} CEC_SIGNAL_FREETIME_T; + +/** + * @brief CEC_RxTolerance + */ +typedef enum +{ + CEC_RX_TOLERANCE_STANDARD = 0x00, /*!< Standard tolerance margin */ + CEC_RX_TOLERANCE_EXTENDED = 0x01 /*!< Extended Tolerance */ +} CEC_RX_TOLERANCE_T; + +/** + * @brief CEC_Stop_Reception + */ +typedef enum +{ + CEC_STOP_RECEPTION_OFF, /*!< CEC Stop Reception Off */ + CEC_STOP_RECEPTION_ON /*!< CEC Stop Reception On */ +} CEC_STOP_RECEPTION_T; + +/** + * @brief CEC_Bit_Rising_Error_Generation + */ +typedef enum +{ + CEC_BIT_RISING_ERR_OFF, /*!< BRE detection does not generate an Error-Bit on the CEC line */ + CEC_BIT_RISING_ERR_ON /*!< BRE detection generates an Error-Bit on the CEC line (if BRESTP is set) */ +} CEC_BIT_RISING_ERR_T; + +/** + * @brief CEC_Long_Bit_Error_Generation + */ +typedef enum +{ + CEC_LONG_PERIOD_ERR_OFF, /*!< LBPE detection does not generate an Error-Bit on the CEC line */ + CEC_LONG_PERIOD_ERR_ON /*!< LBPE detection generates an Error-Bit on the CEC line */ +} CEC_LONG_PERIOD_ERR_T; + +/** + * @brief CEC_BDR_No_Gen + */ +typedef enum +{ + CEC_BROADCAST_NO_ERR_OFF, /*!< Broadcast Bit Rising Error generation turned Off */ + CEC_BROADCAST_NO_ERR_ON /*!< Broadcast Bit Rising Error generation turned On */ +} CEC_BROADCAST_NO_ERR_T; + +/** + * @brief CEC_SFT_Option + */ +typedef enum +{ + CEC_SIGNAL_FREETIME_OPTION_OFF, /*!< SFTCFG timer starts when TXSOM is set by software */ + CEC_SIGNAL_FREETIME_OPTION_ON /*!< SFTCFG timer starts automatically at the end of message transmission/reception */ +} CEC_SIGNAL_FREETIME_OPTION_T; + +/** + * @brief CEC_Interrupt_Configuration_definition + */ +typedef enum +{ + CEC_INT_RXBR = ((uint32_t)0x00000001), /*!< Rx-Byte Received Interrupt */ + CEC_INT_RXEND = ((uint32_t)0x00000002), /*!< End Of Reception Interrupt */ + CEC_INT_RXOVR = ((uint32_t)0x00000004), /*!< Rx-Buffer Overrun Interrupt */ + CEC_INT_BRE = ((uint32_t)0x00000008), /*!< Bit Rising Error Interrupt */ + CEC_INT_SBPE = ((uint32_t)0x00000010), /*!< Short Bit Period Error Interrupt */ + CEC_INT_LBPE = ((uint32_t)0x00000020), /*!< Long Bit Period Error Interrupt */ + CEC_INT_RXACKE = ((uint32_t)0x00000040), /*!< Rx-Missing Acknowledge Error Interrupt */ + CEC_INT_ARBLST = ((uint32_t)0x00000080), /*!< Arbitration Lost Interrupt */ + CEC_INT_TXBR = ((uint32_t)0x00000100), /*!< Tx-Byte Request Interrupt */ + CEC_INT_TXEND = ((uint32_t)0x00000200), /*!< Tx-End Of Message Interrupt */ + CEC_INT_TXUDR = ((uint32_t)0x00000400), /*!< Tx-Underrun Interrupt */ + CEC_INT_TXERR = ((uint32_t)0x00000800), /*!< Tx-Error Interrupt */ + CEC_INT_TXACKE = ((uint32_t)0x00001000), /*!< Tx-Missing Acknowledge Error Interrupt */ +} CEC_INT_T; + +/** + * @brief CEC_STS_register_flags_definition + */ +typedef enum +{ + CEC_FLAG_RXBR = ((uint32_t)0x00000001), /*!< Rx-Byte Received Flag */ + CEC_FLAG_RXEND = ((uint32_t)0x00000002), /*!< End Of Reception Flag */ + CEC_FLAG_RXOVR = ((uint32_t)0x00000004), /*!< Rx-Buffer Overrun Flag */ + CEC_FLAG_BRE = ((uint32_t)0x00000008), /*!< Bit Rising Error Flag */ + CEC_FLAG_SBPE = ((uint32_t)0x00000010), /*!< Short Bit Period Error Flag */ + CEC_FLAG_LBPE = ((uint32_t)0x00000020), /*!< Long Bit Period Error Flag */ + CEC_FLAG_RXACKE = ((uint32_t)0x00000040), /*!< Rx-Missing Acknowledge Error Flag */ + CEC_FLAG_ARBLST = ((uint32_t)0x00000080), /*!< Arbitration Lost Flag */ + CEC_FLAG_TXBR = ((uint32_t)0x00000100), /*!< Tx-Byte Request Flag */ + CEC_FLAG_TXEND = ((uint32_t)0x00000200), /*!< Tx-End Of Message Flag */ + CEC_FLAG_TXUDR = ((uint32_t)0x00000400), /*!< Tx-Underrun Flag */ + CEC_FLAG_TXERR = ((uint32_t)0x00000800), /*!< Tx-Error Flag */ + CEC_FLAG_TXACKE = ((uint32_t)0x00001000), /*!< Tx-Missing Acknowledge Error Flag */ +} CEC_FLAG_T; + +/**@} end of group CEC_Enumerations */ + +/** @defgroup CEC_Structures Structures + @{ +*/ + +/** + * @brief CEC Init structure definition + */ +typedef struct +{ + CEC_SIGNAL_FREETIME_T signalFreeTime; /*!< Signal Free Time */ + CEC_RX_TOLERANCE_T RxTolerance; /*!< Rx-Tolerance */ + CEC_STOP_RECEPTION_T stopReception; /*!< Rx-Stop on Bit Rising Error */ + CEC_BIT_RISING_ERR_T bitRisingError; /*!< Generate Error-Bit on Bit Rising Error */ + CEC_LONG_PERIOD_ERR_T longPeriodError; /*!< Generate Error-Bit on Long Bit Period Error */ + CEC_BROADCAST_NO_ERR_T broadcastrNoGen; /*!< Avoid Error-Bit Generation in Broadcast */ + CEC_SIGNAL_FREETIME_OPTION_T signalFreeTimeOption;/*!< Signal Free Time optional */ +} CEC_Config_T; + +/**@} end of group CEC_Structures */ + +/** @defgroup CEC_Variables Variables + @{ +*/ + +/**@} end of group CEC_Variables */ + +/** @defgroup CEC_Functions Functions + @{ +*/ + +/* CEC reset and configuration */ +void CEC_Reset(void); +void CEC_Config(CEC_Config_T* cecConfig); +void CEC_ConfigStructInit(CEC_Config_T* cecConfig); +void CEC_Enable(void); +void CEC_Disable(void); +void CEC_EnableListenMode(void); +void CEC_DisableListenMode(void); +void CEC_ConfigOwnAddress(uint8_t ownAddress); +void CEC_ClearQwnAddress(void); + +/* Transmit and receive */ +void CEC_TxData(uint8_t Data); +uint8_t CEC_RxData(void); + +/* Config Message */ +void CEC_StartNewMessage(void); +void CEC_CompleteMessage(void); + +/* Interrupt and Flag*/ +void CEC_EnableInterrupt(uint32_t interrupt); +void CEC_DisableInterrupt(uint32_t interrupt); +uint8_t CEC_ReadStatusFlag(uint32_t flag); +void CEC_ClearStatusFlag(uint32_t flag); +uint8_t CEC_ReadIntFlag(uint16_t flag); +void CEC_ClearIntFlag(uint16_t flag); + +#ifdef __cplusplus +} +#endif + +#endif /* __APM32F0XX_CEC_H */ + +/**@} end of group CEC_Functions */ +/**@} end of group CEC_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_comp.h b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_comp.h new file mode 100644 index 0000000000..e4aeff7b8b --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_comp.h @@ -0,0 +1,185 @@ +/*! + * @file apm32f0xx_comp.h + * + * @brief This file contains all the functions prototypes for the COMP firmware library + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __APM32F0XX_COMP_H +#define __APM32F0XX_COMP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes */ +#include "apm32f0xx.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup COMP_Driver + @{ +*/ + +/** @defgroup COMP_Macros Macros + @{ +*/ + +/* Macros description */ +#define COMP_CSTS_COMP1OUT ((uint32_t)0x00004000) /*!< COMP1 output state */ +#define COMP_CSTS_COMP2OUT ((uint32_t)0x40000000) /*!< COMP2 output state */ +#define COMP_OUTPUTLEVEL_HIGH ((uint32_t)0x00004000) /*!< COMP output level vaild high */ +#define COMP_OUTPUTLEVEL_LOW ((uint32_t)0x00000000) /*!< COMP output level vaild low */ + +/**@} end of group COMP_Macros */ + +/** @defgroup COMP_Enumerations Enumerations + @{ +*/ + +/** + * @brief COMP_Selection + */ +typedef enum +{ + COMP_SELECT_COMP1 = ((uint32_t)0x00000000), /*!< COMP1 */ + COMP_SELECT_COMP2 = ((uint32_t)0x00000010) /*!< COMP2 */ +} COMP_SELECT_T; + +/** + * @brief COMP_InvertingInput + */ +typedef enum +{ + COMP_INVERTING_INPUT_1_4VREFINT = 0x00, /*!< 1/4 of VREFINT */ + COMP_INVERTING_INPUT_1_2VREFINT = 0x01, /*!< 1/2 of VREFINT */ + COMP_INVERTING_INPUT_3_4VREFINT = 0x02, /*!< 3/4 of VREFINT */ + COMP_INVERTING_INPUT_VREFINT = 0x03, /*!< VREFINT */ + COMP_INVERTING_INPUT_DAC1 = 0x04, /*!< COMP1_INM4 (PA4 with DAC_OUT1 if enabled) */ + COMP_INVERTING_INPUT_DAC2 = 0x05, /*!< COMP1_INM5 (PA5 with DAC_OUT2 if present and enabled, only for APM32F072 and APM32F091 devices) */ + COMP_INVERTING_INPUT_IO = 0x06, /*!< COMP1_INM6 (PA0) */ +} COMP_INVERTING_INPUT_T; + +/** + * @brief COMP_Output + */ +typedef enum +{ + COMP_OUTPUT_NONE = 0x00, /*!< no selection */ + COMP_OUTPUT_TIM1BKIN = 0x01, /*!< Timer 1 break input */ + COMP_OUTPUT_TIM1IC1 = 0x02, /*!< Timer 1 Input capture 1 */ + COMP_OUTPUT_TIM1OCREFCLR = 0x03, /*!< Timer 1 OCrefclear input */ + COMP_OUTPUT_TIM2IC4 = 0x04, /*!< Timer 2 input capture 4 */ + COMP_OUTPUT_TIM2OCREFCLR = 0x05, /*!< Timer 2 OCrefclear input */ + COMP_OUTPUT_TIM3IC1 = 0x06, /*!< Timer 3 input capture 1 */ + COMP_OUTPUT_TIM3OCREFCLR = 0x07, /*!< Timer 3 OCrefclear input */ +} COMP_OUTPUT_T; + +/** + * @brief COMP_OutputPolarity + */ +typedef enum +{ + COMP_OUTPUTPOL_NONINVERTED, /*!< output is not inverted */ + COMP_OUTPUTPOL_INVERTED /*!< output is inverted */ +} COMP_OUTPUTPOL_T; + +/** + * @brief COMP_Hysteresis + */ +typedef enum +{ + COMP_HYSTERRSIS_NO = 0x00, /*!< No hysteresis */ + COMP_HYSTERRSIS_LOW = 0x01, /*!< Low hysteresis */ + COMP_HYSTERRSIS_MEDIUM = 0x02, /*!< Medium hysteresis */ + COMP_HYSTERRSIS_HIGH = 0x03, /*!< High hysteresis */ +} COMP_HYSTERRSIS_T; + +/** + * @brief COMP_Mode + */ +typedef enum +{ + COMP_MODE_HIGHSPEED = 0x00, /*!< High speed / full power */ + COMP_MODE_MEDIUMSPEED = 0x01, /*!< Medium speed / medium power */ + COMP_MODE_LOWPOWER = 0x02, /*!< Low speed / low-power */ + COMP_MODE_VERYLOW = 0x03 /*!< Very-low speed / ultra-low power */ +} COMP_MODE_T; + +/**@} end of group COMP_Enumerations*/ + +/** @defgroup COMP_Structures Structures + @{ +*/ + +/** + * @brief OMP Config structure definition + */ +typedef struct +{ + COMP_INVERTING_INPUT_T invertingInput; /*!< Comparator inverting input selection */ + COMP_OUTPUT_T output; /*!< Comparator output selection */ + COMP_OUTPUTPOL_T outputPol; /*!< Comparator output polarity */ + COMP_HYSTERRSIS_T hysterrsis; /*!< Comparator hysteresis */ + COMP_MODE_T mode; /*!< Comparator mode */ +} COMP_Config_T; + +/**@} end of group COMP_Structures */ + +/** @defgroup COMP_Variables Variables + @{ + */ + +/**@} end of group COMP_Variables */ + +/** @defgroup COMP_Functions Functions + @{ +*/ + +/* COMP configuration */ +void COMP_Reset(void); +void COMP_Config(COMP_SELECT_T compSelect, COMP_Config_T* compConfig); +void COMP_ConfigStructInit(COMP_Config_T* compConfig); +void COMP_Enable(COMP_SELECT_T compSelect); +void COMP_Disable(COMP_SELECT_T compSelect); +void COMP_EnableSwitch(void); +void COMP_DisableSwitch(void); +uint32_t COMP_ReadOutPutLevel(COMP_SELECT_T compSelect); + +/* Window mode control */ +void COMP_EnableWindow(void); +void COMP_DisnableWindow(void); + +/* COMP configuration locking */ +void COMP_ConfigLOCK(COMP_SELECT_T compSelect); + +#ifdef __cplusplus +} +#endif + +#endif /* __APM32F0XX_COMP_H */ + +/**@} end of group COMP_Functions */ +/**@} end of group COMP_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_crc.h b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_crc.h new file mode 100644 index 0000000000..deaa594a76 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_crc.h @@ -0,0 +1,136 @@ +/*! + * @file apm32f0xx_crc.h + * + * @brief This file contains all the functions prototypes for the CRC firmware library + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __APM32F0XX_CRC_H +#define __APM32F0XX_CRC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes */ +#include "apm32f0xx.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup CRC_Driver + @{ +*/ + +/** @defgroup CRC_Macros Macros + @{ +*/ + +/**@} end of group CRC_Macros */ + +/** @defgroup CRC_Enumerations Enumerations + @{ +*/ + +/** + * @brief CRC Reverse Input Data + */ +typedef enum +{ + CRC_REVERSE_INPUT_DATA_NO = ((uint8_t)0x00), /*!< Bit order not affected */ + CRC_REVERSE_INPUT_DATA_8B = ((uint8_t)0x01), /*!< Bit reversal done by byte */ + CRC_REVERSE_INPUT_DATA_16B = ((uint8_t)0x02), /*!< Bit reversal done by half-word */ + CRC_REVERSE_INPUT_DATA_32B = ((uint8_t)0x03), /*!< Bit reversal done by word */ +} CRC_REVERSE_INPUT_DATA_T; + +/** + * @brief CRC Polynomial Size + */ +typedef enum +{ + CRC_POLYNOMIAL_SIZE_7 = ((uint8_t)0x03), /*!< 7-bit polynomial for CRC calculation */ + CRC_POLYNOMIAL_SIZE_8 = ((uint8_t)0x02), /*!< 8-bit polynomial for CRC calculation */ + CRC_POLYNOMIAL_SIZE_16 = ((uint8_t)0x01), /*!< 16-bit polynomial for CRC calculation */ + CRC_POLYNOMIAL_SIZE_32 = ((uint8_t)0x00), /*!< 32-bit polynomial for CRC calculation */ +} CRC_POLYNOMIAL_SIZE_T; + +/**@} end of group CRC_Enumerations*/ + +/** @defgroup CRC_Structures Structures + @{ +*/ + +/**@} end of group CRC_Structures */ + +/** @defgroup CRC_Variables Variables + @{ +*/ + +/**@} end of group CRC_Variables */ + +/** @defgroup CRC_Functions Functions + @{ +*/ + +/* Reset CRC */ +void CRC_Reset(void); + +/* Reset DATA */ +void CRC_ResetDATA(void); + +/* CRC Polynomial Size */ +void CRC_SetPolynomialSize(CRC_POLYNOMIAL_SIZE_T polynomialSize); /*!< Only for APM32F072 and APM32F091 devices */ +void CRC_SetPolynomialValue(uint32_t polynomialValue); /*!< Only for APM32F072 and APM32F091 devices */ + +/* Performed on input data */ +void CRC_SelectReverseInputData(CRC_REVERSE_INPUT_DATA_T revInData); + +/* Enable and Disable Reverse Output Data */ +void CRC_EnableReverseOutputData(void); +void CRC_DisableReverseOutputData(void); + +/* Write INITVAL register */ +void CRC_WriteInitRegister(uint32_t initValue); + +/* Calculate CRC */ +uint32_t CRC_CalculateCRC(uint32_t data); +uint32_t CRC_CalculateCRC8bits(uint8_t data); /*!< Only for APM32F072 and APM32F091 devices */ +uint32_t CRC_CalculateCRC16bits(uint16_t data); /*!< Only for APM32F072 and APM32F091 devices */ +uint32_t CRC_CalculateBlockCRC(uint32_t pBuffer[], uint32_t bufferLength); + +/* Read CRC */ +uint32_t CRC_ReadCRC(void); + +/* Independent Data(ID) */ +void CRC_WriteIDRegister(uint8_t IDValue); +uint8_t CRC_ReadIDRegister(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __APM32F0XX_CRC_H */ + +/**@} end of group CRC_Functions */ +/**@} end of group CRC_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_crs.h b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_crs.h new file mode 100644 index 0000000000..4ec5f2804a --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/inc/apm32f0xx_crs.h @@ -0,0 +1,171 @@ +/*! + * @file apm32f0xx_crs.h + * + * @brief This file contains all the functions prototypes for the CRS firmware library + * + * @note It's only for APM32F072 and APM32F091 devices + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __APM32F0XX_CRS_H +#define __APM32F0XX_CRS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes */ +#include "apm32f0xx.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup CRS_Driver + @{ +*/ + +/** @defgroup CRS_Macros Macros + @{ +*/ + +/**@} end of group CRS_Macros */ + +/** @defgroup CRS_Enumerations Enumerations + @{ +*/ + +/** + * @brief CRS_Interrupt_Sources + */ +typedef enum +{ + CRS_INT_SYNCOK = ((uint32_t)0x00000001), /*!CFG1_B.DATARESCFG = adcConfig->resolution; + ADC->CFG1_B.DALIGCFG = adcConfig->dataAlign; + ADC->CFG1_B.SCANSEQDIR = adcConfig->scanDir; + ADC->CFG1_B.CMODESEL = adcConfig->convMode; + ADC->CFG1_B.EXTPOLSEL = adcConfig->extTrigEdge; + ADC->CFG1_B.EXTTRGSEL = adcConfig->extTrigConv; +} + +/*! + * @brief Fills each adcConfig member with its default value + * + * @param adcConfig: Pointer to a ADC_Config_T structure which will be initialized + * + * @retval None + */ +void ADC_ConfigStructInit(ADC_Config_T* adcConfig) +{ + adcConfig->resolution = ADC_RESOLUTION_12B; + adcConfig->dataAlign = ADC_DATA_ALIGN_RIGHT; + adcConfig->scanDir = ADC_SCAN_DIR_UPWARD; + adcConfig->convMode = ADC_CONVERSION_SINGLE; + adcConfig->extTrigConv = ADC_EXT_TRIG_CONV_TRG0; + adcConfig->extTrigEdge = ADC_EXT_TRIG_EDGE_NONE; +} + +/*! + * @brief Enable the ADC peripheral + * + * @param None + * + * @retval None + */ +void ADC_Enable(void) +{ + ADC->CTRL_B.ADCEN = BIT_SET; +} + +/*! + * @brief Disable the ADC peripheral + * + * @param None + * + * @retval None + */ +void ADC_Disable(void) +{ + ADC->CTRL_B.ADCD = BIT_SET; +} + +/*! + * @brief Configure the ADC to either be clocked by the asynchronous clock + * + * @param clockmode: selects the ADC clock mode. + * The parameter can be one of following values: + * @arg ADC_CLOCK_MODE_ASYNCLK: ADC Asynchronous clock mode + * @arg ADC_CLOCK_MODE_SYNCLKDIV2: Synchronous clock mode divided by 2 + * @arg ADC_CLOCK_MODE_SYNCLKDIV4: Synchronous clock mode divided by 4 + * + * @retval None + */ +void ADC_ClockMode(ADC_CLOCK_MODE_T clockMode) +{ + ADC->CFG2_B.CLKCFG = (uint32_t)clockMode; +} + +/*! + * @brief Enables the jitter when the ADC is clocked by PCLK div2 or div4 + * + * @param jitter: They are replaced by PCLK div2 or div4 + * The parameter can be one of following values: + * @arg ADC_JITTER_PCLKDIV2: ADC clocked by PCLK div2 + * @arg ADC_JITTER_PCLKDIV4: ADC clocked by PCLK div4 + * + * @retval None + */ +void ADC_EnableJitter(ADC_JITTER_T jitter) +{ + ADC->CFG2_B.CLKCFG |= (uint32_t)jitter; +} + +/*! + * @brief Disables the jitter when the ADC is clocked by PCLK div2 or div4 + * + * @param jitter: They are replaced by PCLK div2 or div4 + * The parameter can be one of following values: + * @arg ADC_JITTER_PCLKDIV2: ADC clocked by PCLK div2 + * @arg ADC_JITTER_PCLKDIV4: ADC clocked by PCLK div4 + * @retval None + */ +void ADC_DisableJitter(ADC_JITTER_T jitter) +{ + ADC->CFG2_B.CLKCFG &= (uint32_t)~jitter; +} + +/*! + * @brief Enables the Auto Power Off mode + * + * @param None + * + * @retval None + */ +void ADC_EnableAutoPowerOff(void) +{ + ADC->CFG1_B.AOEN = BIT_SET; +} + +/*! + * @brief Disables the Auto Power Off mode + * + * @param None + * + * @retval None + */ +void ADC_DisableAutoPowerOff(void) +{ + ADC->CFG1_B.AOEN = BIT_RESET; +} + +/*! + * @brief Enables the Auto-delayed conversion mode + * + * @param None + * + * @retval None + */ +void ADC_EnableWaitMode(void) +{ + ADC->CFG1_B.WAITCEN = BIT_SET; +} + +/*! + * @brief Disables the Auto-delayed conversion mode + * + * @param None + * + * @retval None + */ +void ADC_DisableWaitMode(void) +{ + ADC->CFG1_B.WAITCEN = BIT_RESET; +} + +/*! + * @brief Enables the analog watchdog + * + * @param None + * + * @retval None + */ +void ADC_EnableAnalogWatchdog(void) +{ + ADC->CFG1_B.AWDEN = BIT_SET; +} + +/*! + * @brief Disables the analog watchdog + * + * @param None + * + * @retval None + */ +void ADC_DisableAnalogWatchdog(void) +{ + ADC->CFG1_B.AWDEN = BIT_RESET; +} + +/*! + * @brief The analog watchdog low threshold + * + * @param None + * + * @retval None + */ +void ADC_AnalogWatchdogLowThreshold(uint16_t lowThreshold) +{ + ADC->AWDT_B.AWDLT = (uint16_t)lowThreshold; +} + +/*! + * @brief The analog watchdog High threshold + * + * @param None + * + * @retval None + */ +void ADC_AnalogWatchdogHighThreshold(uint16_t highThreshold) +{ + ADC->AWDT_B.AWDHT = (uint16_t)highThreshold; +} + +/*! + * @brief Configures the analog watchdog guarded single channel + * + * @param channel: ADC analog watchdog channel selection + * The parameter can be one of following values: + * @arg ADC_ANALG_WDT_CHANNEL_0: AWD Channel 0 + * @arg ADC_ANALG_WDT_CHANNEL_1: AWD Channel 1 + * @arg ADC_ANALG_WDT_CHANNEL_2: AWD Channel 2 + * @arg ADC_ANALG_WDT_CHANNEL_3: AWD Channel 3 + * @arg ADC_ANALG_WDT_CHANNEL_4: AWD Channel 4 + * @arg ADC_ANALG_WDT_CHANNEL_5: AWD Channel 5 + * @arg ADC_ANALG_WDT_CHANNEL_6: AWD Channel 6 + * @arg ADC_ANALG_WDT_CHANNEL_7: AWD Channel 7 + * @arg ADC_ANALG_WDT_CHANNEL_8: AWD Channel 8 + * @arg ADC_ANALG_WDT_CHANNEL_9: AWD Channel 9 + * @arg ADC_ANALG_WDT_CHANNEL_10: AWD Channel 10 + * @arg ADC_ANALG_WDT_CHANNEL_11: AWD Channel 11 + * @arg ADC_ANALG_WDT_CHANNEL_12: AWD Channel 12 + * @arg ADC_ANALG_WDT_CHANNEL_13: AWD Channel 13 + * @arg ADC_ANALG_WDT_CHANNEL_14: AWD Channel 14 + * @arg ADC_ANALG_WDT_CHANNEL_15: AWD Channel 15 + * @arg ADC_ANALG_WDT_CHANNEL_16: AWD Channel 16 is TempSensor + * @arg ADC_ANALG_WDT_CHANNEL_17: AWD Channel 17 is Vrefint + * @arg ADC_ANALG_WDT_CHANNEL_18: AWD Channel 18 is Vbat, not available for APM32F030 devices + * + * @retval None + */ +void ADC_AnalogWatchdogSingleChannel(uint32_t channel) +{ + ADC->CFG1_B.AWDCHSEL = channel; +} + +/*! + * @brief Enables the Analog Watchdog Single Channel + * + * @param None + * + * @retval None + */ +void ADC_EnableAnalogWatchdogSingleChannel(void) +{ + ADC->CFG1_B.AWDCHEN = BIT_SET; +} + +/*! + * @brief Disables the Analog Watchdog Single Channel + * + * @param None + * + * @retval None + */ +void ADC_DisableAnalogWatchdogSingleChannel(void) +{ + ADC->CFG1_B.AWDCHEN = BIT_RESET; +} + +/*! + * @brief Enables the temperature sensor channel + * + * @param None + * + * @retval None + */ +void ADC_EnableTempSensor(void) +{ + ADC->CCFG_B.TSEN = BIT_SET; +} + +/*! + * @brief Disables the temperature sensor channel + * + * @param None + * + * @retval None + */ +void ADC_DisableTempSensor(void) +{ + ADC->CCFG_B.TSEN = BIT_RESET; +} + +/*! + * @brief Enables the vrefint channel + * + * @param None + * + * @retval None + */ +void ADC_EnableVrefint(void) +{ + ADC->CCFG_B.VREFEN = BIT_SET; +} + +/*! + * @brief Disables the vrefint channel + * + * @param None + * + * @retval None + */ +void ADC_DisableVrefint(void) +{ + ADC->CCFG_B.VREFEN = BIT_RESET; +} + +/*! + * @brief Enables the Vbat channel + * + * @param None + * + * @retval None + * + * @note It's not for APM32F030 devices + */ +void ADC_EnableVbat(void) +{ + ADC->CCFG_B.VBATEN = BIT_SET; +} + +/*! + * @brief Disables the Vbat channel + * + * @param None + * + * @retval None + * + * @note It's not for APM32F030 devices + */ +void ADC_DisableVbat(void) +{ + ADC->CCFG_B.VBATEN = BIT_RESET; +} + +/*! + * @brief Configures for the selected ADC channel and its sampling time + * + * @param channel: the ADC channel + * The parameter can be combination of following values: + * @arg ADC_CHANNEL_0: channel 0 + * @arg ADC_CHANNEL_1: channel 1 + * @arg ADC_CHANNEL_2: channel 2 + * @arg ADC_CHANNEL_3: channel 3 + * @arg ADC_CHANNEL_4: channel 4 + * @arg ADC_CHANNEL_5: channel 5 + * @arg ADC_CHANNEL_6: channel 6 + * @arg ADC_CHANNEL_7: channel 7 + * @arg ADC_CHANNEL_8: channel 8 + * @arg ADC_CHANNEL_9: channel 9 + * @arg ADC_CHANNEL_10: channel 10 + * @arg ADC_CHANNEL_11: channel 11 + * @arg ADC_CHANNEL_12: channel 12 + * @arg ADC_CHANNEL_13: channel 13 + * @arg ADC_CHANNEL_14: channel 14 + * @arg ADC_CHANNEL_15: channel 15 + * @arg ADC_CHANNEL_16: channel 16 is TempSensor + * @arg ADC_CHANNEL_17: channel 17 is Vrefint + * @arg ADC_CHANNEL_18: channel 18 is Vbat, not available for APM32F030 devices + * @param sampleTime: the ADC sampling time + * The parameter can be one of following values: + * @arg ADC_SAMPLE_TIME_1_5: ADC 1.5 clock cycles + * @arg ADC_SAMPLE_TIME_7_5: ADC 7.5 clock cycles + * @arg ADC_SAMPLE_TIME_13_5: ADC 13.5 clock cycles + * @arg ADC_SAMPLE_TIME_28_5: ADC 28.5 clock cycles + * @arg ADC_SAMPLE_TIME_41_5: ADC 41.5 clock cycles + * @arg ADC_SAMPLE_TIME_55_5: ADC 55.5 clock cycles + * @arg ADC_SAMPLE_TIME_71_5: ADC 71.5 clock cycles + * @arg ADC_SAMPLE_TIME_239_5: ADC 239.5 clock cycles + * + * @retval None + */ +void ADC_ConfigChannel(uint32_t channel, uint8_t sampleTime) +{ + ADC->CHSEL |= (uint32_t)channel; + + ADC->SMPTIM |= (uint8_t)sampleTime; +} + +/*! + * @brief Enables the continuous mode + * + * @param None + * + * @retval None + */ +void ADC_EnableContinuousMode(void) +{ + ADC->CFG1_B.CMODESEL = BIT_SET; +} + +/*! + * @brief Disables the continuous mode + * + * @param None + * + * @retval None + */ +void ADC_DisableContinuousMode(void) +{ + ADC->CFG1_B.CMODESEL = BIT_RESET; +} + +/*! + * @brief Enables the discontinuous mode + * + * @param None + * + * @retval None + */ +void ADC_EnableDiscMode(void) +{ + ADC->CFG1_B.DISCEN = BIT_SET; +} + +/*! + * @brief Disables the discontinuous mode + * + * @param None + * + * @retval None + */ +void ADC_DisableDiscMode(void) +{ + ADC->CFG1_B.DISCEN = BIT_RESET; +} + +/*! + * @brief Enables the Overrun mode + * + * @param None + * + * @retval None + */ +void ADC_EnableOverrunMode(void) +{ + ADC->CFG1_B.OVRMAG = BIT_SET; +} + +/*! + * @brief Disables the Overrun mode + * + * @param None + * + * @retval None + */ +void ADC_DisableOverrunMode(void) +{ + ADC->CFG1_B.OVRMAG = BIT_RESET; +} + +/*! + * @brief ADC Read Calibration Factor + * + * @param None + * + * @retval ADC Calibration factor + */ +uint32_t ADC_ReadCalibrationFactor(void) +{ + uint32_t temp = 0, counter = 0, status = 0; + + ADC->CTRL_B.CAL = BIT_SET; + + do + { + status = ADC->CTRL_B.CAL; + counter++; + } + while ((counter != CALIBRATION_TIMEOUT) && (status != 0x00)); + + if ((uint32_t)(ADC->CTRL_B.CAL) == RESET) + { + temp = ADC->DATA; + } + else + { + temp = 0x00000000; + } + + return temp; +} + +/*! + * @brief ADC stop conversion command + * + * @param None + * + * @retval None + */ +void ADC_StopConversion(void) +{ + ADC->CTRL_B.STOPCEN = BIT_SET; +} + +/*! + * @brief ADC start conversion command + * + * @param None + * + * @retval None + */ +void ADC_StartConversion(void) +{ + ADC->CTRL_B.STARTCEN = BIT_SET; +} + +/*! + * @brief Returns the last ADC conversion result data + * + * @param None + * + * @retval The Data conversion value + */ +uint16_t ADC_ReadConversionValue(void) +{ + return ((uint16_t)ADC->DATA); +} + +/*! + * @brief Enables the ADC DMA request + * + * @param None + * + * @retval None + */ +void ADC_EnableDMA(void) +{ + ADC->CFG1_B.DMAEN = BIT_SET; +} + +/*! + * @brief Disables the ADC DMA request + * + * @param None + * + * @retval None + */ +void ADC_DisableDMA(void) +{ + ADC->CFG1_B.DMAEN = BIT_RESET; +} + +/*! + * @brief ADC DMA Request Mode + * + * @param DMARequestMode: Direct memery access configuration . + * The parameter can be one of following values: + * @arg ADC_DMA_MODE_ONESHOUT: ADC DMA Mode Select one shot + * @arg ADC_DMA_MODE_CIRCULAR: ADC DMA Mode Select circular + * + * @retval None + */ +void ADC_DMARequestMode(ADC_DMA_MODE_T DMARequestMode) +{ + ADC->CFG1_B.DMACFG = (uint8_t)DMARequestMode; +} + +/*! + * @brief Enables the specified interrupts + * + * @param interrupt: Specifies the ADC interrupts sources + * The parameter can be combination of following values: + * @arg ADC_INT_ADRDY: ADC ready interrupt + * @arg ADC_INT_CSMP: End of sampling interrupt + * @arg ADC_INT_CC: End of conversion interrupt + * @arg ADC_INT_CS: End of sequence interrupt + * @arg ADC_INT_OVR: ADC overrun interrupt + * @arg ADC_INT_AWD: Analog watchdog interrupt + * + * @retval None + */ +void ADC_EnableInterrupt(uint8_t interrupt) +{ + ADC->INT |= (uint32_t)interrupt; +} + +/*! + * @brief Disable the specified interrupts + * + * @param interrupt: Specifies the ADC interrupts sources + * The parameter can be combination of following values: + * @arg ADC_INT_ADRDY: ADC ready interrupt + * @arg ADC_INT_CSMP: End of sampling interrupt + * @arg ADC_INT_CC: End of conversion interrupt + * @arg ADC_INT_CS: End of sequence interrupt + * @arg ADC_INT_OVR: ADC overrun interrupt + * @arg ADC_INT_AWD: Analog watchdog interrupt + * + * @retval None + */ +void ADC_DisableInterrupt(uint8_t interrupt) +{ + ADC->INT &= (uint32_t)~interrupt; +} + +/*! + * @brief Checks whether the specified ADC flag is set or not + * + * @param flag: Specifies the flag to check + * This parameter can be one of the following values: + * @arg ADC_FLAG_ADCON: ADC enable flag + * @arg ADC_FLAG_ADCOFF: ADC disable flag + * @arg ADC_FLAG_ADCSTA: ADC start conversion flag + * @arg ADC_FLAG_ADCSTOP: ADC stop conversion flag + * @arg ADC_FLAG_ADCCAL: ADC calibration flag + * @arg ADC_FLAG_ADRDY: ADC ready flag + * @arg ADC_FLAG_CSMP: End of sampling flag + * @arg ADC_FLAG_CC: End of conversion flag + * @arg ADC_FLAG_CS: End of sequence flag + * @arg ADC_FLAG_OVR: ADC overrun flag + * @arg ADC_FLAG_AWD: Analog watchdog flag + * + * @retval The new state of flag (SET or RESET) + */ +uint8_t ADC_ReadStatusFlag(ADC_FLAG_T flag) +{ + uint32_t status; + + if ((uint32_t)(flag & 0x01000000)) + { + status = ADC->CTRL & 0xFEFFFFFF; + } + else + { + status = ADC->STS; + } + + if ((status & flag) != (uint32_t)RESET) + { + return SET; + } + + return RESET; +} + +/*! + * @brief Clear the specified ADC flag + * + * @param flag: Specifies the flag to check + * This parameter can be any combination of the following values: + * @arg ADC_FLAG_ADRDY: ADC ready flag + * @arg ADC_FLAG_CSMP: End of sampling flag + * @arg ADC_FLAG_CC: End of conversion flag + * @arg ADC_FLAG_CS: End of sequence flag + * @arg ADC_FLAG_OVR: ADC overrun flag + * @arg ADC_FLAG_AWD: Analog watchdog flag + * + * @retval None + */ +void ADC_ClearStatusFlag(uint32_t flag) +{ + ADC->STS = (uint32_t)flag; +} + +/*! + * @brief Checks whether the specified interrupt has occurred or not + * + * @param flag: Specifies the ADC interrupt pending bit to check + * The parameter can be one of following values: + * @arg ADC_INT_FLAG_ADRDY: ADC ready interrupt + * @arg ADC_INT_FLAG_CSMP: End of sampling interrupt + * @arg ADC_INT_FLAG_CC: End of conversion interrupt + * @arg ADC_INT_FLAG_CS: End of sequence interrupt + * @arg ADC_INT_FLAG_OVR: ADC overrun interrupt + * @arg ADC_INT_FLAG_AWD: Analog watchdog interrupt + * + * @retval None + */ +uint8_t ADC_ReadIntFlag(ADC_INT_FLAG_T flag) +{ + uint8_t intEnable; + uint8_t intStatus; + + intEnable = (uint8_t)(ADC->INT& (uint32_t)flag); + + intStatus = (uint8_t)(ADC->STS & (uint32_t)(flag & 0xff)); + + if (intEnable && intStatus) + { + return SET; + } + + return RESET; +} + +/*! + * @brief Clears the specified interrupt pending bits + * + * @param flag: Specifies the ADC interrupt pending bit to check + * The parameter can be combination of following values: + * @arg ADC_INT_FLAG_ADRDY: ADC ready interrupt + * @arg ADC_INT_FLAG_CSMP: End of sampling interrupt + * @arg ADC_INT_FLAG_CC: End of conversion interrupt + * @arg ADC_INT_FLAG_CS: End of sequence interrupt + * @arg ADC_INT_FLAG_OVR: ADC overrun interrupt + * @arg ADC_INT_FLAG_AWD: Analog watchdog interrupt + * + * @retval None + */ + +void ADC_ClearIntFlag(uint32_t flag) +{ + ADC->STS = flag; +} + +/**@} end of group ADC_Functions */ +/**@} end of group ADC_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_can.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_can.c new file mode 100644 index 0000000000..f108be7c7e --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_can.c @@ -0,0 +1,1170 @@ +/*! + * @file apm32f0xx_can.c + * + * @brief This file contains all the functions for the CAN peripheral + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* include */ +#include "apm32f0xx_can.h" +#include "apm32f0xx_rcm.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup CAN_Driver + @{ +*/ + +/** @defgroup CAN_Macros Macros + @{ +*/ + +/**@} end of group CAN_Macros */ + +/** @defgroup CAN_Enumerations Enumerations + @{ +*/ + +/**@} end of group CAN_Enumerations */ + +/** @defgroup CAN_Structures Structures + @{ +*/ + +/**@} end of group CAN_Structures */ + +/** @defgroup CAN_Variables Variables + @{ +*/ + +/**@} end of group CAN_Variables */ + +/** @defgroup CAN_Functions Functions + @{ +*/ + +/*! + * @brief Reset CAN peripheral registers to their default values. + * + * @param None + * + * @retval None + * + */ +void CAN_Reset(void) +{ + RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_CAN); + RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_CAN); +} + +/*! + * @brief Congfig the CAN peripheral using the specified parameters in the canConfig. + * + * @param canConfig : pointer to a CAN_Config_T structure that contains + * the configuration information for the CAN peripheral. + * + * @retval Configuration status (SET or RESET) + */ +uint8_t CAN_Config(CAN_Config_T* canConfig) +{ + uint8_t InitStatus = RESET; + uint32_t ackWait = 0x00000000; + + CAN->MCTRL_B.SLEEPREQ = BIT_RESET; + + CAN->MCTRL_B.INITREQ = BIT_SET; + + while ((CAN->MSTS_B.INITFLG != BIT_SET) && (ackWait != (uint32_t)0x00FFFFFF)) + { + ackWait++; + } + + if (CAN->MSTS_B.INITFLG != BIT_SET) + { + InitStatus = RESET; + } + else + { + if (canConfig->timeTrigComMode == ENABLE) + { + CAN->MCTRL_B.TTCM = BIT_SET; + } + else + { + CAN->MCTRL_B.TTCM = BIT_RESET; + } + + if (canConfig->autoBusOffManage == ENABLE) + { + CAN->MCTRL_B.ALBOFFM = BIT_SET; + } + else + { + CAN->MCTRL_B.ALBOFFM = BIT_RESET; + } + + if (canConfig->autoWakeUpMode == ENABLE) + { + CAN->MCTRL_B.AWUPCFG = BIT_SET; + } + else + { + CAN->MCTRL_B.AWUPCFG = BIT_RESET; + } + + if (canConfig->nonAutoRetran == ENABLE) + { + CAN->MCTRL_B.ARTXMD = BIT_SET; + } + else + { + CAN->MCTRL_B.ARTXMD = BIT_RESET; + } + + if (canConfig->rxFIFOLockMode == ENABLE) + { + CAN->MCTRL_B.RXFLOCK = BIT_SET; + } + else + { + CAN->MCTRL_B.RXFLOCK = BIT_RESET; + } + + if (canConfig->txFIFOPriority == ENABLE) + { + CAN->MCTRL_B.TXFPCFG = BIT_SET; + } + else + { + CAN->MCTRL_B.TXFPCFG = BIT_RESET; + } + + CAN->BITTIM = (uint32_t)canConfig->mode << 30; + CAN->BITTIM_B.RSYNJW = canConfig->syncJumpWidth; + CAN->BITTIM_B.TIMSEG1 = canConfig->timeSegment1; + CAN->BITTIM_B.TIMSEG2 = canConfig->timeSegment2; + CAN->BITTIM_B.BRPSC = canConfig->prescaler - 1; + + CAN->MCTRL_B.INITREQ = BIT_RESET; + + ackWait = 0x00000000; + + while ((CAN->MSTS_B.INITFLG == BIT_SET) && (ackWait != (uint32_t)0x00FFFFFF)) + { + ackWait++; + } + + if (CAN->MSTS_B.INITFLG == BIT_RESET) + { + InitStatus = SET; + } + else + { + InitStatus = RESET; + } + } + return InitStatus; +} + +/*! + * @brief Congfig the CAN filter according to the specified parameters in the filterConfig. + * + * @param filterConfig: pointer to a CAN_Filter_Config_T structure that + * contains the configuration information. + * + * @retval None + */ +void CAN_ConfigFilter(CAN_FilterConfig_T* filterConfig) +{ + uint16_t filterNumber = 0; + + filterNumber = BIT0 << filterConfig->filterNumber; + + CAN->FCTRL_B.FIM = BIT_SET; + + CAN->FACT &= ~filterNumber; + + if (filterConfig->filterScale == CAN_FILTER_SCALE_16BIT) + { + CAN->FSCFG &= ~filterNumber; + + CAN->sFilterRegister[filterConfig->filterNumber].R1 = + ((0x0000FFFF & filterConfig->filterMaskIdLow) << 16) | + (0x0000FFFF & filterConfig->filterIdLow); + + CAN->sFilterRegister[filterConfig->filterNumber].R2 = + ((0x0000FFFF & filterConfig->filterMaskIdHigh) << 16) | + (0x0000FFFF & filterConfig->filterIdHigh); + } + + if (filterConfig->filterScale == CAN_FILTER_SCALE_32BIT) + { + CAN->FSCFG |= filterNumber; + + CAN->sFilterRegister[filterConfig->filterNumber].R1 = + ((0x0000FFFF & filterConfig->filterIdHigh) << 16) | + (0x0000FFFF & filterConfig->filterIdLow); + + CAN->sFilterRegister[filterConfig->filterNumber].R2 = + ((0x0000FFFF & filterConfig->filterMaskIdHigh) << 16) | + (0x0000FFFF & filterConfig->filterMaskIdLow); + } + + if (filterConfig->filterMode == CAN_FILTER_MODE_IDMASK) + { + CAN->FMCFG &= ~filterNumber; + } + else + { + CAN->FMCFG |= filterNumber; + } + + if (filterConfig->filterFIFO == CAN_FIFO_0) + { + CAN->FFASS &= ~filterNumber; + } + else + { + CAN->FFASS |= filterNumber; + } + + if (filterConfig->filterActivation == ENABLE) + { + CAN->FACT |= filterNumber; + } + + CAN->FCTRL_B.FIM = BIT_RESET; +} + +/*! + * @brief Fills each canConfig member with its default value. + * + * @param canConfig : Pointer to a CAN_Config_T structure which is used for configuration. + * + * @retval None + */ +void CAN_ConfigStructInit(CAN_Config_T* canConfig) +{ + canConfig->timeTrigComMode = DISABLE; + + canConfig->autoBusOffManage = DISABLE; + + canConfig->autoWakeUpMode = DISABLE; + + canConfig->nonAutoRetran = DISABLE; + + canConfig->rxFIFOLockMode = DISABLE; + + canConfig->txFIFOPriority = DISABLE; + + canConfig->mode = CAN_MODE_NORMAL; + + canConfig->syncJumpWidth = CAN_SJW_1; + + canConfig->timeSegment1 = CAN_TIME_SEGMENT1_4; + + canConfig->timeSegment2 = CAN_TIME_SEGMENT2_3; + + canConfig->prescaler = 1; +} + +/*! + * @brief Select the start bank filter for slave CAN. + * + * @param bankNumber:Select the start slave bank filter from 1 to 27. + * + * @retval None + * + * @note This function applies only to APM32 Connectivity line devices. + */ +void CAN_StartBankSlave(uint8_t bankNumber) +{ + CAN->FCTRL_B.FIM = BIT_SET; + + CAN->FCTRL &= 0xFFFFC0F1; + CAN->FCTRL |= (uint32_t)(bankNumber) << 8; + + CAN->FCTRL_B.FIM = BIT_RESET; +} + +/*! + * @brief Enable the Debug Freeze mdoe for CAN. + * + * @param None + * + * @retval None + */ +void CAN_EnableDebugFreeze(void) +{ + CAN->MCTRL_B.DBGFRZE = BIT_SET; +} + +/*! + * @brief Disable the Debug Freeze mode for CAN. + * + * @param None + * + * @retval None + */ +void CAN_DisableDebugFreeze(void) +{ + CAN->MCTRL_B.DBGFRZE = BIT_RESET; +} + +/*! + * @brief Enables the Time Triggered Communication mode for CAN. + * + * @param None + * + * @retval None + */ +void CAN_EnableTTComMode(void) +{ + CAN->MCTRL_B.TTCM = BIT_SET; + + CAN->sTxMailBox[0].TXDLEN_B.TXGT = BIT_SET; + CAN->sTxMailBox[1].TXDLEN_B.TXGT = BIT_SET; + CAN->sTxMailBox[2].TXDLEN_B.TXGT = BIT_SET; +} + +/*! + * @brief Disables the Time Triggered Communication mode for CAN. + * + * @param None + * + * @retval None + */ +void CAN_DisableTTComMode(void) +{ + CAN->MCTRL_B.TTCM = BIT_RESET; + + CAN->sTxMailBox[0].TXDLEN_B.TXGT = BIT_RESET; + CAN->sTxMailBox[1].TXDLEN_B.TXGT = BIT_RESET; + CAN->sTxMailBox[2].TXDLEN_B.TXGT = BIT_RESET; +} + +/*! + * @brief Transmit a message from TxMessage of CAN_Tx_Message structure. + * + * @param TxMessage : Pointer to a structure which contains CAN Id, CAN DLCODE and CAN data. + * + * @retval Returns the number of the transmit mailbox state.It can be one of value: + * @arg 0: Transmit mailbox 0 + * @arg 1: Transmit mailbox 1 + * @arg 2: Transmit mailbox 2 + * @arg 4: There is no empty mailbox + */ +uint8_t CAN_TxMessage(CAN_Tx_Message* TxMessage) +{ + uint8_t TxMailbox = 0; + + if ((CAN->TXSTS_B.TXMEFLG0 == BIT_SET)) + { + TxMailbox = 0; + } + else if ((CAN->TXSTS_B.TXMEFLG1 == BIT_SET)) + { + TxMailbox = 1; + } + else if ((CAN->TXSTS_B.TXMEFLG2 == BIT_SET)) + { + TxMailbox = 2; + } + else + { + TxMailbox = CAN_TX_MAILBOX_FULL; + } + + if (TxMailbox != CAN_TX_MAILBOX_FULL) + { + /* Set up the Id */ + CAN->sTxMailBox[TxMailbox].TXMID &= BIT0; + if (TxMessage->typeID == CAN_TYPEID_STD) + { + CAN->sTxMailBox[TxMailbox].TXMID |= (((uint32_t)TxMessage->stanID << 21) | \ + TxMessage->typeID | \ + TxMessage->remoteTxReq); + } + else + { + CAN->sTxMailBox[TxMailbox].TXMID |= (((uint32_t)TxMessage->extenID << 3) | \ + TxMessage->typeID | \ + TxMessage->remoteTxReq); + } + + /* Set up the DLCODE */ + CAN->sTxMailBox[TxMailbox].TXDLEN_B.DLCODE = (TxMessage->dataLengthCode & 0x0F); + + /* Set up the data field */ + CAN->sTxMailBox[TxMailbox].TXMDH_B.DATABYTE7 = TxMessage->data[7]; + CAN->sTxMailBox[TxMailbox].TXMDH_B.DATABYTE6 = TxMessage->data[6]; + CAN->sTxMailBox[TxMailbox].TXMDH_B.DATABYTE5 = TxMessage->data[5]; + CAN->sTxMailBox[TxMailbox].TXMDH_B.DATABYTE4 = TxMessage->data[4]; + + CAN->sTxMailBox[TxMailbox].TXMDL_B.DATABYTE3 = TxMessage->data[3]; + CAN->sTxMailBox[TxMailbox].TXMDL_B.DATABYTE2 = TxMessage->data[2]; + CAN->sTxMailBox[TxMailbox].TXMDL_B.DATABYTE1 = TxMessage->data[1]; + CAN->sTxMailBox[TxMailbox].TXMDL_B.DATABYTE0 = TxMessage->data[0]; + + /* Request transmission */ + CAN->sTxMailBox[TxMailbox].TXMID |= BIT0; + } + + return TxMailbox; +} + +/*! + * @brief Reads the status of a transmission. + * + * @param TxMailbox: the number of the mailbox + * This parameter can be one of the following values: + * @arg CAN_MAILBOX_0 : Transmit mailbox 0 + * @arg CAN_MAILBOX_1 : Transmit mailbox 1 + * @arg CAN_MAILBOX_2 : Transmit mailbox 2 + * + * @retval Returns the transmission state. + * It can be one of the following values: + * @arg CAN_TX_FAILED + * @arg CAN_TX_OK + * @arg CAN_TX_WAITING + */ +uint8_t CAN_TxMessageStatus(CAN_MAILBOX_T TxMailbox) +{ + uint8_t state = CAN_TX_FAILED; + + switch (TxMailbox) + { + case (CAN_MAILBOX_0): + if (CAN->TXSTS_B.REQCFLG0 && CAN->TXSTS_B.TXSUSFLG0 && CAN->TXSTS_B.TXMEFLG0) + { + state = CAN_TX_OK; + } + else if (!(CAN->TXSTS_B.REQCFLG0 || CAN->TXSTS_B.TXSUSFLG0 || CAN->TXSTS_B.TXMEFLG0)) + { + state = CAN_TX_WAITING; + } + break; + + case (CAN_MAILBOX_1): + if (CAN->TXSTS_B.REQCFLG1 && CAN->TXSTS_B.TXSUSFLG1 && CAN->TXSTS_B.TXMEFLG1) + { + state = CAN_TX_OK; + } + else if (!(CAN->TXSTS_B.REQCFLG1 || CAN->TXSTS_B.TXSUSFLG1 || CAN->TXSTS_B.TXMEFLG1)) + { + state = CAN_TX_WAITING; + } + break; + + case (CAN_MAILBOX_2): + if (CAN->TXSTS_B.REQCFLG2 && CAN->TXSTS_B.TXSUSFLG2 && CAN->TXSTS_B.TXMEFLG2) + { + state = CAN_TX_OK; + } + else if (!(CAN->TXSTS_B.REQCFLG2 || CAN->TXSTS_B.TXSUSFLG2 || CAN->TXSTS_B.TXMEFLG2)) + { + state = CAN_TX_WAITING; + } + break; + + default: + break; + } + + return state; +} + +/*! + * @brief Cancels a transmit request. + * + * @param TxMailbox: the number of the mailbox + * This parameter can be one of the following values: + * @arg CAN_MAILBOX_0 : Abort transmission request for mailbox 0 + * @arg CAN_MAILBOX_1 : Abort transmission request for mailbox 1 + * @arg CAN_MAILBOX_2 : Abort transmission request for mailbox 2 + * + * @retval None + */ +void CAN_CancelTx(CAN_MAILBOX_T TxMailbox) +{ + switch (TxMailbox) + { + case 0: + CAN->TXSTS_B.ABREQFLG0 = BIT_SET; + break; + + case 1: + CAN->TXSTS_B.ABREQFLG1 = BIT_SET; + break; + + case 2: + CAN->TXSTS_B.ABREQFLG2 = BIT_SET; + break; + + default: + break; + } +} + +/*! + * @brief Receive a valid message through the filter. + * + * @param FIFONumber: The number of Receive FIFO + * This parameter can be one of the following values: + * @arg CAN_FIFO_0 : CAN FIFO 0 used to receive + * @arg CAN_FIFO_1 : CAN FIFO 1 used to receive + * + * @param RxMessage : pointer to a structure that is used to receive message + * + * @retval None + */ +void CAN_RxMessage(uint8_t FIFONumber, CAN_Rx_Message* RxMessage) +{ + RxMessage->typeID = (CAN_TYPEID_T)(BIT2 & CAN->sRxFIFO[FIFONumber].RXMID); + + if (RxMessage->typeID == CAN_TYPEID_STD) + { + RxMessage->stanID = CAN->sRxFIFO[FIFONumber].RXMID_B.STDID; + } + else + { + RxMessage->extenID = (CAN->sRxFIFO[FIFONumber].RXMID_B.STDID << 18); + RxMessage->extenID |= CAN->sRxFIFO[FIFONumber].RXMID_B.EXTID; + } + + RxMessage->remoteTxReq = (CAN_RTXR_T)(BIT1 & CAN->sRxFIFO[FIFONumber].RXMID); + RxMessage->dataLengthCode = CAN->sRxFIFO[FIFONumber].RXDLEN_B.DLCODE; + RxMessage->filterMatchIndex = CAN->sRxFIFO[FIFONumber].RXDLEN_B.FMIDX; + + RxMessage->data[7] = CAN->sRxFIFO[FIFONumber].RXMDH_B.DATABYTE7; + RxMessage->data[6] = CAN->sRxFIFO[FIFONumber].RXMDH_B.DATABYTE6; + RxMessage->data[5] = CAN->sRxFIFO[FIFONumber].RXMDH_B.DATABYTE5; + RxMessage->data[4] = CAN->sRxFIFO[FIFONumber].RXMDH_B.DATABYTE4; + + RxMessage->data[3] = CAN->sRxFIFO[FIFONumber].RXMDL_B.DATABYTE3; + RxMessage->data[2] = CAN->sRxFIFO[FIFONumber].RXMDL_B.DATABYTE2; + RxMessage->data[1] = CAN->sRxFIFO[FIFONumber].RXMDL_B.DATABYTE1; + RxMessage->data[0] = CAN->sRxFIFO[FIFONumber].RXMDL_B.DATABYTE0; + + if (FIFONumber == CAN_FIFO_0) + { + CAN->RXF0_B.RFOM0 = BIT_SET; + } + else + { + CAN->RXF1_B.RFOM1 = BIT_SET; + } +} + +/*! + * @brief Releases the specified receive FIFO. + * + * @param FIFONumber : the number of receive FIFO + * This parameter can be one of the following values: + * @arg CAN_FIFO_0 : CAN FIFO 0 used to receive + * @arg CAN_FIFO_1 : CAN FIFO 1 used to receive + * + * @retval None + */ +void CAN_ReleaseFIFO(uint8_t FIFONumber) +{ + if (FIFONumber == CAN_FIFO_0) + { + CAN->RXF0_B.RFOM0 = BIT_SET; + } + else + { + CAN->RXF1_B.RFOM1 = BIT_SET; + } +} + +/*! + * @brief Reads the number of pending messages. + * + * @param FIFONumber : the number of receive FIFO + * This parameter can be one of the following values: + * @arg CAN_FIFO_0 : CAN FIFO 0 used to receive + * @arg CAN_FIFO_1 : CAN FIFO 1 used to receive + * + * @retval which is the number of pending message. + */ +uint8_t CAN_PendingMessage(uint8_t FIFONumber) +{ + if (FIFONumber == CAN_FIFO_0) + { + return CAN->RXF0_B.FMNUM0; + } + else + { + return CAN->RXF1_B.FMNUM1; + } +} + +/*! + * @brief Select the CAN Operation mode. + * + * @param operatingMode: CAN Operating Mode + * This parameter can be one of the following values: + * @arg CAN_OPERATING_MODE_INIT : Initialization mode + * @arg CAN_OPERATING_MODE_NORMAL: Normal mode + * @arg CAN_OPERATING_MODE_SLEEP : sleep mode + * + * @retval status: 0 : CAN failed entering the specific mode + * 1 : CAN Succeed entering the specific mode + */ +uint8_t CAN_OperatingMode(CAN_OPERATING_MODE_T operatingMode) +{ + uint8_t status = RESET; + uint32_t timeout = 0x00FFFFFF; + uint8_t sleepflg, initfig; + + sleepflg = CAN->MSTS_B.SLEEPFLG; + initfig = CAN->MSTS_B.INITFLG; + + switch ((uint8_t)operatingMode) + { + case CAN_OPERATING_MODE_INIT: + CAN->MCTRL_B.SLEEPREQ = BIT_RESET; + CAN->MCTRL_B.INITREQ = BIT_SET; + + while ((sleepflg | !initfig) && (timeout != 0)) + { + sleepflg = CAN->MSTS_B.SLEEPFLG; + initfig = CAN->MSTS_B.INITFLG; + timeout--; + } + + if (sleepflg | !initfig) + { + status = RESET; + } + else + { + status = SET; + } + break; + + case CAN_OPERATING_MODE_NORMAL: + + CAN->MCTRL_B.INITREQ = BIT_RESET; + CAN->MCTRL_B.SLEEPREQ = BIT_RESET; + + while ((sleepflg | initfig) && (timeout != 0)) + { + sleepflg = CAN->MSTS_B.SLEEPFLG; + initfig = CAN->MSTS_B.INITFLG; + timeout--; + } + + if (sleepflg | initfig) + { + status = RESET; + } + else + { + status = SET; + } + break; + + case CAN_OPERATING_MODE_SLEEP: + CAN->MCTRL_B.INITREQ = BIT_RESET; + CAN->MCTRL_B.SLEEPREQ = BIT_SET; + + while ((!sleepflg | initfig) && (timeout != 0)) + { + sleepflg = CAN->MSTS_B.SLEEPFLG; + initfig = CAN->MSTS_B.INITFLG; + timeout--; + } + + if (!sleepflg | initfig) + { + status = RESET; + } + else + { + status = SET; + } + break; + + default: + status = RESET; + break; + } + + return status; +} + +/*! + * @brief Enters the sleep mode. + * + * @param None + * + * @retval status: 0 : Into sleep fail + * 1 : Into sleep success + */ +uint8_t CAN_SleepMode(void) +{ + CAN_SLEEP_T sleepstatus = CAN_SLEEP_FAILED; + + CAN->MCTRL_B.INITREQ = BIT_RESET; + CAN->MCTRL_B.SLEEPREQ = BIT_SET; + + if ((CAN->MSTS_B.SLEEPFLG == BIT_SET) && (CAN->MSTS_B.INITFLG == BIT_RESET)) + { + sleepstatus = CAN_SLEEP_OK; + } + + return (uint8_t)sleepstatus; +} + +/*! + * @brief Wakes up the CAN from sleep mode. + * + * @param None + * + * @retval status: 0 : WakeUp CAN fail + * 1 : WakeUp CAN success + */ +uint8_t CAN_WakeUpMode(void) +{ + uint32_t slakWait = 0x00FFFFFF; + CAN_WUP_T wakeupstatus = CAN_WAKEUP_FAILED; + + CAN->MCTRL_B.SLEEPREQ = BIT_RESET; + + while ((CAN->MSTS_B.SLEEPFLG == BIT_SET) && (slakWait != 0x00)) + { + slakWait--; + } + if (CAN->MSTS_B.SLEEPFLG != BIT_SET) + { + wakeupstatus = CAN_WAKEUP_OK; + } + return (uint8_t)wakeupstatus; +} + +/*! + * @brief Read the last error code of CAN. + * + * @param None + * + * @retval CAN_ErrorCode + */ +uint8_t CAN_ReadLastErrorCode(void) +{ + uint8_t errorcode = 0; + errorcode = CAN->ERRSTS_B.LERRC; + return errorcode; +} + +/*! + * @brief Read the Receive Error Counter of CAN. + * + * @param None + * + * @retval CAN Receive Error Counter. + */ +uint8_t CAN_ReadRxErrorCounter(void) +{ + uint8_t counter = 0; + counter = CAN->ERRSTS_B.RXERRCNT; + return counter; +} + +/*! + * @brief Reads the Least significant byte of the 9-bit CAN Transmit Error Counter. + * + * @param None + * + * @retval Least significant byte of the 9-bit CAN Transmit Error Counter. + */ +uint8_t CAN_ReadLSBTxErrorCounter(void) +{ + uint8_t counter = 0; + counter = CAN->ERRSTS_B.TXERRCNT; + return counter; +} + +/*! + * @brief Enables the specified CAN interrupts. + * + * @param interrupt: Selects the CAN interrupt sources to be enabled. + * The parameter can be any combination of the following values: + * @arg CAN_INT_TXME : Transmit mailbox empty Interrupt + * @arg CAN_INT_F0MP : FIFO 0 message pending Interrupt + * @arg CAN_INT_F0FUL: FIFO 0 full Interrupt + * @arg CAN_INT_F0OVR: FIFO 0 overrun Interrupt + * @arg CAN_INT_F1MP : FIFO 1 message pending Interrupt + * @arg CAN_INT_F1FUL: FIFO 1 full Interrupt + * @arg CAN_INT_F1OVR: FIFO 1 overrun Interrupt + * @arg CAN_INT_EWIE : Error warning Interrupt + * @arg CAN_INT_EPIE : Error passive Interrupt + * @arg CAN_INT_BOIE : Bus-off Interrupt + * @arg CAN_INT_LEC : Last error code Interrupt + * @arg CAN_INT_ERR : Error Interrupt + * @arg CAN_INT_WUP : Wake-up Interrupt + * @arg CAN_INT_SLE : Sleep acknowledge Interrupt + * + * @retval None + */ +void CAN_EnableInterrupt(uint32_t interrupt) +{ + CAN->INTEN |= interrupt; +} + +/*! + * @brief Disables the specified CAN interrupts. + * + * @param interrupt: Selects the CAN interrupt sources to be disabled. + * The parameter can be any combination of the following values: + * @arg CAN_INT_TXME : Transmit mailbox empty Interrupt + * @arg CAN_INT_F0MP : FIFO 0 message pending Interrupt + * @arg CAN_INT_F0FUL: FIFO 0 full Interrupt + * @arg CAN_INT_F0OVR: FIFO 0 overrun Interrupt + * @arg CAN_INT_F1MP : FIFO 1 message pending Interrupt + * @arg CAN_INT_F1FUL: FIFO 1 full Interrupt + * @arg CAN_INT_F1OVR: FIFO 1 overrun Interrupt + * @arg CAN_INT_WUP : Wake-up Interrupt + * @arg CAN_INT_SLE : Sleep acknowledge Interrupt + * @arg CAN_INT_EWIE : Error warning Interrupt + * @arg CAN_INT_EPIE : Error passive Interrupt + * @arg CAN_INT_BOIE : Bus-off Interrupt + * @arg CAN_INT_LEC : Last error code Interrupt + * @arg CAN_INT_ERR : Error Interrupt + * + * @retval None + */ +void CAN_DisableInterrupt(uint32_t interrupt) +{ + CAN->INTEN &= ~interrupt; +} + +/*! + * @brief Reads the specified CAN flag status. + * + * @param flag: specifies the flag of CAN. + * The parameter can be one of following values: + * @arg CAN_FLAG_EWF : Error Warning Flag + * @arg CAN_FLAG_EPF : Error Passive Flag + * @arg CAN_FLAG_BOF : Bus-Off Flag + * @arg CAN_FLAG_LEC : Last error code Flag + * @arg CAN_FLAG_WUP : Wake up Flag + * @arg CAN_FLAG_SLAK : Sleep acknowledge Flag + * @arg CAN_FLAG_RQCP0: Request MailBox0 Flag + * @arg CAN_FLAG_RQCP1: Request MailBox1 Flag + * @arg CAN_FLAG_RQCP2: Request MailBox2 Flag + * @arg CAN_FLAG_FMP0 : FIFO 0 Message Pending Flag + * @arg CAN_FLAG_FF0 : FIFO 0 Full Flag + * @arg CAN_FLAG_FOV0 : FIFO 0 Overrun Flag + * @arg CAN_FLAG_FMP1 : FIFO 1 Message Pending Flag + * @arg CAN_FLAG_FF1 : FIFO 1 Full Flag + * @arg CAN_FLAG_FOV1 : FIFO 1 Overrun Flag + * + * @retval staus : RESET or SET + */ +uint8_t CAN_ReadStatusFlag(CAN_FLAG_T flag) +{ + uint8_t status = RESET; + + if ((flag & 0x00F00000) != (uint32_t)RESET) + { + if ((CAN->ERRSTS & (flag & 0x000FFFFF)) != (uint32_t)RESET) + { + status = SET; + } + else + { + status = RESET; + } + } + else if ((flag & 0x01000000) != (uint32_t)RESET) + { + if ((CAN->MSTS & (flag & 0x000FFFFF)) != (uint32_t)RESET) + { + status = SET; + } + else + { + status = RESET; + } + } + else if ((flag & 0x02000000) != (uint32_t)RESET) + { + if ((CAN->TXSTS & (flag & 0x000FFFFF)) != (uint32_t)RESET) + { + status = SET; + } + else + { + status = RESET; + } + } + else if ((flag & 0x04000000) != (uint32_t)RESET) + { + if ((CAN->RXF0 & (flag & 0x000FFFFF)) != (uint32_t)RESET) + { + status = SET; + } + else + { + status = RESET; + } + } + else + { + if ((CAN->RXF1 & (flag & 0x000FFFFF)) != (uint32_t)RESET) + { + status = SET; + } + else + { + status = RESET; + } + } + return status; +} + +/*! + * @brief Clears the status flags of CAN. + * + * @param flag : specifies the flag to clear. + * The parameter can be one of following values: + * @arg CAN_FLAG_LEC : Last error code Flag + * @arg CAN_FLAG_WUP : Wake up Flag + * @arg CAN_FLAG_SLAK : Sleep acknowledge Flag + * @arg CAN_FLAG_RQCP0: Request MailBox0 Flag + * @arg CAN_FLAG_RQCP1: Request MailBox1 Flag + * @arg CAN_FLAG_RQCP2: Request MailBox2 Flag + * @arg CAN_FLAG_FF0 : FIFO 0 Full Flag + * @arg CAN_FLAG_FOV0 : FIFO 0 Overrun Flag + * @arg CAN_FLAG_FF1 : FIFO 1 Full Flag + * @arg CAN_FLAG_FOV1 : FIFO 1 Overrun Flag + * + * @retval None + */ +void CAN_ClearStatusFlag(CAN_FLAG_T flag) +{ + uint32_t flagtmp = 0; + + if (flag == CAN_FLAG_LEC) + { + CAN->ERRSTS_B.LERRC = 0; + } + else + { + flagtmp = flag & 0x000FFFFF; + + if ((flag & 0x01000000) != RESET) + { + CAN->MSTS = flagtmp; + } + else if ((flag & 0x02000000) != RESET) + { + CAN->TXSTS = flagtmp; + } + else if ((flag & 0x04000000) != RESET) + { + CAN->RXF0 = flagtmp; + } + else + { + CAN->RXF1 = flagtmp; + } + } +} + +/*! + * @brief Reads the specified CAN interrupt flag status. + * + * @param interrupt: specifies the CAN interrupt source. + * The parameter can be one of following values: + * @arg CAN_INT_TXME : Transmit mailbox empty Interrupt + * @arg CAN_INT_F0MP : FIFO 0 message pending Interrupt + * @arg CAN_INT_F0FUL: FIFO 0 full Interrupt + * @arg CAN_INT_F0OVR: FIFO 0 overrun Interrupt + * @arg CAN_INT_F1MP : FIFO 1 message pending Interrupt + * @arg CAN_INT_F1FUL: FIFO 1 full Interrupt + * @arg CAN_INT_F1OVR: FIFO 1 overrun Interrupt + * @arg CAN_INT_EWIE : Error warning Interrupt + * @arg CAN_INT_EPIE : Error passive Interrupt + * @arg CAN_INT_BOIE : Bus-off Interrupt + * @arg CAN_INT_LEC : Last error code Interrupt + * @arg CAN_INT_ERR : Error Interrupt + * @arg CAN_INT_WUP : Wake-up Interrupt + * @arg CAN_INT_SLE : Sleep acknowledge Interrupt + * + * @retval status : SET or RESET + */ +uint8_t CAN_ReadIntFlag(CAN_INT_T interrupt) +{ + uint8_t status = 0; + + if ((CAN->INTEN & interrupt) != RESET) + { + switch (interrupt) + { + case CAN_INT_TXME: + status = CAN->TXSTS_B.REQCFLG0; + status |= CAN->TXSTS_B.REQCFLG1; + status |= CAN->TXSTS_B.REQCFLG2; + break; + case CAN_INT_F0MP: + status = !(!CAN->RXF0_B.FMNUM0); + break; + case CAN_INT_F0FUL: + status = CAN->RXF0_B.FFULLFLG0; + break; + case CAN_INT_F0OVR: + status = CAN->RXF0_B.FOVRFLG0; + break; + case CAN_INT_F1MP: + status = !(!CAN->RXF1_B.FMNUM1); + break; + case CAN_INT_F1FUL: + status = CAN->RXF1_B.FFULLFLG1; + break; + case CAN_INT_F1OVR: + status = CAN->RXF1_B.FOVRFLG1; + break; + case CAN_INT_EWIE: + status = CAN->ERRSTS_B.ERRWFLG; + break; + case CAN_INT_EPIE: + status = CAN->ERRSTS_B.ERRPFLG; + break; + case CAN_INT_BOIE: + status = CAN->ERRSTS_B.BOFLG; + break; + case CAN_INT_LEC: + status = !(!CAN->ERRSTS_B.LERRC); + break; + case CAN_INT_ERR: + status = CAN->MSTS_B.ERRIFLG; + break; + case CAN_INT_WUP: + status = CAN->MSTS_B.WUPIFLG; + break; + case CAN_INT_SLE: + status = CAN->MSTS_B.SLEEPIFLG; + break; + default: + status = RESET; + break; + } + } + else + { + status = RESET; + } + return status; +} + +/*! + * @brief Clears the CAN's interrupt flag. + * + * @param interrupt: specifies the interrupt flag to clear. + * The parameter can be any combination of the following values: + * @arg CAN_INT_TXME : Transmit mailbox empty Interrupt + * @arg CAN_INT_F0FUL: FIFO 0 full Interrupt + * @arg CAN_INT_F0OVR: FIFO 0 overrun Interrupt + * @arg CAN_INT_F1FUL: FIFO 1 full Interrupt + * @arg CAN_INT_F1OVR: FIFO 1 overrun Interrupt + * @arg CAN_INT_EWIE : Error warning Interrupt + * @arg CAN_INT_EPIE : Error passive Interrupt + * @arg CAN_INT_BOIE : Bus-off Interrupt + * @arg CAN_INT_LEC : Last error code Interrupt + * @arg CAN_INT_ERR : Error Interrupt + * @arg CAN_INT_WUP : Wake-up Interrupt + * @arg CAN_INT_SLE : Sleep acknowledge Interrupt + * + * @retval None + */ +void CAN_ClearIntFlag(uint32_t interrupt) +{ + if (interrupt & CAN_INT_TXME) + { + CAN->TXSTS_B.REQCFLG0 = BIT_SET; + CAN->TXSTS_B.REQCFLG1 = BIT_SET; + CAN->TXSTS_B.REQCFLG2 = BIT_SET; + } + if (interrupt & CAN_INT_F0FUL) + { + CAN->RXF0_B.FFULLFLG0 = BIT_SET; + } + if (interrupt & CAN_INT_F0OVR) + { + CAN->RXF0_B.FOVRFLG0 = BIT_SET; + } + if (interrupt & CAN_INT_F1FUL) + { + CAN->RXF1_B.FFULLFLG1 = BIT_SET; + } + if (interrupt & CAN_INT_F1OVR) + { + CAN->RXF1_B.FOVRFLG1 = BIT_SET; + } + if (interrupt & CAN_INT_EWIE) + { + /** Note : the corresponding Flag is cleared by hardware + * depending of the CAN Bus status + */ + CAN->MSTS_B.ERRIFLG = BIT_SET; + } + if (interrupt & CAN_INT_EPIE) + { + /** Note : the corresponding Flag is cleared by hardware + * depending of the CAN Bus status + */ + CAN->MSTS_B.ERRIFLG = BIT_SET; + } + if (interrupt & CAN_INT_BOIE) + { + /** Note : the corresponding Flag is cleared by hardware + * depending of the CAN Bus status + */ + CAN->MSTS_B.ERRIFLG = BIT_SET; + } + if (interrupt & CAN_INT_LEC) + { + CAN->ERRSTS_B.LERRC = 0; + CAN->MSTS_B.ERRIFLG = BIT_SET; + } + if (interrupt & CAN_INT_ERR) + { + CAN->ERRSTS_B.LERRC = 0; + CAN->MSTS_B.ERRIFLG = BIT_SET; + } + if (interrupt & CAN_INT_WUP) + { + CAN->MSTS_B.WUPIFLG = BIT_SET; + } + if (interrupt & CAN_INT_SLE) + { + CAN->MSTS_B.SLEEPIFLG = BIT_SET; + } +} + +/**@} end of group CAN_Functions */ +/**@} end of group CAN_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_cec.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_cec.c new file mode 100644 index 0000000000..b82849ab98 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_cec.c @@ -0,0 +1,418 @@ +/*! + * @file apm32f0xx_cec.c + * + * @brief This file contains all the functions for the CEC peripheral + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "apm32f0xx_cec.h" +#include "apm32f0xx_rcm.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup CEC_Driver + @{ +*/ + +/** @defgroup CEC_Macros Macros + @{ +*/ + +/**@} end of group CEC_Macros */ + +/** @defgroup CEC_Enumerations Enumerations + @{ +*/ + +/**@} end of group CEC_Enumerations */ + +/** @defgroup CEC_Structures Structures + @{ +*/ + +/**@} end of group CEC_Structures */ + +/** @defgroup CEC_Variables Variables + @{ +*/ + +/**@} end of group CEC_Variables */ + +/** @defgroup CEC_Functions Functions + @{ +*/ + +/*! + * @brief Reset CEC peripheral registers to their default values. + * + * @param None + * + * @retval None + */ +void CEC_Reset(void) +{ + RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_CEC); + RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_CEC); +} + +/*! + * @brief Configs the CEC peripheral according to the specified parameters + * in the cecConfig. + * + * @param cecConfig: pointer to an CEC_Config_T structure that is used to + * the configuration information for the specified CEC peripheral. + * + * @retval None + * + * @note The CEC parameters must be configured before enabling the CEC peripheral. + */ +void CEC_Config(CEC_Config_T* cecConfig) +{ + CEC->CFG_B.SFTCFG = cecConfig->signalFreeTime; + CEC->CFG_B.RXTCFG = cecConfig->RxTolerance; + CEC->CFG_B.RXSBRERR = cecConfig->stopReception; + CEC->CFG_B.GEBRERR = cecConfig->bitRisingError; + CEC->CFG_B.GELBPERR = cecConfig->longPeriodError; + CEC->CFG_B.AEBGIB = cecConfig->broadcastrNoGen; + CEC->CFG_B.SFTOB = cecConfig->signalFreeTimeOption; +} + +/*! + * @brief Fills each CEC_InitStruct member with its default value. + * + * @param cecConfig: pointer to a CEC_InitTypeDef structure which will + * be initialized. + * + * @retval None + */ +void CEC_ConfigStructInit(CEC_Config_T* cecConfig) +{ + cecConfig->signalFreeTime = CEC_SINGANL_FREETIME_STANDARD; + cecConfig->RxTolerance = CEC_RX_TOLERANCE_STANDARD; + cecConfig->stopReception = CEC_STOP_RECEPTION_OFF; + cecConfig->bitRisingError = CEC_BIT_RISING_ERR_OFF; + cecConfig->longPeriodError = CEC_LONG_PERIOD_ERR_OFF; + cecConfig->broadcastrNoGen = CEC_BROADCAST_NO_ERR_OFF; + cecConfig->signalFreeTimeOption = CEC_SIGNAL_FREETIME_OPTION_OFF; +} + +/*! + * @brief Enables the CEC peripheral. + * + * @param None + * + * @retval None + */ +void CEC_Enable(void) +{ + CEC->CTRL_B.CECEN = SET; +} + +/*! + * @brief Disables the CEC peripheral. + * + * @param None + * + * @retval None + */ +void CEC_Disable(void) +{ + CEC->CTRL_B.CECEN = RESET; +} + +/*! + * @brief Enables the CEC Listen Mode. + * + * @param None + * + * @retval None + */ +void CEC_EnableListenMode(void) +{ + CEC->CFG_B.LMODSEL = SET; +} + +/*! + * @brief Disables the CEC Listen Mode. + * + * @param None + * + * @retval None + */ +void CEC_DisableListenMode(void) +{ + CEC->CFG_B.LMODSEL = RESET; +} + +/*! + * @brief Defines the Own Address of the CEC device. + * + * @param ownAddress: The CEC own address. + * + * @retval None + */ +void CEC_ConfigOwnAddress(uint8_t ownAddress) +{ + CEC->CFG_B.OACFG |= (1 << ownAddress); +} + +/*! + * @brief Clears the Own Address of the CEC device. + * + * @param CEC_OwnAddress: The CEC own address. + * + * @retval None + */ +void CEC_ClearQwnAddress(void) +{ + CEC->CFG = 0x00; +} + +/*! + * @brief Transmits single data through the CEC peripheral. + * + * @param Data: the data to transmit. + * + * @retval None + */ +void CEC_TxData(uint8_t Data) +{ + CEC->TXDATA = Data; +} + +/*! + * @brief Returns the most recent received data by the CEC peripheral. + * + * @param None + * + * @retval The received data. + */ +uint8_t CEC_RxData(void) +{ + return (uint8_t)(CEC->RXDATA); +} + +/*! + * @brief Starts a new message. + * + * @param None + * + * @retval None + */ +void CEC_StartNewMessage(void) +{ + CEC->CTRL_B.TXSM = SET; +} + +/*! + * @brief Transmits message with an EOM bit. + * + * @param None + * + * @retval None + */ +void CEC_CompleteMessage(void) +{ + CEC->CTRL_B.TXEM = SET; +} + +/*! + * @brief Enables the selected CEC interrupts. + * + * @param flag: specifies the CEC interrupt source to be enabled. + * This parameter can be any combination of the following values: + * @arg CEC_INT_RXBR Rx-Byte Received + * @arg CEC_INT_RXEND End Of Reception + * @arg CEC_INT_RXOVR Rx Overrun. + * @arg CEC_INT_BRE Rx Bit Rising Error + * @arg CEC_INT_SBPE Rx Short period Error + * @arg CEC_INT_LBPE Rx Long period Error + * @arg CEC_INT_RXACKE Rx-Missing Acknowledge + * @arg CEC_INT_ARBLST Arbitration Lost + * @arg CEC_INT_TXBR Tx-Byte Request. + * @arg CEC_INT_TXEND End of Transmission + * @arg CEC_INT_TXUDR Tx-Buffer Underrun. + * @arg CEC_INT_TXERR Tx Error. + * @arg CEC_INT_TXACKE Tx Missing acknowledge Error + * + * @retval None + */ +void CEC_EnableInterrupt(uint32_t interrupt) +{ + CEC->INTEN |= (uint32_t)interrupt; +} + +/*! + * @brief Disables the selected CEC interrupts. + * + * @param flag: specifies the CEC interrupt source to be enabled. + * This parameter can be any combination of the following values: + * @arg CEC_INT_RXBR Rx-Byte Received + * @arg CEC_INT_RXEND End Of Reception + * @arg CEC_INT_RXOVR Rx Overrun. + * @arg CEC_INT_BRE Rx Bit Rising Error + * @arg CEC_INT_SBPE Rx Short period Error + * @arg CEC_INT_LBPE Rx Long period Error + * @arg CEC_INT_RXACKE Rx-Missing Acknowledge + * @arg CEC_INT_ARBLST Arbitration Lost + * @arg CEC_INT_TXBR Tx-Byte Request. + * @arg CEC_INT_TXEND End of Transmission + * @arg CEC_INT_TXUDR Tx-Buffer Underrun. + * @arg CEC_INT_TXERR Tx Error. + * @arg CEC_INT_TXACKE Tx Missing acknowledge Error + * + * @retval None + */ +void CEC_DisableInterrupt(uint32_t interrupt) +{ + CEC->INTEN &= ~(uint32_t)interrupt; +} + +/*! + * @brief Read the CEC flag status. + * + * @param flag: specifies the CEC interrupt source to be enabled. + * This parameter can be any combination of the following values: + * @arg CEC_FLAG_RXBR Rx-Byte Received + * @arg CEC_FLAG_RXEND End Of Reception + * @arg CEC_FLAG_RXOVR Rx Overrun. + * @arg CEC_FLAG_BRE Rx Bit Rising Error + * @arg CEC_FLAG_SBPE Rx Short period Error + * @arg CEC_FLAG_LBPE Rx Long period Error + * @arg CEC_FLAG_RXACKE Rx-Missing Acknowledge + * @arg CEC_FLAG_ARBLST Arbitration Lost + * @arg CEC_FLAG_TXBR Tx-Byte Request. + * @arg CEC_FLAG_TXEND End of Transmission + * @arg CEC_FLAG_TXUDR Tx-Buffer Underrun. + * @arg CEC_FLAG_TXERR Tx Error. + * @arg CEC_FLAG_TXACKE Tx Missing acknowledge Error + * + * @retval The new state of CEC_FLAG (SET or RESET) + */ +uint8_t CEC_ReadStatusFlag(uint32_t flag) +{ + uint32_t status; + + status = (uint32_t)(CEC->STS & flag); + + if (status == flag) + { + return SET; + } + + return RESET; +} + +/*! + * @brief Clears the CEC's pending flags. + * + * @param flag: specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg CEC_FLAG_RXBR Rx-Byte Received + * @arg CEC_FLAG_RXEND End Of Reception + * @arg CEC_FLAG_RXOVR Rx Overrun. + * @arg CEC_FLAG_BRE Rx Bit Rising Error + * @arg CEC_FLAG_SBPE Rx Short period Error + * @arg CEC_FLAG_LBPE Rx Long period Error + * @arg CEC_FLAG_RXACKE Rx-Missing Acknowledge + * @arg CEC_FLAG_ARBLST Arbitration Lost + * @arg CEC_FLAG_TXBR Tx-Byte Request. + * @arg CEC_FLAG_TXEND End of Transmission + * @arg CEC_FLAG_TXUDR Tx-Buffer Underrun. + * @arg CEC_FLAG_TXERR Tx Error. + * @arg CEC_FLAG_TXACKE Tx Missing acknowledge Error + * + * @retval None + */ +void CEC_ClearStatusFlag(uint32_t flag) +{ + CEC->STS = flag; +} + +/*! + * @brief Checks whether the specified CEC interrupt has occurred or not. + * + * @param flag: specifies the CEC interrupt source to check. + * This parameter can be one of the following values: + * @arg CEC_INT_RXBR Rx-Byte Received + * @arg CEC_INT_RXEND End Of Reception + * @arg CEC_INT_RXOVR Rx Overrun. + * @arg CEC_INT_BRE Rx Bit Rising Error + * @arg CEC_INT_SBPE Rx Short period Error + * @arg CEC_INT_LBPE Rx Long period Error + * @arg CEC_INT_RXACKE Rx-Missing Acknowledge + * @arg CEC_INT_ARBLST Arbitration Lost + * @arg CEC_INT_TXBR Tx-Byte Request. + * @arg CEC_INT_TXEND End of Transmission + * @arg CEC_INT_TXUDR Tx-Buffer Underrun. + * @arg CEC_INT_TXERR Tx Error. + * @arg CEC_INT_TXACKE Tx Missing acknowledge Error + * + * @retval The new state of Flag (SET or RESET). + */ +uint8_t CEC_ReadIntFlag(uint16_t flag) +{ + uint32_t intEnable; + uint32_t intStatus; + intEnable = (CEC->INTEN & flag); + intStatus = (CEC->STS & flag); + if ((intStatus != (uint32_t)RESET) && intEnable) + { + return SET; + } + else + { + return RESET; + } +} + +/*! + * @brief Clears the CEC's interrupt flag. + * + * @param flag: specifies the CEC interrupt flag to clear. + * This parameter can be any combination of the following values: + * @arg CEC_INT_RXBR Rx-Byte Received + * @arg CEC_INT_RXEND End Of Reception + * @arg CEC_INT_RXOVR Rx Overrun. + * @arg CEC_INT_BRE Rx Bit Rising Error + * @arg CEC_INT_SBPE Rx Short period Error + * @arg CEC_INT_LBPE Rx Long period Error + * @arg CEC_INT_RXACKE Rx-Missing Acknowledge + * @arg CEC_INT_ARBLST Arbitration Lost + * @arg CEC_INT_TXBR Tx-Byte Request. + * @arg CEC_INT_TXEND End of Transmission + * @arg CEC_INT_TXUDR Tx-Buffer Underrun. + * @arg CEC_INT_TXERR Tx Error. + * @arg CEC_INT_TXACKE Tx Missing acknowledge Error + * + * @retval None + */ +void CEC_ClearIntFlag(uint16_t flag) +{ + CEC->STS = flag; +} + +/**@} end of group CEC_Functions */ +/**@} end of group CEC_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_comp.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_comp.c new file mode 100644 index 0000000000..9f2f034af3 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_comp.c @@ -0,0 +1,298 @@ +/*! + * @file apm32f0xx_comp.c + * + * @brief This file contains all the functions for the COMP peripheral + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "apm32f0xx_comp.h" +#include "apm32f0xx_rcm.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup COMP_Driver + @{ +*/ + +/** @defgroup COMP_Macros Macros + @{ +*/ + +/**@} end of group COMP_Macros */ + +/** @defgroup COMP_Enumerations Enumerations + @{ +*/ + +/**@} end of group COMP_Enumerations */ + +/** @defgroup COMP_Structures Structures + @{ +*/ + +/**@} end of group COMP_Structures */ + +/** @defgroup COMP_Variables Variables + @{ +*/ + +/**@} end of group COMP_Variables */ + +/** @defgroup COMP_Functions Functions + @{ +*/ + +/*! + * @brief Reset COMP peripheral registers to their default values. + * + * @param None + * + * @retval None + * + * @note Deinitialization can't be performed if the COMP configuration is locked. + * To unlock the configuration, perform a system reset. + */ +void COMP_Reset(void) +{ + COMP->CSTS = ((uint32_t)0x00000000); +} + +/*! + * @brief Configs the COMP peripheral according to the specified parameters + * in COMP_InitStruct + * + * @param compSelect: the selected comparator. + * This parameter can be one of the following values: + * @arg COMP_SELECT_COMP1: COMP1 selected + * @arg COMP_SELECT_COMP2: COMP2 selected + * + * @param compConfig: pointer to an COMP_Config_T structure that contains + * the configuration information for the specified COMP peripheral. + * + * @retval None + * + * @note If the selected comparator is locked, initialization can't be performed. + * To unlock the configuration, perform a system reset. + * + * @note By default, PA1 is selected as COMP1 non inverting input. + * To use PA4 as COMP1 non inverting input call COMP_EnableSwitch() after COMP_Config() + * + */ +void COMP_Config(COMP_SELECT_T compSelect, COMP_Config_T* compConfig) +{ + if (compSelect == COMP_SELECT_COMP1) + { + COMP->CSTS_B.INVINSEL1 = compConfig->invertingInput; + COMP->CSTS_B.OUTSEL1 = compConfig->output; + COMP->CSTS_B.OPINV1 = compConfig->outputPol; + COMP->CSTS_B.HYSCFG1 = compConfig->hysterrsis; + COMP->CSTS_B.MOD1 = compConfig->mode; + } + else + { + COMP->CSTS_B.INVINSEL2 = compConfig->invertingInput; + COMP->CSTS_B.OUTSEL2 = compConfig->output; + COMP->CSTS_B.OPINV2 = compConfig->outputPol; + COMP->CSTS_B.HYSCFG2 = compConfig->hysterrsis; + COMP->CSTS_B.MOD2 = compConfig->mode; + } +} + +/*! + * @brief Fills each compConfig member with initial value value. + * + * @param compConfig: pointer to an COMP_InitTypeDef structure which will + * be initialized. + * + * @retval None + */ +void COMP_ConfigStructInit(COMP_Config_T* compConfig) +{ + compConfig->invertingInput = COMP_INVERTING_INPUT_1_4VREFINT; + compConfig->output = COMP_OUTPUT_NONE; + compConfig->outputPol = COMP_OUTPUTPOL_NONINVERTED; + compConfig->hysterrsis = COMP_HYSTERRSIS_NO; + compConfig->mode = COMP_MODE_HIGHSPEED; +} + +/*! + * @brief Enable the COMP peripheral. + * + * @param compSelect: the selected comparator. + * This parameter can be one of the following values: + * @arg COMP_SELECT_COMP1: COMP1 selected + * @arg COMP_SELECT_COMP2: COMP2 selected + * + * @retval None + * + * @note If the selected comparator is locked, enable can't be performed. + * To unlock the configuration, perform a system reset. + */ +void COMP_Enable(COMP_SELECT_T compSelect) +{ + if (compSelect == COMP_SELECT_COMP1) + { + COMP->CSTS_B.EN1 = SET; + } + else + { + COMP->CSTS_B.EN2 = SET; + } +} + +/*! + * @brief Disable the COMP peripheral. + * + * @param compSelect: the selected comparator. + * This parameter can be one of the following values: + * @arg COMP_SELECT_COMP1: COMP1 selected + * @arg COMP_SELECT_COMP2: COMP2 selected + * + * @retval None + * + * @note If the selected comparator is locked, disable can't be performed. + * To unlock the configuration, perform a system reset. + */ +void COMP_Disable(COMP_SELECT_T compSelect) +{ + if (compSelect == COMP_SELECT_COMP1) + { + COMP->CSTS_B.EN1 = RESET; + } + else + { + COMP->CSTS_B.EN2 = RESET; + } +} + +/*! + * @brief Close the SW1 switch. + * + * @param None + * + * @retval None + * + * @note This switch is solely intended to redirect signals onto high + * impedance input, such as COMP1 non-inverting input (highly resistive switch) + */ +void COMP_EnableSwitch(void) +{ + COMP->CSTS_B.SW1 = SET; +} + +/*! + * @brief Open the SW1 switch. + * + * @param None + * + * @retval None + */ +void COMP_DisableSwitch(void) +{ + COMP->CSTS_B.SW1 = RESET; +} + +/*! + * @brief Return the output level (high or low) of the selected comparator. + * + * @param compSelect: the selected comparator. + * This parameter can be one of the following values: + * @arg COMP_SELECT_COMP1: COMP1 selected + * @arg COMP_SELECT_COMP2: COMP2 selected + * + * @retval Returns the selected comparator output level: low or high. + */ +uint32_t COMP_ReadOutPutLevel(COMP_SELECT_T compSelect) +{ + uint32_t compOUT = 0x00; + if (compSelect == COMP_SELECT_COMP1) + { + if ((COMP->CSTS & COMP_CSTS_COMP1OUT) != 0) + { + compOUT = COMP_OUTPUTLEVEL_HIGH; + } + else + compOUT = COMP_OUTPUTLEVEL_LOW; + } + else + { + if ((COMP->CSTS & COMP_CSTS_COMP2OUT) != 0) + { + compOUT = COMP_OUTPUTLEVEL_HIGH; + } + else + compOUT = COMP_OUTPUTLEVEL_LOW; + } + return (uint32_t)(compOUT); +} + +/*! + * @brief Enablesthe window mode. + * + * @param None + * + * @retval None + */ +void COMP_EnableWindow(void) +{ + COMP->CSTS_B.WMODEN = SET; +} + +/*! + * @brief Disables the window mode. + * + * @param None + * + * @retval None + */ +void COMP_DisnableWindow(void) +{ + COMP->CSTS_B.WMODEN = RESET; +} + +/*! + * @brief Lock the selected comparator configuration. + * + * @param compSelect: selects the comparator to be locked + * This parameter can be one of the following values: + * @arg COMP_SELECT_COMP1: COMP1 configuration is locked. + * @arg COMP_SELECT_COMP2: COMP2 configuration is locked. + * + * @retval None + */ +void COMP_ConfigLOCK(COMP_SELECT_T compSelect) +{ + if (compSelect == COMP_SELECT_COMP1) + { + COMP->CSTS_B.LOCK1 = SET; + } + else + { + COMP->CSTS_B.LOCK2 = SET; + } +} + +/**@} end of group COMP_Functions */ +/**@} end of group COMP_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_crc.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_crc.c new file mode 100644 index 0000000000..ae2f6b4426 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_crc.c @@ -0,0 +1,284 @@ +/*! + * @file apm32f0xx_crc.c + * + * @brief This file provides all the CRC firmware functions + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* include */ +#include "apm32f0xx_crc.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup CRC_Driver + @{ +*/ + +/** @defgroup CRC_Macros Macros + @{ +*/ + +/**@} end of group CRC_Macros */ + +/** @defgroup CRC_Enumerations Enumerations + @{ +*/ + +/**@} end of group CRC_Enumerations */ + +/** @defgroup CRC_Structures Structures + @{ +*/ + +/**@} end of group CRC_Structures */ + +/** @defgroup CRC_Variables Variables + @{ +*/ + +/**@} end of group CRC_Variables */ + +/** @defgroup CRC_Functions Functions + @{ +*/ + +/*! + * @brief Resets the CRC peripheral registers to their default reset values. + * + * @param None + * + * @retval None + */ +void CRC_Reset(void) +{ + CRC->DATA = 0xFFFFFFFF; + CRC->INDATA = 0x00; + CRC->INITVAL = 0xFFFFFFFF; + CRC->CTRL = 0x00000000; + CRC->POL = 0x04C11DB7; +} + +/*! + * @brief Reset CRC data register (DATA) + * + * @param None + * + * @retval None + */ +void CRC_ResetDATA(void) +{ + CRC->CTRL_B.RST = BIT_SET; +} + +/*! + * @brief Set the CRC polynomial size. + * + * @param polynomialSize: CRC polynomial size + * The parameter can be one of following values: + * @arg CRC_POLYNOMIAL_SIZE_7: 7-bit polynomial for CRC calculation + * @arg CRC_POLYNOMIAL_SIZE_8: 8-bit polynomial for CRC calculation + * @arg CRC_POLYNOMIAL_SIZE_16: 16-bit polynomial for CRC calculation + * @arg CRC_POLYNOMIAL_SIZE_32: 32-bit polynomial for CRC calculation + * + * @retval None + * + * @note It's only for APM32F072 and APM32F091 devices + */ +void CRC_SetPolynomialSize(CRC_POLYNOMIAL_SIZE_T polynomialSize) +{ + CRC->CTRL_B.POLSIZE = polynomialSize; +} + +/*! + * @brief Set the CRC polynomail coefficients. + * + * @param polynomialValue: Polynomial to be used for CRC calculation + * + * @retval None + * + * @note It's only for APM32F072 and APM32F091 devices + */ +void CRC_SetPolynomialValue(uint32_t polynomialValue) +{ + CRC->POL = polynomialValue; +} + +/*! + * @brief Selects the reverse operation to be performed on input data + * + * @param revInData: Reverse input data + * The parameter can be one of following values: + * @arg CRC_REVERSE_INPUT_DATA_NO: Bit order not affected + * @arg CRC_REVERSE_INPUT_DATA_8B: Bit reversal done by byte + * @arg CRC_REVERSE_INPUT_DATA_16B: Bit reversal done by half-word + * @arg CRC_REVERSE_INPUT_DATA_32B: Bit reversal done by word + * + * @retval None + */ +void CRC_SelectReverseInputData(CRC_REVERSE_INPUT_DATA_T revInData) +{ + CRC->CTRL_B.REVI = revInData; +} + +/*! + * @brief Enable the reverse operation on output data + * + * @param None + * + * @retval None + */ +void CRC_EnableReverseOutputData(void) +{ + CRC->CTRL_B.REVO = BIT_SET; +} + +/*! + * @brief Disable the reverse operation on output data + * + * @param None + * + * @retval None + */ +void CRC_DisableReverseOutputData(void) +{ + CRC->CTRL_B.REVO = BIT_RESET; +} + +/*! + * @brief Initializes the INITVAL register. + * + * @param initValue: Programmable initial CRC value + * + * @retval None + */ +void CRC_WriteInitRegister(uint32_t initValue) +{ + CRC->INITVAL = initValue; +} + +/*! + * @brief Calculate a 32-bit CRC for a given data word (32 bits) + * + * @param data: data word(32-bit) to compute its CRC + * + * @retval 32-bit CRC + */ +uint32_t CRC_CalculateCRC(uint32_t data) +{ + CRC->DATA = data; + + return (CRC->DATA); +} + +/*! + * @brief Calculate a 32-bit CRC for a given data word (16 bits) + * + * @param data: data word(16-bit) to compute its CRC + * + * @retval 16-bit CRC + * + * @note It's only for APM32F072 and APM32F091 devices + */ +uint32_t CRC_CalculateCRC16bits(uint16_t data) +{ + *(uint16_t*)(CRC_BASE) = (uint16_t) data; + + return (CRC->DATA); +} + +/*! + * @brief Calculate a 32-bit CRC for a given data word (8 bits) + * + * @param data: data word(8-bit) to compute its CRC + * + * @retval 8-bit CRC + * + * @note It's only for APM32F072 and APM32F091 devices + */ +uint32_t CRC_CalculateCRC8bits(uint8_t data) +{ + *(uint8_t*)(CRC_BASE) = (uint8_t) data; + + return (CRC->DATA); +} + +/*! + * @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: buffer length + * + * @retval 32-bit CRC + */ +uint32_t CRC_CalculateBlockCRC(uint32_t pBuffer[], uint32_t bufferLength) +{ + uint32_t index = 0; + + for (index = 0; index < bufferLength; index++) + { + CRC->DATA = pBuffer[index]; + } + + return (CRC->DATA); +} + +/*! + * @brief Returns the current CRC value + * + * @param None + * + * @retval 32-bit CRC + */ +uint32_t CRC_ReadCRC(void) +{ + return (CRC->DATA); +} + +/*! + * @brief Stores a 8-bit data in the Independent Data(INDATA) register + * + * @param IDValue: 8-bit value to be stored in the INDATA register + * + * @retval None + */ +void CRC_WriteIDRegister(uint8_t IDValue) +{ + CRC->INDATA = IDValue; +} + +/*! + * @brief Returns a 8-bit data stored in the Independent Data(INDATA) register + * + * @param None + * + * @retval 8-bit value of the INDATA register + */ +uint8_t CRC_ReadIDRegister(void) +{ + return (CRC->INDATA); +} + +/**@} end of group CRC_Functions */ +/**@} end of group CRC_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_crs.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_crs.c new file mode 100644 index 0000000000..0ecec279f3 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_crs.c @@ -0,0 +1,424 @@ +/*! + * @file apm32f0xx_crs.c + * + * @brief This file contains all the functions for the CRS peripheral + * + * @note It's only for APM32F072 and APM32F091 devices + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "apm32f0xx_crs.h" +#include "apm32f0xx_rcm.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup CRS_Driver + @{ +*/ + +/** @defgroup CRS_Macros Macros + @{ +*/ + +/**@} end of group CRS_Macros */ + +/** @defgroup CRS_Enumerations Enumerations + @{ +*/ + +/**@} end of group CRS_Enumerations */ + +/** @defgroup CRS_Structures Structures + @{ +*/ + +/**@} end of group CRS_Structures */ + +/** @defgroup CRS_Variables Variables + @{ +*/ + +/**@} end of group CRS_Variables */ + +/** @defgroup CRS_Functions Functions + @{ +*/ + +/*! + * @brief Resets the CRS peripheral registers to their default reset values. + * + * @param None + * + * @retval None + */ +void CRS_Reset(void) +{ + RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_CRS); + RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_CRS); +} + +/*! + * @brief Adjusts the Internal High Speed 48 oscillator (HSI 48) calibration value. + * + * @param calibrationVal: HSI48 oscillator smooth trimming value. It can be 0x0 to 0xF. + * + * @retval None + */ +void CRS_AdjustHSI48CalibrationValue(uint8_t calibrationVal) +{ + CRS->CTRL_B.HSI48TRM = calibrationVal; +} + +/*! + * @brief Enables the oscillator clock for frequency error counter. + * + * @param None + * + * @retval None + */ +void CRS_EnableFrequencyErrorCounter(void) +{ + CRS->CTRL_B.CNTEN = SET; +} + +/*! + * @brief Disables the oscillator clock for frequency error counter. + * + * @param None + * + * @retval None + */ +void CRS_DisableFrequencyErrorCounter(void) +{ + CRS->CTRL_B.CNTEN = RESET; +} + +/*! + * @brief Enables the automatic hardware adjustement of HSI48TRM bits. + * + * @param None + * + * @retval None + */ +void CRS_EnableAutomaticCalibration(void) +{ + CRS->CTRL_B.AUTOTRMEN = SET; +} + +/*! + * @brief Disables the automatic hardware adjustement of HSI48TRM bits. + * + * @param None + * + * @retval None + */ +void CRS_DisableAutomaticCalibration(void) +{ + CRS->CTRL_B.AUTOTRMEN = RESET; +} + +/*! + * @brief Generate the software synchronization event. + * + * @param None + * + * @retval None + */ +void CRS_GenerateSoftwareSynchronization(void) +{ + CRS->CTRL_B.SWSGNR = SET; +} + +/*! + * @brief Adjusts the Internal High Speed 48 oscillator (HSI 48) calibration value. + * + * @param reloadVal: specifies the HSI calibration trimming value. + * This parameter must be a number between 0 and 0xFFFF. + * + * @retval None + */ +void CRS_FrequencyErrorCounterReloadValue(uint16_t reloadVal) +{ + CRS->CFG_B.RLDVAL = reloadVal; +} + +/** + * @brief Configs the frequency error limit value. + * + * @param errLimitVal: specifies the HSI calibration trimming value. + * + * @retval None + */ +void CRS_ConfigFrequencyErrorLimit(uint8_t errLimitVal) +{ + CRS->CFG_B.FELMT = errLimitVal; +} + +/*! + * @brief Configs SYNC divider. + * + * @param div: defines the SYNC divider. + * This parameter can be one of the following values: + * @arg CRS_SYNC_DIV1 + * @arg CRS_SYNC_DIV2 + * @arg CRS_SYNC_DIV4 + * @arg CRS_SYNC_DIV8 + * @arg CRS_SYNC_DIV16 + * @arg CRS_SYNC_DIV32 + * @arg CRS_SYNC_DIV64 + * @arg CRS_SYNC_DIV128 + * + * @retval None + */ +void CRS_ConfigSynchronizationPrescaler(CRS_SYNC_DIV_T div) +{ + CRS->CFG_B.SYNCPSC = div; +} + +/*! + * @brief Configs the SYNC signal source. + * + * @param source: specifies the SYNC signal source. + * This parameter can be one of the following values: + * @arg CRS_SYNC_SOURCE_GPIO + * @arg CRS_SYNC_SOURCE_LSE + * @arg CRS_SYNC_SOURCE_USB + * + * @retval None + */ +void CRS_ConfigSynchronizationSource(CRS_SYNC_SOURCE_T source) +{ + CRS->CFG_B.SYNCSRCSEL = source; +} + +/*! + * @brief Configs the SYNC polarity. + * + * @param polarity: specifies SYNC polarity. + * This parameter can be one of the following values: + * @arg CRS_SYNC_POL_RISING + * @arg CRS_SYNC_POL_FALLING + * + * @retval None + */ +void CRS_ConfigSynchronizationPolarity(CRS_SYNC_POL_T polarity) +{ + CRS->CFG_B.SYNCPOLSEL = polarity; +} + +/*! + * @brief Returns the Relaod value. + * + * @param None + * + * @retval The reload value + */ +uint32_t CRS_ReadReloadValue(void) +{ + return (uint32_t)CRS->CFG_B.RLDVAL; +} + +/*! + * @brief Returns the HSI48 Calibration value. + * + * @param None + * + * @retval The reload value + */ +uint32_t CRS_ReadHSI48CalibrationValue(void) +{ + return (uint32_t)CRS->CTRL_B.HSI48TRM; +} + +/*! + * @brief Returns the frequency error capture. + * + * @param None + * + * @retval The frequency error capture value + */ +uint32_t CRS_ReadFrequencyErrorValue(void) +{ + return (uint32_t)CRS->INTSTS_B.FECPT; +} + +/*! + * @brief Returns the frequency error direction. + * + * @param None + * + * @retval The frequency error direction. + * The returned value can be one of the following values: + * 0: Up counting + * 1: Down counting + */ +uint32_t CRS_ReadFrequencyErrorDirection(void) +{ + return (uint32_t)CRS->INTSTS_B.CNTDRCT; +} + +/*! + * @brief Enables the specified CRS interrupts. + * + * @param interrupt: specifies the RCC interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg CRS_INT_SYNCOK : SYNC event OK interrupt + * @arg CRS_INT_SYNCWARN: SYNC warning interrupt + * @arg CRS_INT_ERR : Synchronization or trimming error interrupt + * @arg CRS_INT_ESYNC : Expected SYNC interrupt + * + * @retval None + */ +void CRS_EnableInterrupt(CRS_INT_T interrupt) +{ + CRS->CTRL |= interrupt; +} + +/*! + * @brief Disables the specified CRS interrupts. + * + * @param interrupt: specifies the RCC interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg CRS_INT_SYNCOK : SYNC event OK interrupt + * @arg CRS_INT_SYNCWARN: SYNC warning interrupt + * @arg CRS_INT_ERR : Synchronization or trimming error interrupt + * @arg CRS_INT_ESYNC : Expected SYNC interrupt + * + * @retval None + */ +void CRS_DisableInterrupt(CRS_INT_T interrupt) +{ + CRS->CTRL &= ~interrupt; +} + +/*! + * @brief Checks whether the specified CRS flag is set or not. + * + * @param flag: specifies the flag to check. + * This parameter can be one of the following values: + * @arg CRS_FLAG_SYNCOK : SYNC event OK flag + * @arg CRS_FLAG_SYNCWARN: SYNC warning flag + * @arg CRS_FLAG_ERR : Synchronization or trimming error flag + * @arg CRS_FLAG_ESYNC : Expected SYNC flag + * @arg CRS_FLAG_SYNCERR : SYNC error flag + * @arg CRS_FLAG_SYNCMISS: SYNC missed flag + * @arg CRS_FLAG_TRIMOVF : Trimming overflow or underflow falg + * + * @retval The new state of CRS_FLAG (SET or RESET). + */ +uint8_t CRS_ReadStatusFlag(CRS_FLAG_T flag) +{ + uint32_t status; + status = (uint32_t)(CRS->INTSTS & flag); + + if (status == flag) + { + return SET; + } + + return RESET; +} + +/*! + * @brief Clears the CRS specified flag. + * + * @param flag: specifies the flag to check. + * This parameter can be one of the following values: + * @arg CRS_FLAG_SYNCOK : SYNC event OK flag + * @arg CRS_FLAG_SYNCWARN: SYNC warning flag + * @arg CRS_FLAG_ERR : Synchronization or trimming error flag + * @arg CRS_FLAG_ESYNC : Expected SYNC flag + * @arg CRS_FLAG_SYNCERR : SYNC error flag + * @arg CRS_FLAG_SYNCMISS: SYNC missed flag + * @arg CRS_FLAG_TRIMOVF : Trimming overflow or underflow falg + * + * @retval None + */ +void CRS_ClearStatusFlag(CRS_FLAG_T flag) +{ + if ((flag & 0x00000700) != 0) + { + CRS->INTCLR_B.ECLR = BIT_SET; + } + + CRS->INTCLR |= (uint32_t)flag; +} + +/*! + * @brief Checks CRS interrupt flag. + * + * @param flag: specifies the IT pending bit to check. + * This parameter can be one of the following values: + * @arg CRS_INT_SYNCOK : SYNC event OK interrupt + * @arg CRS_INT_SYNCWARN: SYNC warning interrupt + * @arg CRS_INT_ERR : Synchronization or trimming error interrupt + * @arg CRS_INT_ESYNC : Expected SYNC interrupt + * @arg CRS_INT_SYNCERR : SYNC error + * @arg CRS_INT_SYNCMISS: SYNC missed + * @arg CRS_INT_TRIMOVF : Trimming overflow or underflow + * + * @retval The new state of CRS_IT (SET or RESET). + */ +uint8_t CRS_ReadIntFlag(CRS_INT_T flag) +{ + if ((CRS->INTSTS & flag)) + { + return SET; + } + else + { + return RESET; + } +} + +/*! + * @brief Clears the CRS specified interrupt flag. + * + * @param intFlag: specifies the IT pending bi to clear. + * This parameter can be one of the following values: + * @arg CRS_INT_SYNCOK : SYNC event OK interrupt + * @arg CRS_INT_SYNCWARN: SYNC warning interrupt + * @arg CRS_INT_ERR : Synchronization or trimming error interrupt + * @arg CRS_INT_ESYNC : Expected SYNC interrupt + * @arg CRS_INT_SYNCERR : SYNC error + * @arg CRS_INT_SYNCMISS: SYNC missed + * @arg CRS_INT_TRIMOVF : Trimming overflow or underflow + * + * @retval None + */ +void CRS_ClearIntFlag(CRS_INT_T intFlag) +{ + if ((intFlag & (uint32_t)0x700) != 0) + { + CRS->INTCLR |= CRS_INT_ERR; + } + else + { + CRS->INTCLR |= intFlag; + } +} + +/**@} end of group CRS_Functions */ +/**@} end of group CRS_Driver*/ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_dac.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_dac.c new file mode 100644 index 0000000000..5089bb33b9 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_dac.c @@ -0,0 +1,595 @@ +/*! + * @file apm32f0xx_dac.c + * + * @brief This file contains all the functions for the DAC peripheral + * + * @note It's only for APM32F051,APM32F072,APM32F091 devices + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "apm32f0xx_dac.h" +#include "apm32f0xx_rcm.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup DAC_Driver + @{ +*/ + +/** @defgroup DAC_Macros Macros + @{ +*/ + +/**@} end of group DAC_Macros */ + +/** @defgroup DAC_Enumerations Enumerations + @{ +*/ + +/**@} end of group DAC_Enumerations */ + +/** @defgroup DAC_Structures Structures + @{ +*/ + +/**@} end of group DAC_Structures */ + +/** @defgroup DAC_Variables Variables + @{ +*/ + +/**@} end of group DAC_Variables */ + +/** @defgroup DAC_Functions Functions + @{ +*/ + +/*! + * @brief Resets the DAC peripheral registers to their default reset values. + * + * @param None + * + * @retval None + */ +void DAC_Reset(void) +{ + RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_DAC); + RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_DAC); +} + +/*! + * @brief Initializes the DAC peripheral according to the specified parameters in the dacConfig. + * + * @param channel: the selected DAC channel. + * This parameter can be: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * + * @param dacConfig: pointer to a DAC_Config_T structure that contains + * the configuration information for the specified DAC channel. + * + * @retval None + * + * @note DAC_Channel_2 is only for APM32F072 and APM32F091 devices + */ +void DAC_Config(uint32_t channel, DAC_Config_T* dacConfig) +{ + uint32_t tmpcfg; + + tmpcfg = ((uint32_t)dacConfig->trigger | \ + (uint32_t)dacConfig->waveGeneration | \ + (uint32_t)dacConfig->maskAmplitudeSelect | \ + (uint32_t)dacConfig->outputBuff); + DAC->CTRL = (tmpcfg << channel); +} + +/*! + * @brief Fills each DAC_InitStruct member with its default value. + * + * @param dacConfig: pointer to a DAC_InitTypeDef structure which will + * be configed. + * + * @retval None + */ +void DAC_ConfigStructInit(DAC_Config_T* dacConfig) +{ + dacConfig->trigger = DAC_TRIGGER_NONE; + dacConfig->waveGeneration = DAC_WAVE_GENERATION_NONE; + dacConfig->maskAmplitudeSelect = DAC_LFSRUNAMASK_BIT0; + dacConfig->outputBuff = DAC_OUTPUTBUFF_ENABLE; +} + +/*! + * @brief Enables the specified DAC channel. + * + * @param 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 + * + * @retval None + * + * @note When the DAC channel is enabled the trigger source can no more be modified. + * + * @note DAC_Channel_2 is only for APM32F072 and APM32F091 devices + */ +void DAC_Enable(DAC_CHANNEL_T channel) +{ + if (channel == DAC_CHANNEL_1) + { + DAC->CTRL_B.ENCH1 = SET; + } + else + { + DAC->CTRL_B.ENCH2 = SET; + } +} + +/*! + * @brief Disables the specified DAC channel. + * + * @param 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 + * + * @retval None + * + * @note DAC_Channel_2 is only for APM32F072 and APM32F091 devices + */ +void DAC_Disable(DAC_CHANNEL_T channel) +{ + if (channel == DAC_CHANNEL_1) + { + DAC->CTRL_B.ENCH1 = RESET; + } + else + { + DAC->CTRL_B.ENCH2 = RESET; + } +} + +/*! + * @brief Enables the selected DAC channel software trigger. + * + * @param 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 + * + * @retval None + * + * @note DAC_Channel_2 is only for APM32F072 and APM32F091 devices + */ +void DAC_EnableSoftwareTrigger(DAC_CHANNEL_T channel) +{ + if (channel == DAC_CHANNEL_1) + { + DAC->SWTRG_B.SWTRG1 = SET; + } + else + { + DAC->SWTRG_B.SWTRG2 = SET; + } +} + +/*! + * @brief Disable the selected DAC channel software trigger. + * + * @param 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 + * + * @retval None + * + * @note DAC_Channel_2 is only for APM32F072 and APM32F091 devices + */ +void DAC_DisableSoftwareTrigger(DAC_CHANNEL_T channel) +{ + if (channel == DAC_CHANNEL_1) + { + DAC->SWTRG_B.SWTRG1 = RESET; + } + else + { + DAC->SWTRG_B.SWTRG2 = RESET; + } +} + +/*! + * @brief Enables simultaneously the two DAC channels software triggers. + * + * @param None + * + * @retval None + * + * @note This function is only for APM32F072 and APM32F091 devices + */ +void DAC_EnableDualSoftwareTrigger(void) +{ + DAC->SWTRG |= DUAL_SWTRIG_SET; +} + +/*! + * @brief Disables simultaneously the two DAC channels software triggers. + * + * @param None + * + * @retval None + * + * @note This function is only for APM32F072 and APM32F091 devices + */ +void DAC_DisableDualSoftwareTrigger(void) +{ + DAC->SWTRG &= DUAL_SWTRIG_RESET; +} + +/*! + * @brief Enables the selected DAC channel wave generation. + * + * @param channel: The selected DAC channel. + * This parameter can be: + * @arg DAC_CHANNEL_1: DAC Channel1 selected + * @arg DAC_CHANNEL_2: DAC Channel2 selected + * + * @param wave: specifies the wave type to enable or disable. + * This parameter can be: + * @arg DAC_WAVE_GENERATION_NOISE: noise wave generation + * @arg DAC_WAVE_GENERATION_TRIANGLE: triangle wave generation + * + * @retval None + * + * @note This function is only for APM32F072 and APM32F091 devices + */ +void DAC_EnableWaveGeneration(DAC_CHANNEL_T channel, DAC_WAVE_GENERATION_T wave) +{ + DAC->CTRL |= ((uint32_t)wave) << ((uint32_t)channel); +} + +/*! + * @brief Disable the selected DAC channel wave generation. + * + * @param channel: The selected DAC channel. + * This parameter can be: + * @arg DAC_CHANNEL_1: DAC Channel1 selected + * @arg DAC_CHANNEL_2: DAC Channel2 selected + * + * @param wave: specifies the wave type to enable or disable. + * This parameter can be: + * @arg DAC_WAVE_GENERATION_NOISE: noise wave generation + * @arg DAC_WAVE_GENERATION_TRIANGLE: triangle wave generation + * + * @retval None + * + * @note This function is only for APM32F072 and APM32F091 devices + */ +void DAC_DisableWaveGeneration(DAC_CHANNEL_T channel, DAC_WAVE_GENERATION_T wave) +{ + DAC->CTRL &= ~((uint32_t)wave) << ((uint32_t)channel); +} + +/*! + * @brief Sets the specified data holding register value for DAC channel1. + * + * @param dataAlign: Specifies the data alignment for DAC channel1. + * This parameter can be one of the following values: + * @arg DAC_ALIGN_8B_R: 8bit right data alignment selected + * @arg DAC_ALIGN_12B_L: 12bit left data alignment selected + * @arg DAC_ALIGN_12B_R: 12bit right data alignment selected + * + * @param data: Data to be loaded in the selected data holding register. + * + * @retval None + */ +void DAC_ConfigChannel1Data(DAC_DATA_ALIGN_T dataAlign, uint16_t data) +{ + __IO uint32_t tmp = 0; + tmp = (uint32_t)DAC_BASE; + tmp += DH12RCH1_OFFSET + dataAlign; + *(__IO uint32_t*) tmp = data; +} + +/*! + * @brief Sets the specified data holding register value for DAC channel2. + * + * @param dataAlign: Specifies the data alignment for DAC channel2. + * This parameter can be: + * @arg DAC_ALIGN_8B_R: 8bit right data alignment selected + * @arg DAC_ALIGN_12B_L: 12bit left data alignment selected + * @arg DAC_ALIGN_12B_R: 12bit right data alignment selected + * + * @param data: Data to be loaded in the selected data holding register. + * + * @retval None + * + * @note This function is only for APM32F072 and APM32F091 devices + */ +void DAC_ConfigChannel2Data(DAC_DATA_ALIGN_T dataAlign, uint16_t data) +{ + __IO uint32_t tmp = 0; + tmp = (uint32_t)DAC_BASE; + tmp += DH12RCH2_OFFSET + dataAlign; + *(__IO uint32_t*)tmp = data; +} + +/*! + * @brief Sets the specified data holding register value for dual channel DAC. + * + * @param dataAlign: Specifies the data alignment for dual channel DAC. + * This parameter can be: + * @arg DAC_ALIGN_8B_R: 8bit right data alignment selected + * @arg DAC_ALIGN_12B_L: 12bit left data alignment selected + * @arg DAC_ALIGN_12B_R: 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. + * + * @retval None + * + * @note In dual mode, a unique register access is required to write in both + * DAC channels at the same time. + * + * @note This function is only for APM32F072 and APM32F091 devices + */ +void DAC_ConfigDualChannelData(DAC_DATA_ALIGN_T dataAlign, uint16_t data2, uint16_t data1) +{ + uint32_t data = 0, tmp = 0; + + if (dataAlign == DAC_ALIGN_8B_R) + { + data = ((uint32_t)data2 << 8) | data1; + } + else + { + data = ((uint32_t)data2 << 16) | data1; + } + tmp = (uint32_t)DAC_BASE; + tmp += DH12RD_OFFSET + dataAlign; + *(__IO uint32_t*)tmp = data; +} + +/*! + * @brief Returns the last data output value of the selected DAC channel. + * + * @param 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 + * + * @retval The selected DAC channel data output value. + * + * @note DAC_Channel_2 is only for APM32F072 and APM32F091 devices + */ +uint16_t DAC_ReadDataOutputValue(DAC_CHANNEL_T channel) +{ + uint16_t data; + if (channel == DAC_CHANNEL_1) + { + data = DAC->DATAOCH1_B.DATA; + } + else + { + data = DAC->DATAOCH2_B.DATA; + } + return data; +} + +/*! + * @brief Enables the specified DAC channel DMA request. + * When enabled DMA1 is generated when an external trigger (EINT Line9, + * TMR2, TMR3, TMR6 or TMR15 but not a software trigger) occurs + + * @param 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 + * + * @retval None + * + * @note The DAC channel1 is mapped on DMA1 channel3 which must be already configured. + * + * @note The DAC channel2 is mapped on DMA1 channel4 which must be already configured. + * + * @note DAC_Channel_2 is only for APM32F072 and APM32F091 devices + */ +void DAC_EnableDMA(DAC_CHANNEL_T channel) +{ + if (channel == DAC_CHANNEL_1) + { + DAC->CTRL_B.DMAENCH1 = SET; + } + else + { + DAC->CTRL_B.DMAENCH2 = SET; + } +} + +/*! + * @brief Disable the specified DAC channel DMA request. + * + * @param 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 + * + * @retval None + * + * @note The DAC channel1 is mapped on DMA1 channel3 which must be already configured. + * + * @note The DAC channel2 is mapped on DMA1 channel4 which must be already configured. + * + * @note DAC_Channel_2 is only for APM32F072 and APM32F091 devices + */ +void DAC_DisableDMA(DAC_CHANNEL_T channel) +{ + if (channel == DAC_CHANNEL_1) + { + DAC->CTRL_B.DMAENCH1 = RESET; + } + else + { + DAC->CTRL_B.DMAENCH2 = RESET; + } +} + +/*! + * @brief Enables the specified DAC interrupts. + * + * @param channel: The selected DAC channel. + * This parameter can be: + * @arg DAC_CHANNEL_1: DAC Channel1 selected + * @arg DAC_CHANNEL_2: DAC Channel2 selected + * + * @retval None + * + * @note The DMA underrun occurs when a second external trigger arrives before the + * acknowledgement for the first external trigger is received (first request). + * + * @note DAC_Channel_2 is only for APM32F072 and APM32F091 devices + */ +void DAC_EnableInterrupt(DAC_CHANNEL_T channel) +{ + if (channel == DAC_CHANNEL_1) + { + DAC->CTRL_B.DMAUDRIEN1 = SET; + } + else + { + DAC->CTRL_B.DMAUDRIEN2 = SET; + } +} + +/*! + * @brief Disables the specified DAC interrupts. + * + * @param channel: The selected DAC channel. + * This parameter can be: + * @arg DAC_CHANNEL_1: DAC Channel1 selected + * @arg DAC_CHANNEL_2: DAC Channel2 selected + * + * @retval None + * + * @note The DMA underrun occurs when a second external trigger arrives before the + * acknowledgement for the first external trigger is received (first request). + * + * @note DAC_Channel_2 is only for APM32F072 and APM32F091 devices + */ +void DAC_DisableInterrupt(DAC_CHANNEL_T channel) +{ + if (channel == DAC_CHANNEL_1) + { + DAC->CTRL_B.DMAUDRIEN1 = RESET; + } + else + { + DAC->CTRL_B.DMAUDRIEN2 = RESET; + } +} + +/*! + * @brief Reads the DAC status flag. + * + * @param flag: specifies the flag to check. + * This parameter can be only of the following value: + * @arg DAC_FLAG_CH1_DMAUDR: DMA Channel1 underrun flag + * @arg DAC_FLAG_CH2_DMAUDR: DMA Channel2 underrun flag, only for APM32F072 and APM32F091 devices + * + * @retval The new state of DAC flag (SET or RESET). + * + * @note The DMA underrun occurs when a second external trigger arrives before the + * acknowledgement for the first external trigger is received (first request). + */ +uint8_t DAC_ReadStatusFlag(DAC_FLAG_T flag) +{ + uint16_t status; + + status = (uint16_t)(DAC->STS & flag); + if (status == flag) + { + return SET; + } + else + return RESET; +} +/*! + * @brief Clears the DAC status flags. + * + * @param flag: specifies the flag to check. + * This parameter can be only of the following value: + * @arg DAC_FLAG_CH1_DMAUDR: DMA Channel1 underrun flag + * @arg DAC_FLAG_CH2_DMAUDR: DMA Channel2 underrun flag, , only for APM32F072 and APM32F091 devices + * @arg DAC_FLAG_DMAUDR: DMA underrun flag + * + * @retval None + */ +void DAC_ClearStatusFlag(DAC_FLAG_T flag) +{ + DAC->STS &= (uint32_t)~flag; +} + +/*! + * @brief Reads teh DAC interrupt flag. + * + * @param intFlag: specifies the DAC interrupt source to check. + * This parameter can be the following values: + * @arg DAC_INT_CH1_DMAUDR: DMA Channel1 underrun interrupt mask + * @arg DAC_INT_CH2_DMAUDR: DMA Channel2 underrun interrupt mask, , only for APM32F072 and APM32F091 devices + * + * @retval The new state of DAC interrupt flag (SET or RESET). + * + * @note The DMA underrun occurs when a second external trigger arrives before the + * acknowledgement for the first external trigger is received (first request). + */ +uint8_t DAC_ReadIntFlag(DAC_INT_T intFlag) +{ + uint32_t intEnable; + intEnable = (DAC->CTRL & intFlag); + if (((DAC->STS & intFlag) != (uint32_t)RESET) && intEnable) + { + return SET; + } + else + { + return RESET; + } +} + +/*! + * @brief Clears the DAC channel's interrupt flag. + * + * @param intFlag: specifies the DAC interrupt pending bit to clear. + * This parameter can be the following values: + * @arg DAC_INT_CH1_DMAUDR: DMA Channel1 underrun interrupt mask + * @arg DAC_INT_CH2_DMAUDR: DMA Channel2 underrun interrupt mask, , only for APM32F072 and APM32F091 devices + * + * @retval None + */ +void DAC_ClearIntFlag(DAC_INT_T intFlag) +{ + DAC->STS = intFlag; +} + +/**@} end of group DAC_Functions */ +/**@} end of group DAC_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_dbg.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_dbg.c new file mode 100644 index 0000000000..060a13026a --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_dbg.c @@ -0,0 +1,196 @@ +/*! + * @file apm32f0xx_dbg.c + * + * @brief This file provides all the DBG firmware functions + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "apm32f0xx_dbg.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup DBG_Driver + @{ +*/ + +/** @defgroup DBG_Macros Macros + @{ +*/ + +/**@} end of group DBG_Macros */ + +/** @defgroup DBG_Enumerations Enumerations + @{ +*/ + +/**@} end of group DBG_Enumerations*/ + +/** @defgroup DBG_Structures Structures + @{ +*/ + +/**@} end of group DBG_Structures */ + +/** @defgroup DBG_Variables Variables + @{ +*/ + +/**@} end of group DBG_Variables */ + +/** @defgroup DBG_Functions Functions + @{ +*/ + +/*! + * @brief Read Device Identifier + * + * @param None + * + * @retval The value of the Device Identifier + */ +uint32_t DBG_ReadDevId(void) +{ + return ((uint32_t)DBG->IDCODE_B.EQR); +} + +/*! + * @brief Read Revision Identifier + * + * @param None + * + * @retval The value of the Revision Identifier + */ +uint32_t DBG_ReadRevId(void) +{ + return ((uint32_t)DBG->IDCODE_B.WVR); +} + +/*! + * @brief Enable Debug Mode + * + * @param mode: specifies the low power mode. + * The parameter can be combination of following values: + * @arg DBG_MODE_STOP: Keep debugger connection during STOP mode + * @arg DBG_MODE_STANDBY: Keep debugger connection during STANDBY mode + * @retval None + */ +void DBG_EnableDebugMode(uint32_t mode) +{ + DBG->CFG |= (uint32_t)mode; +} + +/*! + * @brief Disable Debug Mode + * + * @param mode: specifies the low power mode. + * The parameter can be combination of following values: + * @arg DBG_MODE_STOP: Keep debugger connection during STOP mode + * @arg DBG_MODE_STANDBY: Keep debugger connection during STANDBY mode + * @retval None + */ +void DBG_DisableDebugMode(uint32_t mode) +{ + DBG->CFG &= (uint32_t)~mode; +} + +/*! + * @brief Enable APB1 peripheral in Debug mode. + * + * @param peripheral: Specifies the APB1 peripheral. + * The parameter can be combination of following values: + * @arg DBG_APB1_PER_TMR2_STOP: TMR2 counter stopped when Core is halted, Not for APM32F030 devices + * @arg DBG_APB1_PER_TMR3_STOP: TMR3 counter stopped when Core is halted + * @arg DBG_APB1_PER_TMR6_STOP: TMR6 counter stopped when Core is halted + * @arg DBG_APB1_PER_TMR7_STOP: TMR7 counter stopped when Core is halted£¬Only for APM32F072 and APM32F091 devices + * @arg DBG_APB1_PER_TMR14_STOP: TMR14 counter stopped when Core is halted + * @arg DBG_APB1_PER_RTC_STOP: RTC counter stopped when Core is halted + * @arg DBG_APB1_PER_WWDT_STOP: Debug WWDT stopped when Core is halted + * @arg DBG_APB1_PER_IWDT_STOP: Debug IWDT stopped when Core is halted + * @arg DBG_APB1_PER_CAN_STOP: Debug CAN stopped when Core is halted£¬Only for APM32F072 and APM32F091 devices + * @arg DBG_APB1_PER_I2C1_SMBUS_TIMEOUT: I2C1 SMBUS timeout mode stopped when Core is halted + * @retval None + */ +void DBG_EnableAPB1Periph(uint32_t peripheral) +{ + DBG->APB1F |= (uint32_t)peripheral; +} + +/*! + * @brief Disable APB1 peripheral in Debug mode. + * + * @param peripheral: Specifies the APB1 peripheral. + * The parameter can be combination of following values: + * @arg DBG_APB1_PER_TMR2_STOP: TMR2 counter stopped when Core is halted, Not for APM32F030 devices + * @arg DBG_APB1_PER_TMR3_STOP: TMR3 counter stopped when Core is halted + * @arg DBG_APB1_PER_TMR6_STOP: TMR6 counter stopped when Core is halted + * @arg DBG_APB1_PER_TMR7_STOP: TMR7 counter stopped when Core is halted£¬Only for APM32F072 and APM32F091 devices + * @arg DBG_APB1_PER_TMR14_STOP: TMR14 counter stopped when Core is halted + * @arg DBG_APB1_PER_RTC_STOP: RTC counter stopped when Core is halted + * @arg DBG_APB1_PER_WWDT_STOP: Debug WWDT stopped when Core is halted + * @arg DBG_APB1_PER_IWDT_STOP: Debug IWDT stopped when Core is halted + * @arg DBG_APB1_PER_CAN_STOP: Debug CAN stopped when Core is halted£¬Only for APM32F072 and APM32F091 devices + * @arg DBG_APB1_PER_I2C1_SMBUS_TIMEOUT: I2C1 SMBUS timeout mode stopped when Core is halted + * @retval None + */ +void DBG_DisableAPB1Periph(uint32_t peripheral) +{ + DBG->APB1F &= (uint32_t)~peripheral; +} + +/*! + * @brief Enable APB2 peripheral in Debug mode. + * + * @param peripheral: Specifies the APB2 peripheral. + * The parameter can be combination of following values: + * @arg DBG_APB2_PER_TMR1_STOP: TMR1 counter stopped when Core is halted + * @arg DBG_APB2_PER_TMR15_STOP: TMR15 counter stopped when Core is halted + * @arg DBG_APB2_PER_TMR16_STOP: TMR16 counter stopped when Core is halted + * @arg DBG_APB2_PER_TMR17_STOP: TMR17 counter stopped when Core is halted + * @retval None + */ +void DBG_EnableAPB2Periph(uint32_t peripheral) +{ + DBG->APB2F |= (uint32_t)peripheral; +} + +/*! + * @brief Disable APB2 peripheral in Debug mode. + * + * @param peripheral: Specifies the APB2 peripheral. + * The parameter can be combination of following values: + * @arg DBG_APB2_PER_TMR1_STOP: TMR1 counter stopped when Core is halted + * @arg DBG_APB2_PER_TMR15_STOP: TMR15 counter stopped when Core is halted + * @arg DBG_APB2_PER_TMR16_STOP: TMR16 counter stopped when Core is halted + * @arg DBG_APB2_PER_TMR17_STOP: TMR17 counter stopped when Core is halted + * + * @retval None + */ +void DBG_DisableAPB2Periph(uint32_t peripheral) +{ + DBG->APB2F &= (uint32_t)~peripheral; +} + +/**@} end of group DBG_Functions */ +/**@} end of group DBG_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_dma.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_dma.c new file mode 100644 index 0000000000..e7cc47e92e --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_dma.c @@ -0,0 +1,695 @@ +/*! + * @file apm32f0xx_dma.c + * + * @brief This file contains all the functions for the DMA peripheral + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "apm32f0xx_dma.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup DMA_Driver + @{ +*/ + +/** @defgroup DMA_Macros Macros + @{ + */ + +/**@} end of group DMA_Macros */ + +/** @defgroup DMA_Enumerates Enumerates + @{ + */ + +/**@} end of group DMA_Enumerates */ + +/** @defgroup DMA_Structures Structures + @{ + */ + +/**@} end of group DMA_Structures */ + +/** @defgroup DMA_Variables Variables + @{ + */ + +/**@} end of group DMA_Variables */ + +/** @defgroup DMA_Functions Functions + @{ + */ + +/*! + * @brief Set the DMA peripheral registers to their default reset values + * + * @param DMA_CHANNEL_T: Pointer to a DMA_CHANNEL_T structure that + * set DMA channel for the DMA peripheral + * This parameter can be one of the following values: + * @arg DMA1_CHANNEL_1 + * @arg DMA1_CHANNEL_2 + * @arg DMA1_CHANNEL_3 + * @arg DMA1_CHANNEL_4 + * @arg DMA1_CHANNEL_5 + * @arg DMA1_CHANNEL_6(only for APM32F072 and APM32F091) + * @arg DMA1_CHANNEL_7(only for APM32F072 and APM32F091) + * @arg DMA2_CHANNEL_1(only for APM32F091) + * @arg DMA2_CHANNEL_2(only for APM32F091) + * @arg DMA2_CHANNEL_3(only for APM32F091) + * @arg DMA2_CHANNEL_4(only for APM32F091) + * @arg DMA2_CHANNEL_5(only for APM32F091) + * @retval None + */ +void DMA_Reset(DMA_CHANNEL_T* channel) +{ + channel->CHCFG_B.CHEN = 0; + channel->CHCFG = 0; + channel->CHNDATA = 0; + channel->CHPADDR = 0; + channel->CHMADDR = 0; + + if (channel == DMA1_CHANNEL_1) + { + DMA1->INTFCLR = (uint32_t)0x0000000F; + } + else if (channel == DMA1_CHANNEL_2) + { + DMA1->INTFCLR = (uint32_t)0x000000F0; + } + else if (channel == DMA1_CHANNEL_3) + { + DMA1->INTFCLR = (uint32_t)0x00000F00; + } + else if (channel == DMA1_CHANNEL_4) + { + DMA1->INTFCLR = (uint32_t)0x0000F000; + } + else if (channel == DMA1_CHANNEL_5) + { + DMA1->INTFCLR = (uint32_t)0x000F0000; + } + else if (channel == DMA1_CHANNEL_6) + { + DMA1->INTFCLR = (uint32_t)0x00F00000; + } + else if (channel == DMA1_CHANNEL_7) + { + DMA1->INTFCLR = (uint32_t)0x0F000000; + } + else if (channel == DMA2_CHANNEL_1) + { + DMA2->INTFCLR = (uint32_t)0x0000000F; + } + else if (channel == DMA2_CHANNEL_2) + { + DMA2->INTFCLR = (uint32_t)0x000000F0; + } + else if (channel == DMA2_CHANNEL_3) + { + DMA2->INTFCLR = (uint32_t)0x00000F00; + } + else if (channel == DMA2_CHANNEL_4) + { + DMA2->INTFCLR = (uint32_t)0x0000F000; + } + else if (channel == DMA2_CHANNEL_5) + { + DMA2->INTFCLR = (uint32_t)0x000F0000; + } +} + +/*! + * @brief Config the DMA peripheral according to the specified parameters in the dmaConfig + * + * @param DMA_CHANNEL_T: Pointer to a DMA_CHANNEL_T structure that + * set DMA channel for the DMA peripheral + * This parameter can be one of the following values: + * @arg DMA1_CHANNEL_1 + * @arg DMA1_CHANNEL_2 + * @arg DMA1_CHANNEL_3 + * @arg DMA1_CHANNEL_4 + * @arg DMA1_CHANNEL_5 + * @arg DMA1_CHANNEL_6(only for APM32F072 and APM32F091) + * @arg DMA1_CHANNEL_7(only for APM32F072 and APM32F091) + * @arg DMA2_CHANNEL_1(only for APM32F091) + * @arg DMA2_CHANNEL_2(only for APM32F091) + * @arg DMA2_CHANNEL_3(only for APM32F091) + * @arg DMA2_CHANNEL_4(only for APM32F091) + * @arg DMA2_CHANNEL_5(only for APM32F091) + * + * @param dmaConfig: Pointer to a DMA_Config_T structure that + * contains the configuration information for the DMA peripheral + * + * @retval None + */ +void DMA_Config(DMA_CHANNEL_T* channel, DMA_Config_T* dmaConfig) +{ + channel->CHCFG_B.DIRCFG = dmaConfig->direction; + channel->CHCFG_B.CIRMODE = dmaConfig->circular; + channel->CHCFG_B.M2MMODE = dmaConfig->memoryTomemory; + channel->CHCFG_B.CHPL = dmaConfig->priority; + channel->CHCFG_B.MIMODE = dmaConfig->memoryInc; + channel->CHCFG_B.PERIMODE = dmaConfig->peripheralInc; + channel->CHCFG_B.MSIZE = dmaConfig->memoryDataSize; + channel->CHCFG_B.PERSIZE = dmaConfig->peripheralDataSize; + + channel->CHNDATA = dmaConfig->bufferSize; + channel->CHMADDR = dmaConfig->memoryAddress; + channel->CHPADDR = dmaConfig->peripheralAddress; + +} + +/*! + * @brief Fills each dmaConfig member with its default value + * + * @param dmaConfig: Pointer to a DMA_Config_T structure which will be initialized + * + * @retval None + */ +void DMA_ConfigStructInit(DMA_Config_T* dmaConfig) +{ + dmaConfig->direction = DMA_DIR_PERIPHERAL; + dmaConfig->circular = DMA_CIRCULAR_DISABLE; + dmaConfig->memoryTomemory = DMA_M2M_DISABLE; + dmaConfig->priority = DMA_PRIORITY_LEVEL_LOW; + dmaConfig->memoryInc = DMA_MEMORY_INC_DISABLE; + dmaConfig->peripheralInc = DMA_PERIPHERAL_INC_DISABLE; + dmaConfig->memoryDataSize = DMA_MEMORY_DATASIZE_BYTE; + dmaConfig->peripheralDataSize = DMA_PERIPHERAL_DATASIZE_BYTE; + + dmaConfig->bufferSize = 0; + dmaConfig->memoryAddress = 0; + dmaConfig->peripheralAddress = 0; +} + +/*! + * @brief Enable the DMA peripheral + * + * @param DMA_CHANNEL_T: Pointer to a DMA_CHANNEL_T structure that + * set DMA channel for the DMA peripheral + * This parameter can be one of the following values: + * @arg DMA1_CHANNEL_1 + * @arg DMA1_CHANNEL_2 + * @arg DMA1_CHANNEL_3 + * @arg DMA1_CHANNEL_4 + * @arg DMA1_CHANNEL_5 + * @arg DMA1_CHANNEL_6(only for APM32F072 and APM32F091) + * @arg DMA1_CHANNEL_7(only for APM32F072 and APM32F091) + * @arg DMA2_CHANNEL_1(only for APM32F091) + * @arg DMA2_CHANNEL_2(only for APM32F091) + * @arg DMA2_CHANNEL_3(only for APM32F091) + * @arg DMA2_CHANNEL_4(only for APM32F091) + * @arg DMA2_CHANNEL_5(only for APM32F091) + * + * @retval None + */ +void DMA_Enable(DMA_CHANNEL_T* channel) +{ + channel->CHCFG_B.CHEN = BIT_SET; +} + +/*! + * @brief Disable the DMA peripheral + * + * @param DMA_CHANNEL_T: Pointer to a DMA_CHANNEL_T structure that + * set DMA channel for the DMA peripheral + * This parameter can be one of the following values: + * @arg DMA1_CHANNEL_1 + * @arg DMA1_CHANNEL_2 + * @arg DMA1_CHANNEL_3 + * @arg DMA1_CHANNEL_4 + * @arg DMA1_CHANNEL_5 + * @arg DMA1_CHANNEL_6(only for APM32F072 and APM32F091) + * @arg DMA1_CHANNEL_7(only for APM32F072 and APM32F091) + * @arg DMA2_CHANNEL_1(only for APM32F091) + * @arg DMA2_CHANNEL_2(only for APM32F091) + * @arg DMA2_CHANNEL_3(only for APM32F091) + * @arg DMA2_CHANNEL_4(only for APM32F091) + * @arg DMA2_CHANNEL_5(only for APM32F091) + * + * @retval None + */ +void DMA_Disable(DMA_CHANNEL_T* channel) +{ + channel->CHCFG_B.CHEN = BIT_RESET; +} + +/*! + * @brief Set the DMA Channelx transfer data of number + * + * @param DMA_CHANNEL_T: Pointer to a DMA_CHANNEL_T structure that + * set DMA channel for the DMA peripheral + * This parameter can be one of the following values: + * @arg DMA1_CHANNEL_1 + * @arg DMA1_CHANNEL_2 + * @arg DMA1_CHANNEL_3 + * @arg DMA1_CHANNEL_4 + * @arg DMA1_CHANNEL_5 + * @arg DMA1_CHANNEL_6(only for APM32F072 and APM32F091) + * @arg DMA1_CHANNEL_7(only for APM32F072 and APM32F091) + * @arg DMA2_CHANNEL_1(only for APM32F091) + * @arg DMA2_CHANNEL_2(only for APM32F091) + * @arg DMA2_CHANNEL_3(only for APM32F091) + * @arg DMA2_CHANNEL_4(only for APM32F091) + * @arg DMA2_CHANNEL_5(only for APM32F091) + * + * @param dataNumber: The number of data units in the current DMA Channel transfer + * + * @retval None + */ +void DMA_SetDataNumber(DMA_CHANNEL_T* channel, uint32_t dataNumber) +{ + channel->CHNDATA = (uint32_t)dataNumber; +} + +/*! + * @brief Read the DMA Channelx transfer data of number + * + * @param DMA_CHANNEL_T: Pointer to a DMA_CHANNEL_T structure that + * set DMA channel for the DMA peripheral + * This parameter can be one of the following values: + * @arg DMA1_CHANNEL_1 + * @arg DMA1_CHANNEL_2 + * @arg DMA1_CHANNEL_3 + * @arg DMA1_CHANNEL_4 + * @arg DMA1_CHANNEL_5 + * @arg DMA1_CHANNEL_6(only for APM32F072 and APM32F091) + * @arg DMA1_CHANNEL_7(only for APM32F072 and APM32F091) + * @arg DMA2_CHANNEL_1(only for APM32F091) + * @arg DMA2_CHANNEL_2(only for APM32F091) + * @arg DMA2_CHANNEL_3(only for APM32F091) + * @arg DMA2_CHANNEL_4(only for APM32F091) + * @arg DMA2_CHANNEL_5(only for APM32F091) + * + * @retval The number of data units in the current DMA Channel transfer + */ +uint32_t DMA_ReadDataNumber(DMA_CHANNEL_T* channel) +{ + return ((uint32_t)channel->CHNDATA); +} + +/*! + * @brief Configure the DMA channels remapping. + * + * @param dma: Select the the DMA peripheral. + It can be DMA1/DMA2. + * + * @param remap: Select the the DMA_CHANNEL_REMAP_T. + When select DMA1, the DMA channel can be 1 to 7. + * When select DMA2, the DMA channel can be 1 to 5. + * + * @retval It's only for APM32F091 devices. + */ +void DMA_ConfigRemap(DMA_T* dma, DMA_CHANNEL_REMAP_T remap) +{ + dma->CHSEL &= ~((uint32_t)0x0F << (uint32_t)(remap >> 28) * 4); + dma->CHSEL |= (uint32_t)(remap & 0x0FFFFFFF); +} + +/*! + * @brief Enables the specified interrupts + * @param DMA_CHANNEL_T: Pointer to a DMA_CHANNEL_T structure that + * set DMA channel for the DMA peripheral + * This parameter can be one of the following values: + * @arg DMA1_CHANNEL_1 + * @arg DMA1_CHANNEL_2 + * @arg DMA1_CHANNEL_3 + * @arg DMA1_CHANNEL_4 + * @arg DMA1_CHANNEL_5 + * @arg DMA1_CHANNEL_6(only for APM32F072 and APM32F091) + * @arg DMA1_CHANNEL_7(only for APM32F072 and APM32F091) + * @arg DMA2_CHANNEL_1(only for APM32F091) + * @arg DMA2_CHANNEL_2(only for APM32F091) + * @arg DMA2_CHANNEL_3(only for APM32F091) + * @arg DMA2_CHANNEL_4(only for APM32F091) + * @arg DMA2_CHANNEL_5(only for APM32F091) + * + * @param interrupt: Specifies the DMA interrupts sources + * The parameter can be combination of following values: + * @arg DMA_INT_TFIE: Transfer complete interrupt + * @arg DMA_INT_HTIE: Half Transfer interrupt + * @arg DMA_INT_TEIE: Transfer error interrupt + * + * @retval None + */ +void DMA_EnableInterrupt(DMA_CHANNEL_T* channel, uint32_t interrupt) +{ + channel->CHCFG |= (uint32_t)interrupt; +} + +/*! + * @brief Disables the specified interrupts + * @param DMA_CHANNEL_T: Pointer to a DMA_CHANNEL_T structure that + * set DMA channel for the DMA peripheral + * This parameter can be one of the following values: + * @arg DMA1_CHANNEL_1 + * @arg DMA1_CHANNEL_2 + * @arg DMA1_CHANNEL_3 + * @arg DMA1_CHANNEL_4 + * @arg DMA1_CHANNEL_5 + * @arg DMA1_CHANNEL_6(only for APM32F072 and APM32F091) + * @arg DMA1_CHANNEL_7(only for APM32F072 and APM32F091) + * @arg DMA2_CHANNEL_1(only for APM32F091) + * @arg DMA2_CHANNEL_2(only for APM32F091) + * @arg DMA2_CHANNEL_3(only for APM32F091) + * @arg DMA2_CHANNEL_4(only for APM32F091) + * @arg DMA2_CHANNEL_5(only for APM32F091) + * + * @param interrupt: Specifies the DMA interrupts sources + * The parameter can be combination of following values: + * @arg DMA_INT_TFIE: Transfer complete interrupt + * @arg DMA_INT_HTIE: Half Transfer interrupt + * @arg DMA_INT_TEIE: Transfer error interrupt + * + * @retval None + */ +void DMA_DisableInterrupt(DMA_CHANNEL_T* channel, uint32_t interrupt) +{ + channel->CHCFG &= (uint32_t)~interrupt; +} + +/*! + * @brief Checks whether the specified DMA flag is set or not + * + * @param flag: Specifies the flag to check + * This parameter can be one of the following values: + * @arg DMA1_FLAG_AL1: DMA1 Channel 1 All flag + * @arg DMA1_FLAG_TF1: DMA1 Channel 1 Transfer Complete flag + * @arg DMA1_FLAG_HT1: DMA1 Channel 1 Half Transfer Complete flag + * @arg DMA1_FLAG_TE1: DMA1 Channel 1 Transfer Error flag + * @arg DMA1_FLAG_AL2: DMA1 Channel 2 All flag + * @arg DMA1_FLAG_TF2: DMA1 Channel 2 Transfer Complete flag + * @arg DMA1_FLAG_HT2: DMA1 Channel 2 Half Transfer Complete flag + * @arg DMA1_FLAG_TE2: DMA1 Channel 2 Transfer Error flag + * @arg DMA1_FLAG_AL3: DMA1 Channel 3 All flag + * @arg DMA1_FLAG_TF3: DMA1 Channel 3 Transfer Complete flag + * @arg DMA1_FLAG_HT3: DMA1 Channel 3 Half Transfer Complete flag + * @arg DMA1_FLAG_TE3: DMA1 Channel 3 Transfer Error flag + * @arg DMA1_FLAG_AL4: DMA1 Channel 4 All flag + * @arg DMA1_FLAG_TF4: DMA1 Channel 4 Transfer Complete flag + * @arg DMA1_FLAG_HT4: DMA1 Channel 4 Half Transfer Complete flag + * @arg DMA1_FLAG_TE4: DMA1 Channel 4 Transfer Error flag + * @arg DMA1_FLAG_AL5: DMA1 Channel 5 All flag + * @arg DMA1_FLAG_TF5: DMA1 Channel 5 Transfer Complete flag + * @arg DMA1_FLAG_HT5: DMA1 Channel 5 Half Transfer Complete flag + * @arg DMA1_FLAG_TE5: DMA1 Channel 5 Transfer Error flag + * Below is only for APM32F072 and APM32F091 devices: + * @arg DMA1_FLAG_AL6: DMA1 Channel 6 All flag + * @arg DMA1_FLAG_TF6: DMA1 Channel 6 Transfer Complete flag + * @arg DMA1_FLAG_HT6: DMA1 Channel 6 Half Transfer Complete flag + * @arg DMA1_FLAG_TE6: DMA1 Channel 6 Transfer Error flag + * @arg DMA1_FLAG_AL7: DMA1 Channel 7 All flag + * @arg DMA1_FLAG_TF7: DMA1 Channel 7 Transfer Complete flag + * @arg DMA1_FLAG_HT7: DMA1 Channel 7 Half Transfer Complete flag + * @arg DMA1_FLAG_TE7: DMA1 Channel 7 Transfer Error flag + * Below is only for APM32F091 devices: + * @arg DMA2_FLAG_AL1: DMA2 Channel 1 All flag + * @arg DMA2_FLAG_TF1: DMA2 Channel 1 Transfer Complete flag + * @arg DMA2_FLAG_HT1: DMA2 Channel 1 Half Transfer Complete flag + * @arg DMA2_FLAG_TE1: DMA2 Channel 1 Transfer Error flag + * @arg DMA2_FLAG_AL2: DMA2 Channel 2 All flag + * @arg DMA2_FLAG_TF2: DMA2 Channel 2 Transfer Complete flag + * @arg DMA2_FLAG_HT2: DMA2 Channel 2 Half Transfer Complete flag + * @arg DMA2_FLAG_TE2: DMA2 Channel 2 Transfer Error flag + * @arg DMA2_FLAG_AL3: DMA2 Channel 3 All flag + * @arg DMA2_FLAG_TF3: DMA2 Channel 3 Transfer Complete flag + * @arg DMA2_FLAG_HT3: DMA2 Channel 3 Half Transfer Complete flag + * @arg DMA2_FLAG_TE3: DMA2 Channel 3 Transfer Error flag + * @arg DMA2_FLAG_AL4: DMA2 Channel 4 All flag + * @arg DMA2_FLAG_TF4: DMA2 Channel 4 Transfer Complete flag + * @arg DMA2_FLAG_HT4: DMA2 Channel 4 Half Transfer Complete flag + * @arg DMA2_FLAG_TE4: DMA2 Channel 4 Transfer Error flag + * @arg DMA2_FLAG_AL5: DMA2 Channel 5 All flag + * @arg DMA2_FLAG_TF5: DMA2 Channel 5 Transfer Complete flag + * @arg DMA2_FLAG_HT5: DMA2 Channel 5 Half Transfer Complete flag + * @arg DMA2_FLAG_TE5: DMA2 Channel 5 Transfer Error flag + * + * @retval The new state of flag (SET or RESET) + */ +uint8_t DMA_ReadStatusFlag(DMA_FLAG_T flag) +{ + uint32_t status; + + if ((flag & 0x10000000) == SET) + { + status = DMA2->INTSTS & ((uint32_t)flag & 0x000FFFFF); + } + else + { + status = DMA1->INTSTS & ((uint32_t)flag & 0x0FFFFFFF); + } + + if (status == flag) + { + return SET; + } + + return RESET; +} + +/*! + * @brief Clear whether the specified DMA flag is set or not + * + * @param flag: Specifies the flag to Clear + * This parameter can be any combination of the following values: + * @arg DMA1_FLAG_AL1: DMA1 Channel 1 All flag + * @arg DMA1_FLAG_TF1: DMA1 Channel 1 Transfer Complete flag + * @arg DMA1_FLAG_HT1: DMA1 Channel 1 Half Transfer Complete flag + * @arg DMA1_FLAG_TE1: DMA1 Channel 1 Transfer Error flag + * @arg DMA1_FLAG_AL2: DMA1 Channel 2 All flag + * @arg DMA1_FLAG_TF2: DMA1 Channel 2 Transfer Complete flag + * @arg DMA1_FLAG_HT2: DMA1 Channel 2 Half Transfer Complete flag + * @arg DMA1_FLAG_TE2: DMA1 Channel 2 Transfer Error flag + * @arg DMA1_FLAG_AL3: DMA1 Channel 3 All flag + * @arg DMA1_FLAG_TF3: DMA1 Channel 3 Transfer Complete flag + * @arg DMA1_FLAG_HT3: DMA1 Channel 3 Half Transfer Complete flag + * @arg DMA1_FLAG_TE3: DMA1 Channel 3 Transfer Error flag + * @arg DMA1_FLAG_AL4: DMA1 Channel 4 All flag + * @arg DMA1_FLAG_TF4: DMA1 Channel 4 Transfer Complete flag + * @arg DMA1_FLAG_HT4: DMA1 Channel 4 Half Transfer Complete flag + * @arg DMA1_FLAG_TE4: DMA1 Channel 4 Transfer Error flag + * @arg DMA1_FLAG_AL5: DMA1 Channel 5 All flag + * @arg DMA1_FLAG_TF5: DMA1 Channel 5 Transfer Complete flag + * @arg DMA1_FLAG_HT5: DMA1 Channel 5 Half Transfer Complete flag + * @arg DMA1_FLAG_TE5: DMA1 Channel 5 Transfer Error flag + * Below is only for APM32F072 and APM32F091 devices: + * @arg DMA1_FLAG_AL6: DMA1 Channel 6 All flag + * @arg DMA1_FLAG_TF6: DMA1 Channel 6 Transfer Complete flag + * @arg DMA1_FLAG_HT6: DMA1 Channel 6 Half Transfer Complete flag + * @arg DMA1_FLAG_TE6: DMA1 Channel 6 Transfer Error flag + * @arg DMA1_FLAG_AL7: DMA1 Channel 7 All flag + * @arg DMA1_FLAG_TF7: DMA1 Channel 7 Transfer Complete flag + * @arg DMA1_FLAG_HT7: DMA1 Channel 7 Half Transfer Complete flag + * @arg DMA1_FLAG_TE7: DMA1 Channel 7 Transfer Error flag + * Below is only for APM32F091 devices: + * @arg DMA2_FLAG_AL1: DMA2 Channel 1 All flag + * @arg DMA2_FLAG_TF1: DMA2 Channel 1 Transfer Complete flag + * @arg DMA2_FLAG_HT1: DMA2 Channel 1 Half Transfer Complete flag + * @arg DMA2_FLAG_TE1: DMA2 Channel 1 Transfer Error flag + * @arg DMA2_FLAG_AL2: DMA2 Channel 2 All flag + * @arg DMA2_FLAG_TF2: DMA2 Channel 2 Transfer Complete flag + * @arg DMA2_FLAG_HT2: DMA2 Channel 2 Half Transfer Complete flag + * @arg DMA2_FLAG_TE2: DMA2 Channel 2 Transfer Error flag + * @arg DMA2_FLAG_AL3: DMA2 Channel 3 All flag + * @arg DMA2_FLAG_TF3: DMA2 Channel 3 Transfer Complete flag + * @arg DMA2_FLAG_HT3: DMA2 Channel 3 Half Transfer Complete flag + * @arg DMA2_FLAG_TE3: DMA2 Channel 3 Transfer Error flag + * @arg DMA2_FLAG_AL4: DMA2 Channel 4 All flag + * @arg DMA2_FLAG_TF4: DMA2 Channel 4 Transfer Complete flag + * @arg DMA2_FLAG_HT4: DMA2 Channel 4 Half Transfer Complete flag + * @arg DMA2_FLAG_TE4: DMA2 Channel 4 Transfer Error flag + * @arg DMA2_FLAG_AL5: DMA2 Channel 5 All flag + * @arg DMA2_FLAG_TF5: DMA2 Channel 5 Transfer Complete flag + * @arg DMA2_FLAG_HT5: DMA2 Channel 5 Half Transfer Complete flag + * @arg DMA2_FLAG_TE5: DMA2 Channel 5 Transfer Error flag + * + * @retval None + */ + +void DMA_ClearStatusFlag(uint32_t flag) +{ + if ((flag & 0x10000000) == SET) + { + DMA2->INTFCLR |= (uint32_t)(flag & 0x000FFFFF); + } + else + { + DMA1->INTFCLR |= (uint32_t)(flag & 0x0FFFFFFF); + } +} + +/*! + * @brief Checks whether the specified interrupt has occurred or not + * + * @param flag: Specifies the DMA interrupt pending bit to check + * The parameter can be one following values: + * @arg DMA1_INT_FLAG_AL1: DMA1_Channel 1 All interrupt flag + * @arg DMA1_INT_FLAG_TF1: DMA1_Channel 1 Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_HT1: DMA1_Channel 1 Half Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_TE1: DMA1_Channel 1 Transfer Error interrupt flag + * @arg DMA1_INT_FLAG_AL2: DMA1_Channel 2 All interrupt flag + * @arg DMA1_INT_FLAG_TF2: DMA1_Channel 2 Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_HT2: DMA1_Channel 2 Half Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_TE2: DMA1_Channel 2 Transfer Error interrupt flag + * @arg DMA1_INT_FLAG_AL3: DMA1_Channel 3 All interrupt flag + * @arg DMA1_INT_FLAG_TF3: DMA1_Channel 3 Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_HT3: DMA1_Channel 3 Half Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_TE3: DMA1_Channel 3 Transfer Error interrupt flag + * @arg DMA1_INT_FLAG_AL4: DMA1_Channel 4 All interrupt flag + * @arg DMA1_INT_FLAG_TF4: DMA1_Channel 4 Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_HT4: DMA1_Channel 4 Half Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_TE4: DMA1_Channel 4 Transfer Error interrupt flag + * @arg DMA1_INT_FLAG_AL5: DMA1_Channel 5 All interrupt flag + * @arg DMA1_INT_FLAG_TF5: DMA1_Channel 5 Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_HT5: DMA1_Channel 5 Half Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_TE5: DMA1_Channel 5 Transfer Error interrupt flag + * Below is only for APM32F072 and APM32F091 devices: + * @arg DMA1_INT_FLAG_AL6: DMA1_Channel 6 All interrupt flag + * @arg DMA1_INT_FLAG_TF6: DMA1_Channel 6 Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_HT6: DMA1_Channel 6 Half Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_TE6: DMA1_Channel 6 Transfer Error interrupt flag + * @arg DMA1_INT_FLAG_AL7: DMA1_Channel 7 All interrupt flag + * @arg DMA1_INT_FLAG_TF7: DMA1_Channel 7 Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_HT7: DMA1_Channel 7 Half Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_TE7: DMA1_Channel 7 Transfer Error interrupt flag + * Below is only for APM32F091 devices: + * @arg DMA2_INT_FLAG_AL1: DMA2_Channel 1 All interrupt flag + * @arg DMA2_INT_FLAG_TF1: DMA2_Channel 1 Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_HT1: DMA2_Channel 1 Half Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_TE1: DMA2_Channel 1 Transfer Error interrupt flag + * @arg DMA2_INT_FLAG_AL2: DMA2_Channel 2 All interrupt flag + * @arg DMA2_INT_FLAG_TF2: DMA2_Channel 2 Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_HT2: DMA2_Channel 2 Half Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_TE2: DMA2_Channel 2 Transfer Error interrupt flag + * @arg DMA2_INT_FLAG_AL3: DMA2_Channel 3 All interrupt flag + * @arg DMA2_INT_FLAG_TF3: DMA2_Channel 3 Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_HT3: DMA2_Channel 3 Half Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_TE3: DMA2_Channel 3 Transfer Error interrupt flag + * @arg DMA2_INT_FLAG_AL4: DMA2_Channel 4 All interrupt flag + * @arg DMA2_INT_FLAG_TF4: DMA2_Channel 4 Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_HT4: DMA2_Channel 4 Half Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_TE4: DMA2_Channel 4 Transfer Error interrupt flag + * @arg DMA2_INT_FLAG_AL5: DMA2_Channel 5 All interrupt flag + * @arg DMA2_INT_FLAG_TF5: DMA2_Channel 5 Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_HT5: DMA2_Channel 5 Half Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_TE5: DMA2_Channel 5 Transfer Error interrupt flag + * + * @retval The new state of flag (SET or RESET) + */ +uint8_t DMA_ReadIntFlag(DMA_INT_FLAG_T flag) +{ + uint32_t status; + + if ((flag & 0x10000000) == SET) + { + status = DMA2->INTSTS & ((uint32_t)flag & 0x000FFFFF); + } + else + { + status = DMA1->INTSTS & ((uint32_t)flag & 0x0FFFFFFF); + } + + if (status == flag) + { + return SET; + } + + return RESET; +} + +/*! + * @brief Clears the specified interrupt pending bits + * + * @param flag: Specifies the DMA interrupt pending bit to clear + * The parameter can be combination of following values: + * @arg DMA1_INT_FLAG_AL1: DMA1_Channel 1 All interrupt flag + * @arg DMA1_INT_FLAG_TF1: DMA1_Channel 1 Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_HT1: DMA1_Channel 1 Half Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_TE1: DMA1_Channel 1 Transfer Error interrupt flag + * @arg DMA1_INT_FLAG_AL2: DMA1_Channel 2 All interrupt flag + * @arg DMA1_INT_FLAG_TF2: DMA1_Channel 2 Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_HT2: DMA1_Channel 2 Half Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_TE2: DMA1_Channel 2 Transfer Error interrupt flag + * @arg DMA1_INT_FLAG_AL3: DMA1_Channel 3 All interrupt flag + * @arg DMA1_INT_FLAG_TF3: DMA1_Channel 3 Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_HT3: DMA1_Channel 3 Half Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_TE3: DMA1_Channel 3 Transfer Error interrupt flag + * @arg DMA1_INT_FLAG_AL4: DMA1_Channel 4 All interrupt flag + * @arg DMA1_INT_FLAG_TF4: DMA1_Channel 4 Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_HT4: DMA1_Channel 4 Half Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_TE4: DMA1_Channel 4 Transfer Error interrupt flag + * @arg DMA1_INT_FLAG_AL5: DMA1_Channel 5 All interrupt flag + * @arg DMA1_INT_FLAG_TF5: DMA1_Channel 5 Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_HT5: DMA1_Channel 5 Half Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_TE5: DMA1_Channel 5 Transfer Error interrupt flag + * Below is only for APM32F072 and APM32F091 devices: + * @arg DMA1_INT_FLAG_AL6: DMA1_Channel 6 All interrupt flag + * @arg DMA1_INT_FLAG_TF6: DMA1_Channel 6 Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_HT6: DMA1_Channel 6 Half Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_TE6: DMA1_Channel 6 Transfer Error interrupt flag + * @arg DMA1_INT_FLAG_AL7: DMA1_Channel 7 All interrupt flag + * @arg DMA1_INT_FLAG_TF7: DMA1_Channel 7 Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_HT7: DMA1_Channel 7 Half Transfer Complete interrupt flag + * @arg DMA1_INT_FLAG_TE7: DMA1_Channel 7 Transfer Error interrupt flag + * Below is only for APM32F091 devices: + * @arg DMA2_INT_FLAG_AL1: DMA2_Channel 1 All interrupt flag + * @arg DMA2_INT_FLAG_TF1: DMA2_Channel 1 Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_HT1: DMA2_Channel 1 Half Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_TE1: DMA2_Channel 1 Transfer Error interrupt flag + * @arg DMA2_INT_FLAG_AL2: DMA2_Channel 2 All interrupt flag + * @arg DMA2_INT_FLAG_TF2: DMA2_Channel 2 Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_HT2: DMA2_Channel 2 Half Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_TE2: DMA2_Channel 2 Transfer Error interrupt flag + * @arg DMA2_INT_FLAG_AL3: DMA2_Channel 3 All interrupt flag + * @arg DMA2_INT_FLAG_TF3: DMA2_Channel 3 Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_HT3: DMA2_Channel 3 Half Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_TE3: DMA2_Channel 3 Transfer Error interrupt flag + * @arg DMA2_INT_FLAG_AL4: DMA2_Channel 4 All interrupt flag + * @arg DMA2_INT_FLAG_TF4: DMA2_Channel 4 Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_HT4: DMA2_Channel 4 Half Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_TE4: DMA2_Channel 4 Transfer Error interrupt flag + * @arg DMA2_INT_FLAG_AL5: DMA2_Channel 5 All interrupt flag + * @arg DMA2_INT_FLAG_TF5: DMA2_Channel 5 Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_HT5: DMA2_Channel 5 Half Transfer Complete interrupt flag + * @arg DMA2_INT_FLAG_TE5: DMA2_Channel 5 Transfer Error interrupt flag + * + * @retval None + */ +void DMA_ClearIntFlag(uint32_t flag) +{ + if ((flag & 0x10000000) == SET) + { + DMA2->INTFCLR |= (uint32_t)(flag & 0x000FFFFF); + } + else + { + DMA1->INTFCLR |= (uint32_t)(flag & 0x0FFFFFFF); + } +} + +/**@} end of group DMA_Functions */ +/**@} end of group DMA_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ + diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_eint.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_eint.c new file mode 100644 index 0000000000..4232c160c0 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_eint.c @@ -0,0 +1,231 @@ +/*! + * @file apm32f0xx_eint.c + * + * @brief This file contains all the functions for the EINT peripheral + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "apm32f0xx_eint.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ + */ + +/** @addtogroup EINT_Driver + @{ + */ + +/** @defgroup EINT_Macros Macros + @{ + */ + +/**@} end of group EINT_Macros */ + +/** @defgroup EINT_Enumerates Enumerates + @{ + */ + +/**@} end of group EINT_Enumerates */ + +/** @defgroup EINT_Structures Structures + @{ + */ + +/**@} end of group EINT_Structures */ + +/** @defgroup EINT_Variables Variables + @{ + */ + +/**@} end of group EINT_Variables */ + +/** @defgroup EINT_Functions Functions + @{ + */ + +/*! + * @brief Set the EINT peripheral registers to their default reset values + * + * @param None + * + * @retval None + */ +void EINT_Reset(void) +{ + EINT->IMASK = EINT_INTMASK_RESET_VALUE; + EINT->EMASK = EINT_EVTMASK_RESET_VALUE; + EINT->RTEN = EINT_RTSEL_RESET_VALUE; + EINT->FTEN = EINT_FTSEL_RESET_VALUE; + EINT->IPEND = EINT_PEND_RESET_VALUE; +} + +/*! + * @brief Configure the EINT + * + * @param eintConfig: Pointer to EINT_Config_T structure + * + * @retval None + */ +void EINT_Config(EINT_Config_T* eintConfig) +{ + if (eintConfig->lineCmd == DISABLE) + { + if (eintConfig->mode == EINT_MODE_INTERRUPT) + { + EINT->IMASK &= ~eintConfig->line; + } + else if (eintConfig->mode == EINT_MODE_EVENT) + { + EINT->EMASK &= ~eintConfig->line; + } + } + else + { + if (eintConfig->mode == EINT_MODE_INTERRUPT) + { + EINT->IMASK |= eintConfig->line; + } + else if (eintConfig->mode == EINT_MODE_EVENT) + { + EINT->EMASK |= eintConfig->line; + } + + if (eintConfig->trigger == EINT_TRIGGER_RISING) + { + EINT->RTEN |= eintConfig->line; + } + else if (eintConfig->trigger == EINT_TRIGGER_FALLING) + { + EINT->FTEN |= eintConfig->line; + } + else + { + EINT->RTEN |= eintConfig->line; + EINT->FTEN |= eintConfig->line; + } + + } +} + +/*! + * @brief Fills each EINT_Config_T member with its default value + * + * @param eintConfig: Pointer to a EINT_Config_T structure which will be initialized + * + * @retval None + */ +void EINT_ConfigStructInit(EINT_Config_T* eintConfig) +{ + eintConfig->line = EINT_LINENONE; + eintConfig->mode = EINT_MODE_INTERRUPT; + eintConfig->trigger = EINT_TRIGGER_FALLING; + eintConfig->lineCmd = DISABLE; +} + +/*! + * @brief Select software interrupt on EINT line + * + * @param line: specifies the EINT line on which the software interrupt + * + * @retval None + */ +void EINT_SelectSWInterrupt(uint32_t line) +{ + EINT->SWINTE |= (uint32_t)line; +} + +/*! + * @brief Read the specified EINT line flag + * + * @param line: Select the EINT line + * + * @retval status: The new state of flag (SET or RESET) + */ +uint8_t EINT_ReadStatusFlag(uint32_t line) +{ + uint8_t status = RESET; + + if ((EINT->IPEND & line) != (uint32_t)RESET) + { + status = SET; + } + else + { + status = RESET; + } + + return status; +} + +/*! + * @brief Clears the EINT line pending bits + * + * @param line: Select the EINT line + * + * @retval None + */ +void EINT_ClearStatusFlag(uint32_t line) +{ + EINT->IPEND = line; +} + +/*! + * @brief Read the specified EINT line interrupt flag + * + * @param line: Select the EINT line + * + * @retval None + */ +uint8_t EINT_ReadIntFlag(uint32_t line) +{ + uint8_t status = RESET; + uint32_t enablestatus = 0; + + enablestatus = EINT->IMASK & line; + + if ((EINT->IPEND & line) != ((uint32_t)RESET) && (enablestatus != (uint32_t)RESET)) + { + status = SET; + } + else + { + status = RESET; + } + + return status; +} + +/*! + * @brief Clears the EINT line pending bits + * + * @param line: Select the EINT line + * + * @retval None + */ +void EINT_ClearIntFlag(uint32_t line) +{ + EINT->IPEND = line; +} + +/**@} end of group EINT_Functions */ +/**@} end of group EINT_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_fmc.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_fmc.c new file mode 100644 index 0000000000..e5aa8143fb --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_fmc.c @@ -0,0 +1,1005 @@ +/*! + * @file apm32f0xx_fmc.c + * + * @brief This file provides all the FMC firmware functions + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +#include "apm32f0xx_fmc.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup FMC_Driver + @{ +*/ + +/** @defgroup FMC_Macros Macros + @{ + */ + +/**@} end of group FMC_Macros */ + +/** @defgroup FMC_Enumerates Enumerates + @{ + */ + +/**@} end of group FMC_Enumerates */ + +/** @defgroup FMC_Structures Structures + @{ + */ + +/**@} end of group FMC_Structures */ + +/** @defgroup FMC_Variables Variables + @{ + */ + +/**@} end of group FMC_Variables */ + +/** @defgroup FMC_Functions Functions + @{ + */ + +/*! + * @brief Sets the code latency value. + * + * @param latency: the flash latency value. + * The parameter can be one of following values: + * @arg FMC_LATENCY_0 + * @arg FMC_LATENCY_1 + * @retval None + */ +void FMC_SetLatency(FMC_LATENCY_T latency) +{ + FMC->CTRL1_B.WS = latency; +} + +/*! + * @brief Enables the Prefetch Buffer. + * + * @param None + * + * @retval None + */ +void FMC_EnablePrefetchBuffer(void) +{ + FMC->CTRL1_B.PBEN = ENABLE; +} + +/*! + * @brief Disables the Prefetch Buffer. + * + * @param None + * + * @retval None + */ +void FMC_DisablePrefetchBuffer(void) +{ + FMC->CTRL1_B.PBEN = DISABLE; +} + +/*! + * @brief Checks whether the flash Prefetch Buffer status is set or not + * + * @param None + * + * @retval flash Prefetch Buffer Status (SET or RESET) + */ +uint8_t FMC_ReadPrefetchBufferStatus(void) +{ + if (FMC->CTRL1_B.PBSF) + { + return SET; + } + + return RESET; +} + +/*! + * @brief Unlocks the flash Program Erase Controller + * + * @param None + * + * @retval None + */ +void FMC_Unlock(void) +{ + FMC->KEY = FMC_KEY_1; + FMC->KEY = FMC_KEY_2; +} + +/*! + * @brief Locks the flash Program Erase Controller + * + * @param None + * + * @retval None + */ +void FMC_Lock(void) +{ + FMC->CTRL2_B.LOCK = BIT_SET; +} + +/*! + * @brief Read flash state + * + * @param None + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_BUSY + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + */ +FMC_STATE_T FMC_ReadState(void) +{ + uint32_t status; + FMC_STATE_T state = FMC_STATE_COMPLETE; + + status = FMC->STS; + + if (status & FMC_FLAG_PE) + { + state = FMC_STATE_PG_ERR; + } + else if (status & FMC_FLAG_WPE) + { + state = FMC_STATE_WRP_ERR; + } + else if (status & FMC_FLAG_BUSY) + { + state = FMC_STATE_BUSY; + } + + return state; +} + +/*! + * @brief Wait for flash controler ready + * + * @param timeOut: Specifies the time to wait + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_BUSY + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + * @arg FMC_STATE_TIMEOUT + */ +FMC_STATE_T FMC_WaitForReady(uint32_t timeOut) +{ + FMC_STATE_T state; + + do + { + state = FMC_ReadState(); + timeOut--; + } + while ((state == FMC_STATE_BUSY) && (timeOut)); + + if (!timeOut) + { + state = FMC_STATE_TIMEOUT; + } + + return state; +} + +/*! + * @brief Erases a specified flash page + * + * @param pageAddr: Specifies the page address + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + * @arg FMC_STATE_TIMEOUT + */ +FMC_STATE_T FMC_ErasePage(uint32_t pageAddr) +{ + FMC_STATE_T state; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state == FMC_STATE_COMPLETE) + { + FMC->CTRL2_B.PAGEERA = BIT_SET; + + FMC->ADDR = pageAddr; + + FMC->CTRL2_B.STA = BIT_SET; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + FMC->CTRL2_B.PAGEERA = BIT_RESET; + } + + return state; +} + +/*! + * @brief Erases all flash pages + * + * @param None + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + * @arg FMC_STATE_TIMEOUT + * @note + */ +FMC_STATE_T FMC_EraseAllPages(void) +{ + FMC_STATE_T state; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state == FMC_STATE_COMPLETE) + { + FMC->CTRL2_B.MASSERA = BIT_SET; + FMC->CTRL2_B.STA = BIT_SET; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + FMC->CTRL2_B.MASSERA = BIT_RESET; + } + + return state; +} + +/*! + * @brief Program a word at a specified address + * + * @param addr: Specifies the address to be programmed + * + * @param data: Specifies the data to be programmed + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + * @arg FMC_STATE_TIMEOUT + */ +FMC_STATE_T FMC_ProgramWord(uint32_t addr, uint32_t data) +{ + FMC_STATE_T state; + + state = FMC_WaitForReady(FMC_DELAY_PROGRAM); + + if (state == FMC_STATE_COMPLETE) + { + FMC->CTRL2_B.PG = BIT_SET; + + *(__IO uint16_t*)addr = (uint16_t)data; + + state = FMC_WaitForReady(FMC_DELAY_PROGRAM); + + if (state == FMC_STATE_COMPLETE) + { + *(__IO uint16_t*)(addr + 2) = (uint16_t)(data >> 16); + + state = FMC_WaitForReady(FMC_DELAY_PROGRAM); + } + + FMC->CTRL2_B.PG = BIT_RESET; + } + + return state; +} + +/*! + * @brief Programs a half word at a specified address + * + * @param addr: Specifies the address to be programmed + * + * @param data: Specifies the data to be programmed + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + * @arg FMC_STATE_TIMEOUT + */ +FMC_STATE_T FMC_ProgramHalfWord(uint32_t addr, uint16_t data) +{ + FMC_STATE_T state; + + state = FMC_WaitForReady(FMC_DELAY_PROGRAM); + + if (state == FMC_STATE_COMPLETE) + { + FMC->CTRL2_B.PG = BIT_SET; + + *(__IO uint16_t*)addr = data; + + state = FMC_WaitForReady(FMC_DELAY_PROGRAM); + + FMC->CTRL2_B.PG = BIT_RESET; + } + + return state; +} + +/*! + * @brief Unlocks the option bytes block access + * + * @param None + * + * @retval None + */ +void FMC_UnlockOptionByte(void) +{ + FMC->OBKEY = FMC_OB_KEY_1; + FMC->OBKEY = FMC_OB_KEY_2; +} + +/*! + * @brief Locks the option bytes block access + * + * @param None + * + * @retval None + */ +void FMC_LockOptionByte(void) +{ + FMC->CTRL2_B.OBWEN = BIT_RESET; +} + +/*! + * @brief Launch the option byte loading + * + * @param None + * + * @retval None + */ +void FMC_LaunchOptionByte(void) +{ + FMC->CTRL2_B.OBLOAD = BIT_SET; +} + +/*! + * @brief Erase the flash option bytes + * + * @param None + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + * @arg FMC_STATE_TIMEOUT + */ +FMC_STATE_T FMC_EraseOptionByte(void) +{ + uint16_t rpKey; + FMC_STATE_T state; + + rpKey = FMC->OBCS_B.READPROT ? 0 : FMC_RP_KEY; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state == FMC_STATE_COMPLETE) + { + FMC->OBKEY = FMC_KEY_1; + FMC->OBKEY = FMC_KEY_2; + + FMC->CTRL2_B.OBE = BIT_SET; + FMC->CTRL2_B.STA = BIT_SET; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state == FMC_STATE_COMPLETE) + { + FMC->CTRL2_B.OBE = BIT_RESET; + + FMC->CTRL2_B.OBP = BIT_SET; + + OB->READPROT = rpKey; + + state = FMC_WaitForReady(FMC_DELAY_PROGRAM); + + if (state != FMC_STATE_TIMEOUT) + { + FMC->CTRL2_B.OBP = BIT_RESET; + } + } + else if (state != FMC_STATE_TIMEOUT) + { + FMC->CTRL2_B.OBE = BIT_RESET; + } + } + + return state; +} + +/*! + * @brief Enable the specified page write protection + * + * @param page: Specifies the address of the pages to be write protected + * This parameter can be any combination of the flowing values: + * @arg FMC_WRP_PAGE_0_1 ... FMC_WRP_PAGE_60_61 + * @arg FMC_WRP_PAGE_ALL + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + * @arg FMC_STATE_TIMEOU + */ +FMC_STATE_T FMC_EnableWriteProtection(uint32_t page) +{ + uint8_t i; + uint16_t temp; + __IO uint16_t* WRPT; + FMC_STATE_T state; + + WRPT = &OB->WRTPROT0; + + state = FMC_WaitForReady(FMC_DELAY_PROGRAM); + + if (state == FMC_STATE_COMPLETE) + { + FMC->OBKEY = FMC_KEY_1; + FMC->OBKEY = FMC_KEY_2; + + FMC->CTRL2_B.OBP = BIT_SET; + + for (i = 0; i < 4; i++) + { + temp = (uint16_t)~(page & 0xff); + + if ((temp != 0xff) && (state == FMC_STATE_COMPLETE)) + { + WRPT[i] = temp; + + state = FMC_WaitForReady(FMC_DELAY_PROGRAM); + } + + page >>= 8; + } + + if (state != FMC_STATE_TIMEOUT) + { + FMC->CTRL2_B.OBP = BIT_RESET; + } + } + + return state; +} + +/*! + * @brief Read out protection configuration. + * + * @param rdp: specifies the read protection level + * This parameter can be any combination of the flowing values: + * @arg FMC_RDP_LEVEL_0 + * @arg FMC_RDP_LEVEL_1 + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + * @arg FMC_STATE_TIMEOU + */ +FMC_STATE_T FMC_ConfigReadOutProtection(FMC_RDP_T rdp) +{ + FMC_STATE_T state; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state == FMC_STATE_COMPLETE) + { + FMC->OBKEY = FMC_KEY_1; + FMC->OBKEY = FMC_KEY_2; + + FMC->CTRL2_B.OBE = BIT_SET; + FMC->CTRL2_B.STA = BIT_SET; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state == FMC_STATE_COMPLETE) + { + FMC->CTRL2_B.OBE = BIT_RESET; + + FMC->CTRL2_B.OBP = BIT_SET; + + OB->READPROT = rdp; + + state = FMC_WaitForReady(FMC_DELAY_PROGRAM); + + if (state != FMC_STATE_TIMEOUT) + { + FMC->CTRL2_B.OBP = BIT_RESET; + } + } + else if (state != FMC_STATE_TIMEOUT) + { + FMC->CTRL2_B.OBE = BIT_SET; + } + } + + return state; +} + +/*! + * @brief User option byte configuration + * + * @param userConfig: Pointer to a FMC_UserConfig_T structure that + * contains the configuration information for User option byte + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + * @arg FMC_STATE_TIMEOU + */ +FMC_STATE_T FMC_ConfigOptionByteUser(FMC_UserConfig_T* userConfig) +{ + FMC_STATE_T state; + uint16_t temp; + + state = FMC_WaitForReady(FMC_DELAY_PROGRAM); + + if (state == FMC_STATE_COMPLETE) + { + FMC->OBKEY = FMC_OB_KEY_1; + FMC->OBKEY = FMC_OB_KEY_2; + + FMC->CTRL2_B.OBP = BIT_SET; + + temp = (uint32_t)userConfig->iwdtSw | \ + (uint32_t)userConfig->stopce | \ + (uint32_t)userConfig->stdbyce | 0xF8; + + OB->USER = temp; + + state = FMC_WaitForReady(FMC_DELAY_PROGRAM); + + if (state != FMC_STATE_TIMEOUT) + { + FMC->CTRL2_B.OBP = BIT_RESET; + } + } + + return state; +} + +/*! + * @brief Enable the BOOT1 option bit + * + * @param None + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + * @arg FMC_STATE_TIMEOU + */ +FMC_STATE_T FMC_EnableOptionByteBOOT(void) +{ + FMC_STATE_T state; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state == FMC_STATE_COMPLETE) + { + FMC->CTRL2_B.OBP = BIT_SET; + + OB->USER_B.BOT1 = BIT_SET; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state != FMC_STATE_TIMEOUT) + { + FMC->CTRL2_B.OBP = BIT_RESET; + } + } + + return state; +} + +/*! + * @brief Disable the BOOT1 option bit + * + * @param None + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + * @arg FMC_STATE_TIMEOU + */ +FMC_STATE_T FMC_DisableOptionByteBOOT(void) +{ + FMC_STATE_T state; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state == FMC_STATE_COMPLETE) + { + FMC->CTRL2_B.OBP = BIT_SET; + + OB->USER_B.BOT1 = BIT_RESET; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state != FMC_STATE_TIMEOUT) + { + FMC->CTRL2_B.OBP = BIT_RESET; + } + } + + return state; + +} + +/*! + * @brief Enable the analogue monitoring on VDDA Power source + * + * @param None + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + * @arg FMC_STATE_TIMEOU + */ +FMC_STATE_T FMC_EnableOptionByteVDDA(void) +{ + FMC_STATE_T state; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state == FMC_STATE_COMPLETE) + { + FMC->CTRL2_B.OBP = BIT_SET; + + OB->USER_B.VDDAMON = BIT_SET; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state != FMC_STATE_TIMEOUT) + { + FMC->CTRL2_B.OBP = BIT_RESET; + } + } + + return state; + +} + +/*! + * @brief Disable the analogue monitoring on VDDA Power source + * + * @param None + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + * @arg FMC_STATE_TIMEOU + */ +FMC_STATE_T FMC_DisableOptionByteVDDA(void) +{ + FMC_STATE_T state; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state == FMC_STATE_COMPLETE) + { + FMC->CTRL2_B.OBP = BIT_SET; + + OB->USER_B.VDDAMON = BIT_RESET; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state != FMC_STATE_TIMEOUT) + { + FMC->CTRL2_B.OBP = BIT_RESET; + } + } + + return state; + +} + +/*! + * @brief Enable the SRAM parity + * + * @param None + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + * @arg FMC_STATE_TIMEOU + */ +FMC_STATE_T FMC_EnableOptionByteSRAMParity(void) +{ + FMC_STATE_T state; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state == FMC_STATE_COMPLETE) + { + FMC->CTRL2_B.OBP = BIT_SET; + + OB->USER_B.RPC = BIT_SET; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state != FMC_STATE_TIMEOUT) + { + FMC->CTRL2_B.OBP = BIT_RESET; + } + } + + return state; + +} + +/*! + * @brief Disable the SRAM parity + * + * @param None + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + * @arg FMC_STATE_TIMEOU + */ +FMC_STATE_T FMC_DisableOptionByteSRAMParity(void) +{ + FMC_STATE_T state; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state == FMC_STATE_COMPLETE) + { + FMC->CTRL2_B.OBP = BIT_SET; + + OB->USER_B.RPC = BIT_RESET; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state != FMC_STATE_TIMEOUT) + { + FMC->CTRL2_B.OBP = BIT_RESET; + } + } + + return state; + +} +/*! + * @brief Programs the FMC User Option Byte: WDT, STOP, STDBY, + * BOOT1 and VDDA ANALOG monitoring + * + * @param ob_user: Selects all user option bytes + * This parameter is a combination of the following values: + * @arg FMC_OB_IWDT_HW / FMC_OB_IWDT_SW + * @arg FMC_OB_STOP_RESET / FMC_OB_STOP_NRST + * @arg FMC_OB_STDBY_RESET / FMC_OB_STDBY_NRST + * @arg FMC_OB_BOOT0_RESET / FMC_OB_BOOT0_SET + * @arg FMC_OB_BOOT1_RESET / FMC_OB_BOOT1_SET + * @arg FMC_OB_VDDA_ANALOG_OFF / FMC_OB_VDDA_ANALOG_ON + * @arg FMC_OB_SRAM_PARITY_SET / FMC_OB_SRAM_PARITY_RESET + * @arg FMC_OB_BOOT0_SW / FMC_OB_BOOT0_HW + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + * @arg FMC_STATE_TIMEOU + */ +FMC_STATE_T FMC_WriteOptionByteUser(uint8_t ob_user) +{ + FMC_STATE_T state; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state == FMC_STATE_COMPLETE) + { + FMC->CTRL2_B.OBP = BIT_SET; + + OB->USER = ob_user; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state != FMC_STATE_TIMEOUT) + { + FMC->CTRL2_B.OBP = BIT_RESET; + } + } + + return state; + +} + +/*! + * @brief Programs a half word at a specified Option Byte Data address + * + * @param addr: specifies the address to be programmed. + * This parameter can be 0x1FFFF804 or 0x1FFFF806. + * @param data: specifies the data to be programmed. + * + * @retval Returns the flash state.It can be one of value: + * @arg FMC_STATE_COMPLETE + * @arg FMC_STATE_PG_ERR + * @arg FMC_STATE_WRP_ERR + * @arg FMC_STATE_TIMEOU + */ +FMC_STATE_T FMC_ProgramOptionByteData(uint32_t addr, uint8_t data) +{ + FMC_STATE_T state; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state == FMC_STATE_COMPLETE) + { + FMC->CTRL2_B.OBP = BIT_SET; + + *(__IO uint16_t*)addr = data; + + state = FMC_WaitForReady(FMC_DELAY_ERASE); + + if (state != FMC_STATE_TIMEOUT) + { + FMC->CTRL2_B.OBP = BIT_RESET; + } + } + + return state; + +} + +/*! + * @brief Returns the Flash User Option Bytes values + * + * @param None + * + * @retval The flash User Option Bytes + */ +uint8_t FMC_ReadOptionByteUser(void) +{ + return (uint8_t)(FMC->OBCS >> 8); +} + +/*! + * @brief Returns the flash Write Protection Option Bytes value: + * + * @param None + * + * @retval The Flash Write Protection Option Bytes value: + */ +uint32_t FMC_ReadOptionByteWriteProtection(void) +{ + return (uint32_t)(FMC->WRTPROT); +} + +/*! + * @brief Checks whether the Flash Read Protection Status is set or not + * + * @param None + * + * @retval Flash ReadOut Protection Status(SET or RESET) + */ +uint8_t FMC_GetReadProtectionStatus(void) +{ + if (FMC->OBCS_B.READPROT) + { + return SET; + } + + return RESET; +} +/*! + * @brief Enable the specified flash interrupts + * + * @param interrupt: Specifies the flash interrupt sources + * The parameter can be combination of following values: + * @arg FMC_INT_ERROR: Error interruption + * @arg FMC_INT_COMPLETE: operation complete interruption + * + * @retval None + */ +void FMC_EnableInterrupt(uint32_t interrupt) +{ + FMC->CTRL2 |= interrupt; +} + +/*! + * @brief Disable the specified flash interrupts + * + * @param interrupt: Specifies the flash interrupt sources + * The parameter can be combination of following values: + * @arg FMC_INT_ERROR: Error interruption + * @arg FMC_INT_COMPLETE: operation complete interruption + * + * @retval None + */ +void FMC_DisableInterrupt(uint32_t interrupt) +{ + FMC->CTRL2 &= ~interrupt; +} + +/*! + * @brief Checks whether the specified flash flag is set or not + * + + * @param flag: Specifies the flash flag to check + * The parameter can be one of following values: + * @arg FMC_FLAG_BUSY: Busy flag + * @arg FMC_FLAG_PE: Program error flag + * @arg FMC_FLAG_WPE: Write protection flag + * @arg FMC_FLAG_OC: Operation complete flag + * + * @retval None + */ +uint8_t FMC_ReadStatusFlag(FMC_FLAG_T flag) +{ + uint8_t status; + + if (flag & 0xff) + { + status = FMC->STS & flag; + } + else + { + status = FMC->OBCS & flag; + } + + if (status) + { + return SET; + } + + return RESET; +} + +/*! + * @brief Clear the specified flash flag + * + * @param flag: Specifies the flash flag to clear + * This parameter can be any combination of the following values: + * @arg FMC_FLAG_BUSY: Busy flag + * @arg FMC_FLAG_PE: Program error flag + * @arg FMC_FLAG_WPE: Write protection error flag + * @arg FMC_FLAG_OC: Operation complete flag + * + * @retval None + */ +void FMC_ClearStatusFlag(uint8_t flag) +{ + if (flag & 0xff) + { + FMC->STS = flag; + } +} + +/**@} end of group FMC_Functions*/ +/**@} end of group FMC_Driver*/ +/**@} end of group APM32F0xx_StdPeriphDriver*/ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_gpio.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_gpio.c new file mode 100644 index 0000000000..bea8569b40 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_gpio.c @@ -0,0 +1,378 @@ +/*! + * @file apm32f0xx_gpio.c + * + * @brief This file contains all the functions for the GPIO peripheral + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "apm32f0xx_gpio.h" +#include "apm32f0xx_rcm.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup GPIO_Driver + @{ +*/ + + +/** @defgroup GPIO_Macros Macros + @{ + */ + +/**@} end of group GPIO_Macros */ + +/** @defgroup GPIO_Enumerates Enumerates + @{ + */ + +/**@} end of group GPIO_Enumerates */ + +/** @defgroup GPIO_Structures Structures + @{ + */ + +/**@} end of group GPIO_Structures */ + +/** @defgroup GPIO_Variables Variables + @{ + */ + +/**@} end of group GPIO_Variables */ + +/** @defgroup GPIO_Functions Functions + @{ + */ + +/*! + * @brief Reset GPIO peripheral registers to their default reset values + * + * @param port: GPIO peripheral.It can be GPIOA/GPIOB/GPIOC/GPIOD/GPIOE/GPIOF + * + * @retval None + * + * @note GPIOE is available only for APM32F072 and APM32F091 + */ +void GPIO_Reset(GPIO_T* port) +{ + if (port == GPIOA) + { + RCM_EnableAHBPeriphReset(RCM_AHB_PERIPH_GPIOA); + RCM_DisableAHBPeriphReset(RCM_AHB_PERIPH_GPIOA); + } + else if (port == GPIOB) + { + RCM_EnableAHBPeriphReset(RCM_AHB_PERIPH_GPIOB); + RCM_DisableAHBPeriphReset(RCM_AHB_PERIPH_GPIOB); + } + else if (port == GPIOC) + { + RCM_EnableAHBPeriphReset(RCM_AHB_PERIPH_GPIOC); + RCM_DisableAHBPeriphReset(RCM_AHB_PERIPH_GPIOC); + } + else if (port == GPIOD) + { + RCM_EnableAHBPeriphReset(RCM_AHB_PERIPH_GPIOD); + RCM_DisableAHBPeriphReset(RCM_AHB_PERIPH_GPIOD); + } + else if (port == GPIOE) + { + RCM_EnableAHBPeriphReset(RCM_AHB_PERIPH_GPIOE); + RCM_DisableAHBPeriphReset(RCM_AHB_PERIPH_GPIOE); + } + else if (port == GPIOF) + { + RCM_EnableAHBPeriphReset(RCM_AHB_PERIPH_GPIOF); + RCM_DisableAHBPeriphReset(RCM_AHB_PERIPH_GPIOF); + } +} + +/*! + * @brief Config the GPIO peripheral according to the specified parameters in the gpioConfig + * + * @param port: GPIO peripheral.It can be GPIOA/GPIOB/GPIOC/GPIOD/GPIOE/GPIOF + * + * @param gpioConfig: Pointer to a GPIO_Config_T structure that + * contains the configuration information for the specified GPIO peripheral + * + * @retval None + * + * @note GPIOE is available only for APM32F072 and APM32F091 + */ +void GPIO_Config(GPIO_T* port, GPIO_Config_T* gpioConfig) +{ + uint32_t i; + uint32_t bit; + + for (i = 0; i < 16; i++) + { + bit = (uint32_t)1 << i; + + if (!(gpioConfig->pin & bit)) + { + continue; + } + + if ((gpioConfig->mode == GPIO_MODE_OUT) || (gpioConfig->mode == GPIO_MODE_AF)) + { + /* speed */ + port->OSSEL &= ~((0x03) << (i * 2)); + port->OSSEL |= ((uint32_t)(gpioConfig->speed) << (i * 2)); + + /* Output mode configuration */ + port->OMODE &= ~(((uint16_t)gpioConfig->outtype) << ((uint16_t)i)); + port->OMODE |= (uint16_t)(((uint16_t)gpioConfig->outtype) << ((uint16_t)i)); + } + + /* input/output mode */ + port->MODE &= ~(0x03 << (i * 2)); + port->MODE |= (((uint32_t)gpioConfig->mode) << (i * 2)); + + /* Pull-up Pull down resistor configuration */ + port->PUPD &= ~(0x03 << ((uint16_t)i * 2)); + port->PUPD |= (((uint32_t)gpioConfig->pupd) << (i * 2)); + } +} + +/*! + * @brief Fills each GPIO_Config_T member with its default value + * + * @param gpioConfig: Pointer to a GPIO_Config_T structure which will be initialized + * + * @retval None + */ +void GPIO_ConfigStructInit(GPIO_Config_T* gpioConfig) +{ + gpioConfig->pin = GPIO_PIN_ALL; + gpioConfig->mode = GPIO_MODE_IN; + gpioConfig->outtype = GPIO_OUT_TYPE_PP; + gpioConfig->speed = GPIO_SPEED_10MHz; + gpioConfig->pupd = GPIO_PUPD_NO; +} + +/*! + * @brief Locks GPIO Pins configuration registers + * + * @param port: GPIOA/B peripheral + * + * @param pin: specifies the port bit to be written + * + * @retval None + */ +void GPIO_ConfigPinLock(GPIO_T* port, uint16_t pin) +{ + uint32_t val = 0x00010000; + + val |= pin; + /* Set LOCK bit */ + port->LOCK = val ; + /* Reset LOCK bit */ + port->LOCK = pin; + /* Set LOCK bit */ + port->LOCK = val; + /* Read LOCK bit*/ + val = port->LOCK; + /* Read LOCK bit*/ + val = port->LOCK; +} + +/*! + * @brief Reads the specified input port pin + * + * @param port: GPIO peripheral.It can be GPIOA/GPIOB/GPIOC/GPIOD/GPIOE/GPIOF + * + * @param pin: specifies pin to read + * + * @retval The input port pin value + * + * @note APM32F072 and APM32F091: (0..15) for GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, (0..10) for GPIOF. + */ +uint8_t GPIO_ReadInputBit(GPIO_T* port, uint16_t pin) +{ + uint8_t ret; + + ret = (port->IDATA & pin) ? BIT_SET : BIT_RESET; + + return ret; +} + +/*! + * @brief Reads the specified GPIO input data port + * + * @param port: GPIO peripheral + * + * @retval GPIO input data port value + * + * @note GPIOE is available only for APM32F072 and APM32F091 + */ +uint16_t GPIO_ReadInputPort(GPIO_T* port) +{ + return ((uint16_t)port->IDATA); +} + +/*! + * @brief Reads the specified output data port bit + * + * @param port: GPIO peripheral + * + * @param pin: specifies pin to read + * + * @retval The output port pin value + * + * @note GPIOE is available only for APM32F072 and APM32F091 + */ +uint8_t GPIO_ReadOutputBit(GPIO_T* port, uint16_t pin) +{ + + uint8_t ret; + + ret = (port->ODATA & pin) ? BIT_SET : BIT_RESET; + + return ret; +} + +/*! + * @brief Reads the specified GPIO output data port + * + * @param port: GPIO peripheral + * + * @retval output data port value + * + * @note GPIOE is available only for APM32F072 and APM32F091 + */ +uint16_t GPIO_ReadOutputPort(GPIO_T* port) +{ + return ((uint16_t)port->ODATA); +} + +/*! + * @brief Sets the selected data port bits + * + * @param port: GPIO peripheral + * + * @param pin: specifies the port bits to be written + * + * @retval None + * + * @note APM32F072 and APM32F091: (0..15) for GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, (0..10) for GPIOF. + */ +void GPIO_SetBit(GPIO_T* port, uint16_t pin) +{ + port->BSC = (uint32_t)pin; +} + +/*! + * @brief Clears the selected data port bits + * + * @param port: GPIO peripheral + * + * @param pin: specifies the port bits to be written + * + * @retval None + * + * @note APM32F072 and APM32F091: (0..15) for GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, (0..10) for GPIOF. + */ +void GPIO_ClearBit(GPIO_T* port, uint16_t pin) +{ + port->BR = (uint32_t)pin; +} + +/*! + * @brief Sets or clears the selected data port bit + * + * @param port: GPIO peripheral + * + * @param pin: specifies the port bits to be written + * + * @param bitVal + * + * @retval None + * + * @note APM32F072 and APM32F091: (0..15) for GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, (0..10) for GPIOF. + */ +void GPIO_WriteBitValue(GPIO_T* port, uint16_t pin, GPIO_BSRET_T bitVal) +{ + if (bitVal != Bit_RESET) + { + port->BSC = pin; + } + else + { + port->BR = pin ; + } +} + +/*! + * @brief Writes data to the specified GPIO data port + * + * @param port: GPIO peripheral + * + * @param portVal: Write value to the port output data register + * + * @retval None + * + * @note GPIOE is available only for APM32F072 and APM32F091 + */ +void GPIO_WriteOutputPort(GPIO_T* port, uint16_t portValue) +{ + port->ODATA = (uint32_t)portValue; +} + +/*! + * @brief Changes the mapping of the specified pin + * + * @param port: GPIO peripheral + * + * @param pinSource: Specifies the pin for the Alternate function. + * This parameter can be one of the following values: + * @arg GPIOA,GPIOB,GPIOD,GPIOE for 0..15 + * @arg GPIOC for 0..12 + * @arg GPIOF for 0, 2..5, 9..10 + * + * @param afPin: Selects the pin to used as Alternate function. + * + * @retval None + * + * @note GPIOC, GPIOD, GPIOE and GPIOF are available only for APM32F072 and APM32F091 + */ +void GPIO_ConfigPinAF(GPIO_T* port, GPIO_PIN_SOURCE_T pinSource, GPIO_AF_T afPin) +{ + uint32_t temp = 0x00; + uint32_t temp1 = 0x00; + + if (pinSource <= 0x07) + { + temp = (uint8_t)afPin << ((uint32_t)pinSource * 4); + port->ALFL &= ~((uint32_t)0xf << ((uint32_t)pinSource * 4)); + port->ALFL |= temp; + } + else + { + temp1 = (uint8_t)afPin << ((uint32_t)(pinSource & 0x07) * 4); + port->ALFH &= ~((uint32_t)0xf << (((uint32_t)pinSource & 0x07) * 4)); + port->ALFH |= temp1; + } +} +/**@} end of group GPIO_Functions */ +/**@} end of group GPIO_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_i2c.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_i2c.c new file mode 100644 index 0000000000..3156024c9a --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_i2c.c @@ -0,0 +1,1177 @@ +/*! + * @file apm32f0xx_i2c.c + * + * @brief This file contains all the functions for the I2C peripheral + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "apm32f0xx_i2c.h" +#include "apm32f0xx_rcm.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup I2C_Driver + @{ +*/ + +/** @defgroup I2C_Macros Macros + @{ + */ + +/**@} end of group I2C_Macros */ + +/** @defgroup I2C_Enumerates Enumerates + @{ + */ + +/**@} end of group I2C_Enumerates */ + +/** @defgroup I2C_Structures Structures + @{ + */ + +/**@} end of group I2C_Structures */ + +/** @defgroup I2C_Variables Variables + @{ + */ + +/**@} end of group I2C_Variables */ + +/** @defgroup I2C_Functions Functions + @{ + */ + +/*! + * @brief Set the I2C peripheral registers to their default reset values + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_Reset(I2C_T* i2c) +{ + if (i2c == I2C1) + { + RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_I2C1); + RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_I2C1); + } + else + { + RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_I2C2); + RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_I2C2); + } +} + +/*! + * @brief Config the I2C peripheral according to the specified parameters in the adcConfig + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @param adcConfig: Pointer to a I2C_Config_T structure that + * contains the configuration information for the I2C peripheral + * + * @retval None + */ +void I2C_Config(I2C_T* i2c, I2C_Config_T* i2cConfig) +{ + uint32_t temp = 0; + + /* Disable I2C */ + i2c->CTRL1_B.I2CEN = BIT_RESET; + + /* FILTERS Configuration */ + temp = i2c->CTRL1; + temp &= ((uint32_t)0x00CFE0FF); + i2c->CTRL1_B.DNFCFG = i2cConfig->digitalfilter; + i2c->CTRL1_B.ANFD = i2cConfig->analogfilter; + + /* TIMING Configuration */ + i2c->TIMING = i2cConfig-> timing & ((uint32_t)0xF0FFFFFF); + + /* Enable I2C */ + i2c->CTRL1_B.I2CEN = BIT_SET; + + /* ADDR1 Configuration */ + temp = 0; + i2c->ADDR1 = 0; + i2c->ADDR2 = 0; + + temp = (uint32_t)((uint32_t)i2cConfig->ackaddress << 10 | \ + (uint32_t)i2cConfig->address1); + + /* Write to I2C ADDR1 */ + i2c->ADDR1 = temp; + + /* Enable Own Address1 acknowledgement */ + i2c->ADDR1_B.ADDR1EN = BIT_SET; + + /* Mode Configuration */ + i2c->CTRL1 &= 0xFFCFFFF; + temp = i2cConfig->mode; + i2c->CTRL1 |= temp; + + /* Ack Configuration */ + i2c->CTRL2_B.NACKEN = i2cConfig->ack; +} + +/*! + * @brief Fills each i2cConfig member with its default value + * + * @param i2cConfig: Pointer to a I2C_Config_T structure which will be initialized + * + * @retval None + */ +void I2C_ConfigStructInit(I2C_Config_T* i2cConfig) +{ + i2cConfig->timing = 0; + i2cConfig->address1 = 0; + i2cConfig->mode = I2C_MODE_I2C; + i2cConfig->analogfilter = I2C_ANALOG_FILTER_ENABLE; + i2cConfig->digitalfilter = I2C_DIGITAL_FILTER_0; + + i2cConfig->ack = I2C_ACK_DISABLE; + i2cConfig->ackaddress = I2C_ACK_ADDRESS_7BIT; +} + +/*! + * @brief Enable the I2C peripheral + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_Enable(I2C_T* i2c) +{ + i2c->CTRL1_B.I2CEN = BIT_SET; +} + +/*! + * @brief Disable the I2C peripheral + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_Disable(I2C_T* i2c) +{ + i2c->CTRL1_B.I2CEN = BIT_RESET; +} + +/*! + * @brief I2C Soft ware Reset + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_SoftwareReset(I2C_T* i2c) +{ + i2c->CTRL1_B.I2CEN = BIT_RESET; + *(__IO uint32_t*)(uint32_t)i2c; + i2c->CTRL1_B.I2CEN = BIT_SET; +} + +/*! + * @brief Enables the specified interrupts + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @param interrupt: Specifies the I2C interrupts sources + * The parameter can be combination of following values: + * @arg I2C_INT_TXIE: TX Interrupt enable + * @arg I2C_INT_RXIE: RX Interrupt enable + * @arg I2C_INT_ADDRIE: Address match interrupt enable (slave only) + * @arg I2C_INT_NACKIE: Not acknowledge received interrupt enable + * @arg I2C_INT_STOPIE: STOP detection Interrupt enable + * @arg I2C_INT_TXCIE: Transfer complete interrupt enable + * @arg I2C_INT_ERRIE: Error interrupts enable + * + * @retval None + */ +void I2C_EnableInterrupt(I2C_T* i2c, uint8_t interrupt) +{ + i2c->CTRL1 |= (uint32_t)interrupt; +} + +/*! + * @brief Disable the specified interrupts + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @param interrupt: Specifies the I2C interrupts sources + * The parameter can be combination of following values: + * @arg I2C_INT_TXIE: TX Interrupt enable + * @arg I2C_INT_RXIE: RX Interrupt enable + * @arg I2C_INT_ADDRIE: Address match interrupt enable (slave only) + * @arg I2C_INT_NACKIE: Not acknowledge received interrupt enable + * @arg I2C_INT_STOPIE: STOP detection Interrupt enable + * @arg I2C_INT_TXCIE: Transfer complete interrupt enable + * @arg I2C_INT_ERRIE: Error interrupts enable + * + * @retval None + */ +void I2C_DisableInterrupt(I2C_T* i2c, uint8_t interrupt) +{ + i2c->CTRL1 &= (uint32_t)~interrupt; +} + +/*! + * @brief Enables the stretch clock + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_EnableStretchClock(I2C_T* i2c) +{ + i2c->CTRL1_B.CLKSTRETCHD = BIT_RESET; +} + +/*! + * @brief Disables the stretch clock + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_DisableStretchClock(I2C_T* i2c) +{ + i2c->CTRL1_B.CLKSTRETCHD = BIT_SET; +} + +/*! + * @brief Enables the stop mode + * + * @param i2c: Select I2C peripheral, It can be I2C1. + * + * @retval None + * + * @note It's not for APM32F030 devices + */ +void I2C_EnableStopMode(I2C_T* i2c) +{ + i2c->CTRL1_B.WUPEN = BIT_SET; +} + +/*! + * @brief Disable the stop mode + * + * @param i2c: Select I2C peripheral, It can be I2C1. + * + * @retval None + * + * @note It's not for APM32F030 devices + */ +void I2C_DisableStopMode(I2C_T* i2c) +{ + i2c->CTRL1_B.WUPEN = BIT_RESET; +} + +/*! + * @brief Enables the I2C own address 2 + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_EnableOwnAddress2(I2C_T* i2c) +{ + i2c->ADDR2_B.ADDR2EN = BIT_SET; +} + +/*! + * @brief Disables the I2C own address 2 + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_DisableOwnAddress2(I2C_T* i2c) +{ + i2c->ADDR2_B.ADDR2EN = BIT_RESET; +} + +/*! + * @brief I2C slave own address 2 and mask + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @param mask: Own address 2 mask selection + * The parameter can be one of following values: + * @arg I2C_ADDR2MSK_NOMASK: No masked + * @arg I2C_ADDR2MSK_MASK01: Don't care masked ADDR2[1:0] + * @arg I2C_ADDR2MSK_MASK02: Don't care masked ADDR2[2:1] + * @arg I2C_ADDR2MSK_MASK03: Don't care masked ADDR2[3:1] + * @arg I2C_ADDR2MSK_MASK04: Don't care masked ADDR2[4:1] + * @arg I2C_ADDR2MSK_MASK05: Don't care masked ADDR2[5:1] + * @arg I2C_ADDR2MSK_MASK06: Don't care masked ADDR2[6:1] + * @arg I2C_ADDR2MSK_MASK07: Don't care masked ADDR2[7:1] + * + * @retval None + */ +void I2C_OwnAddress2Mask(I2C_T* i2c, uint16_t address, I2C_ADDR2MSK_T mask) +{ + i2c->ADDR2_B.ADDR2 = address; + i2c->ADDR2_B.ADDR2MSK = mask; + +} + +/*! + * @brief Enables the Broadcast call mode + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_EnableBroadcastCall(I2C_T* i2c) +{ + i2c->CTRL1_B.RBEN = BIT_SET; +} + +/*! + * @brief Disables the Broadcast call mode + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_DisableBroadcastCall(I2C_T* i2c) +{ + i2c->CTRL1_B.RBEN = BIT_RESET; +} + +/*! + * @brief Enables the slave byte control + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_EnableSlaveByteControl(I2C_T* i2c) +{ + i2c->CTRL1_B.SBCEN = BIT_SET; +} + +/*! + * @brief Disables the slave byte control + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_DisableSlaveByteControl(I2C_T* i2c) +{ + i2c->CTRL1_B.SBCEN = BIT_RESET; +} + +/*! + * @brief Configures the slave address + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @param address: set I2C slave uint16_t Address + * + * @retval None + */ +void I2C_SlaveAddress(I2C_T* i2c, uint16_t address) +{ + uint32_t temp = 0; + temp = i2c->CTRL2; + + temp &= (uint32_t)~((uint32_t)0x000003FF); + i2c->CTRL2 = temp; + + i2c->ADDR2_B.ADDR2 = address; +} + +/*! + * @brief Enables I2C 10-bit addressing mode for the master + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_Enable10BitAddressingMode(I2C_T* i2c) +{ + i2c->CTRL2_B.SADDRLEN = BIT_SET; +} + +/*! + * @brief Disables I2C 10-bit addressing mode for the master + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_Disable10BitAddressingMode(I2C_T* i2c) +{ + i2c->CTRL2_B.SADDRLEN = BIT_RESET; +} + +/*! + * @brief Enables the I2C automatic end mode + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_EnableAutoEnd(I2C_T* i2c) +{ + i2c->CTRL2_B.ENDCFG = BIT_SET; +} + +/*! + * @brief Disables the I2C automatic end mode + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_DisableAutoEnd(I2C_T* i2c) +{ + i2c->CTRL2_B.ENDCFG = BIT_RESET; +} + +/*! + * @brief Enables the I2C nbytes reload mode + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_EnableReload(I2C_T* i2c) +{ + i2c->CTRL2_B.RELOADEN = BIT_SET; +} + +/*! + * @brief Disables the I2C nbytes reload mode + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_DisableReload(I2C_T* i2c) +{ + i2c->CTRL2_B.RELOADEN = BIT_RESET; +} + +/*! + * @brief Configures the number of bytes to be transmitted/received + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @param number:Set uint8_t bytes to read or write + * + * @retval None + */ +void I2C_ConfigNumberOfBytes(I2C_T* i2c, uint8_t number) +{ + i2c->CTRL2_B.NUMBYT = 0xFF; + i2c->CTRL2_B.NUMBYT &= (uint8_t) number ; +} + +/*! + * @brief Configures the type of transfer request for the master + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @param direction: selects the I2C transfer direction. + * The parameter can be one of following values: + * @arg I2C_DIRECTION_TX: Transmission direction + * @arg I2C_DIRECTION_RX: Reception direction + * + * @retval None + */ +void I2C_ConfigMasterRequest(I2C_T* i2c, I2C_DIRECTION_T direction) +{ + i2c->CTRL2_B.TXDIR = direction ; +} + +/*! + * @brief Enables the generates i2c communication start condition + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_EnableGenerateStart(I2C_T* i2c) +{ + i2c->CTRL2_B.START = BIT_SET; +} + +/*! + * @brief Disables the generates i2c communication start condition + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_DisableGenerateStart(I2C_T* i2c) +{ + i2c->CTRL2_B.START = BIT_RESET; +} + +/*! + * @brief Enables the generates i2c communication stop condition + * + * @param i2c: Select I2C peripheral + * This parameter can be any combination of the following values: + * @arg I2C1 + * @arg I2C2 + * + * @retval None + */ +void I2C_EnableGenerateStop(I2C_T* i2c) +{ + i2c->CTRL2_B.STOP = BIT_SET; +} + +/*! + * @brief Disables the generates i2c communication stop condition + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_DisableGenerateStop(I2C_T* i2c) +{ + i2c->CTRL2_B.STOP = BIT_RESET; +} + +/*! + * @brief Enables I2C 10-bit header only mode with read direction + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_Enable10BitAddressHeader(I2C_T* i2c) +{ + i2c->CTRL2_B.ADDR10 = BIT_SET; +} + +/*! + * @brief Disables I2C 10-bit header only mode with read direction + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_Disable10BitAddressHeader(I2C_T* i2c) +{ + i2c->CTRL2_B.ADDR10 = BIT_RESET; +} + +/*! + * @brief Enables I2C communication Acknowledge + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_EnableAcknowledge(I2C_T* i2c) +{ + i2c->CTRL2_B.NACKEN = BIT_RESET; +} + +/*! + * @brief Disables I2C communication Acknowledge + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_DisableAcknowledge(I2C_T* i2c) +{ + i2c->CTRL2_B.NACKEN = BIT_SET; +} + +/*! + * @brief Returns the I2C slave matched address + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval The value is slave matched address + */ +uint8_t I2C_ReadAddressMatched(I2C_T* i2c) +{ + return ((uint8_t)i2c->STS_B.ADDRCMFLG); +} + +/*! + * @brief Returns the I2C slave received request + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval The value of the received request + */ +uint16_t I2C_ReadTransferDirection(I2C_T* i2c) +{ + uint16_t direction = 0; + uint32_t temp = 0; + + temp = (uint32_t) i2c->STS_B.TXDIRFLG; + + if (temp == 0) + { + direction = (uint16_t)I2C_DIRECTION_TX; + } + else + { + direction = (uint16_t)(I2C_DIRECTION_RX << 10); + } + + return direction; +} + +/*! + * @brief Handles I2Cx communication when starting transfer or during transfer + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @param address: specifies the slave address to be programmed. + * + * @param number: specifies the number of bytes to be programmed. + * This parameter must be a value between 0 and 255. + * + * @param reloadend: the I2C reload end mode + * The parameter can be one of following values: + * @arg I2C_RELOAD_MODE_RELOAD: Enable Reload mode. + * @arg I2C_RELOAD_MODE_AUTOEND: Enable Automatic end mode. + * @arg I2C_RELOAD_MODE_SOFTEND: Enable Software end mode. + * + * @param generates: the I2C start/stop mode + * The parameter can be one of following values: + * @arg I2C_GENERATE_NO_STARTSTOP: Don't Generate stop and start condition. + * @arg I2C_GENERATE_START_WRITE: Generate Restart for write request. + * @arg I2C_GENERATE_STOP: Generate stop condition + * @arg I2C_GENERATE_START_READ: Generate Restart for read request. + * + * @retval None + */ +void I2C_HandlingTransfer(I2C_T* i2c, uint16_t address, uint8_t number, I2C_RELOAD_MODE_T reloadend, I2C_GENERATE_T generates) +{ + uint32_t temp = 0; + + /* Get the CTRL2 register value */ + temp = i2c->CTRL2; + + /* clear temp specific bits */ + temp &= (uint32_t)~((uint32_t)(I2C_CTRL2_SADD | I2C_CTRL2_NUMBYT | I2C_CTRL2_MASK)); + + /* update temp */ + temp |= (uint32_t)(((uint32_t)address & I2C_CTRL2_SADD) | (((uint32_t)number << 16) & I2C_CTRL2_NUMBYT) | \ + (uint32_t)reloadend | (uint32_t)generates); + + /* update CTRL2 register */ + i2c->CTRL2 = temp; +} + +/*! + * @brief Enables I2C SMBus alert + * + * @param i2c: Select I2C peripheral,it can be I2C1. + * + * @retval None + */ +void I2C_EnableSMBusAlert(I2C_T* i2c) +{ + i2c->CTRL1_B.ALTEN = BIT_SET; +} + +/*! + * @brief Disables I2C SMBus alert + * + * @param i2c: Select I2C peripheral,it can be I2C1. + * + * @retval None + */ +void I2C_DisableSMBusAlert(I2C_T* i2c) +{ + i2c->CTRL1_B.ALTEN = BIT_RESET; +} + +/*! + * @brief Enable I2C SMBus HADDREN + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_EnableSMBusHAEN(I2C_T* i2c) +{ + i2c->CTRL1_B.HADDREN = BIT_SET; +} + +/*! + * @brief Disable I2C SMBus HADDREN + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_DisableSMBusHAEN(I2C_T* i2c) +{ + i2c->CTRL1_B.HADDREN = BIT_RESET; +} + +/*! + * @brief Enable I2C SMBus DEADDREN + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ + +void I2C_EnableSMBusDAEN(I2C_T* i2c) +{ + i2c->CTRL1_B.DEADDREN = BIT_SET; +} + +/*! + * @brief Disable I2C SMBus DEADDREN + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval None + */ +void I2C_DisableSMBusDAEN(I2C_T* i2c) +{ + i2c->CTRL1_B.DEADDREN = BIT_RESET; +} + +/*! + * @brief Enables I2C Clock Timeout + * + * @param i2c: Select I2C peripheral,it can be I2C1. + * + * @retval None + */ +void I2C_EnableClockTimeout(I2C_T* i2c) +{ + i2c->TIMEOUT_B.CLKTOEN = BIT_SET; +} + +/*! + * @brief Disables I2C Clock Timeout + * + * @param i2c: Select I2C peripheral,it can be I2C1. + * + * @retval None + */ +void I2C_DisableClockTimeout(I2C_T* i2c) +{ + i2c->TIMEOUT_B.CLKTOEN = BIT_RESET; +} + +/*! + * @brief Enables I2C Extend Clock Timeout + * + * @param i2c: Select I2C peripheral,it can be I2C1. + * + * @retval None + */ +void I2C_EnableExtendClockTimeout(I2C_T* i2c) +{ + i2c->TIMEOUT_B.EXCLKTOEN = BIT_SET; +} + +/*! + * @brief Disables I2C Extend Clock Timeout + * + * @param i2c: Select I2C peripheral,it can be I2C1. + * + * @retval None + */ +void I2C_DisableExtendClockTimeout(I2C_T* i2c) +{ + i2c->TIMEOUT_B.EXCLKTOEN = BIT_RESET; +} + +/*! + * @brief Enables I2C Idle Clock Timeout + * + * @param i2c: Select I2C peripheral,it can be I2C1. + * + * @retval None + */ +void I2C_EnableIdleClockTimeout(I2C_T* i2c) +{ + i2c->TIMEOUT_B.IDLECLKTO = BIT_SET; +} + +/*! + * @brief Disables I2C Idle Clock Timeout + * + * @param i2c: Select I2C peripheral,it can be I2C1. + * + * @retval None + */ +void I2C_DisableIdleClockTimeout(I2C_T* i2c) +{ + i2c->TIMEOUT_B.IDLECLKTO = BIT_RESET; +} + +/*! + * @brief Configures the I2C Bus Timeout A + * + * @param i2c: Select I2C peripheral,it can be I2C1. + * + * @param timeout: specifies the Timeout A to be programmed + * + * @retval None + */ +void I2C_ConfigTimeoutA(I2C_T* i2c, uint16_t timeout) +{ + i2c->TIMEOUT_B.TIMEOUTA = timeout; +} + +/*! + * @brief Configures the I2C Bus Timeout B + * + * @param i2c: Select I2C peripheral,it can be I2C1. + * + * @param timeout: specifies the Timeout B to be programmed + * + * @retval None + */ +void I2C_ConfigTimeoutB(I2C_T* i2c, uint16_t timeout) +{ + i2c->TIMEOUT_B.TIMEOUTB = timeout; +} + +/*! + * @brief Enables I2C PEC calculation + * + * @param i2c: Select I2C peripheral,it can be I2C1. + * + * @retval None + */ +void I2C_EnablePEC(I2C_T* i2c) +{ + i2c->CTRL1_B.PECEN = BIT_SET; +} + +/*! + * @brief Disables I2C PEC calculation + * + * @param i2c: Select I2C peripheral,it can be I2C1. + * + * @retval None + */ +void I2C_DisablePEC(I2C_T* i2c) +{ + i2c->CTRL1_B.PECEN = BIT_RESET; +} + +/*! + * @brief Enables I2C PEC transmission/reception request + * + * @param i2c: Select I2C peripheral,it can be I2C1. + * + * @retval None + */ +void I2C_EnablePECRequest(I2C_T* i2c) +{ + i2c->CTRL2_B.PEC = BIT_SET; +} + +/*! + * @brief Disables I2C PEC transmission/reception request + * + * @param i2c: Select I2C peripheral,it can be I2C1. + * + * @retval None + */ +void I2C_DisablePECRequest(I2C_T* i2c) +{ + i2c->CTRL2_B.PEC = BIT_RESET; +} + +/*! + * @brief Returns the I2C PEC + * + * @param i2c: Select I2C peripheral,it can be I2C1. + * + * @retval The value is PEC + */ +uint8_t I2C_ReadPEC(I2C_T* i2c) +{ + return ((uint8_t)i2c->PEC_B.PEC); +} + +/*! + * @brief Reads the specified I2C register and returns its value + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @param registers: Specifies the I2C interrupts sources + * The parameter can be one of following values: + * @arg I2C_REGISTER_CTRL1: CTRL1 register + * @arg I2C_REGISTER_CTRL2: CTRL2 register + * @arg I2C_REGISTER_ADDR1: ADDR1 register + * @arg I2C_REGISTER_ADDR2: ADDR2 register + * @arg I2C_REGISTER_TIMING: TIMING register + * @arg I2C_REGISTER_TIMEOUT: TIMEOUT register + * @arg I2C_REGISTER_STS: STS register + * @arg I2C_REGISTER_INTFCLR: INTFCLR register + * @arg I2C_REGISTER_PEC: PEC register + * @arg I2C_REGISTER_RXDATA: RXDATA register + * @arg I2C_REGISTER_TXDATA: TXDATA register + * + * @retval None + */ +uint32_t I2C_ReadRegister(I2C_T* i2c, uint8_t registers) +{ + __IO uint32_t temp = 0; + + temp = (uint32_t)i2c; + temp += registers; + + return (*(__IO uint32_t*) temp); +} + +/*! + * @brief Send a byte by writing in the TXDATA register + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @param data: Byte to be sent + * + * @retval None + */ +void I2C_TxData(I2C_T* i2c, uint8_t data) +{ + i2c->TXDATA = (uint32_t)data; +} + +/*! + * @brief Returns the most recent received data + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @retval The value of the received byte data + */ +uint8_t I2C_RxData(I2C_T* i2c) +{ + return (uint8_t)i2c->RXDATA; +} + +/*! + * @brief Enables the I2C DMA interface + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @param request: DMA transfer request + * The parameter can be one of following values: + * @arg I2C_DMA_REQ_TX: TX DMA Transmission request + * @arg I2C_DMA_REQ_RX: RX DMA Transmission request + * + * @retval None + */ +void I2C_EnableDMA(I2C_T* i2c, I2C_DMA_REQ_T request) +{ + if (request == I2C_DMA_REQ_TX) + { + i2c->CTRL1_B.DMATXEN = BIT_SET; + } + else + { + i2c->CTRL1_B.DMARXEN = BIT_SET; + } +} + +/*! + * @brief Disables the I2C DMA interface + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @param request: DMA transfer request + * The parameter can be one of following values: + * @arg I2C_DMA_REQ_TX: TX DMA Transmission request + * @arg I2C_DMA_REQ_RX: RX DMA Transmission request + * + * @retval None + */ +void I2C_DisableDMA(I2C_T* i2c, I2C_DMA_REQ_T request) +{ + if (request == I2C_DMA_REQ_TX) + { + i2c->CTRL1_B.DMATXEN = BIT_RESET; + } + else + { + i2c->CTRL1_B.DMARXEN = BIT_RESET; + } +} + +/*! + * @brief Checks whether the specified I2C flag is set or not + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @param flag: Specifies the flag to check + * The parameter can be one of following values: + * @arg I2C_FLAG_TXBE: Transmit buffer data register empty flag + * @arg I2C_FLAG_TXINT: Transmit interrupt flag + * @arg I2C_FLAG_RXBNE: Read buffer data register not empty flag + * @arg I2C_FLAG_ADDR: Address Sent/Matched (master/slave) flag + * @arg I2C_FLAG_NACK: Not acknowledge received flag + * @arg I2C_FLAG_STOP: Stop detected flag + * @arg I2C_FLAG_TXCF: Transfer complete flag + * @arg I2C_FLAG_TCRF: Transfer complete reload flag + * @arg I2C_FLAG_BUSERR:Bus error flag + * @arg I2C_FLAG_ALF: Arbitration Loss flag + * @arg I2C_FLAG_OVR: Overrun/Underrun flag + * @arg I2C_FLAG_PECERR:PEC error flag + * @arg I2C_FLAG_TIMEOUT: Timeout or t_low detection flag + * @arg I2C_FLAG_ALERT: SMBus alert flag + * @arg I2C_FLAG_BUSY: Bus Busy Flag + * + * @retval Status of interrupt flag(SET or RESET) + */ +uint8_t I2C_ReadStatusFlag(I2C_T* i2c, I2C_FLAG_T flag) +{ + uint32_t status = 0; + + status = (uint32_t)(i2c->STS & (flag)); + + if (status == flag) + { + return SET; + } + + return RESET; +} + +/*! + * @brief Clear flags + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @param flag: Specifies the flag to clear + * The parameter can be combination of following values: + * @arg I2C_FLAG_ADDR: Address Sent/Matched (master/slave) flag + * @arg I2C_FLAG_NACK: Not acknowledge received flag + * @arg I2C_FLAG_STOP: Stop detected flag + * @arg I2C_FLAG_BUSERR:Bus error flag + * @arg I2C_FLAG_ALF: Arbitration Loss flag + * @arg I2C_FLAG_OVR: Overrun/Underrun flag + * @arg I2C_FLAG_PECERR:PEC error flag + * @arg I2C_FLAG_TIMEOUT: Timeout or t_low detection flag + * @arg I2C_FLAG_ALERT: SMBus alert flag + * + * @retval None + */ +void I2C_ClearStatusFlag(I2C_T* i2c, uint32_t flag) +{ + i2c->INTFCLR = (uint32_t)flag; +} + +/*! + * @brief Checks whether the specified interrupt has occurred or not + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @param flag: Specifies the I2C interrupt pending bit to check + * The parameter can be one of following values: + * @arg I2C_INT_FLAG_TXINT: Transmit interrupt flag + * @arg I2C_INT_FLAG_RXBNE: Read Buffer Data Register Not Empty interrupt flag + * @arg I2C_INT_FLAG_ADDR: Address Sent/Matched (master/slave) interrupt flag + * @arg I2C_INT_FLAG_NACK: Not acknowledge received interrupt flag + * @arg I2C_INT_FLAG_STOP: Stop detected interrupt flag + * @arg I2C_INT_FLAG_TXCF: Transfer complete interrupt flag + * @arg I2C_INT_FLAG_TCRF: Transfer Complete Reloadinterrupt flag + + * @arg I2C_INT_FLAG_BUSERR: Bus error interrupt flag + * @arg I2C_INT_FLAG_ALF: Arbitration Loss interrupt flag + * @arg I2C_INT_FLAG_OVR: Overrun/Underrun interrupt flag + * @arg I2C_INT_FLAG_PECERR: PEC error interrupt flag + * @arg I2C_INT_FLAG_TIMEOUT: Timeout or t_low detection interrupt flag + * @arg I2C_INT_FLAG_ALERT: SMBus alert interrupt flag + * + * @retval Status of interrupt flag(SET or RESET) + */ +uint8_t I2C_ReadIntFlag(I2C_T* i2c, I2C_INT_FLAG_T flag) +{ + uint32_t temp = 0; + uint32_t enable = 0; + + if (flag & ((uint32_t)0x000000C0)) + { + enable = (uint32_t)((BIT6) & (i2c->CTRL1)); + } + else if (flag & ((uint32_t)0x00003F00)) + { + enable = (uint32_t)((BIT7) & (i2c->CTRL1)); + } + else + { + enable = (uint32_t)((flag) & (i2c->CTRL1)); + } + + temp = i2c->STS; + + temp &= flag; + + if ((temp != 0) && enable) + { + return SET; + } + else + { + return RESET; + } +} + +/*! + * @brief Clears the specified interrupt pending bits + * + * @param i2c: Select I2C peripheral,it can be I2C1/I2C2. + * + * @param flag: Specifies the I2C interrupt pending bit to clear + * The parameter can be combination of following values: + * @arg I2C_INT_FLAG_ADDR: Address Sent/Matched (master/slave) flag + * @arg I2C_INT_FLAG_NACK: Not acknowledge received flag + * @arg I2C_INT_FLAG_STOP: Stop detected flag + * @arg I2C_INT_FLAG_BUSERR:Bus error flag + * @arg I2C_INT_FLAG_ALF: Arbitration Loss flag + * @arg I2C_INT_FLAG_OVR: Overrun/Underrun flag + * @arg I2C_INT_FLAG_PECERR:PEC error flag + * @arg I2C_INT_FLAG_TIMEOUT: Timeout or t_low detection flag + * @arg I2C_INT_FLAG_ALERT: SMBus alert flag + * + * @retval + */ + +void I2C_ClearIntFlag(I2C_T* i2c, uint32_t flag) +{ + i2c->INTFCLR = (uint32_t)flag; +} + +/**@} end of group I2C_Functions */ +/**@} end of group I2C_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_iwdt.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_iwdt.c new file mode 100644 index 0000000000..e5dc5a2821 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_iwdt.c @@ -0,0 +1,184 @@ +/*! + * @file apm32f0xx_iwdt.c + * + * @brief This file contains all the functions for the IWDT peripheral + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +#include "apm32f0xx_iwdt.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup IWDT_Driver + @{ +*/ + +/** @defgroup IWDT_Macros Macros + @{ +*/ + +/**@} end of group IWDT_Macros*/ + +/** @defgroup IWDT_Enumerations Enumerations + @{ +*/ + +/**@} end of group IWDT_Enumerations*/ + +/** @defgroup IWDT_Structures Structures + @{ +*/ + +/**@} end of group IWDT_Structures*/ + +/** @defgroup IWDT_Variables Variables + @{ +*/ + +/**@} end of group IWDT_Variables*/ + +/** @defgroup IWDT_Functions Functions + @{ +*/ + +/*! + * @brief Enable IWDT + * + * @param None + * + * @retval None + */ +void IWDT_Enable(void) +{ + IWDT->KEY = IWDT_KEY_ENABLE; +} + +/*! + * @brief Enable write access to Divider and Counter Reload registers + * + * @param None + * + * @retval None + */ +void IWDT_EnableWriteAccess(void) +{ + IWDT->KEY = IWDT_KEY_ACCESS; +} + +/*! + * @brief Disable write access to Divider and Counter Reload registers + * + * @param None + * + * @retval None + */ +void IWDT_DisableWriteAccess(void) +{ + IWDT->KEY = 0; +} + +/*! + * @brief Refresh IWDT + * + * @param None + * + * @retval None + */ +void IWDT_Refresh(void) +{ + IWDT->KEY = IWDT_KEY_REFRESH; +} + +/*! + * @brief Divider configuration + * + * @param div: Specifies the divider + * The parameter can be one of following values: + * @arg IWDT_DIV_4: Prescaler divider 4 + * @arg IWDT_DIV_8: Prescaler divider 8 + * @arg IWDT_DIV_16: Prescaler divider 16 + * @arg IWDT_DIV_32: Prescaler divider 32 + * @arg IWDT_DIV_64: Prescaler divider 64 + * @arg IWDT_DIV_128: Prescaler divider 128 + * @arg IWDT_DIV_256: Prescaler divider 256 + * + * @retval None + */ +void IWDT_ConfigDivider(IWDT_DIV_T div) +{ + IWDT->PSC = (uint32_t)div; +} + +/*! + * @brief Set counter reload value + * + * @param reload: Specifies the reload value + * + * @retval None + */ +void IWDT_ConfigReload(uint16_t reload) +{ + IWDT->CNTRLD = (uint32_t)reload; +} + +/*! + * @brief Set counter reload value + * + * @param reload: Specifies the reload value + * + * @retval None + */ +void IWDT_ConfigWindowValue(uint16_t windowValue) +{ + IWDT->WIN = (uint32_t)windowValue; +} +/*! + * @brief Read the specified IWDT flag + * + * @param flag: Specifies the flag to read + * The parameter can be one of following values: + * @arg IWDT_FLAG_DIVU: Watchdog prescaler value update + * @arg IWDT_FLAG_CNTU: Watchdog counter reload value update + * @arg IWDT_FLAG_WINU: Watchdog counter window value update + * + * @retval status of IWDT_FLAG (SET or RESET) + */ +uint8_t IWDT_ReadStatusFlag(uint8_t flag) +{ + uint8_t bitStatus = RESET; + + if ((IWDT->STS & flag) != (uint32_t)RESET) + { + bitStatus = SET; + } + else + { + bitStatus = RESET; + } + + return bitStatus; +} + +/**@} end of group IWDT_Functions*/ +/**@} end of group IWDT_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver*/ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_misc.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_misc.c new file mode 100644 index 0000000000..a79c13b679 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_misc.c @@ -0,0 +1,190 @@ +/*! + * @file apm32f0xx_misc.c + * + * @brief This file provides all the miscellaneous firmware functions (add-on to CMSIS functions). + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "apm32f0xx_misc.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup MISC_Driver + @{ +*/ + +/** @defgroup MISC_Macros Macros + @{ +*/ + +/**@} end of group MISC_Macros*/ + +/** @defgroup MISC_Enumerations Enumerations + @{ +*/ + +/**@} end of group MISC_Enumerations*/ + +/** @defgroup MISC_Structures Structures + @{ +*/ + +/**@} end of group MISC_Structures*/ + +/** @defgroup MISC_Variables Variables + @{ +*/ + +/**@} end of group MISC_Variables*/ + +/** @defgroup MISC_Functions Functions + @{ +*/ + +/*! + * @brief Enable NVIC request + * + * @param irq: The NVIC interrupt request, detailed in IRQn_Type + * + * @param priority: Specifies the priority needed to set + * + * @retval None + */ +void NVIC_EnableIRQRequest(IRQn_Type irq, uint8_t priority) +{ + NVIC_SetPriority(irq, priority); + + NVIC_EnableIRQ(irq); +} + +/*! + * @brief Disable NVIC request + * + * @param irq: The NVIC interrupt request, detailed in IRQn_Type + * + * @retval None + */ +void NVIC_DisableIRQRequest(IRQn_Type irq) +{ + NVIC_DisableIRQ(irq); +} + +/** + * @brief Enables the system to enter low power mode. + * + * @param lowPowerMode: Specifies the system to enter low power mode. + * This parameter can be one of the following values: + * @arg NVIC_LOWPOER_SEVONPEND: Low Power SEV on Pend. + * @arg NVIC_LOWPOER_SLEEPDEEP: Low Power DEEPSLEEP request. + * @arg NVIC_LOWPOER_SLEEPONEXIT: Low Power Sleep on Exit. + * + * @retval None + */ +void NVIC_EnableSystemLowPower(uint8_t lowPowerMode) +{ + SCB->SCR |= lowPowerMode; +} + +/** + * @brief Disables the system to enter low power mode. + * + * @param lowPowerMode: Specifies the system to enter low power mode. + * This parameter can be one of the following values: + * @arg NVIC_LOWPOER_SEVONPEND: Low Power SEV on Pend. + * @arg NVIC_LOWPOER_SLEEPDEEP: Low Power DEEPSLEEP request. + * @arg NVIC_LOWPOER_SLEEPONEXIT: Low Power Sleep on Exit. + * + * @retval None + */ +void NVIC_DisableSystemLowPower(uint8_t lowPowerMode) +{ + SCB->SCR &= (uint32_t)(~(uint32_t)lowPowerMode); +} + +/** + * @brief Configures the SysTick clock source. + * + * @param sysTickCLKSource: 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. + * + * @retval None + */ +void SysTick_ConfigCLKSource(uint32_t sysTickCLKSource) +{ + if (sysTickCLKSource == SysTick_CLKSource_HCLK) + { + SysTick->CTRL |= SysTick_CLKSource_HCLK; + } + else + { + SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8; + } +} + +/*! + * @brief Enter Wait Mode + * + * @param None + * + * @retval None + */ +void PMU_EnterWaitMode(void) +{ + SCB->SCR &= (uint32_t)(~(uint32_t)NVIC_LOWPOER_SLEEPDEEP); + __WFI(); +} + +/*! + * @brief Enter Stop Mode with WFI instruction + * + * @param None + * + * @retval None + */ +void PMU_EnterHaltModeWFI(void) +{ + SCB->SCR |= NVIC_LOWPOER_SLEEPDEEP; + __DSB(); + __WFI(); +} + +/*! + * @brief Enter Stop Mode with WFE instruction + * + * @param None + * + * @retval None + */ +void PMU_EnterHaltModeWFE(void) +{ + SCB->SCR |= NVIC_LOWPOER_SLEEPDEEP; + __DSB(); + __WFE(); +} + +/**@} end of group MISC_Functions */ +/**@} end of group MISC_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_ob.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_ob.c new file mode 100644 index 0000000000..fc7ace7881 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_ob.c @@ -0,0 +1,152 @@ +/*! + * @file apm32f0xx_ob.c + * + * @brief This file contains all the functions for the OB peripheral + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +#include "apm32f0xx_ob.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup OB_Driver + @{ +*/ + +/** @defgroup OB_Macros Macros + @{ +*/ + +/**@} end of group OB_Macros*/ + +/** @defgroup OB_Enumerations Enumerations + @{ +*/ + +/**@} end of group OB_Enumerations*/ + +/** @defgroup OB_Structures Structures + @{ +*/ + +/**@} end of group OB_Structures*/ + +/** @defgroup OB_Variables Variables + @{ +*/ + +/**@} end of group OB_Variables*/ + +/** @defgroup OB_Functions Functions + @{ +*/ + +/*! + * @brief Read Flash Protection Level + * + * @param readProtection: Specifies the read protection level. + * The parameter can be one of following values: + * @arg OB_READ_PRO_LEVEL0: No protection + * @arg OB_READ_PRO_LEVEL1: Read protection of the memory + * @retval None + */ +void OB_ReadProtectionOptionByte(OB_READ_PRO_T readProtection) +{ + OB->READPORT_B.READPROT = readProtection; +} + +/*! + * @brief Option Bytes Watchdog + * + * @param wdt: Select Watchdog SW/HW + * + * @retval None + */ +void OB_OptionBytesWatchdog(OB_WDT_T wdt) +{ + OB->USER_B.WDTSEL = wdt; +} + +/*! + * @brief Option Bytes nRST STOP + * + * @param stop: Select nRST STOP RST/SET + * + * @retval None + */ +void OB_OptionBytesStop(OB_STOP_T stop) +{ + OB->USER_B.RSTSTOP = stop; +} + +/*! + * @brief Option Bytes nRST STDBY + * + * @param standby: Select nRST STDBY RST/SET + * + * @retval None + */ +void OB_OptionBytesStandby(OB_STANDBY_T standby) +{ + OB->USER_B.RSTSTDBY = standby; +} + +/*! + * @brief Option Bytes nBOOT1 + * + * @param boot: Select nRST BOOT1 RST/SET + * + * @retval None + */ +void OB_OptionBytesBoot1(OB_BOOT1_T boot) +{ + OB->USER_B.BOT1 = boot; +} + +/*! + * @brief Option Bytes VDDA_Analog_Monitoring + * + * @param vdda: Select VDDA ANALOG OFF/ON + * + * @retval None + */ +void OB_OptionBytesVddaAnalog(OB_VDDA_T vdda) +{ + OB->USER_B.VDDAMON = vdda; +} + +/*! + * @brief Option Bytes RAM PARITY CHECK + * + * @param rpc: Select RAM PARITY OFF/ON + * + * @retval None + */ +void OB_OptionBytesRamParity(OB_RAM_PARITY_CHECK_T ramParityCheck) +{ + OB->USER_B.RPC = ramParityCheck; +} + +/**@} end of group OB_Functions */ +/**@} end of group OB_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_pmu.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_pmu.c new file mode 100644 index 0000000000..7cbfa4ad5c --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_pmu.c @@ -0,0 +1,335 @@ +/*! + * @file apm32f0xx_pmu.c + * + * @brief This file contains all the functions for the PMU peripheral + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +#include "apm32f0xx_pmu.h" +#include "apm32f0xx_rcm.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup PMU_Driver PMU Driver + @{ +*/ + +/** @defgroup PMU_Macros Macros + @{ +*/ + +/**@} end of group PMU_Macros*/ + +/** @defgroup PMU_Enumerations Enumerations + @{ +*/ + +/**@} end of group PMU_Enumerations*/ + +/** @defgroup PMU_Structures Structures + @{ +*/ + +/**@} end of group PMU_Structures*/ + +/** @defgroup PMU_Variables Variables + @{ +*/ + +/**@} end of group PMU_Variables*/ + +/** @defgroup PMU_Functions Functions + @{ +*/ + +/*! + * @brief Resets the PWR peripheral registers to their default reset values + * + * @param None + * + * @retval None + */ +void PMU_Reset(void) +{ + RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU); + RCM_DisableAPB1PeriphClock(RCM_APB1_PERIPH_PMU); +} + +/*! + * @brief Enables access to the Backup domain registers + * + * @param None + * + * @retval None + */ +void PMU_EnableBackupAccess(void) +{ + PMU->CTRL_B.BPWEN = BIT_SET; +} + +/*! + * @brief Disables access to the Backup domain registers + * + * @param None + * + * @retval None + */ +void PMU_DisableBackupAccess(void) +{ + PMU->CTRL_B.BPWEN = BIT_RESET; +} + +/*! + * @brief Configures the PMU PVD Level + * + * @param level: specifies the PVD Level + * This parameter can be one of the following values + * @arg PMU_PVDLEVEL_0 + * @arg PMU_PVDLEVEL_1 + * @arg PMU_PVDLEVEL_2 + * @arg PMU_PVDLEVEL_3 + * @arg PMU_PVDLEVEL_4 + * @arg PMU_PVDLEVEL_5 + * @arg PMU_PVDLEVEL_6 + * @arg PMU_PVDLEVEL_7 + * + * @retval None + * + * @note It's not for APM32F030 devices + */ +void PMU_ConfigPVDLevel(PMU_PVDLEVEL_T level) +{ + PMU->CTRL_B.PLSEL = level; +} + +/*! + * @brief Enables Power voltage detector + * + * @param None + * + * @retval None + * + * @note It's not for APM32F030 devices + */ +void PMU_EnablePVD(void) +{ + PMU->CTRL_B.PVDEN = BIT_SET; +} +/*! + * @brief Disables Power voltage detector + * + * @param None + * + * @retval None + * + * @note It's not for APM32F030 devices + */ +void PMU_DisablePVD(void) +{ + PMU->CTRL_B.PVDEN = BIT_RESET; +} + +/*! + * @brief Enables the WakeUp Pin functionality + * + * @param pin: specifies the WakeUpPin + * This parameter can be one of the following values + * @arg PMU_WAKEUPPIN_1 + * @arg PMU_WAKEUPPIN_2 + * @arg PMU_WAKEUPPIN_3 It's Only for APM32F072/091 devices + * @arg PMU_WAKEUPPIN_4 It's Only for APM32F072/091 devices + * @arg PMU_WAKEUPPIN_5 It's Only for APM32F072/091 devices + * @arg PMU_WAKEUPPIN_6 It's Only for APM32F072/091 devices + * @arg PMU_WAKEUPPIN_7 It's Only for APM32F072/091 devices + * @arg PMU_WAKEUPPIN_8 It's Only for APM32F072/091 devices + * + * @retval None + */ +void PMU_EnableWakeUpPin(PMU_WAKEUPPIN_T pin) +{ + PMU->CSTS |= pin; +} + +/*! + * @brief DIsable the WakeUp Pin functionality + * + * @param pin: specifies the WakeUpPin + * This parameter can be one of the following values + * @arg PMU_WAKEUPPIN_1 + * @arg PMU_WAKEUPPIN_2 + * @arg PMU_WAKEUPPIN_3 It's Only for APM32F072/091 devices + * @arg PMU_WAKEUPPIN_4 It's Only for APM32F072/091 devices + * @arg PMU_WAKEUPPIN_5 It's Only for APM32F072/091 devices + * @arg PMU_WAKEUPPIN_6 It's Only for APM32F072/091 devices + * @arg PMU_WAKEUPPIN_7 It's Only for APM32F072/091 devices + * @arg PMU_WAKEUPPIN_8 It's Only for APM32F072/091 devices + * + * @retval None + */ +void PMU_DisableWakeUpPin(PMU_WAKEUPPIN_T pin) +{ + PMU->CSTS &= ~pin; +} + +/*! + * @brief Enters Sleep mode + * + * @param entry :specifies if SLEEP mode in entered with WFI or WFE instruction + * This parameter can be one of the following values: + * @arg PMU_SLEEPENTRY_WFI: enter SLEEP mode with WFI instruction + * @arg PMU_SLEEPENTRY_WFE: enter SLEEP mode with WFE instruction + * + * @retval None + */ +void PMU_EnterSleepMode(PMU_SLEEPENTRY_T entry) +{ + SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); + + if (entry == PMU_SLEEPENTRY_WFI) + { + __WFI(); + } + else + { + __SEV(); + __WFE(); + __WFE(); + } +} + +/*! + * @brief Enters STOP mode + * + * @param regulator: specifies the regulator state in STOP mode + * This parameter can be one of the following values: + * @arg PMU_REGULATOR_ON: STOP mode with regulator ON + * @arg PMU_REGULATOR_LowPower: STOP mode with regulator in low power mode + * + * @param entry: specifies if STOP mode in entered with WFI or WFE instruction + * This parameter can be one of the following values: + * @arg PMU_STOPENTRY_WFI: enter STOP mode with WFI instruction + * @arg PMU_STOPENTRY_WFE: enter STOP mode with WFE instruction + * @arg PMU_STOPENTRY_SLEEPONEXIT: enter STOP mode with SLEEPONEXIT instruction + * + * @retval None + */ +void PMU_EnterSTOPMode(PMU_REGULATOR_T regulator, PMU_STOPENTRY_T entry) +{ + PMU->CTRL_B.PDDSCFG = BIT_RESET; + + PMU->CTRL_B.LPDSCFG = regulator; + + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + + switch (entry) + { + case PMU_STOPENTRY_WFI: + + __WFI(); + SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); + break; + + case PMU_STOPENTRY_WFE: + __WFE(); + SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); + break; + + case PMU_STOPENTRY_SLEEPONEXIT: + SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk; + break; + + default: + break; + } +} + +/*! + * @brief Enters STANDBY mode + * + * @param None + * + * @retval None + */ +void PMU_EnterSTANDBYMode(void) +{ + PMU->CTRL_B.PDDSCFG = BIT_SET; + + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + + __WFI(); +} + +/*! + * @brief Checks whether the specified PMU flag is set or not + * + * @param flag: specifies the flag to check + * This parameter can be one of the following values: + * @arg PMU_FLAG_WUPF: Wake Up flag + * @arg PMU_FLAG_STDBYF: StandBy flag + * @arg PMU_FLAG_PVDOF: PVD output flag (Not for APM32F030) + * @arg PMU_FLAG_VREFINTF: VREFINT flag + * + * @retval The new state of PMU_FLAG (SET or RESET) + */ +uint8_t PMU_ReadStatusFlag(PMU_FLAG_T flag) +{ + uint8_t bit; + + if ((PMU->CSTS & flag) != (uint32_t)RESET) + { + bit = SET; + } + else + { + bit = RESET; + } + + /** Return the flag status */ + return bit; +} + +/*! + * @brief Clears the PWR's pending flags + * + * @param flag: specifies the flag to clear + * This parameter can be one of the following values: + * @arg PMU_FLAG_WUPF: Wake Up flag + * @arg PMU_FLAG_STDBYF: StandBy flag + * + * @retval None + */ +void PMU_ClearStatusFlag(uint8_t flag) +{ + if (flag == PMU_FLAG_WUPF) + { + PMU->CTRL_B.WUFLGCLR = BIT_SET; + } + else if (flag == PMU_FLAG_STDBYF) + { + PMU->CTRL_B.SBFLGCLR = BIT_SET; + } +} + +/**@} end of group PMU_Functions*/ +/**@} end of group PMU_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver*/ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_rcm.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_rcm.c new file mode 100644 index 0000000000..9214eb978a --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_rcm.c @@ -0,0 +1,1520 @@ +/*! + * @file apm32f0xx_rcm.h + * + * @brief This file provides all the RCM firmware functions + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +#include "apm32f0xx_rcm.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup RCM_Driver RCM Driver + @{ +*/ + +/** @defgroup RCM_Macros Macros + @{ +*/ + +/**@} end of group RCM_Macros*/ + +/** @defgroup RCM_Enumerations Enumerations + @{ +*/ + +/**@} end of group RCM_Enumerations*/ + +/** @defgroup RCM_Structures Structures + @{ +*/ + +/**@} end of group RCM_Structures*/ + +/** @defgroup RCM_Variables Variables + @{ +*/ + +/**@} end of group RCM_Variables*/ + +/** @defgroup RCM_Functions Functions + @{ +*/ + +/*! + * @brief Resets the clock configuration + * + * @param None + * + * @retval None + */ +void RCM_Reset(void) +{ + /** Set HSIEN bit */ + RCM->CTRL1_B.HSIEN = BIT_SET; + RCM->CFG1 &= (uint32_t)0x08FFB80C; + RCM->CTRL1 &= (uint32_t)0xFEF6FFFF; + RCM->CTRL1_B.HSEBCFG = BIT_RESET; + RCM->CFG1 &= (uint32_t)0xFFC0FFFF; + RCM->CFG2 &= (uint32_t)0xFFFFFFF0; + RCM->CFG3 &= (uint32_t)0xFFF0FEAC; + RCM->CTRL2_B.HSI14EN = BIT_RESET; + + /** Disable all interrupts and clear pending bits */ + RCM->INT = 0x00FF0000; +} + +/*! + * @brief Configures HSE + * + * @param state: state of the HSE + * This parameter can be one of the following values: + * @arg RCM_HSE_OPEN: turn ON the HSE oscillator + * @arg RCM_HSE_BYPASS: HSE oscillator bypassed with external clock + * + * @retval None + * + * @note HSE can not be stopped if it is used directly or through the PLL as system clock + */ +void RCM_ConfigHSE(RCM_HSE_T state) +{ + RCM->CTRL1_B.HSEEN = BIT_RESET; + + RCM->CTRL1_B.HSEBCFG = BIT_RESET; + + if (state == RCM_HSE_OPEN) + { + RCM->CTRL1_B.HSEEN = BIT_SET; + } + else if (state == RCM_HSE_BYPASS) + { + RCM->CTRL1_B.HSEBCFG = BIT_SET; + RCM->CTRL1_B.HSEEN = BIT_SET; + } +} + +/*! + * @brief Waits for HSE be ready + * + * @param None + * + * @retval SUCCESS HSE oscillator is stable and ready to use + * ERROR HSE oscillator not yet ready + */ +uint8_t RCM_WaitHSEReady(void) +{ + __IO uint32_t cnt; + + for (cnt = 0; cnt < HSE_STARTUP_TIMEOUT; cnt++) + { + if (RCM->CTRL1_B.HSERDYFLG == BIT_SET) + { + return SUCCESS; + } + } + + return ERROR; +} + +/*! + * @brief Set HSI trimming value + * +* @param HSITrim: HSI trimming value + * This parameter must be a number between 0 and 0x1F. + * + * @retval None + */ +void RCM_SetHSITrim(uint8_t HSITrim) +{ + RCM->CTRL1_B.HSITRM = HSITrim; +} + +/*! + * @brief Enable HSI + * + * @param None + * + * @retval None + * + * @note HSI can not be stopped if it is used directly or through the PLL as system clock + */ +void RCM_EnableHSI(void) +{ + RCM->CTRL1_B.HSIEN = BIT_SET; +} + +/*! + * @brief Disable HSI + * + * @param None + * + * @retval None + * + * @note HSI can not be stopped if it is used directly or through the PLL as system clock + */ +void RCM_DisableHSI(void) +{ + RCM->CTRL1_B.HSIEN = BIT_RESET; +} + +/*! + * @brief Set HSI14 trimming value + * + * @param HSI14TRM: HSI trimming value + * This parameter must be a number between 0 and 0x1F. + * + * @retval None + */ +void RCM_SetHSI14Trim(uint8_t HSI14Trim) +{ + RCM->CTRL2_B.HSI14TRM = HSI14Trim; +} + +/*! + * @brief Enable HSI14 + * + * @param None + * + * @retval None + * + * @note + */ +void RCM_EnableHSI14(void) +{ + RCM->CTRL2_B.HSI14EN = BIT_SET; +} + +/*! + * @brief Disable HSI14 + * + * @param None + * + * @retval None + * + * @note + */ +void RCM_DisableHSI14(void) +{ + RCM->CTRL2_B.HSI14EN = BIT_RESET; +} + +/*! + * @brief Enable HSI14 ADC + * + * @param None + * + * @retval None + * + * @note + */ +void RCM_EnableHSI14ADC(void) +{ + RCM->CTRL2_B.HSI14TO = BIT_SET; +} + +/*! + * @brief Disable HSI14 ADC + * + * @param None + * + * @retval None + * + * @note + */ +void RCM_DisableHSI14ADC(void) +{ + RCM->CTRL2_B.HSI14TO = BIT_RESET; +} + +/*! + * @brief Configures LSE + * + * @param state: state of the LSE + * This parameter can be one of the following values: + * @arg RCM_LSE_OPEN: turn ON the HSE oscillator + * @arg RCM_LSE_BYPASS: HSE oscillator bypassed with external clock + * + * @retval None + * + * @note LSE can not be stopped if it is used directly or through the PLL as system clock + */ +void RCM_ConfigLSE(RCM_LSE_T state) +{ + RCM->BDCTRL_B.LSEEN = BIT_RESET; + + RCM->BDCTRL_B.LSEBCFG = BIT_RESET; + + if (state == RCM_LSE_OPEN) + { + RCM->BDCTRL_B.LSEEN = BIT_SET; + } + else if (state == RCM_LSE_BYPASS) + { + RCM->BDCTRL_B.LSEBCFG = BIT_SET; + RCM->BDCTRL_B.LSEEN = BIT_SET; + } +} + +/*! + * @brief Configures LSE drive capability + * + * @param state: State of the LSE Drive + * This parameter can be one of the following values: + * @arg RCM_LSE_DRIVE_Low: LSE oscillator low drive capability. + * @arg RCM_LSE_DRIVE_MediumLow: LSE oscillator medium low drive capability. + * @arg RCM_LSE_DRIVE_MediumHigh: LSE oscillator medium high drive capability. + * @arg RCM_LSE_DRIVE_High: LSE oscillator high drive capability. + * + * @retval None + * + * @note LSE can not be stopped if it is used directly or through the PLL as system clock + */ +void RCM_ConfigDriveLSE(RCM_LSE_DRIVE_T state) +{ + RCM->BDCTRL_B.LSEDRVCFG = state; +} + +/*! + * @brief Enable LSI + * + * @param None + * + * @retval None + * + * @note LSI can not be stopped if the IWDT is running + */ +void RCM_EnableLSI(void) +{ + RCM->CSTS_B.LSIEN = BIT_SET; +} + +/*! + * @brief Disable LSI + * + * @param None + * + * @retval None + * + * @note LSI can not be stopped if the IWDT is running + */ +void RCM_DisableLSI(void) +{ + RCM->CSTS_B.LSIEN = BIT_RESET; +} + +/*! + * @brief Configures the PLL clock source and multiplication factor + * + * @param pllSelect: PLL entry clock source select + * This parameter can be one of the following values: + * @arg RCM_PLL_SEL_HSI_DIV2: HSI clock divided by 2 selected as PLL clock source + * @arg RCM_PLL_SEL_HSE: HSE/CLKDIV1 selected as PLL clock entry + * @arg RCM_PLL_SEL_HSI48: HSI48 oscillator clock selected as PLL clock source, It's only for 072 and 091 devices + * @arg RCM_PLL_SEL_HSI: HSI clock selected as PLL clock entry, It's only for 072 and 091 devices + * + * @param pllMf: PLL multiplication factor + * This parameter can be RCM_PLLMF_x where x:[2,16] + * + * @retval None + * + * @note + */ +void RCM_ConfigPLL(RCM_PLL_SEL_T pllSelect, RCM_PLLMF_T pllMf) +{ + RCM->CFG1_B.PLLMULCFG = pllMf; + RCM->CFG1_B.PLLSRCSEL = pllSelect; +} + +/*! + * @brief Enables PLL + * + * @param None + * + * @retval None + * + * @note The PLL can not be disabled if it is used as system clock + */ +void RCM_EnablePLL(void) +{ + RCM->CTRL1_B.PLLEN = BIT_SET; +} + +/*! + * @brief Disable PLL + * + * @param None + * + * @retval None + * + * @note The PLL can not be disabled if it is used as system clock + */ +void RCM_DisablePLL(void) +{ + RCM->CTRL1_B.PLLEN = BIT_RESET; +} + +/*! + * @brief Enables HSI48 + * + * @param None + * + * @retval None + * + * @note It's only for APM32F072 and APM32F091 devices + */ +void RCM_EnableHSI48(void) +{ + RCM->CTRL2_B.HSI48EN = BIT_SET; +} + +/*! + * @brief Enables HSI48 + * + * @param None + * + * @retval None + * + * @note It's only for APM32F072 and APM32F091 devices + */ +void RCM_DisableHSI48(void) +{ + RCM->CTRL2_B.HSI48EN = BIT_RESET; +} + +/*! + * @brief Read HSI48 Calibration Value + * + * @param None + * + * @retval Return of HSI48 Value + */ +uint32_t RCM_ReadHSI48CalibrationValue(void) +{ + uint32_t calValue; + + calValue = RCM->CTRL2_B.HSI48CAL; + + return calValue; +} +/*! + * @brief Configures the CLK division factor + * + * @param state: specifies the PLLDIVCFG clock division factor. + * This parameter can be RCM_CLK_Divx where x:[1,16] + * + * @retval None + * + * @note This function must be used only when the PLL is disabled + */ +void RCM_ConfigCLKDIV(RCM_CLK_DIV_T state) +{ + RCM->CFG2_B.PLLDIVCFG = state; +} + +/*! + * @brief Enable Clock Security System + * + * @param None + * + * @retval None + */ +void RCM_EnableCCS(void) +{ + RCM->CTRL1_B.CSSEN = BIT_SET; +} + +/*! + * @brief Disable Clock Security System + * + * @param None + * + * @retval None + */ +void RCM_DisableCCS(void) +{ + RCM->CTRL1_B.CSSEN = BIT_RESET; +} + +#if defined (APM32F030) || defined (APM32F051) +/*! + * @brief Selects clock ouput source + * + * @param cocClock: specifies the clock source to output + * This parameter can be one of the following values: + * @arg RCM_COC_NO_CLOCK: No clock selected. + * @arg RCM_COC_HSI14: HSI14 oscillator clock selected. + * @arg RCM_COC_LSI: LSI oscillator clock selected. + * @arg RCM_COC_LSE: LSE oscillator clock selected. + * @arg RCM_COC_SYSCLK: System clock selected. + * @arg RCM_COC_HSI: HSI oscillator clock selected. + * @arg RCM_COC_HSE: HSE oscillator clock selected. + * @arg RCM_COC_PLLCLK_DIV_2: PLL clock divided by 2 selected. + * + * @retval None + */ +void RCM_ConfigCOC(RCM_COCCLK_T cocClock) +{ + RCM->CFG1_B.MCOSEL = cocClock; +} +#else + +/*! + * @brief Selects clock ouput source + * + * @param cocClock: specifies the clock source to output + * This parameter can be one of the following values: + * @arg RCM_COC_NO_CLOCK: No clock selected. + * @arg RCM_COC_HSI14: HSI14 oscillator clock selected. + * @arg RCM_COC_LSI: LSI oscillator clock selected. + * @arg RCM_COC_LSE: LSE oscillator clock selected. + * @arg RCM_COC_SYSCLK: System clock selected. + * @arg RCM_COC_HSI: HSI oscillator clock selected. + * @arg RCM_COC_HSE: HSE oscillator clock selected. + * @arg RCM_COC_PLLCLK_DIV_2: PLL clock divided by 2 selected. + * @arg RCM_COC_PLLCLK: PLL clock divided selected. + * @arg RCM_COC_HSI48: HSI48 oscillator clock selected. + * + * @param divided: specifies the prescaler on COC pin. + * This parameter can only be the following value: + * @arg RCM_COC_DIV_1: MCOSEL clock is divided by 1. + * @arg RCM_COC_DIV_2: MCOSEL clock is divided by 2. + * @arg RCM_COC_DIV_4: MCOSEL clock is divided by 4. + * @arg RCM_COC_DIV_8: MCOSEL clock is divided by 8. + * @arg RCM_COC_DIV_16: MCOSEL clock is divided by 16. + * @arg RCM_COC_DIV_32: MCOSEL clock is divided by 32. + * @arg RCM_COC_DIV_64: MCOSEL clock is divided by 64. + * @arg RCM_COC_DIV_128: MCOSEL clock is divided by 128. + * + * @retval None + */ +void RCM_ConfigCOC(RCM_COCCLK_T cocClock, RCM_COCPRE_T divided) +{ + RCM->CFG1_B.MCOPSC = divided; + + if (cocClock != RCM_COC_PLLCLK) + { + RCM->CFG1_B.MCOPLLPSC = BIT_RESET; + RCM->CFG1_B.MCOSEL = cocClock; + } + else + { + RCM->CFG1_B.MCOPLLPSC = BIT_SET; + RCM->CFG1_B.MCOSEL = 0x07; + } +} +#endif /* APM32F072 */ + +/*! + * @brief Configures the system clock + * + * @param sysClkSelect: specifies the clock source used as system clock + * This parameter can be one of the following values: + * @arg RCM_SYSCLK_SEL_HSI: HSI selected as system clock source + * @arg RCM_SYSCLK_SEL_HSE: HSE selected as system clock source + * @arg RCM_SYSCLK_SEL_PLL: PLL selected as system clock source + * @arg RCM_SYSCLK_SEL_HSI48: HSI48 selected as system clock source,It's only for 072 devices + * + * @retval None + */ +void RCM_ConfigSYSCLK(RCM_SYSCLK_SEL_T sysClkSelect) +{ + RCM->CFG1_B.SCLKSEL = sysClkSelect; +} + +/*! + * @brief returns the clock source used as system clock + * + * @param None + * + * @retval The clock source used as system clock + */ +RCM_SYSCLK_SEL_T RCM_ReadSYSCLKSource(void) +{ + RCM_SYSCLK_SEL_T sysClock; + + sysClock = (RCM_SYSCLK_SEL_T)RCM->CFG1_B.SCLKSWSTS; + + return sysClock; +} + +/*! + * @brief Configures the AHB clock + * + * @param AHBDiv: AHB divider number. This clock is derived from the system clock (SYSCLK) + * This parameter can be one of the following values: + * @arg RCM_SYSCLK_DIV_1: AHB clock = SYSCLK + * @arg RCM_SYSCLK_DIV_2: AHB clock = SYSCLK/2 + * @arg RCM_SYSCLK_DIV_4: AHB clock = SYSCLK/4 + * @arg RCM_SYSCLK_DIV_8: AHB clock = SYSCLK/8 + * @arg RCM_SYSCLK_DIV_16: AHB clock = SYSCLK/16 + * @arg RCM_SYSCLK_DIV_64: AHB clock = SYSCLK/64 + * @arg RCM_SYSCLK_DIV_128: AHB clock = SYSCLK/128 + * @arg RCM_SYSCLK_DIV_256: AHB clock = SYSCLK/256 + * @arg RCM_SYSCLK_DIV_512: AHB clock = SYSCLK/512 + * + * @retval None + */ +void RCM_ConfigAHB(RCM_AHBDIV_T AHBDiv) +{ + RCM->CFG1_B.AHBPSC = AHBDiv; +} + +/*! + * @brief Configures the APB clock + * + * @param APBDiv: defines the APB clock divider. This clock is derived from the AHB clock (HCLK) + * This parameter can be one of the following values: + * @arg RCM_HCLK_DIV_1: APB clock = HCLK + * @arg RCM_HCLK_DIV_2: APB clock = HCLK/2 + * @arg RCM_HCLK_DIV_4: APB clock = HCLK/4 + * @arg RCM_HCLK_DIV_8: APB clock = HCLK/8 + * @arg RCM_HCLK_DIV_16: APB clock = HCLK/16 + * + * @retval None + */ +void RCM_ConfigAPB(RCM_APBDIV_T APBDiv) +{ + RCM->CFG1_B.APB1PSC = APBDiv; +} + +/*! + * @brief Configures the CEC clock + * + * @param CECClk: defines the CEC clock divider. This clock is derived + * from the HSI/244 (32768Hz) clock or LSI clock + * This parameter can be one of the following values: + * @arg RCM_CECCLK_HSI_DIV_224: CEC clock = HSI/244 (32768Hz) + * @arg RCM_CECCLK_LSI_DIV: CEC clock = LSI + * + * @retval None + */ +void RCM_ConfigCECCLK(RCM_CECCLK_T CECClk) +{ + RCM->CFG3_B.CECSEL = CECClk; +} + +/*! + * @brief Configures the I2C clock + * + * @param I2CClk: defines the I2C1 clock source. This clock is derived + * from the HSI or System clock. + * This parameter can be one of the following values: + * @arg RCM_I2C1CLK_HSI: I2C1 clock = HSI + * @arg RCM_I2C1CLK_SYSCLK: I2C1 clock = System Clock + * + * @retval None + */ +void RCM_ConfigI2CCLK(RCM_I2CCLK_T I2CClk) +{ + RCM->CFG3_B.I2C1SEL = I2CClk; +} + +/*! + * @brief Configures the USART clock (USARTCLK) + * + * @param USARTClk: defines the USART clock source. This clock is derived + * from the HSI or System clock. + * This parameter can be one of the following values: + * @arg RCM_USART1CLK_PCLK: USART1 clock = APB Clock (PCLK) + * @arg RCM_USART1CLK_SYSCLK: USART1 clock = System Clock + * @arg RCM_USART1CLK_LSE: USART1 clock = LSE Clock + * @arg RCM_USART1CLK_HSI: USART1 clock = HSI Clock + * Under it's only for APM32F072 and APM32F091 devices + * @arg RCM_USART2CLK_PCLK: USART2 clock = APB Clock (PCLK) + * @arg RCM_USART2CLK_SYSCLK: USART2 clock = System Clock + * @arg RCM_USART2CLK_LSE: USART2 clock = LSE Clock + * @arg RCM_USART2CLK_HSI: USART2 clock = HSI Clock + * Under it's only for APM32F091 devices + * @arg RCM_USART3CLK_PCLK: USART3 clock = APB Clock (PCLK) + * @arg RCM_USART3CLK_SYSCLK: USART3 clock = System Clock + * @arg RCM_USART3CLK_LSE: USART3 clock = LSE Clock + * @arg RCM_USART3CLK_HSI: USART3 clock = HSI Clock + * + * @retval None + */ +void RCM_ConfigUSARTCLK(RCM_USARTCLK_T USARTClk) +{ + if (USARTClk >> 16 == 1) + { + RCM->CFG3_B.USART1SEL = (uint32_t)(USARTClk & 0x00000003); + } + else if (USARTClk >> 17 == 1) + { + RCM->CFG3_B.USART2SEL = (uint32_t)(USARTClk & 0x00000003); + } + else + { + RCM->CFG3_B.USART3SEL = (uint32_t)(USARTClk & 0x00000003); + } +} + +/*! + * @brief Configures the USB clock (USBCLK) + * + * @param USBClk: defines the USB clock source. This clock is derived + * from the HSI48 or System clock. + * This parameter can be one of the following values: + * @arg RCM_USBCLK_HSI48: USB clock = HSI48 + * @arg RCM_USBCLK_PLLCLK: USB clock = PLL Clock + * + * @retval None + * + * @note It's only for APM32F072 devices + */ +void RCM_ConfigUSBCLK(RCM_USBCLK_T USBClk) +{ + RCM->CFG3_B.USBDSEL = USBClk; +} + +/*! + * @brief Read frequency of SYSCLK + * + * @param None + * + * @retval Return frequency of SYSCLK + */ +uint32_t RCM_ReadSYSCLKFreq(void) +{ + uint32_t sysClock, pllMull, plldiv, pllSource; + + sysClock = RCM->CFG1_B.SCLKSEL; + + switch (sysClock) + { + case RCM_SYSCLK_SEL_HSI: + sysClock = HSI_VALUE; + break; + + case RCM_SYSCLK_SEL_HSE: + sysClock = HSE_VALUE; + break; + + case RCM_SYSCLK_SEL_PLL: + pllMull = RCM->CFG1_B.PLLMULCFG + 2; + pllSource = RCM->CFG1_B.PLLSRCSEL; + plldiv = RCM->CFG2_B.PLLDIVCFG + 1; + + if (pllSource == 0x00) + { + sysClock = ((HSI_VALUE >> 1) / plldiv) * pllMull; + } + else if (pllSource == 0x01) + { + sysClock = (HSI_VALUE / plldiv) * pllMull; + } + else if (pllSource == 0x02) + { + sysClock = (HSE_VALUE / plldiv) * pllMull; + } + else + { + sysClock = (HSI48_VALUE / plldiv) * pllMull; + } + break; + + case RCM_SYSCLK_SEL_HSI48: + sysClock = HSI48_VALUE; + break; + + default: + sysClock = HSI_VALUE; + break; + } + + return sysClock; +} + +/*! + * @brief Read frequency of HCLK(AHB) + * + * @param None + * + * @retval Return frequency of HCLK + */ +uint32_t RCM_ReadHCLKFreq(void) +{ + uint32_t divider; + uint32_t sysClk, hclk; + uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + + sysClk = RCM_ReadSYSCLKFreq(); + divider = AHBPrescTable[RCM->CFG1_B.AHBPSC]; + hclk = sysClk >> divider; + + return hclk; +} + +/*! + * @brief Read frequency of PCLK + * + * @param None + * + * @retval PCLK1 return frequency of PCLK + */ +uint32_t RCM_ReadPCLKFreq(void) +{ + uint32_t hclk, pclk, divider; + uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + + hclk = RCM_ReadSYSCLKFreq(); + + divider = APBPrescTable[RCM->CFG1_B.APB1PSC]; + pclk = hclk >> divider; + + return pclk; + +} + +/*! + * @brief Read frequency of ADC CLK + * + * @param None + * + * @retval Return frequency of ADC CLK + */ +uint32_t RCM_ReadADCCLKFreq(void) +{ + uint32_t adcClk, pclk; + + pclk = RCM_ReadPCLKFreq(); + + if (RCM->CFG3_B.ADCSEL) + { + if (RCM->CFG1_B.ADCPSC) + { + adcClk = pclk >> 2; + } + else + { + adcClk = pclk >> 1; + } + } + else + { + adcClk = HSI14_VALUE; + } + + return adcClk; +} + +/*! + * @brief Read frequency of CEC CLK + * + * @param None + * + * @retval Return frequency of CEC CLK + */ +uint32_t RCM_ReadCECCLKFreq(void) +{ + uint32_t cecClk; + + if (RCM->CFG3_B.CECSEL) + { + cecClk = LSE_VALUE; + } + else + { + cecClk = LSI_VALUE / 244; + } + + return cecClk; +} + +/*! + * @brief Read frequency of I2C1 CLK + * + * @param None + * + * @retval Return frequency of I2C1 CLK + */ +uint32_t RCM_ReadI2C1CLKFreq(void) +{ + uint32_t i2c1Clk, sysClk; + + sysClk = RCM_ReadSYSCLKFreq(); + + if (RCM->CFG3_B.I2C1SEL) + { + i2c1Clk = sysClk; + } + else + { + i2c1Clk = HSI_VALUE; + } + + return i2c1Clk; +} + +/*! + * @brief Read frequency of USART1 CLK + * + * @param None + * + * @retval Return frequency of USART1 CLK + */ +uint32_t RCM_ReadUSART1CLKFreq(void) +{ + uint32_t usart1Clk; + + if (RCM->CFG3_B.USART1SEL == 0x00) + { + usart1Clk = RCM_ReadPCLKFreq(); + } + else if (RCM->CFG3_B.USART1SEL == 0x01) + { + usart1Clk = RCM_ReadSYSCLKFreq(); + } + else if (RCM->CFG3_B.USART1SEL == 0x02) + { + usart1Clk = LSE_VALUE; + } + else if (RCM->CFG3_B.USART1SEL == 0x03) + { + usart1Clk = HSI_VALUE; + } + + return usart1Clk; +} + +/*! + * @brief Read frequency of USB CLK + * + * @param None + * + * @retval Return frequency of USB CLK + */ +uint32_t RCM_ReadUSBCLKFreq(void) +{ + uint32_t usbClk, pllClk, pllMull, clkDiv; + + if (RCM->CFG1_B.SCLKSWSTS & 0x02) + { + pllMull = RCM->CFG1_B.PLLMULCFG; + pllMull = pllMull + 2; + } + + if (RCM->CFG3_B.USBDSEL) + { + if (RCM->CFG1_B.PLLSRCSEL == 0x00) + { + pllClk = (HSI_VALUE >> 1) * pllMull; + } + else + { + clkDiv = (RCM->CFG2_B.PLLDIVCFG) + 1; + pllClk = (HSE_VALUE / clkDiv) * pllMull; + } + usbClk = pllClk; + } + else + { + usbClk = HSI48_VALUE; + } + + return usbClk; +} + +/*! + * @brief Read frequency of USART2 CLK + * + * @param None + * + * @retval Return frequency of USART2 CLK + */ +uint32_t RCM_ReadUSART2CLKFreq(void) +{ + uint32_t usart1Clk; + + if (RCM->CFG3_B.USART2SEL == 0x00) + { + usart1Clk = RCM_ReadPCLKFreq(); + } + else if (RCM->CFG3_B.USART2SEL == 0x01) + { + usart1Clk = RCM_ReadSYSCLKFreq(); + } + else if (RCM->CFG3_B.USART2SEL == 0x02) + { + usart1Clk = LSE_VALUE; + } + else if (RCM->CFG3_B.USART2SEL == 0x03) + { + usart1Clk = HSI_VALUE; + } + + return usart1Clk; +} + +/*! + * @brief Configures the RTC clock (RTCCLK) + * + * @param RTCClk: specifies the RTC clock source + * This parameter can be one of the following values: + * @arg RCM_RTCCLK_LSE: LSE selected as RTC clock + * @arg RCM_RTCCLK_LSI: LSI selected as RTC clock + * @arg RCM_RTCCLK_HSE_DIV_32: HSE divided by 32 selected as RTC clock + * + * @retval None + * + * @note Once the RTC clock is selected it can't be changed unless the Backup domain is reset + */ +void RCM_ConfigRTCCLK(RCM_RTCCLK_T RTCClk) +{ + RCM->BDCTRL_B.RTCSRCSEL = RTCClk; +} + +/*! + * @brief Enables the RTC clock + * + * @param None + * + * @retval None + */ +void RCM_EnableRTCCLK(void) +{ + RCM->BDCTRL_B.RTCCLKEN = BIT_SET; +} + +/*! + * @brief Disables the RTC clock + * + * @param None + * + * @retval None + */ +void RCM_DisableRTCCLK(void) +{ + RCM->BDCTRL_B.RTCCLKEN = BIT_RESET; +} + +/*! + * @brief Enable the Backup domain reset + * + * @param None + * + * @retval None + */ +void RCM_EnableBackupReset(void) +{ + RCM->BDCTRL_B.BDRST = BIT_SET; +} + +/*! + * @brief Disable the Backup domain reset + * + * @param None + * + * @retval None + */ +void RCM_DisableBackupReset(void) +{ + RCM->BDCTRL_B.BDRST = BIT_RESET; +} + +/*! + * @brief Enables AHB peripheral clock + * + * @param AHBPeriph: specifies the AHB peripheral to gates its clock + * This parameter can be any combination of the following values: + * @arg RCM_AHB_PERIPH_DMA1: DMA1 clock + * @arg RCM_AHB_PERIPH_DMA2: DMA2 clock + * @arg RCM_AHB_PERIPH_SRAM: SRAM clock + * @arg RCM_AHB_PERIPH_FPU: FPU clock + * @arg RCM_AHB_PERIPH_CRC: CRC clock + * @arg RCM_AHB_PERIPH_GPIOA: GPIOA clock + * @arg RCM_AHB_PERIPH_GPIOB: GPIOB clock + * @arg RCM_AHB_PERIPH_GPIOC: GPIOC clock + * @arg RCM_AHB_PERIPH_GPIOD: GPIOD clock + * @arg RCM_AHB_PERIPH_GPIOE: GPIOE clock(Only for APM32F072 and APM32F091) + * @arg RCM_AHB_PERIPH_GPIOF: GPIOF clock + * @arg RCM_AHB_PERIPH_TSC: TSC clock + * + * @retval None + */ +void RCM_EnableAHBPeriphClock(uint32_t AHBPeriph) +{ + RCM->AHBCLKEN |= AHBPeriph; +} + +/*! + * @brief Disable AHB peripheral clock + * + * @param AHBPeriph: specifies the AHB peripheral to gates its clock + * This parameter can be any combination of the following values: + * @arg RCM_AHB_PERIPH_DMA1: DMA1 clock + * @arg RCM_AHB_PERIPH_DMA2: DMA2 clock + * @arg RCM_AHB_PERIPH_SRAM: SRAM clock + * @arg RCM_AHB_PERIPH_FPU: FPU clock + * @arg RCM_AHB_PERIPH_CRC: CRC clock + * @arg RCM_AHB_PERIPH_GPIOA: GPIOA clock + * @arg RCM_AHB_PERIPH_GPIOB: GPIOB clock + * @arg RCM_AHB_PERIPH_GPIOC: GPIOC clock + * @arg RCM_AHB_PERIPH_GPIOD: GPIOD clock + * @arg RCM_AHB_PERIPH_GPIOE: GPIOE clock(Only for APM32F072 and APM32F091) + * @arg RCM_AHB_PERIPH_GPIOF: GPIOF clock + * @arg RCM_AHB_PERIPH_TSC: TSC clock + * + * @retval None + */ +void RCM_DisableAHBPeriphClock(uint32_t AHBPeriph) +{ + RCM->AHBCLKEN &= (uint32_t)~AHBPeriph; +} + +/*! + * @brief Enable the High Speed APB (APB2) peripheral clock + * + * @param APB2Periph: specifies the APB2 peripheral to gates its clock + * This parameter can be any combination of the following values: + * @arg RCM_APB2_PERIPH_SYSCFG: SYSCFG clock + * @arg RCM_APB2_PERIPH_USART6: USART6 clock(Only for APM32F091) + * @arg RCM_APB2_PERIPH_USART7: USART7 clock(Only for APM32F091) + * @arg RCM_APB2_PERIPH_USART8: USART8 clock(Only for APM32F091) + * @arg RCM_APB2_PERIPH_ADC1: ADC1 clock + * @arg RCM_APB2_PERIPH_TMR1: TMR1 clock + * @arg RCM_APB2_PERIPH_SPI1: SPI1 clock + * @arg RCM_APB2_PERIPH_USART1: USART1 clock + * @arg RCM_APB2_PERIPH_TMR15: TMR15 clock + * @arg RCM_APB2_PERIPH_TMR16: TMR16 clock + * @arg RCM_APB2_PERIPH_TMR17: TMR17 clock + * @arg RCM_APB2_PERIPH_DBGMCU: DBGMCU clock + * + * @retval None + */ +void RCM_EnableAPB2PeriphClock(uint32_t APB2Periph) +{ + RCM->APBCLKEN2 |= APB2Periph; +} + +/*! + * @brief Disable the High Speed APB (APB2) peripheral clock + * + * @param APB2Periph: specifies the APB2 peripheral to gates its clock + * This parameter can be any combination of the following values: + * @arg RCM_APB2_PERIPH_SYSCFG: SYSCFG clock + * @arg RCM_APB2_PERIPH_USART6: USART6 clock(Only for APM32F091) + * @arg RCM_APB2_PERIPH_USART7: USART7 clock(Only for APM32F091) + * @arg RCM_APB2_PERIPH_USART8: USART8 clock(Only for APM32F091) + * @arg RCM_APB2_PERIPH_ADC1: ADC1 clock + * @arg RCM_APB2_PERIPH_TMR1: TMR1 clock + * @arg RCM_APB2_PERIPH_SPI1: SPI1 clock + * @arg RCM_APB2_PERIPH_USART1: USART1 clock + * @arg RCM_APB2_PERIPH_TMR15: TMR15 clock + * @arg RCM_APB2_PERIPH_TMR16: TMR16 clock + * @arg RCM_APB2_PERIPH_TMR17: TMR17 clock + * @arg RCM_APB2_PERIPH_DBGMCU: DBGMCU clock + * + * @retval None + */ +void RCM_DisableAPB2PeriphClock(uint32_t APB2Periph) +{ + RCM->APBCLKEN2 &= (uint32_t)~APB2Periph; +} + +/*! + * @brief Enable the Low Speed APB (APB1) peripheral clock + * + * @param APB1Periph: specifies the APB1 peripheral to gates its clock + * This parameter can be any combination of the following values: + * @arg RCM_APB1_PERIPH_TMR2: TMR2 clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_TMR3: TMR3 clock + * @arg RCM_APB1_PERIPH_TMR6: TMR6 clock + * @arg RCM_APB1_PERIPH_TMR7: TMR7 clock(Only for APM32F072) + * @arg RCM_APB1_PERIPH_TMR14: TMR14 clock + * @arg RCM_APB1_PERIPH_WWDT: WWDG clock + * @arg RCM_APB1_PERIPH_SPI2: SPI2 clock + * @arg RCM_APB1_PERIPH_USART2: USART2 clock + * @arg RCM_APB1_PERIPH_USART3: USART3 clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_USART4: USART4 clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_USART5: USART5 clock(Only for APM32F091) + * @arg RCM_APB1_PERIPH_I2C1: I2C1 clock + * @arg RCM_APB1_PERIPH_I2C2: I2C2 clock + * @arg RCM_APB1_PERIPH_USB: USB clock(Only for APM32F072) + * @arg RCM_APB1_PERIPH_CAN: CAN clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_CRS: CRS clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_PMU: PMU clock + * @arg RCM_APB1_PERIPH_DAC: DAC clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_CEC: CEC clock(Only for APM32F072 and APM32F091) + * + * @retval None + */ +void RCM_EnableAPB1PeriphClock(uint32_t APB1Periph) +{ + RCM->APBCLKEN1 |= APB1Periph; +} + +/*! + * @brief Disable the Low Speed APB (APB1) peripheral clock + * + * @param APB1Periph: specifies the APB1 peripheral to gates its clock + * This parameter can be any combination of the following values: + * @arg RCM_APB1_PERIPH_TMR2: TMR2 clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_TMR3: TMR3 clock + * @arg RCM_APB1_PERIPH_TMR6: TMR6 clock + * @arg RCM_APB1_PERIPH_TMR7: TMR7 clock(Only for APM32F072) + * @arg RCM_APB1_PERIPH_TMR14: TMR14 clock + * @arg RCM_APB1_PERIPH_WWDT: WWDG clock + * @arg RCM_APB1_PERIPH_SPI2: SPI2 clock + * @arg RCM_APB1_PERIPH_USART2: USART2 clock + * @arg RCM_APB1_PERIPH_USART3: USART3 clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_USART4: USART4 clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_USART5: USART5 clock(Only for APM32F091) + * @arg RCM_APB1_PERIPH_I2C1: I2C1 clock + * @arg RCM_APB1_PERIPH_I2C2: I2C2 clock + * @arg RCM_APB1_PERIPH_USB: USB clock(Only for APM32F072) + * @arg RCM_APB1_PERIPH_CAN: CAN clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_CRS: CRS clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_PMU: PMU clock + * @arg RCM_APB1_PERIPH_DAC: DAC clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_CEC: CEC clock(Only for APM32F072 and APM32F091) + * + * @retval None + */ +void RCM_DisableAPB1PeriphClock(uint32_t APB1Periph) +{ + RCM->APBCLKEN1 &= (uint32_t)~APB1Periph; +} + +/*! + * @brief Enable Low Speed AHB peripheral reset + * + * @param AHBPeriph: specifies the AHB peripheral to reset + * This parameter can be any combination of the following values: + * @arg RCM_AHB_PERIPH_GPIOA: GPIOA reset + * @arg RCM_AHB_PERIPH_GPIOB: GPIOB reset + * @arg RCM_AHB_PERIPH_GPIOC: GPIOC reset + * @arg RCM_AHB_PERIPH_GPIOD: GPIOD reset + * @arg RCM_AHB_PERIPH_GPIOE: GPIOE clock(Only for APM32F072 and APM32F091) + * @arg RCM_AHB_PERIPH_GPIOF: GPIOF reset + * @arg RCM_AHB_PERIPH_TSC: TSC clock + * + * @retval None + */ +void RCM_EnableAHBPeriphReset(uint32_t AHBPeriph) +{ + RCM->AHBRST |= AHBPeriph; +} + +/*! + * @brief Disable Low Speed AHB peripheral reset + * + * @param AHBPeriph: specifies the AHB peripheral to reset + * This parameter can be any combination of the following values: + * @arg RCM_AHB_PERIPH_GPIOA: GPIOA reset + * @arg RCM_AHB_PERIPH_GPIOB: GPIOB reset + * @arg RCM_AHB_PERIPH_GPIOC: GPIOC reset + * @arg RCM_AHB_PERIPH_GPIOD: GPIOD reset + * @arg RCM_AHB_PERIPH_GPIOE: GPIOE clock(Only for APM32F072 and APM32F091) + * @arg RCM_AHB_PERIPH_GPIOF: GPIOF reset + * @arg RCM_AHB_PERIPH_TSC: TSC clock + * + * @retval None + */ +void RCM_DisableAHBPeriphReset(uint32_t AHBPeriph) +{ + RCM->AHBRST &= (uint32_t)~AHBPeriph; +} + +/*! + * @brief Enable Low Speed APB (APB1) peripheral reset + * + * @param APB1Periph: specifies the APB1 peripheral to reset + * This parameter can be any combination of the following values: + * @arg RCM_APB1_PERIPH_TMR2: TMR2 clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_TMR3: TMR3 clock + * @arg RCM_APB1_PERIPH_TMR6: TMR6 clock + * @arg RCM_APB1_PERIPH_TMR7: TMR7 clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_TMR14: TMR14 clock + * @arg RCM_APB1_PERIPH_WWDT: WWDG clock + * @arg RCM_APB1_PERIPH_SPI2: SPI2 clock + * @arg RCM_APB1_PERIPH_USART2: USART2 clock + * @arg RCM_APB1_PERIPH_USART3: USART3 clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_USART4: USART4 clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_USART5: USART5 clock(Only for APM32F091) + * @arg RCM_APB1_PERIPH_I2C1: I2C1 clock + * @arg RCM_APB1_PERIPH_I2C2: I2C2 clock + * @arg RCM_APB1_PERIPH_USB: USB clock(Only for APM32F072) + * @arg RCM_APB1_PERIPH_CAN: CAN clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_CRS: CRS clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_PMU: PMU clock + * @arg RCM_APB1_PERIPH_DAC: DAC clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_CEC: CEC clock(Only for APM32F072 and APM32F091) + * + * @retval None + */ +void RCM_EnableAPB1PeriphReset(uint32_t APB1Periph) +{ + RCM->APBRST1 |= APB1Periph; +} + +/*! + * @brief Disable Low Speed APB (APB1) peripheral reset + * + * @param APB1Periph: specifies the APB1 peripheral to reset + * This parameter can be any combination of the following values: + * @arg RCM_APB1_PERIPH_TMR2: TMR2 clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_TMR3: TMR3 clock + * @arg RCM_APB1_PERIPH_TMR6: TMR6 clock + * @arg RCM_APB1_PERIPH_TMR7: TMR7 clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_TMR14: TMR14 clock + * @arg RCM_APB1_PERIPH_WWDT: WWDG clock + * @arg RCM_APB1_PERIPH_SPI2: SPI2 clock + * @arg RCM_APB1_PERIPH_USART2: USART2 clock + * @arg RCM_APB1_PERIPH_USART3: USART3 clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_USART4: USART4 clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_USART5: USART5 clock(Only for APM32F091) + * @arg RCM_APB1_PERIPH_I2C1: I2C1 clock + * @arg RCM_APB1_PERIPH_I2C2: I2C2 clock + * @arg RCM_APB1_PERIPH_USB: USB clock(Only for APM32F072) + * @arg RCM_APB1_PERIPH_CAN: CAN clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_CRS: CRS clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_PMU: PMU clock + * @arg RCM_APB1_PERIPH_DAC: DAC clock(Only for APM32F072 and APM32F091) + * @arg RCM_APB1_PERIPH_CEC: CEC clock(Only for APM32F072 and APM32F091) + * + * @retval None + */ +void RCM_DisableAPB1PeriphReset(uint32_t APB1Periph) +{ + RCM->APBRST1 &= (uint32_t)~APB1Periph; +} + +/*! + * @brief Enable High Speed APB (APB2) peripheral reset + * + * @param APB2Periph: specifies the APB2 peripheral to reset + * This parameter can be any combination of the following values: + * @arg RCM_APB2_PERIPH_SYSCFG: SYSCFG clock + * @arg RCM_APB2_PERIPH_USART6: USART6 clock(Only for APM32F091) + * @arg RCM_APB2_PERIPH_USART7: USART7 clock(Only for APM32F091) + * @arg RCM_APB2_PERIPH_USART8: USART8 clock(Only for APM32F091) + * @arg RCM_APB2_PERIPH_ADC1: ADC1 clock + * @arg RCM_APB2_PERIPH_TMR1: TMR1 clock + * @arg RCM_APB2_PERIPH_SPI1: SPI1 clock + * @arg RCM_APB2_PERIPH_USART1: USART1 clock + * @arg RCM_APB2_PERIPH_TMR15: TMR15 clock + * @arg RCM_APB2_PERIPH_TMR16: TMR16 clock + * @arg RCM_APB2_PERIPH_TMR17: TMR17 clock + * @arg RCM_APB2_PERIPH_DBGMCU: DBGMCU clock + * + * @retval None + */ +void RCM_EnableAPB2PeriphReset(uint32_t APB2Periph) +{ + RCM->APBRST2 |= APB2Periph; +} + +/*! + * @brief Disable High Speed APB (APB2) peripheral reset + * + * @param APB2Periph: specifies the APB2 peripheral to reset + * This parameter can be any combination of the following values: + * @arg RCM_APB2_PERIPH_SYSCFG: SYSCFG clock + * @arg RCM_APB2_PERIPH_USART6: USART6 clock(Only for APM32F091) + * @arg RCM_APB2_PERIPH_USART7: USART7 clock(Only for APM32F091) + * @arg RCM_APB2_PERIPH_USART8: USART8 clock(Only for APM32F091) + * @arg RCM_APB2_PERIPH_ADC1: ADC1 clock + * @arg RCM_APB2_PERIPH_TMR1: TMR1 clock + * @arg RCM_APB2_PERIPH_SPI1: SPI1 clock + * @arg RCM_APB2_PERIPH_USART1: USART1 clock + * @arg RCM_APB2_PERIPH_TMR15: TMR15 clock + * @arg RCM_APB2_PERIPH_TMR16: TMR16 clock + * @arg RCM_APB2_PERIPH_TMR17: TMR17 clock + * @arg RCM_APB2_PERIPH_DBGMCU: DBGMCU clock + * + * @retval None + */ +void RCM_DisableAPB2PeriphReset(uint32_t APB2Periph) +{ + RCM->APBRST2 &= (uint32_t)~APB2Periph; +} + +/*! + * @brief Enable the specified RCM interrupts + * + * @param interrupt: specifies the RCM interrupt source to check + * This parameter can be any combination of the following values: + * @arg RCM_INT_LSIRDY: LSI ready interrupt + * @arg RCM_INT_LSERDY: LSE ready interrupt + * @arg RCM_INT_HSIRDY: HSI ready interrupt + * @arg RCM_INT_HSERDY: HSE ready interrupt + * @arg RCM_INT_PLLRDY: PLL ready interrupt + * @arg RCM_INT_HSI14RDY: HSI14 ready interrupt + * @arg RCM_INT_HSI48RDY: HSI48 ready interrupt(Only for APM32F072 and APM32F091 devices) + * + * @retval None + */ +void RCM_EnableInterrupt(uint8_t interrupt) +{ + RCM->INT |= (interrupt << 8); +} + +/*! + * @brief Disable the specified RCM interrupts + * + * @param interrupt: specifies the RCM interrupt source to check + * This parameter can be any combination of the following values: + * @arg RCM_INT_LSIRDY: LSI ready interrupt + * @arg RCM_INT_LSERDY: LSE ready interrupt + * @arg RCM_INT_HSIRDY: HSI ready interrupt + * @arg RCM_INT_HSERDY: HSE ready interrupt + * @arg RCM_INT_PLLRDY: PLL ready interrupt + * @arg RCM_INT_HSI14RDY: HSI14 ready interrupt + * @arg RCM_INT_HSI48RDY: HSI48 ready interrupt(Only for APM32F072 and APM32F091 devices) + * + * @retval None + */ +void RCM_DisableInterrupt(uint8_t interrupt) +{ + RCM->INT &= ~(interrupt << 8); +} + +/*! + * @brief Read the specified RCM flag status + * + * @param flag: specifies the flag to check + * This parameter can be one of the following values: + * @arg RCM_FLAG_HSIRDY: HSI oscillator clock ready + * @arg RCM_FLAG_HSERDY: HSE oscillator clock ready + * @arg RCM_FLAG_PLLRDY: PLL clock ready + * @arg RCM_FLAG_LSERDY: LSE oscillator clock ready + * @arg RCM_FLAG_LSIRDY: LSI oscillator clock ready + * @arg RCM_FLAG_V18PRRST: V1.8 power domain reset + * @arg RCM_FLAG_OBRST: Option Byte Loader (OBL) reset + * @arg RCM_FLAG_PINRST: Pin reset + * @arg RCM_FLAG_PWRRST: POR/PDR reset + * @arg RCM_FLAG_SWRST: Software reset + * @arg RCM_FLAG_IWDTRST: Independent Watchdog reset + * @arg RCM_FLAG_WWDTRST: Window Watchdog reset + * @arg RCM_FLAG_LPRRST: Low Power reset + * @arg RCM_FLAG_HSI14RDY: HSI14 clock ready + * @arg RCM_FLAG_HSI48RDY: HSI48 clock ready(Only for APM32F072 and APM32F091) + * + * @retval The new state of flag (SET or RESET) + */ +uint16_t RCM_ReadStatusFlag(RCM_FLAG_T flag) +{ + uint32_t reg, bit; + + bit = (uint32_t)(1 << (flag & 0xff)); + + reg = (flag >> 8) & 0xff; + + switch (reg) + { + case 0: + reg = RCM->CTRL1; + break; + + case 1: + reg = RCM->BDCTRL; + break; + + case 2: + reg = RCM->CSTS; + break; + + case 3: + reg = RCM->CTRL2; + break; + + default: + break; + } + + if (reg & bit) + { + return SET; + } + + return RESET; +} + +/*! + * @brief Clears the RCM reset flags + * + * @param None + * + * @retval None + * + * @note The reset flags are: + * RCM_FLAG_V18PRRST; RCM_FLAG_OBRST; RCM_FLAG_PINRST; RCM_FLAG_PWRRST; + * RCM_FLAG_SWRST; RCM_FLAG_IWDTRST; RCM_FLAG_WWDTRST; RCM_FLAG_LPRRST; + */ +void RCM_ClearStatusFlag(void) +{ + RCM->CSTS_B.RSTFLGCLR = BIT_SET; +} + +/*! + * @brief Read the specified RCM interrupt Flag + * + * @param flag: specifies the RCM interrupt source to check + * This parameter can be one of the following values: + * @arg RCM_INT_LSIRDY: LSI ready interrupt + * @arg RCM_INT_LSERDY: LSE ready interrupt + * @arg RCM_INT_HSIRDY: HSI ready interrupt + * @arg RCM_INT_HSERDY: HSE ready interrupt + * @arg RCM_INT_PLLRDY: PLL ready interrupt + * @arg RCM_INT_HSI14RDY: HSI14 ready interrupt + * @arg RCM_INT_HSI48RDY: HSI48 ready interrupt(Only for APM32F072 and APM32F091 devices) + * @arg RCC_IT_CSS: Clock Security System interrupt + * + * @retval The new state of intFlag (SET or RESET) + */ +uint8_t RCM_ReadIntFlag(RCM_INT_T flag) +{ + uint8_t ret; + + ret = (RCM->INT& flag) ? SET : RESET; + + return ret; +} + +/*! + * @brief Clears the interrupt flag + * + * @param flag: specifies the RCM interrupt source to check + * This parameter can be any combination of the following values: + * @arg RCM_INT_LSIRDY: LSI ready interrupt + * @arg RCM_INT_LSERDY: LSE ready interrupt + * @arg RCM_INT_HSIRDY: HSI ready interrupt + * @arg RCM_INT_HSERDY: HSE ready interrupt + * @arg RCM_INT_PLLRDY: PLL ready interrupt + * @arg RCM_INT_HSI14RDY: HSI14 ready interrupt + * @arg RCM_INT_HSI48RDY: HSI48 ready interrupt(Only for APM32F072 and APM32F091 devices) + * @arg RCC_IT_CSS: Clock Security System interrupt + * + * @retval None + */ +void RCM_ClearIntFlag(uint8_t flag) +{ + uint32_t temp; + + temp = flag << 16; + RCM->INT |= temp; +} + +/**@} end of group RCM_Functions*/ +/**@} end of group RCM_Driver*/ +/**@} end of group APM32F0xx_StdPeriphDriver*/ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_rtc.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_rtc.c new file mode 100644 index 0000000000..fcc600a67b --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_rtc.c @@ -0,0 +1,1753 @@ +/*! + * @file apm32f0xx_rtc.c + * + * @brief This file provides firmware functions to manage the following + * functionalities of the Real-Time Clock (RTC) peripheral + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +#include "apm32f0xx_rtc.h" +#include "apm32f0xx_rcm.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup RTC_Driver RTC Driver + @{ +*/ + +/** @defgroup RTC_Macros Macros + @{ +*/ + +/**@} end of group RTC_Macros */ + +/** @defgroup RRTC_Enumerations Enumerations + @{ +*/ + +/**@} end of group RTC_Macros */ + +/** @defgroup RTC_Structures Structures + @{ +*/ + +/**@} end of group RTC_Structures */ + +/** @defgroup RTC_Variables Variables + @{ +*/ + +/**@} end of group RTC_Variables */ + +/** @defgroup RTC_Functions Functions + @{ +*/ + +static uint8_t RTC_ByteConBcd2(uint8_t val); +static uint8_t RTC_Bcd2ConByte(uint8_t val); + +/*! + * @brief Deinitializes the RTC registers to their default reset values + * + * @param None + * + * @retval SUCCESS or ERROR + */ +uint8_t RTC_Reset(void) +{ + RTC_DisableWriteProtection(); + + if (RTC_EnableInit() == ERROR) + { + RTC_EnableWriteProtection(); + return ERROR; + } + else + { + RTC->TIME = (uint32_t)0x00000000; + RTC->AUTORLD = (uint32_t)0x0000FFFF; + RTC->DATE = (uint32_t)0x00002101; + RTC->CTRL &= (uint32_t)0x00000000; + RTC->PSC = (uint32_t)0x007F00FF; + RTC->ALRMA = (uint32_t)0x00000000; + RTC->SHIFT = (uint32_t)0x00000000; + RTC->CAL = (uint32_t)0x00000000; + RTC->ALRMASS = (uint32_t)0x00000000; + + RTC->STS = (uint32_t)0x00000007; + RTC->TACFG = 0x00000000; + + if (RTC_WaitForSynchro() == ERROR) + { + RTC_EnableWriteProtection(); + return ERROR; + } + else + { + RTC_EnableWriteProtection(); + return SUCCESS; + } + } +} + +/*! + * @brief Deinitializes the RTC registers to their default reset values + * + * @param Struct : pointer to a RTC_Config_T structure which will be initialized + * + * @retval SUCCESS or ERROR + */ +uint8_t RTC_Config(RTC_Config_T* Struct) +{ + RTC_DisableWriteProtection(); + + if (RTC_EnableInit() == ERROR) + { + RTC_EnableWriteProtection(); + return ERROR; + } + else + { + RTC->CTRL_B.TIMEFCFG = (Struct->format); + RTC->PSC_B.SPSC = (Struct->SynchPrediv); + RTC->PSC_B.APSC = (Struct->AsynchPrediv); + + RTC_DisableInit(); + RTC_EnableWriteProtection(); + return SUCCESS; + } +} + +/*! + * @brief Fills each RTC_ConfigStruct member with its default value + * + * @param Struct : pointer to a RTC_Config_T structure which will be initialized + * + * @retval None + */ +void RTC_ConfigStructInit(RTC_Config_T* Struct) +{ + Struct->format = RTC_HourFormat_24; + Struct->AsynchPrediv = (uint32_t)0x7F; + Struct->SynchPrediv = (uint32_t)0xFF; +} + +/*! + * @brief Enable the write protection for RTC registers + * + * @param None + * + * @retval None + */ +void RTC_EnableWriteProtection(void) +{ + RTC->WRPROT = 0xFF; +} + +/*! + * @brief Disable the write protection for RTC registers + * + * @param None + * + * @retval None + */ +void RTC_DisableWriteProtection(void) +{ + RTC->WRPROT = 0xCA; + RTC->WRPROT = 0x53; +} + +/*! + * @brief Enable the RTC Initialization mode. + * + * @param None + * + * @retval SUCCESS or ERROR + */ +uint8_t RTC_EnableInit(void) +{ + __IO uint32_t cnt = 0x00; + uint32_t initstatus = 0x00; + + if (RTC->STS_B.RINITFLG == BIT_RESET) + { + RTC->STS = (uint32_t)0xFFFFFFFF; + + do + { + initstatus = RTC->STS_B.RINITFLG; + cnt++; + } + while ((cnt != RTC_INITMODE_TIMEOUT) && (initstatus == 0x00)); + + if (RTC->STS_B.RINITFLG != BIT_RESET) + { + return SUCCESS; + } + else + { + return ERROR; + } + } + else + { + return SUCCESS; + } +} + +/*! + * @brief Disable the RTC Initialization mode. + * + * @param None + * + * @retval None + */ +void RTC_DisableInit(void) +{ + RTC->STS_B.INITEN = BIT_RESET; +} + +/*! + * @brief Waits until the RTC Time and Date registers (RTC_TIME and RTC_DATA) are + * synchronized with RTC APB clock + * @param None + * + * @retval SUCCESS or ERROR + */ +uint8_t RTC_WaitForSynchro(void) +{ + __IO uint32_t cnt = 0x00; + uint32_t synchrostatus = 0x00; + + if (RTC->CTRL_B.RCMCFG == BIT_RESET) + { + return SUCCESS; + } + else + { + RTC_DisableWriteProtection(); + RTC->STS &= (uint32_t)0xFFFFFF5F; + + do + { + synchrostatus = RTC->STS_B.RSFLG; + cnt++; + } + while ((cnt != RTC_SYNCHRO_TIMEOUT) && (synchrostatus == 0x00)); + + if (RTC->STS_B.RSFLG != BIT_RESET) + { + RTC_EnableWriteProtection(); + return SUCCESS; + } + else + { + RTC_EnableWriteProtection(); + return ERROR; + } + } +} + +/*! + * @brief Enables the RTC reference clock detection + * + * @param None + * + * @retval SUCCESS or ERROR + */ +uint8_t RTC_EnableRefClock(void) +{ + RTC_DisableWriteProtection(); + + if (RTC_EnableInit() == ERROR) + { + RTC_EnableWriteProtection(); + return ERROR; + } + else + { + RTC->CTRL_B.RCLKDEN = BIT_SET; + RTC_DisableInit(); + RTC_EnableWriteProtection(); + return SUCCESS; + } +} + +/*! + * @brief Disable the RTC reference clock detection + * + * @param None + * + * @retval SUCCESS or ERROR + */ +uint8_t RTC_DisableRefClock(void) +{ + RTC_DisableWriteProtection(); + + if (RTC_EnableInit() == ERROR) + { + RTC_EnableWriteProtection(); + return ERROR; + } + else + { + RTC->CTRL_B.RCLKDEN = BIT_RESET; + RTC_DisableInit(); + RTC_EnableWriteProtection(); + return SUCCESS; + } +} + +/*! + * @brief Enable the RTC reference clock detection + * + * @param None + * + * @retval None + */ +void RTC_EnableBypassShadow(void) +{ + RTC_DisableWriteProtection(); + RTC->CTRL_B.RCMCFG = BIT_SET; + RTC_EnableWriteProtection(); +} + +/*! + * @brief Disable the RTC reference clock detection + * + * @param None + * + * @retval None + */ +void RTC_DisableBypassShadow(void) +{ + RTC_DisableWriteProtection(); + RTC->CTRL_B.RCMCFG = BIT_RESET; + RTC_EnableWriteProtection(); +} + +/*! + * @brief Config the RTC current time + * + * @param format: specifies the format to write + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: format in Bin + * @arg RTC_FORMAT_BCD: format in BCD + * + * @param timeStruct: Pointer to a RTC_TIME_T structure that + * contains the configuration information for the RTC peripheral + * + * @retval None + */ +uint8_t RTC_ConfigTime(RTC_FORMAT_T format, RTC_TIME_T* timeStruct) +{ + uint8_t state = ERROR; + uint32_t temp = 0; + + if (format == RTC_FORMAT_BIN) + { + if (RTC->CTRL_B.TIMEFCFG == BIT_RESET) + { + timeStruct->H12 = RTC_H12_AM; + } + } + else + { + if (RTC->CTRL_B.TIMEFCFG == BIT_RESET) + { + timeStruct->H12 = RTC_H12_AM; + } + else + { + temp = RTC_Bcd2ConByte(timeStruct->hours); + } + } + + if (format != RTC_FORMAT_BIN) + { + temp = (((uint32_t)(timeStruct->hours) << 16) | \ + ((uint32_t)(timeStruct->minutes) << 8) | \ + ((uint32_t)(timeStruct->seconds)) | \ + ((uint32_t)(timeStruct->H12) << 22)); + } + else + { + temp = (((uint32_t)RTC_ByteConBcd2(timeStruct->hours) << 16) | \ + ((uint32_t)RTC_ByteConBcd2(timeStruct->minutes) << 8) | \ + ((uint32_t)RTC_ByteConBcd2(timeStruct->seconds)) | \ + ((uint32_t)(timeStruct->H12) << 22)); + } + + RTC_DisableWriteProtection(); + + if (RTC_EnableInit() == ERROR) + { + state = ERROR; + } + else + { + RTC->TIME = (uint32_t)(temp & 0x007F7F7F); + RTC_DisableInit(); + + if (RTC->CTRL_B.RCMCFG == RESET) + { + if (RTC_WaitForSynchro() == ERROR) + { + state = ERROR; + } + else + { + state = SUCCESS; + } + } + else + { + state = SUCCESS; + } + } + + RTC_EnableWriteProtection(); + return state; +} + +/*! + * @brief Fills each timeStruct member with its default value + * + * @param timeStruct: Pointer to a RTC_TIME_T structure that + * contains the configuration information for the RTC peripheral + * + * @retval None + */ +void RTC_ConfigTimeStructInit(RTC_TIME_T* timeStruct) +{ + /** ALRMA Time Settings : Time = 00h:00mn:00sec */ + timeStruct->hours = 0; + timeStruct->minutes = 0; + timeStruct->seconds = 0; + timeStruct->H12 = RTC_H12_AM; +} + +/*! + * @brief Read the RTC current Time + * + * @param format: specifies the format to write + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: format in Bin + * @arg RTC_FORMAT_BCD: format in BCD + * + * @param timeStruct: Pointer to a RTC_TIME_T structure that + * contains the configuration information for the RTC peripheral + * + * @retval None + */ +void RTC_ReadTime(RTC_FORMAT_T format, RTC_TIME_T* timeStruct) +{ + uint32_t temp = 0; + temp = (uint32_t)((RTC->TIME) & 0x007F7F7F); + + timeStruct->hours = (uint8_t)((temp & 0x003F0000) >> 16); + timeStruct->minutes = (uint8_t)((temp & 0x00007F00) >> 8); + timeStruct->seconds = (uint8_t)(temp & 0x0000007F); + timeStruct->H12 = (uint8_t)((temp & 0x00400000) >> 22); + + if (format == RTC_FORMAT_BIN) + { + timeStruct->hours = (uint8_t)RTC_Bcd2ConByte(timeStruct->hours); + timeStruct->minutes = (uint8_t)RTC_Bcd2ConByte(timeStruct->minutes); + timeStruct->seconds = (uint8_t)RTC_Bcd2ConByte(timeStruct->seconds); + } +} + +/*! + * @brief Read the RTC current Calendar Subseconds value + * + * @param None + * + * @retval RTC current Calendar Subseconds value + */ +uint32_t RTC_ReadSubSecond(void) +{ + uint32_t temp = 0; + temp = (uint32_t)(RTC->SUBSEC); + (void)(RTC->DATE); + return (temp); +} + +/*! + * @brief Config the RTC current time + * + * @param format: specifies the format to write + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: format in Bin + * @arg RTC_FORMAT_BCD: format in BCD + * + * @param dateStruct: Pointer to a RTC_DATE_T structure that + * contains the configuration DATE information for the RTC peripheral + * + * @retval None + */ +uint8_t RTC_ConfigDate(RTC_FORMAT_T format, RTC_DATE_T* dateStruct) +{ + uint8_t state = ERROR; + uint32_t temp = 0; + + if (format != RTC_FORMAT_BIN) + { + temp = RTC_Bcd2ConByte(dateStruct->month); + temp = RTC_Bcd2ConByte(dateStruct->date); + } + + if (format != RTC_FORMAT_BIN) + { + temp = (((uint32_t)(dateStruct->year) << 16) | \ + ((uint32_t)(dateStruct->month) << 8) | \ + ((uint32_t)(dateStruct->date)) | \ + ((uint32_t)(dateStruct->weekday) << 13)); + } + else + { + temp = (((uint32_t)RTC_ByteConBcd2(dateStruct->year) << 16) | \ + ((uint32_t)RTC_ByteConBcd2(dateStruct->month) << 8) | \ + ((uint32_t)RTC_ByteConBcd2(dateStruct->date)) | \ + ((uint32_t)(dateStruct->weekday) << 13)); + + } + + RTC_DisableWriteProtection(); + + if (RTC_EnableInit() == ERROR) + { + state = ERROR; + } + else + { + RTC->DATE = (uint32_t)(temp & 0x00FFFF3F); + RTC_DisableInit(); + + if (RTC->CTRL_B.RCMCFG == RESET) + { + if (RTC_WaitForSynchro() == ERROR) + { + state = ERROR; + } + else + { + state = SUCCESS; + } + } + else + { + state = SUCCESS; + } + } + + RTC_EnableWriteProtection(); + return state; +} + +/*! + * @brief Fills each dateStruct member with its default value + * + * @param dateStruct: Pointer to a RTC_DATE_T structure that + * contains the configuration DATE information for the RTC peripheral + * @retval None + */ +void RTC_ConfigDateStructInit(RTC_DATE_T* dateStruct) +{ + dateStruct->weekday = RTC_WEEKDAY_MONDAY; + dateStruct->month = RTC_MONTH_JANUARY; + dateStruct->date = 1; + dateStruct->year = 0; +} + +/*! + * @brief the RTC current date + * + * @param format: specifies the format to write + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: format in Bin + * @arg RTC_FORMAT_BCD: format in BCD + * + * @param dateStruct: Pointer to a RTC_DATE_T structure that + * contains the configuration DATE information for the RTC peripheral + * + * @retval None + */ +void RTC_ReadDate(RTC_FORMAT_T format, RTC_DATE_T* dateStruct) +{ + uint32_t temp = 0; + temp = (uint32_t)((RTC->DATE) & 0x00FFFF3F); + + dateStruct->year = (uint8_t)((temp & 0x00FF0000) >> 16); + dateStruct->month = (uint8_t)((temp & 0x00001F00) >> 8); + dateStruct->date = (uint8_t)(temp & 0x0000003F); + dateStruct->weekday = (uint8_t)((temp & 0x0000E000) >> 13); + + if (format == RTC_FORMAT_BIN) + { + dateStruct->year = (uint8_t)RTC_Bcd2ConByte(dateStruct->year); + dateStruct->month = (uint8_t)RTC_Bcd2ConByte(dateStruct->month); + dateStruct->date = (uint8_t)RTC_Bcd2ConByte(dateStruct->date); + dateStruct->weekday = (uint8_t)(dateStruct->weekday); + } +} + +/*! + * @brief Config the specified RTC ALRMA + * + * @param format: specifies the format to write + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: format in Bin + * @arg RTC_FORMAT_BCD: format in BCD + * + * @param alarmStruct: Pointer to a RTC_ALARM_T structure that + * contains the configuration ALRMA information for the RTC peripheral + * + * @retval None + */ +void RTC_ConfigAlarm(RTC_FORMAT_T format, RTC_ALARM_T* alarmStruct) +{ + uint32_t temp = 0; + + if (format != RTC_FORMAT_BCD) + { + if (RTC->CTRL_B.TIMEFCFG == BIT_RESET) + { + alarmStruct->time.H12 = 0x00; + } + } + else + { + if (RTC->CTRL_B.TIMEFCFG == BIT_RESET) + { + alarmStruct->time.H12 = 0x00; + } + else + { + temp = RTC_Bcd2ConByte(alarmStruct->time.hours); + } + + if (alarmStruct->AlarmDateWeekDaySel == RTC_WEEKDAY_SEL_DATE) + { + temp = RTC_ByteConBcd2(alarmStruct->AlarmDateWeekDay); + } + else + { + temp = RTC_ByteConBcd2(alarmStruct->AlarmDateWeekDay); + } + } + + if (format == RTC_FORMAT_BCD) + { + temp = (((uint32_t)(alarmStruct->time.hours) << 16) | \ + ((uint32_t)(alarmStruct->time.minutes) << 8) | \ + ((uint32_t)alarmStruct->time.seconds) | \ + ((uint32_t)(alarmStruct->time.H12) << 22) | \ + ((uint32_t)(alarmStruct->AlarmDateWeekDay) << 24) | \ + ((uint32_t)alarmStruct->AlarmDateWeekDaySel << 30) | \ + ((uint32_t)alarmStruct->AlarmMask)); + } + else + { + temp = (((uint32_t)RTC_ByteConBcd2(alarmStruct->time.hours) << 16) | \ + ((uint32_t)RTC_ByteConBcd2(alarmStruct->time.minutes) << 8) | \ + ((uint32_t)RTC_ByteConBcd2(alarmStruct->time.seconds)) | \ + ((uint32_t)(alarmStruct->time.H12) << 22) | \ + ((uint32_t)RTC_ByteConBcd2(alarmStruct->AlarmDateWeekDay) << 24) | \ + ((uint32_t)alarmStruct->AlarmDateWeekDaySel << 30) | \ + ((uint32_t)alarmStruct->AlarmMask)); + } + + RTC_DisableWriteProtection(); + RTC->ALRMA = temp; + RTC_EnableWriteProtection(); +} + +/*! + * @brief Fills each alarmStruct member with its default value + * + * @param alarmStruct: Pointer to a RTC_ALARM_T structure that + * contains the configuration ALRMA information for the RTC peripheral + * + * @retval None + */ +void RTC_ConfigAlarmStructInit(RTC_ALARM_T* alarmStruct) +{ + alarmStruct->time.hours = 1; + alarmStruct->time.minutes = 2; + alarmStruct->time.seconds = 3; + alarmStruct->time.H12 = RTC_H12_AM; + alarmStruct->AlarmDateWeekDay = 1; + alarmStruct->AlarmDateWeekDaySel = RTC_WEEKDAY_SEL_DATE; + alarmStruct->AlarmMask = RTC_MASK_NONE; +} + +/*! + * @brief Get the RTC ALRMA value and masks + * + * @param format: specifies the format to write + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: format in Bin + * @arg RTC_FORMAT_BCD: format in BCD + * + * @param alarmStruct: Pointer to a RTC_ALARM_T structure that + * contains the configuration ALRMA information for the RTC peripheral + * + * @retval None + */ +void RTC_ReadAlarm(RTC_FORMAT_T format, RTC_ALARM_T* alarmStruct) +{ + uint8_t day_d, day_u, hours_d, hours_u, minutes_d, minutes_u, seconds_d, seconds_u; + uint32_t day_mask, hours_mask, minutes_mask, seconds_mask; + + day_d = RTC->ALRMA_B.DAYT << 0x04; + day_u = RTC->ALRMA_B.DAYU; + hours_d = RTC->ALRMA_B.HRT << 0x04; + hours_u = RTC->ALRMA_B.HRU; + minutes_d = RTC->ALRMA_B.MINT << 0x04; + minutes_u = RTC->ALRMA_B.MINU; + seconds_d = RTC->ALRMA_B.SECT << 0x04; + seconds_u = RTC->ALRMA_B.SECU; + + day_mask = RTC->ALRMA_B.DATEMEN << 8; + hours_mask = RTC->ALRMA_B.HRMEN << 8; + minutes_mask = RTC->ALRMA_B.MINMEN << 8; + seconds_mask = RTC->ALRMA_B.SECMEN << 7; + + alarmStruct->time.hours = (uint8_t)(hours_d | hours_u); + alarmStruct->time.minutes = (uint8_t)(minutes_d | minutes_u); + alarmStruct->time.seconds = (uint8_t)(seconds_d | seconds_u); + alarmStruct->time.H12 = (uint8_t)(RTC->ALRMA_B.TIMEFCFG); + alarmStruct->AlarmDateWeekDay = (uint8_t)(day_d | day_u); + alarmStruct->AlarmDateWeekDaySel = (RTC_WEEKDAY_SEL_T)(RTC->ALRMA_B.WEEKSEL); + alarmStruct->AlarmMask = (uint32_t)(day_mask | hours_mask | minutes_mask | seconds_mask); + + if (format == RTC_FORMAT_BIN) + { + alarmStruct->time.hours = (uint8_t)RTC_Bcd2ConByte(alarmStruct->time.hours); + alarmStruct->time.minutes = (uint8_t)RTC_Bcd2ConByte(alarmStruct->time.minutes); + alarmStruct->time.seconds = (uint8_t)RTC_Bcd2ConByte(alarmStruct->time.seconds); + alarmStruct->AlarmDateWeekDay = (uint8_t)RTC_Bcd2ConByte(alarmStruct->AlarmDateWeekDay); + } +} + +/*! + * @brief Enable the RTC ALRMA. + * + * @param None + * + * @retval None + */ +void RTC_EnableAlarm(void) +{ + RTC_DisableWriteProtection(); + RTC->CTRL_B.ALREN = BIT_SET; + RTC_EnableWriteProtection(); +} + +/*! + * @brief Disable the the RTC ALRMA. + * + * @param None + * + * @retval None + */ +uint8_t RTC_DisableAlarm(void) +{ + __IO uint32_t count = 0x00; + RTC_DisableWriteProtection(); + RTC->CTRL_B.ALREN = BIT_RESET; + + while ((count != RTC_INITMODE_TIMEOUT) && ((RTC->STS_B.ALRWFLG) == BIT_RESET)) + { + count++; + } + + if ((RTC->STS_B.ALRWFLG) == BIT_RESET) + { + RTC_EnableWriteProtection(); + return ERROR; + } + else + { + RTC_EnableWriteProtection(); + return SUCCESS; + } +} + +/*! + * @brief Read the RTC ALRMA Subseconds value + * + * @param val: specifies the value for ALRMA Sub Second + * this value must less than 0x00007FFF + * + * @param mask: specifies the mask for ALRMA Sub Second + * this value must less than 0x0f + * + * @retval None + */ +void RTC_ConfigAlarmSubSecond(uint32_t val, uint8_t mask) +{ + RTC_DisableWriteProtection(); + RTC->ALRMASS_B.SUBSEC = val; + RTC->ALRMASS_B.MASKSEL = mask; + RTC_EnableWriteProtection(); +} + +/*! + * @brief Read the RTC ALRMA Subseconds value + * + * @param None + * + * @retval RTC ALRMA Subseconds value + */ +uint32_t RTC_ReadAlarmSubSecond(void) +{ + return (uint32_t)(RTC->ALRMASS_B.SUBSEC); +} + +/*! + * @brief Configure the RTC Wakeup clock source. + * + * @param wakeUpClock: Wakeup Clock source. + * This parameter can be one of the following values: + * @arg RTC_WAKEUP_CLOCK_RTCDIV16 + * @arg RTC_WAKEUP_CLOCK_RTCDIV8 + * @arg RTC_WAKEUP_CLOCK_RTCDIV4 + * @arg RTC_WAKEUP_CLOCK_RTCDIV2 + * @arg RTC_WAKEUP_CLOCK_CK_SPRE_16B + * @arg RTC_WAKEUP_CLOCK_CK_SPRE_17B + * + * @retval None + * + * @note It's only for APM32F072 and APM32F091 devices + */ +void RTC_ConfigWakeUpClock(RTC_WAKEUP_CLOCK_T wakeUpClock) +{ + RTC_DisableWriteProtection(); + RTC->CTRL_B.WUCLKSEL = wakeUpClock; + RTC_EnableWriteProtection(); +} + +/*! + * @brief Configure the RTC Wakeup counter value. + * + * @param wakeUpValue: Wakeup auto-reload value. + * This parameter can be a value from 0x0000 to 0xFFFF. + * + * @retval None + * + * @note The value from 0x0000 to 0xFFFF. + */ +void RTC_SetWakeUpValue(uint32_t wakeUpValue) +{ + RTC_DisableWriteProtection(); + RTC->AUTORLD = wakeUpValue; + RTC_EnableWriteProtection(); +} + +/*! + * @brief Read the RTC Wakeup counter value. + * + * @param None + * + * @retval The RTC WakeUp Counter value. + */ +uint32_t RTC_ReadWakeUpValue(void) +{ + return ((uint32_t)(RTC->AUTORLD & 0x0000FFFF)); +} + +/*! + * @brief Enable the RTC WakeUp timer. + * + * @param None + * + * @retval None + */ +void RTC_EnableWakeUp(void) +{ + RTC_DisableWriteProtection(); + RTC->CTRL_B.WUTEN = BIT_SET; + RTC_EnableWriteProtection(); +} + +/*! + * @brief Disable the RTC WakeUp timer. + * + * @param None + * + * @retval None + */ +uint8_t RTC_DisableWakeUp(void) +{ + __IO uint32_t count = 0x00; + RTC_DisableWriteProtection(); + + RTC->CTRL_B.WUTEN = BIT_RESET; + + while ((count != RTC_INITMODE_TIMEOUT) && ((RTC->STS_B.WUTWFLG) == BIT_RESET)) + { + count++; + } + + if ((RTC->STS_B.WUTWFLG) == BIT_RESET) + { + RTC_EnableWriteProtection(); + return ERROR; + } + else + { + RTC_EnableWriteProtection(); + return SUCCESS; + } +} + +/*! + * @brief Adds or substract one hour from the current time + * + * @param sav: specifies the DayLightSaving + * This parameter can be one of the following values: + * @arg RTC_DLS_SUB1H + * @arg RTC_DLS_ADD1H + * + * @param bit: specifies the DayLightSaving + * This parameter can be one of the following values: + * @arg RTC_SO_RESET + * @arg RTC_SO_SET + * + * @retval None + */ +void RTC_ConfigDayLightSaving(RTC_DAYLIGHT_SAVING_T sav, RTC_STORE_OPERATION_T bit) +{ + RTC_DisableWriteProtection(); + + if (sav == RTC_DLS_ADD1H) + { + RTC->CTRL_B.STCCFG = (uint32_t)BIT_SET; + RTC->CTRL_B.WTCCFG = (uint32_t)BIT_RESET; + } + else + { + RTC->CTRL_B.STCCFG = (uint32_t)BIT_RESET; + RTC->CTRL_B.WTCCFG = (uint32_t)BIT_SET; + } + + RTC->CTRL_B.BAKP = (uint32_t)bit; + RTC_EnableWriteProtection(); +} + +/*! + * @brief Returns the RTC Day Light Saving stored operation + * + * @param None + * + * @retval RTC Day Light Saving stored operation + */ +uint32_t RTC_ReadStoreOperation(void) +{ + return (RTC->CTRL_B.BAKP); +} + +/*! + * @brief Enables the RTC TimeStamp functionality with the + * specified time stamp pin stimulating edge + * + * @param opsel: specifies RTC TimeStamp functionality + * This parameter can be one of the following values: + * @arg RTC_OPSEL_DISABLE + * @arg RTC_OPSEL_ALARMA +* @arg RTC_OPSEL_WAKEUP: available only for APM32F072 and APM32F091 devices + * + * @param opp: specified time stamp pin stimulating edge + * This parameter can be one of the following values: + * @arg RTC_OPP_HIGH + * @arg RTC_OPP_LOW + * + * @retval None + */ +void RTC_ConfigOutput(RTC_OPSEL_T opsel, RTC_OPP_T opp) +{ + RTC_DisableWriteProtection(); + RTC->CTRL_B.OUTSEL = (uint32_t)opsel; + RTC->CTRL_B.POLCFG = (uint32_t)opp; + RTC_EnableWriteProtection(); +} + +/*! + * @brief Enable the RTC clock to be output through the relative pin + * + * @param None + * + * @retval None + */ +void RTC_EnableCalibOutput(void) +{ + RTC_DisableWriteProtection(); + RTC->CTRL_B.CALOEN = BIT_SET; + RTC_EnableWriteProtection(); +} + +/*! + * @brief Disable the RTC clock to be output through the relative pin + * + * @param None + * + * @retval None + */ +void RTC_DisableCalibOutput(void) +{ + RTC_DisableWriteProtection(); + RTC->CTRL_B.CALOEN = BIT_RESET; + RTC_EnableWriteProtection(); +} + +/*! + * @brief Configure the Calibration Pinout Selection (1Hz or 512Hz). + * + * @param calib: Select the Calibration output Selection . + * This parameter can be one of the following values: + * @arg RTC_CALIBOUTPUT_512Hz + * @arg RTC_CALIBOUTPUT_1Hz + * + * @retval None + */ +void RTC_ConfigCalibOutput(RTC_CALIB_OUTPUT_T calib) +{ + RTC_DisableWriteProtection(); + RTC->CTRL_B.CALOSEL = (uint32_t)calib; + RTC_EnableWriteProtection(); +} + +/*! + * @brief Configures the Synchronization Shift Control Settings. + * + * @param period: Select the Smooth Calibration period. + * This parameter can be can be one of the following values: + * @arg RTC_SCP_16SEC: The smooth calibration periode is 16. + * @arg RTC_SCP_8SEC: The smooth calibartion periode is 8s. + * + * @param bit: Select to Set or reset the CALP bit. + * This parameter can be one of the following values: + * @arg RTC_SCPP_RESET: Add one RTCCLK puls every 2**11 pulses. + * @arg RTC_SCPP_SET: No RTCCLK pulses are added. + * + * @param value: Select the value of CALM[8:0] bits. + * This parameter can be one any value from 0 to 0x000001FF. + * + * @retval SUCCESS or ERROR + */ +uint8_t RTC_ConfigSmoothCalib(RTC_SCP_T period, RTC_SCPP_T bit, uint32_t value) +{ + uint8_t state = ERROR; + uint32_t count = 0; + + RTC_DisableWriteProtection(); + + if (RTC->STS_B.RCALPFLG != BIT_RESET) + { + while ((RTC->STS_B.RCALPFLG != BIT_RESET) && (count != RTC_RECALPF_TIMEOUT)) + { + count++; + } + } + + if (RTC->STS_B.RCALPFLG == BIT_RESET) + { + if (period == RTC_SCP_16SEC) + { + RTC->CAL = ((((uint32_t)bit << 15) | \ + (uint32_t)BIT_SET << 13) | \ + (uint32_t)value); + } + else + { + RTC->CAL = ((((uint32_t)bit << 15) | \ + (uint32_t)BIT_SET << 14) | \ + (uint32_t)value); + } + + state = SUCCESS; + } + else + { + state = ERROR; + } + + RTC_EnableWriteProtection(); + return (state); +} + +/*! + * @brief Enables the RTC TimeStamp functionality with the + * specified time stamp pin stimulating edge + * + * @param edge: Specifies the pin edge on which the TimeStamp is activated. + * This paramete can be one of the following: + * @arg RTC_TIME_STAMPEDGE_RISING: the Time stamp event occurs on the rising + * edge of the related pin. + * @arg RTC_TIME_STAMPEDGE_FALLING: the Time stamp event occurs on the + * falling edge of the related pin. + * @retval None + */ +void RTC_EnableTimeStamp(RTC_TIMESTAMP_EDGE_T edge) +{ + RTC_DisableWriteProtection(); + RTC->CTRL_B.TSEN = BIT_SET; + RTC->CTRL_B.TSETECFG = (uint32_t)edge; + RTC_EnableWriteProtection(); +} + +/*! + * @brief Disables the RTC TimeStamp functionality with the + * specified time stamp pin stimulating edge + * + * @param edge: Specifies the pin edge on which the TimeStamp is activated. + * This paramete can be one of the following: + * @arg RTC_TIME_STAMPEDGE_RISING: the Time stamp event occurs on the rising + * edge of the related pin. + * @arg RTC_TIME_STAMPEDGE_FALLING: the Time stamp event occurs on the + * falling edge of the related pin. + * + * @retval None + */ +void RTC_DisableTimeStamp(RTC_TIMESTAMP_EDGE_T edge) +{ + RTC_DisableWriteProtection(); + RTC->CTRL_B.TSEN = BIT_RESET; + RTC->CTRL_B.TSETECFG = (uint32_t)edge; + RTC_EnableWriteProtection(); +} + +/*! + * @brief Read the RTC TimeStamp value and masks + * + * @param format: specifies the format of the output parameters. + * This parameter can be one of the following values: + * @arg RTC_Format_BIN: data in Binary format + * @arg RTC_Format_BCD: data in BCD format + * + * @param timeStruct: pointer to a RTC_TIME_T structure that will + * contains the TimeStamp time values. + * + * @param dateStruct: pointer to a RTC_DATE_T structure that will + * contains the TimeStamp date values. + * + * @retval None + */ +void RTC_ReadTimeDate(RTC_FORMAT_T format, RTC_TIME_T* timeStruct, RTC_DATE_T* dateStruct) +{ + uint32_t temptime = 0, tempdate = 0; + temptime = (uint32_t)((RTC->TSTIME) & 0x007F7F7F); + tempdate = (uint32_t)((RTC->TSDATE) & 0x00FFFF3F); + + timeStruct->hours = (uint8_t)((temptime & 0x003F0000) >> 16); + timeStruct->minutes = (uint8_t)((temptime & 0x00007F00) >> 8); + timeStruct->seconds = (uint8_t)(temptime & 0x0000007F); + timeStruct->H12 = (uint8_t)((temptime & 0x00400000) >> 22); + + dateStruct->year = 0; + dateStruct->month = (uint8_t)((tempdate & 0x00001F00) >> 8); + dateStruct->date = (uint8_t)(tempdate & 0x0000003F); + dateStruct->weekday = (uint8_t)((tempdate & 0x0000E000) >> 13); + + if (format == RTC_FORMAT_BIN) + { + timeStruct->hours = (uint8_t)RTC_Bcd2ConByte(timeStruct->hours); + timeStruct->minutes = (uint8_t)RTC_Bcd2ConByte(timeStruct->minutes); + timeStruct->seconds = (uint8_t)RTC_Bcd2ConByte(timeStruct->seconds); + + dateStruct->month = (uint8_t)RTC_Bcd2ConByte(dateStruct->month); + dateStruct->date = (uint8_t)RTC_Bcd2ConByte(dateStruct->date); + dateStruct->weekday = (uint8_t)(dateStruct->weekday); + } +} + +/*! + * @brief Get the RTC timestamp Subseconds value + * + * @param None + * + * @retval RTC current timestamp Subseconds value + */ +uint32_t RTC_ReadTimeStampSubSecond(void) +{ + return (uint32_t)(RTC->TSSUBSEC); +} + +/*! + * @brief Configures the select Tamper pin edge + * + * @param tamper: Selected tamper pin. + * This parameter can be one of the following values: + * @arg RTC_TAMPER_1: Select Tamper 1. + * @arg RTC_TAMPER_2: Select Tamper 2. + * @arg RTC_TAMPER_3: Select Tamper 3. (Only for APM32F072 and APM32F091 devices) + * + * @param trigger: Specifies the trigger on the tamper pin that stimulates tamper event. + * This parameter can be one of the following values: + * @arg RTC_TAMPER_TRIGGER_RISINGEDGE: Rising Edge of the tamper pin causes tamper event. + * @arg RTC_TAMPER_TRIGGER_FALLINGEDGE: Falling Edge of the tamper pin causes tamper event. + * @arg RTC_TAMPER_TRIGGER_LOWLEVEL: Low Level of the tamper pin causes tamper event. + * @arg RTC_TAMPER_TRIGGER_HIGHLEVEL: High Level of the tamper pin causes tamper event. + * + * @retval None + */ +void RTC_ConfigTamperTrigger(RTC_TAMPER_T tamper, RTC_TAMPER_TRIGGER_T trigger) +{ + if (trigger == RTC_TAMPER_TRIGGER_RISINGEDGE) + { + if (tamper == RTC_TAMPER_1) + { + RTC->TACFG_B.TP1ALCFG = BIT_RESET; + } + if (tamper == RTC_TAMPER_2) + { + RTC->TACFG_B.TP2ALCFG = BIT_RESET; + } + if (tamper == RTC_TAMPER_3) + { + RTC->TACFG_B.TP3ALCFG = BIT_RESET; + } + } + else + { + if (tamper == RTC_TAMPER_1) + { + RTC->TACFG_B.TP1ALCFG = BIT_SET; + } + if (tamper == RTC_TAMPER_2) + { + RTC->TACFG_B.TP2ALCFG = BIT_SET; + } + if (tamper == RTC_TAMPER_3) + { + RTC->TACFG_B.TP3ALCFG = BIT_SET; + } + } +} + +/*! + * @brief Enables the Tamper detection + * + * @param tamper: Selected tamper pin. + * This parameter can be one of the following values: + * @arg RTC_TAMPER_1: Select Tamper 1. + * @arg RTC_TAMPER_2: Select Tamper 2. + * @arg RTC_TAMPER_3: Select Tamper 3.(Only for APM32F072 and APM32F091 devices) + * + * @retval None + */ +void RTC_EnableTamper(RTC_TAMPER_T tamper) +{ + if (tamper == RTC_TAMPER_1) + { + RTC->TACFG_B.TP1EN = BIT_SET; + } + if (tamper == RTC_TAMPER_2) + { + RTC->TACFG_B.TP2EN = BIT_SET; + } + if (tamper == RTC_TAMPER_3) + { + RTC->TACFG_B.TP3EN = BIT_SET; + } + +} + +/*! + * @brief Disables the Tamper detection + * + * @param tamper: Selected tamper pin. + * This parameter can be any combination of the following values: + * @arg RTC_TAMPER_1: Select Tamper 1. + * @arg RTC_TAMPER_2: Select Tamper 2. + * @arg RTC_TAMPER_3: Select Tamper 3.(Only for APM32F072 and APM32F091 devices) + * + * @retval None + */ +void RTC_DisableTamper(RTC_TAMPER_T tamper) +{ + if (tamper == RTC_TAMPER_1) + { + RTC->TACFG_B.TP1EN = BIT_RESET; + } + if (tamper == RTC_TAMPER_2) + { + RTC->TACFG_B.TP2EN = BIT_RESET; + } + if (tamper == RTC_TAMPER_3) + { + RTC->TACFG_B.TP3EN = BIT_RESET; + } +} + +/*! + * @brief Configures the Tampers Filter + * + * @param filter: Specifies the tampers filter. + * This parameter can be one of the following values: + * @arg RTC_TAMPER_FILTER_DISABLE: Tamper filter is disabled. + * @arg RTC_TAMPER_FILTER_2SAMPLE: Tamper is activated after 2 consecutive samples at the active level + * @arg RTC_TAMPER_FILTER_4SAMPLE: Tamper is activated after 4 consecutive samples at the active level + * @arg RTC_TAMPER_FILTER_8SAMPLE: Tamper is activated after 8 consecutive samples at the active level + * + * + * @retval None + */ +void RTC_ConfigFilter(RTC_TAMPER_FILTER_T filter) +{ + RTC->TACFG_B.TPFCSEL = (uint32_t)filter; +} + +/*! + * @brief Configures the Tampers Sampling Frequency + * + * @param freq: Specifies the tampers Sampling Frequency. + * This parameter can be one of the following values: + * @arg RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV32768: Each of the tamper inputs are sampled + * with a frequency = RTCCLK / 32768 + * @arg RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV16384: Each of the tamper inputs are sampled + * with a frequency = RTCCLK / 16384 + * @arg RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV8192: Each of the tamper inputs are sampled + * with a frequency = RTCCLK / 8192 + * @arg RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV4096: Each of the tamper inputs are sampled + * with a frequency = RTCCLK / 4096 + * @arg RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV2048: Each of the tamper inputs are sampled + * with a frequency = RTCCLK / 2048 + * @arg RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV1024: Each of the tamper inputs are sampled + * with a frequency = RTCCLK / 1024 + * @arg RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV512: Each of the tamper inputs are sampled + * with a frequency = RTCCLK / 512 + * @arg RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV256: Each of the tamper inputs are sampled + * with a frequency = RTCCLK / 256 + * + * @retval None + */ +void RTC_ConfigSamplingFreq(RTC_TAMPER_SAMPLING_FREQ_T freq) +{ + RTC->TACFG_B.TPSFSEL = (uint32_t)freq; +} + +/*! + * @brief Configures the Precharge Duration + * + * @param duration: Specifies the Tampers Pins input Precharge Duration. + * This parameter can be one of the following values: + * @arg RTC_PRECHARGEDURATION_1RTCCLK: Tamper pins are pre-charged before sampling during 1 RTCCLK cycle + * @arg RTC_PRECHARGEDURATION_2RTCCLK: Tamper pins are pre-charged before sampling during 2 RTCCLK cycle + * @arg RTC_PRECHARGEDURATION_4RTCCLK: Tamper pins are pre-charged before sampling during 4 RTCCLK cycle + * @arg RTC_PRECHARGEDURATION_8RTCCLK: Tamper pins are pre-charged before sampling during 8 RTCCLK cycle + * + * @retval None + */ +void RTC_PinsPrechargeDuration(RTC_PRECHARGE_DURATION_T duration) +{ + RTC->TACFG_B.TPPRDUSEL = (uint32_t)duration; +} + +/*! + * @brief Enables the TimeStamp on Tamper Detection Event + * + * @param None + * + * @retval None + */ +void RTC_EnableTDE(void) +{ + RTC->TACFG_B.TPTSEN = BIT_SET; +} + +/*! + * @brief Disable the TimeStamp on Tamper Detection Event + * + * @param None + * + * @retval None + */ +void RTC_DisableTDE(void) +{ + RTC->TACFG_B.TPTSEN = BIT_RESET; +} + +/*! + * @brief Enable precharge of the selected Tamper pin + * + * @param None + * + * @retval None + */ +void RTC_EnablePullUp(void) +{ + RTC->TACFG_B.TPPUDIS = BIT_SET; +} + +/*! + * @brief Disable precharge of the selected Tamper pin + * + * @param None + * + * @retval None + */ +void RTC_DisablePullUp(void) +{ + RTC->TACFG_B.TPPUDIS = BIT_RESET; +} + +/*! + * @brief Writes a data in RTC Backup data. + * + * @param backup: RTC Backup data Register number. + * This parameter can be one of the following values: + * @arg RTC_BAKP_DATA0 + * @arg RTC_BAKP_DATA1 + * @arg RTC_BAKP_DATA2 + * @arg RTC_BAKP_DATA3 + * @arg RTC_BAKP_DATA4 + * @param data: Data to be written in the specified RTC Backup data register. + * + * @retval None + */ +void RTC_WriteBackup(RTC_BAKP_DATA_T backup, uint32_t data) +{ + switch (backup) + { + case 0: + RTC->BAKP0 = data; + break; + + case 1: + RTC->BAKP1 = data; + break; + + case 2: + RTC->BAKP2 = data; + break; + + case 3: + RTC->BAKP3 = data; + break; + + case 4: + RTC->BAKP4 = data; + break; + + default: + break; + } +} + +/*! + * @brief Reads a data in RTC Backup data. + * + * @param backup: RTC Backup data Register number. + * This parameter can be one of the following values: + * @arg RTC_BAKP_DATA0 + * @arg RTC_BAKP_DATA1 + * @arg RTC_BAKP_DATA2 + * @arg RTC_BAKP_DATA3 + * @arg RTC_BAKP_DATA4 + * + * @retval None + */ +uint32_t RTC_ReadBackup(RTC_BAKP_DATA_T backup) +{ + uint32_t data; + + switch (backup) + { + case 0: + data = RTC->BAKP0; + break; + + case 1: + data = RTC->BAKP1; + break; + + case 2: + data = RTC->BAKP2; + break; + + case 3: + data = RTC->BAKP3; + break; + + case 4: + data = RTC->BAKP4; + break; + + default: + break; + } + + return (data); +} + +/*! + * @brief Configures the RTC Output Pin mode + * + * @param output: specifies the RTC Output (PC13) pin mode. + * This parameter can be one of the following values: + * @arg RTC_OPENDRAIN: RTC Output (PC13) is configured in + * Open Drain mode. + * @arg RTC_PUSHPULL: RTC Output (PC13) is configured in + * Push Pull mode. + * + * @retval None + */ +void RTC_ConfigOutputType(RTC_OUTPUT_T output) +{ + RTC->TACFG_B.PC13VAL = (uint32_t)output; +} + +/*! + * @brief Configures the Synchronization Shift Control Settings. + * + * @param add1S: Select to add or not 1 second to the time Calendar. + * This parameter can be one of the following values : + * @arg RTC_SHIFTADD1S_SET: Add one second to the clock calendar. + * @arg RTC_SHIFTADD1S_RESET: No effect. + * + * @param subFS: Select the number of Second Fractions to Substitute. + * This parameter can be one any value from 0 to 0x7FFF. + * + * @retval SUCCESS or ERROR + */ +uint8_t RTC_ConfigSynchroShift(RTC_SHIFT_ADD1S_T add1S, uint32_t subFS) +{ + uint8_t state = ERROR; + uint32_t shpfcount = 0; + RTC_DisableWriteProtection(); + + if (RTC->STS_B.SOPFLG != BIT_RESET) + { + while ((RTC->STS_B.SOPFLG != BIT_RESET) && (shpfcount != RTC_SHPF_TIMEOUT)) + { + shpfcount++; + } + } + + if (RTC->STS_B.SOPFLG == BIT_RESET) + { + if (RTC->CTRL_B.RCLKDEN == BIT_RESET) + { + RTC->SHIFT_B.ADD1SECEN = add1S; + RTC->SHIFT_B.SFSEC = subFS; + + if (RTC_WaitForSynchro() == ERROR) + { + state = ERROR; + } + else + { + state = SUCCESS; + } + } + else + { + state = ERROR; + } + } + else + { + state = ERROR; + } + + RTC_EnableWriteProtection(); + return (state); +} + +/*! + * @brief Enable RTC interrupts. + * + * @param interrupt: specifies the RTC interrupt sources to be enabled + * This parameter can be any combination of the following values: + * @arg RTC_INT_ALR: ALRMA A interrupt mask + * @arg RTC_INT_WT: WakeUp Timer interrupt mask(only APM32F072 and APM32F091 devices) + * @arg RTC_INT_TS: Time Stamp interrupt mask + * @arg RTC_INT_TAMP: Tamper event interrupt mask + * + * @retval None + */ +void RTC_EnableInterrupt(uint32_t interrupt) +{ + RTC_DisableWriteProtection(); + RTC->CTRL |= (uint32_t)(interrupt & ~0x00000004); + RTC->TACFG |= (uint32_t)(interrupt & 0x00000004); + RTC_EnableWriteProtection(); +} + +/*! + * @brief Disable RTC interrupts. + * + * @param interrupt: specifies the RTC interrupt sources to be disable + * This parameter can be any combination of the following values: + * @arg RTC_INT_ALR: ALRMA A interrupt mask + * @arg RTC_INT_WT: WakeUp Timer interrupt mask(only APM32F072 and APM32F091 devices) + * @arg RTC_INT_TS: Time Stamp interrupt mask + * @arg RTC_INT_TAMP: Tamper event interrupt mask + * + * @retval None + */ +void RTC_DisableInterrupt(uint32_t interrupt) +{ + RTC_DisableWriteProtection(); + RTC->CTRL &= (uint32_t)~(interrupt & ~0x00000004); + RTC->TACFG &= (uint32_t)~(interrupt & 0x00000004); + RTC_EnableWriteProtection(); +} + +/*! + * @brief Read interrupt flag bit is set + * + * @param flag: specifies the flag to read. + * This parameter can be one of the following values: + * @arg RTC_INT_FLAG_ALR: ALRMA interrupt + * @arg RTC_INT_FLAG_TS: Time Stamp interrupt + * @arg RTC_INT_FLAG_WT: WakeUp Timer interrupt (only APM32F072 and APM32F091 devices) + * @arg RTC_INT_FLAG_TAMP1: Tamper1 event interrupt + * @arg RTC_INT_FLAG_TAMP2: Tamper2 event interrupt + * @arg RTC_INT_FLAG_TAMP3: Tamper3 event interrupt (Only for APM32F072 and APM32F091 devices) + * @retval The new state of flag (SET or RESET). + */ +uint8_t RTC_ReadIntFlag(RTC_INT_FLAG_T flag) +{ + uint32_t intEnable; + uint32_t intStatus; + + if (flag & 0x04) + { + intEnable = (uint32_t)RTC->TACFG_B.TPIEN; + intStatus = (uint32_t)(RTC->STS & (flag >> 4)); + } + else + { + intEnable = (uint32_t)RTC->CTRL; + intStatus = (uint32_t)(RTC->STS & (flag >> 4)); + } + + if (intEnable && intStatus) + { + return SET; + } + + return RESET; +} + +/*! + * @brief Clear RTC interrupt flag bit + * + * @param flag: specifies the flag to clear. + * This parameter can be any combination the following values: + * @arg RTC_INT_FLAG_ALR: ALRMA interrupt + * @arg RTC_INT_FLAG_TS: Time Stamp interrupt + * @arg RTC_INT_FLAG_WT: WakeUp Timer interrupt (only APM32F072 and APM32F091 devices) + * @arg RTC_INT_FLAG_TAMP1: Tamper1 event interrupt + * @arg RTC_INT_FLAG_TAMP2: Tamper2 event interrupt + * @arg RTC_INT_FLAG_TAMP3: Tamper3 event interrupt (Only for APM32F072 and APM32F091 devices) + * @retval The new state of flag (SET or RESET). + */ +void RTC_ClearIntFlag(uint32_t flag) +{ + RTC->STS &= (uint32_t) ~(flag >> 4); +} + +/*! + * @brief Checks whether the specified RTC flag is set or not. + * + * @param flag: specifies the flag to check. + * This parameter can be one of the following values: + * @arg RTC_FLAG_ISF + * @arg RTC_FLAG_RSF + * @arg RTC_FLAG_INTF + * @arg RTC_FLAG_ALRF + * @arg RTC_FLAG_WTF (only APM32F072 and APM32F091 devices) + * @arg RTC_FLAG_TSF + * @arg RTC_FLAG_TSOF + * @arg RTC_FLAG_TP1F + * @arg RTC_FLAG_TP2F + * @arg RTC_FLAG_TP3F (only APM32F072 and APM32F091 devices) + * @arg RTC_FLAG_RPF + * @retval The new state of RTC_FLAG (SET or RESET). + */ +uint8_t RTC_ReadStatusFlag(RTC_FLAG_T flag) +{ + return (RTC->STS & flag) ? SET : RESET; +} + +/*! + * @brief Clears the RTC's status flags. + * @param flag: specifies the RTC flag to clear. + * This parameter can be any combination of the following values: + * @arg RTC_FLAG_TP3F: Tamper 3 event flag (only APM32F072 and APM32F091 devices) + * @arg RTC_FLAG_TP2F: Tamper 2 event flag + * @arg RTC_FLAG_TP1F: Tamper 1 event flag + * @arg RTC_FLAG_TSOF: Time Stamp Overflow flag + * @arg RTC_FLAG_TSF : Time Stamp event flag + * @arg RTC_FLAG_WTF £ºWakeUp Timer flag (only APM32F072 and APM32F091 devices) + * @arg RTC_FLAG_ALRF: ALRMA A flag + * @arg RTC_FLAG_RSF: Registers Synchronized flag + */ +void RTC_ClearStatusFlag(uint32_t flag) +{ + RTC->STS &= (uint32_t)~flag; +} + +/*! + * @brief Converts a 2 digit decimal to BCD format + * + * @param val: Byte to be converted + * + * @retval Converted byte + */ +static uint8_t RTC_ByteConBcd2(uint8_t val) +{ + uint8_t bcdhigh = 0; + + while (val >= 10) + { + bcdhigh++; + val -= 10; + } + + return ((uint8_t)(bcdhigh << 4) | val); +} + +/*! + * @brief Convert from 2 digit BCD to Binary + * + * @param val: BCD value to be converted + * + * @retval Converted word + */ +static uint8_t RTC_Bcd2ConByte(uint8_t val) +{ + uint8_t tmp = 0; + tmp = ((uint8_t)(val & (uint8_t)0xF0) >> (uint8_t)0x4) * 10; + return (tmp + (val & (uint8_t)0x0F)); +} + +/**@} end of group RTC_Functions*/ +/**@} end of group RTC_Driver*/ +/**@} end of group APM32F0xx_StdPeriphDriver*/ + diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_spi.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_spi.c new file mode 100644 index 0000000000..3cbb93d35f --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_spi.c @@ -0,0 +1,786 @@ +/*! + * @file apm32f0xx_spi.c + * + * @brief This file contains all the functions for the SPI peripheral + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +#include "apm32f0xx_spi.h" +#include "apm32f0xx_rcm.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup SPI_Driver SPI Driver + @{ +*/ + +/** @defgroup SPI_Macros Macros + @{ +*/ + +/**@} end of group SPI_Macros */ + +/** @defgroup SPI_Enumerations Enumerations + @{ +*/ + +/**@} end of group SPI_Enumerations */ + +/** @defgroup SPI_Structures Structures + @{ +*/ + +/**@} end of group SPI_Structures */ + +/** @defgroup SPI_Variables Variables + @{ +*/ + +/**@} end of group SPI_Variables */ + +/** @defgroup SPI_Functions Functions + @{ +*/ + +/*! + * @brief Set the SPI peripheral registers to their default reset values + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_Reset(SPI_T* spi) +{ + if (spi == SPI1) + { + RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_SPI1); + RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_SPI1); + } + else + { + RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_SPI2); + RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_SPI2); + } +} + +/*! + * @brief Config the SPI peripheral according to the specified parameters in the adcConfig + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @param spiConfig: Pointer to a SPI_Config_T structure that + * contains the configuration information for the SPI peripheral + * + * @retval None + */ +void SPI_Config(SPI_T* spi, SPI_Config_T* spiConfig) +{ + spi->CTRL1_B.MSMCFG = spiConfig->mode; + spi->CTRL2_B.DSCFG = spiConfig->length; + spi->CTRL1_B.CPHA = spiConfig->phase; + spi->CTRL1_B.CPOL = spiConfig->polarity; + spi->CTRL1_B.SSEN = spiConfig->slaveSelect; + spi->CTRL1_B.LSBSEL = spiConfig->firstBit; + + spi->CTRL1 &= (uint16_t)~0xC400; + spi->CTRL1 |= (uint32_t)spiConfig->direction; + + spi->CTRL1_B.BRSEL = spiConfig->baudrateDiv; + + spi->CRCPOLY |= spiConfig->crcPolynomial; +} + +/*! + * @brief Config the SPI peripheral according to the specified parameters in the adcConfig + * + * @param spi: Select the the SPI peripheral.It can be SPI1 + * + * @param i2sConfig: Pointer to a SPI_Config_T structure that + * contains the configuration information for the SPI peripheral + * + * @retval None + */ +void I2S_Config(SPI_T* spi, I2S_Config_T* i2sConfig) +{ + uint16_t i2sDiv = 2, i2sOdd = 0, i2sLen = 1; + uint32_t sourceClock = 0, value = 0, temp = 0; + + spi->I2SPSC = 0x0002; + spi->I2SCFG &= 0xF040; + temp = spi->I2SCFG; + + if (i2sConfig->audioDiv == I2S_AUDIO_DIV_DEFAULT) + { + i2sDiv = (uint16_t)2; + i2sOdd = (uint16_t)0; + } + else + { + if (i2sConfig->length == I2S_DATA_LENGTH_16B) + { + i2sLen = 1; + } + else + { + i2sLen = 2; + } + + sourceClock = RCM_ReadSYSCLKFreq(); + + if (i2sConfig->MCLKOutput == I2S_MCLK_OUTPUT_ENABLE) + { + value = (uint16_t)(((((sourceClock / 256) * 10) / i2sConfig->audioDiv)) + 5); + } + else + { + value = (uint16_t)(((((sourceClock / (32 * i2sLen)) * 10) / i2sConfig->audioDiv)) + 5); + } + + value = value / 10; + i2sOdd = (uint16_t)(value & (uint16_t)0x0001); + i2sDiv = (uint16_t)((value - i2sOdd) / 2); + } + + if ((i2sDiv < 2) || (i2sDiv > 0xFF)) + { + i2sDiv = 2; + i2sOdd = 0; + } + + spi->I2SPSC_B.I2SPSC = i2sDiv; + spi->I2SPSC_B.ODDPSC = i2sOdd; + spi->I2SPSC_B.MCOEN = i2sConfig->MCLKOutput; + spi->I2SCFG_B.MODESEL = BIT_SET; + spi->I2SCFG_B.I2SMOD = i2sConfig->mode; + spi->I2SCFG_B.CPOL = i2sConfig->polarity; + + temp = (uint16_t)((uint16_t)i2sConfig->standard | (uint16_t)i2sConfig->length); + spi->I2SCFG |= temp; +} + +/*! + * @brief Fills each spiConfig member with its default value + * + * @param spiConfig: Pointer to a SPI_Config_T structure which will be initialized + * + * @retval None + */ +void SPI_ConfigStructInit(SPI_Config_T* spiConfig) +{ + spiConfig->mode = SPI_MODE_SLAVE; + spiConfig->length = SPI_DATA_LENGTH_8B; + spiConfig->phase = SPI_CLKPHA_1EDGE; + spiConfig->polarity = SPI_CLKPOL_HIGH; + spiConfig->slaveSelect = SPI_SSC_DISABLE; + spiConfig->firstBit = SPI_FIRST_BIT_MSB; + spiConfig->direction = SPI_DIRECTION_2LINES_FULLDUPLEX; + spiConfig->baudrateDiv = SPI_BAUDRATE_DIV_2; + spiConfig->crcPolynomial = 7; +} + +/*! + * @brief Fills each i2sConfig member with its default value + * + * @param i2sConfig: Pointer to a SPI_Config_T structure which will be initialized + * + * @retval None + */ +void I2S_ConfigStructInit(I2S_Config_T* i2sConfig) +{ + i2sConfig->mode = I2S_MODE_SLAVER_TX; + i2sConfig->standard = I2S_STANDARD_PHILIPS; + i2sConfig->length = I2S_DATA_LENGTH_16B; + i2sConfig->MCLKOutput = I2S_MCLK_OUTPUT_DISABLE; + i2sConfig->audioDiv = I2S_AUDIO_DIV_DEFAULT; + i2sConfig->polarity = I2S_CLKPOL_LOW; +} + +/*! + * @brief Enable the SPI peripheral + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_Enable(SPI_T* spi) +{ + spi->CTRL1_B.SPIEN = BIT_SET; +} + +/*! + * @brief Disable the SPI peripheral + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_Disable(SPI_T* spi) +{ + spi->CTRL1_B.SPIEN = BIT_RESET; +} + +/*! + * @brief Enable the SPI peripheral + * + * @param spi: Select the the SPI peripheral.It can be SPI1 + * + * @retval None + * + * @note Not supported for APM32F030 devices. + */ +void I2S_Enable(SPI_T* spi) +{ + spi->I2SCFG_B.I2SEN = BIT_SET; +} + +/*! + * @brief Disable the SPI peripheral + * + * @param spi: Select the the SPI peripheral.It can be SPI1 + * + * @retval None + * + * @note Not supported for APM32F030 devices. + */ +void I2S_Disable(SPI_T* spi) +{ + spi->I2SCFG_B.I2SEN = BIT_RESET; +} + +/*! + * @brief Enable the frame format mode + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_EnableFrameFormatMode(SPI_T* spi) +{ + spi->CTRL2_B.FRFCFG = BIT_SET; +} + +/*! + * @brief Disable the frame format mode + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_DisableFrameFormatMode(SPI_T* spi) +{ + spi->CTRL2_B.FRFCFG = BIT_RESET; +} + +/*! + * @brief Configures the SPI data length + * + * @param length: specifies the SPI length + * The parameter can be one of following values: + * @arg SPI_DATA_LENGTH_4B: Set data length to 4 bits + * @arg SPI_DATA_LENGTH_5B: Set data length to 5 bits + * @arg SPI_DATA_LENGTH_6B: Set data length to 6 bits + * @arg SPI_DATA_LENGTH_7B: Set data length to 7 bits + * @arg SPI_DATA_LENGTH_8B: Set data length to 8 bits + * @arg SPI_DATA_LENGTH_9B: Set data length to 9 bits + * @arg SPI_DATA_LENGTH_10B: Set data length to 10 bits + * @arg SPI_DATA_LENGTH_11B: Set data length to 11 bits + * @arg SPI_DATA_LENGTH_12B: Set data length to 12 bits + * @arg SPI_DATA_LENGTH_13B: Set data length to 13 bits + * @arg SPI_DATA_LENGTH_14B: Set data length to 14 bits + * @arg SPI_DATA_LENGTH_15B: Set data length to 15 bits + * @arg SPI_DATA_LENGTH_16B: Set data length to 16 bits + * + * @retval None + */ +void SPI_ConfigDatalength(SPI_T* spi, uint8_t length) +{ + spi->CTRL2_B.DSCFG = (uint8_t)length; +} + +/*! + * @brief Configures the FIFO reception threshold + * + * @param threshold: selects the SPI FIFO reception threshold + * The parameter can be one of following values: + * @arg SPI_RXFIFO_HALF: FIFO level is greater than or equal to 1/2 (16-bit) + * @arg SPI_RXFIFO_QUARTER: FIFO level is greater than or equal to 1/4 (8-bit) + * + * @retval None + */ +void SPI_ConfigFIFOThreshold(SPI_T* spi, SPI_RXFIFO_T threshold) +{ + spi->CTRL2_B.FRTCFG = threshold; +} + +/*! + * @brief Enable the data transfer direction + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_EnableOutputDirection(SPI_T* spi) +{ + spi->CTRL1_B.BMOEN = BIT_SET; +} + +/*! + * @brief Disable the data transfer direction + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_DisableOutputDirection(SPI_T* spi) +{ + spi->CTRL1_B.BMOEN = BIT_RESET; +} + +/*! + * @brief Enable internal slave select + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_EnableInternalSlave(SPI_T* spi) +{ + spi->CTRL1_B.ISSEL = BIT_SET; +} + +/*! + * @brief Disable internal slave select + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_DisableInternalSlave(SPI_T* spi) +{ + spi->CTRL1_B.ISSEL = BIT_RESET; +} + +/*! + * @brief Enable the SS output mode + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_EnableSSoutput(SPI_T* spi) +{ + spi->CTRL2_B.SSOEN = BIT_SET; +} + +/*! + * @brief Disable the SS output mode + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_DisableSSoutput(SPI_T* spi) +{ + spi->CTRL2_B.SSOEN = BIT_RESET; +} + +/*! + * @brief Enable the NSS pulse management mode + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_EnableNSSPulse(SPI_T* spi) +{ + spi->CTRL2_B.NSSPEN = BIT_SET; +} + +/*! + * @brief Disable the NSS pulse management mode + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_DisableNSSPulse(SPI_T* spi) +{ + spi->CTRL2_B.NSSPEN = BIT_RESET; +} + +/*! + * @brief Transmits a Data + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @param data: Byte to be transmitted + * + * @retval None + */ +void SPI_I2S_TxData16(SPI_T* spi, uint16_t data) +{ + spi->DATA = (uint16_t)data; +} + +/*! + * @brief Transmits a uint8_t Data + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @param data: Byte to be transmitted + * + * @retval None + */ +void SPI_TxData8(SPI_T* spi, uint8_t data) +{ + *((uint8_t*) & (spi->DATA)) = data; +} + +/*! + * @brief Returns the most recent received data by the SPI peripheral + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @param None + * + * @retval The value of the received data + */ +uint16_t SPI_I2S_RxData16(SPI_T* spi) +{ + return ((uint16_t)spi->DATA); +} + +/*! + * @brief Returns the most recent received data by the SPI peripheral + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @param None + * + * @retval The value of the received data + */ +uint8_t SPI_RxData8(SPI_T* spi) +{ + return *((uint8_t*) & (spi->DATA)); +} + +/*! + * @brief Selects the data transfer direction + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * @param crcLength: selects the SPI transfer direction + * The parameter can be one of following values: + * @arg SPI_CRC_LENGTH_8B: 8-bit CRC length + * @arg SPI_CRC_LENGTH_16B: 16-bit CRC length + * + * @retval None + */ +void SPI_CRCLength(SPI_T* spi, SPI_CRC_LENGTH_T crcLength) +{ + spi->CTRL1_B.CRCLSEL = crcLength; +} + +/*! + * @brief Enable the CRC value calculation + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_EnableCRC(SPI_T* spi) +{ + spi->CTRL1_B.CRCEN = BIT_SET; +} + +/*! + * @brief Disable the CRC value calculation + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_DisableCRC(SPI_T* spi) +{ + spi->CTRL1_B.CRCEN = BIT_RESET; +} + +/*! + * @brief Transmit CRC value + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_TxCRC(SPI_T* spi) +{ + spi->CTRL1_B.CRCNXT = BIT_SET; +} + +/*! + * @brief Returns the receive CRC register value + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + * + * @note None + */ +uint16_t SPI_ReadRxCRC(SPI_T* spi) +{ + return (uint16_t)spi->RXCRC; +} + +/*! + * @brief Returns the transmit CRC register value + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + * + * @note None + */ +uint16_t SPI_ReadTxCRC(SPI_T* spi) +{ + return (uint16_t)spi->TXCRC; +} + +/*! + * @brief Returns the CRC Polynomial register value + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +uint16_t SPI_ReadCRCPolynomial(SPI_T* spi) +{ + return (uint16_t)spi->CRCPOLY; +} + +/*! + * @brief Enable the DMA Rx buffer + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_EnableDMARxBuffer(SPI_T* spi) +{ + spi->CTRL2_B.RXDEN = BIT_SET; +} + +/*! + * @brief Disable the DMA Rx buffer + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_DisableDMARxBuffer(SPI_T* spi) +{ + spi->CTRL2_B.RXDEN = BIT_RESET; +} + +/*! + * @brief Enable the DMA Tx buffer + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_EnableDMATxBuffer(SPI_T* spi) +{ + spi->CTRL2_B.TXDEN = BIT_SET; +} + +/*! + * @brief Disable the DMA Tx buffer + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval None + */ +void SPI_DisableDMATxBuffer(SPI_T* spi) +{ + spi->CTRL2_B.TXDEN = BIT_RESET; +} + +/*! + * @brief Selects the last DMA transfer is type(Even/Odd) + * + * @param crcLength: specifies the SPI last DMA transfers + * The parameter can be one of following values: + * @arg SPI_LAST_DMA_TXRXEVEN: transmission Even reception Even + * @arg SPI_LAST_DMA_TXEVENRXODD: transmission Even reception Odd + * @arg SPI_LAST_DMA_TXODDRXEVEN: transmission Odd reception Even + * @arg SPI_LAST_DMA_TXRXODD: transmission Odd reception Odd + * + * @retval None + */ +void SPI_LastDMATransfer(SPI_T* spi, SPI_LAST_DMA_T lastDMA) +{ + spi->CTRL2 &= 0x9FFF; + spi->CTRL2 |= (uint16_t)lastDMA; +} + +/*! + * @brief Returns the SPI Transmission FIFO filled level + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval Transmission FIFO filled level: + * SPI_TXFIFO_LEVEL_EMPTY: Transmission FIFO filled level is empty + * SPI_TXFIFO_LEVEL_QUARTER: Transmission FIFO filled level is more than quarter + * SPI_TXFIFO_LEVEL_HALF: Transmission FIFO filled level is more than half + * SPI_TXFIFO_LEVEL_FULL: Transmission FIFO filled level is full + */ +uint8_t SPI_ReadTransmissionFIFOLeve(SPI_T* spi) +{ + return (uint8_t)((spi->STS_B.FTLSEL & 0x03)); +} + +/*! + * @brief Returns the SPI Reception FIFO filled level + * + * @param spi: Select the the SPI peripheral.It can be SPI1/SPI2 + * + * @retval Reception FIFO filled level: + * SPI_RXFIFO_LEVEL_EMPTY: Reception FIFO filled level is empty + * SPI_RXFIFO_LEVEL_QUARTER: Reception FIFO filled level is more than quarter + * SPI_RXFIFO_LEVEL_HALF: Reception FIFO filled level is more than half + * SPI_RXFIFO_LEVEL_FULL: Reception FIFO filled level is full + */ +uint8_t SPI_ReadReceptionFIFOLeve(SPI_T* spi) +{ + return (uint8_t)((spi->STS_B.FRLSEL & 0x03)); +} + +/*! + * @brief Enable the SPI interrupts + * + * @param interrupt: Specifies the SPI interrupts sources + * The parameter can be combination of following values: + * @arg SPI_INT_ERRIE: Error interrupt + * @arg SPI_INT_RXBNEIE: Receive buffer not empty interrupt + * @arg SPI_INT_TXBEIE: Transmit buffer empty interrupt + * + * @retval None + */ +void SPI_EnableInterrupt(SPI_T* spi, uint8_t interrupt) +{ + spi->CTRL2 |= (uint8_t)interrupt; +} + +/*! + * @brief Disable the SPI interrupts + * + * @param interrupt: Specifies the SPI interrupts sources + * The parameter can be combination of following values: + * @arg SPI_INT_ERRIE: Error interrupt + * @arg SPI_INT_RXBNEIE: Receive buffer not empty interrupt + * @arg SPI_INT_TXBEIE: Transmit buffer empty interrupt + * + * @retval None + */ +void SPI_DisableInterrupt(SPI_T* spi, uint8_t interrupt) +{ + spi->CTRL2 &= (uint8_t)~interrupt; +} + +/*! + * @brief Checks whether the specified SPI flag is set or not + * + * @param flag: Specifies the flag to check + * This parameter can be one of the following values: + * @arg SPI_FLAG_RXBNE: Receive buffer not empty flag + * @arg SPI_FLAG_TXBE: Transmit buffer empty flag + * @arg I2S_FLAG_CHDIR: Channel direction flag + * @arg I2S_FLAG_UDR: Underrun flag + * @arg SPI_FLAG_CRCE: CRC error flag + * @arg SPI_FLAG_MME: Master mode error flag + * @arg SPI_FLAG_OVR: Receive Overrun flag + * @arg SPI_FLAG_BUSY: Busy flag + * @arg SPI_FLAG_FFE: Frame format error flag + * + * @retval The new state of flag (SET or RESET) + */ +uint8_t SPI_ReadStatusFlag(SPI_T* spi, SPI_FLAG_T flag) +{ + uint16_t status; + + status = (uint16_t)(spi->STS & flag); + + if (status == flag) + { + return SET; + } + + return RESET; +} + +/*! + * @brief Clear the specified SPI flag + * + * @param flag: Specifies the flag to clear + * This parameter can be any combination of the following values: + * @arg SPI_FLAG_CRCE: CRC error flag + + * @retval None + */ +void SPI_ClearStatusFlag(SPI_T* spi, uint8_t flag) +{ + spi->STS &= (uint32_t)~flag; +} + +/*! + * @brief Checks whether the specified interrupt has occurred or not + * + * @param flag: Specifies the SPI interrupt pending bit to check + * This parameter can be one of the following values: + * @arg SPI_INT_FLAG_RXBNE: Receive buffer not empty flag + * @arg SPI_INT_FLAG_TXBE: Transmit buffer empty flag + * @arg SPI_INT_FLAG_UDR: Underrun flag interrupt flag + * @arg SPI_INT_FLAG_MME: Master mode error flag + * @arg SPI_INT_FLAG_OVR: Receive Overrun flag + * @arg SPI_INT_FLAG_FFE: Frame format error interrupt flag + * + * @retval None + */ +uint8_t SPI_ReadIntFlag(SPI_T* spi, SPI_INT_FLAG_T flag) +{ + uint32_t intEnable; + uint32_t intStatus; + + intEnable = (uint32_t)(spi->CTRL2 & (uint32_t)(flag >> 16)); + + intStatus = (uint32_t)(spi->STS & (uint32_t)(flag & 0x1ff)); + + if (intEnable && intStatus) + { + return SET; + } + + return RESET; +} + +/**@} end of group SPI_Functions*/ +/**@} end of group SPI_Driver*/ +/**@} end of group APM32F0xx_StdPeriphDriver*/ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_syscfg.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_syscfg.c new file mode 100644 index 0000000000..d8761379f2 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_syscfg.c @@ -0,0 +1,316 @@ +/*! + * @file apm32f0xx_syscfg.c + * + * @brief This file contains all the functions for the SYSCFG peripheral + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +#include "apm32f0xx_syscfg.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup SYSCFG_Driver SYSCFG Driver + @{ +*/ + +/** @defgroup SYSCFG_Macros Macros + @{ +*/ + +/**@} end of group SYSCFG_Macros */ + +/** @defgroup SYSCFG_Enumerations Enumerations + @{ +*/ + +/**@} end of group SYSCFG_Enumerations */ + +/** @defgroup SYSCFG_Structures Structures + @{ +*/ + +/**@} end of group SYSCFG_Structures */ + +/** @defgroup SYSCFG_Variables Variables + @{ +*/ + +/**@} end of group SYSCFG_Variables */ + +/** @defgroup SYSCFG_Functions Functions + @{ +*/ + +/*! + * @brief Set SYSCFG CFG0/1 EINTCFG1/2/3/4 register to reset value + * + * @param None + * + * @retval None + */ +void SYSCFG_Reset(void) +{ + SYSCFG->CFG1 &= (uint32_t) SYSCFG_CFG1_MEMMODE; + SYSCFG->EINTCFG1 = 0; + SYSCFG->EINTCFG2 = 0; + SYSCFG->EINTCFG3 = 0; + SYSCFG->EINTCFG4 = 0; + SYSCFG->CFG2 |= (uint32_t) SYSCFG_CFG2_SRAMPEF; +} + +/*! + * @brief SYSCFG Memory Remap selects + * + * @param memory: selects the memory remapping + * The parameter can be one of following values: + * @arg SYSCFG_MEMORY_REMAP_FMC: SYSCFG MemoryRemap Flash + * @arg SYSCFG_MEMORY_REMAP_SYSTEM: SYSCFG MemoryRemap SystemMemory + * @arg SYSCFG_MEMORY_REMAP_SRAM: SYSCFG MemoryRemap SRAM + * + * @retval None + */ +void SYSCFG_MemoryRemapSelect(uint8_t memory) +{ + SYSCFG->CFG1_B.MMSEL = (uint8_t)memory; +} + +/*! + * @brief Enables SYSCFG DMA Channel Remap + * + * @param channel: selects the DMA channels remap. + * The parameter can be any combination of following values: + * @arg SYSCFG_DAM_REMAP_ADC: ADC DMA remap + * @arg SYSCFG_DAM_REMAP_USART1TX: USART1 TX DMA remap + * @arg SYSCFG_DAM_REMAP_USART1RX: USART1 RX DMA remap + * @arg SYSCFG_DAM_REMAP_TMR16: Timer 16 DMA remap + * @arg SYSCFG_DAM_REMAP_TMR17: Timer 17 DMA remap + * @arg SYSCFG_DAM_REMAP_TMR16_2£º Timer 16 DMA remap2(only for APM32F072) + * @arg SYSCFG_DAM_REMAP_TMR17_2£º Timer 17 DMA remap2(only for APM32F072) + * @arg SYSCFG_DAM_REMAP_SPI2£º SPI2 DMA remap(only for APM32F072) + * @arg SYSCFG_DAM_REMAP_USART2£º USART1 TX DMA remap(only for APM32F072) + * @arg SYSCFG_DAM_REMAP_USART3£º USART1 RX DMA remap(only for APM32F072) + * @arg SYSCFG_DAM_REMAP_I2C1£º I2C1 DMA remap(only for APM32F072) + * @arg SYSCFG_DAM_REMAP_TMR1£º Timer 1 DMA remap(only for APM32F072) + * @arg SYSCFG_DAM_REMAP_TMR2£º Timer 2 DMA remap(only for APM32F072) + * @arg SYSCFG_DAM_REMAP_TMR3£º Timer 3 DMA remap(only for APM32F072) + * + * @retval None + */ +void SYSCFG_EnableDMAChannelRemap(uint32_t channel) +{ + SYSCFG->CFG1 |= (uint32_t)channel; +} + +/*! + * @brief Disables SYSCFG DMA Channel Remap + * + * @param channel: selects the DMA channels remap. + * The parameter can be any combination of following values: + * @arg SYSCFG_DAM_REMAP_ADC: ADC DMA remap + * @arg SYSCFG_DAM_REMAP_USART1TX: USART1 TX DMA remap + * @arg SYSCFG_DAM_REMAP_USART1RX: USART1 RX DMA remap + * @arg SYSCFG_DAM_REMAP_TMR16: Timer 16 DMA remap + * @arg SYSCFG_DAM_REMAP_TMR17: Timer 17 DMA remap + * @arg SYSCFG_DAM_REMAP_TMR16_2£º Timer 16 DMA remap2(only for APM32F072) + * @arg SYSCFG_DAM_REMAP_TMR17_2£º Timer 17 DMA remap2(only for APM32F072) + * @arg SYSCFG_DAM_REMAP_SPI2£º SPI2 DMA remap(only for APM32F072) + * @arg SYSCFG_DAM_REMAP_USART2£º USART1 TX DMA remap(only for APM32F072) + * @arg SYSCFG_DAM_REMAP_USART3£º USART1 RX DMA remap(only for APM32F072) + * @arg SYSCFG_DAM_REMAP_I2C1£º I2C1 DMA remap(only for APM32F072) + * @arg SYSCFG_DAM_REMAP_TMR1£º Timer 1 DMA remap(only for APM32F072) + * @arg SYSCFG_DAM_REMAP_TMR2£º Timer 2 DMA remap(only for APM32F072) + * @arg SYSCFG_DAM_REMAP_TMR3£º Timer 3 DMA remap(only for APM32F072) + * + * @retval None + */ +void SYSCFG_DisableDMAChannelRemap(uint32_t channel) +{ + SYSCFG->CFG1 &= (uint32_t)~channel; +} + +/*! + * @brief Enables SYSCFG I2C Fast Mode Plus + * + * @param pin: selects the pin. + * The parameter can be combination of following values: + * @arg SYSCFG_I2C_FMP_PB6: I2C PB6 Fast mode plus + * @arg SYSCFG_I2C_FMP_PB7: I2C PB7 Fast mode plus + * @arg SYSCFG_I2C_FMP_PB8: I2C PB8 Fast mode plus + * @arg SYSCFG_I2C_FMP_PB9: I2C PB9 Fast mode plus + * @arg SYSCFG_I2C_FMP_PA9: I2C PA9 Fast mode plus(only for APM32F030 and APM32F091) + * @arg SYSCFG_I2C_FMP_PA10: I2C PA10 Fast mode plus(only for APM32F030 and APM32F091) + * @arg SYSCFG_I2C_FMP_I2C1: PB10, PB11, PF6 and PF7 + * @arg SYSCFG_I2C_FMP_I2C2: I2C2 Fast mode plus(only for APM32F072 and APM32F091) + * + * @retval None + */ +void SYSCFG_EnableI2CFastModePlus(uint32_t pin) +{ + SYSCFG->CFG1 |= (uint32_t)pin; +} + +/*! + * @brief Disables SYSCFG I2C Fast Mode Plus + * + * @param pin: selects the pin. + * The parameter can be combination of following values: + * @arg SYSCFG_I2C_FMP_PB6: I2C PB6 Fast mode plus + * @arg SYSCFG_I2C_FMP_PB7: I2C PB7 Fast mode plus + * @arg SYSCFG_I2C_FMP_PB8: I2C PB8 Fast mode plus + * @arg SYSCFG_I2C_FMP_PB9: I2C PB9 Fast mode plus + * @arg SYSCFG_I2C_FMP_PA9: I2C PA9 Fast mode plus(only for APM32F030 and APM32F091) + * @arg SYSCFG_I2C_FMP_PA10: I2C PA10 Fast mode plus(only for APM32F030 and APM32F091) + * @arg SYSCFG_I2C_FMP_I2C1: PB10, PB11, PF6 and PF7 + * @arg SYSCFG_I2C_FMP_I2C2: I2C2 Fast mode plus(only for APM32F072 and APM32F091) + * + * @retval None + */ +void SYSCFG_DisableI2CFastModePlus(uint32_t pin) +{ + SYSCFG->CFG1 &= (uint32_t)~pin; +} + +/*! + * @brief Select the modulation envelope source + * + * @param IRDAEnv: selects the envelope source + * The parameter can be one of following values: + * @arg SYSCFG_IRDA_ENV_TMR16: Timer16 as IRDA Modulation envelope source + * @arg SYSCFG_IRDA_ENV_USART1: USART1 as IRDA Modulation envelope source + * @arg SYSCFG_IRDA_ENV_USART2: USART4 as IRDA Modulation envelope source + * + * @retval None + * + * @note It's only for APM32F091 devices. + */ +void SYSCFG_SelectIRDAEnv(SYSCFG_IRDA_ENV_T IRDAEnv) +{ + SYSCFG->CFG1 &= ~(0x000000C0); + SYSCFG->CFG1 |= (IRDAEnv); +} + +/*! + * @brief Selects the GPIO pin used as EINT Line. + * + * @param port: selects the port can be GPIOA/B/C/D/E/F + * + * @param pin: selects the pin can be SYSCFG_PIN_(0..15) + * + * @retval None + * + * @note GPIOE only for APM32F072 and APM32F091 + */ + +void SYSCFG_EINTLine(SYSCFG_PORT_T port, SYSCFG_PIN_T pin) +{ + uint32_t status; + + status = (((uint32_t)0x0F) & port) << (0x04 * (pin & (uint8_t)0x03)); + + if (pin <= 0x03) + { + SYSCFG->EINTCFG1 |= status; + } + else if ((0x04 <= pin) & (pin <= 0x07)) + { + SYSCFG->EINTCFG2 |= status; + } + else if ((0x08 <= pin) & (pin <= 0x0B)) + { + SYSCFG->EINTCFG3 |= status; + } + else if ((0x0C <= pin) & (pin <= 0x0F)) + { + SYSCFG->EINTCFG4 |= status; + } +} + +/*! + * @brief Selected parameter to the break input of TMR1. + * + * @param lock: selects the configuration to break + * The parameter can be one of following values: + * @arg SYSCFG_LOCK_LOCKUP: Cortex-M0 LOCKUP bit + * @arg SYSCFG_LOCK_SRAM: SRAM parity lock bit + * @arg SYSCFG_LOCK_PVD: PVD lock enable bit + * + * @retval None + */ +void SYSCFG_BreakLock(uint32_t lock) +{ + SYSCFG->CFG2_B.LOCK = 0; + SYSCFG->CFG2_B.SRAMLOCK = 0; + SYSCFG->CFG2_B.PVDLOCK = 0; + + if (lock == SYSCFG_LOCK_LOCKUP) + { + SYSCFG->CFG2_B.LOCK = BIT_SET; + } + if (lock == SYSCFG_LOCK_SRAM) + { + SYSCFG->CFG2_B.SRAMLOCK = BIT_SET; + } + if (lock == SYSCFG_LOCK_PVD) + { + SYSCFG->CFG2_B.PVDLOCK = BIT_SET; + } +} + +/*! + * @brief Read the specified SYSCFG flag + * + * @param flag: SRAM Parity error flag + * @arg SYSCFG_CFG2_SRAMPEF + * + * @retval None + */ +uint8_t SYSCFG_ReadStatusFlag(uint32_t flag) +{ + uint32_t status; + + status = (uint32_t)(SYSCFG->CFG2 & flag); + + if (status == flag) + { + return SET; + } + + return RESET; +} + +/*! + * @brief Clear the specified SYSCFG flag + * + * @param flag: SRAM Parity error flag + * @arg SYSCFG_CFG2_SRAMPEF + * + * @retval None + */ +void SYSCFG_ClearStatusFlag(uint8_t flag) +{ + SYSCFG->CFG2 |= (uint32_t) flag; +} + +/**@} end of group SYSCFG_Functions*/ +/**@} end of group SYSCFG_Driver*/ +/**@} end of group APM32F0xx_StdPeriphDriver*/ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_tmr.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_tmr.c new file mode 100644 index 0000000000..9f4dea8e07 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_tmr.c @@ -0,0 +1,2394 @@ +/*! + * @file apm32f0xx_tmr.c + * + * @brief This file contains all the functions for the TMR peripheral + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +#include "apm32f0xx_tmr.h" +#include "apm32f0xx_rcm.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup TMR_Driver TMR Driver + @{ +*/ + +/** @defgroup TMR_Marcos Marcos + @{ + */ + +/**@} end of group TMR_Marcos */ + +/** @defgroup TMR_Enumerations Enumerations + @{ + */ + +/**@} end of group TMR_Enumerations */ + +/** @defgroup TMR_Structures Structures + @{ + */ + +/**@} end of group TMR_Structures */ + +/** @defgroup TMR_Variables Variables + @{ + */ + +/**@} end of group TMR_Variables */ + +/** @defgroup TMR_Functions Functions + @{ +*/ + +/*! + * @brief Reset the TMR peripheral registers to their default reset values + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @retval None + * + * @note TMR2 TMR15 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_Reset(TMR_T* TMRx) +{ + if (TMRx == TMR1) + { + RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_TMR1); + RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_TMR1); + } + else if (TMRx == TMR2) + { + RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_TMR2); + RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_TMR2); + } + else if (TMRx == TMR3) + { + RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_TMR3); + RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_TMR3); + } + else if (TMRx == TMR6) + { + RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_TMR6); + RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_TMR6); + } + else if (TMRx == TMR7) + { + RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_TMR7); + RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_TMR7); + } + else if (TMRx == TMR14) + { + RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_TMR14); + RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_TMR14); + } + else if (TMRx == TMR15) + { + RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_TMR15); + RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_TMR15); + } + else if (TMRx == TMR16) + { + RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_TMR16); + RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_TMR16); + } + else if (TMRx == TMR17) + { + RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_TMR17); + RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_TMR17); + } +} + +/*! + * @brief Initializes the TMRx Time Base Unit peripheral according to + * the specified parameters in the TMR_ConfigTimeBase + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @param timeBaseConfig: pointer to a TMR_TimeBase_T structure that contains + * the configuration information for the specified TMR peripheral + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_ConfigTimeBase(TMR_T* TMRx, TMR_TimeBase_T* timeBaseConfig) +{ + if ((TMRx == TMR1) || (TMRx == TMR3)) + { + /** Select the Counter Mode */ + TMRx->CTRL1_B.CNTDIR = timeBaseConfig->counterMode; + TMRx->CTRL1_B.CAMSEL = (timeBaseConfig->counterMode) >> 1; + } + + if (TMRx != TMR6) + { + /** Set the clock division */ + TMRx->CTRL1_B.CLKDIV = timeBaseConfig->clockDivision; + } + + /** Set the Autoreload value */ + TMRx->AUTORLD = timeBaseConfig->period ; + + /** Set the Prescaler value */ + TMRx->PSC = timeBaseConfig->div ; + + if ((TMRx == TMR1) || (TMRx == TMR15) || (TMRx == TMR16) || (TMRx == TMR17)) + { + /** Set the Repetition Counter value */ + TMRx->REPCNT = timeBaseConfig->repetitionCounter; + } + + /** Enable Update generation */ + TMRx->CEG_B.UEG = BIT_SET; +} + +/*! + * @brief Fills each TMR_ConfigTimeBaseStruct member with its default value + * + * @param timeBaseConfig: pointer to a TMR_TimeBase_T structure that contains + * the configuration information for the specified TMR peripheral + * + * @retval None + */ +void TMR_ConfigTimeBaseStruct(TMR_TimeBase_T* timeBaseConfig) +{ + timeBaseConfig->period = 0xFFFFFFFF; + timeBaseConfig->div = 0x0000; + timeBaseConfig->clockDivision = TMR_CKD_DIV1; + timeBaseConfig->counterMode = TMR_COUNTER_MODE_UP; + timeBaseConfig->repetitionCounter = 0x0000; +} + +/*! + * @brief Configures the TMRx Div + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @param div: specifies the Div Register value + * + * @param mode: specifies the TMR Prescaler Reload mode + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_ConfigDIV(TMR_T* TMRx, uint16_t div, TMR_PRESCALER_RELOAD_T mode) +{ + TMRx->PSC = div; + TMRx->CEG_B.UEG = mode; +} + +/*! + * @brief Specifies the TMRx Counter Mode to be used + * + * @param TMRx: x can be can be 1 or 3 to select Timer + * + * @param mode : specifies the Counter Mode to be used + * + * @retval None + */ +void TMR_ConfigCounterMode(TMR_T* TMRx, TMR_COUNTER_MODE_T mode) +{ + TMRx->CTRL1_B.CNTDIR = mode; + TMRx->CTRL1_B.CAMSEL = (mode) >> 1; +} + +/*! + * @brief Sets the TMRx Counter Register value + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @param counter: specifies the Counter register new value + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_SetCounter(TMR_T* TMRx, uint32_t counter) +{ + TMRx->CNT = counter; +} + +/*! + * @brief Read the TMRx Counter value + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @retval Counter Register value + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +uint32_t TMR_ReadCounter(TMR_T* TMRx) +{ + return (uint32_t)TMRx->CNT; +} + +/*! + * @brief Sets the AutoReload Register value + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @param autoReload: autoReload register new value + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_SetAutoReload(TMR_T* TMRx, uint32_t autoReload) +{ + TMRx->AUTORLD = autoReload; +} + +/*! + * @brief Read the TMRx Div value + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @retval Div Register value + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +uint32_t TMR_ReadDiv(TMR_T* TMRx) +{ + return (uint32_t)TMRx->PSC; +} + +/*! + * @brief Enable the No update event + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_EnableNGUpdate(TMR_T* TMRx) +{ + TMRx->CTRL1_B.UD = ENABLE; +} + +/*! + * @brief Enable the No update event + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_DisableNGUpdate(TMR_T* TMRx) +{ + TMRx->CTRL1_B.UD = DISABLE; +} + +/*! + * @brief Configures the Update Request Interrupt source. + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @param source: Config the Update source + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_ConfigUPdateRequest(TMR_T* TMRx, TMR_UPDATE_SOURCE_T source) +{ + if (source != TMR_UPDATE_SOURCE_GLOBAL) + { + TMRx->CTRL1_B.URSSEL = BIT_SET; + } + else + { + TMRx->CTRL1_B.URSSEL = BIT_RESET; + } +} + +/*! + * @brief Enables peripheral Preload register on AUTORLD + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_EnableAUTOReload(TMR_T* TMRx) +{ + TMRx->CTRL1_B.ARPEN = ENABLE; +} + +/*! + * @brief Disable peripheral Preload register on AUTORLD + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_DisableAUTOReload(TMR_T* TMRx) +{ + TMRx->CTRL1_B.ARPEN = DISABLE; +} + +/*! + * @brief Selects the One Pulse Mode + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @param OPMode:Config OP Mode to be used + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_SelectOnePulseMode(TMR_T* TMRx, TMR_OPMODE_T OPMode) +{ + TMRx->CTRL1_B.SPMEN = OPMode; +} + +/*! + * @brief Sets the Clock Division value + * + * @param TMRx: x can be can be 1£¬2£¬3, 14, 15, 16 and 17 to select Timer + * + * @param clockDivision: clock division value + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_SetClockDivision(TMR_T* TMRx, TMR_CKD_T clockDivision) +{ + TMRx->CTRL1_B.CLKDIV = clockDivision; +} + +/*! + * @brief Enable the specified TMR peripheral + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_Enable(TMR_T* TMRx) +{ + TMRx->CTRL1_B.CNTEN = ENABLE; +} + +/*! + * @brief Disable the specified TMR peripheral + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_Disable(TMR_T* TMRx) +{ + TMRx->CTRL1_B.CNTEN = DISABLE; +} + +/*! + * @brief Configures the: Break feature, dead time, Lock level, the OSSI + * + * @param TMRx: x can be can be 1, 15, 16 and 17 to select Timer + * + * @param structure: pointer to a TMR_BDTInit_T structure that contains + * the BDT Register configuration information for the TMR peripheral + * + * @retval None + */ +void TMR_ConfigBDT(TMR_T* TMRx, TMR_BDTInit_T* structure) +{ + TMRx->BDT = (uint32_t)(((uint32_t)structure->automaticOutput) << 14) | + (((uint32_t)structure->breakPolarity) << 13) | + (((uint32_t)structure->breakState) << 12) | + (((uint32_t)structure->RMOS_State) << 11) | + (((uint32_t)structure->IMOS_State) << 10) | + (((uint32_t)structure->lockLevel) << 8) | + ((uint32_t)structure->deadTime); +} + +/*! + * @brief Initialize the BDT timer with its default value. + * + * @param structure: pointer to a TMR_BDTInit_T structure that contains + * the BDT Register configuration information for the TMR peripheral + * + * @retval None + */ +void TMR_ConfigBDTStructInit(TMR_BDTInit_T* structure) +{ + structure->RMOS_State = TMR_RMOS_STATE_DISABLE; + structure->IMOS_State = TMR_IMOS_STATE_DISABLE; + structure->lockLevel = TMR_LOCK_LEVEL_OFF; + structure->deadTime = 0x00; + structure->breakState = TMR_BREAK_STATE_DISABLE; + structure->breakPolarity = TMR_BREAK_POLARITY_LOW; + structure->automaticOutput = TMR_AUTOMATIC_OUTPUT_DISABLE; +} + +/*! + * @brief Enable TMRx PWM output. + * + * @param TMRx: x can be can be 1, 15, 16 and 17 to select Timer + * + * @retval None + */ +void TMR_EnablePWMOutputs(TMR_T* TMRx) +{ + TMRx->BDT_B.MOEN = ENABLE; +} + +/*! + * @brief Disable TMRx PWM output. + * + * @param TMRx: x can be can be 1, 15, 16 and 17 to select Timer + * + * @retval None + */ +void TMR_DisablePWMOutputs(TMR_T* TMRx) +{ + TMRx->BDT_B.MOEN = DISABLE; +} + +/*! + * @brief Configure channel 1 according to parameters + * + * @param TMRx: x can be can be 1, 2, 3, 14, 15, 16 and 17 to select Timer + * + * @param OCcongigStruct: Channel configuration structure + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_OC1Config(TMR_T* TMRx, TMR_OCConfig_T* OCcongigStruct) +{ + + /** Disable the Channel 1: Reset the CC1EN Bit */ + TMRx->CCEN_B.CC1EN = BIT_RESET; + + /** Reset and Select the Output Compare Mode Bits */ + TMRx->CCM1_OUTPUT_B.CC1SEL = BIT_RESET; + TMRx->CCM1_OUTPUT_B.OC1MOD = OCcongigStruct->OC_Mode; + + /** Reset and Set the Output Polarity level */ + TMRx->CCEN_B.CC1POL = OCcongigStruct->OC_Polarity; + + /** Set the Output State */ + TMRx->CCEN_B.CC1EN = OCcongigStruct->OC_OutputState; + + if ((TMRx == TMR1) || (TMRx == TMR15) || (TMRx == TMR16) + || (TMRx == TMR17)) + { + /** Reset and Set the Output N Polarity level */ + TMRx->CCEN_B.CC1NPOL = OCcongigStruct->OC_NPolarity; + + /** Reset and Set the Output N State */ + TMRx->CCEN_B.CC1NEN = OCcongigStruct->OC_OutputNState; + + /** Reset the Output Compare and Output Compare N IDLE State */ + TMRx->CTRL2_B.OC1OIS = BIT_RESET; + TMRx->CTRL2_B.OC1NOIS = BIT_RESET; + + /** Set the Output Idle state */ + TMRx->CTRL2_B.OC1OIS = OCcongigStruct->OC_Idlestate; + /** Set the Output N State */ + TMRx->CTRL2_B.OC1NOIS = OCcongigStruct->OC_NIdlestate; + } + + /** Set the Capture Compare Register value */ + TMRx->CC1 = OCcongigStruct->Pulse; +} + +/*! + * @brief Configure channel 2 according to parameters + * + * @param TMRx: x can be can be 1£¬2£¬3 and 15 to select Timer + * + * @param OCcongigStruct: Channel configuration structure + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_OC2Config(TMR_T* TMRx, TMR_OCConfig_T* OCcongigStruct) +{ + + /** Disable the Channel 2: Reset the CC2EN Bit */ + TMRx->CCEN_B.CC2EN = BIT_RESET; + + /** Reset and Select the Output Compare Mode Bits */ + TMRx->CCM1_OUTPUT_B.CC2SEL = BIT_RESET; + TMRx->CCM1_OUTPUT_B.OC2MOD = OCcongigStruct->OC_Mode; + + /** Reset and Set the Output Polarity level */ + TMRx->CCEN_B.CC2POL = BIT_RESET; + TMRx->CCEN_B.CC2POL = OCcongigStruct->OC_Polarity; + + /** Set the Output State */ + TMRx->CCEN_B.CC2EN = OCcongigStruct->OC_OutputState; + + if (TMRx == TMR1) + { + /** Reset and Set the Output N Polarity level */ + TMRx->CCEN_B.CC2NPOL = BIT_RESET; + TMRx->CCEN_B.CC2NPOL = OCcongigStruct->OC_NPolarity; + + /** Reset and Set the Output N State */ + TMRx->CCEN_B.CC2NEN = BIT_RESET; + TMRx->CCEN_B.CC2NEN = OCcongigStruct->OC_OutputNState; + + /** Reset the Output Compare and Output Compare N IDLE State */ + TMRx->CTRL2_B.OC2OIS = BIT_RESET; + TMRx->CTRL2_B.OC2NOIS = BIT_RESET; + + /** Set the Output Idle state */ + TMRx->CTRL2_B.OC2OIS = OCcongigStruct->OC_Idlestate; + /** Set the Output N State */ + TMRx->CTRL2_B.OC2NOIS = OCcongigStruct->OC_NIdlestate; + } + + /** Set the Capture Compare Register value */ + TMRx->CC2 = OCcongigStruct->Pulse; +} + +/*! + * @brief Configure channel 3 according to parameters + * + * @param TMRx: x can be can be 1, 2, 3 to select Timer + * + * @param OCcongigStruct: Channel configuration structure + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_OC3Config(TMR_T* TMRx, TMR_OCConfig_T* OCcongigStruct) +{ + + /** Disable the Channel 3: Reset the CC3EN Bit */ + TMRx->CCEN_B.CC3EN = BIT_RESET; + + /** Reset and Select the Output Compare Mode Bits */ + TMRx->CCM2_OUTPUT_B.CC3SEL = BIT_RESET; + TMRx->CCM2_OUTPUT_B.OC3MOD = OCcongigStruct->OC_Mode; + + /** Reset and Set the Output Polarity level */ + TMRx->CCEN_B.CC3POL = BIT_RESET; + TMRx->CCEN_B.CC3POL = OCcongigStruct->OC_Polarity; + + /** Set the Output State */ + TMRx->CCEN_B.CC3EN = OCcongigStruct->OC_OutputState; + + if (TMRx == TMR1) + { + /** Reset and Set the Output N Polarity level */ + TMRx->CCEN_B.CC3NPOL = BIT_RESET; + TMRx->CCEN_B.CC3NPOL = OCcongigStruct->OC_NPolarity; + + /** Reset and Set the Output N State */ + TMRx->CCEN_B.CC3NEN = BIT_RESET; + TMRx->CCEN_B.CC3NEN = OCcongigStruct->OC_OutputNState; + + /** Reset the Output Compare and Output Compare N IDLE State */ + TMRx->CTRL2_B.OC3OIS = BIT_RESET; + TMRx->CTRL2_B.OC3NOIS = BIT_RESET; + + /** Set the Output Idle state */ + TMRx->CTRL2_B.OC3OIS = OCcongigStruct->OC_Idlestate; + /** Set the Output N State */ + TMRx->CTRL2_B.OC3NOIS = OCcongigStruct->OC_NIdlestate; + } + + /** Set the Capture Compare Register value */ + TMRx->CC3 = OCcongigStruct->Pulse; +} + +/*! + * @brief Configure channel 4 according to parameters + * + * @param TMRx: x can be can be 1, 2, 3 to select Timer + * + * @param OCcongigStruct: Channel configuration structure + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_OC4Config(TMR_T* TMRx, TMR_OCConfig_T* OCcongigStruct) +{ + + /** Disable the Channel 4: Reset the CC4EN Bit */ + TMRx->CCEN_B.CC4EN = BIT_RESET; + + /** Reset and Select the Output Compare Mode Bits */ + TMRx->CCM2_OUTPUT_B.CC4SEL = BIT_RESET; + TMRx->CCM2_OUTPUT_B.OC4MOD = OCcongigStruct->OC_Mode; + + /** Reset and Set the Output Polarity level */ + TMRx->CCEN_B.CC4POL = BIT_RESET; + TMRx->CCEN_B.CC4POL = OCcongigStruct->OC_Polarity; + + /** Set the Output State */ + TMRx->CCEN_B.CC4EN = OCcongigStruct->OC_OutputState; + + if (TMRx == TMR1) + { + /** Reset the Output Compare and Output Compare IDLE State */ + TMRx->CTRL2_B.OC4OIS = BIT_RESET; + + /** Set the Output Idle state */ + TMRx->CTRL2_B.OC4OIS = OCcongigStruct->OC_Idlestate; + } + + /** Set the Capture Compare Register value */ + TMRx->CC4 = OCcongigStruct->Pulse; +} + +/*! + * @brief Initialize the OC timer with its default value. + * + * @param OCcongigStruct: Channel configuration structure + * + * @retval None + */ +void TMR_OCConfigStructInit(TMR_OCConfig_T* OCcongigStruct) +{ + /** Set the default configuration */ + OCcongigStruct->OC_Mode = TMR_OC_MODE_TMRING; + OCcongigStruct->OC_OutputState = TMR_OUTPUT_STATE_DISABLE; + OCcongigStruct->OC_OutputNState = TMR_OUTPUT_NSTATE_DISABLE; + OCcongigStruct->Pulse = 0x0000; + OCcongigStruct->OC_Polarity = TMR_OC_POLARITY_HIGH; + OCcongigStruct->OC_NPolarity = TMR_OC_NPOLARITY_HIGH; + OCcongigStruct->OC_Idlestate = TMR_OCIDLESTATE_RESET; + OCcongigStruct->OC_NIdlestate = TMR_OCNIDLESTATE_RESET; +} + +/*! + * @brief Selects the Output Compare Mode. + * + * @param TMRx: x can be can be 1£¬2£¬3, 14, 15, 16 and 17 to select Timer + * + * @param channel: specifies the TMR Channel + * This parameter can be one of the following values: + * @arg TMR_CHANNEL_1 + * @arg TMR_CHANNEL_2 + * @arg TMR_CHANNEL_3 + * @arg TMR_CHANNEL_4 + * + * @param OCMode: specifies the TMR Output Compare Mode + * This parameter can be one of the following values: + * @arg TMR_OC_MODE_TMRING + * @arg TMR_OC_MODE_ACTIVE + * @arg TMR_OC_MODE_INACTIVE + * @arg TMR_OC_MODE_LOWLEVEL + * @arg TMR_OC_MODE_HIGHLEVEL + * @arg TMR_OC_MODE_PWM1 + * @arg TMR_OC_MODE_PWM2 + + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_SelectOCxMode(TMR_T* TMRx, TMR_CHANNEL_T channel, TMR_OC_MODE_T mode) +{ + TMRx->CCEN &= BIT_RESET << channel; + + if (channel == TMR_CHANNEL_1) + { + TMRx->CCM1_OUTPUT_B.OC1MOD = mode; + } + else if (channel == TMR_CHANNEL_2) + { + TMRx->CCM1_OUTPUT_B.OC2MOD = mode; + } + else if (channel == TMR_CHANNEL_3) + { + TMRx->CCM2_OUTPUT_B.OC3MOD = mode; + } + else if (channel == TMR_CHANNEL_4) + { + TMRx->CCM2_OUTPUT_B.OC4MOD = mode; + } +} + +/*! + * @brief Sets the Capture Compare1 Register value + * + * @param TMRx: x can be can be 1£¬2£¬3, 14, 15, 16 and 17 to select Timer + * + * @param compare: specifies the Capture Compare1 register new value + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_SetCompare1(TMR_T* TMRx, uint32_t compare) +{ + TMRx->CC1 = compare; +} + +/*! + * @brief Sets the Capture Compare2 Register value + * + * @param TMRx: x can be can be 1£¬2£¬3 and 15 to select Timer + * + * @param compare: specifies the Capture Compare1 register new value + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_SetCompare2(TMR_T* TMRx, uint32_t compare) +{ + TMRx->CC2 = compare; +} + +/*! + * @brief Sets the Capture Compare3 Register value + * + * @param TMRx: x can be can be 1, 2, 3 to select Timer + * + * @param compare: specifies the Capture Compare1 register new value + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_SetCompare3(TMR_T* TMRx, uint32_t compare) +{ + TMRx->CC3 = compare; +} + +/*! + * @brief Sets the Capture Compare4 Register value + * + * @param TMRx: x can be can be 1, 2, 3 to select Timer + * + * @param compare: specifies the Capture Compare1 register new value + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_SetCompare4(TMR_T* TMRx, uint32_t compare) +{ + TMRx->CC4 = compare; +} + +/*! + * @brief Forces the output 1 waveform to active or inactive level + * + * @param TMRx: x can be can be 1£¬2£¬3, 14, 15, 16 and 17 to select Timer + * + * @param action: forced Action to be set to the output waveform + * This parameter can be one of the following values: + * @arg TMR_FORCEDACTION_INACTIVE + * @arg TMR_FORCEDACTION_ACTIVE + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ForcedOC1Config(TMR_T* TMRx, TMR_FORCED_ACTION_T action) +{ + TMRx->CCM1_OUTPUT_B.OC1MOD = action; +} + +/*! + * @brief Forces the output 2 waveform to active or inactive level + * + * @param TMRx: x can be can be 1£¬2£¬3 and 15 to select Timer + * + * @param action: forced Action to be set to the output waveform + * This parameter can be one of the following values: + * @arg TMR_FORCEDACTION_INACTIVE + * @arg TMR_FORCEDACTION_ACTIVE + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ForcedOC2Config(TMR_T* TMRx, TMR_FORCED_ACTION_T action) +{ + TMRx->CCM1_OUTPUT_B.OC2MOD = action; +} + +/*! + * @brief Forces the output 3 waveform to active or inactive level + * + * @param TMRx: x can be can be 1, 2, 3 to select Timer + * + * @param action: forced Action to be set to the output waveform + * This parameter can be one of the following values: + * @arg TMR_FORCEDACTION_INACTIVE + * @arg TMR_FORCEDACTION_ACTIVE + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ForcedOC3Config(TMR_T* TMRx, TMR_FORCED_ACTION_T action) +{ + TMRx->CCM2_OUTPUT_B.OC3MOD = action; +} + +/*! + * @brief Forces the output 4 waveform to active or inactive level + * + * @param TMRx: x can be can be 1, 2, 3 to select Timer + * + * @param action: forced Action to be set to the output waveform + * This parameter can be one of the following values: + * @arg TMR_FORCEDACTION_INACTIVE + * @arg TMR_FORCEDACTION_ACTIVE + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ForcedOC4Config(TMR_T* TMRx, TMR_FORCED_ACTION_T action) +{ + TMRx->CCM2_OUTPUT_B.OC4MOD = action; +} + +/*! + * @brief Sets Capture Compare Preload Control bit + * + * @param TMRx: x can be can be 1£¬2£¬3 and 15 to select Timer + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_EnableCCPreload(TMR_T* TMRx) +{ + TMRx->CTRL2_B.CCPEN = ENABLE; +} + +/*! + * @brief Resets Capture Compare Preload Control bit + * + * @param TMRx: x can be can be 1£¬2£¬3 and 15 to select Timer + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_DisableCCPreload(TMR_T* TMRx) +{ + TMRx->CTRL2_B.CCPEN = DISABLE; +} + +/*! + * @brief Enables or disables the peripheral Preload register on CC1 + * + * @param TMRx: x can be can be 1, 2, 3 ,14, 15, 16 and 17 to select Timer + * + * @param OCPreload: new state of the TMRx peripheral Preload register + * This parameter can be one of the following values: + * @arg TMR_OC_PRELOAD_DISABLE + * @arg TMR_OC_PRELOAD_ENABLE + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_OC1PreloadConfig(TMR_T* TMRx, TMR_OC_PRELOAD_T OCPreload) +{ + TMRx->CCM1_OUTPUT_B.OC1PEN = OCPreload; +} + +/*! + * @brief Enables or disables the peripheral Preload register on CC2 + * + * @param TMRx: x can be can be 1, 2, 3 and 15 to select Timer + * + * @param OCPreload: new state of the TMRx peripheral Preload register + * This parameter can be one of the following values: + * @arg TMR_OC_PRELOAD_DISABLE + * @arg TMR_OC_PRELOAD_ENABLE + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_OC2PreloadConfig(TMR_T* TMRx, TMR_OC_PRELOAD_T OCPreload) +{ + TMRx->CCM1_OUTPUT_B.OC2PEN = OCPreload; +} + +/*! + * @brief Enables or disables the peripheral Preload register on CC3 + * + * @param TMRx: x can be can be 1, 2, 3 to select Timer + * + * @param OCPreload: new state of the TMRx peripheral Preload register + * This parameter can be one of the following values: + * @arg TMR_OC_PRELOAD_DISABLE + * @arg TMR_OC_PRELOAD_ENABLE + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_OC3PreloadConfig(TMR_T* TMRx, TMR_OC_PRELOAD_T OCPreload) +{ + TMRx->CCM2_OUTPUT_B.OC3PEN = OCPreload; +} + +/*! + * @brief Enables or disables the peripheral Preload register on CC4 + * + * @param TMRx: x can be can be 1, 2, 3 to select Timer + * + * @param OCPreload: new state of the TMRx peripheral Preload register + * This parameter can be one of the following values: + * @arg TMR_OC_PRELOAD_DISABLE + * @arg TMR_OC_PRELOAD_ENABLE + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_OC4PreloadConfig(TMR_T* TMRx, TMR_OC_PRELOAD_T OCPreload) +{ + TMRx->CCM2_OUTPUT_B.OC4PEN = OCPreload; +} + +/*! + * @brief Configures the Output Compare 1 Fast feature + * + * @param TMRx: where x can be 1, 2, 3, 14, 15, 16 and 17 to select the TMR peripheral + * + * @param OCFast: new state of the Output Compare Fast Enable Bit + * This parameter can be one of the following values: + * @arg TMR_OCFAST_DISABLE + * @arg TMR_OCFAST_ENABLE + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ + +void TMR_OC1FastConfit(TMR_T* TMRx, TMR_OCFAST_T OCFast) +{ + TMRx->CCM1_OUTPUT_B.OC1FEN = OCFast; +} + +/*! + * @brief Configures the Output Compare 2 Fast feature + * + * @param TMRx: where x can be 1, 2, 3 and 15 to select the TMR peripheral + * + * @param OCFast: new state of the Output Compare Fast Enable Bit + * This parameter can be one of the following values: + * @arg TMR_OCFAST_DISABLE + * @arg TMR_OCFAST_ENABLE + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_OC2FastConfit(TMR_T* TMRx, TMR_OCFAST_T OCFast) +{ + TMRx->CCM1_OUTPUT_B.OC2FEN = OCFast; +} + +/*! + * @brief Configures the Output Compare 3 Fast feature + * + * @param TMRx: where x can be 1, 2, 3 to select the TMR peripheral + * + * @param OCFast: new state of the Output Compare Fast Enable Bit + * This parameter can be one of the following values: + * @arg TMR_OCFAST_DISABLE + * @arg TMR_OCFAST_ENABLE + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_OC3FastConfit(TMR_T* TMRx, TMR_OCFAST_T OCFast) +{ + TMRx->CCM2_OUTPUT_B.OC3FEN = OCFast; +} + +/*! + * @brief Configures the Output Compare 4 Fast feature + * + * @param TMRx: where x can be 1, 2, 3 to select the TMR peripheral + * + * @param OCFast: new state of the Output Compare Fast Enable Bit + * This parameter can be one of the following values: + * @arg TMR_OCFAST_DISABLE + * @arg TMR_OCFAST_ENABLE + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_OC4FastConfit(TMR_T* TMRx, TMR_OCFAST_T OCFast) +{ + TMRx->CCM2_OUTPUT_B.OC4FEN = OCFast; +} + +/*! + * @brief Clears or safeguards the OCREF1 signal on an external event + * + * @param TMRx: where x can be 1, 2, 3, 14, 15, 16 and 17 to select the TMR peripheral + * + * @param OCCler: new state of the Output Compare Clear Enable Bit + * This parameter can be one of the following values: + * @arg TMR_OCCLER_DISABLE + * @arg TMR_OCCLER_ENABLE + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ClearOC1Ref(TMR_T* TMRx, TMR_OCCLER_T OCCler) +{ + TMRx->CCM1_OUTPUT_B.OC1CEN = OCCler; +} + +/*! + * @brief Clears or safeguards the OCREF2 signal on an external event + * + * @param TMRx: where x can be 1, 2, 3 and 15 to select the TMR peripheral + * + * @param OCCler: new state of the Output Compare Clear Enable Bit + * This parameter can be one of the following values: + * @arg TMR_OCCLER_DISABLE + * @arg TMR_OCCLER_ENABLE + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ClearOC2Ref(TMR_T* TMRx, TMR_OCCLER_T OCCler) +{ + TMRx->CCM1_OUTPUT_B.OC2CEN = OCCler; +} + +/*! + * @brief Clears or safeguards the OCREF3 signal on an external event + * + * @param TMRx: where x can be 1, 2, 3 to select the TMR peripheral + * + * @param OCCler: new state of the Output Compare Clear Enable Bit + * This parameter can be one of the following values: + * @arg TMR_OCCLER_DISABLE + * @arg TMR_OCCLER_ENABLE + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ClearOC3Ref(TMR_T* TMRx, TMR_OCCLER_T OCCler) +{ + TMRx->CCM2_OUTPUT_B.OC3CEN = OCCler; +} + +/*! + * @brief Clears or safeguards the OCREF4 signal on an external event + * + * @param TMRx: where x can be 1, 2, 3 to select the TMR peripheral + * + * @param OCCler: new state of the Output Compare Clear Enable Bit + * This parameter can be one of the following values: + * @arg TMR_OCCLER_DISABLE + * @arg TMR_OCCLER_ENABLE + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ClearOC4Ref(TMR_T* TMRx, TMR_OCCLER_T OCCler) +{ + TMRx->CCM2_OUTPUT_B.OC4CEN = OCCler; +} + +/*! + * @brief Configures the channel 1 polarity + * + * @param TMRx: where x can be 1, 2, 3, 14, 15, 16 and 17 to select the TMR peripheral + * + * @param OCPolarity: specifies the OC1 Polarity + * This parameter can be one of the following values: + * @arg TMR_OC_POLARITY_HIGH + * @arg TMR_OC_POLARITY_LOW + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_OC1PolarityConfig(TMR_T* TMRx, TMR_OC_POLARITY_T OCPolarity) +{ + TMRx->CCEN_B.CC1POL = OCPolarity; +} + +/*! + * @brief Configures the channel 1N polarity + * + * @param TMRx: where x can be 1, 15, 16 and 17 to select the TMR peripheral + * + * @param OCNPolarity: specifies the OC1 NPolarity + * This parameter can be one of the following values: + * @arg TMR_OC_NPOLARITY_HIGH + * @arg TMR_OC_NPOLARITY_LOW + * @retval None + */ +void TMR_OC1NPolarityConfig(TMR_T* TMRx, TMR_OC_NPOLARITY_T OCNPolarity) +{ + TMRx->CCEN_B.CC1NPOL = OCNPolarity; +} + +/*! + * @brief Configures the channel 2 polarity + * + * @param TMRx: where x can be 1, 2, 3 and 15 to select the TMR peripheral + * + * @param OCPolarity: specifies the OC2 Polarity + * This parameter can be one of the following values: + * @arg TMR_OC_POLARITY_HIGH + * @arg TMR_OC_POLARITY_LOW + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_OC2PolarityConfig(TMR_T* TMRx, TMR_OC_POLARITY_T OCPolarity) +{ + TMRx->CCEN_B.CC2POL = OCPolarity; +} + +/*! + * @brief Configures the channel 2N polarity + * + * @param TMRx: where x can be 1 to select the TMR peripheral + * + * @param OCNPolarity: specifies the OC2 NPolarity + * This parameter can be one of the following values: + * @arg TMR_OC_NPOLARITY_HIGH + * @arg TMR_OC_NPOLARITY_LOW + * @retval None + */ +void TMR_OC2NPolarityConfig(TMR_T* TMRx, TMR_OC_NPOLARITY_T OCNPolarity) +{ + TMRx->CCEN_B.CC2NPOL = OCNPolarity; +} + +/*! + * @brief Configures the channel 3 polarity + * + * @param TMRx: where x can be 1, 2, 3 to select the TMR peripheral + * + * @param OCPolarity: specifies the OC3 Polarity + * This parameter can be one of the following values: + * @arg TMR_OC_POLARITY_HIGH + * @arg TMR_OC_POLARITY_LOW + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_OC3PolarityConfig(TMR_T* TMRx, TMR_OC_POLARITY_T OCPolarity) +{ + TMRx->CCEN_B.CC3POL = OCPolarity; +} + +/*! + * @brief Configures the channel 3N polarity + * + * @param TMRx: where x can be 1 to select the TMR peripheral + * + * @param OCNPolarity: specifies the OC3 NPolarity + * This parameter can be one of the following values: + * @arg TMR_OC_NPOLARITY_HIGH + * @arg TMR_OC_NPOLARITY_LOW + * @retval None + */ +void TMR_OC3NPolarityConfig(TMR_T* TMRx, TMR_OC_NPOLARITY_T OCNPolarity) +{ + TMRx->CCEN_B.CC3NPOL = OCNPolarity; +} + +/*! + * @brief Configures the channel 4 polarity + * + * @param TMRx: where x can be 1, 2, 3 to select the TMR peripheral + * + * @param OCPolarity: specifies the OC4 Polarity + * This parameter can be one of the following values: + * @arg TMR_OC_POLARITY_HIGH + * @arg TMR_OC_POLARITY_LOW + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_OC4PolarityConfig(TMR_T* TMRx, TMR_OC_POLARITY_T OCPolarity) +{ + TMRx->CCEN_B.CC4POL = OCPolarity; +} + +/*! + * @brief Selects the OCReference Clear source + * + * @param TMRx: x can be 1, 2, 3 to select Timer. + * + * @param OCReferenceClear: specifies the OCReference Clear source + * This parameter can be one of the following values: + * @arg TMR_OCCS_ETRF + * @arg TMR_OCCS_OCREFCLR + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_SelectOCREFClear(TMR_T* TMRx, TMR_OCCSEL_T OCReferenceClear) +{ + TMRx->SMCTRL_B.OCCSEL = OCReferenceClear; +} + +/*! + * @brief Enables the Capture Compare Channel x + * + * @param TMRx: where x can be 1, 2, 3, 14, 15, 16 and 17 to select the TMR peripheral + * + * @param channel: TMR channel + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_EnableCCxChannel(TMR_T* TMRx, TMR_CHANNEL_T channel) +{ + TMRx->CCEN |= BIT_SET << channel; +} + +/*! + * @brief Disables the Capture Compare Channel x + * + * @param TMRx: where x can be 1, 2, 3, 14, 15, 16 and 17 to select the TMR peripheral + * + * @param channel: TMR channel + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_DisableCCxChannel(TMR_T* TMRx, TMR_CHANNEL_T channel) +{ + TMRx->CCEN &= ~(BIT_SET << channel); +} + +/*! + * @brief Enables the Capture Compare Channel xN. + * + * @param TMRx: where x can be 1, 15, 16 and 17 to select the TMR peripheral + * + * @param channel: TMR channel + * + * @retval None + */ +void TMR_EnableCCxNChannel(TMR_T* TMRx, TMR_CHANNEL_T channel) +{ + TMRx->CCEN |= 0x04 << channel; +} + +/*! + * @brief Disables the Capture Compare Channel xN + * + * @param TMRx: where x can be 1, 15, 16 and 17 to select the TMR peripheral + * + * @param channel: TMR channel + * + * @retval None + */ +void TMR_DisableCCxNChannel(TMR_T* TMRx, TMR_CHANNEL_T channel) +{ + TMRx->CCEN &= ~(0x04 << channel); +} + +/*! + * @brief Enable Selects the TMR peripheral Commutation event + * + * @param TMRx: where x can be 1, 15, 16 and 17 to select the TMR peripheral + * + * @retval None + */ + +void TMR_EnableSelectCOM(TMR_T* TMRx) +{ + TMRx->CTRL2_B.CCUSEL = ENABLE; +} +/*! + * @brief Disable Selects the TMR peripheral Commutation event + * + * @param TMRx: where x can be 1, 15, 16 and 17 to select the TMR peripheral + * + * @retval None + */ +void TMR_DisableSelectCOM(TMR_T* TMRx) +{ + TMRx->CTRL2_B.CCUSEL = DISABLE; +} + +/*! + * @brief Configure the TI1 as Input. + * + * @param TMRx: where x can be 1, 2, 3, 14, 15, 16 and 17 to select the TMR peripheral + * + * @param ICpolarity: The Input Polarity. + * + * @param ICselection: specifies the input to be used. + * + * @param ICfilter: Specifies the Input Capture Filter + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +static void TI1Config(TMR_T* TMRx, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter) +{ + uint16_t tmpchctrl = 0; + + /** Disable the Channel 1: Reset the CC1EN Bit */ + TMRx->CCEN_B.CC1EN = BIT_RESET; + + /** Select the Input and set the filter */ + TMRx->CCM1_INPUT_B.CC1SEL = BIT_RESET; + TMRx->CCM1_INPUT_B.IC1F = BIT_RESET; + TMRx->CCM1_INPUT_B.CC1SEL = ICselection; + TMRx->CCM1_INPUT_B.IC1F = ICfilter; + + /** Select the Polarity */ + tmpchctrl = TMRx->CCEN; + tmpchctrl &= (uint16_t)~((uint16_t)TMR_IC_POLARITY_BOTHEDGE); + tmpchctrl |= ICpolarity; + TMRx->CCEN = tmpchctrl; + + /** Set the CC1EN Bit */ + TMRx->CCEN_B.CC1EN = BIT_SET; +} + +/*! + * @brief Configure the TI2 as Input + * + * @param TMRx: where x can be 1, 2, 3, 14, 15, 16 and 17 to select the TMR periphera + * + * @param ICpolarity: The Input Polarity. + * + * @param ICselection: specifies the input to be used. + * + * @param ICfilter: Specifies the Input Capture Filter + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +static void TI2Config(TMR_T* TMRx, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter) +{ + uint16_t tmpchctrl = 0; + + /** Disable the Channel 2: Reset the CC2EN Bit */ + TMRx->CCEN_B.CC2EN = BIT_RESET; + + /** Select the Input and set the filter */ + TMRx->CCM1_INPUT_B.CC2SEL = BIT_RESET; + TMRx->CCM1_INPUT_B.IC2F = BIT_RESET; + TMRx->CCM1_INPUT_B.CC2SEL = ICselection; + TMRx->CCM1_INPUT_B.IC2F = ICfilter; + + /** Select the Polarity */ + tmpchctrl = TMRx->CCEN; + tmpchctrl &= (uint16_t)~((uint16_t)TMR_IC_POLARITY_BOTHEDGE << 4); + tmpchctrl |= (uint16_t)(ICpolarity << 4); + TMRx->CCEN = tmpchctrl; + + /** Set the CC2EN Bit */ + TMRx->CCEN_B.CC2EN = BIT_SET; +} + +/*! + * @brief Configure the TI3 as Input. + * + * @param TMRx: where x can be 1, 2, 3, 14, 15, 16 or 17 to select the TMR peripheral + * + * @param ICpolarity: The Input Polarity. + * + * @param ICselection: specifies the input to be used. + * + * @param ICfilter: Specifies the Input Capture Filter + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +static void TI3Config(TMR_T* TMRx, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter) +{ + uint16_t tmpchctrl = 0; + + /** Disable the Channel 3: Reset the CC3EN Bit */ + TMRx->CCEN_B.CC3EN = BIT_RESET; + + /** Select the Input and set the filter */ + TMRx->CCM2_INPUT_B.CC3SEL = BIT_RESET; + TMRx->CCM2_INPUT_B.IC3F = BIT_RESET; + TMRx->CCM2_INPUT_B.CC3SEL = ICselection; + TMRx->CCM2_INPUT_B.IC3F = ICfilter; + + /** Select the Polarity */ + tmpchctrl = TMRx->CCEN; + tmpchctrl &= (uint16_t)~((uint16_t)TMR_IC_POLARITY_BOTHEDGE << 8); + tmpchctrl |= (uint16_t)(ICpolarity << 8); + TMRx->CCEN = tmpchctrl; + + /** Set the CC3EN Bit */ + TMRx->CCEN_B.CC3EN = BIT_SET; +} + +/*! + * @brief Configure the TI4 as Input + * + * @param TMRx: where x can be 1, 2, 3, 14, 15, 16 or 17 to select the TMR peripheral + * + * @param ICpolarity: The Input Polarity. + * + * @param ICselection: specifies the input to be used. + * + * @param ICfilter: Specifies the Input Capture Filter + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +static void TI4Config(TMR_T* TMRx, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter) +{ + uint16_t tmpchctrl = 0; + + /** Disable the Channel 4: Reset the CC4EN Bit */ + TMRx->CCEN_B.CC4EN = BIT_RESET; + + /** Select the Input and set the filter */ + TMRx->CCM2_INPUT_B.CC4SEL = BIT_RESET; + TMRx->CCM2_INPUT_B.IC4F = BIT_RESET; + TMRx->CCM2_INPUT_B.CC4SEL = ICselection; + TMRx->CCM2_INPUT_B.IC4F = ICfilter; + + /** Select the Polarity */ + tmpchctrl = TMRx->CCEN; + tmpchctrl &= (uint16_t)~((uint16_t)TMR_IC_POLARITY_BOTHEDGE << 12); + tmpchctrl |= (uint16_t)(ICpolarity << 12); + TMRx->CCEN = tmpchctrl; + + /** Set the CC4EN Bit */ + TMRx->CCEN_B.CC4EN = BIT_SET; +} + +/*! + * @brief Configure Peripheral equipment + * + * @param TMRx: where x can be 1, 2, 3, 14, 15, 16 or 17 to select the TMR peripheral + * + * @param ICconfigstruct: pointer to a TMR_ICConfig_T structure + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ICConfig(TMR_T* TMRx, TMR_ICConfig_T* ICconfigstruct) +{ + if (ICconfigstruct->channel == TMR_CHANNEL_1) + { + /** TI1 Configuration */ + TI1Config(TMRx, ICconfigstruct->ICpolarity, ICconfigstruct->ICselection, ICconfigstruct->ICfilter); + TMR_SetIC1Prescal(TMRx, ICconfigstruct->ICprescaler); + } + else if (ICconfigstruct->channel == TMR_CHANNEL_2) + { + /** TI2 Configuration */ + TI2Config(TMRx, ICconfigstruct->ICpolarity, ICconfigstruct->ICselection, ICconfigstruct->ICfilter); + TMR_SetIC2Prescal(TMRx, ICconfigstruct->ICprescaler); + } + else if (ICconfigstruct->channel == TMR_CHANNEL_3) + { + /** TI3 Configuration */ + TI3Config(TMRx, ICconfigstruct->ICpolarity, ICconfigstruct->ICselection, ICconfigstruct->ICfilter); + TMR_SetIC3Prescal(TMRx, ICconfigstruct->ICprescaler); + } + else if (ICconfigstruct->channel == TMR_CHANNEL_4) + { + /** TI4 Configuration */ + TI4Config(TMRx, ICconfigstruct->ICpolarity, ICconfigstruct->ICselection, ICconfigstruct->ICfilter); + TMR_SetIC4Prescal(TMRx, ICconfigstruct->ICprescaler); + } +} + +/*! + * @brief Initialize the IC timer with its default value. + * + * @param ICconfigstruct: pointer to a TMR_ICConfig_T structure + * + * @retval None + */ +void TMR_ICConfigStructInit(TMR_ICConfig_T* ICconfigstruct) +{ + ICconfigstruct->channel = TMR_CHANNEL_1; + ICconfigstruct->ICpolarity = TMR_IC_POLARITY_RISING; + ICconfigstruct->ICselection = TMR_IC_SELECTION_DIRECT_TI; + ICconfigstruct->ICprescaler = TMR_ICPSC_DIV1; + ICconfigstruct->ICfilter = 0x00; +} + +/*! + * @brief Config of PWM output + * + * @param TMRx: where x can be 1, 2, 3 and 15 to select the TMR peripheral + * + * @param ICconfigstruct: pointer to a TMR_ICConfig_T structure + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_PWMConfig(TMR_T* TMRx, TMR_ICConfig_T* ICconfigstruct) +{ + uint16_t icpolarity = TMR_IC_POLARITY_RISING; + uint16_t icselection = TMR_IC_SELECTION_DIRECT_TI; + + /** Select the Opposite Input Polarity */ + if (ICconfigstruct->ICpolarity == TMR_IC_POLARITY_RISING) + { + icpolarity = TMR_IC_POLARITY_FALLING; + } + else + { + icpolarity = TMR_IC_POLARITY_RISING; + } + + /** Select the Opposite Input */ + if (ICconfigstruct->ICselection == TMR_IC_SELECTION_DIRECT_TI) + { + icselection = TMR_IC_SELECTION_INDIRECT_TI; + } + else + { + icselection = TMR_IC_SELECTION_DIRECT_TI; + } + + if (ICconfigstruct->channel == TMR_CHANNEL_1) + { + /** TI1 Configuration */ + TI1Config(TMRx, ICconfigstruct->ICpolarity, ICconfigstruct->ICselection, ICconfigstruct->ICfilter); + /** Set the Input Capture Prescaler value */ + TMR_SetIC1Prescal(TMRx, ICconfigstruct->ICprescaler); + /** TI2 Configuration */ + TI2Config(TMRx, icpolarity, icselection, ICconfigstruct->ICfilter); + /** Set the Input Capture Prescaler value */ + TMR_SetIC2Prescal(TMRx, ICconfigstruct->ICprescaler); + } + else + { + /** TI2 Configuration */ + TI2Config(TMRx, ICconfigstruct->ICpolarity, ICconfigstruct->ICselection, ICconfigstruct->ICfilter); + /** Set the Input Capture Prescaler value */ + TMR_SetIC2Prescal(TMRx, ICconfigstruct->ICprescaler); + /** TI1 Configuration */ + TI1Config(TMRx, icpolarity, icselection, ICconfigstruct->ICfilter); + /** Set the Input Capture Prescaler value */ + TMR_SetIC1Prescal(TMRx, ICconfigstruct->ICprescaler); + } +} + +/*! + * @brief Read Input Capture 1 value + * + * @param TMRx: where x can be 1, 2, 3, 14, 15, 16 and 17 to select the TMR peripheral + * + * @retval Capture Compare 1 Register value + * + * @note TMR2 it's not for APM32F030 devices + */ +uint16_t TMR_ReadCaputer1(TMR_T* TMRx) +{ + return TMRx->CC1; +} + +/*! + * @brief Read Input Capture 2 value + * + * @param TMRx: where x can be 1, 2, 3 and 15 to select the TMR peripheral + * + * @retval Capture Compare 2 Register value + * + * @note TMR2 it's not for APM32F030 devices + */ +uint16_t TMR_ReadCaputer2(TMR_T* TMRx) +{ + return TMRx->CC2; +} + +/*! + * @brief Read Input Capture 3 value + * + * @param TMRx: where x can be 1, 2, 3 to select the TMR peripheral + * + * @retval Capture Compare 3 Register value + * + * @note TMR2 it's not for APM32F030 devices + */ +uint16_t TMR_ReadCaputer3(TMR_T* TMRx) +{ + return TMRx->CC3; +} + +/*! + * @brief Read Input Capture 4 value + * + * @param TMRx: where x can be 1, 2, 3 to select the TMR peripheral + * + * @retval Capture Compare 4 Register value + * + * @note TMR2 it's not for APM32F030 devices + */ +uint16_t TMR_ReadCaputer4(TMR_T* TMRx) +{ + return TMRx->CC4; +} + +/*! + * @brief Sets the TMRx Input Capture 1 prescaler + * + * @param TMRx: where x can be 1, 2, 3, 14, 15, 16 and 17 to select the TMR peripheral + * + * @param prescaler: specifies the Input Capture 1 prescaler new value + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_SetIC1Prescal(TMR_T* TMRx, TMR_IC_PRESCALER_T prescaler) +{ + TMRx->CCM1_INPUT_B.IC1PSC = BIT_RESET; + TMRx->CCM1_INPUT_B.IC1PSC = prescaler; +} +/*! + * @brief Sets the TMRx Input Capture 2 prescaler + * + * @param TMRx: where x can be 1, 2, 3 and 15 to select the TMR peripheral + * + * @param prescaler: specifies the Input Capture 2 prescaler new value + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_SetIC2Prescal(TMR_T* TMRx, TMR_IC_PRESCALER_T prescaler) +{ + TMRx->CCM1_INPUT_B.IC2PSC = BIT_RESET; + TMRx->CCM1_INPUT_B.IC2PSC = prescaler; +} + +/*! + * @brief Sets the TMRx Input Capture 3 prescaler + * + * @param TMRx: where x can be 1, 2, 3 to select the TMR peripheral + * + * @param prescaler: specifies the Input Capture 3 prescaler new value + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_SetIC3Prescal(TMR_T* TMRx, TMR_IC_PRESCALER_T prescaler) +{ + TMRx->CCM2_INPUT_B.IC3PSC = BIT_RESET; + TMRx->CCM2_INPUT_B.IC3PSC = prescaler; +} + +/*! + * @brief Sets the TMRx Input Capture 4 prescaler + * + * @param TMRx: where x can be 1, 2, 3 to select the TMR peripheral + * + * @param prescaler: specifies the Input Capture 4 prescaler new value + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_SetIC4Prescal(TMR_T* TMRx, TMR_IC_PRESCALER_T prescaler) +{ + TMRx->CCM2_INPUT_B.IC4PSC = BIT_RESET; + TMRx->CCM2_INPUT_B.IC4PSC = prescaler; +} + +/*! + * @brief Enable intterupts + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @param interrupt: specifies the TMR interrupts sources + * The parameter can be any combination of following values: + * @arg TMR_INT_UPDATE: TMR update Interrupt source + * @arg TMR_INT_CH1: TMR Capture Compare 1 Interrupt source + * @arg TMR_INT_CH2: TMR Capture Compare 2 Interrupt source + * @arg TMR_INT_CH3: TMR Capture Compare 3 Interrupt source + * @arg TMR_INT_CH4: TMR Capture Compare 4 Interrupt source + * @arg TMR_INT_CCU: TMR Commutation Interrupt source + * @arg TMR_INT_TRG: TMR Trigger Interrupt source + * @arg TMR_INT_BRK: TMR Break Interrupt source + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_EnableInterrupt(TMR_T* TMRx, uint16_t interrupt) +{ + TMRx->DIEN |= interrupt; +} + +/*! + * @brief Disable intterupts + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @param interrupt: specifies the TMR interrupts sources + * The parameter can be any combination of following values: + * @arg TMR_INT_UPDATE: TMR update Interrupt source + * @arg TMR_INT_CH1: TMR Capture Compare 1 Interrupt source + * @arg TMR_INT_CH2: TMR Capture Compare 2 Interrupt source + * @arg TMR_INT_CH3: TMR Capture Compare 3 Interrupt source + * @arg TMR_INT_CH4: TMR Capture Compare 4 Interrupt source + * @arg TMR_INT_CCU: TMR Commutation Interrupt source + * @arg TMR_INT_TRG: TMR Trigger Interrupt source + * @arg TMR_INT_BRK: TMR Break Interrupt source + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_DisableInterrupt(TMR_T* TMRx, uint16_t interrupt) +{ + TMRx->DIEN &= ~interrupt; +} + +/*! + * @brief Configures the TMRx event to be generate by software + * + * @param TMRx: where x can be 1£¬2£¬3, 14, 15, 16 and 17 to select the TMR peripheral + * + * @param event: specifies the TMR generate event + * The parameter can be any combination of following values: + * @arg TMR_EVENT_UPDATE: TMR update Interrupt source + * @arg TMR_EVENT_CH1: TMR Capture Compare 1 Interrupt source + * @arg TMR_EVENT_CH2: TMR Capture Compare 2 Interrupt source + * @arg TMR_EVENT_CH3: TMR Capture Compare 3 Interrupt source + * @arg TMR_EVENT_CH4: TMR Capture Compare 4 Interrupt source + * @arg TMR_EVENT_CCU: TMR Commutation Interrupt source + * @arg TMR_EVENT_TRG: TMR Trigger Interrupt source + * @arg TMR_EVENT_BRK: TMR Break Interrupt source + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + * TMR6 and TMR7 only TMR_EVENT_UPDATE + * TMR_EVENT_CCU and TMR_EVENT_BRK are used only with TMR1 + */ +void TMR_GenerateEvent(TMR_T* TMRx, uint16_t event) +{ + TMRx->CEG |= event; +} + +/*! + * @brief Check whether the flag is set or reset + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + * + * @param flag: specifies the TMR flag + * The parameter can be one of following values: + * @arg TMR_FLAG_UPDATA: TMR update Flag + * @arg TMR_FLAG_CH1: TMR Capture Compare 1 flag + * @arg TMR_FLAG_CH2: TMR Capture Compare 2 flag + * @arg TMR_FLAG_CH3: TMR Capture Compare 3 flag + * @arg TMR_FLAG_CH4: TMR Capture Compare 4 flag + * @arg TMR_FLAG_CCU: TMR Commutation flag + * @arg TMR_FLAG_TRG: TMR Trigger flag + * @arg TMR_FLAG_BRK: TMR Break flag + * @arg TMR_FLAG_CH1OC: TMR Capture Compare 1 overcapture flag + * @arg TMR_FLAG_CH2OC: TMR Capture Compare 2 overcapture flag + * @arg TMR_FLAG_CH3OC: TMR Capture Compare 3 overcapture flag + * @arg TMR_FLAG_CH4OC: TMR Capture Compare 4 overcapture flag + * + * @retval The new state of the flag is SET or RESET + * + * @note TMR15 can have only TMR_FLAG_UPDATA, TMR_FLAG_CH1, TMR_FLAG_CH2 and TMR_FLAG_TRG + * TMR14, TMR16 and TMR17 can have TMR_FLAG_UPDATA and TMR_FLAG_CH1 + * TMR6, TMR7 only TMR_FLAG_UPDATA + * TMR_FLAG_BRK is used only with TMR1 and TMR15. + * TMR_FLAG_CCU is used only with TMR1, TMR15, TMR16 and TMR17 + */ +uint16_t TMR_ReadStatusFlag(TMR_T* TMRx, TMR_FLAG_T flag) +{ + if ((TMRx->STS & flag) != RESET) + { + return SET; + } + else + { + return RESET; + } +} + +/*! + * @brief Clears the TMR's pending flags + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + * + * @param flag: specifies the TMR flag + * The parameter can be any combination of following values: + * @arg TMR_FLAG_UPDATA: TMR update Flag + * @arg TMR_FLAG_CH1: TMR Capture Compare 1 flag + * @arg TMR_FLAG_CH2: TMR Capture Compare 2 flag + * @arg TMR_FLAG_CH3: TMR Capture Compare 3 flag + * @arg TMR_FLAG_CH4: TMR Capture Compare 4 flag + * @arg TMR_FLAG_CCU: TMR Commutation flag + * @arg TMR_FLAG_TRG: TMR Trigger flag + * @arg TMR_FLAG_BRK: TMR Break flag + * @arg TMR_FLAG_CH1OC: TMR Capture Compare 1 overcapture flag + * @arg TMR_FLAG_CH2OC: TMR Capture Compare 2 overcapture flag + * @arg TMR_FLAG_CH3OC: TMR Capture Compare 3 overcapture flag + * @arg TMR_FLAG_CH4OC: TMR Capture Compare 4 overcapture flag + * + * @retval None + */ +void TMR_ClearStatusFlag(TMR_T* TMRx, uint16_t flag) +{ + TMRx->STS = ~flag; +} + +/*! + * @brief Check whether the TMR Interrupt flag is set or reset + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + * + * @param flag: specifies the TMR interrupts flag + * The parameter can be one of following values: + * @arg TMR_INT_FLAG_UPDATE: TMR update Interrupt flag + * @arg TMR_INT_FLAG_CH1: TMR Capture Compare 1 Interrupt flag + * @arg TMR_INT_FLAG_CH2: TMR Capture Compare 2 Interrupt flag + * @arg TMR_INT_FLAG_CH3: TMR Capture Compare 3 Interrupt flag + * @arg TMR_INT_FLAG_CH4: TMR Capture Compare 4 Interrupt flag + * @arg TMR_INT_FLAG_CCU: TMR Commutation Interrupt flag + * @arg TMR_INT_FLAG_TRG: TMR Trigger Interrupt flag + * @arg TMR_INT_FLAG_BRK: TMR Break Interrupt flag + * + * @retval The new state of the INT flag is SET or RESET + * + * @note TMR15 can have only TMR_INT_FLAG_UPDATE, TMR_INT_FLAG_CH1, TMR_INT_FLAG_CH2 and TMR_INT_FLAG_TRG + * TMR14, TMR16 and TMR17 can have TMR_INT_FLAG_UPDATE and TMR_INT_FLAG_CH1 + * TMR6, TMR7 only TMR_INT_FLAG_UPDATE + * TMR_INT_FLAG_BRK is used only with TMR1 and TMR15. + * TMR_INT_FLAG_CCU is used only with TMR1, TMR15, TMR16 and TMR17 + */ +uint16_t TMR_ReadIntFlag(TMR_T* TMRx, TMR_INT_FLAG_T flag) +{ + if (((TMRx->STS & flag) != RESET) && ((TMRx->DIEN & flag) != RESET)) + { + return SET; + } + else + { + return RESET; + } +} + +/*! + * @brief Clears the TMR's interrupt pending bits + * + * @param TMRx: x can be can be 1, 2, 3, 6, 7, 14, 15, 16 and 17 to select Timer + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + * + * @param flag: specifies the TMR interrupts flag + * The parameter can be any combination of following values: + * @arg TMR_INT_FLAG_UPDATE: TMR update Interrupt flag + * @arg TMR_INT_FLAG_CH1: TMR Capture Compare 1 Interrupt flag + * @arg TMR_INT_FLAG_CH2: TMR Capture Compare 2 Interrupt flag + * @arg TMR_INT_FLAG_CH3: TMR Capture Compare 3 Interrupt flag + * @arg TMR_INT_FLAG_CH4: TMR Capture Compare 4 Interrupt flag + * @arg TMR_INT_FLAG_CCU: TMR Commutation Interrupt flag + * @arg TMR_INT_FLAG_TRG: TMR Trigger Interrupt flag + * @arg TMR_INT_FLAG_BRK: TMR Break Interrupt flag + * + * @retval None + */ +void TMR_ClearIntFlag(TMR_T* TMRx, uint16_t flag) +{ + TMRx->STS = ~flag; +} + +/*! + * @brief Configures the TMRx's DMA interface. + * + * @param TMRx: where x can be 1, 2, 3, 15, 16 and 17 to select the TMR peripheral + * + * @param address: DMA Base address + * + * @param lenght: DMA Burst length + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ConfigDMA(TMR_T* TMRx, TMR_DMA_BASE_ADDERSS_T address, TMR_DMA_BURST_LENGHT_T lenght) +{ + TMRx->DCTRL = (uint32_t)address | (uint32_t)lenght; +} + +/*! + * @brief Enable TMRx Requests + * + * @param TMRx: where x can be 1, 2, 3, 6, 7, 15, 16 and 17 to select the TMR peripheral + * + * @param souces: specifies the TMR DMA souces + * The parameter can be any combination of following values: + * @arg TMR_DMA_UPDATE: TMR update DMA souces + * @arg TMR_DMA_CH1: TMR Capture Compare 1 DMA souces + * @arg TMR_DMA_CH2: TMR Capture Compare 2 DMA souces + * @arg TMR_DMA_CH3: TMR Capture Compare 3 DMA souces + * @arg TMR_DMA_CH4: TMR Capture Compare 4 DMA souces + * @arg TMR_DMA_CCU: TMR Commutation DMA souces + * @arg TMR_DMA_TRG: TMR Trigger DMA souces + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_EnableDMASoure(TMR_T* TMRx, uint16_t souces) +{ + TMRx->DIEN |= souces; +} + +/*! + * @brief Disable TMRx Requests + * + * @param TMRx: where x can be 1, 2, 3, 6, 7, 15, 16 and 17 to select the TMR peripheral + * + * @param souces: specifies the TMR DMA souces + * The parameter can be any combination of following values: + * @arg TMR_DMA_UPDATE: TMR update DMA souces + * @arg TMR_DMA_CH1: TMR Capture Compare 1 DMA souces + * @arg TMR_DMA_CH2: TMR Capture Compare 2 DMA souces + * @arg TMR_DMA_CH3: TMR Capture Compare 3 DMA souces + * @arg TMR_DMA_CH4: TMR Capture Compare 4 DMA souces + * @arg TMR_DMA_CCU: TMR Commutation DMA souces + * @arg TMR_DMA_TRG: TMR Trigger DMA souces + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_DisableDMASoure(TMR_T* TMRx, uint16_t souces) +{ + TMRx->DIEN &= ~souces; +} + +/*! + * @brief Enable Capture Compare DMA source + * + * @param TMRx: where x can be 1, 2, 3, 15, 16 and 17 to select the TMR peripheral + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_EnableCCDMA(TMR_T* TMRx) +{ + TMRx->CTRL2_B.CCDSEL = ENABLE; +} + +/*! + * @brief Disable Capture Compare DMA source + * + * @param TMRx: where x can be 1, 2, 3, 15, 16 and 17 to select the TMR peripheral + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_DisableCCDMA(TMR_T* TMRx) +{ + TMRx->CTRL2_B.CCDSEL = DISABLE; +} + +/*! + * @brief Configures the TMRx internal Clock + * + * @param TMRx: where x can be 1, 2, 3, and 15 select the TMR peripheral + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ConfigInternalClock(TMR_T* TMRx) +{ + TMRx->SMCTRL_B.SMFSEL = DISABLE; +} + +/*! + * @brief Configures the TMRx Internal Trigger as External Clock + * + * @param TMRx: where x can be 1, 2, 3, and 15 select the TMR peripheral + * + * @param input: specifies the TMR trigger souces + * The parameter can be one of following values: + * @arg TMR_TS_ITR0: TMR Internal Trigger 0 + * @arg TMR_TS_ITR1: TMR Internal Trigger 1 + * @arg TMR_TS_ITR2: TMR Internal Trigger 2 + * @arg TMR_TS_ITR3: TMR Internal Trigger 3 + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ConfigITRxExternalClock(TMR_T* TMRx, TMR_INPUT_TRIGGER_SOURCE_T input) +{ + TMR_SelectInputTrigger(TMRx, input); + TMRx->SMCTRL_B.SMFSEL = 0x07; +} + +/*! + * @brief Configures the TMRx Trigger as External Clock + * + * @param TMRx: where x can be 1, 2, 3, and 15 select the TMR peripheral + * + * @param input: specifies the TMR trigger souces + * The parameter can be one of following values: + * @arg TMR_TS_TI1F_ED: TI1 Edge Detector + * @arg TMR_TS_TI1FP1: Filtered Timer Input 1 + * @arg TMR_TS_TI2FP2: Filtered Timer Input 2 + * + * @param ICpolarity: specifies the TMR IC polarity + * The parameter can be one of following values: + * @arg TMR_IC_POLARITY_RISING: TMR IC polarity rising + * @arg TMR_IC_POLARITY_FALLING: TMR IC polarity falling + * + * @param ICfilter:specifies the filter value.This parameter must be a value between 0x00 and 0x0F. + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ConfigTIxExternalClock(TMR_T* TMRx, TMR_INPUT_TRIGGER_SOURCE_T input, + TMR_IC_POLARITY_T ICpolarity, uint16_t ICfilter) +{ + if (input == TMR_TS_TI2FP2) + { + TI2Config(TMRx, ICpolarity, TMR_IC_SELECTION_DIRECT_TI, ICfilter); + } + else + { + TI1Config(TMRx, ICpolarity, TMR_IC_SELECTION_DIRECT_TI, ICfilter); + } + + TMR_SelectInputTrigger(TMRx, input); + TMRx->SMCTRL_B.SMFSEL = 0x07; +} + +/*! + * @brief Configures the External clock Mode1 + * + * @param TMRx: where x can be 1, 2, 3 select the TMR peripheral + * + * @param prescaler: The external Trigger Prescaler. + * + * @param polarity: The external Trigger Polarity. + * + * @param filter: External Trigger Filter. + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ConfigExternalClockMode1(TMR_T* TMRx, TMR_EXTTRG_PRESCALER_T prescaler, + TMR_EXTTRG_POLARITY_T polarity, uint16_t filter) +{ + TMR_ConfigExternalTrigger(TMRx, prescaler, polarity, filter); + TMRx->SMCTRL_B.SMFSEL = BIT_RESET; + TMRx->SMCTRL_B.SMFSEL = 0x07; + TMRx->SMCTRL_B.TRGSEL = 0x07; +} + +/*! + * @brief Configures the External clock Mode2 + * + * @param TMRx: where x can be 1, 2, 3 select the TMR peripheral + * + * @param prescaler: The external Trigger Prescaler + * + * @param polarity: The external Trigger Polarity + * + * @param filter: External Trigger Filter + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ConfigExternalClockMode2(TMR_T* TMRx, TMR_EXTTRG_PRESCALER_T prescaler, + TMR_EXTTRG_POLARITY_T polarity, uint16_t filter) +{ + TMR_ConfigExternalTrigger(TMRx, prescaler, polarity, filter); + TMRx->SMCTRL_B.ECEN = ENABLE; +} + +/*! + * @brief Selects the Input Trigger source + * + * @param TMRx: where x can be 1, 2, 3 and 15 select the TMR peripheral + * + * @param input: specifies the TMR trigger souces + * The parameter can be one of following values: + * @arg TMR_TS_ITR0: TMR Internal Trigger 0 + * @arg TMR_TS_ITR1: TMR Internal Trigger 1 + * @arg TMR_TS_ITR2: TMR Internal Trigger 2 + * @arg TMR_TS_ITR3: TMR Internal Trigger 3 + * @arg TMR_TS_TI1F_ED: TI1 Edge Detector + * @arg TMR_TS_TI1FP1: Filtered Timer Input 1 + * @arg TMR_TS_TI2FP2: Filtered Timer Input 2 + * @arg TMR_TS_ETRF: External Trigger input + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_SelectInputTrigger(TMR_T* TMRx, TMR_INPUT_TRIGGER_SOURCE_T input) +{ + TMRx->SMCTRL_B.TRGSEL = BIT_RESET; + TMRx->SMCTRL_B.TRGSEL = input; +} + +/*! + * @brief Selects the Trigger Output Mode. + * + * @param TMRx: where x can be 1, 2, 3, 6, 7 and 15 select the TMR peripheral + * + * @param source: specifies the TMR trigger souces + * The parameter can be one of following values: + * For all TMR: + * @arg TMR_TRGOSOURCE_RESET + * @arg TMR_TRGOSOURCE_ENABLE + * @arg TMR_TRGOSOURCE_UPDATE + For all TMR except TMR6 and TMR7 + * @arg TMR_TRGOSOURCE_OC1, + * @arg TMR_TRGOSOURCE_OC1REF + * @arg TMR_TRGOSOURCE_OC2REF + * @arg TMR_TRGOSOURCE_OC3REF + * @arg TMR_TRGOSOURCE_OC4REF + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + * TMR7 it's only for APM32F072 and APM32F091 devices + */ +void TMR_SelectOutputTrigger(TMR_T* TMRx, TMR_TRGOSOURCE_T source) +{ + TMRx->CTRL2_B.MMSEL = source; +} + +/*! + * @brief Selects the Slave Mode. + * + * @param TMRx: where x can be 1, 2, 3 and 15 select the TMR peripheral + * + * @param mode: TMR_SLAVEMODE_T + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_SelectSlaveMode(TMR_T* TMRx, TMR_SLAVEMODE_T mode) +{ + TMRx->SMCTRL_B.SMFSEL = mode; +} + +/*! + * @brief Enable the Master Slave Mode + * + * @param TMRx: where x can be 1, 2, 3 and 15 select the TMR peripheral + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_EnableMasterSlaveMode(TMR_T* TMRx) +{ + TMRx->SMCTRL_B.MSMEN = ENABLE ; +} + +/*! + * @brief Disable the Master Slave Mode + * + * @param TMRx: where x can be 1, 2, 3 and 15 select the TMR peripheral + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_DisableMasterSlaveMode(TMR_T* TMRx) +{ + TMRx->SMCTRL_B.MSMEN = DISABLE ; +} + +/*! + * @brief Configures the TMRx External Trigger (ETR) + * + * @param TMRx: where x can be 1, 2, 3 select the TMR peripheral + * + * @param prescaler: The external Trigger Prescaler + * + * @param polarity: The external Trigger Polarity + * + * @param filter: External Trigger Filter + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ConfigExternalTrigger(TMR_T* TMRx, TMR_EXTTRG_PRESCALER_T prescaler, + TMR_EXTTRG_POLARITY_T polarity, uint16_t filter) +{ + TMRx->SMCTRL &= 0x00FF; + TMRx->SMCTRL_B.ETPCFG = prescaler; + TMRx->SMCTRL_B.ETPOL = polarity; + TMRx->SMCTRL_B.ETFCFG = filter; +} + +/*! + * @brief Configures the Encoder Interface + * + * @param TMRx: where x can be 1, 2, 3 select the TMR peripheral + * + * @param encodeMode: specifies the Encoder Mode + * + * @param IC1Polarity: specifies the IC1 Polarity + * + * @param IC2Polarity: specifies the IC2 Polarity + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ConfigEncodeInterface(TMR_T* TMRx, TMR_ENCODER_MODE_T encodeMode, TMR_IC_POLARITY_T IC1Polarity, + TMR_IC_POLARITY_T IC2Polarity) +{ + /** Set the encoder Mode */ + TMRx->SMCTRL_B.SMFSEL = BIT_RESET; + TMRx->SMCTRL_B.SMFSEL = encodeMode; + + /** Select the Capture Compare 1 and the Capture Compare 2 as input */ + TMRx->CCM1_INPUT_B.CC1SEL = BIT_RESET ; + TMRx->CCM1_INPUT_B.CC2SEL = BIT_RESET ; + TMRx->CCM1_INPUT_B.CC1SEL = BIT_SET ; + TMRx->CCM1_INPUT_B.CC2SEL = BIT_SET ; + + /** Set the TI1 and the TI2 Polarities */ + TMRx->CCEN &= ~(TMR_IC_POLARITY_BOTHEDGE) & ~(TMR_IC_POLARITY_BOTHEDGE << 4); + TMRx->CCEN |= (IC1Polarity | IC2Polarity << 4); +} + +/*! + * @brief Enables Hall sensor interface. + * + * @param TMRx: where x can be 1, 2, 3 select the TMR peripheral + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_EnableHallSensor(TMR_T* TMRx) +{ + TMRx->CTRL2_B.TI1SEL = ENABLE; +} + +/*! + * @brief Disable Hall sensor interface. + * + * @param TMRx: where x can be 1, 2, 3 select the TMR peripheral + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_DisableHallSensor(TMR_T* TMRx) +{ + TMRx->CTRL2_B.TI1SEL = DISABLE; +} + +/*! + * @brief Configures the TMR14 Remapping input Capabilities. + * + * @param TMRx: where x can only for 14 select the TMR peripheral + * + * @param remap: specifies the TMR input reampping source + * The parameter can be one of following values: + * @arg TMR_REMAP_GPIO + * @arg TMR_REMAP_RTC_CLK + * @arg TMR_REMAP_HSEDiv32 + * @arg TMR_REMAP_MCO + * + * @retval None + * + * @note TMR2 it's not for APM32F030 devices + */ +void TMR_ConfigRemap(TMR_T* TMRx, TMR_REMAP_T remap) +{ + TMRx->OPT_B.RMPSEL = remap; +} + +/**@} end of group TMR_Functions*/ +/**@} end of group TMR_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver*/ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_usart.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_usart.c new file mode 100644 index 0000000000..3ffd8245d5 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_usart.c @@ -0,0 +1,1741 @@ +/*! + * @file apm32f0xx_usart.c + * + * @brief This file provides all the USART firmware functions + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +#include "apm32f0xx_usart.h" +#include "apm32f0xx_rcm.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup USART_Driver USART Driver + @{ +*/ + +/** @defgroup USART_Macros Macros + @{ + */ + +/**@} end of group USART_Macros */ + +/** @defgroup USART_Enumerations Enumerations + @{ + */ + +/**@} end of group USART_Enumerations */ + +/** @defgroup USART_Structures Structures + @{ + */ + +/**@} end of group USART_Structures */ + +/** @defgroup USART_Variables Variables + @{ + */ + +/**@} end of group USART_Variables */ + +/** @defgroup USART_Functions Functions + @{ +*/ + +/*! + * @brief Reset usart peripheral registers to their default reset values + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ + +void USART_Reset(USART_T* usart) +{ + if (USART1 == usart) + { + RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_USART1); + RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_USART1); + } + else if (USART2 == usart) + { + RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_USART2); + RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_USART2); + } + else if (USART3 == usart) + { + RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_USART3); + RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_USART3); + } + else if (USART4 == usart) + { + RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_USART4); + RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_USART4); + } + else if (USART5 == usart) + { + RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_USART5); + RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_USART5); + } + else if (USART6 == usart) + { + RCM_EnableAPB1PeriphReset(RCM_APB2_PERIPH_USART6); + RCM_DisableAPB1PeriphReset(RCM_APB2_PERIPH_USART6); + } + else if (USART7 == usart) + { + RCM_EnableAPB1PeriphReset(RCM_APB2_PERIPH_USART7); + RCM_DisableAPB1PeriphReset(RCM_APB2_PERIPH_USART7); + } + else if (USART8 == usart) + { + RCM_EnableAPB1PeriphReset(RCM_APB2_PERIPH_USART8); + RCM_DisableAPB1PeriphReset(RCM_APB2_PERIPH_USART8); + } +} + +/*! + * @brief Config the USART peripheral according to the specified parameters in the USART_InitStruct + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param configStruct pointer to a USART_Config_T structure + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_Config(USART_T* uart, USART_Config_T* configStruct) +{ + uint32_t temp, fCLK, intDiv, fractionalDiv; + + /** Disable USART */ + uart->CTRL1_B.UEN = 0x00; + + /** WLS, PCEN, TXEN, RXEN */ + temp = uart->CTRL1; + temp &= 0xE9F3; + temp |= (uint32_t)configStruct->mode | \ + (uint32_t)configStruct->parity | \ + (uint32_t)configStruct->wordLength; + uart->CTRL1 = temp; + + /** STOP bits */ + temp = uart->CTRL2; + temp &= 0xCFFF; + temp |= configStruct->stopBits; + uart->CTRL2 = temp; + + /** Hardware Flow Control */ + temp = uart->CTRL3; + temp &= 0xFCFF; + temp |= (uint32_t)configStruct->hardwareFlowCtrl; + uart->CTRL3 = temp; + + if (uart == USART1) + { + fCLK = RCM_ReadUSART1CLKFreq(); + } + else if (uart == USART2) + { + fCLK = RCM_ReadUSART2CLKFreq(); + } + else + { + fCLK = RCM_ReadPCLKFreq(); + } + + intDiv = ((25 * fCLK) / (4 * (configStruct->baudRate))); + temp = (intDiv / 100) << 4; + fractionalDiv = intDiv - (100 * (temp >> 4)); + temp |= ((((fractionalDiv * 16) + 50) / 100)) & ((uint8_t)0x0F); + + uart->BR = temp; +} + +/*! + * @brief Fills each USART_InitStruct member with its default value + * + * @param configStruct£º pointer to a USART_Config_T structure which will be initialized + * + * @retval None + */ +void USART_ConfigStructInit(USART_Config_T* configStruct) +{ + configStruct->baudRate = 9600; + configStruct->wordLength = USART_WORD_LEN_8B; + configStruct->stopBits = USART_STOP_BIT_1; + configStruct->parity = USART_PARITY_NONE ; + configStruct->mode = USART_MODE_TX_RX; + configStruct->hardwareFlowCtrl = USART_FLOW_CTRL_NONE; +} + +/*! + * @brief Synchronous communication clock configuration + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param SyncClockConfig: Pointer to a USART_SyncClockConfig_T structure that + * contains the configuration information for the clock + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_ConfigSyncClock(USART_T* usart, USART_SyncClockConfig_T* SyncClockConfig) +{ + usart->CTRL2_B.CLKEN = SyncClockConfig->enable; + usart->CTRL2_B.CPHA = SyncClockConfig->phase; + usart->CTRL2_B.CPOL = SyncClockConfig->polarity; + usart->CTRL2_B.LBCPOEN = SyncClockConfig->lastBitClock; +} + +/*! + * @brief Fills each SyncClockConfig member with its default value + * + * @param SyncClockConfig: Pointer to a USART_SyncClockConfig_T structure + * + * @retval None + */ +void USART_ConfigSyncClockStructInit(USART_SyncClockConfig_T* SyncClockConfig) +{ + SyncClockConfig->enable = USART_CLKEN_DISABLE; + SyncClockConfig->phase = USART_CLKPHA_1EDGE; + SyncClockConfig->polarity = USART_CLKPOL_LOW; + SyncClockConfig->lastBitClock = USART_LBCP_DISABLE; +} + +/*! + * @brief Enables the specified USART peripheral + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_Enable(USART_T* usart) +{ + usart->CTRL1_B.UEN = BIT_SET; +} + +/*! + * @brief Disables the specified USART peripheral + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_Disable(USART_T* usart) +{ + usart->CTRL1_B.UEN = BIT_RESET; +} + +/*! + * @brief Enables the USART direction mode + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param mode: Specifies the USART direction + * The parameter can be one of following values: + * @arg USART_MODE_RX: USART Transmitter + * @arg USART_MODE_TX: USART Receiver + * @arg USART_MODE_TX_RX: USART Transmitter and Receiver + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_EnableDirectionMode(USART_T* usart, USART_MODE_T mode) +{ + if (mode == USART_MODE_RX) + { + usart->CTRL1_B.RXEN = BIT_SET; + } + + if (mode == USART_MODE_TX) + { + usart->CTRL1_B.TXEN = BIT_SET; + } + + if (mode == USART_MODE_TX_RX) + { + usart->CTRL1_B.TXEN = BIT_SET; + usart->CTRL1_B.RXEN = BIT_SET; + } +} + +/*! + * @brief Disables the USART direction mode + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param mode: Specifies the USART direction + * The parameter can be one of following values: + * @arg USART_MODE_RX: USART Transmitter + * @arg USART_MODE_TX: USART Receiver + * @arg USART_MODE_TX_RX: USART Transmitter and Receiver + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_DisableDirectionMode(USART_T* usart, USART_MODE_T mode) +{ + if (mode == USART_MODE_RX) + { + usart->CTRL1_B.RXEN = BIT_RESET; + } + + if (mode == USART_MODE_TX) + { + usart->CTRL1_B.TXEN = BIT_RESET; + } + + if (mode == USART_MODE_TX_RX) + { + usart->CTRL1_B.TXEN = BIT_RESET; + usart->CTRL1_B.RXEN = BIT_RESET; + } +} + +/*! + * @brief Enables the Over Sampling 8/16 mode + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + * + * @note 0: Oversampling by 16 1: Oversampling by 8 + */ +void USART_EnableOverSampling8(USART_T* usart) +{ + usart->CTRL1_B.OSMCFG = BIT_SET; +} + +/*! + * @brief Disables the the Over Sampling 8/16 mode + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + * + * @note 0: Oversampling by 16 1: Oversampling by 8 + */ +void USART_DisableOverSampling8(USART_T* usart) +{ + usart->CTRL1_B.OSMCFG = BIT_RESET; +} + +/*! + * @brief Enables the USART's one bit sampling method. + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_EnableOneBitMethod(USART_T* usart) +{ + usart->CTRL3_B.SAMCFG = BIT_SET; +} + +/*! + * @brief Disables the USART's one bit sampling method. + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_DisableOneBitMethod(USART_T* usart) +{ + usart->CTRL3_B.SAMCFG = BIT_RESET; +} + +/*! + * @brief Enables the most significant bit first + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_EnableMSBFirst(USART_T* usart) +{ + usart->CTRL2_B.MSBFEN = BIT_SET; +} + +/*! + * @brief Disables the most significant bit first + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_DisableMSBFirst(USART_T* usart) +{ + usart->CTRL2_B.MSBFEN = BIT_RESET; +} + +/*! + * @brief Enables the the binary data inversion + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_EnableDataInv(USART_T* usart) +{ + usart->CTRL2_B.BINVEN = BIT_SET; +} + +/*! + * @brief Disables the the binary data inversion + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_DisableDataInv(USART_T* usart) +{ + usart->CTRL2_B.BINVEN = BIT_RESET; +} + +/*! + * @brief Enables the specified USART peripheral + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param invPin: specifies the USART pin(s) to invert + * This parameter can be one of the following values: + * @arg USART_INVERSION_RX: USART Tx pin active level inversion + * @arg USART_INVERSION_TX: USART Rx pin active level inversion + * @arg USART_INVERSION_TX_RX: USART TX Rx pin active level inversion + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_EnableInvPin(USART_T* usart, USART_INVERSION_T invPin) +{ + if (invPin == USART_INVERSION_RX) + { + usart->CTRL2_B.RXINVEN = BIT_SET; + } + + if (invPin == USART_INVERSION_TX) + { + usart->CTRL2_B.TXINVEN = BIT_SET; + } + + if (invPin == (USART_INVERSION_TX_RX)) + { + usart->CTRL2_B.TXINVEN = BIT_SET; + usart->CTRL2_B.RXINVEN = BIT_SET; + } +} + +/*! + * @brief Disables the specified USART peripheral + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param invPin: specifies the USART pin(s) to invert + * This parameter can be one of the following values: + * @arg USART_INVERSION_RX: USART Tx pin active level inversion + * @arg USART_INVERSION_TX: USART Rx pin active level inversion + * @arg USART_INVERSION_TX_RX: USART TX Rx pin active level inversion + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_DisableInvPin(USART_T* usart, USART_INVERSION_T invPin) +{ + if (invPin == USART_INVERSION_RX) + { + usart->CTRL2_B.RXINVEN = BIT_RESET; + } + + if (invPin == USART_INVERSION_TX) + { + usart->CTRL2_B.TXINVEN = BIT_RESET; + } + + if (invPin == USART_INVERSION_TX_RX) + { + usart->CTRL2_B.TXINVEN = BIT_RESET; + usart->CTRL2_B.RXINVEN = BIT_RESET; + } +} + +/*! + * @brief Enables the swap Tx/Rx pins + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_EnableSWAPPin(USART_T* usart) +{ + usart->CTRL2_B.SWAPEN = BIT_SET; +} + +/*! + * @brief Disables the swap Tx/Rx pins + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_DisableSWAPPin(USART_T* usart) +{ + usart->CTRL2_B.SWAPEN = BIT_RESET; +} + +/*! + * @brief Enables the receiver Time Out feature + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @retval None + * + * @note The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_EnableReceiverTimeOut(USART_T* usart) +{ + usart->CTRL2_B.RXTODEN = BIT_SET; +} + +/*! + * @brief Disables the receiver Time Out feature + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @retval None + * + * @note The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_DisableReceiverTimeOut(USART_T* usart) +{ + usart->CTRL2_B.RXTODEN = BIT_RESET; +} + +/*! + * @brief Sets the receiver Time Out value + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @param timeOut: Specifies the Receiver Time Out value + * + * @retval None + * + * @note The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + * + * @note The value must less than 0x00FFFFFF + */ +void USART_ReceiverTimeOutValue(USART_T* usart, uint32_t timeOut) +{ + usart->RXTO = (uint32_t)0x00; + + if (timeOut <= (uint32_t)0x00FFFFFF) + { + usart->RXTO = ((uint32_t)timeOut & 0x00FFFFFF); + } +} + +/*! + * @brief Sets the system clock divider. + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @param divider: Specifies the prescaler clock value + * + * @retval None + * + * @note It's not for APM32F030 devices. + * The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_ConfigDivider(USART_T* usart, uint8_t divider) +{ + usart->GTPSC &= (uint16_t)0xFF00; + usart->GTPSC_B.PSC = (uint8_t)divider; +} + +/*! + * @brief Enables the stop mode + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @retval None + * + * @note The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_EnableStopMode(USART_T* usart) +{ + usart->CTRL1_B.USWMEN = BIT_SET; +} + +/*! + * @brief Disables the stop mode + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @retval None + * + * @note The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_DisableStopMode(USART_T* usart) +{ + usart->CTRL1_B.USWMEN = BIT_RESET; +} + +/*! + * @brief Selects the USART WakeUp method form stop mode. + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @param source: Specifies the selected USART wakeup method + * This parameter can be one of the following values: + * @arg USART_WAKEUP_SOURCE_ADDRESS: WUP active on address match. + * @arg USART_WAKEUP_SOURCE_START: WUP active on Start bit detection. + * @arg USART_WAKEUP_SOURCE_RXNE: WUP active on RXNE. + * + * @note It's not for APM32F030 devices. + * The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_ConfigStopModeWakeUpSource(USART_T* usart, USART_WAKEUP_SOURCE_T source) +{ + usart->CTRL3_B.WSIFLGSEL = source; +} + +/*! + * @brief Enables the auto baud rate + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @retval None + * + * @note The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_EnableAutoBaudRate(USART_T* usart) +{ + usart->CTRL2_B.ABRDEN = BIT_SET; +} + +/*! + * @brief Disables the auto baud rate + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @retval None + * + * @note The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_DisableAutoBaudRate(USART_T* usart) +{ + usart->CTRL2_B.ABRDEN = BIT_RESET; +} + +/*! + * @brief Enables the auto baud rate + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @param mode: specifies the selected USART auto baud rate method + * This parameter can be one of the following values: + * @arg USART_AUTO_BAUD_RATE_STARTBIT: Start Bit duration measurement + * @arg USART_AUTO_BAUD_RATE_FALLINGEDGE: Falling edge to falling edge measurement + * + * @retval None + * + * @note The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_ConfigAutoBaudRate(USART_T* usart, USART_AUTO_BAUD_RATE_T mode) +{ + usart->CTRL2_B.ABRDCFG = mode; +} + +/*! + * @brief Transmit Data + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param data: Specifies the Transmits data value + * + * @retval None + * + * @note It's not for APM32F030 devices. + * The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + * + * @note The value must less than 0x01FF + */ +void USART_TxData(USART_T* usart, uint16_t data) +{ + usart->TXDATA = (data & (uint16_t)0x01FF); +} + +/*! + * @brief Received Data + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval Returns the received data value + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +uint16_t USART_RxData(USART_T* usart) +{ + return (uint16_t)(usart->RXDATA & (uint16_t)0x01FF); +} + +/*! + * @brief Sets USART the address + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_Address(USART_T* usart, uint8_t address) +{ + usart->CTRL2_B.ADDRL = ((uint8_t)address & 0x0F); + usart->CTRL2_B.ADDRH = ((uint8_t)address >> 4 & 0x0F); + +} + +/*! + * @brief Enables the USART's mute mode + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_EnableMuteMode(USART_T* usart) +{ + usart->CTRL1_B.RXMUTEEN = BIT_SET; +} + +/*! + * @brief Disables the USART's mute mode + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_DisableMuteMode(USART_T* usart) +{ + usart->CTRL1_B.RXMUTEEN = BIT_RESET; +} + +/*! + * @brief Selects the USART WakeUp method from mute mode + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param wakeup: Specifies the selected USART auto baud rate method + * This parameter can be one of the following values: + * @arg USART_WAKEUP_IDLE_LINE: WakeUp by an idle line detection + * @arg USART_WAKEUP_ADDRESS_MARK: WakeUp by an address mark + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_ConfigMuteModeWakeUp(USART_T* usart, USART_WAKEUP_T wakeup) +{ + usart->CTRL1_B.WUPMCFG = wakeup; +} + +/*! + * @brief Enables the USART's LIN mode + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @retval None + * + * @note It's not for APM32F030 devices. + * The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_EnableLINmode(USART_T* usart) +{ + usart->CTRL2_B.LINMEN = BIT_SET; +} + +/*! + * @brief Disables the USART's LIN mode + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @retval None + * + * @note It's not for APM32F030 devices. + * The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_DisableLINmode(USART_T* usart) +{ + usart->CTRL2_B.LINMEN = BIT_RESET; +} + +/*! + * @brief Sets the USART LIN Break detection length. + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @param length: Specifies the selected USART auto baud rate method + * This parameter can be one of the following values: + * @arg USART_BREAK_LENGTH_10B: 10-bit break detection + * @arg USART_BREAK_LENGTH_11B: 11-bit break detection + * + * @retval None + * + * @note It's not for APM32F030 devices. + * The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_ConfigLINbreakDetectLength(USART_T* usart, USART_BREAK_LENGTH_T length) +{ + usart->CTRL2_B.LBDLCFG = length; +} + +/*! + * @brief Enables the USART's Half-duplex mode + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_EnableHalfDuplex(USART_T* usart) +{ + usart->CTRL3_B.HDEN = BIT_SET; +} + +/*! + * @brief Disables the USART's Half-duplex mode + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_DisableHalfDuplex(USART_T* usart) +{ + usart->CTRL3_B.HDEN = BIT_RESET; +} + +/*! + * @brief Enables the USART's Smart Card mode + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @retval None + * + * @note It's not for APM32F030 devices. + * The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_EnableSmartCard(USART_T* usart) +{ + usart->CTRL3_B.SCEN = BIT_SET; +} + +/*! + * @brief Disables the USART's Smart Card mode + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @retval None + * + * @note It's not for APM32F030 devices. + * The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_DisableSmartCard(USART_T* usart) +{ + usart->CTRL3_B.SCEN = BIT_RESET; +} + +/*! + * @brief Enables the USART's NACK transmission + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @retval None + * + * @note It's not for APM32F030 devices. + * The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_EnableSmartCardNACK(USART_T* usart) +{ + usart->CTRL3_B.SCNACKEN = BIT_SET; +} + +/*! + * @brief Disables the USART's NACK transmission + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @retval None + * + * @note It's not for APM32F030 devices. + * The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_DisableSmartCardNACK(USART_T* usart) +{ + usart->CTRL3_B.SCNACKEN = BIT_RESET; +} + +/*! + * @brief Config the specified USART guard time. + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @param guardTime: specifies the guard time value + * + * @retval None + * + * @note It's not for APM32F030 devices. + * The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_ConfigGuardTime(USART_T* usart, uint8_t guardTime) +{ + usart->GTPSC &= (uint16_t)0x00FF; + usart->GTPSC_B.GRDT = (uint8_t)guardTime; +} + +/*! + * @brief Config the specified USART Smart Card number. + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @param autoCount: specifies the Smart Card auto retry count. + * It's <= 0x07. + * + * @retval None + * + * @note It's not for APM32F030 devices. + * The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_ConfigAutoCount(USART_T* usart, uint8_t autoCount) +{ + usart->CTRL3_B.SCARCCFG = autoCount; +} + +/*! + * @brief Config the Smart Card Block length. + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @param blockSize: specifies the Smart Card block size. + * + * @retval None + * + * @note It's not for APM32F030 devices. + * The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_ConfigBlockSize(USART_T* usart, uint8_t blockSize) +{ + usart->RXTO_B.BLEN = (uint8_t)blockSize; +} + +/*! + * @brief Enables the USART's IrDA mode. + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @retval None + * + * @note It's not for APM32F030 devices. + * The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_EnableIrDA(USART_T* usart) +{ + usart->CTRL3_B.IREN = BIT_SET; +} + +/*! + * @brief Disables the USART's IrDA mode. + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @retval None + * + * @note It's not for APM32F030 devices. + * The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_DisableIrDA(USART_T* usart) +{ + usart->CTRL3_B.IREN = BIT_RESET; +} + +/*! + * @brief Configures the USART's IrDA interface. + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3. + * + * @param IrDAMode:Specifies the selected USART auto baud rate method + * This parameter can be one of the following values: + * @arg USART_IRDA_MODE_NORMAL: Normal + * @arg USART_IRDA_MODE_LOWPOWER: Low-Power + * + * @retval None + * + * @note It's not for APM32F030 devices. + * The USART2 only for APM32F072 and APM32F091 devices. + * The USART3 only for APM32F091 devices. + */ +void USART_ConfigIrDAMode(USART_T* usart, USART_IRDA_MODE_T IrDAMode) +{ + usart->CTRL3_B.IRLPEN = IrDAMode; +} + +/*! + * @brief Configure the the USART Address detection length. + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param address: Specifies the selected USART auto baud rate method + * This parameter can be one of the following values: + * @arg USART_ADDRESS_MODE_4B: 4-bit address length detection + * @arg USART_ADDRESS_MODE_7B: 7-bit address length detection + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_ConfigAddressDetection(USART_T* usart, USART_ADDRESS_MODE_T address) +{ + usart->CTRL2_B.ADDRLEN = address; +} + +/*! + * @brief Enables the DE functionality + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_EnableDE(USART_T* usart) +{ + usart->CTRL3_B.DEN = BIT_SET; +} + +/*! + * @brief Disables the DE functionality + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_DisableDE(USART_T* usart) +{ + usart->CTRL3_B.DEN = BIT_RESET; +} + +/*! + * @brief Selects the USART WakeUp method from mute mode + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param polarity: Specifies the selected USART auto baud rate method + * This parameter can be one of the following values: + * @arg USART_DE_POL_HIGH: DE signal is active high + * @arg USART_DE_POL_LOW: DE signal is active low + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_ConfigDEPolarity(USART_T* usart, USART_DE_POL_T polarity) +{ + usart->CTRL3_B.DPCFG = polarity; +} + +/*! + * @brief Sets the driver enable assertion time value + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param value: Specifies the DE assertion time value + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_DEAssertionTimeValue(USART_T* usart, uint8_t value) +{ + usart->CTRL1_B.DLTEN = (uint8_t)0x00; + + if (value <= (uint8_t)0x1F) + { + usart->CTRL1_B.DLTEN = ((uint8_t)value & 0x1F); + } +} + +/*! + * @brief Sets the driver enable deassertion time value + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param value: Specifies the DE deassertion time value + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_DEDeassertionTimeValue(USART_T* usart, uint8_t value) +{ + usart->CTRL1_B.DDLTEN = (uint8_t)0x00; + + if (value <= (uint8_t)0x1F) + { + usart->CTRL1_B.DDLTEN = ((uint8_t)value & 0x1F); + } +} + +/*! + * @brief Enables the USART DMA interface + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param dmaReq: Specifies the DMA request + * This parameter can be any combination of the following values: + * @arg USART_DMA_REQUEST_RX: USART DMA receive request + * @arg USART_DMA_REQUEST_TX: USART DMA transmit request + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_EnableDMA(USART_T* usart, uint32_t dmaReq) +{ + if (dmaReq == USART_DMA_REQUEST_RX) + { + usart->CTRL3_B.DMARXEN = BIT_SET; + } + else if (dmaReq == USART_DMA_REQUEST_TX) + { + usart->CTRL3_B.DMATXEN = BIT_SET; + } + else if (dmaReq == (BIT6 | BIT7)) + { + usart->CTRL3_B.DMATXEN = BIT_SET; + usart->CTRL3_B.DMARXEN = BIT_SET; + } +} + +/*! + * @brief Disables the USART DMA interface + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param dmaReq: Specifies the DMA request + * This parameter can be any combination of the following values: + * @arg USART_DMA_REQUEST_RX: USART DMA receive request + * @arg USART_DMA_REQUEST_TX: USART DMA transmit request + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_DisableDMA(USART_T* usart, uint32_t dmaReq) +{ + if (dmaReq == USART_DMA_REQUEST_RX) + { + usart->CTRL3_B.DMARXEN = BIT_RESET; + } + else if (dmaReq == USART_DMA_REQUEST_TX) + { + usart->CTRL3_B.DMATXEN = BIT_RESET; + } + else if (dmaReq == (BIT6 | BIT7)) + { + usart->CTRL3_B.DMATXEN = BIT_RESET; + usart->CTRL3_B.DMARXEN = BIT_RESET; + } +} + +/*! + * @brief Enables or disables the USART DMA interface when reception error occurs + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param dmaReq: Specifies the DMA request + * This parameter can be one of the following values: + * @arg USART_DMA_RXERR_ENABLE: DMA receive request enabled + * @arg USART_DMA_RXERR_DISABLE: DMA receive request disabled + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_ConfigDMAReceptionError(USART_T* usart, USART_DMA_RXERR_T error) +{ + usart->CTRL3_B.DDISRXEEN = error; +} + +/*! + * @brief Enables the specified interrupts + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param interrupt: Specifies the USART interrupts sources + * The parameter can be one of following values: + * @arg USART_INT_WAKEUP: Wake up interrupt (Not for APM32F030 devices) + * @arg USART_INT_CMIE: Character match interrupt + * @arg USART_INT_EOBIE: End of Block interrupt + * @arg USART_INT_RXTOIE: Receive time out interrupt + * @arg USART_INT_CTSIE: CTS change interrupt + * @arg USART_INT_LBDIE: LIN Break detection interrupt (Not for APM32F030 devices) + * @arg USART_INT_TXBEIE: Tansmit Data Register empty interrupt + * @arg USART_INT_TXCIE: Transmission complete interrupt + * @arg USART_INT_RXBNEIE: Receive Data register not empty interrupt + * @arg USART_INT_IDLEIE: Idle line detection interrupt + * @arg USART_INT_PEIE: Parity Error interrupt + * @arg USART_INT_ERRIE: Error interrupt + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_EnableInterrupt(USART_T* usart, USART_INT_T interrupt) +{ + if ((interrupt == USART_INT_ERRIE) | (interrupt == USART_INT_CTSIE) | (interrupt == USART_INT_WAKEUP)) + { + usart->CTRL3 |= (uint32_t)interrupt; + } + else if (interrupt == USART_INT_LBDIE) + { + usart->CTRL2 |= (uint32_t)interrupt; + } + else + { + usart->CTRL1 |= (uint32_t)interrupt; + } +} + +/*! + * @brief Disables the specified interrupts + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param interrupt: Specifies the USART interrupts sources + * The parameter can be one of following values: + * @arg USART_INT_WAKEUP: Wake up interrupt (Not for APM32F030 devices) + * @arg USART_INT_CMIE: Character match interrupt + * @arg USART_INT_EOBIE: End of Block interrupt + * @arg USART_INT_RXTOIE: Receive time out interrupt + * @arg USART_INT_CTSIE: CTS change interrupt + * @arg USART_INT_LBDIE: LIN Break detection interrupt (Not for APM32F030 devices) + * @arg USART_INT_TXBEIE: Tansmit Data Register empty interrupt + * @arg USART_INT_TXCIE: Transmission complete interrupt + * @arg USART_INT_RXBNEIE: Receive Data register not empty interrupt + * @arg USART_INT_IDLEIE: Idle line detection interrupt + * @arg USART_INT_PEIE: Parity Error interrupt + * @arg USART_INT_ERRIE: Error interrupt + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_DisableInterrupt(USART_T* usart, USART_INT_T interrupt) +{ + if ((interrupt == USART_INT_ERRIE) | (interrupt == USART_INT_CTSIE) | (interrupt == USART_INT_WAKEUP)) + { + usart->CTRL3 &= (uint32_t)~interrupt; + } + else if (interrupt == USART_INT_LBDIE) + { + usart->CTRL2 &= (uint32_t)~interrupt; + } + else + { + usart->CTRL1 &= (uint32_t)~interrupt; + } +} + +/*! + * @brief Enables the specified USART's Request. + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param request: specifies the USART request + * This parameter can be one of the following values: + * @arg USART_REQUEST_ABRQ: Auto Baud Rate Request + * @arg USART_REQUEST_SBQ: Send Break Request + * @arg USART_REQUEST_MMQ: Mute Mode Request + * @arg USART_REQUEST_RDFQ: Receive data flush Request + * @arg USART_REQUEST_TDFQ: Transmit data flush Request + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_EnableRequest(USART_T* usart, USART_REQUEST_T request) +{ + if (request == USART_REQUEST_ABRQ) + { + usart->REQUEST_B.ABRDQ = BIT_SET; + } + + if (request == USART_REQUEST_SBQ) + { + usart->REQUEST_B.TXBFQ = BIT_SET; + } + + if (request == USART_REQUEST_MMQ) + { + usart->REQUEST_B.MUTEQ = BIT_SET; + } + + if (request == USART_REQUEST_RDFQ) + { + usart->REQUEST_B.RXDFQ = BIT_SET; + } + + if (request == USART_REQUEST_TDFQ) + { + usart->REQUEST_B.TXDFQ = BIT_SET; + } +} + +/*! + * @brief Disables the specified USART's Request. + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param request: specifies the USART request + * This parameter can be one of the following values: + * @arg USART_REQUEST_ABRQ: Auto Baud Rate Request + * @arg USART_REQUEST_SBQ: Send Break Request + * @arg USART_REQUEST_MMQ: Mute Mode Request + * @arg USART_REQUEST_RDFQ: Receive data flush Request + * @arg USART_REQUEST_TDFQ: Transmit data flush Request + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_DisableRequest(USART_T* usart, USART_REQUEST_T request) +{ + if (request == USART_REQUEST_ABRQ) + { + usart->REQUEST_B.ABRDQ = BIT_RESET; + } + + if (request == USART_REQUEST_SBQ) + { + usart->REQUEST_B.TXBFQ = BIT_RESET; + } + + if (request == USART_REQUEST_MMQ) + { + usart->REQUEST_B.MUTEQ = BIT_RESET; + } + + if (request == USART_REQUEST_RDFQ) + { + usart->REQUEST_B.RXDFQ = BIT_RESET; + } + + if (request == USART_REQUEST_TDFQ) + { + usart->REQUEST_B.TXDFQ = BIT_RESET; + } +} + +/*! + * @brief Enables or disables the USART DMA interface when reception error occurs + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param overDetection: specifies the OVR detection status in case of OVR error + * This parameter can be one of the following values: + * @arg USART_OVER_DETECTION_ENABLE: OVR error detection enabled + * @arg USART_OVER_DETECTION_DISABLE: OVR error detection disabled + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_ConfigOverrunDetection(USART_T* usart, USART_OVER_DETECTION_T overDetection) +{ + usart->CTRL3_B.OVRDEDIS = overDetection; +} + +/*! + * @brief Read the specified USART flag + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param flag: Specifies the flag to check + * The parameter can be one of following values: + * @arg USART_FLAG_RXENACKF: Receive Enable Acknowledge Flag + * @arg USART_FLAG_TXENACKF: Transmit Enable Acknowledge Flag + * @arg USART_FLAG_WAKEUP: Wake Up from stop mode Flag (Not for APM32F030 devices) + * @arg USART_FLAG_RWF: Send Break flag (Not for APM32F030 devices) + * @arg USART_FLAG_SBF: Send Break flag + * @arg USART_FLAG_CMF: Character match flag + * @arg USART_FLAG_BUSY: Busy flag + * @arg USART_FLAG_ABRTF: Auto baud rate flag + * @arg USART_FLAG_ABRTE: Auto baud rate error flag + * @arg USART_FLAG_EOBF: End of block flag (Not for APM32F030 devices) + * @arg USART_FLAG_RXTOF: Receive time out flag + * @arg USART_FLAG_CTSF: CTS Change flag + * @arg USART_FLAG_CTSIF: CTS interrupt flag + * @arg USART_FLAG_LBDF£º LIN Break Detection Flag (Not for APM32F030 devices) + * @arg USART_FLAG_TXBE: Transmit data register empty flag + * @arg USART_FLAG_TXC: Transmission Complete flag + * @arg USART_FLAG_RXBNE: Receive data buffer not empty flag + * @arg USART_FLAG_IDLEF: Idle Line detection flag + * @arg USART_FLAG_OVRE: OverRun Error flag + * @arg USART_FLAG_NEF: Noise Error flag + * @arg USART_FLAG_FEF: Framing Error flag + * @arg USART_FLAG_PEF: Parity Error flag + * + * @retval The new state of flag (SET or RESET) + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ + +uint8_t USART_ReadStatusFlag(USART_T* usart, USART_FLAG_T flag) +{ + if ((usart->STS & (uint32_t)flag) != RESET) + { + return SET; + } + + return RESET; +} + +/*! + * @brief Clear the specified USART flag + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param flag: Specifies the flag to clear + * The parameter can be any combination of following values: + * @arg USART_FLAG_WAKEUP: Wake Up from stop mode Flag (Not for APM32F030 devices) + * @arg USART_FLAG_CMF: Character match flag + * @arg USART_FLAG_EOBF: End of block flag (Not for APM32F030 devices) + * @arg USART_FLAG_RXTOF: Receive time out flag + * @arg USART_FLAG_CTSIF: CTS interrupt flag + * @arg USART_FLAG_LBDF£º LIN Break Detection Flag (Not for APM32F030 devices) + * @arg USART_FLAG_TXC: Transmission Complete flag + * @arg USART_FLAG_IDLEF: Idle Line detection flag + * @arg USART_FLAG_OVRE: OverRun Error flag + * @arg USART_FLAG_NEF: Noise Error flag + * @arg USART_FLAG_FEF: Framing Error flag + * @arg USART_FLAG_PEF: Parity Error flag + * + * @retval Note + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ + +void USART_ClearStatusFlag(USART_T* usart, uint32_t flag) +{ + usart->INTFCLR = (uint32_t)flag; +} + +/*! + * @brief Read the specified USART interrupt flag + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param flag: Specifies the USART interrupt flag to check + * The parameter can be one of following values: + * @arg USART_INT_FLAG_WAKEUP: Wake up interrupt flag (Not for APM32F030 devices) + * @arg USART_INT_FLAG_CMF: Character match interrupt flag + * @arg USART_INT_FLAG_EOBF: End of block interrupt flag Not for APM32F030 devices) + * @arg USART_INT_FLAG_RXTOF: Receive time out interrupt flag + * @arg USART_INT_FLAG_CTSIF: CTS interrupt flag + * @arg USART_INT_FLAG_LBDF: LIN Break detection interrupt flag (Not for APM32F030 devices) + * @arg USART_INT_FLAG_TXBE: Transmit data register empty interrupt flag + * @arg USART_INT_FLAG_TXC: Transmission Complete interrupt flag + * @arg USART_INT_FLAG_RXBNE: Receive data buffer not empty interrupt flag + * @arg USART_INT_FLAG_IDLE: Idle Line detection interrupt flag + * @arg USART_INT_FLAG_OVRE: OverRun Error interrupt flag + * @arg USART_INT_FLAG_NE: Noise Error interrupt flag + * @arg USART_INT_FLAG_FE: Framing Error interrupt flag + * @arg USART_INT_FLAG_PE: Parity Error interrupt flag + * + * @retval The new state of flag (SET or RESET) + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ + +uint8_t USART_ReadIntFlag(USART_T* usart, USART_INT_FLAG_T flag) +{ + uint32_t intEnable = 0; + uint32_t intFlag = 0; + + if (flag & 0x0E) + { + intEnable = usart->CTRL3_B.ERRIEN; + intFlag = (usart->STS) & flag; + } + else if (flag & 0xF0) + { + intEnable = (usart->CTRL1)& flag; + intFlag = (usart->STS) & flag; + } + else if (flag & 0x01) + { + intEnable = usart->CTRL1_B.PEIEN; + intFlag = usart->STS_B.PEFLG; + } + else if (flag & 0x200) + { + intEnable = usart->CTRL3_B.CTSIEN; + intFlag = usart->STS_B.CTSFLG; + } + else if (flag & 0x100) + { + intEnable = usart->CTRL2_B.LBDIEN; + intFlag = usart->STS_B.LBDFLG; + } + else if (flag & 0x800) + { + intEnable = usart->CTRL1_B.RXTOIEN; + intFlag = usart->STS_B.RXTOFLG; + } + else if (flag & 0x1000) + { + intEnable = usart->CTRL1_B.EOBIEN; + intFlag = usart->STS_B.EOBFLG; + } + else if (flag & 0x20000) + { + intEnable = usart->CTRL1_B.CMIEN; + intFlag = usart->STS_B.CMFLG; + } + else if (flag & 0x100000) + { + intEnable = usart->CTRL3_B.WSMIEN; + intFlag = usart->STS_B.WSMFLG; + } + + if (intFlag && intEnable) + { + return SET; + } + + return RESET; +} + +/*! + * @brief Clears the USART interrupt pending bits + * + * @param usart: Select the the USART peripheral. + * It can be USART1/USART2/USART3/USART4/USART5/USART6/USART7/USART8. + * + * @param flag: Specifies the USART interrupt flag to clear + * The parameter can be any combination following values: + * @arg USART_INT_FLAG_WAKEUP: Wake up interrupt flag (Not for APM32F030 devices) + * @arg USART_INT_FLAG_CMF: Character match interrupt flag + * @arg USART_INT_FLAG_EOBF: End of block interrupt flag (Not for APM32F030 devices) + * @arg USART_INT_FLAG_RXTOF: Receive time out interrupt flag + * @arg USART_INT_FLAG_CTSIF: CTS interrupt flag + * @arg USART_INT_FLAG_LBDF: LIN Break detection interrupt flag (Not for APM32F030 devices) + * @arg USART_INT_FLAG_TXC: Transmission Complete interrupt flag + * @arg USART_INT_FLAG_IDLE: Idle Line detection interrupt flag + * @arg USART_INT_FLAG_OVRE: OverRun Error interrupt flag + * @arg USART_INT_FLAG_NE: Noise Error interrupt flag + * @arg USART_INT_FLAG_FE: Framing Error interrupt flag + * @arg USART_INT_FLAG_PE: Parity Error interrupt flag + * + * @retval None + * + * @note The USART3/USART4 only for APM32F072 and APM32F091 devices. + * USART5, USART6, USART7 and USART8 are available only for APM32F091 devices. + */ +void USART_ClearIntFlag(USART_T* usart, uint32_t flag) +{ + usart->INTFCLR |= (uint32_t)flag; +} + +/**@} end of group USART_Functions*/ +/**@} end of group USART_Driver*/ +/**@} end of group APM32F0xx_StdPeriphDriver*/ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_wwdt.c b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_wwdt.c new file mode 100644 index 0000000000..2daba3150f --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/APM32F0xx_StdPeriphDriver/src/apm32f0xx_wwdt.c @@ -0,0 +1,175 @@ +/*! + * @file apm32f0xx_wwdt.c + * + * @brief This file contains all the functions for the WWDG peripheral + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +#include "apm32f0xx_wwdt.h" +#include "apm32f0xx_rcm.h" + +/** @addtogroup APM32F0xx_StdPeriphDriver + @{ +*/ + +/** @addtogroup WWDT_Driver WWDT Driver + @{ +*/ + +/** @defgroup WWDT_Macros Macros + @{ +*/ + +/**@} end of group WWDT_Macros */ + +/** @defgroup WWDT_Enumerations Enumerations + @{ +*/ + +/**@} end of group WWDT_Enumerations */ + +/** @defgroup WWDT_Structures Structures + @{ +*/ + +/**@} end of group WWDT_Structures */ + +/** @defgroup WWDT_Variables Variables + @{ +*/ + +/**@} end of group WWDT_Variables */ + +/** @defgroup WWDT_Functions Functions + @{ +*/ + +/*! + * @brief Set the WWDT peripheral registers to their default reset values + * + * @param None + + * @retval None + */ +void WWDT_Reset(void) +{ + RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_WWDT); + RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_WWDT); +} + +/*! + * @brief Set the WWDT Timebase + * + * @param timebase: WWDT Prescaler + * The parameter can be one of following values: + * @arg WWDT_DIV_1: WWDT counter clock = (PCLK1/4096)/1 + * @arg WWDT_DIV_2: WWDT counter clock = (PCLK1/4096)/2 + * @arg WWDT_DIV_4: WWDT counter clock = (PCLK1/4096)/4 + * @arg WWDT_DIV_8: WWDT counter clock = (PCLK1/4096)/8 + * + * @retval None + */ +void WWDT_SetTimebase(uint32_t div) +{ + WWDT->CFG_B.TBPSC = 0; + WWDT->CFG_B.TBPSC = div; +} + +/*! + * @brief Set the Window data + * + * @param data: Specifies the window data to be set + * + * @retval None + */ +void WWDT_ConfigWindowValue(uint16_t windowValue) +{ + uint32_t reg; + + reg = (windowValue | BIT6) & 0x7f; + + WWDT->CFG_B.WIN = reg; +} + +/*! + * @brief Enable the WWDT Early Wakeup interrupt + * + * @param None + * + * @retval None + */ +void WWDT_EnableEWI(void) +{ + WWDT->CFG_B.EWIEN = SET; +} + +/*! + * @brief Set counter + * + * @param couter: Specifies the counter to be set + * + * @retval None + */ +void WWDT_ConfigCounter(uint8_t couter) +{ + WWDT->CTRL = (uint32_t)(couter & 0x7f); +} + +/*! + * @brief Enable WWDT and set the counter value + * + * @param count: the window watchdog counter value + * + * @retval None + */ +void WWDT_Enable(uint8_t count) +{ + WWDT->CTRL_B.CNT = count; + WWDT->CTRL_B.WWDTEN = SET; +} + +/*! + * @brief Read the Early Wakeup interrupt flag + * + * @param None + * + * @retval the state of the Early Wakeup interrupt flag + */ +uint8_t WWDT_ReadStatusFlag(void) +{ + return (uint8_t)(WWDT->STS); +} + +/*! + * @brief Clear the Early Wakeup interrupt flag + * + * @param None + * + * @retval None + */ +void WWDT_ClearStatusFlag(void) +{ + WWDT->STS_B.EWIFLG = RESET; +} + +/**@} end of group WWDT_Functions*/ +/**@} end of group WWDT_Driver */ +/**@} end of group APM32F0xx_StdPeriphDriver*/ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/CMSIS/Include/core_cm0plus.h b/bsp/apm32/libraries/APM32F0xx_Library/CMSIS/Include/core_cm0plus.h new file mode 100644 index 0000000000..5cea74e9af --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/CMSIS/Include/core_cm0plus.h @@ -0,0 +1,793 @@ +/**************************************************************************//** + * @file core_cm0plus.h + * @brief CMSIS Cortex-M0+ Core Peripheral Access Layer Header File + * @version V3.20 + * @date 25. February 2013 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + 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 following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef __CORE_CM0PLUS_H_GENERIC +#define __CORE_CM0PLUS_H_GENERIC + +/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** \ingroup Cortex-M0+ + @{ + */ + +/* CMSIS CM0P definitions */ +#define __CM0PLUS_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ +#define __CM0PLUS_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ +#define __CM0PLUS_CMSIS_VERSION ((__CM0PLUS_CMSIS_VERSION_MAIN << 16) | \ + __CM0PLUS_CMSIS_VERSION_SUB) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x00) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#endif + +/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all +*/ +#define __FPU_USED 0 + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif +#endif + +#include /* standard types definitions */ +#include /* Core Instruction Access */ +#include /* Core Function Access */ + +#endif /* __CORE_CM0PLUS_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM0PLUS_H_DEPENDANT +#define __CORE_CM0PLUS_H_DEPENDANT + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM0PLUS_REV + #define __CM0PLUS_REV 0x0000 + #warning "__CM0PLUS_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0 + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __VTOR_PRESENT + #define __VTOR_PRESENT 0 + #warning "__VTOR_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2 + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0 + #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 */ + +/*@} end of group Cortex-M0+ */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core MPU Register + ******************************************************************************/ +/** \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ +#else + 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 */ +#endif + 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; + + +/** \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; + + +/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ +#else + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ +#endif + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + + +/** \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; + +/*@} 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 +{ + __IO uint32_t ISER[1]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31]; + __IO uint32_t ICER[1]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31]; + __IO uint32_t ISPR[1]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31]; + __IO uint32_t ICPR[1]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31]; + uint32_t RESERVED4[64]; + __IO uint32_t IP[8]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ +#if (__VTOR_PRESENT == 1) + __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ +#else + uint32_t RESERVED0; +#endif + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IO uint32_t SHP[2]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0 /*!< 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 31 /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ + +#if (__VTOR_PRESENT == 1) +/* SCB Interrupt Control State Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 8 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0xFFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< 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 9 /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0 /*!< 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 0 /*!< 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 0 /*!< 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 31 /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + +#if (__MPU_PRESENT == 1) +/** \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 +{ + __I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register */ +#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register */ +#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register */ +#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register */ +#define MPU_RBAR_ADDR_Pos 8 /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register */ +#define MPU_RASR_ATTRS_Pos 16 /*!< 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 28 /*!< 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 24 /*!< 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 19 /*!< 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 18 /*!< 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 17 /*!< 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 16 /*!< 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 8 /*!< 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 1 /*!< 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 0 /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Cortex-M0+ Core Debug Registers (DCB registers, SHCSR, and DFSR) + are only accessible over DAP and not via processor. Therefore + they are not covered by the Cortex-M0 header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M0+ Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + +#if (__MPU_PRESENT == 1) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/* Interrupt Priorities are WORD accessible only under ARMv6M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( (((uint32_t)(IRQn) ) & 0x03) * 8 ) +#define _SHP_IDX(IRQn) ( ((((uint32_t)(IRQn) & 0x0F)-8) >> 2) ) +#define _IP_IDX(IRQn) ( ((uint32_t)(IRQn) >> 2) ) + + +/** \brief Enable External Interrupt + + The function enables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Disable External Interrupt + + The function disables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Get Pending Interrupt + + The function reads the pending register in the NVIC and returns the pending bit + for the specified interrupt. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[0] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); +} + + +/** \brief Set Pending Interrupt + + The function sets the pending bit of an external interrupt. + + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Clear Pending Interrupt + + The function clears the pending bit of an external interrupt. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} + + +/** \brief Set Interrupt Priority + + The function sets the priority of an interrupt. + + \note The priority cannot be set for every core interrupt. + + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) { + SCB->SHP[_SHP_IDX(IRQn)] = (SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) | + (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); } + else { + NVIC->IP[_IP_IDX(IRQn)] = (NVIC->IP[_IP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) | + (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); } +} + + +/** \brief Get Interrupt Priority + + The function reads the priority of an interrupt. The interrupt + number can be positive to specify an external (device specific) + interrupt, or negative to specify an internal (core) interrupt. + + + \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(IRQn < 0) { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M0 system interrupts */ + else { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ +} + + +/** \brief System Reset + + The function initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + while(1); /* wait until reset */ +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0) + +/** \brief System Tick Configuration + + The function 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 - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ + + SysTick->LOAD = ticks - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0; /* 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 (0); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#endif /* __CORE_CM0PLUS_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ + +#ifdef __cplusplus +} +#endif diff --git a/bsp/apm32/libraries/APM32F0xx_Library/CMSIS/Include/core_cmFunc.h b/bsp/apm32/libraries/APM32F0xx_Library/CMSIS/Include/core_cmFunc.h new file mode 100644 index 0000000000..0a18fafc30 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/CMSIS/Include/core_cmFunc.h @@ -0,0 +1,636 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V3.20 + * @date 25. February 2013 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + 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 following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** \brief Get Control Register + + This function 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 + + This function 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 + + This function 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 + + This function 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 + + This function 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 + + This function 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 + + This function 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 + + This function 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 + + This function 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 + + This function 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 + + This function 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 (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function 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 + + This function 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 + + This function 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 + + This function 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 & 0xff); +} + + +/** \brief Get Fault Mask + + This function 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 + + This function 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)1); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function 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 (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function 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 (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief Enable IRQ Interrupts + + This function enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** \brief Disable IRQ Interrupts + + This function disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp"); +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); + return(result); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + uint32_t result; + + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all instrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +#endif /* __CORE_CMFUNC_H */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/CMSIS/Include/core_cmInstr.h b/bsp/apm32/libraries/APM32F0xx_Library/CMSIS/Include/core_cmInstr.h new file mode 100644 index 0000000000..d213f0eed7 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/CMSIS/Include/core_cmInstr.h @@ -0,0 +1,688 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V3.20 + * @date 05. March 2013 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + 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 following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** \brief Wait For Interrupt + + 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 + + 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 + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** \brief Instruction Synchronization Barrier + + 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() __isb(0xF) + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __dsb(0xF) + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __dmb(0xF) + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \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 in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +/** \brief Breakpoint + + This function 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) + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __rbit + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command 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(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command 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(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command 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(value, ptr) __strex(value, ptr) + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +#define __CLREX __clrex + + +/** \brief Signed Saturate + + This function 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 + + This function 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 Count leading zeros + + This function 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 + +#endif /* (__CORTEX_M >= 0x03) */ + + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constrant "l" + * Otherwise, use general registers, specified by constrant "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 + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** \brief Wait For Event + + 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. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** \brief Instruction Synchronization Barrier + + 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. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb"); +} + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb"); +} + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb"); +} + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE 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) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE 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 in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (short)__builtin_bswap16(value); +#else + uint32_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) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32 - op2)); +} + + +/** \brief Breakpoint + + This function 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) + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE 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(result); +} + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE 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(result); +} + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE 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) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE 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 + + This function removes the exclusive lock which is created by LDREX. + + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + + +/** \brief Signed Saturate + + This function 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(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Unsigned Saturate + + This function 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(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Count leading zeros + + This function 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 + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * 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. + */ + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/CMSIS/LICENSE.txt b/bsp/apm32/libraries/APM32F0xx_Library/CMSIS/LICENSE.txt new file mode 100644 index 0000000000..f0cd2d9ccf --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/CMSIS/LICENSE.txt @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Include/apm32f0xx.h b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Include/apm32f0xx.h new file mode 100644 index 0000000000..5188982986 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Include/apm32f0xx.h @@ -0,0 +1,5662 @@ +/*! + * @file apm32f0xx.h + * + * @brief CMSIS Cortex-M0 Device Peripheral Access Layer Header File. + * + * @details This file contains all the peripheral register's definitions, bits definitions and memory mapping + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __APM32F0XX_H +#define __APM32F0XX_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup CMSIS + @{ +*/ + +/** @addtogroup APM32F0xx + * @brief Peripheral Access Layer + @{ +*/ +#if defined (APM32F030x6) || defined (APM32F030x8) || defined (APM32F030xC) +#define APM32F030 +#endif /*!< APM32F030x6 or APM32F030x8 or APM32F030xC */ + +#if defined (APM32F051x6) || defined (APM32F051x8) +#define APM32F051 +#endif /*!< APM32F051x6 or APM32F051x8 */ + +#if defined (APM32F070xB) +#define APM32F070 +#endif /*!< APM32F070xB */ + +#if defined (APM32F071x8) || defined (APM32F071xB) +#define APM32F071 +#endif /*!< APM32F071x8 or APM32F071xB */ + +#if defined (APM32F072x8) || defined (APM32F072xB) +#define APM32F072 +#endif /*!< APM32F072x8 or APM32F072xB */ + +#if defined (APM32F091xB) || defined (APM32F091xC) +#define APM32F091 +#endif /*!< APM32F091xB or APM32F091xC */ + +#if !defined (APM32F030) && !defined (APM32F051) && !defined (APM32F070) && \ + !defined (APM32F071) && !defined (APM32F072) && !defined (APM32F091) +#error "Please select first the target APM32F0xx device used in your application (in apm32f0xx.h file)" +#endif + +/** @defgroup HSE_Macros + @{ +*/ + +/** + * @brief Define Value of the External oscillator in Hz + */ +#ifndef HSE_VALUE +#define HSE_VALUE ((uint32_t)8000000) +#endif + +/* Time out for HSE start up */ +#define HSE_STARTUP_TIMEOUT ((uint32_t)0x10000) + +/* Time out for HSI start up */ +#define HSI_STARTUP_TIMEOUT ((uint32_t)0x0500) + +/* Value of the Internal oscillator in Hz */ +#define HSI_VALUE ((uint32_t)8000000) +#define HSI14_VALUE ((uint32_t)14000000) +#define HSI48_VALUE ((uint32_t)48000000) + +#define LSE_VALUE ((uint32_t)32768) +#define LSI_VALUE ((uint32_t)40000) + +/**@} end of group HSE_Macros */ + +/** @defgroup APM32F0xx_StdPeripheral_Library_Version + @{ +*/ + +/*!< [31:16] APM32F0XX Standard Peripheral Library main version V1.0.3*/ +#define __APM32F0_DEVICE_VERSION_MAIN (0x01) /*!< [31:24] main version */ +#define __APM32F0_DEVICE_VERSION_SUB1 (0x00) /*!< [23:16] sub1 version */ +#define __APM32F0_DEVICE_VERSION_SUB2 (0x03) /*!< [15:8] sub2 version */ +#define __APM32F0_DEVICE_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __APM32F0_DEVICE_VERSION ((__APM32F0_DEVICE_VERSION_MAIN << 24)\ + |(__APM32F0_DEVICE_VERSION_SUB1 << 16)\ + |(__APM32F0_DEVICE_VERSION_SUB2 << 8 )\ + |(__APM32F0_DEVICE_VERSION_RC)) + +/**@} end of group APM32F0xx_StdPeripheral_Library_Version */ + +/** @defgroup Configuraion_for_CMSIS + @{ +*/ + +/* Core Revision r0p1 */ +#define __CM0PLUS_REV 0 +/* APM32F0xx do not provide MPU */ +#define __MPU_PRESENT 0 +/* APM32F0xx uses 2 Bits for the Priority Levels */ +#define __NVIC_PRIO_BITS 2 +/* Set to 1 if different SysTick Config is used */ +#define __Vendor_SysTickConfig 0 +/* Set to 1 if different Vector Table Offset is used */ +#define __VTOR_PRESENT 1 + +/** + * @brief Interrupt Number Definition + */ +typedef enum +{ + /* Cortex-M0 Processor Exceptions Numbers */ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 3 Cortex-M0 Hard Fault Interrupt */ + SVC_IRQn = -5, /*!< 11 Cortex-M0 SV Call Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M0 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M0 System Tick Interrupt */ + +#if defined (APM32F030) + /* APM32F030 specific Interrupt Numbers */ + WWDT_IRQn = 0, /*!< Window WatchDog Interrupt */ + RTC_IRQn = 2, /*!< RTC Interrupt through EINT Lines 17, 19 and 20 */ + FLASH_IRQn = 3, /*!< FLASH global Interrupt */ + RCM_IRQn = 4, /*!< RCM global Interrupt */ + EINT0_1_IRQn = 5, /*!< EINT Line 0 and 1 Interrupt */ + EINT2_3_IRQn = 6, /*!< EINT Line 2 and 3 Interrupt */ + EINT4_15_IRQn = 7, /*!< EINT Line 4 to 15 Interrupt */ + DMA1_CH1_IRQn = 9, /*!< DMA1 Channel 1 Interrupt */ + DMA1_CH2_3_IRQn = 10, /*!< DMA1 Channel 2 and Channel 3 Interrupt */ + DMA1_CH4_5_IRQn = 11, /*!< DMA1 Channel 4 and Channel 5 Interrupt */ + ADC1_IRQn = 12, /*!< ADC1 Interrupt */ + TMR1_BRK_UP_TRG_COM_IRQn = 13, /*!< TMR1 Break, Update, Trigger and Commutation Interrupt */ + TMR1_CC_IRQn = 14, /*!< TMR1 Capture Compare Interrupt */ + TMR3_IRQn = 16, /*!< TMR3 global Interrupt */ + TMR6_IRQn = 17, /*!< TMR6 global Interrupt */ + TMR7_IRQn = 18, /*!< TMR7 global Interrupt */ + TMR14_IRQn = 19, /*!< TMR14 global Interrupt */ + TMR15_IRQn = 20, /*!< TMR15 global Interrupt */ + TMR16_IRQn = 21, /*!< TMR16 global Interrupt */ + TMR17_IRQn = 22, /*!< TMR17 global Interrupt */ + I2C1_IRQn = 23, /*!< I2C1 Event Interrupt */ + I2C2_IRQn = 24, /*!< I2C2 Event Interrupt */ + SPI1_IRQn = 25, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 26, /*!< SPI2 global Interrupt */ + USART1_IRQn = 27, /*!< USART1 global Interrupt */ + USART2_IRQn = 28, /*!< USART2 global Interrupt */ + USART3_6_IRQn = 29 /*!< USART3 to USART6 global Interrupt */ +#elif defined (APM32F051) + /* APM32F051 specific Interrupt Numbers */ + WWDT_IRQn = 0, /*!< Window WatchDog Interrupt */ + PVD_IRQn = 1, /*!< PVD through EXTI Line detect Interrupt */ + RTC_IRQn = 2, /*!< RTC Interrupt through EINT Lines 17, 19 and 20 */ + FLASH_IRQn = 3, /*!< FLASH global Interrupt */ + RCM_IRQn = 4, /*!< RCM global Interrupt */ + EINT0_1_IRQn = 5, /*!< EINT Line 0 and 1 Interrupt */ + EINT2_3_IRQn = 6, /*!< EINT Line 2 and 3 Interrupt */ + EINT4_15_IRQn = 7, /*!< EINT Line 4 to 15 Interrupt */ + TSC_IRQn = 8, /*!< TSC Interrupt */ + DMA1_CH1_IRQn = 9, /*!< DMA1 Channel 1 Interrupt */ + DMA1_CH2_3_IRQn = 10, /*!< DMA1 Channel 2 and Channel 3 Interrupt */ + DMA1_CH4_5_IRQn = 11, /*!< DMA1 Channel 4 and Channel 5 Interrupt */ + ADC1_COMP_IRQn = 12, /*!< ADC1 and comparator Interrupt */ + TMR1_BRK_UP_TRG_COM_IRQn = 13, /*!< TMR1 Break, Update, Trigger and Commutation Interrupt */ + TMR1_CC_IRQn = 14, /*!< TMR1 Capture Compare Interrupt */ + TMR2_IRQn = 15, /*!< TMR2 global Interrupt */ + TMR3_IRQn = 16, /*!< TMR3 global Interrupt */ + TMR6_DAC_IRQn = 17, /*!< TMR6 and DAC Interrupt */ + TMR14_IRQn = 19, /*!< TMR14 global Interrupt */ + TMR15_IRQn = 20, /*!< TMR15 global Interrupt */ + TMR16_IRQn = 21, /*!< TMR16 global Interrupt */ + TMR17_IRQn = 22, /*!< TMR17 global Interrupt */ + I2C1_IRQn = 23, /*!< I2C1 Event Interrupt */ + I2C2_IRQn = 24, /*!< I2C2 Event Interrupt */ + SPI1_IRQn = 25, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 26, /*!< SPI2 global Interrupt */ + USART1_IRQn = 27, /*!< USART1 global Interrupt */ + USART2_IRQn = 28, /*!< USART2 global Interrupt */ + CEC_IRQn = 30 /*!< CEC global Interrupt */ +#elif defined (APM32F070) + /* APM32F070 specific Interrupt Numbers */ + WWDT_IRQn = 0, /*!< Window WatchDog Interrupt */ + RTC_IRQn = 2, /*!< RTC Interrupt through EINT Lines */ + FLASH_IRQn = 3, /*!< FLASH global Interrupt */ + RCM_IRQn = 4, /*!< RCM global Interrupt */ + EINT0_1_IRQn = 5, /*!< EINT Line 0 and 1 Interrupt */ + EINT2_3_IRQn = 6, /*!< EINT Line 2 and 3 Interrupt */ + EINT4_15_IRQn = 7, /*!< EINT Line 4 to 15 Interrupt */ + DMA1_CH1_IRQn = 9, /*!< DMA1 Channel 1 Interrupt */ + DMA1_CH2_3_IRQn = 10, /*!< DMA1 Channel 2 and Channel 3 Interrupts */ + DMA1_CH4_5_IRQn = 11, /*!< DMA1 Channel 4, Channel 5 Interrupts */ + ADC1_IRQn = 12, /*!< ADC1 Interrupt */ + TMR1_BRK_UP_TRG_COM_IRQn = 13, /*!< TMR1 Break, Update, Trigger and Commutation Interrupt */ + TMR1_CC_IRQn = 14, /*!< TMR1 Capture Compare Interrupt */ + TMR3_IRQn = 16, /*!< TMR3 global Interrupt */ + TMR6_IRQn = 17, /*!< TMR6 global Interrupt */ + TMR7_IRQn = 18, /*!< TMR7 global Interrupt */ + TMR14_IRQn = 19, /*!< TMR14 global Interrupt */ + TMR15_IRQn = 20, /*!< TMR15 global Interrupt */ + TMR16_IRQn = 21, /*!< TMR16 global Interrupt */ + TMR17_IRQn = 22, /*!< TMR17 global Interrupt */ + I2C1_IRQn = 23, /*!< I2C1 Event Interrupt */ + I2C2_IRQn = 24, /*!< I2C2 Event Interrupt */ + SPI1_IRQn = 25, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 26, /*!< SPI2 global Interrupt */ + USART1_IRQn = 27, /*!< USART1 global Interrupt */ + USART2_IRQn = 28, /*!< USART2 global Interrupt */ + USART3_4_IRQn = 29, /*!< USART3 and USART4 global Interrupt */ + USBD_IRQn = 31 /*!< USB Low Priority global Interrupt */ +#elif defined (APM32F071) + /* APM32F071 specific Interrupt Numbers */ + WWDT_IRQn = 0, /*!< Window WatchDog Interrupt */ + PVD_VDDIO2_IRQn = 1, /*!< PVD and VDDIO2 Interrupt */ + RTC_IRQn = 2, /*!< RTC Interrupt through EINT Lines */ + FLASH_IRQn = 3, /*!< FLASH global Interrupt */ + RCM_CRS_IRQn = 4, /*!< RCM and CRS global Interrupt */ + EINT0_1_IRQn = 5, /*!< EINT Line 0 and 1 Interrupt */ + EINT2_3_IRQn = 6, /*!< EINT Line 2 and 3 Interrupt */ + EINT4_15_IRQn = 7, /*!< EINT Line 4 to 15 Interrupt */ + TSC_IRQn = 8, /*!< TSC Interrupt */ + DMA1_CH1_IRQn = 9, /*!< DMA1 Channel 1 Interrupt */ + DMA1_CH2_3_IRQn = 10, /*!< DMA1 Channel 2 and Channel 3 Interrupts */ + DMA1_CH4_5_6_7_IRQn = 11, /*!< DMA1 Channel 4, Channel 5, Channel 6 and Channel 7 Interrupts */ + ADC1_COMP_IRQn = 12, /*!< ADC1 and comparator Interrupt */ + TMR1_BRK_UP_TRG_COM_IRQn = 13, /*!< TMR1 Break, Update, Trigger and Commutation Interrupt */ + TMR1_CC_IRQn = 14, /*!< TMR1 Capture Compare Interrupt */ + TMR2_IRQn = 15, /*!< TMR2 global Interrupt */ + TMR3_IRQn = 16, /*!< TMR3 global Interrupt */ + TMR6_DAC_IRQn = 17, /*!< TMR6 and DAC Interrupt */ + TMR7_IRQn = 18, /*!< TMR7 global Interrupt */ + TMR14_IRQn = 19, /*!< TMR14 global Interrupt */ + TMR15_IRQn = 20, /*!< TMR15 global Interrupt */ + TMR16_IRQn = 21, /*!< TMR16 global Interrupt */ + TMR17_IRQn = 22, /*!< TMR17 global Interrupt */ + I2C1_IRQn = 23, /*!< I2C1 Event Interrupt */ + I2C2_IRQn = 24, /*!< I2C2 Event Interrupt */ + SPI1_IRQn = 25, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 26, /*!< SPI2 global Interrupt */ + USART1_IRQn = 27, /*!< USART1 global Interrupt */ + USART2_IRQn = 28, /*!< USART2 global Interrupt */ + USART3_4_IRQn = 29, /*!< USART3 and USART4 global Interrupt */ + CEC_IRQn = 30 /*!< CEC global Interrupt */ +#elif defined (APM32F072) + /* APM32F072 specific Interrupt Numbers */ + WWDT_IRQn = 0, /*!< Window WatchDog Interrupt */ + PVD_VDDIO2_IRQn = 1, /*!< PVD and VDDIO2 Interrupt */ + RTC_IRQn = 2, /*!< RTC Interrupt through EINT Lines 17, 19 and 20 */ + FLASH_IRQn = 3, /*!< FLASH global Interrupt */ + RCM_CRS_IRQn = 4, /*!< RCM and CRS global Interrupt */ + EINT0_1_IRQn = 5, /*!< EINT Line 0 and 1 Interrupt */ + EINT2_3_IRQn = 6, /*!< EINT Line 2 and 3 Interrupt */ + EINT4_15_IRQn = 7, /*!< EINT Line 4 to 15 Interrupt */ + TSC_IRQn = 8, /*!< TSC Interrupt */ + DMA1_CH1_IRQn = 9, /*!< DMA1 Channel 1 Interrupt */ + DMA1_CH2_3_IRQn = 10, /*!< DMA1 Channel 2 and Channel 3 Interrupts */ + DMA1_CH4_5_6_7_IRQn = 11, /*!< DMA1 Channel 4, Channel 5, Channel 6 and Channel 7 Interrupts */ + ADC1_COMP_IRQn = 12, /*!< ADC1 and comparator Interrupt */ + TMR1_BRK_UP_TRG_COM_IRQn = 13, /*!< TMR1 Break, Update, Trigger and Commutation Interrupt */ + TMR1_CC_IRQn = 14, /*!< TMR1 Capture Compare Interrupt */ + TMR2_IRQn = 15, /*!< TMR2 global Interrupt */ + TMR3_IRQn = 16, /*!< TMR3 global Interrupt */ + TMR6_DAC_IRQn = 17, /*!< TMR6 and DAC Interrupt */ + TMR7_IRQn = 18, /*!< TMR7 global Interrupt */ + TMR14_IRQn = 19, /*!< TMR14 global Interrupt */ + TMR15_IRQn = 20, /*!< TMR15 global Interrupt */ + TMR16_IRQn = 21, /*!< TMR16 global Interrupt */ + TMR17_IRQn = 22, /*!< TMR17 global Interrupt */ + I2C1_IRQn = 23, /*!< I2C1 Event Interrupt */ + I2C2_IRQn = 24, /*!< I2C2 Event Interrupt */ + SPI1_IRQn = 25, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 26, /*!< SPI2 global Interrupt */ + USART1_IRQn = 27, /*!< USART1 global Interrupt */ + USART2_IRQn = 28, /*!< USART2 global Interrupt */ + USART3_4_IRQn = 29, /*!< USART3 and USART4 global Interrupt */ + CEC_CAN_IRQn = 30, /*!< CEC and CAN global Interrupt */ + USBD_IRQn = 31 /*!< USB Low Priority global Interrupt */ +#elif defined (APM32F091) + /* APM32F091 specific Interrupt Numbers */ + WWDT_IRQn = 0, /*!< Window WatchDog Interrupt */ + PVD_VDDIO2_IRQn = 1, /*!< PVD and VDDIO2 Interrupt */ + RTC_IRQn = 2, /*!< RTC Interrupt through EINT Lines 17, 19 and 20 */ + FLASH_IRQn = 3, /*!< FLASH global Interrupt */ + RCM_CRS_IRQn = 4, /*!< RCM and CRS global Interrupt */ + EINT0_1_IRQn = 5, /*!< EINT Line 0 and 1 Interrupt */ + EINT2_3_IRQn = 6, /*!< EINT Line 2 and 3 Interrupt */ + EINT4_15_IRQn = 7, /*!< EINT Line 4 to 15 Interrupt */ + TSC_IRQn = 8, /*!< TSC Interrupt */ + DMA1_CH1_IRQn = 9, /*!< DMA1 Channel 1 Interrupt */ + DMA1_CH2_3_DMA2_CH1_2_IRQn = 10, /*!< DMA1 Channel 2 and 3 DMA2 Channel 1 and 2 Interrupts */ + DMA1_CH4_7_DMA2_CH3_5_IRQn = 11, /*!< DMA1 Channel 4 to 7 DMA2 Channel 3 to 5 Interrupts */ + ADC1_COMP_IRQn = 12, /*!< ADC1 and comparator Interrupt */ + TMR1_BRK_UP_TRG_COM_IRQn = 13, /*!< TMR1 Break, Update, Trigger and Commutation Interrupt */ + TMR1_CC_IRQn = 14, /*!< TMR1 Capture Compare Interrupt */ + TMR2_IRQn = 15, /*!< TMR2 global Interrupt */ + TMR3_IRQn = 16, /*!< TMR3 global Interrupt */ + TMR6_DAC_IRQn = 17, /*!< TMR6 and DAC Interrupt */ + TMR7_IRQn = 18, /*!< TMR7 global Interrupt */ + TMR14_IRQn = 19, /*!< TMR14 global Interrupt */ + TMR15_IRQn = 20, /*!< TMR15 global Interrupt */ + TMR16_IRQn = 21, /*!< TMR16 global Interrupt */ + TMR17_IRQn = 22, /*!< TMR17 global Interrupt */ + I2C1_IRQn = 23, /*!< I2C1 Event Interrupt */ + I2C2_IRQn = 24, /*!< I2C2 Event Interrupt */ + SPI1_IRQn = 25, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 26, /*!< SPI2 global Interrupt */ + USART1_IRQn = 27, /*!< USART1 global Interrupt */ + USART2_IRQn = 28, /*!< USART2 global Interrupt */ + USART3_8_IRQn = 29, /*!< USART3 and USART8 global Interrupt */ + CEC_CAN_IRQn = 30 /*!< CEC and CAN global Interrupt */ +#endif +} IRQn_Type; + +/**@} end of group Configuraion_for_CMSIS */ + +/* Includes */ + +#include "core_cm0plus.h" /*!< Cortex-M0+ processor and core peripherals */ +#include "system_apm32f0xx.h" /*!< APM32F0xx System Header */ +#include + +/** @defgroup Exported_types + * @{ +*/ + +typedef enum {FALSE, TRUE} BOOL; + +enum {BIT_RESET, BIT_SET}; + +enum {RESET = 0, SET = !RESET}; + +enum {DISABLE = 0, ENABLE = !DISABLE}; + +enum {ERROR = 0, SUCCESS = !ERROR}; + +#ifndef __IM +#define __IM __I +#endif +#ifndef __OM +#define __OM __O +#endif +#ifndef __IOM +#define __IOM __IO +#endif + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#if defined (__CC_ARM ) +#pragma anon_unions +#endif + +/**@} end of group Exported_types */ + +/** @defgroup Peripheral_registers_structures + @{ +*/ + + +/** + * @brief Analog-to-digital converter (ADC) + */ + +typedef struct +{ + /* interrupt and status register */ + union + { + __IOM uint32_t STS; + + struct + { + __IOM uint32_t ADCRDYFLG : 1; + __IOM uint32_t EOSMPFLG : 1; + __IOM uint32_t EOCFLG : 1; + __IOM uint32_t EOSEQFLG : 1; + __IOM uint32_t OVREFLG : 1; + __IM uint32_t RESERVED1 : 2; + __IOM uint32_t AWDFLG : 1; + __IM uint32_t RESERVED2 : 24; + } STS_B; + } ; + + /* interrupt enable register */ + union + { + __IOM uint32_t INT; + + struct + { + __IOM uint32_t ADCRDYIEN : 1; + __IOM uint32_t EOSMPIEN : 1; + __IOM uint32_t EOCIEN : 1; + __IOM uint32_t EOSEQIEN : 1; + __IOM uint32_t OVRIEN : 1; + __IM uint32_t RESERVED1 : 2; + __IOM uint32_t AWDIEN : 1; + __IM uint32_t RESERVED2 : 24; + } INT_B; + } ; + + /* control register */ + union + { + __IOM uint32_t CTRL; + + struct + { + __IOM uint32_t ADCEN : 1; + __IOM uint32_t ADCD : 1; + __IOM uint32_t STARTCEN : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t STOPCEN : 1; + __IM uint32_t RESERVED2 : 26; + __IOM uint32_t CAL : 1; + } CTRL_B; + } ; + + /* configuration register 1 */ + union + { + __IOM uint32_t CFG1; + + struct + { + __IOM uint32_t DMAEN : 1; + __IOM uint32_t DMACFG : 1; + __IOM uint32_t SCANSEQDIR : 1; + __IOM uint32_t DATARESCFG : 2; + __IOM uint32_t DALIGCFG : 1; + __IOM uint32_t EXTTRGSEL : 3; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t EXTPOLSEL : 2; + __IOM uint32_t OVRMAG : 1; + __IOM uint32_t CMODESEL : 1; + __IOM uint32_t WAITCEN : 1; + __IOM uint32_t AOEN : 1; + __IOM uint32_t DISCEN : 1; + __IM uint32_t RESERVED2 : 5; + __IOM uint32_t AWDCHEN : 1; + __IOM uint32_t AWDEN : 1; + __IM uint32_t RESERVED3 : 2; + __IOM uint32_t AWDCHSEL : 5; + __IM uint32_t RESERVED4 : 1; + } CFG1_B; + } ; + + /* configuration register 2 */ + union + { + __IOM uint32_t CFG2; + + struct + { + __IM uint32_t RESERVED1 : 30; + __IOM uint32_t CLKCFG : 2; + } CFG2_B; + } ; + + /* sampling time register */ + union + { + __IOM uint32_t SMPTIM; + + struct + { + __IOM uint32_t SMPCYCSEL : 3; + __IM uint32_t RESERVED1 : 29; + } SMPTIM_B; + } ; + __IM uint32_t RESERVED[2]; + + /* watchdog threshold register */ + union + { + __IOM uint32_t AWDT; + + struct + { + __IOM uint32_t AWDLT : 12; + __IM uint32_t RESERVED1 : 4; + __IOM uint32_t AWDHT : 12; + __IM uint32_t RESERVED2 : 4; + } AWDT_B; + } ; + __IM uint32_t RESERVED1; + + /* channel selection register */ + union + { + __IOM uint32_t CHSEL; + + struct + { + __IOM uint32_t CH0SEL : 1; + __IOM uint32_t CH1SEL : 1; + __IOM uint32_t CH2SEL : 1; + __IOM uint32_t CH3SEL : 1; + __IOM uint32_t CH4SEL : 1; + __IOM uint32_t CH5SEL : 1; + __IOM uint32_t CH6SEL : 1; + __IOM uint32_t CH7SEL : 1; + __IOM uint32_t CH8SEL : 1; + __IOM uint32_t CH9SEL : 1; + __IOM uint32_t CH10SEL : 1; + __IOM uint32_t CH11SEL : 1; + __IOM uint32_t CH12SEL : 1; + __IOM uint32_t CH13SEL : 1; + __IOM uint32_t CH14SEL : 1; + __IOM uint32_t CH15SEL : 1; + __IOM uint32_t CH16SEL : 1; + __IOM uint32_t CH17SEL : 1; + __IOM uint32_t CH18SEL : 1; + __IM uint32_t RESERVED1 : 13; + } CHSEL_B; + } ; + __IM uint32_t RESERVED2[5]; + + /* data register */ + union + { + __IM uint32_t DATA; + + struct + { + __IM uint32_t DATA : 16; + __IM uint32_t RESERVED1 : 16; + } DATA_B; + } ; + __IM uint32_t RESERVED3[177]; + + /* common configuration register */ + union + { + __IOM uint32_t CCFG; + + struct + { + __IM uint32_t RESERVED1 : 22; + __IOM uint32_t VREFEN : 1; + __IOM uint32_t TSEN : 1; + __IOM uint32_t VBATEN : 1; + __IM uint32_t RESERVED2 : 7; + } CCFG_B; + } ; +} ADC_T; + +/** + * @brief Controller area network (CAN) TxMailBox Typedef + */ +typedef struct +{ + /* TX mailbox identifier register */ + union + { + __IOM uint32_t TXMID; + + struct + { + __IOM uint32_t TXMREQ : 1; + __IOM uint32_t TXRFREQ : 1; + __IOM uint32_t IDTYPESEL : 1; + __IOM uint32_t EXTID : 18; + __IOM uint32_t STDID : 11; + } TXMID_B; + } ; + + /* Mailbox data length control and time stamp register */ + union + { + __IOM uint32_t TXDLEN; + + struct + { + __IOM uint32_t DLCODE : 4; + __IM uint32_t RESERVED1 : 4; + __IOM uint32_t TXGT : 1; + __IM uint32_t RESERVED2 : 7; + __IOM uint32_t MTS : 16; + } TXDLEN_B; + } ; + + /* Mailbox data low register 0*/ + union + { + __IOM uint32_t TXMDL; + + struct + { + __IOM uint32_t DATABYTE0 : 8; + __IOM uint32_t DATABYTE1 : 8; + __IOM uint32_t DATABYTE2 : 8; + __IOM uint32_t DATABYTE3 : 8; + } TXMDL_B; + } ; + + /* Mailbox data high register 0*/ + union + { + __IOM uint32_t TXMDH; + + struct + { + __IOM uint32_t DATABYTE4 : 8; + __IOM uint32_t DATABYTE5 : 8; + __IOM uint32_t DATABYTE6 : 8; + __IOM uint32_t DATABYTE7 : 8; + } TXMDH_B; + } ; + +} CAN_TxMailBox_T; + +/** + * @brief Controller area network (CAN) Receive FIFO MailBox Typedef + */ +typedef struct +{ + /* Receive FIFO mailbox identifier register */ + union + { + __IM uint32_t RXMID; + + struct + { + __IM uint32_t RESERVED1 : 1; + __IM uint32_t RFTXREQ : 1; + __IM uint32_t IDTYPESEL : 1; + __IM uint32_t EXTID : 18; + __IM uint32_t STDID : 11; + } RXMID_B; + } ; + + /* Receive FIFO mailbox data length control and time stamp register */ + union + { + __IM uint32_t RXDLEN; + + struct + { + __IM uint32_t DLCODE : 4; + __IM uint32_t RESERVED1 : 4; + __IM uint32_t FMIDX : 8; + __IM uint32_t MTS : 16; + } RXDLEN_B; + } ; + + /* Receive FIFO mailbox data low register */ + union + { + __IM uint32_t RXMDL; + + struct + { + __IM uint32_t DATABYTE0 : 8; + __IM uint32_t DATABYTE1 : 8; + __IM uint32_t DATABYTE2 : 8; + __IM uint32_t DATABYTE3 : 8; + } RXMDL_B; + } ; + + /* Receive FIFO mailbox data high register */ + union + { + __IM uint32_t RXMDH; + + struct + { + __IM uint32_t DATABYTE4 : 8; + __IM uint32_t DATABYTE5 : 8; + __IM uint32_t DATABYTE6 : 8; + __IM uint32_t DATABYTE7 : 8; + } RXMDH_B; + } ; + +} CAN_RxFIFO_T; + +/** + * @brief Controller area network (CAN) Filter register Typedef + */ +typedef struct +{ + /* CAN Filter1 register */ + union + { + __IOM uint32_t R1; + + struct + { + __IOM uint32_t FBIT0 : 1; + __IOM uint32_t FBIT1 : 1; + __IOM uint32_t FBIT2 : 1; + __IOM uint32_t FBIT3 : 1; + __IOM uint32_t FBIT4 : 1; + __IOM uint32_t FBIT5 : 1; + __IOM uint32_t FBIT6 : 1; + __IOM uint32_t FBIT7 : 1; + __IOM uint32_t FBIT8 : 1; + __IOM uint32_t FBIT9 : 1; + __IOM uint32_t FBIT10 : 1; + __IOM uint32_t FBIT11 : 1; + __IOM uint32_t FBIT12 : 1; + __IOM uint32_t FBIT13 : 1; + __IOM uint32_t FBIT14 : 1; + __IOM uint32_t FBIT15 : 1; + __IOM uint32_t FBIT16 : 1; + __IOM uint32_t FBIT17 : 1; + __IOM uint32_t FBIT18 : 1; + __IOM uint32_t FBIT19 : 1; + __IOM uint32_t FBIT20 : 1; + __IOM uint32_t FBIT21 : 1; + __IOM uint32_t FBIT22 : 1; + __IOM uint32_t FBIT23 : 1; + __IOM uint32_t FBIT24 : 1; + __IOM uint32_t FBIT25 : 1; + __IOM uint32_t FBIT26 : 1; + __IOM uint32_t FBIT27 : 1; + __IOM uint32_t FBIT28 : 1; + __IOM uint32_t FBIT29 : 1; + __IOM uint32_t FBIT30 : 1; + __IOM uint32_t FBIT31 : 1; + } R1_B; + }; + + /* CAN Filter2 register */ + union + { + __IOM uint32_t R2; + + struct + { + __IOM uint32_t FBIT0 : 1; + __IOM uint32_t FBIT1 : 1; + __IOM uint32_t FBIT2 : 1; + __IOM uint32_t FBIT3 : 1; + __IOM uint32_t FBIT4 : 1; + __IOM uint32_t FBIT5 : 1; + __IOM uint32_t FBIT6 : 1; + __IOM uint32_t FBIT7 : 1; + __IOM uint32_t FBIT8 : 1; + __IOM uint32_t FBIT9 : 1; + __IOM uint32_t FBIT10 : 1; + __IOM uint32_t FBIT11 : 1; + __IOM uint32_t FBIT12 : 1; + __IOM uint32_t FBIT13 : 1; + __IOM uint32_t FBIT14 : 1; + __IOM uint32_t FBIT15 : 1; + __IOM uint32_t FBIT16 : 1; + __IOM uint32_t FBIT17 : 1; + __IOM uint32_t FBIT18 : 1; + __IOM uint32_t FBIT19 : 1; + __IOM uint32_t FBIT20 : 1; + __IOM uint32_t FBIT21 : 1; + __IOM uint32_t FBIT22 : 1; + __IOM uint32_t FBIT23 : 1; + __IOM uint32_t FBIT24 : 1; + __IOM uint32_t FBIT25 : 1; + __IOM uint32_t FBIT26 : 1; + __IOM uint32_t FBIT27 : 1; + __IOM uint32_t FBIT28 : 1; + __IOM uint32_t FBIT29 : 1; + __IOM uint32_t FBIT30 : 1; + __IOM uint32_t FBIT31 : 1; + } R2_B; + }; +} CAN_FilterRegister_T; + +/** + * @brief Controller area network (CAN) + */ + +typedef struct +{ + /* Master control register */ + union + { + __IOM uint32_t MCTRL; + + struct + { + __IOM uint32_t INITREQ : 1; + __IOM uint32_t SLEEPREQ : 1; + __IOM uint32_t TXFPCFG : 1; + __IOM uint32_t RXFLOCK : 1; + __IOM uint32_t ARTXMD : 1; + __IOM uint32_t AWUPCFG : 1; + __IOM uint32_t ALBOFFM : 1; + __IOM uint32_t TTCM : 1; + __IM uint32_t RESERVED1 : 7; + __IOM uint32_t SWRST : 1; + __IOM uint32_t DBGFRZE : 1; + __IM uint32_t RESERVED2 : 15; + } MCTRL_B; + } ; + + /* Master status register */ + union + { + __IOM uint32_t MSTS; + + struct + { + __IM uint32_t INITFLG : 1; + __IM uint32_t SLEEPFLG : 1; + __IOM uint32_t ERRIFLG : 1; + __IOM uint32_t WUPIFLG : 1; + __IOM uint32_t SLEEPIFLG : 1; + __IM uint32_t RESERVED1 : 3; + __IM uint32_t TXMFLG : 1; + __IM uint32_t RXMFLG : 1; + __IM uint32_t LSAMVALUE : 1; + __IM uint32_t RXSIGL : 1; + __IM uint32_t RESERVED2 : 20; + } MSTS_B; + } ; + + /* Transmit status register */ + union + { + __IOM uint32_t TXSTS; + + struct + { + __IOM uint32_t REQCFLG0 : 1; + __IOM uint32_t TXSUSFLG0 : 1; + __IOM uint32_t ARBLSTFLG0 : 1; + __IOM uint32_t TXERRFLG0 : 1; + __IM uint32_t RESERVED1 : 3; + __IOM uint32_t ABREQFLG0 : 1; + __IOM uint32_t REQCFLG1 : 1; + __IOM uint32_t TXSUSFLG1 : 1; + __IOM uint32_t ARBLSTFLG1 : 1; + __IOM uint32_t TXERRFLG1 : 1; + __IM uint32_t RESERVED2 : 3; + __IOM uint32_t ABREQFLG1 : 1; + __IOM uint32_t REQCFLG2 : 1; + __IOM uint32_t TXSUSFLG2 : 1; + __IOM uint32_t ARBLSTFLG2 : 1; + __IOM uint32_t TXERRFLG2 : 1; + __IM uint32_t RESERVED3 : 3; + __IOM uint32_t ABREQFLG2 : 1; + __IM uint32_t EMNUM : 2; + __IM uint32_t TXMEFLG0 : 1; + __IM uint32_t TXMEFLG1 : 1; + __IM uint32_t TXMEFLG2 : 1; + __IM uint32_t LOWESTP0 : 1; + __IM uint32_t LOWESTP1 : 1; + __IM uint32_t LOWESTP2 : 1; + } TXSTS_B; + } ; + + /* Receive FIFO 0 register */ + union + { + __IOM uint32_t RXF0; + + struct + { + __IM uint32_t FMNUM0 : 2; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t FFULLFLG0 : 1; + __IOM uint32_t FOVRFLG0 : 1; + __IOM uint32_t RFOM0 : 1; + __IM uint32_t RESERVED2 : 26; + } RXF0_B; + } ; + + /* Receive FIFO 1 register */ + union + { + __IOM uint32_t RXF1; + + struct + { + __IM uint32_t FMNUM1 : 2; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t FFULLFLG1 : 1; + __IOM uint32_t FOVRFLG1 : 1; + __IOM uint32_t RFOM1 : 1; + __IM uint32_t RESERVED2 : 26; + } RXF1_B; + } ; + + /* Interrupt enable register */ + union + { + __IOM uint32_t INTEN; + + struct + { + __IOM uint32_t TXMEIE : 1; + __IOM uint32_t FMIEN0 : 1; + __IOM uint32_t FFULLIEN0 : 1; + __IOM uint32_t FOVRIEN0 : 1; + __IOM uint32_t FMPIEN1 : 1; + __IOM uint32_t FFULLIEN1 : 1; + __IOM uint32_t FOVRIEN1 : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t ERRWIEN : 1; + __IOM uint32_t ERRPIEN : 1; + __IOM uint32_t BOFFIEN : 1; + __IOM uint32_t LECIEN : 1; + __IM uint32_t RESERVED2 : 3; + __IOM uint32_t ERRIEN : 1; + __IOM uint32_t WUPIEN : 1; + __IOM uint32_t SLEEPIEN : 1; + __IM uint32_t RESERVED3 : 14; + } INTEN_B; + } ; + + /* Error status register */ + union + { + __IOM uint32_t ERRSTS; + + struct + { + __IM uint32_t ERRWFLG : 1; + __IM uint32_t ERRPFLG : 1; + __IM uint32_t BOFLG : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t LERRC : 3; + __IM uint32_t RESERVED2 : 9; + __IM uint32_t TXERRCNT : 8; + __IM uint32_t RXERRCNT : 8; + } ERRSTS_B; + } ; + + /* Bit timing register */ + union + { + __IOM uint32_t BITTIM; + + struct + { + __IOM uint32_t BRPSC : 10; + __IM uint32_t RESERVED1 : 6; + __IOM uint32_t TIMSEG1 : 4; + __IOM uint32_t TIMSEG2 : 3; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t RSYNJW : 2; + __IM uint32_t RESERVED3 : 4; + __IOM uint32_t LBKMEN : 1; + __IOM uint32_t SILMEN : 1; + } BITTIM_B; + } ; + __IM uint32_t RESERVED1[88]; + + CAN_TxMailBox_T sTxMailBox[3]; + + CAN_RxFIFO_T sRxFIFO[2]; + + __IM uint32_t RESERVED2[12]; + + /* Filter master register */ + union + { + __IOM uint32_t FCTRL; + + struct + { + __IOM uint32_t FIM : 1; + __IM uint32_t RESERVED1 : 31; + } FCTRL_B; + } ; + + /* Filter mode register */ + union + { + __IOM uint32_t FMCFG; + + struct + { + __IOM uint32_t FMCFG0 : 1; + __IOM uint32_t FMCFG1 : 1; + __IOM uint32_t FMCFG2 : 1; + __IOM uint32_t FMCFG3 : 1; + __IOM uint32_t FMCFG4 : 1; + __IOM uint32_t FMCFG5 : 1; + __IOM uint32_t FMCFG6 : 1; + __IOM uint32_t FMCFG7 : 1; + __IOM uint32_t FMCFG8 : 1; + __IOM uint32_t FMCFG9 : 1; + __IOM uint32_t FMCFG10 : 1; + __IOM uint32_t FMCFG11 : 1; + __IOM uint32_t FMCFG12 : 1; + __IOM uint32_t FMCFG13 : 1; + __IM uint32_t RESERVED1 : 18; + } FMCFG_B; + } ; + __IM uint32_t RESERVED3; + + /* Filter scale register */ + union + { + __IOM uint32_t FSCFG; + + struct + { + __IOM uint32_t FSCFG0 : 1; + __IOM uint32_t FSCFG1 : 1; + __IOM uint32_t FSCFG2 : 1; + __IOM uint32_t FSCFG3 : 1; + __IOM uint32_t FSCFG4 : 1; + __IOM uint32_t FSCFG5 : 1; + __IOM uint32_t FSCFG6 : 1; + __IOM uint32_t FSCFG7 : 1; + __IOM uint32_t FSCFG8 : 1; + __IOM uint32_t FSCFG9 : 1; + __IOM uint32_t FSCFG10 : 1; + __IOM uint32_t FSCFG11 : 1; + __IOM uint32_t FSCFG12 : 1; + __IOM uint32_t FSCFG13 : 1; + __IM uint32_t RESERVED1 : 18; + } FSCFG_B; + } ; + __IM uint32_t RESERVED4; + + /* Filter FIFO assignment register */ + union + { + __IOM uint32_t FFASS; + + struct + { + __IOM uint32_t FFASS0 : 1; + __IOM uint32_t FFASS1 : 1; + __IOM uint32_t FFASS2 : 1; + __IOM uint32_t FFASS3 : 1; + __IOM uint32_t FFASS4 : 1; + __IOM uint32_t FFASS5 : 1; + __IOM uint32_t FFASS6 : 1; + __IOM uint32_t FFASS7 : 1; + __IOM uint32_t FFASS8 : 1; + __IOM uint32_t FFASS9 : 1; + __IOM uint32_t FFASS10 : 1; + __IOM uint32_t FFASS11 : 1; + __IOM uint32_t FFASS12 : 1; + __IOM uint32_t FFASS13 : 1; + __IM uint32_t RESERVED1 : 18; + } FFASS_B; + } ; + __IM uint32_t RESERVED5; + + /* Filter activation register */ + union + { + __IOM uint32_t FACT; + + struct + { + __IOM uint32_t FACT0 : 1; + __IOM uint32_t FACT1 : 1; + __IOM uint32_t FACT2 : 1; + __IOM uint32_t FACT3 : 1; + __IOM uint32_t FACT4 : 1; + __IOM uint32_t FACT5 : 1; + __IOM uint32_t FACT6 : 1; + __IOM uint32_t FACT7 : 1; + __IOM uint32_t FACT8 : 1; + __IOM uint32_t FACT9 : 1; + __IOM uint32_t FACT10 : 1; + __IOM uint32_t FACT11 : 1; + __IOM uint32_t FACT12 : 1; + __IOM uint32_t FACT13 : 1; + __IM uint32_t RESERVED1 : 18; + } FACT_B; + } ; + __IM uint32_t RESERVED6[8]; + + /* Filter bank register */ + CAN_FilterRegister_T sFilterRegister[14]; +} CAN_T; + +/** + * @brief HDMI-CEC registers (CEC) + */ + +typedef struct +{ + /* Control register */ + union + { + __IOM uint32_t CTRL; + + struct + { + __IOM uint32_t CECEN : 1; + __IOM uint32_t TXSM : 1; + __IOM uint32_t TXEM : 1; + __IM uint32_t RESERVED1 : 29; + } CTRL_B; + } ; + + /* Configuration register */ + union + { + __IOM uint32_t CFG; + + struct + { + __IOM uint32_t SFTCFG : 3; + __IOM uint32_t RXTCFG : 1; + __IOM uint32_t RXSBRERR : 1; + __IOM uint32_t GEBRERR : 1; + __IOM uint32_t GELBPERR : 1; + __IOM uint32_t AEBGIB : 1; + __IOM uint32_t SFTOB : 1; + __IM uint32_t RESERVED1 : 7; + __IOM uint32_t OACFG : 15; + __IOM uint32_t LMODSEL : 1; + } CFG_B; + } ; + + /* Tx data register */ + union + { + __OM uint32_t TXDATA; + + struct + { + __OM uint32_t TXDATA : 8; + __IM uint32_t RESERVED1 : 24; + } TXDATA_B; + } ; + + /* Rx data register */ + union + { + __IM uint32_t RXDATA; + + struct + { + __IM uint32_t RXDATA : 8; + __IM uint32_t RESERVED1 : 24; + } RXDATA_B; + } ; + + /* Interrupt and Status Register */ + union + { + __IOM uint32_t STS; + + struct + { + __IOM uint32_t RXBREFLG : 1; + __IOM uint32_t RXEFLG : 1; + __IOM uint32_t RXOVRFLG : 1; + __IOM uint32_t RXBRERRFLG : 1; + __IOM uint32_t RXSBPEFLG : 1; + __IOM uint32_t RXLBPEFLG : 1; + __IOM uint32_t RXMACKFLG : 1; + __IOM uint32_t ARBLOSFLG : 1; + __IOM uint32_t TXBREFLG : 1; + __IOM uint32_t TXEFLG : 1; + __IOM uint32_t TXBUFLG : 1; + __IOM uint32_t TXERRFLG : 1; + __IOM uint32_t TXMACKFLG : 1; + __IM uint32_t RESERVED1 : 19; + } STS_B; + } ; + + /* interrupt enable register */ + union + { + __IOM uint32_t INTEN; + + struct + { + __IOM uint32_t RXBREIEN : 1; + __IOM uint32_t RXEIEN : 1; + __IOM uint32_t RXOVRIEN : 1; + __IOM uint32_t RXBRERRIEN : 1; + __IOM uint32_t RXSBPEIEN : 1; + __IOM uint32_t RXLBPEIEN : 1; + __IOM uint32_t RXMACKIEN : 1; + __IOM uint32_t ARBLOSIEN : 1; + __IOM uint32_t TXBREIEN : 1; + __IOM uint32_t TXIEN : 1; + __IOM uint32_t TXBUIEN : 1; + __IOM uint32_t TXERRIEN : 1; + __IOM uint32_t TXMACKIEN : 1; + __IM uint32_t RESERVED1 : 19; + } INTEN_B; + } ; +} CEC_T; + +/** + * @brief Cyclic redundancy check calculation unit (CRC) + */ + +typedef struct +{ + /* Data register */ + union + { + __IOM uint32_t DATA; + + struct + { + __IOM uint32_t DATA : 32; + } DATA_B; + } ; + + /* Independent data register */ + union + { + __IOM uint32_t INDATA; + + struct + { + __IOM uint32_t INDATA : 8; + __IM uint32_t RESERVED1 : 24; + } INDATA_B; + } ; + + /* Control register */ + union + { + __IOM uint32_t CTRL; + + struct + { + __IOM uint32_t RST : 1; + __IM uint32_t RESERVED1 : 2; + __IOM uint32_t POLSIZE : 2; + __IOM uint32_t REVI : 2; + __IOM uint32_t REVO : 1; + __IM uint32_t RESERVED2 : 24; + } CTRL_B; + } ; + __IM uint32_t RESERVED; + + /* Initial CRC value */ + union + { + __IOM uint32_t INITVAL; + + struct + { + __IOM uint32_t VALUE : 32; + } INITVAL_B; + } ; + + /* CRC polynomia register*/ + union + { + __IOM uint32_t POL; + + struct + { + __IOM uint32_t PPOL : 32; + } POL_B; + } ; +} CRC_T; + +/** + * @brief CRS registers (CRS) + */ + +typedef struct +{ + /* Control register */ + union + { + __IOM uint32_t CTRL; + + struct + { + __IOM uint32_t SNINTEN : 1; + __IOM uint32_t SWINTEN : 1; + __IOM uint32_t EINTEN : 1; + __IOM uint32_t ESINTEN : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t CNTEN : 1; + __IOM uint32_t AUTOTRMEN : 1; + __IOM uint32_t SWSGNR : 1; + __IOM uint32_t HSI48TRM : 6; + __IM uint32_t RESERVED2 : 18; + } CTRL_B; + } ; + + union + { + __IOM uint32_t CFG; + + struct + { + __IOM uint32_t RLDVAL : 16; + __IOM uint32_t FELMT : 8; + __IOM uint32_t SYNCPSC : 3; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t SYNCSRCSEL : 2; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t SYNCPOLSEL : 1; + } CFG_B; + } ; + + union + { + __IM uint32_t INTSTS; + + struct + { + __IM uint32_t SNFLG : 1; + __IM uint32_t SWFLG : 1; + __IM uint32_t EFLG : 1; + __IM uint32_t ESFLG : 1; + __IM uint32_t RESERVED1 : 4; + __IM uint32_t ERRORFLG : 1; + __IM uint32_t SYNCMISS : 1; + __IM uint32_t TRMFLG : 1; + __IM uint32_t RESERVED2 : 4; + __IM uint32_t CNTDRCT : 1; + __IM uint32_t FECPT : 16; + } INTSTS_B; + } ; + + union + { + __IOM uint32_t INTCLR; + + struct + { + __IOM uint32_t SNCLR : 1; + __IOM uint32_t SWCLR : 1; + __IOM uint32_t ECLR : 1; + __IOM uint32_t ESCLR : 1; + __IM uint32_t RESERVED1 : 28; + } INTCLR_B; + } ; +} CRS_T; + +/** + * @brief Comparator (COMP) + */ + +typedef struct +{ + /* control and status register */ + union + { + __IOM uint32_t CSTS; + + struct + { + __IOM uint32_t EN1 : 1; + __IOM uint32_t SW1 : 1; + __IOM uint32_t MOD1 : 2; + __IOM uint32_t INVINSEL1 : 3; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t OUTSEL1 : 3; + __IOM uint32_t OPINV1 : 1; + __IOM uint32_t HYSCFG1 : 2; + __IM uint32_t OUTSTS1 : 1; + __IOM uint32_t LOCK1 : 1; + __IOM uint32_t EN2 : 1; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t MOD2 : 2; + __IOM uint32_t INVINSEL2 : 3; + __IOM uint32_t WMODEN : 1; + __IOM uint32_t OUTSEL2 : 3; + __IOM uint32_t OPINV2 : 1; + __IOM uint32_t HYSCFG2 : 2; + __IM uint32_t OUTSTS2 : 1; + __IOM uint32_t LOCK2 : 1; + } CSTS_B; + } ; +} COMP_T; + +/** + * @brief Digital-to-Analog converter (DAC) + */ + +typedef struct +{ + /* Control register */ + union + { + __IOM uint32_t CTRL; + + struct + { + __IOM uint32_t ENCH1 : 1; + __IOM uint32_t BUFFDCH1 : 1; + __IOM uint32_t TRGENCH1 : 1; + __IOM uint32_t TRGSELCH1 : 3; + __IOM uint32_t WAVENCH1 : 2; + __IOM uint32_t MAMPSELCH1 : 4; + __IOM uint32_t DMAENCH1 : 1; + __IOM uint32_t DMAUDRIEN1 : 1; + __IM uint32_t RESERVED1 : 2; + __IOM uint32_t ENCH2 : 1; + __IOM uint32_t BUFFDCH2 : 1; + __IOM uint32_t TRGENCH2 : 1; + __IOM uint32_t TRGSELCH2 : 3; + __IOM uint32_t WAVENCH2 : 2; + __IOM uint32_t MAMPSELCH2 : 4; + __IOM uint32_t DMAENCH2 : 1; + __IOM uint32_t DMAUDRIEN2 : 1; + __IM uint32_t RESERVED2 : 2; + } CTRL_B; + } ; + + /* Software trigger register */ + union + { + __OM uint32_t SWTRG; + + struct + { + __OM uint32_t SWTRG1 : 1; + __OM uint32_t SWTRG2 : 1; + __IM uint32_t RESERVED1 : 30; + } SWTRG_B; + } ; + + /* Channel1 12-bit right-aligned data holding register */ + union + { + __IOM uint32_t DH12R1; + + struct + { + __IOM uint32_t DATA : 12; + __IM uint32_t RESERVED1 : 20; + } DH12R1_B; + } ; + + /* Channel1 12-bit left-aligned data holding register */ + union + { + __IOM uint32_t DH12L1; + + struct + { + __IM uint32_t RESERVED1 : 4; + __IOM uint32_t DATA : 12; + __IM uint32_t RESERVED2 : 16; + } DH12L1_B; + } ; + + /* Channel1 8-bit right-aligned data holding register */ + union + { + __IOM uint32_t DH8R1; + + struct + { + __IOM uint32_t DATA : 8; + __IM uint32_t RESERVED2 : 24; + } DH8R1_B; + } ; + + /* Channel2 12-bit right-aligned data holding register */ + union + { + __IOM uint32_t DH12R2; + + struct + { + __IOM uint32_t DATA : 12; + __IM uint32_t RESERVED1 : 20; + } DH12R2_B; + } ; + + /* Channel2 12-bit left-aligned data holding register */ + union + { + __IOM uint32_t DH12L2; + + struct + { + __IM uint32_t RESERVED1 : 4; + __IOM uint32_t DATA : 12; + __IM uint32_t RESERVED2 : 16; + } DH12L2_B; + } ; + + /* Channel2 8-bit right-aligned data holding register */ + union + { + __IOM uint32_t DH8R2; + + struct + { + __IOM uint32_t DATA : 8; + __IM uint32_t RESERVED1 : 24; + } DH8R2_B; + } ; + + /* Dual DAC 12-bit right-aligned data holding register */ + union + { + __IOM uint32_t DH12RDUAL; + + struct + { + __IOM uint32_t DATACH1 : 12; + __IM uint32_t RESERVED1 : 4; + __IOM uint32_t DATACH2 : 12; + __IM uint32_t RESERVED2 : 4; + } DH12RDUAL_B; + } ; + + /* Dual DAC 12-bit left-aligned data holding register */ + union + { + __IOM uint32_t DH12LDUAL; + + struct + { + __IM uint32_t RESERVED1 : 4; + __IOM uint32_t DATACH1 : 12; + __IM uint32_t RESERVED2 : 4; + __IOM uint32_t DATACH2 : 12; + } DH12LDUAL_B; + } ; + + /* Dual DAC 8-bit right-aligned data holding register */ + union + { + __IOM uint32_t DH8RDUAL; + + struct + { + __IOM uint32_t DATACH1 : 8; + __IOM uint32_t DATACH2 : 8; + __IM uint32_t RESERVED1 : 16; + } DH8RDUAL_B; + } ; + + /* DAC channel1 data output register */ + union + { + __IM uint32_t DATAOCH1; + + struct + { + __IM uint32_t DATA : 12; + __IM uint32_t RESERVED1 : 20; + } DATAOCH1_B; + } ; + + /* DAC channel2 data output register */ + union + { + __IM uint32_t DATAOCH2; + + struct + { + __IM uint32_t DATA : 12; + __IM uint32_t RESERVED1 : 20; + } DATAOCH2_B; + } ; + + /* Status register */ + union + { + __IOM uint32_t STS; + + struct + { + __IM uint32_t RESERVED1 : 13; + __IOM uint32_t DMAUDRFLG1 : 1; + __IM uint32_t RESERVED2 : 15; + __IOM uint32_t DMAUDRFLG2 : 1; + __IM uint32_t RESERVED3 : 2; + } STS_B; + } ; +} DAC_T; + +/** + * @brief Debug support (DBG) + */ + +typedef struct +{ + + /* MCU Device ID Code Register */ + union + { + __IM uint32_t IDCODE; + + struct + { + __IM uint32_t EQR : 12; + __IM uint32_t RESERVED1 : 4; + __IM uint32_t WVR : 16; + } IDCODE_B; + } ; + + /* Debug MCU Configuration Register */ + union + { + __IOM uint32_t CFG; + + struct + { + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t STOP_CLK_STS : 1; + __IOM uint32_t STANDBY_CLK_STS : 1; + __IM uint32_t RESERVED2 : 29; + } CFG_B; + } ; + + /* APB Low Freeze Register */ + union + { + __IOM uint32_t APB1F; + + struct + { + __IOM uint32_t TMR2_STS : 1; + __IOM uint32_t TMR3_STS : 1; + __IM uint32_t RESERVED1 : 2; + __IOM uint32_t TMR6_STS : 1; + __IOM uint32_t TMR7_STS : 1; + __IM uint32_t RESERVED2 : 2; + __IOM uint32_t TMR14_STS : 1; + __IM uint32_t RESERVED3 : 1; + __IOM uint32_t RTC_STS : 1; + __IOM uint32_t WWDT_STS : 1; + __IOM uint32_t IWDT_STS : 1; + __IM uint32_t RESERVED4 : 8; + __IOM uint32_t I2C1_SMBUS_TIMEOUT_STS : 1; + __IM uint32_t RESERVED5 : 3; + __IOM uint32_t CAN_STS : 1; + __IM uint32_t RESERVED6 : 6; + } APB1F_B; + } ; + + /* APB High Freeze Register */ + union + { + __IOM uint32_t APB2F; + + struct + { + __IM uint32_t RESERVED1 : 11; + __IOM uint32_t TMR1_STS : 1; + __IM uint32_t RESERVED2 : 4; + __IOM uint32_t TMR15_STS : 1; + __IOM uint32_t TMR16_STS : 1; + __IOM uint32_t TMR17_STS : 1; + __IM uint32_t RESERVED3 : 13; + } APB2F_B; + } ; +} DBG_T; + +/** + * @brief DMA controller (DMA) + */ + +typedef struct +{ + + /* DMA interrupt status register */ + union + { + __IM uint32_t INTSTS; + + struct + { + __IM uint32_t GINTFLG1 : 1; + __IM uint32_t TCFLG1 : 1; + __IM uint32_t HTFLG1 : 1; + __IM uint32_t TERRFLG1 : 1; + __IM uint32_t GINTFLG2 : 1; + __IM uint32_t TCFLG2 : 1; + __IM uint32_t HTFLG2 : 1; + __IM uint32_t TERRFLG2 : 1; + __IM uint32_t GINTFLG3 : 1; + __IM uint32_t TCFLG3 : 1; + __IM uint32_t HTFLG3 : 1; + __IM uint32_t TERRFLG3 : 1; + __IM uint32_t GINTFLG4 : 1; + __IM uint32_t TCFLG4 : 1; + __IM uint32_t HTFLG4 : 1; + __IM uint32_t TERRFLG4 : 1; + __IM uint32_t GINTFLG5 : 1; + __IM uint32_t TCFLG5 : 1; + __IM uint32_t HTFLG5 : 1; + __IM uint32_t TERRFLG5 : 1; + __IM uint32_t GINTFLG6 : 1; + __IM uint32_t TCFLG6 : 1; + __IM uint32_t HTFLG6 : 1; + __IM uint32_t TERRFLG6 : 1; + __IM uint32_t GINTFLG7 : 1; + __IM uint32_t TCFLG7 : 1; + __IM uint32_t HTFLG7 : 1; + __IM uint32_t TERRFLG7 : 1; + __IM uint32_t RESERVED1 : 4; + } ISTS_B; + } ; + + /* DMA interrupt flag clear register */ + union + { + __OM uint32_t INTFCLR; + + struct + { + __OM uint32_t GINTCLR1 : 1; + __OM uint32_t TCCLR1 : 1; + __OM uint32_t HTCLR1 : 1; + __OM uint32_t TERRCLR1 : 1; + __OM uint32_t GINTCLR2 : 1; + __OM uint32_t TCCLR2 : 1; + __OM uint32_t HTCLR2 : 1; + __OM uint32_t TERRCLR2 : 1; + __OM uint32_t GINTCLR3 : 1; + __OM uint32_t TCCLR3 : 1; + __OM uint32_t HTCLR3 : 1; + __OM uint32_t TERRCLR3 : 1; + __OM uint32_t GINTCLR4 : 1; + __OM uint32_t TCCLR4 : 1; + __OM uint32_t HTCLR4 : 1; + __OM uint32_t TERRCLR4 : 1; + __OM uint32_t GINTCLR5 : 1; + __OM uint32_t TCCLR5 : 1; + __OM uint32_t HTCLR5 : 1; + __OM uint32_t TERRCLR5 : 1; + __OM uint32_t GINTCLR6 : 1; + __OM uint32_t TCCLR6 : 1; + __OM uint32_t HTCLR6 : 1; + __OM uint32_t TERRCLR6 : 1; + __OM uint32_t GINTCLR7 : 1; + __OM uint32_t TCCLR7 : 1; + __OM uint32_t HTCLR7 : 1; + __OM uint32_t TERRCLR7 : 1; + __IM uint32_t RESERVED1 : 4; + } INTFCLR_B; + } ; + + /* DMA channel configuration register */ + union + { + __IOM uint32_t CHCFG1; + + struct + { + __IOM uint32_t CHEN : 1; + __IOM uint32_t TCINTEN : 1; + __IOM uint32_t HTINTEN : 1; + __IOM uint32_t TERRINTEN : 1; + __IOM uint32_t DIRCFG : 1; + __IOM uint32_t CIRMODE : 1; + __IOM uint32_t PERIMODE : 1; + __IOM uint32_t MIMODE : 1; + __IOM uint32_t PERSIZE : 2; + __IOM uint32_t MSIZE : 2; + __IOM uint32_t CHPL : 2; + __IOM uint32_t M2MMODE : 1; + __IM uint32_t RESERVED1 : 17; + } CHCFG1_B; + } ; + + /* DMA channel 1 number of data register */ + union + { + __IOM uint32_t CHNDATA1; + + struct + { + __IOM uint32_t NDATAT : 16; + __IM uint32_t RESERVED1 : 16; + } CHNDATA1_B; + } ; + + /* DMA channel 1 peripheral address register */ + union + { + __IOM uint32_t CHPADDR1; + + struct + { + __IOM uint32_t PERADDR : 32; + } CHPADDR1_B; + } ; + + /* DMA channel 1 memory address register */ + union + { + __IOM uint32_t CHMADDR1; + + struct + { + __IOM uint32_t MEMADD : 32; + } CHMADDR1_B; + } ; + __IM uint32_t RESERVED1; + + /* DMA channel configuration register */ + union + { + __IOM uint32_t CHCFG2; + + struct + { + __IOM uint32_t CHEN : 1; + __IOM uint32_t TCINTEN : 1; + __IOM uint32_t HTINTEN : 1; + __IOM uint32_t TERRINTEN : 1; + __IOM uint32_t DIRCFG : 1; + __IOM uint32_t CIRMODE : 1; + __IOM uint32_t PERIMODE : 1; + __IOM uint32_t MIMODE : 1; + __IOM uint32_t PERSIZE : 2; + __IOM uint32_t MSIZE : 2; + __IOM uint32_t CHPL : 2; + __IOM uint32_t M2MMODE : 1; + __IM uint32_t RESERVED1 : 17; + } CHCFG2_B; + } ; + + /* DMA channel 2 number of data register */ + union + { + __IOM uint32_t CHNDATA2; + + struct + { + __IOM uint32_t NDATAT : 16; + __IM uint32_t RESERVED1 : 16; + } CHNDATA2_B; + } ; + + /* DMA channel 2 peripheral address register */ + union + { + __IOM uint32_t CHPADDR2; + + struct + { + __IOM uint32_t PERADDR : 32; + } CHPADDR2_B; + } ; + + /* DMA channel 2 memory address register */ + union + { + __IOM uint32_t CHMADDR2; + + struct + { + __IOM uint32_t MEMADD : 32; + } CHMADDR2_B; + } ; + __IM uint32_t RESERVED2; + + /* DMA channel configuration register */ + union + { + __IOM uint32_t CHCFG3; + + struct + { + __IOM uint32_t CHEN : 1; + __IOM uint32_t TCINTEN : 1; + __IOM uint32_t HTINTEN : 1; + __IOM uint32_t TERRINTEN : 1; + __IOM uint32_t DIRCFG : 1; + __IOM uint32_t CIRMODE : 1; + __IOM uint32_t PERIMODE : 1; + __IOM uint32_t MIMODE : 1; + __IOM uint32_t PERSIZE : 2; + __IOM uint32_t MSIZE : 2; + __IOM uint32_t CHPL : 2; + __IOM uint32_t M2MMODE : 1; + __IM uint32_t RESERVED1 : 17; + } CHCFG3_B; + } ; + + /* DMA channel 3 number of data register */ + union + { + __IOM uint32_t CHNDATA3; + + struct + { + __IOM uint32_t NDATAT : 16; + __IM uint32_t RESERVED1 : 16; + } CHNDATA3_B; + } ; + + /* DMA channel 3 peripheral address register */ + union + { + __IOM uint32_t CHPADDR3; + + struct + { + __IOM uint32_t PERADDR : 32; + } CHPADDR3_B; + } ; + + /* DMA channel 3 memory address register */ + union + { + __IOM uint32_t CHMADDR3; + + struct + { + __IOM uint32_t MEMADD : 32; + } CHMADDR3_B; + } ; + __IM uint32_t RESERVED3; + + /* DMA channel configuration register */ + union + { + __IOM uint32_t CHCFG4; + + struct + { + __IOM uint32_t CHEN : 1; + __IOM uint32_t TCINTEN : 1; + __IOM uint32_t HTINTEN : 1; + __IOM uint32_t TERRINTEN : 1; + __IOM uint32_t DIRCFG : 1; + __IOM uint32_t CIRMODE : 1; + __IOM uint32_t PERIMODE : 1; + __IOM uint32_t MIMODE : 1; + __IOM uint32_t PERSIZE : 2; + __IOM uint32_t MSIZE : 2; + __IOM uint32_t CHPL : 2; + __IOM uint32_t M2MMODE : 1; + __IM uint32_t RESERVED1 : 17; + } CHCFG4_B; + } ; + + /* DMA channel 4 number of data register */ + union + { + __IOM uint32_t CHNDATA4; + + struct + { + __IOM uint32_t NDATAT : 16; + __IM uint32_t RESERVED1 : 16; + } CHNDATA4_B; + } ; + + /* DMA channel 4 peripheral address register */ + union + { + __IOM uint32_t CHPADDR4; + + struct + { + __IOM uint32_t PERADDR : 32; + } CHPADDR4_B; + } ; + + /* DMA channel 4 memory address register */ + union + { + __IOM uint32_t CHMADDR4; + + struct + { + __IOM uint32_t MEMADD : 32; + } CHMADDR4_B; + } ; + __IM uint32_t RESERVED4; + + /* DMA channel configuration register */ + union + { + __IOM uint32_t CHCFG5; + + struct + { + __IOM uint32_t CHEN : 1; + __IOM uint32_t TCINTEN : 1; + __IOM uint32_t HTINTEN : 1; + __IOM uint32_t TERRINTEN : 1; + __IOM uint32_t DIRCFG : 1; + __IOM uint32_t CIRMODE : 1; + __IOM uint32_t PERIMODE : 1; + __IOM uint32_t MIMODE : 1; + __IOM uint32_t PERSIZE : 2; + __IOM uint32_t MSIZE : 2; + __IOM uint32_t CHPL : 2; + __IOM uint32_t M2MMODE : 1; + __IM uint32_t RESERVED1 : 17; + } CHCFG5_B; + } ; + + /* DMA channel 5 number of data register */ + union + { + __IOM uint32_t CHNDATA5; + + struct + { + __IOM uint32_t NDATAT : 16; + __IM uint32_t RESERVED1 : 16; + } CHNDATA5_B; + } ; + + /* DMA channel 5 peripheral address register */ + union + { + __IOM uint32_t CHPADDR5; + + struct + { + __IOM uint32_t PERADDR : 32; + } CHPADDR5_B; + } ; + + /* DMA channel 5 memory address register */ + union + { + __IOM uint32_t CHMADDR5; + + struct + { + __IOM uint32_t MEMADD : 32; + } CHMADDR5_B; + } ; + __IM uint32_t RESERVED5; + + /* DMA channel configuration register */ + union + { + __IOM uint32_t CHCFG6; + + struct + { + __IOM uint32_t CHEN : 1; + __IOM uint32_t TCINTEN : 1; + __IOM uint32_t HTINTEN : 1; + __IOM uint32_t TERRINTEN : 1; + __IOM uint32_t DIRCFG : 1; + __IOM uint32_t CIRMODE : 1; + __IOM uint32_t PERIMODE : 1; + __IOM uint32_t MIMODE : 1; + __IOM uint32_t PERSIZE : 2; + __IOM uint32_t MSIZE : 2; + __IOM uint32_t CHPL : 2; + __IOM uint32_t M2MMODE : 1; + __IM uint32_t RESERVED1 : 17; + } CHCFG6_B; + } ; + + /* DMA channel 6 number of data register */ + union + { + __IOM uint32_t CHNDATA6; + + struct + { + __IOM uint32_t NDATAT : 16; + __IM uint32_t RESERVED1 : 16; + } CHNDATA6_B; + } ; + + /* DMA channel 6 peripheral address register */ + union + { + __IOM uint32_t CHPADDR6; + + struct + { + __IOM uint32_t PERADDR : 32; + } CHPADDR6_B; + } ; + + /* DMA channel 6 memory address register */ + union + { + __IOM uint32_t CHMADDR6; + + struct + { + __IOM uint32_t MEMADD : 32; + } CHMADDR6_B; + } ; + __IM uint32_t RESERVED6; + + /* DMA channel configuration register */ + union + { + __IOM uint32_t CHCFG7; + + struct + { + __IOM uint32_t CHEN : 1; + __IOM uint32_t TCINTEN : 1; + __IOM uint32_t HTINTEN : 1; + __IOM uint32_t TERRINTEN : 1; + __IOM uint32_t DIRCFG : 1; + __IOM uint32_t CIRMODE : 1; + __IOM uint32_t PERIMODE : 1; + __IOM uint32_t MIMODE : 1; + __IOM uint32_t PERSIZE : 2; + __IOM uint32_t MSIZE : 2; + __IOM uint32_t CHPL : 2; + __IOM uint32_t M2MMODE : 1; + __IM uint32_t RESERVED1 : 17; + } CHCFG7_B; + } ; + + /* DMA channel 7 number of data register */ + union + { + __IOM uint32_t CHNDATA7; + + struct + { + __IOM uint32_t NDATAT : 16; + __IM uint32_t RESERVED1 : 16; + } CHNDATA7_B; + } ; + + /* DMA channel 7 peripheral address register */ + union + { + __IOM uint32_t CHPADDR7; + + struct + { + __IOM uint32_t PERADDR : 32; + } CHPADDR7_B; + } ; + + /* DMA channel 7 memory address register */ + union + { + __IOM uint32_t CHMADDR7; + + struct + { + __IOM uint32_t MEMADD : 32; + } CHMADDR7_B; + } ; + __IM uint32_t RESERVED7[6]; + + /* DMA channel remap selection register */ + union + { + __IOM uint32_t CHSEL; + + struct + { + __IOM uint32_t CHSEL1 : 4; + __IOM uint32_t CHSEL2 : 4; + __IOM uint32_t CHSEL3 : 4; + __IOM uint32_t CHSEL4 : 4; + __IOM uint32_t CHSEL5 : 4; + __IOM uint32_t CHSEL6 : 4; + __IOM uint32_t CHSEL7 : 4; + __IM uint32_t RESERVED1 : 4; + } CHSEL_B; + } ; +} DMA_T; + +/** + * @brief DMA CHANNEL register + */ + +typedef struct +{ + + /* DMA channel configuration register */ + union + { + __IOM uint32_t CHCFG; + + struct + { + __IOM uint32_t CHEN : 1; + __IOM uint32_t TCINTEN : 1; + __IOM uint32_t HTINTEN : 1; + __IOM uint32_t TERRINTEN : 1; + __IOM uint32_t DIRCFG : 1; + __IOM uint32_t CIRMODE : 1; + __IOM uint32_t PERIMODE : 1; + __IOM uint32_t MIMODE : 1; + __IOM uint32_t PERSIZE : 2; + __IOM uint32_t MSIZE : 2; + __IOM uint32_t CHPL : 2; + __IOM uint32_t M2MMODE : 1; + __IM uint32_t RESERVED1 : 17; + } CHCFG_B; + } ; + + /* DMA channelx number of data register */ + union + { + __IOM uint32_t CHNDATA; + + struct + { + __IOM uint32_t NDATAT : 16; + __IM uint32_t RESERVED1 : 16; + } CHNDATA_B; + } ; + + /* DMA channelx peripheral address register */ + union + { + __IOM uint32_t CHPADDR; + + struct + { + __IOM uint32_t PERADDR : 32; + } CHPADDR_B; + } ; + + /* DMA channelx memory address register */ + union + { + __IOM uint32_t CHMADDR; + + struct + { + __IOM uint32_t MEMADD : 32; + } CHMADDR_B; + } ; +} DMA_CHANNEL_T; + +/** + * @brief External interrupt/event controller (EINT) + */ + +typedef struct +{ + /* Interrupt mask register */ + union + { + __IOM uint32_t IMASK; + + struct + { + __IOM uint32_t IMASK0 : 1; + __IOM uint32_t IMASK1 : 1; + __IOM uint32_t IMASK2 : 1; + __IOM uint32_t IMASK3 : 1; + __IOM uint32_t IMASK4 : 1; + __IOM uint32_t IMASK5 : 1; + __IOM uint32_t IMASK6 : 1; + __IOM uint32_t IMASK7 : 1; + __IOM uint32_t IMASK8 : 1; + __IOM uint32_t IMASK9 : 1; + __IOM uint32_t IMASK10 : 1; + __IOM uint32_t IMASK11 : 1; + __IOM uint32_t IMASK12 : 1; + __IOM uint32_t IMASK13 : 1; + __IOM uint32_t IMASK14 : 1; + __IOM uint32_t IMASK15 : 1; + __IOM uint32_t IMASK16 : 1; + __IOM uint32_t IMASK17 : 1; + __IOM uint32_t IMASK18 : 1; + __IOM uint32_t IMASK19 : 1; + __IOM uint32_t IMASK20 : 1; + __IOM uint32_t IMASK21 : 1; + __IOM uint32_t IMASK22 : 1; + __IOM uint32_t IMASK23 : 1; + __IOM uint32_t IMASK24 : 1; + __IOM uint32_t IMASK25 : 1; + __IOM uint32_t IMASK26 : 1; + __IOM uint32_t IMASK27 : 1; + __IOM uint32_t IMASK28 : 1; + __IOM uint32_t IMASK29 : 1; + __IOM uint32_t IMASK30 : 1; + __IOM uint32_t IMASK31 : 1; + } IMASK_B; + } ; + + /* Event mask register (EINT_EVTMASK) */ + union + { + + __IOM uint32_t EMASK; + + struct + { + __IOM uint32_t EMASK0 : 1; + __IOM uint32_t EMASK1 : 1; + __IOM uint32_t EMASK2 : 1; + __IOM uint32_t EMASK3 : 1; + __IOM uint32_t EMASK4 : 1; + __IOM uint32_t EMASK5 : 1; + __IOM uint32_t EMASK6 : 1; + __IOM uint32_t EMASK7 : 1; + __IOM uint32_t EMASK8 : 1; + __IOM uint32_t EMASK9 : 1; + __IOM uint32_t EMASK10 : 1; + __IOM uint32_t EMASK11 : 1; + __IOM uint32_t EMASK12 : 1; + __IOM uint32_t EMASK13 : 1; + __IOM uint32_t EMASK14 : 1; + __IOM uint32_t EMASK15 : 1; + __IOM uint32_t EMASK16 : 1; + __IOM uint32_t EMASK17 : 1; + __IOM uint32_t EMASK18 : 1; + __IOM uint32_t EMASK19 : 1; + __IOM uint32_t EMASK20 : 1; + __IOM uint32_t EMASK21 : 1; + __IOM uint32_t EMASK22 : 1; + __IOM uint32_t EMASK23 : 1; + __IOM uint32_t EMASK24 : 1; + __IOM uint32_t EMASK25 : 1; + __IOM uint32_t EMASK26 : 1; + __IOM uint32_t EMASK27 : 1; + __IOM uint32_t EMASK28 : 1; + __IOM uint32_t EMASK29 : 1; + __IOM uint32_t EMASK30 : 1; + __IOM uint32_t EMASK31 : 1; + } EMASK_B; + } ; + + union + { + __IOM uint32_t RTEN; + + struct + { + __IOM uint32_t RTEN0 : 1; + __IOM uint32_t RTEN1 : 1; + __IOM uint32_t RTEN2 : 1; + __IOM uint32_t RTEN3 : 1; + __IOM uint32_t RTEN4 : 1; + __IOM uint32_t RTEN5 : 1; + __IOM uint32_t RTEN6 : 1; + __IOM uint32_t RTEN7 : 1; + __IOM uint32_t RTEN8 : 1; + __IOM uint32_t RTEN9 : 1; + __IOM uint32_t RTEN10 : 1; + __IOM uint32_t RTEN11 : 1; + __IOM uint32_t RTEN12 : 1; + __IOM uint32_t RTEN13 : 1; + __IOM uint32_t RTEN14 : 1; + __IOM uint32_t RTEN15 : 1; + __IOM uint32_t RTEN16 : 1; + __IOM uint32_t RTEN17 : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t RTEN19 : 1; + __IOM uint32_t RTEN20 : 1; + __IOM uint32_t RTEN21 : 1; + __IOM uint32_t RTEN22 : 1; + __IM uint32_t RESERVED2 : 8; + __IOM uint32_t RTEN31 : 1; + } RTEN_B; + } ; + + /* Falling Trigger selection register */ + union + { + __IOM uint32_t FTEN; + + struct + { + __IOM uint32_t FTEN0 : 1; + __IOM uint32_t FTEN1 : 1; + __IOM uint32_t FTEN2 : 1; + __IOM uint32_t FTEN3 : 1; + __IOM uint32_t FTEN4 : 1; + __IOM uint32_t FTEN5 : 1; + __IOM uint32_t FTEN6 : 1; + __IOM uint32_t FTEN7 : 1; + __IOM uint32_t FTEN8 : 1; + __IOM uint32_t FTEN9 : 1; + __IOM uint32_t FTEN10 : 1; + __IOM uint32_t FTEN11 : 1; + __IOM uint32_t FTEN12 : 1; + __IOM uint32_t FTEN13 : 1; + __IOM uint32_t FTEN14 : 1; + __IOM uint32_t FTEN15 : 1; + __IOM uint32_t FTEN16 : 1; + __IOM uint32_t FTEN17 : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t FTEN19 : 1; + __IOM uint32_t FTEN20 : 1; + __IOM uint32_t FTEN21 : 1; + __IOM uint32_t FTEN22 : 1; + __IM uint32_t RESERVED2 : 8; + __IOM uint32_t FTEN31 : 1; + } FTEN_B; + } ; + + /* Software interrupt event register */ + union + { + __IOM uint32_t SWINTE; + + struct + { + __IOM uint32_t SWINTE0 : 1; + __IOM uint32_t SWINTE1 : 1; + __IOM uint32_t SWINTE2 : 1; + __IOM uint32_t SWINTE3 : 1; + __IOM uint32_t SWINTE4 : 1; + __IOM uint32_t SWINTE5 : 1; + __IOM uint32_t SWINTE6 : 1; + __IOM uint32_t SWINTE7 : 1; + __IOM uint32_t SWINTE8 : 1; + __IOM uint32_t SWINTE9 : 1; + __IOM uint32_t SWINTE10 : 1; + __IOM uint32_t SWINTE11 : 1; + __IOM uint32_t SWINTE12 : 1; + __IOM uint32_t SWINTE13 : 1; + __IOM uint32_t SWINTE14 : 1; + __IOM uint32_t SWINTE15 : 1; + __IOM uint32_t SWINTE16 : 1; + __IOM uint32_t SWINTE17 : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t SWINTE19 : 1; + __IOM uint32_t SWINTE20 : 1; + __IOM uint32_t SWINTE21 : 1; + __IOM uint32_t SWINTE22 : 1; + __IM uint32_t RESERVED2 : 8; + __IOM uint32_t SWINTE31 : 1; + } SWINTE_B; + } ; + + /* Pending register */ + union + { + __IOM uint32_t IPEND; + + struct + { + __IOM uint32_t IPEND0 : 1; + __IOM uint32_t IPEND1 : 1; + __IOM uint32_t IPEND2 : 1; + __IOM uint32_t IPEND3 : 1; + __IOM uint32_t IPEND4 : 1; + __IOM uint32_t IPEND5 : 1; + __IOM uint32_t IPEND6 : 1; + __IOM uint32_t IPEND7 : 1; + __IOM uint32_t IPEND8 : 1; + __IOM uint32_t IPEND9 : 1; + __IOM uint32_t IPEND10 : 1; + __IOM uint32_t IPEND11 : 1; + __IOM uint32_t IPEND12 : 1; + __IOM uint32_t IPEND13 : 1; + __IOM uint32_t IPEND14 : 1; + __IOM uint32_t IPEND15 : 1; + __IOM uint32_t IPEND16 : 1; + __IOM uint32_t IPEND17 : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t IPEND19 : 1; + __IOM uint32_t IPEND20 : 1; + __IOM uint32_t IPEND21 : 1; + __IOM uint32_t IPEND22 : 1; + __IM uint32_t RESERVED2 : 8; + __IOM uint32_t IPEND31 : 1; + } IPEND_B; + } ; +} EINT_T; + +/** + * @brief FMC (FMC) + */ + +typedef struct +{ + + /* Flash access control register */ + union + { + __IOM uint32_t CTRL1; + + struct + { + __IOM uint32_t WS : 3; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t PBEN : 1; + __IM uint32_t PBSF : 1; + __IM uint32_t RESERVED3 : 26; + } CTRL1_B; + } ; + + /* Flash key register */ + union + { + __OM uint32_t KEY; + + struct + { + __OM uint32_t KEY : 32; + } KEY_B; + } ; + + /* Flash option key register */ + union + { + __OM uint32_t OBKEY; + + struct + { + __OM uint32_t OBKEY : 32; + } OBKEY_B; + } ; + + /* Flash status register */ + union + { + __IOM uint32_t STS; + + struct + { + __IM uint32_t BUSYF : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t PEF : 1; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t WPEF : 1; + __IOM uint32_t OCF : 1; + __IM uint32_t RESERVED3 : 26; + } STS_B; + } ; + + /* Flash control register */ + union + { + __IOM uint32_t CTRL2; + + struct + { + __IOM uint32_t PG : 1; + __IOM uint32_t PAGEERA : 1; + __IOM uint32_t MASSERA : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t OBP : 1; + __IOM uint32_t OBE : 1; + __IOM uint32_t STA : 1; + __IOM uint32_t LOCK : 1; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t OBWEN : 1; + __IOM uint32_t ERRIE : 1; + __IM uint32_t RESERVED3 : 1; + __IOM uint32_t OCIE : 1; + __IOM uint32_t OBLOAD : 1; + __IM uint32_t RESERVED4 : 18; + } CTRL2_B; + } ; + + /* Flash address register */ + union + { + __OM uint32_t ADDR; + + struct + { + __OM uint32_t ADDR : 32; + } ADDR_B; + } ; + __IM uint32_t RESERVED; + + /* Option byte register */ + union + { + __IM uint32_t OBCS; + + struct + { + __IM uint32_t OBE : 1; + __IM uint32_t READPROT : 2; + __IM uint32_t RESERVED1 : 5; + __IM uint32_t WDTSEL : 1; + __IM uint32_t RSTSTOP : 1; + __IM uint32_t RSTSTDB : 1; + __IM uint32_t RESERVED2 : 1; + __IM uint32_t nBOOT1 : 1; + __IM uint32_t VDDAMONI : 1; + __IM uint32_t SRAMPARITY : 1; + __IM uint32_t nBOOT0 : 1; + __IM uint32_t DATA0 : 8; + __IM uint32_t DATA1 : 8; + } OBCS_B; + } ; + + /* Write protection register */ + union + { + __IM uint32_t WRTPROT; + + struct + { + __IM uint32_t WRTPROT : 32; + } WRTPROT_B; + } ; +} FMC_T; + +/* + * @brief General-purpose I/Os (GPIO) + */ + +typedef struct +{ + /* GPIO port mode register*/ + union + { + __IOM uint32_t MODE; + + struct + { + __IOM uint32_t MODE0 : 2; + __IOM uint32_t MODE1 : 2; + __IOM uint32_t MODE2 : 2; + __IOM uint32_t MODE3 : 2; + __IOM uint32_t MODE4 : 2; + __IOM uint32_t MODE5 : 2; + __IOM uint32_t MODE6 : 2; + __IOM uint32_t MODE7 : 2; + __IOM uint32_t MODE8 : 2; + __IOM uint32_t MODE9 : 2; + __IOM uint32_t MODE10 : 2; + __IOM uint32_t MODE11 : 2; + __IOM uint32_t MODE12 : 2; + __IOM uint32_t MODE13 : 2; + __IOM uint32_t MODE14 : 2; + __IOM uint32_t MODE15 : 2; + } MODE_B; + } ; + + /* GPIO port output type register*/ + union + { + __IOM uint32_t OMODE; + + struct + { + __IOM uint32_t OMODE0 : 1; + __IOM uint32_t OMODE1 : 1; + __IOM uint32_t OMODE2 : 1; + __IOM uint32_t OMODE3 : 1; + __IOM uint32_t OMODE4 : 1; + __IOM uint32_t OMODE5 : 1; + __IOM uint32_t OMODE6 : 1; + __IOM uint32_t OMODE7 : 1; + __IOM uint32_t OMODE8 : 1; + __IOM uint32_t OMODE9 : 1; + __IOM uint32_t OMODE10 : 1; + __IOM uint32_t OMODE11 : 1; + __IOM uint32_t OMODE12 : 1; + __IOM uint32_t OMODE13 : 1; + __IOM uint32_t OMODE14 : 1; + __IOM uint32_t OMODE15 : 1; + __IOM uint32_t RESERVED1 : 16; + } OMODE_B; + } ; + + /* GPIO port output speed register*/ + union + { + __IOM uint32_t OSSEL; + + struct + { + __IOM uint32_t OSSEL0 : 2; + __IOM uint32_t OSSEL1 : 2; + __IOM uint32_t OSSEL2 : 2; + __IOM uint32_t OSSEL3 : 2; + __IOM uint32_t OSSEL4 : 2; + __IOM uint32_t OSSEL5 : 2; + __IOM uint32_t OSSEL6 : 2; + __IOM uint32_t OSSEL7 : 2; + __IOM uint32_t OSSEL8 : 2; + __IOM uint32_t OSSEL9 : 2; + __IOM uint32_t OSSEL10 : 2; + __IOM uint32_t OSSEL11 : 2; + __IOM uint32_t OSSEL12 : 2; + __IOM uint32_t OSSEL13 : 2; + __IOM uint32_t OSSEL14 : 2; + __IOM uint32_t OSSEL15 : 2; + } OSSEL_B; + } ; + + /* GPIO port pull-up/pull-down register*/ + union + { + __IOM uint32_t PUPD; + + struct + { + __IOM uint32_t PUPD0 : 2; + __IOM uint32_t PUPD1 : 2; + __IOM uint32_t PUPD2 : 2; + __IOM uint32_t PUPD3 : 2; + __IOM uint32_t PUPD4 : 2; + __IOM uint32_t PUPD5 : 2; + __IOM uint32_t PUPD6 : 2; + __IOM uint32_t PUPD7 : 2; + __IOM uint32_t PUPD8 : 2; + __IOM uint32_t PUPD9 : 2; + __IOM uint32_t PUPD10 : 2; + __IOM uint32_t PUPD11 : 2; + __IOM uint32_t PUPD12 : 2; + __IOM uint32_t PUPD13 : 2; + __IOM uint32_t PUPD14 : 2; + __IOM uint32_t PUPD15 : 2; + } PUPD_B; + } ; + + /* GPIO port input data register*/ + union + { + __IM uint32_t IDATA; + + struct + { + __IM uint32_t IDATA0 : 1; + __IM uint32_t IDATA1 : 1; + __IM uint32_t IDATA2 : 1; + __IM uint32_t IDATA3 : 1; + __IM uint32_t IDATA4 : 1; + __IM uint32_t IDATA5 : 1; + __IM uint32_t IDATA6 : 1; + __IM uint32_t IDATA7 : 1; + __IM uint32_t IDATA8 : 1; + __IM uint32_t IDATA9 : 1; + __IM uint32_t IDATA10 : 1; + __IM uint32_t IDATA11 : 1; + __IM uint32_t IDATA12 : 1; + __IM uint32_t IDATA13 : 1; + __IM uint32_t IDATA14 : 1; + __IM uint32_t IDATA15 : 1; + __IM uint32_t RESERVED1 : 16; + } IDATA_B; + } ; + + /* GPIO port output data register*/ + union + { + __IOM uint32_t ODATA; + + struct + { + __IOM uint32_t ODATA0 : 1; + __IOM uint32_t ODATA1 : 1; + __IOM uint32_t ODATA2 : 1; + __IOM uint32_t ODATA3 : 1; + __IOM uint32_t ODATA4 : 1; + __IOM uint32_t ODATA5 : 1; + __IOM uint32_t ODATA6 : 1; + __IOM uint32_t ODATA7 : 1; + __IOM uint32_t ODATA8 : 1; + __IOM uint32_t ODATA9 : 1; + __IOM uint32_t ODATA10 : 1; + __IOM uint32_t ODATA11 : 1; + __IOM uint32_t ODATA12 : 1; + __IOM uint32_t ODATA13 : 1; + __IOM uint32_t ODATA14 : 1; + __IOM uint32_t ODATA15 : 1; + __IOM uint32_t RESERVED1 : 16; + } ODATA_B; + } ; + + /* GPIO port bit set/clear register*/ + union + { + __OM uint32_t BSC; + + struct + { + __OM uint32_t BS0 : 1; + __OM uint32_t BS1 : 1; + __OM uint32_t BS2 : 1; + __OM uint32_t BS3 : 1; + __OM uint32_t BS4 : 1; + __OM uint32_t BS5 : 1; + __OM uint32_t BS6 : 1; + __OM uint32_t BS7 : 1; + __OM uint32_t BS8 : 1; + __OM uint32_t BS9 : 1; + __OM uint32_t BS10 : 1; + __OM uint32_t BS11 : 1; + __OM uint32_t BS12 : 1; + __OM uint32_t BS13 : 1; + __OM uint32_t BS14 : 1; + __OM uint32_t BS15 : 1; + __OM uint32_t BC0 : 1; + __OM uint32_t BC1 : 1; + __OM uint32_t BC2 : 1; + __OM uint32_t BC3 : 1; + __OM uint32_t BC4 : 1; + __OM uint32_t BC5 : 1; + __OM uint32_t BC6 : 1; + __OM uint32_t BC7 : 1; + __OM uint32_t BC8 : 1; + __OM uint32_t BC9 : 1; + __OM uint32_t BC10 : 1; + __OM uint32_t BC11 : 1; + __OM uint32_t BC12 : 1; + __OM uint32_t BC13 : 1; + __OM uint32_t BC14 : 1; + __OM uint32_t BC15 : 1; + } BSC_B; + } ; + + /* GPIO port configuration lock register*/ + union + { + __IOM uint32_t LOCK; + + struct + { + __IOM uint32_t LOCK0 : 1; + __IOM uint32_t LOCK1 : 1; + __IOM uint32_t LOCK2 : 1; + __IOM uint32_t LOCK3 : 1; + __IOM uint32_t LOCK4 : 1; + __IOM uint32_t LOCK5 : 1; + __IOM uint32_t LOCK6 : 1; + __IOM uint32_t LOCK7 : 1; + __IOM uint32_t LOCK8 : 1; + __IOM uint32_t LOCK9 : 1; + __IOM uint32_t LOCK10 : 1; + __IOM uint32_t LOCK11 : 1; + __IOM uint32_t LOCK12 : 1; + __IOM uint32_t LOCK13 : 1; + __IOM uint32_t LOCK14 : 1; + __IOM uint32_t LOCK15 : 1; + __IOM uint32_t LOCKKEY : 1; + __IOM uint32_t RESERVED1 : 15; + } LOCK_B; + } ; + + /* GPIO alternate function low register*/ + union + { + __IOM uint32_t ALFL; + + struct + { + __IOM uint32_t AF0 : 4; + __IOM uint32_t AF1 : 4; + __IOM uint32_t AF2 : 4; + __IOM uint32_t AF3 : 4; + __IOM uint32_t AF4 : 4; + __IOM uint32_t AF5 : 4; + __IOM uint32_t AF6 : 4; + __IOM uint32_t AF7 : 4; + } ALFL_B; + } ; + + /* GPIO alternate function high register*/ + union + { + __IOM uint32_t ALFH; + + struct + { + __IOM uint32_t AF0 : 4; + __IOM uint32_t AF1 : 4; + __IOM uint32_t AF2 : 4; + __IOM uint32_t AF3 : 4; + __IOM uint32_t AF4 : 4; + __IOM uint32_t AF5 : 4; + __IOM uint32_t AF6 : 4; + __IOM uint32_t AF7 : 4; + } ALFH_B; + } ; + + /* Port bit clear register*/ + union + { + __OM uint32_t BR; + + struct + { + __OM uint32_t BR0 : 1; + __OM uint32_t BR1 : 1; + __OM uint32_t BR2 : 1; + __OM uint32_t BR3 : 1; + __OM uint32_t BR4 : 1; + __OM uint32_t BR5 : 1; + __OM uint32_t BR6 : 1; + __OM uint32_t BR7 : 1; + __OM uint32_t BR8 : 1; + __OM uint32_t BR9 : 1; + __OM uint32_t BR10 : 1; + __OM uint32_t BR11 : 1; + __OM uint32_t BR12 : 1; + __OM uint32_t BR13 : 1; + __OM uint32_t BR14 : 1; + __OM uint32_t BR15 : 1; + __OM uint32_t RESERVED1 : 16; + } BR_B; + } ; +} GPIO_T; + + +/** + * @brief Inter-integrated circuit (I2C) + */ + +typedef struct +{ + /* Control register 1*/ + union + { + __IOM uint32_t CTRL1; + + struct + { + __IOM uint32_t I2CEN : 1; + __IOM uint32_t TXIEN : 1; + __IOM uint32_t RXIEN : 1; + __IOM uint32_t SADDRMIEN : 1; + __IOM uint32_t NACKRXIEN : 1; + __IOM uint32_t STOPIEN : 1; + __IOM uint32_t TXCIEN : 1; + __IOM uint32_t ERRIEN : 1; + __IOM uint32_t DNFCFG : 4; + __IOM uint32_t ANFD : 1; + __OM uint32_t SWRST : 1; + __IOM uint32_t DMATXEN : 1; + __IOM uint32_t DMARXEN : 1; + __IOM uint32_t SBCEN : 1; + __IOM uint32_t CLKSTRETCHD : 1; + __IOM uint32_t WUPEN : 1; + __IOM uint32_t RBEN : 1; + __IOM uint32_t HADDREN : 1; + __IOM uint32_t DEADDREN : 1; + __IOM uint32_t ALTEN : 1; + __IOM uint32_t PECEN : 1; + __IM uint32_t RESERVED2 : 8; + } CTRL1_B; + } ; + + /* Control register 2*/ + union + { + __IOM uint32_t CTRL2; + + struct + { + __IOM uint32_t SADDR0 : 1; + __IOM uint32_t SADDR1 : 7; + __IOM uint32_t SADDR8 : 2; + __IOM uint32_t TXDIR : 1; + __IOM uint32_t SADDRLEN : 1; + __IOM uint32_t ADDR10 : 1; + __IOM uint32_t START : 1; + __IOM uint32_t STOP : 1; + __IOM uint32_t NACKEN : 1; + __IOM uint32_t NUMBYT : 8; + __IOM uint32_t RELOADEN : 1; + __IOM uint32_t ENDCFG : 1; + __IOM uint32_t PEC : 1; + __IOM uint32_t RESERVED1 : 5; + } CTRL2_B; + } ; + + /* Own address register 1*/ + union + { + __IOM uint32_t ADDR1; + + struct + { + __IOM uint32_t ADDR0 : 1; + __IOM uint32_t ADDR1 : 7; + __IOM uint32_t ADDR8 : 2; + __IOM uint32_t ADDR1LEN : 1; + __IM uint32_t RESERVED1 : 4; + __IOM uint32_t ADDR1EN : 1; + __IM uint32_t RESERVED2 : 16; + } ADDR1_B; + } ; + + /* Own address register 2*/ + union + { + __IOM uint32_t ADDR2; + + struct + { + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t ADDR2 : 7; + __IOM uint32_t ADDR2MSK : 3; + __IM uint32_t RESERVED2 : 4; + __IOM uint32_t ADDR2EN : 1; + __IM uint32_t RESERVED3 : 16; + } ADDR2_B; + } ; + + /* Timing register*/ + union + { + __IOM uint32_t TIMING; + + struct + { + __IOM uint32_t SCLL : 8; + __IOM uint32_t SCLH : 8; + __IOM uint32_t DATAHT : 4; + __IOM uint32_t DATAT : 4; + __IM uint32_t RESERVED1 : 4; + __IOM uint32_t TIMINGPSC : 4; + } TIMING_B; + } ; + + /* Status register 1*/ + union + { + __IOM uint32_t TIMEOUT; + + struct + { + __IOM uint32_t TIMEOUTA : 12; + __IOM uint32_t IDLECLKTO : 1; + __IM uint32_t RESERVED1 : 2; + __IOM uint32_t CLKTOEN : 1; + __IOM uint32_t TIMEOUTB : 12; + __IM uint32_t RESERVED2 : 3; + __IOM uint32_t EXCLKTOEN : 1; + } TIMEOUT_B; + } ; + + /* Interrupt and Status register*/ + union + { + __IOM uint32_t STS; + + struct + { + __IOM uint32_t TXBEFLG : 1; + __IOM uint32_t TXINTFLG : 1; + __IM uint32_t RXBNEFLG : 1; + __IM uint32_t ADDRMFLG : 1; + __IM uint32_t NACKFLG : 1; + __IM uint32_t STOPFLG : 1; + __IM uint32_t TXCFLG : 1; + __IM uint32_t TXCRFLG : 1; + __IM uint32_t BERRFLG : 1; + __IM uint32_t ALFLG : 1; + __IM uint32_t OVRURFLG : 1; + __IM uint32_t PECEFLG : 1; + __IM uint32_t TTEFLG : 1; + __IM uint32_t SMBALTFLG : 1; + __IM uint32_t RESERVED1 : 1; + __IM uint32_t BUSBSYFLG : 1; + __IM uint32_t TXDIRFLG : 1; + __IM uint32_t ADDRCMFLG : 7; + __IM uint32_t RESERVED2 : 8; + } STS_B; + } ; + + /* Interrupt clear register*/ + union + { + __OM uint32_t INTFCLR; + + struct + { + __IM uint32_t RESERVED1 : 3; + __OM uint32_t ADDRMCLR : 1; + __OM uint32_t NACKCLR : 1; + __OM uint32_t STOPCLR : 1; + __IM uint32_t RESERVED2 : 2; + __OM uint32_t BERRCLR : 1; + __OM uint32_t ALCLR : 1; + __OM uint32_t OVRURCLR : 1; + __OM uint32_t PECECLR : 1; + __OM uint32_t TTECLR : 1; + __OM uint32_t SMBALTCLR : 1; + __IM uint32_t RESERVED3 : 18; + } INTFCLR_B; + } ; + + /* PEC data register*/ + union + { + __IM uint32_t PEC; + + struct + { + __IM uint32_t PEC : 8; + __IM uint32_t RESERVED1 : 24; + } PEC_B; + } ; + + /* Receive data register*/ + union + { + __IM uint32_t RXDATA; + + struct + { + __IM uint32_t RXDATA : 8; + __IM uint32_t RESERVED1 : 24; + } RXDATA_B; + } ; + + /* Transmit data register*/ + union + { + __IOM uint32_t TXDATA; + + struct + { + __IOM uint32_t TXDATA : 8; + __IOM uint32_t RESERVED1 : 24; + } TXDATA_B; + } ; +} I2C_T; + +/** + * @brief Independent watchdog (IWDT) + */ + +typedef struct +{ + + /* Key register */ + union + { + __OM uint32_t KEY; + + struct + { + __OM uint32_t KEY : 16; + __IM uint32_t RESERVED1 : 16; + } KEY_B; + } ; + + /* Prescaler register */ + union + { + __IOM uint32_t PSC; + + struct + { + __IOM uint32_t PSC : 3; + __IM uint32_t RESERVED1 : 29; + } PSC_B; + } ; + + /* Counter reload register */ + union + { + __IOM uint32_t CNTRLD; + + struct + { + __IOM uint32_t CNTRLD : 12; + __IM uint32_t RESERVED1 : 20; + } CNTRLD_B; + } ; + + /* Status register */ + union + { + __IM uint32_t STS; + + struct + { + __IM uint32_t PSCUFLG : 1; + __IM uint32_t CNTUFLG : 1; + __IM uint32_t WINUFLG : 1; + __IM uint32_t RESERVED1 : 29; + } STS_B; + } ; + + /* Window register */ + union + { + __IOM uint32_t WIN; + + struct + { + __IOM uint32_t WIN : 12; + __IM uint32_t RESERVED1 : 20; + } WIN_B; + } ; +} IWDT_T; + +/** + * @brief Option bytes (OB) + */ + +typedef struct +{ + + /* Read protection option byte */ + union + { + __IOM uint16_t READPROT; + + struct + { + __IOM uint16_t READPROT : 8; + __IOM uint16_t nREADPROT : 8; + } READPORT_B; + } ; + + /* User protection option byte */ + union + { + __IOM uint16_t USER; + + struct + { + __IOM uint16_t WDTSEL : 1; + __IOM uint16_t RSTSTOP : 1; + __IOM uint16_t RSTSTDBY : 1; + __IM uint16_t RESERVED1 : 1; + __IOM uint16_t BOT1 : 1; + __IOM uint16_t VDDAMON : 1; + __IOM uint16_t RPC : 1; + __IM uint16_t RESERVED2 : 1; + __IOM uint16_t nUSER : 8; + } USER_B; + } ; + + /* User data option byte */ + union + { + __IOM uint16_t DATA0; + + struct + { + __IOM uint16_t DATA0 : 8; + __IOM uint16_t nDATA0 : 8; + } DATA0_B; + } ; + + /* User data option byte */ + union + { + __IOM uint16_t DATA1; + + struct + { + __IOM uint16_t DATA1 : 8; + __IOM uint16_t nDATA1 : 8; + } DATA1_B; + } ; + + /* Write protection option byte */ + union + { + __IOM uint16_t WRTPROT0; + + struct + { + __IOM uint16_t WRTPROT0 : 8; + __IOM uint16_t nWRTPROT0 : 8; + } WRTPROT0_B; + } ; + + /* Write protection option byte */ + union + { + __IOM uint16_t WRTPROT1; + + struct + { + __IOM uint16_t WRTPROT1 : 8; + __IOM uint16_t nWRTPROT1 : 8; + } WRTPROT1_B; + } ; +} OB_T; + +/** + * @brief Power control (PMU) + */ + +typedef struct +{ + /* power control register */ + union + { + __IOM uint32_t CTRL; + + struct + { + __IOM uint32_t LPDSCFG : 1; + __IOM uint32_t PDDSCFG : 1; + __IOM uint32_t WUFLGCLR : 1; + __IOM uint32_t SBFLGCLR : 1; + __IOM uint32_t PVDEN : 1; + __IOM uint32_t PLSEL : 3; + __IOM uint32_t BPWEN : 1; + __IM uint32_t RESERVED1 : 23; + + } CTRL_B; + } ; + + /* power control/status register */ + union + { + __IOM uint32_t CSTS; + + struct + { + __IM uint32_t WUEFLG : 1; + __IM uint32_t SBFLG : 1; + __IM uint32_t PVDOFLG : 1; + __IM uint32_t RESERVED1 : 5; + __IOM uint32_t WKUPCFG1 : 1; + __IOM uint32_t WKUPCFG2 : 1; + __IOM uint32_t WKUPCFG3 : 1; + __IOM uint32_t WKUPCFG4 : 1; + __IOM uint32_t WKUPCFG5 : 1; + __IOM uint32_t WKUPCFG6 : 1; + __IOM uint32_t WKUPCFG7 : 1; + __IOM uint32_t WKUPCFG8 : 1; + __IM uint32_t RESERVED2 : 16; + } CSTS_B; + } ; +} PMU_T; + +/** + * @brief Reset and clock control (RCM) + */ + +typedef struct +{ + /*Clock control register 1 */ + union + { + /* Clock control register */ + __IOM uint32_t CTRL1; + + struct + { + __IOM uint32_t HSIEN : 1; + __IM uint32_t HSIRDYFLG : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t HSITRM : 5; + __IM uint32_t HSICAL : 8; + __IOM uint32_t HSEEN : 1; + __IM uint32_t HSERDYFLG : 1; + __IOM uint32_t HSEBCFG : 1; + __IOM uint32_t CSSEN : 1; + __IM uint32_t RESERVED2 : 4; + __IOM uint32_t PLLEN : 1; + __IM uint32_t PLLRDYFLG : 1; + __IM uint32_t RESERVED3 : 6; + } CTRL1_B; + } ; + + /* Clock configuration register 1 */ + union + { + __IOM uint32_t CFG1; + + struct + { + __IOM uint32_t SCLKSEL : 2; + __IM uint32_t SCLKSWSTS : 2; + __IOM uint32_t AHBPSC : 4; + __IOM uint32_t APB1PSC : 3; + __IM uint32_t RESERVED1 : 3; + __IOM uint32_t ADCPSC : 1; + __IOM uint32_t PLLSRCSEL : 2; + __IOM uint32_t PLLHSEPSC : 1; + __IOM uint32_t PLLMULCFG : 4; + __IM uint32_t RESERVED3 : 2; + __IOM uint32_t MCOSEL : 4; + __IOM uint32_t MCOPSC : 3; + __IOM uint32_t MCOPLLPSC : 1; + } CFG1_B; + } ; + + /* Clock interrupt register */ + union + { + __IOM uint32_t INT; + + struct + { + __IM uint32_t LSIRDYFLG : 1; + __IM uint32_t LSERDYFLG : 1; + __IM uint32_t HSIRDYFLG : 1; + __IM uint32_t HSERDYFLG : 1; + __IM uint32_t PLLRDYFLG : 1; + __IM uint32_t HSI14RDYFLG : 1; + __IM uint32_t HSI48RDYFLG : 1; + __IM uint32_t CSSFLG : 1; + __IOM uint32_t LSIRDYEN : 1; + __IOM uint32_t LSERDYEN : 1; + __IOM uint32_t HSIRDYEN : 1; + __IOM uint32_t HSERDYEN : 1; + __IOM uint32_t PLLRDYEN : 1; + __IOM uint32_t HSI14RDYEN : 1; + __IOM uint32_t HSI48RDYEN : 1; + __IM uint32_t RESERVED1 : 1; + __OM uint32_t LSIRDYCLR : 1; + __OM uint32_t LSERDYCLR : 1; + __OM uint32_t HSIRDYCLR : 1; + __OM uint32_t HSERDYCLR : 1; + __OM uint32_t PLLRDYCLR : 1; + __OM uint32_t HSI14RDYCLR : 1; + __OM uint32_t HSI48RDYCLR : 1; + __OM uint32_t CSSCLR : 1; + __IM uint32_t RESERVED2 : 8; + } INT_B; + } ; + + /* APB2 peripheral reset register */ + union + { + __IOM uint32_t APBRST2; + + struct + { + __IOM uint32_t SYSCFGRST : 1; + __IM uint32_t RESERVED1 : 4; + __IOM uint32_t USART5RST : 1; + __IOM uint32_t USART6RST : 1; + __IOM uint32_t USART7RST : 1; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t ADCRST : 1; + __IM uint32_t RESERVED3 : 1; + __IOM uint32_t TMR1RST : 1; + __IOM uint32_t SPI1RST : 1; + __IM uint32_t RESERVED4 : 1; + __IOM uint32_t USART1RST : 1; + __IM uint32_t RESERVED5 : 1; + __IOM uint32_t TMR15RST : 1; + __IOM uint32_t TMR16RST : 1; + __IOM uint32_t TMR17RST : 1; + __IM uint32_t RESERVED6 : 3; + __IOM uint32_t DBGRST : 1; + __IM uint32_t RESERVED7 : 9; + } APBRST2_B; + } ; + + /*APB1 peripheral reset register */ + union + { + __IOM uint32_t APBRST1; + + struct + { + __IOM uint32_t TMR2RST : 1; + __IOM uint32_t TMR3RST : 1; + __IM uint32_t RESERVED1 : 2; + __IOM uint32_t TMR6RST : 1; + __IOM uint32_t TMR7RST : 1; + __IM uint32_t RESERVED2 : 2; + __IOM uint32_t TMR14RST : 1; + __IM uint32_t RESERVED3 : 2; + __IOM uint32_t WWDTRST : 1; + __IM uint32_t RESERVED4 : 2; + __IOM uint32_t SPI2RST : 1; + __IM uint32_t RESERVED5 : 2; + __IOM uint32_t USART2RST : 1; + __IOM uint32_t USART3RST : 1; + __IOM uint32_t USART4RST : 1; + __IOM uint32_t USART5RST : 1; + __IOM uint32_t I2C1RST : 1; + __IOM uint32_t I2C2RST : 1; + __IOM uint32_t USBDRST : 1; + __IM uint32_t RESERVED6 : 1; + __IOM uint32_t CANRST : 1; + __IM uint32_t RESERVED7 : 1; + __IOM uint32_t CRSRST : 1; + __IOM uint32_t PMURST : 1; + __IOM uint32_t DACRST : 1; + __IOM uint32_t CECRST : 1; + __IM uint32_t RESERVED8 : 1; + } APBRST1_B; + } ; + + /* AHB Peripheral Clock enable register */ + union + { + __IOM uint32_t AHBCLKEN; + + struct + { + __IOM uint32_t DMA1EN : 1; + __IOM uint32_t DMA2EN : 1; + __IOM uint32_t SRAMEN : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t FMCEN : 1; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t CRCEN : 1; + __IM uint32_t RESERVED3 : 10; + __IOM uint32_t PAEN : 1; + __IOM uint32_t PBEN : 1; + __IOM uint32_t PCEN : 1; + __IOM uint32_t PDEN : 1; + __IOM uint32_t PEEN : 1; + __IOM uint32_t PFEN : 1; + __IM uint32_t RESERVED4 : 1; + __IOM uint32_t TSCEN : 1; + __IM uint32_t RESERVED5 : 7; + } AHBCLKEN_B; + } ; + + union + { + __IOM uint32_t APBCLKEN2; + + struct + { + __IOM uint32_t SCFGCOMPEN : 1; + __IM uint32_t RESERVED1 : 4; + __IOM uint32_t USART6EN : 1; + __IOM uint32_t USART7EN : 1; + __IOM uint32_t USART8EN : 1; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t ADCEN : 1; + __IM uint32_t RESERVED3 : 1; + __IOM uint32_t TMR1EN : 1; + __IOM uint32_t SPI1EN : 1; + __IM uint32_t RESERVED4 : 1; + __IOM uint32_t USART1V : 1; + __IM uint32_t RESERVED5 : 1; + __IOM uint32_t TMR15EN : 1; + __IOM uint32_t TMR16EN : 1; + __IOM uint32_t TMR17EN : 1; + __IM uint32_t RESERVED6 : 3; + __IOM uint32_t DBGEN : 1; + __IM uint32_t RESERVED7 : 9; + } APBCLKEN2_B; + } ; + + /* APB1 peripheral clock enable register */ + union + { + __IOM uint32_t APBCLKEN1; + + struct + { + __IOM uint32_t TMR2EN : 1; + __IOM uint32_t TMR3EN : 1; + __IM uint32_t RESERVED1 : 2; + __IOM uint32_t TMR6EN : 1; + __IOM uint32_t TMR7EN : 1; + __IM uint32_t RESERVED2 : 2; + __IOM uint32_t TMR14EN : 1; + __IM uint32_t RESERVED3 : 2; + __IOM uint32_t WWDTEN : 1; + __IM uint32_t RESERVED4 : 2; + __IOM uint32_t SPI2EN : 1; + __IM uint32_t RESERVED5 : 2; + __IOM uint32_t USART2EN : 1; + __IOM uint32_t USART3EN : 1; + __IOM uint32_t USART4EN : 1; + __IOM uint32_t USART5EN : 1; + __IOM uint32_t I2C1EN : 1; + __IOM uint32_t I2C2EN : 1; + __IOM uint32_t USBDEN : 1; + __IM uint32_t RESERVED6 : 1; + __IOM uint32_t CANEN : 1; + __IM uint32_t RESERVED7 : 1; + __IOM uint32_t CRSEN : 1; + __IOM uint32_t PMUEN : 1; + __IOM uint32_t DACEN : 1; + __IOM uint32_t CECEN : 1; + __IM uint32_t RESERVED8 : 1; + } APBCLKEN1_B; + } ; + + /* Backup domain control register */ + union + { + __IOM uint32_t BDCTRL; + + struct + { + __IOM uint32_t LSEEN : 1; + __IM uint32_t LSERDYFLG : 1; + __IOM uint32_t LSEBCFG : 1; + __IOM uint32_t LSEDRVCFG : 2; + __IM uint32_t RESERVED1 : 3; + __IOM uint32_t RTCSRCSEL : 2; + __IM uint32_t RESERVED2 : 5; + __IOM uint32_t RTCCLKEN : 1; + __IOM uint32_t BDRST : 1; + __IM uint32_t RESERVED3 : 15; + } BDCTRL_B; + } ; + + /* Control/status register */ + union + { + __IOM uint32_t CSTS; + + struct + { + __IOM uint32_t LSIEN : 1; + __IM uint32_t LSIRDYFLG : 1; + __IM uint32_t RESERVED1 : 21; + __IM uint32_t PWRRSTFLG : 1; + __IOM uint32_t RSTFLGCLR : 1; + __IM uint32_t OBRSTFLG : 1; + __IM uint32_t PINRSTFLG : 1; + __IM uint32_t PODRSTFLG : 1; + __IM uint32_t SWRSTFLG : 1; + __IM uint32_t IWDTRSTFLG : 1; + __IM uint32_t WWDTRSTFLG : 1; + __IM uint32_t LPWRRSTFLG : 1; + } CSTS_B; + } ; + + /* AHB peripheral reset register */ + union + { + __IOM uint32_t AHBRST; + + struct + { + __IM uint32_t RESERVED1 : 17; + __IOM uint32_t PARST : 1; + __IOM uint32_t PBRST : 1; + __IOM uint32_t PCRST : 1; + __IOM uint32_t PDRST : 1; + __IOM uint32_t PERST : 1; + __IOM uint32_t PFRST : 1; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t TSCRST : 1; + __IM uint32_t RESERVED3 : 7; + } AHBRST_B; + } ; + + /* Clock configuration register 2 */ + union + { + __IOM uint32_t CFG2; + + struct + { + __IOM uint32_t PLLDIVCFG : 4; + __IM uint32_t RESERVED1 : 28; + } CFG2_B; + } ; + + /*Clock configuration register 3 */ + union + { + __IOM uint32_t CFG3; + + struct + { + __IOM uint32_t USART1SEL : 2; + __IM uint32_t RESERVED1 : 2; + __IOM uint32_t I2C1SEL : 1; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t CECSEL : 1; + __IOM uint32_t USBDSEL : 1; + __IOM uint32_t ADCSEL : 1; + __IM uint32_t RESERVED3 : 7; + __IOM uint32_t USART2SEL : 2; + __IOM uint32_t USART3SEL : 2; + __IM uint32_t RESERVED4 : 12; + } CFG3_B; + } ; + + union + { + __IOM uint32_t CTRL2; + + struct + { + __IOM uint32_t HSI14EN : 1; + __IM uint32_t HSI14RDFLG : 1; + __IOM uint32_t HSI14TO : 1; + __IOM uint32_t HSI14TRM : 5; + __IM uint32_t HSI14CAL : 8; + __IOM uint32_t HSI48EN : 1; + __IM uint32_t HSI48RDFLG : 1; + __IM uint32_t RESERVED1 : 6; + __IM uint32_t HSI48CAL : 8; + } CTRL2_B; + } ; +} RCM_T; + +/** + * @brief Real-time clock (RTC) + */ + +typedef struct +{ + + /* time register */ + union + { + __IOM uint32_t TIME; + + struct + { + __IOM uint32_t SECU : 4; + __IOM uint32_t SECT : 3; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t MINU : 4; + __IOM uint32_t MINT : 3; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t HRU : 4; + __IOM uint32_t HRT : 2; + __IOM uint32_t TIMEFCFG : 1; + __IM uint32_t RESERVED3 : 9; + } TIME_B; + } ; + + /* date register */ + union + { + __IOM uint32_t DATE; + + struct + { + __IOM uint32_t DAYU : 4; + __IOM uint32_t DAYT : 2; + __IM uint32_t RESERVED1 : 2; + __IOM uint32_t MONU : 4; + __IOM uint32_t MONT : 1; + __IOM uint32_t WEEKSEL : 3; + __IOM uint32_t YRU : 4; + __IOM uint32_t YRT : 4; + __IM uint32_t RESERVED2 : 8; + } DATE_B; + } ; + + /* control register */ + union + { + __IOM uint32_t CTRL; + + struct + { + __IOM uint32_t WUCLKSEL : 3; + __IOM uint32_t TSETECFG : 1; + __IOM uint32_t RCLKDEN : 1; + __IOM uint32_t RCMCFG : 1; + __IOM uint32_t TIMEFCFG : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t ALREN : 1; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t WUTEN : 1; + __IOM uint32_t TSEN : 1; + __IOM uint32_t ALRIEN : 1; + __IM uint32_t RESERVED3 : 1; + __IOM uint32_t WUTIEN : 1; + __IOM uint32_t TSIEN : 1; + __OM uint32_t STCCFG : 1; + __OM uint32_t WTCCFG : 1; + __IOM uint32_t BAKP : 1; + __IOM uint32_t CALOSEL : 1; + __IOM uint32_t POLCFG : 1; + __IOM uint32_t OUTSEL : 2; + __IOM uint32_t CALOEN : 1; + __IM uint32_t RESERVED4 : 8; + } CTRL_B; + } ; + + /* initialization and status register */ + union + { + __IOM uint32_t STS; + + struct + { + __IM uint32_t ALRWFLG : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t WUTWFLG : 1; + __IOM uint32_t SOPFLG : 1; + __IM uint32_t INITSFLG : 1; + __IOM uint32_t RSFLG : 1; + __IM uint32_t RINITFLG : 1; + __IOM uint32_t INITEN : 1; + __IOM uint32_t ALRAFLG : 1; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t WUTFLG : 1; + __IOM uint32_t TSFLG : 1; + __IOM uint32_t TSOVRFLG : 1; + __IOM uint32_t TP1FLG : 1; + __IOM uint32_t TP2FLG : 1; + __IM uint32_t TP3FLG : 1; + __IM uint32_t RCALPFLG : 1; + __IM uint32_t RESERVED3 : 15; + } STS_B; + } ; + + /* prescaler register */ + union + { + __IOM uint32_t PSC; + + struct + { + __IOM uint32_t SPSC : 15; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t APSC : 7; + __IM uint32_t RESERVED2 : 9; + } PSC_B; + } ; + + /* auto-reload register */ + union + { + __OM uint32_t AUTORLD; + + struct + { + __OM uint32_t WUAUTORE : 15; + __IM uint32_t RESERVED1 : 17; + } AUTORLD_B; + } ; + __IM uint32_t RESERVED; + + /* alarm A register */ + union + { + __IOM uint32_t ALRMA; + + struct + { + __IOM uint32_t SECU : 4; + __IOM uint32_t SECT : 3; + __IOM uint32_t SECMEN : 1; + __IOM uint32_t MINU : 4; + __IOM uint32_t MINT : 3; + __IOM uint32_t MINMEN : 1; + __IOM uint32_t HRU : 4; + __IOM uint32_t HRT : 2; + __IOM uint32_t TIMEFCFG : 1; + __IOM uint32_t HRMEN : 1; + __IOM uint32_t DAYU : 4; + __IOM uint32_t DAYT : 2; + __IOM uint32_t WEEKSEL : 1; + __IOM uint32_t DATEMEN : 1; + } ALRMA_B; + } ; + + __IM uint32_t RESERVED1; + + /* write protection register */ + union + { + __OM uint32_t WRPROT; + + struct + { + __OM uint32_t KEY : 8; + __IM uint32_t RESERVED1 : 24; + } WRPROT_B; + } ; + + /* sub second register */ + union + { + __IM uint32_t SUBSEC; + + struct + { + __IM uint32_t SUBSEC : 16; + __IM uint32_t RESERVED1 : 16; + } SUBSEC_B; + } ; + + /* shift control register */ + union + { + __OM uint32_t SHIFT; + + struct + { + __OM uint32_t SFSEC : 15; + __IM uint32_t RESERVED1 : 16; + __OM uint32_t ADD1SECEN : 1; + } SHIFT_B; + } ; + + /* timestamp time register */ + union + { + __IM uint32_t TSTIME; + + struct + { + __IM uint32_t SECU : 4; + __IM uint32_t SECT : 3; + __IM uint32_t RESERVED1 : 1; + __IM uint32_t MINU : 4; + __IM uint32_t MINT : 3; + __IM uint32_t RESERVED2 : 1; + __IM uint32_t HRU : 4; + __IM uint32_t HRT : 2; + __IM uint32_t TIMEFCFG : 1; + __IM uint32_t RESERVED3 : 9; + } TSTIME_B; + } ; + + /* timestamp date register */ + union + { + __IM uint32_t TSDATE; + + struct + { + __IM uint32_t DAYU : 4; + __IM uint32_t DAYT : 2; + __IM uint32_t RESERVED1 : 2; + __IM uint32_t MONU : 4; + __IM uint32_t MONT : 1; + __IM uint32_t WEEKSEL : 3; + __IM uint32_t RESERVED2 : 16; + } TSDATE_B; + } ; + + /* time-stamp sub second register */ + union + { + __IM uint32_t TSSUBSEC; + + struct + { + __IM uint32_t SUBSEC : 16; + __IM uint32_t RESERVED1 : 16; + } TSSUBSEC_B; + } ; + + /* calibration register */ + union + { + __IOM uint32_t CAL; + + struct + { + __IOM uint32_t RECALF : 9; + __IM uint32_t RESERVED1 : 4; + __IOM uint32_t CAL16CFG : 1; + __IOM uint32_t CAL8CFG : 1; + __IOM uint32_t ICALFEN : 1; + __IM uint32_t RESERVED2 : 16; + } CAL_B; + } ; + + /* tamper and alternate function configuration register */ + union + { + __IOM uint32_t TACFG; + + struct + { + __IOM uint32_t TP1EN : 1; + __IOM uint32_t TP1ALCFG : 1; + __IOM uint32_t TPIEN : 1; + __IOM uint32_t TP2EN : 1; + __IOM uint32_t TP2ALCFG : 1; + __IOM uint32_t TP3EN : 1; + __IOM uint32_t TP3ALCFG : 1; + __IOM uint32_t TPTSEN : 1; + __IOM uint32_t TPSFSEL : 3; + __IOM uint32_t TPFCSEL : 2; + __IOM uint32_t TPPRDUSEL : 2; + __IOM uint32_t TPPUDIS : 1; + __IM uint32_t RESERVED1 : 2; + __IOM uint32_t PC13VAL : 1; + __IOM uint32_t PC13EN : 1; + __IOM uint32_t PC14VAL : 1; + __IOM uint32_t PC14EN : 1; + __IOM uint32_t PC15VAL : 1; + __IOM uint32_t PC15EN : 1; + __IM uint32_t RESERVED2 : 8; + } TACFG_B; + } ; + + /* alarm A sub second register */ + union + { + __IOM uint32_t ALRMASS; + + struct + { + __IOM uint32_t SUBSEC : 15; + __IM uint32_t RESERVED1 : 9; + __IOM uint32_t MASKSEL : 4; + __IM uint32_t RESERVED2 : 4; + } ALRMASS_B; + } ; + + __IM uint32_t RESERVED2[2]; + + union + { + __IOM uint32_t BAKP0; + + struct + { + __IOM uint32_t BAKP : 32; + } BAKP0_B; + } ; + + union + { + __IOM uint32_t BAKP1; + + struct + { + __IOM uint32_t BAKP : 32; + } BAKP1_B; + } ; + union + { + __IOM uint32_t BAKP2; + + struct + { + __IOM uint32_t BAKP : 32; + } BAKP2_B; + } ; + union + { + __IOM uint32_t BAKP3; + + struct + { + __IOM uint32_t BAKP : 32; + } BAKP3_B; + } ; + union + { + __IOM uint32_t BAKP4; + + struct + { + __IOM uint32_t BAKP : 32; + } BAKP4_B; + } ; +} RTC_T; + +/** + * @brief Serial peripheral interface (SPI1) + */ + +typedef struct +{ + /* control register 1 */ + union + { + __IOM uint32_t CTRL1; + + struct + { + __IOM uint32_t CPHA : 1; + __IOM uint32_t CPOL : 1; + __IOM uint32_t MSMCFG : 1; + __IOM uint32_t BRSEL : 3; + __IOM uint32_t SPIEN : 1; + __IOM uint32_t LSBSEL : 1; + __IOM uint32_t ISSEL : 1; + __IOM uint32_t SSEN : 1; + __IOM uint32_t RXOMEN : 1; + __IOM uint32_t CRCLSEL : 1; + __IOM uint32_t CRCNXT : 1; + __IOM uint32_t CRCEN : 1; + __IOM uint32_t BMOEN : 1; + __IOM uint32_t BMEN : 1; + __IM uint32_t RESERVED1 : 16; + } CTRL1_B; + } ; + + /* control register 2 */ + union + { + __IOM uint32_t CTRL2; + + struct + { + __IOM uint32_t RXDEN : 1; + __IOM uint32_t TXDEN : 1; + __IOM uint32_t SSOEN : 1; + __IOM uint32_t NSSPEN : 1; + __IOM uint32_t FRFCFG : 1; + __IOM uint32_t ERRIEN : 1; + __IOM uint32_t RXBNEIEN : 1; + __IOM uint32_t TXBEIEN : 1; + __IOM uint32_t DSCFG : 4; + __IOM uint32_t FRTCFG : 1; + __IOM uint32_t LDRX : 1; + __IOM uint32_t LDTX : 1; + __IM uint32_t RESERVED1 : 17; + } CTRL2_B; + } ; + + /* status register */ + union + { + __IOM uint32_t STS; + + struct + { + __IM uint32_t RXBNEFLG : 1; + __IM uint32_t TXBEFLG : 1; + __IM uint32_t SCHDIR : 1; + __IM uint32_t UDRFLG : 1; + __IOM uint32_t CRCEFLG : 1; + __IM uint32_t MEFLG : 1; + __IM uint32_t OVRFLG : 1; + __IM uint32_t BSYFLG : 1; + __IM uint32_t FRECFG : 1; + __IM uint32_t FRLSEL : 2; + __IM uint32_t FTLSEL : 2; + __IM uint32_t RESERVED1 : 19; + } STS_B; + } ; + + /* data register */ + union + { + __IOM uint32_t DATA; + + struct + { + __IOM uint32_t DATA : 16; + __IM uint32_t RESERVED1 : 16; + } DATA_B; + } ; + + /* CRC polynomial register */ + union + { + __IOM uint32_t CRCPOLY; + + struct + { + __IOM uint32_t CRCPOLY : 16; + __IM uint32_t RESERVED1 : 16; + } CRCPOLY_B; + } ; + + /*RX CRC register */ + union + { + + __IM uint32_t RXCRC; + + struct + { + __IM uint32_t RXCRC : 16; + __IM uint32_t RESERVED1 : 16; + } RXCRC_B; + } ; + + /* TX CRC register */ + union + { + + __IM uint32_t TXCRC; + + struct + { + __IM uint32_t TXCRC : 16; + __IM uint32_t RESERVED1 : 16; + } TXCRC_B; + } ; + + /* I2S CFG register */ + union + { + __IOM uint32_t I2SCFG; + + struct + { + __IOM uint32_t CHLEN : 1; + __IOM uint32_t DATALEN : 2; + __IOM uint32_t CPOL : 1; + __IOM uint32_t I2SSSEL : 2; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t PFSSEL : 1; + __IOM uint32_t I2SMOD : 2; + __IOM uint32_t I2SEN : 1; + __IOM uint32_t MODESEL : 1; + __IM uint32_t RESERVED2 : 20; + } I2SCFG_B; + } ; + + /* I2S Prescaler */ + union + { + __IOM uint32_t I2SPSC; + + struct + { + __IOM uint32_t I2SPSC : 8; + __IOM uint32_t ODDPSC : 1; + __IOM uint32_t MCOEN : 1; + __IM uint32_t RESERVED1 : 22; + } I2SPSC_B; + } ; +} SPI_T; + +/** + * @brief System configuration controller (SYSCFG) + */ + +typedef struct +{ + /* configuration register 1 */ + union + { + __IOM uint32_t CFG1; + + struct + { + __IOM uint32_t MMSEL : 2; + __IM uint32_t RESERVED1 : 4; + __IOM uint32_t IRSEL : 2; + __IOM uint32_t ADCDMARMP : 1; + __IOM uint32_t USART1TXRMP : 1; + __IOM uint32_t USART1RXRMP : 1; + __IOM uint32_t TMR16DMARMP : 1; + __IOM uint32_t TMR17DMARMP : 1; + __IOM uint32_t TMR16DMARMP2 : 1; + __IOM uint32_t TMR17DMARMP2 : 1; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t I2CPB6FMP : 1; + __IOM uint32_t I2CPB7FMP : 1; + __IOM uint32_t I2CPB8FMP : 1; + __IOM uint32_t I2CPB9FMP : 1; + __IOM uint32_t I2C1FMP : 1; + __IOM uint32_t I2C2FMP : 1; + __IOM uint32_t I2CPA9FMP : 1; + __IOM uint32_t I2CPA10FMP : 1; + __IOM uint32_t SPI2DMARMP : 1; + __IOM uint32_t USART2DMARMP : 1; + __IOM uint32_t USART3DMARMP : 1; + __IOM uint32_t I2C1DMARMP : 1; + __IOM uint32_t TMR1DMARMP : 1; + __IOM uint32_t TMR2DMARMP : 1; + __IOM uint32_t TMR3DMARMP : 1; + __IM uint32_t RESERVED3 : 1; + } CFG1_B; + } ; + __IM uint32_t RESERVED; + + /* external interrupt configuration register 1 */ + union + { + + __IOM uint32_t EINTCFG1; + + struct + { + __IOM uint32_t EINT0 : 4; + __IOM uint32_t EINT1 : 4; + __IOM uint32_t EINT2 : 4; + __IOM uint32_t EINT3 : 4; + __IM uint32_t RESERVED1 : 16; + } EINTCFG1_B; + } ; + + /* external interrupt configuration register 2 */ + union + { + __IOM uint32_t EINTCFG2; + + struct + { + __IOM uint32_t EINT4 : 4; + __IOM uint32_t EINT5 : 4; + __IOM uint32_t EINT6 : 4; + __IOM uint32_t EINT7 : 4; + __IM uint32_t RESERVED1 : 16; + } EINTCFG2_B; + } ; + + /* external interrupt configuration register 3 */ + union + { + __IOM uint32_t EINTCFG3; + + struct + { + __IOM uint32_t EINT8 : 4; + __IOM uint32_t EINT9 : 4; + __IOM uint32_t EINT10 : 4; + __IOM uint32_t EINT11 : 4; + __IM uint32_t RESERVED1 : 16; + } EINTCFG3_B; + } ; + + /* external interrupt configuration register 4 */ + union + { + __IOM uint32_t EINTCFG4; + + struct + { + __IOM uint32_t EINT12 : 4; + __IOM uint32_t EINT13 : 4; + __IOM uint32_t EINT14 : 4; + __IOM uint32_t EINT15 : 4; + __IM uint32_t RESERVED1 : 16; + } EINTCFG4_B; + } ; + + /* configuration register 2 */ + union + { + __IOM uint32_t CFG2; + + struct + { + __IOM uint32_t LOCK : 1; + __IOM uint32_t SRAMLOCK : 1; + __IOM uint32_t PVDLOCK : 1; + __IM uint32_t RESERVED1 : 5; + __IOM uint32_t SRAMEFLG : 1; + __IM uint32_t RESERVED2 : 23; + } CFG2_B; + } ; +} SYSCFG_T; + +/** + * @brief Touch sensing controller (TSC) + */ + +typedef struct +{ + /* I/O group 1~8 counter register */ + union + { + __IM uint32_t IOGCNT; + + struct + { + __IM uint32_t CNTVAL : 14; + __IM uint32_t RESERVED1 : 18; + } IOGCNT_B; + }; +} TSC_IOGroupRegister_T; + +typedef struct +{ + /* configuration register */ + union + { + __IOM uint32_t CTRL; + + struct + { + __IOM uint32_t TSCEN : 1; + __IOM uint32_t STARTAFLG : 1; + __IOM uint32_t AMCFG : 1; + __IOM uint32_t SYNPPOL : 1; + __IOM uint32_t IODEFCFG : 1; + __IOM uint32_t MCNTVSEL : 3; + __IM uint32_t RESERVED1 : 4; + __IOM uint32_t PGCDFSEL : 3; + __IOM uint32_t SSCDFSEL : 1; + __IOM uint32_t SSEN : 1; + __IOM uint32_t SSERRVSEL : 7; + __IOM uint32_t CTPLSEL : 4; + __IOM uint32_t CTPHSEL : 4; + } CTRL_B; + } ; + + /* interrupt enable register */ + union + { + __IOM uint32_t INTEN; + + struct + { + __IOM uint32_t EOAIEN : 1; + __IOM uint32_t MCEIEN : 1; + __IM uint32_t RESERVED1 : 30; + } INTEN_B; + } ; + + /* interrupt clear register */ + union + { + __IOM uint32_t INTFCLR; + + struct + { + __IOM uint32_t EOAICLR : 1; + __IOM uint32_t MCEICLR : 1; + __IM uint32_t RESERVED1 : 30; + } INTFCLR_B; + } ; + + /* interrupt status register */ + union + { + __IOM uint32_t INTSTS; + + struct + { + __IOM uint32_t EOAFLG : 1; + __IOM uint32_t MCEFLG : 1; + __IM uint32_t RESERVED1 : 30; + } INTSTS_B; + } ; + + /* I/O hysteresis control register */ + union + { + __IOM uint32_t IOHCTRL; + + struct + { + __IOM uint32_t G1P1 : 1; + __IOM uint32_t G1P2 : 1; + __IOM uint32_t G1P3 : 1; + __IOM uint32_t G1P4 : 1; + __IOM uint32_t G2P1 : 1; + __IOM uint32_t G2P2 : 1; + __IOM uint32_t G2P3 : 1; + __IOM uint32_t G2P4 : 1; + __IOM uint32_t G3P1 : 1; + __IOM uint32_t G3P2 : 1; + __IOM uint32_t G3P3 : 1; + __IOM uint32_t G3P4 : 1; + __IOM uint32_t G4P1 : 1; + __IOM uint32_t G4P2 : 1; + __IOM uint32_t G4P3 : 1; + __IOM uint32_t G4P4 : 1; + __IOM uint32_t G5P1 : 1; + __IOM uint32_t G5P2 : 1; + __IOM uint32_t G5P3 : 1; + __IOM uint32_t G5P4 : 1; + __IOM uint32_t G6P1 : 1; + __IOM uint32_t G6P2 : 1; + __IOM uint32_t G6P3 : 1; + __IOM uint32_t G6P4 : 1; + __IM uint32_t RESERVED1 : 8; + } IOHCTRL_B; + } ; + __IM uint32_t RESERVED; + + /* I/O analog switch control register */ + union + { + __IOM uint32_t IOASWCTRL; + + struct + { + __IOM uint32_t G1P1 : 1; + __IOM uint32_t G1P2 : 1; + __IOM uint32_t G1P3 : 1; + __IOM uint32_t G1P4 : 1; + __IOM uint32_t G2P1 : 1; + __IOM uint32_t G2P2 : 1; + __IOM uint32_t G2P3 : 1; + __IOM uint32_t G2P4 : 1; + __IOM uint32_t G3P1 : 1; + __IOM uint32_t G3P2 : 1; + __IOM uint32_t G3P3 : 1; + __IOM uint32_t G3P4 : 1; + __IOM uint32_t G4P1 : 1; + __IOM uint32_t G4P2 : 1; + __IOM uint32_t G4P3 : 1; + __IOM uint32_t G4P4 : 1; + __IOM uint32_t G5P1 : 1; + __IOM uint32_t G5P2 : 1; + __IOM uint32_t G5P3 : 1; + __IOM uint32_t G5P4 : 1; + __IOM uint32_t G6P1 : 1; + __IOM uint32_t G6P2 : 1; + __IOM uint32_t G6P3 : 1; + __IOM uint32_t G6P4 : 1; + __IM uint32_t RESERVED1 : 8; + } IOASWCTRL_B; + } ; + __IM uint32_t RESERVED1; + + /* I/O sampling control register */ + union + { + __IOM uint32_t IOSMPCTRL; + + struct + { + __IOM uint32_t G1P1 : 1; + __IOM uint32_t G1P2 : 1; + __IOM uint32_t G1P3 : 1; + __IOM uint32_t G1P4 : 1; + __IOM uint32_t G2P1 : 1; + __IOM uint32_t G2P2 : 1; + __IOM uint32_t G2P3 : 1; + __IOM uint32_t G2P4 : 1; + __IOM uint32_t G3P1 : 1; + __IOM uint32_t G3P2 : 1; + __IOM uint32_t G3P3 : 1; + __IOM uint32_t G3P4 : 1; + __IOM uint32_t G4P1 : 1; + __IOM uint32_t G4P2 : 1; + __IOM uint32_t G4P3 : 1; + __IOM uint32_t G4P4 : 1; + __IOM uint32_t G5P1 : 1; + __IOM uint32_t G5P2 : 1; + __IOM uint32_t G5P3 : 1; + __IOM uint32_t G5P4 : 1; + __IOM uint32_t G6P1 : 1; + __IOM uint32_t G6P2 : 1; + __IOM uint32_t G6P3 : 1; + __IOM uint32_t G6P4 : 1; + __IM uint32_t RESERVED1 : 8; + } IOSMPCTRL_B; + } ; + __IM uint32_t RESERVED2; + + /* I/O channel control register */ + union + { + __IOM uint32_t IOCHCTRL; + + struct + { + __IOM uint32_t G1P1 : 1; + __IOM uint32_t G1P2 : 1; + __IOM uint32_t G1P3 : 1; + __IOM uint32_t G1P4 : 1; + __IOM uint32_t G2P1 : 1; + __IOM uint32_t G2P2 : 1; + __IOM uint32_t G2P3 : 1; + __IOM uint32_t G2P4 : 1; + __IOM uint32_t G3P1 : 1; + __IOM uint32_t G3P2 : 1; + __IOM uint32_t G3P3 : 1; + __IOM uint32_t G3P4 : 1; + __IOM uint32_t G4P1 : 1; + __IOM uint32_t G4P2 : 1; + __IOM uint32_t G4P3 : 1; + __IOM uint32_t G4P4 : 1; + __IOM uint32_t G5P1 : 1; + __IOM uint32_t G5P2 : 1; + __IOM uint32_t G5P3 : 1; + __IOM uint32_t G5P4 : 1; + __IOM uint32_t G6P1 : 1; + __IOM uint32_t G6P2 : 1; + __IOM uint32_t G6P3 : 1; + __IOM uint32_t G6P4 : 1; + __IM uint32_t RESERVED1 : 8; + } IOCHCTRL_B; + } ; + __IM uint32_t RESERVED3; + + /* I/O group control status register */ + union + { + __IOM uint32_t IOGCSTS; + + struct + { + __IOM uint32_t G1EN : 1; + __IOM uint32_t G2EN : 1; + __IOM uint32_t G3EN : 1; + __IOM uint32_t G4EN : 1; + __IOM uint32_t G5EN : 1; + __IOM uint32_t G6EN : 1; + __IOM uint32_t G7EN : 1; + __IOM uint32_t G8EN : 1; + __IM uint32_t RESERVED1 : 8; + __IM uint32_t G1STS : 1; + __IM uint32_t G2STS : 1; + __IM uint32_t G3STS : 1; + __IM uint32_t G4STS : 1; + __IM uint32_t G5STS : 1; + __IM uint32_t G6STS : 1; + __IM uint32_t G7STS : 1; + __IM uint32_t G8STS : 1; + __IM uint32_t RESERVED2 : 8; + } IOGCSTS_B; + } ; + + TSC_IOGroupRegister_T IOGxCNT[8]; +} TSC_T; + +/** + * @brief Advanced-timers (TMR1) + */ + +typedef struct +{ + /* control register 1 */ + union + { + __IOM uint32_t CTRL1; + + struct + { + __IOM uint32_t CNTEN : 1; + __IOM uint32_t UD : 1; + __IOM uint32_t URSSEL : 1; + __IOM uint32_t SPMEN : 1; + __IOM uint32_t CNTDIR : 1; + __IOM uint32_t CAMSEL : 2; + __IOM uint32_t ARPEN : 1; + __IOM uint32_t CLKDIV : 2; + __IM uint32_t RESERVED1 : 22; + } CTRL1_B; + } ; + + /* control register 2 */ + union + { + __IOM uint32_t CTRL2; + + struct + { + __IOM uint32_t CCPEN : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t CCUSEL : 1; + __IOM uint32_t CCDSEL : 1; + __IOM uint32_t MMSEL : 3; + __IOM uint32_t TI1SEL : 1; + __IOM uint32_t OC1OIS : 1; + __IOM uint32_t OC1NOIS : 1; + __IOM uint32_t OC2OIS : 1; + __IOM uint32_t OC2NOIS : 1; + __IOM uint32_t OC3OIS : 1; + __IOM uint32_t OC3NOIS : 1; + __IOM uint32_t OC4OIS : 1; + __IM uint32_t RESERVED2 : 17; + } CTRL2_B; + } ; + + /* slave mode control register */ + union + { + __IOM uint32_t SMCTRL; + + struct + { + __IOM uint32_t SMFSEL : 3; + __IOM uint32_t OCCSEL : 1; + __IOM uint32_t TRGSEL : 3; + __IOM uint32_t MSMEN : 1; + __IOM uint32_t ETFCFG : 4; + __IOM uint32_t ETPCFG : 2; + __IOM uint32_t ECEN : 1; + __IOM uint32_t ETPOL : 1; + __IM uint32_t RESERVED1 : 16; + } SMCTRL_B; + } ; + + /* DMA/Interrupt enable register */ + union + { + __IOM uint32_t DIEN; + + struct + { + __IOM uint32_t UIEN : 1; + __IOM uint32_t CC1IEN : 1; + __IOM uint32_t CC2IEN : 1; + __IOM uint32_t CC3IEN : 1; + __IOM uint32_t CC4IEN : 1; + __IOM uint32_t COMIEN : 1; + __IOM uint32_t TRGIEN : 1; + __IOM uint32_t BRKIEN : 1; + __IOM uint32_t UDIEN : 1; + __IOM uint32_t CC1DEN : 1; + __IOM uint32_t CC2DEN : 1; + __IOM uint32_t CC3DEN : 1; + __IOM uint32_t CC4DEN : 1; + __IOM uint32_t COMDEN : 1; + __IOM uint32_t TRGDEN : 1; + __IM uint32_t RESERVED1 : 17; + } DIEN_B; + } ; + + /* status register */ + union + { + __IOM uint32_t STS; + + struct + { + __IOM uint32_t UIFLG : 1; + __IOM uint32_t CC1IFLG : 1; + __IOM uint32_t CC2IFLG : 1; + __IOM uint32_t CC3IFLG : 1; + __IOM uint32_t CC4IFLG : 1; + __IOM uint32_t COMIFLG : 1; + __IOM uint32_t TRGIFLG : 1; + __IOM uint32_t BRKIFLG : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t CC1RCFLG : 1; + __IOM uint32_t CC2RCFLG : 1; + __IOM uint32_t CC3RCFLG : 1; + __IOM uint32_t CC4RCFLG : 1; + __IM uint32_t RESERVED2 : 19; + } STS_B; + } ; + + /* event generation register */ + union + { + __OM uint32_t CEG; + + struct + { + __OM uint32_t UEG : 1; + __OM uint32_t CC1EG : 1; + __OM uint32_t CC2EG : 1; + __OM uint32_t CC3EG : 1; + __OM uint32_t CC4EG : 1; + __OM uint32_t COMG : 1; + __OM uint32_t TEG : 1; + __OM uint32_t BEG : 1; + __IM uint32_t RESERVED1 : 24; + } CEG_B; + } ; + + union + { + /* capture/compare mode register (output mode) */ + union + { + __IOM uint32_t CCM1_OUTPUT; + + struct + { + __IOM uint32_t CC1SEL : 2; + __IOM uint32_t OC1FEN : 1; + __IOM uint32_t OC1PEN : 1; + __IOM uint32_t OC1MOD : 3; + __IOM uint32_t OC1CEN : 1; + __IOM uint32_t CC2SEL : 2; + __IOM uint32_t OC2FEN : 1; + __IOM uint32_t OC2PEN : 1; + __IOM uint32_t OC2MOD : 3; + __IOM uint32_t OC2CEN : 1; + __IM uint32_t RESERVED1 : 16; + } CCM1_OUTPUT_B; + } ; + + /* capture/compare mode register 1 (input mode) */ + union + { + __IOM uint32_t CCM1_INPUT; + + struct + { + __IOM uint32_t CC1SEL : 2; + __IOM uint32_t IC1PSC : 2; + __IOM uint32_t IC1F : 4; + __IOM uint32_t CC2SEL : 2; + __IOM uint32_t IC2PSC : 2; + __IOM uint32_t IC2F : 4; + __IM uint32_t RESERVED1 : 16; + } CCM1_INPUT_B; + } ; + }; + + union + { + /* capture/compare mode register (output mode) */ + union + { + __IOM uint32_t CCM2_OUTPUT; + + struct + { + __IOM uint32_t CC3SEL : 2; + __IOM uint32_t OC3FEN : 1; + __IOM uint32_t OC3PEN : 1; + __IOM uint32_t OC3MOD : 3; + __IOM uint32_t OC3CEN : 1; + __IOM uint32_t CC4SEL : 2; + __IOM uint32_t OC4FEN : 1; + __IOM uint32_t OC4PEN : 1; + __IOM uint32_t OC4MOD : 3; + __IOM uint32_t OC4CEN : 1; + __IM uint32_t RESERVED1 : 16; + } CCM2_OUTPUT_B; + } ; + + /* capture/compare mode register 2 (input mode) */ + union + { + __IOM uint32_t CCM2_INPUT; + + struct + { + __IOM uint32_t CC3SEL : 2; + __IOM uint32_t IC3PSC : 2; + __IOM uint32_t IC3F : 4; + __IOM uint32_t CC4SEL : 2; + __IOM uint32_t IC4PSC : 2; + __IOM uint32_t IC4F : 4; + __IM uint32_t RESERVED1 : 16; + } CCM2_INPUT_B; + } ; + }; + + /* capture/compare enable register */ + union + { + __IOM uint32_t CCEN; + + struct + { + __IOM uint32_t CC1EN : 1; + __IOM uint32_t CC1POL : 1; + __IOM uint32_t CC1NEN : 1; + __IOM uint32_t CC1NPOL : 1; + __IOM uint32_t CC2EN : 1; + __IOM uint32_t CC2POL : 1; + __IOM uint32_t CC2NEN : 1; + __IOM uint32_t CC2NPOL : 1; + __IOM uint32_t CC3EN : 1; + __IOM uint32_t CC3POL : 1; + __IOM uint32_t CC3NEN : 1; + __IOM uint32_t CC3NPOL : 1; + __IOM uint32_t CC4EN : 1; + __IOM uint32_t CC4POL : 1; + __IM uint32_t RESERVED1 : 18; + } CCEN_B; + } ; + + /* counter */ + union + { + __IOM uint32_t CNT; + + struct + { + __IOM uint32_t CNT : 32; + } CNT_B; + } ; + + /* prescaler */ + union + { + __IOM uint32_t PSC; + + struct + { + __IOM uint32_t PSC : 16; + __IM uint32_t RESERVED1 : 16; + } PSC_B; + } ; + + /* auto-reload register */ + union + { + __IOM uint32_t AUTORLD; + + struct + { + __IOM uint32_t AUTORLD : 32; + } AUTORLD_B; + } ; + + /* repetition counter register */ + union + { + __IOM uint32_t REPCNT; + + struct + { + __IOM uint32_t REPCNT : 8; + __IM uint32_t RESERVED1 : 24; + } REPCNT_B; + } ; + + /* capture/compare register 1 */ + union + { + __IOM uint32_t CC1; + + struct + { + __IOM uint32_t CC1 : 32; + } CC1_B; + } ; + + /* capture/compare register 2 */ + union + { + __IOM uint32_t CC2; + + struct + { + __IOM uint32_t CC2 : 32; + } CC2_B; + } ; + + /* capture/compare register 3 */ + union + { + __IOM uint32_t CC3; + + struct + { + __IOM uint32_t CC3 : 32; + } CC3_B; + } ; + + /* capture/compare register 4 */ + union + { + __IOM uint32_t CC4; + + struct + { + __IOM uint32_t CC4 : 32; + } CC4_B; + } ; + + /* break and dead-time register */ + union + { + __IOM uint32_t BDT; + + struct + { + __IOM uint32_t DTS : 8; + __IOM uint32_t LOCKCFG : 2; + __IOM uint32_t IMOS : 1; + __IOM uint32_t RMOS : 1; + __IOM uint32_t BRKEN : 1; + __IOM uint32_t BRKPOL : 1; + __IOM uint32_t AOEN : 1; + __IOM uint32_t MOEN : 1; + __IM uint32_t RESERVED1 : 16; + } BDT_B; + } ; + + /* DMA control register */ + union + { + __IOM uint32_t DCTRL; + + struct + { + __IOM uint32_t DBADDR : 5; + __IM uint32_t RESERVED1 : 3; + __IOM uint32_t DBLEN : 5; + __IM uint32_t RESERVED2 : 19; + } DCTRL_B; + } ; + + /* DMA address for full transfer */ + union + { + __IOM uint32_t DMADDR; + + struct + { + __IOM uint32_t DMADDR : 16; + __IM uint32_t RESERVED1 : 16; + } DMADDR_B; + } ; + + /* TMR14 Remap */ + union + { + __IOM uint32_t OPT; + + struct + { + __IOM uint32_t RMPSEL : 2; + __IM uint32_t RESERVED1 : 30; + } OPT_B; + } ; +} TMR_T; + +/** + * @brief Universal synchronous asynchronous receiver transmitter (USART) + */ + +typedef struct +{ + /* Control register 1 */ + union + { + __IOM uint32_t CTRL1; + + struct + { + __IOM uint32_t UEN : 1; + __IOM uint32_t USWMEN : 1; + __IOM uint32_t RXEN : 1; + __IOM uint32_t TXEN : 1; + __IOM uint32_t IDLEIEN : 1; + __IOM uint32_t RXBNEIEN : 1; + __IOM uint32_t TXCIEN : 1; + __IOM uint32_t TXBEIEN : 1; + __IOM uint32_t PEIEN : 1; + __IOM uint32_t PCFG : 1; + __IOM uint32_t PCEN : 1; + __IOM uint32_t WUPMCFG : 1; + __IOM uint32_t DBLCFG0 : 1; + __IOM uint32_t RXMUTEEN : 1; + __IOM uint32_t CMIEN : 1; + __IOM uint32_t OSMCFG : 1; + __IOM uint32_t DDLTEN : 5; + __IOM uint32_t DLTEN : 5; + __IOM uint32_t RXTOIEN : 1; + __IOM uint32_t EOBIEN : 1; + __IOM uint32_t DBLCFG1 : 1; + __IM uint32_t RESERVED2 : 3; + } CTRL1_B; + } ; + + /* Control register 2 */ + union + { + __IOM uint32_t CTRL2; + + struct + { + __IM uint32_t RESERVED1 : 4; + __IOM uint32_t ADDRLEN : 1; + __IOM uint32_t LBDLCFG : 1; + __IOM uint32_t LBDIEN : 1; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t LBCPOEN : 1; + __IOM uint32_t CPHA : 1; + __IOM uint32_t CPOL : 1; + __IOM uint32_t CLKEN : 1; + __IOM uint32_t STOPCFG : 2; + __IOM uint32_t LINMEN : 1; + __IOM uint32_t SWAPEN : 1; + __IOM uint32_t RXINVEN : 1; + __IOM uint32_t TXINVEN : 1; + __IOM uint32_t BINVEN : 1; + __IOM uint32_t MSBFEN : 1; + __IOM uint32_t ABRDEN : 1; + __IOM uint32_t ABRDCFG : 2; + __IOM uint32_t RXTODEN : 1; + __IOM uint32_t ADDRL : 4; + __IOM uint32_t ADDRH : 4; + } CTRL2_B; + } ; + + /* Control register 3 */ + union + { + __IOM uint32_t CTRL3; + + struct + { + __IOM uint32_t ERRIEN : 1; + __IOM uint32_t IREN : 1; + __IOM uint32_t IRLPEN : 1; + __IOM uint32_t HDEN : 1; + __IOM uint32_t SCNACKEN : 1; + __IOM uint32_t SCEN : 1; + __IOM uint32_t DMARXEN : 1; + __IOM uint32_t DMATXEN : 1; + __IOM uint32_t RTSEN : 1; + __IOM uint32_t CTSEN : 1; + __IOM uint32_t CTSIEN : 1; + __IOM uint32_t SAMCFG : 1; + __IOM uint32_t OVRDEDIS : 1; + __IOM uint32_t DDISRXEEN : 1; + __IOM uint32_t DEN : 1; + __IOM uint32_t DPCFG : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t SCARCCFG : 3; + __IOM uint32_t WSIFLGSEL : 2; + __IOM uint32_t WSMIEN : 1; + __IM uint32_t RESERVED2 : 9; + } CTRL3_B; + } ; + + /* Baud rate register */ + union + { + __IOM uint32_t BR; + + struct + { + __IOM uint32_t FBR : 4; + __IOM uint32_t MBR : 12; + __IM uint32_t RESERVED1 : 16; + } BR_B; + } ; + + /* Guard time and prescaler */ + union + { + __IOM uint32_t GTPSC; + + struct + { + __IOM uint32_t PSC : 8; + __IOM uint32_t GRDT : 8; + __IM uint32_t RESERVED1 : 16; + } GTPSC_B; + } ; + + /* Receiver timeout register */ + union + { + __IOM uint32_t RXTO; + + struct + { + __IOM uint32_t RXTO : 24; + __IOM uint32_t BLEN : 8; + } RXTO_B; + } ; + + /* Request register */ + union + { + __IOM uint32_t REQUEST; + + struct + { + __IOM uint32_t ABRDQ : 1; + __IOM uint32_t TXBFQ : 1; + __IOM uint32_t MUTEQ : 1; + __IOM uint32_t RXDFQ : 1; + __IOM uint32_t TXDFQ : 1; + __IM uint32_t RESERVED1 : 27; + } REQUEST_B; + } ; + + /* Interrupt & status register */ + union + { + __IM uint32_t STS; + + struct + { + __IM uint32_t PEFLG : 1; + __IM uint32_t FEFLG : 1; + __IM uint32_t NEFLG : 1; + __IM uint32_t OVREFLG : 1; + __IM uint32_t IDLEFLG : 1; + __IM uint32_t RXBNEFLG : 1; + __IM uint32_t TXCFLG : 1; + __IM uint32_t TXBEFLG : 1; + __IM uint32_t LBDFLG : 1; + __IM uint32_t CTSFLG : 1; + __IM uint32_t CTSCFG : 1; + __IM uint32_t RXTOFLG : 1; + __IM uint32_t EOBFLG : 1; + __IM uint32_t RESERVED1 : 1; + __IM uint32_t ABRDEFLG : 1; + __IM uint32_t ABRDFLG : 1; + __IM uint32_t BSYFLG : 1; + __IM uint32_t CMFLG : 1; + __IM uint32_t TXBFFLG : 1; + __IM uint32_t RXWFMUTE : 1; + __IM uint32_t WSMFLG : 1; + __IM uint32_t TXENACKFLG : 1; + __IM uint32_t RXENACKFLG : 1; + __IM uint32_t RESERVED2 : 9; + } STS_B; + } ; + + /* Interrupt flag clear register */ + union + { + __IOM uint32_t INTFCLR; + + struct + { + __IOM uint32_t PECLR : 1; + __IOM uint32_t FECLR : 1; + __IOM uint32_t NECLR : 1; + __IOM uint32_t OVRECLR : 1; + __IOM uint32_t IDLECLR : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t TXCCLR : 1; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t LBDCLR : 1; + __IOM uint32_t CTSCLR : 1; + __IM uint32_t RESERVED3 : 1; + __IOM uint32_t RXTOCLR : 1; + __IOM uint32_t EOBCLR : 1; + __IM uint32_t RESERVED4 : 4; + __IOM uint32_t CMCLR : 1; + __IM uint32_t RESERVED5 : 2; + __IOM uint32_t WSMCLR : 1; + __IM uint32_t RESERVED6 : 11; + } INTFCLR_B; + } ; + + /* Receive data register */ + union + { + __IM uint32_t RXDATA; + + struct + { + __IM uint32_t RXDATA : 9; + __IM uint32_t RESERVED1 : 23; + } RXDATA_B; + } ; + + /* Transmit data register */ + union + { + __IOM uint32_t TXDATA; + + struct + { + __IOM uint32_t TXDATA : 9; + __IM uint32_t RESERVED1 : 23; + } TXDATA_B; + } ; +} USART_T; + +/** + * @brief Window watchdog (WWDT) + */ + +typedef struct +{ + union + { + /* Control register */ + __IOM uint32_t CTRL; + + struct + { + __IOM uint32_t CNT : 7; + __IOM uint32_t WWDTEN : 1; + __IM uint32_t RESERVED1 : 24; + } CTRL_B; + } ; + + union + { + /* Configuration register */ + __IOM uint32_t CFG; + + struct + { + __IOM uint32_t WIN : 7; + __IOM uint32_t TBPSC : 2; + __IOM uint32_t EWIEN : 1; + __IM uint32_t RESERVED1 : 22; + } CFG_B; + } ; + + union + { + /* Status register */ + __IOM uint32_t STS; + + struct + { + __IOM uint32_t EWIFLG : 1; + __IM uint32_t RESERVED1 : 31; + } STS_B; + } ; +} WWDT_T; + +/** + * @brief Universal Serial Bus Device (USB) + */ + +typedef union +{ + __IOM uint32_t EP; + + struct + { + __IOM uint32_t ADDR : 4; + __IOM uint32_t TXSTS : 2; + __IOM uint32_t TXDTOG : 1; + __IOM uint32_t CTFT : 1; + __IOM uint32_t KIND : 1; + __IOM uint32_t TYPE : 2; + __IOM uint32_t SETUP : 1; + __IOM uint32_t RXSTS : 2; + __IOM uint32_t RXDTOG : 1; + __IOM uint32_t CTFR : 1; + __IM uint32_t RESERVED : 16; + } EP_B; +} USB_EP_REG_T; + +typedef struct +{ + /* Endpoint */ + USB_EP_REG_T EP[8]; + + __IOM uint32_t RESERVED1[8]; + + /** + * @brief Control register + */ + union + { + __IOM uint32_t CTRL; + + struct + { + __IOM uint32_t FORRST : 1; + __IOM uint32_t PWRDOWN : 1; + __IOM uint32_t LPWREN : 1; + __IOM uint32_t FORSUS : 1; + __IOM uint32_t WKUPREQ : 1; + __IOM uint32_t L1WKUPREQ : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t L1STSREQIM : 1; + __IOM uint32_t ESOFIEN : 1; + __IOM uint32_t SOFIEN : 1; + __IOM uint32_t RSTIEN : 1; + __IOM uint32_t SUSIEN : 1; + __IOM uint32_t WKUPIEN : 1; + __IOM uint32_t ERRIEN : 1; + __IOM uint32_t PMAOUIEN : 1; + __IOM uint32_t CTRIEN : 1; + __IM uint32_t RESERVED2 : 16; + } CTRL_B; + }; + + /** + * @brief Interrupt status register + */ + union + { + __IOM uint32_t INTSTS; + + struct + { + __IOM uint32_t EPID : 4; + __IOM uint32_t DOT : 1; + __IM uint32_t RESERVED1 : 2; + __IOM uint32_t L1STSREQ : 1; + __IOM uint32_t ESOFFLG : 1; + __IOM uint32_t SOFFLG : 1; + __IOM uint32_t RSTREQ : 1; + __IOM uint32_t SUSREQ : 1; + __IOM uint32_t WUPREQ : 1; + __IOM uint32_t ERRFLG : 1; + __IOM uint32_t PMOFLG : 1; + __IOM uint32_t CTFLG : 1; + __IM uint32_t RESERVED2 : 16; + } INTSTS_B; + }; + + /** + * @brief Frame number register + */ + union + { + __IOM uint32_t FRANUM; + + struct + { + __IOM uint32_t FRANUM : 11; + __IOM uint32_t LSOFNUM : 2; + __IOM uint32_t LOCK : 1; + __IOM uint32_t RXDMSTS : 1; + __IOM uint32_t RXDPSTS : 1; + __IM uint32_t RESERVED : 16; + } FRANUM_B; + }; + + /** + * @brief Device address register + */ + union + { + __IOM uint32_t ADDR; + + struct + { + __IOM uint32_t ADDR : 7; + __IOM uint32_t USBDEN : 1; + __IM uint32_t RESERVED : 24; + } ADDR_B; + }; + + /** + * @brief Buffer table address register + */ + union + { + __IOM uint32_t BUFFTB; + + struct + { + __IM uint32_t RESERVED1 : 3; + __IOM uint32_t BUFFTB : 13; + __IM uint32_t RESERVED2 : 16; + } BUFFTB_B; + }; + + /** + * @brief LPM control and status regiter + */ + union + { + __IOM uint32_t LPMCTRLSTS; + + struct + { + __IOM uint32_t LPMEN : 1; + __IOM uint32_t LPMACKEN : 1; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t REMWAKE : 1; + __IOM uint32_t BESL : 4; + __IM uint32_t RESERVED2 : 24; + } LPMCTRLSTS_B; + }; + + /** + * @brief Battery charging detector regiter + */ + union + { + __IOM uint32_t BCD; + + struct + { + __IOM uint32_t BCDEN : 1; + __IOM uint32_t DCDEN : 1; + __IOM uint32_t PDEN : 1; + __IOM uint32_t SDEN : 1; + __IOM uint32_t DCDFLG : 1; + __IOM uint32_t PDFLG : 1; + __IOM uint32_t SDFLG : 1; + __IOM uint32_t DMPUDFLG : 1; + __IM uint32_t RESERVED1 : 7; + __IOM uint32_t DPPUCTRL : 1; + __IM uint32_t RESERVED2 : 16; + } BCD_B; + }; +} USBD_T; + +/**@} end of group Peripheral_registers_structures*/ + +/** @defgroup Peripheral_memory_map + @{ +*/ + +/*@} end of group Device_Register*/ + +/* FMC base address in the alias region */ +#define FMC_BASE ((uint32_t)0x08000000) +/* SRAM base address in the alias region */ +#define SRAM_BASE ((uint32_t)0x20000000) +/* Peripheral base address in the alias region */ +#define PERIPH_BASE ((uint32_t)0x40000000) + +/* Peripheral memory map */ +#define APBPERIPH_BASE PERIPH_BASE +#define AHBPERIPH_BASE (PERIPH_BASE + 0x00020000) +#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000) + +#define TMR2_BASE (APBPERIPH_BASE + 0x00000000) +#define TMR3_BASE (APBPERIPH_BASE + 0x00000400) +#define TMR6_BASE (APBPERIPH_BASE + 0x00001000) +#define TMR7_BASE (APBPERIPH_BASE + 0x00001400) +#define TMR14_BASE (APBPERIPH_BASE + 0x00002000) +#define RTC_BASE (APBPERIPH_BASE + 0x00002800) +#define WWDT_BASE (APBPERIPH_BASE + 0x00002C00) +#define IWDT_BASE (APBPERIPH_BASE + 0x00003000) +#define SPI2_BASE (APBPERIPH_BASE + 0x00003800) +#define USART2_BASE (APBPERIPH_BASE + 0x00004400) +#define USART3_BASE (APBPERIPH_BASE + 0x00004800) +#define USART4_BASE (APBPERIPH_BASE + 0x00004C00) +#define USART5_BASE (APBPERIPH_BASE + 0x00005000) +#define I2C1_BASE (APBPERIPH_BASE + 0x00005400) +#define I2C2_BASE (APBPERIPH_BASE + 0x00005800) +#define USBD_BASE (APBPERIPH_BASE + 0x00005C00) +#define CAN_BASE (APBPERIPH_BASE + 0x00006400) +#define CRS_BASE (APBPERIPH_BASE + 0x00006C00) +#define PMU_BASE (APBPERIPH_BASE + 0x00007000) +#define DAC_BASE (APBPERIPH_BASE + 0x00007400) +#define CEC_BASE (APBPERIPH_BASE + 0x00007800) + +#define SYSCFG_BASE (APBPERIPH_BASE + 0x00010000) +#define COMP_BASE (APBPERIPH_BASE + 0x0001001C) +#define EINT_BASE (APBPERIPH_BASE + 0x00010400) +#define USART6_BASE (APBPERIPH_BASE + 0x00011400) +#define USART7_BASE (APBPERIPH_BASE + 0x00011800) +#define USART8_BASE (APBPERIPH_BASE + 0x00011C00) +#define ADC_BASE (APBPERIPH_BASE + 0x00012400) +#define TMR1_BASE (APBPERIPH_BASE + 0x00012C00) +#define SPI1_BASE (APBPERIPH_BASE + 0x00013000) +#define USART1_BASE (APBPERIPH_BASE + 0x00013800) +#define TMR15_BASE (APBPERIPH_BASE + 0x00014000) +#define TMR16_BASE (APBPERIPH_BASE + 0x00014400) +#define TMR17_BASE (APBPERIPH_BASE + 0x00014800) +#define DBG_BASE (APBPERIPH_BASE + 0x00015800) + +#define DMA1_BASE (AHBPERIPH_BASE + 0x00000000) +#define DMA1_CHANNEL_1_BASE (DMA1_BASE + 0x00000008) +#define DMA1_CHANNEL_2_BASE (DMA1_BASE + 0x0000001C) +#define DMA1_CHANNEL_3_BASE (DMA1_BASE + 0x00000030) +#define DMA1_CHANNEL_4_BASE (DMA1_BASE + 0x00000044) +#define DMA1_CHANNEL_5_BASE (DMA1_BASE + 0x00000058) +#define DMA1_CHANNEL_6_BASE (DMA1_BASE + 0x0000006C) +#define DMA1_CHANNEL_7_BASE (DMA1_BASE + 0x00000080) +#define DMA2_BASE (AHBPERIPH_BASE + 0x00000400) +#define DMA2_CHANNEL_1_BASE (DMA2_BASE + 0x00000008) +#define DMA2_CHANNEL_2_BASE (DMA2_BASE + 0x0000001C) +#define DMA2_CHANNEL_3_BASE (DMA2_BASE + 0x00000030) +#define DMA2_CHANNEL_4_BASE (DMA2_BASE + 0x00000044) +#define DMA2_CHANNEL_5_BASE (DMA2_BASE + 0x00000058) + +#define RCM_BASE (AHBPERIPH_BASE + 0x00001000) +#define FMC_R_BASE (AHBPERIPH_BASE + 0x00002000) +#define CRC_BASE (AHBPERIPH_BASE + 0x00003000) +#define TSC_BASE (AHBPERIPH_BASE + 0x00004000) +#define OB_BASE ((uint32_t)0x1FFFF800) + +#define GPIOA_BASE (AHB2PERIPH_BASE + 0x00000000) +#define GPIOB_BASE (AHB2PERIPH_BASE + 0x00000400) +#define GPIOC_BASE (AHB2PERIPH_BASE + 0x00000800) +#define GPIOD_BASE (AHB2PERIPH_BASE + 0x00000C00) +#define GPIOE_BASE (AHB2PERIPH_BASE + 0x00001000) +#define GPIOF_BASE (AHB2PERIPH_BASE + 0x00001400) + +/**@} end of group Peripheral_memory_map*/ + +/** @defgroup Peripheral_declaration + @{ +*/ + +#define ADC ((ADC_T*) ADC_BASE) +#define CAN ((CAN_T*) CAN_BASE) +#define CEC ((CEC_T*) CEC_BASE) +#define CRS ((CRS_T*) CRS_BASE) +#define CRC ((CRC_T*) CRC_BASE) +#define COMP ((COMP_T*) COMP_BASE) +#define DAC ((DAC_T*) DAC_BASE) +#define DBG ((DBG_T*) DBG_BASE) +#define EINT ((EINT_T*) EINT_BASE) +#define FMC ((FMC_T*) FMC_R_BASE) +#define I2C1 ((I2C_T*) I2C1_BASE) +#define I2C2 ((I2C_T*) I2C2_BASE) +#define IWDT ((IWDT_T*) IWDT_BASE) +#define OB ((OB_T*) OB_BASE) +#define PMU ((PMU_T*) PMU_BASE) +#define RCM ((RCM_T*) RCM_BASE) +#define RTC ((RTC_T*) RTC_BASE) +#define SPI1 ((SPI_T*) SPI1_BASE) +#define SPI2 ((SPI_T*) SPI2_BASE) +#define SYSCFG ((SYSCFG_T*) SYSCFG_BASE) +#define TSC ((TSC_T*) TSC_BASE) +#define USART1 ((USART_T*) USART1_BASE) +#define USART2 ((USART_T*) USART2_BASE) +#define USART3 ((USART_T*) USART3_BASE) +#define USART4 ((USART_T*) USART4_BASE) +#define USART5 ((USART_T*) USART5_BASE) +#define USART6 ((USART_T*) USART6_BASE) +#define USART7 ((USART_T*) USART7_BASE) +#define USART8 ((USART_T*) USART8_BASE) +#define USBD ((USBD_T*) USBD_BASE) +#define WWDT ((WWDT_T*) WWDT_BASE) + +#define DMA1 ((DMA_T*) DMA1_BASE) +#define DMA1_CHANNEL_1 ((DMA_CHANNEL_T*) DMA1_CHANNEL_1_BASE) +#define DMA1_CHANNEL_2 ((DMA_CHANNEL_T*) DMA1_CHANNEL_2_BASE) +#define DMA1_CHANNEL_3 ((DMA_CHANNEL_T*) DMA1_CHANNEL_3_BASE) +#define DMA1_CHANNEL_4 ((DMA_CHANNEL_T*) DMA1_CHANNEL_4_BASE) +#define DMA1_CHANNEL_5 ((DMA_CHANNEL_T*) DMA1_CHANNEL_5_BASE) +#define DMA1_CHANNEL_6 ((DMA_CHANNEL_T*) DMA1_CHANNEL_6_BASE) +#define DMA1_CHANNEL_7 ((DMA_CHANNEL_T*) DMA1_CHANNEL_7_BASE) +#define DMA2 ((DMA_T *) DMA2_BASE) +#define DMA2_CHANNEL_1 ((DMA_CHANNEL_T *) DMA2_CHANNEL_1_BASE) +#define DMA2_CHANNEL_2 ((DMA_CHANNEL_T *) DMA2_CHANNEL_2_BASE) +#define DMA2_CHANNEL_3 ((DMA_CHANNEL_T *) DMA2_CHANNEL_3_BASE) +#define DMA2_CHANNEL_4 ((DMA_CHANNEL_T *) DMA2_CHANNEL_4_BASE) +#define DMA2_CHANNEL_5 ((DMA_CHANNEL_T *) DMA2_CHANNEL_5_BASE) + +#define GPIOF ((GPIO_T*) GPIOF_BASE) +#define GPIOE ((GPIO_T*) GPIOE_BASE) +#define GPIOD ((GPIO_T*) GPIOD_BASE) +#define GPIOC ((GPIO_T*) GPIOC_BASE) +#define GPIOB ((GPIO_T*) GPIOB_BASE) +#define GPIOA ((GPIO_T*) GPIOA_BASE) + +#define TMR1 ((TMR_T*) TMR1_BASE) +#define TMR2 ((TMR_T*) TMR2_BASE) +#define TMR3 ((TMR_T*) TMR3_BASE) +#define TMR6 ((TMR_T*) TMR6_BASE) +#define TMR7 ((TMR_T*) TMR7_BASE) +#define TMR14 ((TMR_T*) TMR14_BASE) +#define TMR15 ((TMR_T*) TMR15_BASE) +#define TMR16 ((TMR_T*) TMR16_BASE) +#define TMR17 ((TMR_T*) TMR17_BASE) + +/**@} end of group Peripheral_declaration*/ + +/** @defgroup Exported_Macros + @{ +*/ + +/* Define one bit mask */ +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +#define SET_BIT(REG, BIT) ((REG) |= (BIT)) + +#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT)) + +#define READ_BIT(REG, BIT) ((REG) & (BIT)) + +#define CLEAR_REG(REG) ((REG) = (0x0)) + +#define WRITE_REG(REG, VAL) ((REG) = (VAL)) + +#define READ_REG(REG) ((REG)) + +#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK))) + +/**@} end of group Exported_Macros*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __APM32F0xx_H */ + +/**@} end of group APM32F0xx */ +/**@} end of group CMSIS */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Include/system_apm32f0xx.h b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Include/system_apm32f0xx.h new file mode 100644 index 0000000000..8547132b3b --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Include/system_apm32f0xx.h @@ -0,0 +1,86 @@ +/*! + * @file system_apm32f0xx.h + * + * @brief CMSIS Cortex-M0 Device Peripheral Access Layer System Source File + * + * @details This file contains the system clock configuration for APM32F0xx devices. + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __SYSTEM_APM32F0XX_H +#define __SYSTEM_APM32F0XX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup CMSIS + @{ +*/ + +/** @addtogroup APM32F0xx_System + @{ +*/ + +/** @defgroup System_Macros Macros + @{ + */ + +/**@} end of group System_Macros */ + +/** @defgroup System_Enumerations Enumerations + @{ + */ + +/**@} end of group System_Enumerations */ + +/** @defgroup System_Structures Structures + @{ + */ + +/**@} end of group System_Structures */ + +/** @defgroup System_Variables Variables + @{ + */ + +/* System Clock Frequency (Core Clock) */ +extern uint32_t SystemCoreClock; + +/**@} end of group System_Variables */ + +/** @defgroup System_Functions Functions + @{ + */ + +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __SYSTEM_APM32F0XX_H */ + +/**@} end of group System_Functions */ +/**@} end of group APM32F0xx_System */ +/**@} end of group CMSIS */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f030.s b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f030.s new file mode 100644 index 0000000000..1398c772e6 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f030.s @@ -0,0 +1,239 @@ +;/*! +; * @file startup_apm32f030.s +; * +; * @brief CMSIS Cortex-M0 PLUS based Core Device Startup File for Device startup_apm32f030 +; * +; * @version V1.0.2 +; * +; * @date 2022-02-21 +; * +; * @attention +; * +; * Copyright (C) 2020-2022 Geehy Semiconductor +; * +; * You may not use this file except in compliance with the +; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). +; * +; * The program is only for reference, which is distributed in the hope +; * that it will be useful and instructional for customers to develop +; * their software. Unless required by applicable law or agreed to in +; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT +; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. +; * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions +; * and limitations under the License. +; */ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + 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 0x00000200 + + 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 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDT_IRQHandler ; Window Watchdog + DCD 0 ; Reserved + DCD RTC_IRQHandler ; RTC through EINT Line + DCD FLASH_IRQHandler ; FLASH + DCD RCM_IRQHandler ; RCM + DCD EINT0_1_IRQHandler ; EINT Line 0 and 1 + DCD EINT2_3_IRQHandler ; EINT Line 2 and 3 + DCD EINT4_15_IRQHandler ; EINT Line 4 to 15 + DCD 0 ; Reserved + DCD DMA1_CH1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_CH2_3_IRQHandler ; DMA1 Channel 2 and Channel 3 + DCD DMA1_CH4_5_IRQHandler ; DMA1 Channel 4 and Channel 5 + DCD ADC1_IRQHandler ; ADC1 + DCD TMR1_BRK_UP_TRG_COM_IRQHandler ; TMR1 Break, Update, Trigger and Commutation + DCD TMR1_CC_IRQHandler ; TMR1 Capture Compare + DCD 0 ; Reserved + DCD TMR3_IRQHandler ; TMR3 + DCD TMR6_IRQHandler ; TMR6 + DCD TMR7_IRQHandler ; TMR7 + DCD TMR14_IRQHandler ; TMR14 + DCD TMR15_IRQHandler ; TMR15 + DCD TMR16_IRQHandler ; TMR16 + DCD TMR17_IRQHandler ; TMR17 + DCD I2C1_IRQHandler ; I2C1 + DCD I2C2_IRQHandler ; I2C2 + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_6_IRQHandler ; USART3,USART4,USART5,USART6 + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler routine +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 +SVC_Handler PROC + EXPORT SVC_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 WWDT_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCM_IRQHandler [WEAK] + EXPORT EINT0_1_IRQHandler [WEAK] + EXPORT EINT2_3_IRQHandler [WEAK] + EXPORT EINT4_15_IRQHandler [WEAK] + EXPORT DMA1_CH1_IRQHandler [WEAK] + EXPORT DMA1_CH2_3_IRQHandler [WEAK] + EXPORT DMA1_CH4_5_IRQHandler [WEAK] + EXPORT ADC1_IRQHandler [WEAK] + EXPORT TMR1_BRK_UP_TRG_COM_IRQHandler [WEAK] + EXPORT TMR1_CC_IRQHandler [WEAK] + EXPORT TMR3_IRQHandler [WEAK] + EXPORT TMR6_IRQHandler [WEAK] + EXPORT TMR7_IRQHandler [WEAK] + EXPORT TMR14_IRQHandler [WEAK] + EXPORT TMR15_IRQHandler [WEAK] + EXPORT TMR16_IRQHandler [WEAK] + EXPORT TMR17_IRQHandler [WEAK] + EXPORT I2C1_IRQHandler [WEAK] + EXPORT I2C2_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT USART3_6_IRQHandler [WEAK] + + +WWDT_IRQHandler +RTC_IRQHandler +FLASH_IRQHandler +RCM_IRQHandler +EINT0_1_IRQHandler +EINT2_3_IRQHandler +EINT4_15_IRQHandler +DMA1_CH1_IRQHandler +DMA1_CH2_3_IRQHandler +DMA1_CH4_5_IRQHandler +ADC1_IRQHandler +TMR1_BRK_UP_TRG_COM_IRQHandler +TMR1_CC_IRQHandler +TMR3_IRQHandler +TMR6_IRQHandler +TMR7_IRQHandler +TMR14_IRQHandler +TMR15_IRQHandler +TMR16_IRQHandler +TMR17_IRQHandler +I2C1_IRQHandler +I2C2_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +USART3_6_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/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f051.s b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f051.s new file mode 100644 index 0000000000..f870c5fba1 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f051.s @@ -0,0 +1,246 @@ +;/*! +; * @file startup_apm32f051.s +; * +; * @brief CMSIS Cortex-M0 PLUS based Core Device Startup File for Device startup_apm32f030 +; * +; * @version V1.0.2 +; * +; * @date 2022-02-21 +; * +; * @attention +; * +; * Copyright (C) 2020-2022 Geehy Semiconductor +; * +; * You may not use this file except in compliance with the +; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). +; * +; * The program is only for reference, which is distributed in the hope +; * that it will be useful and instructional for customers to develop +; * their software. Unless required by applicable law or agreed to in +; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT +; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. +; * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions +; * and limitations under the License. +; */ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + 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 0x00000200 + + 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 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDT_IRQHandler ; Window Watchdog + DCD PVD_IRQHandler ; PVD through EINT Line detect + DCD RTC_IRQHandler ; RTC through EINT Line + DCD FLASH_IRQHandler ; FLASH + DCD RCM_IRQHandler ; RCM + DCD EINT0_1_IRQHandler ; EINT Line 0 and 1 + DCD EINT2_3_IRQHandler ; EINT Line 2 and 3 + DCD EINT4_15_IRQHandler ; EINT Line 4 to 15 + DCD TSC_IRQHandler ; TSC + DCD DMA1_CH1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_CH2_3_IRQHandler ; DMA1 Channel 2 and Channel 3 + DCD DMA1_CH4_5_IRQHandler ; DMA1 Channel 4 and Channel 5 + DCD ADC1_COMP_IRQHandler ; ADC1, COMP1 and COMP2 + DCD TMR1_BRK_UP_TRG_COM_IRQHandler ; TMR1 Break, Update, Trigger and Commutation + DCD TMR1_CC_IRQHandler ; TMR1 Capture Compare + DCD TMR2_IRQHandler ; TMR2 + DCD TMR3_IRQHandler ; TMR3 + DCD TMR6_DAC_IRQHandler ; TMR6 and DAC + DCD 0 ; Reserved + DCD TMR14_IRQHandler ; TMR14 + DCD TMR15_IRQHandler ; TMR15 + DCD TMR16_IRQHandler ; TMR16 + DCD TMR17_IRQHandler ; TMR17 + DCD I2C1_IRQHandler ; I2C1 + DCD I2C2_IRQHandler ; I2C2 + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD 0 ; Reserved + DCD CEC_IRQHandler ; CEC + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler routine +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 +SVC_Handler PROC + EXPORT SVC_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 WWDT_IRQHandler [WEAK] + EXPORT PVD_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCM_IRQHandler [WEAK] + EXPORT EINT0_1_IRQHandler [WEAK] + EXPORT EINT2_3_IRQHandler [WEAK] + EXPORT EINT4_15_IRQHandler [WEAK] + EXPORT TSC_IRQHandler [WEAK] + EXPORT DMA1_CH1_IRQHandler [WEAK] + EXPORT DMA1_CH2_3_IRQHandler [WEAK] + EXPORT DMA1_CH4_5_IRQHandler [WEAK] + EXPORT ADC1_COMP_IRQHandler [WEAK] + EXPORT TMR1_BRK_UP_TRG_COM_IRQHandler [WEAK] + EXPORT TMR1_CC_IRQHandler [WEAK] + EXPORT TMR2_IRQHandler [WEAK] + EXPORT TMR3_IRQHandler [WEAK] + EXPORT TMR6_DAC_IRQHandler [WEAK] + EXPORT TMR14_IRQHandler [WEAK] + EXPORT TMR15_IRQHandler [WEAK] + EXPORT TMR16_IRQHandler [WEAK] + EXPORT TMR17_IRQHandler [WEAK] + EXPORT I2C1_IRQHandler [WEAK] + EXPORT I2C2_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT CEC_IRQHandler [WEAK] + + +WWDT_IRQHandler +PVD_IRQHandler +RTC_IRQHandler +FLASH_IRQHandler +RCM_IRQHandler +EINT0_1_IRQHandler +EINT2_3_IRQHandler +EINT4_15_IRQHandler +TSC_IRQHandler +DMA1_CH1_IRQHandler +DMA1_CH2_3_IRQHandler +DMA1_CH4_5_IRQHandler +ADC1_COMP_IRQHandler +TMR1_BRK_UP_TRG_COM_IRQHandler +TMR1_CC_IRQHandler +TMR2_IRQHandler +TMR3_IRQHandler +TMR6_DAC_IRQHandler +TMR14_IRQHandler +TMR15_IRQHandler +TMR16_IRQHandler +TMR17_IRQHandler +I2C1_IRQHandler +I2C2_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +CEC_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 + +>>>>>>> .r17560 diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f070.s b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f070.s new file mode 100644 index 0000000000..97c729bd2f --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f070.s @@ -0,0 +1,243 @@ +;/*! +; * @file startup_apm32f070.s +; * +; * @brief CMSIS Cortex-M0 PLUS based Core Device Startup File for Device startup_apm32f070 +; * +; * @version V1.0.2 +; * +; * @date 2022-02-21 +; * +; * @attention +; * +; * Copyright (C) 2020-2022 Geehy Semiconductor +; * +; * You may not use this file except in compliance with the +; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). +; * +; * The program is only for reference, which is distributed in the hope +; * that it will be useful and instructional for customers to develop +; * their software. Unless required by applicable law or agreed to in +; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT +; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. +; * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions +; * and limitations under the License. +; */ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + 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 0x00000200 + + 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 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDT_IRQHandler ; Window Watchdog + DCD 0 ; Reserved + DCD RTC_IRQHandler ; RTC through EINT Line + DCD FLASH_IRQHandler ; FLASH + DCD RCM_IRQHandler ; RCM + DCD EINT0_1_IRQHandler ; EINT Line 0 and 1 + DCD EINT2_3_IRQHandler ; EINT Line 2 and 3 + DCD EINT4_15_IRQHandler ; EINT Line 4 to 15 + DCD 0 ; Reserved + DCD DMA1_CH1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_CH2_3_IRQHandler ; DMA1 Channel 2 and Channel 3 + DCD DMA1_CH4_5_IRQHandler ; DMA1 Channel 4, Channel 5 + DCD ADC1_IRQHandler ; ADC1 + DCD TMR1_BRK_UP_TRG_COM_IRQHandler ; TMR1 Break, Update, Trigger and Commutation + DCD TMR1_CC_IRQHandler ; TMR1 Capture Compare + DCD 0 ; Reserved + DCD TMR3_IRQHandler ; TMR3 + DCD TMR6_IRQHandler ; TMR6 + DCD TMR7_IRQHandler ; TMR7 + DCD TMR14_IRQHandler ; TMR14 + DCD TMR15_IRQHandler ; TMR15 + DCD TMR16_IRQHandler ; TMR16 + DCD TMR17_IRQHandler ; TMR17 + DCD I2C1_IRQHandler ; I2C1 + DCD I2C2_IRQHandler ; I2C2 + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_4_IRQHandler ; USART3 and USART4 + DCD 0 ; Reserved + DCD USBD_IRQHandler ; USB + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler routine +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 +SVC_Handler PROC + EXPORT SVC_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 WWDT_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCM_IRQHandler [WEAK] + EXPORT EINT0_1_IRQHandler [WEAK] + EXPORT EINT2_3_IRQHandler [WEAK] + EXPORT EINT4_15_IRQHandler [WEAK] + EXPORT DMA1_CH1_IRQHandler [WEAK] + EXPORT DMA1_CH2_3_IRQHandler [WEAK] + EXPORT DMA1_CH4_5_IRQHandler [WEAK] + EXPORT ADC1_IRQHandler [WEAK] + EXPORT TMR1_BRK_UP_TRG_COM_IRQHandler [WEAK] + EXPORT TMR1_CC_IRQHandler [WEAK] + EXPORT TMR3_IRQHandler [WEAK] + EXPORT TMR6_IRQHandler [WEAK] + EXPORT TMR7_IRQHandler [WEAK] + EXPORT TMR14_IRQHandler [WEAK] + EXPORT TMR15_IRQHandler [WEAK] + EXPORT TMR16_IRQHandler [WEAK] + EXPORT TMR17_IRQHandler [WEAK] + EXPORT I2C1_IRQHandler [WEAK] + EXPORT I2C2_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT USART3_4_IRQHandler [WEAK] + EXPORT USBD_IRQHandler [WEAK] + + +WWDT_IRQHandler +RTC_IRQHandler +FLASH_IRQHandler +RCM_IRQHandler +EINT0_1_IRQHandler +EINT2_3_IRQHandler +EINT4_15_IRQHandler +DMA1_CH1_IRQHandler +DMA1_CH2_3_IRQHandler +DMA1_CH4_5_IRQHandler +ADC1_IRQHandler +TMR1_BRK_UP_TRG_COM_IRQHandler +TMR1_CC_IRQHandler +TMR3_IRQHandler +TMR6_IRQHandler +TMR7_IRQHandler +TMR14_IRQHandler +TMR15_IRQHandler +TMR16_IRQHandler +TMR17_IRQHandler +I2C1_IRQHandler +I2C2_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +USART3_4_IRQHandler +USBD_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/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f071.s b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f071.s new file mode 100644 index 0000000000..246a28183f --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f071.s @@ -0,0 +1,248 @@ +;/*! +; * @file startup_apm32f071.s +; * +; * @brief CMSIS Cortex-M0 PLUS based Core Device Startup File for Device startup_apm32f071 +; * +; * @version V1.0.2 +; * +; * @date 2022-02-21 +; * +; * @attention +; * +; * Copyright (C) 2020-2022 Geehy Semiconductor +; * +; * You may not use this file except in compliance with the +; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). +; * +; * The program is only for reference, which is distributed in the hope +; * that it will be useful and instructional for customers to develop +; * their software. Unless required by applicable law or agreed to in +; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT +; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. +; * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions +; * and limitations under the License. +; */ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + 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 0x00000200 + + 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 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDT_IRQHandler ; Window Watchdog + DCD PVD_VDDIO2_IRQHandler ; PVD and VDDIO2 through EINT Line detect + DCD RTC_IRQHandler ; RTC through EINT Line + DCD FLASH_IRQHandler ; FLASH + DCD RCM_CRS_IRQHandler ; RCM and CRS + DCD EINT0_1_IRQHandler ; EINT Line 0 and 1 + DCD EINT2_3_IRQHandler ; EINT Line 2 and 3 + DCD EINT4_15_IRQHandler ; EINT Line 4 to 15 + DCD TSC_IRQHandler ; TSC + DCD DMA1_CH1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_CH2_3_IRQHandler ; DMA1 Channel 2 and Channel 3 + DCD DMA1_CH4_5_6_7_IRQHandler ; DMA1 Channel 4, Channel 5, Channel 6 and Channel 7 + DCD ADC1_COMP_IRQHandler ; ADC1, COMP1 and COMP2 + DCD TMR1_BRK_UP_TRG_COM_IRQHandler ; TMR1 Break, Update, Trigger and Commutation + DCD TMR1_CC_IRQHandler ; TMR1 Capture Compare + DCD TMR2_IRQHandler ; TMR2 + DCD TMR3_IRQHandler ; TMR3 + DCD TMR6_DAC_IRQHandler ; TMR6 and DAC + DCD TMR7_IRQHandler ; TMR7 + DCD TMR14_IRQHandler ; TMR14 + DCD TMR15_IRQHandler ; TMR15 + DCD TMR16_IRQHandler ; TMR16 + DCD TMR17_IRQHandler ; TMR17 + DCD I2C1_IRQHandler ; I2C1 + DCD I2C2_IRQHandler ; I2C2 + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_4_IRQHandler ; USART3 and USART4 + DCD CEC_IRQHandler ; CEC + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler routine +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 +SVC_Handler PROC + EXPORT SVC_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 WWDT_IRQHandler [WEAK] + EXPORT PVD_VDDIO2_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCM_CRS_IRQHandler [WEAK] + EXPORT EINT0_1_IRQHandler [WEAK] + EXPORT EINT2_3_IRQHandler [WEAK] + EXPORT EINT4_15_IRQHandler [WEAK] + EXPORT TSC_IRQHandler [WEAK] + EXPORT DMA1_CH1_IRQHandler [WEAK] + EXPORT DMA1_CH2_3_IRQHandler [WEAK] + EXPORT DMA1_CH4_5_6_7_IRQHandler [WEAK] + EXPORT ADC1_COMP_IRQHandler [WEAK] + EXPORT TMR1_BRK_UP_TRG_COM_IRQHandler [WEAK] + EXPORT TMR1_CC_IRQHandler [WEAK] + EXPORT TMR2_IRQHandler [WEAK] + EXPORT TMR3_IRQHandler [WEAK] + EXPORT TMR6_DAC_IRQHandler [WEAK] + EXPORT TMR7_IRQHandler [WEAK] + EXPORT TMR14_IRQHandler [WEAK] + EXPORT TMR15_IRQHandler [WEAK] + EXPORT TMR16_IRQHandler [WEAK] + EXPORT TMR17_IRQHandler [WEAK] + EXPORT I2C1_IRQHandler [WEAK] + EXPORT I2C2_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT USART3_4_IRQHandler [WEAK] + EXPORT CEC_IRQHandler [WEAK] + + +WWDT_IRQHandler +PVD_VDDIO2_IRQHandler +RTC_IRQHandler +FLASH_IRQHandler +RCM_CRS_IRQHandler +EINT0_1_IRQHandler +EINT2_3_IRQHandler +EINT4_15_IRQHandler +TSC_IRQHandler +DMA1_CH1_IRQHandler +DMA1_CH2_3_IRQHandler +DMA1_CH4_5_6_7_IRQHandler +ADC1_COMP_IRQHandler +TMR1_BRK_UP_TRG_COM_IRQHandler +TMR1_CC_IRQHandler +TMR2_IRQHandler +TMR3_IRQHandler +TMR6_DAC_IRQHandler +TMR7_IRQHandler +TMR14_IRQHandler +TMR15_IRQHandler +TMR16_IRQHandler +TMR17_IRQHandler +I2C1_IRQHandler +I2C2_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +USART3_4_IRQHandler +CEC_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 \ No newline at end of file diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f072.s b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f072.s new file mode 100644 index 0000000000..b6bdfa2f26 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f072.s @@ -0,0 +1,251 @@ +;/*! +; * @file startup_apm32f072.s +; * +; * @brief CMSIS Cortex-M0 PLUS based Core Device Startup File for Device startup_apm32f072 +; * +; * @version V1.0.2 +; * +; * @date 2022-02-21 +; * +; * @attention +; * +; * Copyright (C) 2020-2022 Geehy Semiconductor +; * +; * You may not use this file except in compliance with the +; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). +; * +; * The program is only for reference, which is distributed in the hope +; * that it will be useful and instructional for customers to develop +; * their software. Unless required by applicable law or agreed to in +; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT +; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. +; * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions +; * and limitations under the License. +; */ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + 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 0x00000200 + + 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 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDT_IRQHandler ; Window Watchdog + DCD PVD_VDDIO2_IRQHandler ; PVD and VDDIO2 through EINT Line detect + DCD RTC_IRQHandler ; RTC through EINT Line + DCD FLASH_IRQHandler ; FLASH + DCD RCM_CRS_IRQHandler ; RCM and CRS + DCD EINT0_1_IRQHandler ; EINT Line 0 and 1 + DCD EINT2_3_IRQHandler ; EINT Line 2 and 3 + DCD EINT4_15_IRQHandler ; EINT Line 4 to 15 + DCD TSC_IRQHandler ; TSC + DCD DMA1_CH1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_CH2_3_IRQHandler ; DMA1 Channel 2 and Channel 3 + DCD DMA1_CH4_5_6_7_IRQHandler ; DMA1 Channel 4, Channel 5, Channel 6 and Channel 7 + DCD ADC1_COMP_IRQHandler ; ADC1, COMP1 and COMP2 + DCD TMR1_BRK_UP_TRG_COM_IRQHandler ; TMR1 Break, Update, Trigger and Commutation + DCD TMR1_CC_IRQHandler ; TMR1 Capture Compare + DCD TMR2_IRQHandler ; TMR2 + DCD TMR3_IRQHandler ; TMR3 + DCD TMR6_DAC_IRQHandler ; TMR6 and DAC + DCD TMR7_IRQHandler ; TMR7 + DCD TMR14_IRQHandler ; TMR14 + DCD TMR15_IRQHandler ; TMR15 + DCD TMR16_IRQHandler ; TMR16 + DCD TMR17_IRQHandler ; TMR17 + DCD I2C1_IRQHandler ; I2C1 + DCD I2C2_IRQHandler ; I2C2 + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_4_IRQHandler ; USART3 and USART4 + DCD CEC_CAN_IRQHandler ; CEC and CAN + DCD USBD_IRQHandler ; USB + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler routine +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 +SVC_Handler PROC + EXPORT SVC_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 WWDT_IRQHandler [WEAK] + EXPORT PVD_VDDIO2_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCM_CRS_IRQHandler [WEAK] + EXPORT EINT0_1_IRQHandler [WEAK] + EXPORT EINT2_3_IRQHandler [WEAK] + EXPORT EINT4_15_IRQHandler [WEAK] + EXPORT TSC_IRQHandler [WEAK] + EXPORT DMA1_CH1_IRQHandler [WEAK] + EXPORT DMA1_CH2_3_IRQHandler [WEAK] + EXPORT DMA1_CH4_5_6_7_IRQHandler [WEAK] + EXPORT ADC1_COMP_IRQHandler [WEAK] + EXPORT TMR1_BRK_UP_TRG_COM_IRQHandler [WEAK] + EXPORT TMR1_CC_IRQHandler [WEAK] + EXPORT TMR2_IRQHandler [WEAK] + EXPORT TMR3_IRQHandler [WEAK] + EXPORT TMR6_DAC_IRQHandler [WEAK] + EXPORT TMR7_IRQHandler [WEAK] + EXPORT TMR14_IRQHandler [WEAK] + EXPORT TMR15_IRQHandler [WEAK] + EXPORT TMR16_IRQHandler [WEAK] + EXPORT TMR17_IRQHandler [WEAK] + EXPORT I2C1_IRQHandler [WEAK] + EXPORT I2C2_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT USART3_4_IRQHandler [WEAK] + EXPORT CEC_CAN_IRQHandler [WEAK] + EXPORT USBD_IRQHandler [WEAK] + + +WWDT_IRQHandler +PVD_VDDIO2_IRQHandler +RTC_IRQHandler +FLASH_IRQHandler +RCM_CRS_IRQHandler +EINT0_1_IRQHandler +EINT2_3_IRQHandler +EINT4_15_IRQHandler +TSC_IRQHandler +DMA1_CH1_IRQHandler +DMA1_CH2_3_IRQHandler +DMA1_CH4_5_6_7_IRQHandler +ADC1_COMP_IRQHandler +TMR1_BRK_UP_TRG_COM_IRQHandler +TMR1_CC_IRQHandler +TMR2_IRQHandler +TMR3_IRQHandler +TMR6_DAC_IRQHandler +TMR7_IRQHandler +TMR14_IRQHandler +TMR15_IRQHandler +TMR16_IRQHandler +TMR17_IRQHandler +I2C1_IRQHandler +I2C2_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +USART3_4_IRQHandler +CEC_CAN_IRQHandler +USBD_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 \ No newline at end of file diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f091.s b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f091.s new file mode 100644 index 0000000000..604d39f181 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/arm/startup_apm32f091.s @@ -0,0 +1,248 @@ +;/*! +; * @file startup_apm32f091.s +; * +; * @brief CMSIS Cortex-M0 PLUS based Core Device Startup File for Device startup_apm32f072 +; * +; * @version V1.0.2 +; * +; * @date 2022-02-21 +; * +; * @attention +; * +; * Copyright (C) 2020-2022 Geehy Semiconductor +; * +; * You may not use this file except in compliance with the +; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). +; * +; * The program is only for reference, which is distributed in the hope +; * that it will be useful and instructional for customers to develop +; * their software. Unless required by applicable law or agreed to in +; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT +; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. +; * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions +; * and limitations under the License. +; */ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + 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 0x00000200 + + 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 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDT_IRQHandler ; Window Watchdog + DCD PVD_VDDIO2_IRQHandler ; PVD and VDDIO2 through EINT Line detect + DCD RTC_IRQHandler ; RTC through EINT Line + DCD FLASH_IRQHandler ; FLASH + DCD RCM_CRS_IRQHandler ; RCM and CRS + DCD EINT0_1_IRQHandler ; EINT Line 0 and 1 + DCD EINT2_3_IRQHandler ; EINT Line 2 and 3 + DCD EINT4_15_IRQHandler ; EINT Line 4 to 15 + DCD TSC_IRQHandler ; TSC + DCD DMA1_CH1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_CH2_3_DMA2_CH1_2_IRQHandler ; DMA1 Channel 2 and 3 DMA2 Channel 1 and 2 + DCD DMA1_CH4_7_DMA2_CH3_5_IRQHandler ; DMA1 Channel 4 to 7 DMA2 Channel 3 to 5 Interrupts + DCD ADC1_COMP_IRQHandler ; ADC1, COMP1 and COMP2 + DCD TMR1_BRK_UP_TRG_COM_IRQHandler ; TMR1 Break, Update, Trigger and Commutation + DCD TMR1_CC_IRQHandler ; TMR1 Capture Compare + DCD TMR2_IRQHandler ; TMR2 + DCD TMR3_IRQHandler ; TMR3 + DCD TMR6_DAC_IRQHandler ; TMR6 and DAC + DCD TMR7_IRQHandler ; TMR7 + DCD TMR14_IRQHandler ; TMR14 + DCD TMR15_IRQHandler ; TMR15 + DCD TMR16_IRQHandler ; TMR16 + DCD TMR17_IRQHandler ; TMR17 + DCD I2C1_IRQHandler ; I2C1 + DCD I2C2_IRQHandler ; I2C2 + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_8_IRQHandler ; USART3, USART4, USART5, USART6, USART7, USART8 + DCD CEC_CAN_IRQHandler ; CEC and CAN + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler routine +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 +SVC_Handler PROC + EXPORT SVC_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 WWDT_IRQHandler [WEAK] + EXPORT PVD_VDDIO2_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCM_CRS_IRQHandler [WEAK] + EXPORT EINT0_1_IRQHandler [WEAK] + EXPORT EINT2_3_IRQHandler [WEAK] + EXPORT EINT4_15_IRQHandler [WEAK] + EXPORT TSC_IRQHandler [WEAK] + EXPORT DMA1_CH1_IRQHandler [WEAK] + EXPORT DMA1_CH2_3_DMA2_CH1_2_IRQHandler [WEAK] + EXPORT DMA1_CH4_7_DMA2_CH3_5_IRQHandler [WEAK] + EXPORT ADC1_COMP_IRQHandler [WEAK] + EXPORT TMR1_BRK_UP_TRG_COM_IRQHandler [WEAK] + EXPORT TMR1_CC_IRQHandler [WEAK] + EXPORT TMR2_IRQHandler [WEAK] + EXPORT TMR3_IRQHandler [WEAK] + EXPORT TMR6_DAC_IRQHandler [WEAK] + EXPORT TMR7_IRQHandler [WEAK] + EXPORT TMR14_IRQHandler [WEAK] + EXPORT TMR15_IRQHandler [WEAK] + EXPORT TMR16_IRQHandler [WEAK] + EXPORT TMR17_IRQHandler [WEAK] + EXPORT I2C1_IRQHandler [WEAK] + EXPORT I2C2_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT USART3_8_IRQHandler [WEAK] + EXPORT CEC_CAN_IRQHandler [WEAK] + + +WWDT_IRQHandler +PVD_VDDIO2_IRQHandler +RTC_IRQHandler +FLASH_IRQHandler +RCM_CRS_IRQHandler +EINT0_1_IRQHandler +EINT2_3_IRQHandler +EINT4_15_IRQHandler +TSC_IRQHandler +DMA1_CH1_IRQHandler +DMA1_CH2_3_DMA2_CH1_2_IRQHandler +DMA1_CH4_7_DMA2_CH3_5_IRQHandler +ADC1_COMP_IRQHandler +TMR1_BRK_UP_TRG_COM_IRQHandler +TMR1_CC_IRQHandler +TMR2_IRQHandler +TMR3_IRQHandler +TMR6_DAC_IRQHandler +TMR7_IRQHandler +TMR14_IRQHandler +TMR15_IRQHandler +TMR16_IRQHandler +TMR17_IRQHandler +I2C1_IRQHandler +I2C2_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +USART3_8_IRQHandler +CEC_CAN_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/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F03xx6.ld b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F03xx6.ld new file mode 100644 index 0000000000..836289fb0b --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F03xx6.ld @@ -0,0 +1,162 @@ +/*! + * @file gcc_APM32F03xx6.ld + * + * @brief Linker script for APM32F03xx6 Device with + * 32KByte FLASH, 4KByte RAM + * + * @version V1.0.0 + * + * @date 2022-08-30 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Flash Configuration*/ +/* Flash Base Address */ +_rom_base = 0x8000000; +/*Flash Size (in Bytes) */ +_rom_size = 0x0008000; + +/* Embedded RAM Configuration */ +/* RAM Base Address */ +_ram_base = 0x20000000; +/* RAM Size (in Bytes) */ +_ram_size = 0x00001000; + +/* Stack / Heap Configuration */ +_end_stack = 0x20001000; +/* Heap Size (in Bytes) */ +_heap_size = 0x200; +/* Stack Size (in Bytes) */ +_stack_size = 0x400; + +MEMORY +{ +FLASH (rx) : ORIGIN = _rom_base, LENGTH = _rom_size + RAM (xrw) : ORIGIN = _ram_base, LENGTH = _ram_size +} + +SECTIONS +{ + .apm32_isr_vector : + { + . = ALIGN(4); + KEEP(*(.apm32_isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = 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 + + _start_address_init_data = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _start_address_data = .; + *(.data) + *(.data*) + + . = ALIGN(4); + _end_address_data = .; + } >RAM AT> FLASH + + . = ALIGN(4); + .bss : + { + + _start_address_bss = .; + __bss_start__ = _start_address_bss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _end_address_bss = .; + __bss_end__ = _end_address_bss; + } >RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _heap_size; + . = . + _stack_size; + . = ALIGN(8); + } >RAM + + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F03xx8.ld b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F03xx8.ld new file mode 100644 index 0000000000..f7fdf162c6 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F03xx8.ld @@ -0,0 +1,162 @@ +/*! + * @file gcc_APM32F03xx8.ld + * + * @brief Linker script for APM32F03xx8 Device with + * 64KByte FLASH, 8KByte RAM + * + * @version V1.0.0 + * + * @date 2022-08-30 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Flash Configuration*/ +/* Flash Base Address */ +_rom_base = 0x8000000; +/*Flash Size (in Bytes) */ +_rom_size = 0x0010000; + +/* Embedded RAM Configuration */ +/* RAM Base Address */ +_ram_base = 0x20000000; +/* RAM Size (in Bytes) */ +_ram_size = 0x00002000; + +/* Stack / Heap Configuration */ +_end_stack = 0x20002000; +/* Heap Size (in Bytes) */ +_heap_size = 0x200; +/* Stack Size (in Bytes) */ +_stack_size = 0x400; + +MEMORY +{ +FLASH (rx) : ORIGIN = _rom_base, LENGTH = _rom_size + RAM (xrw) : ORIGIN = _ram_base, LENGTH = _ram_size +} + +SECTIONS +{ + .apm32_isr_vector : + { + . = ALIGN(4); + KEEP(*(.apm32_isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = 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 + + _start_address_init_data = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _start_address_data = .; + *(.data) + *(.data*) + + . = ALIGN(4); + _end_address_data = .; + } >RAM AT> FLASH + + . = ALIGN(4); + .bss : + { + + _start_address_bss = .; + __bss_start__ = _start_address_bss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _end_address_bss = .; + __bss_end__ = _end_address_bss; + } >RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _heap_size; + . = . + _stack_size; + . = ALIGN(8); + } >RAM + + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F03xxC.ld b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F03xxC.ld new file mode 100644 index 0000000000..11f5098091 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F03xxC.ld @@ -0,0 +1,162 @@ +/*! + * @file gcc_APM32F03xxC.ld.ld + * + * @brief Linker script for APM32F03xxC.ld Device with + * 256KByte FLASH, 32KByte RAM + * + * @version V1.0.0 + * + * @date 2022-08-30 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Flash Configuration*/ +/* Flash Base Address */ +_rom_base = 0x8000000; +/*Flash Size (in Bytes) */ +_rom_size = 0x0040000; + +/* Embedded RAM Configuration */ +/* RAM Base Address */ +_ram_base = 0x20000000; +/* RAM Size (in Bytes) */ +_ram_size = 0x00008000; + +/* Stack / Heap Configuration */ +_end_stack = 0x20008000; +/* Heap Size (in Bytes) */ +_heap_size = 0x200; +/* Stack Size (in Bytes) */ +_stack_size = 0x400; + +MEMORY +{ +FLASH (rx) : ORIGIN = _rom_base, LENGTH = _rom_size + RAM (xrw) : ORIGIN = _ram_base, LENGTH = _ram_size +} + +SECTIONS +{ + .apm32_isr_vector : + { + . = ALIGN(4); + KEEP(*(.apm32_isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = 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 + + _start_address_init_data = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _start_address_data = .; + *(.data) + *(.data*) + + . = ALIGN(4); + _end_address_data = .; + } >RAM AT> FLASH + + . = ALIGN(4); + .bss : + { + + _start_address_bss = .; + __bss_start__ = _start_address_bss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _end_address_bss = .; + __bss_end__ = _end_address_bss; + } >RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _heap_size; + . = . + _stack_size; + . = ALIGN(8); + } >RAM + + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F05xx6.ld b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F05xx6.ld new file mode 100644 index 0000000000..761320e139 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F05xx6.ld @@ -0,0 +1,162 @@ +/*! + * @file gcc_APM32F05xx6.ld + * + * @brief Linker script for APM32F05xx6 Device with + * 32KByte FLASH, 8KByte RAM + * + * @version V1.0.0 + * + * @date 2022-08-30 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Flash Configuration*/ +/* Flash Base Address */ +_rom_base = 0x8000000; +/*Flash Size (in Bytes) */ +_rom_size = 0x0008000; + +/* Embedded RAM Configuration */ +/* RAM Base Address */ +_ram_base = 0x20000000; +/* RAM Size (in Bytes) */ +_ram_size = 0x00002000; + +/* Stack / Heap Configuration */ +_end_stack = 0x20002000; +/* Heap Size (in Bytes) */ +_heap_size = 0x200; +/* Stack Size (in Bytes) */ +_stack_size = 0x400; + +MEMORY +{ +FLASH (rx) : ORIGIN = _rom_base, LENGTH = _rom_size + RAM (xrw) : ORIGIN = _ram_base, LENGTH = _ram_size +} + +SECTIONS +{ + .apm32_isr_vector : + { + . = ALIGN(4); + KEEP(*(.apm32_isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = 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 + + _start_address_init_data = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _start_address_data = .; + *(.data) + *(.data*) + + . = ALIGN(4); + _end_address_data = .; + } >RAM AT> FLASH + + . = ALIGN(4); + .bss : + { + + _start_address_bss = .; + __bss_start__ = _start_address_bss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _end_address_bss = .; + __bss_end__ = _end_address_bss; + } >RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _heap_size; + . = . + _stack_size; + . = ALIGN(8); + } >RAM + + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F05xx8.ld b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F05xx8.ld new file mode 100644 index 0000000000..6af71d5157 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F05xx8.ld @@ -0,0 +1,162 @@ +/*! + * @file gcc_APM32F05xx8.ld + * + * @brief Linker script for APM32F05xx8 Device with + * 64KByte FLASH, 8KByte RAM + * + * @version V1.0.0 + * + * @date 2022-08-30 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Flash Configuration*/ +/* Flash Base Address */ +_rom_base = 0x8000000; +/*Flash Size (in Bytes) */ +_rom_size = 0x0010000; + +/* Embedded RAM Configuration */ +/* RAM Base Address */ +_ram_base = 0x20000000; +/* RAM Size (in Bytes) */ +_ram_size = 0x00002000; + +/* Stack / Heap Configuration */ +_end_stack = 0x20002000; +/* Heap Size (in Bytes) */ +_heap_size = 0x200; +/* Stack Size (in Bytes) */ +_stack_size = 0x400; + +MEMORY +{ +FLASH (rx) : ORIGIN = _rom_base, LENGTH = _rom_size + RAM (xrw) : ORIGIN = _ram_base, LENGTH = _ram_size +} + +SECTIONS +{ + .apm32_isr_vector : + { + . = ALIGN(4); + KEEP(*(.apm32_isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = 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 + + _start_address_init_data = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _start_address_data = .; + *(.data) + *(.data*) + + . = ALIGN(4); + _end_address_data = .; + } >RAM AT> FLASH + + . = ALIGN(4); + .bss : + { + + _start_address_bss = .; + __bss_start__ = _start_address_bss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _end_address_bss = .; + __bss_end__ = _end_address_bss; + } >RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _heap_size; + . = . + _stack_size; + . = ALIGN(8); + } >RAM + + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F07xx8.ld b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F07xx8.ld new file mode 100644 index 0000000000..3a5be775ec --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F07xx8.ld @@ -0,0 +1,162 @@ +/*! + * @file gcc_APM32F07xx8.ld + * + * @brief Linker script for APM32F07xx8 Device with + * 64KByte FLASH, 16KByte RAM + * + * @version V1.0.0 + * + * @date 2022-08-30 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Flash Configuration*/ +/* Flash Base Address */ +_rom_base = 0x8000000; +/*Flash Size (in Bytes) */ +_rom_size = 0x0010000; + +/* Embedded RAM Configuration */ +/* RAM Base Address */ +_ram_base = 0x20000000; +/* RAM Size (in Bytes) */ +_ram_size = 0x00004000; + +/* Stack / Heap Configuration */ +_end_stack = 0x20004000; +/* Heap Size (in Bytes) */ +_heap_size = 0x200; +/* Stack Size (in Bytes) */ +_stack_size = 0x400; + +MEMORY +{ +FLASH (rx) : ORIGIN = _rom_base, LENGTH = _rom_size + RAM (xrw) : ORIGIN = _ram_base, LENGTH = _ram_size +} + +SECTIONS +{ + .apm32_isr_vector : + { + . = ALIGN(4); + KEEP(*(.apm32_isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = 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 + + _start_address_init_data = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _start_address_data = .; + *(.data) + *(.data*) + + . = ALIGN(4); + _end_address_data = .; + } >RAM AT> FLASH + + . = ALIGN(4); + .bss : + { + + _start_address_bss = .; + __bss_start__ = _start_address_bss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _end_address_bss = .; + __bss_end__ = _end_address_bss; + } >RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _heap_size; + . = . + _stack_size; + . = ALIGN(8); + } >RAM + + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F07xxB.ld b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F07xxB.ld new file mode 100644 index 0000000000..aa13a33e9c --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F07xxB.ld @@ -0,0 +1,162 @@ +/*! + * @file gcc_APM32F07xxB.ld + * + * @brief Linker script for APM32F07xxB Device with + * 128KByte FLASH, 32KByte RAM + * + * @version V1.0.0 + * + * @date 2022-08-30 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Flash Configuration*/ +/* Flash Base Address */ +_rom_base = 0x8000000; +/*Flash Size (in Bytes) */ +_rom_size = 0x0020000; + +/* Embedded RAM Configuration */ +/* RAM Base Address */ +_ram_base = 0x20000000; +/* RAM Size (in Bytes) */ +_ram_size = 0x00004000; + +/* Stack / Heap Configuration */ +_end_stack = 0x20004000; +/* Heap Size (in Bytes) */ +_heap_size = 0x200; +/* Stack Size (in Bytes) */ +_stack_size = 0x400; + +MEMORY +{ +FLASH (rx) : ORIGIN = _rom_base, LENGTH = _rom_size + RAM (xrw) : ORIGIN = _ram_base, LENGTH = _ram_size +} + +SECTIONS +{ + .apm32_isr_vector : + { + . = ALIGN(4); + KEEP(*(.apm32_isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = 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 + + _start_address_init_data = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _start_address_data = .; + *(.data) + *(.data*) + + . = ALIGN(4); + _end_address_data = .; + } >RAM AT> FLASH + + . = ALIGN(4); + .bss : + { + + _start_address_bss = .; + __bss_start__ = _start_address_bss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _end_address_bss = .; + __bss_end__ = _end_address_bss; + } >RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _heap_size; + . = . + _stack_size; + . = ALIGN(8); + } >RAM + + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F09xxB.ld b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F09xxB.ld new file mode 100644 index 0000000000..ffe63e368f --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F09xxB.ld @@ -0,0 +1,162 @@ +/*! + * @file gcc_APM32F09xxB.ld + * + * @brief Linker script for APM32F09xxB Device with + * 128KByte FLASH, 32KByte RAM + * + * @version V1.0.0 + * + * @date 2022-08-30 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Flash Configuration*/ +/* Flash Base Address */ +_rom_base = 0x8000000; +/*Flash Size (in Bytes) */ +_rom_size = 0x0020000; + +/* Embedded RAM Configuration */ +/* RAM Base Address */ +_ram_base = 0x20000000; +/* RAM Size (in Bytes) */ +_ram_size = 0x00008000; + +/* Stack / Heap Configuration */ +_end_stack = 0x20008000; +/* Heap Size (in Bytes) */ +_heap_size = 0x200; +/* Stack Size (in Bytes) */ +_stack_size = 0x400; + +MEMORY +{ +FLASH (rx) : ORIGIN = _rom_base, LENGTH = _rom_size + RAM (xrw) : ORIGIN = _ram_base, LENGTH = _ram_size +} + +SECTIONS +{ + .apm32_isr_vector : + { + . = ALIGN(4); + KEEP(*(.apm32_isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = 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 + + _start_address_init_data = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _start_address_data = .; + *(.data) + *(.data*) + + . = ALIGN(4); + _end_address_data = .; + } >RAM AT> FLASH + + . = ALIGN(4); + .bss : + { + + _start_address_bss = .; + __bss_start__ = _start_address_bss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _end_address_bss = .; + __bss_end__ = _end_address_bss; + } >RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _heap_size; + . = . + _stack_size; + . = ALIGN(8); + } >RAM + + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F09xxC.ld b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F09xxC.ld new file mode 100644 index 0000000000..947d8f33da --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/gcc_APM32F09xxC.ld @@ -0,0 +1,162 @@ +/*! + * @file gcc_APM32F09xxC.ld + * + * @brief Linker script for APM32F09xxC Device with + * 256KByte FLASH, 32KByte RAM + * + * @version V1.0.0 + * + * @date 2022-08-30 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Flash Configuration*/ +/* Flash Base Address */ +_rom_base = 0x8000000; +/*Flash Size (in Bytes) */ +_rom_size = 0x0040000; + +/* Embedded RAM Configuration */ +/* RAM Base Address */ +_ram_base = 0x20000000; +/* RAM Size (in Bytes) */ +_ram_size = 0x00008000; + +/* Stack / Heap Configuration */ +_end_stack = 0x20008000; +/* Heap Size (in Bytes) */ +_heap_size = 0x200; +/* Stack Size (in Bytes) */ +_stack_size = 0x400; + +MEMORY +{ +FLASH (rx) : ORIGIN = _rom_base, LENGTH = _rom_size + RAM (xrw) : ORIGIN = _ram_base, LENGTH = _ram_size +} + +SECTIONS +{ + .apm32_isr_vector : + { + . = ALIGN(4); + KEEP(*(.apm32_isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = 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 + + _start_address_init_data = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _start_address_data = .; + *(.data) + *(.data*) + + . = ALIGN(4); + _end_address_data = .; + } >RAM AT> FLASH + + . = ALIGN(4); + .bss : + { + + _start_address_bss = .; + __bss_start__ = _start_address_bss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _end_address_bss = .; + __bss_end__ = _end_address_bss; + } >RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _heap_size; + . = . + _stack_size; + . = ALIGN(8); + } >RAM + + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f030.S b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f030.S new file mode 100644 index 0000000000..dbe06bca8d --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f030.S @@ -0,0 +1,247 @@ +/*! + * @file startup_apm32f030.S + * + * @brief CMSIS Cortex-M0 PLUS based Core Device Startup File for Device startup_apm32f030 + * + * @version V1.0.0 + * + * @date 2022-08-30 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + + .syntax unified + .cpu cortex-m0plus + .fpu softvfp + .thumb + +.global g_apm32_Vectors +.global Default_Handler + +.word _start_address_init_data +.word _start_address_data +.word _end_address_data +.word _start_address_bss +.word _end_address_bss + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function + +// Reset handler routine +Reset_Handler: +// User Stack and Heap initialization + ldr r0, =_end_stack + mov sp, r0 + + ldr r0, =_start_address_data + ldr r1, =_end_address_data + ldr r2, =_start_address_init_data + movs r3, #0 + b L_loop0_0 + +L_loop0: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +L_loop0_0: + adds r4, r0, r3 + cmp r4, r1 + bcc L_loop0 + + ldr r2, =_start_address_bss + ldr r4, =_end_address_bss + movs r3, #0 + b L_loop1 + +L_loop2: + str r3, [r2] + adds r2, r2, #4 + +L_loop1: + cmp r2, r4 + bcc L_loop2 + + bl SystemInit + bl __libc_init_array + bl main + +L_loop3: + b L_loop3 + +.size Reset_Handler, .-Reset_Handler + +// This is the code that gets called when the processor receives an unexpected interrupt. + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +L_Loop_infinite: + b L_Loop_infinite + .size Default_Handler, .-Default_Handler + +// The minimal vector table for a Cortex M0 Plus. + .section .apm32_isr_vector,"a",%progbits + .type g_apm32_Vectors, %object + .size g_apm32_Vectors, .-g_apm32_Vectors + +// Vector Table Mapped to Address 0 at Reset +g_apm32_Vectors: + .word _end_stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word 0 // Reserved + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // External Interrupts + .word WWDT_IRQHandler // Window Watchdog + .word 0 // Reserved + .word RTC_IRQHandler // RTC through EINT Line + .word FLASH_IRQHandler // FLASH + .word RCM_IRQHandler // RCM + .word EINT0_1_IRQHandler // EINT Line 0 and 1 + .word EINT2_3_IRQHandler // EINT Line 2 and 3 + .word EINT4_15_IRQHandler // EINT Line 4 to 15 + .word 0 // Reserved + .word DMA1_CH1_IRQHandler // DMA1 Channel 1 + .word DMA1_CH2_3_IRQHandler // DMA1 Channel 2 and Channel 3 + .word DMA1_CH4_5_IRQHandler // DMA1 Channel 4 and Channel 5 + .word ADC1_IRQHandler // ADC1 + .word TMR1_BRK_UP_TRG_COM_IRQHandler // TMR1 Break, Update, Trigger and Commutation + .word TMR1_CC_IRQHandler // TMR1 Capture Compare + .word 0 // Reserved + .word TMR3_IRQHandler // TMR3 + .word TMR6_IRQHandler // TMR6 + .word TMR7_IRQHandler // TMR7 + .word TMR14_IRQHandler // TMR14 + .word TMR15_IRQHandler // TMR15 + .word TMR16_IRQHandler // TMR16 + .word TMR17_IRQHandler // TMR17 + .word I2C1_IRQHandler // I2C1 + .word I2C2_IRQHandler // I2C2 + .word SPI1_IRQHandler // SPI1 + .word SPI2_IRQHandler // SPI2 + .word USART1_IRQHandler // USART1 + .word USART2_IRQHandler // USART2 + .word USART3_6_IRQHandler // USART3,USART4,USART5,USART6 + +// Default exception/interrupt handler + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDT_IRQHandler + .thumb_set WWDT_IRQHandler,Default_Handler + + .weak RTC_IRQHandler + .thumb_set RTC_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCM_IRQHandler + .thumb_set RCM_IRQHandler,Default_Handler + + .weak EINT0_1_IRQHandler + .thumb_set EINT0_1_IRQHandler,Default_Handler + + .weak EINT2_3_IRQHandler + .thumb_set EINT2_3_IRQHandler,Default_Handler + + .weak EINT4_15_IRQHandler + .thumb_set EINT4_15_IRQHandler,Default_Handler + + .weak DMA1_CH1_IRQHandler + .thumb_set DMA1_CH1_IRQHandler,Default_Handler + + .weak DMA1_CH2_3_IRQHandler + .thumb_set DMA1_CH2_3_IRQHandler,Default_Handler + + .weak DMA1_CH4_5_IRQHandler + .thumb_set DMA1_CH4_5_IRQHandler,Default_Handler + + .weak ADC1_IRQHandler + .thumb_set ADC1_IRQHandler,Default_Handler + + .weak TMR1_BRK_UP_TRG_COM_IRQHandler + .thumb_set TMR1_BRK_UP_TRG_COM_IRQHandler,Default_Handler + + .weak TMR1_CC_IRQHandler + .thumb_set TMR1_CC_IRQHandler,Default_Handler + + .weak TMR3_IRQHandler + .thumb_set TMR3_IRQHandler,Default_Handler + + .weak TMR6_IRQHandler + .thumb_set TMR6_IRQHandler,Default_Handler + + .weak TMR7_IRQHandler + .thumb_set TMR7_IRQHandler,Default_Handler + + .weak TMR14_IRQHandler + .thumb_set TMR14_IRQHandler,Default_Handler + + .weak TMR15_IRQHandler + .thumb_set TMR15_IRQHandler,Default_Handler + + .weak TMR16_IRQHandler + .thumb_set TMR16_IRQHandler,Default_Handler + + .weak TMR17_IRQHandler + .thumb_set TMR17_IRQHandler,Default_Handler + + .weak I2C1_IRQHandler + .thumb_set I2C1_IRQHandler,Default_Handler + + .weak I2C2_IRQHandler + .thumb_set I2C2_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_6_IRQHandler + .thumb_set USART3_6_IRQHandler,Default_Handler diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f051.S b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f051.S new file mode 100644 index 0000000000..c3302e17d6 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f051.S @@ -0,0 +1,254 @@ +/*! + * @file startup_apm32f051.S + * + * @brief CMSIS Cortex-M0 PLUS based Core Device Startup File for Device startup_apm32f051 + * + * @version V1.0.0 + * + * @date 2022-08-30 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + + .syntax unified + .cpu cortex-m0plus + .fpu softvfp + .thumb + +.global g_apm32_Vectors +.global Default_Handler + +.word _start_address_init_data +.word _start_address_data +.word _end_address_data +.word _start_address_bss +.word _end_address_bss + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function + +// Reset handler routine +Reset_Handler: +// User Stack and Heap initialization + ldr r0, =_end_stack + mov sp, r0 + + ldr r0, =_start_address_data + ldr r1, =_end_address_data + ldr r2, =_start_address_init_data + movs r3, #0 + b L_loop0_0 + +L_loop0: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +L_loop0_0: + adds r4, r0, r3 + cmp r4, r1 + bcc L_loop0 + + ldr r2, =_start_address_bss + ldr r4, =_end_address_bss + movs r3, #0 + b L_loop1 + +L_loop2: + str r3, [r2] + adds r2, r2, #4 + +L_loop1: + cmp r2, r4 + bcc L_loop2 + + bl SystemInit + bl __libc_init_array + bl main + +L_loop3: + b L_loop3 + +.size Reset_Handler, .-Reset_Handler + +// This is the code that gets called when the processor receives an unexpected interrupt. + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +L_Loop_infinite: + b L_Loop_infinite + .size Default_Handler, .-Default_Handler + +// The minimal vector table for a Cortex M0 Plus. + .section .apm32_isr_vector,"a",%progbits + .type g_apm32_Vectors, %object + .size g_apm32_Vectors, .-g_apm32_Vectors + +// Vector Table Mapped to Address 0 at Reset +g_apm32_Vectors: + .word _end_stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word 0 // Reserved + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // External Interrupts + .word WWDT_IRQHandler // Window Watchdog + .word PVD_IRQHandler // PVD through EINT Line detect + .word RTC_IRQHandler // RTC through EINT Line + .word FLASH_IRQHandler // FLASH + .word RCM_IRQHandler // RCM + .word EINT0_1_IRQHandler // EINT Line 0 and 1 + .word EINT2_3_IRQHandler // EINT Line 2 and 3 + .word EINT4_15_IRQHandler // EINT Line 4 to 15 + .word TSC_IRQHandler // TSC + .word DMA1_CH1_IRQHandler // DMA1 Channel 1 + .word DMA1_CH2_3_IRQHandler // DMA1 Channel 2 and Channel 3 + .word DMA1_CH4_5_IRQHandler // DMA1 Channel 4 and Channel 5 + .word ADC1_IRQHandler // ADC1 + .word TMR1_BRK_UP_TRG_COM_IRQHandler // TMR1 Break, Update, Trigger and Commutation + .word TMR1_CC_IRQHandler // TMR1 Capture Compare + .word TMR2_IRQHandler // TMR2 + .word TMR3_IRQHandler // TMR3 + .word TMR6_DAC_IRQHandler // TMR6 and DAC + .word 0 // Reserved + .word TMR14_IRQHandler // TMR14 + .word TMR15_IRQHandler // TMR15 + .word TMR16_IRQHandler // TMR16 + .word TMR17_IRQHandler // TMR17 + .word I2C1_IRQHandler // I2C1 + .word I2C2_IRQHandler // I2C2 + .word SPI1_IRQHandler // SPI1 + .word SPI2_IRQHandler // SPI2 + .word USART1_IRQHandler // USART1 + .word USART2_IRQHandler // USART2 + .word 0 // Reserved + .word CEC_IRQHandler // CEC + +// Default exception/interrupt handler + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDT_IRQHandler + .thumb_set WWDT_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak RTC_IRQHandler + .thumb_set RTC_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCM_IRQHandler + .thumb_set RCM_IRQHandler,Default_Handler + + .weak EINT0_1_IRQHandler + .thumb_set EINT0_1_IRQHandler,Default_Handler + + .weak EINT2_3_IRQHandler + .thumb_set EINT2_3_IRQHandler,Default_Handler + + .weak EINT4_15_IRQHandler + .thumb_set EINT4_15_IRQHandler,Default_Handler + + .weak TSC_IRQHandler + .thumb_set TSC_IRQHandler,Default_Handler + + .weak DMA1_CH1_IRQHandler + .thumb_set DMA1_CH1_IRQHandler,Default_Handler + + .weak DMA1_CH2_3_IRQHandler + .thumb_set DMA1_CH2_3_IRQHandler,Default_Handler + + .weak DMA1_CH4_5_IRQHandler + .thumb_set DMA1_CH4_5_IRQHandler,Default_Handler + + .weak ADC1_IRQHandler + .thumb_set ADC1_IRQHandler,Default_Handler + + .weak TMR1_BRK_UP_TRG_COM_IRQHandler + .thumb_set TMR1_BRK_UP_TRG_COM_IRQHandler,Default_Handler + + .weak TMR1_CC_IRQHandler + .thumb_set TMR1_CC_IRQHandler,Default_Handler + + .weak TMR2_IRQHandler + .thumb_set TMR2_IRQHandler,Default_Handler + + .weak TMR3_IRQHandler + .thumb_set TMR3_IRQHandler,Default_Handler + + .weak TMR6_DAC_IRQHandler + .thumb_set TMR6_DAC_IRQHandler,Default_Handler + + .weak TMR14_IRQHandler + .thumb_set TMR14_IRQHandler,Default_Handler + + .weak TMR15_IRQHandler + .thumb_set TMR15_IRQHandler,Default_Handler + + .weak TMR16_IRQHandler + .thumb_set TMR16_IRQHandler,Default_Handler + + .weak TMR17_IRQHandler + .thumb_set TMR17_IRQHandler,Default_Handler + + .weak I2C1_IRQHandler + .thumb_set I2C1_IRQHandler,Default_Handler + + .weak I2C2_IRQHandler + .thumb_set I2C2_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 CEC_IRQHandler + .thumb_set CEC_IRQHandler,Default_Handler diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f070.S b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f070.S new file mode 100644 index 0000000000..e2ab3ed3ab --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f070.S @@ -0,0 +1,252 @@ +/*! + * @file startup_apm32f070.S + * + * @brief CMSIS Cortex-M0 PLUS based Core Device Startup File for Device startup_apm32f070 + * + * @version V1.0.0 + * + * @date 2022-08-30 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + + .syntax unified + .cpu cortex-m0plus + .fpu softvfp + .thumb + +.global g_apm32_Vectors +.global Default_Handler + +.word _start_address_init_data +.word _start_address_data +.word _end_address_data +.word _start_address_bss +.word _end_address_bss + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function + +// Reset handler routine +Reset_Handler: +// User Stack and Heap initialization + ldr r0, =_end_stack + mov sp, r0 + + ldr r0, =_start_address_data + ldr r1, =_end_address_data + ldr r2, =_start_address_init_data + movs r3, #0 + b L_loop0_0 + +L_loop0: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +L_loop0_0: + adds r4, r0, r3 + cmp r4, r1 + bcc L_loop0 + + ldr r2, =_start_address_bss + ldr r4, =_end_address_bss + movs r3, #0 + b L_loop1 + +L_loop2: + str r3, [r2] + adds r2, r2, #4 + +L_loop1: + cmp r2, r4 + bcc L_loop2 + + bl SystemInit + bl __libc_init_array + bl main + +L_loop3: + b L_loop3 + +.size Reset_Handler, .-Reset_Handler + +// This is the code that gets called when the processor receives an unexpected interrupt. + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +L_Loop_infinite: + b L_Loop_infinite + .size Default_Handler, .-Default_Handler + +// The minimal vector table for a Cortex M0 Plus. + .section .apm32_isr_vector,"a",%progbits + .type g_apm32_Vectors, %object + .size g_apm32_Vectors, .-g_apm32_Vectors + +// Vector Table Mapped to Address 0 at Reset +g_apm32_Vectors: + .word _end_stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word 0 // Reserved + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // External Interrupts + .word WWDT_IRQHandler // Window Watchdog + .word 0 // Reserved + .word RTC_IRQHandler // RTC through EINT Line + .word FLASH_IRQHandler // FLASH + .word RCM_IRQHandler // RCM + .word EINT0_1_IRQHandler // EINT Line 0 and 1 + .word EINT2_3_IRQHandler // EINT Line 2 and 3 + .word EINT4_15_IRQHandler // EINT Line 4 to 15 + .word 0 // Reserved + .word DMA1_CH1_IRQHandler // DMA1 Channel 1 + .word DMA1_CH2_3_IRQHandler // DMA1 Channel 2 and Channel 3 + .word DMA1_CH4_5_IRQHandler // DMA1 Channel 4 and Channel 5 + .word ADC1_IRQHandler // ADC1 + .word TMR1_BRK_UP_TRG_COM_IRQHandler // TMR1 Break, Update, Trigger and Commutation + .word TMR1_CC_IRQHandler // TMR1 Capture Compare + .word 0 // Reserved + .word TMR3_IRQHandler // TMR3 + .word TMR6_IRQHandler // TMR6 + .word TMR7_IRQHandler // TMR7 + .word TMR14_IRQHandler // TMR14 + .word TMR15_IRQHandler // TMR15 + .word TMR16_IRQHandler // TMR16 + .word TMR17_IRQHandler // TMR17 + .word I2C1_IRQHandler // I2C1 + .word I2C2_IRQHandler // I2C2 + .word SPI1_IRQHandler // SPI1 + .word SPI2_IRQHandler // SPI2 + .word USART1_IRQHandler // USART1 + .word USART2_IRQHandler // USART2 + .word USART3_4_IRQHandler // USART3, USART4 + .word 0 // Reserved + word USBD_IRQHandler // USB + +// Default exception/interrupt handler + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDT_IRQHandler + .thumb_set WWDT_IRQHandler,Default_Handler + + .weak RTC_IRQHandler + .thumb_set RTC_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCM_IRQHandler + .thumb_set RCM_IRQHandler,Default_Handler + + .weak EINT0_1_IRQHandler + .thumb_set EINT0_1_IRQHandler,Default_Handler + + .weak EINT2_3_IRQHandler + .thumb_set EINT2_3_IRQHandler,Default_Handler + + .weak EINT4_15_IRQHandler + .thumb_set EINT4_15_IRQHandler,Default_Handler + + .weak DMA1_CH1_IRQHandler + .thumb_set DMA1_CH1_IRQHandler,Default_Handler + + .weak DMA1_CH2_3_IRQHandler + .thumb_set DMA1_CH2_3_IRQHandler,Default_Handler + + .weak DMA1_CH4_5_IRQHandler + .thumb_set DMA1_CH4_5_IRQHandler,Default_Handler + + .weak ADC1_IRQHandler + .thumb_set ADC1_IRQHandler,Default_Handler + + .weak TMR1_BRK_UP_TRG_COM_IRQHandler + .thumb_set TMR1_BRK_UP_TRG_COM_IRQHandler,Default_Handler + + .weak TMR1_CC_IRQHandler + .thumb_set TMR1_CC_IRQHandler,Default_Handler + + .weak TMR3_IRQHandler + .thumb_set TMR3_IRQHandler,Default_Handler + + .weak TMR6_IRQHandler + .thumb_set TMR6_IRQHandler,Default_Handler + + .weak TMR7_IRQHandler + .thumb_set TMR7_IRQHandler,Default_Handler + + .weak TMR14_IRQHandler + .thumb_set TMR14_IRQHandler,Default_Handler + + .weak TMR15_IRQHandler + .thumb_set TMR15_IRQHandler,Default_Handler + + .weak TMR16_IRQHandler + .thumb_set TMR16_IRQHandler,Default_Handler + + .weak TMR17_IRQHandler + .thumb_set TMR17_IRQHandler,Default_Handler + + .weak I2C1_IRQHandler + .thumb_set I2C1_IRQHandler,Default_Handler + + .weak I2C2_IRQHandler + .thumb_set I2C2_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_4_IRQHandler + .thumb_set USART3_4_IRQHandler,Default_Handler + + .weak USBD_IRQHandler + .thumb_set USBD_IRQHandler,Default_Handler diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f071.S b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f071.S new file mode 100644 index 0000000000..63483afbb6 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f071.S @@ -0,0 +1,261 @@ +/*! + * @file startup_apm32f071.S + * + * @brief CMSIS Cortex-M0 PLUS based Core Device Startup File for Device startup_apm32f071 + * + * @version V1.0.0 + * + * @date 2022-08-30 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + + .syntax unified + .cpu cortex-m0plus + .fpu softvfp + .thumb + +.global g_apm32_Vectors +.global Default_Handler + +.word _start_address_init_data +.word _start_address_data +.word _end_address_data +.word _start_address_bss +.word _end_address_bss + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function + +// Reset handler routine +Reset_Handler: +// User Stack and Heap initialization + ldr r0, =_end_stack + mov sp, r0 + + ldr r0, =_start_address_data + ldr r1, =_end_address_data + ldr r2, =_start_address_init_data + movs r3, #0 + b L_loop0_0 + +L_loop0: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +L_loop0_0: + adds r4, r0, r3 + cmp r4, r1 + bcc L_loop0 + + ldr r2, =_start_address_bss + ldr r4, =_end_address_bss + movs r3, #0 + b L_loop1 + +L_loop2: + str r3, [r2] + adds r2, r2, #4 + +L_loop1: + cmp r2, r4 + bcc L_loop2 + + bl SystemInit + bl __libc_init_array + bl main + +L_loop3: + b L_loop3 + +.size Reset_Handler, .-Reset_Handler + +// This is the code that gets called when the processor receives an unexpected interrupt. + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +L_Loop_infinite: + b L_Loop_infinite + .size Default_Handler, .-Default_Handler + +// The minimal vector table for a Cortex M0 Plus. + .section .apm32_isr_vector,"a",%progbits + .type g_apm32_Vectors, %object + .size g_apm32_Vectors, .-g_apm32_Vectors + +// Vector Table Mapped to Address 0 at Reset +g_apm32_Vectors: + .word _end_stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word 0 // Reserved + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // External Interrupts + .word WWDT_IRQHandler // Window Watchdog + .word PVD_VDDIO2_IRQHandler // PVD and VDDIO2 through EINT Line detect + .word RTC_IRQHandler // RTC through EINT Line + .word FLASH_IRQHandler // FLASH + .word RCM_CRS_IRQHandler // RCM and CRS + .word EINT0_1_IRQHandler // EINT Line 0 and 1 + .word EINT2_3_IRQHandler // EINT Line 2 and 3 + .word EINT4_15_IRQHandler // EINT Line 4 to 15 + .word TSC_IRQHandler // TSC + .word DMA1_CH1_IRQHandler // DMA1 Channel 1 + .word DMA1_CH2_3_IRQHandler // DMA1 Channel 2 and Channel 3 + .word DMA1_CH4_5_6_7_IRQHandler // DMA1 Channel 4 and Channel 5 + .word ADC1_COMP_IRQHandler // ADC1 , COMP1 and COMP2 + .word TMR1_BRK_UP_TRG_COM_IRQHandler // TMR1 Break, Update, Trigger and Commutation + .word TMR1_CC_IRQHandler // TMR1 Capture Compare + .word TMR2_IRQHandler // TMR2 + .word TMR3_IRQHandler // TMR3 + .word TMR6_DAC_IRQHandler // TMR6 and DAC + .word TMR7_IRQHandler // TMR7 + .word TMR14_IRQHandler // TMR14 + .word TMR15_IRQHandler // TMR15 + .word TMR16_IRQHandler // TMR16 + .word TMR17_IRQHandler // TMR17 + .word I2C1_IRQHandler // I2C1 + .word I2C2_IRQHandler // I2C2 + .word SPI1_IRQHandler // SPI1 + .word SPI2_IRQHandler // SPI2 + .word USART1_IRQHandler // USART1 + .word USART2_IRQHandler // USART2 + .word USART3_4_IRQHandler // USART3, USART4 + .word CEC_IRQHandler // CEC and CAN + +// Default exception/interrupt handler + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDT_IRQHandler + .thumb_set WWDT_IRQHandler,Default_Handler + + .weak PVD_VDDIO2_IRQHandler + .thumb_set PVD_VDDIO2_IRQHandler,Default_Handler + + .weak RTC_IRQHandler + .thumb_set RTC_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCM_CRS_IRQHandler + .thumb_set RCM_CRS_IRQHandler,Default_Handler + + .weak EINT0_1_IRQHandler + .thumb_set EINT0_1_IRQHandler,Default_Handler + + .weak EINT2_3_IRQHandler + .thumb_set EINT2_3_IRQHandler,Default_Handler + + .weak EINT4_15_IRQHandler + .thumb_set EINT4_15_IRQHandler,Default_Handler + + .weak TSC_IRQHandler + .thumb_set TSC_IRQHandler,Default_Handler + + .weak DMA1_CH1_IRQHandler + .thumb_set DMA1_CH1_IRQHandler,Default_Handler + + .weak DMA1_CH2_3_IRQHandler + .thumb_set DMA1_CH2_3_IRQHandler,Default_Handler + + .weak DMA1_CH4_5_6_7_IRQHandler + .thumb_set DMA1_CH4_5_6_7_IRQHandler,Default_Handler + + .weak ADC1_COMP_IRQHandler + .thumb_set ADC1_COMP_IRQHandler,Default_Handler + + .weak TMR1_BRK_UP_TRG_COM_IRQHandler + .thumb_set TMR1_BRK_UP_TRG_COM_IRQHandler,Default_Handler + + .weak TMR1_CC_IRQHandler + .thumb_set TMR1_CC_IRQHandler,Default_Handler + + .weak TMR2_IRQHandler + .thumb_set TMR2_IRQHandler,Default_Handler + + + .weak TMR3_IRQHandler + .thumb_set TMR3_IRQHandler,Default_Handler + + .weak TMR6_DAC_IRQHandler + .thumb_set TMR6_DAC_IRQHandler,Default_Handler + + .weak TMR7_IRQHandler + .thumb_set TMR7_IRQHandler,Default_Handler + + .weak TMR14_IRQHandler + .thumb_set TMR14_IRQHandler,Default_Handler + + .weak TMR15_IRQHandler + .thumb_set TMR15_IRQHandler,Default_Handler + + .weak TMR16_IRQHandler + .thumb_set TMR16_IRQHandler,Default_Handler + + .weak TMR17_IRQHandler + .thumb_set TMR17_IRQHandler,Default_Handler + + .weak I2C1_IRQHandler + .thumb_set I2C1_IRQHandler,Default_Handler + + .weak I2C2_IRQHandler + .thumb_set I2C2_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_4_IRQHandler + .thumb_set USART3_4_IRQHandler,Default_Handler + + .weak CEC_IRQHandler + .thumb_set CEC_IRQHandler,Default_Handler diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f072.S b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f072.S new file mode 100644 index 0000000000..80b0a4275a --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f072.S @@ -0,0 +1,264 @@ +/*! + * @file startup_apm32f072.S + * + * @brief CMSIS Cortex-M0 PLUS based Core Device Startup File for Device startup_apm32f072 + * + * @version V1.0.0 + * + * @date 2022-08-30 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + + .syntax unified + .cpu cortex-m0plus + .fpu softvfp + .thumb + +.global g_apm32_Vectors +.global Default_Handler + +.word _start_address_init_data +.word _start_address_data +.word _end_address_data +.word _start_address_bss +.word _end_address_bss + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function + +// Reset handler routine +Reset_Handler: +// User Stack and Heap initialization + ldr r0, =_end_stack + mov sp, r0 + + ldr r0, =_start_address_data + ldr r1, =_end_address_data + ldr r2, =_start_address_init_data + movs r3, #0 + b L_loop0_0 + +L_loop0: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +L_loop0_0: + adds r4, r0, r3 + cmp r4, r1 + bcc L_loop0 + + ldr r2, =_start_address_bss + ldr r4, =_end_address_bss + movs r3, #0 + b L_loop1 + +L_loop2: + str r3, [r2] + adds r2, r2, #4 + +L_loop1: + cmp r2, r4 + bcc L_loop2 + + bl SystemInit + bl __libc_init_array + bl main + +L_loop3: + b L_loop3 + +.size Reset_Handler, .-Reset_Handler + +// This is the code that gets called when the processor receives an unexpected interrupt. + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +L_Loop_infinite: + b L_Loop_infinite + .size Default_Handler, .-Default_Handler + +// The minimal vector table for a Cortex M0 Plus. + .section .apm32_isr_vector,"a",%progbits + .type g_apm32_Vectors, %object + .size g_apm32_Vectors, .-g_apm32_Vectors + +// Vector Table Mapped to Address 0 at Reset +g_apm32_Vectors: + .word _end_stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word 0 // Reserved + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // External Interrupts + .word WWDT_IRQHandler // Window Watchdog + .word PVD_VDDIO2_IRQHandler // PVD and VDDIO2 through EINT Line detect + .word RTC_IRQHandler // RTC through EINT Line + .word FLASH_IRQHandler // FLASH + .word RCM_CRS_IRQHandler // RCM and CRS + .word EINT0_1_IRQHandler // EINT Line 0 and 1 + .word EINT2_3_IRQHandler // EINT Line 2 and 3 + .word EINT4_15_IRQHandler // EINT Line 4 to 15 + .word TSC_IRQHandler // TSC + .word DMA1_CH1_IRQHandler // DMA1 Channel 1 + .word DMA1_CH2_3_IRQHandler // DMA1 Channel 2 and Channel 3 + .word DMA1_CH4_5_6_7_IRQHandler // DMA1 Channel 4 and Channel 5 + .word ADC1_COMP_IRQHandler // ADC1 , COMP1 and COMP2 + .word TMR1_BRK_UP_TRG_COM_IRQHandler // TMR1 Break, Update, Trigger and Commutation + .word TMR1_CC_IRQHandler // TMR1 Capture Compare + .word TMR2_IRQHandler // TMR2 + .word TMR3_IRQHandler // TMR3 + .word TMR6_DAC_IRQHandler // TMR6 and DAC + .word TMR7_IRQHandler // TMR7 + .word TMR14_IRQHandler // TMR14 + .word TMR15_IRQHandler // TMR15 + .word TMR16_IRQHandler // TMR16 + .word TMR17_IRQHandler // TMR17 + .word I2C1_IRQHandler // I2C1 + .word I2C2_IRQHandler // I2C2 + .word SPI1_IRQHandler // SPI1 + .word SPI2_IRQHandler // SPI2 + .word USART1_IRQHandler // USART1 + .word USART2_IRQHandler // USART2 + .word USART3_4_IRQHandler // USART3, USART4 + .word CEC_CAN_IRQHandler // CEC and CAN + .word USBD_IRQHandler // USB + +// Default exception/interrupt handler + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDT_IRQHandler + .thumb_set WWDT_IRQHandler,Default_Handler + + .weak PVD_VDDIO2_IRQHandler + .thumb_set PVD_VDDIO2_IRQHandler,Default_Handler + + .weak RTC_IRQHandler + .thumb_set RTC_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCM_CRS_IRQHandler + .thumb_set RCM_CRS_IRQHandler,Default_Handler + + .weak EINT0_1_IRQHandler + .thumb_set EINT0_1_IRQHandler,Default_Handler + + .weak EINT2_3_IRQHandler + .thumb_set EINT2_3_IRQHandler,Default_Handler + + .weak EINT4_15_IRQHandler + .thumb_set EINT4_15_IRQHandler,Default_Handler + + .weak TSC_IRQHandler + .thumb_set TSC_IRQHandler,Default_Handler + + .weak DMA1_CH1_IRQHandler + .thumb_set DMA1_CH1_IRQHandler,Default_Handler + + .weak DMA1_CH2_3_IRQHandler + .thumb_set DMA1_CH2_3_IRQHandler,Default_Handler + + .weak DMA1_CH4_5_6_7_IRQHandler + .thumb_set DMA1_CH4_5_6_7_IRQHandler,Default_Handler + + .weak ADC1_COMP_IRQHandler + .thumb_set ADC1_COMP_IRQHandler,Default_Handler + + .weak TMR1_BRK_UP_TRG_COM_IRQHandler + .thumb_set TMR1_BRK_UP_TRG_COM_IRQHandler,Default_Handler + + .weak TMR1_CC_IRQHandler + .thumb_set TMR1_CC_IRQHandler,Default_Handler + + .weak TMR2_IRQHandler + .thumb_set TMR2_IRQHandler,Default_Handler + + .weak TMR3_IRQHandler + .thumb_set TMR3_IRQHandler,Default_Handler + + .weak TMR6_DAC_IRQHandler + .thumb_set TMR6_DAC_IRQHandler,Default_Handler + + .weak TMR7_IRQHandler + .thumb_set TMR7_IRQHandler,Default_Handler + + .weak TMR14_IRQHandler + .thumb_set TMR14_IRQHandler,Default_Handler + + .weak TMR15_IRQHandler + .thumb_set TMR15_IRQHandler,Default_Handler + + .weak TMR16_IRQHandler + .thumb_set TMR16_IRQHandler,Default_Handler + + .weak TMR17_IRQHandler + .thumb_set TMR17_IRQHandler,Default_Handler + + .weak I2C1_IRQHandler + .thumb_set I2C1_IRQHandler,Default_Handler + + .weak I2C2_IRQHandler + .thumb_set I2C2_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_4_IRQHandler + .thumb_set USART3_4_IRQHandler,Default_Handler + + .weak CEC_CAN_IRQHandler + .thumb_set CEC_CAN_IRQHandler,Default_Handler + + .weak USBD_IRQHandler + .thumb_set USBD_IRQHandler,Default_Handler diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f091.S b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f091.S new file mode 100644 index 0000000000..fb650567e6 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/gcc/startup_apm32f091.S @@ -0,0 +1,261 @@ +/*! + * @file startup_apm32f091.S + * + * @brief CMSIS Cortex-M0 PLUS based Core Device Startup File for Device startup_apm32f091 + * + * @version V1.0.0 + * + * @date 2022-08-30 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + + .syntax unified + .cpu cortex-m0plus + .fpu softvfp + .thumb + +.global g_apm32_Vectors +.global Default_Handler + +.word _start_address_init_data +.word _start_address_data +.word _end_address_data +.word _start_address_bss +.word _end_address_bss + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function + +// Reset handler routine +Reset_Handler: +// User Stack and Heap initialization + ldr r0, =_end_stack + mov sp, r0 + + ldr r0, =_start_address_data + ldr r1, =_end_address_data + ldr r2, =_start_address_init_data + movs r3, #0 + b L_loop0_0 + +L_loop0: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +L_loop0_0: + adds r4, r0, r3 + cmp r4, r1 + bcc L_loop0 + + ldr r2, =_start_address_bss + ldr r4, =_end_address_bss + movs r3, #0 + b L_loop1 + +L_loop2: + str r3, [r2] + adds r2, r2, #4 + +L_loop1: + cmp r2, r4 + bcc L_loop2 + + bl SystemInit + bl __libc_init_array + bl main + +L_loop3: + b L_loop3 + +.size Reset_Handler, .-Reset_Handler + +// This is the code that gets called when the processor receives an unexpected interrupt. + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +L_Loop_infinite: + b L_Loop_infinite + .size Default_Handler, .-Default_Handler + +// The minimal vector table for a Cortex M0 Plus. + .section .apm32_isr_vector,"a",%progbits + .type g_apm32_Vectors, %object + .size g_apm32_Vectors, .-g_apm32_Vectors + +// Vector Table Mapped to Address 0 at Reset +g_apm32_Vectors: + .word _end_stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word 0 // Reserved + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // External Interrupts + .word WWDT_IRQHandler // Window Watchdog + .word PVD_VDDIO2_IRQHandler // PVD and VDDIO2 through EINT Line detect + .word RTC_IRQHandler // RTC through EINT Line + .word FLASH_IRQHandler // FLASH + .word RCM_CRS_IRQHandler // RCM and CRS + .word EINT0_1_IRQHandler // EINT Line 0 and 1 + .word EINT2_3_IRQHandler // EINT Line 2 and 3 + .word EINT4_15_IRQHandler // EINT Line 4 to 15 + .word TSC_IRQHandler // TSC + .word DMA1_CH1_IRQHandler // DMA1 Channel 1 + .word DMA1_CH2_3_DMA2_CH1_2_IRQHandler // DMA1 Channel 2 and 3 DMA2 Channel 1 and 2 + .word DMA1_CH4_7_DMA2_CH3_5_IRQHandler // DMA1 Channel 4 to 7 DMA2 Channel 3 to 5 Interrupts + .word ADC1_COMP_IRQHandler // ADC1 , COMP1 and COMP2 + .word TMR1_BRK_UP_TRG_COM_IRQHandler // TMR1 Break, Update, Trigger and Commutation + .word TMR1_CC_IRQHandler // TMR1 Capture Compare + .word TMR2_IRQHandler // TMR2 + .word TMR3_IRQHandler // TMR3 + .word TMR6_DAC_IRQHandler // TMR6 and DAC + .word TMR7_IRQHandler // TMR7 + .word TMR14_IRQHandler // TMR14 + .word TMR15_IRQHandler // TMR15 + .word TMR16_IRQHandler // TMR16 + .word TMR17_IRQHandler // TMR17 + .word I2C1_IRQHandler // I2C1 + .word I2C2_IRQHandler // I2C2 + .word SPI1_IRQHandler // SPI1 + .word SPI2_IRQHandler // SPI2 + .word USART1_IRQHandler // USART1 + .word USART2_IRQHandler // USART2 + .word USART3_8_IRQHandler // USART3, USART4, USART5, USART6, USART7, USART8 + .word CEC_CAN_IRQHandler // CEC and CAN + +// Default exception/interrupt handler + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDT_IRQHandler + .thumb_set WWDT_IRQHandler,Default_Handler + + .weak PVD_VDDIO2_IRQHandler + .thumb_set PVD_VDDIO2_IRQHandler,Default_Handler + + .weak RTC_IRQHandler + .thumb_set RTC_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCM_CRS_IRQHandler + .thumb_set RCM_CRS_IRQHandler,Default_Handler + + .weak EINT0_1_IRQHandler + .thumb_set EINT0_1_IRQHandler,Default_Handler + + .weak EINT2_3_IRQHandler + .thumb_set EINT2_3_IRQHandler,Default_Handler + + .weak EINT4_15_IRQHandler + .thumb_set EINT4_15_IRQHandler,Default_Handler + + .weak TSC_IRQHandler + .thumb_set TSC_IRQHandler,Default_Handler + + .weak DMA1_CH1_IRQHandler + .thumb_set DMA1_CH1_IRQHandler,Default_Handler + + .weak DMA1_CH2_3_DMA2_CH1_2_IRQHandler + .thumb_set DMA1_CH2_3_DMA2_CH1_2_IRQHandler,Default_Handler + + .weak DMA1_CH4_7_DMA2_CH3_5_IRQHandler + .thumb_set DMA1_CH4_7_DMA2_CH3_5_IRQHandler,Default_Handler + + .weak ADC1_COMP_IRQHandler + .thumb_set ADC1_COMP_IRQHandler,Default_Handler + + .weak TMR1_BRK_UP_TRG_COM_IRQHandler + .thumb_set TMR1_BRK_UP_TRG_COM_IRQHandler,Default_Handler + + .weak TMR1_CC_IRQHandler + .thumb_set TMR1_CC_IRQHandler,Default_Handler + + .weak TMR2_IRQHandler + .thumb_set TMR2_IRQHandler,Default_Handler + + + .weak TMR3_IRQHandler + .thumb_set TMR3_IRQHandler,Default_Handler + + .weak TMR6_DAC_IRQHandler + .thumb_set TMR6_DAC_IRQHandler,Default_Handler + + .weak TMR7_IRQHandler + .thumb_set TMR7_IRQHandler,Default_Handler + + .weak TMR14_IRQHandler + .thumb_set TMR14_IRQHandler,Default_Handler + + .weak TMR15_IRQHandler + .thumb_set TMR15_IRQHandler,Default_Handler + + .weak TMR16_IRQHandler + .thumb_set TMR16_IRQHandler,Default_Handler + + .weak TMR17_IRQHandler + .thumb_set TMR17_IRQHandler,Default_Handler + + .weak I2C1_IRQHandler + .thumb_set I2C1_IRQHandler,Default_Handler + + .weak I2C2_IRQHandler + .thumb_set I2C2_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_8_IRQHandler + .thumb_set USART3_8_IRQHandler,Default_Handler + + .weak CEC_CAN_IRQHandler + .thumb_set CEC_CAN_IRQHandler,Default_Handler diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f030.s b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f030.s new file mode 100644 index 0000000000..ca63f71cfa --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f030.s @@ -0,0 +1,278 @@ +;/*! +; * @file startup_apm32f030.s +; * +; * @brief APM32F030 devices vector table for EWARM toolchain. +; * +; * @version V1.0.0 +; * +; * @date 2022-02-21 +; * +; * @attention +; * +; * Copyright (C) 2020-2022 Geehy Semiconductor +; * +; * You may not use this file except in compliance with the +; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). +; * +; * The program is only for reference, which is distributed in the hope +; * that it will be useful and instructional for customers to develop +; * their software. Unless required by applicable law or agreed to in +; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT +; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. +; * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions +; * and limitations under the License. +; */ + + MODULE ?cstartup + + 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 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDT_IRQHandler ; Window Watchdog + DCD 0 ; Reserved + DCD RTC_IRQHandler ; RTC through EXTI Line + DCD FLASH_IRQHandler ; FLASH + DCD RCM_IRQHandler ; RCC + DCD EINT0_1_IRQHandler ; EINT Line 0 and 1 + DCD EINT2_3_IRQHandler ; EINT Line 2 and 3 + DCD EINT4_15_IRQHandler ; EINT Line 4 to 15 + DCD 0 ; Reserved + DCD DMA1_CH1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_CH2_3_IRQHandler ; DMA1 Channel 2 and Channel 3 + DCD DMA1_CH4_5_IRQHandler ; DMA1 Channel 4 and Channel 5 + DCD ADC1_IRQHandler ; ADC1 + DCD TMR1_BRK_UP_TRG_COM_IRQHandler ; TMR1 Break, Update, Trigger and Commutation + DCD TMR1_CC_IRQHandler ; TMR1 Capture Compare + DCD 0 ; Reserved + DCD TMR3_IRQHandler ; TMR3 + DCD TMR6_IRQHandler ; TMR6 + DCD TMR7_IRQHandler ; TMR7 + DCD TMR14_IRQHandler ; TMR14 + DCD TMR15_IRQHandler ; TMR15 + DCD TMR16_IRQHandler ; TMR16 + DCD TMR17_IRQHandler ; TMR17 + DCD I2C1_IRQHandler ; I2C1 + DCD I2C2_IRQHandler ; I2C2 + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_6_IRQHandler ; USART3,USART4,USART5,USART6 + + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + + LDR R0, =sfe(CSTACK) ; set stack pointer + MSR MSP, R0 + + LDR R0,=0x00000004 + LDR R1, [R0] + LSRS R1, R1, #24 + LDR R2,=0x1F + CMP R1, R2 + + BNE ApplicationStart + + LDR R0,=0x40021018 + LDR R1,=0x00000001 + STR R1, [R0] + + LDR R0,=0x40010000 + LDR R1,=0x00000000 + STR R1, [R0] +ApplicationStart + LDR R0, =SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDT_IRQHandler + B WWDT_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FLASH_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FLASH_IRQHandler + B FLASH_IRQHandler + + PUBWEAK RCM_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCM_IRQHandler + B RCM_IRQHandler + + PUBWEAK EINT0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT0_1_IRQHandler + B EINT0_1_IRQHandler + + PUBWEAK EINT2_3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT2_3_IRQHandler + B EINT2_3_IRQHandler + + PUBWEAK EINT4_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT4_15_IRQHandler + B EINT4_15_IRQHandler + + PUBWEAK DMA1_CH1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH1_IRQHandler + B DMA1_CH1_IRQHandler + + PUBWEAK DMA1_CH2_3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH2_3_IRQHandler + B DMA1_CH2_3_IRQHandler + + PUBWEAK DMA1_CH4_5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH4_5_IRQHandler + B DMA1_CH4_5_IRQHandler + + PUBWEAK ADC1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC1_IRQHandler + B ADC1_IRQHandler + + PUBWEAK TMR1_BRK_UP_TRG_COM_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR1_BRK_UP_TRG_COM_IRQHandler + B TMR1_BRK_UP_TRG_COM_IRQHandler + + PUBWEAK TMR1_CC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR1_CC_IRQHandler + B TMR1_CC_IRQHandler + + PUBWEAK TMR3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR3_IRQHandler + B TMR3_IRQHandler + + PUBWEAK TMR6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR6_IRQHandler + B TMR6_IRQHandler + + PUBWEAK TMR7_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR7_IRQHandler + B TMR7_IRQHandler + + PUBWEAK TMR14_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR14_IRQHandler + B TMR14_IRQHandler + + PUBWEAK TMR15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR15_IRQHandler + B TMR15_IRQHandler + + PUBWEAK TMR16_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR16_IRQHandler + B TMR16_IRQHandler + + PUBWEAK TMR17_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR17_IRQHandler + B TMR17_IRQHandler + + PUBWEAK I2C1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_IRQHandler + B I2C1_IRQHandler + + PUBWEAK I2C2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C2_IRQHandler + B I2C2_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK USART3_6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART3_6_IRQHandler + B USART3_6_IRQHandler + + END diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f051.s b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f051.s new file mode 100644 index 0000000000..db1f59d4ae --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f051.s @@ -0,0 +1,289 @@ +;/*! +; * @file startup_apm32f051.s +; * +; * @brief APM32F051 devices vector table for EWARM toolchain. +; * +; * @version V1.0.0 +; * +; * @date 2022-02-21 +; * +; * @attention +; * +; * Copyright (C) 2020-2022 Geehy Semiconductor +; * +; * You may not use this file except in compliance with the +; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). +; * +; * The program is only for reference, which is distributed in the hope +; * that it will be useful and instructional for customers to develop +; * their software. Unless required by applicable law or agreed to in +; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT +; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. +; * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions +; * and limitations under the License. +; */ + + MODULE ?cstartup + + 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 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDT_IRQHandler ; Window Watchdog + DCD PVD_IRQHandler ; PVD through EINT Line detect + DCD RTC_IRQHandler ; RTC through EXTI Line + DCD FLASH_IRQHandler ; FLASH + DCD RCM_IRQHandler ; RCC + DCD EINT0_1_IRQHandler ; EINT Line 0 and 1 + DCD EINT2_3_IRQHandler ; EINT Line 2 and 3 + DCD EINT4_15_IRQHandler ; EINT Line 4 to 15 + DCD TSC_IRQHandler ; TSC + DCD DMA1_CH1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_CH2_3_IRQHandler ; DMA1 Channel 2 and Channel 3 + DCD DMA1_CH4_5_IRQHandler ; DMA1 Channel 4 and Channel 5 + DCD ADC1_COMP_IRQHandler ; ADC1, COMP1 and COMP2 + DCD TMR1_BRK_UP_TRG_COM_IRQHandler ; TMR1 Break, Update, Trigger and Commutation + DCD TMR1_CC_IRQHandler ; TMR1 Capture Compare + DCD TMR2_IRQHandler ; TMR2 + DCD TMR3_IRQHandler ; TMR3 + DCD TMR6_DAC_IRQHandler ; TMR6 + DCD 0 ; Reserved + DCD TMR14_IRQHandler ; TMR14 + DCD TMR15_IRQHandler ; TMR15 + DCD TMR16_IRQHandler ; TMR16 + DCD TMR17_IRQHandler ; TMR17 + DCD I2C1_IRQHandler ; I2C1 + DCD I2C2_IRQHandler ; I2C2 + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD 0 ; Reserved + DCD CEC_IRQHandler ; CEC + + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + + LDR R0, =sfe(CSTACK) ; set stack pointer + MSR MSP, R0 + + LDR R0,=0x00000004 + LDR R1, [R0] + LSRS R1, R1, #24 + LDR R2,=0x1F + CMP R1, R2 + + BNE ApplicationStart + + LDR R0,=0x40021018 + LDR R1,=0x00000001 + STR R1, [R0] + + LDR R0,=0x40010000 + LDR R1,=0x00000000 + STR R1, [R0] +ApplicationStart + LDR R0, =SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDT_IRQHandler + B WWDT_IRQHandler + + PUBWEAK PVD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +PVD_IRQHandler + B PVD_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FLASH_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FLASH_IRQHandler + B FLASH_IRQHandler + + PUBWEAK RCM_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCM_IRQHandler + B RCM_IRQHandler + + PUBWEAK EINT0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT0_1_IRQHandler + B EINT0_1_IRQHandler + + PUBWEAK EINT2_3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT2_3_IRQHandler + B EINT2_3_IRQHandler + + PUBWEAK EINT4_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT4_15_IRQHandler + B EINT4_15_IRQHandler + + PUBWEAK TSC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TSC_IRQHandler + B TSC_IRQHandler + + PUBWEAK DMA1_CH1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH1_IRQHandler + B DMA1_CH1_IRQHandler + + PUBWEAK DMA1_CH2_3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH2_3_IRQHandler + B DMA1_CH2_3_IRQHandler + + PUBWEAK DMA1_CH4_5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH4_5_IRQHandler + B DMA1_CH4_5_IRQHandler + + PUBWEAK ADC1_COMP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC1_COMP_IRQHandler + B ADC1_COMP_IRQHandler + + PUBWEAK TMR1_BRK_UP_TRG_COM_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR1_BRK_UP_TRG_COM_IRQHandler + B TMR1_BRK_UP_TRG_COM_IRQHandler + + PUBWEAK TMR1_CC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR1_CC_IRQHandler + B TMR1_CC_IRQHandler + + PUBWEAK TMR2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR2_IRQHandler + B TMR2_IRQHandler + + PUBWEAK TMR3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR3_IRQHandler + B TMR3_IRQHandler + + PUBWEAK TMR6_DAC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR6_DAC_IRQHandler + B TMR6_DAC_IRQHandler + + PUBWEAK TMR14_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR14_IRQHandler + B TMR14_IRQHandler + + PUBWEAK TMR15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR15_IRQHandler + B TMR15_IRQHandler + + PUBWEAK TMR16_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR16_IRQHandler + B TMR16_IRQHandler + + PUBWEAK TMR17_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR17_IRQHandler + B TMR17_IRQHandler + + PUBWEAK I2C1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_IRQHandler + B I2C1_IRQHandler + + PUBWEAK I2C2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C2_IRQHandler + B I2C2_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK CEC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CEC_IRQHandler + B CEC_IRQHandler + + END diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f070.s b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f070.s new file mode 100644 index 0000000000..d86ef74edc --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f070.s @@ -0,0 +1,285 @@ +;/*! +; * @file startup_apm32f070.s +; * +; * @brief APM32F070 devices vector table for EWARM toolchain. +; * +; * @version V1.0.0 +; * +; * @date 2022-02-21 +; * +; * @attention +; * +; * Copyright (C) 2020-2022 Geehy Semiconductor +; * +; * You may not use this file except in compliance with the +; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). +; * +; * The program is only for reference, which is distributed in the hope +; * that it will be useful and instructional for customers to develop +; * their software. Unless required by applicable law or agreed to in +; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT +; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. +; * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions +; * and limitations under the License. +; */ + + MODULE ?cstartup + + 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 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDT_IRQHandler ; Window Watchdog + DCD 0 ; Reserved + DCD RTC_IRQHandler ; RTC through EXTI Line + DCD FLASH_IRQHandler ; FLASH + DCD RCM_IRQHandler ; RCC + DCD EINT0_1_IRQHandler ; EINT Line 0 and 1 + DCD EINT2_3_IRQHandler ; EINT Line 2 and 3 + DCD EINT4_15_IRQHandler ; EINT Line 4 to 15 + DCD 0 ; Reserved + DCD DMA1_CH1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_CH2_3_IRQHandler ; DMA1 Channel 2 and Channel 3 + DCD DMA1_CH4_5_IRQHandler ; DMA1 Channel 4 and Channel 5 + DCD ADC1_IRQHandler ; ADC1 + DCD TMR1_BRK_UP_TRG_COM_IRQHandler ; TMR1 Break, Update, Trigger and Commutation + DCD TMR1_CC_IRQHandler ; TMR1 Capture Compare + DCD 0 ; Reserved + DCD TMR3_IRQHandler ; TMR3 + DCD TMR6_IRQHandler ; TMR6 + DCD TMR7_IRQHandler ; TMR7 + DCD TMR14_IRQHandler ; TMR14 + DCD TMR15_IRQHandler ; TMR15 + DCD TMR16_IRQHandler ; TMR16 + DCD TMR17_IRQHandler ; TMR17 + DCD I2C1_IRQHandler ; I2C1 + DCD I2C2_IRQHandler ; I2C2 + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_4_IRQHandler ; USART3 and USART4 + DCD 0 ; Reserved + DCD USBD_IRQHandler ; USB + + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + + LDR R0, =sfe(CSTACK) ; set stack pointer + MSR MSP, R0 + + LDR R0,=0x00000004 + LDR R1, [R0] + LSRS R1, R1, #24 + LDR R2,=0x1F + CMP R1, R2 + + BNE ApplicationStart + + LDR R0,=0x40021018 + LDR R1,=0x00000001 + STR R1, [R0] + + LDR R0,=0x40010000 + LDR R1,=0x00000000 + STR R1, [R0] +ApplicationStart + LDR R0, =SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDT_IRQHandler + B WWDT_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FLASH_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FLASH_IRQHandler + B FLASH_IRQHandler + + PUBWEAK RCM_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCM_IRQHandler + B RCM_IRQHandler + + PUBWEAK EINT0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT0_1_IRQHandler + B EINT0_1_IRQHandler + + PUBWEAK EINT2_3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT2_3_IRQHandler + B EINT2_3_IRQHandler + + PUBWEAK EINT4_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT4_15_IRQHandler + B EINT4_15_IRQHandler + + PUBWEAK DMA1_CH1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH1_IRQHandler + B DMA1_CH1_IRQHandler + + PUBWEAK DMA1_CH2_3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH2_3_IRQHandler + B DMA1_CH2_3_IRQHandler + + PUBWEAK DMA1_CH4_5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH4_5_IRQHandler + B DMA1_CH4_5_IRQHandler + + PUBWEAK ADC1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC1_IRQHandler + B ADC1_IRQHandler + + PUBWEAK TMR1_BRK_UP_TRG_COM_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR1_BRK_UP_TRG_COM_IRQHandler + B TMR1_BRK_UP_TRG_COM_IRQHandler + + PUBWEAK TMR1_CC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR1_CC_IRQHandler + B TMR1_CC_IRQHandler + + PUBWEAK TMR3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR3_IRQHandler + B TMR3_IRQHandler + + PUBWEAK TMR6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR6_IRQHandler + B TMR6_IRQHandler + + PUBWEAK TMR7_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR7_IRQHandler + B TMR7_IRQHandler + + PUBWEAK TMR14_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR14_IRQHandler + B TMR14_IRQHandler + + PUBWEAK TMR15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR15_IRQHandler + B TMR15_IRQHandler + + PUBWEAK TMR16_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR16_IRQHandler + B TMR16_IRQHandler + + PUBWEAK TMR17_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR17_IRQHandler + B TMR17_IRQHandler + + PUBWEAK I2C1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_IRQHandler + B I2C1_IRQHandler + + PUBWEAK I2C2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C2_IRQHandler + B I2C2_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK USART3_4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART3_4_IRQHandler + B USART3_4_IRQHandler + + PUBWEAK USBD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_IRQHandler + B USBD_IRQHandler + + END diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f071.s b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f071.s new file mode 100644 index 0000000000..7fc1ba995b --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f071.s @@ -0,0 +1,299 @@ +;/*! +; * @file startup_apm32f071.s +; * +; * @brief APM32F071 devices vector table for EWARM toolchain. +; * +; * @version V1.0.0 +; * +; * @date 2022-02-21 +; * +; * @attention +; * +; * Copyright (C) 2020-2022 Geehy Semiconductor +; * +; * You may not use this file except in compliance with the +; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). +; * +; * The program is only for reference, which is distributed in the hope +; * that it will be useful and instructional for customers to develop +; * their software. Unless required by applicable law or agreed to in +; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT +; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. +; * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions +; * and limitations under the License. +; */ + + MODULE ?cstartup + + 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 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDT_IRQHandler ; Window Watchdog + DCD PVD_VDDIO2_IRQHandler ; PVD and VDDIO2 through EINT Line detect + DCD RTC_IRQHandler ; RTC through EXTI Line + DCD FLASH_IRQHandler ; FLASH + DCD RCM_IRQHandler ; RCC + DCD EINT0_1_IRQHandler ; EINT Line 0 and 1 + DCD EINT2_3_IRQHandler ; EINT Line 2 and 3 + DCD EINT4_15_IRQHandler ; EINT Line 4 to 15 + DCD TSC_IRQHandler ; TSC + DCD DMA1_CH1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_CH2_3_IRQHandler ; DMA1 Channel 2 and Channel 3 + DCD DMA1_CH4_5_6_7_IRQHandler ; DMA1 Channel 4, Channel 5, Channel 6 and Channel 7 + DCD ADC1_COMP_IRQHandler ; ADC1, COMP1 and COMP2 + DCD TMR1_BRK_UP_TRG_COM_IRQHandler ; TMR1 Break, Update, Trigger and Commutation + DCD TMR1_CC_IRQHandler ; TMR1 Capture Compare + DCD TMR2_IRQHandler ; TMR2 + DCD TMR3_IRQHandler ; TMR3 + DCD TMR6_DAC_IRQHandler ; TMR6 and DAC + DCD TMR7_IRQHandler ; TMR7 + DCD TMR14_IRQHandler ; TMR14 + DCD TMR15_IRQHandler ; TMR15 + DCD TMR16_IRQHandler ; TMR16 + DCD TMR17_IRQHandler ; TMR17 + DCD I2C1_IRQHandler ; I2C1 + DCD I2C2_IRQHandler ; I2C2 + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_4_IRQHandler ; USART3 and USART4 + DCD CEC_IRQHandler ; CEC + + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + + LDR R0, =sfe(CSTACK) ; set stack pointer + MSR MSP, R0 + + LDR R0,=0x00000004 + LDR R1, [R0] + LSRS R1, R1, #24 + LDR R2,=0x1F + CMP R1, R2 + + BNE ApplicationStart + + LDR R0,=0x40021018 + LDR R1,=0x00000001 + STR R1, [R0] + + LDR R0,=0x40010000 + LDR R1,=0x00000000 + STR R1, [R0] +ApplicationStart + LDR R0, =SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDT_IRQHandler + B WWDT_IRQHandler + + PUBWEAK PVD_VDDIO2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +PVD_VDDIO2_IRQHandler + B PVD_VDDIO2_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FLASH_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FLASH_IRQHandler + B FLASH_IRQHandler + + PUBWEAK RCM_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCM_IRQHandler + B RCM_IRQHandler + + PUBWEAK EINT0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT0_1_IRQHandler + B EINT0_1_IRQHandler + + PUBWEAK EINT2_3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT2_3_IRQHandler + B EINT2_3_IRQHandler + + PUBWEAK EINT4_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT4_15_IRQHandler + B EINT4_15_IRQHandler + + PUBWEAK TSC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TSC_IRQHandler + B TSC_IRQHandler + + PUBWEAK DMA1_CH1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH1_IRQHandler + B DMA1_CH1_IRQHandler + + PUBWEAK DMA1_CH2_3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH2_3_IRQHandler + B DMA1_CH2_3_IRQHandler + + PUBWEAK DMA1_CH4_5_6_7_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH4_5_6_7_IRQHandler + B DMA1_CH4_5_6_7_IRQHandler + + PUBWEAK ADC1_COMP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC1_COMP_IRQHandler + B ADC1_COMP_IRQHandler + + PUBWEAK TMR1_BRK_UP_TRG_COM_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR1_BRK_UP_TRG_COM_IRQHandler + B TMR1_BRK_UP_TRG_COM_IRQHandler + + PUBWEAK TMR1_CC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR1_CC_IRQHandler + B TMR1_CC_IRQHandler + + PUBWEAK TMR2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR2_IRQHandler + B TMR2_IRQHandler + + PUBWEAK TMR3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR3_IRQHandler + B TMR3_IRQHandler + + PUBWEAK TMR6_DAC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR6_DAC_IRQHandler + B TMR6_DAC_IRQHandler + + PUBWEAK TMR7_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR7_IRQHandler + B TMR7_IRQHandler + + PUBWEAK TMR14_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR14_IRQHandler + B TMR14_IRQHandler + + PUBWEAK TMR15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR15_IRQHandler + B TMR15_IRQHandler + + PUBWEAK TMR16_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR16_IRQHandler + B TMR16_IRQHandler + + PUBWEAK TMR17_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR17_IRQHandler + B TMR17_IRQHandler + + PUBWEAK I2C1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_IRQHandler + B I2C1_IRQHandler + + PUBWEAK I2C2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C2_IRQHandler + B I2C2_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK USART3_4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART3_4_IRQHandler + B USART3_4_IRQHandler + + PUBWEAK CEC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CEC_IRQHandler + B CEC_IRQHandler + + END diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f072.s b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f072.s new file mode 100644 index 0000000000..d43ad8cff7 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f072.s @@ -0,0 +1,305 @@ +;/*! +; * @file startup_apm32f072.s +; * +; * @brief APM32F072 devices vector table for EWARM toolchain. +; * +; * @version V1.0.0 +; * +; * @date 2022-02-21 +; * +; * @attention +; * +; * Copyright (C) 2020-2022 Geehy Semiconductor +; * +; * You may not use this file except in compliance with the +; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). +; * +; * The program is only for reference, which is distributed in the hope +; * that it will be useful and instructional for customers to develop +; * their software. Unless required by applicable law or agreed to in +; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT +; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. +; * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions +; * and limitations under the License. +; */ + + MODULE ?cstartup + + 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 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDT_IRQHandler ; Window Watchdog + DCD PVD_VDDIO2_IRQHandler ; PVD and VDDIO2 through EINT Line detect + DCD RTC_IRQHandler ; RTC through EXTI Line + DCD FLASH_IRQHandler ; FLASH + DCD RCM_CRS_IRQHandler ; RCM and CRS + DCD EINT0_1_IRQHandler ; EINT Line 0 and 1 + DCD EINT2_3_IRQHandler ; EINT Line 2 and 3 + DCD EINT4_15_IRQHandler ; EINT Line 4 to 15 + DCD TSC_IRQHandler ; TSC + DCD DMA1_CH1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_CH2_3_IRQHandler ; DMA1 Channel 2 and Channel 3 + DCD DMA1_CH4_5_6_7_IRQHandler ; DMA1 Channel 4, Channel 5, Channel 6 and Channel 7 + DCD ADC1_COMP_IRQHandler ; ADC1, COMP1 and COMP2 + DCD TMR1_BRK_UP_TRG_COM_IRQHandler ; TMR1 Break, Update, Trigger and Commutation + DCD TMR1_CC_IRQHandler ; TMR1 Capture Compare + DCD TMR2_IRQHandler ; TMR2 + DCD TMR3_IRQHandler ; TMR3 + DCD TMR6_DAC_IRQHandler ; TMR6 and DAC + DCD TMR7_IRQHandler ; TMR7 + DCD TMR14_IRQHandler ; TMR14 + DCD TMR15_IRQHandler ; TMR15 + DCD TMR16_IRQHandler ; TMR16 + DCD TMR17_IRQHandler ; TMR17 + DCD I2C1_IRQHandler ; I2C1 + DCD I2C2_IRQHandler ; I2C2 + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_4_IRQHandler ; USART3 and USART4 + DCD CEC_CAN_IRQHandler ; CEC and CAN + DCD USBD_IRQHandler ; USB + + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + + LDR R0, =sfe(CSTACK) ; set stack pointer + MSR MSP, R0 + + LDR R0,=0x00000004 + LDR R1, [R0] + LSRS R1, R1, #24 + LDR R2,=0x1F + CMP R1, R2 + + BNE ApplicationStart + + LDR R0,=0x40021018 + LDR R1,=0x00000001 + STR R1, [R0] + + LDR R0,=0x40010000 + LDR R1,=0x00000000 + STR R1, [R0] +ApplicationStart + LDR R0, =SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDT_IRQHandler + B WWDT_IRQHandler + + PUBWEAK PVD_VDDIO2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +PVD_VDDIO2_IRQHandler + B PVD_VDDIO2_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FLASH_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FLASH_IRQHandler + B FLASH_IRQHandler + + PUBWEAK RCM_CRS_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCM_CRS_IRQHandler + B RCM_CRS_IRQHandler + + PUBWEAK EINT0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT0_1_IRQHandler + B EINT0_1_IRQHandler + + PUBWEAK EINT2_3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT2_3_IRQHandler + B EINT2_3_IRQHandler + + PUBWEAK EINT4_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT4_15_IRQHandler + B EINT4_15_IRQHandler + + PUBWEAK TSC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TSC_IRQHandler + B TSC_IRQHandler + + PUBWEAK DMA1_CH1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH1_IRQHandler + B DMA1_CH1_IRQHandler + + PUBWEAK DMA1_CH2_3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH2_3_IRQHandler + B DMA1_CH2_3_IRQHandler + + PUBWEAK DMA1_CH4_5_6_7_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH4_5_6_7_IRQHandler + B DMA1_CH4_5_6_7_IRQHandler + + PUBWEAK ADC1_COMP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC1_COMP_IRQHandler + B ADC1_COMP_IRQHandler + + PUBWEAK TMR1_BRK_UP_TRG_COM_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR1_BRK_UP_TRG_COM_IRQHandler + B TMR1_BRK_UP_TRG_COM_IRQHandler + + PUBWEAK TMR1_CC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR1_CC_IRQHandler + B TMR1_CC_IRQHandler + + PUBWEAK TMR2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR2_IRQHandler + B TMR2_IRQHandler + + PUBWEAK TMR3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR3_IRQHandler + B TMR3_IRQHandler + + PUBWEAK TMR6_DAC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR6_DAC_IRQHandler + B TMR6_DAC_IRQHandler + + PUBWEAK TMR7_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR7_IRQHandler + B TMR7_IRQHandler + + PUBWEAK TMR14_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR14_IRQHandler + B TMR14_IRQHandler + + PUBWEAK TMR15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR15_IRQHandler + B TMR15_IRQHandler + + PUBWEAK TMR16_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR16_IRQHandler + B TMR16_IRQHandler + + PUBWEAK TMR17_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR17_IRQHandler + B TMR17_IRQHandler + + PUBWEAK I2C1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_IRQHandler + B I2C1_IRQHandler + + PUBWEAK I2C2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C2_IRQHandler + B I2C2_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK USART3_4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART3_4_IRQHandler + B USART3_4_IRQHandler + + PUBWEAK CEC_CAN_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CEC_CAN_IRQHandler + B CEC_CAN_IRQHandler + + PUBWEAK USBD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_IRQHandler + B USBD_IRQHandler + + END diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f091.s b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f091.s new file mode 100644 index 0000000000..8d1497a489 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/iar/startup_apm32f091.s @@ -0,0 +1,299 @@ +;/*! +; * @file startup_apm32f091.s +; * +; * @brief APM32F091 devices vector table for EWARM toolchain. +; * +; * @version V1.0.0 +; * +; * @date 2022-02-21 +; * +; * @attention +; * +; * Copyright (C) 2020-2022 Geehy Semiconductor +; * +; * You may not use this file except in compliance with the +; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). +; * +; * The program is only for reference, which is distributed in the hope +; * that it will be useful and instructional for customers to develop +; * their software. Unless required by applicable law or agreed to in +; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT +; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. +; * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions +; * and limitations under the License. +; */ + + MODULE ?cstartup + + 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 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDT_IRQHandler ; Window Watchdog + DCD PVD_VDDIO2_IRQHandler ; PVD and VDDIO2 through EINT Line detect + DCD RTC_IRQHandler ; RTC through EXTI Line + DCD FLASH_IRQHandler ; FLASH + DCD RCM_CRS_IRQHandler ; RCM and CRS + DCD EINT0_1_IRQHandler ; EINT Line 0 and 1 + DCD EINT2_3_IRQHandler ; EINT Line 2 and 3 + DCD EINT4_15_IRQHandler ; EINT Line 4 to 15 + DCD TSC_IRQHandler ; TSC + DCD DMA1_CH1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_CH2_3_DMA2_CH1_2_IRQHandler ; DMA1 Channel 2 and 3 DMA2 Channel 1 and 2 + DCD DMA1_CH4_7_DMA2_CH3_5_IRQHandler ; DMA1 Channel 4 to 7 DMA2 Channel 3 to 5 Interrupts + DCD ADC1_COMP_IRQHandler ; ADC1, COMP1 and COMP2 + DCD TMR1_BRK_UP_TRG_COM_IRQHandler ; TMR1 Break, Update, Trigger and Commutation + DCD TMR1_CC_IRQHandler ; TMR1 Capture Compare + DCD TMR2_IRQHandler ; TMR2 + DCD TMR3_IRQHandler ; TMR3 + DCD TMR6_DAC_IRQHandler ; TMR6 and DAC + DCD TMR7_IRQHandler ; TMR7 + DCD TMR14_IRQHandler ; TMR14 + DCD TMR15_IRQHandler ; TMR15 + DCD TMR16_IRQHandler ; TMR16 + DCD TMR17_IRQHandler ; TMR17 + DCD I2C1_IRQHandler ; I2C1 + DCD I2C2_IRQHandler ; I2C2 + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_4_IRQHandler ; USART3 and USART4 + DCD CEC_CAN_IRQHandler ; CEC and CAN + + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + + LDR R0, =sfe(CSTACK) ; set stack pointer + MSR MSP, R0 + + LDR R0,=0x00000004 + LDR R1, [R0] + LSRS R1, R1, #24 + LDR R2,=0x1F + CMP R1, R2 + + BNE ApplicationStart + + LDR R0,=0x40021018 + LDR R1,=0x00000001 + STR R1, [R0] + + LDR R0,=0x40010000 + LDR R1,=0x00000000 + STR R1, [R0] +ApplicationStart + LDR R0, =SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDT_IRQHandler + B WWDT_IRQHandler + + PUBWEAK PVD_VDDIO2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +PVD_VDDIO2_IRQHandler + B PVD_VDDIO2_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FLASH_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FLASH_IRQHandler + B FLASH_IRQHandler + + PUBWEAK RCM_CRS_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCM_CRS_IRQHandler + B RCM_CRS_IRQHandler + + PUBWEAK EINT0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT0_1_IRQHandler + B EINT0_1_IRQHandler + + PUBWEAK EINT2_3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT2_3_IRQHandler + B EINT2_3_IRQHandler + + PUBWEAK EINT4_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EINT4_15_IRQHandler + B EINT4_15_IRQHandler + + PUBWEAK TSC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TSC_IRQHandler + B TSC_IRQHandler + + PUBWEAK DMA1_CH1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH1_IRQHandler + B DMA1_CH1_IRQHandler + + PUBWEAK DMA1_CH2_3_DMA2_CH1_2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH2_3_DMA2_CH1_2_IRQHandler + B DMA1_CH2_3_DMA2_CH1_2_IRQHandler + + PUBWEAK DMA1_CH4_7_DMA2_CH3_5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_CH4_7_DMA2_CH3_5_IRQHandler + B DMA1_CH4_7_DMA2_CH3_5_IRQHandler + + PUBWEAK ADC1_COMP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC1_COMP_IRQHandler + B ADC1_COMP_IRQHandler + + PUBWEAK TMR1_BRK_UP_TRG_COM_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR1_BRK_UP_TRG_COM_IRQHandler + B TMR1_BRK_UP_TRG_COM_IRQHandler + + PUBWEAK TMR1_CC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR1_CC_IRQHandler + B TMR1_CC_IRQHandler + + PUBWEAK TMR2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR2_IRQHandler + B TMR2_IRQHandler + + PUBWEAK TMR3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR3_IRQHandler + B TMR3_IRQHandler + + PUBWEAK TMR6_DAC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR6_DAC_IRQHandler + B TMR6_DAC_IRQHandler + + PUBWEAK TMR7_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR7_IRQHandler + B TMR7_IRQHandler + + PUBWEAK TMR14_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR14_IRQHandler + B TMR14_IRQHandler + + PUBWEAK TMR15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR15_IRQHandler + B TMR15_IRQHandler + + PUBWEAK TMR16_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR16_IRQHandler + B TMR16_IRQHandler + + PUBWEAK TMR17_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TMR17_IRQHandler + B TMR17_IRQHandler + + PUBWEAK I2C1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_IRQHandler + B I2C1_IRQHandler + + PUBWEAK I2C2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C2_IRQHandler + B I2C2_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK USART3_4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART3_4_IRQHandler + B USART3_4_IRQHandler + + PUBWEAK CEC_CAN_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CEC_CAN_IRQHandler + B CEC_CAN_IRQHandler + + END diff --git a/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/system_apm32f0xx.c b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/system_apm32f0xx.c new file mode 100644 index 0000000000..d84a74de3c --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/Device/Geehy/APM32F0xx/Source/system_apm32f0xx.c @@ -0,0 +1,444 @@ +/*! + * @file system_apm32f0xx.c + * + * @brief CMSIS Cortex-M0+ Device Peripheral Access Layer System Source File + * + * @version V1.0.3 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "apm32f0xx.h" + +/** @addtogroup CMSIS + @{ +*/ + +/** @addtogroup APM32F0xx_System + @{ +*/ + +/** @defgroup System_Macros Macros + @{ + */ + +/* HSE is used as system clock source */ +//#define SYSTEM_CLOCK_HSE HSE_VALUE + +/* HSE (8MHz) used to clock the PLL, and the PLL is used as system clock source */ +//#define SYSTEM_CLOCK_24MHz (24000000) +//#define SYSTEM_CLOCK_36MHz (36000000) +#define SYSTEM_CLOCK_48MHz (48000000) + +//#define VECT_TAB_SRAM +/* Vector Table base offset field. This value must be a multiple of 0x200. */ +#define VECT_TAB_OFFSET 0x00 + +/**@} end of group System_Macros */ + +/** @defgroup System_Enumerations Enumerations + @{ + */ + +/**@} end of group System_Enumerations */ + +/** @defgroup System_Structures Structures + @{ + */ + +/**@} end of group System_Structures */ + +/** @defgroup System_Variables Variables + @{ + */ + +#ifdef SYSTEM_CLOCK_HSE + uint32_t SystemCoreClock = SYSTEM_CLOCK_HSE; +#elif defined SYSTEM_CLOCK_24MHz + uint32_t SystemCoreClock = SYSTEM_CLOCK_24MHz; +#elif defined SYSTEM_CLOCK_36MHz + uint32_t SystemCoreClock = SYSTEM_CLOCK_36MHz; +#elif defined SYSTEM_CLOCK_48MHz + uint32_t SystemCoreClock = SYSTEM_CLOCK_48MHz; +#else + uint32_t SystemCoreClock = HSI_VALUE; +#endif + +static void SystemClockConfig(void); + +#ifdef SYSTEM_CLOCK_HSE + static void SystemClockHSE(void); +#elif defined SYSTEM_CLOCK_24MHz + static void SystemClock24M(void); +#elif defined SYSTEM_CLOCK_36MHz + static void SystemClock36M(void); +#elif defined SYSTEM_CLOCK_48MHz + static void SystemClock48M(void); + +#endif + +/**@} end of group System_Variables */ + +/** @defgroup System_Functions Functions + @{ + */ + +/*! + * @brief Setup the microcontroller system + * + * @param None + * + * @retval None + * + * @note + */ +void SystemInit(void) +{ + /* Set HSIEN bit */ + RCM->CTRL1_B.HSIEN = BIT_SET; + /* Reset SCLKSEL, AHBPSC, APB1PSC, APB2PSC, ADCPSC and COC bits */ + RCM->CFG1 &= (uint32_t)0x08FFB80CU; + /* Reset HSEEN, CSSEN and PLLEN bits */ + RCM->CTRL1 &= (uint32_t)0xFEF6FFFFU; + /* Reset HSEBCFG bit */ + RCM->CTRL1_B.HSEBCFG = BIT_RESET; + /* Reset PLLSRCSEL, PLLHSEPSC, PLLMULCFG bits */ + RCM->CFG1 &= (uint32_t)0xFFC0FFFFU; + /* Reset PREDIV[3:0] bits */ + RCM->CFG1 &= (uint32_t)0xFFFFFFF0U; + /* Reset USARTSW[1:0], I2CSW, CECSW and ADCSW bits */ + RCM->CFG3 &= (uint32_t)0xFFFFFEAC; + /* Reset HSI14 bit */ + RCM->CTRL2_B.HSI14EN = BIT_RESET; + /* Disable all interrupts */ + RCM->INT = 0x00000000U; + + SystemClockConfig(); + +#ifdef VECT_TAB_SRAM + SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; +#else + SCB->VTOR = FMC_BASE | VECT_TAB_OFFSET; +#endif +} + +/*! + * @brief Update SystemCoreClock variable according to Clock Register Values + * The SystemCoreClock variable contains the core clock (HCLK) + * + * @param None + * + * @retval None + * + * @note + */ +void SystemCoreClockUpdate(void) +{ + uint32_t sysClock, pllMull, pllSource, Prescaler; + uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + + /* Get SYSCLK source */ + sysClock = RCM->CFG1_B.SCLKSWSTS; + + switch (sysClock) + { + case 0: + SystemCoreClock = HSI_VALUE; + break; + + /* sys clock is HSE */ + case 1: + SystemCoreClock = HSE_VALUE; + break; + + /* sys clock is PLL */ + case 2: + pllMull = RCM->CFG1_B.PLLMULCFG + 2; + pllSource = RCM->CFG1_B.PLLSRCSEL; + + /* PLL entry clock source is HSE */ + if (pllSource == 2) + { + SystemCoreClock = HSE_VALUE * pllMull; + + /* HSE clock divided by 2 */ + if (pllSource == RCM->CFG1_B.PLLHSEPSC) + { + SystemCoreClock >>= 1; + } + } + /* PLL entry clock source is HSI/2 */ + else + { + SystemCoreClock = (HSI_VALUE >> 1) * pllMull; + } + + break; + + default: + SystemCoreClock = HSI_VALUE; + break; + } + + Prescaler = AHBPrescTable[(RCM->CFG1_B.AHBPSC)]; + SystemCoreClock >>= Prescaler; +} +/*! + * @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers + * + * @param None + * + * @retval None + * + * @note + */ +static void SystemClockConfig(void) +{ +#ifdef SYSTEM_CLOCK_HSE + SystemClockHSE(); +#elif defined SYSTEM_CLOCK_24MHz + SystemClock24M(); +#elif defined SYSTEM_CLOCK_36MHz + SystemClock36M(); +#elif defined SYSTEM_CLOCK_48MHz + SystemClock48M(); +#endif +} + +#if defined SYSTEM_CLOCK_HSE + +/*! + * @brief Selects HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers + * + * @param None + * + * @retval None + * + * @note + */ +static void SystemClockHSE(void) +{ + uint32_t i; + + RCM->CTRL1_B.HSEEN = BIT_SET; + + for (i = 0; i < HSE_STARTUP_TIMEOUT; i++) + { + if (RCM->CTRL1_B.HSERDYFLG) + { + break; + } + } + + if (RCM->CTRL1_B.HSERDYFLG) + { + /* Enable Prefetch Buffer */ + FMC->CTRL1_B.PBEN = BIT_SET; + /* Flash 0 wait state */ + FMC->CTRL1_B.WS = 0; + + /* HCLK = SYSCLK */ + RCM->CFG1_B.AHBPSC = 0X00; + + /* PCLK = HCLK */ + RCM->CFG1_B.APB1PSC = 0X00; + + /* Select HSE as system clock source */ + RCM->CFG1_B.SCLKSEL = 1; + + /* Wait till HSE is used as system clock source */ + while (RCM->CFG1_B.SCLKSWSTS != 0x01); + } +} + +#elif defined SYSTEM_CLOCK_24MHz + +/*! + * @brief Sets System clock frequency to 24MHz and configure HCLK, PCLK2 and PCLK1 prescalers + * + * @param None + * + * @retval None + * + * @note + */ +static void SystemClock24M(void) +{ + uint32_t i; + + RCM->CTRL1_B.HSEEN = BIT_SET; + + for (i = 0; i < HSE_STARTUP_TIMEOUT; i++) + { + if (RCM->CTRL1_B.HSERDYFLG) + { + break; + } + } + + if (RCM->CTRL1_B.HSERDYFLG) + { + /* Enable Prefetch Buffer */ + FMC->CTRL1_B.PBEN = BIT_SET; + /* Flash 1 wait state */ + FMC->CTRL1_B.WS = 1; + + /* HCLK = SYSCLK */ + RCM->CFG1_B.AHBPSC = 0X00; + + /* PCLK = HCLK */ + RCM->CFG1_B.APB1PSC = 0X00; + + /* PLL: (HSE / 2) * 6 */ + RCM->CFG1_B.PLLSRCSEL = 2; + RCM->CFG1_B.PLLHSEPSC = 1; + RCM->CFG1_B.PLLMULCFG = 4; + + /* Enable PLL */ + RCM->CTRL1_B.PLLEN = 1; + + /* Wait PLL Ready */ + while (RCM->CTRL1_B.PLLRDYFLG == BIT_RESET); + + /* Select PLL as system clock source */ + RCM->CFG1_B.SCLKSEL = 2; + + /* Wait till PLL is used as system clock source */ + while (RCM->CFG1_B.SCLKSWSTS != 0x02); + } +} + +#elif defined SYSTEM_CLOCK_36MHz + +/*! + * @brief Sets System clock frequency to 36MHz and configure HCLK, PCLK2 and PCLK1 prescalers + * + * @param None + * + * @retval None + * + * @note + */ +static void SystemClock36M(void) +{ + uint32_t i; + + RCM->CTRL1_B.HSEEN = BIT_SET; + + for (i = 0; i < HSE_STARTUP_TIMEOUT; i++) + { + if (RCM->CTRL1_B.HSERDYFLG) + { + break; + } + } + + if (RCM->CTRL1_B.HSERDYFLG) + { + /* Enable Prefetch Buffer */ + FMC->CTRL1_B.PBEN = BIT_SET; + /* Flash 1 wait state */ + FMC->CTRL1_B.WS = 1; + + /* HCLK = SYSCLK */ + RCM->CFG1_B.AHBPSC = 0X00; + + /* PCLK = HCLK */ + RCM->CFG1_B.APB1PSC = 0X00; + + /* PLL: (HSE / 2) * 9 */ + RCM->CFG1_B.PLLSRCSEL = 2; + RCM->CFG1_B.PLLHSEPSC = 1; + RCM->CFG1_B.PLLMULCFG = 7; + + /* Enable PLL */ + RCM->CTRL1_B.PLLEN = 1; + + /* Wait PLL Ready */ + while (RCM->CTRL1_B.PLLRDYFLG == BIT_RESET); + + /* Select PLL as system clock source */ + RCM->CFG1_B.SCLKSEL = 2; + + /* Wait till PLL is used as system clock source */ + while (RCM->CFG1_B.SCLKSWSTS != 0x02); + } +} + +#elif defined SYSTEM_CLOCK_48MHz + +/*! + * @brief Sets System clock frequency to 46MHz and configure HCLK, PCLK2 and PCLK1 prescalers + * + * @param None + * + * @retval None + * + * @note + */ +static void SystemClock48M(void) +{ + uint32_t i; + + RCM->CTRL1_B.HSEEN = BIT_SET; + + for (i = 0; i < HSE_STARTUP_TIMEOUT; i++) + { + if (RCM->CTRL1_B.HSERDYFLG) + { + break; + } + } + + if (RCM->CTRL1_B.HSERDYFLG) + { + /* Enable Prefetch Buffer */ + FMC->CTRL1_B.PBEN = BIT_SET; + /* Flash 1 wait state */ + FMC->CTRL1_B.WS = 1; + + /* HCLK = SYSCLK */ + RCM->CFG1_B.AHBPSC = 0X00; + + /* PCLK = HCLK */ + RCM->CFG1_B.APB1PSC = 0X00; + + /* PLL: HSE * 6 */ + RCM->CFG1_B.PLLSRCSEL = 2; + RCM->CFG1_B.PLLMULCFG = 4; + + /* Enable PLL */ + RCM->CTRL1_B.PLLEN = 1; + + /* Wait PLL Ready */ + while (RCM->CTRL1_B.PLLRDYFLG == BIT_RESET); + + /* Select PLL as system clock source */ + RCM->CFG1_B.SCLKSEL = 2; + + /* Wait till PLL is used as system clock source */ + while (RCM->CFG1_B.SCLKSWSTS != 0x02); + } +} + +#endif + +/**@} end of group System_Functions */ +/**@} end of group APM32F0xx_System */ +/**@} end of group CMSIS */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/SConscript b/bsp/apm32/libraries/APM32F0xx_Library/SConscript new file mode 100644 index 0000000000..fe845e860f --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/SConscript @@ -0,0 +1,49 @@ +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(""" +Device/Geehy/APM32F0xx/Source/system_apm32f0xx.c +APM32F0xx_StdPeriphDriver/src/apm32f0xx_gpio.c +APM32F0xx_StdPeriphDriver/src/apm32f0xx_syscfg.c +APM32F0xx_StdPeriphDriver/src/apm32f0xx_misc.c +APM32F0xx_StdPeriphDriver/src/apm32f0xx_rcm.c +APM32F0xx_StdPeriphDriver/src/apm32f0xx_usart.c +APM32F0xx_StdPeriphDriver/src/apm32f0xx_eint.c +""") + +if GetDepend(['RT_USING_ADC']): + src += ['APM32F0xx_StdPeriphDriver/src/apm32f0xx_adc.c'] + +if GetDepend(['RT_USING_DAC']): + src += ['APM32F0xx_StdPeriphDriver/src/apm32f0xx_dac.c'] + +if GetDepend(['RT_USING_RTC']): + src += ['APM32F0xx_StdPeriphDriver/src/apm32f0xx_rtc.c'] + src += ['APM32F0xx_StdPeriphDriver/src/apm32f0xx_pmu.c'] + +if GetDepend(['RT_USING_SPI']): + src += ['APM32F0xx_StdPeriphDriver/src/apm32f0xx_spi.c'] + +if GetDepend(['RT_USING_HWTIMER']) or GetDepend(['RT_USING_PWM']): + src += ['APM32F0xx_StdPeriphDriver/src/apm32f0xx_tmr.c'] + +if GetDepend(['RT_USING_WDT']): + src += ['APM32F0xx_StdPeriphDriver/src/apm32f0xx_wwdt.c'] + src += ['APM32F0xx_StdPeriphDriver/src/apm32f0xx_iwdt.c'] + +if GetDepend(['RT_USING_CAN']): + src += ['APM32F0xx_StdPeriphDriver/src/apm32f0xx_can.c'] + +path = [cwd + '/Device/Geehy/APM32F0xx/Include', + cwd + '/APM32F0xx_StdPeriphDriver/inc', + cwd + '/CMSIS/Include'] + +CPPDEFINES = ['USE_STDPERIPH_DRIVER'] +group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc.h b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc.h new file mode 100644 index 0000000000..e61692fa6b --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc.h @@ -0,0 +1,135 @@ +/*! + * @file tsc.h + * + * @brief This file contains external declarations of the tsc.c file. + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __TSC_H +#define __TSC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes */ +#include "tsc_acq.h" +#include "tsc_time.h" +#include "tsc_touchkey.h" +#include "tsc_linrot.h" +#include "tsc_object.h" +#include "tsc_dxs.h" +#include "tsc_ecs.h" +#include "tsc_filter.h" + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_Driver TSC Driver + @{ +*/ + +/** @defgroup TSC_Macros Macros + @{ +*/ + +/**@} end of group TSC_Macros */ + +/** @defgroup TSC_Enumerations Enumerations + @{ +*/ + +/**@} end of group TSC_Enumerations */ + +/** @defgroup TSC_Structures Structures + @{ +*/ + +/** + * @brief Store all global variables shared between the Touch Driver and the Application. + */ +typedef struct +{ + TSC_tTick_ms_T Tick_ms; /*!< Incremented each 0.5ms by timing interrupt routine */ + TSC_tTick_sec_T Tick_sec; /*!< Incremented each second by timing interrupt routine */ + CONST TSC_Block_T* Block_Array; /*!< Pointer to the array containing all Blocks */ + TSC_tIndex_T For_Block; /*!< Pointer to the current Block */ + CONST TSC_Object_T* For_Obj; /*!< Pointer to the current Object */ +#if TOUCH_USE_ZONE > 0 + CONST TSC_Zone_T* For_Zone; /*!< Pointer to the current Zone */ + TSC_tIndex_T Index_For_Zone; /*!< Index in the current Zone */ +#endif +#if TOUCH_TOTAL_KEYS > 0 + CONST TSC_TouchKey_T* For_Key; /*!< Pointer to the current Touch Key */ +#endif +#if TOUCH_TOTAL_LNRTS > 0 + CONST TSC_LinRot_T* For_LinRot; /*!< Pointer to the current Linear or Rotary sensor */ +#endif +} TSC_Globals_T; + +/** + * @brief Store all global parametersshared between the Touch Driver and the Application. + * @warning Only one variable of this structure type must be created and be placed in RAM only. + */ +typedef struct +{ + TSC_tMeas_T AcqMin; /*!< Acquisition minimum limit */ + TSC_tMeas_T AcqMax; /*!< Acquisition maximum limit */ + TSC_tNum_T NumCalibSample; /*!< Number of Calibration samples */ + TSC_tTick_sec_T DTO; /*!< Detection Time Out */ +#if TOUCH_TOTAL_KEYS > 0 + CONST TSC_State_T* p_KeySta; /*!< Default state machine for TouchKey sensors */ + CONST TSC_TouchKeyMethods_T* p_KeyMet; /*!< Default methods for TouchKey sensors */ +#endif +#if TOUCH_TOTAL_LNRTS > 0 + CONST TSC_State_T* p_LinRotSta; /*!< Default state machine for Linear/Rotary sensors */ + CONST TSC_LinRotMethods_T* p_LinRotMet; /*!< Default methods for Linear/Rotary sensors */ +#endif +} TSC_Params_T; + +/**@} end of group TSC_Structures */ + +/** @defgroup TSC_Variables Variables + @{ +*/ + +extern TSC_Globals_T TSC_Globals; +extern TSC_Params_T TSC_Params; + +/**@} end of group TSC_Variables */ + +/** @defgroup TSC_Functions Functions + @{ +*/ + +TSC_STATUS_T TSC_Config(CONST TSC_Block_T* block); + +#ifdef __cplusplus +} +#endif + +#endif /* __TSC_H */ + +/**@} end of group TSC_Functions */ +/**@} end of group TSC_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_acq.h b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_acq.h new file mode 100644 index 0000000000..8947832695 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_acq.h @@ -0,0 +1,253 @@ +/*! + * @file tsc_acq.h + * + * @brief This file contains external declarations of the tsc_acq.c file. + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __TSC_ACQ_H +#define __TSC_ACQ_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes */ +#include "apm32f0xx.h" +#include "tsc_config.h" +#include "tsc_types.h" +#include "apm32f0xx_gpio.h" +#include "apm32f0xx_rcm.h" + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_Acquisition_Driver TSC Acquisition Driver + @{ +*/ + +#if !defined(APM32F051) && defined(APM32F071) && defined(APM32F072) && defined(APM32F091) +#error "Device family not declared in the toolchain compiler preprocessor." +#endif + +/** @defgroup TSC_Acquisition_Macros Macros + @{ + */ + +#ifndef CONST +#define CONST const +#endif + +/* SysTick enable/disable interrupt macros */ +#define enableInterrupts() {SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;} +#define disableInterrupts() {SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;} + +#define TSC_NB_GROUPS (8) + +#define TSC_GROUP1 (0x01) +#define TSC_GROUP2 (0x02) +#define TSC_GROUP3 (0x04) +#define TSC_GROUP4 (0x08) +#define TSC_GROUP5 (0x10) +#define TSC_GROUP6 (0x20) +#define TSC_GROUP7 (0x40) +#define TSC_GROUP8 (0x80) + +/* GxIOy masks */ +#define TSC_GROUP1_IO1 (0x00000001) +#define TSC_GROUP1_IO2 (0x00000002) +#define TSC_GROUP1_IO3 (0x00000004) +#define TSC_GROUP1_IO4 (0x00000008) +#define TSC_GROUP2_IO1 (0x00000010) +#define TSC_GROUP2_IO2 (0x00000020) +#define TSC_GROUP2_IO3 (0x00000040) +#define TSC_GROUP2_IO4 (0x00000080) +#define TSC_GROUP3_IO1 (0x00000100) +#define TSC_GROUP3_IO2 (0x00000200) +#define TSC_GROUP3_IO3 (0x00000400) +#define TSC_GROUP3_IO4 (0x00000800) +#define TSC_GROUP4_IO1 (0x00001000) +#define TSC_GROUP4_IO2 (0x00002000) +#define TSC_GROUP4_IO3 (0x00004000) +#define TSC_GROUP4_IO4 (0x00008000) +#define TSC_GROUP5_IO1 (0x00010000) +#define TSC_GROUP5_IO2 (0x00020000) +#define TSC_GROUP5_IO3 (0x00040000) +#define TSC_GROUP5_IO4 (0x00080000) +#define TSC_GROUP6_IO1 (0x00100000) +#define TSC_GROUP6_IO2 (0x00200000) +#define TSC_GROUP6_IO3 (0x00400000) +#define TSC_GROUP6_IO4 (0x00800000) +#define TSC_GROUP7_IO1 (0x01000000) +#define TSC_GROUP7_IO2 (0x02000000) +#define TSC_GROUP7_IO3 (0x04000000) +#define TSC_GROUP7_IO4 (0x08000000) +#define TSC_GROUP8_IO1 (0x10000000) +#define TSC_GROUP8_IO2 (0x20000000) +#define TSC_GROUP8_IO3 (0x40000000) +#define TSC_GROUP8_IO4 (0x80000000) + +/* Exported types, For all devices/acquisitions */ +typedef uint16_t TSC_tMeas_T; /*!< Measurement */ +typedef uint16_t TSC_tRefer_T; /*!< Reference */ +typedef int16_t TSC_tDelta_T; /*!< Delta */ + +typedef uint8_t TSC_tIndexSrc_T; /*!< Channel source index */ +typedef uint16_t TSC_tIndexDest_T; /*!< Channel destination index */ + +typedef uint8_t TSC_tRefRest_T; /*!< Reference Rest (ECS) */ +typedef uint16_t TSC_tKCoeff_T; /*!< K coefficient (ECS) */ + +typedef uint8_t TSC_tIndex_T; /*!< Generic index */ +typedef uint16_t TSC_tNum_T; /*!< Generic number */ +typedef uint8_t TSC_tCounter_T; /*!< Generic counter used for debounce */ + +typedef uint8_t TSC_tThreshold_T; /*!< Delta threshold */ + +typedef int16_t TSC_tPosition_T; /*!< Linear and Rotary sensors position */ +typedef uint8_t TSC_tsignPosition_T; /*!< Linear and Rotary sensors position */ + +typedef uint16_t TSC_tTick_ms_T; /*!< Time in ms */ +typedef uint8_t TSC_tTick_sec_T; /*!< Time in sec */ + +/**@} end of group TSC_Acquisition_Macros */ + +/** @defgroup TSC_Acquisition_Enumerations Enumerations + @{ + */ + +/**@} end of group TSC_Acquisition_Enumerations */ + +/** @defgroup TSC_Acquisition_Structures Structures + @{ + */ + +/* Pointer to the Measure filter function */ +typedef TSC_tMeas_T(* TSC_pMeasFilter_T)(TSC_tMeas_T, TSC_tMeas_T); +/* Pointer to the Delta filter function */ +typedef TSC_tDelta_T(* TSC_pDeltaFilter_T)(TSC_tDelta_T); + +/** + * @brief Channel destination index + */ +typedef struct +{ + TSC_tIndexDest_T IdxDest; /*!< Index in the Channel data array */ +} TSC_Channel_Dest_T; + +/** + * @brief Channel Source and Configuration + */ +typedef struct +{ + TSC_tIndexSrc_T IdxSrc; /*!< Index of TSC->IOGxCNT[] registers */ + /* For apm32f0xx only */ + uint32_t msk_IOCHCTRL_channel; /*!< Mask of the Channel IO (electrodes only) */ + uint32_t msk_IOGCSTS_group; /*!< Mask of the Group used (electrodes only) */ +} TSC_Channel_Src_T; + +/** + * @brief Channel flags + */ +typedef struct +{ + unsigned int DataReady : 1; /*!< To identify a new measurement (TSC_DATA_T) */ + unsigned int AcqStatus : 2; /*!< Acquisition status (TSC_ACQ_STATUS_T) */ + unsigned int ObjStatus : 2; /*!< Object status (TSC_OBJ_STATUS_T) */ +} TSC_Channel_Flag_T; + +/** + * @brief Channel Data + */ +typedef struct +{ + TSC_Channel_Flag_T Flag; /*!< Flag */ + TSC_tRefer_T Refer; /*!< Reference */ + TSC_tRefRest_T RefRest; /*!< Reference rest for ECS */ + TSC_tDelta_T Delta; /*!< Delta */ +#if TOUCH_USE_MEAS > 0 + TSC_tMeas_T Meas; /*!< Hold the last acquisition measure */ +#endif +} TSC_Channel_Data_T; + +/** + * @brief Block Configuration + */ +typedef struct +{ + /* Common to all acquisitions */ + CONST TSC_Channel_Src_T* p_chSrc; /*!< Pointer to the Channel Source and Configuration */ + CONST TSC_Channel_Dest_T* p_chDest; /*!< Pointer to the Channel Destination */ + TSC_Channel_Data_T* p_chData; /*!< Pointer to the Channel Data */ + TSC_tNum_T NumChannel; /*!< Number of channels in the block */ + /* For apm32f0xx only */ + uint32_t msk_IOCHCTRL_channels; /*!< Mask of all channel IOs (electrodes and shields) */ + uint32_t msk_IOGCSTS_groups; /*!< Mask of all groups used (electrodes only) */ +} TSC_Block_T; + +/** + * @brief Structure containing all data of a Zone. + * A Zone is a set of Blocks. + * Variables of this structure type can be placed in RAM or ROM. + */ +typedef struct +{ + /* Common to all acquisitions */ + TSC_tIndex_T* indexBlock; /*!< Pointer to an array of block indexes */ + TSC_pDeltaFilter_T* daltaFilter; /*!< Pointer to a Delta filter function */ + TSC_tNum_T numBlock; /*!< Number of blocks in the zone */ +} TSC_Zone_T; + +/**@} end of group TSC_Acquisition_Structures */ + +/** @defgroup TSC_Acquisition_Functions Functions + @{ + */ + +TSC_STATUS_T TSC_Acq_Config(void); +void TSC_Acq_ConfigGPIO(void); +TSC_STATUS_T TSC_Acq_ConfigBlock(TSC_tIndex_T idxBlock); +TSC_BOOL_T TSC_Acq_UseFilter(TSC_Channel_Data_T* pCh); +TSC_BOOL_T TSC_Acq_TestReferenceRange(TSC_Channel_Data_T* pCh); +TSC_BOOL_T TSC_Acq_TestFirstReference(TSC_Channel_Data_T* pCh, TSC_tMeas_T newMeas); +void TSC_Acq_StartPerConfigBlock(void); +TSC_STATUS_T TSC_Acq_WaitBlockEOA(void); +TSC_ACQ_STATUS_T TSC_Acq_CheckNoise(void); +TSC_tMeas_T TSC_Acq_ReadMeasurVal(TSC_tIndexSrc_T index); +TSC_tDelta_T TSC_Acq_ComputeDelta(TSC_tRefer_T refVal, TSC_tMeas_T measVal); +TSC_tMeas_T TSC_Acq_ComputeMeas(TSC_tRefer_T refVal, TSC_tDelta_T deltaVal); + +TSC_STATUS_T TSC_Acq_ConfigZone(CONST TSC_Zone_T* zone, TSC_tIndex_T idxBlock); +TSC_STATUS_T TSC_Acq_ReadBlockResult(TSC_tIndex_T idxBlock, TSC_pMeasFilter_T mfilter, TSC_pDeltaFilter_T dfilter); +TSC_STATUS_T TSC_Acq_CalibrateBlock(TSC_tIndex_T block); +void TSC_acq_ClearBlockData(TSC_tIndex_T block); + +#ifdef __cplusplus +} +#endif + +#endif /* __TSC_ACQ_H */ + +/**@} end of group TSC_Acquisition_Functions */ +/**@} end of group TSC_Acquisition_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_check.h b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_check.h new file mode 100644 index 0000000000..d0f78ebf71 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_check.h @@ -0,0 +1,578 @@ +/*! + * @file tsc_check.h + * + * @brief This file contains the check of all parameters defined in the + * common configuration file. + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __TOUCH_CHECK_H +#define __TOUCH_CHECK_H + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_Check_Driver TSC Check Driver + @{ +*/ + +/* Local check */ +#if ((TOUCH_TOTAL_CHANNELS < 1) || (TOUCH_TOTAL_CHANNELS > 24)) + #error "TOUCH_TOTAL_CHANNELS can be (1 .. 24)." +#endif + +#if ((TOUCH_TOTAL_BLOCKS < 1) || (TOUCH_TOTAL_BLOCKS > 8)) + #error "TOUCH_TOTAL_BLOCKS can be (1 .. 8)." +#endif + +#if ((TOUCH_TOTAL_TOUCHKEYS < 0) || (TOUCH_TOTAL_TOUCHKEYS > 24)) + #error "TOUCH_TOTAL_TOUCHKEYS can be (0 .. 24)." +#endif + +#if ((TOUCH_TOTAL_TOUCHKEYS_B < 0) || (TOUCH_TOTAL_TOUCHKEYS_B > 24)) + #error "TOUCH_TOTAL_TOUCHKEYS_B can be (0 .. 24)." +#endif + +#if ((TOUCH_TOTAL_LINROTS < 0) || (TOUCH_TOTAL_LINROTS > 24)) + #error "TOUCH_TOTAL_LINROTS can be (0 .. 24)." +#endif + +#if ((TOUCH_TOTAL_LINROTS_B < 0) || (TOUCH_TOTAL_LINROTS_B > 24)) + #error "TOUCH_TOTAL_LINROTS_B can be (0 .. 24)." +#endif + +#if ((TOUCH_TOTAL_OBJECTS < 1) || (TOUCH_TOTAL_OBJECTS > 24)) + #error "TOUCH_TOTAL_OBJECTS can be (1 .. 24)." +#endif + +#if ((TOUCH_TOTAL_KEYS + TOUCH_TOTAL_LNRTS) > 24) + #error "The Sum of TouchKeys and Linear/Rotary sensors exceeds 24." +#endif + +#ifndef TOUCH_TSC_GPIO_CONFIG + #error "Please Config TOUCH_TSC_GPIO_CONFIG." +#endif + +#if ((TOUCH_TSC_GPIO_CONFIG < 0) || (TOUCH_TSC_GPIO_CONFIG > 1)) + #error "TOUCH_TSC_GPIO_CONFIG can be (0 .. 1)." +#endif + +#ifndef TOUCH_TSC_CTPHSEL + #error "Please Config TOUCH_TSC_CTPHSEL." +#endif + +#if ((TOUCH_TSC_CTPHSEL < 0) || (TOUCH_TSC_CTPHSEL > 15)) + #error "TOUCH_TSC_CTPHSEL can be (0 .. 15)." +#endif + +#ifndef TOUCH_TSC_CTPLSEL + #error "Please Config TOUCH_TSC_CTPLSEL." +#endif + +#if ((TOUCH_TSC_CTPLSEL < 0) || (TOUCH_TSC_CTPLSEL > 15)) + #error "TOUCH_TSC_CTPLSEL can be (0 .. 15)." +#endif + +#ifndef TOUCH_TSC_PGCDFSEL + #error "Please Config TOUCH_TSC_PGCDFSEL." +#endif + +#if ((TOUCH_TSC_PGCDFSEL < 0) || (TOUCH_TSC_PGCDFSEL > 7)) + #error "TOUCH_TSC_PGCDFSEL can be (0 .. 7)." +#endif + +#if (TOUCH_ACQ_MAX > 0) && (TOUCH_ACQ_MAX < 256) + #define TOUCH_TSC_MCNTVSEL 0 /*!< 255 */ +#endif + +#if (TOUCH_ACQ_MAX > 255) && (TOUCH_ACQ_MAX < 512) + #define TOUCH_TSC_MCNTVSEL 1 /*!< 511 */ +#endif + +#if (TOUCH_ACQ_MAX > 511) && (TOUCH_ACQ_MAX < 1024) + #define TOUCH_TSC_MCNTVSEL 2 /*!< 1023 */ +#endif + +#if (TOUCH_ACQ_MAX > 1023) && (TOUCH_ACQ_MAX < 2048) + #define TOUCH_TSC_MCNTVSEL 3 /*!< 2047 */ +#endif + +#if (TOUCH_ACQ_MAX > 2047) && (TOUCH_ACQ_MAX < 4096) + #define TOUCH_TSC_MCNTVSEL 4 /*!< 4095 */ +#endif + +#if (TOUCH_ACQ_MAX > 4095) && (TOUCH_ACQ_MAX < 8192) + #define TOUCH_TSC_MCNTVSEL 5 /*!< 8191 */ +#endif + +#if (TOUCH_ACQ_MAX > 8191) + #define TOUCH_TSC_MCNTVSEL 6 /*!< 16383 */ +#endif + +#ifndef TOUCH_TSC_MCNTVSEL + #error "Please Config TOUCH_TSC_MCNTVSEL." +#endif + +#if ((TOUCH_TSC_MCNTVSEL < 0) || (TOUCH_TSC_MCNTVSEL > 6)) + #error "TOUCH_TSC_MCNTVSEL can be (0 .. 6)." +#endif + +#ifndef TOUCH_TSC_IODEF + #error "Please Config TOUCH_TSC_IODEF." +#endif + +#if ((TOUCH_TSC_IODEF < 0) || (TOUCH_TSC_IODEF > 1)) + #error "TOUCH_TSC_IODEF can be (0 .. 1)." +#endif + +#ifndef TOUCH_TSC_AMCFG + #error "Please Config TOUCH_TSC_AMCFG." +#endif + +#if ((TOUCH_TSC_AMCFG < 0) || (TOUCH_TSC_AMCFG > 1)) + #error "TOUCH_TSC_AMCFG can be (0 .. 1)." +#endif + +#ifndef TOUCH_TSC_SYNC_PIN + #error "Please Config TOUCH_TSC_SYNC_PIN." +#endif + +#if ((TOUCH_TSC_SYNC_PIN < 0) || (TOUCH_TSC_SYNC_PIN > 1)) + #error "TOUCH_TSC_SYNC_PIN can be (0 .. 1)." +#endif + +#ifndef TOUCH_TSC_SYNC_POL + #error "Please Config TOUCH_TSC_SYNC_POL." +#endif + +#if ((TOUCH_TSC_SYNC_POL < 0) || (TOUCH_TSC_SYNC_POL > 1)) + #error "TOUCH_TSC_SYNC_POL can be (0 .. 1)." +#endif + +#ifndef TOUCH_TSC_USE_SSEN + #error "Please Config TOUCH_TSC_USE_SSEN." +#endif + +#if ((TOUCH_TSC_USE_SSEN < 0) || (TOUCH_TSC_USE_SSEN > 1)) + #error "TOUCH_TSC_USE_SSEN can be (0 .. 1)." +#endif + +#ifndef TOUCH_TSC_SSERRVSEL + #error "Please Config TOUCH_TSC_SSERRVSEL." +#endif + +#if ((TOUCH_TSC_SSERRVSEL < 0) || (TOUCH_TSC_SSERRVSEL > 127)) + #error "TOUCH_TSC_SSERRVSEL can be (0 .. 127)." +#endif + +#ifndef TOUCH_TSC_SSCDFSEL + #error "Please Config TOUCH_TSC_SSCDFSEL." +#endif + +#if ((TOUCH_TSC_SSCDFSEL < 0) || (TOUCH_TSC_SSCDFSEL > 1)) + #error "TOUCH_TSC_SSCDFSEL can be (0 .. 1)." +#endif + +#ifdef TSC_GROUP7_ENABLED + #undef TSC_GROUP7_ENABLED +#endif + +#if (TOUCH_TSC_GROUP7_IO1 != NU) || (TOUCH_TSC_GROUP7_IO2 != NU) || (TOUCH_TSC_GROUP7_IO3 != NU) || (TOUCH_TSC_GROUP7_IO4 != NU) + #define TSC_GROUP7_ENABLED (1) +#endif + +#ifdef TSC_GROUP8_ENABLED + #undef TSC_GROUP8_ENABLED +#endif + +#if (TOUCH_TSC_GROUP8_IO1 != NU) || (TOUCH_TSC_GROUP8_IO2 != NU) || (TOUCH_TSC_GROUP8_IO3 != NU) || (TOUCH_TSC_GROUP8_IO4 != NU) + #define TSC_GROUP8_ENABLED (1) +#endif + +#ifndef TOUCH_DELAY_DISCHARGE_ALL + #error "Please Config TOUCH_DELAY_DISCHARGE_ALL." +#endif + +#if ((TOUCH_DELAY_DISCHARGE_ALL < 0) || (TOUCH_DELAY_DISCHARGE_ALL > 65535)) + #error "TOUCH_DELAY_DISCHARGE_ALL can be (0 .. 65535)." +#endif + +/* Global check */ +#ifndef TOUCH_TOTAL_CHANNELS + #error "Please Config TOUCH_TOTAL_CHANNELS." +#endif + +#ifndef TOUCH_TOTAL_BLOCKS + #error "Please Config TOUCH_TOTAL_BLOCKS." +#endif + +#ifndef TOUCH_TOTAL_TOUCHKEYS + #error "Please Config TOUCH_TOTAL_TOUCHKEYS." +#endif + +#ifndef TOUCH_TOTAL_TOUCHKEYS_B + #error "Please Config TOUCH_TOTAL_TOUCHKEYS_B." +#endif + +#ifndef TOUCH_TOTAL_LINROTS + #error "Please Config TOUCH_TOTAL_LINROTS." +#endif + +#ifndef TOUCH_TOTAL_LINROTS_B + #error "Please Config TOUCH_TOTAL_LINROTS_B." +#endif + +#ifndef TOUCH_TOTAL_OBJECTS + #error "Please Config TOUCH_TOTAL_OBJECTS." +#endif + +#define TOUCH_TOTAL_KEYS (TOUCH_TOTAL_TOUCHKEYS + TOUCH_TOTAL_TOUCHKEYS_B) +#define TOUCH_TOTAL_LNRTS (TOUCH_TOTAL_LINROTS + TOUCH_TOTAL_LINROTS_B) + +#if ((TOUCH_TOTAL_KEYS == 0) && (TOUCH_TOTAL_LNRTS == 0)) + #error "Please Config TouchKey and Linear/Rotary sensors." +#endif + +#ifndef TOUCH_CALIB_SAMPLES + #error "Please Config TOUCH_CALIB_SAMPLES." +#endif + +#if ((TOUCH_CALIB_SAMPLES != 4) && (TOUCH_CALIB_SAMPLES != 8) && (TOUCH_CALIB_SAMPLES != 16)) + #error "TOUCH_CALIB_SAMPLES can be (4, 8, 16)." +#endif + +#ifndef TOUCH_CALIB_DELAY + #error "Please Config TOUCH_CALIB_DELAY." +#endif + +#if ((TOUCH_CALIB_DELAY < 0) || (TOUCH_CALIB_DELAY > 40)) + #error "TOUCH_CALIB_DELAY can be (0..40)." +#endif + +#ifndef TOUCH_ACQ_MIN + #error "Please Config TOUCH_ACQ_MIN." +#endif + +#ifndef TOUCH_ACQ_MAX + #error "Please Config TOUCH_ACQ_MAX." +#endif + +#if ((TOUCH_ACQ_MIN < 1) || (TOUCH_ACQ_MIN > (TOUCH_ACQ_MAX-1))) + #error "TOUCH_ACQ_MIN can be (1 .. ACQ_MAX-1)." +#endif + +#if ((TOUCH_ACQ_MAX < (TOUCH_ACQ_MIN+1)) || (TOUCH_ACQ_MAX > 50000)) + #error "TOUCH_ACQ_MAX can be (ACQ_MIN+1 .. 50000)." +#endif + +#ifndef TOUCH_KEY_PROX_IN_TH + #error "Please Config TOUCH_KEY_PROX_IN_TH." +#endif + +#ifndef TOUCH_KEY_PROX_OUT_TH + #error "Please Config TOUCH_KEY_PROX_OUT_TH." +#endif + +#if ((TOUCH_KEY_PROX_OUT_TH < 0) || (TOUCH_KEY_PROX_OUT_TH > (TOUCH_KEY_PROX_IN_TH-1))) + #error "TOUCH_KEY_PROX_OUT_TH can be (0 .. TOUCH_KEY_PROX_IN_TH-1)." +#endif + +#if TOUCH_COEFF_TH == 0 + #if ((TOUCH_KEY_PROX_IN_TH < (TOUCH_KEY_PROX_OUT_TH+1)) || (TOUCH_KEY_PROX_IN_TH > (TOUCH_KEY_DETECT_OUT_TH-1))) + #error "TOUCH_KEY_PROX_IN_TH can be (TOUCH_KEY_PROX_OUT_TH+1 .. TOUCH_KEY_DETECT_OUT_TH-1)." + #endif +#endif + +#ifndef TOUCH_LINROT_PROX_IN_TH + #error "Please Config TOUCH_LINROT_PROX_IN_TH." +#endif + +#ifndef TOUCH_LINROT_PROX_OUT_TH + #error "Please Config TOUCH_LINROT_PROX_OUT_TH." +#endif + +#if ((TOUCH_LINROT_PROX_OUT_TH < 0) || (TOUCH_LINROT_PROX_OUT_TH > (TOUCH_LINROT_PROX_IN_TH-1))) + #error "TOUCH_LINROT_PROX_OUT_TH can be (0 .. TOUCH_LINROT_PROX_IN_TH-1)." +#endif + +#if TOUCH_COEFF_TH == 0 + #if ((TOUCH_LINROT_PROX_IN_TH < (TOUCH_LINROT_PROX_OUT_TH+1)) || (TOUCH_LINROT_PROX_IN_TH > (TOUCH_LINROT_DETECT_OUT_TH-1))) + #error "TOUCH_LINROT_PROX_IN_TH can be (TOUCH_LINROT_PROX_OUT_TH+1 .. TOUCH_LINROT_DETECT_OUT_TH-1)." + #endif +#endif + +#ifndef TOUCH_KEY_DETECT_IN_TH + #error "Please Config TOUCH_KEY_DETECT_IN_TH." +#endif + +#ifndef TOUCH_KEY_DETECT_OUT_TH + #error "Please Config TOUCH_KEY_DETECT_OUT_TH." +#endif + +#if TOUCH_COEFF_TH == 0 + #if ((TOUCH_KEY_DETECT_OUT_TH < (TOUCH_KEY_PROX_IN_TH+1)) || (TOUCH_KEY_DETECT_OUT_TH > (TOUCH_KEY_DETECT_IN_TH-1))) + #error "TOUCH_KEY_DETECT_OUT_TH can be (TOUCH_KEY_PROX_IN_TH+1 .. TOUCH_KEY_DETECT_IN_TH-1)." + #endif +#endif + +#if ((TOUCH_KEY_DETECT_IN_TH < (TOUCH_KEY_DETECT_OUT_TH+1)) || (TOUCH_KEY_DETECT_IN_TH > 255)) + #error "TOUCH_KEY_DETECT_IN_TH can be (TOUCH_KEY_DETECT_OUT_TH+1 .. 255)." +#endif + +#ifndef TOUCH_LINROT_DETECT_IN_TH + #error "Please Config TOUCH_LINROT_DETECT_IN_TH." +#endif + +#ifndef TOUCH_LINROT_DETECT_OUT_TH + #error "Please Config TOUCH_LINROT_DETECT_OUT_TH." +#endif + +#if TOUCH_COEFF_TH == 0 + #if ((TOUCH_LINROT_DETECT_OUT_TH < (TOUCH_LINROT_PROX_IN_TH+1)) || (TOUCH_LINROT_DETECT_OUT_TH > (TOUCH_LINROT_DETECT_IN_TH-1))) + #error "TOUCH_LINROT_DETECT_OUT_TH can be (TOUCH_LINROT_PROX_IN_TH+1 .. TOUCH_LINROT_DETECT_IN_TH-1)." + #endif +#endif + +#if ((TOUCH_LINROT_DETECT_IN_TH < (TOUCH_LINROT_DETECT_OUT_TH+1)) || (TOUCH_LINROT_DETECT_IN_TH > 255)) + #error "TOUCH_LINROT_DETECT_IN_TH can be (TOUCH_LINROT_DETECT_OUT_TH+1 .. 255)." +#endif + +#ifndef TOUCH_KEY_CALIB_TH + #error "Please Config TOUCH_KEY_CALIB_TH." +#endif + +#if ((TOUCH_KEY_CALIB_TH < 0) || (TOUCH_KEY_CALIB_TH > 255)) + #error "TOUCH_KEY_CALIB_TH can be (0 .. 255)." +#endif + +#ifndef TOUCH_LINROT_CALIB_TH + #error "Please Config TOUCH_LINROT_CALIB_TH." +#endif + +#if ((TOUCH_LINROT_CALIB_TH < 0) || (TOUCH_LINROT_CALIB_TH > 255)) + #error "TOUCH_LINROT_CALIB_TH can be (0 .. 255)." +#endif + +#ifndef TOUCH_LINROT_USE_NORMDELTA + #error "Please Config TOUCH_LINROT_USE_NORMDELTA." +#endif + +#if ((TOUCH_LINROT_USE_NORMDELTA < 0) || (TOUCH_LINROT_USE_NORMDELTA > 1)) + #error "TOUCH_LINROT_USE_NORMDELTA can be (0 .. 1)." +#endif + +#ifndef TOUCH_COEFF_TH + #error "Please Config TOUCH_COEFF_TH." +#endif + +#if ((TOUCH_COEFF_TH < 0) || (TOUCH_COEFF_TH > 4)) + #error "TOUCH_COEFF_TH can be (0 .. 4)." +#endif + +#ifndef TOUCH_LINROT_DIR_CHG_POS + #error "Please Config TOUCH_LINROT_DIR_CHG_POS." +#endif + +#if ((TOUCH_LINROT_DIR_CHG_POS < 0) || (TOUCH_LINROT_DIR_CHG_POS > 255)) + #error "TOUCH_LINROT_DIR_CHG_POS can be (0 .. 255)." +#endif + +#ifndef TOUCH_LINROT_RESOLUTION + #error "Please Config TOUCH_LINROT_RESOLUTION." +#endif + +#if ((TOUCH_LINROT_RESOLUTION < 1) || (TOUCH_LINROT_RESOLUTION > 8)) + #error "TOUCH_LINROT_RESOLUTION can be (1 .. 8)." +#endif + +#ifndef TOUCH_DEBOUNCE_PROX + #error "Please Config TOUCH_DEBOUNCE_PROX." +#endif + +#if ((TOUCH_DEBOUNCE_PROX < 0) || (TOUCH_DEBOUNCE_PROX > 63)) + #error "TOUCH_DEBOUNCE_PROX can be (0 .. 63)." +#endif + +#ifndef TOUCH_DEBOUNCE_DETECT + #error "Please Config TOUCH_DEBOUNCE_DETECT." +#endif + +#if ((TOUCH_DEBOUNCE_DETECT < 0) || (TOUCH_DEBOUNCE_DETECT > 63)) + #error "TOUCH_DEBOUNCE_DETECT can be (0 .. 63)." +#endif + +#ifndef TOUCH_DEBOUNCE_RELEASE + #error "Please Config TOUCH_DEBOUNCE_RELEASE." +#endif + +#if ((TOUCH_DEBOUNCE_RELEASE < 0) || (TOUCH_DEBOUNCE_RELEASE > 63)) + #error "TOUCH_DEBOUNCE_RELEASE can be (0 .. 63)." +#endif + +#ifndef TOUCH_DEBOUNCE_CALIB + #error "Please Config TOUCH_DEBOUNCE_CALIB." +#endif + +#if ((TOUCH_DEBOUNCE_CALIB < 0) || (TOUCH_DEBOUNCE_CALIB > 63)) + #error "TOUCH_DEBOUNCE_CALIB can be (0 .. 63)." +#endif + +#ifndef TOUCH_DEBOUNCE_ERROR + #error "Please Config TOUCH_DEBOUNCE_ERROR." +#endif + +#if ((TOUCH_DEBOUNCE_ERROR < 0) || (TOUCH_DEBOUNCE_ERROR > 63)) + #error "TOUCH_DEBOUNCE_ERROR can be (0 .. 63)." +#endif + +#ifndef TOUCH_LINROT_DIR_CHG_DEB + #error "Please Config TOUCH_LINROT_DIR_CHG_DEB." +#endif + +#if ((TOUCH_LINROT_DIR_CHG_DEB < 0) || (TOUCH_LINROT_DIR_CHG_DEB > 63)) + #error "TOUCH_LINROT_DIR_CHG_DEB can be (0 .. 63)." +#endif + +#ifndef TOUCH_ECS_K_DIFFER + #error "Please Config TOUCH_ECS_K_DIFFER." +#endif + +#if ((TOUCH_ECS_K_DIFFER < 0) || (TOUCH_ECS_K_DIFFER > 255)) + #error "TOUCH_ECS_K_DIFFER can be (0 .. 255)." +#endif + +#ifndef TOUCH_ECS_K_SAME + #error "Please Config TOUCH_ECS_K_SAME." +#endif + +#if ((TOUCH_ECS_K_SAME < 0) || (TOUCH_ECS_K_SAME > 255)) + #error "TOUCH_ECS_K_SAME can be (0 .. 255)." +#endif + +#ifndef TOUCH_ECS_DELAY + #error "Please Config TOUCH_ECS_DELAY." +#endif + +#if ((TOUCH_ECS_DELAY < 0) || (TOUCH_ECS_DELAY > 5000)) + #error "TOUCH_ECS_DELAY can be (0 .. 5000)." +#endif + +#ifndef TOUCH_USE_MEAS + #error "Please Config TOUCH_USE_MEAS." +#endif + +#if ((TOUCH_USE_MEAS != 0) && (TOUCH_USE_MEAS != 1)) + #error "TOUCH_USE_MEAS can be (0 .. 1)." +#endif + +#ifndef TOUCH_USE_PROX + #error "Please Config TOUCH_USE_PROX." +#endif + +#if ((TOUCH_USE_PROX != 0) && (TOUCH_USE_PROX != 1)) + #error "TOUCH_USE_PROX can be (0 .. 1)." +#endif + +#ifndef TOUCH_USE_ZONE + #error "Please Config TOUCH_USE_ZONE." +#endif + +#if ((TOUCH_USE_ZONE != 0) && (TOUCH_USE_ZONE != 1)) + #error "TOUCH_USE_ZONE can be (0 .. 1)." +#endif + +#ifndef TOUCH_USE_ACQ_INTERRUPT + #error "Please Config TOUCH_USE_ACQ_INTERRUPT." +#endif + +#if ((TOUCH_USE_ACQ_INTERRUPT != 0) && (TOUCH_USE_ACQ_INTERRUPT != 1)) + #error "TOUCH_USE_ACQ_INTERRUPT can be (0 .. 1)." +#endif + +#ifndef TOUCH_DTO + #error "Please Config TOUCH_DTO." +#endif + +#if ((TOUCH_DTO < 0) || (TOUCH_DTO > 63)) + #error "TOUCH_DTO can be (0 .. 63)." +#endif + +#ifndef TOUCH_TICK_FREQ + #error "Please Config TOUCH_TICK_FREQ." +#endif + +#if ((TOUCH_TICK_FREQ != 125) && (TOUCH_TICK_FREQ != 250) && (TOUCH_TICK_FREQ != 500) &&\ + (TOUCH_TICK_FREQ != 1000) && (TOUCH_TICK_FREQ != 2000)) +#error "TOUCH_TICK_FREQ can be (125, 250, 500, 1000, 2000)." +#endif + +#ifndef TOUCH_USE_DXS + #error "Please Config TOUCH_USE_DXS." +#endif + +#if ((TOUCH_USE_DXS < 0) || (TOUCH_USE_DXS > 1)) + #error "TOUCH_USE_DXS can be (0 .. 1)." +#endif + +#ifndef TOUCH_USE_TIMER_CALLBACK + #error "Please Config TOUCH_USE_TIMER_CALLBACK." +#endif + +#if ((TOUCH_USE_TIMER_CALLBACK != 0) && (TOUCH_USE_TIMER_CALLBACK != 1)) + #error "TOUCH_USE_TIMER_CALLBACK can be (0 .. 1)." +#endif + +#endif /* __TOUCH_CHECK_H */ + +/** @defgroup TSC_Check_Macros Macros + @{ + */ + +/**@} end of group TSC_Check_Macros */ + +/** @defgroup TSC_Check_Enumerations Enumerations + @{ + */ + +/**@} end of group TSC_Check_Enumerations */ + +/** @defgroup TSC_Check_Structures Structures + @{ + */ + +/**@} end of group TSC_Check_Structures */ + +/** @defgroup TSC_Check_Variables Variables + @{ + */ + +/**@} end of group TSC_Check_Variables */ + +/** @defgroup TSC_Check_Functions Functions + @{ + */ + +/**@} end of group TSC_Check_Functions */ + +/**@} end of group TSC_Check_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_config.h b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_config.h new file mode 100644 index 0000000000..f0508b959d --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_config.h @@ -0,0 +1,583 @@ +/*! + * @file tsc_config.h + * + * @brief Acquisition parameters for APM32F0xx products. + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __TSC_CONFIG_H +#define __TSC_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_Config_Driver TSC Config Driver + @{ +*/ + +/** @defgroup TSC_Config_Macros Macros + @{ +*/ + +/** @defgroup Common_Parameters_Number_Of_Elements + @{ +*/ + +/* The number of channels (1..24) */ +#define TOUCH_TOTAL_CHANNELS (11) + +/* The number of blocks (1..8) */ +#define TOUCH_TOTAL_BLOCKS (3) + +/* The number of "Extended" TouchKeys (0..24) */ +#define TOUCH_TOTAL_TOUCHKEYS (5) + +/* The number of "Basic" TouchKeys (0..24) */ +#define TOUCH_TOTAL_TOUCHKEYS_B (0) + +/* The number of "Extended" Linear and Rotary sensors (0..24) */ +#define TOUCH_TOTAL_LINROTS (2) + +/* The number of "Basic" Linear and Rotary sensors (0..24) */ +#define TOUCH_TOTAL_LINROTS_B (0) + +/** The number of sensors/objects (1..24) + * - Count all TouchKeys, Linear and Rotary sensors + */ +#define TOUCH_TOTAL_OBJECTS (7) + +/**@} Common_Parameters_Number_Of_Elements */ + +/** @defgroup Common_Parameters_Optional_Features + @{ +*/ + +/** Record the last measure (0=No, 1=Yes) + * - If No the measure is recalculated using the Reference and Delta + */ +#define TOUCH_USE_MEAS (1) + +/* Zone management usage (0=No, 1=Yes) */ +#define TOUCH_USE_ZONE (0) + +/* Proximity detection usage (0=No, 1=Yes) */ +#define TOUCH_USE_PROX (1) + +/** Use the Timer tick callback (0=No, 1=Yes) + * - When equal to 1, the function TSC_CallBack_TimerTick + */ +#define TOUCH_USE_TIMER_CALLBACK (0) + +/** Acquisition interrupt mode (0=No, 1=Yes) + * - If No the TSC interrupt is not used. + * - If Yes the TSC interrupt is used. + */ +#define TOUCH_USE_ACQ_INTERRUPT (0) + +/**@} Common_Parameters_Optional_Features */ + +/** @defgroup Common_Parameters_Acquisition_limits + @{ +*/ + +/** Minimum acquisition measurement (0..65535) + * - This is the minimum acceptable value for the acquisition measure. + * - The acquisition will be in error if the measure is below this value. + */ +#define TOUCH_ACQ_MIN (10) + +/** Maximum acquisition measurement (255, 511, 1023, 2047, 8191, 16383) + * - This is the maximum acceptable value for the acquisition measure. + * - The acquisition will be in error if the measure is above this value. + */ +#define TOUCH_ACQ_MAX (8191) + +/**@} Common_Parameters_Acquisition_limits */ + +/** @defgroup Common_Parameters_Calibration + @{ +*/ +/** Number of calibration samples (4, 8, 16) + * - Low value = faster calibration but less precision. + * - High value = slower calibration but more precision. + */ +#define TOUCH_CALIB_SAMPLES (16) + +/** Delay in measurement samples before starting the calibration (0..40) + * - This is useful if a noise filter is used. + * - Write 0 to disable the delay. + */ +#define TOUCH_CALIB_DELAY (0) + +/**@} Common_Parameters_Calibration */ + +/** @defgroup Common_Parameters_Thresholds_for_TouchKey + @{ +*/ + +/** TouchKeys Proximity state input threshold (0..255) + * - Enter Proximity state if delta is above + */ +#define TOUCH_KEY_PROX_IN_TH (10) + +/** TouchKeys Proximity state output threshold (0..255) + * - Exit Proximity state if delta is below + */ +#define TOUCH_KEY_PROX_OUT_TH (5) + +/** TouchKeys Detect state input threshold (0..255) + * - Enter Detect state if delta is above + */ +#define TOUCH_KEY_DETECT_IN_TH (200) + +/** TouchKeys Detect state output threshold (0..255) + * - Exit Detect state if delta is below + */ +#define TOUCH_KEY_DETECT_OUT_TH (150) + +/** TouchKeys re-Calibration threshold (0..255) + * - @warning The value is inverted in the sensor state machine + * - Enter Calibration state if delta is below + */ +#define TOUCH_KEY_CALIB_TH (150) + +/** TouchKey, Linear and Rotary sensors thresholds coefficient (0..4) + * This multiplier coefficient is applied on Detect and Re-Calibration thresholds only. + * - 0: disabled + * - 1: thresholds x 2 + * - 2: thresholds x 4 + * - 3: thresholds x 8 + * - 4: thresholds x 16 + */ +#define TOUCH_COEFF_TH (0) + +/**@} Common_Parameters_Thresholds_for_TouchKey */ + +/** @defgroup Common_Parameters_Thresholds_For_Linear_Rotary + @{ +*/ + +/** Linear/Rotary Proximity state input threshold (0..255) + * - Enter Proximity state if delta is above + */ +#define TOUCH_LINROT_PROX_IN_TH (10) + +/** Linear/Rotary Proximity state output threshold (0..255) + * - Exit Proximity state if delta is below + */ +#define TOUCH_LINROT_PROX_OUT_TH (5) + +/** Linear/Rotary Detect state input threshold (0..255) + * - Enter Detect state if delta is above + */ +#define TOUCH_LINROT_DETECT_IN_TH (20) + +/** Linear/Rotary Detect state output threshold (0..255) + * - Exit Detect state if delta is below + */ +#define TOUCH_LINROT_DETECT_OUT_TH (15) + +/** Linear/Rotary Re-Calibration threshold (0..255) + * - @warning The value is inverted in the sensor state machine + * - Enter Calibration state if delta is below + */ +#define TOUCH_LINROT_CALIB_TH (30) + +/** Linear/Rotary Delta normalization (0=No, 1=Yes) + * - When this parameter is set, a coefficient is applied on all Delta of all sensors + * in order to normalize them and to improve the position calculation. + * - These coefficients must be defined in a constant table + * - The MSB is the coefficient integer part, the LSB is the coefficient real part. + * Examples: + * - To apply a factor 1.10: + * 0x01 to the MSB + * 0x1A to the LSB (0.10 x 256 = 25.6 -> rounded to 26 = 0x1A) + * - To apply a factor 0.90: + * 0x00 to the MSB + * 0xE6 to the LSB (0.90 x 256 = 230.4 -> rounded to 230 = 0xE6) + */ +#define TOUCH_LINROT_USE_NORMDELTA (0) + +/**@} Common_Parameters_Thresholds_For_Linear_Rotary */ + +/** @defgroup Common_Parameters_Used_Linear_Rotary + @{ +*/ + +/** Select which Linear and Rotary sensors you use in your application. + * - 0 = Not Used + * - 1 = Used + * + * LIN = Linear sensor + * ROT = Rotary sensor + * M1 = Mono electrodes design with 0/255 position at extremities of the sensor + * M2 = Mono electrodes design + * H = Half-ended electrodes design + * D = Dual electrodes design + */ +#define TOUCH_USE_3CH_LIN_M1 (1) +#define TOUCH_USE_3CH_LIN_M2 (1) +#define TOUCH_USE_3CH_LIN_H (1) +#define TOUCH_USE_3CH_ROT_M (1) + +#define TOUCH_USE_4CH_LIN_M1 (1) +#define TOUCH_USE_4CH_LIN_M2 (1) +#define TOUCH_USE_4CH_LIN_H (1) +#define TOUCH_USE_4CH_ROT_M (1) + +#define TOUCH_USE_5CH_LIN_M1 (1) +#define TOUCH_USE_5CH_LIN_M2 (1) +#define TOUCH_USE_5CH_LIN_H (1) +#define TOUCH_USE_5CH_ROT_M (1) +#define TOUCH_USE_5CH_ROT_D (1) + +#define TOUCH_USE_6CH_LIN_M1 (1) +#define TOUCH_USE_6CH_LIN_M2 (1) +#define TOUCH_USE_6CH_LIN_H (1) +#define TOUCH_USE_6CH_ROT_M (1) + +/**@} Common_Parameters_Used_Linear_Rotary */ + +/** @defgroup Common_Parameters_Position_Linear_Rotary + @{ +*/ + +/** Position resolution in number of bits (1..8) + * - A Low value will result in a low resolution and will be less subject to noise. + * - A High value will result in a high resolution and will be more subject to noise. + */ +#define TOUCH_LINROT_RESOLUTION (7) + +/** Direction change threshold in position unit (0..255) + * - Defines the default threshold used during the change direction process. + * - A Low value will result in a faster direction change. + * - A High value will result in a slower direction change. + */ +#define TOUCH_LINROT_DIR_CHG_POS (10) + +/** Direction change debounce (0..63) + * - Defines the default integrator counter used during the change direction process. + * - This counter is decremented when the same change in the position is detected and the direction will + * change after this counter reaches zero. + * - A Low value will result in a faster direction change. + * - A High value will result in a slower direction change. + */ +#define TOUCH_LINROT_DIR_CHG_DEB (1) + +/**@} Common_Parameters_Position_Linear_Rotary */ + +/** @defgroup Common_Parameters_Debounce_Counters + @{ +*/ + +/** Proximity state debounce in samples unit (0..63) + * - A Low value will result in a higher sensitivity during the Proximity detection but with less noise filtering. + * - A High value will result in improving the system noise immunity but will increase the system response time. + */ +#define TOUCH_DEBOUNCE_PROX (3) + +/** Detect state debounce in samples unit (0..63) + * - A Low value will result in a higher sensitivity during the detection but with less noise filtering. + * - A High value will result in improving the system noise immunity but will increase the system response time. + */ +#define TOUCH_DEBOUNCE_DETECT (3) + +/** Release state debounce in samples unit (0..63) + * - A Low value will result in a higher sensitivity during the end-detection but with less noise filtering. + * - A High value will result in a lower sensitivity during the end-detection but with more noise filtering. + */ +#define TOUCH_DEBOUNCE_RELEASE (3) + +/** Re-calibration state debounce in samples unit (0..63) + * - A Low value will result in a higher sensitivity during the recalibration but with less noise filtering. + * - A High value will result in a lower sensitivity during the recalibration but with more noise filtering. + */ +#define TOUCH_DEBOUNCE_CALIB (3) + +/** Error state debounce in samples unit (0..63) + * - A Low value will result in a higher sensitivity to enter in error state. + * - A High value will result in a lower sensitivity to enter in error state. + */ +#define TOUCH_DEBOUNCE_ERROR (3) + +/**@} Common_Parameters_Debounce_Counters */ + +/** @defgroup Common_Parameters_Environment_Change_System (ECS) + @{ +*/ + +/** Environment Change System Different K factor (0..255) + * - The higher value is K, the faster is the response time. + */ +#define TOUCH_ECS_K_DIFFER (10) + +/** Environment Change System Same K factor (0..255) + * - The higher value is K, the faster is the response time. + */ +#define TOUCH_ECS_K_SAME (20) + +/** Environment Change System delay in msec (0..5000) + * - The ECS will be started after this delay and when all sensors are in Release state. + */ +#define TOUCH_ECS_DELAY (500) + +/**@} Common_Parameters_Environment_Change_System */ + +/** @defgroup Common_Parameters_Detection_Time_Out (DTO) + @{ +*/ + +/** Detection Time Out delay in seconds (0..63) + * - Value 0: DTO processing not compiled in the code (to gain size if not used). + * - Value 1: Default time out infinite. + * - Value between 2 and 63: Default time out between value n-1 and n. + * - Examples: + * - With a DTO equal to 2, the time out is between 1s and 2s. + * - With a DTO equal to 63, the time out is between 62s and 63s. + * + *@note The DTO can be changed in run-time by the application only if the + * default value is between 1 and 63. + */ +#define TOUCH_DTO (0) + +/**@} Common_Parameters_Detection_Time_Out */ + +/** @defgroup Common_Parameters_Detection_Exclusion_System (DXS) + @{ +*/ + +/** Detection Exclusion System (0=No, 1=Yes) */ +#define TOUCH_USE_DXS (0) + +/**@} Common_Parameters_Detection_Exclusion_System */ + +/** @defgroup Common_Parameters_Miscellaneous_Parameters + @{ +*/ + +/** Timing tick frequency in Hz (125, 250, 500, 1000, 2000) + * - Result to a timing interrupt respectively every 8ms, 4ms, 2ms, 1ms, 0.5ms + */ +#define TOUCH_TICK_FREQ (1000) + +/** Delay for discharging Cx and Cs capacitors (0..65535) + * - The value corresponds to the Softdelay function parameter. + * - 500 gives around 53 delay whatever HCLK + * - 1000 gives around 106 delay whatever HCLK + * - 2000 gives around 210 delay whatever HCLK + */ +#define TOUCH_DELAY_DISCHARGE_ALL (1000) + +/**@} Common_Parameters_Miscellaneous_Parameters */ + +/** @defgroup APM32F0xx_Parameters_GPIOs_Configuration + @{ +*/ + +/** TSC GPIOs Configuration selection (0..1) + * - 0: Manual. The TSC GPIOs configuration must be done by the application code. + * - 1: Automatic. The TOUCH_TSC_GROUPx_IOy parameters below must be filled up. + * The TSC GPIOs configuration is automatically done by the Touch driver. + */ +#define TOUCH_TSC_GPIO_CONFIG (1) + +/* DO NOT CHANGE THESE VALUES */ +/* These defines must be applied to the TOUCH_TSC_GROUPx_IOy parameters below */ +#define NU (0) /*!< Not Used IO */ +#define CHANNEL (1) /*!< Channel IO */ +#define SHIELD (2) /*!< Shield IO (= Channel IO but not acquired) */ +#define SAMPCAP (3) /*!< Sampling Capacitor IO */ + +/* If TOUCH_TSC_GPIO_CONFIG=0 these parameters are ignored */ +/* If TOUCH_TSC_GPIO_CONFIG=1 assign each TOUCH_TSC_GROUPx_IOy parameters below */ + +#define TOUCH_TSC_GROUP1_IO1 SAMPCAP /*!< PA0 */ +#define TOUCH_TSC_GROUP1_IO2 CHANNEL /*!< PA1 */ +#define TOUCH_TSC_GROUP1_IO3 CHANNEL /*!< PA2 */ +#define TOUCH_TSC_GROUP1_IO4 NU /*!< PA3 */ + +#define TOUCH_TSC_GROUP2_IO1 SAMPCAP /*!< PA4 */ +#define TOUCH_TSC_GROUP2_IO2 CHANNEL /*!< PA5 */ +#define TOUCH_TSC_GROUP2_IO3 CHANNEL /*!< PA6 */ +#define TOUCH_TSC_GROUP2_IO4 CHANNEL /*!< PA7 */ + +#define TOUCH_TSC_GROUP3_IO1 SAMPCAP /*!< PC5 */ +#define TOUCH_TSC_GROUP3_IO2 NU /*!< PB0 */ +#define TOUCH_TSC_GROUP3_IO3 CHANNEL /*!< PB1 */ +#define TOUCH_TSC_GROUP3_IO4 CHANNEL /*!< PB2 */ + +#define TOUCH_TSC_GROUP4_IO1 SAMPCAP /*!< PA9 */ +#define TOUCH_TSC_GROUP4_IO2 NU /*!< PA10 */ +#define TOUCH_TSC_GROUP4_IO3 CHANNEL /*!< PA11 */ +#define TOUCH_TSC_GROUP4_IO4 CHANNEL /*!< PA12 */ + +#define TOUCH_TSC_GROUP5_IO1 NU /*!< PB3 */ +#define TOUCH_TSC_GROUP5_IO2 NU /*!< PB4 */ +#define TOUCH_TSC_GROUP5_IO3 NU /*!< PB6 */ +#define TOUCH_TSC_GROUP5_IO4 NU /*!< PB7 */ + +#define TOUCH_TSC_GROUP6_IO1 SAMPCAP /*!< PB11 */ +#define TOUCH_TSC_GROUP6_IO2 NU /*!< PB12 */ +#define TOUCH_TSC_GROUP6_IO3 CHANNEL /*!< PB13 */ +#define TOUCH_TSC_GROUP6_IO4 CHANNEL /*!< PB14 */ + +/* Warning: this group is available on some devices only */ +#define TOUCH_TSC_GROUP7_IO1 NU /*!< PE2 */ +#define TOUCH_TSC_GROUP7_IO2 NU /*!< PE3 */ +#define TOUCH_TSC_GROUP7_IO3 NU /*!< PE4 */ +#define TOUCH_TSC_GROUP7_IO4 NU /*!< PE5 */ + +/* Warning: this group is available on some devices only */ +#define TOUCH_TSC_GROUP8_IO1 NU /*!< PD12 */ +#define TOUCH_TSC_GROUP8_IO2 NU /*!< PD13 */ +#define TOUCH_TSC_GROUP8_IO3 NU /*!< PD14 */ +#define TOUCH_TSC_GROUP8_IO4 NU /*!< PD15 */ + +/**@} APM32F0xx_Parameters_GPIOs_Configuration */ + +/** @defgroup APM32F0xx_Parameters_Charge_Transfer_Pulses + @{ +*/ + +/** Charge Transfer Pulse High (0..15) + * - 0: 1 x tPGCLK + * - 1: 2 x tPGCLK + * - ... + * - 15: 16 x tPGCLK + */ +#define TOUCH_TSC_CTPHSEL (1) + +/** Charge Transfer Pulse Low (0..15) + * - 0: 1 x tPGCLK + * - 1: 2 x tPGCLK + * - ... + * - 15: 16 x tPGCLK + */ +#define TOUCH_TSC_CTPLSEL (1) + +/** Pulse Generator Clock Divide Factor Select (0..7) + * - 0: fPGCLK = fHCLK + * - 1: fPGCLK = fHCLK/2 + * - ... + * - 7: fPGCLK = fHCLK/128 + */ +#define TOUCH_TSC_PGCDFSEL (3) + +/**@} APM32F0xx_Parameters_Charge_Transfer_Pulses */ + +/** @defgroup APM32F0xx_Parameters_GPIOs + @{ +*/ + +/** TSC IOs default mode when no on-going acquisition (0..1) + * - 0: Output push-pull low + * - 1: Input floating + * @note To ensure a correct operation in noisy environment, this parameter should + * be configured to output push-pull low. + */ +#define TOUCH_TSC_IODEF (0) + +/** Acquisition Mode (0..1) + * - 0: Normal acquisition mode + * - 1: Synchronized acquisition mode + */ +#define TOUCH_TSC_AMCFG (0) + +/** Synchronization Pin (0..1) + * - 0: PB8 + * - 1: PB10 + */ +#define TOUCH_TSC_SYNC_PIN (0) + +/** Synchronization Polarity (0..1) + * - 0: Falling edge only + * - 1: Rising edge and high level + */ +#define TOUCH_TSC_SYNC_POL (0) + +/**@} APM32F0xx_Parameters_GPIOs */ + +/** @addtogroup APM32F0xx_Parameters_Spread_Spectrum + @{ +*/ + +/* Use Spread Spectrum (0=No, 1=Yes) */ +#define TOUCH_TSC_USE_SSEN (0) + +/** Spread Spectrum Error Value Select (0..127) + * - 0: 1 x tSSCLK + * - 1: 2 x tSSCLK + * - ... + * - 127: 128 x tSSCLK + */ +#define TOUCH_TSC_SSERRVSEL (0) + +/** Spread Spectrum Clock Divide Factor Select (0..1) + * - 0: fSSCLK = fHCLK + * - 1: fSSCLK = fHCLK/2 + */ +#define TOUCH_TSC_SSCDFSEL (0) + +/**@} APM32F0xx_Parameters_Spread_Spectrum */ + +/* Includes */ +/* Must be placed last */ +#include "tsc_check.h" + +#ifdef __cplusplus +} +#endif + +#endif /* __TSC_CONFIG_H */ + +/**@} end of group TSC_Config_Macros */ + +/** @defgroup TSC_Config_Enumerations Enumerations + @{ +*/ + +/**@} end of group TSC_Config_Enumerations */ + +/** @defgroup TSC_Config_Structures Structures + @{ +*/ + +/**@} end of group TSC_Config_Structures */ + +/** @defgroup TSC_Config_Variables Variables + @{ +*/ + +/**@} end of group TSC_Config_Variables */ + +/** @defgroup TSC_Config_Functions Functions + @{ +*/ + +/**@} end of group TSC_Config_Functions */ +/**@} end of group TSC_Config_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_dxs.h b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_dxs.h new file mode 100644 index 0000000000..166a5c3691 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_dxs.h @@ -0,0 +1,95 @@ +/*! + * @file tsc_dxs.h + * + * @brief This file contains external declarations of the tsc_dxs.c file. + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __TOUCH_DXS_H +#define __TOUCH_DXS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes */ +#include "tsc_object.h" + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_DXS_Driver TSC DXS Driver + @{ +*/ + +/** @defgroup TSC_DXS_Macros Macros + @{ +*/ + +#define FOR_OBJ_TYPE TSC_Globals.For_Obj->Type + +#define FOR_KEY TSC_Globals.For_Key +#define FOR_KEY_STATEID TSC_Globals.For_Key->p_Data->StateId +#define FOR_KEY_DXSLOCK TSC_Globals.For_Key->p_Data->DxsLock +#define FOR_KEY_CHANGE TSC_Globals.For_Key->p_Data->Change + +#define FOR_LINROT TSC_Globals.For_LinRot +#define FOR_LINROT_STATEID TSC_Globals.For_LinRot->p_Data->StateId +#define FOR_LINROT_DXSLOCK TSC_Globals.For_LinRot->p_Data->DxsLock +#define FOR_LINROT_CHANGE TSC_Globals.For_LinRot->p_Data->Change + +/**@} end of group TSC_DXS_Macros */ + +/** @defgroup TSC_DXS_Enumerations Enumerations + @{ +*/ + +/**@} end of group TSC_DXS_Enumerations */ + +/** @defgroup TSC_DXS_Structures Structures + @{ +*/ + +/**@} end of group TSC_DXS_Structures */ + +/** @defgroup TSC_DXS_Variables Variables + @{ +*/ + +/**@} end of group TSC_DXS_Variables */ + +/** @defgroup TSC_DXS_Functions Functions + @{ +*/ + +void TSC_Dxs_FirstObj(CONST TSC_ObjectGroup_T* objgrp); + +#ifdef __cplusplus +} +#endif + +#endif /* __TSC_DXS_H */ + +/**@} end of group TSC_DXS_Functions */ +/**@} end of group TSC_DXS_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_ecs.h b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_ecs.h new file mode 100644 index 0000000000..55b1f3ae13 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_ecs.h @@ -0,0 +1,94 @@ +/*! + * @file tsc_ecs.h + * + * @brief This file contains external declarations of the tsc_ecs.c file. + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __TOUCH_ECS_H +#define __TOUCH_ECS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes */ +#include "tsc_object.h" + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_ECS_Driver TSC ECS Driver + @{ +*/ + +/** @defgroup TSC_ECS_Macros Macros + @{ +*/ + +#define FOR_OBJ_TYPE TSC_Globals.For_Obj->Type +#define FOR_KEY_REF TSC_Globals.For_Key->p_ChD->Refer +#define FOR_KEY_REFREST TSC_Globals.For_Key->p_ChD->RefRest +#define FOR_KEY_DELTA TSC_Globals.For_Key->p_ChD->Delta +#define FOR_KEY_STATEID TSC_Globals.For_Key->p_Data->StateId + +#define FOR_LINROT_STATEID TSC_Globals.For_LinRot->p_Data->StateId +#define FOR_LINROT_NB_CHANNELS TSC_Globals.For_LinRot->NumChannel + +/**@} end of group TSC_ECS_Macros */ + +/** @defgroup TSC_ECS_Enumerations Enumerations + @{ +*/ + +/**@} end of group TSC_ECS_Enumerations */ + +/** @defgroup TSC_ECS_Structures Structures + @{ +*/ + +/**@} end of group TSC_ECS_Structures */ + +/** @defgroup TSC_ECS_Variables Variables + @{ +*/ + +/**@} end of group TSC_ECS_Variables */ + +/** @defgroup TSC_ECS_Functions Functions + @{ +*/ + +TSC_tKCoeff_T TSC_Ecs_CalculateK(TSC_ObjectGroup_T* objgrp, TSC_tKCoeff_T kDiffer, TSC_tKCoeff_T kSame); +void TSC_Ecs_ProcessK(TSC_ObjectGroup_T* objgrp, TSC_tKCoeff_T kCoeff); +TSC_STATUS_T TSC_Ecs_Process(TSC_ObjectGroup_T* objgrp); + +#ifdef __cplusplus +} +#endif + +#endif /* __TSC_ECS_H */ + +/**@} end of group TSC_ECS_Functions*/ +/**@} end of group TSC_ECS_Driver */ +/**@} end of group TSC_Driver_Library*/ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_filter.h b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_filter.h new file mode 100644 index 0000000000..ec5a291042 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_filter.h @@ -0,0 +1,90 @@ +/*! + * @file tsc_filter.h + * + * @brief This file contains external declarations of the tsc_filter.c file. + * + * @version V1.0.0 + * + * @date 2022-02-21 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __TSC_FILTER_H +#define __TSC_FILTER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes */ +#include "tsc_acq.h" + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_Filter_Driver TSC Filter Driver + @{ +*/ + +/** @defgroup TSC_Filter_Macros Macros + @{ +*/ + +/* Can be[0..5] - Warning: all thresholds must be shifted if different from 0 */ +#define ACQ_FILTER_RANGE (0) + +/* Can be[1..255] - First order filter coefficient (k = ACQ_FILTER_COEFF/256) */ +#define ACQ_FILTER_COEFF (128) + +/**@} end of group TSC_Filter_Macros */ + +/** @defgroup TSC_Filter_Enumerations Enumerations + @{ +*/ + +/**@} end of group TSC_Filter_Enumerations */ + +/** @defgroup TSC_Filter_Structures Structures + @{ +*/ + +/**@} end of group TSC_Filter_Structures */ + +/** @defgroup TSC_Filter_Variables Variables + @{ +*/ + +/**@} end of group TSC_Filter_Variables */ + +/** @defgroup TSC_Filter_Functions Functions + @{ +*/ + +TSC_tMeas_T TSC_Filt_MeasFilter(TSC_tMeas_T preMeasn, TSC_tMeas_T curMeasn); +TSC_tDelta_T TSC_Filt_DeltaFilter(TSC_tDelta_T delta); + +#ifdef __cplusplus +} +#endif + +#endif /* __TSC_FILTER_H */ + +/**@} end of group TSC_Filter_Functions */ +/**@} end of group TSC_Filter_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_linrot.h b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_linrot.h new file mode 100644 index 0000000000..58c05da738 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_linrot.h @@ -0,0 +1,273 @@ +/*! + * @file tsc_linrot.h + * + * @brief This file contains external declarations of the tsc_linrot.c file. + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __TOUCH_LINROT_H +#define __TOUCH_LINROT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes */ +#include "tsc_acq.h" +#include "tsc_time.h" + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_Linrot_Driver TSC Linrot Driver + @{ +*/ + +/** @defgroup TSC_Linrot_Macros Macros + @{ +*/ + +#define TSC_SCTCOMP_3CH_LIN_M1 ((TSC_tNum_T)(128)) +#define TSC_POSCORR_3CH_LIN_M1 ((TSC_tNum_T)( 64)) +#define TSC_SCTCOMP_3CH_LIN_M2 ((TSC_tNum_T)(256)) +#define TSC_POSCORR_3CH_LIN_M2 ((TSC_tNum_T)(256)) + +#define TSC_SCTCOMP_3CH_LIN_H ((TSC_tNum_T)(128)) +#define TSC_POSCORR_3CH_LIN_H ((TSC_tNum_T)(128)) + +#define TSC_SCTCOMP_3CH_ROT_M ((TSC_tNum_T)( 85)) + +#define TSC_SCTCOMP_4CH_LIN_M1 ((TSC_tNum_T)( 85)) +#define TSC_POSCORR_4CH_LIN_M1 ((TSC_tNum_T)( 43)) +#define TSC_SCTCOMP_4CH_LIN_M2 ((TSC_tNum_T)(128)) +#define TSC_POSCORR_4CH_LIN_M2 ((TSC_tNum_T)(128)) + +#define TSC_SCTCOMP_4CH_LIN_H ((TSC_tNum_T)( 85)) +#define TSC_POSCORR_4CH_LIN_H ((TSC_tNum_T)( 85)) + +#define TSC_SCTCOMP_4CH_ROT_M ((TSC_tNum_T)( 64)) + +#define TSC_SCTCOMP_5CH_LIN_M1 ((TSC_tNum_T)( 64)) +#define TSC_POSCORR_5CH_LIN_M1 ((TSC_tNum_T)( 32)) +#define TSC_SCTCOMP_5CH_LIN_M2 ((TSC_tNum_T)( 85)) +#define TSC_POSCORR_5CH_LIN_M2 ((TSC_tNum_T)( 85)) + +#define TSC_SCTCOMP_5CH_LIN_H ((TSC_tNum_T)( 64)) +#define TSC_POSCORR_5CH_LIN_H ((TSC_tNum_T)( 64)) + +#define TSC_SCTCOMP_5CH_ROT_M ((TSC_tNum_T)( 51)) + +#define TSC_SCTCOMP_5CH_ROT_D ((TSC_tNum_T)( 26)) + +#define TSC_SCTCOMP_6CH_LIN_M1 ((TSC_tNum_T)( 51)) +#define TSC_POSCORR_6CH_LIN_M1 ((TSC_tNum_T)( 25)) +#define TSC_SCTCOMP_6CH_LIN_M2 ((TSC_tNum_T)( 64)) +#define TSC_POSCORR_6CH_LIN_M2 ((TSC_tNum_T)( 64)) + +#define TSC_SCTCOMP_6CH_LIN_H ((TSC_tNum_T)( 51)) +#define TSC_POSCORR_6CH_LIN_H ((TSC_tNum_T)( 51)) + +#define TSC_SCTCOMP_6CH_ROT_M ((TSC_tNum_T)( 43)) + +/**@} end of group TSC_Linrot_Macros */ + +/** @defgroup TSC_Linrot_Enumerations Enumerations + @{ +*/ + +/**@} end of group TSC_Linrot_Enumerations */ + +/** @defgroup TSC_Linrot_Structures Structures + @{ +*/ + +/** + * @brief Contains all data related to Linear and Rotary sensor. + * Variables of this structure type must be placed in RAM only. + */ +typedef struct +{ + TSC_STATEID_T StateId; /*!< Current state identifier */ + TSC_tsignPosition_T RawPosition; /*!< Raw position */ + TSC_tsignPosition_T Position; /*!< Scaled position */ + TSC_tCounter_T CounterDebounce; /*!< Counter for debounce and calibration management */ + unsigned int CounterDTO : 6; /*!< Counter for DTO management (TSC_tCounter_T) */ + unsigned int Change : 1; /*!< The State is different from the previous one (TSC_STATE_T) */ + unsigned int PosChange : 1; /*!< The RawPosition/Position is different from the previous one (TSC_STATE_T) */ + unsigned int CounterDirection : 6; /*!< Counter for direction debounce management (TSC_tCounter_T) */ + unsigned int DxsLock : 1; /*!< The State is locked by the DxS (TSC_BOOL_T) */ + unsigned int Direction : 1; /*!< Movement direction (TSC_BOOL_T) */ +} TSC_LinRotData_T; + +/** + * @brief Contains all parameters related to Linear and Rotary sensor. + * Variables of this structure type can be placed in RAM or ROM. + */ +typedef struct +{ + /* Thresholds */ +#if TOUCH_USE_PROX > 0 + TSC_tThreshold_T ProxInTh; /*!< Proximity state in threshold */ + TSC_tThreshold_T ProxOutTh; /*!< Proximity state out threshold */ +#endif + TSC_tThreshold_T DetectInTh; /*!< Detection state in threshold */ + TSC_tThreshold_T DetectOutTh; /*!< Detection state out threshold */ + TSC_tThreshold_T CalibTh; /*!< Calibration state threshold */ + + /* Debounce counters */ + TSC_tCounter_T CounterDebCalib; /*!< Debounce counter to enter in Calibration state */ +#if TOUCH_USE_PROX > 0 + TSC_tCounter_T CounterDebProx; /*!< Debounce counter to enter in Proximity state */ +#endif + TSC_tCounter_T CounterDebDetect; /*!< Debounce counter to enter in Detect state */ + TSC_tCounter_T CounterDebRelease; /*!< Debounce counter to enter in Release state */ + TSC_tCounter_T CounterDebError; /*!< Debounce counter to enter in Error state */ + TSC_tCounter_T CounterDebDirection; /*!< Debounce counter for the direction change */ + + /* Other parameters */ + TSC_tCounter_T Resolution; /*!< Position resolution */ + TSC_tsignPosition_T DirChangePos; /*!< Direction change position threshold */ +} TSC_LinRotParam_T; + +/** + * @brief Contains all parameters related to Linear and Rotary sensor. + * Variables of this structure type can be placed in RAM or ROM. + */ +typedef struct +{ + TSC_LinRotData_T* p_Data; /*!< Data (state id, counter, flag, ...) */ + TSC_LinRotParam_T* p_Param; /*!< Parameters (thresholds, debounce, ...) */ + TSC_Channel_Data_T* p_ChD; /*!< First Channel Data (Meas, Refer, Delta, ...) */ + TSC_tNum_T NumChannel; /*!< Number of channels */ + CONST uint16_t* p_DeltaCoeff; /*!< Coefficient to apply on Delta */ + CONST TSC_tPosition_T* p_PosOff; /*!< Position offset table */ + TSC_tNum_T SctComp; /*!< Sector Computation */ + TSC_tNum_T PosCorr; /*!< Position Correction */ + CONST TSC_State_T* p_SM; /*!< State Machine */ + CONST TSC_LinRotMethods_T* p_Methods; /*!< Methods */ +} TSC_LinRot_T; + +/** + * @brief Contains all parameters related to Linear and Rotary sensor. + * Variables of this structure type can be placed in RAM or ROM. + * Basic sensor does not contain its own state machine and methods. + * It used default ones instead to gain memory space. + */ +typedef struct +{ + TSC_LinRotData_T* p_Data; /*!< Data (state id, counter, flag, ...) */ + TSC_LinRotParam_T* p_Param; /*!< Parameters (thresholds, debounce, ...) */ + TSC_Channel_Data_T* p_ChD; /*!< First Channel Data (Meas, Refer, Delta, ...) */ + TSC_tNum_T NumChannel; /*!< Number of channels */ + CONST uint16_t* p_DeltaCoeff; /*!< Coefficient to apply on Delta */ + CONST TSC_tPosition_T* p_PosOff; /*!< Position offset table */ + TSC_tNum_T SctComp; /*!< Sector Computation */ + TSC_tNum_T PosCorr; /*!< Position Correction */ +} TSC_LinRotB_T; + +/**@} end of group TSC_Linrot_Structures */ + +/** @defgroup TSC_Linrot_Variables Variables + @{ +*/ + +/* Position offset constant tables and corrections */ +extern CONST TSC_tPosition_T TSC_POSOFF_3CH_LIN_M1[3][3]; +extern CONST TSC_tPosition_T TSC_POSOFF_3CH_LIN_M2[3][3]; +extern CONST TSC_tPosition_T TSC_POSOFF_3CH_LIN_H[3][3]; +extern CONST TSC_tPosition_T TSC_POSOFF_3CH_ROT_M[3][3]; + +extern CONST TSC_tPosition_T TSC_POSOFF_4CH_LIN_M1[4][4]; +extern CONST TSC_tPosition_T TSC_POSOFF_4CH_LIN_M2[4][4]; +extern CONST TSC_tPosition_T TSC_POSOFF_4CH_LIN_H[4][4]; +extern CONST TSC_tPosition_T TSC_POSOFF_4CH_ROT_M[4][4]; + +extern CONST TSC_tPosition_T TSC_POSOFF_5CH_LIN_M1[5][5]; +extern CONST TSC_tPosition_T TSC_POSOFF_5CH_LIN_M2[5][5]; +extern CONST TSC_tPosition_T TSC_POSOFF_5CH_LIN_H[5][5]; +extern CONST TSC_tPosition_T TSC_POSOFF_5CH_ROT_M[5][5]; +extern CONST TSC_tPosition_T TSC_POSOFF_5CH_ROT_D[5][5]; + +extern CONST TSC_tPosition_T TSC_POSOFF_6CH_LIN_M1[6][6]; +extern CONST TSC_tPosition_T TSC_POSOFF_6CH_LIN_M2[6][6]; +extern CONST TSC_tPosition_T TSC_POSOFF_6CH_LIN_H[6][6]; +extern CONST TSC_tPosition_T TSC_POSOFF_6CH_ROT_M[6][6]; + +/**@} end of group TSC_Linrot_Variables */ + +/** @defgroup TSC_Linrot_Functions Functions + @{ +*/ + +/* "Object methods" functions */ +void TSC_Linrot_Config(void); +void TSC_Linrot_Process(void); +TSC_STATUS_T TSC_Linrot_CalcPos(void); + +/* Utility functions */ +void TSC_Linrot_ConfigCalibrationState(TSC_tCounter_T delay); +void TSC_Linrot_ConfigOffState(void); +void TSC_Linrot_ConfigBurstOnlyState(void); +TSC_STATEID_T TSC_Linrot_ReadStateId(void); +TSC_STATEMASK_T TSC_Linrot_ReadStateMask(void); +TSC_tNum_T TSC_Linrot_ReadChangeFlag(void); + +/* State machine functions */ +void TSC_Linrot_ProcessCalibrationState(void); +void TSC_Linrot_ProcessDebCalibrationState(void); +void TSC_Linrot_ProcessReleaseState(void); +void TSC_Linrot_ProcessDebReleaseProxState(void); +void TSC_Linrot_ProcessDebReleaseDetectState(void); +void TSC_Linrot_ProcessDebReleaseTouchState(void); +void TSC_Linrot_ProcessProxState(void); +void TSC_Linrot_ProcessDebProxState(void); +void TSC_Linrot_ProcessDebProxDetectState(void); +void TSC_Linrot_ProcessDebProxTouchState(void); +void TSC_Linrot_ProcessDetectState(void); +void TSC_Linrot_ProcessDebDetectState(void); +void TSC_Linrot_ProcessTouchState(void); +void TSC_Linrot_ProcessDebTouchState(void); +void TSC_Linrot_ProcessDebErrorState(void); + +/* Private functions */ +void TSC_Linrot_ReadTimeForDTO(void); +void TSC_Linrot_Process_AllChannel_Status(TSC_OBJ_STATUS_T status); +TSC_STATUS_T TSC_Linrot_Process_OneChannel_DataReady(void); +TSC_STATUS_T TSC_Linrot_Process_AllChannel_AcqStatus(TSC_ACQ_STATUS_T status); +TSC_STATUS_T TSC_Linrot_Process_OneChannel_AcqStatusError(void); +TSC_STATUS_T TSC_Linrot_Process_OneChannel_DeltaBelowEquMinus(TSC_tThreshold_T threshold, TSC_tIndex_T Cmd); +TSC_STATUS_T TSC_Linrot_Process_OneChannel_DeltaAboveEqu(TSC_tThreshold_T threshold, TSC_tIndex_T Cmd); +TSC_STATUS_T TSC_Linrot_Process_OneChannel_DeltaAbove(TSC_tThreshold_T threshold, TSC_tIndex_T Cmd); +TSC_STATUS_T TSC_Linrot_Process_AllChannel_DeltaBelowEqu(TSC_tThreshold_T threshold, TSC_tIndex_T Cmd); +void TSC_Linrot_Process_AllChannel_ClearRef(void); +TSC_tDelta_T TSC_Linrot_NormDelta(TSC_Channel_Data_T* channel, TSC_tIndex_T index); + +#ifdef __cplusplus +} +#endif + +#endif /* __TSC_LINROT_H */ + +/**@} end of group TSC_Linrot_Functions */ +/**@} end of group TSC_Linrot_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_object.h b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_object.h new file mode 100644 index 0000000000..64def000a6 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_object.h @@ -0,0 +1,126 @@ +/*! + * @file tsc_object.h + * + * @brief This file contains external declarations of the tsc_object.c file. + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __TOUCH_OBJECT_H +#define __TOUCH_OBJECT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes */ +#include "tsc_touchkey.h" +#include "tsc_linrot.h" + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_Object_Driver TSC Object Driver + @{ +*/ + +/** @defgroup TSC_Object_Macros Macros + @{ +*/ + +#define TSC_OBJ_TYPE_KEY_MASK (0x10) /*!< TouchKey object mask */ +#define TSC_OBJ_TYPE_LINROT_MASK (0x20) /*!< Linear and Rotary objects mask */ +#define TSC_OBJ_TYPE_TRACKNAV_MASK (0x40) /*!< TrackPad and NaviPad objects mask */ + +/**@} end of group TSC_Object_Macros */ + +/** @defgroup TSC_Object_Enumerations Enumerations + @{ +*/ + +/** + * @brief Contains all different kinds of sensors + */ +typedef enum +{ + TSC_OBJ_TOUCHKEY = (TSC_OBJ_TYPE_KEY_MASK + 0), /*!< Normal TouchKey */ + TSC_OBJ_TOUCHKEYB = (TSC_OBJ_TYPE_KEY_MASK + 1), /*!< Basic TouchKey */ + TSC_OBJ_LINEAR = (TSC_OBJ_TYPE_LINROT_MASK + 0), /*!< Normal Linear sensor */ + TSC_OBJ_LINEARB = (TSC_OBJ_TYPE_LINROT_MASK + 1), /*!< Basic Linear sensor */ + TSC_OBJ_ROTARY = (TSC_OBJ_TYPE_LINROT_MASK + 2), /*!< Normal Rotary sensor */ + TSC_OBJ_ROTARYB = (TSC_OBJ_TYPE_LINROT_MASK + 3), /*!< Basic Rotary sensor */ + TSC_OBJ_TRACKPAD = (TSC_OBJ_TYPE_TRACKNAV_MASK + 0), /*!< TrackPad sensor */ + TSC_OBJ_NAVIPAD = (TSC_OBJ_TYPE_TRACKNAV_MASK + 1) /*!< NaviPad sensor */ +} TSC_OBJECT_T; + +/**@} end of group TSC_Object_Enumerations */ + +/** @defgroup TSC_Object_Structures Data Object Structures + @{ +*/ + +/** + * @brief Contains the definition of an Object. + * Variables of this structure type can be placed in RAM or ROM. + */ +typedef struct +{ + TSC_OBJECT_T Type; /*!< Object type */ + void* MyObj; /*!< Pointer to the object */ +} TSC_Object_T; + +/** + * @brief Contains the definition of a Group of Objects. + * Variables of this structure type can be placed in RAM or ROM. + */ +typedef struct +{ + CONST TSC_Object_T* p_Obj; /*!< Pointer to the first object */ + TSC_tNum_T NbObjects; /*!< Number of objects in the group */ + TSC_tNum_T StateMask; /*!< "OR" of all objects state mask */ + TSC_STATE_T Change; /*!< The State is different from the previous one */ + TSC_tIndex_T execution; /*!< Flag for the ECS execution */ +#if TOUCH_ECS_DELAY > 0 + TSC_tIndex_T wait; /*!< Flag for the ECS delay */ + TSC_tTick_ms_T time; /*!< Keep the time for the ECS delay */ +#endif +} TSC_ObjectGroup_T; + +/**@} end of group TSC_Object_Structures */ + +/** @defgroup TSC_Object_Functions Functions + @{ +*/ + +void TSC_Obj_ConfigGroup(TSC_ObjectGroup_T* objgrp); +void TSC_Obj_ProcessGroup(TSC_ObjectGroup_T* objgrp); +void TSC_Obj_ConfigGlobalObj(CONST TSC_Object_T* pObj); + +#ifdef __cplusplus +} +#endif + +#endif /* __TSC_OBJECT_H */ + +/**@} end of group TSC_Object_Functions */ +/**@} end of group TSC_Object_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_time.h b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_time.h new file mode 100644 index 0000000000..806535aa5a --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_time.h @@ -0,0 +1,87 @@ +/*! + * @file tsc_time.h + * + * @brief This file contains external declarations of the tsc_time.c file. + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __TOUCH_TIME_H +#define __TOUCH_TIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes */ +#include "apm32f0xx.h" +#include "tsc_types.h" +#include "tsc_acq.h" + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_Time_Driver TSC Time Driver + @{ +*/ + +/** @defgroup TSC_Time_Macros Macros + @{ +*/ + +/**@} end of group TSC_Time_Macros */ + +/** @defgroup TSC_Time_Enumerations Enumerations + @{ +*/ + +/**@} end of group TSC_Time_Enumerations */ + +/** @defgroup TSC_Time_Structures Structures + @{ +*/ +/**@} end of group TSC_Time_Structures */ + +/** @defgroup TSC_Time_Variables Variables + @{ +*/ +/**@} end of group TSC_Time_Variables */ + +/** @defgroup TSC_Time_Functions Functions + @{ +*/ + +TSC_STATUS_T TSC_Time_Config(void); +void TSC_Time_ProcessInterrupt(void); +TSC_STATUS_T TSC_Time_Delay_ms(TSC_tTick_ms_T delay_ms, __IO TSC_tTick_ms_T* last_tick); +TSC_STATUS_T TSC_Time_Delay_sec(TSC_tTick_sec_T delay_sec, __IO TSC_tTick_sec_T* last_tick); +void TSC_CallBack_TimerTick(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __TSC_TIME_H */ + +/**@} end of group TSC_Time_Functions */ +/**@} end of group TSC_Time_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_touchkey.h b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_touchkey.h new file mode 100644 index 0000000000..284c7c81a2 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_touchkey.h @@ -0,0 +1,165 @@ +/*! + * @file tsc_touchkey.h + * + * @brief This file contains external declarations of the tsc_touchkey.c file. + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __TOUCH_TOUCHKEY_H +#define __TOUCH_TOUCHKEY_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes */ +#include "tsc_acq.h" +#include "tsc_time.h" + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_TouchKey_Driver TSC TouchKey Driver + @{ +*/ + +/** @defgroup TSC_TouchKey_Macros Macros + @{ +*/ + +/**@} end of group TSC_TouchKey_Macros */ + +/** @defgroup TSC_TouchKey_Enumerations Enumerations + @{ +*/ + +/**@} end of group TSC_TouchKey_Enumerations */ + +/** @defgroup TSC_TouchKey_Structures Structures + @{ +*/ + +/** + * @brief Contains all data related to TouchKey sensor. + * Variables of this structure type must be placed in RAM only. + */ +typedef struct +{ + TSC_STATEID_T StateId; /*!< Current state identifier */ + TSC_tCounter_T CounterDebounce; /*!< Counter for debounce and calibration management */ + unsigned int CounterDTO : 6; /*!< Counter for DTO management (TSC_tCounter_T) */ + unsigned int Change : 1; /*!< The State is different from the previous one (TSC_STATE_T) */ + unsigned int DxsLock : 1; /*!< The State is locked by the DxS (TSC_BOOL_T) */ +} TSC_TouchKeyData_T; + +/** + * @brief Contains all data related to TouchKey sensor. + * Variables of this structure type can be placed in RAM or ROM. + */ +typedef struct +{ +#if TOUCH_USE_PROX > 0 + TSC_tThreshold_T ProxInTh; /*!< Proximity in threshold */ + TSC_tThreshold_T ProxOutTh; /*!< Proximity out threshold */ +#endif + TSC_tThreshold_T DetectInTh; /*!< Detection in threshold */ + TSC_tThreshold_T DetectOutTh; /*!< Detection out threshold */ + TSC_tThreshold_T CalibTh; /*!< Calibration threshold */ + TSC_tCounter_T CounterDebCalib; /*!< Debounce counter to enter in Calibration state */ +#if TOUCH_USE_PROX > 0 + TSC_tCounter_T CounterDebProx; /*!< Debounce counter to enter in Proximity state */ +#endif + TSC_tCounter_T CounterDebDetect; /*!< Debounce counter to enter in Detect state */ + TSC_tCounter_T CounterDebRelease; /*!< Debounce counter to enter in Release state */ + TSC_tCounter_T CounterDebError; /*!< Debounce counter to enter in Error state */ +} TSC_TouchKeyParam_T; + +/** + * @brief Contains definition of a TouchKey sensor. + * Variables of this structure type can be placed in RAM or ROM. + */ +typedef struct +{ + TSC_TouchKeyData_T* p_Data; /*!< Data (state id, counter, flag, ...) */ + TSC_TouchKeyParam_T* p_Param; /*!< Parameters (thresholds, debounce, ...) */ + TSC_Channel_Data_T* p_ChD; /*!< Channel Data (Meas, Refer, Delta, ...) */ + CONST TSC_State_T* p_SM; /*!< State Machine */ + CONST TSC_TouchKeyMethods_T* p_Methods; /*!< Methods */ +} TSC_TouchKey_T; + +/** + * @brief Contains definition of a Basic TouchKey sensor. + * Variables of this structure type can be placed in RAM or ROM. + * Basic sensor does not contain its own state machine and methods. It used + * default ones instead to gain memory space. + */ +typedef struct +{ + TSC_TouchKeyData_T* p_Data; /*!< Data (state id, counters, flag, ...) */ + TSC_TouchKeyParam_T* p_Param; /*!< Parameters (thresholds, debounce, ...) */ + TSC_Channel_Data_T* p_ChD; /*!< Channel Data (Meas, Refer, Delta, ...) */ +} TSC_TouchKeyB_T; + +/**@} end of group TSC_TouchKey_Structures */ + +/** @defgroup TSC_TouchKey_Functions Functions + @{ +*/ + +/* "Object methods" functions */ +void TSC_TouchKey_Config(void); +void TSC_TouchKey_Process(void); + +/* Utility functions */ +void TSC_TouchKey_ConfigCalibrationState(TSC_tCounter_T delay); +void TSC_TouchKey_ConfigOffState(void); +void TSC_TouchKey_ConfigBurstOnlyState(void); +TSC_STATEID_T TSC_TouchKey_ReadStateId(void); +TSC_STATEMASK_T TSC_TouchKey_ReadStateMask(void); +TSC_tNum_T TSC_TouchKey_ReadChangeFlag(void); + +/* State machine functions */ +void TSC_TouchKey_ProcessCalibrationState(void); +void TSC_TouchKey_ProcessDebCalibrationState(void); +void TSC_TouchKey_ProcessReleaseState(void); +void TSC_TouchKey_ProcessDebReleaseProxState(void); +void TSC_TouchKey_ProcessDebReleaseDetectState(void); +void TSC_TouchKey_ProcessDebReleaseTouchState(void); +void TSC_TouchKey_ProcessProxState(void); +void TSC_TouchKey_ProcessDebProxState(void); +void TSC_TouchKey_ProcessDebProxDetectState(void); +void TSC_TouchKey_ProcessDebProxTouchState(void); +void TSC_TouchKey_ProcessDetectState(void); +void TSC_TouchKey_ProcessDebDetectState(void); +void TSC_TouchKey_ProcessTouchState(void); +void TSC_TouchKey_ProcessDebErrorState(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __TSC_TOUCHKEY_H */ + +/**@} end of group TSC_TouchKey_Functions */ +/**@} end of group TSC_TouchKey_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_types.h b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_types.h new file mode 100644 index 0000000000..42b2202e96 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/inc/tsc_types.h @@ -0,0 +1,271 @@ +/*! + * @file tsc_types.h + * + * @brief This file contains all general structures definition. + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __TSC_TYPES_H +#define __TSC_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_Types_Driver TSC Types Driver + @{ +*/ + +/** @defgroup TSC_Types_Macros Macros + @{ +*/ + +#define TSC_ACQ_STATUS_ERROR_MASK (0x02) /*!< Associated to TSC_ACQ_STATUS_T */ + +#define TSC_OBJ_STATUS_ACQ_MASK (0x01) /*!< Associated to TSC_OBJ_STATUS_T */ +#define TSC_OBJ_STATUS_BURST_MASK (0x02) /*!< Associated to TSC_OBJ_STATUS_T */ + + +#define TSC_STATE_ERROR_BIT_MASK (0x80) /*!< Associated to TSC_STATEMASK_T */ +#define TSC_STATE_OFF_BIT_MASK (0x40) /*!< Associated to TSC_STATEMASK_T */ +#define TSC_STATE_DEBOUNCE_BIT_MASK (0x20) /*!< Associated to TSC_STATEMASK_T */ +#define TSC_STATE_CALIB_BIT_MASK (0x10) /*!< Associated to TSC_STATEMASK_T */ +#define TSC_STATE_TOUCH_BIT_MASK (0x08) /*!< Associated to TSC_STATEMASK_T */ +#define TSC_STATE_DETECT_BIT_MASK (0x04) /*!< Associated to TSC_STATEMASK_T */ +#define TSC_STATE_PROX_BIT_MASK (0x02) /*!< Associated to TSC_STATEMASK_T */ +#define TSC_STATE_RELEASE_BIT_MASK (0x01) /*!< Associated to TSC_STATEMASK_T */ + +/**@} end of group TSC_Types_Macros */ + +/** @defgroup TSC_Types_Enumerations Enumerations + @{ +*/ + +/** + * @brief Generic Boolean status + */ +typedef enum +{ + TSC_FALSE = 0, /*!< A False value */ + TSC_TRUE = 1 /*!< A True value */ +} TSC_BOOL_T; + +/** + * @brief Generic status returned by functions + */ +typedef enum +{ + TSC_STATUS_OK = 0, /*!< The function has been executed correctly */ + TSC_STATUS_BUSY = 1, /*!< The function is in a Busy state */ + TSC_STATUS_ERROR = 2 /*!< The function has been executed not correctly */ +} TSC_STATUS_T; + +/** + * @brief DataReady status : 1 bit + * Used by acquisition to indicate if a new measurement is ready or not. + */ +typedef enum +{ + TSC_DATA_NOT_READY = 0, /*!< No new measurement or measurement treated */ + TSC_DATA_READY = 1 /*!< A new measurement is ready */ +} TSC_DATA_T; + +/** + * @brief State change status + */ +typedef enum +{ + TSC_STATE_NOT_CHANGED = 0, /*!< The object has the same state */ + TSC_STATE_CHANGED = 1 /*!< The object has changed of state */ +} TSC_STATE_T; + + +/** + * @brief Acquisition status + */ +typedef enum +{ + TSC_ACQ_STATUS_OK = 0, /*!< The acquisition is correct */ + TSC_ACQ_STATUS_NOISE = 1, /*!< Noise detected during the acquisition */ + TSC_ACQ_STATUS_ERROR_MIN = TSC_ACQ_STATUS_ERROR_MASK, /*!< The measure is below the minimum threshold */ + TSC_ACQ_STATUS_ERROR_MAX = (TSC_ACQ_STATUS_ERROR_MASK | 0x01) /*!< The measure is above the maximum threshold */ +} TSC_ACQ_STATUS_T; + +/** + * @brief Block status + */ +typedef enum +{ + TSC_BLOCK_STATUS_DISABLED = 0, /*!< The block is disabled */ + TSC_BLOCK_STATUS_ENABLED = 1 /*!< The block is enabled */ +} TSC_BLOCK_STATUS_T; + +/** + * @brief Zone status + */ +typedef enum +{ + TSC_ZONE_STATUS_DISABLED = 0, /*!< The zone is disabled */ + TSC_ZONE_STATUS_ENABLED = 1 /*!< The zone is enabled */ +} TSC_ZONE_STATUS_T; + +/** + * @brief Object status + */ +typedef enum +{ + TSC_OBJ_STATUS_OFF = 0, /*!< No burst and no acquisition */ + TSC_OBJ_STATUS_BURST_ONLY = TSC_OBJ_STATUS_BURST_MASK, /*!< Burst only */ + TSC_OBJ_STATUS_ON = (TSC_OBJ_STATUS_BURST_MASK | TSC_OBJ_STATUS_ACQ_MASK) /*!< Burst and acquisition */ +} TSC_OBJ_STATUS_T; + +/** + * @brief Object state masks + */ +typedef enum +{ + /* Calibration states */ + TSC_STATEMASK_CALIB = TSC_STATE_CALIB_BIT_MASK, /*!< 0x10 */ + TSC_STATEMASK_DEB_CALIB = (TSC_STATE_DEBOUNCE_BIT_MASK | TSC_STATE_CALIB_BIT_MASK), /*!< 0x30 */ + /* Release states */ + TSC_STATEMASK_RELEASE = TSC_STATE_RELEASE_BIT_MASK, /*!< 0x01 */ + TSC_STATEMASK_DEB_RELEASE_PROX = (TSC_STATE_DEBOUNCE_BIT_MASK | TSC_STATE_RELEASE_BIT_MASK | TSC_STATE_PROX_BIT_MASK), /*!< 0x23 */ + TSC_STATEMASK_DEB_RELEASE_DETECT = (TSC_STATE_DEBOUNCE_BIT_MASK | TSC_STATE_RELEASE_BIT_MASK | TSC_STATE_DETECT_BIT_MASK), /*!< 0x25 */ + TSC_STATEMASK_DEB_RELEASE_TOUCH = (TSC_STATE_DEBOUNCE_BIT_MASK | TSC_STATE_RELEASE_BIT_MASK | TSC_STATE_TOUCH_BIT_MASK), /*!< 0x29 */ + /* Proximity states */ + TSC_STATEMASK_PROX = TSC_STATE_PROX_BIT_MASK, /*!< 0x02 */ + TSC_STATEMASK_DEB_PROX = (TSC_STATE_DEBOUNCE_BIT_MASK | TSC_STATE_PROX_BIT_MASK), /*!< 0x22 */ + TSC_STATEMASK_DEB_PROX_DETECT = (TSC_STATE_DEBOUNCE_BIT_MASK | TSC_STATE_PROX_BIT_MASK | TSC_STATE_DETECT_BIT_MASK), /*!< 0x26 */ + TSC_STATEMASK_DEB_PROX_TOUCH = (TSC_STATE_DEBOUNCE_BIT_MASK | TSC_STATE_PROX_BIT_MASK | TSC_STATE_TOUCH_BIT_MASK), /*!< 0x2A */ + /* Detect states */ + TSC_STATEMASK_DETECT = TSC_STATE_DETECT_BIT_MASK, /*!< 0x04 */ + TSC_STATEMASK_DEB_DETECT = (TSC_STATE_DEBOUNCE_BIT_MASK | TSC_STATE_DETECT_BIT_MASK), /*!< 0x24 */ + /* Touch state */ + TSC_STATEMASK_TOUCH = TSC_STATE_TOUCH_BIT_MASK, /*!< 0x08 */ + /* Error states */ + TSC_STATEMASK_ERROR = TSC_STATE_ERROR_BIT_MASK, /*!< 0x80 */ + TSC_STATEMASK_DEB_ERROR_CALIB = (TSC_STATE_DEBOUNCE_BIT_MASK | TSC_STATE_ERROR_BIT_MASK | TSC_STATE_CALIB_BIT_MASK), /*!< 0xB0 */ + TSC_STATEMASK_DEB_ERROR_RELEASE = (TSC_STATE_DEBOUNCE_BIT_MASK | TSC_STATE_ERROR_BIT_MASK | TSC_STATE_RELEASE_BIT_MASK), /*!< 0xA1 */ + TSC_STATEMASK_DEB_ERROR_PROX = (TSC_STATE_DEBOUNCE_BIT_MASK | TSC_STATE_ERROR_BIT_MASK | TSC_STATE_PROX_BIT_MASK), /*!< 0xA2 */ + TSC_STATEMASK_DEB_ERROR_DETECT = (TSC_STATE_DEBOUNCE_BIT_MASK | TSC_STATE_ERROR_BIT_MASK | TSC_STATE_DETECT_BIT_MASK), /*!< 0xA4 */ + TSC_STATEMASK_DEB_ERROR_TOUCH = (TSC_STATE_DEBOUNCE_BIT_MASK | TSC_STATE_ERROR_BIT_MASK | TSC_STATE_TOUCH_BIT_MASK), /*!< 0xA8 */ + /* OFF state */ + TSC_STATEMASK_OFF = TSC_STATE_OFF_BIT_MASK, /*!< 0x40 */ + /* Other states not associated to a state id */ + TSC_STATEMASK_ACTIVE = (TSC_STATE_PROX_BIT_MASK | TSC_STATE_DETECT_BIT_MASK | TSC_STATE_TOUCH_BIT_MASK | TSC_STATE_CALIB_BIT_MASK | TSC_STATE_DEBOUNCE_BIT_MASK), /*!< 0x3E */ + TSC_STATEMASK_UNKNOWN = 0 /*!< 0x00 */ +} TSC_STATEMASK_T; + +/** + * @brief Object state identifiers + */ +typedef enum +{ + /* Calibration states */ + TSC_STATEID_CALIB = 0, /*!< 0 - Object is in Calibration */ + TSC_STATEID_DEB_CALIB = 1, /*!< 1 - Object is in Debounce Calibration */ + /* Release states */ + TSC_STATEID_RELEASE = 2, /*!< 2 - Object is released */ + TSC_STATEID_DEB_RELEASE_PROX = 3, /*!< 3 - Object is in Debounce Release from Proximity state */ + TSC_STATEID_DEB_RELEASE_DETECT = 4, /*!< 4 - Object is in Debounce Release from Detect state */ + TSC_STATEID_DEB_RELEASE_TOUCH = 5, /*!< 5 - Object is in Debounce Release from Touch state */ + /* Proximity states */ + TSC_STATEID_PROX = 6, /*!< 6 - Object is in Proximity */ + TSC_STATEID_DEB_PROX = 7, /*!< 7 - Object is in Debounce Proximity from Release state */ + TSC_STATEID_DEB_PROX_DETECT = 8, /*!< 8 - Object is in Debounce Proximity from Detect state */ + TSC_STATEID_DEB_PROX_TOUCH = 9, /*!< 9 - Object is in Debounce Proximity from Detect state */ + /* Detect states */ + TSC_STATEID_DETECT = 10, /*!< 10 - Object is in Detect */ + TSC_STATEID_DEB_DETECT = 11, /*!< 11 - Object is in Debounce Detect */ + /* Touch state */ + TSC_STATEID_TOUCH = 12, /*!< 12 - Object is in Touch */ + /* Error states */ + TSC_STATEID_ERROR = 13, /*!< 13 - Object is in Error */ + TSC_STATEID_DEB_ERROR_CALIB = 14, /*!< 14 - Object is in Debounce Error from Calibration */ + TSC_STATEID_DEB_ERROR_RELEASE = 15, /*!< 15 - Object is in Debounce Error from Release */ + TSC_STATEID_DEB_ERROR_PROX = 16, /*!< 16 - Object is in Debounce Error from Proximity */ + TSC_STATEID_DEB_ERROR_DETECT = 17, /*!< 17 - Object is in Debounce Error from Detect */ + TSC_STATEID_DEB_ERROR_TOUCH = 18, /*!< 18 - Object is in Debounce Error from Touch */ + /* Other states */ + TSC_STATEID_OFF = 19 /*!< 19 - Object is OFF (no burst, no acquisition) */ +} TSC_STATEID_T; + +/**@} end of group TSC_Types_Enumerations */ + +/** @defgroup TSC_Types_Structures Structures + @{ +*/ + +/** + * @brief Object state + */ +typedef struct +{ + TSC_STATEMASK_T StateMask; /*!< Current state mask */ + void(* StateFunc)(void); /*!< Function executed in the state */ +} TSC_State_T; + +/** + * @brief Touchkey methods + */ +typedef struct +{ + void(* Config)(void); /*!< Used to configure the TouchKey sensor */ + void(* Process)(void); /*!< Used to execute the TouchKey sensor state machine */ +} TSC_TouchKeyMethods_T; + +/** + * @brief Linear/Rotary methods + */ +typedef struct +{ + void(* Config)(void); /*!< Used to configure the Linear/Rotary sensor */ + void(* Process)(void); /*!< Used to execute the Linear/Rotary sensor state machine */ + TSC_STATUS_T(* CalcPosition)(void); /*!< Used to calculate the Linear/Rotary sensor position */ +} TSC_LinRotMethods_T; + +/**@} end of group TSC_Types_Structures */ + +/** @defgroup TSC_Types_Variables Variables + @{ +*/ + +/**@} end of group TSC_Types_Variables */ + +/** @defgroup TSC_Types_Functions Functions + @{ +*/ + +/**@} end of group TSC_Types_Functions */ + +#ifdef __cplusplus +} +#endif + +#endif /* __TSC_TYPES_H */ + +/**@} end of group TSC_Types_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc.c b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc.c new file mode 100644 index 0000000000..ffb11fbc77 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc.c @@ -0,0 +1,88 @@ +/*! + * @file tsc.c + * + * @brief This file contains the Touch Driver main functions. + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "tsc.h" + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_Driver TSC Driver + @{ +*/ + +/** @defgroup TSC_Macros Macros + @{ +*/ + +/**@} end of group TSC_Macros */ + +/** @defgroup TSC_Enumerations Enumerations + @{ +*/ + +/**@} end of group TSC_Enumerations */ + +/** @defgroup TSC_Variables Variables + @{ +*/ + +/* Global variables used by main() and TSC modules */ +TSC_Globals_T TSC_Globals; + +/**@} end of group TSC_Variables */ + +/** @defgroup TSC_Functions Functions + @{ +*/ + +/*! + * @brief Config the TSC GPIO interface + * + * @param block: Array holding all the blocks + * + * @retval pointer to a TSC_STATUS_T structure + */ +TSC_STATUS_T TSC_Config(CONST TSC_Block_T* block) +{ + TSC_STATUS_T retval; + + /* Read blocks array */ + TSC_Globals.Block_Array = block; + + retval = TSC_Time_Config(); + + if (retval == TSC_STATUS_OK) + { + retval = TSC_Acq_Config(); + } + + return retval; +} + +/**@} end of group TSC_Functions */ +/**@} end of group TSC_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_acq.c b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_acq.c new file mode 100644 index 0000000000..df66a47f85 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_acq.c @@ -0,0 +1,1483 @@ +/*! + * @file tsc_acq.c + * + * @brief This file contains all functions to manage the acquisition in general. + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "tsc.h" +#include "tsc_acq.h" +#include "apm32f0xx_int.h" + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_Acquisition_Driver TSC Acquisition Driver + @{ +*/ + +/** @defgroup TSC_Acquisition_Macros Macros + @{ +*/ + +/**@} end of group TSC_Acquisition_Macros */ + +/** @defgroup TSC_Acquisition_Enumerations Enumerations + @{ +*/ + +/**@} end of group TSC_Acquisition_Enumerations */ + +/** @defgroup TSC_Acquisition_Structures Structures + @{ +*/ + +/**@} end of group TSC_Acquisition_Structures */ + +/** @defgroup TSC_Acquisition_Variables Variables + @{ +*/ + +uint32_t DelayDischarge; + +/**@} end of group TSC_Acquisition_Variables */ + +/** @defgroup TSC_Acquisition_Functions Functions + @{ +*/ + +void SoftDelay(uint32_t val); + +/*! + * @brief Output Open-Drain for Sampling Capacitor in GPIOA + * + * @param None + * + * @retval pin value + */ +uint32_t TSC_Acq_GPIOA_SAMPCAP(void) +{ + uint32_t pin = 0; +#if TOUCH_TSC_GROUP1_IO1 == SAMPCAP + pin |= GPIO_PIN_0; +#endif +#if TOUCH_TSC_GROUP1_IO2 == SAMPCAP + pin |= GPIO_PIN_1; +#endif +#if TOUCH_TSC_GROUP1_IO3 == SAMPCAP + pin |= GPIO_PIN_2; +#endif +#if TOUCH_TSC_GROUP1_IO4 == SAMPCAP + pin |= GPIO_PIN_3; +#endif +#if TOUCH_TSC_GROUP2_IO1 == SAMPCAP + pin |= GPIO_PIN_4; +#endif +#if TOUCH_TSC_GROUP2_IO2 == SAMPCAP + pin |= GPIO_PIN_5; +#endif +#if TOUCH_TSC_GROUP2_IO3 == SAMPCAP + pin |= GPIO_PIN_6; +#endif +#if TOUCH_TSC_GROUP2_IO4 == SAMPCAP + pin |= GPIO_PIN_7; +#endif +#if TOUCH_TSC_GROUP4_IO1 == SAMPCAP + pin |= GPIO_PIN_9; +#endif +#if TOUCH_TSC_GROUP4_IO2 == SAMPCAP + pin |= GPIO_PIN_10; +#endif +#if TOUCH_TSC_GROUP4_IO3 == SAMPCAP + pin |= GPIO_PIN_11; +#endif +#if TOUCH_TSC_GROUP4_IO4 == SAMPCAP + pin |= GPIO_PIN_12; +#endif + return pin; +} + +/*! + * @brief Output Open-Drain for Sampling Capacitor in GPIOB + * + * @param None + * + * @retval pin value + */ +uint32_t TSC_Acq_GPIOB_SAMPCAP(void) +{ + uint32_t pin = 0; +#if TOUCH_TSC_GROUP3_IO2 == SAMPCAP + pin |= GPIO_PIN_0; +#endif +#if TOUCH_TSC_GROUP3_IO3 == SAMPCAP + pin |= GPIO_PIN_1; +#endif +#if TOUCH_TSC_GROUP3_IO4 == SAMPCAP + pin |= GPIO_PIN_2; +#endif +#if TOUCH_TSC_GROUP5_IO1 == SAMPCAP + pin |= GPIO_PIN_3; +#endif +#if TOUCH_TSC_GROUP5_IO2 == SAMPCAP + pin |= GPIO_PIN_4; +#endif +#if TOUCH_TSC_GROUP5_IO3 == SAMPCAP + pin |= GPIO_PIN_6; +#endif +#if TOUCH_TSC_GROUP5_IO4 == SAMPCAP + pin |= GPIO_PIN_7; +#endif +#if TOUCH_TSC_GROUP6_IO1 == SAMPCAP + pin |= GPIO_PIN_11; +#endif +#if TOUCH_TSC_GROUP6_IO2 == SAMPCAP + pin |= GPIO_PIN_12; +#endif +#if TOUCH_TSC_GROUP6_IO3 == SAMPCAP + pin |= GPIO_PIN_13; +#endif +#if TOUCH_TSC_GROUP6_IO4 == SAMPCAP + pin |= GPIO_PIN_14; +#endif + return pin; +} + +/*! + * @brief Output Open-Drain for Sampling Capacitor in GPIOC + * + * @param None + * + * @retval pin value + */ +uint32_t TSC_Acq_GPIOC_SAMPCAP(void) +{ + uint32_t pin = 0; +#if TOUCH_TSC_GROUP3_IO1 == SAMPCAP + pin |= GPIO_PIN_5; +#endif + return pin; +} + +/*! + * @brief Output Open-Drain for Sampling Capacitor in GPIOD + * + * @param None + * + * @retval pin value + */ +#if (TSC_GROUP8_ENABLED > 0) +uint32_t TSC_Acq_GPIOD_SAMPCAP(void) +{ + uint32_t pin = 0; +#if TOUCH_TSC_GROUP8_IO1 == SAMPCAP + pin |= GPIO_PIN_12; +#endif +#if TOUCH_TSC_GROUP8_IO2 == SAMPCAP + pin |= GPIO_PIN_13; +#endif +#if TOUCH_TSC_GROUP8_IO3 == SAMPCAP + pin |= GPIO_PIN_14; +#endif +#if TOUCH_TSC_GROUP8_IO4 == SAMPCAP + pin |= GPIO_PIN_15; +#endif + return pin; +} +#endif + +/*! + * @brief Output Open-Drain for Sampling Capacitor in GPIOE + * + * @param None + * + * @retval pin value + */ +#if (TSC_GROUP7_ENABLED > 0) +uint32_t TSC_Acq_GPIOE_SAMPCAP(void) +{ + pin = 0; +#if TOUCH_TSC_GROUP7_IO1 == SAMPCAP + pin |= GPIO_PIN_2; +#endif +#if TOUCH_TSC_GROUP7_IO2 == SAMPCAP + pin |= GPIO_PIN_3; +#endif +#if TOUCH_TSC_GROUP7_IO3 == SAMPCAP + pin |= GPIO_PIN_4; +#endif +#if TOUCH_TSC_GROUP7_IO4 == SAMPCAP + pin |= GPIO_PIN_5; +#endif + return pin; +} +#endif + +/*! + * @brief Output Push-Pull for Channel and Shield GPIOA + * + * @param None + * + * @retval pin value + */ +uint32_t TSC_Acq_GPIOA_CHANNEL_SHIELD(void) +{ + uint32_t pin = 0; +#if (TOUCH_TSC_GROUP1_IO1 == CHANNEL) || (TOUCH_TSC_GROUP1_IO1 == SHIELD) + pin |= GPIO_PIN_0; +#endif +#if (TOUCH_TSC_GROUP1_IO2 == CHANNEL) || (TOUCH_TSC_GROUP1_IO2 == SHIELD) + pin |= GPIO_PIN_1; +#endif +#if (TOUCH_TSC_GROUP1_IO3 == CHANNEL) || (TOUCH_TSC_GROUP1_IO3 == SHIELD) + pin |= GPIO_PIN_2; +#endif +#if (TOUCH_TSC_GROUP1_IO4 == CHANNEL) || (TOUCH_TSC_GROUP1_IO4 == SHIELD) + pin |= GPIO_PIN_3; +#endif +#if (TOUCH_TSC_GROUP2_IO1 == CHANNEL) || (TOUCH_TSC_GROUP2_IO1 == SHIELD) + pin |= GPIO_PIN_4; +#endif +#if (TOUCH_TSC_GROUP2_IO2 == CHANNEL) || (TOUCH_TSC_GROUP2_IO2 == SHIELD) + pin |= GPIO_PIN_5; +#endif +#if (TOUCH_TSC_GROUP2_IO3 == CHANNEL) || (TOUCH_TSC_GROUP2_IO3 == SHIELD) + pin |= GPIO_PIN_6; +#endif +#if (TOUCH_TSC_GROUP2_IO4 == CHANNEL) || (TOUCH_TSC_GROUP2_IO4 == SHIELD) + pin |= GPIO_PIN_7; +#endif +#if (TOUCH_TSC_GROUP4_IO1 == CHANNEL) || (TOUCH_TSC_GROUP4_IO1 == SHIELD) + pin |= GPIO_PIN_9; +#endif +#if (TOUCH_TSC_GROUP4_IO2 == CHANNEL) || (TOUCH_TSC_GROUP4_IO2 == SHIELD) + pin |= GPIO_PIN_10; +#endif +#if (TOUCH_TSC_GROUP4_IO3 == CHANNEL) || (TOUCH_TSC_GROUP4_IO3 == SHIELD) + pin |= GPIO_PIN_11; +#endif +#if (TOUCH_TSC_GROUP4_IO4 == CHANNEL) || (TOUCH_TSC_GROUP4_IO4 == SHIELD) + pin |= GPIO_PIN_12; +#endif + return pin; +} + +/*! + * @brief Output Push-Pull for Channel and Shield GPIOB + * + * @param None + * + * @retval pin value + */ +uint32_t TSC_Acq_GPIOB_CHANNEL_SHIELD(void) +{ + uint32_t pin = 0; +#if (TOUCH_TSC_GROUP3_IO2 == CHANNEL) || (TOUCH_TSC_GROUP3_IO2 == SHIELD) + pin |= GPIO_PIN_0; +#endif +#if (TOUCH_TSC_GROUP3_IO3 == CHANNEL) || (TOUCH_TSC_GROUP3_IO3 == SHIELD) + pin |= GPIO_PIN_1; +#endif +#if (TOUCH_TSC_GROUP3_IO4 == CHANNEL) || (TOUCH_TSC_GROUP3_IO4 == SHIELD) + pin |= GPIO_PIN_2; +#endif +#if (TOUCH_TSC_GROUP5_IO1 == CHANNEL) || (TOUCH_TSC_GROUP5_IO1 == SHIELD) + pin |= GPIO_PIN_3; +#endif +#if (TOUCH_TSC_GROUP5_IO2 == CHANNEL) || (TOUCH_TSC_GROUP5_IO2 == SHIELD) + pin |= GPIO_PIN_4; +#endif +#if (TOUCH_TSC_GROUP5_IO3 == CHANNEL) || (TOUCH_TSC_GROUP5_IO3 == SHIELD) + pin |= GPIO_PIN_6; +#endif +#if (TOUCH_TSC_GROUP5_IO4 == CHANNEL) || (TOUCH_TSC_GROUP5_IO4 == SHIELD) + pin |= GPIO_PIN_7; +#endif +#if (TOUCH_TSC_GROUP6_IO1 == CHANNEL) || (TOUCH_TSC_GROUP6_IO1 == SHIELD) + pin |= GPIO_PIN_11; +#endif +#if (TOUCH_TSC_GROUP6_IO2 == CHANNEL) || (TOUCH_TSC_GROUP6_IO2 == SHIELD) + pin |= GPIO_PIN_12; +#endif +#if (TOUCH_TSC_GROUP6_IO3 == CHANNEL) || (TOUCH_TSC_GROUP6_IO3 == SHIELD) + pin |= GPIO_PIN_13; +#endif +#if (TOUCH_TSC_GROUP6_IO4 == CHANNEL) || (TOUCH_TSC_GROUP6_IO4 == SHIELD) + pin |= GPIO_PIN_14; +#endif + return pin; +} + +/*! + * @brief Output Push-Pull for Channel and Shield GPIOC + * + * @param None + * + * @retval pin value + */ +uint32_t TSC_Acq_GPIOC_CHANNEL_SHIELD(void) +{ + uint32_t pin = 0; +#if (TOUCH_TSC_GROUP3_IO1 == CHANNEL) || (TOUCH_TSC_GROUP3_IO1 == SHIELD) + pin |= GPIO_PIN_5; +#endif + return pin; +} + +/*! + * @brief Output Push-Pull for Channel and Shield GPIOD + * + * @param None + * + * @retval pin value + */ +#if (TSC_GROUP8_ENABLED > 0) +uint32_t TSC_Acq_GPIOD_CHANNEL_SHIELD(void) +{ + uint32_t pin = 0; +#if (TOUCH_TSC_GROUP8_IO1 == CHANNEL) || (TOUCH_TSC_GROUP8_IO1 == SHIELD) + pin |= GPIO_PIN_12; +#endif +#if (TOUCH_TSC_GROUP8_IO2 == CHANNEL) || (TOUCH_TSC_GROUP8_IO2 == SHIELD) + pin |= GPIO_PIN_13; +#endif +#if (TOUCH_TSC_GROUP8_IO3 == CHANNEL) || (TOUCH_TSC_GROUP8_IO3 == SHIELD) + pin |= GPIO_PIN_14; +#endif +#if (TOUCH_TSC_GROUP8_IO4 == CHANNEL) || (TOUCH_TSC_GROUP8_IO4 == SHIELD) + pin |= GPIO_PIN_15; +#endif + return pin; +} +#endif + +/*! + * @brief Output Push-Pull for Channel and Shield GPIOE + * + * @param None + * + * @retval pin value + */ +#if (TSC_GROUP7_ENABLED > 0) +uint32_t TSC_Acq_GPIOE_CHANNEL_SHIELD(void) +{ + uint32_t pin = 0; +#if (TOUCH_TSC_GROUP7_IO1 == CHANNEL) || (TOUCH_TSC_GROUP7_IO1 == SHIELD) + pin |= GPIO_PIN_2; +#endif +#if (TOUCH_TSC_GROUP7_IO2 == CHANNEL) || (TOUCH_TSC_GROUP7_IO2 == SHIELD) + pin |= GPIO_PIN_3; +#endif +#if (TOUCH_TSC_GROUP7_IO3 == CHANNEL) || (TOUCH_TSC_GROUP7_IO3 == SHIELD) + pin |= GPIO_PIN_4; +#endif +#if (TOUCH_TSC_GROUP7_IO4 == CHANNEL) || (TOUCH_TSC_GROUP7_IO4 == SHIELD) + pin |= GPIO_PIN_5; +#endif + return pin; +#endif + + /*! + * @brief Alternate-Function AF3 for GPIOA in ALFL register + * + * @param None + * + * @retval ALFL value + */ + uint32_t TSC_Acq_GPIOA_AF3_L(void) + { + uint32_t val_ALFL = 0; +#if TOUCH_TSC_GROUP1_IO1 != NU + val_ALFL |= (uint32_t)((uint32_t)3 << (0 * 4)); +#endif +#if TOUCH_TSC_GROUP1_IO2 != NU + val_ALFL |= (uint32_t)((uint32_t)3 << (1 * 4)); +#endif +#if TOUCH_TSC_GROUP1_IO3 != NU + val_ALFL |= (uint32_t)((uint32_t)3 << (2 * 4)); +#endif +#if TOUCH_TSC_GROUP1_IO4 != NU + val_ALFL |= (uint32_t)((uint32_t)3 << (3 * 4)); +#endif +#if TOUCH_TSC_GROUP2_IO1 != NU + val_ALFL |= (uint32_t)((uint32_t)3 << (4 * 4)); +#endif +#if TOUCH_TSC_GROUP2_IO2 != NU + val_ALFL |= (uint32_t)((uint32_t)3 << (5 * 4)); +#endif +#if TOUCH_TSC_GROUP2_IO3 != NU + val_ALFL |= (uint32_t)((uint32_t)3 << (6 * 4)); +#endif +#if TOUCH_TSC_GROUP2_IO4 != NU + val_ALFL |= (uint32_t)((uint32_t)3 << (7 * 4)); +#endif + return val_ALFL; + } + + /*! + * @brief Alternate-Function AF3 for GPIOA in ALFH register + * + * @param None + * + * @retval ALFH value + */ + uint32_t TSC_Acq_GPIOA_AF3_H(void) + { + uint32_t val_ALFH = 0; +#if TOUCH_TSC_GROUP4_IO1 != NU + val_ALFH |= (uint32_t)((uint32_t)3 << (1 * 4)); +#endif +#if TOUCH_TSC_GROUP4_IO2 != NU + val_ALFH |= (uint32_t)((uint32_t)3 << (2 * 4)); +#endif +#if TOUCH_TSC_GROUP4_IO3 != NU + val_ALFH |= (uint32_t)((uint32_t)3 << (3 * 4)); +#endif +#if TOUCH_TSC_GROUP4_IO4 != NU + val_ALFH |= (uint32_t)((uint32_t)3 << (4 * 4)); +#endif + return val_ALFH; + } + + /*! + * @brief Alternate-Function AF3 for GPIOB in ALFL register + * + * @param None + * + * @retval ALFL value + */ + uint32_t TSC_Acq_GPIOB_AF3_L(void) + { + uint32_t val_ALFL = 0; +#if TOUCH_TSC_GROUP3_IO2 != NU + val_ALFL |= (uint32_t)((uint32_t)3 << (0 * 4)); +#endif +#if TOUCH_TSC_GROUP3_IO3 != NU + val_ALFL |= (uint32_t)((uint32_t)3 << (1 * 4)); +#endif +#if TOUCH_TSC_GROUP3_IO4 != NU + val_ALFL |= (uint32_t)((uint32_t)3 << (2 * 4)); +#endif +#if TOUCH_TSC_GROUP5_IO1 != NU + val_ALFL |= (uint32_t)((uint32_t)3 << (3 * 4)); +#endif +#if TOUCH_TSC_GROUP5_IO2 != NU + val_ALFL |= (uint32_t)((uint32_t)3 << (4 * 4)); +#endif +#if TOUCH_TSC_GROUP5_IO3 != NU + val_ALFL |= (uint32_t)((uint32_t)3 << (6 * 4)); +#endif +#if TOUCH_TSC_GROUP5_IO4 != NU + val_ALFL |= (uint32_t)((uint32_t)3 << (7 * 4)); +#endif + return val_ALFL; + } + + /*! + * @brief Alternate-Function AF3 for GPIOB in ALFH register + * + * @param None + * + * @retval ALFH value + */ + uint32_t TSC_Acq_GPIOB_AF3_H(void) + { + uint32_t val_ALFH = 0; +#if TOUCH_TSC_GROUP6_IO1 != NU + val_ALFH |= (uint32_t)((uint32_t)3 << (3 * 4)); +#endif +#if TOUCH_TSC_GROUP6_IO2 != NU + val_ALFH |= (uint32_t)((uint32_t)3 << (4 * 4)); +#endif +#if TOUCH_TSC_GROUP6_IO3 != NU + val_ALFH |= (uint32_t)((uint32_t)3 << (5 * 4)); +#endif +#if TOUCH_TSC_GROUP6_IO4 != NU + val_ALFH |= (uint32_t)((uint32_t)3 << (6 * 4)); +#endif + return val_ALFH; + } + + /*! + * @brief Alternate-Function AF1 for GPIOD in ALFH register + * + * @param None + * + * @retval ALFH value + */ +#if (TSC_GROUP8_ENABLED > 0) + uint32_t TSC_Acq_GPIOD_AF1_H(void) + { + uint32_t val_ALFH = 0; +#if TOUCH_TSC_GROUP8_IO1 != NU + val_ALFH |= (uint32_t)((uint32_t)1 << (4 * 4)); +#endif +#if TOUCH_TSC_GROUP8_IO2 != NU + val_ALFH |= (uint32_t)((uint32_t)1 << (5 * 4)); +#endif +#if TOUCH_TSC_GROUP8_IO3 != NU + val_ALFH |= (uint32_t)((uint32_t)1 << (6 * 4)); +#endif +#if TOUCH_TSC_GROUP8_IO4 != NU + val_ALFH |= (uint32_t)((uint32_t)1 << (7 * 4)); +#endif + return val_ALFH; + } +#endif + + /*! + * @brief Alternate-Function AF1 for GPIOE in ALFL register + * + * @param None + * + * @retval ALFL value + */ +#if (TSC_GROUP7_ENABLED > 0) + uint32_t TSC_Acq_GPIOE_AF1_L(void) + { + uint32_t val_ALFL = 0; +#if TOUCH_TSC_GROUP7_IO1 != NU + val_ALFL |= (uint32_t)((uint32_t)1 << (2 * 4)); +#endif +#if TOUCH_TSC_GROUP7_IO2 != NU + val_ALFL |= (uint32_t)((uint32_t)1 << (3 * 4)); +#endif +#if TOUCH_TSC_GROUP7_IO3 != NU + val_ALFL |= (uint32_t)((uint32_t)1 << (4 * 4)); +#endif +#if TOUCH_TSC_GROUP7_IO4 != NU + val_ALFL |= (uint32_t)((uint32_t)1 << (5 * 4)); +#endif + return val_ALFL; + } +#endif + + /*! + * @brief Disable Schmitt trigger hysteresis GPIO in IOHCTRL register + * + * @param None + * + * @retval IOHCTRL value + */ + uint32_t TSC_Acq_Schmitt_Trigger_Hysteresis(void) + { + uint32_t val_IOHCTRL = 0xFFFFFFFF; +#if TOUCH_TSC_GROUP1_IO1 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 0); +#endif +#if TOUCH_TSC_GROUP1_IO2 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 1); +#endif +#if TOUCH_TSC_GROUP1_IO3 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 2); +#endif +#if TOUCH_TSC_GROUP1_IO4 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 3); +#endif +#if TOUCH_TSC_GROUP2_IO1 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 4); +#endif +#if TOUCH_TSC_GROUP2_IO2 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 5); +#endif +#if TOUCH_TSC_GROUP2_IO3 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 6); +#endif +#if TOUCH_TSC_GROUP2_IO4 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 7); +#endif +#if TOUCH_TSC_GROUP3_IO1 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 8); +#endif +#if TOUCH_TSC_GROUP3_IO2 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 9); +#endif +#if TOUCH_TSC_GROUP3_IO3 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 10); +#endif +#if TOUCH_TSC_GROUP3_IO4 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 11); +#endif +#if TOUCH_TSC_GROUP4_IO1 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 12); +#endif +#if TOUCH_TSC_GROUP4_IO2 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 13); +#endif +#if TOUCH_TSC_GROUP4_IO3 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 14); +#endif +#if TOUCH_TSC_GROUP4_IO4 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 15); +#endif +#if TOUCH_TSC_GROUP5_IO1 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 16); +#endif +#if TOUCH_TSC_GROUP5_IO2 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 17); +#endif +#if TOUCH_TSC_GROUP5_IO3 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 18); +#endif +#if TOUCH_TSC_GROUP5_IO4 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 19); +#endif +#if TOUCH_TSC_GROUP6_IO1 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 20); +#endif +#if TOUCH_TSC_GROUP6_IO2 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 21); +#endif +#if TOUCH_TSC_GROUP6_IO3 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 22); +#endif +#if TOUCH_TSC_GROUP6_IO4 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 23); +#endif +#if (TSC_GROUP7_ENABLED > 0) +#if TOUCH_TSC_GROUP7_IO1 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 24); +#endif +#if TOUCH_TSC_GROUP7_IO2 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 25); +#endif +#if TOUCH_TSC_GROUP7_IO3 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 26); +#endif +#if TOUCH_TSC_GROUP7_IO4 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 27); +#endif +#endif /*!< TSC_GROUP7_ENABLED */ +#if (TSC_GROUP8_ENABLED > 0) +#if TOUCH_TSC_GROUP8_IO1 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 28); +#endif +#if TOUCH_TSC_GROUP8_IO2 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 29); +#endif +#if TOUCH_TSC_GROUP8_IO3 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 30); +#endif +#if TOUCH_TSC_GROUP8_IO4 != NU + val_IOHCTRL &= (uint32_t)~((uint32_t)1 << 31); +#endif +#endif /*!< TSC_GROUP8_ENABLED */ + return val_IOHCTRL; + } + + /*! + * @brief Sampling Capacitor GPIO in IOSMPCTRL register + * + * @param None + * + * @retval IOSMPCTRL value + */ + uint32_t TSC_Acq_Sampling_Capacitor(void) + { + uint32_t val_IOSMPCTRL = 0; +#if TOUCH_TSC_GROUP1_IO1 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 0); +#endif +#if TOUCH_TSC_GROUP1_IO2 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 1); +#endif +#if TOUCH_TSC_GROUP1_IO3 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 2); +#endif +#if TOUCH_TSC_GROUP1_IO4 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 3); +#endif +#if TOUCH_TSC_GROUP2_IO1 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 4); +#endif +#if TOUCH_TSC_GROUP2_IO2 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 5); +#endif +#if TOUCH_TSC_GROUP2_IO3 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 6); +#endif +#if TOUCH_TSC_GROUP2_IO4 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 7); +#endif +#if TOUCH_TSC_GROUP3_IO1 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 8); +#endif +#if TOUCH_TSC_GROUP3_IO2 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 9); +#endif +#if TOUCH_TSC_GROUP3_IO3 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 10); +#endif +#if TOUCH_TSC_GROUP3_IO4 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 11); +#endif +#if TOUCH_TSC_GROUP4_IO1 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 12); +#endif +#if TOUCH_TSC_GROUP4_IO2 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 13); +#endif +#if TOUCH_TSC_GROUP4_IO3 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 14); +#endif +#if TOUCH_TSC_GROUP4_IO4 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 15); +#endif +#if TOUCH_TSC_GROUP5_IO1 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 16); +#endif +#if TOUCH_TSC_GROUP5_IO2 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 17); +#endif +#if TOUCH_TSC_GROUP5_IO3 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 18); +#endif +#if TOUCH_TSC_GROUP5_IO4 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 19); +#endif +#if TOUCH_TSC_GROUP6_IO1 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 20); +#endif +#if TOUCH_TSC_GROUP6_IO2 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 21); +#endif +#if TOUCH_TSC_GROUP6_IO3 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 22); +#endif +#if TOUCH_TSC_GROUP6_IO4 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 23); +#endif +#if (TSC_GROUP7_ENABLED > 0) +#if TOUCH_TSC_GROUP7_IO1 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 24); +#endif +#if TOUCH_TSC_GROUP7_IO2 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 25); +#endif +#if TOUCH_TSC_GROUP7_IO3 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 26); +#endif +#if TOUCH_TSC_GROUP7_IO4 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 27); +#endif +#endif /*!< TSC_GROUP7_ENABLED */ +#if (TSC_GROUP8_ENABLED > 0) +#if TOUCH_TSC_GROUP8_IO1 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 28); +#endif +#if TOUCH_TSC_GROUP8_IO2 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 29); +#endif +#if TOUCH_TSC_GROUP8_IO3 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 30); +#endif +#if TOUCH_TSC_GROUP8_IO4 == SAMPCAP + val_IOSMPCTRL |= (uint32_t)((uint32_t)1 << 31); +#endif +#endif /*!< TSC_GROUP8_ENABLED */ + return val_IOSMPCTRL; + } + + /*! + * @brief Config the Touch Sensing GPIO + * + * @param None + * + * @retval None + * + * @note NU: Not Used IO + * CHANNEL: Channel IO + * SHIELD: Channel IO but not acquired + * SAMPCAP: Sampling Capacitor IO + */ + void TSC_Acq_ConfigGPIO(void) + { + GPIO_Config_T gpioConfig; + + RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA | RCM_AHB_PERIPH_GPIOB | RCM_AHB_PERIPH_GPIOC); +#if (TSC_GROUP7_ENABLED > 0) || (TSC_GROUP8_ENABLED > 0) + RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOD | RCM_AHB_PERIPH_GPIOE); +#endif + + /* Alternate function Output Open-Drain for Sampling Capacitor IOs */ + gpioConfig.mode = GPIO_MODE_AF; + gpioConfig.outtype = GPIO_OUT_TYPE_OD; + gpioConfig.speed = GPIO_SPEED_2MHz; + gpioConfig.pupd = GPIO_PUPD_NO; + + /* GPIOA */ + gpioConfig.pin = TSC_Acq_GPIOA_SAMPCAP(); + GPIO_Config(GPIOA, &gpioConfig); + + /* GPIOB */ + gpioConfig.pin = TSC_Acq_GPIOB_SAMPCAP(); + GPIO_Config(GPIOB, &gpioConfig); + + /* GPIOC */ + gpioConfig.pin = TSC_Acq_GPIOC_SAMPCAP(); + GPIO_Config(GPIOC, &gpioConfig); + + /* GPIOD */ +#if (TSC_GROUP8_ENABLED > 0) + gpioConfig.pin = TSC_Acq_GPIOD_SAMPCAP(); + GPIO_Config(GPIOD, &gpioConfig); +#endif + + /* GPIOE */ +#if (TSC_GROUP7_ENABLED > 0) + gpioConfig.pin = TSC_Acq_GPIOE_SAMPCAP(); + GPIO_Config(GPIOE, &gpioConfig); +#endif + + /* Alternate function Output Push-Pull for Channel and Shield IOs */ + gpioConfig.outtype = GPIO_OUT_TYPE_PP; + + /* GPIOA */ + gpioConfig.pin = TSC_Acq_GPIOA_CHANNEL_SHIELD(); + GPIO_Config(GPIOA, &gpioConfig); + + /* GPIOB */ + gpioConfig.pin = TSC_Acq_GPIOB_CHANNEL_SHIELD(); + GPIO_Config(GPIOB, &gpioConfig); + + /* GPIOC */ + gpioConfig.pin = TSC_Acq_GPIOC_CHANNEL_SHIELD(); + GPIO_Config(GPIOC, &gpioConfig); + + /* GPIOD */ +#if (TSC_GROUP8_ENABLED > 0) + gpioConfig.pin = TSC_Acq_GPIOD_CHANNEL_SHIELD(); + GPIO_Config(GPIOD, &gpioConfig); +#endif + + /* GPIOE */ +#if (TSC_GROUP7_ENABLED > 0) + gpioConfig.pin = TSC_Acq_GPIOE_CHANNEL_SHIELD(); + GPIO_Config(GPIOE, &gpioConfig); +#endif + + /* Config Alternate-Function AF3 for GPIOA and GPIOB */ + /* GPIOA */ + GPIOA->ALFL |= TSC_Acq_GPIOA_AF3_L(); + GPIOA->ALFH |= TSC_Acq_GPIOA_AF3_H(); + + /* GPIOB */ + GPIOB->ALFL |= TSC_Acq_GPIOB_AF3_L(); + GPIOB->ALFH |= TSC_Acq_GPIOB_AF3_H(); + + /* Config Alternate-Function AF1 for GPIOD and GPIOE */ + /* GPIOD */ +#if (TSC_GROUP8_ENABLED > 0) + GPIOD->ALFH |= TSC_Acq_GPIOD_AF1_H(); +#endif + + /* GPIOE */ +#if (TSC_GROUP7_ENABLED > 0) + GPIOE->ALFL |= TSC_Acq_GPIOE_AF1_L(); +#endif + + RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_TSC); + + /* Disable Schmitt trigger hysteresis on all used TSC IOs */ + TSC->IOHCTRL &= TSC_Acq_Schmitt_Trigger_Hysteresis(); + + /* Config Sampling Capacitor IOs */ + TSC->IOSMPCTRL |= TSC_Acq_Sampling_Capacitor(); + } + + /*! + * @brief Configurate the acquisition module + * + * @param None + * + * @retval pointer to a TSC_STATUS_T structure + */ + TSC_STATUS_T TSC_Acq_Config(void) + { +#if TOUCH_TSC_GPIO_CONFIG > 0 + TSC_Acq_ConfigGPIO(); +#endif + + RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_TSC); + + /* TSC enabled */ + TSC->CTRL = 0x01; + + /* Config CTPHSEL */ +#if TOUCH_TSC_CTPHSEL > 0 + TSC->CTRL |= (uint32_t)((uint32_t)TOUCH_TSC_CTPHSEL << 28) & 0xF0000000; +#endif + + /* Config CTPLSEL */ +#if TOUCH_TSC_CTPLSEL > 0 + TSC->CTRL |= (uint32_t)((uint32_t)TOUCH_TSC_CTPLSEL << 24) & 0x0F000000; +#endif + + /* Config Spread Spectrum */ +#if TOUCH_TSC_USE_SSEN > 0 + TSC->CTRL |= (uint32_t)((uint32_t)TOUCH_TSC_USE_SSEN << 16) & 0x00010000; + TSC->CTRL |= (uint32_t)((uint32_t)TOUCH_TSC_SSERRVSEL << 17) & 0x00FE0000; + TSC->CTRL |= (uint32_t)((uint32_t)TOUCH_TSC_SSCDFSEL << 15) & 0x00008000; +#endif + + /* Config Prescaler */ +#if TOUCH_TSC_PGCDFSEL > 0 + TSC->CTRL |= (uint32_t)((uint32_t)TOUCH_TSC_PGCDFSEL << 12) & 0x00007000; +#endif + + /* Config Max Count */ +#if TOUCH_TSC_MCNTVSEL > 0 + TSC->CTRL |= (uint32_t)((uint32_t)TOUCH_TSC_MCNTVSEL << 5) & 0x000000E0; +#endif + + /* Config IO default in Output PP Low to discharge all capacitors */ + TSC->CTRL &= (uint32_t)(~(1 << 4)); + + /* Config Synchronization Mode */ +#if TOUCH_TSC_AMCFG > 0 + /* Config Synchronization Pin in Alternate-Function mode */ + RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOB); + +#if TOUCH_TSC_SYNC_PIN == 0 /*!< PB8 */ + GPIOB->MODE &= 0xFFFCFFFF; + GPIOB->MODE |= 0x00020000; + GPIOB->ALFH |= 0x00000003; +#else /*!< PB10 */ + GPIOB->MODE &= 0xFFCFFFFF; + GPIOB->MODE |= 0x00200000; + GPIOB->ALFH |= 0x00000300; +#endif + + /* Config Synchronization Polarity */ + TSC->CTRL |= (uint32_t)((uint32_t)TOUCH_TSC_SYNC_POL << 3) & 0x00000008; + + /* Config acquisition mode */ + TSC->CTRL |= (uint32_t)((uint32_t)TOUCH_TSC_AMCFG << 2) & 0x00000004; +#endif + +#if TOUCH_USE_ACQ_INTERRUPT > 0 + /* Config both EOAIEN and MCEIEN interrupts */ + TSC->INTEN |= 0x03; + /* Configure NVIC */ + NVIC_EnableIRQRequest(TSC_IRQn, 0) +#endif + + /* Configure the delay that will be used to discharge the capacitors */ + DelayDischarge = (uint32_t)((TOUCH_DELAY_DISCHARGE_ALL * (uint32_t)(SystemCoreClock / 1000000)) / 48); + return TSC_STATUS_OK; + } + + /*! + * @brief Configures a Block + * + * @param idxBlock: Index of the Block + * + * @retval pointer to a TSC_STATUS_T structure + */ + TSC_STATUS_T TSC_Acq_ConfigBlock(TSC_tIndex_T idxBlock) + { + uint32_t idxChannel; + uint32_t objStatus; + uint32_t Gx, IOy; + CONST TSC_Block_T* block = &(TSC_Globals.Block_Array[idxBlock]); + CONST TSC_Channel_Src_T* pchSrc = block->p_chSrc; + CONST TSC_Channel_Dest_T* pchDest = block->p_chDest; + + /* Mark the current block processed */ + TSC_Globals.For_Block = idxBlock; + /* Enable the Gx_IOy used as channels (channels + shield) */ + TSC->IOCHCTRL = block->msk_IOCHCTRL_channels; + /* Enable acquisition on selected Groups */ + TSC->IOGCSTS = block->msk_IOGCSTS_groups; + + for (idxChannel = 0; idxChannel < block->NumChannel; idxChannel++) + { + /* Read Object status flag */ + objStatus = block->p_chData[pchDest->IdxDest].Flag.ObjStatus; + + if (objStatus != TSC_OBJ_STATUS_ON) + { + /* Read the Channel Group mask */ + Gx = pchSrc->msk_IOGCSTS_group; + /* Stop acquisition of the Group */ + TSC->IOGCSTS &= (uint32_t)~Gx; + + if (objStatus == TSC_OBJ_STATUS_OFF) + { + /* Read the Channel IO mask */ + IOy = pchSrc->msk_IOCHCTRL_channel; + /* Stop Burst of the Channel */ + TSC->IOCHCTRL &= (uint32_t)~IOy; + } + } + /* Next channel */ + pchSrc++; + pchDest++; + } + return TSC_STATUS_OK; + } + + /*! + * @brief Start acquisition on a previously configured block + * + * @param None + * + * @retval None + */ + void TSC_Acq_StartPerConfigBlock(void) + { + /* Clear both EOAIC and MCEIC flag */ + TSC->INTFCLR |= 0x03; + + /* Wait capacitors discharge */ + SoftDelay(DelayDischarge); + +#if TOUCH_TSC_IODEF > 0 + /* Config IO default in Input Floating */ + TSC->CTRL |= (1 << 4); +#endif + + /* Start acquisition */ + TSC->CTRL |= 0x02; + } + + /*! + * @brief Wait end of acquisition + * + * @param None + * + * @retval None + */ + TSC_STATUS_T TSC_Acq_WaitBlockEOA(void) + { + TSC_STATUS_T retval = TSC_STATUS_BUSY; + + /* Check EOAFLG flag */ + if (TSC->INTSTS & 0x01) + { +#if TOUCH_TSC_IODEF > 0 + /* Config IO default in Output PP Low to discharge all capacitors */ + TSC->CTRL &= (uint32_t)(~(1 << 4)); +#endif + + /* Check MCEFLG flag */ + if (TSC->INTSTS & 0x02) + { + retval = TSC_STATUS_ERROR; + } + else + { + retval = TSC_STATUS_OK; + } + } + return retval; + } + + /*! + * @brief Return the current measure + * + * @param index: Index of the measure source + * + * @retval Measure + */ + TSC_tMeas_T TSC_Acq_ReadMeasurVal(TSC_tIndex_T index) + { + return ((TSC_tMeas_T)(TSC->IOGxCNT[index].IOGCNT)); + } + + /*! + * @brief Compute the Delta value + * + * @param refVal: Reference value + * + * @param measVal: Measurement value + * + * @retval Delta value + */ + TSC_tDelta_T TSC_Acq_ComputeDelta(TSC_tRefer_T refVal, TSC_tMeas_T measVal) + { + return ((TSC_tDelta_T)(refVal - measVal)); + } + + /*! + * @brief Compute the Measurement value + * + * @param refVal: Reference value + * + * @param deltaVal: delta Delta value + * + * @retval Measurement value + */ + TSC_tMeas_T TSC_Acq_ComputeMeas(TSC_tRefer_T refVal, TSC_tDelta_T deltaVal) + { + return ((TSC_tMeas_T)(refVal - deltaVal)); + } + + /*! + * @brief Check noise (not used) + * + * @param None + * + * @retval pointer to a TSC_STATUS_T structure + */ + TSC_ACQ_STATUS_T TSC_Acq_CheckNoise(void) + { + return TSC_ACQ_STATUS_OK; + } + + /*! + * @brief Check if a filter must be used on the current channel (not used) + * + * @param pCh: Pointer on the channel data information + * + * @retval Result TRUE if a filter can be applied + */ + TSC_BOOL_T TSC_Acq_UseFilter(TSC_Channel_Data_T * pCh) + { + return TSC_TRUE; + } + + /*! + * @brief Test if the Reference is incorrect (not used) + * + * @param pCh: Pointer on the channel data information + * + * @retval Result TRUE if the Reference is out of range + */ + TSC_BOOL_T TSC_Acq_TestReferenceRange(TSC_Channel_Data_T * pCh) + { + return TSC_FALSE; + } + + /*! + * @brief Test if the measure has crossed the reference target (not used) + * + * @param pCh: Pointer on the channel data information + * + * @param newMeas: Measure of the last acquisition on this channel + * + * @retval Result TRUE if the Reference is valid + */ + TSC_BOOL_T TSC_Acq_TestFirstReference(TSC_Channel_Data_T * pCh, TSC_tMeas_T newMeas) + { + return TSC_TRUE; + } + + /*! + * @brief Software delay (private routine) + * + * @param val: Wait delay + * + * @retval None + * + * @note Measurements done with HCLK=48MHz and Keil/MDK-ARM compiler + * val = 500: ~ 53 + * val = 1000: ~106 + * val = 2000: ~210 + */ + void SoftDelay(uint32_t val) + { + uint32_t i; + for (i = val; i > 0; i--) + {} + } + + /*! + * @brief Read all channels measurement of a Block, calculate delta + * + * @param idxBlock: Index of the Block to access + * + * @param mfilter: Pointer to the measure filter + * + * @param dfilter: Pointer to the delta filter + * + * @retval Status + */ + TSC_STATUS_T TSC_Acq_ReadBlockResult(TSC_tIndex_T idxBlock, TSC_pMeasFilter_T mfilter, TSC_pDeltaFilter_T dfilter) + { + TSC_STATUS_T retval = TSC_STATUS_OK; + TSC_tIndex_T idxChannel; + TSC_tIndexDest_T idxDest; + TSC_tMeas_T oldMeas, newMeas; + TSC_tDelta_T newDelta; + CONST TSC_Block_T* block = &(TSC_Globals.Block_Array[idxBlock]); + CONST TSC_Channel_Dest_T* pchDest = block->p_chDest; + CONST TSC_Channel_Src_T* pchSrc = block->p_chSrc; + + /* For all channels in the block copy the measure + calculate delta and store them */ + for (idxChannel = 0; idxChannel < block->NumChannel; idxChannel++) + { + idxDest = pchDest->IdxDest; + + if (block->p_chData[idxDest].Flag.ObjStatus == TSC_OBJ_STATUS_ON) + { + block->p_chData[idxDest].Flag.DataReady = TSC_DATA_READY; + newMeas = TSC_Acq_ReadMeasurVal(pchSrc->IdxSrc); + +#if TOUCH_USE_MEAS > 0 + oldMeas = block->p_chData[idxDest].Meas; +#else + oldMeas = newMeas; +#endif + +#if TOUCH_USE_MEAS > 0 + block->p_chData[idxDest].Meas = newMeas; +#endif + + /* Check acquisition value min/max */ + if (newMeas > TSC_Params.AcqMax) + { + block->p_chData[idxDest].Flag.AcqStatus = TSC_ACQ_STATUS_ERROR_MAX; + block->p_chData[idxDest].Delta = 0; + retval = TSC_STATUS_ERROR; + } + else + { + if (newMeas < TSC_Params.AcqMin) + { + block->p_chData[idxDest].Flag.AcqStatus = TSC_ACQ_STATUS_ERROR_MIN; + block->p_chData[idxDest].Delta = 0; + retval = TSC_STATUS_ERROR; + } + else /*!< The measure is OK */ + { + if (TSC_Acq_UseFilter(&block->p_chData[idxDest]) == 0) + { + block->p_chData[idxDest].Delta = TSC_Acq_ComputeDelta(block->p_chData[idxDest].Refer, newMeas); + block->p_chData[idxDest].Flag.AcqStatus = TSC_Acq_CheckNoise(); + } + else + { + /* Measure filter*/ + if (mfilter) + { + newMeas = mfilter(oldMeas, newMeas); + /* Store the measure */ +#if TOUCH_USE_MEAS > 0 + block->p_chData[idxDest].Meas = newMeas; +#endif + } + + newDelta = TSC_Acq_ComputeDelta(block->p_chData[idxDest].Refer, newMeas); + block->p_chData[idxDest].Flag.AcqStatus = TSC_Acq_CheckNoise(); + + /* Delta filter */ + if (dfilter == 0) + { + block->p_chData[idxDest].Delta = newDelta; + } + else + { + block->p_chData[idxDest].Delta = dfilter(newDelta); + } + } + } + } + } + pchDest++; + pchSrc++; + } + return retval; + } + + /*! + * @brief Calibrate a Block + * + * @param idxBlock: Index of the Block + * + * @retval Status + */ + TSC_STATUS_T TSC_Acq_CalibrateBlock(TSC_tIndex_T idxBlock) + { + TSC_STATUS_T retval; + TSC_STATUS_T acqStatus; + TSC_tIndex_T idxChannel; + TSC_tIndexDest_T idxDest; + TSC_tMeas_T newMeas; + static TSC_tIndex_T goCalibration = 0; + static TSC_tNum_T doneCalibration = 0; + static TSC_tNum_T CalibDiv; + CONST TSC_Block_T* block; + CONST TSC_Channel_Dest_T* pchDest; + CONST TSC_Channel_Src_T* pchSrc; + + block = &(TSC_Globals.Block_Array[idxBlock]); + + if (goCalibration)/*!< Calibration is on-going */ + { + acqStatus = TSC_Acq_WaitBlockEOA(); + + switch (acqStatus) + { + case TSC_STATUS_OK: + pchDest = block->p_chDest; + pchSrc = block->p_chSrc; + + for (idxChannel = 0; idxChannel < block->NumChannel; idxChannel++) + { + idxDest = pchDest->IdxDest; + newMeas = TSC_Acq_ReadMeasurVal(pchSrc->IdxSrc); + + if ((newMeas < TSC_Params.AcqMin) || (newMeas > TSC_Params.AcqMax)) + { + TSC_acq_ClearBlockData(idxBlock); + goCalibration = 0; + return TSC_STATUS_ERROR; + } + else + { + block->p_chData[idxDest].Refer += newMeas; + } + pchDest++; + pchSrc++; + } + + doneCalibration--; + if (doneCalibration) + { + TSC_Acq_StartPerConfigBlock(); + retval = TSC_STATUS_BUSY; + } + else + { + pchDest = block->p_chDest; + + for (idxChannel = 0; idxChannel < block->NumChannel; idxChannel++) + { + idxDest = pchDest->IdxDest; + /* Divide the Reference by the number of samples */ + block->p_chData[idxDest].Refer >>= CalibDiv; + pchDest++; + } + goCalibration = 0; + retval = TSC_STATUS_OK; + } + break; + case TSC_STATUS_ERROR: + TSC_acq_ClearBlockData(idxBlock); + goCalibration = 0; + retval = TSC_STATUS_ERROR; + break; + default: + retval = TSC_STATUS_BUSY; + break; + } + } + else /*!< Calibration is done */ + { + if (TSC_Params.NumCalibSample == 4) + { + CalibDiv = 2; + } + else if (TSC_Params.NumCalibSample == 16) + { + CalibDiv = 4; + } + else + { + TSC_Params.NumCalibSample = 8; + CalibDiv = 3; + } + + TSC_acq_ClearBlockData(idxBlock); + + if (TSC_Acq_ConfigBlock(idxBlock)) + { + TSC_acq_ClearBlockData(idxBlock); + goCalibration = 0; + retval = TSC_STATUS_ERROR; + } + else + { + TSC_Acq_StartPerConfigBlock(); + goCalibration = 1; + doneCalibration = TSC_Params.NumCalibSample; + retval = TSC_STATUS_BUSY; + } + } + return retval; + } + + /*! + * @brief Clear Reference and delta on all channels of a Block + * + * @param idxBlock: Index of the Block + * + * @retval None + */ + void TSC_acq_ClearBlockData(TSC_tIndex_T idxBlock) + { + TSC_tIndex_T idxChannel; + TSC_tIndexDest_T idx_Dest; + CONST TSC_Block_T* block = &(TSC_Globals.Block_Array[idxBlock]); + CONST TSC_Channel_Dest_T* pchDest = block->p_chDest; + + for (idxChannel = 0; idxChannel < block->NumChannel; idxChannel++) + { + idx_Dest = pchDest->IdxDest; + block->p_chData[idx_Dest].Refer = 0; + block->p_chData[idx_Dest].Delta = 0; + pchDest++; + } + } + +#if TOUCH_USE_ZONE > 0 + + /*! + * @brief Configures a Zone + * + * @param zone: Zone to configure + * + * @param idxBlock: Index of the Block to access + * + * @retval Status + */ + TSC_STATUS_T TSC_Acq_ConfigZone(CONST TSC_Zone_T * zone, TSC_tIndex_T idxBlock) + { + TSC_STATUS_T retval; + TSC_Globals.For_Zone = zone; + + do + { + retval = TSC_Acq_ConfigBlock(zone->indexBlock[idxBlock]); + TSC_Globals.For_Block = zone->indexBlock[idxBlock]; + idxBlock++; + } + while ((idxBlock < zone->numBlock) && (retval == TSC_STATUS_ERROR)); + + TSC_Globals.Index_For_Zone = idxBlock; + +#if TOUCH_PXS_LOW_POWER_MODE > 0 + if (idxBlock < zone->numBlock) + { + resetPXSLowPower(); + } +#endif + + return (retval); + } +#endif + + /**@} end of group TSC_Acquisition_Functions */ + /**@} end of group TSC_Acquisition_Driver */ + /**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_dxs.c b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_dxs.c new file mode 100644 index 0000000000..0668f59ddc --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_dxs.c @@ -0,0 +1,202 @@ +/*! + * @file tsc_dxs.c + * + * @brief This file contains all functions to manage the + * Detection Exclusion System (Dxs) algorithm + + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "tsc.h" +#include "tsc_dxs.h" + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_DXS_Driver TSC DXS Driver + @{ +*/ + +/** @defgroup TSC_DXS_Macros Macros + @{ +*/ + +/**@} end of group TSC_DXS_Macros */ + +/** @defgroup TSC_DXS_Enumerations Enumerations + @{ +*/ + +/**@} end of group TSC_DXS_Enumerations */ + +/** @defgroup TSC_DXS_Structures Structures + @{ +*/ + +/**@} end of group TSC_DXS_Structures */ + +/** @defgroup TSC_DXS_Variables Variables + @{ +*/ + +/**@} end of group TSC_DXS_Variables */ + +/** @defgroup TSC_DXS_Functions Functions + @{ +*/ + +/*! + * @brief Detection Exclusion System on the first object in detect state + * + * @param objgrp: Pointer to the objects group to process + * + * @retval None + */ +void TSC_Dxs_FirstObj(CONST TSC_ObjectGroup_T* objgrp) +{ +#if TOUCH_USE_DXS > 0 + + TSC_tIndex_T idxObj; + TSC_tIndex_T objLock = 0; + CONST TSC_Object_T* pObj; + CONST TSC_Object_T* pObjadd = 0; + + /* Exit if no object are in DETECT state */ + if ((objgrp->StateMask & TSC_STATE_DETECT_BIT_MASK) == 0) + { + return; + } + + pObj = objgrp->p_Obj; + + /* Process all objects */ + for (idxObj = 0; idxObj < objgrp->NbObjects; idxObj++) + { + TSC_Obj_ConfigGlobalObj(pObj); + + switch (FOR_OBJ_TYPE) + { +#if TOUCH_TOTAL_KEYS > 0 + case TSC_OBJ_TOUCHKEY: + case TSC_OBJ_TOUCHKEYB: + if (FOR_KEY_STATEID == TSC_STATEID_DETECT) + { + if (FOR_KEY_DXSLOCK == TSC_FALSE) + { + FOR_KEY_STATEID = TSC_STATEID_TOUCH; + FOR_KEY_CHANGE = TSC_STATE_CHANGED; + if ((!pObjadd) && (!objLock)) + { + pObjadd = pObj; + } + } + else + { + if (objLock) + { + FOR_KEY_STATEID = TSC_STATEID_TOUCH; + FOR_KEY_CHANGE = TSC_STATE_CHANGED; + } + else + { + objLock = 1; + pObjadd = 0; + } + } + } + break; +#endif + +#if TOUCH_TOTAL_LNRTS > 0 + case TSC_OBJ_LINEAR: + case TSC_OBJ_LINEARB: + case TSC_OBJ_ROTARY: + case TSC_OBJ_ROTARYB: + if (FOR_LINROT_STATEID == TSC_STATEID_DETECT) + { + if (FOR_LINROT_DXSLOCK == TSC_FALSE) + { + FOR_LINROT_STATEID = TSC_STATEID_TOUCH; + FOR_LINROT_CHANGE = TSC_STATE_CHANGED; + if ((!pObjadd) && (!objLock)) + { + pObjadd = pObj; + } + } + else + { + if (objLock) + { + FOR_LINROT_STATEID = TSC_STATEID_TOUCH; + FOR_LINROT_CHANGE = TSC_STATE_CHANGED; + } + else + { + objLock = 1; + pObjadd = 0; + } + } + } + break; +#endif + default: + break; + } + pObj++; + } + + /* Change state from TOUCH to DETECT + DxsLock flag on the candidate object only */ + if (pObjadd) + { + TSC_Obj_ConfigGlobalObj(pObjadd); + + switch (FOR_OBJ_TYPE) + { +#if TOUCH_TOTAL_KEYS > 0 + case TSC_OBJ_TOUCHKEY: + case TSC_OBJ_TOUCHKEYB: + FOR_KEY_STATEID = TSC_STATEID_DETECT; + FOR_KEY_CHANGE = TSC_STATE_CHANGED; + FOR_KEY_DXSLOCK = TSC_TRUE; + break; +#endif + +#if TOUCH_TOTAL_LNRTS > 0 + case TSC_OBJ_LINEAR: + case TSC_OBJ_LINEARB: + case TSC_OBJ_ROTARY: + case TSC_OBJ_ROTARYB: + FOR_LINROT_STATEID = TSC_STATEID_DETECT; + FOR_LINROT_CHANGE = TSC_STATE_CHANGED; + FOR_LINROT_DXSLOCK = TSC_TRUE; + break; +#endif + default: + break; + } + } +#endif /*!< TOUCH_USE_DXS > 0 */ +} + +/**@} end of group TSC_DXS_Functions */ +/**@} end of group TSC_DXS_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_ecs.c b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_ecs.c new file mode 100644 index 0000000000..9927bb8b32 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_ecs.c @@ -0,0 +1,329 @@ +/*! + * @file tsc_ecs.c + * + * @brief This file contains all functions to manage the ECS + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "tsc.h" +#include "tsc_ecs.h" + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_ECS_Driver TSC ECS Driver + @{ +*/ + +/** @defgroup TSC_ECS_Macros Macros + @{ +*/ + +/**@} end of group TSC_ECS_Macros */ + +/** @defgroup TSC_ECS_Enumerations Enumerations + @{ +*/ + +/**@} end of group TSC_ECS_Enumerations */ + +/** @defgroup TSC_ECS_Structures Structures + @{ +*/ + +/**@} end of group TSC_ECS_Structures */ + +/** @defgroup TSC_ECS_Variables Variables + @{ +*/ + +/**@} end of group TSC_ECS_Variables */ + +/** @defgroup TSC_ECS_Functions Functions + @{ +*/ + +/*! + * @brief Calculate the K coefficient + * + * @param kDiffer: K coefficient when objects have different delta variation + * + * @param kSame: K coefficient when objects have the same delta variation + * + * @retval K coefficient (differ or same) + */ +TSC_tKCoeff_T TSC_Ecs_CalculateK(TSC_ObjectGroup_T* objgrp, TSC_tKCoeff_T kDiffer, TSC_tKCoeff_T kSame) +{ + TSC_tIndex_T idxObj; + TSC_tIndex_T idxChannel; + TSC_tDelta_T value = 0; + TSC_tDelta_T Cmd = 1; + TSC_tDelta_T Dir = 0; + TSC_tNum_T numChannel = 0; + TSC_tKCoeff_T retval = kDiffer; + TSC_Channel_Data_T* p_Ch = 0; + CONST TSC_Object_T* pObj; + + pObj = objgrp->p_Obj; + + /* Process all objects */ + for (idxObj = 0; idxObj < objgrp->NbObjects; idxObj++) + { + TSC_Obj_ConfigGlobalObj(pObj); + + switch (FOR_OBJ_TYPE) + { +#if TOUCH_TOTAL_KEYS > 0 + case TSC_OBJ_TOUCHKEY: + case TSC_OBJ_TOUCHKEYB: + if (FOR_KEY_STATEID != TSC_STATEID_RELEASE) + { + pObj++; + continue; + } + numChannel = 1; + p_Ch = TSC_Globals.For_Key->p_ChD; + break; +#endif + +#if TOUCH_TOTAL_LNRTS > 0 + case TSC_OBJ_LINEAR: + case TSC_OBJ_LINEARB: + case TSC_OBJ_ROTARY: + case TSC_OBJ_ROTARYB: + if (FOR_LINROT_STATEID != TSC_STATEID_RELEASE) + { + pObj++; + continue; + } + numChannel = FOR_LINROT_NB_CHANNELS; + p_Ch = TSC_Globals.For_LinRot->p_ChD; + break; +#endif + default: + break; + } + + /* Check all channels of current object */ + for (idxChannel = 0; idxChannel < numChannel; idxChannel++) + { + value = p_Ch->Delta; + + if (value) + { + if (value >= 0) + { + if (Dir > 0) + { + Dir = 1; + } + else + { + Cmd = 0; + } + } + else + { + if (Dir < 0) + { + Dir = -1; + } + else + { + Cmd = 0; + } + } + } + else + { + Cmd = 0; + } + p_Ch++; + } + pObj++; + } + + if (Cmd) + { + retval = kSame; + } + return retval; +} + +/*! + * @brief Calculate the new Reference on a group of objects + * + * @param objgrp: Pointer to the objects group to process + * + * @param kCoeff: K coefficient to apply + * + * @retval None + */ +void TSC_Ecs_ProcessK(TSC_ObjectGroup_T* objgrp, TSC_tKCoeff_T kCoeff) +{ + TSC_tIndex_T idxObj; + TSC_tIndex_T idxChannel; + CONST TSC_Object_T* pObj; + TSC_tKCoeff_T kCoeffComp; + uint32_t meas, refer; + TSC_tNum_T numChannel = 0; + TSC_Channel_Data_T* p_Ch = 0; + void(*pFunc_SetStateCalibration)(TSC_tCounter_T delay) = 0; + + pObj = objgrp->p_Obj; + + /* Calculate the K coefficient complement */ + kCoeffComp = (0xFF ^ kCoeff) + 1; + + /* Process all objects */ + for (idxObj = 0; idxObj < objgrp->NbObjects; idxObj++) + { + TSC_Obj_ConfigGlobalObj(pObj); + + switch (FOR_OBJ_TYPE) + { +#if TOUCH_TOTAL_KEYS > 0 + case TSC_OBJ_TOUCHKEY: + case TSC_OBJ_TOUCHKEYB: + if (FOR_KEY_STATEID != TSC_STATEID_RELEASE) + { + pObj++; + continue; + } + numChannel = 1; + p_Ch = TSC_Globals.For_Key->p_ChD; + pFunc_SetStateCalibration = &TSC_TouchKey_ConfigCalibrationState; + break; +#endif + +#if TOUCH_TOTAL_LNRTS > 0 + case TSC_OBJ_LINEAR: + case TSC_OBJ_LINEARB: + case TSC_OBJ_ROTARY: + case TSC_OBJ_ROTARYB: + if (FOR_LINROT_STATEID != TSC_STATEID_RELEASE) + { + pObj++; + continue; + } + numChannel = FOR_LINROT_NB_CHANNELS; + p_Ch = TSC_Globals.For_LinRot->p_ChD; + pFunc_SetStateCalibration = &TSC_Linrot_ConfigCalibrationState; + break; +#endif + default: + break; + } + + /* Calculate the new reference + rest for all channels */ + for (idxChannel = 0; idxChannel < numChannel; idxChannel++) + { + meas = TSC_Acq_ComputeMeas(p_Ch->Refer, p_Ch->Delta); + meas <<= 8; + + refer = (uint32_t)(p_Ch->Refer); + refer <<= 8; + refer += p_Ch->RefRest; + refer *= kCoeffComp; + refer += (kCoeff * meas); + + p_Ch->RefRest = (TSC_tRefRest_T)((refer >> 8) & 0xFF); + p_Ch->Refer = (TSC_tRefer_T)(refer >> 16); + + /* Go in Calibration state in the Reference is out of Range */ + if (TSC_Acq_TestReferenceRange(p_Ch) == TSC_TRUE) + { + pFunc_SetStateCalibration(0); + } + p_Ch++; + } + pObj++; + } +} + +/*! + * @brief ECS algorithm on a group of objects + * The ECS is only performed if at least an object is in Release state and + * if no objects are in active states (Prox, Detect or Touch) + * An optional delay is added after the ECS condition (all sensors in Release state) is reached. + * + * @param objgrp: Pointer to the objects group to process + * + * @retval Status + */ +TSC_STATUS_T TSC_Ecs_Process(TSC_ObjectGroup_T* objgrp) +{ + TSC_tKCoeff_T myKcoeff; + TSC_STATUS_T retval; + + if ((objgrp->StateMask & TSC_STATE_RELEASE_BIT_MASK) && !(objgrp->StateMask & TSC_STATEMASK_ACTIVE)) + { +#if TOUCH_ECS_DELAY > 0 + if (!objgrp->wait) + { + disableInterrupts(); + objgrp->time = TSC_Globals.Tick_ms; + enableInterrupts(); + objgrp->wait = 1; + objgrp->execution = 0; + } +#else + objgrp->execution = 1; +#endif + } + else + { +#if TOUCH_ECS_DELAY > 0 + objgrp->wait = 0; +#endif + objgrp->execution = 0; + } + +#if TOUCH_ECS_DELAY > 0 + if (objgrp->wait && (!objgrp->execution)) + { + if (TSC_Time_Delay_ms(TOUCH_ECS_DELAY, &objgrp->time) == TSC_STATUS_OK) + { + objgrp->execution = 1; + } + } +#endif + + if (objgrp->execution == 0) + { + retval = TSC_STATUS_BUSY; + } + else + { + /* Calculate the K coefficient */ + myKcoeff = TSC_Ecs_CalculateK(objgrp, TOUCH_ECS_K_DIFFER, TOUCH_ECS_K_SAME); + /* Process the objects */ + TSC_Ecs_ProcessK(objgrp, myKcoeff); + retval = TSC_STATUS_OK; + } + return retval; +} + +/**@} end of group TSC_ECS_Functions */ +/**@} end of group TSC_ECS_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_filter.c b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_filter.c new file mode 100644 index 0000000000..1bfa0bc371 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_filter.c @@ -0,0 +1,109 @@ +/*! + * @file tsc_filter.c + * + * @brief This file contains all functions to manage the signal or delta filters. + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "tsc_filter.h" + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_Filter_Driver TSC Filter Driver + @{ +*/ + +/** @defgroup TSC_Filter_Macros Macros + @{ +*/ + +/**@} end of group TSC_Filter_Macros */ + +/** @defgroup TSC_Filter_Enumerations Enumerations + @{ +*/ + +/**@} end of group TSC_Filter_Enumerations */ + +/** @defgroup TSC_Filter_Structures Structures + @{ +*/ + +/**@} end of group TSC_Filter_Structures */ + +/** @defgroup TSC_Filter_Variables Variables + @{ +*/ + +/**@} end of group TSC_Filter_Variables */ + +/** @defgroup TSC_Filter_Functions Functions + @{ +*/ + +/*! + * @brief Example of measure value filter + * + * @param preMeasn: Previous measure value + * + * @param curMeasn: Current measure value + * + * @retval Filtered measure + */ +TSC_tMeas_T TSC_Filt_MeasFilter(TSC_tMeas_T preMeasn, TSC_tMeas_T curMeasn) +{ + TSC_tMeas_T value; + + value = (TSC_tMeas_T)(curMeasn << ACQ_FILTER_RANGE); + + if (preMeasn) + { + if (value <= preMeasn) + { + value = preMeasn - ((ACQ_FILTER_COEFF * (preMeasn - value)) >> 8); + } + else + { + value = preMeasn + ((ACQ_FILTER_COEFF * (value - preMeasn)) >> 8); + } + } + return (value); +} + +/*! + * @brief Example of delta value filter + * + * @param delta: Delta value to modify + * + * @retval Filtered delta + */ +TSC_tDelta_T TSC_Filt_DeltaFilter(TSC_tDelta_T delta) +{ + return (delta); +} + +/**@} end of group TSC_Filter_Functions */ +/**@} end of group TSC_Filter_Driver */ +/**@} end of group TSC_Driver_Library */ + diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_linrot.c b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_linrot.c new file mode 100644 index 0000000000..ce0ab7918f --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_linrot.c @@ -0,0 +1,2073 @@ +/*! + * @file tsc_linrot.c + * + * @brief This file contains all functions to manage Linear and Rotary sensors. + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "tsc.h" +#include "tsc_linrot.h" + +#if TOUCH_TOTAL_LNRTS > 0 + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_Linrot_Driver TSC Linrot Driver + @{ +*/ + +/** @defgroup TSC_Linrot_Macros Macros + @{ +*/ + +#define FOR_OBJ_TYPE TSC_Globals.For_Obj->Type + +#define FOR_STATEID TSC_Globals.For_LinRot->p_Data->StateId +#define FOR_RAW_POSITION TSC_Globals.For_LinRot->p_Data->RawPosition +#define FOR_POSITION TSC_Globals.For_LinRot->p_Data->Position +#define FOR_CHANGE TSC_Globals.For_LinRot->p_Data->Change +#define FOR_POSCHANGE TSC_Globals.For_LinRot->p_Data->PosChange +#define FOR_COUNTER_DEB TSC_Globals.For_LinRot->p_Data->CounterDebounce +#define FOR_COUNTER_DIR TSC_Globals.For_LinRot->p_Data->CounterDirection +#define FOR_COUNTER_DTO TSC_Globals.For_LinRot->p_Data->CounterDTO +#define FOR_DXSLOCK TSC_Globals.For_LinRot->p_Data->DxsLock +#define FOR_DIRECTION TSC_Globals.For_LinRot->p_Data->Direction + +#define FOR_PROXIN_TH TSC_Globals.For_LinRot->p_Param->ProxInTh +#define FOR_PROXOUT_TH TSC_Globals.For_LinRot->p_Param->ProxOutTh +#define FOR_DETECTIN_TH TSC_Globals.For_LinRot->p_Param->DetectInTh +#define FOR_DETECTOUT_TH TSC_Globals.For_LinRot->p_Param->DetectOutTh +#define FOR_CALIB_TH TSC_Globals.For_LinRot->p_Param->CalibTh + +#define FOR_RESOLUTION TSC_Globals.For_LinRot->p_Param->Resolution +#define FOR_DIR_CHG_POS TSC_Globals.For_LinRot->p_Param->DirChangePos + +#define FOR_COUNTER_DEB_CALIB TSC_Globals.For_LinRot->p_Param->CounterDebCalib +#define FOR_COUNTER_DEB_PROX TSC_Globals.For_LinRot->p_Param->CounterDebProx +#define FOR_COUNTER_DEB_DETECT TSC_Globals.For_LinRot->p_Param->CounterDebDetect +#define FOR_COUNTER_DEB_RELEASE TSC_Globals.For_LinRot->p_Param->CounterDebRelease +#define FOR_COUNTER_DEB_ERROR TSC_Globals.For_LinRot->p_Param->CounterDebError +#define FOR_COUNTER_DEB_DIRECTION TSC_Globals.For_LinRot->p_Param->CounterDebDirection + +#define FOR_NB_CHANNELS TSC_Globals.For_LinRot->NumChannel +#define FOR_SCT_COMP TSC_Globals.For_LinRot->SctComp +#define FOR_POS_CORR TSC_Globals.For_LinRot->PosCorr + +#if TOUCH_DTO > 0 + #define DTO_READ_TIME {TSC_Linrot_ReadTimeForDTO();} +#else + #define DTO_READ_TIME +#endif + +#define DIRECTION_CHANGE_MAX_DISPLACEMENT (255) +#define DIRECTION_CHANGE_TOTAL_STEPS (256) +#define RESOLUTION_CALCULATION (8) + +/**@} end of group TSC_Linrot_Macros */ + +/** @defgroup TSC_Linrot_Enumerations Enumerations + @{ +*/ + +/**@} end of group TSC_Linrot_Enumerations */ + +/** @defgroup TSC_Linrot_Structures Structures + @{ +*/ + +/**@} end of group TSC_Linrot_Structures */ + +/** @defgroup TSC_Linrot_Variables Variables + @{ +*/ + +static TSC_tNum_T CalibDiv; + +/** + * @brief 3 CHANNELS - CH1 CH2 CH3 + * LINEAR - MONO - 0/255 at extremities + */ +#if TOUCH_USE_3CH_LIN_M1 > 0 +CONST TSC_tPosition_T TSC_POSOFF_3CH_LIN_M1[3][3] = +{ + { 0, -96, 0 }, + { 32, 0, -160 }, + { 0, 96, 0 } +}; +#endif + +/** + * @brief 3 CHANNELS - CH1 CH2 CH3 + * LINEAR - MONO + */ +#if TOUCH_USE_3CH_LIN_M2 > 0 +CONST TSC_tPosition_T TSC_POSOFF_3CH_LIN_M2[3][3] = +{ + { 0, -192, 0 }, + { 64, 0, -320 }, + { 0, 192, 0 } +}; +#endif + +/** + * @brief 3 CHANNELS - CH1 CH2 CH3 CH1 + * LINEAR - HALF-ENDED + */ +#if TOUCH_USE_3CH_LIN_H > 0 +CONST TSC_tPosition_T TSC_POSOFF_3CH_LIN_H[3][3] = +{ + { 0, -96, 160 }, + { 32, 0, -160 }, + { -224, 96, 0 } +}; +#endif + +/** + * @brief 3 CHANNELS - CH1 CH2 CH3 + * ROTARY - MONO + */ +#if TOUCH_USE_3CH_ROT_M > 0 +CONST TSC_tPosition_T TSC_POSOFF_3CH_ROT_M[3][3] = +{ + { 0, -64, 107 }, + { 21, 0, -107 }, + { -149, 64, 0 } +}; +#endif + +/** + * @brief 4 CHANNELS - CH1 CH2 CH3 CH4 + * LINEAR - MONO - 0/255 at extremities + */ +#if TOUCH_USE_4CH_LIN_M1 > 0 +CONST TSC_tPosition_T TSC_POSOFF_4CH_LIN_M1[4][4] = +{ + { 0, -64, 0, 0 }, + { 21, 0, -107, 0 }, + { 0, 64, 0, -149 }, + { 0, 0, 107, 0 } +}; +#endif + +/** + * @brief 4 CHANNELS - CH1 CH2 CH3 CH4 + * LINEAR - MONO + */ +#if TOUCH_USE_4CH_LIN_M2 > 0 +CONST TSC_tPosition_T TSC_POSOFF_4CH_LIN_M2[4][4] = +{ + { 0, -96, 0, 0 }, + { 32, 0, -160, 0 }, + { 0, 96, 0, -224 }, + { 0, 0, 160, 0 } +}; +#endif + +/** + * @brief 4 CHANNELS - CH1 CH2 CH3 CH4 CH1 + * LINEAR - MONO - HALF-ENDED + */ +#if TOUCH_USE_4CH_LIN_H > 0 +CONST TSC_tPosition_T TSC_POSOFF_4CH_LIN_H[4][4] = +{ + { 0, -64, 0, 149 }, + { 21, 0, -107, 0 }, + { 0, 64, 0, -149 }, + { -192, 0, 107, 0 } +}; +#endif + +/** + * @brief 4 CHANNELS - CH1 CH2 CH3 CH4 + * ROTARY - MONO + */ +#if TOUCH_USE_4CH_ROT_M > 0 +CONST TSC_tPosition_T TSC_POSOFF_4CH_ROT_M[4][4] = +{ + { 0, -48, 0, 112 }, + { 16, 0, -80, 0 }, + { 0, 48, 0, -112 }, + { -144, 0, 80, 0 } +}; +#endif + +/** + * @brief 5 CHANNELS - CH1 CH2 CH3 CH4 CH5 + * LINEAR - MONO - 0/255 at extremities + */ +#if TOUCH_USE_5CH_LIN_M1 > 0 +CONST TSC_tPosition_T TSC_POSOFF_5CH_LIN_M1[5][5] = +{ + { 0, -48, 0, 0, 0 }, + { 16, 0, -80, 0, 0 }, + { 0, 48, 0, -112, 0 }, + { 0, 0, 80, 0, -144 }, + { 0, 0, 0, 112, 0 } +}; +#endif + +/** + * @brief 5 CHANNELS - CH1 CH2 CH3 CH4 CH5 + * LINEAR - MONO + */ +#if TOUCH_USE_5CH_LIN_M2 > 0 +CONST TSC_tPosition_T TSC_POSOFF_5CH_LIN_M2[5][5] = +{ + { 0, -64, 0, 0, 0 }, + { 21, 0, -107, 0, 0 }, + { 0, 64, 0, -149, 0 }, + { 0, 0, 107, 0, -192 }, + { 0, 0, 0, 149, 0 } +}; +#endif + +/** + * @brief 5 CHANNELS - CH1 CH2 CH3 CH4 CH5 CH1 + * LINEAR - HALF-ENDED + */ +#if TOUCH_USE_5CH_LIN_H > 0 +CONST TSC_tPosition_T TSC_POSOFF_5CH_LIN_H[5][5] = +{ + { 0, -48, 0, 0, 144 }, + { 16, 0, -80, 0, 0 }, + { 0, 48, 0, -112, 0 }, + { 0, 0, 80, 0, -144 }, + { -176, 0, 0, 112, 0 } +}; +#endif + +/** + * @brief 5 CHANNELS - CH1 CH2 CH3 CH4 CH5 + * ROTARY - MONO + */ +#if TOUCH_USE_5CH_ROT_M > 0 +CONST TSC_tPosition_T TSC_POSOFF_5CH_ROT_M[5][5] = +{ + { 0, -38, 0, 0, 115 }, + { 13, 0, -64, 0, 0 }, + { 0, 38, 0, -90, 0 }, + { 0, 0, 64, 0, -115 }, + {-141, 0, 0, 90, 0 } +}; +#endif + +/** + * @brief 5 CHANNELS - CH1 CH2 CH3 CH4 CH5 CH1 CH3 CH5 CH2 CH4 + * ROTARY - DUAL + */ +#if TOUCH_USE_5CH_ROT_D > 0 +CONST TSC_tPosition_T TSC_POSOFF_5CH_ROT_D[5][5] = +{ + { 0, -19, -83, 122, 58 }, + { 6, 0, -32, -122, 96 }, + { 70, 19, 0, -45, -96 }, + {-134, 109, 32, 0, -58 }, + { -70, -109, 83, 45, 0 } +}; +#endif + +/** + * @brief 6 CHANNELS - CH1 CH2 CH3 CH4 CH5 CH6 + * LINEAR - MONO - 0/255 at extremities + */ +#if TOUCH_USE_6CH_LIN_M1 > 0 +CONST TSC_tPosition_T TSC_POSOFF_6CH_LIN_M1[6][6] = +{ + { 0, -38, 0, 0, 0, 0 }, + { 13, 0, -64, 0, 0, 0 }, + { 0, 38, 0, -90, 0, 0 }, + { 0, 0, 64, 0, -115, 0 }, + { 0, 0, 0, 90, 0, -141 }, + { 0, 0, 0, 0, 115, 0 } +}; +#endif + +/** + * @brief 6 CHANNELS - CH1 CH2 CH3 CH4 CH5 CH6 + * LINEAR - MONO + */ +#if TOUCH_USE_6CH_LIN_M2 > 0 +CONST TSC_tPosition_T TSC_POSOFF_6CH_LIN_M2[6][6] = +{ + { 0, -48, 0, 0, 0, 0 }, + { 16, 0, -80, 0, 0, 0 }, + { 0, 48, 0, -112, 0, 0 }, + { 0, 0, 80, 0, -144, 0 }, + { 0, 0, 0, 112, 0, -176 }, + { 0, 0, 0, 0, 144, 0 } +}; +#endif + +/** + * @brief 6 CHANNELS - CH1 CH2 CH3 CH4 CH5 CH6 CH1 + * LINEAR - HALF-ENDED + */ +#if TOUCH_USE_6CH_LIN_H > 0 +CONST TSC_tPosition_T TSC_POSOFF_6CH_LIN_H[6][6] = +{ + { 0, -38, 0, 0, 0, 141 }, + { 13, 0, -64, 0, 0, 0 }, + { 0, 38, 0, -90, 0, 0 }, + { 0, 0, 64, 0, -115, 0 }, + { 0, 0, 0, 90, 0, -141 }, + {-166, 0, 0, 0, 115, 0 } +}; +#endif + +/** + * @brief 6 CHANNELS - CH1 CH2 CH3 CH4 CH5 CH6 + * ROTARY - MONO + */ +#if TOUCH_USE_6CH_ROT_M > 0 +CONST TSC_tPosition_T TSC_POSOFF_6CH_ROT_M[6][6] = +{ + { 0, -32, 0, 0, 0, 117 }, + { 11, 0, -53, 0, 0, 0 }, + { 0, 32, 0, -75, 0, 0 }, + { 0, 0, 53, 0, -96, 0 }, + { 0, 0, 0, 75, 0, -117 }, + {-139, 0, 0, 0, 96, 0 } +}; +#endif + +/**@} end of group TSC_Linrot_Variables */ + +/** @defgroup TSC_Linrot_Functions Functions + @{ +*/ + +/** @defgroup "Object_methods" Functions + @{ +*/ + +/*! + * @brief The parameters with default values from configuration file + * + * @param None + * + * @retval None + */ +void TSC_Linrot_Config(void) +{ + /* Thresholds */ +#if TOUCH_USE_PROX > 0 + FOR_PROXIN_TH = TOUCH_LINROT_PROX_IN_TH; + FOR_PROXOUT_TH = TOUCH_LINROT_PROX_OUT_TH; +#endif + FOR_DETECTIN_TH = TOUCH_LINROT_DETECT_IN_TH; + FOR_DETECTOUT_TH = TOUCH_LINROT_DETECT_OUT_TH; + FOR_CALIB_TH = TOUCH_LINROT_CALIB_TH; + + /* Debounce counters */ + FOR_COUNTER_DEB_CALIB = TOUCH_DEBOUNCE_CALIB; +#if TOUCH_USE_PROX > 0 + FOR_COUNTER_DEB_PROX = TOUCH_DEBOUNCE_PROX; +#endif + FOR_COUNTER_DEB_DETECT = TOUCH_DEBOUNCE_DETECT; + FOR_COUNTER_DEB_RELEASE = TOUCH_DEBOUNCE_RELEASE; + FOR_COUNTER_DEB_ERROR = TOUCH_DEBOUNCE_ERROR; + + /* Other parameters for linear/rotary only */ + FOR_RESOLUTION = TOUCH_LINROT_RESOLUTION; + FOR_DIR_CHG_POS = TOUCH_LINROT_DIR_CHG_POS; + FOR_COUNTER_DEB_DIRECTION = TOUCH_LINROT_DIR_CHG_DEB; + + /* Config state */ + TSC_Linrot_ConfigCalibrationState(TOUCH_CALIB_DELAY); +} + +/*! + * @brief Process the State Machine + * + * @param None + * + * @retval None + */ +void TSC_Linrot_Process(void) +{ + TSC_STATEID_T stateID; + + /* Check if at least one channel has a data ready */ + if ((TSC_Linrot_Process_OneChannel_DataReady() == TSC_STATUS_OK) || (FOR_STATEID == TSC_STATEID_OFF)) + { + stateID = FOR_STATEID; + +#if TOUCH_TOTAL_LINROTS > 0 + if ((TSC_Globals.For_Obj->Type == TSC_OBJ_LINEAR) || + (TSC_Globals.For_Obj->Type == TSC_OBJ_ROTARY)) + { + TSC_Globals.For_LinRot->p_SM[FOR_STATEID].StateFunc(); + } +#endif + +#if TOUCH_TOTAL_LINROTS_B > 0 + if ((TSC_Globals.For_Obj->Type == TSC_OBJ_LINEARB) || + (TSC_Globals.For_Obj->Type == TSC_OBJ_ROTARYB)) + { + TSC_Params.p_LinRotSta[FOR_STATEID].StateFunc(); + } +#endif + + if (FOR_STATEID != stateID) + { + FOR_CHANGE = TSC_STATE_CHANGED; + } + else + { + FOR_CHANGE = TSC_STATE_NOT_CHANGED; + } + +#if TOUCH_USE_DXS > 0 + if (FOR_STATEID != TSC_STATEID_DETECT) + { + FOR_DXSLOCK = TSC_FALSE; + } + if (FOR_STATEID == TSC_STATEID_TOUCH) + { + FOR_STATEID = TSC_STATEID_DETECT; + } +#endif + } +} + +/*! + * @brief Calculate the position + * + * @param None + * + * @retval Status Return OK if position calculation is correct + * + * @note The position is calculated only if the number of channels is greater than 2 + */ +TSC_STATUS_T TSC_Linrot_CalcPos(void) +{ + TSC_tIndex_T index; + TSC_tDelta_T normDelta; + TSC_tNum_T minor, major; + TSC_tNum_T sector = 0; + TSC_tNum_T prePosition = 0; + TSC_tPosition_T curPosition = 0; + TSC_tsignPosition_T updatePosition = 0; + static TSC_tIndex_T index1, index2; + static TSC_tDelta_T delta1, delta2, delta3; + + TSC_Channel_Data_T* p_Ch = TSC_Globals.For_LinRot->p_ChD; + + index1 = 0; + index2 = 0; + delta1 = 0; + delta2 = 0; + delta3 = 0; + + FOR_POSCHANGE = TSC_STATE_NOT_CHANGED; + + if (FOR_NB_CHANNELS < 3) + { + return TSC_STATUS_ERROR; + } + + /** + * Sort the channels' delta + * - delta1 and index1 = biggest + * - delta2 and index2 = middle + * - delta3 and index3 = lowest + */ + for (index = 0; index < FOR_NB_CHANNELS; index++) + { +#if TOUCH_LINROT_USE_NORMDELTA > 0 + normDelta = TSC_Linrot_NormDelta(p_Ch, index); +#else + normDelta = p_Ch->Delta; +#endif + + if (normDelta < 0) + { + normDelta = 0; + } + + if (normDelta <= delta1) + { + if (normDelta <= delta2) + { + if (normDelta > delta3) + { + delta3 = normDelta; + } + } + else + { + delta3 = delta2; + delta2 = normDelta; + index2 = index; + } + } + else + { + delta3 = delta2; + delta2 = delta1; + delta1 = normDelta; + index2 = index1; + index1 = index; + } + p_Ch++; + } + + if (delta2 < ((TSC_tThreshold_T)(FOR_DETECTOUT_TH >> 1) - 1)) + { + return TSC_STATUS_ERROR; + } + + /******************** Position calculation **********************/ + + /** + * B = Biggest signal measured (Delta1/Index1) + * M = Middle signal measured (Delta2/Index2) + * S = Smallest signal measured (Delta3/Index3) + * + * - The equation to find the position is: + * Position = Offset +/- [ Sector_Size x ( Major / (Major + Minor) ) ] + * + * - The Offset is the position of the middle of the Middle signal segment. + * All the Offset values are stored in the ROM table Table_POSITION_OFFSET. + * + * - Major = Biggest - Smallest signals + * Minor = Middle - Smallest signals + * + * - The Sector_Size depends of the number of channels used + */ + + /* Calculates the Major and Minor parameters */ + minor = (TSC_tNum_T)(delta2 - delta3); /*!p_PosOff + (index1 * FOR_NB_CHANNELS) + index2); + sector = FOR_SCT_COMP; + prePosition = FOR_POS_CORR; + + /* Calculates: [ Sector_Size x ( Major / (Major + Minor) ) ] */ + sector = major * sector; + sector = sector / (major + minor); + + /* Use the sign bit from position table to define the interpretation direction. + The NewPosition is multiplied by 2 because the Offset stored in the ROM + table is divided by 2... */ + if (curPosition <= 0) /*! 0 in the position table */ + { + curPosition = (TSC_tPosition_T)(curPosition << 1); + curPosition += sector; + } + + /* Position is calculated differently if LINEAR or ROTARY sensor */ + if ((FOR_OBJ_TYPE == TSC_OBJ_LINEAR) || (FOR_OBJ_TYPE == TSC_OBJ_LINEARB)) + { + /* First adjustment used to shift all the values to obtain the "zero" */ + if (curPosition <= 0) + { + curPosition = curPosition + (256 - prePosition); + } + else + { + curPosition -= prePosition; + } + /*! 255) + { + curPosition = 255; + } + if (curPosition < 0) + { + curPosition = 0; + } + } + else /*! (uint16_t)(FOR_RAW_POSITION + DIRECTION_CHANGE_MAX_DISPLACEMENT)) + { + if ((curPosition + FOR_DIR_CHG_POS) <= (uint16_t)(FOR_RAW_POSITION + DIRECTION_CHANGE_TOTAL_STEPS)) + { + FOR_COUNTER_DIR--; + if (FOR_COUNTER_DIR) + { + return TSC_STATUS_ERROR; + } + else + { + FOR_COUNTER_DIR = FOR_COUNTER_DEB_DIRECTION; + FOR_DIRECTION = TSC_TRUE; /*! FOR_RAW_POSITION) && (((TSC_tsignPosition_T)curPosition - FOR_RAW_POSITION) < DIRECTION_CHANGE_MAX_DISPLACEMENT)) + { + if (curPosition >= (uint16_t)(FOR_RAW_POSITION + FOR_DIR_CHG_POS)) + { + FOR_COUNTER_DIR--; + if (FOR_COUNTER_DIR) + { + return TSC_STATUS_ERROR; + } + else + { + FOR_COUNTER_DIR = FOR_COUNTER_DEB_DIRECTION; + FOR_DIRECTION = TSC_FALSE; /*!= (uint16_t)(FOR_RAW_POSITION + FOR_DIR_CHG_POS)) + { + FOR_COUNTER_DIR--; + if (FOR_COUNTER_DIR) + { + return TSC_STATUS_ERROR; + } + else + { + FOR_COUNTER_DIR = FOR_COUNTER_DEB_DIRECTION; + FOR_DIRECTION = TSC_FALSE; /*!> (RESOLUTION_CALCULATION - FOR_RESOLUTION)); + + if (FOR_POSITION != updatePosition) + { + FOR_POSITION = updatePosition; + FOR_POSCHANGE = TSC_STATE_CHANGED; + return TSC_STATUS_OK; + } + else + { + return TSC_STATUS_ERROR; + } +} + +/**@} "Object_methods" Functions */ + +/** @defgroup Utility Functions + @{ +*/ + +/*! + * @brief Go in Calibration state + * + * @param delay Delay before calibration starts (stabilization of noise filter) + * + * @retval None + */ +void TSC_Linrot_ConfigCalibrationState(TSC_tCounter_T delay) +{ + FOR_STATEID = TSC_STATEID_CALIB; + FOR_CHANGE = TSC_STATE_CHANGED; + TSC_Linrot_Process_AllChannel_Status(TSC_OBJ_STATUS_ON); + + if (TSC_Params.NumCalibSample == 4) + { + CalibDiv = 2; + } + else if (TSC_Params.NumCalibSample == 16) + { + CalibDiv = 4; + } + else + { + TSC_Params.NumCalibSample = 8; + CalibDiv = 3; + } + + /* If a noise filter is used, the counter must be initialized to a value + different from 0 in order to stabilize the filter */ + FOR_COUNTER_DEB = (TSC_tCounter_T)(delay + (TSC_tCounter_T)TSC_Params.NumCalibSample); + TSC_Linrot_Process_AllChannel_ClearRef(); +} + +/*! + * @brief Go in Off state with sensor "off" + * + * @param None + * + * @retval None + */ +void TSC_Linrot_ConfigOffState(void) +{ + FOR_STATEID = TSC_STATEID_OFF; + FOR_CHANGE = TSC_STATE_CHANGED; + TSC_Linrot_Process_AllChannel_Status(TSC_OBJ_STATUS_OFF); +} + +/*! + * @brief Go in Off state with sensor in "Burst mode only" + * + * @param None + * + * @retval None + */ +void TSC_Linrot_ConfigBurstOnlyState(void) +{ + FOR_STATEID = TSC_STATEID_OFF; + FOR_CHANGE = TSC_STATE_CHANGED; + TSC_Linrot_Process_AllChannel_Status(TSC_OBJ_STATUS_BURST_ONLY); +} + +/*! + * @brief Return the current state identifier + * + * @param None + * + * @retval State id + */ +TSC_STATEID_T TSC_Linrot_ReadStateId(void) +{ + return (FOR_STATEID); +} + +/*! + * @brief Return the current state mask + * + * @param None + * + * @retval State mask + */ +TSC_STATEMASK_T TSC_Linrot_ReadStateMask(void) +{ + TSC_STATEMASK_T state_mask = TSC_STATEMASK_UNKNOWN; + + switch (TSC_Globals.For_Obj->Type) + { +#if TOUCH_TOTAL_LINROTS > 0 + case TSC_OBJ_LINEAR: + case TSC_OBJ_ROTARY: + state_mask = TSC_Globals.For_LinRot->p_SM[FOR_STATEID].StateMask; + break; +#endif + +#if TOUCH_TOTAL_LINROTS_B > 0 + case TSC_OBJ_LINEARB: + case TSC_OBJ_ROTARYB: + state_mask = TSC_Params.p_LinRotSta[FOR_STATEID].StateMask; + break; +#endif + default: + break; + } + return state_mask; +} + +/*! + * @brief Return the Change flag + * + * @param None + * + * @retval Change flag status + */ +TSC_tNum_T TSC_Linrot_ReadChangeFlag(void) +{ + return (FOR_CHANGE); +} + +/**@} Utility Functions */ + +/** @defgroup State_machine Functions + @{ +*/ + +#if TOUCH_USE_PROX > 0 +/*! + * @brief Debounce Release processing (previous state = Proximity) + * + * @param None + * + * @retval None + */ +void TSC_Linrot_ProcessDebReleaseProxState(void) +{ + if (TSC_Linrot_Process_OneChannel_AcqStatusError()) + { + if (TSC_Linrot_Process_OneChannel_DeltaAbove(FOR_PROXOUT_TH, 0)) + { + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + } + else + { + FOR_STATEID = TSC_STATEID_PROX; + } + } + else + { + /* Go back to the previous state */ + FOR_STATEID = TSC_STATEID_PROX; + } +} +#endif /*! 0 */ + +/*! + * @brief Debounce Release processing (previous state = Detect) + * + * @param None + * + * @retval None + */ +void TSC_Linrot_ProcessDebReleaseDetectState(void) +{ + if (TSC_Linrot_Process_OneChannel_AcqStatusError()) + { + if (TSC_Linrot_Process_OneChannel_DeltaAbove(FOR_DETECTOUT_TH, 1)) + { +#if TOUCH_USE_PROX > 0 + if (TSC_Linrot_Process_OneChannel_DeltaAbove(FOR_PROXOUT_TH, 0) == TSC_STATUS_OK) + { + FOR_STATEID = TSC_STATEID_PROX; + return; + } +#endif + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + } + else + { + FOR_STATEID = TSC_STATEID_DETECT; + } + } + else + { + FOR_STATEID = TSC_STATEID_DETECT; + } +} + +/*! + * @brief Debounce Release processing (previous state = Touch) + * Same as Debounce Release Detect processing + * + * @param None + * + * @retval None + */ +void TSC_Linrot_ProcessDebReleaseTouchState(void) +{ + if (TSC_Linrot_Process_OneChannel_AcqStatusError()) + { + if (TSC_Linrot_Process_OneChannel_DeltaAbove(FOR_DETECTOUT_TH, 1)) + { +#if TOUCH_USE_PROX > 0 + if (TSC_Linrot_Process_OneChannel_DeltaAbove(FOR_PROXOUT_TH, 0) == TSC_STATUS_OK) + { + FOR_STATEID = TSC_STATEID_PROX; + return; + } +#endif + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + } + else + { + FOR_STATEID = TSC_STATEID_TOUCH; + } + } + else + { + FOR_STATEID = TSC_STATEID_TOUCH; + } +} + +/*! + * @brief Release state processing + * + * @param None + * + * @retval None + */ +void TSC_Linrot_ProcessReleaseState(void) +{ + if (TSC_Linrot_Process_OneChannel_AcqStatusError()) + { + if (TSC_Linrot_Process_OneChannel_DeltaAboveEqu(FOR_DETECTIN_TH, 1) == TSC_STATUS_OK) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_DETECT; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_DETECT; + } + else + { + FOR_STATEID = TSC_STATEID_DETECT; + DTO_READ_TIME; + } + return; + } + +#if TOUCH_USE_PROX > 0 + if (TSC_Linrot_Process_OneChannel_DeltaAboveEqu(FOR_PROXIN_TH, 0) == TSC_STATUS_OK) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_PROX; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_PROX; + } + else + { + FOR_STATEID = TSC_STATEID_PROX; + DTO_READ_TIME; + } + return; + } +#endif + + /* Check delta for re-calibration */ + if (TSC_Linrot_Process_OneChannel_DeltaBelowEquMinus(FOR_CALIB_TH, 1) == TSC_STATUS_OK) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_CALIB; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_CALIB; + } + else + { + TSC_Linrot_ConfigCalibrationState(0); + } + } + } + else + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_ERROR; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_ERROR_RELEASE; + } + else + { + FOR_STATEID = TSC_STATEID_ERROR; + } + } +} + +/*! + * @brief Debounce Calibration processing (previous state = Release) + * + * @param None + * + * @retval None + */ +void TSC_Linrot_ProcessDebCalibrationState(void) +{ + if (TSC_Linrot_Process_OneChannel_AcqStatusError()) + { + if (TSC_Linrot_Process_OneChannel_DeltaBelowEquMinus(FOR_CALIB_TH, 1)) + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + else + { + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + TSC_Linrot_ConfigCalibrationState(0); + } + } + } + else + { + FOR_STATEID = TSC_STATEID_RELEASE; + } +} + +/*! + * @brief Calibration state processing + * + * @param None + * + * @retval None + */ +void TSC_Linrot_ProcessCalibrationState(void) +{ + TSC_tMeas_T newMeas; + TSC_tIndex_T index; + TSC_Channel_Data_T* p_Ch; + +#if TOUCH_CALIB_DELAY > 0 + /* Noise filter stabilization time */ + if (FOR_COUNTER_DEB > (TSC_tCounter_T)TSC_Params.NumCalibSample) + { + FOR_COUNTER_DEB--; + return; + } +#endif + + if (TSC_Linrot_Process_OneChannel_AcqStatusError()) + { + /* Process all channels */ + p_Ch = TSC_Globals.For_LinRot->p_ChD; + + for (index = 0; index < FOR_NB_CHANNELS; index++) + { + /* Read the new measure or Calculate it */ +#if TOUCH_USE_MEAS > 0 + newMeas = p_Ch->Meas; +#else + newMeas = TSC_Acq_ComputeMeas(p_Ch->Refer, p_Ch->Delta); +#endif + + /* Verify the first Reference value */ + if (FOR_COUNTER_DEB != (TSC_tCounter_T)TSC_Params.NumCalibSample) + { + p_Ch->Refer += newMeas; + + if (p_Ch->Refer < newMeas) + { + p_Ch->Refer = 0; + FOR_STATEID = TSC_STATEID_ERROR; + return; + } + } + else + { + if (TSC_Acq_TestFirstReference(p_Ch, newMeas)) + { + p_Ch->Refer = newMeas; + } + else + { + p_Ch->Refer = 0; + return; + } + } + p_Ch++; + } + + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + /* Process all channels */ + p_Ch = TSC_Globals.For_LinRot->p_ChD; + + for (index = 0; index < FOR_NB_CHANNELS; index++) + { + p_Ch->Refer >>= CalibDiv; + p_Ch->RefRest = 0; + p_Ch->Delta = 0; + p_Ch++; + } + FOR_STATEID = TSC_STATEID_RELEASE; + } + } + else + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_ERROR; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_ERROR_CALIB; + } + else + { + FOR_STATEID = TSC_STATEID_ERROR; + } + } +} + +#if TOUCH_USE_PROX > 0 +/*! + * @brief Debounce Proximity processing (previous state = Release) + * + * @param None + * + * @retval None + */ +void TSC_Linrot_ProcessDebProxState(void) +{ + if (TSC_Linrot_Process_OneChannel_AcqStatusError()) + { + if (TSC_Linrot_Process_OneChannel_DeltaAboveEqu(FOR_DETECTIN_TH, 1) == TSC_STATUS_OK) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_DETECT; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_DETECT; + } + else + { + FOR_STATEID = TSC_STATEID_DETECT; + DTO_READ_TIME; + } + return; + } + + if (TSC_Linrot_Process_OneChannel_DeltaAboveEqu(FOR_PROXIN_TH, 0)) + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + else + { + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + FOR_STATEID = TSC_STATEID_PROX; + DTO_READ_TIME; + } + } + } + else + { + FOR_STATEID = TSC_STATEID_RELEASE; + } +} +#endif + + +#if TOUCH_USE_PROX > 0 +/*! + * @brief Debounce Proximity processing (previous state = Detect) + * + * @param None + * + * @retval None + */ +void TSC_Linrot_ProcessDebProxDetectState(void) +{ + if (TSC_Linrot_Process_OneChannel_AcqStatusError()) + { + if (TSC_Linrot_Process_OneChannel_DeltaAbove(FOR_DETECTOUT_TH, 1) == TSC_STATUS_OK) + { + FOR_STATEID = TSC_STATEID_DETECT; + return; + } + + if (TSC_Linrot_Process_OneChannel_DeltaAbove(FOR_PROXOUT_TH, 0)) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_RELEASE; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_RELEASE_DETECT; + } + else + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + } + else + { + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + FOR_STATEID = TSC_STATEID_PROX; + DTO_READ_TIME; + } + } + } + else + { + FOR_STATEID = TSC_STATEID_DETECT; + } +} +#endif + +#if TOUCH_USE_PROX > 0 +/*! + * @brief Debounce Proximity processing (previous state = Touch) + * + * @param None + * + * @retval None + */ +void TSC_Linrot_ProcessDebProxTouchState(void) +{ + if (TSC_Linrot_Process_OneChannel_AcqStatusError()) + { + if (TSC_Linrot_Process_OneChannel_DeltaAbove(FOR_DETECTOUT_TH, 1) == TSC_STATUS_OK) + { + FOR_STATEID = TSC_STATEID_TOUCH; + return; + } + + if (TSC_Linrot_Process_OneChannel_DeltaAbove(FOR_PROXOUT_TH, 0)) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_RELEASE; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_RELEASE_TOUCH; + } + else + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + } + else + { + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + FOR_STATEID = TSC_STATEID_PROX; + DTO_READ_TIME; + } + } + } + else + { + FOR_STATEID = TSC_STATEID_TOUCH; + } +} +#endif + +#if TOUCH_USE_PROX > 0 +/*! + * @brief roximity state processing + * + * @param None + * + * @retval None + */ +void TSC_Linrot_ProcessProxState(void) +{ +#if TOUCH_DTO > 0 + TSC_tTick_sec_T tick_detected; +#endif + + if (TSC_Linrot_Process_OneChannel_AcqStatusError()) + { + if (TSC_Linrot_Process_OneChannel_DeltaAboveEqu(FOR_DETECTIN_TH, 1) == TSC_STATUS_OK) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_DETECT; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_DETECT; + } + else + { + FOR_STATEID = TSC_STATEID_DETECT; + DTO_READ_TIME; + } + return; + } + + if (TSC_Linrot_Process_AllChannel_DeltaBelowEqu(FOR_PROXOUT_TH, 0) == TSC_STATUS_OK) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_RELEASE; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_RELEASE_PROX; + } + else + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + return; + } + + /* Stay in Proximity state */ +#if TOUCH_DTO > 0 + /* Detection Time Out (DTO) processing */ + if ((TSC_Params.DTO > 1) && (TSC_Params.DTO < 64)) + { + tick_detected = FOR_COUNTER_DTO; + /* Enter in calibration state if the DTO duration has elapsed */ + if (TSC_Time_Delay_sec(TSC_Params.DTO, &tick_detected) == TSC_STATUS_OK) + { + TSC_Linrot_ConfigCalibrationState(0); + } + } +#endif + } + else + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_ERROR; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_ERROR_PROX; + } + else + { + FOR_STATEID = TSC_STATEID_ERROR; + } + } +} +#endif + +/*! + * @brief Debounce Detect processing (previous state = Release or Proximity) + * + * @param None + * + * @retval None + */ +void TSC_Linrot_ProcessDebDetectState(void) +{ + if (TSC_Linrot_Process_OneChannel_AcqStatusError()) + { + if (TSC_Linrot_Process_OneChannel_DeltaAboveEqu(FOR_DETECTIN_TH, 1)) + { +#if TOUCH_USE_PROX > 0 + if (TSC_Linrot_Process_OneChannel_DeltaAboveEqu(FOR_PROXIN_TH, 0)) + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + else + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_PROX; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_PROX; + } + else + { + FOR_STATEID = TSC_STATEID_PROX; + DTO_READ_TIME; + } + } +#else + FOR_STATEID = TSC_STATEID_RELEASE; +#endif + } + else + { + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + FOR_STATEID = TSC_STATEID_DETECT; + DTO_READ_TIME; + } + } + } + else + { + FOR_STATEID = TSC_STATEID_RELEASE; + } +} + +/*! + * @brief Detect state processing + * + * @param None + * + * @retval None + */ +void TSC_Linrot_ProcessDetectState(void) +{ +#if TOUCH_DTO > 0 + TSC_STATUS_T pos_sts; + TSC_tTick_sec_T tick_detected; +#endif + + if (TSC_Linrot_Process_OneChannel_AcqStatusError()) + { + if (TSC_Linrot_Process_OneChannel_DeltaAbove(FOR_DETECTOUT_TH, 1) == TSC_STATUS_OK) + { + /* Calculate position */ + if ((FOR_OBJ_TYPE == TSC_OBJ_LINEAR) || (FOR_OBJ_TYPE == TSC_OBJ_ROTARY)) + { +#if TOUCH_DTO > 0 + pos_sts = TSC_Globals.For_LinRot->p_Methods->CalcPosition(); +#else + TSC_Globals.For_LinRot->p_Methods->CalcPosition(); +#endif + } + else /*! 0 + pos_sts = TSC_Params.p_LinRotMet->CalcPosition(); +#else + TSC_Params.p_LinRotMet->CalcPosition(); +#endif + } +#if TOUCH_DTO > 0 + /* Detection Time Out (DTO) processing, Only if the Position has NOT changed */ + if (pos_sts) + { + if ((TSC_Params.DTO > 1) && (TSC_Params.DTO < 64)) + { + tick_detected = FOR_COUNTER_DTO; + /* Enter in calibration state if the DTO duration has elapsed */ + if (TSC_Time_Delay_sec(TSC_Params.DTO, &tick_detected) == TSC_STATUS_OK) + { + TSC_Linrot_ConfigCalibrationState(0); + } + } + } + else + { + DTO_READ_TIME; + } +#endif + return; + } + +#if TOUCH_USE_PROX > 0 + if (TSC_Linrot_Process_OneChannel_DeltaAbove(FOR_PROXOUT_TH, 0) == TSC_STATUS_OK) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_PROX; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_PROX_DETECT; + } + else + { + FOR_STATEID = TSC_STATEID_PROX; + DTO_READ_TIME; + } + return; + } +#endif + + FOR_COUNTER_DEB = FOR_COUNTER_DEB_RELEASE; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_RELEASE_DETECT; + } + else + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + } + else + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_ERROR; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_ERROR_DETECT; + } + else + { + FOR_STATEID = TSC_STATEID_ERROR; + } + } +} + +/*! + * @brief Touch state processing, Same as Detect state + * + * @param None + * + * @retval None + */ +void TSC_Linrot_ProcessTouchState(void) +{ +#if TOUCH_DTO > 0 + TSC_STATUS_T pos_sts; + TSC_tTick_sec_T tick_detected; +#endif + + if (TSC_Linrot_Process_OneChannel_AcqStatusError()) + { + if (TSC_Linrot_Process_OneChannel_DeltaAbove(FOR_DETECTOUT_TH, 1) == TSC_STATUS_OK) + { + /* Calculate position */ + if ((FOR_OBJ_TYPE == TSC_OBJ_LINEAR) || (FOR_OBJ_TYPE == TSC_OBJ_ROTARY)) + { +#if TOUCH_DTO > 0 + pos_sts = TSC_Globals.For_LinRot->p_Methods->CalcPosition(); +#else + TSC_Globals.For_LinRot->p_Methods->CalcPosition(); +#endif + } + else /* TSC_OBJ_LINEARB or TSC_OBJ_ROTARYB */ + { +#if TOUCH_DTO > 0 + pos_sts = TSC_Params.p_LinRotMet->CalcPosition(); +#else + TSC_Params.p_LinRotMet->CalcPosition(); +#endif + } +#if TOUCH_DTO > 0 + /* Detection Time Out (DTO) processing, Only if the Position has NOT changed */ + if (pos_sts) + { + if ((TSC_Params.DTO > 1) && (TSC_Params.DTO < 64)) + { + tick_detected = FOR_COUNTER_DTO; + /* Enter in calibration state if the DTO duration has elapsed */ + if (TSC_Time_Delay_sec(TSC_Params.DTO, &tick_detected) == TSC_STATUS_OK) + { + TSC_Linrot_ConfigCalibrationState(0); + } + } + } + else + { + DTO_READ_TIME; + } +#endif + return; + } + +#if TOUCH_USE_PROX > 0 + if (TSC_Linrot_Process_OneChannel_DeltaAbove(FOR_PROXOUT_TH, 0) == TSC_STATUS_OK) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_PROX; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_PROX_TOUCH; + } + else + { + FOR_STATEID = TSC_STATEID_PROX; + DTO_READ_TIME; + } + return; + } +#endif + + FOR_COUNTER_DEB = FOR_COUNTER_DEB_RELEASE; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_RELEASE_TOUCH; + } + else + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + } + else + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_ERROR; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_ERROR_TOUCH; + } + else + { + FOR_STATEID = TSC_STATEID_ERROR; + } + } +} + +/*! + * @brief Debounce error state processing + * + * @param None + * + * @retval None + */ +void TSC_Linrot_ProcessDebErrorState(void) +{ + volatile TSC_STATEMASK_T mask; + + if (TSC_Linrot_Process_OneChannel_AcqStatusError()) + { + mask = TSC_Linrot_ReadStateMask(); + mask &= (TSC_STATEMASK_T)(~(TSC_STATE_DEBOUNCE_BIT_MASK | TSC_STATE_ERROR_BIT_MASK)); + + if (mask == TSC_STATEMASK_RELEASE) + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + else if (mask == TSC_STATEMASK_PROX) + { + FOR_STATEID = TSC_STATEID_PROX; + } + else if (mask == TSC_STATEMASK_DETECT) + { + FOR_STATEID = TSC_STATEID_DETECT; + } + else if (mask == TSC_STATEMASK_TOUCH) + { + FOR_STATEID = TSC_STATEID_TOUCH; + } + else + { + TSC_Linrot_ConfigCalibrationState(0); + } + } + else + { + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + FOR_STATEID = TSC_STATEID_ERROR; + } + } +} + +/**@} State_machine Functions */ + +/** @defgroup Private Functions + @{ +*/ + +/*! + * @brief Read the current time in second and affect it to the DTO counter (Private) + * + * @param None + * + * @retval None + */ +void TSC_Linrot_ReadTimeForDTO(void) +{ + disableInterrupts(); + FOR_COUNTER_DTO = (TSC_tCounter_T)TSC_Globals.Tick_sec; + enableInterrupts(); +} + +/*! + * @brief Set all channels status to ON, OFF or BURST only + * + * @param status: Channel status + * + * @retval None + */ +void TSC_Linrot_Process_AllChannel_Status(TSC_OBJ_STATUS_T status) +{ + TSC_tIndex_T index; + TSC_Channel_Data_T* p_Ch = TSC_Globals.For_LinRot->p_ChD; + /* Config channels status */ + for (index = 0; index < FOR_NB_CHANNELS; index++) + { + p_Ch->Flag.ObjStatus = status; + p_Ch++; + } +} + +/*! + * @brief Check if at least one channel has a data ready + * + * @param None + * + * @retval Status + */ +TSC_STATUS_T TSC_Linrot_Process_OneChannel_DataReady(void) +{ + TSC_tIndex_T index; + TSC_Channel_Data_T* p_Ch = TSC_Globals.For_LinRot->p_ChD; + TSC_STATUS_T retval = TSC_STATUS_ERROR; + /* Return OK if at least one channel has a data ready */ + for (index = 0; index < FOR_NB_CHANNELS; index++) + { + if (p_Ch->Flag.DataReady == TSC_DATA_READY) + { + p_Ch->Flag.DataReady = TSC_DATA_NOT_READY; + retval = TSC_STATUS_OK; + } + p_Ch++; + } + return retval; +} + +/*! + * @brief Check if all channels are equal to the status passed + * + * @param status: Channel status + * + * @retval Status + */ +TSC_STATUS_T TSC_Linrot_Process_AllChannel_AcqStatus(TSC_ACQ_STATUS_T status) +{ + TSC_tIndex_T index; + TSC_Channel_Data_T* p_Ch = TSC_Globals.For_LinRot->p_ChD; + /* Return OK if ALL channels have the correct acq status */ + for (index = 0; index < FOR_NB_CHANNELS; index++) + { + if (p_Ch->Flag.AcqStatus != status) + { + return TSC_STATUS_ERROR; + } + p_Ch++; + } + return TSC_STATUS_OK; +} + +/*! + * @brief Check if at least one channel is in error + * + * @param None + * + * @retval Status + */ +TSC_STATUS_T TSC_Linrot_Process_OneChannel_AcqStatusError(void) +{ + TSC_tIndex_T index; + TSC_Channel_Data_T* p_Ch = TSC_Globals.For_LinRot->p_ChD; + /* Return OK if at least one channel is in acquisition error min or max */ + for (index = 0; index < FOR_NB_CHANNELS; index++) + { + if (p_Ch->Flag.AcqStatus & TSC_ACQ_STATUS_ERROR_MASK) + { + return TSC_STATUS_OK; + } + p_Ch++; + } + return TSC_STATUS_ERROR; +} + +/*! + * @brief Check if at least one channel is below or equal a threshold (inverted) + * + * @param threshold: Threshold + * + * @param Cmd: Enable or Disable the multiplier coefficient on threshold + * + * @retval Status + */ +TSC_STATUS_T TSC_Linrot_Process_OneChannel_DeltaBelowEquMinus(TSC_tThreshold_T threshold, TSC_tIndex_T Cmd) +{ + TSC_tIndex_T index; + TSC_tDelta_T normDelta; + TSC_Channel_Data_T* p_Ch = TSC_Globals.For_LinRot->p_ChD; + +#if TOUCH_COEFF_TH > 0 + uint16_t nowThreshold; + if (Cmd != ENABLE) + { + nowThreshold = threshold; + } + else + { + nowThreshold = (uint16_t)((uint16_t)threshold << TOUCH_COEFF_TH); + } +#endif + + /* Return OK if at least one channel is below or equal the threshold */ + for (index = 0; index < FOR_NB_CHANNELS; index++) + { +#if TOUCH_LINROT_USE_NORMDELTA > 0 + normDelta = TSC_Linrot_NormDelta(p_Ch, index); +#else + normDelta = p_Ch->Delta; +#endif + +#if TOUCH_COEFF_TH > 0 + if (normDelta <= -nowThreshold) +#else + if (normDelta <= -threshold) +#endif + { + return TSC_STATUS_OK; + } + p_Ch++; + } + return TSC_STATUS_ERROR; +} + +/*! + * @brief Check if at least one channel is above or equal a threshold + * + * @param threshold: Threshold + * + * @param Cmd: Enable or Disable the multiplier coefficient on threshold + * + * @retval Status + */ +TSC_STATUS_T TSC_Linrot_Process_OneChannel_DeltaAboveEqu(TSC_tThreshold_T threshold, TSC_tIndex_T Cmd) +{ + TSC_tIndex_T index; + TSC_tDelta_T normDelta; + TSC_Channel_Data_T* p_Ch = TSC_Globals.For_LinRot->p_ChD; + +#if TOUCH_COEFF_TH > 0 + uint16_t nowThreshold; + if (Cmd != ENABLE) + { + nowThreshold = threshold; + } + else + { + nowThreshold = (uint16_t)((uint16_t)threshold << TOUCH_COEFF_TH); + } +#endif + + /* Return OK if at least one channel is above or equal the threshold */ + for (index = 0; index < FOR_NB_CHANNELS; index++) + { +#if TOUCH_LINROT_USE_NORMDELTA > 0 + normDelta = TSC_Linrot_NormDelta(p_Ch, index); +#else + normDelta = p_Ch->Delta; +#endif + +#if TOUCH_COEFF_TH > 0 + if (normDelta >= nowThreshold) +#else + if (normDelta >= threshold) +#endif + { +#if TOUCH_COEFF_TH > 0 + if (normDelta < 0) + { + p_Ch++; + continue; + } +#endif + return TSC_STATUS_OK; + } + p_Ch++; + } + return TSC_STATUS_ERROR; +} + +/*! + * @brief Check if at least one channel is stricly above a threshold + * + * @param threshold: Threshold + * + * @param Cmd: Enable or Disable the multiplier coefficient on threshold + * + * @retval Status + */ +TSC_STATUS_T TSC_Linrot_Process_OneChannel_DeltaAbove(TSC_tThreshold_T threshold, TSC_tIndex_T Cmd) +{ + TSC_tIndex_T index; + TSC_tDelta_T normDelta; + TSC_Channel_Data_T* p_Ch = TSC_Globals.For_LinRot->p_ChD; + +#if TOUCH_COEFF_TH > 0 + uint16_t nowThreshold; + if (Cmd != ENABLE) + { + nowThreshold = threshold; + } + else + { + nowThreshold = (uint16_t)((uint16_t)threshold << TOUCH_COEFF_TH); + } +#endif + + /* Return OK if at least one channel is above the threshold */ + for (index = 0; index < FOR_NB_CHANNELS; index++) + { +#if TOUCH_LINROT_USE_NORMDELTA > 0 + normDelta = TSC_Linrot_NormDelta(p_Ch, index); +#else + normDelta = p_Ch->Delta; +#endif + +#if TOUCH_COEFF_TH > 0 + if (normDelta > nowThreshold) +#else + if (normDelta > threshold) +#endif + { +#if TOUCH_COEFF_TH > 0 + if (normDelta < 0) + { + p_Ch++; + continue; + } +#endif + return TSC_STATUS_OK; + } + p_Ch++; + } + return TSC_STATUS_ERROR; +} + +/*! + * @brief Check if all channels are below or equal a threshold + * + * @param threshold: Threshold + * + * @param Cmd: Enable or Disable the multiplier coefficient on threshold + * + * @retval Status + */ +TSC_STATUS_T TSC_Linrot_Process_AllChannel_DeltaBelowEqu(TSC_tThreshold_T threshold, TSC_tIndex_T Cmd) +{ + TSC_tIndex_T index; + TSC_tDelta_T normDelta; + TSC_Channel_Data_T* p_Ch = TSC_Globals.For_LinRot->p_ChD; + +#if TOUCH_COEFF_TH > 0 + uint16_t nowThreshold; + if (Cmd != ENABLE) + { + nowThreshold = threshold; + } + else + { + nowThreshold = (uint16_t)((uint16_t)threshold << TOUCH_COEFF_TH); + } +#endif + + /* Return OK if ALL channels are below or equal the threshold */ + for (index = 0; index < FOR_NB_CHANNELS; index++) + { +#if TOUCH_LINROT_USE_NORMDELTA > 0 + normDelta = TSC_Linrot_NormDelta(p_Ch, index); +#else + normDelta = p_Ch->Delta; +#endif + +#if TOUCH_COEFF_TH > 0 + if (normDelta > nowThreshold) +#else + if (normDelta > threshold) +#endif + { +#if TOUCH_COEFF_TH > 0 + if (normDelta < 0) + { + p_Ch++; + continue; + } +#endif + return TSC_STATUS_ERROR; + } + p_Ch++; + } + return TSC_STATUS_OK; +} + +/*! + * @brief Clear the Reference and ReferenceRest for all channels + * + * @param None + * + * @retval None + */ +void TSC_Linrot_Process_AllChannel_ClearRef(void) +{ + TSC_tIndex_T index; + TSC_Channel_Data_T* p_Ch = TSC_Globals.For_LinRot->p_ChD; + for (index = 0; index < FOR_NB_CHANNELS; index++) + { + p_Ch->Refer = 0; + p_Ch->RefRest = 0; + p_Ch++; + } +} + +/*! + * @brief Normalize a Delta value + * + * @param channel: Pointer to the current channel + * + * @param index: Index of the channel + * + * @retval Normalized Delta value + */ +TSC_tDelta_T TSC_Linrot_NormDelta(TSC_Channel_Data_T* channel, TSC_tIndex_T index) +{ + uint32_t tmpdelta = channel->Delta; + + if (TSC_Globals.For_LinRot->p_DeltaCoeff[index] != 0x0100) + { + tmpdelta = (uint32_t)(tmpdelta * TSC_Globals.For_LinRot->p_DeltaCoeff[index]); + tmpdelta = tmpdelta >> (uint8_t)8; + } + return (TSC_tDelta_T)tmpdelta; +} +#endif /*!<#if TOUCH_TOTAL_LNRTS > 0 */ + +/**@} Private Functions */ + +/**@} end of group TSC_Linrot_Functions */ +/**@} end of group TSC_Linrot_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_object.c b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_object.c new file mode 100644 index 0000000000..cf91a3f455 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_object.c @@ -0,0 +1,250 @@ +/*! + * @file tsc_object.c + * + * @brief This file contains all functions to manage the sensors in general. + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "tsc.h" +#include "tsc_object.h" + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_Object_Driver TSC Driver + @{ +*/ + +/** @defgroup TSC_Object_Macros Macros + @{ +*/ + +/**@} end of group TSC_Object_Macros */ + +/** @defgroup TSC_Object_Enumerations Enumerations + @{ +*/ + +/**@} end of group TSC_Object_Enumerations */ + +/** @defgroup TSC_Object_Structures Structures + @{ +*/ + +/**@} end of group TSC_Object_Structures */ + +/** @defgroup TSC_Object_Variables Variables + @{ +*/ + +/**@} end of group TSC_Object_Variables */ + +/** @defgroup TSC_Object_Functions Functions + @{ +*/ + +/*! + * @brief Config a group of Objects + * + * @param objgrp: Pointer to the group of objects + * + * @retval None + */ +void TSC_Obj_ConfigGroup(TSC_ObjectGroup_T* objgrp) +{ + TSC_tIndex_T idxObj; + CONST TSC_Object_T* pObj; + TSC_tNum_T stateMask = 0; + + pObj = objgrp->p_Obj; + objgrp->Change = TSC_STATE_NOT_CHANGED; + + /* Process all objects */ + for (idxObj = 0; idxObj < objgrp->NbObjects; idxObj++) + { + TSC_Obj_ConfigGlobalObj(pObj); + + if (pObj->Type == TSC_OBJ_TOUCHKEY) + { +#if TOUCH_TOTAL_TOUCHKEYS > 0 + TSC_Globals.For_Key->p_Methods->Config(); + + if (TSC_Globals.For_Key->p_Data->Change) + { + objgrp->Change = TSC_STATE_CHANGED; + } + stateMask |= TSC_Globals.For_Key->p_SM[TSC_Globals.For_Key->p_Data->StateId].StateMask; +#endif + } + else if (pObj->Type == TSC_OBJ_TOUCHKEYB) + { +#if TOUCH_TOTAL_TOUCHKEYS_B > 0 + TSC_Params.p_KeyMet->Config(); + + if (TSC_Globals.For_Key->p_Data->Change) + { + objgrp->Change = TSC_STATE_CHANGED; + } + + stateMask |= TSC_Params.p_KeySta[TSC_Globals.For_Key->p_Data->StateId].StateMask; +#endif + } + else if ((pObj->Type == TSC_OBJ_LINEAR) || (pObj->Type == TSC_OBJ_ROTARY)) + { +#if TOUCH_TOTAL_LINROTS > 0 + TSC_Globals.For_LinRot->p_Methods->Config(); + + if (TSC_Globals.For_LinRot->p_Data->Change) + { + objgrp->Change = TSC_STATE_CHANGED; + } + + stateMask |= TSC_Globals.For_LinRot->p_SM[TSC_Globals.For_LinRot->p_Data->StateId].StateMask; +#endif + } + else if ((pObj->Type == TSC_OBJ_LINEARB) || (pObj->Type == TSC_OBJ_ROTARYB)) + { +#if TOUCH_TOTAL_LINROTS_B > 0 + TSC_Params.p_LinRotMet->Config(); + + if (TSC_Globals.For_LinRot->p_Data->Change) + { + objgrp->Change = TSC_STATE_CHANGED; + } + stateMask |= TSC_Params.p_LinRotSta[TSC_Globals.For_LinRot->p_Data->StateId].StateMask; +#endif + } + pObj++; + } + /* Update the object group state mask */ + objgrp->StateMask = stateMask; +} + +/*! + * @brief Process the state machine on a group of Objects + * + * @param objgrp: Pointer to the group of objects to process + * + * @retval None + */ +void TSC_Obj_ProcessGroup(TSC_ObjectGroup_T* objgrp) +{ + TSC_tIndex_T idxObj; + CONST TSC_Object_T* pObj; + TSC_tNum_T stateMask = 0; + + pObj = objgrp->p_Obj; + objgrp->Change = TSC_STATE_NOT_CHANGED; + + /* Process all objects */ + for (idxObj = 0; idxObj < objgrp->NbObjects; idxObj++) + { + TSC_Obj_ConfigGlobalObj(pObj); + + if (pObj->Type == TSC_OBJ_TOUCHKEY) + { +#if TOUCH_TOTAL_TOUCHKEYS > 0 + TSC_Globals.For_Key->p_Methods->Process(); + + if (TSC_Globals.For_Key->p_Data->Change) + { + objgrp->Change = TSC_STATE_CHANGED; + } + + stateMask |= TSC_Globals.For_Key->p_SM[TSC_Globals.For_Key->p_Data->StateId].StateMask; +#endif + } + else if (pObj->Type == TSC_OBJ_TOUCHKEYB) + { +#if TOUCH_TOTAL_TOUCHKEYS_B > 0 + TSC_Params.p_KeyMet->Process(); + + if (TSC_Globals.For_Key->p_Data->Change) + { + objgrp->Change = TSC_STATE_CHANGED; + } + + stateMask |= TSC_Params.p_KeySta[TSC_Globals.For_Key->p_Data->StateId].StateMask; +#endif + } + else if ((pObj->Type == TSC_OBJ_LINEAR) || (pObj->Type == TSC_OBJ_ROTARY)) + { +#if TOUCH_TOTAL_LINROTS > 0 + TSC_Globals.For_LinRot->p_Methods->Process(); + + if (TSC_Globals.For_LinRot->p_Data->Change) + { + objgrp->Change = TSC_STATE_CHANGED; + } + + stateMask |= TSC_Globals.For_LinRot->p_SM[TSC_Globals.For_LinRot->p_Data->StateId].StateMask; +#endif + } + else if ((pObj->Type == TSC_OBJ_LINEARB) || (pObj->Type == TSC_OBJ_ROTARYB)) + { +#if TOUCH_TOTAL_LINROTS_B > 0 + TSC_Params.p_LinRotMet->Process(); + + if (TSC_Globals.For_LinRot->p_Data->Change) + { + objgrp->Change = TSC_STATE_CHANGED; + } + + stateMask |= TSC_Params.p_LinRotSta[TSC_Globals.For_LinRot->p_Data->StateId].StateMask; +#endif + } + pObj++; + } + /* Update the object group state mask */ + objgrp->StateMask = stateMask; +} + +/*! + * @brief Set the global object variable + * + * @param pObj: Pointer to the object to process + * + * @retval None + */ +void TSC_Obj_ConfigGlobalObj(CONST TSC_Object_T* pObj) +{ + TSC_Globals.For_Obj = pObj; + + if ((pObj->Type == TSC_OBJ_TOUCHKEY) || (pObj->Type == TSC_OBJ_TOUCHKEYB)) + { +#if TOUCH_TOTAL_KEYS > 0 + TSC_Globals.For_Key = (TSC_TouchKey_T*)pObj->MyObj; +#endif + } + else if ((pObj->Type == TSC_OBJ_LINEAR) || (pObj->Type == TSC_OBJ_LINEARB) || + (pObj->Type == TSC_OBJ_ROTARY) || (pObj->Type == TSC_OBJ_ROTARYB)) + { +#if TOUCH_TOTAL_LNRTS > 0 + TSC_Globals.For_LinRot = (TSC_LinRot_T*)pObj->MyObj; +#endif + } +} + +/**@} end of group TSC_Object_Functions */ +/**@} end of group TSC_Object_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_time.c b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_time.c new file mode 100644 index 0000000000..aa88141e18 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_time.c @@ -0,0 +1,224 @@ +/*! + * @file tsc_time.c + * + * @brief This file contains all functions to manage the timings in general. + * + * @version V1.0.0 + * + * @date 2022-02-21 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +#include "tsc.h" +#include "tsc_time.h" + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_Time_Driver TSC Time Driver + @{ +*/ + +/** @defgroup TSC_Time_Macros Macros + @{ +*/ + +/**@} end of group TSC_Time_Macros */ + +/** @defgroup TSC_Time_Enumerations Enumerations + @{ +*/ + +/**@} end of group TSC_Time_Enumerations */ + +/** @defgroup TSC_Time_Structures Structures + @{ +*/ + +/**@} end of group TSC_Time_Structures */ + +/** @defgroup TSC_Time_Variables Variables + @{ +*/ + +/**@} end of group TSC_Time_Variables */ + +/** @defgroup TSC_Time_Functions Functions + @{ +*/ + +/*! + * @brief Configurate of the timing module + * + * @param None + * + * @retval pointer to a TSC_STATUS_T structure + */ +TSC_STATUS_T TSC_Time_Config(void) +{ + /* Program one systick interrupt every (1 / TOUCH_TICK_FREQ) ms */ + if (SysTick_Config(SystemCoreClock / TOUCH_TICK_FREQ)) + { + return TSC_STATUS_ERROR; + } + else + { + return TSC_STATUS_OK; + } +} + +/*! + * @brief Management of the timing module interrupt service routine. + * + * @param None + * + * @retval None + */ +void TSC_Time_ProcessInterrupt(void) +{ + static TSC_tTick_ms_T val_1s = 0; + + /* Count 1 global tick every xxx ms (defined by TOUCH_TICK_FREQ parameter) */ + TSC_Globals.Tick_ms++; + + /* Check if 1 second has elapsed */ + val_1s++; + if (val_1s > (TOUCH_TICK_FREQ - 1)) + { + TSC_Globals.Tick_sec++; + if (TSC_Globals.Tick_sec > 63) + { + TSC_Globals.Tick_sec = 0; + } + val_1s = 0; + } + + /* Callback function */ +#if TOUCH_USE_TIMER_CALLBACK > 0 + TSC_CallBack_TimerTick(); +#endif +} + +/*! + * @brief Check if a delay (in ms) has elapsed + * This function must be called regularly due to counter Roll-over only managed one time + * + * @param delay_ms: Delay in ms + * + * @param last_tick: Variable holding the last tick value + * + * @retval Status + */ +TSC_STATUS_T TSC_Time_Delay_ms(TSC_tTick_ms_T delay_ms, __IO TSC_tTick_ms_T* last_tick) +{ + TSC_tTick_ms_T count1, count2; + + disableInterrupts(); + + count1 = TSC_Globals.Tick_ms; + + if (delay_ms == 0) + { + enableInterrupts(); + return TSC_STATUS_ERROR; + } + + /* Counter Roll-over management */ + if (count1 < *last_tick) + { + count2 = (0xFFFF - *last_tick) + count1 + 1; + + } + else + { + count2 = count1 - *last_tick; + } + +#if (TOUCH_TICK_FREQ == 125) + if (count2 >= (TSC_tTick_ms_T)(delay_ms >> 3)) //!< Divide by 8 for 8ms tick +#endif +#if (TOUCH_TICK_FREQ == 250) + if (count2 >= (TSC_tTick_ms_T)(delay_ms >> 2)) //!< Divide by 4 for 4ms tick +#endif +#if (TOUCH_TICK_FREQ == 500) + if (count2 >= (TSC_tTick_ms_T)(delay_ms >> 1)) //!< Divide by 2 for 2ms tick +#endif +#if (TOUCH_TICK_FREQ == 1000) + if (count2 >= (TSC_tTick_ms_T)delay_ms) //!< Direct value for 1ms tick +#endif +#if (TOUCH_TICK_FREQ == 2000) + if (count2 >= (TSC_tTick_ms_T)(delay_ms << 1)) //!< Multiply by 2 for 0.5ms tick +#endif + { + /* Save current time */ + *last_tick = count1; + enableInterrupts(); + return TSC_STATUS_OK; + } + enableInterrupts(); + return TSC_STATUS_BUSY; +} + +/*! + * @brief Check if a delay has elapsed. + * + * @param delay_sec: Delay in seconds + * + * @param last_tick: Variable holding the last tick value + * + * @retval Status + */ +TSC_STATUS_T TSC_Time_Delay_sec(TSC_tTick_sec_T delay_sec, __IO TSC_tTick_sec_T* last_tick) +{ + TSC_tTick_sec_T count1, count2; + + disableInterrupts(); + + count1 = TSC_Globals.Tick_sec; + + if (delay_sec == 0) + { + enableInterrupts(); + return TSC_STATUS_ERROR; + } + + /* Counter Roll-over management */ + if (count1 < *last_tick) + { + count2 = (TSC_tTick_sec_T)((63 - *last_tick) + count1 + 1); + + } + else + { + count2 = (TSC_tTick_sec_T)(count1 - *last_tick); + } + + if (count2 >= delay_sec) + { + /* Save current time */ + *last_tick = count1; + enableInterrupts(); + return TSC_STATUS_OK; + } + enableInterrupts(); + return TSC_STATUS_BUSY; +} + +/**@} end of group TSC_Time_Functions */ +/**@} end of group TSC_Time_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_touchkey.c b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_touchkey.c new file mode 100644 index 0000000000..22b44f9905 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/TSC_Device_Lib/src/tsc_touchkey.c @@ -0,0 +1,1131 @@ +/*! + * @file tsc_touchkey.c + * + * @brief This file contains all functions to manage TouchKey sensors. + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "tsc.h" +#include "tsc_touchkey.h" + +/** @addtogroup TSC_Driver_Library TSC Driver Library + @{ +*/ + +/** @addtogroup TSC_TouchKey_Driver TSC TouchKey Driver + @{ +*/ + +/** @defgroup TSC_TouchKey_Macros Macros + @{ +*/ + +#if TOUCH_TOTAL_KEYS > 0 + +#define FOR_MEAS TSC_Globals.For_Key->p_ChD->Meas +#define FOR_DELTA TSC_Globals.For_Key->p_ChD->Delta +#define FOR_REFER TSC_Globals.For_Key->p_ChD->Refer +#define FOR_REFREST TSC_Globals.For_Key->p_ChD->RefRest +#define FOR_CHANNEL_DATA TSC_Globals.For_Key->p_ChD +#define FOR_ACQ_STATUS TSC_Globals.For_Key->p_ChD->Flag.AcqStatus +#define FOR_OBJ_STATUS TSC_Globals.For_Key->p_ChD->Flag.ObjStatus +#define FOR_DATA_READY TSC_Globals.For_Key->p_ChD->Flag.DataReady + +#define FOR_STATEID TSC_Globals.For_Key->p_Data->StateId +#define FOR_CHANGE TSC_Globals.For_Key->p_Data->Change +#define FOR_COUNTER_DEB TSC_Globals.For_Key->p_Data->CounterDebounce +#define FOR_COUNTER_DTO TSC_Globals.For_Key->p_Data->CounterDTO +#define FOR_DXSLOCK TSC_Globals.For_Key->p_Data->DxsLock + +#define FOR_PROXIN_TH TSC_Globals.For_Key->p_Param->ProxInTh +#define FOR_PROXOUT_TH TSC_Globals.For_Key->p_Param->ProxOutTh +#define FOR_DETECTIN_TH TSC_Globals.For_Key->p_Param->DetectInTh +#define FOR_DETECTOUT_TH TSC_Globals.For_Key->p_Param->DetectOutTh +#define FOR_CALIB_TH TSC_Globals.For_Key->p_Param->CalibTh + +#define FOR_COUNTER_DEB_CALIB TSC_Globals.For_Key->p_Param->CounterDebCalib +#define FOR_COUNTER_DEB_PROX TSC_Globals.For_Key->p_Param->CounterDebProx +#define FOR_COUNTER_DEB_DETECT TSC_Globals.For_Key->p_Param->CounterDebDetect +#define FOR_COUNTER_DEB_RELEASE TSC_Globals.For_Key->p_Param->CounterDebRelease +#define FOR_COUNTER_DEB_ERROR TSC_Globals.For_Key->p_Param->CounterDebError + +#if TOUCH_DTO > 0 + #define DTO_READ_TIME {TSC_TouchKey_DTOGetTime();} +#else + #define DTO_READ_TIME +#endif + +#if TOUCH_COEFF_TH > 0 + #define TEST_DELTA(OPER,TH) (FOR_DELTA OPER (uint16_t)((uint16_t)TH << TOUCH_COEFF_TH)) + #define TEST_DELTA_N(OPER,TH) (FOR_DELTA OPER -((uint16_t)((uint16_t)TH << TOUCH_COEFF_TH))) + #define TEST_DELTA_NEGATIVE {if (FOR_DELTA < 0) {return;}} +#else + #define TEST_DELTA(OPER,TH) (FOR_DELTA OPER TH) + #define TEST_DELTA_N(OPER,TH) (FOR_DELTA OPER -(TH)) + #define TEST_DELTA_NEGATIVE +#endif + +/**@} end of group TSC_TouchKey_Macros */ + +/** @defgroup TSC_TouchKey_Enumerations Enumerations + @{ +*/ + +/**@} end of group TSC_TouchKey_Enumerations */ + +/** @defgroup TSC_TouchKey_Structures Structures + @{ +*/ + +/**@} end of group TSC_TouchKey_Structures */ + +/** @defgroup TSC_TouchKey_Variables Variables + @{ +*/ + +static TSC_tNum_T CalibDiv; + +/**@} end of group TSC_TouchKey_Variables */ + +/** @defgroup TSC_TouchKey_Functions Functions + @{ +*/ + +void TSC_TouchKey_DTOGetTime(void); + +/*! + * @brief Config parameters with default values from configuration file + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_Config(void) +{ + /* Debounce counters */ + FOR_COUNTER_DEB_CALIB = TOUCH_DEBOUNCE_CALIB; +#if TOUCH_USE_PROX > 0 + FOR_COUNTER_DEB_PROX = TOUCH_DEBOUNCE_PROX; +#endif + FOR_COUNTER_DEB_DETECT = TOUCH_DEBOUNCE_DETECT; + FOR_COUNTER_DEB_RELEASE = TOUCH_DEBOUNCE_RELEASE; + FOR_COUNTER_DEB_ERROR = TOUCH_DEBOUNCE_ERROR; + + /* Thresholds */ +#if TOUCH_USE_PROX > 0 + FOR_PROXIN_TH = TOUCH_KEY_PROX_IN_TH; + FOR_PROXOUT_TH = TOUCH_KEY_PROX_OUT_TH; +#endif + FOR_DETECTIN_TH = TOUCH_KEY_DETECT_IN_TH; + FOR_DETECTOUT_TH = TOUCH_KEY_DETECT_OUT_TH; + FOR_CALIB_TH = TOUCH_KEY_CALIB_TH; + + /* Config state */ + TSC_TouchKey_ConfigCalibrationState(TOUCH_CALIB_DELAY); +} + +/*! + * @brief Process the State Machine + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_Process(void) +{ + TSC_STATEID_T stateID; + + if ((FOR_STATEID == TSC_STATEID_OFF) || (FOR_DATA_READY != 0)) + { + FOR_DATA_READY = TSC_DATA_NOT_READY; + stateID = FOR_STATEID; + +#if TOUCH_TOTAL_TOUCHKEYS > 0 + if (TSC_Globals.For_Obj->Type == TSC_OBJ_TOUCHKEY) + { + TSC_Globals.For_Key->p_SM[FOR_STATEID].StateFunc(); + } +#endif + +#if TOUCH_TOTAL_TOUCHKEYS_B > 0 + if (TSC_Globals.For_Obj->Type == TSC_OBJ_TOUCHKEYB) + { + TSC_Params.p_KeySta[FOR_STATEID].StateFunc(); + } +#endif + + /* Check if the new state has changed */ + if (FOR_STATEID != stateID) + { + FOR_CHANGE = TSC_STATE_CHANGED; + } + else + { + FOR_CHANGE = TSC_STATE_NOT_CHANGED; + } + +#if TOUCH_USE_DXS > 0 + if (FOR_STATEID == TSC_STATEID_TOUCH) + { + FOR_STATEID = TSC_STATEID_DETECT; + } + if (FOR_STATEID != TSC_STATEID_DETECT) + { + FOR_DXSLOCK = TSC_FALSE; + } +#endif + } +} + +/*! + * @brief Go in Calibration state + * + * @param delay: Delay before calibration starts (stabilization of noise filter) + * + * @retval None + */ +void TSC_TouchKey_ConfigCalibrationState(TSC_tCounter_T delay) +{ + FOR_STATEID = TSC_STATEID_CALIB; + FOR_CHANGE = TSC_STATE_CHANGED; + FOR_OBJ_STATUS = TSC_OBJ_STATUS_ON; + + if (TSC_Params.NumCalibSample == 4) + { + CalibDiv = 2; + } + else if (TSC_Params.NumCalibSample == 16) + { + CalibDiv = 4; + } + else + { + TSC_Params.NumCalibSample = 8; + CalibDiv = 3; + } + /* If a noise filter is used, the counter must be initialized to a value + * different from 0 in order to stabilize the filter. */ + FOR_COUNTER_DEB = (TSC_tCounter_T)(delay + (TSC_tCounter_T)TSC_Params.NumCalibSample); + FOR_REFER = 0; +} + +/*! + * @brief Go in Off state with sensor "off" + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_ConfigOffState(void) +{ + FOR_STATEID = TSC_STATEID_OFF; + FOR_CHANGE = TSC_STATE_CHANGED; + FOR_OBJ_STATUS = TSC_OBJ_STATUS_OFF; +} + +/*! + * @brief Go in Off state with sensor in "Burst mode only" + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_ConfigBurstOnlyState(void) +{ + FOR_STATEID = TSC_STATEID_OFF; + FOR_CHANGE = TSC_STATE_CHANGED; + FOR_OBJ_STATUS = TSC_OBJ_STATUS_BURST_ONLY; +} + +/*! + * @brief Return the current state identifier + * + * @param None + * + * @retval State id + */ +TSC_STATEID_T TSC_TouchKey_ReadStateId(void) +{ + return (FOR_STATEID); +} + +/*! + * @brief Return the current state mask + * + * @param None + * + * @retval State mask + */ +TSC_STATEMASK_T TSC_TouchKey_ReadStateMask(void) +{ + TSC_STATEMASK_T state_mask = TSC_STATEMASK_UNKNOWN; + +#if TOUCH_TOTAL_TOUCHKEYS > 0 + if (TSC_Globals.For_Obj->Type == TSC_OBJ_TOUCHKEY) + { + state_mask = TSC_Globals.For_Key->p_SM[FOR_STATEID].StateMask; + } +#endif + +#if TOUCH_TOTAL_TOUCHKEYS_B > 0 + if (TSC_Globals.For_Obj->Type == TSC_OBJ_TOUCHKEYB) + { + state_mask = TSC_Params.p_KeySta[FOR_STATEID].StateMask; + } +#endif + + return state_mask; +} + +/*! + * @brief Return the Change flag + * + * @param None + * + * @retval Change flag status + */ +TSC_tNum_T TSC_TouchKey_ReadChangeFlag(void) +{ + return (FOR_CHANGE); +} + +#if TOUCH_USE_PROX > 0 +/*! + * @brief Debounce Release processing (previous state = Proximity) + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_ProcessDebReleaseProxState(void) +{ + /* Acquisition error (min or max) */ + if (FOR_ACQ_STATUS & TSC_ACQ_STATUS_ERROR_MASK) + { + FOR_STATEID = TSC_STATEID_PROX; + } + else /*!< Acquisition is OK or has NOISE */ + { + if (FOR_DELTA <= FOR_PROXOUT_TH) + { + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + } + else + { + FOR_STATEID = TSC_STATEID_PROX; + } + } +} +#endif /*!< if TOUCH_USE_PROX > 0 */ + +/*! + * @brief Debounce Release processing (previous state = Detect) + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_ProcessDebReleaseDetectState(void) +{ + /* Acquisition error (min or max) */ + if (FOR_ACQ_STATUS & TSC_ACQ_STATUS_ERROR_MASK) + { + FOR_STATEID = TSC_STATEID_DETECT; + } + else /*!< Acquisition is OK or has NOISE */ + { + if TEST_DELTA( <=, FOR_DETECTOUT_TH) + { +#if TOUCH_USE_PROX > 0 + if (FOR_DELTA > FOR_PROXOUT_TH) + { + FOR_STATEID = TSC_STATEID_PROX; + return; + } +#endif + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + } + else + { + TEST_DELTA_NEGATIVE; + FOR_STATEID = TSC_STATEID_DETECT; + } + } +} + +/*! + * @brief Debounce Release processing (previous state = Touch) + * Same as Debounce Release Detect processing + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_ProcessDebReleaseTouchState(void) +{ + /* Acquisition error (min or max) */ + if (FOR_ACQ_STATUS & TSC_ACQ_STATUS_ERROR_MASK) + { + FOR_STATEID = TSC_STATEID_TOUCH; + } + else /*!< Acquisition is OK or has NOISE */ + { + if TEST_DELTA( <=, FOR_DETECTOUT_TH) + { +#if TOUCH_USE_PROX > 0 + if (FOR_DELTA > FOR_PROXOUT_TH) + { + FOR_STATEID = TSC_STATEID_PROX; + return; + } +#endif + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + } + else + { + TEST_DELTA_NEGATIVE; + FOR_STATEID = TSC_STATEID_TOUCH; + } + } +} + +/*! + * @brief Release state processing + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_ProcessReleaseState(void) +{ + /* Acquisition error (min or max) */ + if (FOR_ACQ_STATUS & TSC_ACQ_STATUS_ERROR_MASK) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_ERROR; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_ERROR_RELEASE; + } + else + { + FOR_STATEID = TSC_STATEID_ERROR; + } + } + else /*!< Acquisition is OK or has NOISE */ + { + if TEST_DELTA( >=, FOR_DETECTIN_TH) + { + TEST_DELTA_NEGATIVE; + FOR_COUNTER_DEB = FOR_COUNTER_DEB_DETECT; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_DETECT; + } + else + { + FOR_STATEID = TSC_STATEID_DETECT; + DTO_READ_TIME; + } + return; + } + +#if TOUCH_USE_PROX > 0 + if (FOR_DELTA >= FOR_PROXIN_TH) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_PROX; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_PROX; + } + else + { + FOR_STATEID = TSC_STATEID_PROX; + DTO_READ_TIME; + } + return; + } +#endif + + /* Check delta for re-calibration + Warning: the threshold value is inverted in the macro */ + if TEST_DELTA_N( <=, FOR_CALIB_TH) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_CALIB; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_CALIB; + } + else + { + TSC_TouchKey_ConfigCalibrationState(0); + } + } + } +} + +/*! + * @brief Debounce Calibration processing (previous state = Release) + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_ProcessDebCalibrationState(void) +{ + /* Acquisition error (min or max) */ + if (FOR_ACQ_STATUS & TSC_ACQ_STATUS_ERROR_MASK) + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + else /*!< Acquisition is OK or has NOISE */ + { + /* Still below recalibration threshold + Warning: the threshold value is inverted in the macro */ + if TEST_DELTA_N( >, FOR_CALIB_TH) + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + else + { + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + TSC_TouchKey_ConfigCalibrationState(0); + } + } + } +} + +/*! + * @brief Calibration state processing + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_ProcessCalibrationState(void) +{ + TSC_tMeas_T newMeas; + +#if TOUCH_CALIB_DELAY > 0 + /* Noise filter stabilization time */ + if (FOR_COUNTER_DEB > (TSC_tCounter_T)TSC_Params.NumCalibSample) + { + FOR_COUNTER_DEB--; + return; + } +#endif + /* Acquisition error (min or max) */ + if (FOR_ACQ_STATUS & TSC_ACQ_STATUS_ERROR_MASK) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_ERROR; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_ERROR_CALIB; + } + else + { + FOR_STATEID = TSC_STATEID_ERROR; + } + } + else /*!< Acquisition is OK or has NOISE */ + { + /* Read the new measure or Calculate it */ +#if TOUCH_USE_MEAS > 0 + newMeas = FOR_MEAS; +#else + newMeas = TSC_Acq_ComputeMeas(FOR_REFER, FOR_DELTA); +#endif + + /* Verify the first Reference value */ + if (FOR_COUNTER_DEB != (TSC_tCounter_T)TSC_Params.NumCalibSample) + { + FOR_REFER += newMeas; + + /* Check reference overflow */ + if (FOR_REFER < newMeas) + { + FOR_REFER = 0; + FOR_STATEID = TSC_STATEID_ERROR; + return; + } + } + else + { + if (TSC_Acq_TestFirstReference(FOR_CHANNEL_DATA, newMeas)) + { + FOR_REFER = newMeas; + } + else + { + FOR_REFER = 0; + return; + } + } + + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + FOR_REFER >>= CalibDiv; + FOR_REFREST = 0; + FOR_DELTA = 0; + FOR_STATEID = TSC_STATEID_RELEASE; + } + } +} + +#if TOUCH_USE_PROX > 0 +/*! + * @brief Debounce Proximity processing (previous state = Release) + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_ProcessDebProxState(void) +{ + /* Acquisition error (min or max) */ + if (FOR_ACQ_STATUS & TSC_ACQ_STATUS_ERROR_MASK) + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + else /*!< Acquisition is OK or has NOISE */ + { + if TEST_DELTA( >=, FOR_DETECTIN_TH) + { + TEST_DELTA_NEGATIVE; + FOR_COUNTER_DEB = FOR_COUNTER_DEB_DETECT; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_DETECT; + } + else + { + FOR_STATEID = TSC_STATEID_DETECT; + DTO_READ_TIME; + } + return; + } + + if (FOR_DELTA < FOR_PROXIN_TH) + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + else + { + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + FOR_STATEID = TSC_STATEID_PROX; + DTO_READ_TIME; + } + } + } +} +#endif + +#if TOUCH_USE_PROX > 0 +/*! + * @brief Debounce Proximity processing (previous state = Detect) + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_ProcessDebProxDetectState(void) +{ + /* Acquisition error (min or max) */ + if (FOR_ACQ_STATUS & TSC_ACQ_STATUS_ERROR_MASK) + { + FOR_STATEID = TSC_STATEID_DETECT; + } + else /*!< Acquisition is OK or has NOISE */ + { + if TEST_DELTA( >, FOR_DETECTOUT_TH) + { + TEST_DELTA_NEGATIVE; + FOR_STATEID = TSC_STATEID_DETECT; + return; + } + + if (FOR_DELTA <= FOR_PROXOUT_TH) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_RELEASE; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_RELEASE_DETECT; + } + else + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + } + else + { + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + FOR_STATEID = TSC_STATEID_PROX; + DTO_READ_TIME; + } + } + } +} +#endif + +#if TOUCH_USE_PROX > 0 +/*! + * @brief Debounce Proximity processing (previous state = Touch) + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_ProcessDebProxTouchState(void) +{ + /* Acquisition error (min or max) */ + if (FOR_ACQ_STATUS & TSC_ACQ_STATUS_ERROR_MASK) + { + FOR_STATEID = TSC_STATEID_TOUCH; + } + else /*!< Acquisition is OK or has NOISE */ + { + if TEST_DELTA( >, FOR_DETECTOUT_TH) + { + TEST_DELTA_NEGATIVE; + FOR_STATEID = TSC_STATEID_TOUCH; + return; + } + + if (FOR_DELTA <= FOR_PROXOUT_TH) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_RELEASE; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_RELEASE_TOUCH; + } + else + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + } + else + { + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + FOR_STATEID = TSC_STATEID_PROX; + DTO_READ_TIME; + } + } + } +} +#endif + +#if TOUCH_USE_PROX > 0 +/*! + * @brief Proximity state processing + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_ProcessProxState(void) +{ +#if TOUCH_DTO > 0 + TSC_tTick_sec_T tick_detected; +#endif + + /* Acquisition error (min or max) */ + if (FOR_ACQ_STATUS & TSC_ACQ_STATUS_ERROR_MASK) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_ERROR; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_ERROR_PROX; + } + else + { + FOR_STATEID = TSC_STATEID_ERROR; + } + } + else /*!< Acquisition is OK or has NOISE */ + { + if (FOR_DELTA <= FOR_PROXOUT_TH) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_RELEASE; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_RELEASE_PROX; + } + else + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + return; + } + + if TEST_DELTA( >=, FOR_DETECTIN_TH) + { + TEST_DELTA_NEGATIVE; + FOR_COUNTER_DEB = FOR_COUNTER_DEB_DETECT; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_DETECT; + } + else + { + FOR_STATEID = TSC_STATEID_DETECT; + DTO_READ_TIME; + } + return; + } + + /* Stay in Proximity state */ +#if TOUCH_DTO > 0 + /* Detection Time Out (DTO) processing */ + if ((TSC_Params.DTO > 1) && (TSC_Params.DTO < 64)) + { + /* Read the detected time previously saved */ + tick_detected = FOR_COUNTER_DTO; + /* Enter in calibration state if the DTO duration has elapsed */ + if (TSC_Time_Delay_sec(TSC_Params.DTO, &tick_detected) == TSC_STATUS_OK) + { + TSC_TouchKey_ConfigCalibrationState(0); + } + } +#endif + } +} +#endif + +/*! + * @brief Debounce Detect processing (previous state = Release or Proximity) + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_ProcessDebDetectState(void) +{ + /* Acquisition error (min or max) */ + if (FOR_ACQ_STATUS & TSC_ACQ_STATUS_ERROR_MASK) + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + else /*!< Acquisition is OK or has NOISE */ + { + if TEST_DELTA( <, FOR_DETECTIN_TH) + { +#if TOUCH_USE_PROX > 0 + if (FOR_DELTA < FOR_PROXIN_TH) + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + else + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_PROX; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_PROX; + } + else + { + FOR_STATEID = TSC_STATEID_PROX; + DTO_READ_TIME; + } + } +#else + FOR_STATEID = TSC_STATEID_RELEASE; +#endif + } + else + { + TEST_DELTA_NEGATIVE; + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + FOR_STATEID = TSC_STATEID_DETECT; + DTO_READ_TIME; + } + } + } +} + +/*! + * @brief Detect state processing + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_ProcessDetectState(void) +{ +#if TOUCH_DTO > 0 + TSC_tTick_sec_T tick_detected; +#endif + /* Acquisition error (min or max) */ + if (FOR_ACQ_STATUS & TSC_ACQ_STATUS_ERROR_MASK) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_ERROR; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_ERROR_DETECT; + } + else + { + FOR_STATEID = TSC_STATEID_ERROR; + } + } + else /*!< Acquisition is OK or has NOISE */ + { + if TEST_DELTA( >, FOR_DETECTOUT_TH) + { + TEST_DELTA_NEGATIVE; +#if TOUCH_DTO > 0 + /* Detection Time Out (DTO) processing */ + if ((TSC_Params.DTO > 1) && (TSC_Params.DTO < 64)) + { + /* Read the detected time previously saved */ + tick_detected = FOR_COUNTER_DTO; + /* Enter in calibration state if the DTO duration has elapsed */ + if (TSC_Time_Delay_sec(TSC_Params.DTO, &tick_detected) == TSC_STATUS_OK) + { + TSC_TouchKey_ConfigCalibrationState(0); + } + } +#endif + return; + } + +#if TOUCH_USE_PROX > 0 + if (FOR_DELTA > FOR_PROXOUT_TH) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_PROX; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_PROX_DETECT; + } + else + { + FOR_STATEID = TSC_STATEID_PROX; + DTO_READ_TIME; + } + return; + } +#endif + + FOR_COUNTER_DEB = FOR_COUNTER_DEB_RELEASE; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_RELEASE_DETECT; + } + else + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + } +} + +/*! + * @brief Touch state processing, Same as Detect state + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_ProcessTouchState(void) +{ +#if TOUCH_DTO > 0 + TSC_tTick_sec_T tick_detected; +#endif + /* Acquisition error (min or max) */ + if (FOR_ACQ_STATUS & TSC_ACQ_STATUS_ERROR_MASK) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_ERROR; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_ERROR_TOUCH; + } + else + { + FOR_STATEID = TSC_STATEID_ERROR; + } + } + else /*!< Acquisition is OK or has NOISE */ + { + if TEST_DELTA( >, FOR_DETECTOUT_TH) + { + TEST_DELTA_NEGATIVE; +#if TOUCH_DTO > 0 + /* Detection Time Out (DTO) processing */ + if ((TSC_Params.DTO > 1) && (TSC_Params.DTO < 64)) + { + /* Read the detected time previously saved */ + tick_detected = FOR_COUNTER_DTO; + /* Enter in calibration state if the DTO duration has elapsed */ + if (TSC_Time_Delay_sec(TSC_Params.DTO, &tick_detected) == TSC_STATUS_OK) + { + TSC_TouchKey_ConfigCalibrationState(0); + } + } +#endif + return; + } + +#if TOUCH_USE_PROX > 0 + if (FOR_DELTA > FOR_PROXOUT_TH) + { + FOR_COUNTER_DEB = FOR_COUNTER_DEB_PROX; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_PROX_TOUCH; + } + else + { + FOR_STATEID = TSC_STATEID_PROX; + DTO_READ_TIME; + } + return; + } +#endif + + FOR_COUNTER_DEB = FOR_COUNTER_DEB_RELEASE; + if (FOR_COUNTER_DEB) + { + FOR_STATEID = TSC_STATEID_DEB_RELEASE_TOUCH; + } + else + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + } +} + +/*! + * @brief Debounce error state processing + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_ProcessDebErrorState(void) +{ + volatile TSC_STATEMASK_T mask; + + /* Acquisition error (min or max) */ + if (FOR_ACQ_STATUS & TSC_ACQ_STATUS_ERROR_MASK) + { + if (FOR_COUNTER_DEB > 0) + { + FOR_COUNTER_DEB--; + } + if (FOR_COUNTER_DEB == 0) + { + FOR_STATEID = TSC_STATEID_ERROR; + } + } + else /*!< Acquisition is OK or has NOISE */ + { + mask = TSC_TouchKey_ReadStateMask(); + mask &= (TSC_STATEMASK_T)(~(TSC_STATE_DEBOUNCE_BIT_MASK | TSC_STATE_ERROR_BIT_MASK)); + + if (mask == TSC_STATEMASK_RELEASE) + { + FOR_STATEID = TSC_STATEID_RELEASE; + } + else if (mask == TSC_STATEMASK_PROX) + { + FOR_STATEID = TSC_STATEID_PROX; + } + else if (mask == TSC_STATEMASK_DETECT) + { + FOR_STATEID = TSC_STATEID_DETECT; + } + else if (mask == TSC_STATEMASK_TOUCH) + { + FOR_STATEID = TSC_STATEID_TOUCH; + } + else + { + TSC_TouchKey_ConfigCalibrationState(0); + } + } +} + +/*! + * @brief Read the current time in second and affect it to the DTO counter (Private) + * + * @param None + * + * @retval None + */ +void TSC_TouchKey_DTOGetTime(void) +{ + disableInterrupts(); + FOR_COUNTER_DTO = (TSC_tCounter_T)TSC_Globals.Tick_sec; + enableInterrupts(); +} +#endif /*!< #if TOUCH_TOTAL_KEYS > 0 */ + +/**@} end of group TSC_TouchKey_Functions */ +/**@} end of group TSC_TouchKey_Driver */ +/**@} end of group TSC_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/CDC/inc/usbd_class_cdc.h b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/CDC/inc/usbd_class_cdc.h new file mode 100644 index 0000000000..1cf4cc4694 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/CDC/inc/usbd_class_cdc.h @@ -0,0 +1,85 @@ +/*! + * @file usbd_class_cdc.h + * + * @brief CDC Class handler file head file + * + * @version V1.0.0 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __USBD_CDC_CLASS_ +#define __USBD_CDC_CLASS_ + +/* Includes */ +#include "usbd_core.h" + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup Core_Device Core Device + @{ +*/ + +/** @addtogroup Class + @{ +*/ + +/** @addtogroup CDC + @{ +*/ + +/** @defgroup CDC_Macros Macros + @{ +*/ + +/**@} end of group CDC_Macros */ + +/** @defgroup CDC_Enumerations Enumerations + @{ +*/ + +/**@} end of group CDC_Enumerations */ + +/** @defgroup CDC_Structures Structures + @{ +*/ + +/**@} end of group CDC_Structures */ + +/** @defgroup CDC_Variables Variables + @{ +*/ + +/**@} end of group CDC_Variables */ + +/** @defgroup CDC_Functions Functions + @{ +*/ + +void USBD_ClassHandler(USBD_DevReqData_T* reqData); + +#endif + +/**@} end of group CDC_Functions */ +/**@} end of group CDC */ +/**@} end of group Class */ +/**@} end of group Core_Device */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/CDC/src/usbd_class_cdc.c b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/CDC/src/usbd_class_cdc.c new file mode 100644 index 0000000000..05c0f71371 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/CDC/src/usbd_class_cdc.c @@ -0,0 +1,122 @@ +/*! + * @file usbd_class_cdc.c + * + * @brief CDC Class handler file + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "usbd_class_cdc.h" + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup Core_Device Core Device + @{ +*/ + +/** @addtogroup Class + @{ +*/ + +/** @addtogroup CDC + @{ +*/ + +/** @defgroup CDC_Macros Macros + @{ +*/ + +/**@} end of group CDC_Macros */ + +/** @defgroup CDC_Enumerations Enumerations + @{ +*/ + +/**@} end of group CDC_Enumerations */ + +/** @defgroup CDC_Structures Structures + @{ +*/ + +/**@} end of group CDC_Structures */ + +/** @defgroup CDC_Variables Variables + @{ +*/ + +static uint8_t cmdBuf[8] = {0}; + +/**@} end of group CDC_Variables */ + +/** @defgroup CDC_Functions Functions + @{ +*/ + +/*! + * @brief USB CDC Class request handler + * + * @param reqData : point to USBD_DevReqData_T structure + * + * @retval None + */ +void USBD_ClassHandler(USBD_DevReqData_T* reqData) +{ + uint16_t length = ((uint16_t)reqData->byte.wLength[1] << 8) | \ + reqData->byte.wLength[0] ; + + if (!length) + { + if (!reqData->byte.bmRequestType.bit.dir) + { + USBD_CtrlTxStatus(); + } + else + { + USBD_CtrlRxStatus(); + } + } + else + { + switch (reqData->byte.bRequest) + { + + case 0x20: + USBD_CtrlOutData(cmdBuf, length); + break; + case 0x21: + USBD_CtrlInData(cmdBuf, length); + break; + case 0x22: + USBD_CtrlOutData(cmdBuf, length); + break; + default: + break; + } + } +} + +/**@} end of group CDC_Functions */ +/**@} end of group CDC */ +/**@} end of group Class */ +/**@} end of group Core_Device */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/HID/inc/usbd_class_hid.h b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/HID/inc/usbd_class_hid.h new file mode 100644 index 0000000000..9a7278b6c6 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/HID/inc/usbd_class_hid.h @@ -0,0 +1,94 @@ +/*! + * @file usbd_class_hid.h + * + * @brief HID Class handler file head file + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __USBD_HID_CLASS_ +#define __USBD_HID_CLASS_ + +/* Includes */ +#include "usbd_core.h" + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup Core_Device Core Device + @{ +*/ + +/** @addtogroup Class + @{ +*/ + +/** @addtogroup HID + @{ +*/ + +/** @defgroup HID_Macros Macros + @{ +*/ + +#define HID_CLASS_REQ_SET_PROTOCOL 0x0B +#define HID_CLASS_REQ_GET_PROTOCOL 0x03 + +#define HID_CLASS_REQ_SET_IDLE 0x0A +#define HID_CLASS_REQ_GET_IDLE 0x02 + +#define HID_CLASS_REQ_SET_REPORT 0x09 +#define HID_CLASS_REQ_GET_REPORT 0x01 + +/**@} end of group HID_Macros */ + +/** @defgroup HID_Enumerations Enumerations + @{ +*/ + +/**@} end of group HID_Enumerations */ + +/** @defgroup HID_Structures Structures + @{ +*/ + +/**@} end of group HID_Structures */ + +/** @defgroup HID_Variables Variables + @{ +*/ + +/**@} end of group HID_Variables */ + +/** @defgroup HID_Functions Functions + @{ +*/ + +void USBD_ClassHandler(USBD_DevReqData_T* reqData); + +#endif + +/**@} end of group HID_Functions */ +/**@} end of group HID */ +/**@} end of group Class */ +/**@} end of group Core_Device */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/HID/src/usbd_class_hid.c b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/HID/src/usbd_class_hid.c new file mode 100644 index 0000000000..0a2d0c2384 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/HID/src/usbd_class_hid.c @@ -0,0 +1,114 @@ +/*! + * @file usbd_class_hid.c + * + * @brief HID Class handler file + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "usbd_class_hid.h" + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup Core_Device Core Device + @{ +*/ + +/** @addtogroup Class + @{ +*/ + +/** @addtogroup HID + @{ +*/ + +/** @defgroup HID_Macros Macros + @{ +*/ + +/**@} end of group HID_Macros */ + +/** @defgroup HID_Enumerations Enumerations + @{ +*/ + +/**@} end of group HID_Enumerations */ + +/** @defgroup HID_Structures Structures + @{ +*/ + +/**@} end of group HID_Structures */ + +/** @defgroup HID_Variables Variables + @{ +*/ + +static uint8_t s_hidIdleState; +static uint8_t s_hidProtocol; + +/**@} end of group HID_Variables */ + +/** @defgroup HID_Functions Functions + @{ +*/ + +/*! + * @brief USB HID Class request handler + * + * @param reqData : point to USBD_DevReqData_T structure + * + * @retval None + */ +void USBD_ClassHandler(USBD_DevReqData_T* reqData) +{ + switch (reqData->byte.bRequest) + { + case HID_CLASS_REQ_SET_IDLE: + s_hidIdleState = reqData->byte.wValue[1]; + USBD_CtrlInData(NULL, 0); + break; + + case HID_CLASS_REQ_GET_IDLE: + USBD_CtrlInData(&s_hidIdleState, 1); + break; + + case HID_CLASS_REQ_SET_PROTOCOL: + s_hidProtocol = reqData->byte.wValue[0]; + USBD_CtrlInData(NULL, 0); + break; + + case HID_CLASS_REQ_GET_PROTOCOL: + USBD_CtrlInData(&s_hidProtocol, 1); + break; + + default: + break; + } +} + +/**@} end of group HID_Functions */ +/**@} end of group HID */ +/**@} end of group Class */ +/**@} end of group Core_Device */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/inc/usbd_class_msc.h b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/inc/usbd_class_msc.h new file mode 100644 index 0000000000..12425200c5 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/inc/usbd_class_msc.h @@ -0,0 +1,88 @@ +/*! + * @file usbd_class_msc.h + * + * @brief MSC Class handler file head file + * + * @version V1.0.0 + * + * @date 2021-12-06 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __CLASS_MSC_ +#define __CLASS_MSC_ + +/* Includes */ +#include "usbd_core.h" + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup Core_Device Core Device + @{ +*/ + +/** @addtogroup Class + @{ +*/ + +/** @addtogroup MSC + @{ +*/ + +/** @defgroup MSC_Macros Macros + @{ +*/ + +#define BOT_GET_MAX_LUN 0xFE +#define BOT_RESET 0xFF + +/**@} end of group MSC_Macros */ + +/** @defgroup MSC_Enumerations Enumerations + @{ +*/ + +/**@} end of group MSC_Enumerations */ + +/** @defgroup MSC_Structures Structures + @{ +*/ + +/**@} end of group MSC_Structures */ + +/** @defgroup MSC_Variables Variables + @{ +*/ + +/**@} end of group MSC_Variables */ + +/** @defgroup MSC_Functions Functions + @{ +*/ + +void USBD_MSC_ClassHandler(USBD_DevReqData_T* reqData); + +#endif + +/**@} end of group MSC_Functions */ +/**@} end of group MSC */ +/**@} end of group Class */ +/**@} end of group Core_Device */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/inc/usbd_msc_bot.h b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/inc/usbd_msc_bot.h new file mode 100644 index 0000000000..0f82d7fe6d --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/inc/usbd_msc_bot.h @@ -0,0 +1,156 @@ +/*! + * @file usbd_msc_bot.h + * + * @brief MSC BOT protocol core functions + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __USBD_MSC_BOT_H +#define __USBD_MSC_BOT_H + +/* Includes */ +#include "usbd_core.h" + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup Core_Device Core Device + @{ +*/ + +/** @addtogroup Class + @{ +*/ + +/** @addtogroup MSC_BOT + @{ +*/ + +/** @defgroup MSC_BOT_Macros Macros + @{ +*/ + +#define MSC_BOT_CBW_SIGNATURE (uint32_t)(0x43425355) +#define MSC_BOT_CBW_LENGTH 31 + +#define MSC_BOT_CSW_SIGNATURE (uint32_t)(0x53425355) +#define MSC_BOT_CSW_LENGTH 13 + +/**@} end of group MSC_BOT_Macros */ + +/** @defgroup MSC_BOT_Enumerations Enumerations + @{ +*/ + +typedef enum +{ + BOT_STATE_IDLE, /*!< Idle state */ + BOT_STATE_DATA_OUT, /*!< Data Out state */ + BOT_STATE_DATA_IN, /*!< Data In state */ + BOT_STATE_LAST_DATA_IN, /*!< Last Data In Last */ + BOT_STATE_SEND_DATA /*!< Send Immediate data */ +} BOT_STATE_T; + +typedef enum +{ + BOT_STATUS_NORMAL, + BOT_STATUS_RECOVERY, + BOT_STATUS_ERROR +} BOT_STATUS_T; + +typedef enum +{ + BOT_CSW_STATUS_CMD_OK, + BOT_CSW_STATUS_CMD_FAIL, + BOT_CSW_STATUS_PHASE_ERROR +} BOT_CSW_STATUS_T; + +/**@} end of group MSC_BOT_Enumerations */ + +/** @defgroup MSC_BOT_Structures Structures + @{ +*/ + +/** + * @brief Command Block Wrapper + */ +typedef struct +{ + uint32_t dSignature; + uint32_t dTag; + uint32_t dDataXferLen; + uint8_t bmFlags; + uint8_t bLUN; + uint8_t bCBLen; + uint8_t CB[16]; +} BOT_CBW_T; + +/** + * @brief Command Status Wrapper + */ +typedef struct +{ + uint32_t dSignature; + uint32_t dTag; + uint32_t dDataResidue; + uint8_t bStatus; +} BOT_CSW_T; + +typedef struct +{ + uint8_t state; + uint8_t status; + uint16_t dataLen; + BOT_CBW_T CBW; + BOT_CSW_T CSW; + uint8_t data[MSC_MEDIA_PACKET]; +} BOT_Info_T; + +/**@} end of group MSC_BOT_Structures */ + +/** @defgroup MSC_BOT_Variables Variables + @{ +*/ + +extern BOT_Info_T g_BOTInfo; + +/**@} end of group MSC_BOT_Variables */ + +/** @defgroup MSC_BOT_Functions Functions + @{ +*/ + +void USBD_MSC_BOT_Reset(void); +void USBD_MSC_BOT_Init(void); +void USBD_MSC_BOT_OutData(uint8_t ep); +void USBD_MSC_BOT_InData(uint8_t ep); +void USBD_MSC_BOT_TxCSW(uint8_t cswStatus); +void USBD_MSV_BOT_ClearFeatureHandler(void); + +#endif /*__USBD_MSC_BOT_H */ + +/**@} end of group MSC_BOT_Functions */ +/**@} end of group MSC_BOT_ */ +/**@} end of group Class */ +/**@} end of group Core_Device */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/inc/usbd_msc_scsi.h b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/inc/usbd_msc_scsi.h new file mode 100644 index 0000000000..92140d4c85 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/inc/usbd_msc_scsi.h @@ -0,0 +1,183 @@ +/*! + * @file usbd_msc_scsi.h + * + * @brief MSC scsi + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __USBD_MSC_SCSI_H_ +#define __USBD_MSC_SCSI_H_ + +/* Includes */ +#include "usbd_core.h" + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup Core_Device Core Device + @{ +*/ + +/** @addtogroup Class + @{ +*/ + +/** @addtogroup MSC_SCSI + @{ +*/ + +/** @defgroup MSC_SCSI_Macros Macros + @{ +*/ + +#define SCSI_SENSE_LIST_NUMBER 4 +#define SCSI_INQUIRY_LENGTH 36 + +/* SCSI Commands */ +#define SCSI_CMD_FORMAT_UNIT ((uint8_t)0x04) +#define SCSI_CMD_INQUIRY ((uint8_t)0x12) +#define SCSI_CMD_MODE_SELECT_6 ((uint8_t)0x15) +#define SCSI_CMD_MODE_SELECT_10 ((uint8_t)0x55) +#define SCSI_CMD_MODE_SENSE_6 ((uint8_t)0x1A) +#define SCSI_CMD_MODE_SENSE_10 ((uint8_t)0x5A) +#define SCSI_CMD_ALLOW_MEDIUM_REMOVAL ((uint8_t)0x1E) +#define SCSI_CMD_READ_6 ((uint8_t)0x08) +#define SCSI_CMD_READ_10 ((uint8_t)0x28) +#define SCSI_CMD_READ_12 ((uint8_t)0xA8) +#define SCSI_CMD_READ_16 ((uint8_t)0x88) + +#define SCSI_CMD_READ_CAPACITY_10 ((uint8_t)0x25) +#define SCSI_CMD_READ_CAPACITY_16 ((uint8_t)0x9E) + +#define SCSI_CMD_REQUEST_SENSE ((uint8_t)0x03) +#define SCSI_CMD_START_STOP_UNIT ((uint8_t)0x1B) +#define SCSI_CMD_TEST_UNIT_READY ((uint8_t)0x00) +#define SCSI_CMD_WRITE6 ((uint8_t)0x0A) +#define SCSI_CMD_WRITE10 ((uint8_t)0x2A) +#define SCSI_CMD_WRITE12 ((uint8_t)0xAA) +#define SCSI_CMD_WRITE16 ((uint8_t)0x8A) + +#define SCSI_CMD_VERIFY_10 ((uint8_t)0x2F) +#define SCSI_CMD_VERIFY_12 ((uint8_t)0xAF) +#define SCSI_CMD_VERIFY_16 ((uint8_t)0x8F) + +#define SCSI_CMD_SEND_DIAGNOSTIC ((uint8_t)0x1D) +#define SCSI_CMD_READ_FORMAT_CAPACITIES ((uint8_t)0x23) + +#define SCSI_ASC_INVALID_CDB 0x20 +#define SCSI_ASC_INVALID_FIELED_IN_COMMAND 0x24 +#define SCSI_ASC_PARAMETER_LIST_LENGTH_ERROR 0x1A +#define SCSI_ASC_INVALID_FIELD_IN_PARAMETER_LIST 0x26 +#define SCSI_ASC_ADDRESS_OUT_OF_RANGE 0x21 +#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A +#define SCSI_ASC_MEDIUM_HAVE_CHANGED 0x28 +#define SCSI_ASC_WRITE_PROTECTED 0x27 +#define SCSI_ASC_UNRECOVERED_READ_ERROR 0x11 +#define SCSI_ASC_WRITE_FAULT 0x03 + +#define SCSI_READ_FORMAT_CAPACITY_DATA_LEN 0x0C +#define SCSI_READ_CAPACITY10_DATA_LEN 0x08 +#define SCSI_MODE_SENSE10_DATA_LEN 0x08 +#define SCSI_MODE_SENSE6_DATA_LEN 0x04 +#define SCSI_REQUEST_SENSE_DATA_LEN 0x12 +#define SCSI_STANDARD_INQUIRY_DATA_LEN 0x24 +#define SCSI_BLKVFY 0x04 + +/**@} end of group MSC_SCSI_Macros */ + +/** @defgroup MSC_SCSI_Enumerations Enumerations + @{ +*/ + +/** + * @brief SCSI function status + */ +typedef enum +{ + SCSI_FAIL, + SCSI_OK, +} SCSI_STATUS_T; + +/** + * @brief SCSI Sense Key + */ +typedef enum +{ + SCSI_SKEY_NO_SENSE, + SCSI_SKEY_RECOVERED_ERROR, + SCSI_SKEY_NOT_READY, + SCSI_SKEY_MEDIUM_ERROR, + SCSI_SKEY_HARDWARE_ERROR, + SCSI_SKEY_ILLEGAL_REQUEST, + SCSI_SKEY_UNIT_ATTENTION, + SCSI_SKEY_DATA_PROTECT, + SCSI_SKEY_BLANK_CHECK, + SCSI_SKEY_VENDOR_SPECIFIC, + SCSI_SKEY_COPY_ABORTED, + SCSI_SKEY_ABORTED_COMMAND, + SCSI_SKEY_VOLUME_OVERFLOW = 13, + SCSI_SKEY_MISCOMPARE = 14 +} SCSI_SKEY_T; + +/**@} end of group MSC_SCSI_Enumerations */ + +/** @defgroup MSC_SCSI_Structures Structures + @{ +*/ + +/** + * @brief SCSI Sense + */ +typedef struct +{ + uint8_t sensekey; + uint8_t ASC; + uint8_t ASCQ; +} SCSI_Sense_T; + +/**@} end of group MSC_SCSI_Structures */ + +/** @defgroup MSC_SCSI_Variables Variables + @{ +*/ + +extern SCSI_Sense_T g_scsiSense[SCSI_SENSE_LIST_NUMBER]; +extern uint8_t g_senseTxCnt; +extern uint8_t g_sensePutCnt; + +/**@} end of group MSC_SCSI_Variables */ + +/** @defgroup MSC_SCSI_Functions Functions + @{ +*/ + +uint8_t SCSI_CmdHandler(uint8_t lun, uint8_t* cmd); +void SCSI_PutSenseCode(uint8_t lun, uint8_t sKey, uint8_t ASC, uint8_t ASCQ); + +#endif + +/**@} end of group MSC_SCSI_Functions */ +/**@} end of group MSC_SCSI */ +/**@} end of group Class */ +/**@} end of group Core_Device */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/src/usbd_class_msc.c b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/src/usbd_class_msc.c new file mode 100644 index 0000000000..4df2621207 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/src/usbd_class_msc.c @@ -0,0 +1,130 @@ +/*! + * @file usbd_class_msc.c + * + * @brief MSC Class file + * + * @version V1.0.0 + * + * @date 2021-12-06 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "usbd_class_msc.h" +#include "usbd_msc_bot.h" + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup Core_Device Core Device + @{ +*/ + +/** @addtogroup Class + @{ +*/ + +/** @addtogroup MSC + @{ +*/ + +/** @defgroup MSC_Macros Macros + @{ +*/ + +/**@} end of group MSC_Macros */ + +/** @defgroup MSC_Enumerations Enumerations + @{ +*/ + +/**@} end of group MSC_Enumerations */ + +/** @defgroup MSC_Structures Structures + @{ +*/ + +/**@} end of group MSC_Structures */ + +/** @defgroup MSC_Variables Variables + @{ +*/ + +static uint8_t s_mscMaxLen = 0; + +/**@} end of group MSC_Variables */ + +/** @defgroup MSC_Functions Functions + @{ +*/ + +/*! + * @brief USB MSC Class request handler + * + * @param reqData : point to USBD_DevReqData_T structure + * + * @retval None + */ +void USBD_MSC_ClassHandler(USBD_DevReqData_T* reqData) +{ + uint16_t wValue = ((uint16_t)reqData->byte.wValue[1] << 8) | \ + reqData->byte.wValue[0]; + uint16_t wLength = ((uint16_t)reqData->byte.wLength[1] << 8) | \ + reqData->byte.wLength[0]; + + switch (reqData->byte.bRequest) + { + case BOT_GET_MAX_LUN : + if ((wValue == 0) && (wLength == 1) && \ + (reqData->byte.bmRequestType.bit.dir == 1)) + { + s_mscMaxLen = STORAGE_MAX_LUN - 1; + + USBD_CtrlInData(&s_mscMaxLen, 1); + } + else + { + USBD_SetEPTxRxStatus(USBD_EP_0, USBD_EP_STATUS_STALL, USBD_EP_STATUS_STALL); + } + break; + case BOT_RESET : + if ((wValue == 0) && (wLength == 0) && \ + (reqData->byte.bmRequestType.bit.dir == 0)) + { + USBD_CtrlInData(NULL, 0); + /* Reset */ + USBD_MSC_BOT_Reset(); + } + else + { + USBD_SetEPTxRxStatus(USBD_EP_0, USBD_EP_STATUS_STALL, USBD_EP_STATUS_STALL); + } + + break; + + default: + USBD_SetEPTxRxStatus(USBD_EP_0, USBD_EP_STATUS_STALL, USBD_EP_STATUS_STALL); + break; + } +} + +/**@} end of group MSC_Functions */ +/**@} end of group MSC */ +/**@} end of group Class */ +/**@} end of group Core_Device */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/src/usbd_msc_bot.c b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/src/usbd_msc_bot.c new file mode 100644 index 0000000000..254a0a8884 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/src/usbd_msc_bot.c @@ -0,0 +1,292 @@ +/*! + * @file usbd_msv_bot.c + * + * @brief MSC BOT protocol core functions + * + * @version V1.0.0 + * + * @date 2021-12-25 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "usbd_msc_bot.h" +#include "usbd_core.h" +#include "usbd_storage_disk.h" +#include "usbd_msc_scsi.h" + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup Core_Device Core Device + @{ +*/ + +/** @addtogroup Class + @{ +*/ + +/** @addtogroup MSC_BOT + @{ +*/ + +/** @defgroup MSC_BOT_Macros Macros + @{ +*/ + +/**@} end of group MSC_BOT_Macros */ + +/** @defgroup MSC_BOT_Enumerations Enumerations + @{ +*/ + +/**@} end of group MSC_BOT_Enumerations */ + +/** @defgroup MSC_BOT_Structures Structures + @{ +*/ + +/**@} end of group MSC_BOT_Structures */ + +/** @defgroup MSC_BOT_Variables Variables + @{ +*/ + +BOT_Info_T g_BOTInfo; + +/**@} end of group MSC_BOT_Variables */ + +/** @defgroup MSC_BOT_Functions Functions + @{ +*/ + +static void USBD_MSC_BOT_DecodeCBW(void); +static void USBD_MSC_BOT_TxData(uint8_t* txBuf, uint16_t len); +static void USBD_MSC_BOT_Stall(void); + +/*! + * @brief BOT Process Reset. + * + * @param None + * + * @retval None + */ +void USBD_MSC_BOT_Reset(void) +{ + g_BOTInfo.state = BOT_STATE_IDLE; + g_BOTInfo.status = BOT_STATUS_RECOVERY; + + USBD_RxData(MSC_OUT_EP & 0x7f, (uint8_t*)&g_BOTInfo.CBW, MSC_BOT_CBW_LENGTH); +} + +/*! + * @brief BOT Process initialization. + * + * @param None + * + * @retval None + */ +void USBD_MSC_BOT_Init(void) +{ + g_BOTInfo.state = BOT_STATE_IDLE; + g_BOTInfo.status = BOT_STATUS_NORMAL; + + g_storageCallBack.Init(0); + + USBD_RxData(MSC_OUT_EP & 0x7f, (uint8_t*)&g_BOTInfo.CBW, MSC_BOT_CBW_LENGTH); +} + +/*! + * @brief Bulk OUT data handler. + * + * @param ep : OUT endpoint + * + * @retval None + */ +void USBD_MSC_BOT_OutData(uint8_t ep) +{ + if (g_BOTInfo.state == BOT_STATE_IDLE) + { + USBD_MSC_BOT_DecodeCBW(); + } + else if (g_BOTInfo.state == BOT_STATE_DATA_OUT) + { + if (SCSI_CmdHandler(g_BOTInfo.CBW.bLUN, g_BOTInfo.CBW.CB) != SCSI_OK) + { + USBD_MSC_BOT_TxCSW(BOT_CSW_STATUS_CMD_FAIL); + } + } +} + +/*! + * @brief Bulk IN data handler. + * + * @param ep : IN endpoint + * + * @retval None + */ +void USBD_MSC_BOT_InData(uint8_t ep) +{ + if (g_BOTInfo.state == BOT_STATE_DATA_IN) + { + if (SCSI_CmdHandler(g_BOTInfo.CBW.bLUN, g_BOTInfo.CBW.CB) != SCSI_OK) + { + USBD_MSC_BOT_TxCSW(BOT_CSW_STATUS_CMD_FAIL); + } + } + else if ((g_BOTInfo.state == BOT_STATE_SEND_DATA) || \ + (g_BOTInfo.state == BOT_STATE_LAST_DATA_IN)) + { + USBD_MSC_BOT_TxCSW(BOT_CSW_STATUS_CMD_OK); + } +} + +/*! + * @brief Decode CBW. + * + * @param None + * + * @retval None + */ +static void USBD_MSC_BOT_DecodeCBW(void) +{ + uint32_t xferCnt = g_usbDev.outBuf[MSC_OUT_EP & 0x7f].xferCnt; + + g_BOTInfo.CSW.dTag = g_BOTInfo.CBW.dTag; + g_BOTInfo.CSW.dDataResidue = g_BOTInfo.CBW.dDataXferLen; + + if ((xferCnt != MSC_BOT_CBW_LENGTH) || \ + (g_BOTInfo.CBW.dSignature != MSC_BOT_CBW_SIGNATURE) || \ + (g_BOTInfo.CBW.bLUN > 1) || (g_BOTInfo.CBW.bCBLen < 1) || \ + (g_BOTInfo.CBW.bCBLen > 16)) + { + SCSI_PutSenseCode(g_BOTInfo.CBW.bLUN, SCSI_SKEY_ILLEGAL_REQUEST, + SCSI_ASC_INVALID_CDB, 0); + + g_BOTInfo.status = BOT_STATUS_ERROR; + } + else + { + if (SCSI_CmdHandler(g_BOTInfo.CBW.bLUN, g_BOTInfo.CBW.CB) != SCSI_OK) + { + USBD_MSC_BOT_Stall(); + } + else if ((g_BOTInfo.state == BOT_STATE_IDLE) || \ + (g_BOTInfo.state == BOT_STATE_SEND_DATA)) + { + if (g_BOTInfo.dataLen) + { + USBD_MSC_BOT_TxData(g_BOTInfo.data, g_BOTInfo.dataLen); + } + else + { + USBD_MSC_BOT_TxCSW(BOT_CSW_STATUS_CMD_OK); + } + } + } +} + +/*! + * @brief MSC send data. + * + * @param txBuf : buffer to send + * + * @param len : buffer length + * + * @retval None + */ +static void USBD_MSC_BOT_TxData(uint8_t* txBuf, uint16_t len) +{ + len = USB_MIN(len, g_BOTInfo.CBW.dDataXferLen); + + g_BOTInfo.CSW.dDataResidue -= len; + g_BOTInfo.CSW.bStatus = BOT_CSW_STATUS_CMD_OK; + g_BOTInfo.state = BOT_STATE_SEND_DATA; + + USBD_TxData(MSC_IN_EP & 0x7f, txBuf, len); +} + +/*! + * @brief Send CSW. + * + * @param cswStatus : status of CSW + * + * @retval None + */ +void USBD_MSC_BOT_TxCSW(uint8_t cswStatus) +{ + g_BOTInfo.CSW.dSignature = MSC_BOT_CSW_SIGNATURE; + g_BOTInfo.CSW.bStatus = cswStatus; + g_BOTInfo.state = BOT_STATE_IDLE; + + USBD_TxData(MSC_IN_EP & 0x7f, (uint8_t*)&g_BOTInfo.CSW, + MSC_BOT_CSW_LENGTH); + + USBD_RxData(MSC_OUT_EP & 0x7f, (uint8_t*)&g_BOTInfo.CBW, + MSC_BOT_CBW_LENGTH); +} + +/*! + * @brief handler clearFeature in standard request. + * + * @param None + * + * @retval None + */ +void USBD_MSV_BOT_ClearFeatureHandler(void) +{ + if (g_BOTInfo.status == BOT_STATUS_ERROR) + { + USBD_SetEPTxStatus(MSC_IN_EP & 0x7f, USBD_EP_STATUS_NAK); + g_BOTInfo.status = BOT_STATUS_NORMAL; + } + else if (((g_usbDev.reqData.byte.wIndex[0] & 0x80) == 0x80) && \ + g_BOTInfo.status != BOT_STATUS_RECOVERY) + { + USBD_MSC_BOT_TxCSW(BOT_CSW_STATUS_CMD_FAIL); + } +} + +/*! + * @brief Stall MSC. + * + * @param None + * + * @retval None + */ +static void USBD_MSC_BOT_Stall(void) +{ + if ((g_BOTInfo.CBW.bmFlags == 0) && (g_BOTInfo.CBW.dDataXferLen != 0) && \ + (g_BOTInfo.status == BOT_STATUS_NORMAL)) + { + USBD_SetEPRxStatus(MSC_OUT_EP & 0x7f, USBD_EP_STATUS_STALL); + } + + USBD_SetEPTxStatus(MSC_IN_EP & 0x7f, USBD_EP_STATUS_STALL); + + if (g_BOTInfo.status == BOT_STATUS_ERROR) + { + USBD_RxData(MSC_OUT_EP & 0x7f, (uint8_t*)&g_BOTInfo.CBW, MSC_BOT_CBW_LENGTH); + } +} + +/**@} end of group MSC_BOT_Functions */ +/**@} end of group MSC_BOT_ */ +/**@} end of group Class */ +/**@} end of group Core_Device */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/src/usbd_msc_scsi.c b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/src/usbd_msc_scsi.c new file mode 100644 index 0000000000..d896602681 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Class/MSC/src/usbd_msc_scsi.c @@ -0,0 +1,752 @@ +/*! + * @file usbd_msc_scsi.c + * + * @brief MSC scsi + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "usbd_msc_bot.h" +#include "usbd_msc_scsi.h" +#include "usbd_storage_disk.h" + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup Core_Device Core Device + @{ +*/ + +/** @addtogroup Class + @{ +*/ + +/** @addtogroup MSC_SCSI + @{ +*/ + +/** @defgroup MSC_SCSI_Macros Macros + @{ +*/ + +/**@} end of group MSC_SCSI_Macros */ + +/** @defgroup MSC_SCSI_Enumerations Enumerations + @{ +*/ + +/**@} end of group MSC_SCSI_Enumerations */ + +/** @defgroup MSC_SCSI_Structures Structures + @{ +*/ + +/**@} end of group MSC_SCSI_Structures */ + +/** @defgroup MSC_SCSI_Variables Variables + @{ +*/ + +SCSI_Sense_T g_scsiSenseCode[SCSI_SENSE_LIST_NUMBER]; +uint8_t g_senseTxCnt; +uint8_t g_sensePutCnt; + +static uint32_t s_blkSize; +static uint32_t s_blkNbr; + +static uint32_t s_blkAddr; +static uint32_t s_blkLen; + +/* USB Mass storage Page 0 Inquiry Data */ +static const uint8_t s_page00InquiryData[] = +{ + 0x00, + 0x00, + 0x00, + (7 - 4), + 0x00, + 0x80, + 0x83 +}; +/* USB Mass storage sense 6 Data */ +static const uint8_t s_modeSense6Data[] = +{ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; +/* USB Mass storage sense 10 Data */ +static const uint8_t s_modeSense10Data[] = +{ + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; + +/**@} end of group MSC_SCSI_Variables */ + +/** @defgroup MSC_SCSI_Functions Functions + @{ +*/ + +static uint8_t SCSI_TestUnitReady(uint8_t lun); +static uint8_t SCSI_Inquiry(uint8_t lun, uint8_t* command); +static uint8_t SCSI_RequestSense(uint8_t lun, uint8_t* command); + +static uint8_t SCSI_ReadFormatCapacity(uint8_t lun, uint8_t* command); +static uint8_t SCSI_ReadCapacity10(uint8_t lun, uint8_t* command); +static uint8_t SCSI_Read10(uint8_t lun, uint8_t* command); +static uint8_t SCSI_Write10(uint8_t lun, uint8_t* command); +static uint8_t SCSI_Verify10(uint8_t lun, uint8_t* command); + +static uint8_t SCSI_StartStopUnit(void); +static uint8_t SCSI_ModeSense6(uint8_t lun, uint8_t* command); +static uint8_t SCSI_ModeSense10(uint8_t lun, uint8_t* command); + +static uint8_t SCSI_Read(uint8_t lun); +static uint8_t SCSI_Write(uint8_t lun); +static uint8_t SCSI_CheckAddress(uint8_t lun, uint32_t blkOffset, uint16_t blkNbr); + +/*! + * @brief SCSI command handler. + * + * @param lun: Logical unit number + * + * @param command: Command pointer + * + * @retval SCSI_OK or SCSI_FAILL + */ +uint8_t SCSI_CmdHandler(uint8_t lun, uint8_t* command) +{ + uint8_t ret = SCSI_OK; + + switch (command[0]) + { + case SCSI_CMD_TEST_UNIT_READY: + ret = SCSI_TestUnitReady(lun); + break; + + case SCSI_CMD_INQUIRY: + ret = SCSI_Inquiry(lun, command); + break; + + case SCSI_CMD_REQUEST_SENSE: + ret = SCSI_RequestSense(lun, command); + break; + + case SCSI_CMD_READ_FORMAT_CAPACITIES: + ret = SCSI_ReadFormatCapacity(lun, command); + break; + + case SCSI_CMD_READ_CAPACITY_10: + ret = SCSI_ReadCapacity10(lun, command); + break; + + case SCSI_CMD_READ_10: + ret = SCSI_Read10(lun, command); + break; + + case SCSI_CMD_WRITE10: + ret = SCSI_Write10(lun, command); + break; + + case SCSI_CMD_VERIFY_10: + ret = SCSI_Verify10(lun, command); + break; + case SCSI_CMD_ALLOW_MEDIUM_REMOVAL: + case SCSI_CMD_START_STOP_UNIT: + ret = SCSI_StartStopUnit(); + break; + + case SCSI_CMD_MODE_SENSE_6: + ret = SCSI_ModeSense6(lun, command); + break; + + case SCSI_CMD_MODE_SENSE_10: + ret = SCSI_ModeSense10(lun, command); + break; + + default: + SCSI_PutSenseCode(lun, SCSI_SKEY_ILLEGAL_REQUEST, + SCSI_ASC_INVALID_CDB, 0); + ret = SCSI_FAIL; + } + + return ret; +} + +/*! + * @brief Put the sense code to array. + * + * @param sKey: sense Key + * + * @param ASC: Additional Sense Code + * + * @param ASCQ: Additional Sense Code Qualifier + * + * @retval None + */ +void SCSI_PutSenseCode(uint8_t lun, uint8_t sKey, uint8_t ASC, uint8_t ASCQ) +{ + g_scsiSenseCode[g_sensePutCnt].sensekey = sKey; + g_scsiSenseCode[g_sensePutCnt].ASC = ASC; + g_scsiSenseCode[g_sensePutCnt].ASCQ = ASCQ; + + if ((++g_sensePutCnt) == SCSI_SENSE_LIST_NUMBER) + { + g_sensePutCnt = 0; + } +} + +/*! + * @brief SCSI Test Unit Ready handler. + * + * @param lun: Logical unit number + * + * @retval SCSI_OK or SCSI_FAILL + */ +static uint8_t SCSI_TestUnitReady(uint8_t lun) +{ + if (g_BOTInfo.CBW.dDataXferLen) + { + SCSI_PutSenseCode(g_BOTInfo.CBW.bLUN, SCSI_SKEY_ILLEGAL_REQUEST, + SCSI_ASC_INVALID_CDB, 0); + + return SCSI_FAIL; + } + else if (g_storageCallBack.CheckReady(lun) != SCSI_OK) + { + SCSI_PutSenseCode(lun, SCSI_SKEY_NOT_READY, + SCSI_ASC_MEDIUM_NOT_PRESENT, 0); + + return SCSI_FAIL; + } + else + { + g_BOTInfo.dataLen = 0; + return SCSI_OK; + } +} + +/*! + * @brief SCSI Inquiry handler. + * + * @param lun: Logical unit number + * + * @param command: command pointer + * + * @retval SCSI_OK or SCSI_FAILL + */ +static uint8_t SCSI_Inquiry(uint8_t lun, uint8_t* command) +{ + uint16_t i; + uint8_t* pInquiryData; + + if (command[1] & 0x01) + { + pInquiryData = (uint8_t*)s_page00InquiryData; + g_BOTInfo.dataLen = s_page00InquiryData[3] + 4; + } + else + { + pInquiryData = &g_storageCallBack.pInquiryData[lun * SCSI_INQUIRY_LENGTH]; + + g_BOTInfo.dataLen = USB_MIN((pInquiryData[4] + 5), command[4]); + } + + for (i = 0; i < g_BOTInfo.dataLen; i++) + { + g_BOTInfo.data[i] = pInquiryData[i]; + } + + return SCSI_OK; +} + +/*! + * @brief SCSI Request Sense handler. + * + * @param lun: Logical unit number + * + * @param command: command pointer + * + * @retval SCSI_OK or SCSI_FAILL + */ +static uint8_t SCSI_RequestSense(uint8_t lun, uint8_t* command) +{ + uint8_t i = 0; + + while (i < SCSI_REQUEST_SENSE_DATA_LEN) + { + g_BOTInfo.data[i++] = 0; + } + + g_BOTInfo.data[0] = 0x70; + g_BOTInfo.data[7] = SCSI_REQUEST_SENSE_DATA_LEN - 6; + + if (g_senseTxCnt != g_sensePutCnt) + { + g_BOTInfo.data[2] = g_scsiSenseCode[g_senseTxCnt].sensekey; + g_BOTInfo.data[12] = g_scsiSenseCode[g_senseTxCnt].ASC; + g_BOTInfo.data[13] = g_scsiSenseCode[g_senseTxCnt].ASCQ; + + if ((++g_senseTxCnt) == SCSI_SENSE_LIST_NUMBER) + { + g_senseTxCnt = 0; + } + } + + g_BOTInfo.dataLen = (SCSI_REQUEST_SENSE_DATA_LEN < command[4]) ? \ + SCSI_REQUEST_SENSE_DATA_LEN : command[4]; + + return SCSI_OK; +} + +/*! + * @brief SCSI Read Format Capacity handler. + * + * @param lun: Logical unit number + * + * @param command: command pointer + * + * @retval SCSI_OK or SCSI_FAILL + */ +static uint8_t SCSI_ReadFormatCapacity(uint8_t lun, uint8_t* command) +{ + uint16_t i = 0; + uint32_t blkSize; + uint32_t blkNbr; + + while (i < 12) + { + g_BOTInfo.data[i++] = 0; + } + + if (g_storageCallBack.ReadCapacity(lun, &blkNbr, &blkSize) != SCSI_OK) + { + SCSI_PutSenseCode(lun, SCSI_SKEY_NOT_READY, + SCSI_ASC_MEDIUM_NOT_PRESENT, 0); + + return SCSI_FAIL; + } + else + { + blkNbr--; + + g_BOTInfo.data[3] = 0x08; + g_BOTInfo.data[4] = (uint8_t)(blkNbr >> 24); + g_BOTInfo.data[5] = (uint8_t)(blkNbr >> 16); + g_BOTInfo.data[6] = (uint8_t)(blkNbr >> 8); + g_BOTInfo.data[7] = (uint8_t)(blkNbr); + g_BOTInfo.data[8] = 0x02; + g_BOTInfo.data[9] = (uint8_t)(blkSize >> 16); + g_BOTInfo.data[10] = (uint8_t)(blkSize >> 8); + g_BOTInfo.data[11] = (uint8_t)blkSize; + + g_BOTInfo.dataLen = 12; + + return SCSI_OK; + } +} + +/*! + * @brief SCSI Read Capacity10 handler. + * + * @param lun: Logical unit number + * + * @param command: command pointer + * + * @retval SCSI_OK or SCSI_FAILL + */ +static uint8_t SCSI_ReadCapacity10(uint8_t lun, uint8_t* command) +{ + if (g_storageCallBack.ReadCapacity(lun, &s_blkNbr, &s_blkSize) != SCSI_OK) + { + SCSI_PutSenseCode(lun, SCSI_SKEY_NOT_READY, + SCSI_ASC_MEDIUM_NOT_PRESENT, 0); + + return SCSI_FAIL; + } + else + { + g_BOTInfo.data[0] = (uint8_t)((s_blkNbr - 1) >> 24); + g_BOTInfo.data[1] = (uint8_t)((s_blkNbr - 1) >> 16); + g_BOTInfo.data[2] = (uint8_t)((s_blkNbr - 1) >> 8); + g_BOTInfo.data[3] = (uint8_t)(s_blkNbr - 1); + g_BOTInfo.data[4] = (uint8_t)(s_blkSize >> 24); + g_BOTInfo.data[5] = (uint8_t)(s_blkSize >> 16); + g_BOTInfo.data[6] = (uint8_t)(s_blkSize >> 8); + g_BOTInfo.data[7] = (uint8_t)(s_blkSize); + + g_BOTInfo.dataLen = 8; + + return SCSI_OK; + } +} + +/*! + * @brief SCSI Read10 handler. + * + * @param lun: Logical unit number + * + * @param command: command pointer + * + * @retval SCSI_OK or SCSI_FAILL + */ +static uint8_t SCSI_Read10(uint8_t lun, uint8_t* command) +{ + uint8_t ret = SCSI_OK; + + if (g_BOTInfo.state == BOT_STATE_IDLE) + { + if ((g_BOTInfo.CBW.bmFlags & 0x80) != 0x80) + { + SCSI_PutSenseCode(g_BOTInfo.CBW.bLUN, SCSI_SKEY_ILLEGAL_REQUEST, + SCSI_ASC_INVALID_CDB, 0); + + return SCSI_FAIL; + } + + if (g_storageCallBack.CheckReady(lun) != SCSI_OK) + { + SCSI_PutSenseCode(lun, SCSI_SKEY_NOT_READY, + SCSI_ASC_MEDIUM_NOT_PRESENT, 0); + + return SCSI_FAIL; + } + + s_blkAddr = ((uint32_t)command[2] << 24) | \ + ((uint32_t)command[3] << 16) | \ + ((uint32_t)command[4] << 8) | \ + (uint32_t)command[5]; + + s_blkLen = ((uint16_t)command[7] << 8 | (uint8_t)command[8]); + + if (SCSI_CheckAddress(lun, s_blkAddr, s_blkLen) != SCSI_OK) + { + return SCSI_FAIL; + } + + g_BOTInfo.state = BOT_STATE_DATA_IN; + s_blkAddr *= s_blkSize; + s_blkLen *= s_blkSize; + + if (g_BOTInfo.CBW.dDataXferLen != s_blkLen) + { + SCSI_PutSenseCode(g_BOTInfo.CBW.bLUN, SCSI_SKEY_ILLEGAL_REQUEST, + SCSI_ASC_INVALID_CDB, 0); + + return SCSI_FAIL; + } + + } + + g_BOTInfo.dataLen = MSC_MEDIA_PACKET; + + ret = SCSI_Read(lun); + + return ret; +} + +/*! + * @brief SCSI write10 handler. + * + * @param lun: Logical unit number + * + * @param command: command pointer + * + * @retval SCSI_OK or SCSI_FAILL + */ +static uint8_t SCSI_Write10(uint8_t lun, uint8_t* command) +{ + uint8_t ret = SCSI_OK; + uint32_t len; + + if (g_BOTInfo.state == BOT_STATE_IDLE) + { + if (g_BOTInfo.CBW.bmFlags & 0x80) + { + SCSI_PutSenseCode(g_BOTInfo.CBW.bLUN, SCSI_SKEY_ILLEGAL_REQUEST, + SCSI_ASC_INVALID_CDB, 0); + + return SCSI_FAIL; + } + + if (g_storageCallBack.CheckReady(lun) != SCSI_OK) + { + SCSI_PutSenseCode(lun, SCSI_SKEY_NOT_READY, + SCSI_ASC_MEDIUM_NOT_PRESENT, 0); + + return SCSI_FAIL; + } + + if (g_storageCallBack.CheckWPR(lun) != SCSI_OK) + { + SCSI_PutSenseCode(lun, SCSI_SKEY_NOT_READY, + SCSI_ASC_WRITE_PROTECTED, 0); + + return SCSI_FAIL; + } + + s_blkAddr = ((uint32_t)command[2] << 24) | \ + ((uint32_t)command[3] << 16) | \ + ((uint32_t)command[4] << 8) | \ + (uint32_t)command[5]; + + s_blkLen = ((uint16_t)command[7] << 8 | (uint8_t)command[8]); + + if (SCSI_CheckAddress(lun, s_blkAddr, s_blkLen) != SCSI_OK) + { + return SCSI_FAIL; + } + + s_blkAddr *= s_blkSize; + s_blkLen *= s_blkSize; + + if (g_BOTInfo.CBW.dDataXferLen != s_blkLen) + { + SCSI_PutSenseCode(g_BOTInfo.CBW.bLUN, SCSI_SKEY_ILLEGAL_REQUEST, + SCSI_ASC_INVALID_CDB, 0); + + return SCSI_FAIL; + } + + g_BOTInfo.state = BOT_STATE_DATA_OUT; + len = USB_MIN(s_blkLen, MSC_MEDIA_PACKET); + + USBD_RxData(MSC_OUT_EP & 0x7F, g_BOTInfo.data, len); + + } + else + { + ret = SCSI_Write(lun); + } + + return ret; +} + +/*! + * @brief SCSI Verify10 Handler. + * + * @param lun: Logical unit number + * + * @param command: command pointer + * + * @retval SCSI_OK or SCSI_FAILL + */ +static uint8_t SCSI_Verify10(uint8_t lun, uint8_t* command) +{ + if (command[1] & 0x02) + { + SCSI_PutSenseCode(lun, SCSI_SKEY_ILLEGAL_REQUEST, + SCSI_ASC_INVALID_FIELED_IN_COMMAND, 0); + + return SCSI_FAIL; + } + + s_blkAddr = ((uint32_t)command[2] << 24) | \ + ((uint32_t)command[3] << 16) | \ + ((uint32_t)command[4] << 8) | \ + (uint32_t)command[5]; + + s_blkLen = ((uint16_t)command[7] << 8 | (uint8_t)command[8]); + + if (SCSI_CheckAddress(lun, s_blkAddr, s_blkLen) != SCSI_OK) + { + return SCSI_FAIL; + } + + g_BOTInfo.dataLen = 0; + + return SCSI_OK; +} + +/*! + * @brief SCSI Start Stop Unit Handler. + * + * @param None + * + * @retval SCSI_OK or SCSI_FAILL + */ +static uint8_t SCSI_StartStopUnit(void) +{ + g_BOTInfo.dataLen = 0; + return SCSI_OK; +} + +/*! + * @brief SCSI Mode Sense6 Handler. + * + * @param lun: Logical unit number + * + * @param command: command pointer + * + * @retval SCSI_OK or SCSI_FAILL + */ +static uint8_t SCSI_ModeSense6(uint8_t lun, uint8_t* command) +{ + for (uint16_t i = 0; i < 8; i++) + { + g_BOTInfo.data[i] = s_modeSense6Data[i]; + } + + g_BOTInfo.dataLen = 8; + + return SCSI_OK; +} + +/*! + * @brief SCSI Mode Sense10 Handler. + * + * @param lun: Logical unit number + * + * @param command: command pointer + * + * @retval SCSI_OK or SCSI_FAILL + */ +static uint8_t SCSI_ModeSense10(uint8_t lun, uint8_t* command) +{ + for (uint16_t i = 0; i < 8; i++) + { + g_BOTInfo.data[i] = s_modeSense10Data[i]; + } + + g_BOTInfo.dataLen = 8; + + return SCSI_OK; +} + +/*! + * @brief SCSI Read Process. + * + * @param lun: Logical unit number + * + * @retval SCSI_OK or SCSI_FAILL + */ +static uint8_t SCSI_Read(uint8_t lun) +{ + uint32_t len = USB_MIN(MSC_MEDIA_PACKET, s_blkLen); + + if (g_storageCallBack.ReadData(len, g_BOTInfo.data, (s_blkAddr / s_blkSize), + (len / s_blkSize)) != SCSI_OK) + { + SCSI_PutSenseCode(lun, SCSI_SKEY_HARDWARE_ERROR, + SCSI_ASC_UNRECOVERED_READ_ERROR, 0); + + return SCSI_FAIL; + } + + USBD_TxData(MSC_IN_EP & 0x7F, g_BOTInfo.data, len); + + s_blkAddr += len; + s_blkLen -= len; + + g_BOTInfo.CSW.dDataResidue -= len; + + if (s_blkLen == 0) + { + g_BOTInfo.state = BOT_STATE_LAST_DATA_IN; + } + + return SCSI_OK; +} + +/*! + * @brief SCSI Write Process. + * + * @param lun: Logical unit number + * + * @retval SCSI_OK or SCSI_FAILL + */ +static uint8_t SCSI_Write(uint8_t lun) +{ + uint32_t len = USB_MIN(MSC_MEDIA_PACKET, s_blkLen); + + if (s_blkLen - len) + { + __NOP(); + } + if (g_storageCallBack.WriteData(lun, g_BOTInfo.data, s_blkAddr / s_blkSize, + len / s_blkSize) != SCSI_OK) + { + SCSI_PutSenseCode(lun, SCSI_SKEY_HARDWARE_ERROR, SCSI_ASC_WRITE_FAULT, 0); + + return SCSI_FAIL; + } + + s_blkAddr += len; + s_blkLen -= len; + + g_BOTInfo.CSW.dDataResidue -= len; + + if (s_blkLen) + { + len = USB_MIN(MSC_MEDIA_PACKET, s_blkLen); + + USBD_RxData(MSC_OUT_EP & 0x7f, g_BOTInfo.data, len); + } + else + { + USBD_MSC_BOT_TxCSW(BOT_CSW_STATUS_CMD_OK); + } + + return SCSI_OK; +} + +/*! + * @brief SCSI Check Address Range. + * + * @param lun: Logical unit number + * + * @param blkOffset: first block address + * + * @param blkNbr: number of block to be processed + * + * @retval SCSI_OK or SCSI_FAILL + */ +static uint8_t SCSI_CheckAddress(uint8_t lun, uint32_t blkOffset, uint16_t blkNbr) +{ + if (s_blkNbr < (blkNbr + blkOffset)) + { + SCSI_PutSenseCode(lun, SCSI_SKEY_ILLEGAL_REQUEST, + SCSI_ASC_ADDRESS_OUT_OF_RANGE, 0); + + return SCSI_FAIL; + } + + return SCSI_OK; +} + +/**@} end of group MSC_SCSI_Functions */ +/**@} end of group MSC_SCSI */ +/**@} end of group Class */ +/**@} end of group Core_Device */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/inc/usbd_core.h b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/inc/usbd_core.h new file mode 100644 index 0000000000..0bb68804e0 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/inc/usbd_core.h @@ -0,0 +1,366 @@ +/*! + * @file usbd_core.h + * + * @brief USB protocol core handler head file + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __USBD_CORE_H_ +#define __USBD_CORE_H_ + +/* Includes */ +#include "drv_usb_device.h" + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup Core_Device Core Device + @{ +*/ + +/** @addtogroup Standrad + @{ +*/ + +/** @addtogroup Core + @{ +*/ + +/** @defgroup Core_Macros Macros + @{ +*/ + +/* Get minimum value */ +#define USB_MIN(a, b) (a >= b ? b : a) + +/* Get maximum value */ +#define USB_MAX(a, b) (a >= b ? a : b) + +/* control status function */ +#define USBD_CtrlTxStatus() USBD_CtrlInData(NULL, 0) +#define USBD_CtrlRxStatus() USBD_CtrlOutData(NULL, 0) + +/**@} end of group Core_Macros */ + +/** @defgroup Core_Enumerations Enumerations + @{ +*/ + +/** + * @brief USB request type + */ +enum +{ + USBD_REQ_TYPE_STANDARD = 0, + USBD_REQ_TYPE_CLASS = 1, + USBD_REQ_TYPE_VENDOR = 2, + USBD_REQ_TYPE_RESERVED = 3 +}; + +/** + * @brief USB recipient + */ +enum +{ + USBD_RECIPIENT_DEVICE = 0, + USBD_RECIPIENT_INTERFACE = 1, + USBD_RECIPIENT_ENDPOINT = 2, + USBD_RECIPIENT_OTHER = 3, +}; + +/** + * @brief USB standard device requests + */ +enum +{ + USBD_GET_STATUS = 0, + USBD_CLEAR_FEATURE = 1, + USBD_SET_FEATURE = 3, + USBD_SET_ADDRESS = 5, + USBD_GET_DESCRIPTOR = 6, + USBD_SET_DESCRIPTOR = 7, + USBD_GET_CONFIGURATION = 8, + USBD_SET_CONFIGURATION = 9, + USBD_GET_INTERFACE = 10, + USBD_SET_INTERFACE = 11, + USBD_SYNCH_FRAME = 12, +}; + +/** + * @brief USB descriptor types + */ +enum +{ + USBD_DESC_DEVICE = 1, + USBD_DESC_CONFIGURATION = 2, + USBD_DESC_STRING = 3, + USBD_DESC_INTERFACE = 4, + USBD_DESC_ENDPOINT = 5, + USBD_DESC_DEVICE_QUALIFIER = 6, + USBD_DESC_OTHER_SPEED = 7, + USBD_INTERFACE_POWER = 8, +}; + +/** + * @brief USB standard feature + */ +enum +{ + USBD_FEATURE_ENDPOINT_HALT = 0, + USBD_FEATURE_REMOTE_WAKEUP = 1, + USBD_FEATURE_TEST_MODE = 2 +}; + +/** + * @brief USB internal state machine + */ +typedef enum +{ + USBD_CTRL_STATE_WAIT_SETUP, + USBD_CTRL_STATE_DATA_IN, + USBD_CTRL_STATE_DATA_OUT, + USBD_CTRL_STATE_WAIT_STATUS_IN, + USBD_CTRL_STATE_WAIT_STATUS_OUT, + USBD_CTRL_STATE_STALLED, +} USBD_CTRL_STATE_T; + +/** + * @brief USBD Endpoint type for USB protocol + */ +typedef enum +{ + USBD_EP_TYPE_CONTROL, + USBD_EP_TYPE_ISO, + USBD_EP_TYPE_BULK, + USBD_EP_TYPE_INTERRUPT +} USBD_EP_TYPE_T; + +/**@} end of group Core_Enumerations */ + +/** @defgroup Core_Structures Structures + @{ +*/ + +/** + * @brief USB request type + */ +typedef union +{ + uint8_t byte; + + struct + { + uint8_t recipient : 5; + uint8_t type : 2; + uint8_t dir : 1; + } bit; +} USBD_REQ_TYPE_T; + +/** + * @brief USB device request data + */ +typedef struct +{ + union + { + uint8_t pack[8]; + + struct + { + USBD_REQ_TYPE_T bmRequestType; + uint8_t bRequest; + uint8_t wValue[2]; + uint8_t wIndex[2]; + uint8_t wLength[2]; + } byte; + }; +} USBD_DevReqData_T; + + +/* USB standard request callback handler */ +typedef void (*USBD_StdReqHandler_T)(void); + +/* USB request handler */ +typedef void (*USBD_ReqHandler_T)(USBD_DevReqData_T*); + +/* Ctrl Tx Status handler function define */ +typedef void (*USBD_CtrlTxStatusHandler_T)(void); + +/* Ctrl Rx Status handler function define */ +typedef void (*USBD_CtrlRxStatusHandler_T)(void); + +/* Endpoint handler */ +typedef void (*USBD_EPHandler_T)(uint8_t ep); + +/* Reset handler */ +typedef void (*USBD_ResetHandler_T)(void); + +/* Interrupt handler function define */ +typedef void (*USBD_InterruptHandler_T)(void); + +/** + * @brief Descriptor structure + */ +typedef struct +{ + const uint8_t* pDesc; + uint8_t size; +} USBD_Descriptor_T; + +/** + * @brief USB Class Request handler + */ +typedef struct +{ + USBD_StdReqHandler_T getConfigurationHandler; + USBD_StdReqHandler_T getDescriptorHandler; + USBD_StdReqHandler_T getInterfaceHandler; + USBD_StdReqHandler_T getStatusHandler; + USBD_StdReqHandler_T setAddressHandler; + + USBD_StdReqHandler_T setConfigurationHandler; + USBD_StdReqHandler_T setDescriptorHandler; + USBD_StdReqHandler_T setFeatureHandler; + USBD_StdReqHandler_T setInterfaceHandler; + USBD_StdReqHandler_T clearFeatureHandler; +} USBD_StdReqCallback_T; + +/** + * @brief Control transfer buffer + */ +typedef struct +{ + uint8_t* pBuf; /*!< Data buffer */ + uint32_t bufLen; /*!< Length of the data buffer */ + uint8_t packNum; /*!< Packet number of the data */ + uint8_t zeroPackFill; /*!< Fill a zero pack for IN transfer or not */ + uint16_t maxPackSize; /*!< Max pack size of this endpoint */ + uint32_t xferCnt; /*!< Data count of one pack on from tansfer */ +} USBD_CtrlBuf_T; + +/** + * @brief USB init parameter + */ +typedef struct +{ + USBD_Descriptor_T* pDeviceDesc; /*!< Device descriptor pointer */ + USBD_Descriptor_T* pConfigurationDesc; /*!< Configuration descriptor pointer */ + USBD_Descriptor_T* pStringDesc; /*!< String descriptor pointer */ + USBD_Descriptor_T* pQualifierDesc; /*!< Device Qualifier descriptor pointer */ + USBD_Descriptor_T* pHidReportDesc; /*!< HID report descriptor pointer */ + + + USBD_StdReqCallback_T* pStdReqCallback; + USBD_ReqHandler_T stdReqExceptionHandler; /*!< Standard request exception handler */ + USBD_ReqHandler_T classReqHandler; /*!< Class request handler */ + USBD_ReqHandler_T vendorReqHandler; /*!< vendor request handler */ + + USBD_CtrlTxStatusHandler_T txStatusHandler; /*!< Send IN status early handler */ + USBD_CtrlRxStatusHandler_T rxStatusHandler; /*!< Receive OUT status early handler */ + + USBD_EPHandler_T outEpHandler; /*!< OUT EP transfer done handler except EP0 */ + USBD_EPHandler_T inEpHandler; /*!< IN EP transfer done handler except EP0 */ + USBD_ResetHandler_T resetHandler; /*!< Reset handler */ + USBD_InterruptHandler_T intHandler; /*!< Hadler the rest of interrupt. */ +} USBD_InitParam_T; + +/** + * @brief USB infomation + */ +typedef struct +{ + USBD_CTRL_STATE_T ctrlState; + + uint8_t curFeature; + uint8_t curInterface; + uint8_t curAlternateSetting; + uint8_t curConfiguration; + uint8_t configurationNum; + + /* Setup request data buffer */ + USBD_DevReqData_T reqData; + + /* Endpoint buffer management */ + USBD_CtrlBuf_T inBuf[USB_EP_MAX_NUM]; + USBD_CtrlBuf_T outBuf[USB_EP_MAX_NUM]; + + /* Descriptor pointer */ + USBD_Descriptor_T* pDeviceDesc; + USBD_Descriptor_T* pConfigurationDesc; + USBD_Descriptor_T* pStringDesc; + USBD_Descriptor_T* pQualifierDesc; + USBD_Descriptor_T* pHidReportDesc; + + /* Setup request callback handler */ + USBD_StdReqCallback_T* pStdReqCallback; + USBD_ReqHandler_T stdReqExceptionHandler; + USBD_ReqHandler_T classReqHandler; + USBD_ReqHandler_T vendorReqHandler; + + /* Control transfer status stage handler */ + USBD_CtrlTxStatusHandler_T txStatusHandler; + USBD_CtrlRxStatusHandler_T rxStatusHandler; + + /* Endpoint transfer done handler */ + USBD_EPHandler_T outEpHandler; + USBD_EPHandler_T inEpHandler; + + USBD_ResetHandler_T resetHandler; + USBD_InterruptHandler_T intHandler; +} USBD_Info_T; + +/**@} end of group Core_Structures */ + +/** @defgroup Core_Variables Variables + @{ +*/ + + +extern USBD_Info_T g_usbDev; + +/**@} end of group Core_Variables */ + +/** @defgroup Core_Functions Functions + @{ +*/ + +/* Handler Endpoint 0 control transfer */ +void USBD_SetupProcess(void); +void USBD_CtrlInProcess(void); +void USBD_CtrlOutProcess(void); +void USBD_CtrlOutData(uint8_t* buf, uint32_t len); +void USBD_CtrlInData(uint8_t* buf, uint32_t len); + +/* Handler other Endpoint data transfer */ +void USBD_DataInProcess(USBD_EP_T ep); +void USBD_DataOutProcess(USBD_EP_T ep); +void USBD_TxData(uint8_t ep, uint8_t* buf, uint32_t len); +void USBD_RxData(uint8_t ep, uint8_t* buf, uint32_t len); + +#endif + +/**@} end of group Core_Functions */ +/**@} end of group Core */ +/**@} end of group Standard */ +/**@} end of group Core_Device */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/inc/usbd_init.h b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/inc/usbd_init.h new file mode 100644 index 0000000000..d6c5ef4180 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/inc/usbd_init.h @@ -0,0 +1,116 @@ +/*! + * @file usbd_init.h + * + * @brief USB initialization management head file + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef USBD_INIT_H_ +#define USBD_INIT_H_ + +/* Includes */ +#include "usbd_core.h" + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup Core_Device Core Device + @{ +*/ + +/** @addtogroup Standrad + @{ +*/ + +/** @addtogroup Init + @{ +*/ + +/** @defgroup Init_Macros Macros + @{ +*/ + +/**@} end of group Init_Macros */ + +/** @defgroup Init_Enumerations Enumerations + @{ +*/ + +/**@} end of group Init_Enumerations */ + +/** @defgroup Init_Structures Structures + @{ +*/ + +/** + * @brief Endpoint Configuration Info + */ +typedef struct +{ + USBD_EP_T epNum; /*!< endpoint number */ + USBD_EP_TYPE_T epType; /*!< endpoint type */ + uint8_t epKind; /** + * Which could be ENABLE or DISABLE, it is valid only for + * control and bulk Endpoint. The mean of ENABLE for them like : + * 1. Control endpoint : Only for OUT status which is zero data. + * 2. Bulk endpoint : Enable the double-buffer feature + */ + USBD_EP_STATUS_T epStatus; /*!< Endpoint status */ + uint16_t epBufAddr; /*!< buffer address for the endpoint */ + uint16_t maxPackSize; /*!< max packet size for the endpoint */ +} USBD_EPConfig_T; + +/**@} end of group Init_Structures */ + +/** @defgroup Init_Variables Variables + @{ +*/ + +/**@} end of group Init_Variables */ + +/** @defgroup Init_Functions Functions + @{ +*/ + +/* USB init */ +void USBD_Init(USBD_InitParam_T* param); +void USBD_InitParamStructInit(USBD_InitParam_T* param); + +/* power */ +void USBD_PowerOn(void); +void USBD_PowerOff(void); + +/* Endpoint init */ +void USBD_OpenOutEP(USBD_EPConfig_T* epConfig); +void USBD_OpenInEP(USBD_EPConfig_T* epConfig); + +void USBD_CloseOutEP(USBD_EP_T ep); +void USBD_CloseInEP(USBD_EP_T ep); + +#endif + +/**@} end of group Init_Functions */ +/**@} end of group Init */ +/**@} end of group Standard */ +/**@} end of groupInit_Device */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/inc/usbd_interrupt.h b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/inc/usbd_interrupt.h new file mode 100644 index 0000000000..1606ffb818 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/inc/usbd_interrupt.h @@ -0,0 +1,83 @@ +/*! + * @file usbd_interrupt.h + * + * @brief USB interrupt service routine header file + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __USBD_INTERRUPT_H_ +#define __USBD_INTERRUPT_H_ + +/* Includes */ +#include "apm32f0xx.h" + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup Core_Device Core Device + @{ +*/ + +/** @addtogroup Standrad + @{ +*/ + +/** @addtogroup Interrupt + @{ +*/ + +/** @defgroup Interrupt_Macros Macros + @{ +*/ + +/**@} end of group Interrupt_Macros */ + +/** @defgroup Interrupt_Enumerations Enumerations + @{ +*/ + +/**@} end of group Interrupt_Enumerations */ + +/** @defgroup Interrupt_Structures Structures + @{ +*/ + +/**@} end of group Interrupt_Structures */ + +/** @defgroup Interrupt_Variables Variables + @{ +*/ + +/**@} end of group Interrupt_Variables */ + +/** @defgroup Interrupt_Functions Functions + @{ +*/ + +#endif + +/**@} end of group Interrupt_Functions */ +/**@} end of group Interrupt */ +/**@} end of group Standard */ +/**@} end of group Core_Device */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/inc/usbd_stdReq.h b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/inc/usbd_stdReq.h new file mode 100644 index 0000000000..04b06e27f8 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/inc/usbd_stdReq.h @@ -0,0 +1,82 @@ +/*! + * @file usbd_stdReq.h + * + * @brief USB standard request process head file + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __USBD_STDREQ_H_ +#define __USBD_STDREQ_H_ + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup Core_Device Core Device + @{ +*/ + +/** @addtogroup Standrad + @{ +*/ + +/** @addtogroup StdReq + @{ +*/ + +/** @defgroup StdReq_Macros Macros + @{ +*/ + +/**@} end of group StdReq_Macros */ + +/** @defgroup StdReq_Enumerations Enumerations + @{ +*/ + +/**@} end of group StdReq_Enumerations */ + +/** @defgroup StdReq_Structures Structures + @{ +*/ + +/**@} end of group StdReq_Structures */ + +/** @defgroup StdReq_Variables Variables + @{ +*/ + +/**@} end of group StdReq_Variables */ + +/** @defgroup StdReq_Functions Functions + @{ +*/ + +void USBD_StandardReqeust(void); + +#endif + +/**@} end of group StdReq_Functions */ +/**@} end of group Interrupt */ +/**@} end of group Standard */ +/**@} end of group Core_Device */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/src/usbd_core.c b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/src/usbd_core.c new file mode 100644 index 0000000000..9b62af7212 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/src/usbd_core.c @@ -0,0 +1,456 @@ +/*! + * @file usbd_core.c + * + * @brief USB protocol core handler + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "usbd_core.h" +#include "usbd_stdReq.h" + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup Core_Device Core Device + @{ +*/ + +/** @addtogroup Standrad + @{ +*/ + +/** @addtogroup Core + @{ +*/ + +/** @defgroup Core_Macros Macros + @{ +*/ + +/**@} end of group Core_Macros */ + +/** @defgroup Core_Enumerations Enumerations + @{ +*/ + +/**@} end of group Core_Enumerations */ + +/** @defgroup Core_Structures Structures + @{ +*/ + +/**@} end of group Core_Structures */ + +/** @defgroup Core_Variables Variables + @{ +*/ + +/* USB information */ +USBD_Info_T g_usbDev; + +/**@} end of group Core_Variables */ + +/** @defgroup Core_Functions Functions + @{ +*/ + +/*! + * @brief Endpoint 0 Setup process + * + * @param None + * + * @retval None + */ +void USBD_SetupProcess(void) +{ + uint8_t reqType; + uint8_t dataBuf[8]; + USBD_DevReqData_T* pReqData = &g_usbDev.reqData; + uint16_t xferLen = USBD_ReadEPRxCnt(USBD_EP_0); + + if (xferLen) + { + USBD_ReadDataFromEP(USBD_EP_0, (uint8_t*)dataBuf, xferLen); + } + else + { + return; + } + + pReqData->byte.bmRequestType.byte = dataBuf[0]; + pReqData->byte.bRequest = dataBuf[1]; + pReqData->byte.wValue[0] = dataBuf[2]; + pReqData->byte.wValue[1] = dataBuf[3]; + pReqData->byte.wIndex[0] = dataBuf[4]; + pReqData->byte.wIndex[1] = dataBuf[5]; + pReqData->byte.wLength[0] = dataBuf[6]; + pReqData->byte.wLength[1] = dataBuf[7]; + + reqType = pReqData->byte.bmRequestType.bit.type; + + if (reqType == USBD_REQ_TYPE_STANDARD) + { + USBD_StandardReqeust(); + } + else if (reqType == USBD_REQ_TYPE_CLASS) + { + if (g_usbDev.classReqHandler) + { + g_usbDev.classReqHandler(pReqData); + } + } + else if (reqType == USBD_REQ_TYPE_VENDOR) + { + if (g_usbDev.vendorReqHandler) + { + g_usbDev.vendorReqHandler(pReqData); + } + } + else + { + USBD_SetEPTxRxStatus(USBD_EP_0, USBD_EP_STATUS_STALL, USBD_EP_STATUS_STALL); + } +} + + +/*! + * @brief Endpoint 0 USB Control in process + * + * @param None + * + * @retval None + */ +void USBD_CtrlInProcess(void) +{ + uint32_t tmp; + + if (g_usbDev.ctrlState == USBD_CTRL_STATE_DATA_IN) + { + if (g_usbDev.inBuf[0].packNum) + { + tmp = USB_MIN(g_usbDev.inBuf[0].bufLen, g_usbDev.inBuf[0].maxPackSize); + + USBD_WriteDataToEP(USBD_EP_0, g_usbDev.inBuf[0].pBuf, tmp); + USBD_SetEPTxCnt(USBD_EP_0, tmp); + USBD_SetEPTxRxStatus(USBD_EP_0, USBD_EP_STATUS_VALID, USBD_EP_STATUS_NAK); + + g_usbDev.inBuf[0].pBuf += tmp; + g_usbDev.inBuf[0].bufLen -= tmp; + g_usbDev.inBuf[0].packNum--; + } + else + { + if (g_usbDev.inBuf[USBD_EP_0].zeroPackFill) + { + USBD_SetEPTxCnt(USBD_EP_0, 0); + USBD_SetEPTxStatus(USBD_EP_0, USBD_EP_STATUS_VALID); + g_usbDev.inBuf[USBD_EP_0].zeroPackFill = 0; + } + else + { + if (g_usbDev.rxStatusHandler) + { + g_usbDev.rxStatusHandler(); + } + + g_usbDev.ctrlState = USBD_CTRL_STATE_WAIT_STATUS_OUT; + USBD_SetEPTxRxStatus(USBD_EP_0, USBD_EP_STATUS_NAK, USBD_EP_STATUS_VALID); + } + + } + } + else if (g_usbDev.ctrlState == USBD_CTRL_STATE_WAIT_STATUS_IN) + { + if (g_usbDev.reqData.byte.bRequest == USBD_SET_ADDRESS) + { + USBD_SetDeviceAddr(g_usbDev.reqData.byte.wValue[0]); + } + } +} + +/*! + * @brief Endpoint 0 USB Control out process + * + * @param None + * + * @retval None + */ +void USBD_CtrlOutProcess(void) +{ + uint32_t len; + + if (g_usbDev.ctrlState == USBD_CTRL_STATE_DATA_OUT) + { + if (g_usbDev.outBuf[0].packNum) + { + len = USB_MIN(g_usbDev.outBuf[0].bufLen, g_usbDev.outBuf[0].maxPackSize); + + USBD_ReadDataFromEP(USBD_EP_0, g_usbDev.outBuf[0].pBuf, len); + + g_usbDev.outBuf[0].bufLen -= len; + g_usbDev.outBuf[0].pBuf += len; + g_usbDev.outBuf[0].packNum--; + + if (g_usbDev.outBuf[0].packNum) + { + USBD_CtrlOutData(g_usbDev.outBuf[0].pBuf, g_usbDev.outBuf[0].bufLen); + } + else + { + USBD_CtrlTxStatus(); + } + } + else + { + if (g_usbDev.txStatusHandler) + { + g_usbDev.txStatusHandler(); + } + + USBD_CtrlTxStatus(); + } + } +} + +/*! + * @brief Send data or status in control in transation + * + * @param buf: Buffer pointer + * + * @param len: Buffer length + * + * @retval None + */ +void USBD_CtrlInData(uint8_t* buf, uint32_t len) +{ + uint16_t maxPackSize = g_usbDev.inBuf[0].maxPackSize; + uint16_t reqLen = *(uint16_t*)g_usbDev.reqData.byte.wLength; + + if (len) + { + if ((len < reqLen) && ((len % maxPackSize) == 0)) + { + g_usbDev.inBuf[USBD_EP_0].zeroPackFill = 1; + } + + if (len >= g_usbDev.inBuf[0].maxPackSize) + { + /* Send a packet */ + USBD_WriteDataToEP(USBD_EP_0, buf, g_usbDev.inBuf[0].maxPackSize); + USBD_SetEPTxCnt(USBD_EP_0, g_usbDev.inBuf[0].maxPackSize); + USBD_SetEPTxRxStatus(USBD_EP_0, USBD_EP_STATUS_VALID, USBD_EP_STATUS_NAK); + + /* deal with buffer */ + g_usbDev.inBuf[0].bufLen = len - g_usbDev.inBuf[0].maxPackSize; + g_usbDev.inBuf[0].pBuf = buf + g_usbDev.inBuf[0].maxPackSize; + g_usbDev.inBuf[0].packNum = (g_usbDev.inBuf[0].bufLen + (maxPackSize - 1)) / maxPackSize; + + g_usbDev.ctrlState = USBD_CTRL_STATE_DATA_IN; + } + else + { + USBD_WriteDataToEP(USBD_EP_0, buf, len); + USBD_SetEPTxCnt(USBD_EP_0, len); + USBD_SetEPTxRxStatus(USBD_EP_0, USBD_EP_STATUS_VALID, USBD_EP_STATUS_NAK); + + g_usbDev.ctrlState = g_usbDev.reqData.byte.bmRequestType.bit.dir ? \ + USBD_CTRL_STATE_DATA_IN : \ + USBD_CTRL_STATE_WAIT_STATUS_IN; + } + } + else + { + USBD_SetEPTxCnt(USBD_EP_0, 0); + USBD_SetEPTxStatus(USBD_EP_0, USBD_EP_STATUS_VALID); + + g_usbDev.ctrlState = g_usbDev.reqData.byte.bmRequestType.bit.dir ? \ + USBD_CTRL_STATE_DATA_IN : \ + USBD_CTRL_STATE_WAIT_STATUS_IN; + } +} + +/*! + * @brief Read data or status in control out transation + * + * @param buf: Buffer pointer + * + * @param len: Buffer length + * + * @retval None + */ +void USBD_CtrlOutData(uint8_t* buf, uint32_t len) +{ + uint16_t maxPackSize = g_usbDev.outBuf[USBD_EP_0].maxPackSize; + + if (len) + { + g_usbDev.outBuf[USBD_EP_0].pBuf = buf; + g_usbDev.outBuf[USBD_EP_0].bufLen = len; + g_usbDev.outBuf[USBD_EP_0].packNum = (len + (maxPackSize - 1)) / maxPackSize; + + len = USB_MIN(g_usbDev.outBuf[0].bufLen, maxPackSize); + + USBD_SetEPTxRxStatus(USBD_EP_0, USBD_EP_STATUS_NAK, USBD_EP_STATUS_VALID); + + g_usbDev.ctrlState = USBD_CTRL_STATE_DATA_OUT; + } + else + { + g_usbDev.ctrlState = USBD_CTRL_STATE_WAIT_STATUS_OUT; + } + + USBD_SetEPTxRxStatus(USBD_EP_0, USBD_EP_STATUS_NAK, USBD_EP_STATUS_VALID); +} + +/*! + * @brief USB Data in process except endpoint 0 + * + * @param ep : endpoint Number except endpoint 0 + * + * @retval None + */ +void USBD_DataInProcess(USBD_EP_T ep) +{ + uint16_t len; + + if (g_usbDev.inBuf[ep].packNum) + { + len = g_usbDev.inBuf[ep].bufLen > g_usbDev.inBuf[ep].maxPackSize ? \ + g_usbDev.inBuf[ep].maxPackSize : g_usbDev.inBuf[ep].bufLen; + + + USBD_WriteDataToEP(ep, g_usbDev.inBuf[ep].pBuf, len); + USBD_SetEPTxCnt(ep, len); + USBD_SetEPTxStatus(ep, USBD_EP_STATUS_VALID); + + g_usbDev.inBuf[ep].pBuf += len; + g_usbDev.inBuf[ep].bufLen -= len; + g_usbDev.inBuf[ep].packNum--; + } + else + { + if (g_usbDev.inEpHandler) + { + g_usbDev.inEpHandler(ep); + } + } +} + +/*! + * @brief USB Data out process except endpoint 0 + * + * @param ep : endpoint Number except endpoint 0 + * + * @retval None + */ +void USBD_DataOutProcess(USBD_EP_T ep) +{ + if (g_usbDev.outBuf[ep].packNum) + { + g_usbDev.outBuf[ep].xferCnt = USBD_ReadEPRxCnt(ep); + + if ((g_usbDev.outBuf[ep].xferCnt != 0) && (g_usbDev.outBuf[ep].pBuf != NULL)) + { + USBD_ReadDataFromEP(ep, g_usbDev.outBuf[ep].pBuf, g_usbDev.outBuf[ep].xferCnt); + + g_usbDev.outBuf[ep].bufLen -= g_usbDev.outBuf[ep].xferCnt; + g_usbDev.outBuf[ep].pBuf += g_usbDev.outBuf[ep].xferCnt; + g_usbDev.outBuf[ep].packNum--; + } + if (g_usbDev.outBuf[ep].packNum) + { + USBD_SetEPRxStatus(ep, USBD_EP_STATUS_VALID); + } + } + + if (g_usbDev.outEpHandler && !g_usbDev.outBuf[ep].packNum) + { + g_usbDev.outEpHandler(ep); + } +} + +/*! + * @brief Transfer data to host(except endpoint 0) + * + * @param ep: Endpoint number except endpoint 0 + * + * @param buf: Buffer pointer + * + * @param len: Buffer length + * + * @retval None + */ +void USBD_TxData(uint8_t ep, uint8_t* buf, uint32_t len) +{ + uint16_t maxPackSize = g_usbDev.inBuf[ep].maxPackSize; + + if (len >= maxPackSize) + { + USBD_WriteDataToEP(ep, buf, maxPackSize); + USBD_SetEPTxCnt(ep, maxPackSize); + USBD_SetEPTxStatus(ep, USBD_EP_STATUS_VALID); + + g_usbDev.inBuf[ep].pBuf = buf + maxPackSize; + g_usbDev.inBuf[ep].bufLen = len - maxPackSize; + g_usbDev.inBuf[ep].packNum = (g_usbDev.inBuf[ep].bufLen + (maxPackSize - 1)) / maxPackSize; + } + else + { + USBD_WriteDataToEP(ep, buf, len); + USBD_SetEPTxCnt(ep, len); + USBD_SetEPTxStatus(ep, USBD_EP_STATUS_VALID); + + g_usbDev.inBuf[ep].packNum = 0; + g_usbDev.inBuf[ep].bufLen = 0; + } +} + +/*! + * @brief Receive data from host(except endpoint 0) + * + * @param ep: Endpoint number except endpoint 0 + * + * @param buf: Buffer pointer + * + * @param len: Buffer length + * + * @retval None + */ +void USBD_RxData(uint8_t ep, uint8_t* buf, uint32_t len) +{ + uint16_t maxPackSize = g_usbDev.outBuf[ep].maxPackSize; + + g_usbDev.outBuf[ep].pBuf = buf; + g_usbDev.outBuf[ep].bufLen = len; + g_usbDev.outBuf[ep].packNum = (len + (maxPackSize - 1)) / maxPackSize; + + USBD_SetEPRxCnt(ep, USB_MIN(len, maxPackSize)); + + USBD_SetEPRxStatus(ep, USBD_EP_STATUS_VALID); +} + +/**@} end of group Core_Functions */ +/**@} end of group Core */ +/**@} end of group Standard */ +/**@} end of group Core_Device */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/src/usbd_init.c b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/src/usbd_init.c new file mode 100644 index 0000000000..d1548f9a15 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/src/usbd_init.c @@ -0,0 +1,288 @@ +/*! + * @file usbd_init.c + * + * @brief USB initialization management + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "usbd_init.h" +#include "usb_bsp.h" + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup Core_Device Core Device + @{ +*/ + +/** @addtogroup Standrad + @{ +*/ + +/** @addtogroup Init + @{ +*/ + +/** @defgroup Init_Macros Macros + @{ +*/ + +/**@} end of group Init_Macros */ + +/** @defgroup Init_Enumerations Enumerations + @{ +*/ + +/**@} end of group Init_Enumerations */ + +/** @defgroup Init_Structures Structures + @{ +*/ + +/**@} end of group Init_Structures */ + +/** @defgroup Init_Variables Variables + @{ +*/ + +/**@} end of group Init_Variables */ + +/** @defgroup Init_Functions Functions + @{ +*/ + +static USBD_REG_EP_TYPE_T USBD_ConvertEPType(USBD_EP_TYPE_T epType); + +/*! + * @brief USB initialization + * + * @param param: Initialization parameter + * + * @retval None + */ +void USBD_Init(USBD_InitParam_T* param) +{ + g_usbDev.pDeviceDesc = param->pDeviceDesc; + g_usbDev.pConfigurationDesc = param->pConfigurationDesc; + g_usbDev.pStringDesc = param->pStringDesc; + g_usbDev.pQualifierDesc = param->pQualifierDesc; + g_usbDev.pHidReportDesc = param->pHidReportDesc; + + g_usbDev.pStdReqCallback = param->pStdReqCallback; + g_usbDev.classReqHandler = param->classReqHandler; + g_usbDev.vendorReqHandler = param->vendorReqHandler; + g_usbDev.stdReqExceptionHandler = param->stdReqExceptionHandler; + + g_usbDev.txStatusHandler = param->txStatusHandler; + g_usbDev.rxStatusHandler = param->rxStatusHandler; + + g_usbDev.inEpHandler = param->inEpHandler; + g_usbDev.outEpHandler = param->outEpHandler; + + g_usbDev.resetHandler = param->resetHandler; + g_usbDev.intHandler = param->intHandler; + + USBD_HardWareInit(); + +#ifndef APM32F0xx_USB +#if USB_SELECT == USB1 + USBD2_Disable(); +#else + USB2_Enable(); +#endif +#endif + + USBD_PowerOn(); +} + +/*! + * @brief Init parameter in param + * + * @param param: Initialization parameter + * + * @retval None + */ +void USBD_InitParamStructInit(USBD_InitParam_T* param) +{ + param->pStdReqCallback = NULL; + param->stdReqExceptionHandler = NULL; + param->classReqHandler = NULL; + param->vendorReqHandler = NULL; + + param->txStatusHandler = NULL; + param->rxStatusHandler = NULL; + + param->outEpHandler = NULL; + param->inEpHandler = NULL; + + param->resetHandler = NULL; + param->intHandler = NULL; +} + +/*! + * @brief USB Power on + * + * @param None + * + * @retval None + */ +void USBD_PowerOn(void) +{ + USBD_ResetPowerDown(); + + USBD_SetForceReset(); + USBD_ResetForceReset(); + + USBD_DisableInterrupt(USBD_INT_ALL); + USBD_ClearIntFlag(USBD_INT_ALL); + + USBD_EnableInterrupt(USB_INT_SOURCE); +} + +/*! + * @brief USB Power off + * + * @param None + * + * @retval None + */ +void USBD_PowerOff(void) +{ + USBD_DisableInterrupt(USBD_INT_ALL); + USBD_ClearIntFlag(USBD_INT_ALL); + + /* Power down and Force USB Reset */ + USBD_SetRegCTRL(0X03); +} + + +/*! + * @brief Open OUT endpoint. + * + * @param epConfig: Point to USBD_EPConfig_T structure + * + * @retval None + */ +void USBD_OpenOutEP(USBD_EPConfig_T* epConfig) +{ + g_usbDev.outBuf[epConfig->epNum].maxPackSize = epConfig->maxPackSize; + + USBD_SetEPType(epConfig->epNum, USBD_ConvertEPType(epConfig->epType)); + + if (epConfig->epKind) + { + USBD_SetEPKind(epConfig->epNum); + } + else + { + USBD_ResetEPKind(epConfig->epNum); + } + + USBD_SetEPRxAddr(epConfig->epNum, epConfig->epBufAddr); + USBD_SetEPRxCnt(epConfig->epNum, epConfig->maxPackSize); + USBD_SetEPRxStatus(epConfig->epNum, epConfig->epStatus); +} + +/*! + * @brief Open IN endpoint. + * + * @param epConfig: Point to USBD_EPConfig_T structure + * + * @retval None + */ +void USBD_OpenInEP(USBD_EPConfig_T* epConfig) +{ + g_usbDev.inBuf[epConfig->epNum].maxPackSize = epConfig->maxPackSize; + + USBD_SetEPType(epConfig->epNum, USBD_ConvertEPType(epConfig->epType)); + + if (epConfig->epKind) + { + USBD_SetEPKind(epConfig->epNum); + } + else + { + USBD_ResetEPKind(epConfig->epNum); + } + + USBD_SetEPTxAddr(epConfig->epNum, epConfig->epBufAddr); + USBD_SetEPTxStatus(epConfig->epNum, epConfig->epStatus); +} + +/*! + * @brief Close OUT endpoint. + * + * @param ep: OUT endpoint Number + * + * @retval None + */ +void USBD_CloseOutEP(USBD_EP_T ep) +{ + g_usbDev.outBuf[ep].maxPackSize = 0; + + USBD_SetEPRxStatus(ep, USBD_EP_STATUS_DISABLE); +} + +/*! + * @brief Close IN endpoint. + * + * @param ep: IN endpoint Number + * + * @retval None + */ +void USBD_CloseInEP(USBD_EP_T ep) +{ + g_usbDev.inBuf[ep].maxPackSize = 0; + + USBD_SetEPTxStatus(ep, USBD_EP_STATUS_DISABLE); +} + +/*! + * @brief Convert endpoint Type. + * + * @param epType: endpoint type + * + * @retval Value of USBD_REG_EP_TYPE_T + */ +static USBD_REG_EP_TYPE_T USBD_ConvertEPType(USBD_EP_TYPE_T epType) +{ + switch (epType) + { + case USBD_EP_TYPE_CONTROL : + return USBD_REG_EP_TYPE_CONTROL; + case USBD_EP_TYPE_ISO : + return USBD_REG_EP_TYPE_ISO; + case USBD_EP_TYPE_BULK : + return USBD_REG_EP_TYPE_BULK; + case USBD_EP_TYPE_INTERRUPT : + return USBD_REG_EP_TYPE_INTERRUPT; + default : + return USBD_REG_EP_TYPE_CONTROL; + } +} + +/**@} end of group Init_Functions */ +/**@} end of group Init */ +/**@} end of group Standard */ +/**@} end of groupInit_Device */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/src/usbd_interrupt.c b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/src/usbd_interrupt.c new file mode 100644 index 0000000000..6a750c5b0c --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/src/usbd_interrupt.c @@ -0,0 +1,384 @@ +/*! + * @file usbd_interrupt.c + * + * @brief USB interrupt service routine + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "usbd_init.h" + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup Core_Device Core Device + @{ +*/ + +/** @addtogroup Standrad + @{ +*/ + +/** @addtogroup Interrupt + @{ +*/ + +/** @defgroup Interrupt_Macros Macros + @{ +*/ + +/**@} end of group Interrupt_Macros */ + +/** @defgroup Interrupt_Enumerations Enumerations + @{ +*/ + +/**@} end of group Interrupt_Enumerations */ + +/** @defgroup Interrupt_Structures Structures + @{ +*/ + +/**@} end of group Interrupt_Structures */ + +/** @defgroup Interrupt_Variables Variables + @{ +*/ + +/**@} end of group Interrupt_Variables */ + +/** @defgroup Interrupt_Functions Functions + @{ +*/ + +static void USBD_LowPriorityProc(void); + +static void USBD_ResetIsrHandler(void); +static void USBD_SuspendIsrHandler(void); +static void USBD_ResumeIsrHandler(void); + +/*! + * @brief USB interrupt service routine + * + * @param None + * + * @retval None + */ +#ifdef APM32F0xx_USB /*!< APM32F0xx_USB */ +void USBD_IRQHandler(void) +{ +#if (USB_INT_SOURCE & USBD_INT_CTR) + if (USBD_ReadIntFlag(USBD_INT_CTR)) + { + USBD_LowPriorityProc(); + } +#endif + +#if (USB_INT_SOURCE & USBD_INT_RST) + if (USBD_ReadIntFlag(USBD_INT_RST)) + { + USBD_ClearIntFlag(USBD_INT_RST); + USBD_ResetIsrHandler(); + } +#endif + +#if USB_INT_SOURCE & USBD_INT_PMAOU + if (USBD_ReadIntFlag(USBD_INT_PMAOU)) + { + USBD_ClearIntFlag(USBD_INT_PMAOU); + } +#endif + +#if USB_INT_SOURCE & USBD_INT_ERR + + if (USBD_ReadIntFlag(USBD_INT_ERR)) + { + USBD_ClearIntFlag(USBD_INT_ERR); + } +#endif + +#if USB_INT_SOURCE & USBD_INT_WKUP + if (USBD_ReadIntFlag(USBD_INT_WKUP)) + { + USBD_ResumeIsrHandler(); + USBD_ClearIntFlag(USBD_INT_WKUP); + } +#endif + +#if USB_INT_SOURCE & USBD_INT_SUS + if (USBD_ReadIntFlag(USBD_INT_SUS)) + { + USBD_SuspendIsrHandler(); + USBD_ClearIntFlag(USBD_INT_SUS); + } +#endif + +#if USB_INT_SOURCE & USBD_INT_SOF + if (USBD_ReadIntFlag(USBD_INT_SOF)) + { + USBD_ClearIntFlag(USBD_INT_SOF); + } +#endif + +#if USB_INT_SOURCE & USBD_INT_ESOF + if (USBD_ReadIntFlag(USBD_INT_ESOF)) + { + USBD_ClearIntFlag(USBD_INT_ESOF); + } +#endif +} +#endif + +/*! + * @brief USB low priority process + * + * @param None + * + * @retval None + */ +static void USBD_LowPriorityProc(void) +{ + USBD_EP_T ep; + + while (USBD_ReadIntFlag(USBD_INT_CTR)) + { + ep = (USBD_EP_T)USBD_ReadEP(); + + /* Endpoint 0 */ + if (ep == 0) + { + USBD_SetEPTxRxStatus(USBD_EP_0, USBD_EP_STATUS_NAK, USBD_EP_STATUS_NAK); + + /* Control in */ + if (USBD_ReadDir() == 0) + { + USBD_ResetEPTxFlag(USBD_EP_0); + USBD_CtrlInProcess(); + } + else + { + /* Setup */ + if (USBD_ReadEPSetup(USBD_EP_0) == SET) + { + USBD_ResetEPRxFlag(USBD_EP_0); + USBD_SetupProcess(); + } + /* Control out */ + else + { + USBD_ResetEPRxFlag(USBD_EP_0); + USBD_CtrlOutProcess(); + } + } + } + /* Transfer Handler Except endpoint 0 */ + else + { + if (USBD_ReadEPRxFlag(ep)) + { + USBD_ResetEPRxFlag(ep); + USBD_DataOutProcess(ep); + } + + if (USBD_ReadEPTxFlag(ep)) + { + USBD_ResetEPTxFlag(ep); + USBD_DataInProcess(ep); + } + } + } +} + + +/*! + * @brief USB Device Reset + * + * @param None + * + * @retval None + */ +static void USBD_ResetIsrHandler(void) +{ + uint8_t i; + USBD_EPConfig_T epConfig; + + g_usbDev.configurationNum = USB_CONFIGURATION_NUM; + g_usbDev.curConfiguration = 0; + g_usbDev.curInterface = 0; + g_usbDev.curAlternateSetting = 0; + g_usbDev.curFeature = 0; + g_usbDev.ctrlState = USBD_CTRL_STATE_WAIT_SETUP; + + g_usbDev.inBuf[USBD_EP_0].maxPackSize = USB_EP0_PACKET_SIZE; + g_usbDev.outBuf[USBD_EP_0].maxPackSize = USB_EP0_PACKET_SIZE; + + USBD_SetBufferTable(USB_BUFFER_TABLE_ADDR); + + /* Endpoint 0 IN */ + epConfig.epNum = USBD_EP_0; + epConfig.epType = USBD_EP_TYPE_CONTROL; + epConfig.epKind = DISABLE; + epConfig.epBufAddr = USB_EP0_TX_ADDR; + epConfig.maxPackSize = g_usbDev.inBuf[USBD_EP_0].maxPackSize; + epConfig.epStatus = USBD_EP_STATUS_NAK; + USBD_OpenInEP(&epConfig); + + /* Endpoint 0 OUT */ + epConfig.epBufAddr = USB_EP0_RX_ADDR; + epConfig.maxPackSize = g_usbDev.outBuf[USBD_EP_0].maxPackSize; + epConfig.epStatus = USBD_EP_STATUS_VALID; + USBD_OpenOutEP(&epConfig); + + if (g_usbDev.resetHandler) + { + g_usbDev.resetHandler(); + } + + for (i = 0; i < USB_EP_MAX_NUM; i++) + { + USBD_SetEpAddr((USBD_EP_T)i, i); + } + + USBD_SetDeviceAddr(0); + USBD_Enable(); +} + +/*! + * @brief USB Suspend + * + * @param None + * + * @retval None + */ +static void USBD_SuspendIsrHandler(void) +{ + uint8_t i; + uint16_t bakEP[8]; +#if USB_LOW_POWER_SWITCH + uint32_t bakPwrCR; + uint32_t tmp; +#endif + + for (i = 0; i < 8; i++) + { + bakEP[i] = (uint16_t)USBD->EP[i].EP; + } + + USBD_EnableInterrupt(USBD_INT_RST); + + USBD_SetForceReset(); + USBD_ResetForceReset(); + + while (USBD_ReadIntFlag(USBD_INT_RST) == RESET); + + for (i = 0; i < 8; i++) + { + USBD->EP[i].EP = bakEP[i]; + } + + USBD_SetForceSuspend(); + +#if USB_LOW_POWER_SWITCH + USBD_SetLowerPowerMode(); + + bakPwrCR = PMU->CTRL; + tmp = PMU->CTRL; + tmp &= (uint32_t)0xfffffffc; + tmp |= PMU_REGULATOR_LOWPOWER; + PMU->CTRL = tmp; + + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + + if (USBD_ReadIntFlag(USBD_INT_WKUP) == RESET) + { + __WFI(); + SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); + } + else + { + USBD_ClearIntFlag(USBD_INT_WKUP); + USBD_ResetForceSuspend(); + PMU->CTRL = bakPwrCR; + SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); + } +#endif +} + +/*! + * @brief Resume + * + * @param None + * + * @retval None + */ +static void USBD_ResumeIsrHandler(void) +{ +#if USB_LOW_POWER_SWITCH + USBD_ResetLowerPowerMode(); +#endif + + SystemInit(); + + USBD_SetRegCTRL(USB_INT_SOURCE); +} + +#ifndef APM32F0xx_USB +/*! + * @brief USB High priority process + * + * @param None + * + * @retval None + */ +static void USBD_HighPriorityProc(void) +{ + USBD_EP_T ep; + + while (USBD_ReadIntFlag(USBD_INT_CTR)) + { + USBD_ClearIntFlag(USBD_INT_CTR); + + ep = USBD_ReadEP(); + + if (USBD_ReadEPRxFlag(ep)) + { + USBD_ResetEPRxFlag(ep); + + g_usbDev.outEpHandler(ep); + } + + if (USBD_ReadEPTxFlag(ep)) + { + USBD_ResetEPTxFlag(ep); + + g_usbDev.inEpHandler(ep); + } + } +} + +#endif + +/**@} end of group Interrupt_Functions */ +/**@} end of group Interrupt */ +/**@} end of group Standard */ +/**@} end of group Core_Device */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/src/usbd_stdReq.c b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/src/usbd_stdReq.c new file mode 100644 index 0000000000..a9f737b538 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Core_Device/Standard/src/usbd_stdReq.c @@ -0,0 +1,371 @@ +/*! + * @file usbd_stdReq.c + * + * @brief USB standard request process + * + * @version V1.0.0 + * + * @date 2021-12-30 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be usefull and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +#include "usbd_stdReq.h" +#include "usbd_core.h" +#include "usbd_descriptor.h" + +static uint8_t USBD_StandardGetConfiguration(void); +static uint8_t USBD_StandardGetDescriptor(void); +static uint8_t USBD_StandardGetInterface(void); +static uint8_t USBD_StandardGetStatus(void); + +static uint8_t USBD_StandardSetAddress(void); +static uint8_t USBD_StandardSetConfiguration(void); +static uint8_t USBD_StandardSetDescriptor(void); +static uint8_t USBD_StandardSetFeature(void); +static uint8_t USBD_StandardSetInterface(void); + +static uint8_t USBD_StandardClearFeature(void); + + +/*! + * @brief USB request standard request + * + * @param None + * + * @retval None + */ +void USBD_StandardReqeust(void) +{ + uint8_t result = 1; + + uint8_t bRequest = g_usbDev.reqData.byte.bRequest; + + switch(bRequest) + { + case USBD_GET_CONFIGURATION: + result = USBD_StandardGetConfiguration(); + break; + + case USBD_GET_DESCRIPTOR: + result = USBD_StandardGetDescriptor(); + break; + + case USBD_GET_INTERFACE: + result = USBD_StandardGetInterface(); + break; + + case USBD_GET_STATUS: + result = USBD_StandardGetStatus(); + break; + + case USBD_SET_ADDRESS: + result = USBD_StandardSetAddress(); + break; + + case USBD_SET_CONFIGURATION: + result = USBD_StandardSetConfiguration(); + break; + + case USBD_SET_DESCRIPTOR: + result = USBD_StandardSetDescriptor(); + break; + + case USBD_SET_FEATURE: + result = USBD_StandardSetFeature(); + break; + + case USBD_SET_INTERFACE: + result = USBD_StandardSetInterface(); + + break; + + case USBD_CLEAR_FEATURE: + result = USBD_StandardClearFeature(); + break; + + default: + + break; + } + + if(!result) + { + if(g_usbDev.stdReqExceptionHandler != NULL) + { + g_usbDev.stdReqExceptionHandler(&g_usbDev.reqData); + } + else + { + USBD_SetEPTxRxStatus(USBD_EP_0, USBD_EP_STATUS_STALL, USBD_EP_STATUS_STALL); + } + } +} + +/*! + * @brief Standard request get configuration + * + * @param None + * + * @retval ERROR: 0; SUCCESS : 1 + */ +static uint8_t USBD_StandardGetConfiguration(void) +{ + uint8_t recipient = g_usbDev.reqData.byte.bmRequestType.bit.recipient; + + if(recipient == USBD_RECIPIENT_DEVICE) + { + USBD_CtrlInData(&g_usbDev.curConfiguration, 1); + + if (g_usbDev.pStdReqCallback->getConfigurationHandler) + { + g_usbDev.pStdReqCallback->getConfigurationHandler(); + } + + + return SUCCESS; + } + + return ERROR; +} + +/*! + * @brief Standard request get descriptor + * + * @param None + * + * @retval ERROR: 0; SUCCESS : 1 + */ +static uint8_t USBD_StandardGetDescriptor(void) +{ + uint8_t ret = SUCCESS; + uint32_t len = 0; + uint8_t wValue0 = g_usbDev.reqData.byte.wValue[0]; + uint8_t wValue1 = g_usbDev.reqData.byte.wValue[1]; + + if(wValue1 == USBD_DESC_DEVICE) + { + len = USB_MIN(*(uint16_t *)g_usbDev.reqData.byte.wLength, g_usbDev.pDeviceDesc->size); + USBD_CtrlInData((uint8_t *)g_usbDev.pDeviceDesc->pDesc, len); + } + else if(wValue1 == USBD_DESC_CONFIGURATION) + { + len = USB_MIN(*(uint16_t *)g_usbDev.reqData.byte.wLength, g_usbDev.pConfigurationDesc->size); + USBD_CtrlInData((uint8_t *)g_usbDev.pConfigurationDesc->pDesc, len); + } + else if(wValue1 == USBD_DESC_STRING) + { + if (wValue0 < SRTING_DESC_NUM) + { + len = USB_MIN(*(uint16_t *)g_usbDev.reqData.byte.wLength, g_usbDev.pStringDesc[wValue0].size); + USBD_CtrlInData((uint8_t *)g_usbDev.pStringDesc[wValue0].pDesc, len); + } + else + { + ret = ERROR; + } + + } + else + { + ret = ERROR; + } + + return ret; +} + +/*! + * @brief Standard request get interface + * + * @param None + * + * @retval ERROR: 0; SUCCESS : 1 + */ +static uint8_t USBD_StandardGetInterface(void) +{ + + return ERROR; +} + +/*! + * @brief Standard request get status + * + * @param None + * + * @retval ERROR: 0; SUCCESS : 1 + */ +static uint8_t USBD_StandardGetStatus(void) +{ + uint8_t ret = 1; + + + uint8_t status[2] = {0, 0}; + + if((g_usbDev.reqData.byte.bmRequestType.bit.recipient) == USBD_RECIPIENT_DEVICE) + { + if(g_usbDev.curFeature & (1 << 5)) + { + status[0] |= 0x02; + } + + if(g_usbDev.curFeature & (1 << 6)) + { + status[0] |= 0x01; + } + + USBD_CtrlInData(status, 2); + + + } + + else if((g_usbDev.reqData.byte.bmRequestType.bit.recipient) == USBD_RECIPIENT_INTERFACE) + { + USBD_CtrlInData(status, 2); + + + } + + else if((g_usbDev.reqData.byte.bmRequestType.bit.recipient) == USBD_RECIPIENT_ENDPOINT) + { + + if(g_usbDev.reqData.byte.wIndex[0] & 0x80) + { + if(USBD_ReadEPTxStatus(g_usbDev.reqData.byte.wIndex[0] & 0x0f) == USBD_EP_STATUS_STALL) + { + status[0] |= 0x01; + } + } + else + { + if(USBD_ReadEPRxStatus(g_usbDev.reqData.byte.wIndex[0] & 0x0f) == USBD_EP_STATUS_STALL) + { + status[0] |= 0x01; + } + + } + USBD_CtrlInData(status, 2); + + } + else + { + ret = 0; + } + + return ret; +} + +/*! + * @brief Standard request set address + * + * @param None + * + * @retval ERROR: 0; SUCCESS : 1 + */ +static uint8_t USBD_StandardSetAddress(void) +{ + USBD_DevReqData_T *reqData = &g_usbDev.reqData; + + if((reqData->byte.wValue[0] < 127) && (reqData->byte.wValue[1] == 0) && + (reqData->byte.bmRequestType.bit.recipient == USBD_RECIPIENT_DEVICE)) + { + USBD_CtrlInData((void *)0, 0); + + return 1; + } + + return 0; +} + +/*! + * @brief Standard request set configuration + * + * @param None + * + * @retval ERROR: 0; SUCCESS : 1 + */ +static uint8_t USBD_StandardSetConfiguration(void) +{ + USBD_DevReqData_T *reqData = &g_usbDev.reqData; + + if((reqData->byte.wValue[0] <= g_usbDev.configurationNum) && \ + (reqData->byte.bmRequestType.bit.recipient == USBD_RECIPIENT_DEVICE)) + { + g_usbDev.curConfiguration = reqData->byte.wValue[0]; + + if (g_usbDev.pStdReqCallback->setConfigurationHandler) + { + g_usbDev.pStdReqCallback->setConfigurationHandler(); + } + + USBD_CtrlInData((void *)0, 0); + + return 1; + } + + return 0; +} + +/*! + * @brief Standard request set descriptor + * + * @param None + * + * @retval 0: Failed; 1: Success + */ +static uint8_t USBD_StandardSetDescriptor(void) +{ + + return ERROR; +} + +/*! + * @brief Standard request set feature + * + * @param None + * + * @retval 0: Failed; 1: Success + */ +static uint8_t USBD_StandardSetFeature(void) +{ + uint8_t ret = 1; + + return ret; +} + +/*! + * @brief Standard request set interface + * + * @param None + * + * @retval 0: Failed; 1: Success + */ +static uint8_t USBD_StandardSetInterface(void) +{ + + return 0; +} + +/*! + * @brief Standard request clear feature + * + * @param None + * + * @retval 0: Failed; 1: Success + */ +static uint8_t USBD_StandardClearFeature(void) +{ + return 0; +} diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Driver/inc/drv_usb_device.h b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Driver/inc/drv_usb_device.h new file mode 100644 index 0000000000..a768c2b5ae --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Driver/inc/drv_usb_device.h @@ -0,0 +1,939 @@ +/*! + * @file drv_usb_device.h + * + * @brief This file contains all the prototypes,enumeration and macros for USBD peripheral + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __DRV_USB_DEVICE_H_ +#define __DRV_USB_DEVICE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(APM32F070xB) || defined(APM32F072x8) || defined(APM32F072xB) +#define APM32F0xx_USB +#endif + +/* Includes */ +#ifdef APM32F0xx_USB +#include "apm32f0xx.h" +#include "apm32f0xx_pmu.h" +#include "apm32f0xx_eint.h" +#include "apm32f0xx_gpio.h" +#include "apm32f0xx_rcm.h" +#include "apm32f0xx_misc.h" +#include "usb_config.h" +#endif + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup USBD_Driver + @{ +*/ + +/** @defgroup Driver_Macros Macros + @{ +*/ + +/* USBD packet memory area base address */ +#define USBD_PMA_ADDR (0x40006000L) + +/* Endpoint register mask value default */ +#define USBD_EP_MASK_DEFAULT (USBD_EP_BIT_CTFR | USBD_EP_BIT_SETUP | USBD_EP_BIT_TYPE | USBD_EP_BIT_KIND | USBD_EP_BIT_CTFT |USBD_EP_BIT_ADDR) + +/** + * @brief USBD interrupt source + */ +#define USBD_INT_ESOF 0X100 +#define USBD_INT_SOF 0X200 +#define USBD_INT_RST 0X400 +#define USBD_INT_SUS 0x800 +#define USBD_INT_WKUP 0X1000 +#define USBD_INT_ERR 0X2000 +#define USBD_INT_PMAOU 0X4000 +#define USBD_INT_CTR 0X8000 +#define USBD_INT_ALL 0XFF00 + +/**@} end of group Driver_Macros */ + +/** @defgroup Driver_Macros_Functions Macros Functions + @{ +*/ + +/*! + * @brief Set CTRL register + * + * @param val: Register value + * + * @retval None + * + */ +#define USBD_SetRegCTRL(val) (USBD->CTRL = val) + +/*! + * @brief Set INTSTS register + * + * @param val: Register value + * + * @retval None + */ +#define USBD_SetRegINTSTS(val) (USBD->INTSTS = val) + +/*! + * @brief Set force reset + * + * @param None + * + * @retval None + */ +#define USBD_SetForceReset() (USBD->CTRL_B.FORRST = BIT_SET) + +/*! + * @brief Reset force reset + * + * @param None + * + * @retval None + */ +#define USBD_ResetForceReset() (USBD->CTRL_B.FORRST = BIT_RESET) + +/*! + * @brief Set power down + * + * @param None + * + * @retval None + */ +#define USBD_SetPowerDown() (USBD->CTRL_B.PWRDOWN = BIT_SET) + +/*! + * @brief Reset power down + * + * @param None + * + * @retval None + */ +#define USBD_ResetPowerDown() (USBD->CTRL_B.PWRDOWN = BIT_RESET) + +/*! + * @brief Set low power mode + * + * @param None + * + * @retval None + */ +#define USBD_SetLowerPowerMode() (USBD->CTRL_B.LPWREN = BIT_SET) + +/*! + * @brief Ret low power mode + * + * @param None + * + * @retval None + */ +#define USBD_ResetLowerPowerMode() (USBD->CTRL_B.LPWREN = BIT_RESET) + +/*! + * @brief Set force suspend + * + * @param None + * + * @retval None + */ +#define USBD_SetForceSuspend() (USBD->CTRL_B.FORSUS = BIT_SET) + +/*! + * @brief Reset force suspend + * + * @param None + * + * @retval None + */ +#define USBD_ResetForceSuspend() (USBD->CTRL_B.FORSUS = BIT_RESET) + +/*! + * @brief Read force suspend status + * + * @param None + * + * @retval None + */ +#define USBD_ReadForceSuspend() (USBD->CTRL_B.FORSUS) + +/*! + * @brief Set resume + * + * @param None + * + * @retval None + */ +#define USBD_SetResume() (USBD->CTRL_B.WUPREQ = BIT_SET) + +/*! + * @brief Reset resume + * + * @param None + * + * @retval None + */ +#define USBD_ResetResume() (USBD->CTRL_B.WUPREQ = BIT_RESET) + +/*! + * @brief Enable interrupt + * + * @param int: Interrupt source + * + * @retval None + */ +#define USBD_EnableInterrupt(int) (USBD->CTRL |= int) + +/*! + * @brief Disable interrupt + * + * @param int: Interrupt source + * + * @retval None + */ +#define USBD_DisableInterrupt(int) (USBD->CTRL &= (uint32_t)~int) + +/*! + * @brief Read the specified interrupt flag status + * + * @param int: Interrupt source + * + * @retval Flag status.0 or not 0 + */ +#define USBD_ReadIntFlag(int) (USBD->INTSTS & int) + +/*! + * @brief Clear the specified interrupt flag status + * + * @param int: Interrupt source + * + * @retval None + */ +#define USBD_ClearIntFlag(int) (USBD->INTSTS &= (uint32_t)~int) + +/*! + * @brief Read DOT field value in INTSTS rigister + * + * @param None + * + * @retval DOT field value + */ +#define USBD_ReadDir() (USBD->INTSTS_B.DOT) + +/*! + * @brief Read EPID field value in INTSTS rigister + * + * @param None + * + * @retval EPIDfield value + */ +#define USBD_ReadEP() ((USBD_EP_T)(USBD->INTSTS_B.EPID)) + +/*! + * @brief Read EP type + * + * @param ep: EP number + * + * @retval EP type + */ +#define USBD_ReadEPType(ep) (USBD->EP[ep].EP_B.TYPE) + +/*! + * @brief Read EP Tx status + * + * @param ep: EP number + * + * @retval EP Tx status + */ +#define USBD_ReadEPTxStatus(ep) ((USBD_EP_STATUS_T)(USBD->EP[ep].EP_B.TXSTS)) + +/*! + * @brief Read EP Rx status + * + * @param ep: EP number + * + * @retval EP Rx status + */ +#define USBD_ReadEPRxStatus(ep) ((USBD_EP_STATUS_T)(USBD->EP[ep].EP_B.RXSTS)) + +/*! + * @brief Read SETUP field value in EP register + * + * @param ep: EP number + * + * @retval SETUP field value + */ +#define USBD_ReadEPSetup(ep) (USBD->EP[ep].EP_B.SETUP) + +/*! + * @brief Set buffer table value + * + * @param tab: Buffer table value + * + * @retval None + */ +#define USBD_SetBufferTable(tab) (USBD->BUFFTB_B.BUFFTB = tab) + +/*! + * @brief Set device address + * + * @param addr: Device address + * + * @retval None + */ +#define USBD_SetDeviceAddr(addr) (USBD->ADDR_B.ADDR = addr) + +/*! + * @brief Read CTFR field value in EP register + * + * @param ep: Endpoint number + * + * @retval CTFR field value + */ +#define USBD_ReadEPRxFlag(ep) (USBD->EP[ep].EP_B.CTFR) + +/*! + * @brief Read CTFT field value in EP register + * + * @param ep: Endpoint number + * + * @retval CTFT field value + */ +#define USBD_ReadEPTxFlag(ep) (USBD->EP[ep].EP_B.CTFT) + +/*! + * @brief Enable USBD peripheral + * + * @param None + * + * @retval None + */ +#define USBD_Enable() (USBD->ADDR_B.USBDEN = BIT_SET) + +/*! + * @brief Disable USBD peripheral + * + * @param None + * + * @retval None + */ +#define USBD_Disable() (USBD->ADDR_B.USBDEN = BIT_RESET) + +/*! + * @brief Enable USBD2 peripheral + * + * @param None + * + * @retval None + */ +#define USBD2_Enable() (USBD->SWITCH = BIT_SET) + +/*! + * @brief Disable USBD2 peripheral + * + * @param None + * + * @retval None + */ +#define USBD2_Disable() (USBD->SWITCH = BIT_RESET) + +/*! + * @brief Read RXDPSTS field value in FRANUM register + * + * @param None + * + * @retval RXDPSTS field value + */ +#define USBD_ReadRDPS() (USBD->FRANUM_B.RXDPSTS) + +/*! + * @brief Read RXDMSTS field value in FRANUM register + * + * @param None + * + * @retval RXDMSTS field value + */ +#define USBD_ReadRDMS() (USBD->FRANUM_B.RXDMSTS) + +/*! + * @brief Read LOCK field value in FRANUM register + * + * @param None + * + * @retval LOCK field value + */ +#define USBD_ReadLOCK() (USBD->FRANUM_B.LOCK) + +/*! + * @brief Read LSOFNUM field value in FRANUM register + * + * @param None + * + * @retval LSOFNUM field value + */ +#define USBD_ReadLSOF() (USBD->FRANUM_B.LSOFNUM) + +/*! + * @brief Read FRANUM field value in FRANUM register + * + * @param None + * + * @retval FRANUM field value + */ +#define USBD_ReadFRANUM() (USBD->FRANUM_B.FRANUM) + +#ifdef APM32F0xx_USB +/*! + * @brief Read EP Tx address pointer + * + * @param ep: EP number + * + * @retval EP Tx address pointer + */ +#define USBD_ReadEPTxAddrPointer(ep) (uint16_t *)((USBD->BUFFTB + ep * 8) + USBD_PMA_ADDR) + +/*! + * @brief Read EP Tx count pointer + * + * @param ep: EP number + * + * @retval EP Tx count pointer + */ +#define USBD_ReadEPTxCntPointer(ep) (uint16_t *)((USBD->BUFFTB + ep * 8 + 2) + USBD_PMA_ADDR) + +/*! + * @brief Read EP Rx address pointer + * + * @param ep: EP number + * + * @retval EP Rx address pointer + */ +#define USBD_ReadEPRxAddrPointer(ep) (uint16_t *)((USBD->BUFFTB + ep * 8 + 4) + USBD_PMA_ADDR) + +/*! + * @brief Read EP Rx count pointer + * + * @param ep: EP number + * + * @retval EP Rx count pointer + */ +#define USBD_ReadEPRxCntPointer(ep) (uint16_t *)((USBD->BUFFTB + ep * 8 + 6) + USBD_PMA_ADDR) + +/*! + * @brief Set EP Tx addr + * + * @param ep: EP number + * + * @param addr: Tx addr + * + * @retval None + */ +#define USBD_SetEPTxAddr(ep, addr) (*USBD_ReadEPTxAddrPointer(ep) = (addr >> 1) << 1) + +/*! + * @brief Set EP Rx addr + * + * @param ep: EP number + * + * @param addr: Rx addr + * + * @retval None + */ +#define USBD_SetEPRxAddr(ep, addr) (*USBD_ReadEPRxAddrPointer(ep) = (addr >> 1) << 1) + +/*! + * @brief Read EP Tx addr + * + * @param ep: EP number + * + * @retval EP Tx addr + */ +#define USBD_ReadEPTxAddr(ep) ((uint16_t)*USBD_ReadEPTxAddrPointer(ep)) + +/*! + * @brief Read EP Rx addr + * + * @param ep: EP number + * + * @retval EP Rx addr + */ +#define USBD_ReadEPRxAddr(ep) ((uint16_t)*USBD_ReadEPRxAddrPointer(ep)) + +/*! + * @brief Read EP Tx Buffer Pointer + * + * @param ep: EP number + * + * @retval EP Tx Buffer Pointer + */ +#define USBD_ReadEPTxBufferPointer(ep) (uint16_t *)(USBD_ReadEPTxAddr(ep) + USBD_PMA_ADDR) + +/*! + * @brief Read EP Rx Buffer Pointer + * + * @param ep: EP number + * + * @retval EP Rx Buffer Pointer + */ +#define USBD_ReadEPRxBufferPointer(ep) (uint16_t *)(USBD_ReadEPRxAddr(ep) + USBD_PMA_ADDR) + +/*! + * @brief Set EP Tx Count + * + * @param ep: EP number + * + * @param cnt: Tx count + * + * @retval None + */ +#define USBD_SetEPTxCnt(ep, cnt) (*USBD_ReadEPTxCntPointer(ep) = cnt) + +/*! + * @brief Read EP Tx count + * + * @param ep: EP number + * + * @retval EP Tx count + */ +#define USBD_ReadEPTxCnt(ep) ((uint16_t)*USBD_ReadEPTxCntPointer(ep) & 0x3ff) + +/*! + * @brief Read EP Rx count + * + * @param ep: EP number + * + * @retval EP Rx count + */ +#define USBD_ReadEPRxCnt(ep) ((uint16_t)*USBD_ReadEPRxCntPointer(ep) & 0x3ff) + +/*! + * @brief Set BESL Value + * + * @param val: 4-bits BESL Value to be set + * + * @retval None + */ +#define USBD_SetBESL(val) (USBD->LPMCTRLSTS_B.BESL = val) + +/*! + * @brief Set bRemoteWakew Value + * + * @param val: 1-bit bRemoteWakew Value to be set + * + * @retval None + */ +#define USBD_SetRemoteWakeVal(val) (USBD->LPMCTRLSTS_B.REMWAKE = val) + +/*! + * @brief Enable LPM ACK + * + * @param None + * + * @retval None + */ +#define USBD_EnableAckLPM() (USBD->LPMCTRLSTS_B.LPMACKEN = 1) + +/*! + * @brief Disable LPM ACK + * + * @param None + * + * @retval None + */ +#define USBD_DisableAckLPM() (USBD->LPMCTRLSTS_B.LPMACKEN = 0) + +/*! + * @brief Disable LPM + * + * @param None + * + * @retval None + */ +#define USBD_EnableLPM() (USBD->LPMCTRLSTS_B.LPMEN = 1) + +/*! + * @brief Disable LPM + * + * @param None + * + * @retval None + */ +#define USBD_DisableLPM() (USBD->LPMCTRLSTS_B.LPMEN = 0) + +/*! + * @brief Enable Pull-up of DP line + * + * @param None + * + * @retval None + */ +#define USBD_EnablePullUpDP() (USBD->BCD_B.DPPUCTRL = 1) + +/*! + * @brief Disable Pull-up of DP line + * + * @param None + * + * @retval None + */ +#define USBD_DisablePullUpDP() (USBD->BCD_B.DPPUCTRL = 0) + +/*! + * @brief Read DM Pull-up Detection Status Flag + * + * @param None + * + * @retval DM Pull-up Detection Status Flag + */ +#define USBD_DMPullUpStatus() (USBD->BCD_B.DMPUDFLG) + +/*! + * @brief Read Secondary Detection Status Flag + * + * @param None + * + * @retval Secondary Detection Status Flag + */ +#define USBD_SDStatus() (USBD->BCD_B.SDFLG) + +/*! + * @brief Read Primary Detection Status Flag + * + * @param None + * + * @retval Primary Detection Status Flag + */ +#define USBD_PDStatus() (USBD->BCD_B.PDFLG) + +/*! + * @brief Read Data Contact Detection Status Flag + * + * @param None + * + * @retval Data Contact Detection Status Flag + */ +#define USBD_DCDStatus() (USBD->BCD_B.DCDFLG) + +/*! + * @brief Enable Secondary Detection Mode + * + * @param None + * + * @retval None + */ +#define USBD_EnableSDMode() (USBD->BCD_B.SDEN = 1) + +/*! + * @brief Disable Secondary Detection Mode + * + * @param None + * + * @retval None + */ +#define USBD_DisableSDMode() (USBD->BCD_B.SDEN = 0) + +/*! + * @brief Enable Primary Detection Mode + * + * @param None + * + * @retval None + */ +#define USBD_EnablePDMode() (USBD->BCD_B.PDEN = 1) + +/*! + * @brief Disable Primary Detection Mode + * + * @param None + * + * @retval None + */ +#define USBD_DisablePDMode() (USBD->BCD_B.PDEN = 0) + +/*! + * @brief Enable Data Contact Detection Mode + * + * @param None + * + * @retval None + */ +#define USBD_EnableDCDMode() (USBD->BCD_B.DCDEN = 1) + +/*! + * @brief Disable Data Contact Detection Mode + * + * @param None + * + * @retval None + */ +#define USBD_DisableDCDMode() (USBD->BCD_B.DCDEN = 0) + +/*! + * @brief Enable Battery Charging Detector + * + * @param None + * + * @retval None + */ +#define USBD_EnableBCD() (USBD->BCD_B.BCDEN = 1) + +/*! + * @brief Disable Battery Charging Detector + * + * @param None + * + * @retval None + */ +#define USBD_DisableBCD() (USBD->BCD_B.BCDEN = 0) + +#else //!< APM32F10x_USB +/*! + * @brief Read EP Tx address pointer + * + * @param ep: EP number + * + * @retval EP Tx address pointer + */ +#define USBD_ReadEPTxAddrPointer(ep) (uint16_t *)((USBD->BUFFTB + ep * 8) * 2 + USBD_PMA_ADDR) + +/*! + * @brief Read EP Tx count pointer + * + * @param ep: EP number + * + * @retval EP Tx count pointer + */ +#define USBD_ReadEPTxCntPointer(ep) (uint16_t *)((USBD->BUFFTB + ep * 8 + 2) * 2 + USBD_PMA_ADDR) + +/*! + * @brief Read EP Rx address pointer + * + * @param ep: EP number + * + * @retval EP Rx address pointer + */ +#define USBD_ReadEPRxAddrPointer(ep) (uint16_t *)((USBD->BUFFTB + ep * 8 + 4) * 2 + USBD_PMA_ADDR) + +/*! + * @brief Read EP Rx count pointer + * + * @param ep: EP number + * + * @retval EP Rx count pointer + */ +#define USBD_ReadEPRxCntPointer(ep) (uint16_t *)((USBD->BUFFTB + ep * 8 + 6) * 2 + USBD_PMA_ADDR) + +/*! + * @brief Set EP Tx addr + * + * @param ep: EP number + * + * @param addr: Tx addr + * + * @retval None + */ +#define USBD_SetEPTxAddr(ep, addr) (*USBD_ReadEPTxAddrPointer(ep) = (addr >> 1) << 1) + +/*! + * @brief Set EP Rx addr + * + * @param ep: EP number + * + * @param addr: Rx addr + * + * @retval None + */ +#define USBD_SetEPRxAddr(ep, addr) (*USBD_ReadEPRxAddrPointer(ep) = (addr >> 1) << 1) + +/*! + * @brief Read EP Tx addr + * + * @param ep: EP number + * + * @retval EP Tx addr + */ +#define USBD_ReadEPTxAddr(ep) ((uint16_t)*USBD_ReadEPTxAddrPointer(ep)) + +/*! + * @brief Read EP Rx addr + * + * @param ep: EP number + * + * @retval EP Rx addr + */ +#define USBD_ReadEPRxAddr(ep) ((uint16_t)*USBD_ReadEPRxAddrPointer(ep)) + +/*! + * @brief Read EP Tx Buffer Pointer + * + * @param ep: EP number + * + * @retval EP Tx Buffer Pointer + */ +#define USBD_ReadEPTxBufferPointer(ep) (uint32_t *)(((uint32_t)USBD_ReadEPTxAddr(ep) << 1) + USBD_PMA_ADDR) + +/*! + * @brief Read EP Rx Buffer Pointer + * + * @param ep: EP number + * + * @retval EP Rx Buffer Pointer + */ +#define USBD_ReadEPRxBufferPointer(ep) (uint32_t *)(((uint32_t)USBD_ReadEPRxAddr(ep) << 1) + USBD_PMA_ADDR) + +/*! + * @brief Set EP Tx Count + * + * @param ep: EP number + * + * @param cnt: Tx count + * + * @retval None + */ +#define USBD_SetEPTxCnt(ep, cnt) (*USBD_ReadEPTxCntPointer(ep) = cnt) + +/*! + * @brief Read EP Tx count + * + * @param ep: EP number + * + * @retval EP Tx count + */ +#define USBD_ReadEPTxCnt(ep) ((uint16_t)*USBD_ReadEPTxCntPointer(ep) & 0x3ff) + +/*! + * @brief Read EP Rx count + * + * @param ep: EP number + * + * @retval EP Rx count + */ +#define USBD_ReadEPRxCnt(ep) ((uint16_t)*USBD_ReadEPRxCntPointer(ep) & 0x3ff) + +#endif + +/**@} end of group Driver_Macros_Functions */ + +/** @defgroup Driver_Enumerations Enumerations + @{ +*/ + +/** + * @brief USBD Endpoint register bit definition + */ +typedef enum +{ + USBD_EP_BIT_ADDR = (uint32_t)(BIT0 | BIT1 | BIT2 | BIT3), + USBD_EP_BIT_TXSTS = (uint32_t)(BIT4 | BIT5), + USBD_EP_BIT_TXDTOG = (uint32_t)(BIT6), + USBD_EP_BIT_CTFT = (uint32_t)(BIT7), + USBD_EP_BIT_KIND = (uint32_t)(BIT8), + USBD_EP_BIT_TYPE = (uint32_t)(BIT9 | BIT10), + USBD_EP_BIT_SETUP = (uint32_t)(BIT11), + USBD_EP_BIT_RXSTS = (uint32_t)(BIT12 | BIT13), + USBD_EP_BIT_RXDTOG = (uint32_t)(BIT14), + USBD_EP_BIT_CTFR = (uint32_t)(BIT15) +} USBD_EP_BIT_T; + +/** + * @brief Endpoint id + */ +typedef enum +{ + USBD_EP_0, + USBD_EP_1, + USBD_EP_2, + USBD_EP_3, + USBD_EP_4, + USBD_EP_5, + USBD_EP_6, + USBD_EP_7, +} USBD_EP_T; + +/** + * @brief Endpoint status + */ +typedef enum +{ + USBD_EP_STATUS_DISABLE = ((uint32_t)0), + USBD_EP_STATUS_STALL = ((uint32_t)1), + USBD_EP_STATUS_NAK = ((uint32_t)2), + USBD_EP_STATUS_VALID = ((uint32_t)3), +} USBD_EP_STATUS_T; + +/** + * @brief USBD Endpoint type for register + */ +typedef enum +{ + USBD_REG_EP_TYPE_BULK, + USBD_REG_EP_TYPE_CONTROL, + USBD_REG_EP_TYPE_ISO, + USBD_REG_EP_TYPE_INTERRUPT +} USBD_REG_EP_TYPE_T; + +/**@} end of group Driver_Enumerations */ + +/** @defgroup Driver_Functions Functions + @{ +*/ + +void USBD_SetEPType(uint8_t ep, USBD_REG_EP_TYPE_T type); + +void USBD_SetEPKind(uint8_t ep); +void USBD_ResetEPKind(uint8_t ep); + +void USBD_ResetEPRxFlag(uint8_t ep); +void USBD_ResetEPTxFlag(uint8_t ep); + +void USBD_ToggleTx(uint8_t ep); +void USBD_ToggleRx(uint8_t ep); +void USBD_ResetTxToggle(uint8_t ep); +void USBD_ResetRxToggle(uint8_t ep); + +void USBD_SetEpAddr(uint8_t ep, uint8_t addr); + +void USBD_SetEPTxStatus(uint8_t ep, USBD_EP_STATUS_T status); +void USBD_SetEPRxStatus(uint8_t ep, USBD_EP_STATUS_T status); +void USBD_SetEPTxRxStatus(uint8_t ep, USBD_EP_STATUS_T txStatus, USBD_EP_STATUS_T rxStatus); + +void USBD_SetEPRxCnt(uint8_t ep, uint32_t cnt); + +void USBD_WriteDataToEP(uint8_t ep, uint8_t* wBuf, uint32_t wLen); +void USBD_ReadDataFromEP(uint8_t ep, uint8_t* rBuf, uint32_t rLen); + +#ifdef __cplusplus +} +#endif + +#endif /* __DRV_USB_DEVICE_H */ + +/**@} end of group Driver_Functions */ +/**@} end of group USBD_Driver */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Driver/src/drv_usb_device.c b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Driver/src/drv_usb_device.c new file mode 100644 index 0000000000..6d84210ae7 --- /dev/null +++ b/bsp/apm32/libraries/APM32F0xx_Library/USB_Device_Lib/Driver/src/drv_usb_device.c @@ -0,0 +1,432 @@ +/*! + * @file drv_usb_device.c + * + * @brief This file contains all the functions for the USBD peripheral + * + * @version V1.0.1 + * + * @date 2022-09-20 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Includes */ +#include "drv_usb_device.h" + +/** @addtogroup USB_Driver_Library USB Driver Library + @{ +*/ + +/** @addtogroup USBD_Driver + @{ +*/ + +/** @defgroup Driver_Macros Macros + @{ +*/ + +/**@} end of group Driver_Macros */ + +/** @defgroup Driver_Enumerations Enumerations + @{ +*/ + +/**@} end of group Driver_Enumerations */ + +/** @defgroup Driver_Functions Functions + @{ +*/ + +/*! + * @brief Set Endpoint type + * + * @param ep: Endpoint number + * + * @param type: Endpoint type + * + * @retval None + */ +void USBD_SetEPType(uint8_t ep, USBD_REG_EP_TYPE_T type) +{ + __IOM uint32_t reg; + + reg = USBD->EP[ep].EP; + + reg &= (uint32_t)(USBD_EP_MASK_DEFAULT); + reg &= ~USBD_EP_BIT_TYPE; + reg |= type << 9; + + USBD->EP[ep].EP = reg; +} + +/*! + * @brief Set EP kind + * + * @param ep: Endpoint number + * + * @retval None + */ +void USBD_SetEPKind(uint8_t ep) +{ + __IOM uint32_t reg; + + reg = USBD->EP[ep].EP; + + reg &= (uint32_t)(USBD_EP_MASK_DEFAULT); + reg |= USBD_EP_BIT_KIND; + + USBD->EP[ep].EP = reg; +} + +/*! + * @brief Reset EP kind + * + * @param ep: Endpoint number + * + * @retval None + */ +void USBD_ResetEPKind(uint8_t ep) +{ + __IOM uint32_t reg; + + reg = USBD->EP[ep].EP; + + reg &= (uint32_t)(USBD_EP_MASK_DEFAULT); + reg &= ~USBD_EP_BIT_KIND; + + USBD->EP[ep].EP = reg; +} + + +/*! + * @brief Reset EP CTFR bit + * + * @param ep: Endpoint number + * + * @retval None + */ +void USBD_ResetEPRxFlag(uint8_t ep) +{ + __IOM uint32_t reg; + + reg = USBD->EP[ep].EP; + + reg &= (uint32_t)(USBD_EP_MASK_DEFAULT); + reg &= ~USBD_EP_BIT_CTFR; + + USBD->EP[ep].EP = reg; +} + +/*! + * @brief Reset EP CTFT bit + * + * @param ep: Endpoint number + * + * @retval None + */ +void USBD_ResetEPTxFlag(uint8_t ep) +{ + __IOM uint32_t reg; + + reg = USBD->EP[ep].EP; + + reg &= (uint32_t)(USBD_EP_MASK_DEFAULT); + reg &= ~USBD_EP_BIT_CTFT; + + USBD->EP[ep].EP = reg; +} + +/*! + * @brief Toggle Tx DTOG + * + * @param ep: Endpoint number + * + * @retval None + */ +void USBD_ToggleTx(uint8_t ep) +{ + __IOM uint32_t reg; + + reg = USBD->EP[ep].EP; + + reg &= (uint32_t)(USBD_EP_MASK_DEFAULT); + reg |= USBD_EP_BIT_TXDTOG; + + USBD->EP[ep].EP = reg; +} + +/*! + * @brief Toggle Rx DTOG + * + * @param ep: Endpoint number + * + * @retval None + */ +void USBD_ToggleRx(uint8_t ep) +{ + __IOM uint32_t reg; + + reg = USBD->EP[ep].EP; + + reg &= (uint32_t)(USBD_EP_MASK_DEFAULT); + reg |= USBD_EP_BIT_RXDTOG; + + USBD->EP[ep].EP = reg; +} + +/*! + * @brief Reset Toggle Tx DTOG + * + * @param ep: Endpoint number + * + * @retval None + */ +void USBD_ResetTxToggle(uint8_t ep) +{ + if (USBD->EP[ep].EP_B.TXDTOG) + { + USBD_ToggleTx(ep); + } +} + +/*! + * @brief Reset Toggle Rx DTOG + * + * @param ep: Endpoint number + * + * @retval None + */ +void USBD_ResetRxToggle(uint8_t ep) +{ + if (USBD->EP[ep].EP_B.RXDTOG) + { + USBD_ToggleRx(ep); + } +} + +/*! + * @brief Set EP address + * + * @param ep: Endpoint number + * + * @param addr: Address + * + * @retval None + */ +void USBD_SetEpAddr(uint8_t ep, uint8_t addr) +{ + __IOM uint32_t reg; + + reg = USBD->EP[ep].EP; + + reg &= (uint32_t)(USBD_EP_MASK_DEFAULT); + reg &= ~USBD_EP_BIT_ADDR; + reg |= addr; + + USBD->EP[ep].EP = reg; +} + +/*! + * @brief Set EP Tx status + * + * @param ep: Endpoint number + * + * @param status: status + * + * @retval None + */ +void USBD_SetEPTxStatus(uint8_t ep, USBD_EP_STATUS_T status) +{ + __IOM uint32_t reg; + + status <<= 4; + + reg = USBD->EP[ep].EP; + + reg &= (uint32_t)(USBD_EP_MASK_DEFAULT | USBD_EP_BIT_TXSTS); + reg ^= ((uint32_t)status & (uint32_t)USBD_EP_BIT_TXSTS); + + USBD->EP[ep].EP = reg; +} + +/*! + * @brief Set EP Rx status + * + * @param ep: Endpoint number + * + * @param status: status + * + * @retval None + */ +void USBD_SetEPRxStatus(uint8_t ep, USBD_EP_STATUS_T status) +{ + __IOM uint32_t reg; + uint32_t tmp; + + tmp = status << 12; + + reg = USBD->EP[ep].EP; + + reg &= (uint32_t)(USBD_EP_MASK_DEFAULT | USBD_EP_BIT_RXSTS); + reg ^= (tmp & USBD_EP_BIT_RXSTS); + + USBD->EP[ep].EP = reg; +} + + +/*! + * @brief Set EP Tx and Rx status + * + * @param ep: Endpoint number + * + * @param status: status + * + * @retval None + */ +void USBD_SetEPTxRxStatus(uint8_t ep, USBD_EP_STATUS_T txStatus, USBD_EP_STATUS_T rxStatus) +{ + __IOM uint32_t reg; + uint32_t tmp; + + reg = USBD->EP[ep].EP; + + reg &= (uint32_t)(USBD_EP_MASK_DEFAULT | USBD_EP_BIT_RXSTS | USBD_EP_BIT_TXSTS); + + tmp = rxStatus << 12; + reg ^= (tmp & USBD_EP_BIT_RXSTS); + + tmp = txStatus << 4; + reg ^= (tmp & USBD_EP_BIT_TXSTS); + + USBD->EP[ep].EP = reg; +} + +/*! + * @brief Set EP Rx Count + * + * @param ep: Endpoint number + * + * @param cnt: Rx count + * + * @retval None + */ +void USBD_SetEPRxCnt(uint8_t ep, uint32_t cnt) +{ + __IOM uint16_t* p; + __IOM uint16_t block = 0; + + p = USBD_ReadEPRxCntPointer(ep); + + if (cnt > 62) + { + block = cnt >> 5; + + if (!(cnt & 0x1f)) + { + block -= 1; + } + + *p = (block << 10) | 0x8000; + } + else + { + block = cnt >> 1; + + if (cnt & 0x01) + { + block += 1; + } + + *p = (block << 10); + } +} + +/*! + * @brief Write a buffer of data to a selected endpoint + * + * @param ep: Endpoint number + * + * @retval wBuf: The pointer to the buffer of data to be written to the endpoint + * + * @param wLen: Number of data to be written (in bytes) + * + * @retval None + */ +void USBD_WriteDataToEP(uint8_t ep, uint8_t* wBuf, uint32_t wLen) +{ + uint32_t i; +#ifdef APM32F0xx_USB + uint16_t* epAddr; + uint16_t tmp; +#else + uint32_t* epAddr; + uint32_t tmp; +#endif + + wLen = (wLen + 1) >> 1; + + epAddr = USBD_ReadEPTxBufferPointer(ep); + + for (i = 0; i < wLen; i++) + { + tmp = *wBuf++; + tmp = ((*wBuf++) << 8) | tmp; + + *epAddr++ = tmp; + } +} + +/*! + * @brief Read a buffer of data to a selected endpoint + * + * @param ep: Endpoint number + * + * @retval wBuf: The pointer to the buffer of data to be read to the endpoint + * + * @param wLen: Number of data to be read (in bytes) + * + * @retval None + */ +void USBD_ReadDataFromEP(uint8_t ep, uint8_t* rBuf, uint32_t rLen) +{ +#ifdef APM32F0xx_USB + uint16_t* epAddr; +#else + uint32_t* epAddr; +#endif + uint32_t i, tmp, cnt; + + cnt = rLen >> 1; + + epAddr = USBD_ReadEPRxBufferPointer(ep); + + for (i = 0; i < cnt; i++) + { + tmp = *epAddr++; + *rBuf++ = tmp & 0xFF; + *rBuf++ = (tmp >> 8) & 0xFF; + } + + if (rLen & 1) + { + tmp = *epAddr; + *rBuf = tmp & 0xFF; + } +} + +/**@} end of group Driver_Functions */ +/**@} end of group USBD_Driver */ +/**@} end of group USB_Driver_Library */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_ETH_Driver/inc/apm32f10x_eth.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_ETH_Driver/inc/apm32f10x_eth.h new file mode 100644 index 0000000000..4694e2ffcc --- /dev/null +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_ETH_Driver/inc/apm32f10x_eth.h @@ -0,0 +1,1406 @@ +/*! + * @file apm32f10x_eth.c + * + * @brief This file provides all the ETH firmware functions + * + * @version V1.0.3 + * + * @date 2022-12-01 + * + * @attention + * + * Copyright (C) 2021-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __APM32F10x_ETH_H +#define __APM32F10x_ETH_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes */ +#include "apm32f10x.h" + +/** @addtogroup APM32F10x_ETHDriver + @{ +*/ + +/** @addtogroup ETH_Driver + @{ +*/ + +/** @defgroup ETH_Enumerations + @{ +*/ + +/** + * @brief ETH AutoNegotiation + */ +typedef enum +{ + ETH_AUTONEGOTIATION_DISABLE, /*!< Disable negotiation */ + ETH_AUTONEGOTIATION_ENABLE /*!< Enable negotiation */ +} ETH_AUTONEGOTIATION_T; + +/** + * @brief ETH Watchdog + */ +typedef enum +{ + ETH_WATCHDOG_ENABLE, /*!< Enable watch dog */ + ETH_WATCHDOG_DISABLE /*!< Disable watch dog */ +} ETH_WATCHDOG_T; + +/** + * @brief ETH Jabber + */ +typedef enum +{ + ETH_JABBER_ENABLE, /*!< Enable jabber */ + ETH_JABBER_DISABLE /*!< Disable jabber */ +} ETH_JABBER_T; + +/** + * @brief ETH Inter Frame Gap + */ +typedef enum +{ + ETH_INTERFRAMEGAP_96BIT = 0x00, /*!< Inter-Frame gap = 96-bit */ + ETH_INTERFRAMEGAP_88BIT = 0x01, /*!< Inter-Frame gap = 88-bit */ + ETH_INTERFRAMEGAP_80BIT = 0x02, /*!< Inter-Frame gap = 80-bit */ + ETH_INTERFRAMEGAP_72BIT = 0x03, /*!< Inter-Frame gap = 72-bit */ + ETH_INTERFRAMEGAP_64BIT = 0x04, /*!< Inter-Frame gap = 64-bit */ + ETH_INTERFRAMEGAP_56BIT = 0x05, /*!< Inter-Frame gap = 56-bit */ + ETH_INTERFRAMEGAP_48BIT = 0x06, /*!< Inter-Frame gap = 48-bit */ + ETH_INTERFRAMEGAP_40BIT = 0x07 /*!< Inter-Frame gap = 40-bit */ +} ETH_INTERFRAMEGAP_T; + +/** + * @brief ETH Carrier Sense + */ +typedef enum +{ + ETH_CARRIERSENCE_ENABLE, /*!< Disable carrier sense during transmission */ + ETH_CARRIERSENCE_DISABLE /*!< Ignore MII CRS signal */ +} ETH_CARRIERSENCE_T; + +/** + * @brief ETH Speed + */ +typedef enum +{ + ETH_SPEED_10M, /*!< 10M speed */ + ETH_SPEED_100M /*!< 100M speed */ +} ETH_SPEED_T; + +/** + * @brief ETH Receive Own + */ +typedef enum +{ + ETH_RECEIVEOWN_ENABLE, /*!< Enable receive own */ + ETH_RECEIVEOWN_DISABLE /*!< Disable receive own */ +} ETH_RECEIVEOWN_T; + +/** + * @brief ETH Loop Back Mode + */ +typedef enum +{ + ETH_LOOPBACKMODE_DISABLE, /*!< Disable loopback mode */ + ETH_LOOPBACKMODE_ENABLE /*!< Enable loopback mode */ +} ETH_LOOPBACKMODE_T; + +/** + * @brief ETH Duplex Mode + */ +typedef enum +{ + ETH_MODE_HALFDUPLEX, /*!< Half-Duplex */ + ETH_MODE_FULLDUPLEX /*!< Full-Duplex */ +} ETH_MODE_T; + +/** + * @brief ETH Checksum Offload + */ +typedef enum +{ + ETH_CHECKSUMOFFLAOD_DISABLE, /*!< Disable IPv4 checksum offload */ + ETH_CHECKSUMOFFLAOD_ENABLE /*!< Enable Ipv4 checksum offload */ +} ETH_CHECKSUMOFFLAOD_T; + +/** + * @brief ETH Retry Transmission + */ +typedef enum +{ + ETH_RETRYTRANSMISSION_ENABLE, /*!< Enable retry */ + ETH_RETRYTRANSMISSION_DISABLE /*!< Disable retry */ +} ETH_RETRYTRANSMISSION_T; + +/** + * @brief ETH Automatic Pad CRC Strip + */ +typedef enum +{ + ETH_AUTOMATICPADCRCSTRIP_DISABLE, /*!< Disable automatic pad or CRC stripping */ + ETH_AUTOMATICPADCRCSTRIP_ENABLE /*!< Enable automatic pad or CRC stripping */ +} ETH_AUTOMATICPADCRCSTRIP_T; + +/** + * @brief ETH Back Off Limit + */ +typedef enum +{ + ETH_BACKOFFLIMIT_10, /*!< Set back off limit to 10 */ + ETH_BACKOFFLIMIT_8, /*!< Set back off limit to 18 */ + ETH_BACKOFFLIMIT_4, /*!< Set back off limit to 4 */ + ETH_BACKOFFLIMIT_1 /*!< Set back off limit to 1 */ +} ETH_BACKOFFLIMIT_T; + +/** + * @brief ETH Deferral Check + */ +typedef enum +{ + ETH_DEFFERRALCHECK_DISABLE, /*!< Disable deferral check */ + ETH_DEFFERRALCHECK_ENABLE /*!< Enable deferral check */ +} ETH_DEFFERRALCHECK_T; + +/** + * @brief ETH Receive All + */ +typedef enum +{ + ETH_RECEIVEAll_DISABLE, /*!< Disable receive all */ + ETH_RECEIVEALL_ENABLE /*!< Enable receive all */ +} ETH_RECEIVEAll_T; + +/** + * @brief ETH Source Addr Filter + */ +typedef enum +{ + ETH_SOURCEADDRFILTER_DISABLE, /*!< Disable source address filter */ + ETH_SOURCEADDRFILTER_NORMAL_ENABLE = BIT9, /*!< Enable normal source address filter */ + ETH_SOURCEADDRFILTER_INVERSE_ENABLE = BIT8 | BIT9, /*!< Enable inverse source address filter */ +} ETH_SOURCEADDRFILTER_T; + +/** + * @brief ETH Pass Control Frames + */ +typedef enum +{ + ETH_PASSCONTROLFRAMES_BLOCKALL = 1, /*!< Even if all control frames except pause frames fail the + address filter, MAC forwards them to the application */ + ETH_PASSCONTROLFRAMES_FORWARDALL, /*!< MAC forwards control frames to the application even if + they do not pass the address filter */ + ETH_PASSCONTROLFRAMES_FORWARDPASSEDADDRFILTER /*!< MAC forwards control frames that pass through the address filter */ +} ETH_PASSCONTROLFRAMES_T; + +/** + * @brief ETH Broadcast Frames Reception + */ +typedef enum +{ + ETH_BROADCASTFRAMESRECEPTION_ENABLE, /*!< Enable broadcast frames */ + ETH_BROADCASTFRAMESRECEPTION_DISABLE /*!< Disable broadcast frames */ +} ETH_BROADCASTFRAMESRECEPTION_T; + +/** + * @brief ETH Destination Addr Filter + */ +typedef enum +{ + ETH_DESTINATIONADDRFILTER_NORMAL, /*!< Normal destination address filter */ + ETH_DESTINATIONADDRFILTER_INVERSE /*!< Inverse destination address filter */ +} ETH_DESTINATIONADDRFILTER_T; + +/** + * @brief ETH Destination Addr Filter + */ +typedef enum +{ + ETH_PROMISCUOUS_MODE_DISABLE, /*!< Disable promiscuous mode */ + ETH_PROMISCUOUS_MODE_ENABLE /*!< Enable promiscuous mode */ +} ETH_PROMISCUOUS_MODE_T; + +/** + * @brief ETH Multicast Frames Filter + */ +typedef enum +{ + ETH_MULTICASTFRAMESFILTER_PERFECT, /*!< Multicast perfect filter */ + ETH_MULTICASTFRAMESFILTER_NONE = BIT4, /*!< Multicast pass all multicast */ + ETH_MULTICASTFRAMESFILTER_HASHTABLE = BIT2, /*!< Multicast hash multicast */ + ETH_MULTICASTFRAMESFILTER_PERFECTHASHTABLE = BIT2 | BIT10 /*!< Multicast perfect hash table */ +} ETH_MULTICASTFRAMESFILTER_T; + +/** + * @brief ETH Unicast Frames Filter + */ +typedef enum +{ + ETH_UNICASTFRAMESFILTER_PERFECT, /*!< Unicast perfect filter */ + ETH_UNICASTFRAMESFILTER_HASHTABLE = BIT1, /*!< Unicast hash table */ + ETH_UNICASTFRAMESFILTER_PERFECTHASHTABLE = BIT1 | BIT10 /*!< Unicast perfect hash table */ +} ETH_UNICASTFRAMESFILTER_T; + +/** + * @brief ETH Zero Quanta Pause + */ +typedef enum +{ + ETH_ZEROQUANTAPAUSE_ENABLE, /*!< Enable zero-quanta pause */ + ETH_ZEROQUANTAPAUSE_DISABLE /*!< Disable zero-quanta pause */ +} ETH_ZEROQUANTAPAUSE_T; + +/** + * @brief ETH Pause Low Threshold + */ +typedef enum +{ + ETH_PAUSELOWTHRESHOLD_MINUS4, /*!< Minus 4 slot-time */ + ETH_PAUSELOWTHRESHOLD_MINUS28, /*!< Minus 28 slot-time */ + ETH_PAUSELOWTHRESHOLD_MINUS144, /*!< Minus 144 slot-time */ + ETH_PAUSELOWTHRESHOLD_MINUS256 /*!< Minus 256 slot-time */ +} ETH_PAUSELOWTHRESHOLD_T; + +/** + * @brief ETH Unicast Pause Frame Detect + */ +typedef enum +{ + ETH_UNICASTPAUSEFRAMEDETECT_DISABLE, /*!< Disable unicast pause frame detect */ + ETH_UNICASTPAUSEFRAMEDETECT_ENABLE /*!< Enable unicast pause frame detect */ +} ETH_UNICASTPAUSEFRAMEDETECT_T; + +/** + * @brief ETH Receive Flow Control + */ +typedef enum +{ + ETH_RECEIVEFLOWCONTROL_DISABLE, /*!< Disable receive flow control */ + ETH_RECEIVEFLOWCONTROL_ENABLE /*!< Enable receive flow control */ +} ETH_RECEIVEFLOWCONTROL_T; + +/** + * @brief ETH Transmit Flow Control + */ +typedef enum +{ + ETH_TRANSMITFLOWCONTROL_DISABLE, /*!< Disable transmit flow control */ + ETH_TRANSMITFLOWCONTROL_ENABLE /*!< Enable transmit flow control */ +} ETH_TRANSMITFLOWCONTROL_T; + +/** + * @brief ETH VLAN Tag Comparison + */ +typedef enum +{ + ETH_VLANTAGCOMPARISON_16BIT, /*!< 16-bit VLAN tag comparison */ + ETH_VLANTAGCOMPARISON_12BIT /*!< 12-bit VLAN tag comparison */ +} ETH_VLANTAGCOMPARISON_T; + +/** + * @brief ETH MAC Flags + */ +typedef enum +{ + ETH_MAC_FLAG_TST = 0x00000200, /*!< Time stamp trigger flag */ + ETH_MAC_FLAG_MMCT = 0x00000040, /*!< MMC transmit flag */ + ETH_MAC_FLAG_MMCR = 0x00000020, /*!< MMC receive flag */ + ETH_MAC_FLAG_MMC = 0x00000010, /*!< MMC flag */ + ETH_MAC_FLAG_PMT = 0x00000008 /*!< PMT flag */ +} ETH_MAC_FLAG_T; + +/** + * @brief ETH MAC Interrupts + */ +typedef enum +{ + ETH_MAC_INT_TST = 0x00000200, /*!< Time stamp trigger interrupt */ + ETH_MAC_INT_MMCT = 0x00000040, /*!< MMC transmit interrupt */ + ETH_MAC_INT_MMCR = 0x00000020, /*!< MMC receive interrupt */ + ETH_MAC_INT_MMC = 0x00000010, /*!< MMC interrupt */ + ETH_MAC_INT_PMT = 0x00000008 /*!< PMT interrupt */ +} ETH_MAC_INT_T; + +/** + * @brief ETH MAC Interrupts + */ +typedef enum +{ + ETH_MAC_ADDRESS0 = 0x00000000, /*!< MAC Address0 */ + ETH_MAC_ADDRESS1 = 0x00000008, /*!< MAC Address1 */ + ETH_MAC_ADDRESS2 = 0x00000010, /*!< MAC Address2 */ + ETH_MAC_ADDRESS3 = 0x00000018 /*!< MAC Address3 */ +} ETH_MAC_ADDRESS_T; + +/** + * @brief ETH MAC addresses filter SA/DA + */ +typedef enum +{ + ETH_MAC_ADDRESSFILTER_SA, /*!< MAC Address is used to compare with the + SA fields of the received frame */ + ETH_MAC_ADDRESSFILTER_DA = BIT30 /*!< MAC Address is used to compare with the + DA fields of the received frame */ +} ETH_MAC_ADDRESSFILTER_T; + +/** + * @brief ETH MAC addresses filter Mask bytes + */ +typedef enum +{ + ETH_MAC_ADDRESSMASK_BYTE6 = 0x20000000, /*!< Mask MAC Address high reg bits [15:8] */ + ETH_MAC_ADDRESSMASK_BYTE5 = 0x10000000, /*!< Mask MAC Address high reg bits [7:0] */ + ETH_MAC_ADDRESSMASK_BYTE4 = 0x08000000, /*!< Mask MAC Address low reg bits [31:24] */ + ETH_MAC_ADDRESSMASK_BYTE3 = 0x04000000, /*!< Mask MAC Address low reg bits [23:16] */ + ETH_MAC_ADDRESSMASK_BYTE2 = 0x02000000, /*!< Mask MAC Address low reg bits [15:8] */ + ETH_MAC_ADDRESSMASK_BYTE1 = 0x01000000 /*!< Mask MAC Address low reg bits [70] */ +} ETH_MAC_ADDRESSMASK_T; + +/** + * @brief DMA Tx descriptor flags + */ +typedef enum +{ + ETH_DMATXDESC_OWN = (int)0x80000000, /*!< Descriptor is owned by DMA engine */ + ETH_DMATXDESC_INTC = 0x40000000, /*!< Interrupt on completion */ + ETH_DMATXDESC_LS = 0x20000000, /*!< Last Segment */ + ETH_DMATXDESC_FS = 0x10000000, /*!< First Segment */ + ETH_DMATXDESC_DISC = 0x08000000, /*!< Disable CRC */ + ETH_DMATXDESC_DISP = 0x04000000, /*!< Disable Pad */ + ETH_DMATXDESC_TXTSEN = 0x02000000, /*!< Transmit Time Stamp Enable */ + ETH_DMATXDESC_TXENDR = 0x00200000, /*!< Transmit End of Ring */ + ETH_DMATXDESC_TXCH = 0x00100000, /*!< Second Address Chained */ + ETH_DMATXDESC_TXTSS = 0x00020000, /*!< Tx Time Stamp Status */ + ETH_DMATXDESC_IHERR = 0x00010000, /*!< IP Header Error */ + ETH_DMATXDESC_ERRS = 0x00008000, /*!< Error summary */ + ETH_DMATXDESC_JTO = 0x00004000, /*!< Jabber Timeout */ + ETH_DMATXDESC_FF = 0x00002000, /*!< Frame Flushed: DMA/MTL flushed the frame due to SW flush */ + ETH_DMATXDESC_IPERR = 0x00001000, /*!< Payload Checksum Error */ + ETH_DMATXDESC_LSC = 0x00000800, /*!< Loss of Carrier: carrier lost during transmission */ + ETH_DMATXDESC_NC = 0x00000400, /*!< No Carrier: no carrier signal from the transceiver */ + ETH_DMATXDESC_LC = 0x00000200, /*!< Late Collision: transmission aborted due to collision */ + ETH_DMATXDESC_EC = 0x00000100, /*!< Excessive Collision: transmission aborted after 16 collisions */ + ETH_DMATXDESC_VLANF = 0x00000080, /*!< VLAN Frame */ + ETH_DMATXDESC_CCNT = 0x00000078, /*!< Collision Count */ + ETH_DMATXDESC_EDEF = 0x00000004, /*!< Excessive Deferral */ + ETH_DMATXDESC_UFERR = 0x00000002, /*!< Underflow Error: late data arrival from the memory */ + ETH_DMATXDESC_DEF = 0x00000001 /*!< Deferred Bit */ +} ETH_DMATXDESC_FLAG_T; + +/** + * @brief ETH DMA Tx descriptor segment + */ +typedef enum +{ + ETH_DMATXDESC_LASTSEGMENTS = BIT30, /*!< Actual Tx desc contain last segment */ + ETH_DMATXDESC_FIRSTSEGMENT = BIT29 /*!< Actual Tx desc contain first segment */ +} ETH_DMATXDESC_SEGMENTS_T; + +/** + * @brief ETH DMA Tx descriptor Checksum Insertion Control + */ +typedef enum +{ + ETH_DMATXDESC_CHECKSUMBYPASS, /*!< Checksum bypass */ + ETH_DMATXDESC_CHECKSUMIPV4HEADER = BIT22, /*!< IPv4 header checksum */ + ETH_DMATXDESC_CHECKSUMTCPUDPICMPSEGMENT = BIT23, /*!< TCP/UDP/ICMP checksum. Pseudo header + checksum is assumed to be present */ + ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL = BIT22 | BIT23 /*!< TCP/UDP/ICMP checksum fully in hardware + including pseudo header */ +} ETH_DMATXDESC_CHECKSUMB_T; + +/** + * @brief DMA Rx descriptor status + */ +typedef enum +{ + ETH_DMARXDESC_OWN = (int)0x80000000U, /*!< Descriptor is owned by DMA engine */ + ETH_DMARXDESC_ADDRF = 0x40000000, /*!< DA Filter Fail for the rx frame */ + ETH_DMARXDESC_ERRS = 0x00008000, /*!< Error summary */ + ETH_DMARXDESC_DESERR = 0x00004000, /*!< Descriptor error: no more descriptors for receive frame */ + ETH_DMARXDESC_SADDRF = 0x00002000, /*!< SA Filter Fail for the received frame */ + ETH_DMARXDESC_LERR = 0x00001000, /*!< Frame size not matching with length field */ + ETH_DMARXDESC_OFERR = 0x00000800, /*!< Overflow Error: Frame was damaged due to buffer overflow */ + ETH_DMARXDESC_VLANF = 0x00000400, /*!< VLAN Tag: received frame is a VLAN frame */ + ETH_DMARXDESC_FDES = 0x00000200, /*!< First descriptor of the frame */ + ETH_DMARXDESC_LDES = 0x00000100, /*!< Last descriptor of the frame */ + ETH_DMARXDESC_IPV4HCE = 0x00000080, /*!< IPC Checksum Error/Giant Frame: Rx Ipv4 header checksum error */ + ETH_DMARXDESC_LC = 0x00000040, /*!< Late collision occurred during reception */ + ETH_DMARXDESC_FT = 0x00000020, /*!< Frame type - Ethernet, otherwise 802.3 */ + ETH_DMARXDESC_RXWDTTO = 0x00000010, /*!< Receive Watchdog Timeout: watchdog timer expired during reception */ + ETH_DMARXDESC_RERR = 0x00000008, /*!< Receive error: error reported by MII interface */ + ETH_DMARXDESC_DERR = 0x00000004, /*!< Dribble bit error: frame contains non int multiple of 8 bits */ + ETH_DMARXDESC_CERR = 0x00000002, /*!< CRC error */ + ETH_DMARXDESC_MAMPCE = 0x00000001 /*!< Rx MAC Address/Payload Checksum Error: + Rx MAC address matched/ Rx Payload Checksum Error */ +} ETH_DMARXDESC_FLAG_T; + +/** + * @brief DMA Rx descriptor extended flags + */ +typedef enum +{ + ETH_DMAPTPRXDESC_PTPV = 0x00002000, /*!< PTP version */ + ETH_DMAPTPRXDESC_PTPFT = 0x00001000, /*!< PTP frame type */ + ETH_DMAPTPRXDESC_PTPMT = 0x00000F00, /*!< PTP message type */ + ETH_DMAPTPRXDESC_IPV6P = 0x00000080, /*!< IPv6 packet received */ + ETH_DMAPTPRXDESC_IPV4P = 0x00000040, /*!< IPv4 packet received */ + ETH_DMAPTPRXDESC_IPCBP = 0x00000020, /*!< IP checksum bypassed */ + ETH_DMAPTPRXDESC_IPPERR = 0x00000010, /*!< IP payload error */ + ETH_DMAPTPRXDESC_IPHERR = 0x00000008, /*!< IP header error */ + ETH_DMAPTPRXDESC_IPPT = 0x00000007 /*!< IP payload type */ +} ETH_DMAPTPRXDESC_FLAG_T; + +/** + * @brief ETH DMA Rx descriptor buffers + */ +typedef enum +{ + ETH_DMARXDESC_BUFFER1, /*!< DMA Rx Desc Buffer1 */ + ETH_DMARXDESC_BUFFER2 /*!< DMA Rx Desc Buffer2 */ +} ETH_DMARXDESC_BUFFER_T; + +/** + * @brief ETH Drop TCP IP Checksum Error Frame + */ +typedef enum +{ + ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE, /*!< Enable dropping of TCP/IP checksum error frame */ + ETH_DROPTCPIPCHECKSUMERRORFRAME_DISABLE /*!< Disable dropping of TCP/IP checksum error frame */ +} ETH_DROPTCPIPCHECKSUMERRORFRAME_T; + +/** + * @brief ETH Receive Store Forward + */ +typedef enum +{ + ETH_RECEIVESTOREFORWARD_DISABLE, /*!< Disable receive store and forward */ + ETH_RECEIVESTOREFORWARD_ENABLE /*!< Enable receive store and forward */ +} ETH_RECEIVESTOREFORWARD_T; + +/** + * @brief ETH Flush Received Frame + */ +typedef enum +{ + ETH_FLUSHRECEIVEDFRAME_ENABLE, /*!< Enable flushing of received frames */ + ETH_FLUSHRECEIVEDFRAME_DISABLE /*!< Disable flushing of received frames */ +} ETH_FLUSHRECEIVEDFRAME_T; + +/** + * @brief ETH Transmit Store Forward + */ +typedef enum +{ + ETH_TRANSMITSTOREFORWARD_DISABLE, /*!< Disable transmit store and forward */ + ETH_TRANSMITSTOREFORWARD_ENABLE /*!< Enable transmit store and forward */ +} ETH_TRANSMITSTOREFORWARD_T; + +/** + * @brief ETH Transmit Threshold Control + */ +typedef enum +{ + ETH_TRANSMITTHRESHOLDCONTROL_64BYTES, /*!< Select 64 bytes transmit threshild level */ + ETH_TRANSMITTHRESHOLDCONTROL_128BYTES, /*!< Select 128 bytes transmit threshild level */ + ETH_TRANSMITTHRESHOLDCONTROL_192BYTES, /*!< Select 192 bytes transmit threshild level */ + ETH_TRANSMITTHRESHOLDCONTROL_256BYTES, /*!< Select 256 bytes transmit threshild level */ + ETH_TRANSMITTHRESHOLDCONTROL_40BYTES, /*!< Select 40 bytes transmit threshild level */ + ETH_TRANSMITTHRESHOLDCONTROL_32BYTES, /*!< Select 32 bytes transmit threshild level */ + ETH_TRANSMITTHRESHOLDCONTROL_24BYTES, /*!< Select 24 bytes transmit threshild level */ + ETH_TRANSMITTHRESHOLDCONTROL_16BYTES /*!< Select 16 bytes transmit threshild level */ +} ETH_TRANSMITTHRESHOLDCONTROL_T; + +/** + * @brief ETH Forward Error Frames + */ +typedef enum +{ + ETH_FORWARDERRORFRAMES_DISABLE, /*!< Disable forward error frames */ + ETH_FORWARDERRORFRAMES_ENABLE /*!< Enable forward error frames */ +} ETH_FORWARDERRORFRAMES_T; + +/** + * @brief ETH Forward Undersized Good Frames + */ +typedef enum +{ + ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE, /*!< Disable forward undersized good frames */ + ETH_FORWARDUNDERSIZEDGOODFRAMES_ENABLE /*!< Enable forward undersized good frames */ +} ETH_FORWARDUNDERSIZEDGOODFRAMES_T; + +/** + * @brief ETH Receive Threshold Control + */ +typedef enum +{ + ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES, /*!< Select 64 bytes receive threshold level */ + ETH_RECEIVEDTHRESHOLDCONTROL_32BYTES, /*!< Select 32 bytes receive threshold level */ + ETH_RECEIVEDTHRESHOLDCONTROL_96BYTES, /*!< Select 96 bytes receive threshold level */ + ETH_RECEIVEDTHRESHOLDCONTROL_128BYTES /*!< Select 128 bytes receive threshold level */ +} ETH_RECEIVEDTHRESHOLDCONTROL_T; + +/** + * @brief ETH Second Frame Operate + */ +typedef enum +{ + ETH_SECONDFRAMEOPERARTE_DISABLE, /*!< Disable second frame operate */ + ETH_SECONDFRAMEOPERARTE_ENABLE /*!< Enable second frame operate */ +} ETH_SECONDFRAMEOPERARTE_T; + +/** + * @brief ETH Address Aligned Beats + */ +typedef enum +{ + ETH_ADDRESSALIGNEDBEATS_DISABLE, /*!< Disable address aligned beats */ + ETH_ADDRESSALIGNEDBEATS_ENABLE /*!< Enable address aligned beats */ +} ETH_ADDRESSALIGNEDBEATS_T; + +/** + * @brief ETH Fixed Burst + */ +typedef enum +{ + ETH_FIXEDBURST_DISABLE, /*!< Disable fixed burst */ + ETH_FIXEDBURST_ENABLE /*!< Enable fixed burst */ +} ETH_FIXEDBURST_T; + +/** + * @brief ETH Rx DMA Burst Length + */ +typedef enum +{ + ETH_RXDMABURSTLENGTH_1BEAT = BIT17, /*!< Maxnum number of Rx DMA transaction = 1 beat */ + ETH_RXDMABURSTLENGTH_2BEAT = BIT18, /*!< Maxnum number of Rx DMA transaction = 2 beat */ + ETH_RXDMABURSTLENGTH_4BEAT = BIT19, /*!< Maxnum number of Rx DMA transaction = 4 beat */ + ETH_RXDMABURSTLENGTH_8BEAT = BIT20, /*!< Maxnum number of Rx DMA transaction = 8 beat */ + ETH_RXDMABURSTLENGTH_16BEAT = BIT21, /*!< Maxnum number of Rx DMA transaction = 16 beat */ + ETH_RXDMABURSTLENGTH_32BEAT = BIT22, /*!< Maxnum number of Rx DMA transaction = 32 beat */ + ETH_RXDMABURSTLENGTH_4XPBL_4BEAT = BIT17 | BIT24, /*!< Maxnum number of Rx DMA transaction = 4 beat */ + ETH_RXDMABURSTLENGTH_4XPBL_8BEAT = BIT18 | BIT24, /*!< Maxnum number of Rx DMA transaction = 8 beat */ + ETH_RXDMABURSTLENGTH_4XPBL_16BEAT = BIT19 | BIT24, /*!< Maxnum number of Rx DMA transaction = 16 beat */ + ETH_RXDMABURSTLENGTH_4XPBL_32BEAT = BIT20 | BIT24, /*!< Maxnum number of Rx DMA transaction = 32 beat */ + ETH_RXDMABURSTLENGTH_4XPBL_64BEAT = BIT21 | BIT24, /*!< Maxnum number of Rx DMA transaction = 64 beat */ + ETH_RXDMABURSTLENGTH_4XPBL_128BEAT = BIT22 | BIT24 /*!< Maxnum number of Rx DMA transaction = 128 beat */ +} ETH_RXDMABURSTLENGTH_T; + +/** + * @brief ETH Tx DMA Burst Length + */ +typedef enum +{ + ETH_TXDMABURSTLENGTH_1BEAT = BIT8, /*!< Maxnum number of Tx DMA transaction = 1 beat */ + ETH_TXDMABURSTLENGTH_2BEAT = BIT9, /*!< Maxnum number of Tx DMA transaction = 2 beat */ + ETH_TXDMABURSTLENGTH_4BEAT = BIT10, /*!< Maxnum number of Tx DMA transaction = 4 beat */ + ETH_TXDMABURSTLENGTH_8BEAT = BIT11, /*!< Maxnum number of Tx DMA transaction = 8 beat */ + ETH_TXDMABURSTLENGTH_16BEAT = BIT12, /*!< Maxnum number of Tx DMA transaction = 16 beat */ + ETH_TXDMABURSTLENGTH_32BEAT = BIT13, /*!< Maxnum number of Tx DMA transaction = 32 beat */ + ETH_TXDMABURSTLENGTH_4XPBL_4BEAT = BIT8 | BIT24, /*!< Maxnum number of Tx DMA transaction = 4 beat */ + ETH_TXDMABURSTLENGTH_4XPBL_8BEAT = BIT9 | BIT24, /*!< Maxnum number of Tx DMA transaction = 8 beat */ + ETH_TXDMABURSTLENGTH_4XPBL_16BEAT = BIT10 | BIT24, /*!< Maxnum number of Tx DMA transaction = 16 beat */ + ETH_TXDMABURSTLENGTH_4XPBL_32BEAT = BIT11 | BIT24, /*!< Maxnum number of Tx DMA transaction = 32 beat */ + ETH_TXDMABURSTLENGTH_4XPBL_64BEAT = BIT12 | BIT24, /*!< Maxnum number of Tx DMA transaction = 64 beat */ + ETH_TXDMABURSTLENGTH_4XPBL_128BEAT = BIT13 | BIT24 /*!< Maxnum number of Tx DMA transaction = 128 beat */ +} ETH_TXDMABURSTLENGTH_T; + +/** + * @brief ETH DMA Arbitration + */ +typedef enum +{ + ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1, /*!< Priority ratio RX : TX = 1 : 1 */ + ETH_DMAARBITRATION_ROUNDROBIN_RXTX_2_1 = BIT14, /*!< Priority ratio RX : TX = 2 : 1 */ + ETH_DMAARBITRATION_ROUNDROBIN_RXTX_3_1 = BIT15, /*!< Priority ratio RX : TX = 3 : 1 */ + ETH_DMAARBITRATION_ROUNDROBIN_RXTX_4_1 = BIT14 | BIT15, /*!< Priority ratio RX : TX = 4 : 1 */ + ETH_DMAARBITRATION_RXPRIORTX = BIT1 /*!< Rx priority ratio higher than Tx */ +} ETH_DMAARBITRATION_T; + +/** + * @brief ETH DMA Flags + */ +typedef enum +{ + ETH_DMA_FLAG_TST = 0x20000000, /*!< Time-stamp trigger interrupt (on DMA) */ + ETH_DMA_FLAG_PMT = 0x10000000, /*!< PMT interrupt (on DMA) */ + ETH_DMA_FLAG_MMC = 0x08000000, /*!< MMC interrupt (on DMA) */ + ETH_DMA_FLAG_DATATRANSFERERROR = 0x00800000, /*!< Error bits 0-Rx DMA, 1-Tx DMA */ + ETH_DMA_FLAG_READWRITEERROR = 0x01000000, /*!< Error bits 0-write transfer, 1-read transfer */ + ETH_DMA_FLAG_ACCESSERROR = 0x02000000, /*!< Error bits 0-data buffer, 1-desc. access */ + ETH_DMA_FLAG_NIS = 0x00010000, /*!< Normal interrupt summary flag */ + ETH_DMA_FLAG_AIS = 0x00008000, /*!< Abnormal interrupt summary flag */ + ETH_DMA_FLAG_ER = 0x00004000, /*!< Early receive flag */ + ETH_DMA_FLAG_FBE = 0x00002000, /*!< Fatal bus error flag */ + ETH_DMA_FLAG_ET = 0x00000400, /*!< Early transmit flag */ + ETH_DMA_FLAG_RWT = 0x00000200, /*!< Receive watchdog timeout flag */ + ETH_DMA_FLAG_RPS = 0x00000100, /*!< Receive process stopped flag */ + ETH_DMA_FLAG_RBU = 0x00000080, /*!< Receive buffer unavailable flag */ + ETH_DMA_FLAG_RX = 0x00000040, /*!< Receive flag */ + ETH_DMA_FLAG_TU = 0x00000020, /*!< Underflow flag */ + ETH_DMA_FLAG_RO = 0x00000010, /*!< Overflow flag */ + ETH_DMA_FLAG_TJT = 0x00000008, /*!< Transmit jabber timeout flag */ + ETH_DMA_FLAG_TBU = 0x00000004, /*!< Transmit buffer unavailable flag */ + ETH_DMA_FLAG_TPS = 0x00000002, /*!< Transmit process stopped flag */ + ETH_DMA_FLAG_TX = 0x00000001 /*!< Transmit flag */ +} ETH_DMA_FLAG_T; + +/** + * @brief ETH DMA Interrupts + */ +typedef enum +{ + ETH_DMA_INT_TST = 0x20000000, /*!< Time-stamp trigger interrupt (on DMA) */ + ETH_DMA_INT_PMT = 0x10000000, /*!< PMT interrupt (on DMA) */ + ETH_DMA_INT_MMC = 0x08000000, /*!< MMC interrupt (on DMA) */ + ETH_DMA_INT_NIS = 0x00010000, /*!< Normal interrupt summary */ + ETH_DMA_INT_AIS = 0x00008000, /*!< Abnormal interrupt summary */ + ETH_DMA_INT_ER = 0x00004000, /*!< Early receive interrupt */ + ETH_DMA_INT_FBE = 0x00002000, /*!< Fatal bus error interrupt */ + ETH_DMA_INT_ET = 0x00000400, /*!< Early transmit interrupt */ + ETH_DMA_INT_RWT = 0x00000200, /*!< Receive watchdog timeout interrupt */ + ETH_DMA_INT_RPS = 0x00000100, /*!< Receive process stopped interrupt */ + ETH_DMA_INT_RBU = 0x00000080, /*!< Receive buffer unavailable interrupt */ + ETH_DMA_INT_RX = 0x00000040, /*!< Receive interrupt */ + ETH_DMA_INT_TU = 0x00000020, /*!< Underflow interrupt */ + ETH_DMA_INT_RO = 0x00000010, /*!< Overflow interrupt */ + ETH_DMA_INT_TJT = 0x00000008, /*!< Transmit jabber timeout interrupt */ + ETH_DMA_INT_TBU = 0x00000004, /*!< Transmit buffer unavailable interrupt */ + ETH_DMA_INT_TPS = 0x00000002, /*!< Transmit process stopped interrupt */ + ETH_DMA_INT_TX = 0x00000001 /*!< Transmit interrupt */ +} ETH_DMA_INT_T; + +/** + * @brief ETH DMA transmit process state + */ +typedef enum +{ + ETH_DMA_TRANSMITPROCESS_STOPPED, /*!< Stopped - Reset or Stop Tx Command issued */ + ETH_DMA_TRANSMITPROCESS_FETCHING, /*!< Running - fetching the Tx descriptor */ + ETH_DMA_TRANSMITPROCESS_WAITING, /*!< Running - waiting for status */ + ETH_DMA_TRANSMITPROCESS_READING, /*!< Running - reading the data from host memory */ + ETH_DMA_TRANSMITPROCESS_SUSPENDED = 0x06, /*!< Suspended - Tx Descriptor unavailable */ + ETH_DMA_TRANSMITPROCESS_CLOSING = 0x07, /*!< Running - closing Rx descriptor */ +} ETH_DMA_TRANSMITPROCESS_T; + +/** + * @brief ETH DMA receive process state + */ +typedef enum +{ + ETH_DMA_RECEIVEPROCESS_STOPPED, /*!< Stopped - Reset or Stop Rx Command issued */ + ETH_DMA_RECEIVEPROCESS_FETCHING = 0x02, /*!< Running - fetching the Rx descriptor */ + ETH_DMA_RECEIVEPROCESS_WAITING = 0x06, /*!< Running - waiting for packet */ + ETH_DMA_RECEIVEPROCESS_SUSPENDED = 0x08, /*!< Suspended - Rx Descriptor unavailable */ + ETH_DMA_RECEIVEPROCESS_CLOSING = 0x0A, /*!< Running - closing descriptor */ + ETH_DMA_RECEIVEPROCESS_QUEUING = 0x0E /*!< Running - queuing the receive frame into host memory */ +} ETH_DMA_RECEIVEPROCESS_T; + +/** + * @brief ETH DMA overflow + */ +typedef enum +{ + ETH_DMA_OVERFLOW_RXFIFOCOUNTER = BIT28, /*!< Overflow for FIFO Overflows Counter */ + ETH_DMA_OVERFLOW_MISSEDFRAMECOUNTER = BIT16 /*!< Overflow for Buffer Unavailable Missed Frame Counter */ +} ETH_DMA_OVERFLOW_T; + +/** + * @brief ETH PMT Flags + */ +typedef enum +{ + ETH_PMT_FLAG_WUFFRPR = (int)BIT31, /*!< Wake-Up Frame Filter Register Pointer Reset */ + ETH_PMT_FLAG_WUFR = BIT6, /*!< Wake-Up Frame Received */ + ETH_PMT_FLAG_MPR = BIT5 /*!< Magic Packet Received */ +} ETH_PMT_FLAG_T; + +/** + * @brief ETH MMC Tx/RX Interrupts + */ +typedef enum +{ + ETH_MMC_INT_TGF = BIT21, /*!< When Tx good frame counter reaches half the maximum value */ + ETH_MMC_INT_TGFMSC = BIT15, /*!< When Tx good multi col counter reaches half the maximum value */ + ETH_MMC_INT_TGFSC = BIT14, /*!< When Tx good single col counter reaches half the maximum value */ + ETH_MMC_INT_RGUF = BIT21 | BIT30, /*!< When Rx good unicast frames counter reaches half the maximum value */ + ETH_MMC_INT_RFAE = BIT6 | BIT30, /*!< When Rx alignment error counter reaches half the maximum value */ + ETH_MMC_INT_RFCE = BIT5 | BIT30 /*!< When Rx crc error counter reaches half the maximum value */ +} ETH_MMC_INT_T; + +/** + * @brief ETH MMC Registers + */ +typedef enum +{ + ETH_MMC_CTRL = 0x00000100, /*!< MMC CTRL register */ + ETH_MMC_RXINT = 0x00000104, /*!< MMC RXINT register */ + ETH_MMC_TXINT = 0x00000108, /*!< MMC TXINT register */ + ETH_MMC_RXINTMASK = 0x0000010C, /*!< MMC RXINTMASK register */ + ETH_MMC_TXINTMASK = 0x00000110, /*!< MMC TXINTMASK register */ + ETH_MMC_TXGFSCCNT = 0x0000014C, /*!< MMC TXGFSCCNT register */ + ETH_MMC_TXGFMCCNT = 0x00000150, /*!< MMC TXGFMCCNT register */ + ETH_MMC_TXGFCNT = 0x00000168, /*!< MMC TXGFCNT register */ + ETH_MMC_RXFCECNT = 0x00000194, /*!< MMC RXFCECNT register */ + ETH_MMC_RXFAECNT = 0x00000198, /*!< MMC RXFAECNT register */ + ETH_MMC_RXGUNCNT = 0x000001C4 /*!< MMC RXGUNCNT register */ +} ETH_MMC_REG_T; + +/**@} end of group ETH_Enumerations*/ + + +/** @defgroup ETH_DMA_TX_Descriptor ETH DMA TX Descriptor + * @{ + */ + +/** +* DMA Tx Descriptor +* ----------------------------------------------------------------------------------------------- +* TXDES0 | OWN(31) | CTRL[30:25] | Reserved(24) | CTRL[23:20] | Reserved[19:18] | Status[17:0] | +* ----------------------------------------------------------------------------------------------- +* TXDES1 | Reserved[31:29] | Buffer2 Size[28:16] | Reserved[15:13] | Buffer1 Size[12:0] | +* ----------------------------------------------------------------------------------------------- +* TXDES2 | Buffer1 Address [31:0] | +* ----------------------------------------------------------------------------------------------- +* TXDES3 | Buffer2 Address [31:0] / Next Descriptor Address [31:0] | +* ----------------------------------------------------------------------------------------------- +*/ + +/** + * @brief Bit definition of TXDES0 register: DMA Tx descriptor status register + */ +#define ETH_DMATXDESC_OWN 0x80000000U /*!< OWN bit: descriptor is owned by DMA engine */ +#define ETH_DMATXDESC_INTC 0x40000000U /*!< Interrupt on Completion */ +#define ETH_DMATXDESC_LS 0x20000000U /*!< Last Segment */ +#define ETH_DMATXDESC_FS 0x10000000U /*!< First Segment */ +#define ETH_DMATXDESC_DISC 0x08000000U /*!< Disable CRC */ +#define ETH_DMATXDESC_DISP 0x04000000U /*!< Disable Padding */ +#define ETH_DMATXDESC_TXTSEN 0x02000000U /*!< Transmit Time Stamp Enable */ +#define ETH_DMATXDESC_CIC 0x00C00000U /*!< Checksum Insertion Control: 4 cases */ +#define ETH_DMATXDESC_CIC_BYPASS 0x00000000U /*!< Do Nothing: Checksum Engine is bypassed */ +#define ETH_DMATXDESC_CIC_IPV4HEADER 0x00400000U /*!< IPV4 header Checksum Insertion */ +#define ETH_DMATXDESC_CIC_TCPUDPICMP_SEGMENT 0x00800000U /*!< TCP/UDP/ICMP Checksum Insertion calculated over segment only */ +#define ETH_DMATXDESC_CIC_TCPUDPICMP_FULL 0x00C00000U /*!< TCP/UDP/ICMP Checksum Insertion fully calculated */ +#define ETH_DMATXDESC_TXENDR 0x00200000U /*!< Transmit End of Ring */ +#define ETH_DMATXDESC_TXCH 0x00100000U /*!< Second Address Chained */ +#define ETH_DMATXDESC_TXTSS 0x00020000U /*!< Tx Time Stamp Status */ +#define ETH_DMATXDESC_IHERR 0x00010000U /*!< IP Header Error */ +#define ETH_DMATXDESC_ERRS 0x00008000U /*!< Error summary: OR of the following bits: UFERR || EDEF || EC || LC || NC || LSC || FF || JTO */ +#define ETH_DMATXDESC_JTO 0x00004000U /*!< Jabber Timeout */ +#define ETH_DMATXDESC_FF 0x00002000U /*!< Frame Flushed: DMA/MTL flushed the frame due to SW flush */ +#define ETH_DMATXDESC_IPERR 0x00001000U /*!< Payload Checksum Error */ +#define ETH_DMATXDESC_LSC 0x00000800U /*!< Loss of Carrier: carrier lost during transmission */ +#define ETH_DMATXDESC_NC 0x00000400U /*!< No Carrier: no carrier signal from the transceiver */ +#define ETH_DMATXDESC_LC 0x00000200U /*!< Late Collision: transmission aborted due to collision */ +#define ETH_DMATXDESC_EC 0x00000100U /*!< Excessive Collision: transmission aborted after 16 collisions */ +#define ETH_DMATXDESC_VLANF 0x00000080U /*!< VLAN Frame */ +#define ETH_DMATXDESC_CCNT 0x00000078U /*!< Collision Count */ +#define ETH_DMATXDESC_EDEF 0x00000004U /*!< Excessive Deferral */ +#define ETH_DMATXDESC_UFERR 0x00000002U /*!< Underflow Error: late data arrival from the memory */ +#define ETH_DMATXDESC_DEF 0x00000001U /*!< Deferred Bit */ + +/** + * @brief Bit definition of TXDES1 register + */ +#define ETH_DMATXDESC_TXBS2 0x1FFF0000U /*!< Transmit Buffer2 Size */ +#define ETH_DMATXDESC_TXBS1 0x00001FFFU /*!< Transmit Buffer1 Size */ + +/** + * @brief Bit definition of TXDES2 register + */ +#define ETH_DMATXDESC_B1AP 0xFFFFFFFFU /*!< Buffer1 Address Pointer */ + +/** + * @brief Bit definition of TXDES3 register + */ +#define ETH_DMATXDESC_B2AP 0xFFFFFFFFU /*!< Buffer2 Address Pointer */ + +/** +* --------------------------------------------------------------------------------------------- +* TXDES6 | Transmit Time Stamp Low [31:0] | +* --------------------------------------------------------------------------------------------- +* TXDES7 | Transmit Time Stamp High [31:0] | +* ---------------------------------------------------------------------------------------------- +*/ + +/* Bit definition of TXDES6 register */ +#define ETH_DMAPTPTXDESC_TXTSL 0xFFFFFFFFU /*!< Transmit Time Stamp Low */ + +/* Bit definition of TXDES7 register */ +#define ETH_DMAPTPTXDESC_TXTSH 0xFFFFFFFFU /*!< Transmit Time Stamp High */ + +/** + * @} + */ +/** @defgroup ETH_DMA_RX_Descriptor ETH DMA RX Descriptor + * @{ + */ + +/** + *DMA Rx Descriptor + *-------------------------------------------------------------------------------------------------------------------- + *RXDES0 | OWN(31) | Status [30:0] | + *--------------------------------------------------------------------------------------------------------------------- + *RXDES1 | CTRL(31) | Reserved[30:29] | Buffer2 Size[28:16] | CTRL[15:14] | Reserved(13) | Buffer1 Size[12:0] | + *--------------------------------------------------------------------------------------------------------------------- + *RXDES2 | Buffer1 Address [31:0] | + *--------------------------------------------------------------------------------------------------------------------- + *RXDES3 | Buffer2 Address [31:0] / Next Descriptor Address [31:0] | + *--------------------------------------------------------------------------------------------------------------------- +*/ + +/** + * @brief Bit definition of RXDES0 register: DMA Rx descriptor status register + */ +#define ETH_DMARXDESC_OWN 0x80000000U /*!< OWN bit: descriptor is owned by DMA engine */ +#define ETH_DMARXDESC_ADDRF 0x40000000U /*!< DA Filter Fail for the rx frame */ +#define ETH_DMARXDESC_FL 0x3FFF0000U /*!< Receive descriptor frame length */ +#define ETH_DMARXDESC_ERRS 0x00008000U /*!< Error summary: OR of the following bits: DE || OE || IPC || LC || RWT || RE || CE */ +#define ETH_DMARXDESC_DESERR 0x00004000U /*!< Descriptor error: no more descriptors for receive frame */ +#define ETH_DMARXDESC_SADDRF 0x00002000U /*!< SA Filter Fail for the received frame */ +#define ETH_DMARXDESC_LERR 0x00001000U /*!< Frame size not matching with length field */ +#define ETH_DMARXDESC_OFERR 0x00000800U /*!< Overflow Error: Frame was damaged due to buffer overflow */ +#define ETH_DMARXDESC_VLANF 0x00000400U /*!< VLAN Tag: received frame is a VLAN frame */ +#define ETH_DMARXDESC_FDES 0x00000200U /*!< First descriptor of the frame */ +#define ETH_DMARXDESC_LDES 0x00000100U /*!< Last descriptor of the frame */ +#define ETH_DMARXDESC_IPV4HCE 0x00000080U /*!< IPC Checksum Error: Rx Ipv4 header checksum error */ +#define ETH_DMARXDESC_LC 0x00000040U /*!< Late collision occurred during reception */ +#define ETH_DMARXDESC_FT 0x00000020U /*!< Frame type - Ethernet, otherwise 802.3 */ +#define ETH_DMARXDESC_RXWWTTO 0x00000010U /*!< Receive Watchdog Timeout: watchdog timer expired during reception */ +#define ETH_DMARXDESC_RERR 0x00000008U /*!< Receive error: error reported by MII interface */ +#define ETH_DMARXDESC_DERR 0x00000004U /*!< Dribble bit error: frame contains non int multiple of 8 bits */ +#define ETH_DMARXDESC_CERR 0x00000002U /*!< CRC error */ +#define ETH_DMARXDESC_MAMPCE 0x00000001U /*!< Rx MAC Address/Payload Checksum Error: Rx MAC address matched/ Rx Payload Checksum Error */ + +/** + * @brief Bit definition of RXDES1 register + */ +#define ETH_DMARXDESC_DINTC 0x80000000U /*!< Disable Interrupt on Completion */ +#define ETH_DMARXDESC_RXBS2 0x1FFF0000U /*!< Receive Buffer2 Size */ +#define ETH_DMARXDESC_RXER 0x00008000U /*!< Receive End of Ring */ +#define ETH_DMARXDESC_RXCH 0x00004000U /*!< Second Address Chained */ +#define ETH_DMARXDESC_RXBS1 0x00001FFFU /*!< Receive Buffer1 Size */ + +/** + * @brief Bit definition of RXDES2 register + */ +#define ETH_DMARXDESC_B1AP 0xFFFFFFFFU /*!< Buffer1 Address Pointer */ + +/** + * @brief Bit definition of RXDES3 register + */ +#define ETH_DMARXDESC_B2AP 0xFFFFFFFFU /*!< Buffer2 Address Pointer */ + +/** + *--------------------------------------------------------------------------------------------------------------------- + *RXDES4 | Reserved[31:14] | Extended Status [13:0] | + *--------------------------------------------------------------------------------------------------------------------- + *RXDES5 | Reserved[31:0] | + *--------------------------------------------------------------------------------------------------------------------- + *RXDES6 | Receive Time Stamp Low [31:0] | + *--------------------------------------------------------------------------------------------------------------------- + *RXDES7 | Receive Time Stamp High [31:0] | + *--------------------------------------------------------------------------------------------------------------------- +*/ + +/* Bit definition of RXDES4 register */ +#define ETH_DMAPTPRXDESC_PTPV 0x00002000U /*!< PTP Version */ +#define ETH_DMAPTPRXDESC_PTPFT 0x00001000U /*!< PTP Frame Type */ +#define ETH_DMAPTPRXDESC_PTPMT 0x00000F00U /*!< PTP Message Type */ +#define ETH_DMAPTPRXDESC_PTPMT_SYNC 0x00000100U /*!< SYNC message (all clock types) */ +#define ETH_DMAPTPRXDESC_PTPMT_FOLLOWUP 0x00000200U /*!< FollowUp message (all clock types) */ +#define ETH_DMAPTPRXDESC_PTPMT_DELAYREQ 0x00000300U /*!< DelayReq message (all clock types) */ +#define ETH_DMAPTPRXDESC_PTPMT_DELAYRESP 0x00000400U /*!< DelayResp message (all clock types) */ +#define ETH_DMAPTPRXDESC_PTPMT_PDELAYREQ_ANNOUNCE 0x00000500U /*!< PdelayReq message (peer-to-peer transparent clock) or Announce message (Ordinary or Boundary clock) */ +#define ETH_DMAPTPRXDESC_PTPMT_PDELAYRESP_MANAG 0x00000600U /*!< PdelayResp message (peer-to-peer transparent clock) or Management message (Ordinary or Boundary clock) */ +#define ETH_DMAPTPRXDESC_PTPMT_PDELAYRESPFOLLOWUP_SIGNAL 0x00000700U /*!< PdelayRespFollowUp message (peer-to-peer transparent clock) or Signaling message (Ordinary or Boundary clock) */ +#define ETH_DMAPTPRXDESC_IPV6P 0x00000080U /*!< IPv6 Packet Received */ +#define ETH_DMAPTPRXDESC_IPV4P 0x00000040U /*!< IPv4 Packet Received */ +#define ETH_DMAPTPRXDESC_IPCBP 0x00000020U /*!< IP Checksum Bypassed */ +#define ETH_DMAPTPRXDESC_IPPERR 0x00000010U /*!< IP Payload Error */ +#define ETH_DMAPTPRXDESC_IPHERR 0x00000008U /*!< IP Header Error */ +#define ETH_DMAPTPRXDESC_IPPT 0x00000007U /*!< IP Payload Type */ +#define ETH_DMAPTPRXDESC_IPPT_UDP 0x00000001U /*!< UDP payload encapsulated in the IP datagram */ +#define ETH_DMAPTPRXDESC_IPPT_TCP 0x00000002U /*!< TCP payload encapsulated in the IP datagram */ +#define ETH_DMAPTPRXDESC_IPPT_ICMP 0x00000003U /*!< ICMP payload encapsulated in the IP datagram */ + +/* Bit definition of RXDES6 register */ +#define ETH_DMAPTPRXDESC_RXTSL 0xFFFFFFFFU /*!< Receive Time Stamp Low */ + +/* Bit definition of RXDES7 register */ +#define ETH_DMAPTPRXDESC_RXTSH 0xFFFFFFFFU /*!< Receive Time Stamp High */ +/** + * @} + */ + + +/** @addtogroup ETH_Macros Macros + *@{ + */ + +/* ETH Frames defines */ + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /*!< buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /*!< buffer size for transmit */ +#define ETH_RXBUFNB (5U) /*!< 5 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB (5U) /*!< 5 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* ETH_Buffers_setting ETH Buffers setting */ +#define ETH_MAX_PACKET_SIZE 1524U /*!< ETH_HEADER + ETH_EXTRA + ETH_VLAN_TAG + ETH_MAX_ETH_PAYLOAD + ETH_CRC */ +#define ETH_HEADER 14U /*!< 6 byte Dest addr, 6 byte Src addr, 2 byte length/type */ +#define ETH_CRC 4U /*!< Ethernet CRC */ +#define ETH_EXTRA 2U /*!< Extra bytes in some cases */ +#define ETH_VLAN_TAG 4U /*!< optional 802.1q VLAN Tag */ +#define ETH_MIN_ETH_PAYLOAD 46U /*!< Minimum Ethernet payload size */ +#define ETH_MAX_ETH_PAYLOAD 1500U /*!< Maximum Ethernet payload size */ +#define ETH_JUMBO_FRAME_PAYLOAD 9000U /*!< Jumbo frame payload size */ + +/** +* Ethernet driver receive buffers are organized in a chained linked-list, when +* an ethernet packet is received, the Rx-DMA will transfer the packet from RxFIFO +* to the driver receive buffers memory. +* +* Depending on the size of the received ethernet packet and the size of +* each ethernet driver receive buffer, the received packet can take one or more +* ethernet driver receive buffer. +* +* In below are defined the size of one ethernet driver receive buffer ETH_RX_BUF_SIZE +* and the total count of the driver receive buffers ETH_RXBUFNB. +* +* The configured value for ETH_RX_BUF_SIZE and ETH_RXBUFNB are only provided as +* example, they can be reconfigured in the application layer to fit the application +* needs +*/ + +/** Here we configure each Ethernet driver receive buffer to fit the Max size Ethernet +* packet +*/ +#ifndef ETH_RX_BUF_SIZE +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE +#endif + +/* 5 Ethernet driver receive buffers are used (in a chained linked list)*/ +#ifndef ETH_RXBUFNB +#define ETH_RXBUFNB 5U /*!< 5 Rx buffers of size ETH_RX_BUF_SIZE */ +#endif + +/** +* Ethernet driver transmit buffers are organized in a chained linked-list, when +* an ethernet packet is transmitted, Tx-DMA will transfer the packet from the +* driver transmit buffers memory to the TxFIFO. +* +* Depending on the size of the Ethernet packet to be transmitted and the size of +* each ethernet driver transmit buffer, the packet to be transmitted can take +* one or more ethernet driver transmit buffer. +* +* In below are defined the size of one ethernet driver transmit buffer ETH_TX_BUF_SIZE +* and the total count of the driver transmit buffers ETH_TXBUFNB. +* +* The configured value for ETH_TX_BUF_SIZE and ETH_TXBUFNB are only provided as +* example, they can be reconfigured in the application layer to fit the application +* needs +*/ + +/** Here we configure each Ethernet driver transmit buffer to fit the Max size Ethernet +* packet +*/ +#ifndef ETH_TX_BUF_SIZE +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE +#endif + +/* 5 ethernet driver transmit buffers are used (in a chained linked list)*/ +#ifndef ETH_TXBUFNB +#define ETH_TXBUFNB 5U /*!< 5 Tx buffers of size ETH_TX_BUF_SIZE */ +#endif + +/* 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 Errors */ +#define ETH_SUCCESS 1U +#define ETH_ERROR 0U + +/* ETHERNET DMA Tx descriptors Collision Count Shift */ +#define ETH_DMATXDESC_COLLISION_COUNTSHIFT 3U + +/* ETHERNET DMA Tx descriptors Buffer2 Size Shift */ +#define ETH_DMATXDESC_BUFFER2_SIZESHIFT 16U + +/* ETHERNET DMA Rx descriptors Frame Length Shift */ +#define ETH_DMARXDESC_FRAME_LENGTHSHIFT 16U + +/* ETHERNET DMA Rx descriptors Buffer2 Size Shift */ +#define ETH_DMARXDESC_BUFFER2_SIZESHIFT 16U + +/* ETHERNET DMA Rx descriptors Frame length Shift */ +#define ETH_DMARXDESC_FRAMELENGTHSHIFT 16U + +/* ETHERNET MACMIIAR register Mask */ +#define ETH_MACMIIAR_CR_MASK 0xFFFFFFE3U + +/* ETHERNET MACCR register Mask */ +#define ETH_MACCR_CLEAR_MASK 0xFF20010FU + +/* ETHERNET MACFCR register Mask */ +#define ETH_MACFCR_CLEAR_MASK 0x0000FF41U + +/* ETHERNET DMAOMR register Mask */ +#define ETH_DMAOMR_CLEAR_MASK 0xF8DE3F23U + +/* ETHERNET Remote Wake-up frame register length */ +#define ETH_WAKEUP_REGISTER_LENGTH 8U + +/* ETHERNET Missed frames counter Shift */ +#define ETH_DMA_RX_OVERFLOW_MISSEDFRAMES_COUNTERSHIFT 17U + +/* PHY registers defines */ + +/* PHY Read write Timeouts */ +#define PHY_READ_TIMEOUT ((uint32_t)0x0004FFFF) +#define PHY_WRITE_TIMEOUT ((uint32_t)0x0004FFFF) + +/* PHY Register address */ +#define PHY_BCR 0 /*!< Transceiver Basic Control Register */ +#define PHY_BSR 1 /*!< Transceiver Basic Status Register */ +#define PHY_SR 16 /*!< Transceiver Status Register for dp83848 */ + +/* PHY Status Register (PHYSTS), address 0x10 */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< for dp83848 ((uint16_t)0x0010) */ +#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< for dp83848 ((uint16_t)0x0004) */ + +/* PHY basic status register */ +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ + +/* PHY basic Control register */ +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ +#define PHY_RESTAET_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ + +/* PHY Delay */ +#define PHY_RESET_DELAY ((uint32_t)0x000FFFFF) /*!< PHY reset delay */ +#define PHY_CONFIG_DELAY ((uint32_t)0x00FFFFFF) /*!< PHY configuration delay */ +/* Delay to wait when writing to some Ethernet registers */ +#define ETH_REG_WRITE_DELAY ((uint32_t)0x0000FFFF) + +/* Ethernet MAC MII Address Clock Range*/ +#define ETH_MACMIIAR_CR_DIV42 ((uint8_t)0x00) /*!< HCLK:60-100 MHz; MDC clock = HCLK/42 */ +#define ETH_MACMIIAR_CR_DIV62 ((uint8_t)0x01) /*!< HCLK:100-150 MHz; MDC clock = HCLK/62 */ +#define ETH_MACMIIAR_CR_DIV16 ((uint8_t)0x02) /*!< HCLK:20-35 MHz; MDC clock = HCLK/16 */ +#define ETH_MACMIIAR_CR_DIV26 ((uint8_t)0x03) /*!< HCLK:35-60 MHz; MDC clock = HCLK/26 */ +#define ETH_MACMIIAR_CR_DIV102 ((uint8_t)0x04) /*!< HCLK:150-168 MHz; MDC clock = HCLK/102 */ + +/**@} end of group ETH_Macros */ + + +/** @addtogroup ETH_Structure Data Structure + @{ +*/ + +/** + * @brief ETH MAC Config structure types + */ +typedef struct +{ + /* MAC Configuration */ + ETH_AUTONEGOTIATION_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) */ + + ETH_WATCHDOG_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. */ + + ETH_JABBER_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. */ + ETH_INTERFRAMEGAP_T interFrameGap; /*!< Selects the minimum IFG between frames during transmission */ + + ETH_CARRIERSENCE_T carrierSense; /*!< Selects or not the Carrier Sense */ + + ETH_SPEED_T speed; /*!< Sets the Ethernet speed: 10/100 Mbps */ + + ETH_RECEIVEOWN_T receiveOwn; /*!< Selects or not the ReceiveOwn + ReceiveOwn allows the reception of frames when the TX_EN signal is asserted + in Half-Duplex mode */ + + ETH_LOOPBACKMODE_T loopbackMode; /*!< Selects or not the internal MAC MII Loopback mode */ + + ETH_MODE_T mode; /*!< Selects the MAC duplex mode: Half-Duplex or Full-Duplex mode */ + + ETH_CHECKSUMOFFLAOD_T checksumOffload; /*!< Selects or not the IPv4 checksum checking for received frame payloads' TCP/UDP/ICMP headers. */ + + ETH_RETRYTRANSMISSION_T retryTransmission; /*!< Selects or not the MAC attempt retries transmission, based on the settings of BL, + when a collision occurs (Half-Duplex mode) */ + + ETH_AUTOMATICPADCRCSTRIP_T automaticPadCRCStrip; /*!< Selects or not the Automatic MAC Pad/CRC Stripping */ + + ETH_BACKOFFLIMIT_T backOffLimit; /*!< Selects the BackOff limit value */ + + ETH_DEFFERRALCHECK_T deferralCheck; /*!< Selects or not the deferral check function (Half-Duplex mode) */ + + ETH_RECEIVEAll_T receiveAll; /*!< Selects or not all frames reception by the MAC (No filtering) */ + + ETH_SOURCEADDRFILTER_T sourceAddrFilter; /*!< Selects the Source Address Filter mode */ + + ETH_PASSCONTROLFRAMES_T passControlFrames; /*!< Sets the forwarding mode of the control frames (including unicast and multicast PAUSE frames) */ + + ETH_BROADCASTFRAMESRECEPTION_T broadcastFramesReception; /*!< Selects or not the reception of Broadcast Frames */ + + ETH_DESTINATIONADDRFILTER_T destinationAddrFilter; /*!< Sets the destination filter mode for both unicast and multicast frames */ + + ETH_PROMISCUOUS_MODE_T promiscuousMode; /*!< Selects or not the Promiscuous Mode */ + + ETH_MULTICASTFRAMESFILTER_T multicastFramesFilter; /*!< Selects the Multicast Frames filter mode */ + + ETH_UNICASTFRAMESFILTER_T unicastFramesFilter; /*!< Selects the Unicast Frames filter mode */ + + + 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<=0xFFFF) to be used in the Pause Time */ + + ETH_ZEROQUANTAPAUSE_T zeroQuantaPause; /*!< Selects or not the automatic generation of Zero-Quanta Pause Control frames */ + + ETH_PAUSELOWTHRESHOLD_T pauseLowThreshold; /*!< This field configures the threshold of the PAUSE to be checked for + automatic retransmission of PAUSE Frame */ + + ETH_UNICASTPAUSEFRAMEDETECT_T unicastPauseFrameDetect; /*!< Selects or not the MAC detection of the Pause frames (with MAC Address0 + unicast address and unique multicast address) */ + + ETH_RECEIVEFLOWCONTROL_T receiveFlowControl; /*!< Enables or disables the MAC to decode the received Pause frame and + disable its transmitter for a specified time (Pause Time) */ + + ETH_TRANSMITFLOWCONTROL_T transmitFlowControl; /*!< Enables or disables the MAC to transmit Pause frames (Full-Duplex mode) + or the MAC back-pressure operation (Half-Duplex mode) */ + + ETH_VLANTAGCOMPARISON_T VLANTagComparison; /*!< Selects the 12-bit VLAN identifier or the complete 16-bit VLAN tag for + comparison and filtering */ + + uint32_t VLANTagIdentifier; /*!< Holds the (value <=0xFFFF) VLAN tag identifier for receive frames */ + + /* DMA Configuration */ + ETH_DROPTCPIPCHECKSUMERRORFRAME_T dropTCPIPChecksumErrorFrame; /*!< Selects or not the Dropping of TCP/IP Checksum Error Frames */ + + ETH_RECEIVESTOREFORWARD_T receiveStoreForward; /*!< Enables or disables the Receive store and forward mode */ + + ETH_FLUSHRECEIVEDFRAME_T flushReceivedFrame; /*!< Enables or disables the flushing of received frames */ + + ETH_TRANSMITSTOREFORWARD_T transmitStoreForward; /*!< Enables or disables Transmit store and forward mode */ + + ETH_TRANSMITTHRESHOLDCONTROL_T transmitThresholdControl; /*!< Selects or not the Transmit Threshold Control */ + + ETH_FORWARDERRORFRAMES_T forwardErrorFrames; /*!< Selects or not the forward to the DMA of erroneous frames */ + + ETH_FORWARDUNDERSIZEDGOODFRAMES_T forwardUndersizedGoodFrames; /*!< Enables or disables the Rx FIFO to forward Undersized frames (frames with no Error + and length less than 64 bytes) including pad-bytes and CRC) */ + + ETH_RECEIVEDTHRESHOLDCONTROL_T receiveThresholdControl; /*!< Selects the threshold level of the Receive FIFO */ + + ETH_SECONDFRAMEOPERARTE_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. */ + + ETH_ADDRESSALIGNEDBEATS_T addressAlignedBeats; /*!< Enables or disables the Address Aligned Beats */ + + ETH_FIXEDBURST_T fixedBurst; /*!< Enables or disables the AHB Master interface fixed burst transfers */ + + ETH_RXDMABURSTLENGTH_T rxDMABurstLength; /*!< Indicates the maximum number of beats to be transferred in one Rx DMA transaction */ + + ETH_TXDMABURSTLENGTH_T txDMABurstLength; /*!< Indicates the maximum number of beats to be transferred in one Tx DMA transaction */ + + uint32_t descriptorSkipLength; /*!< Specifies the number of word to skip between two unchained descriptors (Ring mode) (value <= 0x1F) */ + + ETH_DMAARBITRATION_T DMAArbitration; /*!< Selects the DMA Tx/Rx arbitration */ +} ETH_Config_T; + +/** + * @brief ETH DMA Descriptors data structure types + */ +typedef struct +{ + __IO uint32_t Status; /*!< Status */ + uint32_t ControlBufferSize; /*!< Control and Buffer1, Buffer2 lengths */ + uint32_t Buffer1Addr; /*!< Buffer1 address pointer */ + uint32_t Buffer2NextDescAddr; /*!< Buffer2 or next descriptor address pointer */ + /* Enhanced ETHERNET DMA PTP Descriptors */ +} ETH_DMADescConfig_T; + +/** + * @brief ETH DMA Descriptors data structure types + */ +typedef struct +{ + uint32_t length; /*!< Data length */ + uint32_t buffer; /*!< Data buffer */ + __IO ETH_DMADescConfig_T* descriptor; /*!< DMA descriptor */ +} ETH_Frame_T; + +/** + * @brief ETH DMA Descriptors Received Frame Informations structure types + */ +typedef struct +{ + __IO ETH_DMADescConfig_T* FS_RxDesc; /*!< First Segment Rx Desc */ + __IO ETH_DMADescConfig_T* LS_RxDesc; /*!< Last Segment Rx Desc */ + __IO uint32_t segCount; /*!< Segment count */ +} ETH_DMARxFrameInformations; + +/**@} end of group ETH_Structure*/ + +/** @defgroup ETH_Functions + @{ +*/ + +/* ETH Configuration */ +void ETH_Reset(void); +void ETH_ConfigStructInit(ETH_Config_T* ethConfig); +uint32_t ETH_Config(ETH_Config_T* ethConfig, uint16_t addr); +void ETH_SoftwareReset(void); +uint8_t ETH_ReadSoftwareReset(void); +void ETH_Start(void); +void ETH_Stop(void); +uint32_t ETH_ReadRxPacketSize(ETH_DMADescConfig_T* DMARxDesc); + +/* PHY */ +uint16_t ETH_ReadPHYRegister(uint16_t addr, uint16_t reg); +uint32_t ETH_WritePHYRegister(uint16_t addr, uint16_t reg, uint16_t data); +uint32_t ETH_EnablePHYLoopBack(uint16_t addr); +uint32_t ETH_DisablePHYLoopBack(uint16_t addr); + +/* MAC */ +void ETH_EnableMACTransmission(void); +void ETH_DisableMACTransmission(void); +void ETH_EnableMACReceiver(void); +void ETH_DisableMACReceiver(void); +uint8_t ETH_ReadFlowControlBusyStatus(void); +void ETH_SetPauseControlFrame(void); +void ETH_EnableBackPressureActivation(void); +void ETH_DisableBackPressureActivation(void); +uint8_t ETH_ReadMACFlagStatus(ETH_MAC_FLAG_T flag); +void ETH_EnableMACInterrupt(uint32_t interrupt); +void ETH_DisableMACInterrupt(uint32_t interrupt); +void ETH_ConfigMACAddress(ETH_MAC_ADDRESS_T macAddr, uint8_t* addr); +void ETH_ReadMACAddress(ETH_MAC_ADDRESS_T macAddr, uint8_t* addr); +void ETH_EnableMACAddressPerfectFilter(ETH_MAC_ADDRESS_T macAddr); +void ETH_DisableMACAddressPerfectFilter(ETH_MAC_ADDRESS_T macAddr); +void ETH_ConfigMACAddressFilter(ETH_MAC_ADDRESS_T macAddr, ETH_MAC_ADDRESSFILTER_T filter); +void ETH_ConfigMACAddressMaskBytesFilter(ETH_MAC_ADDRESS_T macAddr, uint32_t maskByte); + +/* DMA descriptors */ +void ETH_ConfigDMARxDescChain(ETH_DMADescConfig_T* DMARxDescTab, uint8_t* rxBuff, uint32_t rxBuffcount); +void ETH_ConfigDMATxDescChain(ETH_DMADescConfig_T* DMATxDescTab, uint8_t* txBuff, uint32_t txBuffcount); +uint32_t ETH_CheckReceivedFrame(void); +uint32_t ETH_Transmit_Descriptors(u16 frameLength); +ETH_Frame_T ETH_ReadReceivedFrame(void); +uint8_t ETH_ReadDMATxDescFlagStatus(ETH_DMADescConfig_T* DMATxDesc, ETH_DMATXDESC_FLAG_T flag); +uint32_t ETH_ReadDMATxDescCollisionCount(ETH_DMADescConfig_T* DMATxDesc); +void ETH_ConfigDMATxDescOwnBit(ETH_DMADescConfig_T* DMATxDesc); +void ETH_EnableDMATxDescTransmitInterrupt(ETH_DMADescConfig_T* DMATxDesc); +void ETH_DisableDMATxDescTransmitInterrupt(ETH_DMADescConfig_T* DMATxDesc); +void ETH_ConfigDMATxDescFrameSegment(ETH_DMADescConfig_T* DMATxDesc, ETH_DMATXDESC_SEGMENTS_T frameSegment); +void ETH_ConfigDMATxDescChecksumInsertion(ETH_DMADescConfig_T* DMATxDesc, ETH_DMATXDESC_CHECKSUMB_T checksum); +void ETH_EnableDMATxDescCRC(ETH_DMADescConfig_T* DMATxDesc); +void ETH_DisableDMATxDescCRC(ETH_DMADescConfig_T* DMATxDesc); +void ETH_EnableDMATxDescSecondAddressChained(ETH_DMADescConfig_T* DMATxDesc); +void ETH_DisableDMATxDescSecondAddressChained(ETH_DMADescConfig_T* DMATxDesc); +void ETH_EnableDMATxDescShortFramePadding(ETH_DMADescConfig_T* DMATxDesc); +void ETH_DisableDMATxDescShortFramePadding(ETH_DMADescConfig_T* DMATxDesc); +void ETH_ConfigDMATxDescBufferSize(ETH_DMADescConfig_T* DMATxDesc, uint32_t bufferSize1, uint32_t bufferSize2); +uint8_t ETH_ReadDMARxDescFlagStatus(ETH_DMADescConfig_T* DMARxDesc, ETH_DMARXDESC_FLAG_T flag); + +void ETH_ConfigDMARxDescOwnBit(ETH_DMADescConfig_T* DMARxDesc); +uint32_t ETH_ReadDMARxDescFrameLength(ETH_DMADescConfig_T* DMARxDesc); +void ETH_EnableDMARxDescReceiveInterrupt(ETH_DMADescConfig_T* DMARxDesc); +void ETH_DisableDMARxDescReceiveInterrupt(ETH_DMADescConfig_T* DMATxDesc); +uint32_t ETH_ReadDMARxDescBufferSize(ETH_DMADescConfig_T* DMARxDesc, ETH_DMARXDESC_BUFFER_T buffer); +ETH_Frame_T ETH_ReadReceivedFrameInterrupt(void); + +/* DMA */ +uint8_t ETH_ReadDMAFlagStatus(ETH_DMA_FLAG_T flag); +void ETH_ClearDMAFlag(uint32_t flag); +uint8_t ETH_ReadDMAIntFlag(ETH_DMA_INT_T flag); +void ETH_ClearDMAIntFlag(uint32_t flag); +uint32_t ETH_ReadTransmitProcessState(void); +uint32_t ETH_ReadReceiveProcessState(void); +void ETH_FlushTransmitFIFO(void); +uint8_t ETH_ReadFlushTransmitFIFOStatus(void); +void ETH_EnableDMATransmission(void); +void ETH_DisableDMATransmission(void); +void ETH_EnableDMAReceiver(void); +void ETH_DisableDMAReceiver(void); +void ETH_EnableDMAInterrupt(uint32_t interrupt); +void ETH_DisableDMAInterrupt(uint32_t interrupt); +uint8_t ETH_ReadDMAOverflowStatus(ETH_DMA_OVERFLOW_T overflow); +uint32_t ETH_ReadRxOverflowMissedFrameCounter(void); +uint32_t ETH_ReadBufferUnavailableMissedFrameCounter(void); +uint32_t ETH_ReadCurrentTxDescStartAddress(void); +uint32_t ETH_ReadCurrentRxDescStartAddress(void); +uint32_t ETH_ReadCurrentTxBufferAddress(void); +uint32_t ETH_ReadCurrentRxBufferAddress(void); +void ETH_ResetDMATransmission(void); +void ETH_ResetDMAReception(void); + +/* PMT */ +void ETH_ResetWakeUpFrameFilterRegisterPointer(void); +void ETH_EnableGlobalUnicastWakeUp(void); +void ETH_DisableGlobalUnicastWakeUp(void); +uint8_t ETH_ReadPMTFlagStatus(ETH_PMT_FLAG_T flag); +void ETH_EnableWakeUpFrameDetection(void); +void ETH_DisableWakeUpFrameDetection(void); +void ETH_EnableMagicPacketDetection(void); +void ETH_DisableMagicPacketDetection(void); +void ETH_EnablePowerDown(void); +void ETH_DisablePowerDown(void); + +/* MMC */ +void ETH_EnableMMCCounterFreeze(void); +void ETH_DisableMMCCounterFreeze(void); +void ETH_EnableMMCResetOnRead(void); +void ETH_DisableMMCResetOnRead(void); +void ETH_EnableMMCCounterRollover(void); +void ETH_DisableMMCCounterRollover(void); +void ETH_ResetMMCCounters(void); +void ETH_EnableMMCInterrupt(uint32_t interrupt); +void ETH_DisableMMCInterrupt(uint32_t interrupt); +uint8_t ETH_ReadMMCIntFlag(uint32_t flag); +uint32_t ETH_ReadMMCRegister(ETH_MMC_REG_T MMCReg); + +/**@} end of group ETH_Functions */ +/**@} end of group ETH_Driver */ +/**@} end of group APM32F10x_ETHDriver */ + +#ifdef __cplusplus +} +#endif + +#endif /* __APM32F10x_ETH_H */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_ETH_Driver/src/apm32f10x_eth.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_ETH_Driver/src/apm32f10x_eth.c new file mode 100644 index 0000000000..46842e2a0a --- /dev/null +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_ETH_Driver/src/apm32f10x_eth.c @@ -0,0 +1,2203 @@ +/*! + * @file apm32f10x_eth.c + * + * @brief This file provides all the ETH firmware functions + * + * @version V1.0.3 + * + * @date 2022-12-01 + * + * @attention + * + * Copyright (C) 2021-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +#if defined(APM32F10X_CL) + +#include "apm32f10x_eth.h" +#include "apm32f10x_rcm.h" + +/** @addtogroup APM32F10x_ETHDriver + @{ +*/ + +/** @defgroup ETH_Driver + * @brief ETH driver modules + @{ +*/ + +#if defined (__CC_ARM) /*!< ARM Compiler */ + __align(4) + ETH_DMADescConfig_T DMARxDscrTab[ETH_RXBUFNB]; /*!< Ethernet Rx MA Descriptor */ + __align(4) + ETH_DMADescConfig_T DMATxDscrTab[ETH_TXBUFNB]; /*!< Ethernet Tx DMA Descriptor */ + __align(4) + uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE]; /*!< Ethernet Receive Buffer */ + __align(4) + uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE]; /*!< Ethernet Transmit Buffer */ + +#elif defined ( __ICCARM__ ) + + ETH_DMADescConfig_T DMARxDscrTab[ETH_RXBUFNB]; /*!< Ethernet Rx MA Descriptor */ + ETH_DMADescConfig_T DMATxDscrTab[ETH_TXBUFNB]; /*!< Ethernet Tx DMA Descriptor */ + uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE]; /*!< Ethernet Receive Buffer */ + uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE]; /*!< Ethernet Transmit Buffer */ + +#elif defined (__GNUC__) /*!< GNU Compiler */ +ETH_DMADescConfig_T DMARxDscrTab[ETH_RXBUFNB] __attribute__ ((aligned (4))); /*!< Ethernet Rx MA Descriptor */ +ETH_DMADescConfig_T DMATxDscrTab[ETH_TXBUFNB] __attribute__ ((aligned (4))); /*!< Ethernet Tx DMA Descriptor */ +uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __attribute__ ((aligned (4))); /*!< Ethernet Receive Buffer */ +uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __attribute__ ((aligned (4))); /*!< Ethernet Transmit Buffer */ + +#endif + +/** @defgroup Global_Definition + @{ +*/ + +/* Global pointers on Tx and Rx descriptor used to transmit and receive descriptors */ +__IO ETH_DMADescConfig_T* DMATxDescToSet; +__IO ETH_DMADescConfig_T* DMARxDescToGet; + +/* Structure used to hold the last received packet descriptors info */ +ETH_DMARxFrameInformations RxFrameDescriptor; +__IO ETH_DMARxFrameInformations* DMARxFraminfos; +__IO uint32_t FrameRxindex; + +/** + * @} + */ + +/** @defgroup ETH_Functions + @{ +*/ + +/*! + * @brief Inserts a delay time. + * + * @param count: specifies the delay time length. + * + * @retval None + */ +static void ETH_Delay(__IO uint32_t count) +{ + __IO uint32_t i = 0; + for (i = count; i != 0; i--) + { + } +} + +/* ETH Configuration */ + +/*! + * @brief Reset ETH peripheral registers to their default reset values. + * + * @param None + * + * @retval None + */ +void ETH_Reset(void) +{ + RCM_EnableAHBPeriphReset(RCM_AHB_PERIPH_ETH_MAC); + + RCM_DisableAHBPeriphReset(RCM_AHB_PERIPH_ETH_MAC); +} + +/*! + * @brief Config ETH_Config_T member with its default value. + * + * @param ethConfig: pointer to a ETH_Config_T structure which will be initialized. + * + * @retval None + */ +void ETH_ConfigStructInit(ETH_Config_T* ethConfig) +{ + /* MAC Configuration */ + ethConfig->autoNegotiation = ETH_AUTONEGOTIATION_ENABLE; + ethConfig->watchDog = ETH_WATCHDOG_ENABLE; + ethConfig->jabber = ETH_JABBER_ENABLE; + ethConfig->interFrameGap = ETH_INTERFRAMEGAP_96BIT; + ethConfig->carrierSense = ETH_CARRIERSENCE_ENABLE; + ethConfig->speed = ETH_SPEED_100M; + ethConfig->receiveOwn = ETH_RECEIVEOWN_ENABLE; + ethConfig->loopbackMode = ETH_LOOPBACKMODE_DISABLE; + ethConfig->mode = ETH_MODE_FULLDUPLEX; + ethConfig->checksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE; + ethConfig->retryTransmission = ETH_RETRYTRANSMISSION_ENABLE; + ethConfig->automaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE; + ethConfig->backOffLimit = ETH_BACKOFFLIMIT_10; + ethConfig->deferralCheck = ETH_DEFFERRALCHECK_DISABLE; + ethConfig->receiveAll = ETH_RECEIVEAll_DISABLE; + ethConfig->sourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE; + ethConfig->passControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL; + ethConfig->broadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_DISABLE; + ethConfig->destinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL; + ethConfig->promiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE; + ethConfig->multicastFramesFilter = ETH_MULTICASTFRAMESFILTER_PERFECT; + ethConfig->unicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT; + ethConfig->hashTableHigh = 0x0000; + ethConfig->hashTableLow = 0x0000; + ethConfig->pauseTime = 0x0000; + ethConfig->zeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE; + ethConfig->pauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4; + ethConfig->unicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE; + ethConfig->receiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE; + ethConfig->transmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE; + ethConfig->VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT; + ethConfig->VLANTagIdentifier = 0x0000; + /* DMA Configuration */ + ethConfig->dropTCPIPChecksumErrorFrame = ETH_DROPTCPIPCHECKSUMERRORFRAME_DISABLE; + ethConfig->receiveStoreForward = ETH_RECEIVESTOREFORWARD_ENABLE; + ethConfig->flushReceivedFrame = ETH_FLUSHRECEIVEDFRAME_ENABLE; + ethConfig->transmitStoreForward = ETH_TRANSMITSTOREFORWARD_ENABLE; + ethConfig->transmitThresholdControl = ETH_TRANSMITTHRESHOLDCONTROL_64BYTES; + ethConfig->forwardErrorFrames = ETH_FORWARDERRORFRAMES_DISABLE; + ethConfig->forwardUndersizedGoodFrames = ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE; + ethConfig->receiveThresholdControl = ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES; + ethConfig->secondFrameOperate = ETH_SECONDFRAMEOPERARTE_DISABLE; + ethConfig->addressAlignedBeats = ETH_ADDRESSALIGNEDBEATS_ENABLE; + ethConfig->fixedBurst = ETH_FIXEDBURST_ENABLE; + ethConfig->rxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT; + ethConfig->txDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT; + ethConfig->descriptorSkipLength = 0x00; + ethConfig->DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1; +} + +/*! + * @brief Config the ETH peripheral parameters in the ethConfig. + * + * @param ethConfig: pointer to a ETH_Config_T structure. + * + * @param addr: external PHY address + * + * @retval ETH_ERROR: Ethernet initialization error + * ETH_SUCCESS: Ethernet initialization success + */ +uint32_t ETH_Config(ETH_Config_T* ethConfig, uint16_t addr) +{ + uint32_t regValue = 0; + uint32_t hclk = 60000000; + __IO uint32_t timeout = 0, err = ETH_SUCCESS; + + hclk = RCM_ReadHCLKFreq(); + + if ((hclk >= 20000000) && (hclk <= 35000000)) + { + ETH->ADDR_B.CR = ETH_MACMIIAR_CR_DIV16; + } + else if ((hclk >= 35000000) && (hclk < 60000000)) + { + ETH->ADDR_B.CR = ETH_MACMIIAR_CR_DIV26; + } + else if ((hclk >= 60000000) && (hclk < 100000000)) + { + ETH->ADDR_B.CR = ETH_MACMIIAR_CR_DIV42; + } + else if ((hclk >= 100000000) && (hclk < 150000000)) + { + ETH->ADDR_B.CR = ETH_MACMIIAR_CR_DIV62; + } + else + { + ETH->ADDR_B.CR = ETH_MACMIIAR_CR_DIV102; + } + + /* PHY initialization and configuration */ + if (!(ETH_WritePHYRegister(addr, PHY_BCR, PHY_RESET))) + { + /* Return ERROR in case of write timeout */ + err = ETH_ERROR; + goto error; + } + + ETH_Delay(PHY_RESET_DELAY); + + if (ethConfig->autoNegotiation == ETH_AUTONEGOTIATION_ENABLE) + { + /* Wait for linked status */ + do + { + timeout++ ; + } + while (!(ETH_ReadPHYRegister(addr, PHY_BSR) & PHY_LINKED_STATUS) && (timeout < PHY_READ_TIMEOUT)); + + /* Return ERROR in case of timeout */ + if (timeout == PHY_READ_TIMEOUT) + { + err = ETH_ERROR; + goto error; + } + + timeout = 0; + /* Enable Auto-Negotiation */ + if (!(ETH_WritePHYRegister(addr, PHY_BCR, PHY_AUTONEGOTIATION))) + { + /* Return ERROR in case of write timeout */ + err = ETH_ERROR; + } + + /* Wait until the auto-negotiation will be completed */ + do + { + timeout++; + } + while (!(ETH_ReadPHYRegister(addr, PHY_BSR) & PHY_AUTONEGO_COMPLETE) && (timeout < (uint32_t)PHY_READ_TIMEOUT)); + + /* Return ERROR in case of timeout */ + if (timeout == PHY_READ_TIMEOUT) + { + err = ETH_ERROR; + goto error; + } + + timeout = 0; + /* Read the result of the auto-negotiation */ + regValue = ETH_ReadPHYRegister(addr, PHY_SR); + + if ((regValue & PHY_DUPLEX_STATUS) != (uint32_t)RESET) + { + ethConfig->mode = ETH_MODE_FULLDUPLEX; + } + else + { + ethConfig->mode = ETH_MODE_HALFDUPLEX; + } + if (regValue & PHY_SPEED_STATUS) + { + ethConfig->speed = ETH_SPEED_10M; + } + else + { + ethConfig->speed = ETH_SPEED_100M; + } + } + else + { + if (!ETH_WritePHYRegister(addr, PHY_BCR, ((uint16_t)(ethConfig->speed << 8) | + (uint16_t)(ethConfig->mode << 13)))) + { + err = ETH_ERROR; + } + + ETH_Delay(PHY_CONFIG_DELAY); + } +error: + if (err == ETH_ERROR) + { + ethConfig->speed = ETH_SPEED_100M; + ethConfig->mode = ETH_MODE_FULLDUPLEX; + } + + /* ETHERNET MAC_CFG Configuration */ + ETH->CFG_B.WDTDIS = ethConfig->watchDog; + ETH->CFG_B.JDIS = ethConfig->jabber; + ETH->CFG_B.IFG = ethConfig->interFrameGap; + ETH->CFG_B.DISCRS = ethConfig->carrierSense; + ETH->CFG_B.SSEL = ethConfig->speed; + ETH->CFG_B.DISRXO = ethConfig->receiveOwn; + ETH->CFG_B.LBM = ethConfig->loopbackMode; + ETH->CFG_B.DM = ethConfig->mode; + ETH->CFG_B.IPC = ethConfig->checksumOffload; + ETH->CFG_B.DISR = ethConfig->retryTransmission; + ETH->CFG_B.ACS = ethConfig->automaticPadCRCStrip; + ETH->CFG_B.BL = ethConfig->backOffLimit; + ETH->CFG_B.DC = ethConfig->deferralCheck; + ETH_Delay(ETH_REG_WRITE_DELAY); + + /* ETHERNET MAC_FRAF Configuration */ + ETH->FRAF_B.RXA = ethConfig->receiveAll; + ETH->FRAF |= ethConfig->sourceAddrFilter; + ETH->FRAF_B.PCTRLF = ethConfig->passControlFrames; + ETH->FRAF_B.DISBF = ethConfig->broadcastFramesReception; + ETH->FRAF_B.DAIF = ethConfig->destinationAddrFilter; + ETH->FRAF_B.PR = ethConfig->promiscuousMode; + ETH->FRAF |= ethConfig->multicastFramesFilter; + ETH->FRAF |= ethConfig->unicastFramesFilter; + ETH_Delay(ETH_REG_WRITE_DELAY); + + /* ETHERNET MAC_HTH/HTL Configuration */ + ETH->HTH = ethConfig->hashTableHigh; + ETH->HTL = ethConfig->hashTableLow; + + /* ETHERNET MAC_FCTRL Configuration */ + ETH->FCTRL_B.PT = ethConfig->pauseTime; + ETH->FCTRL_B.ZQPDIS = ethConfig->zeroQuantaPause; + ETH->FCTRL_B.PTSEL = ethConfig->pauseLowThreshold; + ETH->FCTRL_B.UNPFDETE = ethConfig->unicastPauseFrameDetect; + ETH->FCTRL_B.RXFCTRLEN = ethConfig->receiveFlowControl; + ETH->FCTRL_B.TXFCTRLEN = ethConfig->transmitFlowControl; + ETH_Delay(ETH_REG_WRITE_DELAY); + + /* ETHERNET MAC_VLANT Configuration */ + ETH->VLANT_B.VLANTCOMP = ethConfig->VLANTagComparison; + ETH->VLANT_B.VLANTID = ethConfig->VLANTagIdentifier; + ETH_Delay(ETH_REG_WRITE_DELAY); + + /* ETHERNET DMA_OPMOD Configuration */ + ETH->DMAOPMOD_B.DISDT = ethConfig->dropTCPIPChecksumErrorFrame; + ETH->DMAOPMOD_B.RXSF = ethConfig->receiveStoreForward; + ETH->DMAOPMOD_B.DISFRXF = ethConfig->flushReceivedFrame; + ETH->DMAOPMOD_B.TXSF = ethConfig->transmitStoreForward; + ETH->DMAOPMOD_B.TXTHCTRL = ethConfig->transmitThresholdControl; + ETH->DMAOPMOD_B.FERRF = ethConfig->forwardErrorFrames; + ETH->DMAOPMOD_B.FUF = ethConfig->forwardUndersizedGoodFrames; + ETH->DMAOPMOD_B.RXTHCTRL = ethConfig->receiveThresholdControl; + ETH->DMAOPMOD_B.OSECF = ethConfig->secondFrameOperate; + ETH_Delay(ETH_REG_WRITE_DELAY); + + /* ETHERNET DMA_BMOD Configuration */ + ETH->DMABMOD = RESET; + ETH->DMABMOD_B.AAL = ethConfig->addressAlignedBeats; + ETH->DMABMOD_B.FB = ethConfig->fixedBurst; + ETH->DMABMOD |= ethConfig->rxDMABurstLength; + ETH->DMABMOD |= ethConfig->txDMABurstLength; + ETH->DMABMOD_B.DSL = ethConfig->descriptorSkipLength; + ETH->DMABMOD |= ethConfig->DMAArbitration; + ETH->DMABMOD_B.USP = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); + + if (err == ETH_SUCCESS) + { + return ETH_SUCCESS; + } + else + { + return ETH_ERROR; + } +} + +/*! + * @brief Resets all MAC subsystem internal registers and logic. + * + * @param None + * + * @retval None + */ +void ETH_SoftwareReset(void) +{ + ETH->DMABMOD_B.SWR = SET; +} + +/*! + * @brief Read the ETH software reset bit. + * + * @param None + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadSoftwareReset(void) +{ + return ETH->DMABMOD_B.SWR; +} + +/*! + * @brief Enables ETH MAC and DMA reception/transmission + * + * @param None + * + * @retval None + */ +void ETH_Start(void) +{ + ETH_EnableMACTransmission(); + ETH_EnableMACReceiver(); + ETH_FlushTransmitFIFO(); + ETH_EnableDMATransmission(); + ETH_EnableDMAReceiver(); +} + +/*! + * @brief Disables ETH MAC and DMA reception/transmission + * + * @param None + * + * @retval None + */ +void ETH_Stop(void) +{ + ETH_DisableDMATransmission(); + ETH_DisableDMAReceiver(); + ETH_DisableMACReceiver(); + ETH_FlushTransmitFIFO(); + ETH_DisableMACTransmission(); +} + +/*! + * @brief Read the size of the received packet. + * + * @param None + * + * @retval frameLength: received packet size + */ +uint32_t ETH_ReadRxPacketSize(ETH_DMADescConfig_T* DMARxDesc) +{ + uint32_t frameLength = 0; + if (((DMARxDesc->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET) && + ((DMARxDesc->Status & ETH_DMARXDESC_ERRS) == (uint32_t)RESET) && + ((DMARxDesc->Status & ETH_DMARXDESC_LDES) != (uint32_t)RESET)) + { + frameLength = ETH_ReadDMARxDescFrameLength(DMARxDesc); + } + return frameLength; +} + +/* PHY functions */ + +/*! + * @brief Read a PHY register + * + * @param addr: PHY device address + * This parameter can be one of the following values: 0,..,31 + * + * @param reg: PHY register + * This parameter can be one of the following values: + * @arg PHY_BCR : Transceiver Basic Control Register + * @arg PHY_BSR : Transceiver Basic Status Register + * @arg PHY_SR : Transceiver Status Register + * + * @retval ETH_ERROR: in case of timeout + * MAC DATA register value: Data read from the selected PHY register + */ +uint16_t ETH_ReadPHYRegister(uint16_t addr, uint16_t reg) +{ + __IO uint32_t timeout = 0; + + ETH->ADDR_B.PA = addr; + ETH->ADDR_B.MR = reg; + ETH->ADDR_B.MW = RESET; + ETH->ADDR_B.MB = SET; + /* Check for the Busy flag */ + do + { + timeout++ ; + } + while ((ETH->ADDR_B.MB == SET) && (timeout < PHY_READ_TIMEOUT)); + /* Return ERROR in case of timeout */ + if (timeout == PHY_READ_TIMEOUT) + { + return ETH_ERROR; + } + /* Return data register value */ + return (uint16_t)(ETH->DATA); +} + +/*! + * @brief Write to a PHY register + * + * @param addr: PHY device address + * This parameter can be one of the following values: 0,..,31 + + * @param reg: PHY register + * This parameter can be one of the following values: + * @arg PHY_BCR : Transceiver Basic Control Register + + * @param data: the data to write + * + * @retval ETH_ERROR: write timeout + * ETH_SUCCESS: write success + */ +uint32_t ETH_WritePHYRegister(uint16_t addr, uint16_t reg, uint16_t data) +{ + __IO uint32_t timeout = 0; + + ETH->DATA = data; + ETH->ADDR_B.PA = addr; + ETH->ADDR_B.MR = reg; + ETH->ADDR_B.MW = SET; + ETH->ADDR_B.MB = SET; + + /* Check for the Busy flag */ + do + { + timeout++ ; + } + while ((ETH->ADDR_B.MB == SET) && (timeout < PHY_WRITE_TIMEOUT)); + /* Return ERROR in case of timeout */ + if (timeout == PHY_WRITE_TIMEOUT) + { + return ETH_ERROR; + } + /* Return data register value */ + return ETH_SUCCESS; +} + +/*! + * @brief Enable the PHY loopBack mode. + * + * @param addr: PHY device address + * This parameter can be one of the following values: 0,..,31 + * + * @retval ETH_ERROR or ETH_SUCCESS + */ +uint32_t ETH_EnablePHYLoopBack(uint16_t addr) +{ + uint16_t temp = 0; + + temp = ETH_ReadPHYRegister(addr, PHY_BCR); + temp |= PHY_LOOPBACK; + + if (ETH_WritePHYRegister(addr, PHY_BCR, temp) == SET) + { + return ETH_SUCCESS; + } + else + { + return ETH_ERROR; + } +} + +/*! + * @brief Disable the PHY loopBack mode. + * + * @param addr: PHY device address + * This parameter can be one of the following values: 0,..,31 + * + * @retval ETH_ERROR or ETH_SUCCESS + */ +uint32_t ETH_DisablePHYLoopBack(uint16_t addr) +{ + uint16_t temp = 0; + + temp = ETH_ReadPHYRegister(addr, PHY_BCR); + temp &= ((uint16_t)~PHY_LOOPBACK); + + if (ETH_WritePHYRegister(addr, PHY_BCR, temp) == SET) + { + return ETH_SUCCESS; + } + else + { + return ETH_ERROR; + } +} + +/* MAC functions */ + +/*! + * @brief Enable the MAC transmission. + * + * @param None + * + * @retval None + */ +void ETH_EnableMACTransmission(void) +{ + ETH->CFG_B.TXEN = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable the MAC transmission. + * + * @param None + * + * @retval None + */ +void ETH_DisableMACTransmission(void) +{ + ETH->CFG_B.TXEN = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Enable the MAC receiver. + * + * @param None + * + * @retval None + */ +void ETH_EnableMACReceiver(void) +{ + ETH->CFG_B.RXEN = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable the MAC receiver. + * + * @param None + * + * @retval None + */ +void ETH_DisableMACReceiver(void) +{ + ETH->CFG_B.RXEN = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Read the ETH flow control busy status + * + * @param None + * + * @retval SET or RESET + */ +uint8_t ETH_ReadFlowControlBusyStatus(void) +{ + return ETH->FCTRL_B.FCTRLB; +} + +/*! + * @brief Set a Pause Control Frame (Full-duplex only). + * + * @param None + * + * @retval None + */ +void ETH_SetPauseControlFrame(void) +{ + ETH->FCTRL_B.FCTRLB = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Enable the MAC Back Pressure operation activation (Half-duplex only). + * + * @param None + * + * @retval None + */ +void ETH_EnableBackPressureActivation(void) +{ + ETH->FCTRL_B.FCTRLB = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable the MAC Back Pressure operation activation (Half-duplex only). + * + * @param None + * + * @retval None + */ +void ETH_DisableBackPressureActivation(void) +{ + ETH->FCTRL_B.FCTRLB = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Read the specified ETH MAC flag + * + * @param flag: Ethernet MAC flag: + * This parameter can be one of the following values: + * @arg ETH_MAC_FLAG_TST : Time stamp trigger flag + * @arg ETH_MAC_FLAG_MMCT : MMC transmit flag + * @arg ETH_MAC_FLAG_MMCR : MMC receive flag + * @arg ETH_MAC_FLAG_MMC : MMC flag + * @arg ETH_MAC_FLAG_PMT : PMT flag + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadMACFlagStatus(ETH_MAC_FLAG_T flag) +{ + return (ETH->ISTS & flag) ? SET : RESET; +} + +/*! + * @brief Enable the specified ETH MAC interrupts. + * + * @param interrupt: Ethernet MAC interrupt flag: + * 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 + * + * @retval None + */ +void ETH_EnableMACInterrupt(uint32_t interrupt) +{ + ETH->IMASK |= interrupt; +} + +/*! + * @brief Disable the specified ETH MAC interrupts. + * + * @param interrupt: Ethernet MAC interrupt flag: + * 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 + * + * @retval None + */ +void ETH_DisableMACInterrupt(uint32_t interrupt) +{ + ETH->IMASK &= (~(uint32_t)interrupt); +} + +/*! + * @brief Config the MAC address. + * + * @param macAddr: The MAC address. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDRESS0 : MAC Address0 + * @arg ETH_MAC_ADDRESS1 : MAC Address1 + * @arg ETH_MAC_ADDRESS2 : MAC Address2 + * @arg ETH_MAC_ADDRESS3 : MAC Address3 + * + * @param addr: Pointer on MAC address buffer data (6 bytes). + * + * @retval None + */ +void ETH_ConfigMACAddress(ETH_MAC_ADDRESS_T macAddr, uint8_t* addr) +{ + uint32_t temp; + + temp = ((uint32_t)addr[5] << 8) | (uint32_t)addr[4]; + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + macAddr)) = temp; + + temp = ((uint32_t)addr[3] << 24) | ((uint32_t)addr[2] << 16) | ((uint32_t)addr[1] << 8) | addr[0]; + (*(__IO uint32_t*)(ETH_MAC_ADDR_LBASE + macAddr)) = temp; +} + +/*! + * @brief Read the MAC address. + * + * @param macAddr: The MAC address. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDRESS0 : MAC Address0 + * @arg ETH_MAC_ADDRESS1 : MAC Address1 + * @arg ETH_MAC_ADDRESS2 : MAC Address2 + * @arg ETH_MAC_ADDRESS3 : MAC Address3 + * + * @param addr: Pointer on MAC address buffer data (6 bytes). + * + * @retval None + */ +void ETH_ReadMACAddress(ETH_MAC_ADDRESS_T macAddr, uint8_t* addr) +{ + uint32_t temp; + + temp = (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + macAddr)); + + addr[5] = ((temp >> 8) & 0xFF); + addr[4] = (temp & 0xFF); + + temp = (*(__IO uint32_t*)(ETH_MAC_ADDR_LBASE + macAddr)); + addr[3] = ((temp >> 24) & 0xFF); + addr[2] = ((temp >> 16) & 0xFF); + addr[1] = ((temp >> 8) & 0xFF); + addr[0] = (temp & 0xFF); +} + +/*! + * @brief Enable address filters module uses the MAC address for perfect filtering. + * + * @param macAddr: The MAC address. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDRESS1 : MAC Address1 + * @arg ETH_MAC_ADDRESS2 : MAC Address2 + * @arg ETH_MAC_ADDRESS3 : MAC Address3 + * + * @retval None + */ +void ETH_EnableMACAddressPerfectFilter(ETH_MAC_ADDRESS_T macAddr) +{ + __IO uint32_t temp = 0; + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + macAddr)) |= BIT31; + ETH_Delay(ETH_REG_WRITE_DELAY); + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + macAddr)) = temp; +} + +/*! + * @brief Disable address filters module uses the MAC address for perfect filtering. + * + * @param macAddr: The MAC address. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDRESS1 : MAC Address1 + * @arg ETH_MAC_ADDRESS2 : MAC Address2 + * @arg ETH_MAC_ADDRESS3 : MAC Address3 + * + * @retval None + */ +void ETH_DisableMACAddressPerfectFilter(ETH_MAC_ADDRESS_T macAddr) +{ + __IO uint32_t temp = 0; + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + macAddr)) &= (~BIT31); + ETH_Delay(ETH_REG_WRITE_DELAY); + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + macAddr)) = temp; +} + +/*! + * @brief Config the filter type for the MAC address + * + * @param macAddr: The MAC address. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDRESS1 : MAC Address1 + * @arg ETH_MAC_ADDRESS2 : MAC Address2 + * @arg ETH_MAC_ADDRESS3 : MAC Address3 + * + * @param filter: Comparison with the SA/DA fields of the received frame. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDRESSFILTER_SA : MAC Address is used to compare with the + * SA fields of the received frame. + * @arg ETH_MAC_ADDRESSFILTER_DA : MAC Address is used to compare with the + * DA fields of the received frame. + * @retval None + */ +void ETH_ConfigMACAddressFilter(ETH_MAC_ADDRESS_T macAddr, ETH_MAC_ADDRESSFILTER_T filter) +{ + if (filter == ETH_MAC_ADDRESSFILTER_SA) + { + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + macAddr)) |= ETH_MAC_ADDRESSFILTER_SA; + } + else + { + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + macAddr)) |= ETH_MAC_ADDRESSFILTER_DA; + } + +} + +/*! + * @brief Config the filter type for the ETH MAC address. + * + * @param macAddr: The MAC address. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDRESS1 : MAC Address1 + * @arg ETH_MAC_ADDRESS2 : MAC Address2 + * @arg ETH_MAC_ADDRESS3 : MAC Address3 + * + * @param MaskByte: specifies the used address bytes for comparison + * This parameter can be any combination of the following values: + * @arg ETH_MAC_ADDRESSMASK_BYTE6 : Mask MAC Address high reg bits [15:8]. + * @arg ETH_MAC_ADDRESSMASK_BYTE5 : Mask MAC Address high reg bits [7:0]. + * @arg ETH_MAC_ADDRESSMASK_BYTE4 : Mask MAC Address low reg bits [31:24]. + * @arg ETH_MAC_ADDRESSMASK_BYTE3 : Mask MAC Address low reg bits [23:16]. + * @arg ETH_MAC_ADDRESSMASK_BYTE2 : Mask MAC Address low reg bits [15:8]. + * @arg ETH_MAC_ADDRESSMASK_BYTE1 : Mask MAC Address low reg bits [7:0]. + * + * @retval None + */ +void ETH_ConfigMACAddressMaskBytesFilter(ETH_MAC_ADDRESS_T macAddr, uint32_t maskByte) +{ + __IO uint32_t temp = 0; + + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + macAddr)) &= (~(uint32_t)0x3F000000); + + temp = (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + macAddr)); + ETH_Delay(ETH_REG_WRITE_DELAY); + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + macAddr)) = temp; + + /* Set the selected Filter mask bytes */ + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + macAddr)) |= maskByte; + + temp = (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + macAddr)); + ETH_Delay(ETH_REG_WRITE_DELAY); + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + macAddr)) = temp; +} + +/* DMA Descriptors functions */ + +/*! + * @brief Config 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 rxBuffcount: Number of the used Rx desc in the list + * + * @retval None + */ +void ETH_ConfigDMARxDescChain(ETH_DMADescConfig_T* DMARxDescTab, uint8_t* rxBuff, uint32_t rxBuffcount) +{ + uint32_t i = 0; + ETH_DMADescConfig_T* DMARxDesc; + DMARxDescToGet = DMARxDescTab; + + for (i = 0; i < rxBuffcount; i++) + { + DMARxDesc = DMARxDescTab + i; + DMARxDesc->Status = ETH_DMARXDESC_OWN; + DMARxDesc->ControlBufferSize = ETH_DMARXDESC_RXCH | ETH_RX_BUF_SIZE; + DMARxDesc->Buffer1Addr = (uint32_t)(&rxBuff[i * ETH_RX_BUF_SIZE]); + if (i < (rxBuffcount - 1)) + { + DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab + i + 1); + } + else + { + DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab); + } + } + + + ETH->DMARXDLADDR = (uint32_t) DMARxDescTab; + DMARxFraminfos = &RxFrameDescriptor; +} + +/*! + * @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 txBuffcount: Number of the used Tx desc in the list + * + * @retval None + */ +void ETH_ConfigDMATxDescChain(ETH_DMADescConfig_T* DMATxDescTab, uint8_t* txBuff, uint32_t txBuffcount) +{ + uint32_t i = 0; + ETH_DMADescConfig_T* DMATxDesc; + DMATxDescToSet = DMATxDescTab; + + for (i = 0; i < txBuffcount; i++) + { + DMATxDesc = DMATxDescTab + i; + DMATxDesc->Status = ETH_DMATXDESC_TXCH; + DMATxDesc->Buffer1Addr = (uint32_t)(&txBuff[i * ETH_TX_BUF_SIZE]); + if (i < (txBuffcount - 1)) + { + DMATxDesc->Buffer2NextDescAddr = (uint32_t)(DMATxDescTab + i + 1); + } + else + { + DMATxDesc->Buffer2NextDescAddr = (uint32_t)(DMATxDescTab); + } + } + + ETH->DMATXDLADDR = (uint32_t) DMATxDescTab; +} + +/*! + * @brief This function polls for a frame receiver + * + * @param None + * + * @retval Returns 1 when a frame is received, 0 if none. + */ +uint32_t ETH_CheckReceivedFrame(void) +{ + if (((DMARxDescToGet->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARXDESC_LDES) != (uint32_t)RESET)) + { + DMARxFraminfos->segCount++; + if (DMARxFraminfos->segCount == 1) + { + DMARxFraminfos->FS_RxDesc = DMARxDescToGet; + } + DMARxFraminfos->LS_RxDesc = DMARxDescToGet; + return 1; + } + else if (((DMARxDescToGet->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARXDESC_FDES) != (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARXDESC_LDES) == (uint32_t)RESET)) + { + DMARxFraminfos->FS_RxDesc = DMARxDescToGet; + DMARxFraminfos->LS_RxDesc = NULL; + DMARxFraminfos->segCount = 1; + DMARxDescToGet = (ETH_DMADescConfig_T*)(DMARxDescToGet->Buffer2NextDescAddr); + } + else if (((DMARxDescToGet->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARXDESC_FDES) == (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARXDESC_LDES) == (uint32_t)RESET)) + { + (DMARxFraminfos->segCount) ++; + DMARxDescToGet = (ETH_DMADescConfig_T*)(DMARxDescToGet->Buffer2NextDescAddr); + } + return 0; +} + +/*! + * @brief Prepares DMA Tx descriptors to transmit an ethernet frame + * + * @param FrameLength : length of the frame to send + * + * @retval ETH_ERROR or ETH_SUCCESS + */ +uint32_t ETH_Transmit_Descriptors(u16 frameLength) +{ + uint32_t count = 0, size = 0, i = 0; + __IO ETH_DMADescConfig_T* DMATxDesc; + + if ((DMATxDescToSet->Status & ETH_DMATXDESC_OWN) == SET) + { + return ETH_ERROR; + } + + DMATxDesc = DMATxDescToSet; + + if (frameLength > ETH_TX_BUF_SIZE) + { + count = frameLength / ETH_TX_BUF_SIZE; + if (frameLength % ETH_TX_BUF_SIZE) count++; + } + else count = 1; + + if (count == 1) + { + DMATxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS; + DMATxDesc->ControlBufferSize = (frameLength & ETH_DMATXDESC_TXBS1); + DMATxDesc->Status |= ETH_DMATXDESC_OWN; + DMATxDesc = (ETH_DMADescConfig_T*)(DMATxDesc->Buffer2NextDescAddr); + } + else + { + for (i = 0; i < count; i++) + { + DMATxDesc->Status &= ~(ETH_DMATXDESC_FS | ETH_DMATXDESC_LS); + + if (i == 0) + { + DMATxDesc->Status |= ETH_DMATXDESC_FS; + } + DMATxDesc->ControlBufferSize = (ETH_TX_BUF_SIZE & ETH_DMATXDESC_TXBS1); + + if (i == (count - 1)) + { + DMATxDesc->Status |= ETH_DMATXDESC_LS; + size = frameLength - (count - 1) * ETH_TX_BUF_SIZE; + DMATxDesc->ControlBufferSize = (size & ETH_DMATXDESC_TXBS1); + } + + DMATxDesc->Status |= ETH_DMATXDESC_OWN; + DMATxDesc = (ETH_DMADescConfig_T*)(DMATxDesc->Buffer2NextDescAddr); + } + } + DMATxDescToSet = DMATxDesc; + + if (ETH->DMASTS_B.TXBU == SET) + { + ETH->DMASTS = BIT2; + ETH->DMATXPD = 0; + } + + return ETH_SUCCESS; +} + +/*! + * @brief Read the received frame. + * + * @param none + * + * @retval Structure of type ETH_Frame_T + */ +ETH_Frame_T ETH_ReadReceivedFrame(void) +{ + uint32_t frameLength = 0; + ETH_Frame_T frame = {0, 0, 0}; + + frameLength = ((DMARxDescToGet->Status & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAMELENGTHSHIFT) - 4; + frame.length = frameLength; + + frame.descriptor = DMARxFraminfos->FS_RxDesc; + frame.buffer = (DMARxFraminfos->FS_RxDesc)->Buffer1Addr; + DMARxDescToGet = (ETH_DMADescConfig_T*)(DMARxDescToGet->Buffer2NextDescAddr); + + return (frame); +} + +/*! + * @brief Read ETH DMA Tx Descriptor flag. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @param flag: Specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_DMATXDESC_OWN : Descriptor is owned by DMA engine + * @arg ETH_DMATXDESC_INTC : Interrupt on completion + * @arg ETH_DMATXDESC_LS : Last Segment + * @arg ETH_DMATXDESC_FS : First Segment + * @arg ETH_DMATXDESC_DISC : Disable CRC + * @arg ETH_DMATXDESC_DISP : Disable Pad + * @arg ETH_DMATXDESC_TXTSEN: Transmit Time Stamp Enable + * @arg ETH_DMATXDESC_TXENDR: Transmit End of Ring + * @arg ETH_DMATXDESC_TXCH : Second Address Chained + * @arg ETH_DMATXDESC_TXTSS : Tx Time Stamp Status + * @arg ETH_DMATXDESC_IHERR : IP Header Error + * @arg ETH_DMATXDESC_ERRS : Error summary + * @arg ETH_DMATXDESC_JTO : Jabber Timeout + * @arg ETH_DMATXDESC_FF : Frame Flushed: DMA/MTL flushed the frame due to SW flush + * @arg ETH_DMATXDESC_IPERR : Payload Checksum Error + * @arg ETH_DMATXDESC_LSC : Loss of Carrier: carrier lost during transmission + * @arg ETH_DMATXDESC_NC : No Carrier: no carrier signal from the transceiver + * @arg ETH_DMATXDESC_LC : Late Collision: transmission aborted due to collision + * @arg ETH_DMATXDESC_EC : Excessive Collision: transmission aborted after 16 collisions + * @arg ETH_DMATXDESC_VLANF : VLAN Frame + * @arg ETH_DMATXDESC_CCNT : Collision Count + * @arg ETH_DMATXDESC_EDEF : Excessive Deferral + * @arg ETH_DMATXDESC_UFERR : Underflow Error: late data arrival from the memory + * @arg ETH_DMATXDESC_DEF : Deferred Bit + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadDMATxDescFlagStatus(ETH_DMADescConfig_T* DMATxDesc, ETH_DMATXDESC_FLAG_T flag) +{ + return (DMATxDesc->Status & flag) ? SET : RESET; +} + +/*! + * @brief Returns ETH DMA Tx Descriptor collision count. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval The Transmit descriptor collision counter value. + */ +uint32_t ETH_ReadDMATxDescCollisionCount(ETH_DMADescConfig_T* DMATxDesc) +{ + return ((DMATxDesc->Status & ETH_DMATXDESC_CCNT) >> ETH_DMATXDESC_COLLISION_COUNTSHIFT); +} + +/*! + * @brief Config the ETH DMA Tx Descriptor Own bit. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_ConfigDMATxDescOwnBit(ETH_DMADescConfig_T* DMATxDesc) +{ + DMATxDesc->Status |= ETH_DMATXDESC_OWN; +} + +/*! + * @brief Enable the ETH DMA Tx Descriptor Transmit interrupt. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_EnableDMATxDescTransmitInterrupt(ETH_DMADescConfig_T* DMATxDesc) +{ + DMATxDesc->Status |= ETH_DMATXDESC_INTC; +} + +/*! + * @brief Disable the ETH DMA Tx Descriptor Transmit interrupt. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_DisableDMATxDescTransmitInterrupt(ETH_DMADescConfig_T* DMATxDesc) +{ + DMATxDesc->Status &= (~(uint32_t)ETH_DMATXDESC_INTC); +} + +/*! + * @brief Config Tx descriptor as last or first segment + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @param frameSegment: Tx desc contain last or first segment. + * This parameter can be one of the following values: + * @arg ETH_DMATXDESC_LASTSEGMENTS : Actual Tx desc contain last segment + * @arg ETH_DMATXDESC_FIRSTSEGMENT : Actual Tx desc contain first segment + * + * @retval None + */ +void ETH_ConfigDMATxDescFrameSegment(ETH_DMADescConfig_T* DMATxDesc, ETH_DMATXDESC_SEGMENTS_T frameSegment) +{ + DMATxDesc->Status |= frameSegment; +} +/*! + * @brief Config ETH DMA Tx Desc Checksum Insertion. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @param checksum: specifies is the DMA Tx desc checksum insertion. + * This parameter can be one of the following values: + * @arg ETH_DMATXDESC_CHECKSUMBYPASS : Checksum bypass + * @arg ETH_DMATXDESC_CHECKSUMIPV4HEADER : IPv4 header checksum + * @arg ETH_DMATXDESC_CHECKSUMTCPUDPICMPSEGMENT : TCP/UDP/ICMP checksum. Pseudo header checksum is assumed to be present + * @arg ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL : TCP/UDP/ICMP checksum fully in hardware including pseudo header + * + * @retval None + */ +void ETH_ConfigDMATxDescChecksumInsertion(ETH_DMADescConfig_T* DMATxDesc, ETH_DMATXDESC_CHECKSUMB_T checksum) +{ + DMATxDesc->Status |= checksum; +} + +/*! + * @brief Enable the DMA Tx Desc CRC. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_EnableDMATxDescCRC(ETH_DMADescConfig_T* DMATxDesc) +{ + DMATxDesc->Status &= (~(uint32_t)ETH_DMATXDESC_DISC); +} + +/*! + * @brief Disable the DMA Tx Desc CRC. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_DisableDMATxDescCRC(ETH_DMADescConfig_T* DMATxDesc) +{ + DMATxDesc->Status |= ETH_DMATXDESC_DISC; +} + +/*! + * @brief Enable the DMA Tx Desc second address chained. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_EnableDMATxDescSecondAddressChained(ETH_DMADescConfig_T* DMATxDesc) +{ + DMATxDesc->Status |= ETH_DMATXDESC_TXCH; +} + +/*! + * @brief Disable the DMA Tx Desc second address chained. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_DisableDMATxDescSecondAddressChained(ETH_DMADescConfig_T* DMATxDesc) +{ + DMATxDesc->Status &= (~(uint32_t)ETH_DMATXDESC_TXCH); +} + +/*! + * @brief Enable the DMA Tx Desc padding for frame shorter than 64 bytes. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_EnableDMATxDescShortFramePadding(ETH_DMADescConfig_T* DMATxDesc) +{ + DMATxDesc->Status &= (~(uint32_t)ETH_DMATXDESC_DISP); +} + +/*! + * @brief Disable the DMA Tx Desc padding for frame shorter than 64 bytes. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_DisableDMATxDescShortFramePadding(ETH_DMADescConfig_T* DMATxDesc) +{ + DMATxDesc->Status |= ETH_DMATXDESC_DISP; +} + +/*! + * @brief Config the ETH DMA Tx Desc buffer1 and buffer2 sizes. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @param bufferSize1: specifies the Tx desc buffer1 size. + * + * @param bufferSize2: specifies the Tx desc buffer2 size. + * + * @retval None + */ +void ETH_ConfigDMATxDescBufferSize(ETH_DMADescConfig_T* DMATxDesc, uint32_t bufferSize1, uint32_t bufferSize2) +{ + DMATxDesc->ControlBufferSize |= (bufferSize1 | (bufferSize2 << ETH_DMATXDESC_BUFFER2_SIZESHIFT)); +} + +/*! + * @brief Checks whether the specified ETHERNET Rx Desc flag is set or not. + * + * @param DMARxDesc: pointer on a DMA Rx descriptor + + * @param flag: specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_DMARXDESC_OWN : Descriptor is owned by DMA engine + * @arg ETH_DMARXDESC_ADDRF : DA Filter Fail for the rx frame + * @arg ETH_DMARXDESC_ERRS : Error summary + * @arg ETH_DMARXDESC_DESERR : Descriptor error: no more descriptors for receive frame + * @arg ETH_DMARXDESC_SADDRF : SA Filter Fail for the received frame + * @arg ETH_DMARXDESC_LERR : Frame size not matching with length field + * @arg ETH_DMARXDESC_OFERR : Overflow Error: Frame was damaged due to buffer overflow + * @arg ETH_DMARXDESC_VLANF : VLAN Tag: received frame is a VLAN frame + * @arg ETH_DMARXDESC_FDES : First descriptor of the frame + * @arg ETH_DMARXDESC_LDES : Last descriptor of the frame + * @arg ETH_DMARXDESC_IPV4HCE: IPC Checksum Error/Giant Frame: Rx Ipv4 header checksum error + * @arg ETH_DMARXDESC_LC : Late collision occurred during reception + * @arg ETH_DMARXDESC_FT : Frame type - Ethernet, otherwise 802.3 + * @arg ETH_DMARXDESC_RXWDTTO: Receive Watchdog Timeout: watchdog timer expired during reception + * @arg ETH_DMARXDESC_RERR : Receive error: error reported by MII interface + * @arg ETH_DMARXDESC_DERR : Dribble bit error: frame contains non int multiple of 8 bits + * @arg ETH_DMARXDESC_CERR : CRC error + * @arg ETH_DMARXDESC_MAMPCE : Rx MAC Address/Payload Checksum Error: Rx MAC address matched/ Rx Payload Checksum Error + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadDMARxDescFlagStatus(ETH_DMADescConfig_T* DMARxDesc, ETH_DMARXDESC_FLAG_T flag) +{ + return (DMARxDesc->Status & flag) ? SET : RESET; +} + +/*! + * @brief Config the ETH DMA Rx Desc Own bit. + * + * @param DMARxDesc: pointer on a DMA Rx descriptor + * + * @retval None + */ +void ETH_ConfigDMARxDescOwnBit(ETH_DMADescConfig_T* DMARxDesc) +{ + DMARxDesc->Status |= ETH_DMARXDESC_OWN; +} + +/*! + * @brief Returns the ETH DMA Rx descriptor frame length. + * + * @param DMARxDesc: pointer on a DMA Rx descriptor + * + * @retval The Rx descriptor received frame length. + */ +uint32_t ETH_ReadDMARxDescFrameLength(ETH_DMADescConfig_T* DMARxDesc) +{ + return ((DMARxDesc->Status & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAME_LENGTHSHIFT); +} + +/*! + * @brief Enable the ETH DMA Rx Desc receive interrupt. + * + * @param DMARxDesc: pointer on a DMA Rx descriptor + * + * @retval None + */ +void ETH_EnableDMARxDescReceiveInterrupt(ETH_DMADescConfig_T* DMARxDesc) +{ + DMARxDesc->ControlBufferSize &= (~(uint32_t)ETH_DMARXDESC_DINTC); +} + +/*! + * @brief Disable the ETH DMA Rx Desc receive interrupt. + * + * @param DMARxDesc: pointer on a DMA Rx descriptor + * + * @retval None + */ +void ETH_DisableDMARxDescReceiveInterrupt(ETH_DMADescConfig_T* DMARxDesc) +{ + DMARxDesc->ControlBufferSize |= ETH_DMARXDESC_DINTC; +} + +/*! + * @brief Returns the ETH DMA Rx Desc buffer size. + * + * @param DMARxDesc: pointer on a DMA Rx descriptor + * + * @param buffer: specifies the DMA Rx Desc buffer. + * This parameter can be one of the following values: + * @arg ETH_DMARxDesc_Buffer1 : DMA Rx Desc Buffer1 + * @arg ETH_DMARxDesc_Buffer2 : DMA Rx Desc Buffer2 + * + * @retval The Receive descriptor frame length. + */ +uint32_t ETH_ReadDMARxDescBufferSize(ETH_DMADescConfig_T* DMARxDesc, ETH_DMARXDESC_BUFFER_T buffer) +{ + if (buffer == ETH_DMARXDESC_BUFFER1) + { + return (DMARxDesc->ControlBufferSize & ETH_DMARXDESC_RXBS1); + } + else + { + return ((DMARxDesc->ControlBufferSize & ETH_DMARXDESC_RXBS2) >> ETH_DMARXDESC_BUFFER2_SIZESHIFT); + } +} + +/*! + * @brief Read frame using DMA Receive interrupt. + * it allows scanning of Rx descriptors to get the the receive frame + * + * @param None + * + * @retval Structure of type ETH_Frame_T + */ +ETH_Frame_T ETH_ReadReceivedFrameInterrupt(void) +{ + __IO uint32_t count = 0; + ETH_Frame_T frame = {0, 0, 0}; + + while (((DMARxDescToGet->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET) && (count < ETH_RXBUFNB)) + { + count ++; + + if (((DMARxDescToGet->Status & ETH_DMARXDESC_FDES) != (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARXDESC_LDES) == (uint32_t)RESET)) + { + DMARxFraminfos->FS_RxDesc = DMARxDescToGet; + DMARxFraminfos->segCount = 1; + DMARxDescToGet = (ETH_DMADescConfig_T*)(DMARxDescToGet->Buffer2NextDescAddr); + } + else if (((DMARxDescToGet->Status & ETH_DMARXDESC_FDES) == (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARXDESC_LDES) == (uint32_t)RESET)) + { + (DMARxFraminfos->segCount) ++; + DMARxDescToGet = (ETH_DMADescConfig_T*)(DMARxDescToGet->Buffer2NextDescAddr); + } + else + { + DMARxFraminfos->LS_RxDesc = DMARxDescToGet; + (DMARxFraminfos->segCount)++; + + if ((DMARxFraminfos->segCount) == 1) + DMARxFraminfos->FS_RxDesc = DMARxDescToGet; + + frame.length = ((DMARxDescToGet->Status & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAMELENGTHSHIFT) - 4; + + if (DMARxFraminfos->segCount > 1) + { + frame.buffer = (DMARxFraminfos->FS_RxDesc)->Buffer1Addr; + } + else + { + frame.buffer = DMARxDescToGet->Buffer1Addr; + } + + frame.descriptor = DMARxFraminfos->FS_RxDesc; + DMARxDescToGet = (ETH_DMADescConfig_T*)(DMARxDescToGet->Buffer2NextDescAddr); + + return (frame); + } + } + return (frame); +} + +/* DMA functions */ + +/*! + * @brief Read the ETH DMA flag. + * + * @param 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_DATATRANSFERERROR : Error bits 0-data buffer, 1-desc. access + * @arg ETH_DMA_FLAG_READWRITEERROR : Error bits 0-write trnsf, 1-read transfr + * @arg ETH_DMA_FLAG_ACCESSERROR : 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_ER : Early receive flag + * @arg ETH_DMA_FLAG_FBE : Fatal bus error flag + * @arg ETH_DMA_FLAG_ET : Early transmit flag + * @arg ETH_DMA_FLAG_RWT : Receive watchdog timeout flag + * @arg ETH_DMA_FLAG_RPS : Receive process stopped flag + * @arg ETH_DMA_FLAG_RBU : Receive buffer unavailable flag + * @arg ETH_DMA_FLAG_RX : Receive flag + * @arg ETH_DMA_FLAG_TU : Underflow flag + * @arg ETH_DMA_FLAG_RO : Overflow flag + * @arg ETH_DMA_FLAG_TJT : Transmit jabber timeout flag + * @arg ETH_DMA_FLAG_TBU : Transmit buffer unavailable flag + * @arg ETH_DMA_FLAG_TPS : Transmit process stopped flag + * @arg ETH_DMA_FLAG_TX : Transmit flag + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadDMAFlagStatus(ETH_DMA_FLAG_T flag) +{ + return (ETH->DMASTS & flag) ? SET : RESET; +} + +/*! + * @brief Clears the ETH DMA flag. + * + * @param 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_ER : Early receive flag + * @arg ETH_DMA_FLAG_FBE : Fatal bus error flag + * @arg ETH_DMA_FLAG_ET : Early transmit flag + * @arg ETH_DMA_FLAG_RWT : Receive watchdog timeout flag + * @arg ETH_DMA_FLAG_RPS : Receive process stopped flag + * @arg ETH_DMA_FLAG_RBU : Receive buffer unavailable flag + * @arg ETH_DMA_FLAG_RX : Receive flag + * @arg ETH_DMA_FLAG_TU : Transmit Underflow flag + * @arg ETH_DMA_FLAG_RO : Receive Overflow flag + * @arg ETH_DMA_FLAG_TJT : Transmit jabber timeout flag + * @arg ETH_DMA_FLAG_TBU : Transmit buffer unavailable flag + * @arg ETH_DMA_FLAG_TPS : Transmit process stopped flag + * @arg ETH_DMA_FLAG_TX : Transmit flag + * + * @retval None + */ +void ETH_ClearDMAFlag(uint32_t flag) +{ + ETH->DMASTS = flag; +} + +/*! + * @brief Read the ETH DMA interrupt flag. + * + * @param flag: 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_ER : Early receive interrupt + * @arg ETH_DMA_INT_FBE : Fatal bus error interrupt + * @arg ETH_DMA_INT_ET : Early transmit interrupt + * @arg ETH_DMA_INT_RWT : Receive watchdog timeout interrupt + * @arg ETH_DMA_INT_RPS : Receive process stopped interrupt + * @arg ETH_DMA_INT_RBU : Receive buffer unavailable interrupt + * @arg ETH_DMA_INT_RX : Receive interrupt + * @arg ETH_DMA_INT_TU : Underflow interrupt + * @arg ETH_DMA_INT_RO : Overflow interrupt + * @arg ETH_DMA_INT_TJT : Transmit jabber timeout interrupt + * @arg ETH_DMA_INT_TBU : Transmit buffer unavailable interrupt + * @arg ETH_DMA_INT_TPS : Transmit process stopped interrupt + * @arg ETH_DMA_INT_TX : Transmit interrupt + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadDMAIntFlag(ETH_DMA_INT_T flag) +{ + return (ETH->DMASTS & flag) ? SET : RESET; +} + +/*! + * @brief Clears the ETH DMA interrupt flag. + * + * @param flag: specifies the interrupt flag 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_ER : Early receive interrupt + * @arg ETH_DMA_INT_FBE : Fatal bus error interrupt + * @arg ETH_DMA_INT_ET : Early transmit interrupt + * @arg ETH_DMA_INT_RWT : Receive watchdog timeout interrupt + * @arg ETH_DMA_INT_RPS : Receive process stopped interrupt + * @arg ETH_DMA_INT_RBU : Receive buffer unavailable interrupt + * @arg ETH_DMA_INT_RX : Receive interrupt + * @arg ETH_DMA_INT_TU : Transmit Underflow interrupt + * @arg ETH_DMA_INT_RO : Receive Overflow interrupt + * @arg ETH_DMA_INT_TJT : Transmit jabber timeout interrupt + * @arg ETH_DMA_INT_TBU : Transmit buffer unavailable interrupt + * @arg ETH_DMA_INT_TPS : Transmit process stopped interrupt + * @arg ETH_DMA_INT_TX : Transmit interrupt + * + * @retval None + */ +void ETH_ClearDMAIntFlag(uint32_t flag) +{ + ETH->DMASTS = flag; +} + +/*! + * @brief Returns the ETH DMA Transmit Process State. + * + * @param None + + * @retval The new ETH DMA Transmit Process State: + * This can be one of the following values: + * - ETH_DMA_TRANSMITPROCESS_STOPPED : Stopped - Reset or Stop Tx Command issued + * - ETH_DMA_TRANSMITPROCESS_FETCHING : Running - fetching the Tx descriptor + * - ETH_DMA_TRANSMITPROCESS_WAITING : Running - waiting for status + * - ETH_DMA_TRANSMITPROCESS_READING : Running - reading the data from host memory + * - ETH_DMA_TRANSMITPROCESS_SUSPENDED : Suspended - Tx Descriptor unavailable + * - ETH_DMA_TRANSMITPROCESS_CLOSING : Running - closing Rx descriptor + */ +uint32_t ETH_ReadTransmitProcessState(void) +{ + return ((uint32_t)(ETH->DMASTS & BIT0) ? SET : RESET); +} + +/*! + * @brief Returns the ETH DMA Receive Process State. + * + * @param None + * + * @retval The new ETH DMA Receive Process State: + * This can be one of the following values: + * - ETH_DMA_RECEIVEPROCESS_STOPPED : Stopped - Reset or Stop Rx Command issued + * - ETH_DMA_RECEIVEPROCESS_FETCHING : Running - fetching the Rx descriptor + * - ETH_DMA_RECEIVEPROCESS_WAITING : Running - waiting for packet + * - ETH_DMA_RECEIVEPROCESS_SUSPENDED : Suspended - Rx Descriptor unavailable + * - ETH_DMA_RECEIVEPROCESS_CLOSING : Running - closing descriptor + * - ETH_DMA_RECEIVEPROCESS_QUEUING : Running - queuing the receive frame into host memory + */ +uint32_t ETH_ReadReceiveProcessState(void) +{ + return ((uint32_t)(ETH->DMASTS & BIT6) ? SET : RESET); +} + +/*! + * @brief Flush the ETH transmit FIFO. + * + * @param None + * + * @retval None + */ +void ETH_FlushTransmitFIFO(void) +{ + ETH->DMAOPMOD_B.FTXF = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Read the ETH flush transmit FIFO status. + * + * @param None + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadFlushTransmitFIFOStatus(void) +{ + return ETH->DMAOPMOD_B.FTXF; +} + +/*! + * @brief Enable the DMA transmission. + * + * @param None + * + * @retval None + */ +void ETH_EnableDMATransmission(void) +{ + ETH->DMAOPMOD_B.STTX = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable the DMA transmission. + * + * @param None + * + * @retval None + */ +void ETH_DisableDMATransmission(void) +{ + ETH->DMAOPMOD_B.STTX = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Enable the DMA receiver. + * + * @param None + * + * @retval None + */ +void ETH_EnableDMAReceiver(void) +{ + ETH->DMAOPMOD_B.STRX = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable the DMA receiver. + * + * @param None + * + * @retval None + */ +void ETH_DisableDMAReceiver(void) +{ + ETH->DMAOPMOD_B.STRX = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Enable the ETH DMA interrupts. + * + * @param interrupt: specifies the ETH DMA interrupt sources. + * 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_ER : Early receive interrupt + * @arg ETH_DMA_INT_FBE : Fatal bus error interrupt + * @arg ETH_DMA_INT_ET : Early transmit interrupt + * @arg ETH_DMA_INT_RWT : Receive watchdog timeout interrupt + * @arg ETH_DMA_INT_RPS : Receive process stopped interrupt + * @arg ETH_DMA_INT_RBU : Receive buffer unavailable interrupt + * @arg ETH_DMA_INT_RX : Receive interrupt + * @arg ETH_DMA_INT_TU : Underflow interrupt + * @arg ETH_DMA_INT_RO : Overflow interrupt + * @arg ETH_DMA_INT_TJT : Transmit jabber timeout interrupt + * @arg ETH_DMA_INT_TBU : Transmit buffer unavailable interrupt + * @arg ETH_DMA_INT_TPS : Transmit process stopped interrupt + * @arg ETH_DMA_INT_TX : Transmit interrupt + * + * @retval None + */ +void ETH_EnableDMAInterrupt(uint32_t interrupt) +{ + ETH->DMAINTEN |= interrupt; +} + +/*! + * @brief Disable the ETH DMA interrupts. + * + * @param interrupt: specifies the ETH DMA interrupt sources. + * 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_ER : Early receive interrupt + * @arg ETH_DMA_INT_FBE : Fatal bus error interrupt + * @arg ETH_DMA_INT_ET : Early transmit interrupt + * @arg ETH_DMA_INT_RWT : Receive watchdog timeout interrupt + * @arg ETH_DMA_INT_RPS : Receive process stopped interrupt + * @arg ETH_DMA_INT_RBU : Receive buffer unavailable interrupt + * @arg ETH_DMA_INT_RX : Receive interrupt + * @arg ETH_DMA_INT_TU : Underflow interrupt + * @arg ETH_DMA_INT_RO : Overflow interrupt + * @arg ETH_DMA_INT_TJT : Transmit jabber timeout interrupt + * @arg ETH_DMA_INT_TBU : Transmit buffer unavailable interrupt + * @arg ETH_DMA_INT_TPS : Transmit process stopped interrupt + * @arg ETH_DMA_INT_TX : Transmit interrupt + * + * @retval None + */ +void ETH_DisableDMAInterrupt(uint32_t interrupt) +{ + ETH->DMAINTEN &= ((uint32_t)~interrupt); +} + +/*! + * @brief Read the ETH DMA overflow flag. + * + * @param overflow: specifies the DMA overflow flag to check. + * This parameter can be one of the following values: + * @arg ETH_DMA_OVERFLOW_RXFIFOCOUNTER : Overflow for FIFO Overflows Counter + * @arg ETH_DMA_OVERFLOW_MISSEDFRAMECOUNTER : Overflow for Buffer Unavailable Missed Frame Counter + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadDMAOverflowStatus(ETH_DMA_OVERFLOW_T overflow) +{ + return (ETH->DMAMFABOCNT & overflow) ? SET : RESET; +} + +/*! + * @brief Read the ETH DMA Rx Overflow Missed Frame Counter value. + * + * @param None + * + * @retval The value of Rx overflow Missed Frame Counter. + */ +uint32_t ETH_ReadRxOverflowMissedFrameCounter(void) +{ + return (uint32_t)(ETH->DMAMFABOCNT_B.AMISFCNT); +} + +/*! + * @brief Read the ETH DMA Buffer Unavailable Missed Frame Counter value. + * + * @param None + * + * @retval The value of Buffer unavailable Missed Frame Counter. + */ +uint32_t ETH_ReadBufferUnavailableMissedFrameCounter(void) +{ + return (uint32_t)(ETH->DMAMFABOCNT_B.MISFCNT); +} + +/*! + * @brief Read the ETH DMA DMAHTXD register value. + * + * @param None + * + * @retval The value of the current Tx desc start address. + */ +uint32_t ETH_ReadCurrentTxDescStartAddress(void) +{ + return ((uint32_t)(ETH->DMAHTXD)); +} + +/*! + * @brief Read the ETHERNET DMA DMAHRXD register value. + * + * @param None + * + * @retval The value of the current Rx desc start address. + */ +uint32_t ETH_ReadCurrentRxDescStartAddress(void) +{ + return ((uint32_t)(ETH->DMAHRXD)); +} + +/*! + * @brief Read the ETH DMA DMAHTXBADDR register value. + * + * @param None + * + * @retval The value of the current transmit descriptor data buffer address. + */ +uint32_t ETH_ReadCurrentTxBufferAddress(void) +{ + return ((uint32_t)(ETH->DMAHTXBADDR)); +} + +/*! + * @brief Read the ETH DMA DMAHRXBADDR register value. + * + * @param None + * + * @retval The value of the current receive descriptor data buffer address. + */ +uint32_t ETH_ReadCurrentRxBufferAddress(void) +{ + return ((uint32_t)(ETH->DMAHRXBADDR)); +} + +/*! + * @brief Reset the DMA Transmission by writing to the DmaTxPollDemand register + * + * @param None + + * @retval None. + */ +void ETH_ResetDMATransmission(void) +{ + ETH->DMATXPD = 0; +} + +/*! + * @brief Reset the DMA Transmission by writing to the DmaRxPollDemand register + * + * @param None + * + * @retval None. + */ +void ETH_ResetDMAReception(void) +{ + ETH->DMARXPD = 0; +} + +/** Power Management(PMT) functions */ + +/*! + * @brief Reset Wakeup frame filter register pointer. + * + * @param None + * + * @retval None + */ +void ETH_ResetWakeUpFrameFilterRegisterPointer(void) +{ + ETH->PMTCTRLSTS_B.WKUPFRST = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Enable any unicast packet filtered by the MAC address + * recognition to be a wake-up frame. + * + * @retval None + */ +void ETH_EnableGlobalUnicastWakeUp(void) +{ + ETH->PMTCTRLSTS_B.GUN = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable any unicast packet filtered by the MAC address + * recognition to be a wake-up frame. + * + * @retval None + */ +void ETH_DisableGlobalUnicastWakeUp(void) +{ + ETH->PMTCTRLSTS_B.GUN = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Read the ETH PMT flag. + * + * @param flag: specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_PMT_FLAG_WUFFRPR : Wake-Up Frame Filter Register Pointer Reset + * @arg ETH_PMT_FLAG_WUFR : Wake-Up Frame Received + * @arg ETH_PMT_FLAG_MPR : Magic Packet Received + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadPMTFlagStatus(ETH_PMT_FLAG_T flag) +{ + return (ETH->PMTCTRLSTS & flag) ? SET : RESET; +} + +/*! + * @brief Enable the MAC Wake-Up Frame Detection. + * + * @param None + * + * @retval None + */ +void ETH_EnableWakeUpFrameDetection(void) +{ + ETH->PMTCTRLSTS_B.WKUPFEN = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable the MAC Wake-Up Frame Detection. + * + * @param None + * + * @retval None + */ +void ETH_DisableWakeUpFrameDetection(void) +{ + ETH->PMTCTRLSTS_B.WKUPFEN = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Enable the MAC Magic Packet Detection. + * + * @param None + * + * @retval None + */ +void ETH_EnableMagicPacketDetection(void) +{ + ETH->PMTCTRLSTS_B.MPEN = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable the MAC Magic Packet Detection. + * + * @param None + * + * @retval None + */ +void ETH_DisableMagicPacketDetection(void) +{ + ETH->PMTCTRLSTS_B.MPEN = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Enable the MAC Power Down. + * + * @param None + * + * @retval None + */ +void ETH_EnablePowerDown(void) +{ + ETH->PMTCTRLSTS_B.PD = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable the MAC Power Down. + * + * @param None + * + * @retval None + */ +void ETH_DisablePowerDown(void) +{ + ETH->PMTCTRLSTS_B.PD = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Enable the MMC Counter Freeze. + * + * @param None + * + * @retval None + */ +void ETH_EnableMMCCounterFreeze(void) +{ + ETH->CTRL_B.MCNTF = SET; +} + +/*! + * @brief Disable the MMC Counter Freeze. + * + * @param None + * + * @retval None + */ +void ETH_DisableMMCCounterFreeze(void) +{ + ETH->CTRL_B.MCNTF = RESET; +} + +/*! + * @brief Enable the MMC Reset On Read. + * + * @param None + * + * @retval None + */ +void ETH_EnableMMCResetOnRead(void) +{ + ETH->CTRL_B.RSTOR = SET; +} + +/*! + * @brief Disable the MMC Reset On Read. + * + * @param None + * + * @retval None + */ +void ETH_DisableMMCResetOnRead(void) +{ + ETH->CTRL_B.RSTOR = RESET; +} + +/*! + * @brief Enble the MMC Counter Stop Rollover. + * + * @param None + * + * @retval None + */ +void ETH_EnableMMCCounterRollover(void) +{ + ETH->CTRL_B.CNTSTOPRO = RESET; +} + +/*! + * @brief Disable the MMC Counter Stop Rollover. + * + * @param None + * + * @retval None + */ +void ETH_DisableMMCCounterRollover(void) +{ + ETH->CTRL_B.CNTSTOPRO = SET; +} + +/** + * @brief Resets the MMC Counters. + * @param None + * @retval None + */ +void ETH_ResetMMCCounters(void) +{ + ETH->CTRL_B.CNTRST = SET; +} + +/*! + * @brief Enable the ETH MMC interrupts. + * + * @param interrupt: specifies the ETH MMC interrupt sources. + * 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_TGF : When Tx good frame counter reaches half the maximum value + * @arg ETH_MMC_INT_TGFMSC: When Tx good multi col counter reaches half the maximum value + * @arg ETH_MMC_INT_TGFSC : When Tx good single col counter reaches half the maximum value + * @arg ETH_MMC_INT_RGUF : When Rx good unicast frames counter reaches half the maximum value + * @arg ETH_MMC_INT_RFAE : When Rx alignment error counter reaches half the maximum value + * @arg ETH_MMC_INT_RFCE : When Rx crc error counter reaches half the maximum value + * + * @retval None + */ +void ETH_EnableMMCInterrupt(uint32_t interrupt) +{ + if ((interrupt & 0x10000000) == SET) + { + ETH->RXINTMASK &= (~(uint32_t)interrupt); + } + else + { + ETH->TXINTMASK &= (~(uint32_t)interrupt); + } +} + +/*! + * @brief Disable the ETH MMC interrupts. + * + * @param interrupt: specifies the ETH MMC interrupt sources. + * 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_TGF : When Tx good frame counter reaches half the maximum value + * @arg ETH_MMC_INT_TGFMSC: When Tx good multi col counter reaches half the maximum value + * @arg ETH_MMC_INT_TGFSC : When Tx good single col counter reaches half the maximum value + * @arg ETH_MMC_INT_RGUF : When Rx good unicast frames counter reaches half the maximum value + * @arg ETH_MMC_INT_RFAE : When Rx alignment error counter reaches half the maximum value + * @arg ETH_MMC_INT_RFCE : When Rx crc error counter reaches half the maximum value + * + * @retval None + */ +void ETH_DisableMMCInterrupt(uint32_t interrupt) +{ + if ((interrupt & 0x10000000) == SET) + { + ETH->RXINTMASK |= interrupt; + } + else + { + ETH->TXINTMASK |= interrupt; + } +} + +/*! + * @brief Read the ETH MMC interrupt flag. + * + * @param flag: specifies the ETH MMC interrupt. + * This parameter can be one of the following values: + * @arg ETH_MMC_INT_TGF : When Tx good frame counter reaches half the maximum value + * @arg ETH_MMC_INT_TGFMSC: When Tx good multi col counter reaches half the maximum value + * @arg ETH_MMC_INT_TGFSC : When Tx good single col counter reaches half the maximum value + * @arg ETH_MMC_INT_RGUF : When Rx good unicast frames counter reaches half the maximum value + * @arg ETH_MMC_INT_RFAE : When Rx alignment error counter reaches half the maximum value + * @arg ETH_MMC_INT_RFCE : When Rx crc error counter reaches half the maximum value + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadMMCIntFlag(uint32_t flag) +{ + if ((flag & 0x10000000) == SET) + { + return ((((ETH->RXINT & flag) != RESET)) && ((ETH->RXINTMASK & flag) == RESET)); + } + else + { + return ((((ETH->TXINT & flag) != RESET)) && ((ETH->TXINTMASK & flag) == RESET)); + } +} + +/*! + * @brief Read the ETH MMC register value. + * + * @param MMCReg: specifies the ETH MMC register. + * This parameter can be one of the following values: + * @arg ETH_MMC_CTRL : MMC CTRL register + * @arg ETH_MMC_RXINT : MMC RXINT register + * @arg ETH_MMC_TXINT : MMC TXINT register + * @arg ETH_MMC_RXINTMASK : MMC RXINTMASK register + * @arg ETH_MMC_TXINTMASK : MMC TXINTMASK register + * @arg ETH_MMC_TXGFSCCNT : MMC TXGFSCCNT register + * @arg ETH_MMC_TXGFMCCNT : MMC TXGFMCCNT register + * @arg ETH_MMC_TXGFCNT : MMC TXGFCNT register + * @arg ETH_MMC_RXFCECNT : MMC RXFCECNT register + * @arg ETH_MMC_RXFAECNT : MMC RXFAECNT register + * @arg ETH_MMC_RXGUNCNT : MMC RXGUNCNT register + * + * @retval Return ETH MMC Register value. + */ +uint32_t ETH_ReadMMCRegister(ETH_MMC_REG_T MMCReg) +{ + return (*(__IO uint32_t*)(ETH_MAC_BASE + MMCReg)); +} + +#endif + +/**@} end of group ETH_Functions */ +/**@} end of group ETH_Driver */ +/**@} end of group APM32F10x_ETHDriver */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_adc.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_adc.h index da04b17db9..ff8ab89da6 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_adc.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_adc.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the ADC firmware library * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,16 +23,17 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_ADC_H #define __APM32F10X_ADC_H +/* Includes */ +#include "apm32f10x.h" #ifdef __cplusplus - extern "C" { +extern "C" { #endif -#include "apm32f10x.h" - -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,7 +41,33 @@ @{ */ -/** @addtogroup ADC_Enumerations Enumerations + +/** @defgroup ADC_Macros + @{ +*/ + +/* ADC_IJD Offset */ +#define INJDATA_OFFSET ((uint8_t)0x28) + +/* ADC_RDG register address */ +#define RDG_ADDRESS ((uint32_t)0x4001244C) + +/* INJSEQ register config */ +#define INJSEQ_SET_INJSEQC ((uint32_t)0x0000001F) +#define INJSEQ_SET_INJSEQLEN ((uint32_t)0x00300000) + +/* SMPTIM register SET */ +#define SMPCYCCFG_SET_SMPTIM1 ((uint32_t)0x00000007) +#define SMPCYCCFG_SET_SMPTIM2 ((uint32_t)0x00000007) + +/* REGSEQ register SET */ +#define REGSEQC_SET_REGSEQ3 ((uint32_t)0x0000001F) +#define REGSEQC_SET_REGSEQ2 ((uint32_t)0x0000001F) +#define REGSEQC_SET_REGSEQ1 ((uint32_t)0x0000001F) + +/**@} end of group ADC_Macros*/ + +/** @defgroup ADC_Enumerations @{ */ @@ -49,16 +76,16 @@ */ typedef enum { - ADC_MODE_INDEPENDENT = ((uint32_t)0x00000000), //!< Independent mode - ADC_MODE_REG_INJEC_SIMULT = ((uint32_t)0x00010000), //!< Combined regular simultaneous and injected simultaneous mode - ADC_MODE_REG_SIMULT_ALTER_TRIG = ((uint32_t)0x00020000), //!< Combined regular simultaneous and alternate trigger mode - ADC_MODE_INJEC_SIMULT_FAST_TNTERL = ((uint32_t)0x00030000), //!< Combined injected simultaneous and fast interleaved mode - ADC_MODE_INJEC_SIMULT_SLOW_INTERL = ((uint32_t)0x00040000), //!< Combined injected simultaneous and slow interleaved mode - ADC_MODE_INJEC_SIMULT = ((uint32_t)0x00050000), //!< Injected simultaneous mode - ADC_MODE_REG_SIMULT = ((uint32_t)0x00060000), //!< Regular simultaneous mode - ADC_MODE_FAST_INTERL = ((uint32_t)0x00070000), //!< Fast interleaved mode - ADC_MODE_SLOW_INTERL = ((uint32_t)0x00080000), //!< Slow interleaved mode - ADC_MODE_ALTER_TRIG = ((uint32_t)0x00090000) //!< Alternate trigger mode + ADC_MODE_INDEPENDENT = ((uint32_t)0x00000000), /*!< Independent mode */ + ADC_MODE_REG_INJEC_SIMULT = ((uint32_t)0x00010000), /*!< Combined regular simultaneous and injected simultaneous mode */ + ADC_MODE_REG_SIMULT_ALTER_TRIG = ((uint32_t)0x00020000), /*!< Combined regular simultaneous and alternate trigger mode */ + ADC_MODE_INJEC_SIMULT_FAST_TNTERL = ((uint32_t)0x00030000), /*!< Combined injected simultaneous and fast interleaved mode */ + ADC_MODE_INJEC_SIMULT_SLOW_INTERL = ((uint32_t)0x00040000), /*!< Combined injected simultaneous and slow interleaved mode */ + ADC_MODE_INJEC_SIMULT = ((uint32_t)0x00050000), /*!< Injected simultaneous mode */ + ADC_MODE_REG_SIMULT = ((uint32_t)0x00060000), /*!< Regular simultaneous mode */ + ADC_MODE_FAST_INTERL = ((uint32_t)0x00070000), /*!< Fast interleaved mode */ + ADC_MODE_SLOW_INTERL = ((uint32_t)0x00080000), /*!< Slow interleaved mode */ + ADC_MODE_ALTER_TRIG = ((uint32_t)0x00090000) /*!< Alternate trigger mode */ } ADC_MODE_T; /** @@ -139,19 +166,19 @@ typedef enum */ typedef enum { - /** for ADC1 and ADC2 */ + /* for ADC1 and ADC2 */ ADC_EXT_TRIG_INJEC_CONV_TMR2_TRGO = ((uint8_t)0x02), ADC_EXT_TRIG_INJEC_CONV_TMR2_CC1 = ((uint8_t)0x03), ADC_EXT_TRIG_INJEC_CONV_TMR3_CC4 = ((uint8_t)0x04), ADC_EXT_TRIG_INJEC_CONV_TMR4_TRGO = ((uint8_t)0x05), ADC_EXT_TRIG_INJEC_CONV_EINT15_T8_CC4 = ((uint8_t)0x06), - /** for ADC1, ADC2 and ADC3 */ + /* for ADC1, ADC2 and ADC3 */ ADC_EXT_TRIG_INJEC_CONV_TMR1_TRGO = ((uint8_t)0x00), ADC_EXT_TRIG_INJEC_CONV_TMR1_CC4 = ((uint8_t)0x01), ADC_EXT_TRIG_INJEC_CONV_NONE = ((uint8_t)0x07), - /** for ADC3 only */ + /* for ADC3 only */ ADC_EXT_TRIG_INJEC_CONV_TMR4_CC3 = ((uint8_t)0x02), ADC_EXT_TRIG_INJEC_CONV_TMR8_CC2 = ((uint8_t)0x03), ADC_EXT_TRIG_INJEC_CONV_TMR8_CC4 = ((uint8_t)0x04), @@ -189,9 +216,9 @@ typedef enum */ typedef enum { - ADC_INT_AWD = ((uint16_t)0x0140), //!< Analog Watchdog interrupt - ADC_INT_EOC = ((uint16_t)0x0220), //!< End Of Conversion interrupt - ADC_INT_INJEOC = ((uint16_t)0x0480) //!< Injected Channel End Of Conversion interrupt + ADC_INT_AWD = ((uint16_t)0x0140), /*!< Analog Watchdog interrupt */ + ADC_INT_EOC = ((uint16_t)0x0220), /*!< End Of Conversion interrupt */ + ADC_INT_INJEOC = ((uint16_t)0x0480) /*!< Injected Channel End Of Conversion interrupt */ } ADC_INT_T; /** @@ -199,43 +226,16 @@ typedef enum */ typedef enum { - ADC_FLAG_AWD = ((uint8_t)0x01), //!< Analog Watchdog event occur flag - ADC_FLAG_EOC = ((uint8_t)0x02), //!< End Of Conversion flag - ADC_FLAG_INJEOC = ((uint8_t)0x04), //!< Injected Channel End Of Conversion flag - ADC_FLAG_INJCS = ((uint8_t)0x08), //!< Injected Channel Conversion Start flag - ADC_FLAG_REGCS = ((uint8_t)0x10) //!< Regular Channel Conversion Start flag + ADC_FLAG_AWD = ((uint8_t)0x01), /*!< Analog Watchdog event occur flag */ + ADC_FLAG_EOC = ((uint8_t)0x02), /*!< End Of Conversion flag */ + ADC_FLAG_INJEOC = ((uint8_t)0x04), /*!< Injected Channel End Of Conversion flag */ + ADC_FLAG_INJCS = ((uint8_t)0x08), /*!< Injected Channel Conversion Start flag */ + ADC_FLAG_REGCS = ((uint8_t)0x10) /*!< Regular Channel Conversion Start flag */ } ADC_FLAG_T; /**@} end of group ADC_Enumerations*/ - -/** @addtogroup ADC_Macros Macros - @{ -*/ - -/** ADC_IJD Offset */ -#define INJDATA_OFFSET ((uint8_t)0x28) - -/** ADC_RDG register address */ -#define RDG_ADDRESS ((uint32_t)0x4001244C) - -/** INJSEQ register config */ -#define INJSEQ_SET_INJSEQC ((uint32_t)0x0000001F) -#define INJSEQ_SET_INJSEQLEN ((uint32_t)0x00300000) - -/** SMPTIM register SET */ -#define SMPCYCCFG_SET_SMPTIM1 ((uint32_t)0x00000007) -#define SMPCYCCFG_SET_SMPTIM2 ((uint32_t)0x00000007) - -/** REGSEQ register SET */ -#define REGSEQC_SET_REGSEQ3 ((uint32_t)0x0000001F) -#define REGSEQC_SET_REGSEQ2 ((uint32_t)0x0000001F) -#define REGSEQC_SET_REGSEQ1 ((uint32_t)0x0000001F) - -/**@} end of group ADC_Macros*/ - - -/** @addtogroup ADC_Structure Data Structure +/** @defgroup ADC_Structures Structures @{ */ @@ -245,89 +245,89 @@ typedef enum typedef struct { ADC_MODE_T mode; - uint8_t scanConvMode; //!< This parameter can be ENABLE or DISABLE. - uint8_t continuosConvMode; //!< This parameter can be ENABLE or DISABLE. + uint8_t scanConvMode; /*!< This parameter can be ENABLE or DISABLE. */ + uint8_t continuosConvMode; /*!< This parameter can be ENABLE or DISABLE. */ ADC_EXT_TRIG_CONV_T externalTrigConv; ADC_DATA_ALIGN_T dataAlign; - uint8_t nbrOfChannel; //!< This parameter must range from 1 to 16. + uint8_t nbrOfChannel; /*!< This parameter must range from 1 to 16. */ } ADC_Config_T; -/**@} end of group ADC_Structure*/ +/**@} end of group ADC_Structures*/ -/** @addtogroup ADC_Fuctions Fuctions +/** @defgroup ADC_Functions Functions @{ */ -/** ADC reset and common configuration */ +/* ADC reset and common configuration */ void ADC_Reset(ADC_T* adc); void ADC_Config(ADC_T* adc, ADC_Config_T* adcConfig); void ADC_ConfigStructInit(ADC_Config_T* adcConfig); -void ADC_ConfigRegularChannel(ADC_T* adc, uint8_t channel,uint8_t rank, uint8_t sampleTime); +void ADC_ConfigRegularChannel(ADC_T* adc, uint8_t channel, uint8_t rank, uint8_t sampleTime); void ADC_Enable(ADC_T* adc); void ADC_Disable(ADC_T* adc); -/** ADC for DMA */ +/* ADC for DMA */ void ADC_EnableDMA(ADC_T* adc); void ADC_DisableDMA(ADC_T* adc); -/** ADC Calibration */ +/* ADC Calibration */ void ADC_ResetCalibration(ADC_T* adc); uint8_t ADC_ReadResetCalibrationStatus(ADC_T* adc); void ADC_StartCalibration(ADC_T* adc); uint8_t ADC_ReadCalibrationStartFlag(ADC_T* adc); -/** ADC software start conversion */ +/* ADC software start conversion */ void ADC_EnableSoftwareStartConv(ADC_T* adc); void ADC_DisableSoftwareStartConv(ADC_T* adc); uint8_t ADC_ReadSoftwareStartConvStatus(ADC_T* adc); -/** ADC Discontinuous mode */ +/* ADC Discontinuous mode */ void ADC_ConfigDiscMode(ADC_T* adc, uint8_t number); void ADC_EnableDiscMode(ADC_T* adc); void ADC_DisableDiscMode(ADC_T* adc); -/** ADC External trigger conversion */ +/* ADC External trigger conversion */ void ADC_EnableExternalTrigConv(ADC_T* adc); void ADC_DisableExternalTrigConv(ADC_T* adc); -/** ADC Conversion result */ +/* ADC Conversion result */ uint16_t ADC_ReadConversionValue(ADC_T* adc); uint32_t ADC_ReadDualModeConversionValue(ADC_T* adc); -/** ADC Automatic injected group */ +/* ADC Automatic injected group */ void ADC_EnableAutoInjectedConv(ADC_T* adc); void ADC_DisableAutoInjectedConv(ADC_T* adc); void ADC_EnableInjectedDiscMode(ADC_T* adc); void ADC_DisableInjectedDiscMode(ADC_T* adc); -/** ADC External trigger for injected channels conversion */ +/* ADC External trigger for injected channels conversion */ void ADC_ConfigExternalTrigInjectedConv(ADC_T* adc, ADC_EXT_TRIG_INJEC_CONV_T extTrigInjecConv); void ADC_EnableExternalTrigInjectedConv(ADC_T* adc); void ADC_DisableExternalTrigInjectedConv(ADC_T* adc); -/** ADC Start of the injected channels conversion */ +/* ADC Start of the injected channels conversion */ void ADC_EnableSoftwareStartInjectedConv(ADC_T* adc); void ADC_DisableSoftwareStartInjectedConv(ADC_T* adc); uint8_t ADC_ReadSoftwareStartInjectedConvStatus(ADC_T* adc); -/** ADC injected channel */ +/* ADC injected channel */ void ADC_ConfigInjectedChannel(ADC_T* adc, uint8_t channel, uint8_t rank, uint8_t sampleTime); void ADC_ConfigInjectedSequencerLength(ADC_T* adc, uint8_t length); void ADC_ConfigInjectedOffset(ADC_T* adc, ADC_INJEC_CHANNEL_T channel, uint16_t offSet); uint16_t ADC_ReadInjectedConversionValue(ADC_T* adc, ADC_INJEC_CHANNEL_T channel); -/** ADC analog watchdog */ +/* ADC analog watchdog */ void ADC_EnableAnalogWatchdog(ADC_T* adc, uint32_t analogWatchdog); void ADC_DisableAnalogWatchdog(ADC_T* adc); void ADC_ConfigAnalogWatchdogThresholds(ADC_T* adc, uint16_t highThreshold, uint16_t lowThreshold); void ADC_ConfigAnalogWatchdogSingleChannel(ADC_T* adc, uint8_t channel); -/** ADC temperature sensor */ +/* ADC temperature sensor */ void ADC_EnableTempSensorVrefint(ADC_T* adc); void ADC_DisableTempSensorVrefint(ADC_T* adc); -/** Interrupt and flag */ +/* Interrupt and flag */ void ADC_EnableInterrupt(ADC_T* adc, uint16_t interrupt); void ADC_DisableInterrupt(ADC_T* adc, uint16_t interrupt); uint8_t ADC_ReadStatusFlag(ADC_T* adc, ADC_FLAG_T flag); @@ -335,12 +335,14 @@ void ADC_ClearStatusFlag(ADC_T* adc, uint8_t flag); uint8_t ADC_ReadIntFlag(ADC_T* adc, ADC_INT_T flag); void ADC_ClearIntFlag(ADC_T* adc, uint16_t flag); -/**@} end of group ADC_Fuctions*/ -/**@} end of group ADC_Driver*/ -/**@} end of group Peripherals_Library*/ + #ifdef __cplusplus } + +/**@} end of group ADC_Functions*/ +/**@} end of group ADC_Driver*/ +/**@} end of group APM32F10x_StdPeriphDriver */ #endif -#endif /** __APM32F10X_ADC_H */ +#endif /* __APM32F10X_ADC_H */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_bakpr.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_bakpr.h index 874d621682..3b72519388 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_bakpr.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_bakpr.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the BAKPR firmware library. * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,13 +26,14 @@ #ifndef __APM32F10X_BAKPR_H #define __APM32F10X_BAKPR_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,7 +41,7 @@ @{ */ -/** @addtogroup BAKPR_Enumerations Enumerations +/** @defgroup BAKPR_Enumerations Enumerations @{ */ @@ -116,11 +117,11 @@ typedef enum /**@} end of group BAKPR_Enumerations*/ -/** @addtogroup BAKPR_Fuctions Fuctions +/** @defgroup BAKPR_Functions Functions @{ */ -/** BAKPR reset and configuration */ +/* BAKPR reset and configuration */ void BAKPR_Reset(void); void BAKPR_ConfigTamperPinLevel(BAKPR_TAMPER_PIN_LEVEL_T value); void BAKPR_EnableTamperPin(void); @@ -130,7 +131,7 @@ void BAKPR_ConfigRTCCalibrationValue(uint8_t calibrationValue); void BAKPR_ConfigBackupRegister(BAKPR_DATA_T bakrData, uint16_t data); uint16_t BAKPR_ReadBackupRegister(BAKPR_DATA_T bakrData); -/** Interrupts and flags */ +/* Interrupts and flags */ void BAKPR_EnableInterrupt(void); void BAKPR_DisableInterrupt(void); uint8_t BAKPR_ReadStatusFlag(void); @@ -138,9 +139,9 @@ void BAKPR_ClearStatusFlag(void); uint8_t BAKPR_ReadIntFlag(void); void BAKPR_ClearIntFlag(void); -/**@} end of group BAKPR_Fuctions*/ -/**@} end of group BAKPR_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group BAKPR_Functions*/ +/**@} end of group BAKPR_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_can.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_can.h index cd676d4817..47d4973c2a 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_can.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_can.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the CAN firmware library * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,16 +23,18 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_CAN_H #define __APM32F10X_CAN_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,7 +42,7 @@ @{ */ -/** @addtogroup CAN_Enumerations Enumerations +/** @defgroup CAN_Enumerations Enumerations @{ */ @@ -49,10 +51,10 @@ */ typedef enum { - CAN_MODE_NORMAL = ((uint8_t)0x00), //!< normal mode - CAN_MODE_LOOPBACK = ((uint8_t)0x01), //!< loopback mode - CAN_MODE_SILENT = ((uint8_t)0x02), //!< silent mode - CAN_MODE_SILENT_LOOPBACK = ((uint8_t)0x03) //!< loopback combined with silent mode + CAN_MODE_NORMAL = ((uint8_t)0x00), /*!< normal mode */ + CAN_MODE_LOOPBACK = ((uint8_t)0x01), /*!< loopback mode */ + CAN_MODE_SILENT = ((uint8_t)0x02), /*!< silent mode */ + CAN_MODE_SILENT_LOOPBACK = ((uint8_t)0x03) /*!< loopback combined with silent mode */ } CAN_MODE_T; /** @@ -60,10 +62,10 @@ typedef enum */ typedef enum { - CAN_SJW_1 = ((uint8_t)0x00), //!< 1 time quantum - CAN_SJW_2 = ((uint8_t)0x01), //!< 2 time quantum - CAN_SJW_3 = ((uint8_t)0x02), //!< 3 time quantum - CAN_SJW_4 = ((uint8_t)0x03) //!< 4 time quantum + CAN_SJW_1 = ((uint8_t)0x00), /*!< 1 time quantum */ + CAN_SJW_2 = ((uint8_t)0x01), /*!< 2 time quantum */ + CAN_SJW_3 = ((uint8_t)0x02), /*!< 3 time quantum */ + CAN_SJW_4 = ((uint8_t)0x03) /*!< 4 time quantum */ } CAN_SJW_T; /** @@ -71,22 +73,22 @@ typedef enum */ typedef enum { - CAN_TIME_SEGMENT1_1 = ((uint8_t)0x00), //!< 1 time quanta - CAN_TIME_SEGMENT1_2 = ((uint8_t)0x01), //!< 2 time quanta - CAN_TIME_SEGMENT1_3 = ((uint8_t)0x02), //!< 3 time quanta - CAN_TIME_SEGMENT1_4 = ((uint8_t)0x03), //!< 4 time quanta - CAN_TIME_SEGMENT1_5 = ((uint8_t)0x04), //!< 5 time quanta - CAN_TIME_SEGMENT1_6 = ((uint8_t)0x05), //!< 6 time quanta - CAN_TIME_SEGMENT1_7 = ((uint8_t)0x06), //!< 7 time quanta - CAN_TIME_SEGMENT1_8 = ((uint8_t)0x07), //!< 8 time quanta - CAN_TIME_SEGMENT1_9 = ((uint8_t)0x08), //!< 9 time quanta - CAN_TIME_SEGMENT1_10 = ((uint8_t)0x09), //!< 10 time quanta - CAN_TIME_SEGMENT1_11 = ((uint8_t)0x0A), //!< 11 time quanta - CAN_TIME_SEGMENT1_12 = ((uint8_t)0x0B), //!< 12 time quanta - CAN_TIME_SEGMENT1_13 = ((uint8_t)0x0C), //!< 13 time quanta - CAN_TIME_SEGMENT1_14 = ((uint8_t)0x0D), //!< 14 time quanta - CAN_TIME_SEGMENT1_15 = ((uint8_t)0x0E), //!< 15 time quanta - CAN_TIME_SEGMENT1_16 = ((uint8_t)0x0F) //!< 16 time quanta + CAN_TIME_SEGMENT1_1 = ((uint8_t)0x00), /*!< 1 time quanta */ + CAN_TIME_SEGMENT1_2 = ((uint8_t)0x01), /*!< 2 time quanta */ + CAN_TIME_SEGMENT1_3 = ((uint8_t)0x02), /*!< 3 time quanta */ + CAN_TIME_SEGMENT1_4 = ((uint8_t)0x03), /*!< 4 time quanta */ + CAN_TIME_SEGMENT1_5 = ((uint8_t)0x04), /*!< 5 time quanta */ + CAN_TIME_SEGMENT1_6 = ((uint8_t)0x05), /*!< 6 time quanta */ + CAN_TIME_SEGMENT1_7 = ((uint8_t)0x06), /*!< 7 time quanta */ + CAN_TIME_SEGMENT1_8 = ((uint8_t)0x07), /*!< 8 time quanta */ + CAN_TIME_SEGMENT1_9 = ((uint8_t)0x08), /*!< 9 time quanta */ + CAN_TIME_SEGMENT1_10 = ((uint8_t)0x09), /*!< 10 time quanta */ + CAN_TIME_SEGMENT1_11 = ((uint8_t)0x0A), /*!< 11 time quanta */ + CAN_TIME_SEGMENT1_12 = ((uint8_t)0x0B), /*!< 12 time quanta */ + CAN_TIME_SEGMENT1_13 = ((uint8_t)0x0C), /*!< 13 time quanta */ + CAN_TIME_SEGMENT1_14 = ((uint8_t)0x0D), /*!< 14 time quanta */ + CAN_TIME_SEGMENT1_15 = ((uint8_t)0x0E), /*!< 15 time quanta */ + CAN_TIME_SEGMENT1_16 = ((uint8_t)0x0F) /*!< 16 time quanta */ } CAN_TIME_SEGMENT1_T; /** @@ -94,14 +96,14 @@ typedef enum */ typedef enum { - CAN_TIME_SEGMENT2_1 = (uint8_t)0x00, //!< 1 time quanta - CAN_TIME_SEGMENT2_2 = (uint8_t)0x01, //!< 2 time quanta - CAN_TIME_SEGMENT2_3 = (uint8_t)0x02, //!< 3 time quanta - CAN_TIME_SEGMENT2_4 = (uint8_t)0x03, //!< 4 time quanta - CAN_TIME_SEGMENT2_5 = (uint8_t)0x04, //!< 5 time quanta - CAN_TIME_SEGMENT2_6 = (uint8_t)0x05, //!< 6 time quanta - CAN_TIME_SEGMENT2_7 = (uint8_t)0x06, //!< 7 time quanta - CAN_TIME_SEGMENT2_8 = (uint8_t)0x07 //!< 8 time quanta + CAN_TIME_SEGMENT2_1 = (uint8_t)0x00, /*!< 1 time quanta */ + CAN_TIME_SEGMENT2_2 = (uint8_t)0x01, /*!< 2 time quanta */ + CAN_TIME_SEGMENT2_3 = (uint8_t)0x02, /*!< 3 time quanta */ + CAN_TIME_SEGMENT2_4 = (uint8_t)0x03, /*!< 4 time quanta */ + CAN_TIME_SEGMENT2_5 = (uint8_t)0x04, /*!< 5 time quanta */ + CAN_TIME_SEGMENT2_6 = (uint8_t)0x05, /*!< 6 time quanta */ + CAN_TIME_SEGMENT2_7 = (uint8_t)0x06, /*!< 7 time quanta */ + CAN_TIME_SEGMENT2_8 = (uint8_t)0x07 /*!< 8 time quanta */ } CAN_TIME_SEGMENT2_T; /** @@ -109,8 +111,8 @@ typedef enum */ typedef enum { - CAN_FILTER_FIFO_0 = ((uint8_t)0x00), //!< filter FIFO 0 - CAN_FILTER_FIFO_1 = ((uint8_t)0x01) //!< filter FIFO 1 + CAN_FILTER_FIFO_0 = ((uint8_t)0x00), /*!< filter FIFO 0 */ + CAN_FILTER_FIFO_1 = ((uint8_t)0x01) /*!< filter FIFO 1 */ } CAN_FILTER_FIFO_T; /** @@ -118,8 +120,8 @@ typedef enum */ typedef enum { - CAN_FILTER_MODE_IDMASK = ((uint8_t)0x00),//!< identifier/mask mode - CAN_FILTER_MODE_IDLIST = ((uint8_t)0x01) //!< identifier list mode + CAN_FILTER_MODE_IDMASK = ((uint8_t)0x00),/*!< identifier/mask mode */ + CAN_FILTER_MODE_IDLIST = ((uint8_t)0x01) /*!< identifier list mode */ } CAN_FILTER_MODE_T; /** @@ -127,8 +129,8 @@ typedef enum */ typedef enum { - CAN_FILTER_SCALE_16BIT = ((uint8_t)0x00), //!< Two 16-bit filters - CAN_FILTER_SCALE_32BIT = ((uint8_t)0x01) //!< One 32-bit filter + CAN_FILTER_SCALE_16BIT = ((uint8_t)0x00), /*!< Two 16-bit filters */ + CAN_FILTER_SCALE_32BIT = ((uint8_t)0x01) /*!< One 32-bit filter */ } CAN_FILTER_SCALE_T; /** @@ -136,8 +138,8 @@ typedef enum */ typedef enum { - CAN_TYPEID_STD = ((uint32_t)0x00000000), //!< Standard Id - CAN_TYPEID_EXT = ((uint32_t)0x00000004) //!< Extended Id + CAN_TYPEID_STD = ((uint32_t)0x00000000), /*!< Standard Id */ + CAN_TYPEID_EXT = ((uint32_t)0x00000004) /*!< Extended Id */ } CAN_TYPEID_T; /** @@ -145,8 +147,8 @@ typedef enum */ typedef enum { - CAN_RTXR_DATA = ((uint32_t)0x00000000), //!< Data frame - CAN_RTXR_REMOTE = ((uint32_t)0x00000002) //!< Remote frame + CAN_RTXR_DATA = ((uint32_t)0x00000000), /*!< Data frame */ + CAN_RTXR_REMOTE = ((uint32_t)0x00000002) /*!< Remote frame */ } CAN_RTXR_T; /** @@ -154,9 +156,9 @@ typedef enum */ typedef enum { - CAN_TX_MAILBIX_0 = ((uint8_t)0x00), //!< Tx mailbox0 - CAN_TX_MAILBIX_1 = ((uint8_t)0x01), //!< Tx mailbox1 - CAN_TX_MAILBIX_2 = ((uint8_t)0x02) //!< Tx mailbox2 + CAN_TX_MAILBIX_0 = ((uint8_t)0x00), /*!< Tx mailbox0 */ + CAN_TX_MAILBIX_1 = ((uint8_t)0x01), /*!< Tx mailbox1 */ + CAN_TX_MAILBIX_2 = ((uint8_t)0x02) /*!< Tx mailbox2 */ } CAN_TX_MAILBIX_T; /** @@ -164,8 +166,8 @@ typedef enum */ typedef enum { - CAN_RX_FIFO_0 = ((uint8_t)0x00), //!< receive FIFO 0 - CAN_RX_FIFO_1 = ((uint8_t)0x01) //!< receive FIFO 1 + CAN_RX_FIFO_0 = ((uint8_t)0x00), /*!< receive FIFO 0 */ + CAN_RX_FIFO_1 = ((uint8_t)0x01) /*!< receive FIFO 1 */ } CAN_RX_FIFO_T; /** @@ -173,9 +175,9 @@ typedef enum */ typedef enum { - CAN_OPERATING_MODE_INIT = ((uint8_t)0x00), //!< Initialization mode - CAN_OPERATING_MODE_NORMAL = ((uint8_t)0x01), //!< Normal mode - CAN_OPERATING_MODE_SLEEP = ((uint8_t)0x02) //!< sleep mode + CAN_OPERATING_MODE_INIT = ((uint8_t)0x00), /*!< Initialization mode */ + CAN_OPERATING_MODE_NORMAL = ((uint8_t)0x01), /*!< Normal mode */ + CAN_OPERATING_MODE_SLEEP = ((uint8_t)0x02) /*!< sleep mode */ } CAN_OPERATING_MODE_T; /** @@ -183,20 +185,20 @@ typedef enum */ typedef enum { - CAN_INT_TXME = ((uint32_t)0x00000001), //!< Transmit mailbox empty Interrupt - CAN_INT_F0MP = ((uint32_t)0x00000002), //!< FIFO 0 message pending Interrupt - CAN_INT_F0FULL = ((uint32_t)0x00000004), //!< FIFO 0 full Interrupt - CAN_INT_F0OVR = ((uint32_t)0x00000008), //!< FIFO 0 overrun Interrupt - CAN_INT_F1MP = ((uint32_t)0x00000010), //!< FIFO 1 message pending Interrupt - CAN_INT_F1FULL = ((uint32_t)0x00000020), //!< FIFO 1 full Interrupt - CAN_INT_F1OVR = ((uint32_t)0x00000040), //!< FIFO 1 overrun Interrupt - CAN_INT_ERRW = ((uint32_t)0x00000100), //!< Error warning Interrupt - CAN_INT_ERRP = ((uint32_t)0x00000200), //!< Error passive Interrupt - CAN_INT_BOF = ((uint32_t)0x00000400), //!< Bus-off Interrupt - CAN_INT_LEC = ((uint32_t)0x00000800), //!< Last error record code Interrupt - CAN_INT_ERR = ((uint32_t)0x00008000), //!< Error Interrupt - CAN_INT_WUP = ((uint32_t)0x00010000), //!< Wake-up Interrupt - CAN_INT_SLEEP = ((uint32_t)0x00020000) //!< Sleep acknowledge Interrupt + CAN_INT_TXME = ((uint32_t)0x00000001), /*!< Transmit mailbox empty Interrupt */ + CAN_INT_F0MP = ((uint32_t)0x00000002), /*!< FIFO 0 message pending Interrupt */ + CAN_INT_F0FULL = ((uint32_t)0x00000004), /*!< FIFO 0 full Interrupt */ + CAN_INT_F0OVR = ((uint32_t)0x00000008), /*!< FIFO 0 overrun Interrupt */ + CAN_INT_F1MP = ((uint32_t)0x00000010), /*!< FIFO 1 message pending Interrupt */ + CAN_INT_F1FULL = ((uint32_t)0x00000020), /*!< FIFO 1 full Interrupt */ + CAN_INT_F1OVR = ((uint32_t)0x00000040), /*!< FIFO 1 overrun Interrupt */ + CAN_INT_ERRW = ((uint32_t)0x00000100), /*!< Error warning Interrupt */ + CAN_INT_ERRP = ((uint32_t)0x00000200), /*!< Error passive Interrupt */ + CAN_INT_BOF = ((uint32_t)0x00000400), /*!< Bus-off Interrupt */ + CAN_INT_LEC = ((uint32_t)0x00000800), /*!< Last error record code Interrupt */ + CAN_INT_ERR = ((uint32_t)0x00008000), /*!< Error Interrupt */ + CAN_INT_WUP = ((uint32_t)0x00010000), /*!< Wake-up Interrupt */ + CAN_INT_SLEEP = ((uint32_t)0x00020000) /*!< Sleep acknowledge Interrupt */ } CAN_INT_T; /** @@ -205,28 +207,31 @@ typedef enum typedef enum { /** Error flag*/ - CAN_FLAG_ERRW = ((uint32_t)0x10F00001), //!< Error Warning Flag - CAN_FLAG_ERRP = ((uint32_t)0x10F00002), //!< Error Passive Flag - CAN_FLAG_BOF = ((uint32_t)0x10F00004), //!< Bus-Off Flag - CAN_FLAG_LERRC = ((uint32_t)0x30F00070), //!< Last error record code Flag + CAN_FLAG_ERRW = ((uint32_t)0x10F00001), /*!< Error Warning Flag */ + CAN_FLAG_ERRP = ((uint32_t)0x10F00002), /*!< Error Passive Flag */ + CAN_FLAG_BOF = ((uint32_t)0x10F00004), /*!< Bus-Off Flag */ + CAN_FLAG_LERRC = ((uint32_t)0x30F00070), /*!< Last error record code Flag */ /** Operating Mode Flags */ - CAN_FLAG_WUPI = ((uint32_t)0x31000008), //!< Wake up Flag - CAN_FLAG_SLEEP = ((uint32_t)0x31000012), //!< Sleep acknowledge Flag + CAN_FLAG_WUPI = ((uint32_t)0x31000008), /*!< Wake up Flag */ + CAN_FLAG_SLEEP = ((uint32_t)0x31000012), /*!< Sleep acknowledge Flag */ /** Receive Flags */ - CAN_FLAG_F0MP = ((uint32_t)0x12000003), //!< FIFO 0 Message Pending Flag - CAN_FLAG_F0FULL = ((uint32_t)0x32000008), //!< FIFO 0 Full Flag - CAN_FLAG_F0OVR = ((uint32_t)0x32000010), //!< FIFO 0 Overrun Flag - CAN_FLAG_F1MP = ((uint32_t)0x14000003), //!< FIFO 1 Message Pending Flag - CAN_FLAG_F1FULL = ((uint32_t)0x34000008), //!< FIFO 1 Full Flag - CAN_FLAG_F1OVR = ((uint32_t)0x34000010), //!< FIFO 1 Overrun Flag + CAN_FLAG_F0MP = ((uint32_t)0x12000003), /*!< FIFO 0 Message Pending Flag */ + CAN_FLAG_F0FULL = ((uint32_t)0x32000008), /*!< FIFO 0 Full Flag */ + CAN_FLAG_F0OVR = ((uint32_t)0x32000010), /*!< FIFO 0 Overrun Flag */ + CAN_FLAG_F1MP = ((uint32_t)0x14000003), /*!< FIFO 1 Message Pending Flag */ + CAN_FLAG_F1FULL = ((uint32_t)0x34000008), /*!< FIFO 1 Full Flag */ + CAN_FLAG_F1OVR = ((uint32_t)0x34000010), /*!< FIFO 1 Overrun Flag */ /** Transmit Flags */ - CAN_FLAG_REQC0 = ((uint32_t)0x38000001), //!< Request MailBox0 Flag - CAN_FLAG_REQC1 = ((uint32_t)0x38000100), //!< Request MailBox1 Flag - CAN_FLAG_REQC2 = ((uint32_t)0x38010000) //!< Request MailBox2 Flag + CAN_FLAG_REQC0 = ((uint32_t)0x38000001), /*!< Request MailBox0 Flag */ + CAN_FLAG_REQC1 = ((uint32_t)0x38000100), /*!< Request MailBox1 Flag */ + CAN_FLAG_REQC2 = ((uint32_t)0x38010000) /*!< Request MailBox2 Flag */ } CAN_FLAG_T; /**@} end of group CAN_Enumerations*/ +/** @defgroup CAN_Structures Structures + @{ +*/ /** * @brief CAN Config structure definition @@ -237,18 +242,18 @@ typedef enum */ typedef struct { - uint8_t autoBusOffManage; //!< Enable or disable the automatic bus-off management. - uint8_t autoWakeUpMode; //!< Enable or disable the automatic wake-up mode. - uint8_t nonAutoRetran; //!< Enable or disable the non-automatic retransmission mode. - uint8_t rxFIFOLockMode; //!< Enable or disable the Receive FIFO Locked mode. - uint8_t txFIFOPriority; //!< Enable or disable the transmit FIFO priority. - CAN_MODE_T mode; //!< Specifies the CAN operating mode. - CAN_SJW_T syncJumpWidth; /** Specifies the maximum number of time quanta the CAN hardware - * is allowed to lengthen or shorten a bit to perform resynchronization. - */ - CAN_TIME_SEGMENT1_T timeSegment1; //!< Specifies the number of time quanta in Bit Segment 1. - CAN_TIME_SEGMENT2_T timeSegment2; //!< Specifies the number of time quanta in Bit Segment 2. - uint16_t prescaler; //!< Specifies the length of a time quantum. It can be 1 to 1024. + uint8_t autoBusOffManage; /*!< Enable or disable the automatic bus-off management. */ + uint8_t autoWakeUpMode; /*!< Enable or disable the automatic wake-up mode. */ + uint8_t nonAutoRetran; /*!< Enable or disable the non-automatic retransmission mode. */ + uint8_t rxFIFOLockMode; /*!< Enable or disable the Receive FIFO Locked mode. */ + uint8_t txFIFOPriority; /*!< Enable or disable the transmit FIFO priority. */ + CAN_MODE_T mode; /*!< Specifies the CAN operating mode. */ + CAN_SJW_T syncJumpWidth; /* Specifies the maximum number of time quanta the CAN hardware + is allowed to lengthen or shorten a bit to perform resynchronization. + */ + CAN_TIME_SEGMENT1_T timeSegment1; /*!< Specifies the number of time quanta in Bit Segment 1. */ + CAN_TIME_SEGMENT2_T timeSegment2; /*!< Specifies the number of time quanta in Bit Segment 2. */ + uint16_t prescaler; /*!< Specifies the length of a time quantum. It can be 1 to 1024. */ } CAN_Config_T; /** @@ -256,12 +261,12 @@ typedef struct */ typedef struct { - uint32_t stdID; //!< Specifies the standard identifier. It can be 0 to 0x7FF. - uint32_t extID; //!< Specifies the extended identifier. It can be 0 to 0x1FFFFFFF. + uint32_t stdID; /*!< Specifies the standard identifier. It can be 0 to 0x7FF. */ + uint32_t extID; /*!< Specifies the extended identifier. It can be 0 to 0x1FFFFFFF. */ CAN_TYPEID_T typeID; CAN_RTXR_T remoteTxReq; - uint8_t dataLengthCode;//!< Specifies the data length code. It can be 0 to 8. - uint8_t data[8]; //!< Specifies the data to be transmitted. It can be 0 to 0xFF. + uint8_t dataLengthCode;/*!< Specifies the data length code. It can be 0 to 8. */ + uint8_t data[8]; /*!< Specifies the data to be transmitted. It can be 0 to 0xFF. */ } CAN_TxMessage_T; /** @@ -269,13 +274,13 @@ typedef struct */ typedef struct { - uint32_t stdID; //!< Specifies the standard identifier. It can be 0 to 0x7FF. - uint32_t extID; //!< Specifies the extended identifier. It can be 0 to 0x1FFFFFFF. + uint32_t stdID; /*!< Specifies the standard identifier. It can be 0 to 0x7FF. */ + uint32_t extID; /*!< Specifies the extended identifier. It can be 0 to 0x1FFFFFFF. */ uint32_t typeID; uint32_t remoteTxReq; - uint8_t dataLengthCode; //!< Specifies the data length code. It can be 0 to 8. - uint8_t data[8]; //!< Specifies the data to be transmitted. It can be 0 to 0xFF. - uint8_t filterMatchIndex;//!< Specifies the filter match index. It can be 0 to 0xFF. + uint8_t dataLengthCode; /*!< Specifies the data length code. It can be 0 to 8. */ + uint8_t data[8]; /*!< Specifies the data to be transmitted. It can be 0 to 0xFF. */ + uint8_t filterMatchIndex;/*!< Specifies the filter match index. It can be 0 to 0xFF. */ } CAN_RxMessage_T; /** @@ -283,54 +288,58 @@ typedef struct */ typedef struct { - uint8_t filterNumber; //!< Specifies the filter number. It can be 0 to 13. - uint16_t filterIdHigh; //!< Specifies the filter identification number.It can be 0 to 0xFFFF. - uint16_t filterIdLow; //!< Specifies the filter identification number.It can be 0 to 0xFFFF. - uint16_t filterMaskIdHigh; //!< Specifies the filter mask identification. It can be 0 to 0xFFFF. - uint16_t filterMaskIdLow; //!< Specifies the filter mask identification. It can be 0 to 0xFFFF. - uint16_t filterActivation; //!< Specifies the filter Activation. It can be ENABLE or DISABLE. + uint8_t filterNumber; /*!< Specifies the filter number. It can be 0 to 13. */ + uint16_t filterIdHigh; /*!< Specifies the filter identification number.It can be 0 to 0xFFFF. */ + uint16_t filterIdLow; /*!< Specifies the filter identification number.It can be 0 to 0xFFFF. */ + uint16_t filterMaskIdHigh; /*!< Specifies the filter mask identification. It can be 0 to 0xFFFF. */ + uint16_t filterMaskIdLow; /*!< Specifies the filter mask identification. It can be 0 to 0xFFFF. */ + uint16_t filterActivation; /*!< Specifies the filter Activation. It can be ENABLE or DISABLE. */ CAN_FILTER_FIFO_T filterFIFO; CAN_FILTER_MODE_T filterMode; CAN_FILTER_SCALE_T filterScale; } CAN_FilterConfig_T; -/**@} end of group CAN_Structure*/ +/**@} end of group CAN_Structures*/ -/** @addtogroup CAN_Fuctions Fuctions +/** @defgroup CAN_Functions Functions @{ */ -/** CAN reset and configuration */ +/* CAN reset and configuration */ void CAN_Reset(CAN_T* can); uint8_t CAN_Config(CAN_T* can, CAN_Config_T* canConfig); +#if defined(APM32F10X_CL) +void CAN_ConfigFilter(CAN_FilterConfig_T* filterConfig); +void CAN_SlaveStartBank(uint8_t bankNum); +#else void CAN_ConfigFilter(CAN_T* can, CAN_FilterConfig_T* filterConfig); +#endif void CAN_ConfigStructInit(CAN_Config_T* canConfig); void CAN_EnableDBGFreeze(CAN_T* can); void CAN_DisableDBGFreeze(CAN_T* can); -void CAN_SlaveStartBank(CAN_T* can, uint8_t bankNum); -/** CAN frames transmit */ +/* CAN frames transmit */ uint8_t CAN_TxMessage(CAN_T* can, CAN_TxMessage_T* TxMessage); uint8_t CAN_TxMessageStatus(CAN_T* can, CAN_TX_MAILBIX_T TxMailbox); void CAN_CancelTxMailbox(CAN_T* can, CAN_TX_MAILBIX_T TxMailbox); -/** CAN frames receive */ +/* CAN frames receive */ void CAN_RxMessage(CAN_T* can, CAN_RX_FIFO_T FIFONumber, CAN_RxMessage_T* RxMessage); void CAN_ReleaseFIFO(CAN_T* can, CAN_RX_FIFO_T FIFONumber); uint8_t CAN_PendingMessage(CAN_T* can, CAN_RX_FIFO_T FIFONumber); -/** CAN operation modes */ +/* CAN operation modes */ uint8_t CAN_OperatingMode(CAN_T* can, CAN_OPERATING_MODE_T operatingMode); uint8_t CAN_SleepMode(CAN_T* can); uint8_t CAN_WakeUpMode(CAN_T* can); -/** CAN bus error management */ +/* CAN bus error management */ uint8_t CAN_ReadLastErrorCode(CAN_T* can); uint8_t CAN_ReadRxErrorCounter(CAN_T* can); uint8_t CAN_ReadLSBTxErrorCounter(CAN_T* can); -/** CAN interrupt and flag */ +/* CAN interrupt and flag */ void CAN_EnableInterrupt(CAN_T* can, uint32_t interrupt); void CAN_DisableInterrupt(CAN_T* can, uint32_t interrupt); uint8_t CAN_ReadStatusFlag(CAN_T* can, CAN_FLAG_T flag); @@ -338,9 +347,9 @@ void CAN_ClearStatusFlag(CAN_T* can, CAN_FLAG_T flag); uint8_t CAN_ReadIntFlag(CAN_T* can, CAN_INT_T flag); void CAN_ClearIntFlag(CAN_T* can, CAN_INT_T flag); -/**@} end of group CAN_Fuctions*/ -/**@} end of group CAN_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group CAN_Functions*/ +/**@} end of group CAN_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_crc.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_crc.h index 27a9ab64e0..58b2750719 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_crc.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_crc.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the CRC firmware library * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,13 +26,14 @@ #ifndef __APM32F10X_CRC_H #define __APM32F10X_CRC_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,27 +41,26 @@ @{ */ -/** @addtogroup CRC_Fuctions Fuctions +/** @defgroup CRC_Functions Functions @{ */ -/** Reset DATA */ +/* Reset DATA */ void CRC_ResetDATA(void); -/** Operation functions */ +/* Operation functions */ uint32_t CRC_CalculateCRC(uint32_t data); -uint32_t CRC_CalculateBlockCRC(uint32_t *buf, uint32_t bufLen); +uint32_t CRC_CalculateBlockCRC(uint32_t* buf, uint32_t bufLen); uint32_t CRC_ReadCRC(void); void CRC_WriteIDRegister(uint8_t inData); uint8_t CRC_ReadIDRegister(void); -/**@} end of group CRC_Fuctions*/ -/**@} end of group CRC_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group CRC_Functions*/ +/**@} end of group CRC_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ #ifdef __cplusplus } #endif #endif /* __APM32F10X_CRC_H */ - diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_dac.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_dac.h index 74df98d0bf..a73e219e2e 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_dac.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_dac.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the DAC firmware library * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,13 +26,14 @@ #ifndef __APM32F10X_DAC_H #define __APM32F10X_DAC_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,7 +41,7 @@ @{ */ -/** @addtogroup DAC_Enumerations Enumerations +/** @defgroup DAC_Enumerations Enumerations @{ */ @@ -51,7 +52,7 @@ typedef enum { DAC_CHANNEL_1 = 0x00000000, DAC_CHANNEL_2 = 0x00000010 -}DAC_CHANNEL_T; +} DAC_CHANNEL_T; /** * @brief DAC trigger selection @@ -67,7 +68,7 @@ typedef enum DAC_TRIGGER_TMR4_TRGO = 0x0000002C, DAC_TRIGGER_EINT9 = 0x00000034, DAC_TRIGGER_SOFT = 0x0000003C -}DAC_TRIGGER_T; +} DAC_TRIGGER_T; /** * @brief DAC wave generation @@ -77,39 +78,39 @@ typedef enum DAC_WAVE_GENERATION_NONE = 0x00000000, DAC_WAVE_GENERATION_NOISE = 0x00000040, DAC_WAVE_GENERATION_TRIANGLE = 0x00000080 -}DAC_WAVE_GENERATION_T; +} DAC_WAVE_GENERATION_T; /** * @brief DAC channelx mask/amplitude selector */ typedef enum { - DAC_LFSR_MASK_BIT11_1 = 0x00000000, //!< Mask bit[11:1] of LFSR for noise wave generation - DAC_LFSR_MASK_BIT11_2 = 0x00000100, //!< Mask bit[11:2] of LFSR for noise wave generation - DAC_LFSR_MASK_BIT11_3 = 0x00000200, //!< Mask bit[11:3] of LFSR for noise wave generation - DAC_LFSR_MASK_BIT11_4 = 0x00000300, //!< Mask bit[11:4] of LFSR for noise wave generation - DAC_LFSR_MASK_BIT11_5 = 0x00000400, //!< Mask bit[11:5] of LFSR for noise wave generation - DAC_LFSR_MASK_BIT11_6 = 0x00000500, //!< Mask bit[11:6] of LFSR for noise wave generation - DAC_LFSR_MASK_BIT11_7 = 0x00000600, //!< Mask bit[11:7] of LFSR for noise wave generation - DAC_LFSR_MASK_BIT11_8 = 0x00000700, //!< Mask bit[11:8] of LFSR for noise wave generation - DAC_LFSR_MASK_BIT11_9 = 0x00000800, //!< Mask bit[11:9] of LFSR for noise wave generation - DAC_LFSR_MASK_BIT11_10 = 0x00000900, //!< Mask bit[11:10] of LFSR for noise wave generation - DAC_LFSR_MASK_BIT11 = 0x00000A00, //!< Mask bit11 of LFSR for noise wave generation - DAC_LFSR_MASK_NONE = 0x00000B00, //!< Mask none bit of LFSR for noise wave generation + DAC_LFSR_MASK_BIT11_1 = 0x00000000, /*!< Mask bit[11:1] of LFSR for noise wave generation */ + DAC_LFSR_MASK_BIT11_2 = 0x00000100, /*!< Mask bit[11:2] of LFSR for noise wave generation */ + DAC_LFSR_MASK_BIT11_3 = 0x00000200, /*!< Mask bit[11:3] of LFSR for noise wave generation */ + DAC_LFSR_MASK_BIT11_4 = 0x00000300, /*!< Mask bit[11:4] of LFSR for noise wave generation */ + DAC_LFSR_MASK_BIT11_5 = 0x00000400, /*!< Mask bit[11:5] of LFSR for noise wave generation */ + DAC_LFSR_MASK_BIT11_6 = 0x00000500, /*!< Mask bit[11:6] of LFSR for noise wave generation */ + DAC_LFSR_MASK_BIT11_7 = 0x00000600, /*!< Mask bit[11:7] of LFSR for noise wave generation */ + DAC_LFSR_MASK_BIT11_8 = 0x00000700, /*!< Mask bit[11:8] of LFSR for noise wave generation */ + DAC_LFSR_MASK_BIT11_9 = 0x00000800, /*!< Mask bit[11:9] of LFSR for noise wave generation */ + DAC_LFSR_MASK_BIT11_10 = 0x00000900, /*!< Mask bit[11:10] of LFSR for noise wave generation */ + DAC_LFSR_MASK_BIT11 = 0x00000A00, /*!< Mask bit11 of LFSR for noise wave generation */ + DAC_LFSR_MASK_NONE = 0x00000B00, /*!< Mask none bit of LFSR for noise wave generation */ - DAC_TRIANGLE_AMPLITUDE_1 = 0x00000000, //!< Triangle amplitude equal to 1 - DAC_TRIANGLE_AMPLITUDE_3 = 0x00000100, //!< Triangle amplitude equal to 3 - DAC_TRIANGLE_AMPLITUDE_7 = 0x00000200, //!< Triangle amplitude equal to 7 - DAC_TRIANGLE_AMPLITUDE_15 = 0x00000300, //!< Triangle amplitude equal to 15 - DAC_TRIANGLE_AMPLITUDE_31 = 0x00000400, //!< Triangle amplitude equal to 31 - DAC_TRIANGLE_AMPLITUDE_63 = 0x00000500, //!< Triangle amplitude equal to 63 - DAC_TRIANGLE_AMPLITUDE_127 = 0x00000600, //!< Triangle amplitude equal to 127 - DAC_TRIANGLE_AMPLITUDE_255 = 0x00000700, //!< Triangle amplitude equal to 255 - DAC_TRIANGLE_AMPLITUDE_511 = 0x00000800, //!< Triangle amplitude equal to 511 - DAC_TRIANGLE_AMPLITUDE_1023 = 0x00000900, //!< Triangle amplitude equal to 1023 - DAC_TRIANGLE_AMPLITUDE_2047 = 0x00000A00, //!< Triangle amplitude equal to 2047 - DAC_TRIANGLE_AMPLITUDE_4095 = 0x00000B00 //!< Triangle amplitude equal to 4095 -}DAC_MASK_AMPLITUDE_SEL_T; + DAC_TRIANGLE_AMPLITUDE_1 = 0x00000000, /*!< Triangle amplitude equal to 1 */ + DAC_TRIANGLE_AMPLITUDE_3 = 0x00000100, /*!< Triangle amplitude equal to 3 */ + DAC_TRIANGLE_AMPLITUDE_7 = 0x00000200, /*!< Triangle amplitude equal to 7 */ + DAC_TRIANGLE_AMPLITUDE_15 = 0x00000300, /*!< Triangle amplitude equal to 15 */ + DAC_TRIANGLE_AMPLITUDE_31 = 0x00000400, /*!< Triangle amplitude equal to 31 */ + DAC_TRIANGLE_AMPLITUDE_63 = 0x00000500, /*!< Triangle amplitude equal to 63 */ + DAC_TRIANGLE_AMPLITUDE_127 = 0x00000600, /*!< Triangle amplitude equal to 127 */ + DAC_TRIANGLE_AMPLITUDE_255 = 0x00000700, /*!< Triangle amplitude equal to 255 */ + DAC_TRIANGLE_AMPLITUDE_511 = 0x00000800, /*!< Triangle amplitude equal to 511 */ + DAC_TRIANGLE_AMPLITUDE_1023 = 0x00000900, /*!< Triangle amplitude equal to 1023 */ + DAC_TRIANGLE_AMPLITUDE_2047 = 0x00000A00, /*!< Triangle amplitude equal to 2047 */ + DAC_TRIANGLE_AMPLITUDE_4095 = 0x00000B00 /*!< Triangle amplitude equal to 4095 */ +} DAC_MASK_AMPLITUDE_SEL_T; /** * @brief DAC output buffer @@ -118,7 +119,7 @@ typedef enum { DAC_OUTPUT_BUFFER_ENBALE = 0x00000000, DAC_OUTPUT_BUFFER_DISABLE = 0x00000002 -}DAC_OUTPUT_BUFFER_T; +} DAC_OUTPUT_BUFFER_T; /** * @brief DAC data align @@ -128,12 +129,12 @@ typedef enum DAC_ALIGN_12BIT_R = 0x00000000, DAC_ALIGN_12BIT_L = 0x00000004, DAC_ALIGN_8BIT_R = 0x00000008 -}DAC_ALIGN_T; +} DAC_ALIGN_T; /**@} end of group DAC_Enumerations*/ -/** @addtogroup DAC_Structure Data Structure +/** @defgroup DAC_Structures Structures @{ */ @@ -146,47 +147,47 @@ typedef struct DAC_OUTPUT_BUFFER_T outputBuffer; DAC_WAVE_GENERATION_T waveGeneration; DAC_MASK_AMPLITUDE_SEL_T maskAmplitudeSelect; -}DAC_Config_T; +} DAC_Config_T; -/**@} end of group DAC_Structure*/ +/**@} end of group DAC_Structures*/ -/** @addtogroup DAC_Fuctions Fuctions +/** @defgroup DAC_Functions Functions @{ */ -/** DAC Reset and Configuration */ +/* DAC Reset and Configuration */ void DAC_Reset(void); void DAC_Config(uint32_t channel, DAC_Config_T* dacConfig); void DAC_ConfigStructInit(DAC_Config_T* dacConfig); void DAC_Enable(DAC_CHANNEL_T channel); void DAC_Disable(DAC_CHANNEL_T channel); -/** DAC channel for DAM */ +/* DAC channel for DAM */ void DAC_DMA_Enable(DAC_CHANNEL_T channel); void DAC_DMA_Disable(DAC_CHANNEL_T channel); -/** DAC channel software trigger */ +/* DAC channel software trigger */ void DAC_EnableSoftwareTrigger(DAC_CHANNEL_T channel); void DAC_DisableSoftwareTrigger(DAC_CHANNEL_T channel); void DAC_EnableDualSoftwareTrigger(void); void DAC_DisableDualSoftwareTrigger(void); -/** DAC channel wave generation */ +/* DAC channel wave generation */ void DAC_EnableWaveGeneration(DAC_CHANNEL_T channel, DAC_WAVE_GENERATION_T wave); void DAC_DisableWaveGeneration(DAC_CHANNEL_T channel, DAC_WAVE_GENERATION_T wave); -/** DAC set channel data */ +/* DAC set channel data */ void DAC_ConfigChannel1Data(DAC_ALIGN_T align, uint16_t data); void DAC_ConfigChannel2Data(DAC_ALIGN_T align, uint16_t data); void DAC_ConfigDualChannelData(DAC_ALIGN_T align, uint16_t data2, uint16_t data1); -/** DAC read data output value */ +/* DAC read data output value */ uint16_t DAC_ReadDataOutputValue(DAC_CHANNEL_T channel); -/**@} end of group DAC_Fuctions*/ -/**@} end of group DAC_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group DAC_Functions*/ +/**@} end of group DAC_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_dbgmcu.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_dbgmcu.h index aaf8365958..68dee4171a 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_dbgmcu.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_dbgmcu.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the DBUGMCU firmware library * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,16 +23,18 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_DBGMCU_H #define __APM32F10X_DBGMCU_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,10 +42,13 @@ @{ */ -/** @addtogroup DBGMCU_Enumerations Enumerations +/** @defgroup DBGMCU_Enumerations Enumerations @{ */ +/** + * @brief DBGMCU_STOP description + */ enum { DBGMCU_SLEEP = ((uint32_t)0x00000001), @@ -77,7 +82,7 @@ enum /**@} end of group DBGMCU_Enumerations*/ -/** @addtogroup DBGMCU_Fuctions Fuctions +/** @defgroup DBGMCU_Functions Functions @{ */ @@ -86,9 +91,9 @@ uint32_t DBGMCU_ReadREVID(void); void DBGMCU_Enable(uint32_t periph); void DBGMCU_Disable(uint32_t periph); -/**@} end of group DBGMCU_Fuctions*/ -/**@} end of group DBGMCU_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group DBGMCU_Functions*/ +/**@} end of group DBGMCU_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_dma.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_dma.h index 02d0be4c54..8dae060314 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_dma.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_dma.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the DMA firmware library * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,13 +26,14 @@ #ifndef __APM32F10X_DMA_H #define __APM32F10X_DMA_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,7 +41,7 @@ @{ */ -/** @addtogroup DMA_Enumerations Enumerations +/** @defgroup DMA_Enumerations Enumerations @{ */ @@ -245,7 +246,7 @@ typedef enum /**@} end of group DMA_Enumerations*/ -/** @addtogroup DMA_Structure Data Structure +/** @defgroup DMA_Structures Structures @{ */ @@ -267,35 +268,35 @@ typedef struct DMA_M2MEN_T M2M; } DMA_Config_T; -/**@} end of group DMA_Structure*/ +/**@} end of group DMA_Structures*/ -/** @addtogroup DMA_Fuctions Fuctions +/** @defgroup DMA_Functions Functions @{ */ -/** Reset and configuration */ -void DMA_Reset(DMA_Channel_T *channel); +/* Reset and configuration */ +void DMA_Reset(DMA_Channel_T* channel); void DMA_Config(DMA_Channel_T* channel, DMA_Config_T* dmaConfig); -void DMA_ConfigStructInit( DMA_Config_T* dmaConfig); -void DMA_Enable(DMA_Channel_T *channel); -void DMA_Disable(DMA_Channel_T *channel); +void DMA_ConfigStructInit(DMA_Config_T* dmaConfig); +void DMA_Enable(DMA_Channel_T* channel); +void DMA_Disable(DMA_Channel_T* channel); -/** Data number */ -void DMA_ConfigDataNumber(DMA_Channel_T *channel, uint16_t dataNumber); -uint16_t DMA_ReadDataNumber(DMA_Channel_T *channel); +/* Data number */ +void DMA_ConfigDataNumber(DMA_Channel_T* channel, uint16_t dataNumber); +uint16_t DMA_ReadDataNumber(DMA_Channel_T* channel); -/** Interrupt and flag */ -void DMA_EnableInterrupt(DMA_Channel_T *channel, uint32_t interrupt); -void DMA_DisableInterrupt(DMA_Channel_T *channel, uint32_t interrupt); +/* Interrupt and flag */ +void DMA_EnableInterrupt(DMA_Channel_T* channel, uint32_t interrupt); +void DMA_DisableInterrupt(DMA_Channel_T* channel, uint32_t interrupt); uint8_t DMA_ReadStatusFlag(DMA_FLAG_T flag); void DMA_ClearStatusFlag(uint32_t flag); uint8_t DMA_ReadIntFlag(DMA_INT_FLAG_T flag); void DMA_ClearIntFlag(uint32_t flag); -/**@} end of group DMA_Fuctions*/ -/**@} end of group DMA_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group DMA_Functions*/ +/**@} end of group DMA_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_dmc.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_dmc.h index f6b2b70e5a..fcc44a5532 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_dmc.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_dmc.h @@ -3,9 +3,9 @@ * * @brief This file contains all the prototypes,enumeration and macros for the DMC peripheral * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,13 +26,14 @@ #ifndef __APM32F10X_DMC_H #define __APM32F10X_DMC_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,11 +41,10 @@ @{ */ -/** @addtogroup DMC_Enumerations Enumerations +/** @defgroup DMC_Enumerations Enumerations @{ */ - /** * @brief Bank Address Width */ @@ -52,7 +52,7 @@ typedef enum { DMC_BANK_WIDTH_1, DMC_BANK_WIDTH_2 -}DMC_BANK_WIDTH_T; +} DMC_BANK_WIDTH_T; /** * @brief Row Address Width @@ -65,7 +65,7 @@ typedef enum DMC_ROW_WIDTH_14, DMC_ROW_WIDTH_15, DMC_ROW_WIDTH_16 -}DMC_ROW_WIDTH_T; +} DMC_ROW_WIDTH_T; /** * @brief Column Address Width @@ -80,7 +80,7 @@ typedef enum DMC_COL_WIDTH_13, DMC_COL_WIDTH_14, DMC_COL_WIDTH_15 -}DMC_COL_WIDTH_T; +} DMC_COL_WIDTH_T; /** * @brief CAS Latency Select @@ -91,7 +91,7 @@ typedef enum DMC_CAS_LATENCY_2, DMC_CAS_LATENCY_3, DMC_CAS_LATENCY_4 -}DMC_CAS_LATENCY_T; +} DMC_CAS_LATENCY_T; /** * @brief RAS Minimun Time Select @@ -114,7 +114,7 @@ typedef enum DMC_RAS_MINIMUM_14, DMC_RAS_MINIMUM_15, DMC_RAS_MINIMUM_16 -}DMC_RAS_MINIMUM_T; +} DMC_RAS_MINIMUM_T; /** * @brief RAS To CAS Delay Time Select @@ -129,7 +129,7 @@ typedef enum DMC_DELAY_TIME_6, DMC_DELAY_TIME_7, DMC_DELAY_TIME_8 -}DMC_DELAY_TIME_T; +} DMC_DELAY_TIME_T; /** * @brief Precharge Period Select @@ -144,7 +144,7 @@ typedef enum DMC_PRECHARGE_6, DMC_PRECHARGE_7, DMC_PRECHARGE_8 -}DMC_PRECHARGE_T; +} DMC_PRECHARGE_T; /** * @brief Last Data Next Precharge For Write Time Select @@ -155,7 +155,7 @@ typedef enum DMC_NEXT_PRECHARGE_2, DMC_NEXT_PRECHARGE_3, DMC_NEXT_PRECHARGE_4 -}DMC_NEXT_PRECHARGE_T; +} DMC_NEXT_PRECHARGE_T; /** * @brief Auto-Refresh Period Select @@ -178,7 +178,7 @@ typedef enum DMC_AUTO_REFRESH_14, DMC_AUTO_REFRESH_15, DMC_AUTO_REFRESH_16, -}DMC_AUTO_REFRESH_T; +} DMC_AUTO_REFRESH_T; /** * @brief Active-to-active Command Period Select @@ -201,7 +201,7 @@ typedef enum DMC_ATA_CMD_14, DMC_ATA_CMD_15, DMC_ATA_CMD_16, -}DMC_ATA_CMD_T; +} DMC_ATA_CMD_T; /** * @brief Clock PHASE @@ -210,7 +210,7 @@ typedef enum { DMC_CLK_PHASE_NORMAL, DMC_CLK_PHASE_REVERSE -}DMC_CLK_PHASE_T; +} DMC_CLK_PHASE_T; /** * @brief DMC Memory Size @@ -231,7 +231,7 @@ typedef enum DMC_MEMORY_SIZE_64MB, DMC_MEMORY_SIZE_128MB, DMC_MEMORY_SIZE_256MB, -}DMC_MEMORY_SIZE_T; +} DMC_MEMORY_SIZE_T; /** * @brief Open Banks Of Number @@ -254,25 +254,25 @@ typedef enum DMC_BANK_NUMBER_14, DMC_BANK_NUMBER_15, DMC_BANK_NUMBER_16, -}DMC_BANK_NUMBER_T; +} DMC_BANK_NUMBER_T; /** * @brief Full refresh type */ typedef enum { - DMC_REFRESH_ROW_ONE, //!< Refresh one row - DMC_REFRESH_ROW_ALL, //!< Refresh all row -}DMC_REFRESH_T; + DMC_REFRESH_ROW_ONE, /*!< Refresh one row */ + DMC_REFRESH_ROW_ALL, /*!< Refresh all row */ +} DMC_REFRESH_T; /** * @brief Precharge type */ typedef enum { - DMC_PRECHARGE_IM, //!< Immediate precharge - DMC_PRECHARGE_DELAY, //!< Delayed precharge -}DMC_PRECHARE_T; + DMC_PRECHARGE_IM, /*!< Immediate precharge */ + DMC_PRECHARGE_DELAY, /*!< Delayed precharge */ +} DMC_PRECHARE_T; /** * @brief WRAP Burst Type @@ -281,12 +281,12 @@ typedef enum { DMC_WRAPB_4, DMC_WRAPB_8, -}DMC_WRPB_T; +} DMC_WRPB_T; /**@} end of group DMC_Enumerations*/ -/** @addtogroup DMC_Structure Data Structure +/** @defgroup DMC_Structures Structures @{ */ @@ -295,66 +295,66 @@ typedef enum */ typedef struct { - uint32_t latencyCAS : 2; //!< DMC_CAS_LATENCY_T - uint32_t tRAS : 4; //!< DMC_RAS_MINIMUM_T - uint32_t tRCD : 3; //!< DMC_DELAY_TIME_T - uint32_t tRP : 3; //!< DMC_PRECHARGE_T - uint32_t tWR : 2; //!< DMC_NEXT_PRECHARGE_T - uint32_t tARP : 4; //!< DMC_AUTO_REFRESH_T - uint32_t tCMD : 4; //!< DMC_ATA_CMD_T - uint32_t tXSR : 9; //!< auto-refresh commands, can be 0x000 to 0x1FF - uint16_t tRFP : 16; //!< Refresh period, can be 0x0000 to 0xFFFF -}DMC_TimingConfig_T; + uint32_t latencyCAS : 2; /*!< DMC_CAS_LATENCY_T */ + uint32_t tRAS : 4; /*!< DMC_RAS_MINIMUM_T */ + uint32_t tRCD : 3; /*!< DMC_DELAY_TIME_T */ + uint32_t tRP : 3; /*!< DMC_PRECHARGE_T */ + uint32_t tWR : 2; /*!< DMC_NEXT_PRECHARGE_T */ + uint32_t tARP : 4; /*!< DMC_AUTO_REFRESH_T */ + uint32_t tCMD : 4; /*!< DMC_ATA_CMD_T */ + uint32_t tXSR : 9; /*!< auto-refresh commands, can be 0x000 to 0x1FF */ + uint16_t tRFP : 16; /*!< Refresh period, can be 0x0000 to 0xFFFF */ +} DMC_TimingConfig_T; /** * @brief Config struct definition */ typedef struct { - DMC_MEMORY_SIZE_T memorySize; //!< Memory size(byte) - DMC_BANK_WIDTH_T bankWidth; //!< Number of bank bits - DMC_ROW_WIDTH_T rowWidth; //!< Number of row address bits - DMC_COL_WIDTH_T colWidth; //!< Number of col address bits - DMC_CLK_PHASE_T clkPhase; //!< Clock phase - DMC_TimingConfig_T timing; //!< Timing -}DMC_Config_T; + DMC_MEMORY_SIZE_T memorySize; /*!< Memory size(byte) */ + DMC_BANK_WIDTH_T bankWidth; /*!< Number of bank bits */ + DMC_ROW_WIDTH_T rowWidth; /*!< Number of row address bits */ + DMC_COL_WIDTH_T colWidth; /*!< Number of col address bits */ + DMC_CLK_PHASE_T clkPhase; /*!< Clock phase */ + DMC_TimingConfig_T timing; /*!< Timing */ +} DMC_Config_T; -/**@} end of group DMC_Structure*/ +/**@} end of group DMC_Structures*/ -/** @addtogroup DMC_Fuctions Fuctions +/** @defgroup DMC_Functions Functions @{ */ - /** Enable / Disable */ +/* Enable / Disable */ void DMC_Enable(void); void DMC_Disable(void); void DMC_EnableInit(void); -/** Global config */ +/* Global config */ void DMC_Config(DMC_Config_T* dmcConfig); void DMC_ConfigStructInit(DMC_Config_T* dmcConfig); -/** Address */ +/* Address */ void DMC_ConfigBankWidth(DMC_BANK_WIDTH_T bankWidth); void DMC_ConfigAddrWidth(DMC_ROW_WIDTH_T rowWidth, DMC_COL_WIDTH_T colWidth); -/** Timing */ +/* Timing */ void DMC_ConfigTiming(DMC_TimingConfig_T* timingConfig); void DMC_ConfigTimingStructInit(DMC_TimingConfig_T* timingConfig); void DMC_ConfigStableTimePowerup(uint16_t stableTime); void DMC_ConfigAutoRefreshNumDuringInit(DMC_AUTO_REFRESH_T num); void DMC_ConfigRefreshPeriod(uint16_t period); -/** Refresh mode */ +/* Refresh mode */ void DMC_EixtSlefRefreshMode(void); void DMC_EnterSlefRefreshMode(void); -/** Accelerate Module */ +/* Accelerate Module */ void DMC_EnableAccelerateModule(void); void DMC_DisableAccelerateModule(void); -/** Config */ +/* Config */ void DMC_ConfigOpenBank(DMC_BANK_NUMBER_T num); void DMC_EnableUpdateMode(void); void DMC_EnterPowerdownMode(void); @@ -365,12 +365,12 @@ void DMC_ConfigMemorySize(DMC_MEMORY_SIZE_T memorySize); void DMC_ConfigClockPhase(DMC_CLK_PHASE_T clkPhase); void DMC_ConfigWRAPB(DMC_WRPB_T burst); -/** read flag */ +/* read flag */ uint8_t DMC_ReadSelfRefreshStatus(void); -/**@} end of group DMC_Fuctions*/ +/**@} end of group DMC_Functions*/ /**@} end of group DMC_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group APM32F10x_StdPeriphDriver*/ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_eint.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_eint.h index 7cf3cb1454..74e8ac8573 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_eint.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_eint.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the EINT firmware library * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,16 +23,18 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_EINT_H #define __APM32F10X_EINT_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,7 +42,7 @@ @{ */ -/** @addtogroup EINT_Enumerations Enumerations +/** @defgroup EINT_Enumerations Enumerations @{ */ @@ -65,32 +67,32 @@ typedef enum typedef enum { - EINT_LINENONE = 0x00000, //! - EINT_LINE_0 = 0x00001, //!< External interrupt line 0 - EINT_LINE_1 = 0x00002, //!< External interrupt line 1 - EINT_LINE_2 = 0x00004, //!< External interrupt line 2 - EINT_LINE_3 = 0x00008, //!< External interrupt line 3 - EINT_LINE_4 = 0x00010, //!< External interrupt line 4 - EINT_LINE_5 = 0x00020, //!< External interrupt line 5 - EINT_LINE_6 = 0x00040, //!< External interrupt line 6 - EINT_LINE_7 = 0x00080, //!< External interrupt line 7 - EINT_LINE_8 = 0x00100, //!< External interrupt line 8 - EINT_LINE_9 = 0x00200, //!< External interrupt line 9 - EINT_LINE_10 = 0x00400, //!< External interrupt line 10 - EINT_LINE_11 = 0x00800, //!< External interrupt line 11 - EINT_LINE_12 = 0x01000, //!< External interrupt line 12 - EINT_LINE_13 = 0x02000, //!< External interrupt line 13 - EINT_LINE_14 = 0x04000, //!< External interrupt line 14 - EINT_LINE_15 = 0x08000, //!< External interrupt line 15 - EINT_LINE_16 = 0x10000, //!< External interrupt line 16 Connected to the PVD Output - EINT_LINE_17 = 0x20000, //!< External interrupt line 17 Connected to the RTC Alarm event - EINT_LINE_18 = 0x40000, //!< External interrupt line 18 Connected to the USB Device + EINT_LINENONE = 0x00000, /*! */ + EINT_LINE_0 = 0x00001, /*!< External interrupt line 0 */ + EINT_LINE_1 = 0x00002, /*!< External interrupt line 1 */ + EINT_LINE_2 = 0x00004, /*!< External interrupt line 2 */ + EINT_LINE_3 = 0x00008, /*!< External interrupt line 3 */ + EINT_LINE_4 = 0x00010, /*!< External interrupt line 4 */ + EINT_LINE_5 = 0x00020, /*!< External interrupt line 5 */ + EINT_LINE_6 = 0x00040, /*!< External interrupt line 6 */ + EINT_LINE_7 = 0x00080, /*!< External interrupt line 7 */ + EINT_LINE_8 = 0x00100, /*!< External interrupt line 8 */ + EINT_LINE_9 = 0x00200, /*!< External interrupt line 9 */ + EINT_LINE_10 = 0x00400, /*!< External interrupt line 10 */ + EINT_LINE_11 = 0x00800, /*!< External interrupt line 11 */ + EINT_LINE_12 = 0x01000, /*!< External interrupt line 12 */ + EINT_LINE_13 = 0x02000, /*!< External interrupt line 13 */ + EINT_LINE_14 = 0x04000, /*!< External interrupt line 14 */ + EINT_LINE_15 = 0x08000, /*!< External interrupt line 15 */ + EINT_LINE_16 = 0x10000, /*!< External interrupt line 16 Connected to the PVD Output */ + EINT_LINE_17 = 0x20000, /*!< External interrupt line 17 Connected to the RTC Alarm event */ + EINT_LINE_18 = 0x40000, /*!< External interrupt line 18 Connected to the USB Device */ } EINT_LINE_T; /**@} end of group EINT_Enumerations*/ -/** @addtogroup EINT_Structure Data Structure +/** @defgroup EINT_Structures Structures @{ */ @@ -105,31 +107,31 @@ typedef struct uint8_t lineCmd; } EINT_Config_T; -/**@} end of group EINT_Structure*/ +/**@} end of group EINT_Structures*/ -/** @addtogroup EINT_Fuctions Fuctions +/** @defgroup EINT_Functions Functions @{ */ -/** Reset and configuration */ +/* Reset and configuration */ void EINT_Reset(void); -void EINT_Config( EINT_Config_T* eintConfig); +void EINT_Config(EINT_Config_T* eintConfig); void EINT_ConfigStructInit(EINT_Config_T* eintConfig); -/** Interrupt and flag */ +/* Interrupt and flag */ void EINT_SelectSWInterrupt(uint32_t line); uint8_t EINT_ReadStatusFlag(EINT_LINE_T line); void EINT_ClearStatusFlag(uint32_t line); uint8_t EINT_ReadIntFlag(EINT_LINE_T line); void EINT_ClearIntFlag(uint32_t line); -/**@} end of group EINT_Fuctions*/ -/**@} end of group EINT_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group EINT_Functions*/ +/**@} end of group EINT_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver*/ -#ifdef __cplusplus +#ifdef __APM32F10X_cplusplus } #endif -#endif /* __APM32F10XEINT_H */ +#endif /* __EINT_H */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_fmc.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_fmc.h index d8b56e2bf2..240e23efde 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_fmc.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_fmc.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the FMC firmware library * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,16 +23,18 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_FMC_H #define __APM32F10X_FMC_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,7 +42,86 @@ @{ */ -/** @addtogroup FMC_Enumerations Enumerations +/** @defgroup FMC_Macros Macros + @{ +*/ + +/* Macros description */ + +/* Values for APM32 Low and Medium density devices */ +#define FLASH_WRP_PAGE_0_3 ((uint32_t)BIT0) /*!< Write protection of page 0 to 3 */ +#define FLASH_WRP_PAGE_4_7 ((uint32_t)BIT1) /*!< Write protection of page 4 to 7 */ +#define FLASH_WRP_PAGE_8_11 ((uint32_t)BIT2) /*!< Write protection of page 8 to 11 */ +#define FLASH_WRP_PAGE_12_15 ((uint32_t)BIT3) /*!< Write protection of page 12 to 15 */ +#define FLASH_WRP_PAGE_16_19 ((uint32_t)BIT4) /*!< Write protection of page 16 to 19 */ +#define FLASH_WRP_PAGE_20_23 ((uint32_t)BIT5) /*!< Write protection of page 20 to 23 */ +#define FLASH_WRP_PAGE_24_27 ((uint32_t)BIT6) /*!< Write protection of page 24 to 27 */ +#define FLASH_WRP_PAGE_28_31 ((uint32_t)BIT7) /*!< Write protection of page 28 to 31 */ + +/* Values for APM32 Medium-density devices */ +#define FLASH_WRP_PAGE_32_35 ((uint32_t)BIT8) /*!< Write protection of page 32 to 35 */ +#define FLASH_WRP_PAGE_36_39 ((uint32_t)BIT9) /*!< Write protection of page 36 to 39 */ +#define FLASH_WRP_PAGE_40_43 ((uint32_t)BIT10) /*!< Write protection of page 40 to 43 */ +#define FLASH_WRP_PAGE_44_47 ((uint32_t)BIT11) /*!< Write protection of page 44 to 47 */ +#define FLASH_WRP_PAGE_48_51 ((uint32_t)BIT12) /*!< Write protection of page 48 to 51 */ +#define FLASH_WRP_PAGE_52_55 ((uint32_t)BIT13) /*!< Write protection of page 52 to 55 */ +#define FLASH_WRP_PAGE_56_59 ((uint32_t)BIT14) /*!< Write protection of page 56 to 59 */ +#define FLASH_WRP_PAGE_60_63 ((uint32_t)BIT15) /*!< Write protection of page 60 to 63 */ +#define FLASH_WRP_PAGE_64_67 ((uint32_t)BIT16) /*!< Write protection of page 64 to 67 */ +#define FLASH_WRP_PAGE_68_71 ((uint32_t)BIT17) /*!< Write protection of page 68 to 71 */ +#define FLASH_WRP_PAGE_72_75 ((uint32_t)BIT18) /*!< Write protection of page 72 to 75 */ +#define FLASH_WRP_PAGE_76_79 ((uint32_t)BIT19) /*!< Write protection of page 76 to 79 */ +#define FLASH_WRP_PAGE_80_83 ((uint32_t)BIT20) /*!< Write protection of page 80 to 83 */ +#define FLASH_WRP_PAGE_84_87 ((uint32_t)BIT21) /*!< Write protection of page 84 to 87 */ +#define FLASH_WRP_PAGE_88_91 ((uint32_t)BIT22) /*!< Write protection of page 88 to 91 */ +#define FLASH_WRP_PAGE_92_95 ((uint32_t)BIT23) /*!< Write protection of page 92 to 95 */ +#define FLASH_WRP_PAGE_96_99 ((uint32_t)BIT24) /*!< Write protection of page 96 to 99 */ +#define FLASH_WRP_PAGE_100_103 ((uint32_t)BIT25) /*!< Write protection of page 100 to 103 */ +#define FLASH_WRP_PAGE_104_107 ((uint32_t)BIT26) /*!< Write protection of page 104 to 107 */ +#define FLASH_WRP_PAGE_108_111 ((uint32_t)BIT27) /*!< Write protection of page 108 to 111 */ +#define FLASH_WRP_PAGE_112_115 ((uint32_t)BIT28) /*!< Write protection of page 112 to 115 */ +#define FLASH_WRP_PAGE_116_119 ((uint32_t)BIT29) /*!< Write protection of page 116 to 119 */ +#define FLASH_WRP_PAGE_120_123 ((uint32_t)BIT30) /*!< Write protection of page 120 to 123 */ +#define FLASH_WRP_PAGE_124_127 ((uint32_t)BIT31) /*!< Write protection of page 124 to 127 */ + +/* Values only for APM32 High-density devices */ +#define FLASH_WRP_PAGE_0_1 ((uint32_t)BIT0) /*!< Write protection of page 0 to 1 */ +#define FLASH_WRP_PAGE_2_3 ((uint32_t)BIT1) /*!< Write protection of page 2 to 3 */ +#define FLASH_WRP_PAGE_4_5 ((uint32_t)BIT2) /*!< Write protection of page 4 to 5 */ +#define FLASH_WRP_PAGE_6_7 ((uint32_t)BIT3) /*!< Write protection of page 6 to 7 */ +#define FLASH_WRP_PAGE_8_9 ((uint32_t)BIT4) /*!< Write protection of page 8 to 9 */ +#define FLASH_WRP_PAGE_10_11 ((uint32_t)BIT5) /*!< Write protection of page 10 to 11 */ +#define FLASH_WRP_PAGE_12_13 ((uint32_t)BIT6) /*!< Write protection of page 12 to 13 */ +#define FLASH_WRP_PAGE_14_15 ((uint32_t)BIT7) /*!< Write protection of page 14 to 15 */ +#define FLASH_WRP_PAGE_16_17 ((uint32_t)BIT8) /*!< Write protection of page 16 to 17 */ +#define FLASH_WRP_PAGE_18_19 ((uint32_t)BIT9) /*!< Write protection of page 18 to 19 */ +#define FLASH_WRP_PAGE_20_21 ((uint32_t)BIT10) /*!< Write protection of page 20 to 21 */ +#define FLASH_WRP_PAGE_22_23 ((uint32_t)BIT11) /*!< Write protection of page 22 to 23 */ +#define FLASH_WRP_PAGE_24_25 ((uint32_t)BIT12) /*!< Write protection of page 24 to 25 */ +#define FLASH_WRP_PAGE_26_27 ((uint32_t)BIT13) /*!< Write protection of page 26 to 27 */ +#define FLASH_WRP_PAGE_28_29 ((uint32_t)BIT14) /*!< Write protection of page 28 to 29 */ +#define FLASH_WRP_PAGE_30_31 ((uint32_t)BIT15) /*!< Write protection of page 30 to 31 */ +#define FLASH_WRP_PAGE_32_33 ((uint32_t)BIT16) /*!< Write protection of page 32 to 33 */ +#define FLASH_WRP_PAGE_34_35 ((uint32_t)BIT17) /*!< Write protection of page 34 to 35 */ +#define FLASH_WRP_PAGE_36_37 ((uint32_t)BIT18) /*!< Write protection of page 36 to 37 */ +#define FLASH_WRP_PAGE_38_39 ((uint32_t)BIT19) /*!< Write protection of page 38 to 39 */ +#define FLASH_WRP_PAGE_40_41 ((uint32_t)BIT20) /*!< Write protection of page 40 to 41 */ +#define FLASH_WRP_PAGE_42_43 ((uint32_t)BIT21) /*!< Write protection of page 42 to 43 */ +#define FLASH_WRP_PAGE_44_45 ((uint32_t)BIT22) /*!< Write protection of page 44 to 45 */ +#define FLASH_WRP_PAGE_46_47 ((uint32_t)BIT23) /*!< Write protection of page 46 to 47 */ +#define FLASH_WRP_PAGE_48_49 ((uint32_t)BIT24) /*!< Write protection of page 48 to 49 */ +#define FLASH_WRP_PAGE_50_51 ((uint32_t)BIT25) /*!< Write protection of page 50 to 51 */ +#define FLASH_WRP_PAGE_52_53 ((uint32_t)BIT26) /*!< Write protection of page 52 to 53 */ +#define FLASH_WRP_PAGE_54_55 ((uint32_t)BIT27) /*!< Write protection of page 54 to 55 */ +#define FLASH_WRP_PAGE_56_57 ((uint32_t)BIT28) /*!< Write protection of page 56 to 57 */ +#define FLASH_WRP_PAGE_58_59 ((uint32_t)BIT29) /*!< Write protection of page 58 to 59 */ +#define FLASH_WRP_PAGE_60_61 ((uint32_t)BIT30) /*!< Write protection of page 60 to 61 */ +#define FLASH_WRP_PAGE_62_127 ((uint32_t)BIT31) /*!< Write protection of page 62 to 127 */ +#define FMC_WRP_PAGE_ALL ((uint32_t)0xFFFFFFFF) /*!< Write protection of page all */ + +/**@} end of group FMC_Macros*/ + +/** @defgroup FMC_Enumerations Enumerations @{ */ @@ -59,11 +140,11 @@ typedef enum */ typedef enum { - FMC_STATUS_BUSY = 1, //!< flash busy - FMC_STATUS_ERROR_PG, //!< flash programming error - FMC_STATUS_ERROR_WRP, //!< flash write protection error - FMC_STATUS_COMPLETE, //!< flash operation complete - FMC_STATUS_TIMEOUT //!< flash time out + FMC_STATUS_BUSY = 1, /*!< flash busy */ + FMC_STATUS_ERROR_PG, /*!< flash programming error */ + FMC_STATUS_ERROR_WRP, /*!< flash write protection error */ + FMC_STATUS_COMPLETE, /*!< flash operation complete */ + FMC_STATUS_TIMEOUT /*!< flash time out */ } FMC_STATUS_T; /** @@ -107,95 +188,16 @@ typedef enum */ typedef enum { - FMC_FLAG_BUSY = 0x00000001, //!< FMC Busy flag - FMC_FLAG_OC = 0x00000020, //!< FMC End of Operation flag - FMC_FLAG_PE = 0x00000004, //!< FMC Program error flag - FMC_FLAG_WPE = 0x00000010, //!< FMC Write protected error flag - FMC_FLAG_OBE = 0x10000001, //!< FMC Option Byte error flag + FMC_FLAG_BUSY = 0x00000001, /*!< FMC Busy flag */ + FMC_FLAG_OC = 0x00000020, /*!< FMC End of Operation flag */ + FMC_FLAG_PE = 0x00000004, /*!< FMC Program error flag */ + FMC_FLAG_WPE = 0x00000010, /*!< FMC Write protected error flag */ + FMC_FLAG_OBE = 0x10000001, /*!< FMC Option Byte error flag */ } FMC_FLAG_T; /**@} end of group FMC_Enumerations*/ -/** @addtogroup FMC_Macros Macros - @{ -*/ - -/** Macros description */ - -/** Values for APM32 Low and Medium density devices */ -#define FLASH_WRP_PAGE_0_3 ((uint32_t)BIT0) //!< Write protection of page 0 to 3 -#define FLASH_WRP_PAGE_4_7 ((uint32_t)BIT1) //!< Write protection of page 4 to 7 -#define FLASH_WRP_PAGE_8_11 ((uint32_t)BIT2) //!< Write protection of page 8 to 11 -#define FLASH_WRP_PAGE_12_15 ((uint32_t)BIT3) //!< Write protection of page 12 to 15 -#define FLASH_WRP_PAGE_16_19 ((uint32_t)BIT4) //!< Write protection of page 16 to 19 -#define FLASH_WRP_PAGE_20_23 ((uint32_t)BIT5) //!< Write protection of page 20 to 23 -#define FLASH_WRP_PAGE_24_27 ((uint32_t)BIT6) //!< Write protection of page 24 to 27 -#define FLASH_WRP_PAGE_28_31 ((uint32_t)BIT7) //!< Write protection of page 28 to 31 - -/** Values for APM32 Medium-density devices */ -#define FLASH_WRP_PAGE_32_35 ((uint32_t)BIT8) //!< Write protection of page 32 to 35 -#define FLASH_WRP_PAGE_36_39 ((uint32_t)BIT9) //!< Write protection of page 36 to 39 -#define FLASH_WRP_PAGE_40_43 ((uint32_t)BIT10) //!< Write protection of page 40 to 43 -#define FLASH_WRP_PAGE_44_47 ((uint32_t)BIT11) //!< Write protection of page 44 to 47 -#define FLASH_WRP_PAGE_48_51 ((uint32_t)BIT12) //!< Write protection of page 48 to 51 -#define FLASH_WRP_PAGE_52_55 ((uint32_t)BIT13) //!< Write protection of page 52 to 55 -#define FLASH_WRP_PAGE_56_59 ((uint32_t)BIT14) //!< Write protection of page 56 to 59 -#define FLASH_WRP_PAGE_60_63 ((uint32_t)BIT15) //!< Write protection of page 60 to 63 -#define FLASH_WRP_PAGE_64_67 ((uint32_t)BIT16) //!< Write protection of page 64 to 67 -#define FLASH_WRP_PAGE_68_71 ((uint32_t)BIT17) //!< Write protection of page 68 to 71 -#define FLASH_WRP_PAGE_72_75 ((uint32_t)BIT18) //!< Write protection of page 72 to 75 -#define FLASH_WRP_PAGE_76_79 ((uint32_t)BIT19) //!< Write protection of page 76 to 79 -#define FLASH_WRP_PAGE_80_83 ((uint32_t)BIT20) //!< Write protection of page 80 to 83 -#define FLASH_WRP_PAGE_84_87 ((uint32_t)BIT21) //!< Write protection of page 84 to 87 -#define FLASH_WRP_PAGE_88_91 ((uint32_t)BIT22) //!< Write protection of page 88 to 91 -#define FLASH_WRP_PAGE_92_95 ((uint32_t)BIT23) //!< Write protection of page 92 to 95 -#define FLASH_WRP_PAGE_96_99 ((uint32_t)BIT24) //!< Write protection of page 96 to 99 -#define FLASH_WRP_PAGE_100_103 ((uint32_t)BIT25) //!< Write protection of page 100 to 103 -#define FLASH_WRP_PAGE_104_107 ((uint32_t)BIT26) //!< Write protection of page 104 to 107 -#define FLASH_WRP_PAGE_108_111 ((uint32_t)BIT27) //!< Write protection of page 108 to 111 -#define FLASH_WRP_PAGE_112_115 ((uint32_t)BIT28) //!< Write protection of page 112 to 115 -#define FLASH_WRP_PAGE_116_119 ((uint32_t)BIT29) //!< Write protection of page 116 to 119 -#define FLASH_WRP_PAGE_120_123 ((uint32_t)BIT30) //!< Write protection of page 120 to 123 -#define FLASH_WRP_PAGE_124_127 ((uint32_t)BIT31) //!< Write protection of page 124 to 127 - -/** Values only for APM32 High-density devices */ -#define FLASH_WRP_PAGE_0_1 ((uint32_t)BIT0) //!< Write protection of page 0 to 1 -#define FLASH_WRP_PAGE_2_3 ((uint32_t)BIT1) //!< Write protection of page 2 to 3 -#define FLASH_WRP_PAGE_4_5 ((uint32_t)BIT2) //!< Write protection of page 4 to 5 -#define FLASH_WRP_PAGE_6_7 ((uint32_t)BIT3) //!< Write protection of page 6 to 7 -#define FLASH_WRP_PAGE_8_9 ((uint32_t)BIT4) //!< Write protection of page 8 to 9 -#define FLASH_WRP_PAGE_10_11 ((uint32_t)BIT5) //!< Write protection of page 10 to 11 -#define FLASH_WRP_PAGE_12_13 ((uint32_t)BIT6) //!< Write protection of page 12 to 13 -#define FLASH_WRP_PAGE_14_15 ((uint32_t)BIT7) //!< Write protection of page 14 to 15 -#define FLASH_WRP_PAGE_16_17 ((uint32_t)BIT8) //!< Write protection of page 16 to 17 -#define FLASH_WRP_PAGE_18_19 ((uint32_t)BIT9) //!< Write protection of page 18 to 19 -#define FLASH_WRP_PAGE_20_21 ((uint32_t)BIT10) //!< Write protection of page 20 to 21 -#define FLASH_WRP_PAGE_22_23 ((uint32_t)BIT11) //!< Write protection of page 22 to 23 -#define FLASH_WRP_PAGE_24_25 ((uint32_t)BIT12) //!< Write protection of page 24 to 25 -#define FLASH_WRP_PAGE_26_27 ((uint32_t)BIT13) //!< Write protection of page 26 to 27 -#define FLASH_WRP_PAGE_28_29 ((uint32_t)BIT14) //!< Write protection of page 28 to 29 -#define FLASH_WRP_PAGE_30_31 ((uint32_t)BIT15) //!< Write protection of page 30 to 31 -#define FLASH_WRP_PAGE_32_33 ((uint32_t)BIT16) //!< Write protection of page 32 to 33 -#define FLASH_WRP_PAGE_34_35 ((uint32_t)BIT17) //!< Write protection of page 34 to 35 -#define FLASH_WRP_PAGE_36_37 ((uint32_t)BIT18) //!< Write protection of page 36 to 37 -#define FLASH_WRP_PAGE_38_39 ((uint32_t)BIT19) //!< Write protection of page 38 to 39 -#define FLASH_WRP_PAGE_40_41 ((uint32_t)BIT20) //!< Write protection of page 40 to 41 -#define FLASH_WRP_PAGE_42_43 ((uint32_t)BIT21) //!< Write protection of page 42 to 43 -#define FLASH_WRP_PAGE_44_45 ((uint32_t)BIT22) //!< Write protection of page 44 to 45 -#define FLASH_WRP_PAGE_46_47 ((uint32_t)BIT23) //!< Write protection of page 46 to 47 -#define FLASH_WRP_PAGE_48_49 ((uint32_t)BIT24) //!< Write protection of page 48 to 49 -#define FLASH_WRP_PAGE_50_51 ((uint32_t)BIT25) //!< Write protection of page 50 to 51 -#define FLASH_WRP_PAGE_52_53 ((uint32_t)BIT26) //!< Write protection of page 52 to 53 -#define FLASH_WRP_PAGE_54_55 ((uint32_t)BIT27) //!< Write protection of page 54 to 55 -#define FLASH_WRP_PAGE_56_57 ((uint32_t)BIT28) //!< Write protection of page 56 to 57 -#define FLASH_WRP_PAGE_58_59 ((uint32_t)BIT29) //!< Write protection of page 58 to 59 -#define FLASH_WRP_PAGE_60_61 ((uint32_t)BIT30) //!< Write protection of page 60 to 61 -#define FLASH_WRP_PAGE_62_127 ((uint32_t)BIT31) //!< Write protection of page 62 to 127 -#define FMC_WRP_PAGE_ALL ((uint32_t)0xFFFFFFFF) //!< Write protection of page all */ - -/**@} end of group FMC_Macros*/ - -/** @addtogroup FMC_Structure Data Structure +/** @defgroup FMC_Structures Structures @{ */ @@ -211,27 +213,27 @@ typedef struct /**@} end of group FMC_Structure*/ -/** @addtogroup FMC_Fuctions Fuctions +/** @defgroup FMC_Functions Functions @{ */ -/** Initialization and Configuration */ +/* Initialization and Configuration */ void FMC_ConfigLatency(FMC_LATENCY_T latency); void FMC_EnableHalfCycleAccess(void); void FMC_DisableHalfCycleAccess(void); void FMC_EnablePrefetchBuffer(void); void FMC_DisablePrefetchBuffer(void); -/** Lock management */ +/* Lock management */ void FMC_Unlock(void); void FMC_Lock(void); -/** Erase management */ +/* Erase management */ FMC_STATUS_T FMC_ErasePage(uint32_t pageAddr); FMC_STATUS_T FMC_EraseAllPage(void); FMC_STATUS_T FMC_EraseOptionBytes(void); -/** Read Write management */ +/* Read Write management */ FMC_STATUS_T FMC_ProgramWord(uint32_t address, uint32_t data); FMC_STATUS_T FMC_ProgramHalfWord(uint32_t address, uint16_t data); FMC_STATUS_T FMC_ProgramOptionByteData(uint32_t address, uint8_t data); @@ -244,19 +246,19 @@ uint32_t FMC_ReadOptionByteWriteProtection(void); uint8_t FMC_GetReadProtectionStatus(void); uint8_t FMC_ReadPrefetchBufferStatus(void); -/** Interrupts and flags */ +/* Interrupts and flags */ void FMC_EnableInterrupt(FMC_INT_T interrupt); void FMC_DisableInterrupt(FMC_INT_T interrupt); uint8_t FMC_ReadStatusFlag(FMC_FLAG_T flag); void FMC_ClearStatusFlag(uint32_t flag); -/** Status management */ +/* Status management */ FMC_STATUS_T FMC_ReadStatus(void); FMC_STATUS_T FMC_WaitForLastOperation(uint32_t timeOut); -/**@} end of group FMC_Fuctions*/ +/**@} end of group FMC_Functions*/ /**@} end of group FMC_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group APM32F10x_StdPeriphDriver*/ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_gpio.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_gpio.h index b462ba55c5..9ca3b350f9 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_gpio.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_gpio.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the GPIO firmware library * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,16 +23,18 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_GPIO_H #define __APM32F10X_GPIO_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,7 +42,7 @@ @{ */ -/** @addtogroup GPIO_Enumerations Enumerations +/** @defgroup GPIO_Enumerations Enumerations @{ */ @@ -49,25 +51,25 @@ */ typedef enum { - GPIO_SPEED_10MHz = 1, - GPIO_SPEED_20MHz, - GPIO_SPEED_50MHz -}GPIO_SPEED_T; + GPIO_SPEED_10MHz = 1, + GPIO_SPEED_2MHz, + GPIO_SPEED_50MHz +} GPIO_SPEED_T; /** * @brief Configuration Mode enumeration */ typedef enum { - GPIO_MODE_ANALOG = 0x0, //!< Analog mode - GPIO_MODE_IN_FLOATING = 0x04, //!< Floating input - GPIO_MODE_IN_PD = 0x28, //!< Input with pull-down - GPIO_MODE_IN_PU = 0x48, //!< Input with pull-up - GPIO_MODE_OUT_PP = 0x80, //!< General purpose output push-pull - GPIO_MODE_OUT_OD = 0x84, //!< General purpose output Open-drain - GPIO_MODE_AF_PP = 0x88, //!< Alternate function output Push-pull - GPIO_MODE_AF_OD = 0x8C, //!< Alternate function output Open-drain -}GPIO_MODE_T; + GPIO_MODE_ANALOG = 0x0, /*!< Analog mode */ + GPIO_MODE_IN_FLOATING = 0x04, /*!< Floating input */ + GPIO_MODE_IN_PD = 0x28, /*!< Input with pull-down */ + GPIO_MODE_IN_PU = 0x48, /*!< Input with pull-up */ + GPIO_MODE_OUT_PP = 0x80, /*!< General purpose output push-pull */ + GPIO_MODE_OUT_OD = 0x84, /*!< General purpose output Open-drain */ + GPIO_MODE_AF_PP = 0x88, /*!< Alternate function output Push-pull */ + GPIO_MODE_AF_OD = 0x8C, /*!< Alternate function output Open-drain */ +} GPIO_MODE_T; /** * @brief Definition of the GPIO pins @@ -98,113 +100,145 @@ typedef enum */ typedef enum { - GPIO_NO_REMAP_SPI1 = 0x00000010, - GPIO_REMAP_SPI1 = 0x00000011, + GPIO_NO_REMAP_SPI1 = 0x00000010, + GPIO_REMAP_SPI1 = 0x00000011, - GPIO_NO_REMAP_I2C1 = 0x00000110, - GPIO_REMAP_I2C1 = 0x00000111, + GPIO_NO_REMAP_I2C1 = 0x00000110, + GPIO_REMAP_I2C1 = 0x00000111, - GPIO_NO_REMAP_USART1 = 0x00000210, - GPIO_REMAP_USART1 = 0x00000211, + GPIO_NO_REMAP_USART1 = 0x00000210, + GPIO_REMAP_USART1 = 0x00000211, - GPIO_NO_REMAP_USART2 = 0x00000310, - GPIO_REMAP_USART2 = 0x00000311, + GPIO_NO_REMAP_USART2 = 0x00000310, + GPIO_REMAP_USART2 = 0x00000311, - GPIO_NO_REMAP_USART3 = 0x00000430, - GPIO_PARTIAL_REMAP_USART3 = 0x00000431, - GPIO_FULL_REMAP_USART3 = 0x00000433, + GPIO_NO_REMAP_USART3 = 0x00000430, + GPIO_PARTIAL_REMAP_USART3 = 0x00000431, + GPIO_FULL_REMAP_USART3 = 0x00000433, - GPIO_NO_REMAP_TMR1 = 0x00000630, - GPIO_PARTIAL_REMAP_TMR1 = 0x00000631, - GPIO_FULL_REMAP_TMR1 = 0x00000633, + GPIO_NO_REMAP_TMR1 = 0x00000630, + GPIO_PARTIAL_REMAP_TMR1 = 0x00000631, + GPIO_FULL_REMAP_TMR1 = 0x00000633, - GPIO_NO_REMAP_TMR2 = 0x00000830, - GPIO_PARTIAL_REMAP1_TMR2 = 0x00000831, - GPIO_PARTIAL_REMAP2_TMR2 = 0x00000832, - GPIO_FULL_REMAP_TMR2 = 0x00000833, + GPIO_NO_REMAP_TMR2 = 0x00000830, + GPIO_PARTIAL_REMAP1_TMR2 = 0x00000831, + GPIO_PARTIAL_REMAP2_TMR2 = 0x00000832, + GPIO_FULL_REMAP_TMR2 = 0x00000833, - GPIO_NO_REMAP_TMR3 = 0x00000A30, - GPIO_PARTIAL_REMAP_TMR3 = 0x00000A32, - GPIO_FULL_REMAP_TMR3 = 0x00000A33, + GPIO_NO_REMAP_TMR3 = 0x00000A30, + GPIO_PARTIAL_REMAP_TMR3 = 0x00000A32, + GPIO_FULL_REMAP_TMR3 = 0x00000A33, - GPIO_NO_REMAP_TMR4 = 0x00000C10, - GPIO_REMAP_TMR4 = 0x00000C11, + GPIO_NO_REMAP_TMR4 = 0x00000C10, + GPIO_REMAP_TMR4 = 0x00000C11, - GPIO_NO_REMAP_CAN1 = 0x00000D30, - GPIO_REMAP1_CAN1 = 0x00000D32, - GPIO_REMAP2_CAN1 = 0x00000D33, + GPIO_NO_REMAP_CAN1 = 0x00000D30, + GPIO_REMAP1_CAN1 = 0x00000D32, + GPIO_REMAP2_CAN1 = 0x00000D33, - GPIO_NO_REMAP_PD01 = 0x00000F10, - GPIO_REMAP_PD01 = 0x00000F11, + GPIO_NO_REMAP_PD01 = 0x00000F10, + GPIO_REMAP_PD01 = 0x00000F11, - GPIO_NO_REMAP_TMR5CH4_LSI = 0x00001010, - GPIO_REMAP_TMR5CH4_LSI = 0x00001011, + GPIO_NO_REMAP_TMR5CH4_LSI = 0x00001010, + GPIO_REMAP_TMR5CH4_LSI = 0x00001011, - GPIO_NO_REMAP_ADC1_ETRGINJ = 0x00001110, - GPIO_REMAP_ADC1_ETRGINJ = 0x00001111, +#if !defined(APM32F10X_CL) + GPIO_NO_REMAP_ADC1_ETRGINJ = 0x00001110, + GPIO_REMAP_ADC1_ETRGINJ = 0x00001111, - GPIO_NO_REMAP_ADC1_ETRGREG = 0x00001210, - GPIO_REMAP_ADC1_ETRGREG = 0x00001211, + GPIO_NO_REMAP_ADC1_ETRGREG = 0x00001210, + GPIO_REMAP_ADC1_ETRGREG = 0x00001211, - GPIO_NO_REMAP_ADC2_ETRGINJ = 0x00001310, - GPIO_REMAP_ADC2_ETRGINJ = 0x00001311, + GPIO_NO_REMAP_ADC2_ETRGINJ = 0x00001310, + GPIO_REMAP_ADC2_ETRGINJ = 0x00001311, - GPIO_NO_REMAP_ADC2_ETRGREG = 0x00001410, - GPIO_REMAP_ADC2_ETRGREG = 0x00001411, + GPIO_NO_REMAP_ADC2_ETRGREG = 0x00001410, + GPIO_REMAP_ADC2_ETRGREG = 0x00001411, - GPIO_NO_REMAP_CAN2 = 0x00001610, - GPIO_REMAP_CAN2 = 0x00001611, + GPIO_NO_REMAP_ETH = 0x00001510, + GPIO_REMAP_ETH = 0x00001511, - GPIO_NO_REMAP_SWJ = 0x00001870, - GPIO_REMAP_SWJ_NOJTRST = 0x00001871, - GPIO_REMAP_SWJ_JTAGDISABLE = 0x00001872, - GPIO_REMAP_SWJ_DISABLE = 0x00001874, + GPIO_NO_REMAP_CAN2 = 0x00001610, + GPIO_REMAP_CAN2 = 0x00001611, - GPIO_NO_REMAP_EMMC_NADV = 0x00010A10, - GPIO_REMAP_EMMC_NADV = 0x00010A11, -}GPIO_REMAP_T; + GPIO_REMAP_MII = 0x00001710, + GPIO_REMAP_RMII = 0x00001711, + + GPIO_NO_REMAP_SWJ = 0x00001870, + GPIO_REMAP_SWJ_NOJTRST = 0x00001871, + GPIO_REMAP_SWJ_JTAGDISABLE = 0x00001872, + GPIO_REMAP_SWJ_DISABLE = 0x00001874, + + GPIO_NO_REMAP_EMMC_NADV = 0x00010A10, + GPIO_REMAP_EMMC_NADV = 0x00010A11, + +#else /* APM32F10X_CL */ + GPIO_NO_REMAP_ETH_MAC = 0x00001510, + GPIO_REMAP_ETH_MAC = 0x00001511, + + GPIO_NO_REMAP_CAN2 = 0x00001610, + GPIO_REMAP_CAN2 = 0x00001611, + + GPIO_REMAP_MACEISEL_MII = 0x00001710, + GPIO_REMAP_MACEISEL_RMII = 0x00001711, + + GPIO_NO_REMAP_SWJ = 0x00001870, + GPIO_REMAP_SWJ_NOJTRST = 0x00001871, + GPIO_REMAP_SWJ_JTAGDISABLE = 0x00001872, + GPIO_REMAP_SWJ_DISABLE = 0x00001874, + + GPIO_NO_REMAP_SPI3 = 0x00001C10, + GPIO_REMAP_SPI3 = 0x00001C11, + + GPIO_NO_REMAP_TMR2ITR1 = 0x00001D10, + GPIO_REMAP_TMR2ITR1 = 0x00001D11, + + GPIO_NO_REMAP_PTP_PPS = 0x00001E10, + GPIO_REMAP_PTP_PPS = 0x00001E11, +#endif +} GPIO_REMAP_T; /** * @brief gpio port source define */ typedef enum { - GPIO_PORT_SOURCE_A, - GPIO_PORT_SOURCE_B, - GPIO_PORT_SOURCE_C, - GPIO_PORT_SOURCE_D, - GPIO_PORT_SOURCE_E, - GPIO_PORT_SOURCE_F, - GPIO_PORT_SOURCE_G, -}GPIO_PORT_SOURCE_T; + GPIO_PORT_SOURCE_A, + GPIO_PORT_SOURCE_B, + GPIO_PORT_SOURCE_C, + GPIO_PORT_SOURCE_D, + GPIO_PORT_SOURCE_E, + GPIO_PORT_SOURCE_F, + GPIO_PORT_SOURCE_G, +} GPIO_PORT_SOURCE_T; /** * @brief gpio pin source define */ typedef enum { - GPIO_PIN_SOURCE_0, - GPIO_PIN_SOURCE_1, - GPIO_PIN_SOURCE_2, - GPIO_PIN_SOURCE_3, - GPIO_PIN_SOURCE_4, - GPIO_PIN_SOURCE_5, - GPIO_PIN_SOURCE_6, - GPIO_PIN_SOURCE_7, - GPIO_PIN_SOURCE_8, - GPIO_PIN_SOURCE_9, - GPIO_PIN_SOURCE_10, - GPIO_PIN_SOURCE_11, - GPIO_PIN_SOURCE_12, - GPIO_PIN_SOURCE_13, - GPIO_PIN_SOURCE_14, - GPIO_PIN_SOURCE_15, -}GPIO_PIN_SOURCE_T; + GPIO_PIN_SOURCE_0, + GPIO_PIN_SOURCE_1, + GPIO_PIN_SOURCE_2, + GPIO_PIN_SOURCE_3, + GPIO_PIN_SOURCE_4, + GPIO_PIN_SOURCE_5, + GPIO_PIN_SOURCE_6, + GPIO_PIN_SOURCE_7, + GPIO_PIN_SOURCE_8, + GPIO_PIN_SOURCE_9, + GPIO_PIN_SOURCE_10, + GPIO_PIN_SOURCE_11, + GPIO_PIN_SOURCE_12, + GPIO_PIN_SOURCE_13, + GPIO_PIN_SOURCE_14, + GPIO_PIN_SOURCE_15, +} GPIO_PIN_SOURCE_T; /**@} end of group GPIO_Enumerations*/ -/** @addtogroup GPIO_Structure Data Structure +/** @defgroup GPIO_Structures Structures @{ */ @@ -213,36 +247,36 @@ typedef enum */ typedef struct { - uint16_t pin; - GPIO_SPEED_T speed; - GPIO_MODE_T mode; -}GPIO_Config_T; + uint16_t pin; + GPIO_SPEED_T speed; + GPIO_MODE_T mode; +} GPIO_Config_T; -/**@} end of group GPIO_Structure*/ +/**@} end of group GPIO_Structures*/ -/** @addtogroup GPIO_Fuctions Fuctions +/** @defgroup GPIO_Functions Functions @{ */ -/** Reset and common Configuration */ +/* Reset and common Configuration */ void GPIO_Reset(GPIO_T* port); void GPIO_AFIOReset(void); void GPIO_Config(GPIO_T* port, GPIO_Config_T* gpioConfig); void GPIO_ConfigStructInit(GPIO_Config_T* gpioConfig); -/** Read */ +/* Read */ uint8_t GPIO_ReadInputBit(GPIO_T* port, uint16_t pin); uint16_t GPIO_ReadInputPort(GPIO_T* port); uint8_t GPIO_ReadOutputBit(GPIO_T* port, uint16_t pin); uint16_t GPIO_ReadOutputPort(GPIO_T* port); -/** Write */ +/* Write */ void GPIO_SetBit(GPIO_T* port, uint16_t pin); void GPIO_ResetBit(GPIO_T* port, uint16_t pin); void GPIO_WriteOutputPort(GPIO_T* port, uint16_t portValue); void GPIO_WriteBitValue(GPIO_T* port, uint16_t pin, uint8_t bitVal); -/** GPIO Configuration */ +/* GPIO Configuration */ void GPIO_ConfigPinLock(GPIO_T* port, uint16_t pin); void GPIO_ConfigEventOutput(GPIO_PORT_SOURCE_T portSource, GPIO_PIN_SOURCE_T pinSource); void GPIO_EnableEventOutput(void); @@ -250,9 +284,9 @@ void GPIO_DisableEventOutput(void); void GPIO_ConfigPinRemap(GPIO_REMAP_T remap); void GPIO_ConfigEINTLine(GPIO_PORT_SOURCE_T portSource, GPIO_PIN_SOURCE_T pinSource); -/**@} end of group GPIO_Fuctions*/ -/**@} end of group GPIO_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group GPIO_Functions*/ +/**@} end of group GPIO_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver*/ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_i2c.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_i2c.h index ee2cfc71d3..7a4e4da2ea 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_i2c.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_i2c.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the I2C firmware library * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,16 +23,18 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_I2C_H #define __APM32F10X_I2C_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,7 +42,7 @@ @{ */ -/** @addtogroup I2C_Enumerations Enumerations +/** @defgroup I2C_Enumerations Enumerations @{ */ @@ -150,58 +152,56 @@ typedef enum */ typedef enum { - /** I2C Master Events */ - /** Event 5: Communication start event */ - I2C_EVENT_MASTER_MODE_SELECT = 0x00030001, //!< BUSBSYFLG, MSFLG and STARTFLG flag + /* I2C Master Events */ + /* Event 5: Communication start event */ + I2C_EVENT_MASTER_MODE_SELECT = 0x00030001, /*!< BUSBSYFLG, MSFLG and STARTFLG flag */ - /** - * Event 6: 7-bit Address Acknowledge - * in case of master receiver - */ - I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED = 0x00070082, //!< BUSBSYFLG, MSFLG, ADDRFLG, TXBEFLG and TRFLG flags */ - I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED = 0x00030002, //!< BUSBSYFLG, MSFLG and ADDRFLG flags */ - /** - * Event 9: Master has sent the first byte - * in 10-bit address mode - */ - I2C_EVENT_MASTER_MODE_ADDRESS10 = 0x00030008, //!< BUSBSYFLG, MSFLG and ADDR10FLG flags */ + /* Event 6: 7-bit Address Acknowledge + in case of master receiver + */ + I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED = 0x00070082, /*!< BUSBSYFLG, MSFLG, ADDRFLG, TXBEFLG and TRFLG flags */ + I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED = 0x00030002, /*!< BUSBSYFLG, MSFLG and ADDRFLG flags */ + /* Event 9: Master has sent the first byte + in 10-bit address mode + */ + I2C_EVENT_MASTER_MODE_ADDRESS10 = 0x00030008, /*!< BUSBSYFLG, MSFLG and ADDR10FLG flags */ - /** Master RECEIVER mode */ - /** Event 7 */ - I2C_EVENT_MASTER_BYTE_RECEIVED = 0x00030040, //!< BUSBSYFLG, MSFLG and RXBNEFLG flags */ + /* Master RECEIVER mode */ + /* Event 7 */ + I2C_EVENT_MASTER_BYTE_RECEIVED = 0x00030040, /*!< BUSBSYFLG, MSFLG and RXBNEFLG flags */ - /** Master TRANSMITTER mode */ - /** Event 8 */ - I2C_EVENT_MASTER_BYTE_TRANSMITTING = 0x00070080, //!< TRFLG, BUSBSYFLG, MSFLG, TXBEFLG flags */ - /** Event 8_2 */ - I2C_EVENT_MASTER_BYTE_TRANSMITTED = 0x00070084, //!< TRFLG, BUSBSYFLG, MSFLG, TXBEFLG and BTCFLG flags */ + /* Master TRANSMITTER mode */ + /* Event 8 */ + I2C_EVENT_MASTER_BYTE_TRANSMITTING = 0x00070080, /*!< TRFLG, BUSBSYFLG, MSFLG, TXBEFLG flags */ + /* Event 8_2 */ + I2C_EVENT_MASTER_BYTE_TRANSMITTED = 0x00070084, /*!< TRFLG, BUSBSYFLG, MSFLG, TXBEFLG and BTCFLG flags */ - /** EV1 (all the events below are variants of EV1) */ - /** 1, Case of One Single Address managed by the slave */ - I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED = 0x00020002, //!< BUSBSYFLG and ADDRFLG flags */ - I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED = 0x00060082, //!< TRFLG, BUSBSYFLG, TXBEFLG and ADDRFLG flags */ + /* EV1 (all the events below are variants of EV1) */ + /* 1, Case of One Single Address managed by the slave */ + I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED = 0x00020002, /*!< BUSBSYFLG and ADDRFLG flags */ + I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED = 0x00060082, /*!< TRFLG, BUSBSYFLG, TXBEFLG and ADDRFLG flags */ - /** 2, Case of Dual address managed by the slave */ - I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED = 0x00820000, //!< DUALF and BUSBSYFLG flags */ - I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED = 0x00860080, //!< DUALF, TRFLG, BUSBSYFLG and TXBEFLG flags */ + /* 2, Case of Dual address managed by the slave */ + I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED = 0x00820000, /*!< DUALF and BUSBSYFLG flags */ + I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED = 0x00860080, /*!< DUALF, TRFLG, BUSBSYFLG and TXBEFLG flags */ - /** 3, Case of General Call enabled for the slave */ - I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED = 0x00120000, //!< GENCALL and BUSBSYFLG flags */ + /* 3, Case of General Call enabled for the slave */ + I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED = 0x00120000, /*!< GENCALL and BUSBSYFLG flags */ - /** Slave RECEIVER mode */ - /** EV2 */ - I2C_EVENT_SLAVE_BYTE_RECEIVED = 0x00020040, //!< BUSBSYFLG and RXBNEFLG flags */ - /** EV4 */ - I2C_EVENT_SLAVE_STOP_DETECTED = 0x00000010, //!< STOPFLG flag */ + /* Slave RECEIVER mode */ + /* EV2 */ + I2C_EVENT_SLAVE_BYTE_RECEIVED = 0x00020040, /*!< BUSBSYFLG and RXBNEFLG flags */ + /* EV4 */ + I2C_EVENT_SLAVE_STOP_DETECTED = 0x00000010, /*!< STOPFLG flag */ - /** Slave TRANSMITTER mode */ - /** EV3 */ - I2C_EVENT_SLAVE_BYTE_TRANSMITTED = 0x00060084, //!< TRFLG, BUSBSYFLG, TXBEFLG and BTCFLG flags */ - I2C_EVENT_SLAVE_BYTE_TRANSMITTING = 0x00060080, //!< TRFLG, BUSBSYFLG and TXBEFLG flags */ - /** EV3_2 */ - I2C_EVENT_SLAVE_ACK_FAILURE = 0x00000400, //!< AEFLG flag */ + /* Slave TRANSMITTER mode */ + /* EV3 */ + I2C_EVENT_SLAVE_BYTE_TRANSMITTED = 0x00060084, /*!< TRFLG, BUSBSYFLG, TXBEFLG and BTCFLG flags */ + I2C_EVENT_SLAVE_BYTE_TRANSMITTING = 0x00060080, /*!< TRFLG, BUSBSYFLG and TXBEFLG flags */ + /* EV3_2 */ + I2C_EVENT_SLAVE_ACK_FAILURE = 0x00000400, /*!< AEFLG flag */ } I2C_EVENT_T; /** @@ -209,7 +209,7 @@ typedef enum */ typedef enum { - /** STS2 register flags */ + /* STS2 register flags */ I2C_FLAG_DUALADDR, I2C_FLAG_SMMHADDR, I2C_FLAG_SMBDADDR, @@ -218,7 +218,7 @@ typedef enum I2C_FLAG_BUSBSY, I2C_FLAG_MS, - /** STS1 register flags */ + /* STS1 register flags */ I2C_FLAG_SMBALT, I2C_FLAG_TTE, I2C_FLAG_PECE, @@ -258,7 +258,7 @@ typedef enum /**@} end of group I2C_Enumerations*/ -/** @addtogroup I2C_Structure Data Structure +/** @defgroup I2C_Structures Structures @{ */ @@ -275,14 +275,14 @@ typedef struct I2C_ACK_ADDRESS_T ackAddress; } I2C_Config_T; -/**@} end of group I2C_Structure*/ +/**@} end of group I2C_Structures*/ -/** @addtogroup I2C_Fuctions Fuctions +/** @defgroup I2C_Functions Functions @{ */ -/** I2C reset and configuration */ +/* I2C reset and configuration */ void I2C_Reset(I2C_T* i2c); void I2C_Config(I2C_T* i2c, I2C_Config_T* i2cConfig); void I2C_ConfigStructInit(I2C_Config_T* i2cConfig); @@ -300,7 +300,7 @@ void I2C_DisableDualAddress(I2C_T* i2c); void I2C_EnableGeneralCall(I2C_T* i2c); void I2C_DisableGeneralCall(I2C_T* i2c); -/** Transmit Configuration */ +/* Transmit Configuration */ void I2C_TxData(I2C_T* i2c, uint8_t data); uint8_t I2C_RxData(I2C_T* i2c); void I2C_Tx7BitAddress(I2C_T* i2c, uint8_t address, I2C_DIRECTION_T direction); @@ -321,13 +321,13 @@ void I2C_EnableStretchClock(I2C_T* i2c); void I2C_DisableStretchClock(I2C_T* i2c); void I2C_ConfigFastModeDutyCycle(I2C_T* i2c, I2C_DUTYCYCLE_T dutyCycle); -/** DMA */ +/* DMA */ void I2C_EnableDMA(I2C_T* i2c); void I2C_DisableDMA(I2C_T* i2c); void I2C_EnableDMALastTransfer(I2C_T* i2c); void I2C_DisableDMALastTransfer(I2C_T* i2c); -/** Interrupts and flags */ +/* Interrupts and flags */ void I2C_EnableInterrupt(I2C_T* i2c, uint16_t interrupt); void I2C_DisableInterrupt(I2C_T* i2c, uint16_t interrupt); uint8_t I2C_ReadEventStatus(I2C_T* i2c, I2C_EVENT_T i2cEvent); @@ -337,9 +337,9 @@ void I2C_ClearStatusFlag(I2C_T* i2c, I2C_FLAG_T flag); uint8_t I2C_ReadIntFlag(I2C_T* i2c, I2C_INT_FLAG_T flag); void I2C_ClearIntFlag(I2C_T* i2c, uint32_t flag); -/**@} end of group I2C_Fuctions*/ +/**@} end of group I2C_Functions*/ /**@} end of group I2C_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group APM32F10x_StdPeriphDriver*/ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_iwdt.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_iwdt.h index 962f8a1a54..f0965ab896 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_iwdt.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_iwdt.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the IWDT firmware library * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,16 +23,18 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_IWDT_H #define __APM32F10X_IWDT_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,7 +42,7 @@ @{ */ -/** @addtogroup IWDT_Enumerations Enumerations +/** @defgroup IWDT_Enumerations Enumerations @{ */ @@ -51,7 +53,7 @@ typedef enum { IWDT_KEYWORD_RELOAD = 0xAAAA, IWDT_KEYWORD_ENABLE = 0xCCCC -}IWDT_KEYWORD_T; +} IWDT_KEYWORD_T; /** * @brief IWDT Write Access define @@ -60,7 +62,7 @@ typedef enum { IWDT_WRITEACCESS_ENABLE = 0x5555, IWDT_WRITEACCESS_DISABLE = 0x0000 -}IWDT_WRITEACCESS_T; +} IWDT_WRITEACCESS_T; /** * @brief IWDT Divider @@ -74,7 +76,7 @@ typedef enum IWDT_DIVIDER_64 = 0x04, IWDT_DIVIDER_128 = 0x05, IWDT_DIVIDER_256 = 0x06 -}IWDT_DIVIDER_T; +} IWDT_DIVIDER_T; /** * @brief IWDT Flag @@ -83,37 +85,37 @@ typedef enum { IWDT_FLAG_PSCU = BIT0, IWDT_FLAG_CNTU = BIT1 -}IWDT_FLAG_T; +} IWDT_FLAG_T; /**@} end of group IWDT_Enumerations*/ -/** @addtogroup IWDT_Fuctions Fuctions +/** @defgroup IWDT_Functions Functions @{ */ -/** Enable IWDT */ +/* Enable IWDT */ void IWDT_Enable(void); -/** Refresh IWDT */ +/* Refresh IWDT */ void IWDT_Refresh(void); -/** Counter reload */ +/* Counter reload */ void IWDT_ConfigReload(uint16_t reload); -/** Divider */ +/* Divider */ void IWDT_ConfigDivider(uint8_t div); -/** Write Access */ +/* Write Access */ void IWDT_EnableWriteAccess(void); void IWDT_DisableWriteAccess(void); -/** flag */ +/* flag */ uint8_t IWDT_ReadStatusFlag(uint16_t flag); -/**@} end of group IWDT_Fuctions*/ -/**@} end of group IWDT_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group IWDT_Functions*/ +/**@} end of group IWDT_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver*/ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_misc.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_misc.h index 7448aebe11..82cc03ac8f 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_misc.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_misc.h @@ -4,9 +4,9 @@ * @brief This file provides all the miscellaneous firmware functions. * Include NVIC,SystemTick and Power management. * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -16,7 +16,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,16 +24,18 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_MISC_H #define __APM32F10X_MISC_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -41,7 +43,7 @@ @{ */ -/** @addtogroup MISC_Enumerations Enumerations +/** @defgroup MISC_Enumerations Enumerations @{ */ @@ -50,66 +52,66 @@ */ typedef enum { - NVIC_VECT_TAB_RAM = 0x20000000, - NVIC_VECT_TAB_FLASH = 0x08000000, -}NVIC_VECT_TAB_T; + NVIC_VECT_TAB_RAM = 0x20000000, + NVIC_VECT_TAB_FLASH = 0x08000000, +} NVIC_VECT_TAB_T; /** * @brief system low power mode */ typedef enum { - NVIC_LOWPOWER_SEVONPEND = 0x10, - NVIC_LOWPOWER_SLEEPDEEP = 0x04, - NVIC_LOWPOWER_SLEEPONEXIT = 0x02 -}NVIC_LOWPOWER_T; + NVIC_LOWPOWER_SEVONPEND = 0x10, + NVIC_LOWPOWER_SLEEPDEEP = 0x04, + NVIC_LOWPOWER_SLEEPONEXIT = 0x02 +} NVIC_LOWPOWER_T; /** * @brief nvic priority group */ typedef enum { - NVIC_PRIORITY_GROUP_0 = 0x700, //!< 0 bits for pre-emption priority,4 bits for subpriority - NVIC_PRIORITY_GROUP_1 = 0x600, //!< 1 bits for pre-emption priority,3 bits for subpriority - NVIC_PRIORITY_GROUP_2 = 0x500, //!< 2 bits for pre-emption priority,2 bits for subpriority - NVIC_PRIORITY_GROUP_3 = 0x400, //!< 3 bits for pre-emption priority,1 bits for subpriority - NVIC_PRIORITY_GROUP_4 = 0x300 //!< 4 bits for pre-emption priority,0 bits for subpriority -}NVIC_PRIORITY_GROUP_T; + NVIC_PRIORITY_GROUP_0 = 0x700, /*!< 0 bits for pre-emption priority,4 bits for subpriority */ + NVIC_PRIORITY_GROUP_1 = 0x600, /*!< 1 bits for pre-emption priority,3 bits for subpriority */ + NVIC_PRIORITY_GROUP_2 = 0x500, /*!< 2 bits for pre-emption priority,2 bits for subpriority */ + NVIC_PRIORITY_GROUP_3 = 0x400, /*!< 3 bits for pre-emption priority,1 bits for subpriority */ + NVIC_PRIORITY_GROUP_4 = 0x300 /*!< 4 bits for pre-emption priority,0 bits for subpriority */ +} NVIC_PRIORITY_GROUP_T; /** * @brief SysTick Clock source */ typedef enum { - SYSTICK_CLK_SOURCE_HCLK_DIV8 = 0x00, - SYSTICK_CLK_SOURCE_HCLK = 0x01 -}SYSTICK_CLK_SOURCE_T; + SYSTICK_CLK_SOURCE_HCLK_DIV8 = 0x00, + SYSTICK_CLK_SOURCE_HCLK = 0x01 +} SYSTICK_CLK_SOURCE_T; /**@} end of group MISC_Enumerations*/ -/** @addtogroup MISC_Fuctions Fuctions +/** @defgroup MISC_Functions Functions @{ */ -/** NVIC */ +/* NVIC */ void NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_T priorityGroup); void NVIC_EnableIRQRequest(IRQn_Type irq, uint8_t preemptionPriority, uint8_t subPriority); void NVIC_DisableIRQRequest(IRQn_Type irq); -/** Vector Table */ +/* Vector Table */ void NVIC_ConfigVectorTable(NVIC_VECT_TAB_T vectTab, uint32_t offset); -/** Power */ +/* Power */ void NVIC_SetSystemLowPower(NVIC_LOWPOWER_T lowPowerMode); void NVIC_ResetystemLowPower(NVIC_LOWPOWER_T lowPowerMode); -/** Systick */ +/* Systick */ void SysTick_ConfigCLKSource(SYSTICK_CLK_SOURCE_T clkSource); -/**@} end of group MISC_Fuctions*/ +/**@} end of group MISC_Functions*/ /**@} end of group MISC_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group APM32F10x_StdPeriphDriver*/ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_pmu.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_pmu.h index 3c7797a863..05dfe7b0a2 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_pmu.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_pmu.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the PMU firmware library. * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,16 +23,18 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_PMU_H #define __APM32F10X_PMU_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,7 +42,7 @@ @{ */ -/** @addtogroup PMU_Enumerations Enumerations +/** @defgroup PMU_Enumerations Enumerations @{ */ @@ -49,14 +51,14 @@ */ typedef enum { - PMU_PVD_LEVEL_2V2 = 0x00, //!< PVD detection level set to 2.2V - PMU_PVD_LEVEL_2V3 = 0x01, //!< PVD detection level set to 2.3V - PMU_PVD_LEVEL_2V4 = 0x02, //!< PVD detection level set to 2.4V - PMU_PVD_LEVEL_2V5 = 0x03, //!< PVD detection level set to 2.5V - PMU_PVD_LEVEL_2V6 = 0x04, //!< PVD detection level set to 2.6V - PMU_PVD_LEVEL_2V7 = 0x05, //!< PVD detection level set to 2.7V - PMU_PVD_LEVEL_2V8 = 0x06, //!< PVD detection level set to 2.8V - PMU_PVD_LEVEL_2V9 = 0x07, //!< PVD detection level set to 2.9V + PMU_PVD_LEVEL_2V2 = 0x00, /*!< PVD detection level set to 2.2V */ + PMU_PVD_LEVEL_2V3 = 0x01, /*!< PVD detection level set to 2.3V */ + PMU_PVD_LEVEL_2V4 = 0x02, /*!< PVD detection level set to 2.4V */ + PMU_PVD_LEVEL_2V5 = 0x03, /*!< PVD detection level set to 2.5V */ + PMU_PVD_LEVEL_2V6 = 0x04, /*!< PVD detection level set to 2.6V */ + PMU_PVD_LEVEL_2V7 = 0x05, /*!< PVD detection level set to 2.7V */ + PMU_PVD_LEVEL_2V8 = 0x06, /*!< PVD detection level set to 2.8V */ + PMU_PVD_LEVEL_2V9 = 0x07, /*!< PVD detection level set to 2.9V */ } PMU_PVD_LEVEL_T; /** @@ -90,14 +92,14 @@ typedef enum /**@} end of group PMU_Enumerations*/ -/** @addtogroup PMU_Fuctions Fuctions +/** @addtogroup PMU_Functions Functions @{ */ -/** PMU Reset */ +/* PMU Reset */ void PMU_Reset(void); -/** Configuration and Operation modes */ +/* Configuration and Operation modes */ void PMU_EnableBackupAccess(void); void PMU_DisableBackupAccess(void); void PMU_EnablePVD(void); @@ -108,13 +110,13 @@ void PMU_DisableWakeUpPin(void); void PMU_EnterSTOPMode(PMU_REGULATOR_T regulator, PMU_STOP_ENTRY_T entry); void PMU_EnterSTANDBYMode(void); -/** flags */ +/* flags */ uint8_t PMU_ReadStatusFlag(PMU_FLAG_T flag); void PMU_ClearStatusFlag(PMU_FLAG_T flag); -/**@} end of group PMU_Fuctions*/ -/**@} end of group PMU_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group PMU_Functions*/ +/**@} end of group PMU_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver*/ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_qspi.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_qspi.h index 7035b6ce38..446b2ebaa0 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_qspi.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_qspi.h @@ -3,9 +3,9 @@ * * @brief This file contains all the prototypes,enumeration and macros for the QSPI peripheral * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,16 +23,18 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_QSPI_H #define __APM32F10X_QSPI_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,7 +42,42 @@ @{ */ -/** @addtogroup QSPI_Enumerations Enumerations +/** @defgroup QSPI_Macros Macros + @{ +*/ + +/* CTRL1 register reset value */ +#define QSPI_CTRL1_RESET_VALUE ((uint32_t)0x4007) +/* CTRL2 register reset value */ +#define QSPI_CTRL2_RESET_VALUE ((uint32_t)0x00) +/* SSIEN register reset value */ +#define QSPI_SSIEN_RESET_VALUE ((uint32_t)0x00) +/* SLAEN register reset value */ +#define QSPI_SLAEN_RESET_VALUE ((uint32_t)0x00) +/* BR register reset value */ +#define QSPI_BR_RESET_VALUE ((uint32_t)0x00) +/* TFTL register reset value */ +#define QSPI_TFTL_RESET_VALUE ((uint32_t)0x00) +/* RFTL register reset value */ +#define QSPI_RFTL_RESET_VALUE ((uint32_t)0x00) +/* TFL register reset value */ +#define QSPI_TFL_RESET_VALUE ((uint32_t)0x00) +/* RFL register reset value */ +#define QSPI_RFL_RESET_VALUE ((uint32_t)0x00) +/* STS register reset value */ +#define QSPI_STS_RESET_VALUE ((uint32_t)0x06) +/* INTEN register reset value */ +#define QSPI_INTEN_RESET_VALUE ((uint32_t)0x7F) +/* RSD register reset value */ +#define QSPI_RSD_RESET_VALUE ((uint32_t)0x00) +/* CTRL3 register reset value */ +#define QSPI_CTRL3_RESET_VALUE ((uint32_t)0x200) +/* IOSW register reset value */ +#define QSPI_IOSW_RESET_VALUE ((uint32_t)0x00) + +/**@} end of group QSPI_Macros*/ + +/** @defgroup QSPI_Enumerations Enumerations @{ */ @@ -49,21 +86,21 @@ */ typedef enum { - QSPI_FRF_STANDARD, //!< Standard mode - QSPI_FRF_DUAL, //!< Dual SPI - QSPI_FRF_QUAD //!< QUAD SPI -}QSPI_FRF_T; + QSPI_FRF_STANDARD, /*!< Standard mode */ + QSPI_FRF_DUAL, /*!< Dual SPI */ + QSPI_FRF_QUAD /*!< QUAD SPI */ +} QSPI_FRF_T; /** * @brief Transmission mode */ typedef enum { - QSPI_TRANS_MODE_TX_RX, //!< TX and RX mode - QSPI_TRANS_MODE_TX, //!< TX mode only - QSPI_TRANS_MODE_RX, //!< RX mode only - QSPI_TRANS_MODE_EEPROM_READ //!< EEPROM read mode -}QSPI_TRANS_MODE_T; + QSPI_TRANS_MODE_TX_RX, /*!< TX and RX mode */ + QSPI_TRANS_MODE_TX, /*!< TX mode only */ + QSPI_TRANS_MODE_RX, /*!< RX mode only */ + QSPI_TRANS_MODE_EEPROM_READ /*!< EEPROM read mode */ +} QSPI_TRANS_MODE_T; /** * @brief Clock polarity @@ -72,7 +109,7 @@ typedef enum { QSPI_CLKPOL_LOW, QSPI_CLKPOL_HIGH -}QSPI_CLKPOL_T; +} QSPI_CLKPOL_T; /** * @brief Clock phase @@ -81,7 +118,7 @@ typedef enum { QSPI_CLKPHA_1EDGE, QSPI_CLKPHA_2EDGE -}QSPI_CLKPHA_T; +} QSPI_CLKPHA_T; /** * @brief Data format size @@ -117,46 +154,46 @@ typedef enum QSPI_DFS_30BIT, QSPI_DFS_31BIT, QSPI_DFS_32BIT -}QSPI_DFS_T; +} QSPI_DFS_T; /** * @brief QSPI flag */ typedef enum { - QSPI_FLAG_BUSY = BIT0, //!< Busy flag - QSPI_FLAG_TFNF = BIT1, //!< TX FIFO not full flag - QSPI_FLAG_TFE = BIT2, //!< TX FIFO empty flag - QSPI_FLAG_RFNE = BIT3, //!< RX FIFO not empty flag - QSPI_FLAG_RFF = BIT4, //!< RX FIFO full flag - QSPI_FLAG_DCE = BIT6 //!< Data collision error -}QSPI_FLAG_T; + QSPI_FLAG_BUSY = BIT0, /*!< Busy flag */ + QSPI_FLAG_TFNF = BIT1, /*!< TX FIFO not full flag */ + QSPI_FLAG_TFE = BIT2, /*!< TX FIFO empty flag */ + QSPI_FLAG_RFNE = BIT3, /*!< RX FIFO not empty flag */ + QSPI_FLAG_RFF = BIT4, /*!< RX FIFO full flag */ + QSPI_FLAG_DCE = BIT6 /*!< Data collision error */ +} QSPI_FLAG_T; /** * @brief QSPI interrupt source */ typedef enum { - QSPI_INT_TFE = BIT0, //!< TX FIFO empty interrupt - QSPI_INT_TFO = BIT1, //!< TX FIFO overflow interrupt - QSPI_INT_RFU = BIT2, //!< RX FIFO underflow interrupt - QSPI_INT_RFO = BIT3, //!< RX FIFO overflow interrupt - QSPI_INT_RFF = BIT4, //!< RX FIFO full interrupt - QSPI_INT_MST = BIT5 //!< Master interrupt -}QSPI_INT_T; + QSPI_INT_TFE = BIT0, /*!< TX FIFO empty interrupt */ + QSPI_INT_TFO = BIT1, /*!< TX FIFO overflow interrupt */ + QSPI_INT_RFU = BIT2, /*!< RX FIFO underflow interrupt */ + QSPI_INT_RFO = BIT3, /*!< RX FIFO overflow interrupt */ + QSPI_INT_RFF = BIT4, /*!< RX FIFO full interrupt */ + QSPI_INT_MST = BIT5 /*!< Master interrupt */ +} QSPI_INT_T; /** * @brief QSPI interrupt flag */ typedef enum { - QSPI_INT_FLAG_TFE = BIT0, //!< TX FIFO empty interrupt flag - QSPI_INT_FLAG_TFO = BIT1, //!< TX FIFO overflow interrupt flag - QSPI_INT_FLAG_RFU = BIT2, //!< RX FIFO underflow interrupt flag - QSPI_INT_FLAG_RFO = BIT3, //!< RX FIFO overflow interrupt flag - QSPI_INT_FLAG_RFF = BIT4, //!< RX FIFO full interrupt flag - QSPI_INT_FLAG_MST = BIT5 //!< Master interrupt flag -}QSPI_INT_FLAG_T; + QSPI_INT_FLAG_TFE = BIT0, /*!< TX FIFO empty interrupt flag */ + QSPI_INT_FLAG_TFO = BIT1, /*!< TX FIFO overflow interrupt flag */ + QSPI_INT_FLAG_RFU = BIT2, /*!< RX FIFO underflow interrupt flag */ + QSPI_INT_FLAG_RFO = BIT3, /*!< RX FIFO overflow interrupt flag */ + QSPI_INT_FLAG_RFF = BIT4, /*!< RX FIFO full interrupt flag */ + QSPI_INT_FLAG_MST = BIT5 /*!< Master interrupt flag */ +} QSPI_INT_FLAG_T; /** * @brief Reception sample edge @@ -165,7 +202,7 @@ typedef enum { QSPI_RSE_RISING, QSPI_RSE_FALLING -}QSPI_RSE_T; +} QSPI_RSE_T; /** * @brief Instruction length @@ -176,7 +213,7 @@ typedef enum QSPI_INST_LEN_4BIT, QSPI_INST_LEN_8BIT, QSPI_INST_LEN_16BIT -}QSPI_INST_LEN_T; +} QSPI_INST_LEN_T; /** * @brief QSPI address length @@ -199,7 +236,7 @@ typedef enum QSPI_ADDR_LEN_52BIT, QSPI_ADDR_LEN_56BIT, QSPI_ADDR_LEN_60BIT -}QSPI_ADDR_LEN_T; +} QSPI_ADDR_LEN_T; /** * @brief Instruction and address transmission mode @@ -209,7 +246,7 @@ typedef enum QSPI_INST_ADDR_TYPE_STANDARD, QSPI_INST_TYPE_STANDARD, QSPI_INST_ADDR_TYPE_FRF -}QSPI_INST_ADDR_TYPE_T; +} QSPI_INST_ADDR_TYPE_T; /** * @brief Slave Select Toggle @@ -218,134 +255,97 @@ typedef enum { QSPI_SST_DISABLE, QSPI_SST_ENABLE -}QSPI_SST_T; +} QSPI_SST_T; /**@} end of group QSPI_Enumerations*/ -/** @addtogroup QSPI_Macros Macros - @{ -*/ - -/** CTRL1 register reset value */ -#define QSPI_CTRL1_RESET_VALUE ((uint32_t)0x4007) -/** CTRL2 register reset value */ -#define QSPI_CTRL2_RESET_VALUE ((uint32_t)0x00) -/** SSIEN register reset value */ -#define QSPI_SSIEN_RESET_VALUE ((uint32_t)0x00) -/** SLAEN register reset value */ -#define QSPI_SLAEN_RESET_VALUE ((uint32_t)0x00) -/** BR register reset value */ -#define QSPI_BR_RESET_VALUE ((uint32_t)0x00) -/** TFTL register reset value */ -#define QSPI_TFTL_RESET_VALUE ((uint32_t)0x00) -/** RFTL register reset value */ -#define QSPI_RFTL_RESET_VALUE ((uint32_t)0x00) -/** TFL register reset value */ -#define QSPI_TFL_RESET_VALUE ((uint32_t)0x00) -/** RFL register reset value */ -#define QSPI_RFL_RESET_VALUE ((uint32_t)0x00) -/** STS register reset value */ -#define QSPI_STS_RESET_VALUE ((uint32_t)0x06) -/** INTEN register reset value */ -#define QSPI_INTEN_RESET_VALUE ((uint32_t)0x7F) -/** RSD register reset value */ -#define QSPI_RSD_RESET_VALUE ((uint32_t)0x00) -/** CTRL3 register reset value */ -#define QSPI_CTRL3_RESET_VALUE ((uint32_t)0x200) -/** IOSW register reset value */ -#define QSPI_IOSW_RESET_VALUE ((uint32_t)0x00) - -/**@} end of group QSPI_Macros*/ - - -/** @addtogroup QSPI_Structure Data Structure +/** @defgroup QSPI_Structure Data Structure @{ */ typedef struct { - QSPI_SST_T selectSlaveToggle; //!< Slave Select Toggle - QSPI_FRF_T frameFormat; //!< Frame format - uint16_t clockDiv; //!< Clock divider - QSPI_CLKPOL_T clockPolarity; //!< Clock polarity - QSPI_CLKPHA_T clockPhase; //!< Clock phase - QSPI_DFS_T dataFrameSize; //!< Data frame size -}QSPI_Config_T; + QSPI_SST_T selectSlaveToggle; /*!< Slave Select Toggle */ + QSPI_FRF_T frameFormat; /*!< Frame format */ + uint16_t clockDiv; /*!< Clock divider */ + QSPI_CLKPOL_T clockPolarity; /*!< Clock polarity */ + QSPI_CLKPHA_T clockPhase; /*!< Clock phase */ + QSPI_DFS_T dataFrameSize; /*!< Data frame size */ +} QSPI_Config_T; /**@} end of group QSPI_Structure*/ - -/** @addtogroup QSPI_Fuctions Fuctions +/** @defgroup QSPI_Functions Functions @{ */ -/** Reset */ +/* Reset */ void QSPI_Reset(void); -/** Configuration */ -void QSPI_Config(QSPI_Config_T *qspiConfig); -void QSPI_ConfigStructInit(QSPI_Config_T *qspiConfig); +/* Configuration */ +void QSPI_Config(QSPI_Config_T* qspiConfig); +void QSPI_ConfigStructInit(QSPI_Config_T* qspiConfig); -/** Data frame size, frame number, frame format */ +/* Data frame size, frame number, frame format */ void QSPI_ConfigFrameNum(uint16_t num); void QSPI_ConfigDataFrameSize(QSPI_DFS_T dfs); void QSPI_ConfigFrameFormat(QSPI_FRF_T frameFormat); -/** Disable or Enable */ +/* Disable or Enable */ void QSPI_Enable(void); void QSPI_Disable(void); -/** TX and RX FIFO */ +/* TX and RX FIFO */ uint8_t QSPI_ReadTxFifoDataNum(void); uint8_t QSPI_ReadRxFifoDataNum(void); void QSPI_ConfigRxFifoThreshold(uint8_t threshold); void QSPI_ConfigTxFifoThreshold(uint8_t threshold); void QSPI_ConfigTxFifoEmptyThreshold(uint8_t threshold); -/** RX Sample */ +/* RX Sample */ void QSPI_ConfigRxSampleEdge(QSPI_RSE_T rse); void QSPI_ConfigRxSampleDelay(uint8_t delay); -/** Clock stretch */ +/* Clock stretch */ void QSPI_EnableClockStretch(void); void QSPI_DisableClockStretch(void); -/** Instruction, address, Wait cycle */ +/* Instruction, address, Wait cycle */ void QSPI_ConfigInstLen(QSPI_INST_LEN_T len); void QSPI_ConfigAddrLen(QSPI_ADDR_LEN_T len); void QSPI_ConfigInstAddrType(QSPI_INST_ADDR_TYPE_T type); void QSPI_ConfigWaitCycle(uint8_t cycle); -/** IO */ +/* IO */ void QSPI_OpenIO(void); void QSPI_CloseIO(void); -/** Transmission mode */ +/* Transmission mode */ void QSPI_ConfigTansMode(QSPI_TRANS_MODE_T mode); -/** Rx and Tx data */ +/* Rx and Tx data */ uint32_t QSPI_RxData(void); void QSPI_TxData(uint32_t data); -/** Slave */ +/* Slave */ void QSPI_EnableSlave(void); void QSPI_DisableSlave(void); -/** Interrupt */ +/* Interrupt */ void QSPI_EnableInterrupt(uint32_t interrupt); void QSPI_DisableInterrupt(uint32_t interrupt); -/** Flag */ +/* Flag */ uint8_t QSPI_ReadStatusFlag(QSPI_FLAG_T flag); void QSPI_ClearStatusFlag(void); uint8_t QSPI_ReadIntFlag(QSPI_INT_FLAG_T flag); void QSPI_ClearIntFlag(uint32_t flag); -/**@} end of group QSPI_Fuctions*/ +/**@} end of group QSPI_Functions*/ /**@} end of group QSPI_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group APM32F10x_StdPeriphDriver*/ #ifdef __cplusplus } #endif -#endif /* __APM32F10X_QSPI_H_ */ +#endif /* __APM32F10X_QSPI_H */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_rcm.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_rcm.h index 2e58e7c7e1..42e9f6df2c 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_rcm.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_rcm.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the RCM firmware library * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,16 +23,18 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_RCM_H #define __APM32F10X_RCM_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,7 +42,7 @@ @{ */ -/** @addtogroup RCM_Enumerations Enumerations +/** @defgroup RCM_Enumerations Enumerations @{ */ @@ -59,6 +61,15 @@ typedef enum */ typedef enum { +#if defined(APM32F10X_CL) + RCM_PLLMF_4 = 2, + RCM_PLLMF_5, + RCM_PLLMF_6, + RCM_PLLMF_7, + RCM_PLLMF_8, + RCM_PLLMF_9, + RCM_PLLMF_6_5 = 13, +#else RCM_PLLMF_2, RCM_PLLMF_3, RCM_PLLMF_4, @@ -74,8 +85,41 @@ typedef enum RCM_PLLMF_14, RCM_PLLMF_15, RCM_PLLMF_16 +#endif } RCM_PLLMF_T; +/** + * @brief PLL2 multiplication factor + */ +typedef enum +{ + RCM_PLL2MF_8 = 6, + RCM_PLL2MF_9 = 7, + RCM_PLL2MF_10 = 8, + RCM_PLL2MF_11 = 9, + RCM_PLL2MF_12 = 10, + RCM_PLL2MF_13 = 11, + RCM_PLL2MF_14 = 12, + RCM_PLL2MF_16 = 14, + RCM_PLL2MF_20 = 15 +} RCM_PLL2MF_T; + +/** + * @brief PLL3 multiplication factor + */ +typedef enum +{ + RCM_PLL3MF_8 = 6, + RCM_PLL3MF_9 = 7, + RCM_PLL3MF_10 = 8, + RCM_PLL3MF_11 = 9, + RCM_PLL3MF_12 = 10, + RCM_PLL3MF_13 = 11, + RCM_PLL3MF_14 = 12, + RCM_PLL3MF_16 = 14, + RCM_PLL3MF_20 = 15 +} RCM_PLL3MF_T; + /** * @brief System clock select */ @@ -86,6 +130,64 @@ typedef enum RCM_SYSCLK_SEL_PLL } RCM_SYSCLK_SEL_T; +#if defined(APM32F10X_CL) +/** + * @brief PLLPSC1 Source + */ +typedef enum +{ + RCM_PLLPSC1_SRC_HSE, + RCM_PLLPSC1_SRC_PLL2 +} RCM_PLLPSC1_SRC_T; + +/** + * @brief PLLPSC1 divider Number + */ +typedef enum +{ + RCM_PLLPSC1_DIV_1, + RCM_PLLPSC1_DIV_2, + RCM_PLLPSC1_DIV_3, + RCM_PLLPSC1_DIV_4, + RCM_PLLPSC1_DIV_5, + RCM_PLLPSC1_DIV_6, + RCM_PLLPSC1_DIV_7, + RCM_PLLPSC1_DIV_8, + RCM_PLLPSC1_DIV_9, + RCM_PLLPSC1_DIV_10, + RCM_PLLPSC1_DIV_11, + RCM_PLLPSC1_DIV_12, + RCM_PLLPSC1_DIV_13, + RCM_PLLPSC1_DIV_14, + RCM_PLLPSC1_DIV_15, + RCM_PLLPSC1_DIV_16 +} RCM_PLLPSC1_DIV_T; + +/** + * @brief PLLPSC2 divider Number + */ +typedef enum +{ + RCM_PLLPSC2_DIV_1, + RCM_PLLPSC2_DIV_2, + RCM_PLLPSC2_DIV_3, + RCM_PLLPSC2_DIV_4, + RCM_PLLPSC2_DIV_5, + RCM_PLLPSC2_DIV_6, + RCM_PLLPSC2_DIV_7, + RCM_PLLPSC2_DIV_8, + RCM_PLLPSC2_DIV_9, + RCM_PLLPSC2_DIV_10, + RCM_PLLPSC2_DIV_11, + RCM_PLLPSC2_DIV_12, + RCM_PLLPSC2_DIV_13, + RCM_PLLPSC2_DIV_14, + RCM_PLLPSC2_DIV_15, + RCM_PLLPSC2_DIV_16 +} RCM_PLLPSC2_DIV_T; + +#endif + /** * @brief AHB divider Number */ @@ -122,9 +224,18 @@ typedef enum RCM_USB_DIV_1_5, RCM_USB_DIV_1, RCM_USB_DIV_2, - RCM_USB_DIV_2_5 //!< (Only for High-density devices for APM32F103xx) + RCM_USB_DIV_2_5 /*!< (Only for High-density devices for APM32F103xx) */ } RCM_USB_DIV_T; +/** + * @brief OTG FS divider Number + */ +typedef enum +{ + RCM_OTGFS_DIV_1_5, + RCM_OTGFS_DIV_1 +} RCM_OTGFS_DIV_T; + /** * @brief FPU divider Number */ @@ -155,6 +266,24 @@ typedef enum RCM_LSE_BYPASS } RCM_LSE_T; +/** + * @brief I2S2 clock select + */ +typedef enum +{ + RCM_I2S2CLK_SYSCLK, + RCM_I2S2CLK_DOUBLE_PLL3 +} RCM_I2S2CLK_T; + +/** + * @brief I2S3 clock select + */ +typedef enum +{ + RCM_I2S3CLK_SYSCLK, + RCM_I2S3CLK_DOUBLE_PLL3 +} RCM_I2S3CLK_T; + /** * @brief RTC clock select */ @@ -174,7 +303,13 @@ typedef enum RCM_MCOCLK_SYSCLK, RCM_MCOCLK_HSI, RCM_MCOCLK_HSE, - RCM_MCOCLK_PLLCLK_DIV_2 + RCM_MCOCLK_PLLCLK_DIV_2, +#if defined(APM32F10X_CL) + RCM_MCOCLK_PLL2CLK = 8, + RCM_MCOCLK_PLL3CLK_DIV_2, + RCM_MCOCLK_OSCCLK, + RCM_MCOCLK_PLL3CLK +#endif } RCM_MCOCLK_T; /** @@ -183,8 +318,12 @@ typedef enum typedef enum { RCM_PLLSEL_HSI_DIV_2 = 0, +#if defined(APM32F10X_CL) + RCM_PLLSEL_PREDIV1 = 1, +#else RCM_PLLSEL_HSE = 1, RCM_PLLSEL_HSE_DIV2 = 3, +#endif /* APM32F10X_CL */ } RCM_PLLSEL_T; /** @@ -192,12 +331,14 @@ typedef enum */ typedef enum { - RCM_INT_LSIRDY = BIT0, //!< LSI ready interrupt - RCM_INT_LSERDY = BIT1, //!< LSE ready interrupt - RCM_INT_HSIRDY = BIT2, //!< HSI ready interrupt - RCM_INT_HSERDY = BIT3, //!< HSE ready interrupt - RCM_INT_PLLRDY = BIT4, //!< PLL ready interrupt - RCM_INT_CSS = BIT7 //!< Clock security system interrupt + RCM_INT_LSIRDY = BIT0, /*!< LSI ready interrupt */ + RCM_INT_LSERDY = BIT1, /*!< LSE ready interrupt */ + RCM_INT_HSIRDY = BIT2, /*!< HSI ready interrupt */ + RCM_INT_HSERDY = BIT3, /*!< HSE ready interrupt */ + RCM_INT_PLLRDY = BIT4, /*!< PLL ready interrupt */ + RCM_INT_PLL2RDY = BIT5, /*!< PLL2 ready interrupt */ + RCM_INT_PLL3RDY = BIT6, /*!< PLL3 ready interrupt */ + RCM_INT_CSS = BIT7 /*!< Clock security system interrupt */ } RCM_INT_T; /** @@ -205,15 +346,19 @@ typedef enum */ typedef enum { - RCM_AHB_PERIPH_DMA1 = BIT0, - RCM_AHB_PERIPH_DMA2 = BIT1, - RCM_AHB_PERIPH_SRAM = BIT2, - RCM_AHB_PERIPH_FPU = BIT3, - RCM_AHB_PERIPH_FMC = BIT4, - RCM_AHB_PERIPH_QSPI = BIT5, - RCM_AHB_PERIPH_CRC = BIT6, - RCM_AHB_PERIPH_EMMC = BIT8, - RCM_AHB_PERIPH_SDIO = BIT10 + RCM_AHB_PERIPH_DMA1 = BIT0, + RCM_AHB_PERIPH_DMA2 = BIT1, + RCM_AHB_PERIPH_SRAM = BIT2, + RCM_AHB_PERIPH_FPU = BIT3, + RCM_AHB_PERIPH_FMC = BIT4, + RCM_AHB_PERIPH_QSPI = BIT5, + RCM_AHB_PERIPH_CRC = BIT6, + RCM_AHB_PERIPH_EMMC = BIT8, + RCM_AHB_PERIPH_SDIO = BIT10, + RCM_AHB_PERIPH_OTG_FS = BIT12, + RCM_AHB_PERIPH_ETH_MAC = BIT14, + RCM_AHB_PERIPH_ETH_MAC_TX = BIT15, + RCM_AHB_PERIPH_ETH_MAC_RX = BIT16 } RCM_AHB_PERIPH_T; /** @@ -271,51 +416,63 @@ typedef enum */ typedef enum { - RCM_FLAG_HSIRDY = 0x001, //!< HSI Ready Flag - RCM_FLAG_HSERDY = 0x011, //!< HSE Ready Flag - RCM_FLAG_PLLRDY = 0x019, //!< PLL Ready Flag - RCM_FLAG_LSERDY = 0x101, //!< LSE Ready Flag - RCM_FLAG_LSIRDY = 0x201, //!< LSI Ready Flag - RCM_FLAG_PINRST = 0x21A, //!< PIN reset flag - RCM_FLAG_PORRST = 0x21B, //!< POR/PDR reset flag - RCM_FLAG_SWRST = 0x21C, //!< Software reset flag - RCM_FLAG_IWDTRST = 0x21D, //!< Independent watchdog reset flag - RCM_FLAG_WWDTRST = 0x21E, //!< Window watchdog reset flag - RCM_FLAG_LPRRST = 0x21F //!< Low-power reset flag + RCM_FLAG_HSIRDY = 0x001, /*!< HSI Ready Flag */ + RCM_FLAG_HSERDY = 0x011, /*!< HSE Ready Flag */ + RCM_FLAG_PLLRDY = 0x019, /*!< PLL Ready Flag */ + RCM_FLAG_PLL2RDY = 0x01B, /*!< PLL2 Ready Flag */ + RCM_FLAG_PLL3RDY = 0x01D, /*!< PLL3 Ready Flag */ + RCM_FLAG_LSERDY = 0x101, /*!< LSE Ready Flag */ + RCM_FLAG_LSIRDY = 0x201, /*!< LSI Ready Flag */ + RCM_FLAG_PINRST = 0x21A, /*!< PIN reset flag */ + RCM_FLAG_PORRST = 0x21B, /*!< POR/PDR reset flag */ + RCM_FLAG_SWRST = 0x21C, /*!< Software reset flag */ + RCM_FLAG_IWDTRST = 0x21D, /*!< Independent watchdog reset flag */ + RCM_FLAG_WWDTRST = 0x21E, /*!< Window watchdog reset flag */ + RCM_FLAG_LPRRST = 0x21F /*!< Low-power reset flag */ } RCM_FLAG_T; -/**@} end of group RCM_Enumerations*/ +/**@} end of group RCM_Enumerations */ -/** @addtogroup RCM_Fuctions Fuctions +/** @defgroup RCM_Functions Functions @{ */ -/** Function description */ +/* Function description */ -/** RCM Reset */ +/* RCM Reset */ void RCM_Reset(void); -/** HSE clock */ +/* HSE clock */ void RCM_ConfigHSE(RCM_HSE_T state); uint8_t RCM_WaitHSEReady(void); -/** HSI clock */ +/* HSI clock */ void RCM_ConfigHSITrim(uint8_t HSITrim); void RCM_EnableHSI(void); void RCM_DisableHSI(void); -/** LSE and LSI clock */ +/* LSE and LSI clock */ void RCM_ConfigLSE(RCM_LSE_T state); void RCM_EnableLSI(void); void RCM_DisableLSI(void); -/** PLL clock */ +/* PLL clock */ void RCM_ConfigPLL(RCM_PLLSEL_T pllSelect, RCM_PLLMF_T pllMf); void RCM_EnablePLL(void); void RCM_DisablePLL(void); +#if defined(APM32F10X_CL) +void RCM_EnablePLL2(void); +void RCM_DisablePLL2(void); +void RCM_EnablePLL3(void); +void RCM_DisablePLL3(void); +void RCM_ConfigPLLPSC1(RCM_PLLPSC1_SRC_T pllPsc1Src, RCM_PLLPSC1_DIV_T pllPsc1); +void RCM_ConfigPLLPSC2(RCM_PLLPSC2_DIV_T pllpsc2); +void RCM_ConfigPLL2(RCM_PLL2MF_T pll2Mf); +void RCM_ConfigPLL3(RCM_PLL3MF_T pll3Mf); +#endif -/** Clock Security System */ +/* Clock Security System */ void RCM_EnableCSS(void); void RCM_DisableCSS(void); @@ -323,26 +480,32 @@ void RCM_ConfigMCO(RCM_MCOCLK_T mcoClock); void RCM_ConfigSYSCLK(RCM_SYSCLK_SEL_T sysClkSelect); RCM_SYSCLK_SEL_T RCM_ReadSYSCLKSource(void); -/** Config clock prescaler of AHB, APB1, APB2, USB and ADC */ +/* Config clock prescaler of AHB, APB1, APB2, USB and ADC */ void RCM_ConfigAHB(RCM_AHB_DIV_T AHBDiv); void RCM_ConfigAPB1(RCM_APB_DIV_T APB1Div); void RCM_ConfigAPB2(RCM_APB_DIV_T APB2Div); +#if defined(APM32F10X_CL) +void RCM_ConfigI2S2CLK(RCM_I2S2CLK_T i2s2ClkSelect); +void RCM_ConfigI2S3CLK(RCM_I2S2CLK_T i2s3ClkSelect); +void RCM_ConfigOTGFSCLK(RCM_OTGFS_DIV_T OTGDiv); +#else void RCM_ConfigUSBCLK(RCM_USB_DIV_T USBDiv); void RCM_ConfigFPUCLK(RCM_FPU_DIV_T FPUDiv); +#endif void RCM_ConfigADCCLK(RCM_PCLK2_DIV_T ADCDiv); -/** RTC clock */ +/* RTC clock */ void RCM_ConfigRTCCLK(RCM_RTCCLK_T rtcClkSelect); void RCM_EnableRTCCLK(void); void RCM_DisableRTCCLK(void); -/** Reads the clock frequency */ +/* Reads the clock frequency */ uint32_t RCM_ReadSYSCLKFreq(void); uint32_t RCM_ReadHCLKFreq(void); void RCM_ReadPCLKFreq(uint32_t* PCLK1, uint32_t* PCLK2); uint32_t RCM_ReadADCCLKFreq(void); -/** Enable or disable Periph Clock */ +/* Enable or disable Periph Clock */ void RCM_EnableAHBPeriphClock(uint32_t AHBPeriph); void RCM_DisableAHBPeriphClock(uint32_t AHBPeriph); void RCM_EnableAPB2PeriphClock(uint32_t APB2Periph); @@ -350,17 +513,21 @@ void RCM_DisableAPB2PeriphClock(uint32_t APB2Periph); void RCM_EnableAPB1PeriphClock(uint32_t APB1Periph); void RCM_DisableAPB1PeriphClock(uint32_t APB1Periph); -/** Enable or disable Periph Reset */ +/* Enable or disable Periph Reset */ +#if defined(APM32F10X_CL) +void RCM_EnableAHBPeriphReset(uint32_t AHBPeriph); +void RCM_DisableAHBPeriphReset(uint32_t AHBPeriph); +#endif void RCM_EnableAPB2PeriphReset(uint32_t APB2Periph); void RCM_DisableAPB2PeriphReset(uint32_t APB2Periph); void RCM_EnableAPB1PeriphReset(uint32_t APB1Periph); void RCM_DisableAPB1PeriphReset(uint32_t APB1Periph); -/** Backup domain reset */ +/* Backup domain reset */ void RCM_EnableBackupReset(void); void RCM_DisableBackupReset(void); -/** Interrupts and flags */ +/* Interrupts and flags */ void RCM_EnableInterrupt(uint32_t interrupt); void RCM_DisableInterrupt(uint32_t interrupt); uint8_t RCM_ReadStatusFlag(RCM_FLAG_T flag); @@ -368,9 +535,9 @@ void RCM_ClearStatusFlag(void); uint8_t RCM_ReadIntFlag(RCM_INT_T flag); void RCM_ClearIntFlag(uint32_t flag); -/**@} end of group RCM_Fuctions*/ -/**@} end of group RCM_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group RCM_Functions */ +/**@} end of group RCM_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_rtc.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_rtc.h index b6eb995ce2..5b7008f280 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_rtc.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_rtc.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the RTC firmware library * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,16 +23,18 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_RTC_H #define __APM32F10X_RTC_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,38 +42,37 @@ @{ */ -/** @addtogroup RTC_Enumerations Enumerations +/** @defgroup RTC_Enumerations Enumerations @{ */ typedef enum { - RTC_FLAG_OC = 0x0020, //!< RTC Operation Complete flag - RTC_FLAG_RSYNC = 0x0008, //!< Registers Synchronized flag - RTC_FLAG_OVR = 0x0004, //!< Overflow flag - RTC_FLAG_ALR = 0x0002, //!< Alarm flag - RTC_FLAG_SEC = 0x0001 //!< Second flag + RTC_FLAG_OC = 0x0020, /*!< RTC Operation Complete flag */ + RTC_FLAG_RSYNC = 0x0008, /*!< Registers Synchronized flag */ + RTC_FLAG_OVR = 0x0004, /*!< Overflow flag */ + RTC_FLAG_ALR = 0x0002, /*!< Alarm flag */ + RTC_FLAG_SEC = 0x0001 /*!< Second flag */ } RTC_FLAG_T; typedef enum { - RTC_INT_OVR = 0x0004, //!< Overflow interrupt - RTC_INT_ALR = 0x0002, //!< Alarm interrupt - RTC_INT_SEC = 0x0001 //!< Second interrupt + RTC_INT_OVR = 0x0004, /*!< Overflow interrupt */ + RTC_INT_ALR = 0x0002, /*!< Alarm interrupt */ + RTC_INT_SEC = 0x0001 /*!< Second interrupt */ } RTC_INT_T; -/**@} end of group RTC_Enumerations*/ +/**@} end of group RTC_Enumerations */ - -/** @addtogroup RTC_Fuctions Fuctions +/** @defgroup RTC_Functions Functions @{ */ -/** Operation modes */ +/* Operation modes */ void RTC_EnableConfigMode(void); void RTC_DisableConfigMode(void); -/** Configuration */ +/* Configuration */ uint32_t RTC_ReadCounter(void); void RTC_ConfigCounter(uint32_t value); void RTC_ConfigPrescaler(uint32_t value); @@ -80,7 +81,7 @@ uint32_t RTC_ReadDivider(void); void RTC_WaitForLastTask(void); void RTC_WaitForSynchro(void); -/** Interrupts and flags */ +/* Interrupts and flags */ void RTC_EnableInterrupt(uint16_t interrupt); void RTC_DisableInterrupt(uint16_t interrupt); uint8_t RTC_ReadStatusFlag(RTC_FLAG_T flag); @@ -88,9 +89,9 @@ void RTC_ClearStatusFlag(uint16_t flag); uint8_t RTC_ReadIntFlag(RTC_INT_T flag); void RTC_ClearIntFlag(uint16_t flag); -/**@} end of group RTC_Fuctions*/ -/**@} end of group RTC_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group RTC_Functions */ +/**@} end of group RTC_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_sci2c.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_sci2c.h index 11f4b0707f..48b51fe4eb 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_sci2c.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_sci2c.h @@ -3,9 +3,9 @@ * * @brief This file contains all the prototypes,enumeration and macros for the SCI2C(I2C3, I2C4) peripheral * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,16 +23,18 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_SCI2C_H #define __APM32F10X_SCI2C_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,7 +42,7 @@ @{ */ -/** @addtogroup SCI2C_Enumerations Enumerations +/** @defgroup SCI2C_Enumerations Enumerations @{ */ @@ -52,7 +54,7 @@ typedef enum SCI2C_SPEED_STANDARD = 1, SCI2C_SPEED_FAST, SCI2C_SPEED_HIGH -}SCI2C_SPEED_T; +} SCI2C_SPEED_T; /** * @brief Address mode @@ -61,7 +63,7 @@ typedef enum { SCI2C_ADDR_MODE_7BIT, SCI2C_ADDR_MODE_10BIT -}SCI2C_ADDR_MODE_T; +} SCI2C_ADDR_MODE_T; /** * @brief SCI2C mode enumeration @@ -70,7 +72,7 @@ typedef enum { SCI2C_MODE_MASTER, SCI2C_MODE_SLAVE -}SCI2C_MODE_T; +} SCI2C_MODE_T; /** * @brief Restart enable or disable @@ -79,7 +81,7 @@ typedef enum { SCI2C_RESTART_DISABLE, SCI2C_RESTART_ENABLE -}SCI2C_RESTART_T; +} SCI2C_RESTART_T; /** * @brief Enable or disable generate stop condition @@ -88,7 +90,7 @@ typedef enum { SCI2C_STOP_DISABLE, SCI2C_STOP_ENABLE -}SCI2C_STOP_T; +} SCI2C_STOP_T; /** * @brief Data direction */ @@ -96,69 +98,69 @@ typedef enum { SCI2C_DATA_DIR_WRITE, SCI2C_DATA_DIR_READ, -}SCI2C_DATA_DIR_T; +} SCI2C_DATA_DIR_T; /** * @brief SCI2C interrupt */ typedef enum { - SCI2C_INT_RFU = BIT0, //!< Rx FIFO underflow interrupt - SCI2C_INT_RFO = BIT1, //!< Rx FIFO onverflow interrupt - SCI2C_INT_RFF = BIT2, //!< Rx FIFO full interrupt - SCI2C_INT_TFO = BIT3, //!< Tx FIFO onverflow interrupt - SCI2C_INT_TFE = BIT4, //!< Tx FIFO empty interrupt - SCI2C_INT_RR = BIT5, //!< Read request interrupt - SCI2C_INT_TA = BIT6, //!< Tx abort interrupt - SCI2C_INT_RD = BIT7, //!< Read done interrupt - SCI2C_INT_ACT = BIT8, //!< Activity interrupt - SCI2C_INT_STPD = BIT9, //!< Stop detect interrupt - SCI2C_INT_STAD = BIT10, //!< Start detect interrupt - SCI2C_INT_GC = BIT11, //!< Gernal call interrupt - SCI2C_INT_RSTAD = BIT12, //!< Restart detect interrupt - SCI2C_INT_MOH = BIT13, //!< Master on hold interrupt - SCI2C_INT_ALL = BIT15 //!< All interrupt -}SCI2C_INT_T; + SCI2C_INT_RFU = BIT0, /*!< Rx FIFO underflow interrupt */ + SCI2C_INT_RFO = BIT1, /*!< Rx FIFO onverflow interrupt */ + SCI2C_INT_RFF = BIT2, /*!< Rx FIFO full interrupt */ + SCI2C_INT_TFO = BIT3, /*!< Tx FIFO onverflow interrupt */ + SCI2C_INT_TFE = BIT4, /*!< Tx FIFO empty interrupt */ + SCI2C_INT_RR = BIT5, /*!< Read request interrupt */ + SCI2C_INT_TA = BIT6, /*!< Tx abort interrupt */ + SCI2C_INT_RD = BIT7, /*!< Read done interrupt */ + SCI2C_INT_ACT = BIT8, /*!< Activity interrupt */ + SCI2C_INT_STPD = BIT9, /*!< Stop detect interrupt */ + SCI2C_INT_STAD = BIT10, /*!< Start detect interrupt */ + SCI2C_INT_GC = BIT11, /*!< Gernal call interrupt */ + SCI2C_INT_RSTAD = BIT12, /*!< Restart detect interrupt */ + SCI2C_INT_MOH = BIT13, /*!< Master on hold interrupt */ + SCI2C_INT_ALL = BIT15 /*!< All interrupt */ +} SCI2C_INT_T; /** * @brief Flag enumeration */ typedef enum { - SCI2C_FLAG_ACT = BIT0, //!< Activity flag - SCI2C_FLAG_TFNF = BIT1, //!< Tx FIFO not full flag - SCI2C_FLAG_TFE = BIT2, //!< Tx FIFO empty flag - SCI2C_FLAG_RFNE = BIT3, //!< Rx FIFO not empty flag - SCI2C_FLAG_RFF = BIT4, //!< Rx FIFO full flag - SCI2C_FLAG_MA = BIT5, //!< Master activity flag - SCI2C_FLAG_SA = BIT6, //!< Slave activity flag - SCI2C_FLAG_I2CEN = BIT8 | BIT0, //!< I2C enable flag - SCI2C_FLAG_SDWB = BIT8 | BIT1, //!< Slave disable while busy flag - SCI2C_FLAG_SRDL = BIT8 | BIT2 //!< Slave receive data lost flag -}SCI2C_FLAG_T; + SCI2C_FLAG_ACT = BIT0, /*!< Activity flag */ + SCI2C_FLAG_TFNF = BIT1, /*!< Tx FIFO not full flag */ + SCI2C_FLAG_TFE = BIT2, /*!< Tx FIFO empty flag */ + SCI2C_FLAG_RFNE = BIT3, /*!< Rx FIFO not empty flag */ + SCI2C_FLAG_RFF = BIT4, /*!< Rx FIFO full flag */ + SCI2C_FLAG_MA = BIT5, /*!< Master activity flag */ + SCI2C_FLAG_SA = BIT6, /*!< Slave activity flag */ + SCI2C_FLAG_I2CEN = BIT8 | BIT0, /*!< I2C enable flag */ + SCI2C_FLAG_SDWB = BIT8 | BIT1, /*!< Slave disable while busy flag */ + SCI2C_FLAG_SRDL = BIT8 | BIT2 /*!< Slave receive data lost flag */ +} SCI2C_FLAG_T; /** * @brief Tx abort source */ typedef enum { - SCI2C_TAS_AD7NA = BIT0, //!< 7 bit address mode NACK - SCI2C_TAS_AD10FBNA = BIT1, //!< 10 bit address mode first byte NACK - SCI2C_TAS_AD10SBNA = BIT2, //!< 10 bit address mode second byte NACK - SCI2C_TAS_TDNA = BIT3, //!< Tx data NACK - SCI2C_TAS_GCNA = BIT4, //!< Gernal call NACK - SCI2C_TAS_GCR = BIT5, //!< Gernal call read - SCI2C_TAS_HSAD = BIT6, //!< High speed ack detected - SCI2C_TAS_SNR = BIT7, //!< Start byte no restart - SCI2C_TAS_RNR10B = BIT8, //!< Read 10bit address mode when restart disable - SCI2C_TAS_MSTDIS = BIT9, //!< Master disable - SCI2C_TAS_ARBLOST = BIT10, //!< Arbitration lost - SCI2C_TAS_LFTF = BIT11, //!< Slave flush tx FIFO - SCI2C_TAS_SAL = BIT12, //!< Slave arbitration lost - SCI2C_TAS_SRI = BIT13, //!< Slave read done - SCI2C_TAS_USRARB = BIT14, //!< User abort - SCI2C_TAS_FLUCNT = BIT15 //!< Tx flush counter -}SCI2C_TAS_T; + SCI2C_TAS_AD7NA = BIT0, /*!< 7 bit address mode NACK */ + SCI2C_TAS_AD10FBNA = BIT1, /*!< 10 bit address mode first byte NACK */ + SCI2C_TAS_AD10SBNA = BIT2, /*!< 10 bit address mode second byte NACK */ + SCI2C_TAS_TDNA = BIT3, /*!< Tx data NACK */ + SCI2C_TAS_GCNA = BIT4, /*!< Gernal call NACK */ + SCI2C_TAS_GCR = BIT5, /*!< Gernal call read */ + SCI2C_TAS_HSAD = BIT6, /*!< High speed ack detected */ + SCI2C_TAS_SNR = BIT7, /*!< Start byte no restart */ + SCI2C_TAS_RNR10B = BIT8, /*!< Read 10bit address mode when restart disable */ + SCI2C_TAS_MSTDIS = BIT9, /*!< Master disable */ + SCI2C_TAS_ARBLOST = BIT10, /*!< Arbitration lost */ + SCI2C_TAS_LFTF = BIT11, /*!< Slave flush tx FIFO */ + SCI2C_TAS_SAL = BIT12, /*!< Slave arbitration lost */ + SCI2C_TAS_SRI = BIT13, /*!< Slave read done */ + SCI2C_TAS_USRARB = BIT14, /*!< User abort */ + SCI2C_TAS_FLUCNT = BIT15 /*!< Tx flush counter */ +} SCI2C_TAS_T; /** * @brief DMA Enable @@ -167,17 +169,15 @@ typedef enum { SCI2C_DMA_RX = BIT0, SCI2C_DMA_TX = BIT1, -}SCI2C_DMA_T; +} SCI2C_DMA_T; -/**@} end of group SCI2C_Enumerations*/ +/**@} end of group SCI2C_Enumerations */ - -/** @addtogroup SCI2C_Macros Macros +/** @defgroup SCI2C_Macros Macros @{ */ -/** Macros description */ - +/* Macros description */ #define SCI2C_CTRL1_RESET_VALUE ((uint32_t)0x3E) #define SCI2C_TARADDR_RESET_VALUE ((uint32_t)0x1055) #define SCI2C_SLAADDR_RESET_VALUE ((uint32_t)0x55) @@ -206,117 +206,116 @@ typedef enum #define SCI2C_HSSSL_RESET_VALUE ((uint32_t)0x01) #define SCI2C_FIFO_DEPTH (0X08) -/**@} end of group SCI2C_Macros*/ +/**@} end of group SCI2C_Macros */ -/** @addtogroup SCI2C_Structure Data Structure +/** @defgroup SCI2C_Structures Structures @{ */ /** - * @brief Struct description + * @brief Structure description */ typedef struct { - uint16_t slaveAddr; //!< Slave address. - SCI2C_MODE_T mode; //!< Specifies mode, master mode or slave mode - SCI2C_SPEED_T speed; //!< Specifies speed. Standard speed, fast speed or high speed. - uint16_t clkLowPeriod; //!< SCL high period - uint16_t clkHighPeriod; //!< SCL low period - uint8_t rxFifoThreshold; //!< Rx FIFO threshold - uint8_t txFifoThreshold; //!< Tx FIFO threshold - SCI2C_RESTART_T restart; //!< Enable or disable restart - SCI2C_ADDR_MODE_T addrMode; //!< Address mode. 7-bit or 10-bit mode. -}SCI2C_Config_T; + uint16_t slaveAddr; /*!< Slave address. */ + SCI2C_MODE_T mode; /*!< Specifies mode, master mode or slave mode */ + SCI2C_SPEED_T speed; /*!< Specifies speed. Standard speed, fast speed or high speed. */ + uint16_t clkLowPeriod; /*!< SCL high period */ + uint16_t clkHighPeriod; /*!< SCL low period */ + uint8_t rxFifoThreshold; /*!< Rx FIFO threshold */ + uint8_t txFifoThreshold; /*!< Tx FIFO threshold */ + SCI2C_RESTART_T restart; /*!< Enable or disable restart */ + SCI2C_ADDR_MODE_T addrMode; /*!< Address mode. 7-bit or 10-bit mode. */ +} SCI2C_Config_T; -/**@} end of group SCI2C_Structure*/ +/**@} end of group SCI2C_Structure */ - -/** @addtogroup SCI2C_Fuctions Fuctions +/** @defgroup SCI2C_Functions Functions @{ */ -/** Reset */ -void SCI2C_Reset(SCI2C_T *i2c); +/* Reset */ +void SCI2C_Reset(SCI2C_T* i2c); -/** Configuration */ -void SCI2C_Config(SCI2C_T *i2c, SCI2C_Config_T *sci2cConfig); -void SCI2C_ConfigStructInit(SCI2C_Config_T *sci2cConfig); +/* Configuration */ +void SCI2C_Config(SCI2C_T* i2c, SCI2C_Config_T* sci2cConfig); +void SCI2C_ConfigStructInit(SCI2C_Config_T* sci2cConfig); -/** Stop detect */ -void SCI2C_EnableStopDetectAddressed(SCI2C_T *i2c); -void SCI2C_DisableStopDetectAddressed(SCI2C_T *i2c); -void SCI2C_EnableStopDetectMasterActivity(SCI2C_T *i2c); -void SCI2C_DisableStopDetectMasterActivity(SCI2C_T *i2c); +/* Stop detect */ +void SCI2C_EnableStopDetectAddressed(SCI2C_T* i2c); +void SCI2C_DisableStopDetectAddressed(SCI2C_T* i2c); +void SCI2C_EnableStopDetectMasterActivity(SCI2C_T* i2c); +void SCI2C_DisableStopDetectMasterActivity(SCI2C_T* i2c); -/** Restart */ -void SCI2C_EnableRestart(SCI2C_T *i2c); -void SCI2C_DisableRestart(SCI2C_T *i2c); +/* Restart */ +void SCI2C_EnableRestart(SCI2C_T* i2c); +void SCI2C_DisableRestart(SCI2C_T* i2c); -/** Speed */ -void SCI2C_ConfigSpeed(SCI2C_T *i2c, SCI2C_SPEED_T speed); +/* Speed */ +void SCI2C_ConfigSpeed(SCI2C_T* i2c, SCI2C_SPEED_T speed); -/** Address */ -void SCI2C_ConfigMasterAddr(SCI2C_T *i2c, SCI2C_ADDR_MODE_T mode, uint16_t addr); -void SCI2C_ConfigSlaveAddr(SCI2C_T *i2c, SCI2C_ADDR_MODE_T mode, uint16_t addr); +/* Address */ +void SCI2C_ConfigMasterAddr(SCI2C_T* i2c, SCI2C_ADDR_MODE_T mode, uint16_t addr); +void SCI2C_ConfigSlaveAddr(SCI2C_T* i2c, SCI2C_ADDR_MODE_T mode, uint16_t addr); -/** Master mode and slave mode */ -void SCI2C_EnableMasterMode(SCI2C_T *i2c); -void SCI2C_DisableMasterMode(SCI2C_T *i2c); -void SCI2C_EnableSlaveMode(SCI2C_T *i2c); -void SCI2C_DisableSlaveMode(SCI2C_T *i2c); -void SCI2C_ConfigMasterCode(SCI2C_T *i2c, uint8_t code); +/* Master mode and slave mode */ +void SCI2C_EnableMasterMode(SCI2C_T* i2c); +void SCI2C_DisableMasterMode(SCI2C_T* i2c); +void SCI2C_EnableSlaveMode(SCI2C_T* i2c); +void SCI2C_DisableSlaveMode(SCI2C_T* i2c); +void SCI2C_ConfigMasterCode(SCI2C_T* i2c, uint8_t code); -/** Data */ -void SCI2C_ConfigDataDir(SCI2C_T *i2c, SCI2C_DATA_DIR_T dir); -void SCI2C_TxData(SCI2C_T *i2c, uint8_t data); -uint8_t SCI2C_RxData(SCI2C_T *i2c); -void SCI2C_ConfigDataRegister(SCI2C_T *i2c, SCI2C_STOP_T stop, SCI2C_DATA_DIR_T dataDir, uint8_t data); +/* Data */ +void SCI2C_ConfigDataDir(SCI2C_T* i2c, SCI2C_DATA_DIR_T dir); +void SCI2C_TxData(SCI2C_T* i2c, uint8_t data); +uint8_t SCI2C_RxData(SCI2C_T* i2c); +void SCI2C_ConfigDataRegister(SCI2C_T* i2c, SCI2C_STOP_T stop, SCI2C_DATA_DIR_T dataDir, uint8_t data); -/** Rx and Tx FIFO */ -uint8_t SCI2C_ReadRxFifoDataCnt(SCI2C_T *i2c); -uint8_t SCI2C_ReadTxFifoDataCnt(SCI2C_T *i2c); -void SCI2C_ConfigRxFifoThreshold(SCI2C_T *i2c, uint8_t threshold); -void SCI2C_ConfigTxFifoThreshold(SCI2C_T *i2c, uint8_t threshold); +/* Rx and Tx FIFO */ +uint8_t SCI2C_ReadRxFifoDataCnt(SCI2C_T* i2c); +uint8_t SCI2C_ReadTxFifoDataCnt(SCI2C_T* i2c); +void SCI2C_ConfigRxFifoThreshold(SCI2C_T* i2c, uint8_t threshold); +void SCI2C_ConfigTxFifoThreshold(SCI2C_T* i2c, uint8_t threshold); -/** I2C Enable, disable, abort, block */ -void SCI2C_Enable(SCI2C_T *i2c); -void SCI2C_Disable(SCI2C_T *i2c); -void SCI2C_Abort(SCI2C_T *i2c); -void SCI2C_BlockTxCmd(SCI2C_T *i2c, uint8_t enable); +/* I2C Enable, disable, abort, block */ +void SCI2C_Enable(SCI2C_T* i2c); +void SCI2C_Disable(SCI2C_T* i2c); +void SCI2C_Abort(SCI2C_T* i2c); +void SCI2C_BlockTxCmd(SCI2C_T* i2c, uint8_t enable); -/** SCL and SDA */ -void SCI2C_ConfigClkPeriod(SCI2C_T *i2c, SCI2C_SPEED_T speed, uint16_t highPeriod, uint16_t lowPeriod); -void SCI2C_ConfigSDAHoldTime(SCI2C_T *i2c, uint16_t txHold, uint8_t rxHold); -void SCI2C_ConfigSDADelayTime(SCI2C_T *i2c, uint8_t delay); +/* SCL and SDA */ +void SCI2C_ConfigClkPeriod(SCI2C_T* i2c, SCI2C_SPEED_T speed, uint16_t highPeriod, uint16_t lowPeriod); +void SCI2C_ConfigSDAHoldTime(SCI2C_T* i2c, uint16_t txHold, uint8_t rxHold); +void SCI2C_ConfigSDADelayTime(SCI2C_T* i2c, uint8_t delay); -/** ACK and NACK */ -void SCI2C_GernalCallAck(SCI2C_T *i2c, uint8_t enable); -void SCI2C_SlaveDataNackOnly(SCI2C_T *i2c, uint8_t enable); +/* ACK and NACK */ +void SCI2C_GernalCallAck(SCI2C_T* i2c, uint8_t enable); +void SCI2C_SlaveDataNackOnly(SCI2C_T* i2c, uint8_t enable); -/** Abort */ -uint32_t SCI2C_ReadTxAbortSource(SCI2C_T *i2c); +/* Abort */ +uint32_t SCI2C_ReadTxAbortSource(SCI2C_T* i2c); -/** DMA */ -void SCI2C_EnableDMA(SCI2C_T *i2c, SCI2C_DMA_T dma); -void SCI2C_DisableDMA(SCI2C_T *i2c, SCI2C_DMA_T dma); -void SCI2C_ConfigDMATxDataLevel(SCI2C_T *i2c, uint8_t cnt); -void SCI2C_ConfigDMARxDataLevel(SCI2C_T *i2c, uint8_t cnt); +/* DMA */ +void SCI2C_EnableDMA(SCI2C_T* i2c, SCI2C_DMA_T dma); +void SCI2C_DisableDMA(SCI2C_T* i2c, SCI2C_DMA_T dma); +void SCI2C_ConfigDMATxDataLevel(SCI2C_T* i2c, uint8_t cnt); +void SCI2C_ConfigDMARxDataLevel(SCI2C_T* i2c, uint8_t cnt); -/** Spike suppression limit */ -void SCI2C_ConfigSpikeSuppressionLimit(SCI2C_T *i2c, SCI2C_SPEED_T speed, uint8_t limit); +/* Spike suppression limit */ +void SCI2C_ConfigSpikeSuppressionLimit(SCI2C_T* i2c, SCI2C_SPEED_T speed, uint8_t limit); -/** Ingerrupt and flag */ -uint8_t SCI2C_ReadStatusFlag(SCI2C_T *i2c, SCI2C_FLAG_T flag); -void SCI2C_ClearIntFlag(SCI2C_T *i2c, SCI2C_INT_T flag); -uint8_t SCI2C_ReadIntFlag(SCI2C_T *i2c, SCI2C_INT_T flag); -uint8_t SCI2C_ReadRawIntFlag(SCI2C_T *i2c, SCI2C_INT_T flag); -void SCI2C_EnableInterrupt(SCI2C_T *i2c, uint16_t interrupt); -void SCI2C_DisableInterrupt(SCI2C_T *i2c, uint16_t interrupt); +/* Ingerrupt and flag */ +uint8_t SCI2C_ReadStatusFlag(SCI2C_T* i2c, SCI2C_FLAG_T flag); +void SCI2C_ClearIntFlag(SCI2C_T* i2c, SCI2C_INT_T flag); +uint8_t SCI2C_ReadIntFlag(SCI2C_T* i2c, SCI2C_INT_T flag); +uint8_t SCI2C_ReadRawIntFlag(SCI2C_T* i2c, SCI2C_INT_T flag); +void SCI2C_EnableInterrupt(SCI2C_T* i2c, uint16_t interrupt); +void SCI2C_DisableInterrupt(SCI2C_T* i2c, uint16_t interrupt); -/**@} end of group SCI2C_Fuctions*/ -/**@} end of group SCI2C_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group SCI2C_Functions */ +/**@} end of group SCI2C_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_sdio.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_sdio.h index 7f63a65dd2..0c63633767 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_sdio.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_sdio.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the SDIO firmware library * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,16 +23,18 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_SDIO_H #define __APM32F10X_SDIO_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,7 +42,7 @@ @{ */ -/** @addtogroup SDIO_Enumerations Enumerations +/** @defgroup SDIO_Enumerations Enumerations @{ */ @@ -51,7 +53,7 @@ typedef enum { SDIO_CLOCK_EDGE_RISING = 0x00000000, SDIO_CLOCK_EDGE_FALLING = 0x00002000 -}SDIO_CLOCK_EDGE_T; +} SDIO_CLOCK_EDGE_T; /** * @brief SDIO clock bypass @@ -60,7 +62,7 @@ typedef enum { SDIO_CLOCK_BYPASS_DISABLE = 0x00000000, SDIO_CLOCK_BYPASS_ENABLE = 0x00000400 -}SDIO_CLOCK_BYPASS_T; +} SDIO_CLOCK_BYPASS_T; /** * @brief SDIO clock power save @@ -69,7 +71,7 @@ typedef enum { SDIO_CLOCK_POWER_SAVE_DISABLE = 0x00000000, SDIO_CLOCK_POWER_SAVE_ENABLE = 0x00000200 -}SDIO_CLOCK_POWER_SAVE_T; +} SDIO_CLOCK_POWER_SAVE_T; /** * @brief SDIO bus wide @@ -79,7 +81,7 @@ typedef enum SDIO_BUS_WIDE_1B = 0x00000000, SDIO_BUS_WIDE_4B = 0x00000800, SDIO_BUS_WIDE_8B = 0x00001000 -}SDIO_BUS_WIDE_T; +} SDIO_BUS_WIDE_T; /** * @brief SDIO hardware flow control @@ -88,7 +90,7 @@ typedef enum { SDIO_HARDWARE_FLOW_CONTROL_DISABLE = 0x00000000, SDIO_HARDWARE_FLOW_CONTROL_ENABLE = 0x00004000 -}SDIO_HARDWARE_FLOW_CONTROL_T; +} SDIO_HARDWARE_FLOW_CONTROL_T; /** * @brief SDIO power state @@ -97,7 +99,7 @@ typedef enum { SDIO_POWER_STATE_OFF = 0x00000000, SDIO_POWER_STATE_ON = 0x00000003 -}SDIO_POWER_STATE_T; +} SDIO_POWER_STATE_T; /** * @brief SDIO interrupt sources @@ -128,7 +130,7 @@ typedef enum SDIO_INT_RXDA = 0x00200000, SDIO_INT_SDIOINT = 0x00400000, SDIO_INT_ATAEND = 0x00800000 -}SDIO_INT_T; +} SDIO_INT_T; /** * @brief SDIO response @@ -138,7 +140,7 @@ typedef enum SDIO_RESPONSE_NO = 0x00000000, SDIO_RESPONSE_SHORT = 0x00000040, SDIO_RESPONSE_LONG = 0x000000C0 -}SDIO_RESPONSE_T; +} SDIO_RESPONSE_T; /** * @brief SDIO wait interrupt state @@ -148,7 +150,7 @@ typedef enum SDIO_WAIT_NO = 0x00000000, SDIO_WAIT_INT = 0x00000100, SDIO_WAIT_PEND = 0x00000200 -}SDIO_WAIT_T; +} SDIO_WAIT_T; /** * @brief SDIO CPSM state @@ -157,7 +159,7 @@ typedef enum { SDIO_CPSM_DISABLE = 0x00000000, SDIO_CPSM_ENABLE = 0x00000400 -}SDIO_CPSM_T; +} SDIO_CPSM_T; /** * @brief SDIO response registers @@ -168,7 +170,7 @@ typedef enum SDIO_RES2 = 0x00000004, SDIO_RES3 = 0x00000008, SDIO_RES4 = 0x0000000C -}SDIO_RES_T; +} SDIO_RES_T; /** * @brief SDIO data block size @@ -190,7 +192,7 @@ typedef enum SDIO_DATA_BLOCKSIZE_496B = 0x000000C0, SDIO_DATA_BLOCKSIZE_8192B = 0x000000D0, SDIO_DATA_BLOCKSIZE_16384B = 0x000000E0 -}SDIO_DATA_BLOCKSIZE_T; +} SDIO_DATA_BLOCKSIZE_T; /** * @brief SDIO transfer direction @@ -199,7 +201,7 @@ typedef enum { SDIO_TRANSFER_DIR_TO_CARD = 0x00000000, SDIO_TRANSFER_DIR_TO_SDIO = 0x00000002 -}SDIO_TRANSFER_DIR_T; +} SDIO_TRANSFER_DIR_T; /** * @brief SDIO transfer type @@ -208,7 +210,7 @@ typedef enum { SDIO_TRANSFER_MODE_BLOCK = 0x00000000, SDIO_TRANSFER_MODE_STREAM = 0x00000004 -}SDIO_TRANSFER_MODE_T; +} SDIO_TRANSFER_MODE_T; /** * @brief SDIO DPSM state @@ -217,7 +219,7 @@ typedef enum { SDIO_DPSM_DISABLE = 0x00000000, SDIO_DPSM_ENABLE = 0x00000001 -}SDIO_DPSM_T; +} SDIO_DPSM_T; /** * @brief SDIO flag @@ -248,7 +250,7 @@ typedef enum SDIO_FLAG_RXDA = 0x00200000, SDIO_FLAG_SDIOINT = 0x00400000, SDIO_FLAG_ATAEND = 0x00800000 -}SDIO_FLAG_T; +} SDIO_FLAG_T; /** * @brief SDIO read wait mode @@ -257,75 +259,75 @@ typedef enum { SDIO_READ_WAIT_MODE_CLK = 0x00000001, SDIO_READ_WAIT_MODE_DATA2 = 0x00000000 -}SDIO_READ_WAIT_MODE_T; +} SDIO_READ_WAIT_MODE_T; -/**@} end of group SDIO_Enumerations*/ +/**@} end of group SDIO_Enumerations */ -/** @addtogroup SDIO_Macros Macros +/** @defgroup SDIO_Macros Macros @{ */ -/** ------------ SDIO registers bit address in the alias region ----------- */ +/* ------------ SDIO registers bit address in the alias region ----------- */ #define SDIO_OFFSET (SDIO_BASE - PERIPH_BASE) -/** --- CLKCTRL Register ---*/ +/* --- CLKCTRL Register --- */ -/** Alias word address of CLKEN bit */ +/* Alias word address of CLKEN bit */ #define CLKCTRL_OFFSET (SDIO_OFFSET + 0x04) #define CLKEN_BitNumber 0x08 #define CLKCTRL_CLKEN_BB (PERIPH_BB_BASE + (CLKCTRL_OFFSET * 32) + (CLKEN_BitNumber * 4)) -/** --- CMD Register ---*/ +/* --- CMD Register --- */ -/** Alias word address of SDIOSC bit */ +/* Alias word address of SDIOSC bit */ #define CMD_OFFSET (SDIO_OFFSET + 0x0C) #define SDIOSC_BitNumber 0x0B #define CMD_SDIOSC_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (SDIOSC_BitNumber * 4)) -/** Alias word address of CMDCPEN bit */ +/* Alias word address of CMDCPEN bit */ #define CMDCPEN_BitNumber 0x0C #define CMD_CMDCPEN_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (CMDCPEN_BitNumber * 4)) -/** Alias word address of INTEN bit */ +/* Alias word address of INTEN bit */ #define INTEN_BitNumber 0x0D #define CMD_INTEN_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (INTEN_BitNumber * 4)) -/** Alias word address of ATACMD bit */ +/* Alias word address of ATACMD bit */ #define ATACMD_BitNumber 0x0E #define CMD_ATACMD_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (ATACMD_BitNumber * 4)) -/** --- DCTRL Register ---*/ +/* --- DCTRL Register --- */ -/** Alias word address of DMAEN bit */ +/* Alias word address of DMAEN bit */ #define DCTRL_OFFSET (SDIO_OFFSET + 0x2C) #define DMAEN_BitNumber 0x03 #define DCTRL_DMAEN_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (DMAEN_BitNumber * 4)) -/** Alias word address of RWSTR bit */ +/* Alias word address of RWSTR bit */ #define RWSTR_BitNumber 0x08 #define DCTRL_RWSTR_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWSTR_BitNumber * 4)) -/** Alias word address of RWSTOP bit */ +/* Alias word address of RWSTOP bit */ #define RWSTOP_BitNumber 0x09 #define DCTRL_RWSTOP_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWSTOP_BitNumber * 4)) -/** Alias word address of RDWAIT bit */ +/* Alias word address of RDWAIT bit */ #define RDWAIT_BitNumber 0x0A #define DCTRL_RDWAIT_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RDWAIT_BitNumber * 4)) -/** Alias word address of SDIOF bit */ +/* Alias word address of SDIOF bit */ #define SDIOF_BitNumber 0x0B #define DCTRL_SDIOF_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (SDIOF_BitNumber * 4)) -/**@} end of group SDIO_Macros*/ +/**@} end of group SDIO_Macros */ -/** @addtogroup SDIO_Structure Data Structure +/** @defgroup SDIO_Structures Structures @{ */ /** - * @brief SDIO Config structure definition + * @brief SDIO Configure structure definition */ typedef struct { @@ -335,10 +337,10 @@ typedef struct SDIO_BUS_WIDE_T busWide; SDIO_HARDWARE_FLOW_CONTROL_T hardwareFlowControl; uint8_t clockDiv; -}SDIO_Config_T; +} SDIO_Config_T; /** - * @brief SDIO CMD Config structure definition + * @brief SDIO CMD Configure structure definition */ typedef struct { @@ -347,10 +349,10 @@ typedef struct SDIO_RESPONSE_T response; SDIO_WAIT_T wait; SDIO_CPSM_T CPSM; -}SDIO_CmdConfig_T; +} SDIO_CmdConfig_T; /** - * @brief SDIO Data Config structure definition + * @brief SDIO Data Configure structure definition */ typedef struct { @@ -360,16 +362,15 @@ typedef struct SDIO_TRANSFER_DIR_T transferDir; SDIO_TRANSFER_MODE_T transferMode; SDIO_DPSM_T DPSM; -}SDIO_DataConfig_T; +} SDIO_DataConfig_T; -/**@} end of group SDIO_Structure*/ +/**@} end of group SDIO_Structures */ - -/** @addtogroup SDIO_Fuctions Fuctions +/** @defgroup SDIO_Functions Functions @{ */ -/** SDIO reset and configuration */ +/* SDIO reset and configuration */ void SDIO_Reset(void); void SDIO_Config(SDIO_Config_T* sdioConfig); void SDIO_ConfigStructInit(SDIO_Config_T* sdioConfig); @@ -378,17 +379,17 @@ void SDIO_DisableClock(void); void SDIO_ConfigPowerState(SDIO_POWER_STATE_T powerState); uint32_t SDIO_ReadPowerState(void); -/** DMA */ +/* DMA */ void SDIO_EnableDMA(void); void SDIO_DisableDMA(void); -/** Command */ -void SDIO_TxCommand(SDIO_CmdConfig_T *cmdConfig); +/* Command */ +void SDIO_TxCommand(SDIO_CmdConfig_T* cmdConfig); void SDIO_TxCommandStructInit(SDIO_CmdConfig_T* cmdconfig); uint8_t SDIO_ReadCommandResponse(void); uint32_t SDIO_ReadResponse(SDIO_RES_T res); -/** SDIO data configuration */ +/* SDIO data configuration */ void SDIO_ConfigData(SDIO_DataConfig_T* dataConfig); void SDIO_ConfigDataStructInit(SDIO_DataConfig_T* dataConfig); uint32_t SDIO_ReadDataCounter(void); @@ -396,7 +397,7 @@ void SDIO_WriteData(uint32_t data); uint32_t SDIO_ReadData(void); uint32_t SDIO_ReadFIFOCount(void); -/** SDIO mode */ +/* SDIO mode */ void SDIO_EnableStartReadWait(void); void SDIO_DisableStartReadWait(void); void SDIO_EnableStopReadWait(void); @@ -413,7 +414,7 @@ void SDIO_DisableCEATAInterrupt(void); void SDIO_EnableTxCEATA(void); void SDIO_DisableTxCEATA(void); -/** Interrupt and flags */ +/* Interrupt and flags */ void SDIO_EnableInterrupt(uint32_t interrupt); void SDIO_DisableInterrupt(uint32_t interrupt); uint8_t SDIO_ReadStatusFlag(SDIO_FLAG_T flag); @@ -421,12 +422,12 @@ void SDIO_ClearStatusFlag(uint32_t flag); uint8_t SDIO_ReadIntFlag(SDIO_INT_T flag); void SDIO_ClearIntFlag(uint32_t flag); -/**@} end of group SDIO_Fuctions*/ -/**@} end of group SDIO_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group SDIO_Functions */ +/**@} end of group SDIO_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ #ifdef __cplusplus } #endif -#endif /* __APM32F10X_SDIO_H */ +#endif /*__APM32F10X_SDIO_H */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_smc.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_smc.h new file mode 100644 index 0000000000..77be32fe0c --- /dev/null +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_smc.h @@ -0,0 +1,370 @@ +/*! + * @file apm32f10x_smc.h + * + * @brief This file contains all the functions prototypes for the SMC firmware library + * + * @version V1.0.4 + * + * @date 2022-12-01 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __APM32F10X_SMC_H +#define __APM32F10X_SMC_H + +/* Includes */ +#include "apm32f10x.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver + @{ +*/ + +/** @addtogroup SMC_Driver SMC Driver + @{ +*/ + +/** @defgroup SMC_Enumerations Enumerations + @{ +*/ + +/** + * @brief SMC NORSRAM_Bank + */ +typedef enum +{ + SMC_BANK1_NORSRAM_1 = 0x00000000, + SMC_BANK1_NORSRAM_2 = 0x00000002, + SMC_BANK1_NORSRAM_3 = 0x00000004, + SMC_BANK1_NORSRAM_4 = 0x00000006 +} SMC_BANK1_NORSRAM_T; + +/** + * @brief SMC NAND and PC Card Bank + */ +typedef enum +{ + SMC_BANK2_NAND = 0x00000010, + SMC_BANK3_NAND = 0x00000100, + SMC_BANK4_PCCARD = 0x00001000 +} SMC_BANK_NAND_T; + +/** + * @brief SMC_Data_Address_Bus_Multiplexing + */ +typedef enum +{ + SMC_DATA_ADDRESS_MUX_DISABLE = 0x00000000, + SMC_DATA_ADDRESS_MUX_ENABLE = 0x00000002 +} SMC_DATA_ADDRESS_MUX_T; + +/** + * @brief SMC_Memory_Type + */ +typedef enum +{ + SMC_MEMORY_TYPE_SRAM = 0x00000000, + SMC_MEMORY_TYPE_PSRAM = 0x00000004, + SMC_MEMORY_TYPE_NOR = 0x00000008 +} SMC_MEMORY_TYPE_T; + +/** + * @brief SMC_Data_Width + */ +typedef enum +{ + SMC_MEMORY_DATA_WIDTH_8BIT = 0x00000000, + SMC_MEMORY_DATA_WIDTH_16BIT = 0x00000010 +} SMC_MEMORY_DATA_WIDTH_T; + +/** + * @brief SMC_Burst_Access_Mode + */ +typedef enum +{ + SMC_BURST_ACCESS_MODE_DISABLE = 0x00000000, + SMC_BURST_ACCESS_MODE_ENABLE = 0x00000100 +} SMC_BURST_ACCESS_MODE_T; + +/** + * @brief SMC_AsynchronousWait + */ +typedef enum +{ + SMC_ASYNCHRONOUS_WAIT_DISABLE = 0x00000000, + SMC_ASYNCHRONOUS_WAIT_ENABLE = 0x00008000 +} SMC_ASYNCHRONOUS_WAIT_T; + +/** + * @brief SMC_Wait_Signal_Polarity + */ +typedef enum +{ + SMC_WAIT_SIGNAL_POLARITY_LOW = 0x00000000, + SMC_WAIT_SIGNAL_POLARITY_HIGH = 0x00000200 +} SMC_WAIT_SIGNAL_POLARITY_T; + +/** + * @brief SMC_Wrap_Mode + */ +typedef enum +{ + SMC_WRAP_MODE_DISABLE = 0x00000000, + SMC_WRAP_MODE_ENABLE = 0x00000400 +} SMC_WRAP_MODE_T; + +/** + * @brief SMC_Wait_Timing + */ +typedef enum +{ + SMC_WAIT_SIGNAL_ACTIVE_BEFORE_WAIT = 0x00000000, + SMC_WAIT_SIGNAL_ACTIVE_DURING_WAIT = 0x00000800 +} SMC_WAIT_SIGNAL_ACTIVE_T; + +/** + * @brief SMC_Write_Operation + */ +typedef enum +{ + SMC_WRITE_OPERATION_DISABLE = 0x00000000, + SMC_WRITE_OPERATION_ENABLE = 0x00001000 +} SMC_WRITE_OPERATION_T; + +/** + * @brief SMC_Wait_Signal + */ +typedef enum +{ + SMC_WAITE_SIGNAL_DISABLE = 0x00000000, + SMC_WAITE_SIGNAL_ENABLE = 0x00002000 +} SMC_WAITE_SIGNAL_T; + +/** + * @brief SMC_Extended_Mode + */ +typedef enum +{ + SMC_EXTENDEN_MODE_DISABLE = 0x00000000, + SMC_EXTENDEN_MODE_ENABLE = 0x00004000 +} SMC_EXTENDEN_MODE_T; + +/** + * @brief SMC_Write_Burst + */ +typedef enum +{ + SMC_WRITE_BURST_DISABLE = 0x00000000, + SMC_WRITE_BURST_ENABLE = 0x00080000 +} SMC_WRITE_BURST_T; + +/** + * @brief SMC_WAIT_FEATURE + */ +typedef enum +{ + SMC_WAIT_FEATURE_DISABLE = 0x00000000, + SMC_WAIT_FEATURE_ENABLE = 0x00000002 +} SMC_WAIT_FEATURE_T; + +/** + * @brief SMC_ECC + */ +typedef enum +{ + SMC_ECC_DISABLE = 0x00000000, + SMC_ECC_ENABLE = 0x00000040 +} SMC_ECC_T; + +/** + * @brief SMC_ECC_Page_Size + */ +typedef enum +{ + SMC_ECC_PAGE_SIZE_BYTE_256 = 0x00000000, + SMC_ECC_PAGE_SIZE_BYTE_512 = 0x00020000, + SMC_ECC_PAGE_SIZE_BYTE_1024 = 0x00040000, + SMC_ECC_PAGE_SIZE_BYTE_2048 = 0x00060000, + SMC_ECC_PAGE_SIZE_BYTE_4096 = 0x00080000, + SMC_ECC_PAGE_SIZE_BYTE_8192 = 0x000A0000 +} SMC_ECC_PAGE_SIZE_BYTE_T; + +/** + * @brief SMC_Access_Mode + */ +typedef enum +{ + SMC_ACCESS_MODE_A = 0x00000000, + SMC_ACCESS_MODE_B = 0x10000000, + SMC_ACCESS_MODE_C = 0x20000000, + SMC_ACCESS_MODE_D = 0x30000000 +} SMC_ACCESS_MODE_T; + +/** + * @brief SMC_Interrupt_sources + */ +typedef enum +{ + SMC_INT_EDGE_RISING = 0x00000008, + SMC_INT_LEVEL_HIGH = 0x00000010, + SMC_INT_EDGE_FALLING = 0x00000020 +} SMC_INT_T; + +/** + * @brief SMC_Flags + */ +typedef enum +{ + SMC_FLAG_EDGE_RISING = 0x00000001, + SMC_FLAG_LEVEL_HIGH = 0x00000002, + SMC_FLAG_EDGE_FALLING = 0x00000004, + SMC_FLAG_FIFO_EMPTY = 0x00000040 +} SMC_FLAG_T; + +/**@} end of group SMC_Enumerations */ + +/** @defgroup SMC_Structures Structures + @{ +*/ + +/** + * @brief Timing parameters for NOR/SRAM Banks + */ +typedef struct +{ + uint32_t addressSetupTime; + uint32_t addressHodeTime; + uint32_t dataSetupTime; + uint32_t busTurnaroundTime; + uint32_t clockDivision; + uint32_t dataLatency; + SMC_ACCESS_MODE_T accessMode; +} SMC_NORSRAMTimingConfig_T; + +/** + * @brief SMC NOR/SRAM Configure structure + */ +typedef struct +{ + SMC_BANK1_NORSRAM_T bank; + SMC_DATA_ADDRESS_MUX_T dataAddressMux; + SMC_MEMORY_TYPE_T memoryType; + SMC_MEMORY_DATA_WIDTH_T memoryDataWidth; + SMC_BURST_ACCESS_MODE_T burstAcceesMode; + SMC_ASYNCHRONOUS_WAIT_T asynchronousWait; + SMC_WAIT_SIGNAL_POLARITY_T waitSignalPolarity; + SMC_WRAP_MODE_T wrapMode; + SMC_WAIT_SIGNAL_ACTIVE_T waitSignalActive; + SMC_WRITE_OPERATION_T writeOperation; + SMC_WAITE_SIGNAL_T waiteSignal; + SMC_EXTENDEN_MODE_T extendedMode; + SMC_WRITE_BURST_T writeBurst; + SMC_NORSRAMTimingConfig_T* readWriteTimingStruct; + SMC_NORSRAMTimingConfig_T* writeTimingStruct; +} SMC_NORSRAMConfig_T; + +/** + * @brief Timing parameters for NAND and PCCARD Banks + */ +typedef struct +{ + uint32_t setupTime; + uint32_t waitSetupTime; + uint32_t holdSetupTime; + uint32_t HiZSetupTime; +} SMC_NAND_PCCARDTimingConfig_T; + +/** + * @brief SMC NAND Configure structure + */ +typedef struct +{ + SMC_BANK_NAND_T bank; + SMC_WAIT_FEATURE_T waitFeature; + SMC_MEMORY_DATA_WIDTH_T memoryDataWidth; + SMC_ECC_T ECC; + SMC_ECC_PAGE_SIZE_BYTE_T ECCPageSize; + uint32_t TCLRSetupTime; + uint32_t TARSetupTime; + SMC_NAND_PCCARDTimingConfig_T* commonSpaceTimingStruct; + SMC_NAND_PCCARDTimingConfig_T* attributeSpaceTimingStruct; +} SMC_NANDConfig_T; + +/** + * @brief SMC PCCARD Configure structure + */ +typedef struct +{ + SMC_WAIT_FEATURE_T waitFeature; + uint32_t TCLRSetupTime; + uint32_t TARSetupTime; + SMC_NAND_PCCARDTimingConfig_T* commonSpaceTimingStruct; + SMC_NAND_PCCARDTimingConfig_T* attributeSpaceTimingStruct; + SMC_NAND_PCCARDTimingConfig_T* IOSpaceTimingStruct; +} SMC_PCCARDConfig_T; + +/**@} end of group SMC_Structures */ + +/** @defgroup SMC_Functions Functions + @{ +*/ + +/* SMC reset */ +void SMC_ResetNORSRAM(SMC_BANK1_NORSRAM_T bank); +void SMC_ResetNAND(SMC_BANK_NAND_T bank); +void SMC_ResetPCCard(void); + +/* SMC Configuration */ +void SMC_ConfigNORSRAM(SMC_NORSRAMConfig_T* smcNORSRAMConfig); +void SMC_ConfigNAND(SMC_NANDConfig_T* smcNANDConfig); +void SMC_ConfigPCCard(SMC_PCCARDConfig_T* smcPCCardConfig); +void SMC_ConfigNORSRAMStructInit(SMC_NORSRAMConfig_T* smcNORSRAMConfig); +void SMC_ConfigNANDStructInit(SMC_NANDConfig_T* smcNANDConfig); +void SMC_ConfigPCCardStructInit(SMC_PCCARDConfig_T* smcPCCardConfig); + +/* SMC bank control */ +void SMC_EnableNORSRAM(SMC_BANK1_NORSRAM_T bank); +void SMC_DisableNORSRAM(SMC_BANK1_NORSRAM_T bank); +void SMC_EnableNAND(SMC_BANK_NAND_T bank); +void SMC_DisableNAND(SMC_BANK_NAND_T bank); +void SMC_EnablePCCARD(void); +void SMC_DisablePCCARD(void); +void SMC_EnableNANDECC(SMC_BANK_NAND_T bank); +void SMC_DisableNANDECC(SMC_BANK_NAND_T bank); +uint32_t SMC_ReadECC(SMC_BANK_NAND_T bank); + +/* Interrupt and flag */ +void SMC_EnableInterrupt(SMC_BANK_NAND_T bank, uint32_t interrupt); +void SMC_DisableInterrupt(SMC_BANK_NAND_T bank, uint32_t interrupt); +uint8_t SMC_ReadStatusFlag(SMC_BANK_NAND_T bank, SMC_FLAG_T flag); +void SMC_ClearStatusFlag(SMC_BANK_NAND_T bank, uint32_t flag); +uint8_t SMC_ReadIntFlag(SMC_BANK_NAND_T bank, SMC_INT_T flag); +void SMC_ClearIntFlag(SMC_BANK_NAND_T bank, uint32_t flag); + +/**@} end of group SMC_Functions */ +/**@} end of group SMC_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ + +#ifdef __cplusplus +} +#endif + +#endif /* __APM32F10X_SMC_H */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_spi.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_spi.h index 6e6d8e3338..c7609be840 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_spi.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_spi.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the SPI firmware library * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,16 +23,18 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_SPI_H #define __APM32F10X_SPI_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,7 +42,7 @@ @{ */ -/** @addtogroup SPI_Enumerations Enumerations +/** @defgroup SPI_Enumerations Enumerations @{ */ @@ -53,7 +55,7 @@ typedef enum SPI_DIRECTION_2LINES_RXONLY = 0x0400, SPI_DIRECTION_1LINE_RX = 0x8000, SPI_DIRECTION_1LINE_TX = 0xC000 -}SPI_DIRECTION_T; +} SPI_DIRECTION_T; /** * @brief SPI mode @@ -62,7 +64,7 @@ typedef enum { SPI_MODE_MASTER = 0x0104, SPI_MODE_SLAVE = 0x0000 -}SPI_MODE_T; +} SPI_MODE_T; /** * @brief SPI Data length @@ -71,7 +73,7 @@ typedef enum { SPI_DATA_LENGTH_16B = 0x0800, SPI_DATA_LENGTH_8B = 0x0000 -}SPI_DATA_LENGTH_T; +} SPI_DATA_LENGTH_T; /** * @brief SPI Clock Polarity @@ -80,7 +82,7 @@ typedef enum { SPI_CLKPOL_LOW = 0x0000, SPI_CLKPOL_HIGH = 0x0002 -}SPI_CLKPOL_T; +} SPI_CLKPOL_T; /** * @brief SPI Clock Phase @@ -89,7 +91,7 @@ typedef enum { SPI_CLKPHA_1EDGE = 0x0000, SPI_CLKPHA_2EDGE = 0x0001 -}SPI_CLKPHA_T; +} SPI_CLKPHA_T; /** * @brief SPI Slave Select management @@ -98,7 +100,7 @@ typedef enum { SPI_NSS_SOFT = 0x0200, SPI_NSS_HARD = 0x0000 -}SPI_NSS_T; +} SPI_NSS_T; /** * @brief SPI BaudRate Prescaler @@ -113,7 +115,7 @@ typedef enum SPI_BAUDRATE_DIV_64 = 0x0028, SPI_BAUDRATE_DIV_128 = 0x0030, SPI_BAUDRATE_DIV_256 = 0x0038, -}SPI_BAUDRATE_DIV_T; +} SPI_BAUDRATE_DIV_T; /** * @brief SPI MSB LSB transmission @@ -122,7 +124,7 @@ typedef enum { SPI_FIRSTBIT_MSB = 0x0000, SPI_FIRSTBIT_LSB = 0x0080 -}SPI_FIRSTBIT_T; +} SPI_FIRSTBIT_T; /** * @brief I2S Mode @@ -133,7 +135,7 @@ typedef enum I2S_MODE_SLAVE_RX = 0x0100, I2S_MODE_MASTER_TX = 0x0200, I2S_MODE_MASTER_RX = 0x0300 -}I2S_MODE_T; +} I2S_MODE_T; /** * @brief I2S Standard @@ -145,7 +147,7 @@ typedef enum I2S_STANDARD_LSB = 0x0020, I2S_STANDARD_PCMSHORT = 0x0030, I2S_STANDARD_PCMLONG = 0x00B0 -}I2S_STANDARD_T; +} I2S_STANDARD_T; /** * @brief I2S data length @@ -165,7 +167,7 @@ typedef enum { I2S_MCLK_OUTPUT_DISABLE = 0x0000, I2S_MCLK_OUTPUT_ENABLE = 0x0200, -}I2S_MCLK_OUTPUT_T; +} I2S_MCLK_OUTPUT_T; /** * @brief I2S Audio divider @@ -182,7 +184,7 @@ typedef enum I2S_AUDIO_DIV_11K = 11025, I2S_AUDIO_DIV_8K = 8000, I2S_AUDIO_DIV_DEFAULT = 2 -}I2S_AUDIO_DIV_T; +} I2S_AUDIO_DIV_T; /** * @brief I2S Clock Polarity @@ -191,7 +193,7 @@ typedef enum { I2S_CLKPOL_LOW = 0x0000, I2S_CLKPOL_HIGH = 0x0008 -}I2S_CLKPOL_T; +} I2S_CLKPOL_T; /** * @brief SPI Direction select @@ -200,7 +202,7 @@ typedef enum { SPI_DIRECTION_RX = 0xBFFF, SPI_DIRECTION_TX = 0x4000 -}SPI_DIRECTION_SELECT_T; +} SPI_DIRECTION_SELECT_T; /** * @brief SPI interrupts definition @@ -214,7 +216,7 @@ typedef enum SPI_INT_CRCE = 0x2010, SPI_INT_ME = 0x2020, I2S_INT_UDR = 0x2008 -}SPI_I2S_INT_T; +} SPI_I2S_INT_T; /** * @brief SPI flags definition @@ -229,7 +231,7 @@ typedef enum SPI_FLAG_ME = 0x0020, SPI_FLAG_OVR = 0x0040, SPI_FLAG_BSY = 0x0080 -}SPI_FLAG_T; +} SPI_FLAG_T; /** * @brief SPI I2S DMA requests @@ -238,12 +240,12 @@ typedef enum { SPI_I2S_DMA_REQ_TX = 0x0002, SPI_I2S_DMA_REQ_RX = 0x0001 -}SPI_I2S_DMA_REQ_T; +} SPI_I2S_DMA_REQ_T; /**@} end of group SPI_Enumerations*/ -/** @addtogroup SPI_Structure Data Structure +/** @addtogroup SPI_Structures Structures @{ */ @@ -261,7 +263,7 @@ typedef struct SPI_DIRECTION_T direction; SPI_BAUDRATE_DIV_T baudrateDiv; uint16_t crcPolynomial; -}SPI_Config_T; +} SPI_Config_T; /** * @brief I2S Config structure definition @@ -274,15 +276,15 @@ typedef struct I2S_MCLK_OUTPUT_T MCLKOutput; I2S_AUDIO_DIV_T audioDiv; I2S_CLKPOL_T polarity; -}I2S_Config_T; +} I2S_Config_T; -/**@} end of group SPI_Structure*/ +/**@} end of group SPI_Structures */ -/** @addtogroup SPI_Fuctions Fuctions +/** @defgroup SPI_Functions Functions @{ */ -/** Reset and Configuration */ +/* Reset and Configuration */ void SPI_I2S_Reset(SPI_T* spi); void SPI_Config(SPI_T* spi, SPI_Config_T* spiConfig); void I2S_Config(SPI_T* spi, I2S_Config_T* i2sConfig); @@ -301,11 +303,11 @@ void SPI_EnableSSOutput(SPI_T* spi); void SPI_DisableSSOutput(SPI_T* spi); void SPI_ConfigDataSize(SPI_T* spi, SPI_DATA_LENGTH_T length); -/** DMA */ +/* DMA */ void SPI_I2S_EnableDMA(SPI_T* spi, SPI_I2S_DMA_REQ_T dmaReq); void SPI_I2S_DisableDMA(SPI_T* spi, SPI_I2S_DMA_REQ_T dmaReq); -/** CRC */ +/* CRC */ void SPI_TxCRC(SPI_T* spi); void SPI_EnableCRC(SPI_T* spi); void SPI_DisableCRC(SPI_T* spi); @@ -314,7 +316,7 @@ uint16_t SPI_ReadRxCRC(SPI_T* spi); uint16_t SPI_ReadCRCPolynomial(SPI_T* spi); void SPI_ConfigBiDirectionalLine(SPI_T* spi, SPI_DIRECTION_SELECT_T direction); -/** Interrupts and flag */ +/* Interrupts and flag */ void SPI_I2S_EnableInterrupt(SPI_T* spi, SPI_I2S_INT_T interrupt); void SPI_I2S_DisableInterrupt(SPI_T* spi, SPI_I2S_INT_T interrupt); uint8_t SPI_I2S_ReadStatusFlag(SPI_T* spi, SPI_FLAG_T flag); @@ -322,9 +324,9 @@ void SPI_I2S_ClearStatusFlag(SPI_T* spi, SPI_FLAG_T flag); uint8_t SPI_I2S_ReadIntFlag(SPI_T* spi, SPI_I2S_INT_T flag); void SPI_I2S_ClearIntFlag(SPI_T* spi, SPI_I2S_INT_T flag); -/**@} end of group SPI_Fuctions*/ -/**@} end of group SPI_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group SPI_Functions */ +/**@} end of group SPI_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_tmr.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_tmr.h index 62069152fe..9a71cc1016 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_tmr.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_tmr.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the TMR firmware library. * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,31 +15,33 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_TMR_H #define __APM32F10X_TMR_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ -/** @addtogroup TMR_Driver TMR Driver +/** @addtogroup TMR_Driver TMR Driver @{ */ -/** @addtogroup TMR_Enumerations Enumerations +/** @defgroup TMR_Enumerations Enumerations @{ */ @@ -480,26 +482,26 @@ typedef enum TMR_FLAG_CC4RC = 0x1000 } TMR_FLAG_T; -/**@} end of group TMR_Enumerations*/ +/**@} end of group TMR_Enumerations */ -/** @addtogroup TMR_Structure Data Structure +/** @defgroup TMR_Structures Structures @{ */ /** - * @brief TMR Config struct definition + * @brief TMR Base Configure structure definition */ typedef struct { TMR_COUNTER_MODE_T countMode; TMR_CLOCK_DIV_T clockDivision; - uint16_t period; //!< This must between 0x0000 and 0xFFFF - uint16_t division; //!< This must between 0x0000 and 0xFFFF - uint8_t repetitionCounter; //!< This must between 0x00 and 0xFF, only for TMR1 and TMR8. + uint16_t period; /*!< This must between 0x0000 and 0xFFFF */ + uint16_t division; /*!< This must between 0x0000 and 0xFFFF */ + uint8_t repetitionCounter; /*!< This must between 0x00 and 0xFF, only for TMR1 and TMR8. */ } TMR_BaseConfig_T; ; /** - * @brief TMR Config struct definition + * @brief TMR Output Compare Configure structure definition */ typedef struct { @@ -510,7 +512,7 @@ typedef struct TMR_OC_NPOLARITY_T nPolarity; TMR_OC_IDLE_STATE_T idleState; TMR_OC_NIDLE_STATE_T nIdleState; - uint16_t pulse; //!< This must between 0x0000 and 0xFFFF + uint16_t pulse; /*!< This must between 0x0000 and 0xFFFF */ } TMR_OCConfig_T; /** @@ -528,7 +530,7 @@ typedef struct } TMR_BDTConfig_T; /** - * @brief TMR Input Capture Config struct definition + * @brief TMR Input Capture Configure structure definition */ typedef struct { @@ -536,48 +538,48 @@ typedef struct TMR_IC_POLARITY_T polarity; TMR_IC_SELECTION_T selection; TMR_IC_PSC_T prescaler; - uint16_t filter; //!< This must between 0x00 and 0x0F + uint16_t filter; /*!< This must between 0x00 and 0x0F */ } TMR_ICConfig_T; -/**@} end of group TMR_Structure*/ +/**@} end of group TMR_Structures */ -/** @addtogroup TMR_Fuctions Fuctions +/** @defgroup TMR_Functions Functions @{ */ -/** Reset and Configuration */ +/* Reset and Configuration */ void TMR_Reset(TMR_T* tmr); -void TMR_ConfigTimeBase(TMR_T* tmr, TMR_BaseConfig_T *baseConfig); -void TMR_ConfigOC1(TMR_T* tmr, TMR_OCConfig_T *OCConfig); -void TMR_ConfigOC2(TMR_T* tmr, TMR_OCConfig_T *OCConfig); -void TMR_ConfigOC3(TMR_T* tmr, TMR_OCConfig_T *OCConfig); -void TMR_ConfigOC4(TMR_T* tmr, TMR_OCConfig_T *OCConfig); -void TMR_ConfigIC(TMR_T* tmr, TMR_ICConfig_T *ICConfig); -void TMR_ConfigBDT(TMR_T* tmr, TMR_BDTConfig_T *BDTConfig); -void TMR_ConfigTimeBaseStructInit(TMR_BaseConfig_T *baseConfig); -void TMR_ConfigOCStructInit(TMR_OCConfig_T *OCConfig); -void TMR_ConfigICStructInit(TMR_ICConfig_T *ICConfig); -void TMR_ConfigBDTStructInit( TMR_BDTConfig_T *BDTConfig); +void TMR_ConfigTimeBase(TMR_T* tmr, TMR_BaseConfig_T* baseConfig); +void TMR_ConfigOC1(TMR_T* tmr, TMR_OCConfig_T* OCConfig); +void TMR_ConfigOC2(TMR_T* tmr, TMR_OCConfig_T* OCConfig); +void TMR_ConfigOC3(TMR_T* tmr, TMR_OCConfig_T* OCConfig); +void TMR_ConfigOC4(TMR_T* tmr, TMR_OCConfig_T* OCConfig); +void TMR_ConfigIC(TMR_T* tmr, TMR_ICConfig_T* ICConfig); +void TMR_ConfigBDT(TMR_T* tmr, TMR_BDTConfig_T* BDTConfig); +void TMR_ConfigTimeBaseStructInit(TMR_BaseConfig_T* baseConfig); +void TMR_ConfigOCStructInit(TMR_OCConfig_T* OCConfig); +void TMR_ConfigICStructInit(TMR_ICConfig_T* ICConfig); +void TMR_ConfigBDTStructInit(TMR_BDTConfig_T* BDTConfig); void TMR_ConfigSinglePulseMode(TMR_T* tmr, TMR_SPM_T singlePulseMode); void TMR_ConfigClockDivision(TMR_T* tmr, TMR_CLOCK_DIV_T clockDivision); void TMR_Enable(TMR_T* tmr); void TMR_Disable(TMR_T* tmr); -/** PWM Configuration */ -void TMR_ConfigPWM(TMR_T* tmr, TMR_ICConfig_T *PWMConfig); +/* PWM Configuration */ +void TMR_ConfigPWM(TMR_T* tmr, TMR_ICConfig_T* PWMConfig); void TMR_EnablePWMOutputs(TMR_T* tmr); void TMR_DisablePWMOutputs(TMR_T* tmr); -/** DMA */ +/* DMA */ void TMR_ConfigDMA(TMR_T* tmr, TMR_DMA_BASE_T baseAddress, TMR_DMA_BURSTLENGTH_T burstLength); void TMR_EnableDMASoure(TMR_T* tmr, uint16_t dmaSource); void TMR_DisableDMASoure(TMR_T* tmr, uint16_t dmaSource); -/** Configuration */ +/* Configuration */ void TMR_ConfigInternalClock(TMR_T* tmr); void TMR_ConfigIntTrigExternalClock(TMR_T* tmr, TMR_TRIGGER_SOURCE_T triggerSource); void TMR_ConfigTrigExternalClock(TMR_T* tmr, TMR_TRIGGER_SOURCE_T triggerSource, - TMR_IC_POLARITY_T ICpolarity, uint16_t ICfilter); + TMR_IC_POLARITY_T ICpolarity, uint16_t ICfilter); void TMR_ConfigETRClockMode1(TMR_T* tmr, TMR_EXTTRG_PSC_T prescaler, TMR_EXTTRG_POL_T polarity, uint16_t filter); void TMR_ConfigETRClockMode2(TMR_T* tmr, TMR_EXTTRG_PSC_T prescaler, @@ -589,10 +591,10 @@ void TMR_ConfigCounterMode(TMR_T* tmr, TMR_COUNTER_MODE_T countMode); void TMR_SelectInputTrigger(TMR_T* tmr, TMR_TRIGGER_SOURCE_T triggerSouce); void TMR_ConfigEncodeInterface(TMR_T* tmr, TMR_ENCODER_MODE_T encodeMode, TMR_IC_POLARITY_T IC1Polarity, TMR_IC_POLARITY_T IC2Polarity); -void TMR_ConfigForcedOC1(TMR_T* tmr,TMR_FORCED_ACTION_T forcesAction); -void TMR_ConfigForcedOC2(TMR_T* tmr,TMR_FORCED_ACTION_T forcesAction); -void TMR_ConfigForcedOC3(TMR_T* tmr,TMR_FORCED_ACTION_T forcesAction); -void TMR_ConfigForcedOC4(TMR_T* tmr,TMR_FORCED_ACTION_T forcesAction); +void TMR_ConfigForcedOC1(TMR_T* tmr, TMR_FORCED_ACTION_T forcesAction); +void TMR_ConfigForcedOC2(TMR_T* tmr, TMR_FORCED_ACTION_T forcesAction); +void TMR_ConfigForcedOC3(TMR_T* tmr, TMR_FORCED_ACTION_T forcesAction); +void TMR_ConfigForcedOC4(TMR_T* tmr, TMR_FORCED_ACTION_T forcesAction); void TMR_EnableAutoReload(TMR_T* tmr); void TMR_DisableAutoReload(TMR_T* tmr); void TMR_EnableSelectCOM(TMR_T* tmr); @@ -620,16 +622,17 @@ void TMR_ConfigOC2NPolarity(TMR_T* tmr, TMR_OC_NPOLARITY_T OCNPolarity); void TMR_ConfigOC3Polarity(TMR_T* tmr, TMR_OC_POLARITY_T OCPolarity); void TMR_ConfigOC3NPolarity(TMR_T* tmr, TMR_OC_NPOLARITY_T OCNPolarity); void TMR_ConfigOC4Polarity(TMR_T* tmr, TMR_OC_POLARITY_T OCPolarity); -void TMR_EnableCCxChannel(TMR_T* tmr,TMR_CHANNEL_T channel); -void TMR_DisableCCxChannel(TMR_T* tmr,TMR_CHANNEL_T channel); -void TMR_EnableCCxNChannel(TMR_T* tmr,TMR_CHANNEL_T channel); -void TMR_DisableCCxNChannel(TMR_T* tmr,TMR_CHANNEL_T channel); +void TMR_EnableCCxChannel(TMR_T* tmr, TMR_CHANNEL_T channel); +void TMR_DisableCCxChannel(TMR_T* tmr, TMR_CHANNEL_T channel); +void TMR_EnableCCxNChannel(TMR_T* tmr, TMR_CHANNEL_T channel); +void TMR_DisableCCxNChannel(TMR_T* tmr, TMR_CHANNEL_T channel); void TMR_SelectOCxMode(TMR_T* tmr, TMR_CHANNEL_T channel, TMR_OC_MODE_T OCMode); void TMR_EnableUpdate(TMR_T* tmr); void TMR_DisableUpdate(TMR_T* tmr); void TMR_ConfigUpdateRequest(TMR_T* tmr, TMR_UPDATE_SOURCE_T updateSource); void TMR_EnableHallSensor(TMR_T* tmr); void TMR_DisableHallSensor(TMR_T* tmr); + void TMR_SelectOutputTrigger(TMR_T* tmr, TMR_TRGO_SOURCE_T TRGOSource); void TMR_SelectSlaveMode(TMR_T* tmr, TMR_SLAVE_MODE_T slaveMode); void TMR_EnableMasterSlaveMode(TMR_T* tmr); @@ -644,6 +647,7 @@ void TMR_ConfigIC1Prescal(TMR_T* tmr, TMR_IC_PSC_T prescaler); void TMR_ConfigIC2Prescal(TMR_T* tmr, TMR_IC_PSC_T prescaler); void TMR_ConfigIC3Prescal(TMR_T* tmr, TMR_IC_PSC_T prescaler); void TMR_ConfigIC4Prescal(TMR_T* tmr, TMR_IC_PSC_T prescaler); + uint16_t TMR_ReadCaputer1(TMR_T* tmr); uint16_t TMR_ReadCaputer2(TMR_T* tmr); uint16_t TMR_ReadCaputer3(TMR_T* tmr); @@ -651,20 +655,20 @@ uint16_t TMR_ReadCaputer4(TMR_T* tmr); uint16_t TMR_ReadCounter(TMR_T* tmr); uint16_t TMR_ReadPrescaler(TMR_T* tmr); -/** Interrupts and Event */ +/* Interrupts and Event */ void TMR_EnableInterrupt(TMR_T* tmr, uint16_t interrupt); void TMR_DisableInterrupt(TMR_T* tmr, uint16_t interrupt); -void TMR_GenerateEvent(TMR_T* tmr,uint16_t eventSources); +void TMR_GenerateEvent(TMR_T* tmr, uint16_t eventSources); -/** flags */ +/* flags */ uint16_t TMR_ReadStatusFlag(TMR_T* tmr, TMR_FLAG_T flag); void TMR_ClearStatusFlag(TMR_T* tmr, uint16_t flag); uint16_t TMR_ReadIntFlag(TMR_T* tmr, TMR_INT_T flag); void TMR_ClearIntFlag(TMR_T* tmr, uint16_t flag); -/**@} end of group TMR_Fuctions*/ -/**@} end of group TMR_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group TMR_Functions */ +/**@} end of group TMR_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_usart.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_usart.h index d18418d839..7d4434320c 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_usart.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_usart.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the USART firmware library * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,16 +23,18 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_USART_H #define __APM32F10X_USART_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -40,12 +42,12 @@ @{ */ -/** @addtogroup USART_Enumerations Enumerations +/** @defgroup USART_Enumerations Enumerations @{ */ /** - * @brief USART Word Length define + * @brief USART Word Length definition */ typedef enum { @@ -54,7 +56,7 @@ typedef enum } USART_WORD_LEN_T; /** - * @brief USART Stop bits define + * @brief USART Stop bits definition */ typedef enum { @@ -65,7 +67,7 @@ typedef enum } USART_STOP_BIT_T; /** - * @brief USART Parity define + * @brief USART Parity definition */ typedef enum { @@ -75,7 +77,7 @@ typedef enum } USART_PARITY_T; /** - * @brief USART mode define + * @brief USART mode definition */ typedef enum { @@ -85,7 +87,7 @@ typedef enum } USART_MODE_T; /** - * @brief USART hardware flow control define + * @brief USART hardware flow control definition */ typedef enum { @@ -105,7 +107,7 @@ typedef enum } USART_CLKEN_T; /** - * @brief USART Clock polarity define + * @brief USART Clock polarity definition */ typedef enum { @@ -114,7 +116,7 @@ typedef enum } USART_CLKPOL_T; /** - * @brief USART Clock phase define + * @brief USART Clock phase definition */ typedef enum { @@ -123,7 +125,7 @@ typedef enum } USART_CLKPHA_T; /** - * @brief USART Last bit clock pulse enable + * @brief USART Last bit clock pulse definition */ typedef enum { @@ -187,7 +189,7 @@ typedef enum } USART_IRDALP_T; /** - * @brief USART flag define + * @brief USART flag definition */ typedef enum { @@ -203,43 +205,43 @@ typedef enum USART_FLAG_PE = 0x0001 } USART_FLAG_T; -/**@} end of group USART_Enumerations*/ +/**@} end of group USART_Enumerations */ -/** @addtogroup USART_Structure Data Structure +/** @defgroup USART_Structures Structures @{ */ /** - * @brief USART Config struct definition + * @brief USART Configure structure definition */ typedef struct { - uint32_t baudRate; //!< Specifies the baud rate - USART_WORD_LEN_T wordLength; //!< Specifies the word length - USART_STOP_BIT_T stopBits; //!< Specifies the stop bits - USART_PARITY_T parity; //!< Specifies the parity - USART_MODE_T mode; //!< Specifies the mode - USART_HARDWARE_FLOW_T hardwareFlow; //!< Specifies the hardware flow control + uint32_t baudRate; /*!< Specifies the baud rate */ + USART_WORD_LEN_T wordLength; /*!< Specifies the word length */ + USART_STOP_BIT_T stopBits; /*!< Specifies the stop bits */ + USART_PARITY_T parity; /*!< Specifies the parity */ + USART_MODE_T mode; /*!< Specifies the mode */ + USART_HARDWARE_FLOW_T hardwareFlow; /*!< Specifies the hardware flow control */ } USART_Config_T; /** - * @brief USART synchronous communication clock config struct definition + * @brief USART synchronous communication clock configure structure definition */ typedef struct { - USART_CLKEN_T clock; //!< Enable or Disable Clock - USART_CLKPOL_T polarity; //!< Specifies the clock polarity - USART_CLKPHA_T phase; //!< Specifies the clock phase - USART_LBCP_T lastBit; //!< Enable or Disable last bit clock + USART_CLKEN_T clock; /*!< Enable or Disable Clock */ + USART_CLKPOL_T polarity; /*!< Specifies the clock polarity */ + USART_CLKPHA_T phase; /*!< Specifies the clock phase */ + USART_LBCP_T lastBit; /*!< Enable or Disable last bit clock */ } USART_ClockConfig_T; -/**@} end of group USART_Structure*/ +/**@} end of group USART_Structures */ -/** @addtogroup USART_Fuctions Fuctions +/** @defgroup USART_Functions Functions @{ */ -/** USART Reset and Configuration */ +/* USART Reset and Configuration */ void USART_Reset(USART_T* usart); void USART_Config(USART_T* uart, USART_Config_T* usartConfig); void USART_ConfigStructInit(USART_Config_T* usartConfig); @@ -247,25 +249,25 @@ void USART_Address(USART_T* usart, uint8_t address); void USART_Enable(USART_T* usart); void USART_Disable(USART_T* usart); -/** Clock communication */ +/* Clock communication */ void USART_ConfigClock(USART_T* usart, USART_ClockConfig_T* clockConfig); void USART_ConfigClockStructInit(USART_ClockConfig_T* clockConfig); -/** DMA mode */ +/* DMA mode */ void USART_EnableDMA(USART_T* usart, USART_DMA_T dmaReq); void USART_DisableDMA(USART_T* usart, USART_DMA_T dmaReq); -/** Mute mode */ +/* Mute mode */ void USART_ConfigWakeUp(USART_T* usart, USART_WAKEUP_T wakeup); void USART_EnableMuteMode(USART_T* usart); void USART_DisableMuteMode(USART_T* usart); -/** LIN mode */ +/* LIN mode */ void USART_ConfigLINBreakDetectLength(USART_T* usart, USART_LBDL_T length); void USART_EnableLIN(USART_T* usart); void USART_DisableLIN(USART_T* usart); -/** Transmit and receive */ +/* Transmit and receive */ void USART_EnableTx(USART_T* usart); void USART_DisableTx(USART_T* usart); void USART_EnableRx(USART_T* usart); @@ -274,7 +276,7 @@ void USART_TxData(USART_T* usart, uint16_t data); uint16_t USART_RxData(USART_T* usart); void USART_TxBreak(USART_T* usart); -/** Smartcard mode */ +/* Smartcard mode */ void USART_ConfigGuardTime(USART_T* usart, uint8_t guardTime); void USART_ConfigPrescaler(USART_T* usart, uint8_t div); void USART_EnableSmartCard(USART_T* usart); @@ -282,16 +284,16 @@ void USART_DisableSmartCard(USART_T* usart); void USART_EnableSmartCardNACK(USART_T* usart); void USART_DisableSmartCardNACK(USART_T* usart); -/** Half-duplex mode */ +/* Half-duplex mode */ void USART_EnableHalfDuplex(USART_T* usart); void USART_DisableHalfDuplex(USART_T* usart); -/** IrDA mode */ +/* IrDA mode */ void USART_ConfigIrDA(USART_T* usart, USART_IRDALP_T IrDAMode); void USART_EnableIrDA(USART_T* usart); void USART_DisableIrDA(USART_T* usart); -/** Interrupt and flag */ +/* Interrupt and flag */ void USART_EnableInterrupt(USART_T* usart, USART_INT_T interrupt); void USART_DisableInterrupt(USART_T* usart, USART_INT_T interrupt); uint8_t USART_ReadStatusFlag(USART_T* usart, USART_FLAG_T flag); @@ -299,9 +301,9 @@ void USART_ClearStatusFlag(USART_T* usart, USART_FLAG_T flag); uint8_t USART_ReadIntFlag(USART_T* usart, USART_INT_T flag); void USART_ClearIntFlag(USART_T* usart, USART_INT_T flag); -/**@} end of group USART_Fuctions*/ -/**@} end of group USART_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group USART_Functions */ +/**@} end of group USART_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_wwdt.h b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_wwdt.h index 1acc761036..b30c098738 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_wwdt.h +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/inc/apm32f10x_wwdt.h @@ -3,9 +3,9 @@ * * @brief This file contains all the functions prototypes for the WWDT firmware library * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,29 +23,31 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_WWDT_H #define __APM32F10X_WWDT_H -#ifdef __cplusplus - extern "C" { -#endif - +/* Includes */ #include "apm32f10x.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ -/** @addtogroup WWDT_Driver WWDT Driver +/** @addtogroup WWDT_Driver WWDT Driver @{ */ -/** @addtogroup WWDT_Enumerations Enumerations +/** @defgroup WWDT_Enumerations Enumerations @{ */ /** - * @brief WWDT Timebase(Prescaler) define + * @brief WWDT Timebase(Prescaler) definition */ typedef enum { @@ -53,37 +55,37 @@ typedef enum WWDT_TIME_BASE_2 = 0x00000080, WWDT_TIME_BASE_4 = 0x00000100, WWDT_TIME_BASE_8 = 0x00000180 -}WWDT_TIME_BASE_T; +} WWDT_TIME_BASE_T; -/**@} end of group WWDT_Enumerations*/ +/**@} end of group WWDT_Enumerations */ -/** @addtogroup WWDT_Fuctions Fuctions +/** @defgroup WWDT_Functions Functions @{ */ -/** WWDT reset */ +/* WWDT reset */ void WWDT_Reset(void); -/** Config WWDT Timebase */ +/* Configure WWDT Timebase */ void WWDT_ConfigTimebase(WWDT_TIME_BASE_T timeBase); -/** Config Window Data */ +/* Configure Window Data */ void WWDT_ConfigWindowData(uint8_t windowData); -/** Config Couter */ +/* Configure Couter */ void WWDT_ConfigCounter(uint8_t counter); -/** Enable WWDT and Early Wakeup interrupt */ +/* Enable WWDT and Early Wakeup interrupt */ void WWDT_EnableEWI(void); void WWDT_Enable(uint8_t count); -/** Read Flag and Clear Flag */ +/* Read Flag and Clear Flag */ uint8_t WWDT_ReadFlag(void); void WWDT_ClearFlag(void); -/**@} end of group WWDT_Fuctions*/ -/**@} end of group WWDT_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group WWDT_Functions */ +/**@} end of group WWDT_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ #ifdef __cplusplus } diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_adc.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_adc.c index 0f7ef97b8b..36d591de55 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_adc.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_adc.c @@ -3,9 +3,9 @@ * * @brief This file provides all the ADC firmware functions * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,15 +26,16 @@ #include "apm32f10x_adc.h" #include "apm32f10x_rcm.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ /** @addtogroup ADC_Driver ADC Driver + * @brief ADC driver modules @{ */ -/** @addtogroup ADC_Fuctions Fuctions +/** @defgroup ADC_Functions Functions @{ */ @@ -47,7 +48,7 @@ * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_Reset(ADC_T *adc) +void ADC_Reset(ADC_T* adc) { if (adc == ADC1) { @@ -77,7 +78,7 @@ void ADC_Reset(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_Config(ADC_T *adc, ADC_Config_T *adcConfig) +void ADC_Config(ADC_T* adc, ADC_Config_T* adcConfig) { uint32_t reg; @@ -107,7 +108,7 @@ void ADC_Config(ADC_T *adc, ADC_Config_T *adcConfig) * * @retval None */ -void ADC_ConfigStructInit(ADC_Config_T *adcConfig) +void ADC_ConfigStructInit(ADC_Config_T* adcConfig) { adcConfig->mode = ADC_MODE_INDEPENDENT; adcConfig->scanConvMode = DISABLE; @@ -126,7 +127,7 @@ void ADC_ConfigStructInit(ADC_Config_T *adcConfig) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_Enable(ADC_T *adc) +void ADC_Enable(ADC_T* adc) { adc->CTRL2_B.ADCEN = BIT_SET; } @@ -140,7 +141,7 @@ void ADC_Enable(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_Disable(ADC_T *adc) +void ADC_Disable(ADC_T* adc) { adc->CTRL2_B.ADCEN = BIT_RESET; } @@ -154,7 +155,7 @@ void ADC_Disable(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_EnableDMA(ADC_T *adc) +void ADC_EnableDMA(ADC_T* adc) { adc->CTRL2_B.DMAEN = BIT_SET; } @@ -168,7 +169,7 @@ void ADC_EnableDMA(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_DisableDMA(ADC_T *adc) +void ADC_DisableDMA(ADC_T* adc) { adc->CTRL2_B.DMAEN = BIT_RESET; } @@ -182,7 +183,7 @@ void ADC_DisableDMA(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_ResetCalibration(ADC_T *adc) +void ADC_ResetCalibration(ADC_T* adc) { adc->CTRL2_B.CALRST = BIT_SET; } @@ -196,7 +197,7 @@ void ADC_ResetCalibration(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -uint8_t ADC_ReadResetCalibrationStatus(ADC_T *adc) +uint8_t ADC_ReadResetCalibrationStatus(ADC_T* adc) { uint8_t ret; ret = (adc->CTRL2_B.CALRST) ? BIT_SET : BIT_RESET; @@ -212,7 +213,7 @@ uint8_t ADC_ReadResetCalibrationStatus(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_StartCalibration(ADC_T *adc) +void ADC_StartCalibration(ADC_T* adc) { adc->CTRL2_B.CAL = BIT_SET; } @@ -226,7 +227,7 @@ void ADC_StartCalibration(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -uint8_t ADC_ReadCalibrationStartFlag(ADC_T *adc) +uint8_t ADC_ReadCalibrationStartFlag(ADC_T* adc) { uint8_t ret; ret = (adc->CTRL2_B.CAL) ? BIT_SET : BIT_RESET; @@ -242,7 +243,7 @@ uint8_t ADC_ReadCalibrationStartFlag(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_EnableSoftwareStartConv(ADC_T *adc) +void ADC_EnableSoftwareStartConv(ADC_T* adc) { adc->CTRL2 |= 0x00500000; } @@ -256,7 +257,7 @@ void ADC_EnableSoftwareStartConv(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_DisableSoftwareStartConv(ADC_T *adc) +void ADC_DisableSoftwareStartConv(ADC_T* adc) { adc->CTRL2 &= 0xFFAFFFFF; } @@ -270,7 +271,7 @@ void ADC_DisableSoftwareStartConv(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -uint8_t ADC_ReadSoftwareStartConvStatus(ADC_T *adc) +uint8_t ADC_ReadSoftwareStartConvStatus(ADC_T* adc) { uint8_t ret; ret = (adc->CTRL2_B.REGSWSC) ? BIT_SET : BIT_RESET; @@ -289,7 +290,7 @@ uint8_t ADC_ReadSoftwareStartConvStatus(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_ConfigDiscMode(ADC_T *adc, uint8_t number) +void ADC_ConfigDiscMode(ADC_T* adc, uint8_t number) { adc->CTRL1_B.DISCNUMCFG |= number - 1; } @@ -303,7 +304,7 @@ void ADC_ConfigDiscMode(ADC_T *adc, uint8_t number) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_EnableDiscMode(ADC_T *adc) +void ADC_EnableDiscMode(ADC_T* adc) { adc->CTRL1_B.REGDISCEN = BIT_SET; } @@ -317,7 +318,7 @@ void ADC_EnableDiscMode(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_DisableDiscMode(ADC_T *adc) +void ADC_DisableDiscMode(ADC_T* adc) { adc->CTRL1_B.REGDISCEN = BIT_RESET; } @@ -366,7 +367,7 @@ void ADC_DisableDiscMode(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_ConfigRegularChannel(ADC_T *adc, uint8_t channel, uint8_t rank, uint8_t sampleTime) +void ADC_ConfigRegularChannel(ADC_T* adc, uint8_t channel, uint8_t rank, uint8_t sampleTime) { uint32_t temp1 = 0; uint32_t temp2 = 0; @@ -427,7 +428,7 @@ void ADC_ConfigRegularChannel(ADC_T *adc, uint8_t channel, uint8_t rank, uint8_t * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_EnableExternalTrigConv(ADC_T *adc) +void ADC_EnableExternalTrigConv(ADC_T* adc) { adc->CTRL2_B.REGEXTTRGEN = BIT_SET; } @@ -441,7 +442,7 @@ void ADC_EnableExternalTrigConv(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_DisableExternalTrigConv(ADC_T *adc) +void ADC_DisableExternalTrigConv(ADC_T* adc) { adc->CTRL2_B.REGEXTTRGEN = BIT_RESET; } @@ -455,7 +456,7 @@ void ADC_DisableExternalTrigConv(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -uint16_t ADC_ReadConversionValue(ADC_T *adc) +uint16_t ADC_ReadConversionValue(ADC_T* adc) { return (uint16_t) adc->REGDATA; } @@ -469,9 +470,9 @@ uint16_t ADC_ReadConversionValue(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -uint32_t ADC_ReadDualModeConversionValue(ADC_T *adc) +uint32_t ADC_ReadDualModeConversionValue(ADC_T* adc) { - return (*(__IOM uint32_t *) RDG_ADDRESS); + return (*(__IOM uint32_t*) RDG_ADDRESS); } /*! @@ -483,7 +484,7 @@ uint32_t ADC_ReadDualModeConversionValue(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_EnableAutoInjectedConv(ADC_T *adc) +void ADC_EnableAutoInjectedConv(ADC_T* adc) { adc->CTRL1_B.INJGACEN = BIT_SET; } @@ -497,7 +498,7 @@ void ADC_EnableAutoInjectedConv(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_DisableAutoInjectedConv(ADC_T *adc) +void ADC_DisableAutoInjectedConv(ADC_T* adc) { adc->CTRL1_B.INJGACEN = BIT_RESET; } @@ -511,7 +512,7 @@ void ADC_DisableAutoInjectedConv(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_EnableInjectedDiscMode(ADC_T *adc) +void ADC_EnableInjectedDiscMode(ADC_T* adc) { adc->CTRL1_B.INJDISCEN = BIT_SET; } @@ -525,7 +526,7 @@ void ADC_EnableInjectedDiscMode(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_DisableInjectedDiscMode(ADC_T *adc) +void ADC_DisableInjectedDiscMode(ADC_T* adc) { adc->CTRL1_B.INJDISCEN = BIT_RESET; } @@ -558,7 +559,7 @@ void ADC_DisableInjectedDiscMode(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_ConfigExternalTrigInjectedConv(ADC_T *adc, ADC_EXT_TRIG_INJEC_CONV_T extTrigInjecConv) +void ADC_ConfigExternalTrigInjectedConv(ADC_T* adc, ADC_EXT_TRIG_INJEC_CONV_T extTrigInjecConv) { adc->CTRL2_B.INJGEXTTRGSEL = RESET; adc->CTRL2_B.INJGEXTTRGSEL |= extTrigInjecConv; @@ -573,7 +574,7 @@ void ADC_ConfigExternalTrigInjectedConv(ADC_T *adc, ADC_EXT_TRIG_INJEC_CONV_T ex * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_EnableExternalTrigInjectedConv(ADC_T *adc) +void ADC_EnableExternalTrigInjectedConv(ADC_T* adc) { adc->CTRL2_B.INJEXTTRGEN = BIT_SET; } @@ -587,7 +588,7 @@ void ADC_EnableExternalTrigInjectedConv(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_DisableExternalTrigInjectedConv(ADC_T *adc) +void ADC_DisableExternalTrigInjectedConv(ADC_T* adc) { adc->CTRL2_B.INJEXTTRGEN = BIT_RESET; } @@ -601,7 +602,7 @@ void ADC_DisableExternalTrigInjectedConv(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_EnableSoftwareStartInjectedConv(ADC_T *adc) +void ADC_EnableSoftwareStartInjectedConv(ADC_T* adc) { adc->CTRL2_B.INJEXTTRGEN = BIT_SET; adc->CTRL2_B.INJSWSC = BIT_SET; @@ -616,7 +617,7 @@ void ADC_EnableSoftwareStartInjectedConv(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_DisableSoftwareStartInjectedConv(ADC_T *adc) +void ADC_DisableSoftwareStartInjectedConv(ADC_T* adc) { adc->CTRL2_B.INJEXTTRGEN = BIT_RESET; adc->CTRL2_B.INJSWSC = BIT_RESET; @@ -631,7 +632,7 @@ void ADC_DisableSoftwareStartInjectedConv(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -uint8_t ADC_ReadSoftwareStartInjectedConvStatus(ADC_T *adc) +uint8_t ADC_ReadSoftwareStartInjectedConvStatus(ADC_T* adc) { uint8_t ret; ret = (adc->CTRL2_B.INJSWSC) ? BIT_SET : BIT_RESET; @@ -682,7 +683,7 @@ uint8_t ADC_ReadSoftwareStartInjectedConvStatus(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_ConfigInjectedChannel(ADC_T *adc, uint8_t channel, uint8_t rank, uint8_t sampleTime) +void ADC_ConfigInjectedChannel(ADC_T* adc, uint8_t channel, uint8_t rank, uint8_t sampleTime) { uint32_t temp1 = 0; uint32_t temp2 = 0; @@ -726,7 +727,7 @@ void ADC_ConfigInjectedChannel(ADC_T *adc, uint8_t channel, uint8_t rank, uint8_ * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_ConfigInjectedSequencerLength(ADC_T *adc, uint8_t length) +void ADC_ConfigInjectedSequencerLength(ADC_T* adc, uint8_t length) { adc->INJSEQ_B.INJSEQLEN = RESET; adc->INJSEQ_B.INJSEQLEN |= length - 1; @@ -751,14 +752,14 @@ void ADC_ConfigInjectedSequencerLength(ADC_T *adc, uint8_t length) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_ConfigInjectedOffset(ADC_T *adc, ADC_INJEC_CHANNEL_T channel, uint16_t offSet) +void ADC_ConfigInjectedOffset(ADC_T* adc, ADC_INJEC_CHANNEL_T channel, uint16_t offSet) { __IOM uint32_t tmp = 0; tmp = (uint32_t)adc; tmp += channel; - *(__IOM uint32_t *) tmp = (uint32_t)offSet; + *(__IOM uint32_t*) tmp = (uint32_t)offSet; } /*! @@ -777,14 +778,14 @@ void ADC_ConfigInjectedOffset(ADC_T *adc, ADC_INJEC_CHANNEL_T channel, uint16_t * * @note adc can be ADC1, ADC2 or ADC3. */ -uint16_t ADC_ReadInjectedConversionValue(ADC_T *adc, ADC_INJEC_CHANNEL_T channel) +uint16_t ADC_ReadInjectedConversionValue(ADC_T* adc, ADC_INJEC_CHANNEL_T channel) { __IOM uint32_t temp = 0; temp = (uint32_t)adc; temp += channel + INJDATA_OFFSET; - return (uint16_t)(*(__IOM uint32_t *) temp); + return (uint16_t)(*(__IOM uint32_t*) temp); } /*! @@ -806,7 +807,7 @@ uint16_t ADC_ReadInjectedConversionValue(ADC_T *adc, ADC_INJEC_CHANNEL_T channel * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_EnableAnalogWatchdog(ADC_T *adc, uint32_t analogWatchdog) +void ADC_EnableAnalogWatchdog(ADC_T* adc, uint32_t analogWatchdog) { adc->CTRL1 &= 0xFF3FFDFF; adc->CTRL1 |= analogWatchdog; @@ -821,7 +822,7 @@ void ADC_EnableAnalogWatchdog(ADC_T *adc, uint32_t analogWatchdog) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_DisableAnalogWatchdog(ADC_T *adc) +void ADC_DisableAnalogWatchdog(ADC_T* adc) { adc->CTRL1 &= 0xFF3FFDFF; } @@ -841,7 +842,7 @@ void ADC_DisableAnalogWatchdog(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_ConfigAnalogWatchdogThresholds(ADC_T *adc, uint16_t highThreshold, uint16_t lowThreshold) +void ADC_ConfigAnalogWatchdogThresholds(ADC_T* adc, uint16_t highThreshold, uint16_t lowThreshold) { adc->AWDHT = highThreshold; adc->AWDLT = lowThreshold; @@ -877,7 +878,7 @@ void ADC_ConfigAnalogWatchdogThresholds(ADC_T *adc, uint16_t highThreshold, uint * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_ConfigAnalogWatchdogSingleChannel(ADC_T *adc, uint8_t channel) +void ADC_ConfigAnalogWatchdogSingleChannel(ADC_T* adc, uint8_t channel) { adc->CTRL1_B.AWDCHSEL = BIT_RESET; adc->CTRL1 |= channel; @@ -892,7 +893,7 @@ void ADC_ConfigAnalogWatchdogSingleChannel(ADC_T *adc, uint8_t channel) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_EnableTempSensorVrefint(ADC_T *adc) +void ADC_EnableTempSensorVrefint(ADC_T* adc) { adc->CTRL2_B.TSVREFEN = BIT_SET; } @@ -906,7 +907,7 @@ void ADC_EnableTempSensorVrefint(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_DisableTempSensorVrefint(ADC_T *adc) +void ADC_DisableTempSensorVrefint(ADC_T* adc) { adc->CTRL2_B.TSVREFEN = BIT_RESET; } @@ -926,7 +927,7 @@ void ADC_DisableTempSensorVrefint(ADC_T *adc) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_EnableInterrupt(ADC_T *adc, uint16_t interrupt) +void ADC_EnableInterrupt(ADC_T* adc, uint16_t interrupt) { uint8_t mask; @@ -949,7 +950,7 @@ void ADC_EnableInterrupt(ADC_T *adc, uint16_t interrupt) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_DisableInterrupt(ADC_T *adc, uint16_t interrupt) +void ADC_DisableInterrupt(ADC_T* adc, uint16_t interrupt) { uint8_t mask; @@ -974,7 +975,7 @@ void ADC_DisableInterrupt(ADC_T *adc, uint16_t interrupt) * * @note adc can be ADC1, ADC2 or ADC3. */ -uint8_t ADC_ReadStatusFlag(ADC_T *adc, ADC_FLAG_T flag) +uint8_t ADC_ReadStatusFlag(ADC_T* adc, ADC_FLAG_T flag) { return (adc->STS & flag) ? SET : RESET; } @@ -996,7 +997,7 @@ uint8_t ADC_ReadStatusFlag(ADC_T *adc, ADC_FLAG_T flag) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_ClearStatusFlag(ADC_T *adc, uint8_t flag) +void ADC_ClearStatusFlag(ADC_T* adc, uint8_t flag) { adc->STS = ~(uint32_t)flag; } @@ -1016,7 +1017,7 @@ void ADC_ClearStatusFlag(ADC_T *adc, uint8_t flag) * * @note adc can be ADC1, ADC2 or ADC3. */ -uint8_t ADC_ReadIntFlag(ADC_T *adc, ADC_INT_T flag) +uint8_t ADC_ReadIntFlag(ADC_T* adc, ADC_INT_T flag) { uint8_t bitStatus = RESET; uint32_t itmask = 0; @@ -1051,7 +1052,7 @@ uint8_t ADC_ReadIntFlag(ADC_T *adc, ADC_INT_T flag) * * @note adc can be ADC1, ADC2 or ADC3. */ -void ADC_ClearIntFlag(ADC_T *adc, uint16_t flag) +void ADC_ClearIntFlag(ADC_T* adc, uint16_t flag) { uint8_t mask = 0; @@ -1059,6 +1060,6 @@ void ADC_ClearIntFlag(ADC_T *adc, uint16_t flag) adc->STS = ~(uint32_t)mask; } -/**@} end of group ADC_Fuctions*/ -/**@} end of group ADC_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group ADC_Functions */ +/**@} end of group ADC_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_bakpr.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_bakpr.c index d5c19a0e08..627eb37525 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_bakpr.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_bakpr.c @@ -3,9 +3,9 @@ * * @brief This file provides all the BAKPR firmware functions. * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,15 +26,16 @@ #include "apm32f10x_bakpr.h" #include "apm32f10x_rcm.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ -/** @addtogroup BAKPR_Driver ADC Driver +/** @addtogroup BAKPR_Driver BAKPR Driver + * @brief BAKPR driver modules @{ */ -/** @addtogroup BAKPR_Fuctions Fuctions +/** @defgroup BAKPR_Functions Functions @{ */ @@ -177,7 +178,7 @@ void BAKPR_ConfigBackupRegister(BAKPR_DATA_T bakrData, uint16_t data) tmp = (uint32_t)BAKPR_BASE; tmp += bakrData; - *(__IOM uint32_t *) tmp = data; + *(__IOM uint32_t*) tmp = data; } /*! @@ -195,7 +196,7 @@ uint16_t BAKPR_ReadBackupRegister(BAKPR_DATA_T bakrData) tmp = (uint32_t)BAKPR_BASE; tmp += bakrData; - return (*(__IOM uint32_t *) tmp); + return (*(__IOM uint32_t*) tmp); } /*! @@ -246,6 +247,6 @@ void BAKPR_ClearIntFlag(void) BAKPR->CSTS_B.TICLR = BIT_SET; } -/**@} end of group BAKPR_Fuctions*/ +/**@} end of group BAKPR_Functions*/ /**@} end of group BAKPR_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group APM32F10x_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_can.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_can.c index ed0ef63b81..2573ef328f 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_can.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_can.c @@ -3,9 +3,9 @@ * * @brief This file provides all the CAN firmware functions * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,15 +26,16 @@ #include "apm32f10x_can.h" #include "apm32f10x_rcm.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ /** @addtogroup CAN_Driver CAN Driver + * @brief CAN driver modules @{ */ -/** @addtogroup CAN_Fuctions Fuctions +/** @defgroup CAN_Functions Functions @{ */ @@ -47,7 +48,7 @@ * * @note CAN2 applies only to APM32F103xC device. */ -void CAN_Reset(CAN_T *can) +void CAN_Reset(CAN_T* can) { if (can == CAN1) { @@ -72,22 +73,22 @@ void CAN_Reset(CAN_T *can) * * @note CAN2 applies only to APM32F103xC device. */ -uint8_t CAN_Config(CAN_T *can, CAN_Config_T *canConfig) +uint8_t CAN_Config(CAN_T* can, CAN_Config_T* canConfig) { uint8_t initStatus = ERROR; uint32_t wait_ack = 0x00000000; - /** Exit from sleep mode */ + /* Exit from sleep mode */ can->MCTRL_B.SLEEPREQ = BIT_RESET; - /** Request initialisation */ + /* Request initialisation */ can->MCTRL_B.INITREQ = BIT_SET; - /** Wait the acknowledge */ + /* Wait the acknowledge */ while (((can->MSTS_B.INITFLG) != BIT_SET) && (wait_ack != 0x0000FFFF)) { wait_ack++; } - /** Check acknowledge */ + /* Check acknowledge */ if (((can->MSTS_B.INITFLG) != BIT_SET)) { initStatus = ERROR; @@ -139,7 +140,7 @@ uint8_t CAN_Config(CAN_T *can, CAN_Config_T *canConfig) can->MCTRL_B.TXFPCFG = BIT_RESET; } - /** Set the bit timing register */ + /* Set the bit timing register */ can->BITTIM &= (uint32_t)0x3fffffff; can->BITTIM |= (uint32_t)canConfig->mode << 30; can->BITTIM_B.RSYNJW = canConfig->syncJumpWidth; @@ -147,16 +148,16 @@ uint8_t CAN_Config(CAN_T *can, CAN_Config_T *canConfig) can->BITTIM_B.TIMSEG2 = canConfig->timeSegment2; can->BITTIM_B.BRPSC = canConfig->prescaler - 1; - /** Request leave initialisation */ + /* Request leave initialisation */ can->MCTRL_B.INITREQ = BIT_RESET; wait_ack = 0; - /** Wait the acknowledge */ + /* Wait the acknowledge */ while (((can->MSTS_B.INITFLG) != BIT_RESET) && (wait_ack != 0x0000FFFF)) { wait_ack++; } - /** Check acknowledge */ + /* Check acknowledge */ if (((can->MSTS_B.INITFLG) != BIT_RESET)) { initStatus = ERROR; @@ -169,6 +170,92 @@ uint8_t CAN_Config(CAN_T *can, CAN_Config_T *canConfig) return initStatus; } +#if defined(APM32F10X_CL) +/*! + * @brief Congig the CAN peripheral according to the specified parameters in the filterConfig. + * + * @param filterConfig :Point to a CAN_FilterConfig_T structure. + * + * @retval None + * + * @note This function is for CAN1 and CAN2. + */ +void CAN_ConfigFilter(CAN_FilterConfig_T* filterConfig) +{ + CAN1->FCTRL_B.FINITEN = BIT_SET; + + CAN1->FACT &= ~(1 << filterConfig->filterNumber); + + /* Filter Scale */ + if (filterConfig->filterScale == CAN_FILTER_SCALE_16BIT) + { + /* 16-bit scale for the filter */ + CAN1->FSCFG &= ~(1 << filterConfig->filterNumber); + + CAN1->sFilterRegister[filterConfig->filterNumber].FBANK1 = + ((0x0000FFFF & filterConfig->filterMaskIdLow) << 16) | + (0x0000FFFF & filterConfig->filterIdLow); + + CAN1->sFilterRegister[filterConfig->filterNumber].FBANK2 = + ((0x0000FFFF & filterConfig->filterMaskIdHigh) << 16) | + (0x0000FFFF & filterConfig->filterIdHigh); + } + + if (filterConfig->filterScale == CAN_FILTER_SCALE_32BIT) + { + CAN1->FSCFG |= (1 << filterConfig->filterNumber); + + CAN1->sFilterRegister[filterConfig->filterNumber].FBANK1 = + ((0x0000FFFF & filterConfig->filterIdHigh) << 16) | + (0x0000FFFF & filterConfig->filterIdLow); + + CAN1->sFilterRegister[filterConfig->filterNumber].FBANK2 = + ((0x0000FFFF & filterConfig->filterMaskIdHigh) << 16) | + (0x0000FFFF & filterConfig->filterMaskIdLow); + } + + /* Filter Mode */ + if (filterConfig->filterMode == CAN_FILTER_MODE_IDMASK) + { + CAN1->FMCFG &= ~(1 << filterConfig->filterNumber); + } + else + { + CAN1->FMCFG |= (1 << filterConfig->filterNumber); + } + + /* Filter FIFO assignment */ + if (filterConfig->filterFIFO == CAN_FILTER_FIFO_0) + { + CAN1->FFASS &= ~(1 << filterConfig->filterNumber); + } + if (filterConfig->filterFIFO == CAN_FILTER_FIFO_1) + { + CAN1->FFASS |= (1 << filterConfig->filterNumber); + } + + /* Filter activation */ + if (filterConfig->filterActivation == ENABLE) + { + CAN1->FACT |= (1 << filterConfig->filterNumber); + } + CAN1->FCTRL_B.FINITEN = BIT_RESET; +} + +/*! + * @brief Select the start bank filter for slave CAN. + * + * @param bankNum: the start slave bank filter from 1..27. + * + * @retval None + */ +void CAN_SlaveStartBank(uint8_t bankNum) +{ + CAN1->FCTRL_B.FINITEN = SET; + CAN1->FCTRL_B.CAN2BN = bankNum; + CAN1->FCTRL_B.FINITEN = RESET; +} +#else /*! * @brief Congig the CAN peripheral according to the specified parameters in the filterConfig. * @@ -180,16 +267,16 @@ uint8_t CAN_Config(CAN_T *can, CAN_Config_T *canConfig) * * @note CAN2 applies only to APM32F103xC device. */ -void CAN_ConfigFilter(CAN_T *can, CAN_FilterConfig_T *filterConfig) +void CAN_ConfigFilter(CAN_T* can, CAN_FilterConfig_T* filterConfig) { can->FCTRL_B.FINITEN = BIT_SET; can->FACT &= ~(1 << filterConfig->filterNumber); - /** Filter Scale */ + /* Filter Scale */ if (filterConfig->filterScale == CAN_FILTER_SCALE_16BIT) { - /** 16-bit scale for the filter */ + /* 16-bit scale for the filter */ can->FSCFG &= ~(1 << filterConfig->filterNumber); can->sFilterRegister[filterConfig->filterNumber].FBANK1 = @@ -214,7 +301,7 @@ void CAN_ConfigFilter(CAN_T *can, CAN_FilterConfig_T *filterConfig) (0x0000FFFF & filterConfig->filterMaskIdLow); } - /** Filter Mode */ + /* Filter Mode */ if (filterConfig->filterMode == CAN_FILTER_MODE_IDMASK) { can->FMCFG &= ~(1 << filterConfig->filterNumber); @@ -224,7 +311,7 @@ void CAN_ConfigFilter(CAN_T *can, CAN_FilterConfig_T *filterConfig) can->FMCFG |= (1 << filterConfig->filterNumber); } - /** Filter FIFO assignment */ + /* Filter FIFO assignment */ if (filterConfig->filterFIFO == CAN_FILTER_FIFO_0) { can->FFASS &= ~(1 << filterConfig->filterNumber); @@ -234,13 +321,14 @@ void CAN_ConfigFilter(CAN_T *can, CAN_FilterConfig_T *filterConfig) can->FFASS |= (1 << filterConfig->filterNumber); } - /** Filter activation */ + /* Filter activation */ if (filterConfig->filterActivation == ENABLE) { can->FACT |= (1 << filterConfig->filterNumber); } can->FCTRL_B.FINITEN = BIT_RESET; } +#endif /*! * @brief Initialize a CAN_Config_T structure with the initial value. @@ -251,7 +339,7 @@ void CAN_ConfigFilter(CAN_T *can, CAN_FilterConfig_T *filterConfig) * * @note CAN2 applies only to APM32F103xC device. */ -void CAN_ConfigStructInit(CAN_Config_T *canConfig) +void CAN_ConfigStructInit(CAN_Config_T* canConfig) { canConfig->autoBusOffManage = DISABLE; canConfig->autoWakeUpMode = DISABLE; @@ -274,7 +362,7 @@ void CAN_ConfigStructInit(CAN_Config_T *canConfig) * * @note CAN2 applies only to APM32F103xC device. */ -void CAN_EnableDBGFreeze(CAN_T *can) +void CAN_EnableDBGFreeze(CAN_T* can) { can->MCTRL_B.DBGFRZE = ENABLE; } @@ -288,25 +376,11 @@ void CAN_EnableDBGFreeze(CAN_T *can) * * @note CAN2 applies only to APM32F103xC device. */ -void CAN_DisableDBGFreeze(CAN_T *can) +void CAN_DisableDBGFreeze(CAN_T* can) { can->MCTRL_B.DBGFRZE = DISABLE; } -/*! - * @brief Select the start bank filter for slave CAN. - * - * @param bankNum: the start slave bank filter from 1..27. - * - * @retval None - */ -void CAN_SlaveStartBank(CAN_T *can, uint8_t bankNum) -{ - can->FCTRL_B.FINITEN = SET; - can->FCTRL_B.CAN2BN = bankNum; - can->FCTRL_B.FINITEN = RESET; -} - /*! * @brief Initiates the transmission of a message. * @@ -318,11 +392,11 @@ void CAN_SlaveStartBank(CAN_T *can, uint8_t bankNum) * * @note CAN2 applies only to APM32F103xC device. */ -uint8_t CAN_TxMessage(CAN_T *can, CAN_TxMessage_T *TxMessage) +uint8_t CAN_TxMessage(CAN_T* can, CAN_TxMessage_T* TxMessage) { uint8_t transmit_milbox = 0; - /** Select one empty transmit mailbox */ + /* Select one empty transmit mailbox */ if ((can->TXSTS & 0x04000000) == 0x04000000) { transmit_milbox = 0; @@ -340,7 +414,7 @@ uint8_t CAN_TxMessage(CAN_T *can, CAN_TxMessage_T *TxMessage) return 3; //!< No mailbox is empty } - /** Set up the Id */ + /* Set up the Id */ can->sTxMailBox[transmit_milbox].TXMID &= 0x00000001; if (TxMessage->typeID == CAN_TYPEID_STD) { @@ -351,17 +425,17 @@ uint8_t CAN_TxMessage(CAN_T *can, CAN_TxMessage_T *TxMessage) can->sTxMailBox[transmit_milbox].TXMID |= (TxMessage->extID << 3) | (TxMessage->typeID) | (TxMessage->remoteTxReq); } - /** Set up the TXDLEN */ + /* Set up the TXDLEN */ TxMessage->dataLengthCode &= 0x0F; can->sTxMailBox[transmit_milbox].TXDLEN &= (uint32_t)0xFFFFFFF0; can->sTxMailBox[transmit_milbox].TXDLEN |= TxMessage->dataLengthCode; - /** Set up the data field */ + /* Set up the data field */ can->sTxMailBox[transmit_milbox].TXMDL = ((uint32_t)TxMessage->data[3] << 24) | ((uint32_t)TxMessage->data[2] << 16) | ((uint32_t)TxMessage->data[1] << 8) | ((uint32_t)TxMessage->data[0]); can->sTxMailBox[transmit_milbox].TXMDH = ((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 */ + /* Request transmission */ can->sTxMailBox[transmit_milbox].TXMID |= 0x00000001; return transmit_milbox; @@ -380,54 +454,54 @@ uint8_t CAN_TxMessage(CAN_T *can, CAN_TxMessage_T *TxMessage) * * @note CAN2 applies only to APM32F103xC device. */ -uint8_t CAN_TxMessageStatus(CAN_T *can, CAN_TX_MAILBIX_T TxMailbox) +uint8_t CAN_TxMessageStatus(CAN_T* can, CAN_TX_MAILBIX_T TxMailbox) { uint32_t state = 0; switch (TxMailbox) { - case (CAN_TX_MAILBIX_0): - state = can->TXSTS & (0x00000001 | 0x00000002 | 0x04000000); - break; - case (CAN_TX_MAILBIX_1): - state = can->TXSTS & (0x00000100 | 0x00000200 | 0x08000000); - break; - case (CAN_TX_MAILBIX_2): - state = can->TXSTS & (0x00010000 | 0x00020000 | 0x10000000); - break; - default: - state = 0; - break; + case (CAN_TX_MAILBIX_0): + state = can->TXSTS & (0x00000001 | 0x00000002 | 0x04000000); + break; + case (CAN_TX_MAILBIX_1): + state = can->TXSTS & (0x00000100 | 0x00000200 | 0x08000000); + break; + case (CAN_TX_MAILBIX_2): + state = can->TXSTS & (0x00010000 | 0x00020000 | 0x10000000); + break; + default: + state = 0; + break; } switch (state) { - /** Transmit pending */ - case (0x0): - state = 2; - break; - /** Transmit failed */ - case (0x00000001 | 0x04000000): - state = 0; - break; - case (0x00000100 | 0x08000000): - state = 0; - break; - case (0x00010000 | 0x10000000): - state = 0; - break; - /** Transmit succeeded */ - case (0x00000001 | 0x00000002 | 0x04000000): - state = 1; - break; - case (0x00000100 | 0x00000200 | 0x08000000): - state = 1; - break; - case (0x00010000 | 0x00020000 | 0x10000000): - state = 1; - break; - default: - state = 0; - break; + /* Transmit pending */ + case (0x0): + state = 2; + break; + /* Transmit failed */ + case (0x00000001 | 0x04000000): + state = 0; + break; + case (0x00000100 | 0x08000000): + state = 0; + break; + case (0x00010000 | 0x10000000): + state = 0; + break; + /* Transmit succeeded */ + case (0x00000001 | 0x00000002 | 0x04000000): + state = 1; + break; + case (0x00000100 | 0x00000200 | 0x08000000): + state = 1; + break; + case (0x00010000 | 0x00020000 | 0x10000000): + state = 1; + break; + default: + state = 0; + break; } return (uint8_t) state; } @@ -447,21 +521,21 @@ uint8_t CAN_TxMessageStatus(CAN_T *can, CAN_TX_MAILBIX_T TxMailbox) * * @note CAN2 applies only to APM32F103xC device. */ -void CAN_CancelTxMailbox(CAN_T *can, CAN_TX_MAILBIX_T TxMailbox) +void CAN_CancelTxMailbox(CAN_T* can, CAN_TX_MAILBIX_T TxMailbox) { switch (TxMailbox) { - case CAN_TX_MAILBIX_0: - can->TXSTS_B.ABREQFLG0 = BIT_SET; - break; - case CAN_TX_MAILBIX_1: - can->TXSTS_B.ABREQFLG1 = BIT_SET; - break; - case CAN_TX_MAILBIX_2: - can->TXSTS_B.ABREQFLG2 = BIT_SET; - break; - default: - break; + case CAN_TX_MAILBIX_0: + can->TXSTS_B.ABREQFLG0 = BIT_SET; + break; + case CAN_TX_MAILBIX_1: + can->TXSTS_B.ABREQFLG1 = BIT_SET; + break; + case CAN_TX_MAILBIX_2: + can->TXSTS_B.ABREQFLG2 = BIT_SET; + break; + default: + break; } } @@ -481,9 +555,9 @@ void CAN_CancelTxMailbox(CAN_T *can, CAN_TX_MAILBIX_T TxMailbox) * * @note CAN2 applies only to APM32F103xC device. */ -void CAN_RxMessage(CAN_T *can, CAN_RX_FIFO_T FIFONumber, CAN_RxMessage_T *RxMessage) +void CAN_RxMessage(CAN_T* can, CAN_RX_FIFO_T FIFONumber, CAN_RxMessage_T* RxMessage) { - /** Get the Id */ + /* Get the Id */ RxMessage->typeID = ((uint8_t)0x04 & (can->sRxMailBox[FIFONumber].RXMID)); if (RxMessage->typeID == CAN_TYPEID_STD) { @@ -497,7 +571,7 @@ void CAN_RxMessage(CAN_T *can, CAN_RX_FIFO_T FIFONumber, CAN_RxMessage_T *RxMess RxMessage->remoteTxReq = can->sRxMailBox[FIFONumber].RXMID_B.RFTXREQ; RxMessage->dataLengthCode = can->sRxMailBox[FIFONumber].RXDLEN_B.DLCODE; RxMessage->filterMatchIndex = can->sRxMailBox[FIFONumber].RXDLEN_B.FMIDX; - /** Get the data field */ + /* Get the data field */ RxMessage->data[0] = can->sRxMailBox[FIFONumber].RXMDL_B.DATABYTE0; RxMessage->data[1] = can->sRxMailBox[FIFONumber].RXMDL_B.DATABYTE1; RxMessage->data[2] = can->sRxMailBox[FIFONumber].RXMDL_B.DATABYTE2; @@ -531,7 +605,7 @@ void CAN_RxMessage(CAN_T *can, CAN_RX_FIFO_T FIFONumber, CAN_RxMessage_T *RxMess * * @note CAN2 applies only to APM32F103xC device. */ -void CAN_ReleaseFIFO(CAN_T *can, CAN_RX_FIFO_T FIFONumber) +void CAN_ReleaseFIFO(CAN_T* can, CAN_RX_FIFO_T FIFONumber) { if (FIFONumber == CAN_RX_FIFO_0) { @@ -557,7 +631,7 @@ void CAN_ReleaseFIFO(CAN_T *can, CAN_RX_FIFO_T FIFONumber) * * @note CAN2 applies only to APM32F103xC device. */ -uint8_t CAN_PendingMessage(CAN_T *can, CAN_RX_FIFO_T FIFONumber) +uint8_t CAN_PendingMessage(CAN_T* can, CAN_RX_FIFO_T FIFONumber) { if (FIFONumber == CAN_RX_FIFO_0) { @@ -586,7 +660,7 @@ uint8_t CAN_PendingMessage(CAN_T *can, CAN_RX_FIFO_T FIFONumber) * * @note CAN2 applies only to APM32F103xC device. */ -uint8_t CAN_OperatingMode(CAN_T *can, CAN_OPERATING_MODE_T operatingMode) +uint8_t CAN_OperatingMode(CAN_T* can, CAN_OPERATING_MODE_T operatingMode) { uint8_t states = 0; uint32_t time_out = 0x0000FFFF; @@ -651,7 +725,7 @@ uint8_t CAN_OperatingMode(CAN_T *can, CAN_OPERATING_MODE_T operatingMode) * * @note CAN2 applies only to APM32F103xC device. */ -uint8_t CAN_SleepMode(CAN_T *can) +uint8_t CAN_SleepMode(CAN_T* can) { can->MCTRL_B.SLEEPREQ = BIT_SET; can->MCTRL_B.INITREQ = BIT_RESET; @@ -674,7 +748,7 @@ uint8_t CAN_SleepMode(CAN_T *can) * * @note CAN2 applies only to APM32F103xC device. */ -uint8_t CAN_WakeUpMode(CAN_T *can) +uint8_t CAN_WakeUpMode(CAN_T* can) { uint32_t time_out = 0x0000FFFF; @@ -699,7 +773,7 @@ uint8_t CAN_WakeUpMode(CAN_T *can) * * @note CAN2 applies only to APM32F103xC device. */ -uint8_t CAN_ReadLastErrorCode(CAN_T *can) +uint8_t CAN_ReadLastErrorCode(CAN_T* can) { return can->ERRSTS_B.LERRC; } @@ -713,7 +787,7 @@ uint8_t CAN_ReadLastErrorCode(CAN_T *can) * * @note CAN2 applies only to APM32F103xC device. */ -uint8_t CAN_ReadRxErrorCounter(CAN_T *can) +uint8_t CAN_ReadRxErrorCounter(CAN_T* can) { return can->ERRSTS_B.RXERRCNT; } @@ -727,7 +801,7 @@ uint8_t CAN_ReadRxErrorCounter(CAN_T *can) * * @note CAN2 applies only to APM32F103xC device. */ -uint8_t CAN_ReadLSBTxErrorCounter(CAN_T *can) +uint8_t CAN_ReadLSBTxErrorCounter(CAN_T* can) { return can->ERRSTS_B.TXERRCNT; } @@ -758,7 +832,7 @@ uint8_t CAN_ReadLSBTxErrorCounter(CAN_T *can) * * @note CAN2 applies only to APM32F103xC device. */ -void CAN_EnableInterrupt(CAN_T *can, uint32_t interrupts) +void CAN_EnableInterrupt(CAN_T* can, uint32_t interrupts) { can->INTEN |= interrupts; } @@ -789,7 +863,7 @@ void CAN_EnableInterrupt(CAN_T *can, uint32_t interrupts) * * @note CAN2 applies only to APM32F103xC device. */ -void CAN_DisableInterrupt(CAN_T *can, uint32_t interrupts) +void CAN_DisableInterrupt(CAN_T* can, uint32_t interrupts) { can->INTEN &= ~interrupts; } @@ -821,7 +895,7 @@ void CAN_DisableInterrupt(CAN_T *can, uint32_t interrupts) * * @note CAN2 applies only to APM32F103xC device. */ -uint8_t CAN_ReadStatusFlag(CAN_T *can, CAN_FLAG_T flag) +uint8_t CAN_ReadStatusFlag(CAN_T* can, CAN_FLAG_T flag) { uint8_t status = 0; @@ -905,11 +979,11 @@ uint8_t CAN_ReadStatusFlag(CAN_T *can, CAN_FLAG_T flag) * * @note CAN2 applies only to APM32F103xC device. */ -void CAN_ClearStatusFlag(CAN_T *can, CAN_FLAG_T flag) +void CAN_ClearStatusFlag(CAN_T* can, CAN_FLAG_T flag) { uint32_t flagtmp = 0; - /** ERRSTS register */ + /* ERRSTS register */ if (flag == 0x30F00070) { can->ERRSTS = RESET; @@ -962,7 +1036,7 @@ void CAN_ClearStatusFlag(CAN_T *can, CAN_FLAG_T flag) * * @note CAN2 applies only to APM32F103xC device. */ -uint8_t CAN_ReadIntFlag(CAN_T *can, CAN_INT_T flag) +uint8_t CAN_ReadIntFlag(CAN_T* can, CAN_INT_T flag) { uint8_t status = 0; @@ -970,53 +1044,53 @@ uint8_t CAN_ReadIntFlag(CAN_T *can, CAN_INT_T flag) { switch (flag) { - case CAN_INT_TXME: - status = can->TXSTS_B.REQCFLG0; - status |= can->TXSTS_B.REQCFLG1; - status |= can->TXSTS_B.REQCFLG2; - break; - case CAN_INT_F0MP: - status = can->RXF0_B.FMNUM0; - break; - case CAN_INT_F0FULL: - status = can->RXF0_B.FFULLFLG0; - break; - case CAN_INT_F0OVR: - status = can->RXF0_B.FOVRFLG0; - break; - case CAN_INT_F1MP: - status = can->RXF1_B.FMNUM1; - break; - case CAN_INT_F1FULL: - status = can->RXF1_B.FFULLFLG1; - break; - case CAN_INT_F1OVR: - status = can->RXF1_B.FOVRFLG1; - break; - case CAN_INT_WUP: - status = can->MSTS_B.WUPIFLG; - break; - case CAN_INT_SLEEP: - status = can->MSTS_B.SLEEPIFLG; - break; - case CAN_INT_ERRW: - status = can->ERRSTS_B.ERRWFLG; - break; - case CAN_INT_ERRP: - status = can->ERRSTS_B.ERRPFLG; - break; - case CAN_INT_BOF: - status = can->ERRSTS_B.BOFLG; - break; - case CAN_INT_LEC: - status = can->ERRSTS_B.LERRC; - break; - case CAN_INT_ERR: - status = can->MSTS_B.ERRIFLG; - break; - default: - status = RESET; - break; + case CAN_INT_TXME: + status = can->TXSTS_B.REQCFLG0; + status |= can->TXSTS_B.REQCFLG1; + status |= can->TXSTS_B.REQCFLG2; + break; + case CAN_INT_F0MP: + status = can->RXF0_B.FMNUM0; + break; + case CAN_INT_F0FULL: + status = can->RXF0_B.FFULLFLG0; + break; + case CAN_INT_F0OVR: + status = can->RXF0_B.FOVRFLG0; + break; + case CAN_INT_F1MP: + status = can->RXF1_B.FMNUM1; + break; + case CAN_INT_F1FULL: + status = can->RXF1_B.FFULLFLG1; + break; + case CAN_INT_F1OVR: + status = can->RXF1_B.FOVRFLG1; + break; + case CAN_INT_WUP: + status = can->MSTS_B.WUPIFLG; + break; + case CAN_INT_SLEEP: + status = can->MSTS_B.SLEEPIFLG; + break; + case CAN_INT_ERRW: + status = can->ERRSTS_B.ERRWFLG; + break; + case CAN_INT_ERRP: + status = can->ERRSTS_B.ERRPFLG; + break; + case CAN_INT_BOF: + status = can->ERRSTS_B.BOFLG; + break; + case CAN_INT_LEC: + status = can->ERRSTS_B.LERRC; + break; + case CAN_INT_ERR: + status = can->MSTS_B.ERRIFLG; + break; + default: + status = RESET; + break; } } else @@ -1050,55 +1124,55 @@ uint8_t CAN_ReadIntFlag(CAN_T *can, CAN_INT_T flag) * * @note CAN2 applies only to APM32F103xC device. */ -void CAN_ClearIntFlag(CAN_T *can, CAN_INT_T flag) +void CAN_ClearIntFlag(CAN_T* can, CAN_INT_T flag) { switch (flag) { - case CAN_INT_TXME: - can->TXSTS_B.REQCFLG0 = BIT_SET; - can->TXSTS_B.REQCFLG1 = BIT_SET; - can->TXSTS_B.REQCFLG2 = BIT_SET; - break; - case CAN_INT_F0FULL: - can->RXF0_B.FFULLFLG0 = BIT_SET; - break; - case CAN_INT_F0OVR: - can->RXF0_B.FOVRFLG0 = BIT_SET; - break; - case CAN_INT_F1FULL: - can->RXF1_B.FFULLFLG1 = BIT_SET; - break; - case CAN_INT_F1OVR: - can->RXF1_B.FOVRFLG1 = BIT_SET; - break; - case CAN_INT_WUP: - can->MSTS_B.WUPIFLG = BIT_SET; - break; - case CAN_INT_SLEEP: - can->MSTS_B.SLEEPIFLG = BIT_SET; - break; - case CAN_INT_ERRW: - can->MSTS_B.ERRIFLG = BIT_SET; - break; - case CAN_INT_ERRP: - can->MSTS_B.ERRIFLG = BIT_SET; - break; - case CAN_INT_BOF: - can->MSTS_B.ERRIFLG = BIT_SET; - break; - case CAN_INT_LEC: - can->ERRSTS_B.LERRC = BIT_RESET; - can->MSTS_B.ERRIFLG = BIT_SET; - break; - case CAN_INT_ERR: - can->ERRSTS_B.LERRC = BIT_RESET; - can->MSTS_B.ERRIFLG = BIT_SET; - break; - default: - break; + case CAN_INT_TXME: + can->TXSTS_B.REQCFLG0 = BIT_SET; + can->TXSTS_B.REQCFLG1 = BIT_SET; + can->TXSTS_B.REQCFLG2 = BIT_SET; + break; + case CAN_INT_F0FULL: + can->RXF0_B.FFULLFLG0 = BIT_SET; + break; + case CAN_INT_F0OVR: + can->RXF0_B.FOVRFLG0 = BIT_SET; + break; + case CAN_INT_F1FULL: + can->RXF1_B.FFULLFLG1 = BIT_SET; + break; + case CAN_INT_F1OVR: + can->RXF1_B.FOVRFLG1 = BIT_SET; + break; + case CAN_INT_WUP: + can->MSTS_B.WUPIFLG = BIT_SET; + break; + case CAN_INT_SLEEP: + can->MSTS_B.SLEEPIFLG = BIT_SET; + break; + case CAN_INT_ERRW: + can->MSTS_B.ERRIFLG = BIT_SET; + break; + case CAN_INT_ERRP: + can->MSTS_B.ERRIFLG = BIT_SET; + break; + case CAN_INT_BOF: + can->MSTS_B.ERRIFLG = BIT_SET; + break; + case CAN_INT_LEC: + can->ERRSTS_B.LERRC = BIT_RESET; + can->MSTS_B.ERRIFLG = BIT_SET; + break; + case CAN_INT_ERR: + can->ERRSTS_B.LERRC = BIT_RESET; + can->MSTS_B.ERRIFLG = BIT_SET; + break; + default: + break; } } -/**@} end of group CAN_Fuctions*/ -/**@} end of group CAN_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group CAN_Functions */ +/**@} end of group CAN_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_crc.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_crc.c index fe208b5678..f1a145053c 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_crc.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_crc.c @@ -3,9 +3,9 @@ * * @brief This file provides all the CRC firmware functions * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,15 +25,16 @@ #include "apm32f10x_crc.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ /** @addtogroup CRC_Driver CRC Driver + * @brief CRC driver modules @{ */ -/** @addtogroup CRC_Fuctions Fuctions +/** @defgroup CRC_Functions Functions @{ */ @@ -73,7 +74,7 @@ uint32_t CRC_CalculateCRC(uint32_t data) * * @retval A 32-bit CRC value */ -uint32_t CRC_CalculateBlockCRC(uint32_t *buf, uint32_t bufLen) +uint32_t CRC_CalculateBlockCRC(uint32_t* buf, uint32_t bufLen) { while (bufLen--) { @@ -119,6 +120,6 @@ uint8_t CRC_ReadIDRegister(void) return (CRC->INDATA); } -/**@} end of group CRC_Fuctions*/ +/**@} end of group CRC_Functions*/ /**@} end of group CRC_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group APM32F10x_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_dac.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_dac.c index fac9e9f135..fd076d3d38 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_dac.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_dac.c @@ -3,9 +3,9 @@ * * @brief This file provides all the DAC firmware functions * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,15 +26,16 @@ #include "apm32f10x_dac.h" #include "apm32f10x_rcm.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ /** @addtogroup DAC_Driver DAC Driver + * @brief DAC driver modules @{ */ -/** @addtogroup DAC_Fuctions Fuctions +/** @defgroup DAC_Functions Functions @{ */ @@ -63,7 +64,7 @@ void DAC_Reset(void) * * @retval None */ -void DAC_Config(uint32_t channel, DAC_Config_T *dacConfig) +void DAC_Config(uint32_t channel, DAC_Config_T* dacConfig) { uint32_t tmp1 = 0, tmp2 = 0; @@ -88,15 +89,15 @@ void DAC_Config(uint32_t channel, DAC_Config_T *dacConfig) * * @retval None */ -void DAC_ConfigStructInit(DAC_Config_T *dacConfig) +void DAC_ConfigStructInit(DAC_Config_T* dacConfig) { - /** Initialize the DAC_Trigger member */ + /* Initialize the DAC_Trigger member */ dacConfig->trigger = DAC_TRIGGER_NONE; - /** Initialize the DAC_WaveGeneration member */ + /* Initialize the DAC_WaveGeneration member */ dacConfig->waveGeneration = DAC_WAVE_GENERATION_NONE; - /** Initialize the DAC_LFSRUnmask_TriangleAmplitude member */ + /* Initialize the DAC_LFSRUnmask_TriangleAmplitude member */ dacConfig->maskAmplitudeSelect = DAC_LFSR_MASK_BIT11_1; - /** Initialize the DAC_OutputBuffer member */ + /* Initialize the DAC_OutputBuffer member */ dacConfig->outputBuffer = DAC_OUTPUT_BUFFER_ENBALE; } @@ -321,8 +322,8 @@ void DAC_ConfigChannel1Data(DAC_ALIGN_T align, uint16_t data) tmp = (uint32_t)DAC_BASE; tmp += 0x00000008 + align; - /** Set the DAC channel1 selected data holding register */ - *(__IO uint32_t *) tmp = data; + /* Set the DAC channel1 selected data holding register */ + *(__IO uint32_t*) tmp = data; } /*! @@ -345,8 +346,8 @@ void DAC_ConfigChannel2Data(DAC_ALIGN_T align, uint16_t data) tmp = (uint32_t)DAC_BASE; tmp += 0x00000014 + align; - /** Set the DAC channel1 selected data holding register */ - *(__IO uint32_t *) tmp = data; + /* Set the DAC channel1 selected data holding register */ + *(__IO uint32_t*) tmp = data; } /*! @@ -368,7 +369,7 @@ void DAC_ConfigDualChannelData(DAC_ALIGN_T align, uint16_t data2, uint16_t data1 { uint32_t data = 0, tmp = 0; - /** Calculate and set dual DAC data holding register value */ + /* Calculate and set dual DAC data holding register value */ if (align == DAC_ALIGN_8BIT_R) { data = ((uint32_t)data2 << 8) | data1; @@ -381,8 +382,8 @@ void DAC_ConfigDualChannelData(DAC_ALIGN_T align, uint16_t data2, uint16_t data1 tmp = (uint32_t)DAC_BASE; tmp += 0x00000020 + align; - /** Set the dual DAC selected data holding register */ - *(__IO uint32_t *)tmp = data; + /* Set the dual DAC selected data holding register */ + *(__IO uint32_t*)tmp = data; } /*! @@ -402,10 +403,10 @@ uint16_t DAC_ReadDataOutputValue(DAC_CHANNEL_T channel) tmp = (uint32_t) DAC_BASE ; tmp += 0x0000002C + ((uint32_t)channel >> 2); - /** Returns the DAC channel data output register value */ - return (uint16_t)(*(__IO uint32_t *) tmp); + /* Returns the DAC channel data output register value */ + return (uint16_t)(*(__IO uint32_t*) tmp); } -/**@} end of group DAC_Fuctions*/ +/**@} end of group DAC_Functions*/ /**@} end of group DAC_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group APM32F10x_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_dbgmcu.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_dbgmcu.c index 3486aa8cfe..1de630864c 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_dbgmcu.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_dbgmcu.c @@ -3,9 +3,9 @@ * * @brief This file provides all the DEBUG firmware functions * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,15 +25,16 @@ #include "apm32f10x_dbgmcu.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ /** @addtogroup DBGMCU_Driver DBGMCU Driver + * @brief DBGMCU driver modules @{ */ -/** @addtogroup DBGMCU_Fuctions Fuctions +/** @defgroup DBGMCU_Functions Functions @{ */ @@ -141,6 +142,6 @@ void DBGMCU_Disable(uint32_t periph) DBGMCU->CFG &= ~periph; } -/**@} end of group DBGMCU_Fuctions*/ -/**@} end of group DBGMCU_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group DBGMCU_Functions*/ +/**@} end of group DBGMCU_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_dma.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_dma.c index fc302ad9a4..01a7185fc6 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_dma.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_dma.c @@ -3,9 +3,9 @@ * * @brief This file provides all the DMA firmware functions * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,15 +25,16 @@ #include "apm32f10x_dma.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ /** @addtogroup DMA_Driver DMA Driver + * @brief DMA driver modules @{ */ -/** @addtogroup DMA_Fuctions Fuctions +/** @defgroup DMA_Functions Functions @{ */ @@ -46,7 +47,7 @@ * * @note DMA2 Channel only for APM32 High density devices. */ -void DMA_Reset(DMA_Channel_T *channel) +void DMA_Reset(DMA_Channel_T* channel) { channel->CHCFG_B.CHEN = BIT_RESET; channel->CHCFG = 0; @@ -115,7 +116,7 @@ void DMA_Reset(DMA_Channel_T *channel) * * @note DMA2 Channel only for APM32 High density devices. */ -void DMA_Config(DMA_Channel_T *channel, DMA_Config_T *dmaConfig) +void DMA_Config(DMA_Channel_T* channel, DMA_Config_T* dmaConfig) { channel->CHCFG_B.DIRCFG = dmaConfig->dir; channel->CHCFG_B.CIRMODE = dmaConfig->loopMode; @@ -138,7 +139,7 @@ void DMA_Config(DMA_Channel_T *channel, DMA_Config_T *dmaConfig) * * @retval None */ -void DMA_ConfigStructInit(DMA_Config_T *dmaConfig) +void DMA_ConfigStructInit(DMA_Config_T* dmaConfig) { dmaConfig->peripheralBaseAddr = 0; dmaConfig->memoryBaseAddr = 0; @@ -162,7 +163,7 @@ void DMA_ConfigStructInit(DMA_Config_T *dmaConfig) * * @note DMA2 Channel only for APM32 High density devices. */ -void DMA_Enable(DMA_Channel_T *channel) +void DMA_Enable(DMA_Channel_T* channel) { channel->CHCFG_B.CHEN = ENABLE; } @@ -176,7 +177,7 @@ void DMA_Enable(DMA_Channel_T *channel) * * @note DMA2 Channel only for APM32 High density devices. */ -void DMA_Disable(DMA_Channel_T *channel) +void DMA_Disable(DMA_Channel_T* channel) { channel->CHCFG_B.CHEN = DISABLE; } @@ -192,7 +193,7 @@ void DMA_Disable(DMA_Channel_T *channel) * * @note DMA2 Channel only for APM32 High density devices. */ -void DMA_ConfigDataNumber(DMA_Channel_T *channel, uint16_t dataNumber) +void DMA_ConfigDataNumber(DMA_Channel_T* channel, uint16_t dataNumber) { channel->CHNDATA = dataNumber; } @@ -206,7 +207,7 @@ void DMA_ConfigDataNumber(DMA_Channel_T *channel, uint16_t dataNumber) * * @note DMA2 Channel only for APM32 High density devices. */ -uint16_t DMA_ReadDataNumber(DMA_Channel_T *channel) +uint16_t DMA_ReadDataNumber(DMA_Channel_T* channel) { return channel->CHNDATA; } @@ -226,7 +227,7 @@ uint16_t DMA_ReadDataNumber(DMA_Channel_T *channel) * * @note DMA2 Channel only for APM32 High density devices. */ -void DMA_EnableInterrupt(DMA_Channel_T *channel, uint32_t interrupt) +void DMA_EnableInterrupt(DMA_Channel_T* channel, uint32_t interrupt) { channel->CHCFG |= interrupt; } @@ -246,7 +247,7 @@ void DMA_EnableInterrupt(DMA_Channel_T *channel, uint32_t interrupt) * * @note DMA2 Channel only for APM32 High density devices. */ -void DMA_DisableInterrupt(DMA_Channel_T *channel, uint32_t interrupt) +void DMA_DisableInterrupt(DMA_Channel_T* channel, uint32_t interrupt) { channel->CHCFG &= ~interrupt; } @@ -491,6 +492,7 @@ uint8_t DMA_ReadIntFlag(DMA_INT_FLAG_T flag) } } } + /*! * @brief Clears the specified DMA Channel's interrupts. * @@ -562,6 +564,6 @@ void DMA_ClearIntFlag(uint32_t flag) } } -/**@} end of group DMA_Fuctions*/ +/**@} end of group DMA_Functions*/ /**@} end of group DMA_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group APM32F10x_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_dmc.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_dmc.c index 290ab8d697..3aa7cde45a 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_dmc.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_dmc.c @@ -3,9 +3,9 @@ * * @brief This file contains all the functions for the DMC controler peripheral * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,15 +26,16 @@ #ifdef APM32F10X_HD #include "apm32f10x_dmc.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ -/** @addtogroup DMC_Driver DMC Driver +/** @addtogroup DMC_Driver DMC Driver + * @brief DMC driver modules @{ */ -/** @addtogroup DMC_Fuctions Fuctions +/** @defgroup DMC_Functions Functions @{ */ @@ -45,7 +46,7 @@ * * @retval None */ -void DMC_Config(DMC_Config_T *dmcConfig) +void DMC_Config(DMC_Config_T* dmcConfig) { DMC->SW_B.MCSW = 1; while (!DMC->CTRL1_B.INIT); @@ -73,7 +74,7 @@ void DMC_Config(DMC_Config_T *dmcConfig) * * @retval None */ -void DMC_ConfigStructInit(DMC_Config_T *dmcConfig) +void DMC_ConfigStructInit(DMC_Config_T* dmcConfig) { dmcConfig->bankWidth = DMC_BANK_WIDTH_2; dmcConfig->clkPhase = DMC_CLK_PHASE_REVERSE; @@ -91,7 +92,7 @@ void DMC_ConfigStructInit(DMC_Config_T *dmcConfig) * * @retval None */ -void DMC_ConfigTiming(DMC_TimingConfig_T *timingConfig) +void DMC_ConfigTiming(DMC_TimingConfig_T* timingConfig) { DMC->TIM0_B.RASMINTSEL = timingConfig->tRAS; DMC->TIM0_B.DTIMSEL = timingConfig->tRCD; @@ -116,7 +117,7 @@ void DMC_ConfigTiming(DMC_TimingConfig_T *timingConfig) * * @retval None */ -void DMC_ConfigTimingStructInit(DMC_TimingConfig_T *timingConfig) +void DMC_ConfigTimingStructInit(DMC_TimingConfig_T* timingConfig) { timingConfig->latencyCAS = DMC_CAS_LATENCY_3; timingConfig->tARP = DMC_AUTO_REFRESH_10; @@ -457,8 +458,9 @@ void DMC_ConfigWRAPB(DMC_WRPB_T burst) DMC->CTRL2_B.WRPBSEL = burst; } +/**@} end of group DMC_Functions*/ +/**@} end of group DMC_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver*/ + #endif //defined APM32F10X_HD -/**@} end of group DMC_Fuctions*/ -/**@} end of group DMC_Driver*/ -/**@} end of group Peripherals_Library*/ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_eint.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_eint.c index 9b4c63aeac..d88685e045 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_eint.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_eint.c @@ -3,9 +3,9 @@ * * @brief This file provides all the EINT firmware functions * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,15 +25,16 @@ #include "apm32f10x_eint.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ /** @addtogroup EINT_Driver EINT Driver + * @brief EINT driver modules @{ */ -/** @addtogroup EINT_Fuctions Fuctions +/** @defgroup EINT_Functions Functions @{ */ @@ -60,7 +61,7 @@ void EINT_Reset(void) * * @retval None */ -void EINT_Config(EINT_Config_T *eintConfig) +void EINT_Config(EINT_Config_T* eintConfig) { uint32_t temp = 0; temp = (uint32_t)EINT_BASE; @@ -71,7 +72,7 @@ void EINT_Config(EINT_Config_T *eintConfig) EINT->EMASK &= ~eintConfig->line; temp += eintConfig->mode; - *(__IOM uint32_t *) temp |= eintConfig->line; + *(__IOM uint32_t*) temp |= eintConfig->line; EINT->RTEN &= ~eintConfig->line; EINT->FTEN &= ~eintConfig->line; @@ -86,14 +87,14 @@ void EINT_Config(EINT_Config_T *eintConfig) temp = (uint32_t)EINT_BASE; temp += eintConfig->trigger; - *(__IOM uint32_t *) temp |= eintConfig->line; + *(__IOM uint32_t*) temp |= eintConfig->line; } } else { temp += eintConfig->mode; - *(__IOM uint32_t *) temp &= ~eintConfig->line; + *(__IOM uint32_t*) temp &= ~eintConfig->line; } } @@ -104,7 +105,7 @@ void EINT_Config(EINT_Config_T *eintConfig) * * @retval None */ -void EINT_ConfigStructInit(EINT_Config_T *eintConfig) +void EINT_ConfigStructInit(EINT_Config_T* eintConfig) { eintConfig->line = EINT_LINENONE; eintConfig->mode = EINT_MODE_INTERRUPT; @@ -200,6 +201,6 @@ void EINT_ClearIntFlag(uint32_t line) EINT->IPEND = line; } -/**@} end of group EINT_Fuctions*/ -/**@} end of group EINT_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group EINT_Functions*/ +/**@} end of group EINT_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver*/ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_fmc.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_fmc.c index 4543a7178f..d0a01013b9 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_fmc.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_fmc.c @@ -3,9 +3,9 @@ * * @brief This file provides all the FMC firmware functions * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,10 +23,11 @@ * and limitations under the License. */ +/* Includes */ #include "apm32f10x_fmc.h" #include "apm32f10x_rcm.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -34,7 +35,7 @@ @{ */ -/** @addtogroup FMC_Fuctions Fuctions +/** @defgroup FMC_Functions Functions @{ */ @@ -257,7 +258,7 @@ FMC_STATUS_T FMC_ProgramWord(uint32_t address, uint32_t data) { FMC->CTRL2_B.PG = BIT_SET; - *(__IOM uint16_t *)address = data; + *(__IOM uint16_t*)address = data; status = FMC_WaitForLastOperation(0x000B0000); @@ -265,7 +266,7 @@ FMC_STATUS_T FMC_ProgramWord(uint32_t address, uint32_t data) { temp = address + 2; - *(__IOM uint16_t *) temp = data >> 16; + *(__IOM uint16_t*) temp = data >> 16; status = FMC_WaitForLastOperation(0x000B0000); FMC->CTRL2_B.PG = BIT_RESET; @@ -309,7 +310,7 @@ FMC_STATUS_T FMC_ProgramHalfWord(uint32_t address, uint16_t data) if (status == FMC_STATUS_COMPLETE) { FMC->CTRL2_B.PG = BIT_SET; - *(__IOM uint16_t *)address = data; + *(__IOM uint16_t*)address = data; status = FMC_WaitForLastOperation(0x000B0000); FMC->CTRL2_B.PG = BIT_RESET; } @@ -346,7 +347,7 @@ FMC_STATUS_T FMC_ProgramOptionByteData(uint32_t address, uint8_t data) FMC->OBKEY = 0xCDEF89AB; FMC->CTRL2_B.OBP = BIT_SET; - *(__IOM uint16_t *)address = data; + *(__IOM uint16_t*)address = data; status = FMC_WaitForLastOperation(0x000B0000); if (status == FMC_STATUS_TIMEOUT) { @@ -361,11 +362,11 @@ FMC_STATUS_T FMC_ProgramOptionByteData(uint32_t address, uint8_t data) * * @param page:the address of the pages to be write protection * This parameter can be any combination of the following values: - * for APM32F10X_LD £º + * for APM32F10X_LD : * @arg FLASH_WRP_PAGE_0_3 to FLASH_WRP_PAGE_28_31 - * for APM32F10X_MD £º + * for APM32F10X_MD : * @arg FLASH_WRP_PAGE_0_3 to FLASH_WRP_PAGE_124_127 - * for APM32F10X_HD £º + * for APM32F10X_HD : * @arg FLASH_WRP_PAGE_0_1 to FLASH_WRP_PAGE_60_61 or FLASH_WRP_PAGE_62_127 * @arg FMC_WRP_PAGE_ALL * @@ -454,7 +455,7 @@ FMC_STATUS_T FMC_EnableReadOutProtection(void) { FMC->CTRL2_B.OBE = BIT_RESET; FMC->CTRL2_B.OBP = BIT_SET; - OB->RDP = 0x0000; + OB->RDP = 0x00; status = FMC_WaitForLastOperation(0x000B0000); @@ -501,7 +502,7 @@ FMC_STATUS_T FMC_DisableReadOutProtection(void) { FMC->CTRL2_B.OBE = BIT_RESET; FMC->CTRL2_B.OBP = BIT_SET; - OB->RDP = 0x00A5; + OB->RDP = 0xA5; status = FMC_WaitForLastOperation(0x000B0000); @@ -529,7 +530,7 @@ FMC_STATUS_T FMC_DisableReadOutProtection(void) * @arg FMC_STATUS_COMPLETE * @arg FMC_STATUS_TIMEOUT */ -FMC_STATUS_T FMC_ConfigUserOptionByte(FMC_UserConfig_T *userConfig) +FMC_STATUS_T FMC_ConfigUserOptionByte(FMC_UserConfig_T* userConfig) { FMC_STATUS_T status = FMC_STATUS_COMPLETE; @@ -763,6 +764,6 @@ FMC_STATUS_T FMC_WaitForLastOperation(uint32_t timeOut) return status; } -/**@} end of group FMC_Fuctions*/ +/**@} end of group FMC_Functions*/ /**@} end of group FMC_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group APM32F10x_StdPeriphDriver*/ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_gpio.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_gpio.c index e4399deb9e..be9e785ae2 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_gpio.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_gpio.c @@ -3,9 +3,9 @@ * * @brief This file provides all the GPIO firmware functions * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,10 +23,11 @@ * and limitations under the License. */ +/* Includes */ #include "apm32f10x_gpio.h" #include "apm32f10x_rcm.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -34,7 +35,7 @@ @{ */ -/** @addtogroup GPIO_Fuctions Fuctions +/** @defgroup GPIO_Functions Functions @{ */ @@ -46,7 +47,7 @@ * * @retval None */ -void GPIO_Reset(GPIO_T *port) +void GPIO_Reset(GPIO_T* port) { RCM_APB2_PERIPH_T APB2Periph; @@ -106,7 +107,7 @@ void GPIO_AFIOReset(void) * * @retval None */ -void GPIO_Config(GPIO_T *port, GPIO_Config_T *gpioConfig) +void GPIO_Config(GPIO_T* port, GPIO_Config_T* gpioConfig) { uint8_t i; uint32_t mode; @@ -181,10 +182,10 @@ void GPIO_Config(GPIO_T *port, GPIO_Config_T *gpioConfig) * * @retval None */ -void GPIO_ConfigStructInit(GPIO_Config_T *gpioConfig) +void GPIO_ConfigStructInit(GPIO_Config_T* gpioConfig) { gpioConfig->pin = GPIO_PIN_ALL; - gpioConfig->speed = GPIO_SPEED_20MHz; + gpioConfig->speed = GPIO_SPEED_2MHz; gpioConfig->mode = GPIO_MODE_IN_FLOATING; } @@ -199,7 +200,7 @@ void GPIO_ConfigStructInit(GPIO_Config_T *gpioConfig) * * @retval The input port pin value */ -uint8_t GPIO_ReadInputBit(GPIO_T *port, uint16_t pin) +uint8_t GPIO_ReadInputBit(GPIO_T* port, uint16_t pin) { uint8_t ret; @@ -216,7 +217,7 @@ uint8_t GPIO_ReadInputBit(GPIO_T *port, uint16_t pin) * * @retval GPIO input data port value */ -uint16_t GPIO_ReadInputPort(GPIO_T *port) +uint16_t GPIO_ReadInputPort(GPIO_T* port) { return ((uint16_t)port->IDATA); } @@ -232,7 +233,7 @@ uint16_t GPIO_ReadInputPort(GPIO_T *port) * * @retval The output port pin value */ -uint8_t GPIO_ReadOutputBit(GPIO_T *port, uint16_t pin) +uint8_t GPIO_ReadOutputBit(GPIO_T* port, uint16_t pin) { uint8_t ret; @@ -250,7 +251,7 @@ uint8_t GPIO_ReadOutputBit(GPIO_T *port, uint16_t pin) * * @retval output data port value */ -uint16_t GPIO_ReadOutputPort(GPIO_T *port) +uint16_t GPIO_ReadOutputPort(GPIO_T* port) { return ((uint16_t)port->ODATA); } @@ -266,7 +267,7 @@ uint16_t GPIO_ReadOutputPort(GPIO_T *port) * * @retval None */ -void GPIO_SetBit(GPIO_T *port, uint16_t pin) +void GPIO_SetBit(GPIO_T* port, uint16_t pin) { port->BSC = (uint32_t)pin; } @@ -282,7 +283,7 @@ void GPIO_SetBit(GPIO_T *port, uint16_t pin) * * @retval None */ -void GPIO_ResetBit(GPIO_T *port, uint16_t pin) +void GPIO_ResetBit(GPIO_T* port, uint16_t pin) { port->BC = (uint32_t)pin; } @@ -304,7 +305,7 @@ void GPIO_ResetBit(GPIO_T *port, uint16_t pin) * * @retval None */ -void GPIO_WriteBitValue(GPIO_T *port, uint16_t pin, uint8_t bitVal) +void GPIO_WriteBitValue(GPIO_T* port, uint16_t pin, uint8_t bitVal) { if (bitVal != BIT_RESET) { @@ -326,7 +327,7 @@ void GPIO_WriteBitValue(GPIO_T *port, uint16_t pin, uint8_t bitVal) * * @retval None */ -void GPIO_WriteOutputPort(GPIO_T *port, uint16_t portValue) +void GPIO_WriteOutputPort(GPIO_T* port, uint16_t portValue) { port->ODATA = (uint32_t)portValue; } @@ -342,20 +343,20 @@ void GPIO_WriteOutputPort(GPIO_T *port, uint16_t portValue) * * @retval None */ -void GPIO_ConfigPinLock(GPIO_T *port, uint16_t pin) +void GPIO_ConfigPinLock(GPIO_T* port, uint16_t pin) { uint32_t val = 0x00010000; val |= pin; - /** Set LCKK bit */ + /* Set LCKK bit */ port->LOCK = val ; - /** Reset LCKK bit */ + /* Reset LCKK bit */ port->LOCK = pin; - /** Set LCKK bit */ + /* Set LCKK bit */ port->LOCK = val; - /** Read LCKK bit*/ + /* Read LCKK bit*/ val = port->LOCK; - /** Read LCKK bit*/ + /* Read LCKK bit*/ val = port->LOCK; } @@ -435,6 +436,24 @@ void GPIO_DisableEventOutput(void) * @arg GPIO_REMAP_PD01 : PD01 Alternate Function mapping * @arg GPIO_NO_REMAP_TMR5CH4_LSI : No LSI connected to TIM5 Channel4 input capture for calibration * @arg GPIO_REMAP_TMR5CH4_LSI : LSI connected to TIM5 Channel4 input capture for calibration + * Only For APM32F10X_CL devices(APM32F107xx and APM32F105xx): + * @arg GPIO_NO_REMAP_ETH_MAC : No Ethernet MAC Alternate remapping + * @arg GPIO_REMAP_ETH_MAC : Ethernet MAC Alternate remapping + * @arg GPIO_NO_REMAP_CAN2 : No CAN2 Alternate Function mapping + * @arg GPIO_REMAP_CAN2 : CAN2 Alternate Function mapping + * @arg GPIO_REMAP_MACEISEL_MII : Ethernet MAC External Interface Select MII Interface + * @arg GPIO_REMAP_MACEISEL_RMII : Ethernet MAC External Interface Select RMII Interface + * @arg GPIO_NO_REMAP_SPI3 : No SPI3 Alternate Function mapping + * @arg GPIO_REMAP_SPI3 : SPI3 Alternate Function mapping + * @arg GPIO_NO_REMAP_SWJ : Full SWJ Enabled (JTAG-DP + SW-DP) + * @arg GPIO_REMAP_SWJ_NOJTRST : Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST + * @arg GPIO_REMAP_SWJ_JTAGDISABLE : JTAG-DP Disabled and SW-DP Enabled + * @arg GPIO_REMAP_SWJ_DISABLE : Full SWJ Disabled (JTAG-DP + SW-DP) + * @arg GPIO_NO_REMAP_TMR2ITR1 : No TMR2 ITR1 Alternate Function mapping + * @arg GPIO_REMAP_TMR2ITR1 : TMR2 ITR1 Alternate Function mapping + * @arg GPIO_NO_REMAP_PTP_PPS : No Ethernet MAC PTP_PPS Alternate Function mapping + * @arg GPIO_REMAP_PTP_PPS : Ethernet MAC PTP_PPS Alternate Function mapping + * For Other APM32F10X_HD/MD/LD devices: * @arg GPIO_NO_REMAP_ADC1_ETRGINJ : No ADC1 External Trigger Injected Conversion remapping * @arg GPIO_REMAP_ADC1_ETRGINJ : ADC1 External Trigger Injected Conversion remapping * @arg GPIO_NO_REMAP_ADC1_ETRGREG : No ADC1 External Trigger Regular Conversion remapping @@ -540,6 +559,6 @@ void GPIO_ConfigEINTLine(GPIO_PORT_SOURCE_T portSource, GPIO_PIN_SOURCE_T pinSou } } -/**@} end of group GPIO_Fuctions*/ +/**@} end of group GPIO_Functions*/ /**@} end of group GPIO_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group APM32F10x_StdPeriphDriver*/ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_i2c.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_i2c.c index f03564c023..1b1ce60fcb 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_i2c.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_i2c.c @@ -3,9 +3,9 @@ * * @brief This file provides all the I2C firmware functions * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,10 +23,11 @@ * and limitations under the License. */ +/* Includes */ #include "apm32f10x_i2c.h" #include "apm32f10x_rcm.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -34,7 +35,7 @@ @{ */ -/** @addtogroup I2C_Fuctions Fuctions +/** @defgroup I2C_Functions Functions @{ */ @@ -45,7 +46,7 @@ * * @retval None */ -void I2C_Reset(I2C_T *i2c) +void I2C_Reset(I2C_T* i2c) { if (i2c == I2C1) { @@ -68,7 +69,7 @@ void I2C_Reset(I2C_T *i2c) * * @retval None */ -void I2C_Config(I2C_T *i2c, I2C_Config_T *i2cConfig) +void I2C_Config(I2C_T* i2c, I2C_Config_T* i2cConfig) { uint16_t tmpreg = 0, freqrange = 0; uint32_t PCLK1 = 8000000, PCLK2 = 0; @@ -76,12 +77,12 @@ void I2C_Config(I2C_T *i2c, I2C_Config_T *i2cConfig) i2c->SWITCH = 0; - /** I2C CTRL2 Configuration */ + /* I2C CTRL2 Configuration */ RCM_ReadPCLKFreq(&PCLK1, &PCLK2); freqrange = PCLK1 / 1000000; i2c->CTRL2_B.CLKFCFG = freqrange; - /** I2C CLKCTRL Configuration */ + /* I2C CLKCTRL Configuration */ i2c->CTRL1_B.I2CEN = BIT_RESET; if (i2cConfig->clockSpeed <= 100000) @@ -94,7 +95,7 @@ void I2C_Config(I2C_T *i2c, I2C_Config_T *i2cConfig) i2c->RISETMAX = freqrange + 1; tmpreg |= result; } - /** Configure speed in fast mode */ + /* Configure speed in fast mode */ else { if (i2cConfig->dutyCycle == I2C_DUTYCYCLE_2) @@ -118,7 +119,7 @@ void I2C_Config(I2C_T *i2c, I2C_Config_T *i2cConfig) i2c->CLKCTRL = tmpreg; i2c->CTRL1_B.I2CEN = BIT_SET; - /** i2c CTRL1 Configuration */ + /* i2c CTRL1 Configuration */ i2c->CTRL1_B.ACKEN = BIT_RESET; i2c->CTRL1_B.SMBTCFG = BIT_RESET; i2c->CTRL1_B.SMBEN = BIT_RESET; @@ -136,7 +137,7 @@ void I2C_Config(I2C_T *i2c, I2C_Config_T *i2cConfig) * * @retval None */ -void I2C_ConfigStructInit(I2C_Config_T *i2cConfig) +void I2C_ConfigStructInit(I2C_Config_T* i2cConfig) { i2cConfig->clockSpeed = 5000; i2cConfig->mode = I2C_MODE_I2C; @@ -153,7 +154,7 @@ void I2C_ConfigStructInit(I2C_Config_T *i2cConfig) * * @retval None */ -void I2C_Enable(I2C_T *i2c) +void I2C_Enable(I2C_T* i2c) { i2c->CTRL1_B.I2CEN = ENABLE; } @@ -165,7 +166,7 @@ void I2C_Enable(I2C_T *i2c) * * @retval None */ -void I2C_Disable(I2C_T *i2c) +void I2C_Disable(I2C_T* i2c) { i2c->CTRL1_B.I2CEN = DISABLE; } @@ -177,7 +178,7 @@ void I2C_Disable(I2C_T *i2c) * * @retval None */ -void I2C_EnableGenerateStart(I2C_T *i2c) +void I2C_EnableGenerateStart(I2C_T* i2c) { i2c->CTRL1_B.START = BIT_SET; } @@ -189,7 +190,7 @@ void I2C_EnableGenerateStart(I2C_T *i2c) * * @retval None */ -void I2C_DisableGenerateStart(I2C_T *i2c) +void I2C_DisableGenerateStart(I2C_T* i2c) { i2c->CTRL1_B.START = BIT_RESET; } @@ -201,7 +202,7 @@ void I2C_DisableGenerateStart(I2C_T *i2c) * * @retval None */ -void I2C_EnableGenerateStop(I2C_T *i2c) +void I2C_EnableGenerateStop(I2C_T* i2c) { i2c->CTRL1_B.STOP = BIT_SET; } @@ -213,7 +214,7 @@ void I2C_EnableGenerateStop(I2C_T *i2c) * * @retval None */ -void I2C_DisableGenerateStop(I2C_T *i2c) +void I2C_DisableGenerateStop(I2C_T* i2c) { i2c->CTRL1_B.STOP = BIT_RESET; } @@ -225,7 +226,7 @@ void I2C_DisableGenerateStop(I2C_T *i2c) * * @retval None */ -void I2C_EnableAcknowledge(I2C_T *i2c) +void I2C_EnableAcknowledge(I2C_T* i2c) { i2c->CTRL1_B.ACKEN = ENABLE; } @@ -237,7 +238,7 @@ void I2C_EnableAcknowledge(I2C_T *i2c) * * @retval None */ -void I2C_DisableAcknowledge(I2C_T *i2c) +void I2C_DisableAcknowledge(I2C_T* i2c) { i2c->CTRL1_B.ACKEN = DISABLE; } @@ -251,7 +252,7 @@ void I2C_DisableAcknowledge(I2C_T *i2c) * * @retval None */ -void I2C_ConfigOwnAddress2(I2C_T *i2c, uint8_t address) +void I2C_ConfigOwnAddress2(I2C_T* i2c, uint8_t address) { i2c->SADDR2_B.ADDR2 = address; } @@ -263,7 +264,7 @@ void I2C_ConfigOwnAddress2(I2C_T *i2c, uint8_t address) * * @retval None */ -void I2C_EnableDualAddress(I2C_T *i2c) +void I2C_EnableDualAddress(I2C_T* i2c) { i2c->SADDR2_B.ADDRNUM = ENABLE; } @@ -275,7 +276,7 @@ void I2C_EnableDualAddress(I2C_T *i2c) * * @retval None */ -void I2C_DisableDualAddress(I2C_T *i2c) +void I2C_DisableDualAddress(I2C_T* i2c) { i2c->SADDR2_B.ADDRNUM = DISABLE; } @@ -287,7 +288,7 @@ void I2C_DisableDualAddress(I2C_T *i2c) * * @retval None */ -void I2C_EnableGeneralCall(I2C_T *i2c) +void I2C_EnableGeneralCall(I2C_T* i2c) { i2c->CTRL1_B.SRBEN = ENABLE; } @@ -299,7 +300,7 @@ void I2C_EnableGeneralCall(I2C_T *i2c) * * @retval None */ -void I2C_DisableGeneralCall(I2C_T *i2c) +void I2C_DisableGeneralCall(I2C_T* i2c) { i2c->CTRL1_B.SRBEN = DISABLE; } @@ -313,7 +314,7 @@ void I2C_DisableGeneralCall(I2C_T *i2c) * * @retval None */ -void I2C_TxData(I2C_T *i2c, uint8_t data) +void I2C_TxData(I2C_T* i2c, uint8_t data) { i2c->DATA_B.DATA = data; } @@ -325,7 +326,7 @@ void I2C_TxData(I2C_T *i2c, uint8_t data) * * @retval received data */ -uint8_t I2C_RxData(I2C_T *i2c) +uint8_t I2C_RxData(I2C_T* i2c) { return i2c->DATA_B.DATA; } @@ -343,7 +344,7 @@ uint8_t I2C_RxData(I2C_T *i2c) * @arg I2C_DIRECTION_RX: Receiver mode * @retval None */ -void I2C_Tx7BitAddress(I2C_T *i2c, uint8_t address, I2C_DIRECTION_T direction) +void I2C_Tx7BitAddress(I2C_T* i2c, uint8_t address, I2C_DIRECTION_T direction) { if (direction != I2C_DIRECTION_TX) { @@ -375,32 +376,32 @@ void I2C_Tx7BitAddress(I2C_T *i2c, uint8_t address, I2C_DIRECTION_T direction) * * @retval The value of the read register */ -uint16_t I2C_ReadRegister(I2C_T *i2c, I2C_REGISTER_T i2cRegister) +uint16_t I2C_ReadRegister(I2C_T* i2c, I2C_REGISTER_T i2cRegister) { switch (i2cRegister) { - case I2C_REGISTER_CTRL1: - return i2c->CTRL1; - case I2C_REGISTER_CTRL2: - return i2c->CTRL2; - case I2C_REGISTER_SADDR1: - return i2c->SADDR1; - case I2C_REGISTER_SADDR2: - return i2c->SADDR2; - case I2C_REGISTER_DATA: - return i2c->DATA; - case I2C_REGISTER_STS1: - return i2c->STS1; - case I2C_REGISTER_STS2: - return i2c->STS2; - case I2C_REGISTER_CLKCTRL: - return i2c->CLKCTRL; - case I2C_REGISTER_RISETMAX: - return i2c->RISETMAX; - case I2C_REGISTER_SWITCH: - return i2c->SWITCH; - default: - return 0; + case I2C_REGISTER_CTRL1: + return i2c->CTRL1; + case I2C_REGISTER_CTRL2: + return i2c->CTRL2; + case I2C_REGISTER_SADDR1: + return i2c->SADDR1; + case I2C_REGISTER_SADDR2: + return i2c->SADDR2; + case I2C_REGISTER_DATA: + return i2c->DATA; + case I2C_REGISTER_STS1: + return i2c->STS1; + case I2C_REGISTER_STS2: + return i2c->STS2; + case I2C_REGISTER_CLKCTRL: + return i2c->CLKCTRL; + case I2C_REGISTER_RISETMAX: + return i2c->RISETMAX; + case I2C_REGISTER_SWITCH: + return i2c->SWITCH; + default: + return 0; } } @@ -411,7 +412,7 @@ uint16_t I2C_ReadRegister(I2C_T *i2c, I2C_REGISTER_T i2cRegister) * * @retval None */ -void I2C_EnableSoftwareReset(I2C_T *i2c) +void I2C_EnableSoftwareReset(I2C_T* i2c) { i2c->CTRL1_B.SWRST = ENABLE; } @@ -423,7 +424,7 @@ void I2C_EnableSoftwareReset(I2C_T *i2c) * * @retval None */ -void I2C_DisableSoftwareReset(I2C_T *i2c) +void I2C_DisableSoftwareReset(I2C_T* i2c) { i2c->CTRL1_B.SWRST = DISABLE; } @@ -437,7 +438,7 @@ void I2C_DisableSoftwareReset(I2C_T *i2c) * * @retval None */ -void I2C_ConfigNACKPosition(I2C_T *i2c, I2C_NACK_POSITION_T NACKPosition) +void I2C_ConfigNACKPosition(I2C_T* i2c, I2C_NACK_POSITION_T NACKPosition) { if (NACKPosition == I2C_NACK_POSITION_NEXT) { @@ -460,7 +461,7 @@ void I2C_ConfigNACKPosition(I2C_T *i2c, I2C_NACK_POSITION_T NACKPosition) * @arg I2C_SMBUSALER_HIGH: SMBus Alert pin high * @retval None */ -void I2C_ConfigSMBusAlert(I2C_T *i2c, I2C_SMBUSALER_T SMBusState) +void I2C_ConfigSMBusAlert(I2C_T* i2c, I2C_SMBUSALER_T SMBusState) { if (SMBusState == I2C_SMBUSALER_LOW) { @@ -479,7 +480,7 @@ void I2C_ConfigSMBusAlert(I2C_T *i2c, I2C_SMBUSALER_T SMBusState) * * @retval None */ -void I2C_EnablePECTransmit(I2C_T *i2c) +void I2C_EnablePECTransmit(I2C_T* i2c) { i2c->CTRL1_B.PEC = BIT_SET; } @@ -491,7 +492,7 @@ void I2C_EnablePECTransmit(I2C_T *i2c) * * @retval None */ -void I2C_DisablePECTransmit(I2C_T *i2c) +void I2C_DisablePECTransmit(I2C_T* i2c) { i2c->CTRL1_B.PEC = BIT_RESET; } @@ -507,7 +508,7 @@ void I2C_DisablePECTransmit(I2C_T *i2c) * @arg I2C_PEC_POSITION_CURRENT: indicates that current byte is PEC * @retval None */ -void I2C_ConfigPECPosition(I2C_T *i2c, I2C_PEC_POSITION_T PECPosition) +void I2C_ConfigPECPosition(I2C_T* i2c, I2C_PEC_POSITION_T PECPosition) { if (PECPosition == I2C_PEC_POSITION_NEXT) { @@ -526,7 +527,7 @@ void I2C_ConfigPECPosition(I2C_T *i2c, I2C_PEC_POSITION_T PECPosition) * * @retval None */ -void I2C_EnablePEC(I2C_T *i2c) +void I2C_EnablePEC(I2C_T* i2c) { i2c->CTRL1_B.PECEN = BIT_SET; } @@ -538,7 +539,7 @@ void I2C_EnablePEC(I2C_T *i2c) * * @retval None */ -void I2C_DisablePEC(I2C_T *i2c) +void I2C_DisablePEC(I2C_T* i2c) { i2c->CTRL1_B.PECEN = BIT_RESET; } @@ -550,7 +551,7 @@ void I2C_DisablePEC(I2C_T *i2c) * * @retval value of PEC */ -uint8_t I2C_ReadPEC(I2C_T *i2c) +uint8_t I2C_ReadPEC(I2C_T* i2c) { return i2c->STS2_B.PECVALUE; } @@ -562,7 +563,7 @@ uint8_t I2C_ReadPEC(I2C_T *i2c) * * @retval None */ -void I2C_EnableARP(I2C_T *i2c) +void I2C_EnableARP(I2C_T* i2c) { i2c->CTRL1_B.ARPEN = BIT_SET; } @@ -574,7 +575,7 @@ void I2C_EnableARP(I2C_T *i2c) * * @retval None */ -void I2C_DisableARP(I2C_T *i2c) +void I2C_DisableARP(I2C_T* i2c) { i2c->CTRL1_B.ARPEN = BIT_RESET; } @@ -586,7 +587,7 @@ void I2C_DisableARP(I2C_T *i2c) * * @retval None */ -void I2C_EnableStretchClock(I2C_T *i2c) +void I2C_EnableStretchClock(I2C_T* i2c) { i2c->CTRL1_B.CLKSTRETCHD = BIT_RESET; } @@ -598,7 +599,7 @@ void I2C_EnableStretchClock(I2C_T *i2c) * * @retval None */ -void I2C_DisableStretchClock(I2C_T *i2c) +void I2C_DisableStretchClock(I2C_T* i2c) { i2c->CTRL1_B.CLKSTRETCHD = BIT_SET; } @@ -614,7 +615,7 @@ void I2C_DisableStretchClock(I2C_T *i2c) * @arg I2C_DUTYCYCLE_2: I2C fast mode Tlow/Thigh = 2 * @retval None */ -void I2C_ConfigFastModeDutyCycle(I2C_T *i2c, I2C_DUTYCYCLE_T dutyCycle) +void I2C_ConfigFastModeDutyCycle(I2C_T* i2c, I2C_DUTYCYCLE_T dutyCycle) { if (dutyCycle == I2C_DUTYCYCLE_16_9) { @@ -633,7 +634,7 @@ void I2C_ConfigFastModeDutyCycle(I2C_T *i2c, I2C_DUTYCYCLE_T dutyCycle) * * @retval None */ -void I2C_EnableDMA(I2C_T *i2c) +void I2C_EnableDMA(I2C_T* i2c) { i2c->CTRL2_B.DMAEN = ENABLE; } @@ -645,7 +646,7 @@ void I2C_EnableDMA(I2C_T *i2c) * * @retval None */ -void I2C_DisableDMA(I2C_T *i2c) +void I2C_DisableDMA(I2C_T* i2c) { i2c->CTRL2_B.DMAEN = DISABLE; } @@ -657,7 +658,7 @@ void I2C_DisableDMA(I2C_T *i2c) * * @retval None */ -void I2C_EnableDMALastTransfer(I2C_T *i2c) +void I2C_EnableDMALastTransfer(I2C_T* i2c) { i2c->CTRL2_B.LTCFG = BIT_SET; } @@ -669,7 +670,7 @@ void I2C_EnableDMALastTransfer(I2C_T *i2c) * * @retval None */ -void I2C_DisableDMALastTransfer(I2C_T *i2c) +void I2C_DisableDMALastTransfer(I2C_T* i2c) { i2c->CTRL2_B.LTCFG = BIT_RESET; } @@ -687,7 +688,7 @@ void I2C_DisableDMALastTransfer(I2C_T *i2c) * * @retval None */ -void I2C_EnableInterrupt(I2C_T *i2c, uint16_t interrupt) +void I2C_EnableInterrupt(I2C_T* i2c, uint16_t interrupt) { i2c->CTRL2 |= interrupt; } @@ -705,7 +706,7 @@ void I2C_EnableInterrupt(I2C_T *i2c, uint16_t interrupt) * * @retval None */ -void I2C_DisableInterrupt(I2C_T *i2c, uint16_t interrupt) +void I2C_DisableInterrupt(I2C_T* i2c, uint16_t interrupt) { i2c->CTRL2 &= ~interrupt; } @@ -736,7 +737,7 @@ void I2C_DisableInterrupt(I2C_T *i2c, uint16_t interrupt) * * @retval Status: SUCCESS or ERROR */ -uint8_t I2C_ReadEventStatus(I2C_T *i2c, I2C_EVENT_T i2cEvent) +uint8_t I2C_ReadEventStatus(I2C_T* i2c, I2C_EVENT_T i2cEvent) { uint32_t lastevent = 0; uint32_t flag1 = 0, flag2 = 0; @@ -761,7 +762,7 @@ uint8_t I2C_ReadEventStatus(I2C_T *i2c, I2C_EVENT_T i2cEvent) * * @retval The last event */ -uint32_t I2C_ReadLastEvent(I2C_T *i2c) +uint32_t I2C_ReadLastEvent(I2C_T* i2c) { uint32_t lastevent = 0; uint32_t flag1 = 0, flag2 = 0; @@ -806,77 +807,77 @@ uint32_t I2C_ReadLastEvent(I2C_T *i2c) * * @retval Status: flag SET or RESET */ -uint8_t I2C_ReadStatusFlag(I2C_T *i2c, I2C_FLAG_T flag) +uint8_t I2C_ReadStatusFlag(I2C_T* i2c, I2C_FLAG_T flag) { uint8_t status = 0; switch (flag) { - case I2C_FLAG_DUALADDR: - status = i2c->STS2_B.DUALADDRFLG; - break; - case I2C_FLAG_SMMHADDR: - status = i2c->STS2_B.SMMHADDR; - break; - case I2C_FLAG_SMBDADDR: - status = i2c->STS2_B.SMBDADDRFLG; - break; - case I2C_FLAG_GENCALL: - status = i2c->STS2_B.GENCALLFLG; - break; - case I2C_FLAG_TR: - status = i2c->STS2_B.TRFLG; - break; - case I2C_FLAG_BUSBSY: - status = i2c->STS2_B.BUSBSYFLG; - break; - case I2C_FLAG_MS: - status = i2c->STS2_B.MSFLG; - break; - case I2C_FLAG_SMBALT: - status = i2c->STS1_B.SMBALTFLG; - break; - case I2C_FLAG_TTE: - status = i2c->STS1_B.TTEFLG; - break; - case I2C_FLAG_PECE: - status = i2c->STS1_B.PECEFLG; - break; - case I2C_FLAG_OVRUR: - status = i2c->STS1_B.OVRURFLG; - break; - case I2C_FLAG_AE: - status = i2c->STS1_B.AEFLG; - break; - case I2C_FLAG_AL: - status = i2c->STS1_B.ALFLG; - break; - case I2C_FLAG_BERR: - status = i2c->STS1_B.BERRFLG; - break; - case I2C_FLAG_TXBE: - status = i2c->STS1_B.TXBEFLG; - break; - case I2C_FLAG_RXBNE: - status = i2c->STS1_B.RXBNEFLG; - break; - case I2C_FLAG_STOP: - status = i2c->STS1_B.STOPFLG; - break; - case I2C_FLAG_ADDR10: - status = i2c->STS1_B.ADDR10FLG; - break; - case I2C_FLAG_BTC: - status = i2c->STS1_B.BTCFLG; - break; - case I2C_FLAG_ADDR: - status = i2c->STS1_B.ADDRFLG; - break; - case I2C_FLAG_START: - status = i2c->STS1_B.STARTFLG; - break; - default: - break; + case I2C_FLAG_DUALADDR: + status = i2c->STS2_B.DUALADDRFLG; + break; + case I2C_FLAG_SMMHADDR: + status = i2c->STS2_B.SMMHADDR; + break; + case I2C_FLAG_SMBDADDR: + status = i2c->STS2_B.SMBDADDRFLG; + break; + case I2C_FLAG_GENCALL: + status = i2c->STS2_B.GENCALLFLG; + break; + case I2C_FLAG_TR: + status = i2c->STS2_B.TRFLG; + break; + case I2C_FLAG_BUSBSY: + status = i2c->STS2_B.BUSBSYFLG; + break; + case I2C_FLAG_MS: + status = i2c->STS2_B.MSFLG; + break; + case I2C_FLAG_SMBALT: + status = i2c->STS1_B.SMBALTFLG; + break; + case I2C_FLAG_TTE: + status = i2c->STS1_B.TTEFLG; + break; + case I2C_FLAG_PECE: + status = i2c->STS1_B.PECEFLG; + break; + case I2C_FLAG_OVRUR: + status = i2c->STS1_B.OVRURFLG; + break; + case I2C_FLAG_AE: + status = i2c->STS1_B.AEFLG; + break; + case I2C_FLAG_AL: + status = i2c->STS1_B.ALFLG; + break; + case I2C_FLAG_BERR: + status = i2c->STS1_B.BERRFLG; + break; + case I2C_FLAG_TXBE: + status = i2c->STS1_B.TXBEFLG; + break; + case I2C_FLAG_RXBNE: + status = i2c->STS1_B.RXBNEFLG; + break; + case I2C_FLAG_STOP: + status = i2c->STS1_B.STOPFLG; + break; + case I2C_FLAG_ADDR10: + status = i2c->STS1_B.ADDR10FLG; + break; + case I2C_FLAG_BTC: + status = i2c->STS1_B.BTCFLG; + break; + case I2C_FLAG_ADDR: + status = i2c->STS1_B.ADDRFLG; + break; + case I2C_FLAG_START: + status = i2c->STS1_B.STARTFLG; + break; + default: + break; } return status; } @@ -914,33 +915,33 @@ uint8_t I2C_ReadStatusFlag(I2C_T *i2c, I2C_FLAG_T flag) * a read operation to I2C_STS1 register (I2C_ReadStatusFlag()) * followed by a write operation to I2C_DATA register (I2C_TxData()). */ -void I2C_ClearStatusFlag(I2C_T *i2c, I2C_FLAG_T flag) +void I2C_ClearStatusFlag(I2C_T* i2c, I2C_FLAG_T flag) { switch (flag) { - case I2C_FLAG_SMBALT: - i2c->STS1_B.SMBALTFLG = BIT_RESET; - break; - case I2C_FLAG_TTE: - i2c->STS1_B.TTEFLG = BIT_RESET; - break; - case I2C_FLAG_PECE: - i2c->STS1_B.PECEFLG = BIT_RESET; - break; - case I2C_FLAG_OVRUR: - i2c->STS1_B.OVRURFLG = BIT_RESET; - break; - case I2C_FLAG_AE: - i2c->STS1_B.AEFLG = BIT_RESET; - break; - case I2C_FLAG_AL: - i2c->STS1_B.ALFLG = BIT_RESET; - break; - case I2C_FLAG_BERR: - i2c->STS1_B.BERRFLG = BIT_RESET; - break; - default: - break; + case I2C_FLAG_SMBALT: + i2c->STS1_B.SMBALTFLG = BIT_RESET; + break; + case I2C_FLAG_TTE: + i2c->STS1_B.TTEFLG = BIT_RESET; + break; + case I2C_FLAG_PECE: + i2c->STS1_B.PECEFLG = BIT_RESET; + break; + case I2C_FLAG_OVRUR: + i2c->STS1_B.OVRURFLG = BIT_RESET; + break; + case I2C_FLAG_AE: + i2c->STS1_B.AEFLG = BIT_RESET; + break; + case I2C_FLAG_AL: + i2c->STS1_B.ALFLG = BIT_RESET; + break; + case I2C_FLAG_BERR: + i2c->STS1_B.BERRFLG = BIT_RESET; + break; + default: + break; } } @@ -968,7 +969,7 @@ void I2C_ClearStatusFlag(I2C_T *i2c, I2C_FLAG_T flag) * * @retval Status: flag SET or RESET */ -uint8_t I2C_ReadIntFlag(I2C_T *i2c, I2C_INT_FLAG_T flag) +uint8_t I2C_ReadIntFlag(I2C_T* i2c, I2C_INT_FLAG_T flag) { uint32_t enablestatus = 0; @@ -1014,11 +1015,11 @@ uint8_t I2C_ReadIntFlag(I2C_T *i2c, I2C_INT_FLAG_T flag) * a read operation to I2C_STS1 register (I2C_ReadIntFlag()) * followed by a write operation to I2C_DATA register (I2C_TxData()). */ -void I2C_ClearIntFlag(I2C_T *i2c, uint32_t flag) +void I2C_ClearIntFlag(I2C_T* i2c, uint32_t flag) { i2c->STS1 = (uint16_t)~(flag & 0x00FFFFFF); } -/**@} end of group I2C_Fuctions*/ +/**@} end of group I2C_Functions*/ /**@} end of group I2C_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group APM32F10x_StdPeriphDriver*/ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_iwdt.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_iwdt.c index d3d64748a0..bd455c6147 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_iwdt.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_iwdt.c @@ -3,9 +3,9 @@ * * @brief This file provides all the IWDT firmware functions * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,9 +23,10 @@ * and limitations under the License. */ +/* Includes */ #include "apm32f10x_iwdt.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -33,7 +34,7 @@ @{ */ -/** @addtogroup IWDT_Fuctions Fuctions +/** @defgroup IWDT_Functions Functions @{ */ @@ -143,6 +144,6 @@ uint8_t IWDT_ReadStatusFlag(uint16_t flag) return bitStatus; } -/**@} end of group IWDT_Fuctions*/ -/**@} end of group IWDT_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group IWDT_Functions*/ +/**@} end of group IWDT_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver*/ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_misc.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_misc.c index e642f786bd..61f62d5ec3 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_misc.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_misc.c @@ -4,9 +4,9 @@ * @brief This file provides all the miscellaneous firmware functions. * Include NVIC,SystemTick and Power management. * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -16,7 +16,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,9 +24,10 @@ * and limitations under the License. */ +/* Includes */ #include "apm32f10x_misc.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ @@ -34,7 +35,7 @@ @{ */ -/** @addtogroup MISC_Macros Macros +/** @defgroup MISC_Macros Macros @{ */ @@ -43,7 +44,7 @@ /**@} end of group MISC_Macros*/ -/** @addtogroup MISC_Fuctions Fuctions +/** @defgroup MISC_Functions Functions @{ */ @@ -82,42 +83,42 @@ void NVIC_EnableIRQRequest(IRQn_Type irq, uint8_t preemptionPriority, uint8_t su uint32_t tempPriority, tempPrePri, tempSubPri; uint32_t priorityGrp; - /** Get priority group */ + /* Get priority group */ priorityGrp = (SCB->AIRCR) & (uint32_t)0x700U; - /** get pre-emption priority and subpriority */ + /* get pre-emption priority and subpriority */ switch (priorityGrp) { - case NVIC_PRIORITY_GROUP_0: - tempPrePri = 0; - tempSubPri = 4; - break; + case NVIC_PRIORITY_GROUP_0: + tempPrePri = 0; + tempSubPri = 4; + break; - case NVIC_PRIORITY_GROUP_1: - tempPrePri = 1; - tempSubPri = 3; - break; + case NVIC_PRIORITY_GROUP_1: + tempPrePri = 1; + tempSubPri = 3; + break; - case NVIC_PRIORITY_GROUP_2: - tempPrePri = 2; - tempSubPri = 2; - break; + case NVIC_PRIORITY_GROUP_2: + tempPrePri = 2; + tempSubPri = 2; + break; - case NVIC_PRIORITY_GROUP_3: - tempPrePri = 3; - tempSubPri = 1; - break; + case NVIC_PRIORITY_GROUP_3: + tempPrePri = 3; + tempSubPri = 1; + break; - case NVIC_PRIORITY_GROUP_4: - tempPrePri = 4; - tempSubPri = 0; - break; + case NVIC_PRIORITY_GROUP_4: + tempPrePri = 4; + tempSubPri = 0; + break; - default: - NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_0); - tempPrePri = 0; - tempSubPri = 4; - break; + default: + NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_0); + tempPrePri = 0; + tempSubPri = 4; + break; } tempPrePri = 4 - tempPrePri; @@ -127,7 +128,7 @@ void NVIC_EnableIRQRequest(IRQn_Type irq, uint8_t preemptionPriority, uint8_t su tempPriority <<= 4; NVIC->IP[irq] = (uint8_t)tempPriority; - /** enable the selected IRQ */ + /* enable the selected IRQ */ NVIC->ISER[irq >> 0x05U] = (uint32_t)0x01U << (irq & (uint8_t)0x1FU); } @@ -140,7 +141,7 @@ void NVIC_EnableIRQRequest(IRQn_Type irq, uint8_t preemptionPriority, uint8_t su */ void NVIC_DisableIRQRequest(IRQn_Type irq) { - /** disable the selected IRQ.*/ + /* disable the selected IRQ.*/ NVIC->ICER[irq >> 0x05U] = (uint32_t)0x01U << (irq & (uint8_t)0x1FU); } @@ -215,6 +216,6 @@ void SysTick_ConfigCLKSource(SYSTICK_CLK_SOURCE_T clkSource) } } -/**@} end of group MISC_Fuctions*/ -/**@} end of group MISC_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group MISC_Functions*/ +/**@} end of group MISC_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver*/ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_pmu.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_pmu.c index c57ff98cec..9c5d8d506b 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_pmu.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_pmu.c @@ -3,9 +3,9 @@ * * @brief This file provides all the PMU firmware functions. * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,18 +23,19 @@ * and limitations under the License. */ +/* Includes */ #include "apm32f10x_pmu.h" #include "apm32f10x_rcm.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ -/** @addtogroup PMU_Driver PMU Driver +/** @addtogroup PMU_Driver PMU Driver @{ */ -/** @addtogroup PMU_Fuctions Fuctions +/** @defgroup PMU_Functions Functions @{ */ @@ -102,7 +103,7 @@ void PMU_DisablePVD(void) /*! * @brief Configure a voltage threshold detected by a power supply voltage detector (PVD). * - * @param level£ºspecifies the PVD detection level + * @param level£ºspecifies the PVD detection level * This parameter can be one of the following values: * @arg PMU_PVD_LEVEL_2V2 : Config PVD detection level to 2.2V * @arg PMU_PVD_LEVEL_2V3 : Config PVD detection level to 2.3V @@ -118,9 +119,9 @@ void PMU_DisablePVD(void) void PMU_ConfigPVDLevel(PMU_PVD_LEVEL_T level) { - /** Clear PLS[7:5] bits */ + /* Clear PLS[7:5] bits */ PMU->CTRL_B.PLSEL = 0x0000; - /** Store the new value */ + /* Store the new value */ PMU->CTRL_B.PLSEL = level; } @@ -165,26 +166,26 @@ void PMU_DisableWakeUpPin(void) */ void PMU_EnterSTOPMode(PMU_REGULATOR_T regulator, PMU_STOP_ENTRY_T entry) { - /** Clear PDDSCFG and LPDSCFG bits */ + /* Clear PDDSCFG and LPDSCFG bits */ PMU->CTRL_B.PDDSCFG = 0x00; PMU->CTRL_B.LPDSCFG = 0x00; - /** Set LPDSCFG bit according to regulator value */ + /* Set LPDSCFG bit according to regulator value */ PMU->CTRL_B.LPDSCFG = regulator; - /** Set Cortex System Control Register */ + /* Set Cortex System Control Register */ SCB->SCR |= (uint32_t)0x04; - /** Select STOP mode entry*/ + /* Select STOP mode entry*/ if (entry == PMU_STOP_ENTRY_WFI) { - /** Request Wait For Interrupt */ + /* Request Wait For Interrupt */ __WFI(); } else { - /** Request Wait For Event */ + /* Request Wait For Event */ __WFE(); } - /** Reset SLEEPDEEP bit of Cortex System Control Register */ + /* Reset SLEEPDEEP bit of Cortex System Control Register */ SCB->SCR &= (uint32_t)~((uint32_t)0x04); } @@ -197,16 +198,16 @@ void PMU_EnterSTOPMode(PMU_REGULATOR_T regulator, PMU_STOP_ENTRY_T entry) */ void PMU_EnterSTANDBYMode(void) { - /** Clear Wake-up flag */ + /* Clear Wake-up flag */ PMU->CTRL_B.WUFLGCLR = BIT_SET; - /** Select STANDBY mode */ + /* Select STANDBY mode */ PMU->CTRL_B.PDDSCFG = BIT_SET; - /** Set Cortex System Control Register */ + /* Set Cortex System Control Register */ SCB->SCR |= (uint32_t)0x04; #if defined ( __CC_ARM ) __force_stores(); #endif - /** Request Wait For Interrupt */ + /* Request Wait For Interrupt */ __WFI(); } @@ -214,7 +215,7 @@ void PMU_EnterSTANDBYMode(void) /*! * @brief Read the specified PWR flag is set or not. * - * @param flag£ºReads the status of specifies the flag. + * @param flag£ºReads the status of specifies the flag. * This parameter can be one of the following values: * @arg PMU_FLAG_WUE : Wake Up flag * @arg PMU_FLAG_SB : StandBy flag @@ -244,7 +245,7 @@ uint8_t PMU_ReadStatusFlag(PMU_FLAG_T flag) /*! * @brief Clears the PWR's pending flags. * - * @param flag£ºClears the status of specifies the flag. + * @param flag£ºClears the status of specifies the flag. * This parameter can be one of the following values: * @arg PMU_FLAG_WUE : Wake Up flag * @arg PMU_FLAG_SB : StandBy flag @@ -263,6 +264,6 @@ void PMU_ClearStatusFlag(PMU_FLAG_T flag) } } -/**@} end of group PMU_Fuctions*/ -/**@} end of group PMU_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group PMU_Functions*/ +/**@} end of group PMU_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver*/ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_qspi.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_qspi.c index 2e3b694aa0..405301db8c 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_qspi.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_qspi.c @@ -3,9 +3,9 @@ * * @brief This file contains all the functions for the QSPI peripheral * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,18 +23,19 @@ * and limitations under the License. */ +/* Includes */ #if defined (APM32F10X_MD) || defined (APM32F10X_LD) #include "apm32f10x_qspi.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ -/** @addtogroup QSPI_Driver QSPI Driver +/** @addtogroup QSPI_Driver QSPI Driver @{ */ -/** @addtogroup QSPI_Fuctions Fuctions +/** @defgroup QSPI_Functions Functions @{ */ @@ -73,7 +74,7 @@ void QSPI_Reset(void) * * @retval None */ -void QSPI_Config(QSPI_Config_T *qspiConfig) +void QSPI_Config(QSPI_Config_T* qspiConfig) { QSPI->CTRL1_B.CPHA = qspiConfig->clockPhase; QSPI->CTRL1_B.CPOL = qspiConfig->clockPolarity; @@ -91,7 +92,7 @@ void QSPI_Config(QSPI_Config_T *qspiConfig) * * @retval None */ -void QSPI_ConfigStructInit(QSPI_Config_T *qspiConfig) +void QSPI_ConfigStructInit(QSPI_Config_T* qspiConfig) { qspiConfig->clockPhase = QSPI_CLKPHA_2EDGE; qspiConfig->clockPolarity = QSPI_CLKPOL_LOW; @@ -602,8 +603,8 @@ void QSPI_ClearIntFlag(uint32_t flag) dummy = QSPI->MIC; } } -#endif //defined APM32F10X_MD/LD -/**@} end of group QSPI_Fuctions*/ -/**@} end of group QSPI_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group QSPI_Functions*/ +/**@} end of group QSPI_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver*/ +#endif //defined APM32F10X_MD/LD diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_rcm.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_rcm.c index ac2db4e3f8..a90abbd0ad 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_rcm.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_rcm.c @@ -3,9 +3,9 @@ * * @brief This file provides all the RCM firmware functions * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,20 +25,21 @@ #include "apm32f10x_rcm.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ /** @addtogroup RCM_Driver RCM Driver + * @brief RCM driver modules @{ */ -/** @addtogroup RCM_Fuctions Fuctions +/** @defgroup RCM_Functions Functions @{ */ /*! - * @brief Resets the clock configuration to the default state + * @brief Reset the clock configuration to the default state * * @param None * @@ -46,22 +47,40 @@ */ void RCM_Reset(void) { - /** Open HSI clock */ + /* Open HSI clock */ RCM->CTRL_B.HSIEN = BIT_SET; - /** Config HSI to system clock and Reset AHBPSC, APB1PSC, APB2PSC, ADCPSC and MCOSEL bits */ + /* Configures HSI to system clock and Reset AHBPSC, APB1PSC, APB2PSC, ADCPSC and MCOSEL bits */ +#if defined(APM32F10X_CL) + RCM->CFG &= (uint32_t)0xF0FF0000; +#else RCM->CFG &= (uint32_t)0xF8FF0000; - /** Reset HSEEN, CSSEN and PLLEN bits */ +#endif + + /* Reset HSEEN, CSSEN and PLLEN bits */ RCM->CTRL &= (uint32_t)0xFEF6FFFF; - /** Reset HSEBCFG bit */ + /* Reset HSEBCFG bit */ RCM->CTRL_B.HSEBCFG = BIT_RESET; - /** Reset PLLSRCSEL, PLLHSEPSC, PLLMULCFG and USBDIV bits */ + /* Reset PLLSRCSEL, PLLHSEPSC, PLLMULCFG and USBDIV bits */ RCM->CFG &= (uint32_t)0xFF00FFFF; - /** Disable all interrupts and clear pending bits */ + +#if defined(APM32F10X_CL) + /* Reset PLL2EN and PLL3EN bits */ + RCM->CTRL_B.PLL2EN = BIT_RESET; + RCM->CTRL_B.PLL3EN = BIT_RESET; + + /* Disable all interrupts and clear pending bits */ + RCM->INT = 0x00FF0000; + + /* Reset CFG2 register */ + RCM->CFG2 = 0x00000000; +#else + /* Disable all interrupts and clear pending bits */ RCM->INT = 0x009F0000; +#endif } /*! - * @brief Configs the HSE oscillator + * @brief Configures the HSE oscillator * * @param state: state of the HSE * This parameter can be one of the following values: @@ -75,10 +94,10 @@ void RCM_Reset(void) */ void RCM_ConfigHSE(RCM_HSE_T state) { - /** Reset HSEEN bit */ + /* Reset HSEEN bit */ RCM->CTRL_B.HSEEN = BIT_RESET; - /** Reset HSEBCFG bit */ + /* Reset HSEBCFG bit */ RCM->CTRL_B.HSEBCFG = BIT_RESET; if (state == RCM_HSE_OPEN) @@ -93,7 +112,7 @@ void RCM_ConfigHSE(RCM_HSE_T state) } /*! - * @brief Waits for HSE to be ready + * @brief Wait for HSE to be ready * * @param None * @@ -116,7 +135,7 @@ uint8_t RCM_WaitHSEReady(void) } /*! - * @brief Config HSI trimming value + * @brief Configures HSI trimming value * * @param HSITrim: HSI trimming value * This parameter must be a number between 0 and 0x1F. @@ -183,7 +202,7 @@ void RCM_ConfigLSE(RCM_LSE_T state) } /*! - * @brief Enables the Internal Low Speed oscillator (LSI) + * @brief Enable the Internal Low Speed oscillator (LSI) * * @param None * @@ -195,7 +214,7 @@ void RCM_EnableLSI(void) } /*! - * @brief Disables the Internal Low Speed oscillator (LSI) + * @brief Disable the Internal Low Speed oscillator (LSI) * * @param None * @@ -207,16 +226,30 @@ void RCM_DisableLSI(void) } /*! - * @brief Configs the PLL clock source and multiplication factor + * @brief Configures the PLL clock source and multiplication factor * - * @param pllSelect: PLL entry clock source select - * This parameter can be one of the following values: - * @arg RCM_PLLSEL_HSI_DIV_2: HSI clock divided by 2 selected as PLL clock source - * @arg RCM_PLLSEL_HSE: HSE clock selected as PLL clock source - * @arg RCM_PLLSEL_HSE_DIV2: HSE clock divided by 2 selected as PLL clock source + * @param pllSelect: PLL entry clock source select + * This parameter can be one of the following values: + * For APM32F105xx and APM32F107xx devices: + * @arg RCM_PLLSEL_HSI_DIV_2: HSI clock divided by 2 selected as PLL clock source + * @arg RCM_PLLSEL_PREDIV1 : PLL prescaler 1 clock selected as PLL clock source + * For other devices: + * @arg RCM_PLLSEL_HSI_DIV_2: HSI clock divided by 2 selected as PLL clock source + * @arg RCM_PLLSEL_HSE : HSE clock selected as PLL clock source + * @arg RCM_PLLSEL_HSE_DIV2 : HSE clock divided by 2 selected as PLL clock source * - * @param pllMf: PLL multiplication factor - * This parameter can be RCM_PLLMF_x where x can be a value from 2 to 16. + * @param pllMf: PLL multiplication factor + * For APM32F105xx and APM32F107xx devices: + * This parameter can be one of the following values: + * @arg RCM_PLLMF_4 : PLL Multiplication Factor Configures to 4 + * @arg RCM_PLLMF_5 : PLL Multiplication Factor Configures to 5 + * @arg RCM_PLLMF_6 : PLL Multiplication Factor Configures to 6 + * @arg RCM_PLLMF_7 : PLL Multiplication Factor Configures to 7 + * @arg RCM_PLLMF_8 : PLL Multiplication Factor Configures to 8 + * @arg RCM_PLLMF_9 : PLL Multiplication Factor Configures to 9 + * @arg RCM_PLLMF_6_5: PLL Multiplication Factor Configures to 6.5 + * For other devices: + * This parameter can be RCM_PLLMF_x where x can be a value from 2 to 16. * * @retval None * @@ -224,13 +257,16 @@ void RCM_DisableLSI(void) */ void RCM_ConfigPLL(RCM_PLLSEL_T pllSelect, RCM_PLLMF_T pllMf) { - RCM->CFG_B.PLLMULCFG = pllMf; - RCM->CFG_B.PLLSRCSEL = pllSelect & 0x01; + RCM->CFG_B.PLL1MULCFG = pllMf; + RCM->CFG_B.PLL1SRCSEL = pllSelect & 0x01; + +#ifndef APM32F10X_CL RCM->CFG_B.PLLHSEPSC = (pllSelect >> 1) & 0x01; +#endif } /*! - * @brief Enables the PLL + * @brief Enable the PLL * * @param None * @@ -238,23 +274,139 @@ void RCM_ConfigPLL(RCM_PLLSEL_T pllSelect, RCM_PLLMF_T pllMf) */ void RCM_EnablePLL(void) { - RCM->CTRL_B.PLLEN = BIT_SET; + RCM->CTRL_B.PLL1EN = BIT_SET; } /*! -* @brief Disable the PLL -* -* @param None -* -* @retval None -* -* @note When PLL is not used as system clock, it can be stopped. -*/ + * @brief Disable the PLL + * + * @param None + * + * @retval None + * + * @note When PLL is not used as system clock, it can be stopped. + */ void RCM_DisablePLL(void) { - RCM->CTRL_B.PLLEN = BIT_RESET; + RCM->CTRL_B.PLL1EN = BIT_RESET; } +#if defined(APM32F10X_CL) +/*! + * @brief Enable the PLL2 + * + * @param None + * + * @retval None + */ +void RCM_EnablePLL2(void) +{ + RCM->CTRL_B.PLL2EN = BIT_SET; +} + +/*! + * @brief Disable the PLL2 + * + * @param None + * + * @retval None + */ +void RCM_DisablePLL2(void) +{ + RCM->CTRL_B.PLL2EN = BIT_RESET; +} + +/*! + * @brief Enable the PLL3 + * + * @param None + * + * @retval None + */ +void RCM_EnablePLL3(void) +{ + RCM->CTRL_B.PLL3EN = BIT_SET; +} + +/*! + * @brief Disable the PLL3 + * + * @param None + * + * @retval None + */ +void RCM_DisablePLL3(void) +{ + RCM->CTRL_B.PLL3EN = BIT_RESET; +} + +/*! + * @brief Configures the PLL prescaler 1 factor. + * + * @param pllPsc1Src: PLL prescaler 1 source select + * This parameter can be one of the following values: + * @arg RCM_PLLPSC1_SRC_HSE : HSE clock selected as PLL prescaler 1 clock source + * @arg RCM_PLLPSC1_SRC_PLL2: PLL2 clock selected as PLL prescaler 1 clock source + * + * @param pllPsc1: PLL prescaler 1 factor + * This parameter can be RCM_PLLPSC1_DIV_x where x can be a value from 1 to 16. + * + * @retval None + * + * @note PLL should be disabled while use this function. + */ +void RCM_ConfigPLLPSC1(RCM_PLLPSC1_SRC_T pllPsc1Src, RCM_PLLPSC1_DIV_T pllPsc1) +{ + RCM->CFG2_B.PLLPSC1SRC = pllPsc1Src; + RCM->CFG2_B.PLLPSC1 = pllPsc1; +} + +/*! + * @brief Configures the PLL prescaler 2 factor. + * + * @param pllpsc2: PLL prescaler 2 factor + * This parameter can be RCM_PLLPSC2_DIV_x where x can be a value from 1 to 16. + * + * @retval None + * + * @note PLL2 and PLL3 should be disabled while use this function. + */ +void RCM_ConfigPLLPSC2(RCM_PLLPSC2_DIV_T pllpsc2) +{ + RCM->CFG2_B.PLLPSC2 = pllpsc2; +} + +/*! + * @brief Configures the PLL2 clock multiplication factor + * + * @param pll2Mf: PLL2 multiplication factor + * This parameter can be RCM_PLL2MF_x where x can be a value from 8 to 14, and 16, 20. + * + * @retval None + * + * @note PLL2 should be disabled while use this function. + */ +void RCM_ConfigPLL2(RCM_PLL2MF_T pll2Mf) +{ + RCM->CFG2_B.PLL2MUL = pll2Mf; +} + +/*! + * @brief Configures the PLL3 clock multiplication factor + * + * @param pll3Mf: PLL3 multiplication factor + * This parameter can be RCM_PLL3MF_x where x can be a value from 8 to 14, and 16, 20. + * + * @retval None + * + * @note PLL3 should be disabled while use this function. + */ +void RCM_ConfigPLL3(RCM_PLL3MF_T pll3Mf) +{ + RCM->CFG2_B.PLL3MUL = pll3Mf; +} +#endif + /*! * @brief Enable the Clock Security System * @@ -280,15 +432,20 @@ void RCM_DisableCSS(void) } /*! - * @brief Selects the MCO pin clock ouput source + * @brief Select the MCO pin clock output source * * @param mcoClock: specifies the clock source to output * This parameter can be one of the following values: - * @arg RCM_MCOCLK_NO_CLOCK : No clock selected. - * @arg RCM_MCOCLK_SYSCLK : System clock selected. - * @arg RCM_MCOCLK_HSI : HSI oscillator clock selected. - * @arg RCM_MCOCLK_HSE : HSE oscillator clock selected. - * @arg RCM_MCOCLK_PLLCLK_DIV_2 : PLL clock divided by 2 selected. + * @arg RCM_MCOCLK_NO_CLOCK : No clock selected. + * @arg RCM_MCOCLK_SYSCLK : System clock selected. + * @arg RCM_MCOCLK_HSI : HSI oscillator clock selected. + * @arg RCM_MCOCLK_HSE : HSE oscillator clock selected. + * @arg RCM_MCOCLK_PLLCLK_DIV_2 : PLL clock divided by 2 selected. + * The following values is only for APM32F105xx or APM32F107xx: + * @arg RCM_MCOCLK_PLL2CLK : PLL2 clock selected. + * @arg RCM_MCOCLK_PLL3CLK_DIV_2 : PLL3 clock divided by 2 selected. + * @arg RCM_MCOCLK_OSCCLK : OSC clock selected. + * @arg RCM_MCOCLK_PLL3CLK : PLL3 clock selected. * * @retval None */ @@ -306,7 +463,7 @@ void RCM_ConfigMCO(RCM_MCOCLK_T mcoClock) * @arg RCM_SYSCLK_SEL_HSE: HSE is selected as system clock source * @arg RCM_SYSCLK_SEL_PLL: PLL is selected as system clock source * - * @retva None + * @retval None */ void RCM_ConfigSYSCLK(RCM_SYSCLK_SEL_T sysClkSelect) { @@ -314,7 +471,7 @@ void RCM_ConfigSYSCLK(RCM_SYSCLK_SEL_T sysClkSelect) } /*! - * @brief Returns the clock source which is used as system clock + * @brief Return the clock source which is used as system clock * * @param None * @@ -326,7 +483,7 @@ RCM_SYSCLK_SEL_T RCM_ReadSYSCLKSource(void) } /*! - * @brief Configs the AHB clock prescaler. + * @brief Configures the AHB clock prescaler. * * @param AHBDiv : Specifies the AHB clock prescaler from the system clock. * This parameter can be one of the following values: @@ -348,7 +505,7 @@ void RCM_ConfigAHB(RCM_AHB_DIV_T AHBDiv) } /*! - * @brief Configs the APB1 clock prescaler. + * @brief Configures the APB1 clock prescaler. * * @param APB1Div: Specifies the APB1 clock prescaler from the AHB clock. * This parameter can be one of the following values: @@ -366,7 +523,7 @@ void RCM_ConfigAPB1(RCM_APB_DIV_T APB1Div) } /*! - * @brief Configs the APB2 clock prescaler + * @brief Configures the APB2 clock prescaler * * @param APB2Div: Specifies the APB2 clock prescaler from the AHB clock. * This parameter can be one of the following values: @@ -383,8 +540,58 @@ void RCM_ConfigAPB2(RCM_APB_DIV_T APB2Div) RCM->CFG_B.APB2PSC = APB2Div; } +#if defined(APM32F10X_CL) /*! - * @brief Configs the USB clock prescaler + * @brief Configures the I2S2 clock source. + * + * @param i2s2ClkSelect: specifies the I2S2 clock source. + * This parameter can be one of the following values: + * @arg RCM_I2S2CLK_SYSCLK : I2S2CLK = System clock + * @arg RCM_I2S2CLK_DOUBLE_PLL3: I2S2CLK = Double PLL3 clock + * + * @retval None + * + * @note I2S2 clock source should be changed when I2S2 Clock is disabled. + */ +void RCM_ConfigI2S2CLK(RCM_I2S2CLK_T i2s2ClkSelect) +{ + RCM->CFG2_B.I2S2SRCSEL = i2s2ClkSelect; +} + +/*! + * @brief Configures the I2S3 clock source. + * + * @param i2s3ClkSelect: specifies the I2S3 clock source. + * This parameter can be one of the following values: + * @arg RCM_I2S3CLK_SYSCLK : I2S3CLK = System clock + * @arg RCM_I2S3CLK_DOUBLE_PLL3: I2S3CLK = Double PLL3 clock + * + * @retval None + * + * @note I2S3 clock source should be changed when I2S3 Clock is disabled. + */ +void RCM_ConfigI2S3CLK(RCM_I2S2CLK_T i2s3ClkSelect) +{ + RCM->CFG2_B.I2S3SRCSEL = i2s3ClkSelect; +} + +/*! + * @brief Configures the OTG FS clock prescaler + * + * @param OTGDiv: Specifies the OTG FS clock prescaler from the PLL clock. + * This parameter can be one of the following values: + * @arg RCM_OTGFS_DIV_1_5 : OTGFSCLK = PLL clock /1.5 + * @arg RCM_OTGFS_DIV_1 : OTGFSCLK = PLL clock + * + * @retval None + */ +void RCM_ConfigOTGFSCLK(RCM_OTGFS_DIV_T OTGDiv) +{ + RCM->CFG_B.OTGFSPSC = OTGDiv; +} +#else +/*! + * @brief Configures the USB clock prescaler * * @param USBDiv: Specifies the USB clock prescaler from the PLL clock. * This parameter can be one of the following values: @@ -401,7 +608,7 @@ void RCM_ConfigUSBCLK(RCM_USB_DIV_T USBDiv) } /*! - * @brief Configs the FPU clock prescaler + * @brief Configures the FPU clock prescaler * * @param FPUDiv: Specifies the FPU clock prescaler from the AHB clock. * This parameter can be one of the following values: @@ -414,9 +621,11 @@ void RCM_ConfigFPUCLK(RCM_FPU_DIV_T FPUDiv) { RCM->CFG_B.FPUPSC = FPUDiv; } +#endif + /*! - * @brief Configs the ADC clock prescaler + * @brief Configures the ADC clock prescaler * * @param ADCDiv : Specifies the ADC clock prescaler from the APB2 clock. * This parameter can be one of the following values: @@ -443,7 +652,7 @@ void RCM_ConfigADCCLK(RCM_PCLK2_DIV_T ADCDiv) * * @retval None * - * @note Once the RTC clock is configed it can't be changed unless reset the Backup domain. + * @note Once the RTC clock is configured it can't be changed unless reset the Backup domain. */ void RCM_ConfigRTCCLK(RCM_RTCCLK_T rtcClkSelect) { @@ -451,7 +660,7 @@ void RCM_ConfigRTCCLK(RCM_RTCCLK_T rtcClkSelect) } /*! - * @brief Enables the RTC clock + * @brief Enable the RTC clock * * @param None * @@ -463,7 +672,7 @@ void RCM_EnableRTCCLK(void) } /*! - * @brief Disables the RTC clock + * @brief Disable the RTC clock * * @param None * @@ -475,7 +684,7 @@ void RCM_DisableRTCCLK(void) } /*! - * @brief Reads the frequency of SYSCLK + * @brief Read the frequency of SYSCLK * * @param None * @@ -483,57 +692,102 @@ void RCM_DisableRTCCLK(void) */ uint32_t RCM_ReadSYSCLKFreq(void) { +#ifdef APM32F10X_CL + uint32_t sysClock, pllMull, pllSource, pll2Mull, pllPsc1, pllPsc2; +#else uint32_t sysClock, pllMull, pllSource; +#endif - /** get sys clock */ + /* get sys clock */ sysClock = RCM->CFG_B.SCLKSEL; switch (sysClock) { - /** sys clock is HSI */ - case RCM_SYSCLK_SEL_HSI: - sysClock = HSI_VALUE; - break; + /* sys clock is HSI */ + case RCM_SYSCLK_SEL_HSI: + sysClock = HSI_VALUE; + break; - /** sys clock is HSE */ - case RCM_SYSCLK_SEL_HSE: - sysClock = HSE_VALUE; - break; + /* sys clock is HSE */ + case RCM_SYSCLK_SEL_HSE: + sysClock = HSE_VALUE; + break; - /** sys clock is PLL */ - case RCM_SYSCLK_SEL_PLL: - pllMull = RCM->CFG_B.PLLMULCFG + 2; - pllSource = RCM->CFG_B.PLLSRCSEL; + /* sys clock is PLL */ + case RCM_SYSCLK_SEL_PLL: +#ifdef APM32F10X_CL + /* NOTE : PLL is the same as PLL1 */ + pllSource = RCM->CFG_B.PLL1SRCSEL; - /** PLL entry clock source is HSE */ - if (pllSource == BIT_SET) - { - sysClock = HSE_VALUE * pllMull; - - /** HSE clock divided by 2 */ - if (pllSource == RCM->CFG_B.PLLHSEPSC) + /* PLL entry clock source is HSE */ + if (pllSource) { - sysClock >>= 1; + /* PLLPSC1 prescaler factor */ + pllPsc1 = (RCM->CFG2_B.PLLPSC1 + 1); + + /* PLL entry clock source is PLL2 */ + if (RCM->CFG2_B.PLLPSC1SRC) + { + pll2Mull = (RCM->CFG2_B.PLL2MUL != 15) ? (RCM->CFG2_B.PLL2MUL + 2) : 20; + pllPsc2 = RCM->CFG2_B.PLLPSC2 + 1; + + pllSource = ((HSE_VALUE / pllPsc2) * pll2Mull) / pllPsc1; + } + /* PLL entry clock source is HSE */ + else + { + pllSource = HSE_VALUE / pllPsc1; + } + } + /* PLL entry clock source is HSI/2 */ + else + { + pllSource = HSI_VALUE >> 1; } - } - /** PLL entry clock source is HSI/2 */ - else - { - sysClock = (HSI_VALUE >> 1) * pllMull; - } - break; + pllMull = RCM->CFG_B.PLL1MULCFG; + if (pllMull == 13) + { + /* For 6.5 multiplication factor */ + sysClock = pllSource * pllMull / 2; + } + else + { + sysClock = pllSource * (pllMull + 2); + } +#else + pllMull = RCM->CFG_B.PLL1MULCFG + 2; + pllSource = RCM->CFG_B.PLL1SRCSEL; - default: - sysClock = HSI_VALUE; - break; + /* PLL entry clock source is HSE */ + if (pllSource == BIT_SET) + { + sysClock = HSE_VALUE * pllMull; + + /* HSE clock divided by 2 */ + if (pllSource == RCM->CFG_B.PLLHSEPSC) + { + sysClock >>= 1; + } + } + /* PLL entry clock source is HSI/2 */ + else + { + sysClock = (HSI_VALUE >> 1) * pllMull; + } +#endif + break; + + default: + sysClock = HSI_VALUE; + break; } return sysClock; } /*! - * @brief Reads the frequency of HCLK(AHB) + * @brief Read the frequency of HCLK(AHB) * * @param None * @@ -553,7 +807,7 @@ uint32_t RCM_ReadHCLKFreq(void) } /*! - * @brief Reads the frequency of PCLK1 And PCLK2 + * @brief Read the frequency of PCLK1 And PCLK2 * * @param PCLK1 : Return the frequency of PCLK1 * @@ -561,7 +815,7 @@ uint32_t RCM_ReadHCLKFreq(void) * * @retval None */ -void RCM_ReadPCLKFreq(uint32_t *PCLK1, uint32_t *PCLK2) +void RCM_ReadPCLKFreq(uint32_t* PCLK1, uint32_t* PCLK2) { uint32_t hclk, divider; uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; @@ -582,7 +836,7 @@ void RCM_ReadPCLKFreq(uint32_t *PCLK1, uint32_t *PCLK2) } /*! - * @brief Reads the frequency of ADCCLK + * @brief Read the frequency of ADCCLK * * @param None * @@ -595,7 +849,7 @@ uint32_t RCM_ReadADCCLKFreq(void) RCM_ReadPCLKFreq(NULL, &pclk2); - /** Get ADC CLK */ + /* Get ADC CLK */ divider = ADCPrescTable[RCM->CFG_B.ADCPSC]; adcClk = pclk2 / divider; @@ -603,19 +857,23 @@ uint32_t RCM_ReadADCCLKFreq(void) } /*! - * @brief Enables AHB peripheral clock. + * @brief Enable AHB peripheral clock. * * @param AHBPeriph : Enable the specifies clock of AHB peripheral. * This parameter can be any combination of the following values: - * @arg RCM_AHB_PERIPH_DMA1 : Enable DMA1 clock - * @arg RCM_AHB_PERIPH_DMA2 : Enable DMA2 clock (Only for High-density devices for APM32F103xx) - * @arg RCM_AHB_PERIPH_SRAM : Enable SRAM clock - * @arg RCM_AHB_PERIPH_FPU : Enable FPU clock - * @arg RCM_AHB_PERIPH_FMC : Enable FMC clock - * @arg RCM_AHB_PERIPH_QSPI : Enable QSPI clock - * @arg RCM_AHB_PERIPH_CRC : Enable CRC clock - * @arg RCM_AHB_PERIPH_EMMC : Enable EMMC clock (Only for High-density devices for APM32F103xx) - * @arg RCM_AHB_PERIPH_SDIO : Enable SDIO clock (Only for High-density devices for APM32F103xx) + * @arg RCM_AHB_PERIPH_DMA1 : Enable DMA1 clock + * @arg RCM_AHB_PERIPH_DMA2 : Enable DMA2 clock (Only for High-density devices for APM32F103xx) + * @arg RCM_AHB_PERIPH_SRAM : Enable SRAM clock + * @arg RCM_AHB_PERIPH_FPU : Enable FPU clock + * @arg RCM_AHB_PERIPH_FMC : Enable FMC clock + * @arg RCM_AHB_PERIPH_QSPI : Enable QSPI clock + * @arg RCM_AHB_PERIPH_CRC : Enable CRC clock + * @arg RCM_AHB_PERIPH_EMMC : Enable EMMC clock (Only for High-density devices for APM32F103xx) + * @arg RCM_AHB_PERIPH_SDIO : Enable SDIO clock (Only for High-density devices for APM32F103xx) + * @arg RCM_AHB_PERIPH_OTG_FS : Enable OTG FS clock (Only for APM32F105xx or APM32F107xx) + * @arg RCM_AHB_PERIPH_ETH_MAC : Enable Ethernet MAC clock (Only for APM32F105xx or APM32F107xx) + * @arg RCM_AHB_PERIPH_ETH_MAC_TX : Enable Ethernet MAC TX clock (Only for APM32F105xx or APM32F107xx) + * @arg RCM_AHB_PERIPH_ETH_MAC_RX : Enable Ethernet MAC RX clock (Only for APM32F105xx or APM32F107xx) * * @retval None */ @@ -627,17 +885,21 @@ void RCM_EnableAHBPeriphClock(uint32_t AHBPeriph) /*! * @brief Disable AHB peripheral clock. * - * @param AHBPeriph : Disable the specifies clock of AHB peripheral. + * @param AHBPeriph : Enable the specifies clock of AHB peripheral. * This parameter can be any combination of the following values: - * @arg RCM_AHB_PERIPH_DMA1 : Disable DMA1 clock - * @arg RCM_AHB_PERIPH_DMA2 : Disable DMA2 clock (Only for High-density devices for APM32F103xx) - * @arg RCM_AHB_PERIPH_SRAM : Disable SRAM clock - * @arg RCM_AHB_PERIPH_FPU : Disable FPU clock - * @arg RCM_AHB_PERIPH_FMC : Disable FMC clock - * @arg RCM_AHB_PERIPH_QSPI : Disable QSPI clock - * @arg RCM_AHB_PERIPH_CRC : Disable CRC clock - * @arg RCM_AHB_PERIPH_EMMC : Disable EMMC clock (Only for High-density devices for APM32F103xx) - * @arg RCM_AHB_PERIPH_SDIO : Disable SDIO clock (Only for High-density devices for APM32F103xx) + * @arg RCM_AHB_PERIPH_DMA1 : Disable DMA1 clock + * @arg RCM_AHB_PERIPH_DMA2 : Disable DMA2 clock (Only for High-density devices for APM32F103xx) + * @arg RCM_AHB_PERIPH_SRAM : Disable SRAM clock + * @arg RCM_AHB_PERIPH_FPU : Disable FPU clock + * @arg RCM_AHB_PERIPH_FMC : Disable FMC clock + * @arg RCM_AHB_PERIPH_QSPI : Disable QSPI clock + * @arg RCM_AHB_PERIPH_CRC : Disable CRC clock + * @arg RCM_AHB_PERIPH_EMMC : Disable EMMC clock (Only for High-density devices for APM32F103xx) + * @arg RCM_AHB_PERIPH_SDIO : Disable SDIO clock (Only for High-density devices for APM32F103xx) + * @arg RCM_AHB_PERIPH_OTG_FS : Disable OTG FS clock (Only for APM32F105xx or APM32F107xx) + * @arg RCM_AHB_PERIPH_ETH_MAC : Disable Ethernet MAC clock (Only for APM32F105xx or APM32F107xx) + * @arg RCM_AHB_PERIPH_ETH_MAC_TX : Disable Ethernet MAC TX clock (Only for APM32F105xx or APM32F107xx) + * @arg RCM_AHB_PERIPH_ETH_MAC_RX : Disable Ethernet MAC RX clock (Only for APM32F105xx or APM32F107xx) * * @retval None */ @@ -770,6 +1032,36 @@ void RCM_DisableAPB1PeriphClock(uint32_t APB1Periph) RCM->APB1CLKEN &= (uint32_t)~APB1Periph; } +#if defined(APM32F10X_CL) +/*! + * @brief Enable AHB peripheral reset + * + * @param AHBPeriph : Enable specifies AHB peripheral reset. + * This parameter can be any combination of the following values: + * @arg RCM_AHB_PERIPH_OTG_FS : Enable OTG FS reset + * @arg RCM_AHB_PERIPH_ETH_MAC : Enable ETH MAC reset * + * @retval None + */ +void RCM_EnableAHBPeriphReset(uint32_t AHBPeriph) +{ + RCM->AHBRST |= AHBPeriph; +} + +/*! + * @brief Disable AHB peripheral reset + * + * @param AHBPeriph : Disable specifies AHB peripheral reset. + * This parameter can be any combination of the following values: + * @arg RCM_AHB_PERIPH_OTG_FS : Disable OTG FS reset + * @arg RCM_AHB_PERIPH_ETH_MAC : Disable ETH MAC reset * + * @retval None + */ +void RCM_DisableAHBPeriphReset(uint32_t AHBPeriph) +{ + RCM->AHBRST &= (uint32_t)~AHBPeriph; +} +#endif + /*! * @brief Enable High Speed APB (APB2) peripheral reset * @@ -929,6 +1221,8 @@ void RCM_DisableBackupReset(void) * @arg RCM_INT_HSIRDY : HSI ready interrupt * @arg RCM_INT_HSERDY : HSE ready interrupt * @arg RCM_INT_PLLRDY : PLL ready interrupt + * @arg RCM_INT_PLL2RDY: PLL2 ready interrupt + * @arg RCM_INT_PLL3RDY: PLL3 ready interrupt * * @retval None */ @@ -966,11 +1260,13 @@ void RCM_DisableInterrupt(uint32_t interrupt) /*! * @brief Read the specified RCM flag status * - * @param flag : Returns specifies the flag status. + * @param flag : Return specifies the flag status. * This parameter can be one of the following values: * @arg RCM_FLAG_HSIRDY : HSI ready flag * @arg RCM_FLAG_HSERDY : HSE ready flag * @arg RCM_FLAG_PLLRDY : PLL ready flag + * @arg RCM_FLAG_PLL2RDY : PLL2 ready flag (Only for APM32F105xx or APM32F107xx) + * @arg RCM_FLAG_PLL3RDY : PLL3 ready flag (Only for APM32F105xx or APM32F107xx) * @arg RCM_FLAG_LSERDY : LSE ready flag * @arg RCM_FLAG_LSIRDY : LSI ready flag * @arg RCM_FLAG_PINRST : NRST PIN Reset Occur Flag @@ -992,20 +1288,20 @@ uint8_t RCM_ReadStatusFlag(RCM_FLAG_T flag) switch (reg) { - case 0: - reg = RCM->CTRL; - break; + case 0: + reg = RCM->CTRL; + break; - case 1: - reg = RCM->BDCTRL; - break; + case 1: + reg = RCM->BDCTRL; + break; - case 2: - reg = RCM->CSTS; - break; + case 2: + reg = RCM->CSTS; + break; - default: - break; + default: + break; } if (reg & bit) @@ -1017,7 +1313,7 @@ uint8_t RCM_ReadStatusFlag(RCM_FLAG_T flag) } /*! - * @brief Clears all the RCM reset flags + * @brief Clear all the RCM reset flags * * @param None * @@ -1033,33 +1329,37 @@ void RCM_ClearStatusFlag(void) } /*! - * @brief Reads the specified RCM interrupt Flag + * @brief Read the specified RCM interrupt Flag * - * @param flag £ºReads specifies RCM interrupt flag. + * @param flag ��Reads specifies RCM interrupt flag. * This parameter can be one of the following values: * @arg RCM_INT_LSIRDY : LSI ready interrupt flag * @arg RCM_INT_LSERDY : LSE ready interrupt flag * @arg RCM_INT_HSIRDY : HSI ready interrupt flag * @arg RCM_INT_HSERDY : HSE ready interrupt flag * @arg RCM_INT_PLLRDY : PLL ready interrupt flag + * @arg RCM_INT_PLL2RDY: PLL2 ready interrupt flag + * @arg RCM_INT_PLL3RDY: PLL3 ready interrupt flag * @arg RCM_INT_CSS : Clock Security System interrupt flag * * @retval The new state of intFlag (SET or RESET) */ uint8_t RCM_ReadIntFlag(RCM_INT_T flag) { - return (RCM->INT &flag) ? SET : RESET; + return (RCM->INT& flag) ? SET : RESET; } /*! - * @brief Clears the interrupt flag + * @brief Clear the interrupt flag * - * @param flag : Clears specifies interrupt flag. + * @param flag : Clear specifies interrupt flag. * @arg RCM_INT_LSIRDY : Clear LSI ready interrupt flag * @arg RCM_INT_LSERDY : Clear LSE ready interrupt flag * @arg RCM_INT_HSIRDY : Clear HSI ready interrupt flag * @arg RCM_INT_HSERDY : Clear HSE ready interrupt flag * @arg RCM_INT_PLLRDY : Clear PLL ready interrupt flag + * @arg RCM_INT_PLL2RDY: Clear PLL2 ready interrupt flag + * @arg RCM_INT_PLL3RDY: Clear PLL3 ready interrupt flag * @arg RCM_INT_CSS : Clear Clock Security System interrupt flag * * @retval None @@ -1072,6 +1372,6 @@ void RCM_ClearIntFlag(uint32_t flag) RCM->INT |= temp; } -/**@} end of group RCM_Fuctions*/ -/**@} end of group RCM_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group RCM_Functions */ +/**@} end of group RCM_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_rtc.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_rtc.c index d72487ede1..5f30bb993b 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_rtc.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_rtc.c @@ -3,9 +3,9 @@ * * @brief This file provides all the RTC firmware functions * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,24 +15,26 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions * and limitations under the License. */ + #include "apm32f10x_rtc.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ /** @addtogroup RTC_Driver RTC Driver + * @brief RTC driver modules @{ */ -/** @addtogroup RTC_Fuctions Fuctions +/** @defgroup RTC_Functions Functions @{ */ @@ -76,7 +78,7 @@ uint32_t RTC_ReadCounter(void) } /*! - * @brief Config the RTC counter value. + * @brief Configures the RTC counter value. * * @param value: RTC counter new value. * @@ -91,7 +93,7 @@ void RTC_ConfigCounter(uint32_t value) } /*! - * @brief Config the RTC prescaler value. + * @brief Configures the RTC prescaler value. * * @param value: RTC prescaler new value. * @@ -106,7 +108,7 @@ void RTC_ConfigPrescaler(uint32_t value) } /*! - * @brief Config the RTC alarm value. + * @brief Configures the RTC alarm value. * * @param value: RTC alarm new value. * @@ -121,7 +123,7 @@ void RTC_ConfigAlarm(uint32_t value) } /*! - * @brief Reads the RTC divider value. + * @brief Read the RTC divider value. * * @param None * @@ -150,7 +152,7 @@ void RTC_WaitForLastTask(void) } /*! - * @brief Waits until the RTC registers + * @brief Waits until the RTC registers Synchronized. * * @param None * @@ -258,6 +260,6 @@ void RTC_ClearIntFlag(uint16_t flag) RTC->CSTS &= (uint32_t)~flag; } -/**@} end of group RTC_Fuctions*/ -/**@} end of group RTC_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group RTC_Functions */ +/**@} end of group RTC_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_sci2c.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_sci2c.c index 9c7f865592..3e5995d616 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_sci2c.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_sci2c.c @@ -3,9 +3,9 @@ * * @brief This file contains all the functions for the SCI2C peripheral * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,26 +26,27 @@ #include "apm32f10x_sci2c.h" #include "apm32f10x_rcm.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ /** @addtogroup SCI2C_Driver SCI2C Driver + * @brief SCI2C driver modules @{ */ -/** @addtogroup SCI2C_Fuctions Fuctions +/** @defgroup SCI2C_Functions Functions @{ */ /*! * @brief Set I2C peripheral registers to their default reset values * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @retval None */ -void SCI2C_Reset(SCI2C_T *i2c) +void SCI2C_Reset(SCI2C_T* i2c) { if (i2c == I2C3) { @@ -64,7 +65,7 @@ void SCI2C_Reset(SCI2C_T *i2c) } /*! - * @brief Config the I2C peripheral according to the specified parameters in the sci2cConfig + * @brief Configures the I2C peripheral according to the specified parameters in the sci2cConfig * * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 * @@ -72,7 +73,7 @@ void SCI2C_Reset(SCI2C_T *i2c) * * @retval None */ -void SCI2C_Config(SCI2C_T *i2c, SCI2C_Config_T *sci2cConfig) +void SCI2C_Config(SCI2C_T* i2c, SCI2C_Config_T* sci2cConfig) { i2c->SW = BIT_SET; @@ -122,7 +123,7 @@ void SCI2C_Config(SCI2C_T *i2c, SCI2C_Config_T *sci2cConfig) * * @retval None */ -void SCI2C_ConfigStructInit(SCI2C_Config_T *sci2cConfig) +void SCI2C_ConfigStructInit(SCI2C_Config_T* sci2cConfig) { sci2cConfig->addrMode = SCI2C_ADDR_MODE_7BIT; sci2cConfig->slaveAddr = 0x55; @@ -138,7 +139,7 @@ void SCI2C_ConfigStructInit(SCI2C_Config_T *sci2cConfig) /*! * @brief Read specified flag * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param flag: Specifies the flag to be checked * The parameter can be one of following values: @@ -155,7 +156,7 @@ void SCI2C_ConfigStructInit(SCI2C_Config_T *sci2cConfig) * * @retval The new state of flag (SET or RESET) */ -uint8_t SCI2C_ReadStatusFlag(SCI2C_T *i2c, SCI2C_FLAG_T flag) +uint8_t SCI2C_ReadStatusFlag(SCI2C_T* i2c, SCI2C_FLAG_T flag) { uint8_t ret = RESET; @@ -174,7 +175,7 @@ uint8_t SCI2C_ReadStatusFlag(SCI2C_T *i2c, SCI2C_FLAG_T flag) /*! * @brief Read specified interrupt flag * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param flag: Specifies the interrupt flag to be checked * The parameter can be one of following values: @@ -195,7 +196,7 @@ uint8_t SCI2C_ReadStatusFlag(SCI2C_T *i2c, SCI2C_FLAG_T flag) * * @retval The new state of flag (SET or RESET) */ -uint8_t SCI2C_ReadIntFlag(SCI2C_T *i2c, SCI2C_INT_T flag) +uint8_t SCI2C_ReadIntFlag(SCI2C_T* i2c, SCI2C_INT_T flag) { uint8_t ret = RESET; @@ -207,7 +208,7 @@ uint8_t SCI2C_ReadIntFlag(SCI2C_T *i2c, SCI2C_INT_T flag) /*! * @brief Clear specified interrupt flag * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param flag: Specifies the interrupt flag to be checked * The parameter can be one of following values: @@ -224,7 +225,7 @@ uint8_t SCI2C_ReadIntFlag(SCI2C_T *i2c, SCI2C_INT_T flag) * @arg SCI2C_INT_ALL: All interrupt flag * @retval The new state of flag (SET or RESET) */ -void SCI2C_ClearIntFlag(SCI2C_T *i2c, SCI2C_INT_T flag) +void SCI2C_ClearIntFlag(SCI2C_T* i2c, SCI2C_INT_T flag) { volatile uint32_t dummy = 0; @@ -277,7 +278,7 @@ void SCI2C_ClearIntFlag(SCI2C_T *i2c, SCI2C_INT_T flag) /*! * @brief Read specified interrupt flag(Raw register) * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param flag: Specifies the interrupt flag to be checked * The parameter can be one of following values: @@ -298,7 +299,7 @@ void SCI2C_ClearIntFlag(SCI2C_T *i2c, SCI2C_INT_T flag) * * @retval The new state of flag (SET or RESET) */ -uint8_t SCI2C_ReadRawIntFlag(SCI2C_T *i2c, SCI2C_INT_T flag) +uint8_t SCI2C_ReadRawIntFlag(SCI2C_T* i2c, SCI2C_INT_T flag) { uint8_t ret = RESET; @@ -310,7 +311,7 @@ uint8_t SCI2C_ReadRawIntFlag(SCI2C_T *i2c, SCI2C_INT_T flag) /*! * @brief Enable the specified interrupts * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param interrupt: Specifies the interrupt sources * The parameter can be any combination of following values: @@ -331,7 +332,7 @@ uint8_t SCI2C_ReadRawIntFlag(SCI2C_T *i2c, SCI2C_INT_T flag) * * @retval None */ -void SCI2C_EnableInterrupt(SCI2C_T *i2c, uint16_t interrupt) +void SCI2C_EnableInterrupt(SCI2C_T* i2c, uint16_t interrupt) { i2c->INTEN |= interrupt; } @@ -339,7 +340,7 @@ void SCI2C_EnableInterrupt(SCI2C_T *i2c, uint16_t interrupt) /*! * @brief Disable the specified interrupts * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param interrupt: Specifies the interrupt sources * The parameter can be any combination of following values: @@ -360,7 +361,7 @@ void SCI2C_EnableInterrupt(SCI2C_T *i2c, uint16_t interrupt) * * @retval None */ -void SCI2C_DisableInterrupt(SCI2C_T *i2c, uint16_t interrupt) +void SCI2C_DisableInterrupt(SCI2C_T* i2c, uint16_t interrupt) { i2c->INTEN &= ~interrupt; } @@ -368,9 +369,9 @@ void SCI2C_DisableInterrupt(SCI2C_T *i2c, uint16_t interrupt) /*! * @brief Enable stop detected only master in activity. * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 */ -void SCI2C_EnableStopDetectMasterActivity(SCI2C_T *i2c) +void SCI2C_EnableStopDetectMasterActivity(SCI2C_T* i2c) { i2c->CTRL1_B.DSMA = BIT_SET; } @@ -378,9 +379,9 @@ void SCI2C_EnableStopDetectMasterActivity(SCI2C_T *i2c) /*! * @brief Disable stop detected only master in activity. * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 */ -void SCI2C_DisableStopDetectMasterActivity(SCI2C_T *i2c) +void SCI2C_DisableStopDetectMasterActivity(SCI2C_T* i2c) { i2c->CTRL1_B.DSMA = BIT_RESET; } @@ -388,9 +389,9 @@ void SCI2C_DisableStopDetectMasterActivity(SCI2C_T *i2c) /*! * @brief Enable stop detected only address is matched in slave mode. * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 */ -void SCI2C_EnableStopDetectAddressed(SCI2C_T *i2c) +void SCI2C_EnableStopDetectAddressed(SCI2C_T* i2c) { i2c->CTRL1_B.DSA = BIT_SET; } @@ -398,9 +399,9 @@ void SCI2C_EnableStopDetectAddressed(SCI2C_T *i2c) /*! * @brief Disable stop detected only address is matched in slave mode. * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 */ -void SCI2C_DisableStopDetectAddressed(SCI2C_T *i2c) +void SCI2C_DisableStopDetectAddressed(SCI2C_T* i2c) { i2c->CTRL1_B.DSA = BIT_RESET; } @@ -408,11 +409,11 @@ void SCI2C_DisableStopDetectAddressed(SCI2C_T *i2c) /*! * @brief Enable restart * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @retval None */ -void SCI2C_EnableRestart(SCI2C_T *i2c) +void SCI2C_EnableRestart(SCI2C_T* i2c) { i2c->CTRL1_B.RSTAEN = BIT_SET; } @@ -420,19 +421,19 @@ void SCI2C_EnableRestart(SCI2C_T *i2c) /*! * @brief Disable restart * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @retval None */ -void SCI2C_DisableRestart(SCI2C_T *i2c) +void SCI2C_DisableRestart(SCI2C_T* i2c) { i2c->CTRL1_B.RSTAEN = BIT_RESET; } /*! - * @brief Config speed. + * @brief Configures speed. * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param speed: Specifies the speed. * @arg SCI2C_SPEED_STANDARD: Standard speed. @@ -441,15 +442,15 @@ void SCI2C_DisableRestart(SCI2C_T *i2c) * * @retval None */ -void SCI2C_ConfigSpeed(SCI2C_T *i2c, SCI2C_SPEED_T speed) +void SCI2C_ConfigSpeed(SCI2C_T* i2c, SCI2C_SPEED_T speed) { i2c->CTRL1_B.SPD = speed; } /*! - * @brief Config master address. + * @brief Configures master address. * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param mode: Specifies the address mode. * @arg SCI2C_ADDR_MODE_7BIT: 7-bit address mode. @@ -459,7 +460,7 @@ void SCI2C_ConfigSpeed(SCI2C_T *i2c, SCI2C_SPEED_T speed) * * @retval None */ -void SCI2C_ConfigMasterAddr(SCI2C_T *i2c, SCI2C_ADDR_MODE_T mode, uint16_t addr) +void SCI2C_ConfigMasterAddr(SCI2C_T* i2c, SCI2C_ADDR_MODE_T mode, uint16_t addr) { i2c->TARADDR_B.MAM = mode; i2c->TARADDR_B.ADDR = addr; @@ -467,7 +468,7 @@ void SCI2C_ConfigMasterAddr(SCI2C_T *i2c, SCI2C_ADDR_MODE_T mode, uint16_t addr) /*! - * @brief Config slave address. + * @brief Configures slave address. * * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 * @@ -479,7 +480,7 @@ void SCI2C_ConfigMasterAddr(SCI2C_T *i2c, SCI2C_ADDR_MODE_T mode, uint16_t addr) * * @retval None */ -void SCI2C_ConfigSlaveAddr(SCI2C_T *i2c, SCI2C_ADDR_MODE_T mode, uint16_t addr) +void SCI2C_ConfigSlaveAddr(SCI2C_T* i2c, SCI2C_ADDR_MODE_T mode, uint16_t addr) { i2c->CTRL1_B.SAM = mode; i2c->SLAADDR = addr; @@ -488,11 +489,11 @@ void SCI2C_ConfigSlaveAddr(SCI2C_T *i2c, SCI2C_ADDR_MODE_T mode, uint16_t addr) /*! * @brief Enable master mode * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @retval None */ -void SCI2C_EnableMasterMode(SCI2C_T *i2c) +void SCI2C_EnableMasterMode(SCI2C_T* i2c) { i2c->CTRL1_B.MST = BIT_SET; } @@ -500,11 +501,11 @@ void SCI2C_EnableMasterMode(SCI2C_T *i2c) /*! * @brief Disable master mode * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @retval None */ -void SCI2C_DisableMasterMode(SCI2C_T *i2c) +void SCI2C_DisableMasterMode(SCI2C_T* i2c) { i2c->CTRL1_B.MST = BIT_RESET; } @@ -512,11 +513,11 @@ void SCI2C_DisableMasterMode(SCI2C_T *i2c) /*! * @brief Enable slave mode * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @retval None */ -void SCI2C_EnableSlaveMode(SCI2C_T *i2c) +void SCI2C_EnableSlaveMode(SCI2C_T* i2c) { i2c->CTRL1_B.SLADIS = BIT_RESET; } @@ -524,11 +525,11 @@ void SCI2C_EnableSlaveMode(SCI2C_T *i2c) /*! * @brief Disable slave mode * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @retval None */ -void SCI2C_DisableSlaveMode(SCI2C_T *i2c) +void SCI2C_DisableSlaveMode(SCI2C_T* i2c) { i2c->CTRL1_B.SLADIS = BIT_SET; } @@ -536,13 +537,13 @@ void SCI2C_DisableSlaveMode(SCI2C_T *i2c) /*! * @brief Config master code * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param code: Master code * * @retval None */ -void SCI2C_ConfigMasterCode(SCI2C_T *i2c, uint8_t code) +void SCI2C_ConfigMasterCode(SCI2C_T* i2c, uint8_t code) { i2c->HSMC = code; } @@ -550,7 +551,7 @@ void SCI2C_ConfigMasterCode(SCI2C_T *i2c, uint8_t code) /*! * @brief Config data direction * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param dir: Data direction * @arg SCI2C_DATA_DIR_WRITE: Write data @@ -558,7 +559,7 @@ void SCI2C_ConfigMasterCode(SCI2C_T *i2c, uint8_t code) * * @retval None */ -void SCI2C_ConfigDataDir(SCI2C_T *i2c, SCI2C_DATA_DIR_T dir) +void SCI2C_ConfigDataDir(SCI2C_T* i2c, SCI2C_DATA_DIR_T dir) { i2c->DATA = (uint32_t)(dir << 8); } @@ -566,13 +567,13 @@ void SCI2C_ConfigDataDir(SCI2C_T *i2c, SCI2C_DATA_DIR_T dir) /*! * @brief Transmit data * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param data: Data to be transmited * * @retval None */ -void SCI2C_TxData(SCI2C_T *i2c, uint8_t data) +void SCI2C_TxData(SCI2C_T* i2c, uint8_t data) { i2c->DATA_B.DATA = data; } @@ -580,20 +581,20 @@ void SCI2C_TxData(SCI2C_T *i2c, uint8_t data) /*! * @brief Returns the most recent received data * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @retval Received data * */ -uint8_t SCI2C_RxData(SCI2C_T *i2c) +uint8_t SCI2C_RxData(SCI2C_T* i2c) { return (uint8_t)(i2c->DATA & 0XFF); } /*! - * @brief Config data register + * @brief Configures data register * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param stop: Enable or disable generate stop condition * @@ -605,7 +606,7 @@ uint8_t SCI2C_RxData(SCI2C_T *i2c) * * @retval None */ -void SCI2C_ConfigDataRegister(SCI2C_T *i2c, SCI2C_STOP_T stop, SCI2C_DATA_DIR_T dataDir, uint8_t data) +void SCI2C_ConfigDataRegister(SCI2C_T* i2c, SCI2C_STOP_T stop, SCI2C_DATA_DIR_T dataDir, uint8_t data) { i2c->DATA = (uint32_t)((stop << 9) | (dataDir << 8) | data); } @@ -613,11 +614,11 @@ void SCI2C_ConfigDataRegister(SCI2C_T *i2c, SCI2C_STOP_T stop, SCI2C_DATA_DIR_T /*! * @brief Read Rx FIFO data number * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @retval None */ -uint8_t SCI2C_ReadRxFifoDataCnt(SCI2C_T *i2c) +uint8_t SCI2C_ReadRxFifoDataCnt(SCI2C_T* i2c) { return (uint8_t)i2c->RFL; } @@ -625,39 +626,39 @@ uint8_t SCI2C_ReadRxFifoDataCnt(SCI2C_T *i2c) /*! * @brief Read Tx FIFO data number * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @retval None */ -uint8_t SCI2C_ReadTxFifoDataCnt(SCI2C_T *i2c) +uint8_t SCI2C_ReadTxFifoDataCnt(SCI2C_T* i2c) { return (uint8_t)i2c->TFL; } /*! - * @brief Config Rx FIFO threshold + * @brief Configures Rx FIFO threshold * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param threshold: FIFO threshold * * @retval None */ -void SCI2C_ConfigRxFifoThreshold(SCI2C_T *i2c, uint8_t threshold) +void SCI2C_ConfigRxFifoThreshold(SCI2C_T* i2c, uint8_t threshold) { i2c->RFT = threshold; } /*! - * @brief Config Tx FIFO threshold + * @brief Configures Tx FIFO threshold * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param threshold: FIFO threshold * * @retval None */ -void SCI2C_ConfigTxFifoThreshold(SCI2C_T *i2c, uint8_t threshold) +void SCI2C_ConfigTxFifoThreshold(SCI2C_T* i2c, uint8_t threshold) { i2c->TFT = threshold; } @@ -665,12 +666,12 @@ void SCI2C_ConfigTxFifoThreshold(SCI2C_T *i2c, uint8_t threshold) /*! * @brief Enable I2C peripheral * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @retval None */ -void SCI2C_Enable(SCI2C_T *i2c) +void SCI2C_Enable(SCI2C_T* i2c) { i2c->CTRL2_B.I2CEN = BIT_SET; } @@ -678,11 +679,11 @@ void SCI2C_Enable(SCI2C_T *i2c) /*! * @brief Disable I2C peripheral * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @retval None */ -void SCI2C_Disable(SCI2C_T *i2c) +void SCI2C_Disable(SCI2C_T* i2c) { i2c->CTRL2_B.I2CEN = BIT_RESET; } @@ -690,11 +691,11 @@ void SCI2C_Disable(SCI2C_T *i2c) /*! * @brief Abort I2C transmit * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @retval None */ -void SCI2C_Abort(SCI2C_T *i2c) +void SCI2C_Abort(SCI2C_T* i2c) { i2c->CTRL2_B.ABR = BIT_SET; } @@ -702,21 +703,21 @@ void SCI2C_Abort(SCI2C_T *i2c) /*! * @brief Tx command block * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param enable: ENABLE or DISABLE * * @retval None */ -void SCI2C_BlockTxCmd(SCI2C_T *i2c, uint8_t enable) +void SCI2C_BlockTxCmd(SCI2C_T* i2c, uint8_t enable) { i2c->CTRL2_B.TCB = enable; } /*! - * @brief Config SCL high and low period + * @brief Configures SCL high and low period * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param speed: Specifies the speed. * @arg SCI2C_SPEED_STANDARD: Standard speed. @@ -729,7 +730,7 @@ void SCI2C_BlockTxCmd(SCI2C_T *i2c, uint8_t enable) * * @retval None */ -void SCI2C_ConfigClkPeriod(SCI2C_T *i2c, SCI2C_SPEED_T speed, uint16_t highPeriod, uint16_t lowPeriod) +void SCI2C_ConfigClkPeriod(SCI2C_T* i2c, SCI2C_SPEED_T speed, uint16_t highPeriod, uint16_t lowPeriod) { if (speed == SCI2C_SPEED_STANDARD) { @@ -749,9 +750,9 @@ void SCI2C_ConfigClkPeriod(SCI2C_T *i2c, SCI2C_SPEED_T speed, uint16_t highPerio } /*! - * @brief Config SDA hold time length + * @brief Configures SDA hold time length * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param txHold: Tx SDA hold time length * @@ -759,22 +760,22 @@ void SCI2C_ConfigClkPeriod(SCI2C_T *i2c, SCI2C_SPEED_T speed, uint16_t highPerio * * @retval None */ -void SCI2C_ConfigSDAHoldTime(SCI2C_T *i2c, uint16_t txHold, uint8_t rxHold) +void SCI2C_ConfigSDAHoldTime(SCI2C_T* i2c, uint16_t txHold, uint8_t rxHold) { i2c->SDAHOLD_B.TXHOLD = txHold; i2c->SDAHOLD_B.RXHOLD = rxHold; } /*! - * @brief Config SDA delay time + * @brief Configures SDA delay time * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param delay: SDA delay time * * @retval None */ -void SCI2C_ConfigSDADelayTime(SCI2C_T *i2c, uint8_t delay) +void SCI2C_ConfigSDADelayTime(SCI2C_T* i2c, uint8_t delay) { i2c->SDADLY = delay; } @@ -782,13 +783,13 @@ void SCI2C_ConfigSDADelayTime(SCI2C_T *i2c, uint8_t delay) /*! * @brief Enable or disable generate gernal call ack * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param enable: SDA delay time * * @retval None */ -void SCI2C_GernalCallAck(SCI2C_T *i2c, uint8_t enable) +void SCI2C_GernalCallAck(SCI2C_T* i2c, uint8_t enable) { i2c->GCA = enable; } @@ -796,13 +797,13 @@ void SCI2C_GernalCallAck(SCI2C_T *i2c, uint8_t enable) /*! * @brief When received data no ack generated in slave mode. * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param enable: ENABLE or DISABLE * * @retval None */ -void SCI2C_SlaveDataNackOnly(SCI2C_T *i2c, uint8_t enable) +void SCI2C_SlaveDataNackOnly(SCI2C_T* i2c, uint8_t enable) { i2c->SDNO = enable; } @@ -810,11 +811,11 @@ void SCI2C_SlaveDataNackOnly(SCI2C_T *i2c, uint8_t enable) /*! * @brief Read Tx abort source * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @retval Return Tx abort source */ -uint32_t SCI2C_ReadTxAbortSource(SCI2C_T *i2c) +uint32_t SCI2C_ReadTxAbortSource(SCI2C_T* i2c) { return (uint32_t)i2c->TAS; } @@ -822,7 +823,7 @@ uint32_t SCI2C_ReadTxAbortSource(SCI2C_T *i2c) /*! * @brief Enable DMA * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param dma: DMA requst source * @arg SCI2C_DMA_RX: DMA RX channel @@ -830,7 +831,7 @@ uint32_t SCI2C_ReadTxAbortSource(SCI2C_T *i2c) * * @retval None */ -void SCI2C_EnableDMA(SCI2C_T *i2c, SCI2C_DMA_T dma) +void SCI2C_EnableDMA(SCI2C_T* i2c, SCI2C_DMA_T dma) { i2c->DMACTRL |= dma; } @@ -838,7 +839,7 @@ void SCI2C_EnableDMA(SCI2C_T *i2c, SCI2C_DMA_T dma) /*! * @brief Disable DMA * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param dma: DMA requst source * @arg SCI2C_DMA_RX: DMA RX channel @@ -846,43 +847,43 @@ void SCI2C_EnableDMA(SCI2C_T *i2c, SCI2C_DMA_T dma) * * @retval None */ -void SCI2C_DisableDMA(SCI2C_T *i2c, SCI2C_DMA_T dma) +void SCI2C_DisableDMA(SCI2C_T* i2c, SCI2C_DMA_T dma) { i2c->DMACTRL &= (uint32_t)~dma; } /*! - * @brief Config DMA Tx data level + * @brief Configures DMA Tx data level * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param cnt: DMA Tx data level * * @retval None */ -void SCI2C_ConfigDMATxDataLevel(SCI2C_T *i2c, uint8_t cnt) +void SCI2C_ConfigDMATxDataLevel(SCI2C_T* i2c, uint8_t cnt) { i2c->DTDL = cnt; } /*! - * @brief Config DMA Rx data level + * @brief Configures DMA Rx data level * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param cnt: DMA Rx data level * * @retval None */ -void SCI2C_ConfigDMARxDataLevel(SCI2C_T *i2c, uint8_t cnt) +void SCI2C_ConfigDMARxDataLevel(SCI2C_T* i2c, uint8_t cnt) { i2c->DRDL = cnt; } /*! - * @brief Config spike suppressio limit + * @brief Configures spike suppressio limit * - * @param i2c: Select the the I2C peripheral.It can be I2C3 or I2C4 + * @param i2c: Select the the I2C peripheral. It can be I2C3 or I2C4 * * @param speed: I2C speed mode * @arg SCI2C_SPEED_STANDARD: Standard speed. @@ -893,7 +894,7 @@ void SCI2C_ConfigDMARxDataLevel(SCI2C_T *i2c, uint8_t cnt) * * @retval None */ -void SCI2C_ConfigSpikeSuppressionLimit(SCI2C_T *i2c, SCI2C_SPEED_T speed, uint8_t limit) +void SCI2C_ConfigSpikeSuppressionLimit(SCI2C_T* i2c, SCI2C_SPEED_T speed, uint8_t limit) { if (speed == SCI2C_SPEED_HIGH) { @@ -905,6 +906,6 @@ void SCI2C_ConfigSpikeSuppressionLimit(SCI2C_T *i2c, SCI2C_SPEED_T speed, uint8_ } } -/**@} end of group SCI2C_Fuctions*/ -/**@} end of group SCI2C_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group SCI2C_Functions */ +/**@} end of group SCI2C_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_sdio.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_sdio.c index 691352116c..0e26f4319c 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_sdio.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_sdio.c @@ -1,11 +1,11 @@ /*! * @file apm32f10x_sdio.c * - * @brief This file provides all the SDIO firmware functions + * @brief This file provides all the SDIO firmware functions * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,24 +26,25 @@ #include "apm32f10x_sdio.h" #include "apm32f10x_rcm.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ /** @addtogroup SDIO_Driver SDIO Driver + * @brief SDIO driver modules @{ */ -/** @addtogroup SDIO_Fuctions Fuctions +/** @defgroup SDIO_Functions Functions @{ */ /*! - * @brief Reset sdio peripheral registers to their default reset values + * @brief Reset sdio peripheral registers to their default reset values * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_Reset(void) { @@ -59,13 +60,13 @@ void SDIO_Reset(void) } /*! - * @brief Config the SDIO peripheral according to the specified parameters in the sdioConfig + * @brief Configures the SDIO peripheral according to the specified parameters in the sdioConfig * - * @param sdioConfig: pointer to a SDIO_Config_T structure + * @param sdioConfig: pointer to a SDIO_Config_T structure * - * @retval None + * @retval None */ -void SDIO_Config(SDIO_Config_T *sdioConfig) +void SDIO_Config(SDIO_Config_T* sdioConfig) { uint32_t tmp = 0; @@ -79,13 +80,13 @@ void SDIO_Config(SDIO_Config_T *sdioConfig) } /*! - * @brief Fills each SDIO_Config_T member with its default value + * @brief Fills each SDIO_Config_T member with its default value * - * @param sdioConfig: pointer to a SDIO_Config_T structure + * @param sdioConfig: pointer to a SDIO_Config_T structure * - * @retval None + * @retval None */ -void SDIO_ConfigStructInit(SDIO_Config_T *sdioConfig) +void SDIO_ConfigStructInit(SDIO_Config_T* sdioConfig) { sdioConfig->clockDiv = 0x00; sdioConfig->clockEdge = SDIO_CLOCK_EDGE_RISING; @@ -96,33 +97,33 @@ void SDIO_ConfigStructInit(SDIO_Config_T *sdioConfig) } /*! - * @brief Enables the SDIO clock + * @brief Enable the SDIO clock * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_EnableClock(void) { - *(__IO uint32_t *) CLKCTRL_CLKEN_BB = (uint32_t)SET; + *(__IO uint32_t*) CLKCTRL_CLKEN_BB = (uint32_t)SET; } /*! - * @brief Disables the SDIO clock + * @brief Disable the SDIO clock * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_DisableClock(void) { - *(__IO uint32_t *) CLKCTRL_CLKEN_BB = (uint32_t)RESET; + *(__IO uint32_t*) CLKCTRL_CLKEN_BB = (uint32_t)RESET; } /*! - * @brief Sets the power status of the controller + * @brief Set the power status of the controller * - * @param powerState: new state of the Power state + * @param powerState: new state of the Power state * The parameter can be one of following values: * @arg SDIO_POWER_STATE_OFF * @arg SDIO_POWER_STATE_ON @@ -135,13 +136,13 @@ void SDIO_ConfigPowerState(SDIO_POWER_STATE_T powerState) } /*! - * @brief Reads the SDIO power state + * @brief Read the SDIO power state * - * @param None + * @param None * - * @retval The new state SDIO power + * @retval The new state SDIO power * - * @note 0x00:Power OFF, 0x02:Power UP, 0x03:Power ON + * @note 0x00:Power OFF, 0x02:Power UP, 0x03:Power ON */ uint32_t SDIO_ReadPowerState(void) { @@ -149,38 +150,38 @@ uint32_t SDIO_ReadPowerState(void) } /*! - * @brief Enables the SDIO DMA request + * @brief Enable the SDIO DMA request * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_EnableDMA(void) { - *(__IO uint32_t *) DCTRL_DMAEN_BB = (uint32_t)SET; + *(__IO uint32_t*) DCTRL_DMAEN_BB = (uint32_t)SET; } /*! - * @brief Disables the SDIO DMA request + * @brief Disable the SDIO DMA request * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_DisableDMA(void) { - *(__IO uint32_t *) DCTRL_DMAEN_BB = (uint32_t)RESET; + *(__IO uint32_t*) DCTRL_DMAEN_BB = (uint32_t)RESET; } /*! - * @brief Configs the SDIO Command and send the command + * @brief Configures the SDIO Command and send the command * - * @param cmdConfig: pointer to a SDIO_CmdConfig_T structure + * @param cmdConfig: pointer to a SDIO_CmdConfig_T structure * - * @retval None + * @retval None * */ -void SDIO_TxCommand(SDIO_CmdConfig_T *cmdConfig) +void SDIO_TxCommand(SDIO_CmdConfig_T* cmdConfig) { uint32_t tmpreg = 0; @@ -193,14 +194,14 @@ void SDIO_TxCommand(SDIO_CmdConfig_T *cmdConfig) } /*! - * @brief Fills each SDIO_CMD_ConfigStruct_T member with its default value + * @brief Fills each SDIO_CMD_ConfigStruct_T member with its default value * - * @param cmdConfig: pointer to a SDIO_CmdConfig_T structure + * @param cmdConfig: pointer to a SDIO_CmdConfig_T structure * - * @retval None + * @retval None * */ -void SDIO_TxCommandStructInit(SDIO_CmdConfig_T *cmdConfig) +void SDIO_TxCommandStructInit(SDIO_CmdConfig_T* cmdConfig) { cmdConfig->argument = 0x00; cmdConfig->cmdIndex = 0x00; @@ -210,11 +211,11 @@ void SDIO_TxCommandStructInit(SDIO_CmdConfig_T *cmdConfig) } /*! - * @brief Reads the SDIO command response + * @brief Read the SDIO command response * - * @param None + * @param None * - * @retval The command index of the last command response received + * @retval The command index of the last command response received * */ uint8_t SDIO_ReadCommandResponse(void) @@ -223,16 +224,16 @@ uint8_t SDIO_ReadCommandResponse(void) } /*! - * @brief Reads the SDIO response + * @brief Read the SDIO response * - * @param res: Specifies the SDIO response register + * @param res: Specifies the SDIO response register * The parameter can be one of following values: * @arg SDIO_RES1: Response Register 1 * @arg SDIO_RES2: Response Register 2 * @arg SDIO_RES3: Response Register 3 * @arg SDIO_RES4: Response Register 4 * - * @retval The Corresponding response register value + * @retval The Corresponding response register value */ uint32_t SDIO_ReadResponse(SDIO_RES_T res) { @@ -240,17 +241,17 @@ uint32_t SDIO_ReadResponse(SDIO_RES_T res) tmp = ((uint32_t)(SDIO_BASE + 0x14)) + res; - return (*(__IO uint32_t *) tmp); + return (*(__IO uint32_t*) tmp); } /*! - * @brief Configs the SDIO Dataaccording to the specified parameters in the dataConfig + * @brief Configures the SDIO Dataaccording to the specified parameters in the dataConfig * - * @param dataConfig: pointer to a SDIO_DataConfig_T structure + * @param dataConfig: pointer to a SDIO_DataConfig_T structure * - * @retval None + * @retval None */ -void SDIO_ConfigData(SDIO_DataConfig_T *dataConfig) +void SDIO_ConfigData(SDIO_DataConfig_T* dataConfig) { uint32_t tmpreg = 0; @@ -269,13 +270,13 @@ void SDIO_ConfigData(SDIO_DataConfig_T *dataConfig) } /*! - * @brief Fills each SDIO_DataConfig_T member with its default value + * @brief Fills each SDIO_DataConfig_T member with its default value * - * @param dataConfig: pointer to a SDIO_DataConfig_T structure + * @param dataConfig: pointer to a SDIO_DataConfig_T structure * - * @retval None + * @retval None */ -void SDIO_ConfigDataStructInit(SDIO_DataConfig_T *dataConfig) +void SDIO_ConfigDataStructInit(SDIO_DataConfig_T* dataConfig) { dataConfig->dataTimeOut = 0xFFFFFFFF; dataConfig->dataLength = 0x00; @@ -286,11 +287,11 @@ void SDIO_ConfigDataStructInit(SDIO_DataConfig_T *dataConfig) } /*! - * @brief Reads the SDIO Data counter + * @brief Read the SDIO Data counter * - * @param None + * @param None * - * @retval The SDIO Data counter value + * @retval The SDIO Data counter value */ uint32_t SDIO_ReadDataCounter(void) { @@ -298,11 +299,11 @@ uint32_t SDIO_ReadDataCounter(void) } /*! - * @brief Write the SDIO Data + * @brief Write the SDIO Data * - * @param Data£ºWrite 32-bit data + * @param Data: Write 32-bit data * - * @retval None + * @retval None */ void SDIO_WriteData(uint32_t data) { @@ -310,11 +311,11 @@ void SDIO_WriteData(uint32_t data) } /*! - * @brief Reads the SDIO Data + * @brief Read the SDIO Data * - * @param None + * @param None * - * @retval The SDIO FIFO Data value + * @retval The SDIO FIFO Data value */ uint32_t SDIO_ReadData(void) { @@ -322,11 +323,11 @@ uint32_t SDIO_ReadData(void) } /*! - * @brief Reads the SDIO FIFO count value + * @brief Read the SDIO FIFO count value * - * @param None + * @param None * - * @retval The SDIO FIFO count value + * @retval The SDIO FIFO count value */ uint32_t SDIO_ReadFIFOCount(void) { @@ -334,217 +335,217 @@ uint32_t SDIO_ReadFIFOCount(void) } /*! - * @brief Enables SDIO start read wait + * @brief Enable SDIO start read wait * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_EnableStartReadWait(void) { - *(__IO uint32_t *) DCTRL_RWSTR_BB = (uint32_t) SET; + *(__IO uint32_t*) DCTRL_RWSTR_BB = (uint32_t) SET; } /*! - * @brief Disables SDIO start read wait + * @brief Disable SDIO start read wait * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_DisableStopReadWait(void) { - *(__IO uint32_t *) DCTRL_RWSTR_BB = (uint32_t) RESET; + *(__IO uint32_t*) DCTRL_RWSTR_BB = (uint32_t) RESET; } /*! - * @brief Enables SDIO stop read wait + * @brief Enable SDIO stop read wait * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_EnableStopReadWait(void) { - *(__IO uint32_t *) DCTRL_RWSTOP_BB = (uint32_t) SET; + *(__IO uint32_t*) DCTRL_RWSTOP_BB = (uint32_t) SET; } /*! - * @brief Disables SDIO stop read wait + * @brief Disable SDIO stop read wait * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_DisableStartReadWait(void) { - *(__IO uint32_t *) DCTRL_RWSTOP_BB = (uint32_t) RESET; + *(__IO uint32_t*) DCTRL_RWSTOP_BB = (uint32_t) RESET; } /*! - * @brief Sets the read wait interval + * @brief Set the read wait interval * - * @param readWaitMode: SDIO read Wait Mode + * @param readWaitMode: SDIO read Wait Mode * The parameter can be one of following values: * @arg SDIO_READ_WAIT_MODE_CLK: Read Wait control by stopping SDIOCLK * @arg SDIO_READ_WAIT_MODE_DATA2: Read Wait control using SDIO_DATA2 * - * @retval None + * @retval None * */ void SDIO_ConfigSDIOReadWaitMode(SDIO_READ_WAIT_MODE_T readWaitMode) { - *(__IO uint32_t *) DCTRL_RDWAIT_BB = readWaitMode; + *(__IO uint32_t*) DCTRL_RDWAIT_BB = readWaitMode; } /*! - * @brief Enables SDIO SD I/O Mode Operation + * @brief Enable SDIO SD I/O Mode Operation * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_EnableSDIO(void) { - *(__IO uint32_t *) DCTRL_SDIOF_BB = (uint32_t)SET; + *(__IO uint32_t*) DCTRL_SDIOF_BB = (uint32_t)SET; } /*! - * @brief Disables SDIO SD I/O Mode Operation + * @brief Disable SDIO SD I/O Mode Operation * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_DisableSDIO(void) { - *(__IO uint32_t *) DCTRL_SDIOF_BB = (uint32_t)RESET; + *(__IO uint32_t*) DCTRL_SDIOF_BB = (uint32_t)RESET; } /*! - * @brief Ensables SDIO SD I/O Mode suspend command sending + * @brief Enable SDIO SD I/O Mode suspend command sending * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_EnableTxSDIOSuspend(void) { - *(__IO uint32_t *) CMD_SDIOSC_BB = (uint32_t)SET; + *(__IO uint32_t*) CMD_SDIOSC_BB = (uint32_t)SET; } /*! - * @brief Disables SDIO SD I/O Mode suspend command sending + * @brief Disable SDIO SD I/O Mode suspend command sending * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_DisableTxSDIOSuspend(void) { - *(__IO uint32_t *) CMD_SDIOSC_BB = (uint32_t)RESET; + *(__IO uint32_t*) CMD_SDIOSC_BB = (uint32_t)RESET; } /*! - * @brief Enables the command completion signal + * @brief Enable the command completion signal * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_EnableCommandCompletion(void) { - *(__IO uint32_t *) CMD_CMDCPEN_BB = (uint32_t)SET; + *(__IO uint32_t*) CMD_CMDCPEN_BB = (uint32_t)SET; } /*! - * @brief Disables the command completion signal + * @brief Disable the command completion signal * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_DisableCommandCompletion(void) { - *(__IO uint32_t *) CMD_CMDCPEN_BB = (uint32_t)RESET; + *(__IO uint32_t*) CMD_CMDCPEN_BB = (uint32_t)RESET; } /*! - * @brief Enables the CE-ATA interrupt + * @brief Enable the CE-ATA interrupt * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_EnableCEATAInterrupt(void) { - *(__IO uint32_t *) CMD_INTEN_BB = (uint32_t)((~((uint32_t)SET)) & ((uint32_t)0x1)); + *(__IO uint32_t*) CMD_INTEN_BB = (uint32_t)((~((uint32_t)SET)) & ((uint32_t)0x1)); } /*! - * @brief Disables the CE-ATA interrupt + * @brief Disable the CE-ATA interrupt * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_DisableCEATAInterrupt(void) { - *(__IO uint32_t *) CMD_INTEN_BB = (uint32_t)((~((uint32_t)RESET)) & ((uint32_t)0x1)); + *(__IO uint32_t*) CMD_INTEN_BB = (uint32_t)((~((uint32_t)RESET)) & ((uint32_t)0x1)); } /*! - * @brief Ensables Sends CE-ATA command + * @brief Enable Sends CE-ATA command * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_EnableTxCEATA(void) { - *(__IO uint32_t *) CMD_ATACMD_BB = (uint32_t)SET; + *(__IO uint32_t*) CMD_ATACMD_BB = (uint32_t)SET; } /*! - * @brief Disables Sends CE-ATA command + * @brief Disable Sends CE-ATA command * - * @param None + * @param None * - * @retval None + * @retval None */ void SDIO_DisableTxCEATA(void) { - *(__IO uint32_t *) CMD_ATACMD_BB = (uint32_t)RESET; + *(__IO uint32_t*) CMD_ATACMD_BB = (uint32_t)RESET; } /*! - * @brief Enables the specified SDIO interrupt + * @brief Enable the specified SDIO interrupt * * @param interrupt: Select the SDIO interrupt source - * The parameter can be any combination of following values: - * @arg SDIO_INT_COMRESP: Command response received (CRC check failed) interrupt - * @arg SDIO_INT_DBDR: Data block sent/received (CRC check failed) interrupt - * @arg SDIO_INT_CMDRESTO: Command response timeout interrupt - * @arg SDIO_INT_DATATO: Data timeout interrupt - * @arg SDIO_INT_TXUDRER: Transmit FIFO underrun error interrupt - * @arg SDIO_INT_RXOVRER: Received FIFO overrun error interrupt - * @arg SDIO_INT_CMDRES: Command response received (CRC check passed) interrupt - * @arg SDIO_INT_CMDSENT: Command sent (no response required) interrupt - * @arg SDIO_INT_DATAEND: Data end (data counter is zero) interrupt - * @arg SDIO_INT_SBE: Start bit not detected on all data signals in wide bus mode interrupt - * @arg SDIO_INT_DBCP: Data block sent/received (CRC check passed) interrupt - * @arg SDIO_INT_CMDACT: Command transfer in progress interrupt - * @arg SDIO_INT_TXACT: Data transmit in progress interrupt - * @arg SDIO_INT_RXACT: Data receive in progress interrupt - * @arg SDIO_INT_TXFHF: Transmit FIFO Half Empty interrupt - * @arg SDIO_INT_RXFHF: Receive FIFO Half Full interrupt - * @arg SDIO_INT_TXFF: Transmit FIFO full interrupt - * @arg SDIO_INT_RXFF: Receive FIFO full interrupt - * @arg SDIO_INT_TXFE: Transmit FIFO empty interrupt - * @arg SDIO_INT_RXFE: Receive FIFO empty interrupt - * @arg SDIO_INT_TXDA: Data available in transmit FIFO interrupt - * @arg SDIO_INT_RXDA: Data available in receive FIFO interrupt - * @arg SDIO_INT_SDIOINT: SD I/O interrupt received interrupt - * @arg SDIO_INT_ATAEND: CE-ATA command completion signal received for CMD61 interrupt + * The parameter can be any combination of following values: + * @arg SDIO_INT_COMRESP: Command response received (CRC check failed) interrupt + * @arg SDIO_INT_DBDR: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_INT_CMDRESTO: Command response timeout interrupt + * @arg SDIO_INT_DATATO: Data timeout interrupt + * @arg SDIO_INT_TXUDRER: Transmit FIFO underrun error interrupt + * @arg SDIO_INT_RXOVRER: Received FIFO overrun error interrupt + * @arg SDIO_INT_CMDRES: Command response received (CRC check passed) interrupt + * @arg SDIO_INT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_INT_DATAEND: Data end (data counter is zero) interrupt + * @arg SDIO_INT_SBE: Start bit not detected on all data signals in wide bus mode interrupt + * @arg SDIO_INT_DBCP: Data block sent/received (CRC check passed) interrupt + * @arg SDIO_INT_CMDACT: Command transfer in progress interrupt + * @arg SDIO_INT_TXACT: Data transmit in progress interrupt + * @arg SDIO_INT_RXACT: Data receive in progress interrupt + * @arg SDIO_INT_TXFHF: Transmit FIFO Half Empty interrupt + * @arg SDIO_INT_RXFHF: Receive FIFO Half Full interrupt + * @arg SDIO_INT_TXFF: Transmit FIFO full interrupt + * @arg SDIO_INT_RXFF: Receive FIFO full interrupt + * @arg SDIO_INT_TXFE: Transmit FIFO empty interrupt + * @arg SDIO_INT_RXFE: Receive FIFO empty interrupt + * @arg SDIO_INT_TXDA: Data available in transmit FIFO interrupt + * @arg SDIO_INT_RXDA: Data available in receive FIFO interrupt + * @arg SDIO_INT_SDIOINT: SD I/O interrupt received interrupt + * @arg SDIO_INT_ATAEND: CE-ATA command completion signal received for CMD61 interrupt * @retval None */ void SDIO_EnableInterrupt(uint32_t interrupt) @@ -553,34 +554,34 @@ void SDIO_EnableInterrupt(uint32_t interrupt) } /*! - * @brief Disables the specified SDIO interrupt + * @brief Disable the specified SDIO interrupt * * @param interrupt: Select the SDIO interrupt source - * The parameter can be any combination of following values: - * @arg SDIO_INT_COMRESP: Command response received (CRC check failed) interrupt - * @arg SDIO_INT_DBDR: Data block sent/received (CRC check failed) interrupt - * @arg SDIO_INT_CMDRESTO: Command response timeout interrupt - * @arg SDIO_INT_DATATO: Data timeout interrupt - * @arg SDIO_INT_TXUDRER: Transmit FIFO underrun error interrupt - * @arg SDIO_INT_RXOVRER: Received FIFO overrun error interrupt - * @arg SDIO_INT_CMDRES: Command response received (CRC check passed) interrupt - * @arg SDIO_INT_CMDSENT: Command sent (no response required) interrupt - * @arg SDIO_INT_DATAEND: Data end (data counter is zero) interrupt - * @arg SDIO_INT_SBE: Start bit not detected on all data signals in wide bus mode interrupt - * @arg SDIO_INT_DBCP: Data block sent/received (CRC check passed) interrupt - * @arg SDIO_INT_CMDACT: Command transfer in progress interrupt - * @arg SDIO_INT_TXACT: Data transmit in progress interrupt - * @arg SDIO_INT_RXACT: Data receive in progress interrupt - * @arg SDIO_INT_TXFHF: Transmit FIFO Half Empty interrupt - * @arg SDIO_INT_RXFHF: Receive FIFO Half Full interrupt - * @arg SDIO_INT_TXFF: Transmit FIFO full interrupt - * @arg SDIO_INT_RXFF: Receive FIFO full interrupt - * @arg SDIO_INT_TXFE: Transmit FIFO empty interrupt - * @arg SDIO_INT_RXFE: Receive FIFO empty interrupt - * @arg SDIO_INT_TXDA: Data available in transmit FIFO interrupt - * @arg SDIO_INT_RXDA: Data available in receive FIFO interrupt - * @arg SDIO_INT_SDIOINT: SD I/O interrupt received interrupt - * @arg SDIO_INT_ATAEND: CE-ATA command completion signal received for CMD61 interrupt + * The parameter can be any combination of following values: + * @arg SDIO_INT_COMRESP: Command response received (CRC check failed) interrupt + * @arg SDIO_INT_DBDR: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_INT_CMDRESTO: Command response timeout interrupt + * @arg SDIO_INT_DATATO: Data timeout interrupt + * @arg SDIO_INT_TXUDRER: Transmit FIFO underrun error interrupt + * @arg SDIO_INT_RXOVRER: Received FIFO overrun error interrupt + * @arg SDIO_INT_CMDRES: Command response received (CRC check passed) interrupt + * @arg SDIO_INT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_INT_DATAEND: Data end (data counter is zero) interrupt + * @arg SDIO_INT_SBE: Start bit not detected on all data signals in wide bus mode interrupt + * @arg SDIO_INT_DBCP: Data block sent/received (CRC check passed) interrupt + * @arg SDIO_INT_CMDACT: Command transfer in progress interrupt + * @arg SDIO_INT_TXACT: Data transmit in progress interrupt + * @arg SDIO_INT_RXACT: Data receive in progress interrupt + * @arg SDIO_INT_TXFHF: Transmit FIFO Half Empty interrupt + * @arg SDIO_INT_RXFHF: Receive FIFO Half Full interrupt + * @arg SDIO_INT_TXFF: Transmit FIFO full interrupt + * @arg SDIO_INT_RXFF: Receive FIFO full interrupt + * @arg SDIO_INT_TXFE: Transmit FIFO empty interrupt + * @arg SDIO_INT_RXFE: Receive FIFO empty interrupt + * @arg SDIO_INT_TXDA: Data available in transmit FIFO interrupt + * @arg SDIO_INT_RXDA: Data available in receive FIFO interrupt + * @arg SDIO_INT_SDIOINT: SD I/O interrupt received interrupt + * @arg SDIO_INT_ATAEND: CE-ATA command completion signal received for CMD61 interrupt * @retval None */ void SDIO_DisableInterrupt(uint32_t interrupt) @@ -589,34 +590,34 @@ void SDIO_DisableInterrupt(uint32_t interrupt) } /*! - * @brief Reads the specified SDIO flag + * @brief Read the specified SDIO flag * * @param flag: Select the flag to read - * The parameter can be one of following values: - * @arg SDIO_FLAG_COMRESP: Command response received (CRC check failed) flag - * @arg SDIO_FLAG_DBDR: Data block sent/received (CRC check failed) flag - * @arg SDIO_FLAG_CMDRESTO: Command response timeout flag - * @arg SDIO_FLAG_DATATO: Data timeout flag - * @arg SDIO_FLAG_TXUDRER: Transmit FIFO underrun error flag - * @arg SDIO_FLAG_RXOVRER: Received FIFO overrun error flag - * @arg SDIO_FLAG_CMDRES: Command response received (CRC check passed) flag - * @arg SDIO_FLAG_CMDSENT: Command sent (no response required) flag - * @arg SDIO_FLAG_DATAEND: Data end (data counter is zero) flag - * @arg SDIO_FLAG_SBE: Start bit not detected on all data signals in wide bus mode flag - * @arg SDIO_FLAG_DBCP: Data block sent/received (CRC check passed) flag - * @arg SDIO_FLAG_CMDACT: Command transfer in progress flag - * @arg SDIO_FLAG_TXACT: Data transmit in progress flag - * @arg SDIO_FLAG_RXACT: Data receive in progress flag - * @arg SDIO_FLAG_TXFHF: Transmit FIFO Half Empty flag - * @arg SDIO_FLAG_RXFHF: Receive FIFO Half Full flag - * @arg SDIO_FLAG_TXFF: Transmit FIFO full flag - * @arg SDIO_FLAG_RXFF: Receive FIFO full flag - * @arg SDIO_FLAG_TXFE: Transmit FIFO empty flag - * @arg SDIO_FLAG_RXFE: Receive FIFO empty flag - * @arg SDIO_FLAG_TXDA: Data available in transmit FIFO flag - * @arg SDIO_FLAG_RXDA: Data available in receive FIFO flag - * @arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag - * @arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received for CMD61 flag + * The parameter can be one of following values: + * @arg SDIO_FLAG_COMRESP: Command response received (CRC check failed) flag + * @arg SDIO_FLAG_DBDR: Data block sent/received (CRC check failed) flag + * @arg SDIO_FLAG_CMDRESTO: Command response timeout flag + * @arg SDIO_FLAG_DATATO: Data timeout flag + * @arg SDIO_FLAG_TXUDRER: Transmit FIFO underrun error flag + * @arg SDIO_FLAG_RXOVRER: Received FIFO overrun error flag + * @arg SDIO_FLAG_CMDRES: Command response received (CRC check passed) flag + * @arg SDIO_FLAG_CMDSENT: Command sent (no response required) flag + * @arg SDIO_FLAG_DATAEND: Data end (data counter is zero) flag + * @arg SDIO_FLAG_SBE: Start bit not detected on all data signals in wide bus mode flag + * @arg SDIO_FLAG_DBCP: Data block sent/received (CRC check passed) flag + * @arg SDIO_FLAG_CMDACT: Command transfer in progress flag + * @arg SDIO_FLAG_TXACT: Data transmit in progress flag + * @arg SDIO_FLAG_RXACT: Data receive in progress flag + * @arg SDIO_FLAG_TXFHF: Transmit FIFO Half Empty flag + * @arg SDIO_FLAG_RXFHF: Receive FIFO Half Full flag + * @arg SDIO_FLAG_TXFF: Transmit FIFO full flag + * @arg SDIO_FLAG_RXFF: Receive FIFO full flag + * @arg SDIO_FLAG_TXFE: Transmit FIFO empty flag + * @arg SDIO_FLAG_RXFE: Receive FIFO empty flag + * @arg SDIO_FLAG_TXDA: Data available in transmit FIFO flag + * @arg SDIO_FLAG_RXDA: Data available in receive FIFO flag + * @arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag + * @arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received for CMD61 flag * * @retval SET or RESET */ @@ -626,23 +627,23 @@ uint8_t SDIO_ReadStatusFlag(SDIO_FLAG_T flag) } /*! - * @brief Clears the specified SDIO flag + * @brief Clear the specified SDIO flag * * @param flag: Select the flag to clear - * The parameter can be any combination of following values: - * @arg SDIO_FLAG_COMRESP: Command response received (CRC check failed) flag - * @arg SDIO_FLAG_DBDR: Data block sent/received (CRC check failed) flag - * @arg SDIO_FLAG_CMDRESTO: Command response timeout flag - * @arg SDIO_FLAG_DATATO: Data timeout flag - * @arg SDIO_FLAG_TXUDRER: Transmit FIFO underrun error flag - * @arg SDIO_FLAG_RXOVRER: Received FIFO overrun error flag - * @arg SDIO_FLAG_CMDRES: Command response received (CRC check passed) flag - * @arg SDIO_FLAG_CMDSENT: Command sent (no response required) flag - * @arg SDIO_FLAG_DATAEND: Data end (data counter is zero) flag - * @arg SDIO_FLAG_SBE: Start bit not detected on all data signals in wide bus mode flag - * @arg SDIO_FLAG_DBCP: Data block sent/received (CRC check passed) flag - * @arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag - * @arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received for CMD61 flag + * The parameter can be any combination of following values: + * @arg SDIO_FLAG_COMRESP: Command response received (CRC check failed) flag + * @arg SDIO_FLAG_DBDR: Data block sent/received (CRC check failed) flag + * @arg SDIO_FLAG_CMDRESTO: Command response timeout flag + * @arg SDIO_FLAG_DATATO: Data timeout flag + * @arg SDIO_FLAG_TXUDRER: Transmit FIFO underrun error flag + * @arg SDIO_FLAG_RXOVRER: Received FIFO overrun error flag + * @arg SDIO_FLAG_CMDRES: Command response received (CRC check passed) flag + * @arg SDIO_FLAG_CMDSENT: Command sent (no response required) flag + * @arg SDIO_FLAG_DATAEND: Data end (data counter is zero) flag + * @arg SDIO_FLAG_SBE: Start bit not detected on all data signals in wide bus mode flag + * @arg SDIO_FLAG_DBCP: Data block sent/received (CRC check passed) flag + * @arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag + * @arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received for CMD61 flag * * @retval None */ @@ -652,34 +653,34 @@ void SDIO_ClearStatusFlag(uint32_t flag) } /*! - * @brief Reads the specified SDIO Interrupt flag + * @brief Read the specified SDIO Interrupt flag * * @param flag: Select the SDIO interrupt source - * The parameter can be one of following values: - * @arg SDIO_INT_COMRESP: Command response received (CRC check failed) interrupt - * @arg SDIO_INT_DBDR: Data block sent/received (CRC check failed) interrupt - * @arg SDIO_INT_CMDRESTO: Command response timeout interrupt - * @arg SDIO_INT_DATATO: Data timeout interrupt - * @arg SDIO_INT_TXUDRER: Transmit FIFO underrun error interrupt - * @arg SDIO_INT_RXOVRER: Received FIFO overrun error interrupt - * @arg SDIO_INT_CMDRES: Command response received (CRC check passed) interrupt - * @arg SDIO_INT_CMDSENT: Command sent (no response required) interrupt - * @arg SDIO_INT_DATAEND: Data end (data counter is zero) interrupt - * @arg SDIO_INT_SBE: Start bit not detected on all data signals in wide bus mode interrupt - * @arg SDIO_INT_DBCP: Data block sent/received (CRC check passed) interrupt - * @arg SDIO_INT_CMDACT: Command transfer in progress interrupt - * @arg SDIO_INT_TXACT: Data transmit in progress interrupt - * @arg SDIO_INT_RXACT: Data receive in progress interrupt - * @arg SDIO_INT_TXFHF: Transmit FIFO Half Empty interrupt - * @arg SDIO_INT_RXFHF: Receive FIFO Half Full interrupt - * @arg SDIO_INT_TXFF: Transmit FIFO full interrupt - * @arg SDIO_INT_RXFF: Receive FIFO full interrupt - * @arg SDIO_INT_TXFE: Transmit FIFO empty interrupt - * @arg SDIO_INT_RXFE: Receive FIFO empty interrupt - * @arg SDIO_INT_TXDA: Data available in transmit FIFO interrupt - * @arg SDIO_INT_RXDA: Data available in receive FIFO interrupt - * @arg SDIO_INT_SDIOINT: SD I/O interrupt received interrupt - * @arg SDIO_INT_ATAEND: CE-ATA command completion signal received for CMD61 interrupt + * The parameter can be one of following values: + * @arg SDIO_INT_COMRESP: Command response received (CRC check failed) interrupt + * @arg SDIO_INT_DBDR: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_INT_CMDRESTO: Command response timeout interrupt + * @arg SDIO_INT_DATATO: Data timeout interrupt + * @arg SDIO_INT_TXUDRER: Transmit FIFO underrun error interrupt + * @arg SDIO_INT_RXOVRER: Received FIFO overrun error interrupt + * @arg SDIO_INT_CMDRES: Command response received (CRC check passed) interrupt + * @arg SDIO_INT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_INT_DATAEND: Data end (data counter is zero) interrupt + * @arg SDIO_INT_SBE: Start bit not detected on all data signals in wide bus mode interrupt + * @arg SDIO_INT_DBCP: Data block sent/received (CRC check passed) interrupt + * @arg SDIO_INT_CMDACT: Command transfer in progress interrupt + * @arg SDIO_INT_TXACT: Data transmit in progress interrupt + * @arg SDIO_INT_RXACT: Data receive in progress interrupt + * @arg SDIO_INT_TXFHF: Transmit FIFO Half Empty interrupt + * @arg SDIO_INT_RXFHF: Receive FIFO Half Full interrupt + * @arg SDIO_INT_TXFF: Transmit FIFO full interrupt + * @arg SDIO_INT_RXFF: Receive FIFO full interrupt + * @arg SDIO_INT_TXFE: Transmit FIFO empty interrupt + * @arg SDIO_INT_RXFE: Receive FIFO empty interrupt + * @arg SDIO_INT_TXDA: Data available in transmit FIFO interrupt + * @arg SDIO_INT_RXDA: Data available in receive FIFO interrupt + * @arg SDIO_INT_SDIOINT: SD I/O interrupt received interrupt + * @arg SDIO_INT_ATAEND: CE-ATA command completion signal received for CMD61 interrupt * * @retval SET or RESET */ @@ -700,23 +701,23 @@ uint8_t SDIO_ReadIntFlag(SDIO_INT_T flag) } /*! - * @brief Clears the specified SDIO Interrupt pending bits + * @brief Clear the specified SDIO Interrupt pending bits * * @param flag: Select the SDIO interrupt source - * The parameter can be any combination of following values: - * @arg SDIO_INT_COMRESP: Command response received (CRC check failed) interrupt - * @arg SDIO_INT_DBDR: Data block sent/received (CRC check failed) interrupt - * @arg SDIO_INT_CMDRESTO: Command response timeout interrupt - * @arg SDIO_INT_DATATO: Data timeout interrupt - * @arg SDIO_INT_TXUDRER: Transmit FIFO underrun error interrupt - * @arg SDIO_INT_RXOVRER: Received FIFO overrun error interrupt - * @arg SDIO_INT_CMDRES: Command response received (CRC check passed) interrupt - * @arg SDIO_INT_CMDSENT: Command sent (no response required) interrupt - * @arg SDIO_INT_DATAEND: Data end (data counter is zero) interrupt - * @arg SDIO_INT_SBE: Start bit not detected on all data signals in wide bus mode interrupt - * @arg SDIO_INT_DBCP: Data block sent/received (CRC check passed) interrupt - * @arg SDIO_INT_SDIOINT: SD I/O interrupt received interrupt - * @arg SDIO_INT_ATAEND: CE-ATA command completion signal received for CMD61 interrupt + * The parameter can be any combination of following values: + * @arg SDIO_INT_COMRESP: Command response received (CRC check failed) interrupt + * @arg SDIO_INT_DBDR: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_INT_CMDRESTO: Command response timeout interrupt + * @arg SDIO_INT_DATATO: Data timeout interrupt + * @arg SDIO_INT_TXUDRER: Transmit FIFO underrun error interrupt + * @arg SDIO_INT_RXOVRER: Received FIFO overrun error interrupt + * @arg SDIO_INT_CMDRES: Command response received (CRC check passed) interrupt + * @arg SDIO_INT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_INT_DATAEND: Data end (data counter is zero) interrupt + * @arg SDIO_INT_SBE: Start bit not detected on all data signals in wide bus mode interrupt + * @arg SDIO_INT_DBCP: Data block sent/received (CRC check passed) interrupt + * @arg SDIO_INT_SDIOINT: SD I/O interrupt received interrupt + * @arg SDIO_INT_ATAEND: CE-ATA command completion signal received for CMD61 interrupt * * @retval None */ @@ -725,6 +726,6 @@ void SDIO_ClearIntFlag(uint32_t flag) SDIO->ICF = flag; } -/**@} end of group SDIO_Fuctions*/ -/**@} end of group SDIO_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group SDIO_Functions */ +/**@} end of group SDIO_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_smc.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_smc.c new file mode 100644 index 0000000000..df31f13a13 --- /dev/null +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_smc.c @@ -0,0 +1,747 @@ +/*! + * @file apm32f10x_smc.c + * + * @brief This file provides all the SMC firmware functions + * + * @version V1.0.4 + * + * @date 2022-12-01 + * + * @attention + * + * Copyright (C) 2020-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +#include "apm32f10x_smc.h" +#include "apm32f10x_rcm.h" + +/** @addtogroup APM32F10x_StdPeriphDriver + @{ +*/ + +/** @addtogroup SMC_Driver SMC Driver + * @brief SMC driver modules + @{ +*/ + +/** @defgroup SMC_Functions Functions + @{ +*/ + +/*! + * @brief Reset the EMMMC NOR/SRAM Banks registers + * + * @param bank: Select the EMMMC Bank. + * The parameter can be one of following values: + * @arg SMC_BANK1_NORSRAM_1: SMC Bank1 NOR/SRAM1 + * @arg SMC_BANK1_NORSRAM_2: SMC Bank1 NOR/SRAM2 + * @arg SMC_BANK1_NORSRAM_3: SMC Bank1 NOR/SRAM3 + * @arg SMC_BANK1_NORSRAM_4: SMC Bank1 NOR/SRAM4 + * + * @retval None + */ +void SMC_ResetNORSRAM(SMC_BANK1_NORSRAM_T bank) +{ + /* SMC_BANK1_NORSRAM_1 */ + if (bank == SMC_BANK1_NORSRAM_1) + { + SMC_Bank1->SNCTRL_T[bank] = 0x000030DB; + } + /* SMC_BANK1_NORSRAM_2, SMC_BANK1_NORSRAM_3 or SMC_BANK1_NORSRAM_4 */ + else + { + SMC_Bank1->SNCTRL_T[bank] = 0x000030D2; + } + SMC_Bank1->SNCTRL_T[bank + 1] = 0x0FFFFFFF; + SMC_Bank1E->WRTTIM[bank] = 0x0FFFFFFF; +} + +/*! + * @brief Reset the EMMMC NAND Banks registers + * + * @param bank: Select the EMMMC Bank. + * The parameter can be one of following values: + * @arg SMC_BANK2_NAND: FSMC Bank2 NAND + * @arg SMC_BANK3_NAND: FSMC Bank3 NAND + * + * @retval None + */ +void SMC_ResetNAND(SMC_BANK_NAND_T bank) +{ + if (bank == SMC_BANK2_NAND) + { + /* Set the SMC_Bank2 registers to their reset values */ + SMC_Bank2->CTRL2 = 0x00000018; + SMC_Bank2->STSINT2 = 0x00000040; + SMC_Bank2->CMSTIM2 = 0xFCFCFCFC; + SMC_Bank2->AMSTIM2 = 0xFCFCFCFC; + } + /* SMC BANK3 NAND */ + else + { + /* Set the SMC_Bank3 registers to their reset values */ + SMC_Bank3->CTRL3 = 0x00000018; + SMC_Bank3->STSINT3 = 0x00000040; + SMC_Bank3->CMSTIM3 = 0xFCFCFCFC; + SMC_Bank3->AMSTIM3 = 0xFCFCFCFC; + } +} + +/*! + * @brief Reset the EMMMC PCCARD Banks registers + * + * @param None + * + * @retval None + */ +void SMC_ResetPCCard(void) +{ + /* Set the SMC_Bank4 registers to their reset values */ + SMC_Bank4->CTRL4 = 0x00000018; + SMC_Bank4->STSINT4 = 0x00000040; + SMC_Bank4->CMSTIM4 = 0xFCFCFCFC; + SMC_Bank4->AMSTIM4 = 0xFCFCFCFC; + SMC_Bank4->IOSTIM4 = 0xFCFCFCFC; +} + +/*! + * @brief Configures the SMC NOR/SRAM Banks according to the specified parameters in the smcNORSRAMConfig. + * + * @param smcNORSRAMConfig: Point to a SMC_NORSRAMConfig_T structure + * + * @retval None + */ +void SMC_ConfigNORSRAM(SMC_NORSRAMConfig_T* smcNORSRAMConfig) +{ + /* Bank1 NOR/SRAM control register configuration */ + SMC_Bank1->SNCTRL_T[smcNORSRAMConfig->bank] = + (uint32_t)smcNORSRAMConfig->dataAddressMux | + smcNORSRAMConfig->memoryType | + smcNORSRAMConfig->memoryDataWidth | + smcNORSRAMConfig->burstAcceesMode | + smcNORSRAMConfig->asynchronousWait | + smcNORSRAMConfig->waitSignalPolarity | + smcNORSRAMConfig->wrapMode | + smcNORSRAMConfig->waitSignalActive | + smcNORSRAMConfig->writeOperation | + smcNORSRAMConfig->waiteSignal | + smcNORSRAMConfig->extendedMode | + smcNORSRAMConfig->writeBurst; + + if (smcNORSRAMConfig->memoryType == SMC_MEMORY_TYPE_NOR) + { + SMC_Bank1->SNCTRL_T[smcNORSRAMConfig->bank] |= 0x00000040; + } + + /* Bank1 NOR/SRAM timing register configuration */ + SMC_Bank1->SNCTRL_T[smcNORSRAMConfig->bank + 1] = + (uint32_t)smcNORSRAMConfig->readWriteTimingStruct->addressSetupTime | + (smcNORSRAMConfig->readWriteTimingStruct->addressHodeTime << 4) | + (smcNORSRAMConfig->readWriteTimingStruct->dataSetupTime << 8) | + (smcNORSRAMConfig->readWriteTimingStruct->busTurnaroundTime << 16) | + (smcNORSRAMConfig->readWriteTimingStruct->clockDivision << 20) | + (smcNORSRAMConfig->readWriteTimingStruct->dataLatency << 24) | + smcNORSRAMConfig->readWriteTimingStruct->accessMode; + + /* Bank1 NOR/SRAM timing register for write configuration, if extended mode is used */ + if (smcNORSRAMConfig->extendedMode == SMC_EXTENDEN_MODE_ENABLE) + { + SMC_Bank1E->WRTTIM[smcNORSRAMConfig->bank] = + (uint32_t)smcNORSRAMConfig->writeTimingStruct->addressSetupTime | + (smcNORSRAMConfig->writeTimingStruct->addressHodeTime << 4) | + (smcNORSRAMConfig->writeTimingStruct->dataSetupTime << 8) | + (smcNORSRAMConfig->writeTimingStruct->clockDivision << 20) | + (smcNORSRAMConfig->writeTimingStruct->dataLatency << 24) | + smcNORSRAMConfig->writeTimingStruct->accessMode; + } + else + { + SMC_Bank1E->WRTTIM[smcNORSRAMConfig->bank] = 0x0FFFFFFF; + } +} + +/*! + * @brief Configures the SMC NAND Banks according to the specified parameters in the smcNANDConfig. + * + * @param smcNANDConfig : Point to a SMC_NANDConfig_T structure. + * + * @retval None + */ +void SMC_ConfigNAND(SMC_NANDConfig_T* smcNANDConfig) +{ + uint32_t tmppcr = 0x00000000, tmppmem = 0x00000000, tmppatt = 0x00000000; + + /* Set the tmppcr value according to SMC_NANDInitStruct parameters */ + tmppcr = (uint32_t)smcNANDConfig->waitFeature | 0x00000008 | + smcNANDConfig->memoryDataWidth | + smcNANDConfig->ECC | + smcNANDConfig->ECCPageSize | + (smcNANDConfig->TCLRSetupTime << 9) | + (smcNANDConfig->TARSetupTime << 13); + + /* Set tmppmem value according to SMC_CommonSpaceTimingStructure parameters */ + tmppmem = (uint32_t)smcNANDConfig->commonSpaceTimingStruct->setupTime | + (smcNANDConfig->commonSpaceTimingStruct->waitSetupTime << 8) | + (smcNANDConfig->commonSpaceTimingStruct->holdSetupTime << 16) | + (smcNANDConfig->commonSpaceTimingStruct->HiZSetupTime << 24); + + /* Set tmppatt value according to SMC_AttributeSpaceTimingStructure parameters */ + tmppatt = (uint32_t)smcNANDConfig->attributeSpaceTimingStruct->setupTime | + (smcNANDConfig->attributeSpaceTimingStruct->waitSetupTime << 8) | + (smcNANDConfig->attributeSpaceTimingStruct->holdSetupTime << 16) | + (smcNANDConfig->attributeSpaceTimingStruct->HiZSetupTime << 24); + + if (smcNANDConfig->bank == SMC_BANK2_NAND) + { + /* SMC_BANK2_NAND registers configuration */ + SMC_Bank2->CTRL2 = tmppcr; + SMC_Bank2->CMSTIM2 = tmppmem; + SMC_Bank2->AMSTIM2 = tmppatt; + } + else + { + /* SMC_BANK3_NAND registers configuration */ + SMC_Bank3->CTRL3 = tmppcr; + SMC_Bank3->CMSTIM3 = tmppmem; + SMC_Bank3->AMSTIM3 = tmppatt; + } + +} + +/*! + * @brief Configures the SMC PCCARD according to the specified parameters in the smcPCCardConfig. + * + * @param smcPCCardConfig: Point to a SMC_PCCARDConfig_T structure. + * + * @retval None + */ +void SMC_ConfigPCCard(SMC_PCCARDConfig_T* smcPCCardConfig) +{ + /* Set the PCR4 register value according to SMC_PCCARDInitStruct parameters */ + SMC_Bank4->CTRL4 = (uint32_t)smcPCCardConfig->waitFeature | SMC_MEMORY_DATA_WIDTH_16BIT | + (smcPCCardConfig->TCLRSetupTime << 9) | + (smcPCCardConfig->TARSetupTime << 13); + + /* Set PMEM4 register value according to SMC_CommonSpaceTimingStructure parameters */ + SMC_Bank4->CMSTIM4 = (uint32_t)smcPCCardConfig->commonSpaceTimingStruct->setupTime | + (smcPCCardConfig->commonSpaceTimingStruct->waitSetupTime << 8) | + (smcPCCardConfig->commonSpaceTimingStruct->holdSetupTime << 16) | + (smcPCCardConfig->commonSpaceTimingStruct->HiZSetupTime << 24); + + /* Set PATT4 register value according to SMC_AttributeSpaceTimingStructure parameters */ + SMC_Bank4->AMSTIM4 = (uint32_t)smcPCCardConfig->attributeSpaceTimingStruct->setupTime | + (smcPCCardConfig->attributeSpaceTimingStruct->waitSetupTime << 8) | + (smcPCCardConfig->attributeSpaceTimingStruct->holdSetupTime << 16) | + (smcPCCardConfig->attributeSpaceTimingStruct->HiZSetupTime << 24); + + /* Set PIO4 register value according to SMC_IOSpaceTimingStructure parameters */ + SMC_Bank4->IOSTIM4 = (uint32_t)smcPCCardConfig->IOSpaceTimingStruct->setupTime | + (smcPCCardConfig->IOSpaceTimingStruct->waitSetupTime << 8) | + (smcPCCardConfig->IOSpaceTimingStruct->holdSetupTime << 16) | + (smcPCCardConfig->IOSpaceTimingStruct->HiZSetupTime << 24); +} + +/*! + * @brief Fills each smcNORSRAMConfig member with its default value. + * + * @param smcNORSRAMConfig : Point to a SMC_NORSRAMConfig_T structure. + * + * @retval None + */ +void SMC_ConfigNORSRAMStructInit(SMC_NORSRAMConfig_T* smcNORSRAMConfig) +{ + /* Reset NOR/SRAM Init structure parameters values */ + smcNORSRAMConfig->bank = SMC_BANK1_NORSRAM_1; + smcNORSRAMConfig->dataAddressMux = SMC_DATA_ADDRESS_MUX_ENABLE; + smcNORSRAMConfig->memoryType = SMC_MEMORY_TYPE_SRAM; + smcNORSRAMConfig->memoryDataWidth = SMC_MEMORY_DATA_WIDTH_8BIT; + smcNORSRAMConfig->burstAcceesMode = SMC_BURST_ACCESS_MODE_DISABLE; + smcNORSRAMConfig->asynchronousWait = SMC_ASYNCHRONOUS_WAIT_DISABLE; + smcNORSRAMConfig->waitSignalPolarity = SMC_WAIT_SIGNAL_POLARITY_LOW; + smcNORSRAMConfig->wrapMode = SMC_WRAP_MODE_DISABLE; + smcNORSRAMConfig->waitSignalActive = SMC_WAIT_SIGNAL_ACTIVE_BEFORE_WAIT; + smcNORSRAMConfig->writeOperation = SMC_WRITE_OPERATION_ENABLE; + smcNORSRAMConfig->waiteSignal = SMC_WAITE_SIGNAL_ENABLE; + smcNORSRAMConfig->extendedMode = SMC_EXTENDEN_MODE_DISABLE; + smcNORSRAMConfig->writeBurst = SMC_WRITE_BURST_DISABLE; + smcNORSRAMConfig->readWriteTimingStruct->addressSetupTime = 0xF; + smcNORSRAMConfig->readWriteTimingStruct->addressHodeTime = 0xF; + smcNORSRAMConfig->readWriteTimingStruct->dataSetupTime = 0xFF; + smcNORSRAMConfig->readWriteTimingStruct->busTurnaroundTime = 0xF; + smcNORSRAMConfig->readWriteTimingStruct->clockDivision = 0xF; + smcNORSRAMConfig->readWriteTimingStruct->dataLatency = 0xF; + smcNORSRAMConfig->readWriteTimingStruct->accessMode = SMC_ACCESS_MODE_A; + smcNORSRAMConfig->writeTimingStruct->addressSetupTime = 0xF; + smcNORSRAMConfig->writeTimingStruct->addressHodeTime = 0xF; + smcNORSRAMConfig->writeTimingStruct->dataSetupTime = 0xFF; + smcNORSRAMConfig->writeTimingStruct->busTurnaroundTime = 0xF; + smcNORSRAMConfig->writeTimingStruct->clockDivision = 0xF; + smcNORSRAMConfig->writeTimingStruct->dataLatency = 0xF; + smcNORSRAMConfig->writeTimingStruct->accessMode = SMC_ACCESS_MODE_A; +} + +/*! + * @brief Fills each smcNANDConfig member with its default value. + * + * @param smcNANDConfig : Point to a SMC_NANDConfig_T structure. + * + * @retval None + */ +void SMC_ConfigNANDStructInit(SMC_NANDConfig_T* smcNANDConfig) +{ + /* Reset NAND Init structure parameters values */ + smcNANDConfig->bank = SMC_BANK2_NAND; + smcNANDConfig->waitFeature = SMC_WAIT_FEATURE_DISABLE; + smcNANDConfig->memoryDataWidth = SMC_MEMORY_DATA_WIDTH_8BIT; + smcNANDConfig->ECC = SMC_ECC_DISABLE; + smcNANDConfig->ECCPageSize = SMC_ECC_PAGE_SIZE_BYTE_256; + smcNANDConfig->TCLRSetupTime = 0x0; + smcNANDConfig->TARSetupTime = 0x0; + smcNANDConfig->commonSpaceTimingStruct->setupTime = 0xFC; + smcNANDConfig->commonSpaceTimingStruct->waitSetupTime = 0xFC; + smcNANDConfig->commonSpaceTimingStruct->holdSetupTime = 0xFC; + smcNANDConfig->commonSpaceTimingStruct->HiZSetupTime = 0xFC; + smcNANDConfig->attributeSpaceTimingStruct->setupTime = 0xFC; + smcNANDConfig->attributeSpaceTimingStruct->waitSetupTime = 0xFC; + smcNANDConfig->attributeSpaceTimingStruct->holdSetupTime = 0xFC; + smcNANDConfig->attributeSpaceTimingStruct->HiZSetupTime = 0xFC; +} + +/*! + * @brief Fills each smcPCCardConfig member with its default value. + * + * @param smcPCCardConfig : Point to a SMC_PCCARDConfig_T structure. + * + * @retval None + */ +void SMC_ConfigPCCardStructInit(SMC_PCCARDConfig_T* smcPCCardConfig) +{ + /* Reset PCCARD Init structure parameters values */ + smcPCCardConfig->waitFeature = SMC_WAIT_FEATURE_DISABLE; + smcPCCardConfig->TCLRSetupTime = 0x0; + smcPCCardConfig->TARSetupTime = 0x0; + smcPCCardConfig->commonSpaceTimingStruct->setupTime = 0xFC; + smcPCCardConfig->commonSpaceTimingStruct->waitSetupTime = 0xFC; + smcPCCardConfig->commonSpaceTimingStruct->holdSetupTime = 0xFC; + smcPCCardConfig->commonSpaceTimingStruct->HiZSetupTime = 0xFC; + smcPCCardConfig->attributeSpaceTimingStruct->setupTime = 0xFC; + smcPCCardConfig->attributeSpaceTimingStruct->waitSetupTime = 0xFC; + smcPCCardConfig->attributeSpaceTimingStruct->holdSetupTime = 0xFC; + smcPCCardConfig->attributeSpaceTimingStruct->HiZSetupTime = 0xFC; + smcPCCardConfig->IOSpaceTimingStruct->setupTime = 0xFC; + smcPCCardConfig->IOSpaceTimingStruct->waitSetupTime = 0xFC; + smcPCCardConfig->IOSpaceTimingStruct->holdSetupTime = 0xFC; + smcPCCardConfig->IOSpaceTimingStruct->HiZSetupTime = 0xFC; +} + +/*! + * @brief Enable the specified NOR/SRAM Memory Bank. + * + * @param bank: Select the EMMMC Bank. + * The parameter can be one of following values: + * @arg SMC_BANK1_NORSRAM_1: SMC Bank1 NOR/SRAM1 + * @arg SMC_BANK1_NORSRAM_2: SMC Bank1 NOR/SRAM2 + * @arg SMC_BANK1_NORSRAM_3: SMC Bank1 NOR/SRAM3 + * @arg SMC_BANK1_NORSRAM_4: SMC Bank1 NOR/SRAM4 + * + * @retval None + */ +void SMC_EnableNORSRAM(SMC_BANK1_NORSRAM_T bank) +{ + SMC_Bank1->SNCTRL_T[bank] |= 0x00000001; +} + +/*! + * @brief Disable the specified NOR/SRAM Memory Bank. + * + * @param bank: Select the EMMMC Bank. + * The parameter can be one of following values: + * @arg SMC_BANK1_NORSRAM_1: SMC Bank1 NOR/SRAM1 + * @arg SMC_BANK1_NORSRAM_2: SMC Bank1 NOR/SRAM2 + * @arg SMC_BANK1_NORSRAM_3: SMC Bank1 NOR/SRAM3 + * @arg SMC_BANK1_NORSRAM_4: SMC Bank1 NOR/SRAM4 + * + * @retval None + */ +void SMC_DisableNORSRAM(SMC_BANK1_NORSRAM_T bank) +{ + SMC_Bank1->SNCTRL_T[bank] &= 0x000FFFFE; +} + +/*! + * @brief Enable the specified NAND Memory Bank. + * + * @param bank: Select the EMMMC Bank. + * The parameter can be one of following values: + * @arg SMC_BANK2_NAND: FSMC Bank2 NAND + * @arg SMC_BANK3_NAND: FSMC Bank3 NAND + * + * @retval None + */ +void SMC_EnableNAND(SMC_BANK_NAND_T bank) +{ + if (bank == SMC_BANK2_NAND) + { + SMC_Bank2->CTRL2_B.MBKEN = BIT_SET; + } + else + { + SMC_Bank3->CTRL3_B.MBKEN = BIT_SET; + } +} + +/*! + * @brief Disable the specified NAND Memory Bank. + * + * @param bank: Select the EMMMC Bank. + * The parameter can be one of following values: + * @arg SMC_BANK2_NAND: FSMC Bank2 NAND + * @arg SMC_BANK3_NAND: FSMC Bank3 NAND + * + * @retval None + */ +void SMC_DisableNAND(SMC_BANK_NAND_T bank) +{ + if (bank == SMC_BANK2_NAND) + { + SMC_Bank2->CTRL2_B.MBKEN = BIT_RESET; + } + else + { + SMC_Bank3->CTRL3_B.MBKEN = BIT_RESET; + } +} + +/*! + * @brief Enable the specified PC Card Memory Bank. + * + * @param None + * + * @retval None + */ +void SMC_EnablePCCARD(void) +{ + SMC_Bank4->CTRL4_B.MBKEN = BIT_SET; +} + +/*! + * @brief Disable the specified PC Card Memory Bank. + * + * @param None + * + * @retval None + */ +void SMC_DisablePCCARD(void) +{ + SMC_Bank4->CTRL4_B.MBKEN = BIT_RESET; +} + +/*! + * @brief Enable the SMC NAND ECC feature. + * + * @param bank: Select the EMMMC Bank. + * The parameter can be one of following values: + * @arg SMC_BANK2_NAND: FSMC Bank2 NAND + * @arg SMC_BANK3_NAND: FSMC Bank3 NAND + * + * @retval None + */ +void SMC_EnableNANDECC(SMC_BANK_NAND_T bank) +{ + if (bank == SMC_BANK2_NAND) + { + SMC_Bank2->CTRL2 |= 0x00000040; + } + else + { + SMC_Bank3->CTRL3 |= 0x00000040; + } +} + +/*! + * @brief Disable the SMC Bank2 or Bank3 NAND ECC feature. + * + * @param bank: Select the EMMMC Bank. + * The parameter can be one of following values: + * @arg SMC_BANK2_NAND: FSMC Bank2 NAND + * @arg SMC_BANK3_NAND: FSMC Bank3 NAND + * + * @retval None + * + */ +void SMC_DisableNANDECC(SMC_BANK_NAND_T bank) +{ + if (bank == SMC_BANK2_NAND) + { + SMC_Bank2->CTRL2 &= 0x000FFFBF; + } + else + { + SMC_Bank3->CTRL3 &= 0x000FFFBF; + } +} + +/*! + * @brief Read the error correction code register value. + * + * @param bank: Select the EMMMC Bank. + * The parameter can be one of following values: + * @arg SMC_BANK2_NAND: FSMC Bank2 NAND + * @arg SMC_BANK3_NAND: FSMC Bank3 NAND + * + * @retval The value of Error Correction Code (ECC). + */ +uint32_t SMC_ReadECC(SMC_BANK_NAND_T bank) +{ + uint32_t eccval = 0x00000000; + + if (bank == SMC_BANK2_NAND) + { + eccval = SMC_Bank2->ECCRS2; + } + else + { + eccval = SMC_Bank3->ECCRS3; + } + return eccval; +} + +/*! + * @brief Enable the specified SMC interrupts. + * + * @param bank: Select the EMMMC Bank. + * The parameter can be one of following values: + * @arg SMC_BANK2_NAND : FSMC Bank2 NAND + * @arg SMC_BANK3_NAND : FSMC Bank3 NAND + * @arg SMC_BANK4_PCCARD: FSMC Bank4 PCCARD + * + * @param interrupt: Select the SMC interrupt sources. + * This parameter can be any combination of the following values: + * @arg SMC_INT_EDGE_RISING : Rising edge detection interrupt. + * @arg SMC_INT_LEVEL_HIGH : High level detection interrupt. + * @arg SMC_INT_EDGE_FALLING: Falling edge detection interrupt. + * + * @retval None + */ +void SMC_EnableInterrupt(SMC_BANK_NAND_T bank, uint32_t interrupt) +{ + if (bank == SMC_BANK2_NAND) + { + SMC_Bank2->STSINT2 |= interrupt; + } + else if (bank == SMC_BANK3_NAND) + { + SMC_Bank3->STSINT3 |= interrupt; + } + else + { + SMC_Bank4->STSINT4 |= interrupt; + } +} + +/*! + * @brief Enable the specified SMC interrupts. + * + * @param bank: Select the EMMMC Bank. + * The parameter can be one of following values: + * @arg SMC_BANK2_NAND : FSMC Bank2 NAND + * @arg SMC_BANK3_NAND : FSMC Bank3 NAND + * @arg SMC_BANK4_PCCARD: FSMC Bank4 PCCARD + * + * @param interrupt: Select the SMC interrupt sources. + * This parameter can be any combination of the following values: + * @arg SMC_INT_EDGE_RISING : Rising edge detection interrupt. + * @arg SMC_INT_LEVEL_HIGH : High level edge detection interrupt. + * @arg SMC_INT_EDGE_FALLING: Falling edge detection interrupt. + * + * @retval None + */ +void SMC_DisableInterrupt(SMC_BANK_NAND_T bank, uint32_t interrupt) +{ + if (bank == SMC_BANK2_NAND) + { + SMC_Bank2->STSINT2 &= ~interrupt; + } + else if (bank == SMC_BANK3_NAND) + { + SMC_Bank3->STSINT3 &= ~interrupt; + } + else + { + SMC_Bank4->STSINT4 &= ~interrupt; + } +} + +/*! + * @brief Read the status of specified SMC flag. + * + * @param bank: Select the EMMMC Bank. + * The parameter can be one of following values: + * @arg SMC_BANK2_NAND : FSMC Bank2 NAND + * @arg SMC_BANK3_NAND : FSMC Bank3 NAND + * @arg SMC_BANK4_PCCARD: FSMC Bank4 PCCARD + * + * @param flag: Select the SMC interrupt sources. + * This parameter can be one of the following values: + * @arg SMC_FLAG_EDGE_RISING : Rising egde detection Flag. + * @arg SMC_FLAG_LEVEL_HIGH : High level detection Flag. + * @arg SMC_FLAG_EDGE_FALLING: Falling egde detection Flag. + * @arg SMC_FLAG_FIFO_EMPTY : FIFO empty Flag. + * + * @retval SET or RESET + * + */ +uint8_t SMC_ReadStatusFlag(SMC_BANK_NAND_T bank, SMC_FLAG_T flag) +{ + uint32_t tmpsr = 0x00000000; + + if (bank == SMC_BANK2_NAND) + { + tmpsr = SMC_Bank2->STSINT2; + } + else if (bank == SMC_BANK3_NAND) + { + tmpsr = SMC_Bank3->STSINT3; + } + else + { + tmpsr = SMC_Bank4->STSINT4; + } + /* Get the flag status */ + if ((tmpsr & flag) != RESET) + { + return SET; + } + else + { + return RESET; + } +} + +/*! + * @brief Clear the SMC's pending flags. + * + * @param bank: Select the EMMMC Bank. + * The parameter can be one of following values: + * @arg SMC_BANK2_NAND : FSMC Bank2 NAND + * @arg SMC_BANK3_NAND : FSMC Bank3 NAND + * @arg SMC_BANK4_PCCARD: FSMC Bank4 PCCARD + * + * @param flag: Select the SMC interrupt sources. + * This parameter can be any combination of the following values: + * @arg SMC_FLAG_EDGE_RISING : Rising egde detection Flag. + * @arg SMC_FLAG_LEVEL_HIGH : High level detection Flag. + * @arg SMC_FLAG_EDGE_FALLING: Falling egde detection Flag. + * + * @retval None + */ +void SMC_ClearStatusFlag(SMC_BANK_NAND_T bank, uint32_t flag) +{ + if (bank == SMC_BANK2_NAND) + { + SMC_Bank2->STSINT2 &= ~flag; + } + else if (bank == SMC_BANK3_NAND) + { + SMC_Bank3->STSINT3 &= ~flag; + } + else + { + SMC_Bank4->STSINT4 &= ~flag; + } +} + +/*! + * @brief Read the specified SMC interrupt has occurred or not. + * + * @param bank: Select the EMMMC Bank. + * The parameter can be one of following values: + * @arg SMC_BANK2_NAND : FSMC Bank2 NAND + * @arg SMC_BANK3_NAND : FSMC Bank3 NAND + * @arg SMC_BANK4_PCCARD: FSMC Bank4 PCCARD + * + * @param interrupt: Select the SMC interrupt source. + * This parameter can be one of the following values: + * @arg SMC_INT_EDGE_RISING : Rising edge detection interrupt. + * @arg SMC_INT_LEVEL_HIGH : High level edge detection interrupt. + * @arg SMC_INT_EDGE_FALLING: Falling edge detection interrupt. + * + * @retval The status of specified SMC interrupt source. + */ +uint8_t SMC_ReadIntFlag(SMC_BANK_NAND_T bank, SMC_INT_T flag) +{ + uint32_t tmpsr = 0x0, itstatus = 0x0, itenable = 0x0; + + if (bank == SMC_BANK2_NAND) + { + tmpsr = SMC_Bank2->STSINT2; + } + else if (bank == SMC_BANK3_NAND) + { + tmpsr = SMC_Bank3->STSINT3; + } + else + { + tmpsr = SMC_Bank4->STSINT4; + } + + itstatus = tmpsr & flag; + itenable = tmpsr & (flag >> 3); + + if ((itstatus != RESET) && (itenable != RESET)) + { + return SET; + } + else + { + return RESET; + } +} + +/*! + * @brief Clear the SMC's interrupt Flag. + * + * @param bank: Select the EMMMC Bank. + * The parameter can be one of following values: + * @arg SMC_BANK2_NAND : FSMC Bank2 NAND + * @arg SMC_BANK3_NAND : FSMC Bank3 NAND + * @arg SMC_BANK4_PCCARD: FSMC Bank4 PCCARD + * + * @param interrupt: Select the SMC interrupt sources. + * This parameter can be any combination of the following values: + * @arg SMC_INT_EDGE_RISING : Rising edge detection interrupt. + * @arg SMC_INT_LEVEL_HIGH : High level edge detection interrupt. + * @arg SMC_INT_EDGE_FALLING: Falling edge detection interrupt. + * + * @retval None + */ +void SMC_ClearIntFlag(SMC_BANK_NAND_T bank, uint32_t flag) +{ + if (bank == SMC_BANK2_NAND) + { + SMC_Bank2->STSINT2 &= ~(flag >> 3); + } + else if (bank == SMC_BANK3_NAND) + { + SMC_Bank3->STSINT3 &= ~(flag >> 3); + } + else + { + SMC_Bank4->STSINT4 &= ~(flag >> 3); + } +} + +/**@} end of group SMC_Functions */ +/**@} end of group SMC_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_spi.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_spi.c index 1588cc17ab..1dde4acb9c 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_spi.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_spi.c @@ -3,9 +3,9 @@ * * @brief This file provides all the SPI firmware functions * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,15 +26,16 @@ #include "apm32f10x_spi.h" #include "apm32f10x_rcm.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ /** @addtogroup SPI_Driver SPI Driver + * @brief SPI driver modules @{ */ -/** @addtogroup SPI_Fuctions Fuctions +/** @defgroup SPI_Functions Functions @{ */ @@ -45,7 +46,7 @@ * * @retval None */ -void SPI_I2S_Reset(SPI_T *spi) +void SPI_I2S_Reset(SPI_T* spi) { if (spi == SPI1) { @@ -65,7 +66,7 @@ void SPI_I2S_Reset(SPI_T *spi) } /*! - * @brief Config the SPI peripheral according to the specified parameters in the spiConfig + * @brief Configures the SPI peripheral according to the specified parameters in the spiConfig * * @param spi: The SPIx can be 1,2,3 * @@ -73,7 +74,7 @@ void SPI_I2S_Reset(SPI_T *spi) * * @retval None */ -void SPI_Config(SPI_T *spi, SPI_Config_T *spiConfig) +void SPI_Config(SPI_T* spi, SPI_Config_T* spiConfig) { spi->CTRL1 &= 0x3040; spi->CTRL1 |= (uint16_t)((uint32_t)spiConfig->direction | spiConfig->mode | @@ -84,7 +85,7 @@ void SPI_Config(SPI_T *spi, SPI_Config_T *spiConfig) } /*! - * @brief Config the I2S peripheral according to the specified parameters in the spiConfig + * @brief Configures the I2S peripheral according to the specified parameters in the spiConfig * * @param spi: The SPIx can be 2,3 * @@ -92,13 +93,13 @@ void SPI_Config(SPI_T *spi, SPI_Config_T *spiConfig) * * @retval None */ -void I2S_Config(SPI_T *spi, I2S_Config_T *i2sConfig) +void I2S_Config(SPI_T* spi, I2S_Config_T* i2sConfig) { uint16_t i2sDiv = 2, i2sOdd = 0, packetSize = 1; uint32_t tmp = 0; uint32_t sysClock = 0; - /** Clear MODESEL, I2SEN, I2SMOD, PFSSEL, I2SSSEL, CPOL, DATALEN and CHLEN bits */ + /* Clear MODESEL, I2SEN, I2SMOD, PFSSEL, I2SSSEL, CPOL, DATALEN and CHLEN bits */ spi->I2SCFG &= 0xF040; spi->I2SPSC = 0x0002; @@ -149,7 +150,7 @@ void I2S_Config(SPI_T *spi, I2S_Config_T *i2sConfig) (uint32_t)i2sConfig->length | \ (uint32_t)i2sConfig->polarity; - /** select I2S mode */ + /* select I2S mode */ spi->I2SCFG_B.MODESEL = BIT_SET; } @@ -160,7 +161,7 @@ void I2S_Config(SPI_T *spi, I2S_Config_T *i2sConfig) * * @retval None */ -void SPI_ConfigStructInit(SPI_Config_T *spiConfig) +void SPI_ConfigStructInit(SPI_Config_T* spiConfig) { spiConfig->direction = SPI_DIRECTION_2LINES_FULLDUPLEX; spiConfig->mode = SPI_MODE_SLAVE; @@ -180,7 +181,7 @@ void SPI_ConfigStructInit(SPI_Config_T *spiConfig) * * @retval None */ -void I2S_ConfigStructInit(I2S_Config_T *i2sConfig) +void I2S_ConfigStructInit(I2S_Config_T* i2sConfig) { i2sConfig->mode = I2S_MODE_SLAVE_TX; i2sConfig->standard = I2S_STANDARD_PHILLIPS; @@ -190,13 +191,13 @@ void I2S_ConfigStructInit(I2S_Config_T *i2sConfig) i2sConfig->polarity = I2S_CLKPOL_LOW; } /*! - * @brief Enables the specified SPI peripheral + * @brief Enable the specified SPI peripheral * * @param spi: The SPIx can be 1,2,3 * * @retval None */ -void SPI_Enable(SPI_T *spi) +void SPI_Enable(SPI_T* spi) { spi->CTRL1_B.SPIEN = BIT_SET; } @@ -208,19 +209,19 @@ void SPI_Enable(SPI_T *spi) * * @retval None */ -void SPI_Disable(SPI_T *spi) +void SPI_Disable(SPI_T* spi) { spi->CTRL1_B.SPIEN = BIT_RESET; } /*! - * @brief Enables the specified I2S peripheral + * @brief Enable the specified I2S peripheral * * @param spi: The I2S can be SPI2,SPI3 * * @retval None */ -void I2S_Enable(SPI_T *spi) +void I2S_Enable(SPI_T* spi) { spi->I2SCFG_B.I2SEN = BIT_SET; } @@ -232,23 +233,23 @@ void I2S_Enable(SPI_T *spi) * * @retval None */ -void I2S_Disable(SPI_T *spi) +void I2S_Disable(SPI_T* spi) { spi->I2SCFG_B.I2SEN = BIT_RESET; } /*! - * @brief Enables the SPIx/I2Sx DMA interface. + * @brief Enable the SPIx/I2Sx DMA interface. * * @param spi: The SPIx can be 1,2,3, When the I2S can be 2,3 * * @param dmaReq: specifies the SPI/I2S DMA transfer request - * The parameter can be one of following values: - * @arg SPI_I2S_DMA_REQ_TX: Tx buffer DMA transfer request - * @arg SPI_I2S_DMA_REQ_RX: Rx buffer DMA transfer request + * The parameter can be one of following values: + * @arg SPI_I2S_DMA_REQ_TX: Tx buffer DMA transfer request + * @arg SPI_I2S_DMA_REQ_RX: Rx buffer DMA transfer request * @retval None */ -void SPI_I2S_EnableDMA(SPI_T *spi, SPI_I2S_DMA_REQ_T dmaReq) +void SPI_I2S_EnableDMA(SPI_T* spi, SPI_I2S_DMA_REQ_T dmaReq) { if (dmaReq == SPI_I2S_DMA_REQ_TX) { @@ -261,17 +262,17 @@ void SPI_I2S_EnableDMA(SPI_T *spi, SPI_I2S_DMA_REQ_T dmaReq) } /*! - * @brief Disables the SPIx/I2Sx DMA interface. + * @brief Disable the SPIx/I2Sx DMA interface. * * @param spi: The SPIx can be 1,2,3, When the I2S can be 2,3 * * @param dmaReq: specifies the SPI/I2S DMA transfer request - * The parameter can be one of following values: - * @arg SPI_I2S_DMA_REQ_TX: Tx buffer DMA transfer request - * @arg SPI_I2S_DMA_REQ_RX: Rx buffer DMA transfer request + * The parameter can be one of following values: + * @arg SPI_I2S_DMA_REQ_TX: Tx buffer DMA transfer request + * @arg SPI_I2S_DMA_REQ_RX: Rx buffer DMA transfer request * @retval None */ -void SPI_I2S_DisableDMA(SPI_T *spi, SPI_I2S_DMA_REQ_T dmaReq) +void SPI_I2S_DisableDMA(SPI_T* spi, SPI_I2S_DMA_REQ_T dmaReq) { if (dmaReq == SPI_I2S_DMA_REQ_TX) { @@ -284,7 +285,7 @@ void SPI_I2S_DisableDMA(SPI_T *spi, SPI_I2S_DMA_REQ_T dmaReq) } /*! - * @brief Transmits a Data through the SPIx/I2Sx peripheral. + * @brief Transmit a Data through the SPIx/I2Sx peripheral. * * @param spi: The SPIx can be 1,2,3, When the I2S can be 2,3 * @@ -292,13 +293,13 @@ void SPI_I2S_DisableDMA(SPI_T *spi, SPI_I2S_DMA_REQ_T dmaReq) * * @retval None */ -void SPI_I2S_TxData(SPI_T *spi, uint16_t data) +void SPI_I2S_TxData(SPI_T* spi, uint16_t data) { spi->DATA = data; } /*! - * @brief Returns the most recent received data by the SPIx/I2Sx peripheral. + * @brief Return the most recent received data by the SPIx/I2Sx peripheral. * * @param spi: The SPIx can be 1,2,3, When the I2S can be 2,3 * @@ -306,7 +307,7 @@ void SPI_I2S_TxData(SPI_T *spi, uint16_t data) * * @retval None */ -uint16_t SPI_I2S_RxData(SPI_T *spi) +uint16_t SPI_I2S_RxData(SPI_T* spi) { return spi->DATA; } @@ -318,7 +319,7 @@ uint16_t SPI_I2S_RxData(SPI_T *spi) * * @retval None */ -void SPI_SetSoftwareNSS(SPI_T *spi) +void SPI_SetSoftwareNSS(SPI_T* spi) { spi->CTRL1_B.ISSEL = BIT_SET; } @@ -330,19 +331,19 @@ void SPI_SetSoftwareNSS(SPI_T *spi) * * @retval None */ -void SPI_ResetSoftwareNSS(SPI_T *spi) +void SPI_ResetSoftwareNSS(SPI_T* spi) { spi->CTRL1_B.ISSEL = BIT_RESET; } /*! - * @brief Enables the specified SPI SS output + * @brief Enable the specified SPI SS output * * @param spi: The SPIx can be 1,2,3 * * @retval None */ -void SPI_EnableSSOutput(SPI_T *spi) +void SPI_EnableSSOutput(SPI_T* spi) { spi->CTRL2_B.SSOEN = BIT_SET; } @@ -354,7 +355,7 @@ void SPI_EnableSSOutput(SPI_T *spi) * * @retval None */ -void SPI_DisableSSOutput(SPI_T *spi) +void SPI_DisableSSOutput(SPI_T* spi) { spi->CTRL2_B.SSOEN = BIT_RESET; } @@ -371,7 +372,7 @@ void SPI_DisableSSOutput(SPI_T *spi) * * @retval None */ -void SPI_ConfigDataSize(SPI_T *spi, SPI_DATA_LENGTH_T length) +void SPI_ConfigDataSize(SPI_T* spi, SPI_DATA_LENGTH_T length) { spi->CTRL1_B.DFLSEL = BIT_RESET; spi->CTRL1 |= length; @@ -384,19 +385,19 @@ void SPI_ConfigDataSize(SPI_T *spi, SPI_DATA_LENGTH_T length) * * @retval None */ -void SPI_TxCRC(SPI_T *spi) +void SPI_TxCRC(SPI_T* spi) { spi->CTRL1_B.CRCNXT = BIT_SET; } /*! - * @brief Enables the specified SPI CRC value calculation of the transferred bytes + * @brief Enable the specified SPI CRC value calculation of the transferred bytes * * @param spi: The SPIx can be 1,2,3 * * @retval None */ -void SPI_EnableCRC(SPI_T *spi) +void SPI_EnableCRC(SPI_T* spi) { spi->CTRL1_B.CRCEN = BIT_SET; } @@ -407,43 +408,43 @@ void SPI_EnableCRC(SPI_T *spi) * @param spi: The SPIx can be 1,2,3 * */ -void SPI_DisableCRC(SPI_T *spi) +void SPI_DisableCRC(SPI_T* spi) { spi->CTRL1_B.CRCEN = BIT_RESET; } /*! - * @brief Reads the specified SPI transmit CRC register value + * @brief Read the specified SPI transmit CRC register value * * @param spi: The SPIx can be 1,2,3 * * @retval The SPI transmit CRC register value */ -uint16_t SPI_ReadTxCRC(SPI_T *spi) +uint16_t SPI_ReadTxCRC(SPI_T* spi) { return spi->TXCRC_B.TXCRC; } /*! - * @brief Reads the specified SPI receive CRC register value + * @brief Read the specified SPI receive CRC register value * * @param spi: The SPIx can be 1,2,3 * * @retval The SPI receive CRC register value */ -uint16_t SPI_ReadRxCRC(SPI_T *spi) +uint16_t SPI_ReadRxCRC(SPI_T* spi) { return spi->RXCRC_B.RXCRC; } /*! - * @brief Reads the specified SPI CRC Polynomial register value + * @brief Read the specified SPI CRC Polynomial register value * * @param spi: The SPIx can be 1,2,3 * * @retval The SPI CRC Polynomial register value */ -uint16_t SPI_ReadCRCPolynomial(SPI_T *spi) +uint16_t SPI_ReadCRCPolynomial(SPI_T* spi) { return spi->CRCPOLY_B.CRCPOLY; } @@ -454,12 +455,12 @@ uint16_t SPI_ReadCRCPolynomial(SPI_T *spi) * @param spi: The SPIx can be 1,2,3 * * @param direction: Select the SPI data transfer direction - * The parameter can be one of following values: - * @arg SPI_DIRECTION_RX: Selects Rx receive direction - * @arg SPI_DIRECTION_TX: Selects Tx transmission direction + * The parameter can be one of following values: + * @arg SPI_DIRECTION_RX: Selects Rx receive direction + * @arg SPI_DIRECTION_TX: Selects Tx transmission direction * @retval None */ -void SPI_ConfigBiDirectionalLine(SPI_T *spi, SPI_DIRECTION_SELECT_T direction) +void SPI_ConfigBiDirectionalLine(SPI_T* spi, SPI_DIRECTION_SELECT_T direction) { if (direction == SPI_DIRECTION_TX) { @@ -472,58 +473,58 @@ void SPI_ConfigBiDirectionalLine(SPI_T *spi, SPI_DIRECTION_SELECT_T direction) } /*! - * @brief Enables the specified SPI/I2S interrupts. + * @brief Enable the specified SPI/I2S interrupts. * * @param spi: The SPIx can be 1,2,3, When the I2S can be 2,3 * * @param interrupt: specifies the TMR interrupts sources - * The parameter can be one of following values: - * @arg SPI_I2S_INT_TXBE: Tx buffer empty interrupt - * @arg SPI_I2S_INT_RXBNE: Rx buffer not empty interrupt - * @arg SPI_I2S_INT_ERR: Error interrupt + * The parameter can be one of following values: + * @arg SPI_I2S_INT_TXBE: Tx buffer empty interrupt + * @arg SPI_I2S_INT_RXBNE: Rx buffer not empty interrupt + * @arg SPI_I2S_INT_ERR: Error interrupt * @retval None */ -void SPI_I2S_EnableInterrupt(SPI_T *spi, SPI_I2S_INT_T interrupt) +void SPI_I2S_EnableInterrupt(SPI_T* spi, SPI_I2S_INT_T interrupt) { spi->CTRL2 |= (interrupt >> 8); } /*! - * @brief Disables the specified SPI/I2S interrupts. + * @brief Disable the specified SPI/I2S interrupts. * * @param spi: The SPIx can be 1,2,3, When the I2S can be 2,3 * * @param interrupt: specifies the TMR interrupts sources - * The parameter can be one of following values: - * @arg SPI_I2S_INT_TXBE: Tx buffer empty interrupt - * @arg SPI_I2S_INT_RXBNE: Rx buffer not empty interrupt - * @arg SPI_I2S_INT_ERR: Error interrupt + * The parameter can be one of following values: + * @arg SPI_I2S_INT_TXBE: Tx buffer empty interrupt + * @arg SPI_I2S_INT_RXBNE: Rx buffer not empty interrupt + * @arg SPI_I2S_INT_ERR: Error interrupt * @retval None */ -void SPI_I2S_DisableInterrupt(SPI_T *spi, SPI_I2S_INT_T interrupt) +void SPI_I2S_DisableInterrupt(SPI_T* spi, SPI_I2S_INT_T interrupt) { spi->CTRL2 &= ~(interrupt >> 8); } /*! - * @brief Checks whether the specified SPI/I2S flag is set or not. + * @brief Check whether the specified SPI/I2S flag is set or not. * * @param spi: The SPIx can be 1,2,3, When the I2S can be 2,3 * * @param flag: specifies the SPI/I2S flag to check - * The parameter can be one of following values: - * @arg SPI_FLAG_RXBNE: Receive buffer not empty flag - * @arg SPI_FLAG_TXBE: Transmit buffer empty flag - * @arg I2S_FLAG_SCHDIR: Side Channel flag - * @arg I2S_FLAG_UDR: Underrun Error flag - * @arg SPI_FLAG_CRCE: CRC Error flag - * @arg SPI_FLAG_ME: Mode Error flag - * @arg SPI_FLAG_OVR: Overrun flag - * @arg SPI_FLAG_BSY: Busy flag + * The parameter can be one of following values: + * @arg SPI_FLAG_RXBNE: Receive buffer not empty flag + * @arg SPI_FLAG_TXBE: Transmit buffer empty flag + * @arg I2S_FLAG_SCHDIR: Side Channel flag + * @arg I2S_FLAG_UDR: Underrun Error flag + * @arg SPI_FLAG_CRCE: CRC Error flag + * @arg SPI_FLAG_ME: Mode Error flag + * @arg SPI_FLAG_OVR: Overrun flag + * @arg SPI_FLAG_BSY: Busy flag * * @retval SET or RESET */ -uint8_t SPI_I2S_ReadStatusFlag(SPI_T *spi, SPI_FLAG_T flag) +uint8_t SPI_I2S_ReadStatusFlag(SPI_T* spi, SPI_FLAG_T flag) { if ((spi->STS & flag) != RESET) { @@ -536,11 +537,11 @@ uint8_t SPI_I2S_ReadStatusFlag(SPI_T *spi, SPI_FLAG_T flag) } /*! - * @brief Clears the SPIx CRC Error flag + * @brief Clear the SPIx CRC Error flag * * @param spi: The SPIx can be 1,2,3 * - * @param flag: only clears SPI_FLAG_CRCE(CRC Error flag) + * @param flag: only Clear SPI_FLAG_CRCE(CRC Error flag) * * @retval None * @@ -553,28 +554,28 @@ uint8_t SPI_I2S_ReadStatusFlag(SPI_T *spi, SPI_FLAG_T flag) * a read/write operation to SPI_STS register (SPI_I2S_ReadStatusFlag()) * followed by a write operation to SPI_CTRL1 register (SPI_Enable()). */ -void SPI_I2S_ClearStatusFlag(SPI_T *spi, SPI_FLAG_T flag) +void SPI_I2S_ClearStatusFlag(SPI_T* spi, SPI_FLAG_T flag) { spi->STS_B.CRCEFLG = BIT_RESET; } /*! - * @brief Checks whether the specified SPI/I2S interrupt has occurred or not. + * @brief Check whether the specified SPI/I2S interrupt has occurred or not. * * @param spi: The SPIx can be 1,2,3, When the I2S can be 2,3 * * @param flag: specifies the SPI/I2S interrupt flag to check. - * The parameter can be one of following values: - * @arg SPI_I2S_INT_RXBNE: Receive buffer not empty interrupt flag - * @arg SPI_I2S_INT_TXBE: Transmit buffer empty interrupt flag - * @arg SPI_I2S_INT_OVR: Overrun interrupt flag - * @arg SPI_INT_CRCE: CRC Error interrupt flag - * @arg SPI_INT_ME: Mode Error interrupt flag - * @arg I2S_INT_UDR: Underrun Error interrupt flag + * The parameter can be one of following values: + * @arg SPI_I2S_INT_RXBNE: Receive buffer not empty interrupt flag + * @arg SPI_I2S_INT_TXBE: Transmit buffer empty interrupt flag + * @arg SPI_I2S_INT_OVR: Overrun interrupt flag + * @arg SPI_INT_CRCE: CRC Error interrupt flag + * @arg SPI_INT_ME: Mode Error interrupt flag + * @arg I2S_INT_UDR: Underrun Error interrupt flag * * @retval SET or RESET */ -uint8_t SPI_I2S_ReadIntFlag(SPI_T *spi, SPI_I2S_INT_T flag) +uint8_t SPI_I2S_ReadIntFlag(SPI_T* spi, SPI_I2S_INT_T flag) { uint32_t intEnable; uint32_t intStatus; @@ -591,11 +592,11 @@ uint8_t SPI_I2S_ReadIntFlag(SPI_T *spi, SPI_I2S_INT_T flag) } /*! - * @brief Clears the SPIx CRC Error interrupt flag + * @brief Clear the SPIx CRC Error interrupt flag * * @param spi: The SPIx can be 1,2,3 * - * @param flag: only clears SPI_INT_CRCE(CRC Error interrupt flag) + * @param flag: only Clear SPI_INT_CRCE(CRC Error interrupt flag) * * @retval None * @@ -608,11 +609,11 @@ uint8_t SPI_I2S_ReadIntFlag(SPI_T *spi, SPI_I2S_INT_T flag) * a read/write operation to SPI_STS register (SPI_I2S_ReadIntFlag()) * followed by a write operation to SPI_CTRL1 register (SPI_Enable()). */ -void SPI_I2S_ClearIntFlag(SPI_T *spi, SPI_I2S_INT_T flag) +void SPI_I2S_ClearIntFlag(SPI_T* spi, SPI_I2S_INT_T flag) { spi->STS_B.CRCEFLG = BIT_RESET; } -/**@} end of group SPI_Fuctions*/ -/**@} end of group SPI_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group SPI_Functions */ +/**@} end of group SPI_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_tmr.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_tmr.c index 50a1449c36..6cfb6ff572 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_tmr.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_tmr.c @@ -3,9 +3,9 @@ * * @brief This file provides all the TMR firmware functions. * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,32 +26,33 @@ #include "apm32f10x_tmr.h" #include "apm32f10x_rcm.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ -/** @addtogroup TMR_Driver TMR Driver +/** @addtogroup TMR_Driver TMR Driver + * @brief TMR driver modules @{ */ -/** @addtogroup TMR_Fuctions Fuctions +/** @defgroup TMR_Functions Functions @{ */ -static void TI1Config(TMR_T *tmr, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter); -static void TI2Config(TMR_T *tmr, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter); -static void TI3Config(TMR_T *tmr, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter); -static void TI4Config(TMR_T *tmr, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter); +static void TI1Config(TMR_T* tmr, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter); +static void TI2Config(TMR_T* tmr, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter); +static void TI3Config(TMR_T* tmr, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter); +static void TI4Config(TMR_T* tmr, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter); /*! - * @brief Deinitializes the TMRx peripheral registers to their default reset values. + * @brief Deinitialize the TMRx peripheral registers to their default reset values. * - * @param tmr: Select TMRx peripheral, The x can be 1 to 8 + * @param tmr: Clear TMRx peripheral, The x can be 1 to 8 * * @retval None * */ -void TMR_Reset(TMR_T *tmr) +void TMR_Reset(TMR_T* tmr) { if (tmr == TMR1) { @@ -96,15 +97,15 @@ void TMR_Reset(TMR_T *tmr) } /*! - * @brief Initializes the base timer through the structure + * @brief Initialize the base timer through the structure * - * @param tmr: Select TMRx peripheral, The x can be 1 to 8 + * @param tmr: Clear TMRx peripheral, The x can be 1 to 8 * * @param baseConfig: Pointer to a TMR_BaseConfig_T structure * * @retval None */ -void TMR_ConfigTimeBase(TMR_T *tmr, TMR_BaseConfig_T *baseConfig) +void TMR_ConfigTimeBase(TMR_T* tmr, TMR_BaseConfig_T* baseConfig) { uint16_t temp; @@ -133,7 +134,7 @@ void TMR_ConfigTimeBase(TMR_T *tmr, TMR_BaseConfig_T *baseConfig) } /*! - * @brief Configure channel 1 according to parameters + * @brief Configures channel 1 according to parameters * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -141,7 +142,7 @@ void TMR_ConfigTimeBase(TMR_T *tmr, TMR_BaseConfig_T *baseConfig) * * @retval None */ -void TMR_ConfigOC1(TMR_T *tmr, TMR_OCConfig_T *OCConfig) +void TMR_ConfigOC1(TMR_T* tmr, TMR_OCConfig_T* OCConfig) { tmr->CCEN_B.CC1EN = BIT_RESET; @@ -165,7 +166,7 @@ void TMR_ConfigOC1(TMR_T *tmr, TMR_OCConfig_T *OCConfig) } /*! - * @brief Configure channel 2 according to parameters + * @brief Configures channel 2 according to parameters * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -173,7 +174,7 @@ void TMR_ConfigOC1(TMR_T *tmr, TMR_OCConfig_T *OCConfig) * * @retval None */ -void TMR_ConfigOC2(TMR_T *tmr, TMR_OCConfig_T *OCConfig) +void TMR_ConfigOC2(TMR_T* tmr, TMR_OCConfig_T* OCConfig) { tmr->CCEN_B.CC2EN = BIT_RESET; @@ -202,7 +203,7 @@ void TMR_ConfigOC2(TMR_T *tmr, TMR_OCConfig_T *OCConfig) } /*! - * @brief Configure channel 3 according to parameters + * @brief Configures channel 3 according to parameters * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -210,7 +211,7 @@ void TMR_ConfigOC2(TMR_T *tmr, TMR_OCConfig_T *OCConfig) * * @retval None */ -void TMR_ConfigOC3(TMR_T *tmr, TMR_OCConfig_T *OCConfig) +void TMR_ConfigOC3(TMR_T* tmr, TMR_OCConfig_T* OCConfig) { tmr->CCEN_B.CC3EN = BIT_RESET; @@ -238,7 +239,7 @@ void TMR_ConfigOC3(TMR_T *tmr, TMR_OCConfig_T *OCConfig) } /*! - * @brief Configure channel 4 according to parameters + * @brief Configures channel 4 according to parameters * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -246,7 +247,7 @@ void TMR_ConfigOC3(TMR_T *tmr, TMR_OCConfig_T *OCConfig) * * @retval None */ -void TMR_ConfigOC4(TMR_T *tmr, TMR_OCConfig_T *OCConfig) +void TMR_ConfigOC4(TMR_T* tmr, TMR_OCConfig_T* OCConfig) { tmr->CCEN_B.CC4EN = BIT_RESET; @@ -267,7 +268,7 @@ void TMR_ConfigOC4(TMR_T *tmr, TMR_OCConfig_T *OCConfig) } /*! - * @brief Configure Peripheral equipment + * @brief Configures Peripheral equipment * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -275,7 +276,7 @@ void TMR_ConfigOC4(TMR_T *tmr, TMR_OCConfig_T *OCConfig) * * @retval None */ -void TMR_ConfigIC(TMR_T *tmr, TMR_ICConfig_T *ICConfig) +void TMR_ConfigIC(TMR_T* tmr, TMR_ICConfig_T* ICConfig) { if (ICConfig->channel == TMR_CHANNEL_1) { @@ -308,7 +309,7 @@ void TMR_ConfigIC(TMR_T *tmr, TMR_ICConfig_T *ICConfig) * * @retval None */ -void TMR_ConfigBDT(TMR_T *tmr, TMR_BDTConfig_T *BDTConfig) +void TMR_ConfigBDT(TMR_T* tmr, TMR_BDTConfig_T* BDTConfig) { tmr->BDT = (BDTConfig->IMOS) << 10 | \ (BDTConfig->RMOS) << 11 | \ @@ -326,7 +327,7 @@ void TMR_ConfigBDT(TMR_T *tmr, TMR_BDTConfig_T *BDTConfig) * * @retval None */ -void TMR_ConfigTimeBaseStructInit(TMR_BaseConfig_T *baseConfig) +void TMR_ConfigTimeBaseStructInit(TMR_BaseConfig_T* baseConfig) { baseConfig->period = 0xFFFF; baseConfig->division = 0x0000; @@ -342,7 +343,7 @@ void TMR_ConfigTimeBaseStructInit(TMR_BaseConfig_T *baseConfig) * * @retval None */ -void TMR_ConfigOCStructInit(TMR_OCConfig_T *OCConfig) +void TMR_ConfigOCStructInit(TMR_OCConfig_T* OCConfig) { OCConfig->mode = TMR_OC_MODE_TMRING; OCConfig->outputState = TMR_OC_STATE_DISABLE; @@ -361,7 +362,7 @@ void TMR_ConfigOCStructInit(TMR_OCConfig_T *OCConfig) * * @retval None */ -void TMR_ConfigICStructInit(TMR_ICConfig_T *ICConfig) +void TMR_ConfigICStructInit(TMR_ICConfig_T* ICConfig) { ICConfig->channel = TMR_CHANNEL_1; ICConfig->polarity = TMR_IC_POLARITY_RISING; @@ -377,7 +378,7 @@ void TMR_ConfigICStructInit(TMR_ICConfig_T *ICConfig) * * @retval None */ -void TMR_ConfigBDTStructInit(TMR_BDTConfig_T *BDTConfig) +void TMR_ConfigBDTStructInit(TMR_BDTConfig_T* BDTConfig) { BDTConfig->RMOS = TMR_RMOS_STATE_DISABLE; BDTConfig->IMOS = TMR_IMOS_STATE_DISABLE; @@ -388,6 +389,23 @@ void TMR_ConfigBDTStructInit(TMR_BDTConfig_T *BDTConfig) BDTConfig->automaticOutput = TMR_AUTOMATIC_OUTPUT_DISABLE; } +/*! + * @brief Configures the Sing pulse Mode. + * + * @param tmr: The TMRx can be 1 to 8 + * + * @param singlePulseMode: specifies the Single Pulse Mode + * The parameter can be one of following values: + * @arg TMR_SPM_REPETITIVE + * @arg TMR_SPM_SINGLE + * @retval None + */ + +void TMR_ConfigSinglePulseMode(TMR_T* tmr, TMR_SPM_T singlePulseMode) +{ + tmr->CTRL1_B.SPMEN = singlePulseMode; +} + /*! * @brief Enable the specified TMR peripheral * @@ -395,7 +413,7 @@ void TMR_ConfigBDTStructInit(TMR_BDTConfig_T *BDTConfig) * * @retval None */ -void TMR_Enable(TMR_T *tmr) +void TMR_Enable(TMR_T* tmr) { tmr->CTRL1_B.CNTEN = ENABLE; } @@ -407,13 +425,13 @@ void TMR_Enable(TMR_T *tmr) * * @retval None */ -void TMR_Disable(TMR_T *tmr) +void TMR_Disable(TMR_T* tmr) { tmr->CTRL1_B.CNTEN = DISABLE; } /*! - * @brief Config of TMR to PWM + * @brief Configures of TMR to PWM input * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -421,7 +439,7 @@ void TMR_Disable(TMR_T *tmr) * * @retval None */ -void TMR_ConfigPWM(TMR_T *tmr, TMR_ICConfig_T *PWMConfig) +void TMR_ConfigPWM(TMR_T* tmr, TMR_ICConfig_T* PWMConfig) { uint16_t icpolarity = TMR_IC_POLARITY_RISING; uint16_t icselection = TMR_IC_SELECTION_DIRECT_TI; @@ -467,7 +485,7 @@ void TMR_ConfigPWM(TMR_T *tmr, TMR_ICConfig_T *PWMConfig) * * @retval None */ -void TMR_EnablePWMOutputs(TMR_T *tmr) +void TMR_EnablePWMOutputs(TMR_T* tmr) { tmr->BDT_B.MOEN = ENABLE; } @@ -479,7 +497,7 @@ void TMR_EnablePWMOutputs(TMR_T *tmr) * * @retval None */ -void TMR_DisablePWMOutputs(TMR_T *tmr) +void TMR_DisablePWMOutputs(TMR_T* tmr) { tmr->BDT_B.MOEN = DISABLE; } @@ -495,7 +513,7 @@ void TMR_DisablePWMOutputs(TMR_T *tmr) * * @retval None */ -void TMR_ConfigDMA(TMR_T *tmr, TMR_DMA_BASE_T baseAddress, TMR_DMA_BURSTLENGTH_T burstLength) +void TMR_ConfigDMA(TMR_T* tmr, TMR_DMA_BASE_T baseAddress, TMR_DMA_BURSTLENGTH_T burstLength) { tmr->DCTRL = (uint32_t)baseAddress | (uint32_t)burstLength; } @@ -506,18 +524,18 @@ void TMR_ConfigDMA(TMR_T *tmr, TMR_DMA_BASE_T baseAddress, TMR_DMA_BURSTLENGTH_T * @param tmr: The TMRx can be 1 to 8 * * @param souces: specifies the TMR DMA souces - * The parameter can be any combination of following values: - * @arg TMR_DMA_SOURCE_UPDATE: TMR update DMA souces - * @arg TMR_DMA_SOURCE_CC1: TMR Capture Compare 1 DMA souces - * @arg TMR_DMA_SOURCE_CC2: TMR Capture Compare 2 DMA souces - * @arg TMR_DMA_SOURCE_CC3: TMR Capture Compare 3 DMA souces - * @arg TMR_DMA_SOURCE_CC4: TMR Capture Compare 4 DMA souces - * @arg TMR_DMA_SOURCE_COM: TMR Commutation DMA souces - * @arg TMR_DMA_SOURCE_TRG: TMR Trigger DMA souces + * The parameter can be any combination of following values: + * @arg TMR_DMA_SOURCE_UPDATE: TMR update DMA souces + * @arg TMR_DMA_SOURCE_CC1: TMR Capture Compare 1 DMA souces + * @arg TMR_DMA_SOURCE_CC2: TMR Capture Compare 2 DMA souces + * @arg TMR_DMA_SOURCE_CC3: TMR Capture Compare 3 DMA souces + * @arg TMR_DMA_SOURCE_CC4: TMR Capture Compare 4 DMA souces + * @arg TMR_DMA_SOURCE_COM: TMR Commutation DMA souces + * @arg TMR_DMA_SOURCE_TRG: TMR Trigger DMA souces * @retval None * */ -void TMR_EnableDMASoure(TMR_T *tmr, uint16_t dmaSource) +void TMR_EnableDMASoure(TMR_T* tmr, uint16_t dmaSource) { tmr->DIEN |= dmaSource; } @@ -528,18 +546,18 @@ void TMR_EnableDMASoure(TMR_T *tmr, uint16_t dmaSource) * @param tmr: The TMRx can be 1 to 8 * * @param souces: specifies the TMR DMA souces - * The parameter can be any combination of following values: - * @arg TMR_DMA_SOURCE_UPDATE: TMR update DMA souces - * @arg TMR_DMA_SOURCE_CC1: TMR Capture Compare 1 DMA souces - * @arg TMR_DMA_SOURCE_CC2: TMR Capture Compare 2 DMA souces - * @arg TMR_DMA_SOURCE_CC3: TMR Capture Compare 3 DMA souces - * @arg TMR_DMA_SOURCE_CC4: TMR Capture Compare 4 DMA souces - * @arg TMR_DMA_SOURCE_COM: TMR Commutation DMA souces - * @arg TMR_DMA_SOURCE_TRG: TMR Trigger DMA souces + * The parameter can be any combination of following values: + * @arg TMR_DMA_SOURCE_UPDATE: TMR update DMA souces + * @arg TMR_DMA_SOURCE_CC1: TMR Capture Compare 1 DMA souces + * @arg TMR_DMA_SOURCE_CC2: TMR Capture Compare 2 DMA souces + * @arg TMR_DMA_SOURCE_CC3: TMR Capture Compare 3 DMA souces + * @arg TMR_DMA_SOURCE_CC4: TMR Capture Compare 4 DMA souces + * @arg TMR_DMA_SOURCE_COM: TMR Commutation DMA souces + * @arg TMR_DMA_SOURCE_TRG: TMR Trigger DMA souces * @retval None * */ -void TMR_DisableDMASoure(TMR_T *tmr, uint16_t dmaSource) +void TMR_DisableDMASoure(TMR_T* tmr, uint16_t dmaSource) { tmr->DIEN &= ~dmaSource; } @@ -551,7 +569,7 @@ void TMR_DisableDMASoure(TMR_T *tmr, uint16_t dmaSource) * * @retval None */ -void TMR_ConfigInternalClock(TMR_T *tmr) +void TMR_ConfigInternalClock(TMR_T* tmr) { tmr->SMCTRL_B.SMFSEL = DISABLE; } @@ -562,21 +580,21 @@ void TMR_ConfigInternalClock(TMR_T *tmr) * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * * @param triggerSource: specifies the TMR trigger souces - * The parameter can be one of following values: - * @arg TMR_TRIGGER_SOURCE_ITR0: TMR Internal Trigger 0 - * @arg TMR_TRIGGER_SOURCE_ITR1: TMR Internal Trigger 1 - * @arg TMR_TRIGGER_SOURCE_ITR2: TMR Internal Trigger 2 - * @arg TMR_TRIGGER_SOURCE_ITR3: TMR Internal Trigger 3 + * The parameter can be one of following values: + * @arg TMR_TRIGGER_SOURCE_ITR0: TMR Internal Trigger 0 + * @arg TMR_TRIGGER_SOURCE_ITR1: TMR Internal Trigger 1 + * @arg TMR_TRIGGER_SOURCE_ITR2: TMR Internal Trigger 2 + * @arg TMR_TRIGGER_SOURCE_ITR3: TMR Internal Trigger 3 * @retval None */ -void TMR_ConfigIntTrigExternalClock(TMR_T *tmr, TMR_TRIGGER_SOURCE_T triggerSource) +void TMR_ConfigIntTrigExternalClock(TMR_T* tmr, TMR_TRIGGER_SOURCE_T triggerSource) { TMR_SelectInputTrigger(tmr, triggerSource); tmr->SMCTRL_B.SMFSEL = 0x07; } /*! - * @brief Configures the TMRx Trigger as External Clock + * @brief Configures the TMRx Trigger as External Clock * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -595,7 +613,7 @@ void TMR_ConfigIntTrigExternalClock(TMR_T *tmr, TMR_TRIGGER_SOURCE_T triggerSour * * @retval None */ -void TMR_ConfigTrigExternalClock(TMR_T *tmr, TMR_TRIGGER_SOURCE_T triggerSource, +void TMR_ConfigTrigExternalClock(TMR_T* tmr, TMR_TRIGGER_SOURCE_T triggerSource, TMR_IC_POLARITY_T ICpolarity, uint16_t ICfilter) { if (triggerSource == 0x06) @@ -624,7 +642,7 @@ void TMR_ConfigTrigExternalClock(TMR_T *tmr, TMR_TRIGGER_SOURCE_T triggerSource, * @arg TMR_EXTTRG_PSC_DIV8: ETRP frequency divided by 8 * * @param polarity: specifies the TMR IC polarity - * The parameter can be one of following values: + * The parameter can be one of following values: * @arg TMR_EXTTRG_POL_INVERTED: Active low or falling edge active * @arg TMR_EXTTGR_POL_NONINVERTED: Active high or rising edge active * @@ -632,7 +650,7 @@ void TMR_ConfigTrigExternalClock(TMR_T *tmr, TMR_TRIGGER_SOURCE_T triggerSource, * * @retval None */ -void TMR_ConfigETRClockMode1(TMR_T *tmr, TMR_EXTTRG_PSC_T prescaler, +void TMR_ConfigETRClockMode1(TMR_T* tmr, TMR_EXTTRG_PSC_T prescaler, TMR_EXTTRG_POL_T polarity, uint16_t filter) { TMR_ConfigETR(tmr, prescaler, polarity, filter); @@ -662,7 +680,7 @@ void TMR_ConfigETRClockMode1(TMR_T *tmr, TMR_EXTTRG_PSC_T prescaler, * * @retval None */ -void TMR_ConfigETRClockMode2(TMR_T *tmr, TMR_EXTTRG_PSC_T prescaler, +void TMR_ConfigETRClockMode2(TMR_T* tmr, TMR_EXTTRG_PSC_T prescaler, TMR_EXTTRG_POL_T polarity, uint16_t filter) { TMR_ConfigETR(tmr, prescaler, polarity, filter); @@ -689,7 +707,7 @@ void TMR_ConfigETRClockMode2(TMR_T *tmr, TMR_EXTTRG_PSC_T prescaler, * * @retval None */ -void TMR_ConfigETR(TMR_T *tmr, TMR_EXTTRG_PSC_T prescaler, +void TMR_ConfigETR(TMR_T* tmr, TMR_EXTTRG_PSC_T prescaler, TMR_EXTTRG_POL_T polarity, uint16_t filter) { tmr->SMCTRL &= 0x00FF; @@ -711,18 +729,18 @@ void TMR_ConfigETR(TMR_T *tmr, TMR_EXTTRG_PSC_T prescaler, * @arg TMR_PSC_RELOAD_IMMEDIATE: The Prescaler is loaded immediately * @retval None */ -void TMR_ConfigPrescaler(TMR_T *tmr, uint16_t prescaler, TMR_PSC_RELOAD_T pscReloadMode) +void TMR_ConfigPrescaler(TMR_T* tmr, uint16_t prescaler, TMR_PSC_RELOAD_T pscReloadMode) { tmr->PSC = prescaler; tmr->CEG_B.UEG = pscReloadMode; } /*! - * @brief Config counter mode + * @brief Configures counter mode * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * - * @param countMode:specifies the Counter Mode to be used + * @param countMode: specifies the Counter Mode to be used * The parameter can be one of following values: * @arg TMR_COUNTER_MODE_UP: Timer Up Counting Mode * @arg TMR_COUNTER_MODE_DOWN: Timer Down Counting Mode @@ -731,7 +749,7 @@ void TMR_ConfigPrescaler(TMR_T *tmr, uint16_t prescaler, TMR_PSC_RELOAD_T pscRel * @arg TMR_COUNTER_MODE_CENTERALIGNED3: Timer Center Aligned Mode3 * @retval None */ -void TMR_ConfigCounterMode(TMR_T *tmr, TMR_COUNTER_MODE_T countMode) +void TMR_ConfigCounterMode(TMR_T* tmr, TMR_COUNTER_MODE_T countMode) { tmr->CTRL1_B.CNTDIR = BIT_RESET; tmr->CTRL1_B.CAMSEL = BIT_RESET; @@ -756,7 +774,7 @@ void TMR_ConfigCounterMode(TMR_T *tmr, TMR_COUNTER_MODE_T countMode) * * @retval None */ -void TMR_SelectInputTrigger(TMR_T *tmr, TMR_TRIGGER_SOURCE_T triggerSource) +void TMR_SelectInputTrigger(TMR_T* tmr, TMR_TRIGGER_SOURCE_T triggerSource) { tmr->SMCTRL_B.TRGSEL = BIT_RESET; tmr->SMCTRL_B.TRGSEL = triggerSource; @@ -785,7 +803,7 @@ void TMR_SelectInputTrigger(TMR_T *tmr, TMR_TRIGGER_SOURCE_T triggerSource) * @arg TMR_IC_POLARITY_FALLING: TMR IC polarity falling * @retval None */ -void TMR_ConfigEncodeInterface(TMR_T *tmr, TMR_ENCODER_MODE_T encodeMode, TMR_IC_POLARITY_T IC1Polarity, +void TMR_ConfigEncodeInterface(TMR_T* tmr, TMR_ENCODER_MODE_T encodeMode, TMR_IC_POLARITY_T IC1Polarity, TMR_IC_POLARITY_T IC2Polarity) { tmr->SMCTRL_B.SMFSEL = BIT_RESET; @@ -812,7 +830,7 @@ void TMR_ConfigEncodeInterface(TMR_T *tmr, TMR_ENCODER_MODE_T encodeMode, TMR_IC * @arg TMR_FORCED_ACTION_INACTIVE: Force inactive level on OC1REF * @retval None */ -void TMR_ConfigForcedOC1(TMR_T *tmr, TMR_FORCED_ACTION_T forcesAction) +void TMR_ConfigForcedOC1(TMR_T* tmr, TMR_FORCED_ACTION_T forcesAction) { tmr->CCM1_COMPARE_B.OC1MOD = BIT_RESET; tmr->CCM1_COMPARE_B.OC1MOD = forcesAction; @@ -829,7 +847,7 @@ void TMR_ConfigForcedOC1(TMR_T *tmr, TMR_FORCED_ACTION_T forcesAction) * @arg TMR_FORCED_ACTION_INACTIVE: Force inactive level on OC1REF * @retval None */ -void TMR_ConfigForcedOC2(TMR_T *tmr, TMR_FORCED_ACTION_T forcesAction) +void TMR_ConfigForcedOC2(TMR_T* tmr, TMR_FORCED_ACTION_T forcesAction) { tmr->CCM1_COMPARE_B.OC2MOD = BIT_RESET; tmr->CCM1_COMPARE_B.OC2MOD = forcesAction; @@ -847,7 +865,7 @@ void TMR_ConfigForcedOC2(TMR_T *tmr, TMR_FORCED_ACTION_T forcesAction) * * @retval None */ -void TMR_ConfigForcedOC3(TMR_T *tmr, TMR_FORCED_ACTION_T forcesAction) +void TMR_ConfigForcedOC3(TMR_T* tmr, TMR_FORCED_ACTION_T forcesAction) { tmr->CCM2_COMPARE_B.OC3MOD = BIT_RESET; tmr->CCM2_COMPARE_B.OC3MOD = forcesAction; @@ -865,20 +883,20 @@ void TMR_ConfigForcedOC3(TMR_T *tmr, TMR_FORCED_ACTION_T forcesAction) * * @retval None */ -void TMR_ConfigForcedOC4(TMR_T *tmr, TMR_FORCED_ACTION_T forcesAction) +void TMR_ConfigForcedOC4(TMR_T* tmr, TMR_FORCED_ACTION_T forcesAction) { tmr->CCM2_COMPARE_B.OC4MOD = BIT_RESET; tmr->CCM2_COMPARE_B.OC4MOD = forcesAction; } /*! - * @brief Enables peripheral Preload register on AUTORLD. + * @brief Enable peripheral Preload register on AUTORLD. * * @param tmr: The TMRx can be 1 to 8 * * @retval None */ -void TMR_EnableAutoReload(TMR_T *tmr) +void TMR_EnableAutoReload(TMR_T* tmr) { tmr->CTRL1_B.ARPEN = ENABLE; } @@ -890,30 +908,30 @@ void TMR_EnableAutoReload(TMR_T *tmr) * * @retval None */ -void TMR_DisableAutoReload(TMR_T *tmr) +void TMR_DisableAutoReload(TMR_T* tmr) { tmr->CTRL1_B.ARPEN = DISABLE; } /*! - * @brief Enable Selects the TMR peripheral Commutation event. + * @brief Enable Clear the TMR peripheral Commutation event. * * @param tmr: The TMRx it can be TMR1 and TMR8 * * @retval None */ -void TMR_EnableSelectCOM(TMR_T *tmr) +void TMR_EnableSelectCOM(TMR_T* tmr) { tmr->CTRL2_B.CCUSEL = ENABLE; } /*! - * @brief Disable Selects the TMR peripheral Commutation event. + * @brief Disable Clear the TMR peripheral Commutation event. * * @param tmr: The TMRx it can be TMR1 and TMR8 * * @retval None */ -void TMR_DisableSelectCOM(TMR_T *tmr) +void TMR_DisableSelectCOM(TMR_T* tmr) { tmr->CTRL2_B.CCUSEL = DISABLE; } @@ -925,7 +943,7 @@ void TMR_DisableSelectCOM(TMR_T *tmr) * * @retval None */ -void TMR_EnableCCDMA(TMR_T *tmr) +void TMR_EnableCCDMA(TMR_T* tmr) { tmr->CTRL2_B.CCDSEL = ENABLE; } @@ -937,7 +955,7 @@ void TMR_EnableCCDMA(TMR_T *tmr) * * @retval None */ -void TMR_DisableCCDMA(TMR_T *tmr) +void TMR_DisableCCDMA(TMR_T* tmr) { tmr->CTRL2_B.CCDSEL = DISABLE; } @@ -949,7 +967,7 @@ void TMR_DisableCCDMA(TMR_T *tmr) * * @retval None */ -void TMR_EnableCCPreload(TMR_T *tmr) +void TMR_EnableCCPreload(TMR_T* tmr) { tmr->CTRL2_B.CCPEN = ENABLE; } @@ -961,13 +979,13 @@ void TMR_EnableCCPreload(TMR_T *tmr) * * @retval None */ -void TMR_DisableCCPreload(TMR_T *tmr) +void TMR_DisableCCPreload(TMR_T* tmr) { tmr->CTRL2_B.CCPEN = DISABLE; } /*! - * @brief Enables or disables the peripheral Preload register on CCM1. + * @brief Enable or disable the peripheral Preload register on CCM1. * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -977,13 +995,13 @@ void TMR_DisableCCPreload(TMR_T *tmr) * @arg TMR_OC_PRELOAD_ENABLE * @retval None */ -void TMR_ConfigOC1Preload(TMR_T *tmr, TMR_OC_PRELOAD_T OCPreload) +void TMR_ConfigOC1Preload(TMR_T* tmr, TMR_OC_PRELOAD_T OCPreload) { tmr->CCM1_COMPARE_B.OC1PEN = OCPreload; } /*! - * @brief Enables or disables the peripheral Preload register on CCM2. + * @brief Enable or disable the peripheral Preload register on CCM2. * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -993,13 +1011,13 @@ void TMR_ConfigOC1Preload(TMR_T *tmr, TMR_OC_PRELOAD_T OCPreload) * @arg TMR_OC_PRELOAD_ENABLE * @retval None */ -void TMR_ConfigOC2Preload(TMR_T *tmr, TMR_OC_PRELOAD_T OCPreload) +void TMR_ConfigOC2Preload(TMR_T* tmr, TMR_OC_PRELOAD_T OCPreload) { tmr->CCM1_COMPARE_B.OC2PEN = OCPreload; } /*! - * @brief Enables or disables the peripheral Preload register on CCM3. + * @brief Enable or disable the peripheral Preload register on CCM3. * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -1009,13 +1027,13 @@ void TMR_ConfigOC2Preload(TMR_T *tmr, TMR_OC_PRELOAD_T OCPreload) * @arg TMR_OC_PRELOAD_ENABLE * @retval None */ -void TMR_ConfigOC3Preload(TMR_T *tmr, TMR_OC_PRELOAD_T OCPreload) +void TMR_ConfigOC3Preload(TMR_T* tmr, TMR_OC_PRELOAD_T OCPreload) { tmr->CCM2_COMPARE_B.OC3PEN = OCPreload; } /*! - * @brief Enables or disables the peripheral Preload register on CCM4. + * @brief Enable or disable the peripheral Preload register on CCM4. * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -1025,7 +1043,7 @@ void TMR_ConfigOC3Preload(TMR_T *tmr, TMR_OC_PRELOAD_T OCPreload) * @arg TMR_OC_PRELOAD_ENABLE * @retval Nonee */ -void TMR_ConfigOC4Preload(TMR_T *tmr, TMR_OC_PRELOAD_T OCPreload) +void TMR_ConfigOC4Preload(TMR_T* tmr, TMR_OC_PRELOAD_T OCPreload) { tmr->CCM2_COMPARE_B.OC4PEN = OCPreload; } @@ -1041,7 +1059,7 @@ void TMR_ConfigOC4Preload(TMR_T *tmr, TMR_OC_PRELOAD_T OCPreload) * @arg TMR_OC_FAST_ENABLE * @retval None */ -void TMR_ConfigOC1Fast(TMR_T *tmr, TMR_OC_FAST_T OCFast) +void TMR_ConfigOC1Fast(TMR_T* tmr, TMR_OC_FAST_T OCFast) { tmr->CCM1_COMPARE_B.OC1FEN = OCFast; } @@ -1057,7 +1075,7 @@ void TMR_ConfigOC1Fast(TMR_T *tmr, TMR_OC_FAST_T OCFast) * @arg TMR_OC_FAST_ENABLE * @retval None */ -void TMR_ConfigOC2Fast(TMR_T *tmr, TMR_OC_FAST_T OCFast) +void TMR_ConfigOC2Fast(TMR_T* tmr, TMR_OC_FAST_T OCFast) { tmr->CCM1_COMPARE_B.OC2FEN = OCFast; } @@ -1073,7 +1091,7 @@ void TMR_ConfigOC2Fast(TMR_T *tmr, TMR_OC_FAST_T OCFast) * @arg TMR_OC_FAST_ENABLE * @retval None */ -void TMR_ConfigOC3Fast(TMR_T *tmr, TMR_OC_FAST_T OCFast) +void TMR_ConfigOC3Fast(TMR_T* tmr, TMR_OC_FAST_T OCFast) { tmr->CCM2_COMPARE_B.OC3FEN = OCFast; } @@ -1089,13 +1107,13 @@ void TMR_ConfigOC3Fast(TMR_T *tmr, TMR_OC_FAST_T OCFast) * @arg TMR_OC_FAST_ENABLE * @retval None */ -void TMR_ConfigOC4Fast(TMR_T *tmr, TMR_OC_FAST_T OCFast) +void TMR_ConfigOC4Fast(TMR_T* tmr, TMR_OC_FAST_T OCFast) { tmr->CCM2_COMPARE_B.OC4FEN = OCFast; } /*! - * @brief Clears or safeguards the OCREF1 signal on an external event + * @brief Clear or safeguards the OCREF1 signal on an external event * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -1105,13 +1123,13 @@ void TMR_ConfigOC4Fast(TMR_T *tmr, TMR_OC_FAST_T OCFast) * @arg TMR_OC_CLEAR_ENABLE * @retval None */ -void TMR_ClearOC1Ref(TMR_T *tmr, TMR_OC_CLEAR_T OCClear) +void TMR_ClearOC1Ref(TMR_T* tmr, TMR_OC_CLEAR_T OCClear) { tmr->CCM1_COMPARE_B.OC1CEN = OCClear; } /*! - * @brief Clears or safeguards the OCREF2 signal on an external event + * @brief Clear or safeguards the OCREF2 signal on an external event * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -1121,13 +1139,13 @@ void TMR_ClearOC1Ref(TMR_T *tmr, TMR_OC_CLEAR_T OCClear) * @arg TMR_OC_CLEAR_ENABLE * @retval None */ -void TMR_ClearOC2Ref(TMR_T *tmr, TMR_OC_CLEAR_T OCClear) +void TMR_ClearOC2Ref(TMR_T* tmr, TMR_OC_CLEAR_T OCClear) { tmr->CCM1_COMPARE_B.OC2CEN = OCClear; } /*! - * @brief Clears or safeguards the OCREF3 signal on an external event + * @brief Clear or safeguards the OCREF3 signal on an external event * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -1137,13 +1155,13 @@ void TMR_ClearOC2Ref(TMR_T *tmr, TMR_OC_CLEAR_T OCClear) * @arg TMR_OC_CLEAR_ENABLE * @retval None */ -void TMR_ClearOC3Ref(TMR_T *tmr, TMR_OC_CLEAR_T OCClear) +void TMR_ClearOC3Ref(TMR_T* tmr, TMR_OC_CLEAR_T OCClear) { tmr->CCM2_COMPARE_B.OC3CEN = OCClear; } /*! - * @brief Clears or safeguards the OCREF4 signal on an external event + * @brief Clear or safeguards the OCREF4 signal on an external event * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -1153,7 +1171,7 @@ void TMR_ClearOC3Ref(TMR_T *tmr, TMR_OC_CLEAR_T OCClear) * @arg TMR_OC_CLEAR_ENABLE * @retval None */ -void TMR_ClearOC4Ref(TMR_T *tmr, TMR_OC_CLEAR_T OCClear) +void TMR_ClearOC4Ref(TMR_T* tmr, TMR_OC_CLEAR_T OCClear) { tmr->CCM2_COMPARE_B.OC4CEN = OCClear; } @@ -1169,13 +1187,13 @@ void TMR_ClearOC4Ref(TMR_T *tmr, TMR_OC_CLEAR_T OCClear) * @arg TMR_OC_POLARITY_LOW: Output Compare active low * @retval Nonee */ -void TMR_ConfigOC1Polarity(TMR_T *tmr, TMR_OC_POLARITY_T polarity) +void TMR_ConfigOC1Polarity(TMR_T* tmr, TMR_OC_POLARITY_T polarity) { tmr->CCEN_B.CC1POL = polarity; } /*! - * @brief Configures the channel 1 nPolarity. + * @brief Configures the channel 1 nPolarity. * * @param tmr: The TMRx it can be TMR1 and TMR8 * @@ -1185,7 +1203,7 @@ void TMR_ConfigOC1Polarity(TMR_T *tmr, TMR_OC_POLARITY_T polarity) * @arg TMR_OC_NPOLARITY_LOW: Output Compare active low * @retval None */ -void TMR_ConfigOC1NPolarity(TMR_T *tmr, TMR_OC_NPOLARITY_T nPolarity) +void TMR_ConfigOC1NPolarity(TMR_T* tmr, TMR_OC_NPOLARITY_T nPolarity) { tmr->CCEN_B.CC1NPOL = nPolarity; } @@ -1201,13 +1219,13 @@ void TMR_ConfigOC1NPolarity(TMR_T *tmr, TMR_OC_NPOLARITY_T nPolarity) * @arg TMR_OC_POLARITY_LOW: Output Compare active low * @retval None */ -void TMR_ConfigOC2Polarity(TMR_T *tmr, TMR_OC_POLARITY_T polarity) +void TMR_ConfigOC2Polarity(TMR_T* tmr, TMR_OC_POLARITY_T polarity) { tmr->CCEN_B.CC2POL = polarity; } /*! - * @brief Configures the channel 2 nPolarity. + * @brief Configures the channel 2 nPolarity. * * @param tmr: The TMRx it can be TMR1 and TMR8 * @@ -1217,7 +1235,7 @@ void TMR_ConfigOC2Polarity(TMR_T *tmr, TMR_OC_POLARITY_T polarity) * @arg TMR_OC_NPOLARITY_LOW: Output Compare active low * @retval None */ -void TMR_ConfigOC2NPolarity(TMR_T *tmr, TMR_OC_NPOLARITY_T nPolarity) +void TMR_ConfigOC2NPolarity(TMR_T* tmr, TMR_OC_NPOLARITY_T nPolarity) { tmr->CCEN_B.CC2NPOL = nPolarity; } @@ -1233,13 +1251,13 @@ void TMR_ConfigOC2NPolarity(TMR_T *tmr, TMR_OC_NPOLARITY_T nPolarity) * @arg TMR_OC_POLARITY_LOW: Output Compare active low * @retval None */ -void TMR_ConfigOC3Polarity(TMR_T *tmr, TMR_OC_POLARITY_T polarity) +void TMR_ConfigOC3Polarity(TMR_T* tmr, TMR_OC_POLARITY_T polarity) { tmr->CCEN_B.CC3POL = polarity; } /*! - * @brief Configures the channel 3 nPolarity. + * @brief Configures the channel 3 nPolarity. * * @param tmr: The TMRx it can be TMR1 and TMR8 * @@ -1249,7 +1267,7 @@ void TMR_ConfigOC3Polarity(TMR_T *tmr, TMR_OC_POLARITY_T polarity) * @arg TMR_OC_NPOLARITY_LOW: Output Compare active low * @retval None */ -void TMR_ConfigOC3NPolarity(TMR_T *tmr, TMR_OC_NPOLARITY_T nPolarity) +void TMR_ConfigOC3NPolarity(TMR_T* tmr, TMR_OC_NPOLARITY_T nPolarity) { tmr->CCEN_B.CC3NPOL = nPolarity; } @@ -1265,13 +1283,13 @@ void TMR_ConfigOC3NPolarity(TMR_T *tmr, TMR_OC_NPOLARITY_T nPolarity) * @arg TMR_OC_POLARITY_LOW: Output Compare active low * @retval None */ -void TMR_ConfigOC4Polarity(TMR_T *tmr, TMR_OC_POLARITY_T polarity) +void TMR_ConfigOC4Polarity(TMR_T* tmr, TMR_OC_POLARITY_T polarity) { tmr->CCEN_B.CC4POL = polarity; } /*! - * @brief Enables the Capture Compare Channel x. + * @brief Enable the Capture Compare Channel x. * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -1283,13 +1301,13 @@ void TMR_ConfigOC4Polarity(TMR_T *tmr, TMR_OC_POLARITY_T polarity) * @arg TMR_CHANNEL_4: Timer Channel 4 * @retval None */ -void TMR_EnableCCxChannel(TMR_T *tmr, TMR_CHANNEL_T channel) +void TMR_EnableCCxChannel(TMR_T* tmr, TMR_CHANNEL_T channel) { tmr->CCEN |= BIT_SET << channel; } /*! - * @brief Disables the Capture Compare Channel x. + * @brief Disable the Capture Compare Channel x. * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -1301,13 +1319,13 @@ void TMR_EnableCCxChannel(TMR_T *tmr, TMR_CHANNEL_T channel) * @arg TMR_CHANNEL_4: Timer Channel 4 * @retval None */ -void TMR_DisableCCxChannel(TMR_T *tmr, TMR_CHANNEL_T channel) +void TMR_DisableCCxChannel(TMR_T* tmr, TMR_CHANNEL_T channel) { - tmr->CCEN &= BIT_RESET << channel; + tmr->CCEN &= ~(BIT_SET << channel); } /*! - * @brief Enables the Capture Compare Channelx N. + * @brief Enable the Capture Compare Channelx N. * * @param tmr: The TMRx it can be TMR1 and TMR8 * @@ -1318,13 +1336,13 @@ void TMR_DisableCCxChannel(TMR_T *tmr, TMR_CHANNEL_T channel) * @arg TMR_CHANNEL_3: Timer Channel 3 * @retval None */ -void TMR_EnableCCxNChannel(TMR_T *tmr, TMR_CHANNEL_T channel) +void TMR_EnableCCxNChannel(TMR_T* tmr, TMR_CHANNEL_T channel) { - tmr->CCEN |= 0x04 << channel; + tmr->CCEN |= 0x04 << (channel); } /*! - * @brief Disables the Capture Compare Channelx N. + * @brief Disable the Capture Compare Channelx N. * * @param tmr: The TMRx it can be TMR1 and TMR8 * @@ -1335,9 +1353,9 @@ void TMR_EnableCCxNChannel(TMR_T *tmr, TMR_CHANNEL_T channel) * @arg TMR_CHANNEL_3: Timer Channel 3 * @retval None */ -void TMR_DisableCCxNChannel(TMR_T *tmr, TMR_CHANNEL_T channel) +void TMR_DisableCCxNChannel(TMR_T* tmr, TMR_CHANNEL_T channel) { - tmr->CCEN &= BIT_RESET << channel; + tmr->CCEN &= ~(0x04 << (channel)); } /*! @@ -1364,7 +1382,7 @@ void TMR_DisableCCxNChannel(TMR_T *tmr, TMR_CHANNEL_T channel) * @arg TMR_OC_MODE_PWM2 * @retval None */ -void TMR_SelectOCxMode(TMR_T *tmr, TMR_CHANNEL_T channel, TMR_OC_MODE_T mode) +void TMR_SelectOCxMode(TMR_T* tmr, TMR_CHANNEL_T channel, TMR_OC_MODE_T mode) { tmr->CCEN &= BIT_RESET << channel; @@ -1393,7 +1411,7 @@ void TMR_SelectOCxMode(TMR_T *tmr, TMR_CHANNEL_T channel, TMR_OC_MODE_T mode) * * @retval None */ -void TMR_EnableUpdate(TMR_T *tmr) +void TMR_EnableUpdate(TMR_T* tmr) { tmr->CTRL1_B.UD = DISABLE; } @@ -1405,7 +1423,7 @@ void TMR_EnableUpdate(TMR_T *tmr) * * @retval None */ -void TMR_DisableUpdate(TMR_T *tmr) +void TMR_DisableUpdate(TMR_T* tmr) { tmr->CTRL1_B.UD = ENABLE; } @@ -1421,7 +1439,7 @@ void TMR_DisableUpdate(TMR_T *tmr) * @arg TMR_UPDATE_SOURCE_REGULAR * @retval None */ -void TMR_ConfigUpdateRequest(TMR_T *tmr, TMR_UPDATE_SOURCE_T updateSource) +void TMR_ConfigUpdateRequest(TMR_T* tmr, TMR_UPDATE_SOURCE_T updateSource) { if (updateSource != TMR_UPDATE_SOURCE_GLOBAL) { @@ -1434,13 +1452,13 @@ void TMR_ConfigUpdateRequest(TMR_T *tmr, TMR_UPDATE_SOURCE_T updateSource) } /*! - * @brief Enables Hall sensor interface. + * @brief Enable Hall sensor interface. * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * * @retval None */ -void TMR_EnableHallSensor(TMR_T *tmr) +void TMR_EnableHallSensor(TMR_T* tmr) { tmr->CTRL2_B.TI1SEL = ENABLE; } @@ -1452,27 +1470,11 @@ void TMR_EnableHallSensor(TMR_T *tmr) * * @retval None */ -void TMR_DisableHallSensor(TMR_T *tmr) +void TMR_DisableHallSensor(TMR_T* tmr) { tmr->CTRL2_B.TI1SEL = DISABLE; } -/*! - * @brief Config the Sing pulse Mode. - * - * @param tmr: The TMRx can be 1 to 8 - * - * @param singlePulseMode: specifies the Single Pulse Mode - * The parameter can be one of following values: - * @arg TMR_SPM_REPETITIVE - * @arg TMR_SPM_SINGLE - * @retval None - */ -void TMR_ConfigSinglePulseMode(TMR_T *tmr, TMR_SPM_T singlePulseMode) -{ - tmr->CTRL1_B.SPMEN = singlePulseMode; -} - /*! * @brief Selects the Trigger Output Mode. * @@ -1491,7 +1493,7 @@ void TMR_ConfigSinglePulseMode(TMR_T *tmr, TMR_SPM_T singlePulseMode) * @arg TMR_TRGO_SOURCE_OC4REF * @retval None */ -void TMR_SelectOutputTrigger(TMR_T *tmr, TMR_TRGO_SOURCE_T TRGOSource) +void TMR_SelectOutputTrigger(TMR_T* tmr, TMR_TRGO_SOURCE_T TRGOSource) { tmr->CTRL2_B.MMSEL = TRGOSource; } @@ -1509,7 +1511,7 @@ void TMR_SelectOutputTrigger(TMR_T *tmr, TMR_TRGO_SOURCE_T TRGOSource) * @arg TMR_SLAVE_MODE_EXTERNAL1 * @retval None */ -void TMR_SelectSlaveMode(TMR_T *tmr, TMR_SLAVE_MODE_T slaveMode) +void TMR_SelectSlaveMode(TMR_T* tmr, TMR_SLAVE_MODE_T slaveMode) { tmr->SMCTRL_B.SMFSEL = slaveMode; } @@ -1521,7 +1523,7 @@ void TMR_SelectSlaveMode(TMR_T *tmr, TMR_SLAVE_MODE_T slaveMode) * * @retval None */ -void TMR_EnableMasterSlaveMode(TMR_T *tmr) +void TMR_EnableMasterSlaveMode(TMR_T* tmr) { tmr->SMCTRL_B.MSMEN = ENABLE; } @@ -1533,13 +1535,13 @@ void TMR_EnableMasterSlaveMode(TMR_T *tmr) * * @retval None */ -void TMR_DisableMasterSlaveMode(TMR_T *tmr) +void TMR_DisableMasterSlaveMode(TMR_T* tmr) { tmr->SMCTRL_B.MSMEN = DISABLE; } /*! - * @brief Configs the Counter Register value + * @brief Configures the Counter Register value * * @param tmr: The TMRx can be 1 to 8 * @@ -1547,13 +1549,13 @@ void TMR_DisableMasterSlaveMode(TMR_T *tmr) * * @retval None */ -void TMR_ConfigCounter(TMR_T *tmr, uint16_t counter) +void TMR_ConfigCounter(TMR_T* tmr, uint16_t counter) { tmr->CNT = counter; } /*! - * @brief Configs the AutoReload Register value + * @brief Configures the AutoReload Register value * * @param tmr: The TMRx can be 1 to 8 * @@ -1561,13 +1563,13 @@ void TMR_ConfigCounter(TMR_T *tmr, uint16_t counter) * * @retval None */ -void TMR_ConfigAutoreload(TMR_T *tmr, uint16_t autoReload) +void TMR_ConfigAutoreload(TMR_T* tmr, uint16_t autoReload) { tmr->AUTORLD = autoReload; } /*! - * @brief Configs the Capture Compare1 Register value + * @brief Configures the Capture Compare1 Register value * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -1575,13 +1577,13 @@ void TMR_ConfigAutoreload(TMR_T *tmr, uint16_t autoReload) * * @retval None */ -void TMR_ConfigCompare1(TMR_T *tmr, uint16_t compare1) +void TMR_ConfigCompare1(TMR_T* tmr, uint16_t compare1) { tmr->CC1 = compare1; } /*! - * @brief Configs the Capture Compare2 Register value + * @brief Configures the Capture Compare2 Register value * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -1589,13 +1591,13 @@ void TMR_ConfigCompare1(TMR_T *tmr, uint16_t compare1) * * @retval None */ -void TMR_ConfigCompare2(TMR_T *tmr, uint16_t compare2) +void TMR_ConfigCompare2(TMR_T* tmr, uint16_t compare2) { tmr->CC2 = compare2; } /*! - * @brief Configs the Capture Compare3 Register value + * @brief Configures the Capture Compare3 Register value * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -1603,13 +1605,13 @@ void TMR_ConfigCompare2(TMR_T *tmr, uint16_t compare2) * * @retval None */ -void TMR_ConfigCompare3(TMR_T *tmr, uint16_t compare3) +void TMR_ConfigCompare3(TMR_T* tmr, uint16_t compare3) { tmr->CC3 = compare3; } /*! - * @brief Configs the Capture Compare4 Register value + * @brief Configures the Capture Compare4 Register value * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -1617,13 +1619,13 @@ void TMR_ConfigCompare3(TMR_T *tmr, uint16_t compare3) * * @retval None */ -void TMR_ConfigCompare4(TMR_T *tmr, uint16_t compare4) +void TMR_ConfigCompare4(TMR_T* tmr, uint16_t compare4) { tmr->CC4 = compare4; } /*! - * @brief Configs the TMRx Input Capture 1 prescaler. + * @brief Configures the TMRx Input Capture 1 prescaler. * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -1635,7 +1637,7 @@ void TMR_ConfigCompare4(TMR_T *tmr, uint16_t compare4) * @arg TMR_IC_PSC_8: capture is done once every 8 events * @retval None */ -void TMR_ConfigIC1Prescal(TMR_T *tmr, TMR_IC_PSC_T prescaler) +void TMR_ConfigIC1Prescal(TMR_T* tmr, TMR_IC_PSC_T prescaler) { tmr->CCM1_CAPTURE_B.IC1PSC = BIT_RESET; tmr->CCM1_CAPTURE_B.IC1PSC = prescaler; @@ -1653,14 +1655,14 @@ void TMR_ConfigIC1Prescal(TMR_T *tmr, TMR_IC_PSC_T prescaler) * @arg TMR_IC_PSC_8: capture is done once every 8 events * @retval None */ -void TMR_ConfigIC2Prescal(TMR_T *tmr, TMR_IC_PSC_T prescaler) +void TMR_ConfigIC2Prescal(TMR_T* tmr, TMR_IC_PSC_T prescaler) { tmr->CCM1_CAPTURE_B.IC2PSC = BIT_RESET; tmr->CCM1_CAPTURE_B.IC2PSC = prescaler; } /*! - * @brief Configs the TMRx Input Capture 3 prescaler. + * @brief Configures the TMRx Input Capture 3 prescaler. * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -1672,14 +1674,14 @@ void TMR_ConfigIC2Prescal(TMR_T *tmr, TMR_IC_PSC_T prescaler) * @arg TMR_IC_PSC_8: capture is done once every 8 events * @retval None */ -void TMR_ConfigIC3Prescal(TMR_T *tmr, TMR_IC_PSC_T prescaler) +void TMR_ConfigIC3Prescal(TMR_T* tmr, TMR_IC_PSC_T prescaler) { tmr->CCM2_CAPTURE_B.IC3PSC = BIT_RESET; tmr->CCM2_CAPTURE_B.IC3PSC = prescaler; } /*! - * @brief Configs the TMRx Input Capture 4 prescaler. + * @brief Configures the TMRx Input Capture 4 prescaler. * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -1691,14 +1693,14 @@ void TMR_ConfigIC3Prescal(TMR_T *tmr, TMR_IC_PSC_T prescaler) * @arg TMR_IC_PSC_8: capture is done once every 8 events * @retval None */ -void TMR_ConfigIC4Prescal(TMR_T *tmr, TMR_IC_PSC_T prescaler) +void TMR_ConfigIC4Prescal(TMR_T* tmr, TMR_IC_PSC_T prescaler) { tmr->CCM2_CAPTURE_B.IC4PSC = BIT_RESET; tmr->CCM2_CAPTURE_B.IC4PSC = prescaler; } /*! - * @brief Configs the Clock Division value + * @brief Configures the Clock Division value * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -1709,7 +1711,7 @@ void TMR_ConfigIC4Prescal(TMR_T *tmr, TMR_IC_PSC_T prescaler) * @arg TMR_CLOCK_DIV_4: TDTS = 4*Tck_tim * @retval None */ -void TMR_ConfigClockDivision(TMR_T *tmr, TMR_CLOCK_DIV_T clockDivision) +void TMR_ConfigClockDivision(TMR_T* tmr, TMR_CLOCK_DIV_T clockDivision) { tmr->CTRL1_B.CLKDIV = clockDivision; } @@ -1721,7 +1723,7 @@ void TMR_ConfigClockDivision(TMR_T *tmr, TMR_CLOCK_DIV_T clockDivision) * * @retval Capture Compare 1 Register value. */ -uint16_t TMR_ReadCaputer1(TMR_T *tmr) +uint16_t TMR_ReadCaputer1(TMR_T* tmr) { return tmr->CC1; } @@ -1733,7 +1735,7 @@ uint16_t TMR_ReadCaputer1(TMR_T *tmr) * * @retval Capture Compare 2 Register value. */ -uint16_t TMR_ReadCaputer2(TMR_T *tmr) +uint16_t TMR_ReadCaputer2(TMR_T* tmr) { return tmr->CC2; } @@ -1745,7 +1747,7 @@ uint16_t TMR_ReadCaputer2(TMR_T *tmr) * * @retval Capture Compare 3 Register value. */ -uint16_t TMR_ReadCaputer3(TMR_T *tmr) +uint16_t TMR_ReadCaputer3(TMR_T* tmr) { return tmr->CC3; } @@ -1757,7 +1759,7 @@ uint16_t TMR_ReadCaputer3(TMR_T *tmr) * * @retval Capture Compare 4 Register value. */ -uint16_t TMR_ReadCaputer4(TMR_T *tmr) +uint16_t TMR_ReadCaputer4(TMR_T* tmr) { return tmr->CC4; } @@ -1769,19 +1771,19 @@ uint16_t TMR_ReadCaputer4(TMR_T *tmr) * * @retval Counter Register value. */ -uint16_t TMR_ReadCounter(TMR_T *tmr) +uint16_t TMR_ReadCounter(TMR_T* tmr) { return tmr->CNT; } /*! - * @brief Read the TMRx Prescaler value. + * @brief Read the TMRx Prescaler value. * * @param tmr: The TMRx can be 1 to 8 * * @retval Prescaler Register value. */ -uint16_t TMR_ReadPrescaler(TMR_T *tmr) +uint16_t TMR_ReadPrescaler(TMR_T* tmr) { return tmr->PSC; } @@ -1795,7 +1797,7 @@ uint16_t TMR_ReadPrescaler(TMR_T *tmr) * The parameter can be any combination of following values: * @arg TMR_INT_UPDATE: Timer update Interrupt source * @arg TMR_INT_CC1: Timer Capture Compare 1 Interrupt source - * @arg TMR_INT_CC2: Timer Capture Compare 1 Interrupt source + * @arg TMR_INT_CC2: Timer Capture Compare 2 Interrupt source * @arg TMR_INT_CC3: Timer Capture Compare 3 Interrupt source * @arg TMR_INT_CC4: Timer Capture Compare 4 Interrupt source * @arg TMR_INT_COM: Timer Commutation Interrupt source (Only for TMR1 and TMR8) @@ -1805,7 +1807,7 @@ uint16_t TMR_ReadPrescaler(TMR_T *tmr) * * @note TMR6 and TMR7 can only generate an TMR_INT_UPDATE. */ -void TMR_EnableInterrupt(TMR_T *tmr, uint16_t interrupt) +void TMR_EnableInterrupt(TMR_T* tmr, uint16_t interrupt) { tmr->DIEN |= interrupt; } @@ -1819,7 +1821,7 @@ void TMR_EnableInterrupt(TMR_T *tmr, uint16_t interrupt) * The parameter can be any combination of following values: * @arg TMR_INT_UPDATE: Timer update Interrupt source * @arg TMR_INT_CC1: Timer Capture Compare 1 Interrupt source - * @arg TMR_INT_CC2: Timer Capture Compare 1 Interrupt source + * @arg TMR_INT_CC2: Timer Capture Compare 2 Interrupt source * @arg TMR_INT_CC3: Timer Capture Compare 3 Interrupt source * @arg TMR_INT_CC4: Timer Capture Compare 4 Interrupt source * @arg TMR_INT_COM: Timer Commutation Interrupt source (Only for TMR1 and TMR8) @@ -1829,7 +1831,7 @@ void TMR_EnableInterrupt(TMR_T *tmr, uint16_t interrupt) * * @note TMR6 and TMR7 can only generate an TMR_INT_UPDATE. */ -void TMR_DisableInterrupt(TMR_T *tmr, uint16_t interrupt) +void TMR_DisableInterrupt(TMR_T* tmr, uint16_t interrupt) { tmr->DIEN &= ~interrupt; } @@ -1843,7 +1845,7 @@ void TMR_DisableInterrupt(TMR_T *tmr, uint16_t interrupt) * The parameter can be any combination of following values: * @arg TMR_EVENT_UPDATE: Timer update Interrupt source * @arg TMR_EVENT_CC1: Timer Capture Compare 1 Event source - * @arg TMR_EVENT_CC2: Timer Capture Compare 1 Event source + * @arg TMR_EVENT_CC2: Timer Capture Compare 2 Event source * @arg TMR_EVENT_CC3: Timer Capture Compare 3 Event source * @arg TMR_EVENT_CC4: Timer Capture Compare 4 Event source * @arg TMR_EVENT_COM: Timer Commutation Event source (Only for TMR1 and TMR8) @@ -1853,7 +1855,7 @@ void TMR_DisableInterrupt(TMR_T *tmr, uint16_t interrupt) * * @note TMR6 and TMR7 can only generate an TMR_EVENT_UPDATE. */ -void TMR_GenerateEvent(TMR_T *tmr, uint16_t eventSources) +void TMR_GenerateEvent(TMR_T* tmr, uint16_t eventSources) { tmr->CEG = eventSources; } @@ -1881,13 +1883,13 @@ void TMR_GenerateEvent(TMR_T *tmr, uint16_t eventSources) * * @note TMR6 and TMR7 can only generate an TMR_FLAG_UPDATE. */ -uint16_t TMR_ReadStatusFlag(TMR_T *tmr, TMR_FLAG_T flag) +uint16_t TMR_ReadStatusFlag(TMR_T* tmr, TMR_FLAG_T flag) { return (tmr->STS & flag) ? SET : RESET; } /*! - * @brief Clears the TMR's pending flags. + * @brief Clear the TMR's pending flags. * * @param tmr: The TMRx can be 1 to 8 * @@ -1909,7 +1911,7 @@ uint16_t TMR_ReadStatusFlag(TMR_T *tmr, TMR_FLAG_T flag) * * @note TMR6 and TMR7 can only generate an TMR_FLAG_UPDATE. */ -void TMR_ClearStatusFlag(TMR_T *tmr, uint16_t flag) +void TMR_ClearStatusFlag(TMR_T* tmr, uint16_t flag) { tmr->STS = ~flag; } @@ -1923,7 +1925,7 @@ void TMR_ClearStatusFlag(TMR_T *tmr, uint16_t flag) * The parameter can be one of following values: * @arg TMR_INT_UPDATE: Timer update Interrupt source * @arg TMR_INT_CC1: Timer Capture Compare 1 Interrupt source - * @arg TMR_INT_CC2: Timer Capture Compare 1 Interrupt source + * @arg TMR_INT_CC2: Timer Capture Compare 2 Interrupt source * @arg TMR_INT_CC3: Timer Capture Compare 3 Interrupt source * @arg TMR_INT_CC4: Timer Capture Compare 4 Interrupt source * @arg TMR_INT_COM: Timer Commutation Interrupt source (Only for TMR1 and TMR8) @@ -1933,7 +1935,7 @@ void TMR_ClearStatusFlag(TMR_T *tmr, uint16_t flag) * * @note TMR6 and TMR7 can only generate an TMR_INT_UPDATE. */ -uint16_t TMR_ReadIntFlag(TMR_T *tmr, TMR_INT_T flag) +uint16_t TMR_ReadIntFlag(TMR_T* tmr, TMR_INT_T flag) { if (((tmr->STS & flag) != RESET) && ((tmr->DIEN & flag) != RESET)) { @@ -1946,7 +1948,7 @@ uint16_t TMR_ReadIntFlag(TMR_T *tmr, TMR_INT_T flag) } /*! - * @brief Clears the TMR's interrupt pending bits. + * @brief Clear the TMR's interrupt pending bits. * * @param tmr: The TMRx can be 1 to 8 * @@ -1954,7 +1956,7 @@ uint16_t TMR_ReadIntFlag(TMR_T *tmr, TMR_INT_T flag) * The parameter can be any combination following values: * @arg TMR_INT_UPDATE: Timer update Interrupt source * @arg TMR_INT_CC1: Timer Capture Compare 1 Interrupt source - * @arg TMR_INT_CC2: Timer Capture Compare 1 Interrupt source + * @arg TMR_INT_CC2: Timer Capture Compare 2 Interrupt source * @arg TMR_INT_CC3: Timer Capture Compare 3 Interrupt source * @arg TMR_INT_CC4: Timer Capture Compare 4 Interrupt source * @arg TMR_INT_COM: Timer Commutation Interrupt source (Only for TMR1 and TMR8) @@ -1964,13 +1966,13 @@ uint16_t TMR_ReadIntFlag(TMR_T *tmr, TMR_INT_T flag) * * @note TMR6 and TMR7 can only generate an TMR_INT_UPDATE. */ -void TMR_ClearIntFlag(TMR_T *tmr, uint16_t flag) +void TMR_ClearIntFlag(TMR_T* tmr, uint16_t flag) { tmr->STS = ~flag; } /*! - * @brief Configure the TI1 as Input + * @brief Configures the TI1 as Input * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -1982,7 +1984,7 @@ void TMR_ClearIntFlag(TMR_T *tmr, uint16_t flag) * * @retval None */ -static void TI1Config(TMR_T *tmr, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter) +static void TI1Config(TMR_T* tmr, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter) { uint16_t tmpchctrl = 0; @@ -2014,7 +2016,7 @@ static void TI1Config(TMR_T *tmr, uint16_t ICpolarity, uint16_t ICselection, uin } /*! - * @brief Configure the TI2 as Input + * @brief Configures the TI2 as Input * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -2026,7 +2028,7 @@ static void TI1Config(TMR_T *tmr, uint16_t ICpolarity, uint16_t ICselection, uin * * @retval None */ -static void TI2Config(TMR_T *tmr, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter) +static void TI2Config(TMR_T* tmr, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter) { uint16_t tmpchctrl = 0; @@ -2058,7 +2060,7 @@ static void TI2Config(TMR_T *tmr, uint16_t ICpolarity, uint16_t ICselection, uin } /*! - * @brief Configure the TI3 as Input + * @brief Configures the TI3 as Input * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -2070,7 +2072,7 @@ static void TI2Config(TMR_T *tmr, uint16_t ICpolarity, uint16_t ICselection, uin * * @retval None */ -static void TI3Config(TMR_T *tmr, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter) +static void TI3Config(TMR_T* tmr, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter) { uint16_t tmpchctrl = 0; @@ -2102,7 +2104,7 @@ static void TI3Config(TMR_T *tmr, uint16_t ICpolarity, uint16_t ICselection, uin } /*! - * @brief Configure the TI4 as Input + * @brief Configures the TI4 as Input * * @param tmr: The TMRx can be 1 to 8 except 6 and 7 * @@ -2114,7 +2116,7 @@ static void TI3Config(TMR_T *tmr, uint16_t ICpolarity, uint16_t ICselection, uin * * @retval None */ -static void TI4Config(TMR_T *tmr, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter) +static void TI4Config(TMR_T* tmr, uint16_t ICpolarity, uint16_t ICselection, uint16_t ICfilter) { uint16_t tmpchctrl = 0; @@ -2132,6 +2134,6 @@ static void TI4Config(TMR_T *tmr, uint16_t ICpolarity, uint16_t ICselection, uin tmr->CCEN = tmpchctrl; } -/**@} end of group TMR_Fuctions*/ -/**@} end of group TMR_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group TMR_Functions */ +/**@} end of group TMR_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_usart.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_usart.c index 081c50ce7a..4dcd768dbf 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_usart.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_usart.c @@ -3,9 +3,9 @@ * * @brief This file provides all the USART firmware functions * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,15 +26,16 @@ #include "apm32f10x_usart.h" #include "apm32f10x_rcm.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ /** @addtogroup USART_Driver USART Driver + * @brief USART driver modules @{ */ -/** @addtogroup USART_Fuctions Fuctions +/** @defgroup USART_Functions Functions @{ */ @@ -47,7 +48,7 @@ * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_Reset(USART_T *usart) +void USART_Reset(USART_T* usart) { if (USART1 == usart) { @@ -77,7 +78,7 @@ void USART_Reset(USART_T *usart) } /*! - * @brief Config the USART peripheral according to the specified parameters in the usartConfig + * @brief Configures the USART peripheral according to the specified parameters in the usartConfig * * @param uart: Select the USART or the UART peripheral * @@ -87,7 +88,7 @@ void USART_Reset(USART_T *usart) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_Config(USART_T *uart, USART_Config_T *usartConfig) +void USART_Config(USART_T* uart, USART_Config_T* usartConfig) { uint32_t temp, fCLK, intDiv, fractionalDiv; @@ -132,7 +133,7 @@ void USART_Config(USART_T *uart, USART_Config_T *usartConfig) * * @retval None */ -void USART_ConfigStructInit(USART_Config_T *usartConfig) +void USART_ConfigStructInit(USART_Config_T* usartConfig) { usartConfig->baudRate = 9600; usartConfig->wordLength = USART_WORD_LEN_8B; @@ -143,17 +144,17 @@ void USART_ConfigStructInit(USART_Config_T *usartConfig) } /*! - * @brief Configuration communication clock + * @brief Configures communication clock * - * @param usart: Select the USART or the UART peripheral + * @param usart: Select the USART or the UART peripheral * - * @param clockConfig: Pointer to a USART_clockConfig_T structure + * @param clockConfig: Pointer to a USART_clockConfig_T structure * * @retval None * * @note The usart can be USART1, USART2, USART3 */ -void USART_ConfigClock(USART_T *usart, USART_ClockConfig_T *clockConfig) +void USART_ConfigClock(USART_T* usart, USART_ClockConfig_T* clockConfig) { usart->CTRL2_B.CLKEN = clockConfig->clock; usart->CTRL2_B.CPHA = clockConfig->phase; @@ -164,12 +165,12 @@ void USART_ConfigClock(USART_T *usart, USART_ClockConfig_T *clockConfig) /*! * @brief Fills each clockConfig member with its default value * - * @param clockConfig: Pointer to a USART_clockConfig_T structure + * @param clockConfig: Pointer to a USART_clockConfig_T structure * * @retval None * */ -void USART_ConfigClockStructInit(USART_ClockConfig_T *clockConfig) +void USART_ConfigClockStructInit(USART_ClockConfig_T* clockConfig) { clockConfig->clock = USART_CLKEN_DISABLE; clockConfig->phase = USART_CLKPHA_1EDGE; @@ -178,15 +179,15 @@ void USART_ConfigClockStructInit(USART_ClockConfig_T *clockConfig) } /*! - * @brief Enables the specified USART peripheral + * @brief Enable the specified USART peripheral * - * @param usart: Select the USART or the UART peripheral + * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_Enable(USART_T *usart) +void USART_Enable(USART_T* usart) { usart->CTRL1_B.UEN = BIT_SET; } @@ -194,23 +195,23 @@ void USART_Enable(USART_T *usart) /*! * @brief Disable the specified USART peripheral * - * @param usart: Select the USART or the UART peripheral + * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_Disable(USART_T *usart) +void USART_Disable(USART_T* usart) { usart->CTRL1_B.UEN = BIT_RESET; } /*! - * @brief Enables the USART DMA interface + * @brief Enable the USART DMA interface * - * @param usart: Select the USART or the UART peripheral + * @param usart: Select the USART or the UART peripheral * - * @param dmaReq: Specifies the DMA request + * @param dmaReq: Specifies the DMA request * This parameter can be one of the following values: * @arg USART_DMA_TX: USART DMA receive request * @arg USART_DMA_RX: USART DMA transmit request @@ -220,7 +221,7 @@ void USART_Disable(USART_T *usart) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_EnableDMA(USART_T *usart, USART_DMA_T dmaReq) +void USART_EnableDMA(USART_T* usart, USART_DMA_T dmaReq) { usart->CTRL3 |= dmaReq; } @@ -228,9 +229,9 @@ void USART_EnableDMA(USART_T *usart, USART_DMA_T dmaReq) /*! * @brief Disable the USART DMA interface * - * @param usart: Select the USART or the UART peripheral + * @param usart: Select the USART or the UART peripheral * - * @param dmaReq: Specifies the DMA request + * @param dmaReq: Specifies the DMA request * This parameter can be one of the following values: * @arg USART_DMA_TX: USART DMA receive request * @arg USART_DMA_RX: USART DMA transmit request @@ -240,7 +241,7 @@ void USART_EnableDMA(USART_T *usart, USART_DMA_T dmaReq) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_DisableDMA(USART_T *usart, USART_DMA_T dmaReq) +void USART_DisableDMA(USART_T* usart, USART_DMA_T dmaReq) { usart->CTRL3 &= (uint32_t)~dmaReq; } @@ -248,7 +249,7 @@ void USART_DisableDMA(USART_T *usart, USART_DMA_T dmaReq) /*! * @brief Configures the address of the USART node * - * @param usart: Select the USART or the UART peripheral + * @param usart: Select the USART or the UART peripheral * * @param address: Indicates the address of the USART node * @@ -256,7 +257,7 @@ void USART_DisableDMA(USART_T *usart, USART_DMA_T dmaReq) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_Address(USART_T *usart, uint8_t address) +void USART_Address(USART_T* usart, uint8_t address) { usart->CTRL2_B.ADDR = address; } @@ -264,18 +265,18 @@ void USART_Address(USART_T *usart, uint8_t address) /*! * @brief Selects the USART WakeUp method. * - * @param usart: Select the USART or the UART peripheral + * @param usart: Select the USART or the UART peripheral * * @param wakeup: Specifies the selected USART auto baud rate method - * This parameter can be one of the following values: - * @arg USART_WAKEUP_IDLE_LINE: WakeUp by an idle line detection - * @arg USART_WAKEUP_ADDRESS_MARK: WakeUp by an address mark + * This parameter can be one of the following values: + * @arg USART_WAKEUP_IDLE_LINE: WakeUp by an idle line detection + * @arg USART_WAKEUP_ADDRESS_MARK: WakeUp by an address mark * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_ConfigWakeUp(USART_T *usart, USART_WAKEUP_T wakeup) +void USART_ConfigWakeUp(USART_T* usart, USART_WAKEUP_T wakeup) { usart->CTRL1_B.WUPMCFG = wakeup; } @@ -289,7 +290,7 @@ void USART_ConfigWakeUp(USART_T *usart, USART_WAKEUP_T wakeup) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_EnableMuteMode(USART_T *usart) +void USART_EnableMuteMode(USART_T* usart) { usart->CTRL1_B.RXMUTEEN = BIT_SET; } @@ -303,13 +304,13 @@ void USART_EnableMuteMode(USART_T *usart) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_DisableMuteMode(USART_T *usart) +void USART_DisableMuteMode(USART_T* usart) { usart->CTRL1_B.RXMUTEEN = BIT_RESET; } /*! - * @brief Sets the USART LIN Break detection length + * @brief Set the USART LIN Break detection length * * @param usart: Select the USART or the UART peripheral * @@ -322,13 +323,13 @@ void USART_DisableMuteMode(USART_T *usart) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_ConfigLINBreakDetectLength(USART_T *usart, USART_LBDL_T length) +void USART_ConfigLINBreakDetectLength(USART_T* usart, USART_LBDL_T length) { usart->CTRL2_B.LBDLCFG = length; } /*! - * @brief Enables the USART LIN MODE + * @brief Enable the USART LIN MODE * * @param usart: Select the USART or the UART peripheral * @@ -336,7 +337,7 @@ void USART_ConfigLINBreakDetectLength(USART_T *usart, USART_LBDL_T length) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_EnableLIN(USART_T *usart) +void USART_EnableLIN(USART_T* usart) { usart->CTRL2_B.LINMEN = BIT_SET; } @@ -350,13 +351,13 @@ void USART_EnableLIN(USART_T *usart) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_DisableLIN(USART_T *usart) +void USART_DisableLIN(USART_T* usart) { usart->CTRL2_B.LINMEN = BIT_RESET; } /*! - * @brief Transmitter Enable + * @brief Transmitter enable * * @param usart: Select the USART or the UART peripheral * @@ -364,13 +365,13 @@ void USART_DisableLIN(USART_T *usart) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_EnableTx(USART_T *usart) +void USART_EnableTx(USART_T* usart) { usart->CTRL1_B.TXEN = BIT_SET; } /*! - * @brief Transmitter Disable + * @brief Transmitter disable * * @param usart: Select the USART or the UART peripheral * @@ -378,7 +379,7 @@ void USART_EnableTx(USART_T *usart) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_DisableTx(USART_T *usart) +void USART_DisableTx(USART_T* usart) { usart->CTRL1_B.TXEN = BIT_RESET; } @@ -392,7 +393,7 @@ void USART_DisableTx(USART_T *usart) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_EnableRx(USART_T *usart) +void USART_EnableRx(USART_T* usart) { usart->CTRL1_B.RXEN = BIT_SET; } @@ -406,7 +407,7 @@ void USART_EnableRx(USART_T *usart) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_DisableRx(USART_T *usart) +void USART_DisableRx(USART_T* usart) { usart->CTRL1_B.RXEN = BIT_RESET; } @@ -416,19 +417,19 @@ void USART_DisableRx(USART_T *usart) * * @param usart: Select the USART or the UART peripheral * - * @param data: the data to transmit + * @param data: the data to transmit * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_TxData(USART_T *usart, uint16_t data) +void USART_TxData(USART_T* usart, uint16_t data) { usart->DATA_B.DATA = data; } /*! - * @brief Returns the most recent received data + * @brief Return the most recent received data * * @param usart: Select the USART or the UART peripheral * @@ -436,7 +437,7 @@ void USART_TxData(USART_T *usart, uint16_t data) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -uint16_t USART_RxData(USART_T *usart) +uint16_t USART_RxData(USART_T* usart) { return (uint16_t)(usart->DATA_B.DATA); } @@ -450,15 +451,15 @@ uint16_t USART_RxData(USART_T *usart) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_TxBreak(USART_T *usart) +void USART_TxBreak(USART_T* usart) { usart->CTRL1_B.TXBF = BIT_SET; } /*! - * @brief Sets the specified USART guard time + * @brief Set the specified USART guard time * - * @param usart: Select the USART or the UART peripheral + * @param usart: Select the USART or the UART peripheral * * @param guardTime: Specifies the guard time * @@ -466,29 +467,29 @@ void USART_TxBreak(USART_T *usart) * * @note The usart can be USART1, USART2, USART3 */ -void USART_ConfigGuardTime(USART_T *usart, uint8_t guardTime) +void USART_ConfigGuardTime(USART_T* usart, uint8_t guardTime) { usart->GTPSC_B.GRDT = guardTime; } /*! - * @brief Sets the system clock divider number + * @brief Set the system clock divider number * * @param usart: Select the USART or the UART peripheral * - * @param div: specifies the divider number + * @param div: specifies the divider number * * @retval None * * @note The usart can be USART1, USART2, USART3 */ -void USART_ConfigPrescaler(USART_T *usart, uint8_t div) +void USART_ConfigPrescaler(USART_T* usart, uint8_t div) { usart->GTPSC_B.PSC = div; } /*! - * @brief Enables the USART Smart Card mode + * @brief Enable the USART Smart Card mode * * @param usart: Select the USART or the UART peripheral * @@ -496,7 +497,7 @@ void USART_ConfigPrescaler(USART_T *usart, uint8_t div) * * @note The Smart Card mode is not available for UART4 and UART5 */ -void USART_EnableSmartCard(USART_T *usart) +void USART_EnableSmartCard(USART_T* usart) { usart->CTRL3_B.SCEN = BIT_SET; } @@ -510,13 +511,13 @@ void USART_EnableSmartCard(USART_T *usart) * * @note The Smart Card mode is not available for UART4 and UART5 */ -void USART_DisableSmartCard(USART_T *usart) +void USART_DisableSmartCard(USART_T* usart) { usart->CTRL3_B.SCEN = BIT_RESET; } /*! - * @brief Enables NACK transmission + * @brief Enable NACK transmission * * @param usart: Select the USART or the UART peripheral * @@ -524,7 +525,7 @@ void USART_DisableSmartCard(USART_T *usart) * * @note The Smart Card mode is not available for UART4 and UART5 */ -void USART_EnableSmartCardNACK(USART_T *usart) +void USART_EnableSmartCardNACK(USART_T* usart) { usart->CTRL3_B.SCNACKEN = BIT_SET; } @@ -538,13 +539,13 @@ void USART_EnableSmartCardNACK(USART_T *usart) * * @note The Smart Card mode is not available for UART4 and UART5 */ -void USART_DisableSmartCardNACK(USART_T *usart) +void USART_DisableSmartCardNACK(USART_T* usart) { usart->CTRL3_B.SCNACKEN = BIT_RESET; } /*! - * @brief Enables USART Half Duplex communication + * @brief Enable USART Half Duplex communication * * @param usart: Select the USART or the UART peripheral * @@ -552,7 +553,7 @@ void USART_DisableSmartCardNACK(USART_T *usart) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_EnableHalfDuplex(USART_T *usart) +void USART_EnableHalfDuplex(USART_T* usart) { usart->CTRL3_B.HDEN = BIT_SET; } @@ -566,7 +567,7 @@ void USART_EnableHalfDuplex(USART_T *usart) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_DisableHalfDuplex(USART_T *usart) +void USART_DisableHalfDuplex(USART_T* usart) { usart->CTRL3_B.HDEN = BIT_RESET; } @@ -574,23 +575,23 @@ void USART_DisableHalfDuplex(USART_T *usart) /*! * @brief Configures the USART's IrDA interface * - * @param usart: Select the USART or the UART peripheral + * @param usart: Select the USART or the UART peripheral * * @param IrDAMode: Specifies the IrDA mode - * This parameter can be one of the following values: - * @arg USART_IRDALP_NORMAL: Normal - * @arg USART_IRDALP_LOWPOWER: Low-Power + * This parameter can be one of the following values: + * @arg USART_IRDALP_NORMAL: Normal + * @arg USART_IRDALP_LOWPOWER: Low-Power * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_ConfigIrDA(USART_T *usart, USART_IRDALP_T IrDAMode) +void USART_ConfigIrDA(USART_T* usart, USART_IRDALP_T IrDAMode) { usart->CTRL3_B.IRLPEN = IrDAMode; } /*! - * @brief Enables the USART's IrDA interface + * @brief Enable the USART's IrDA interface * * @param usart: Select the USART or the UART peripheral * @@ -598,7 +599,7 @@ void USART_ConfigIrDA(USART_T *usart, USART_IRDALP_T IrDAMode) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_EnableIrDA(USART_T *usart) +void USART_EnableIrDA(USART_T* usart) { usart->CTRL3_B.IREN = BIT_SET; } @@ -612,7 +613,7 @@ void USART_EnableIrDA(USART_T *usart) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_DisableIrDA(USART_T *usart) +void USART_DisableIrDA(USART_T* usart) { usart->CTRL3_B.IREN = BIT_RESET; } @@ -620,24 +621,24 @@ void USART_DisableIrDA(USART_T *usart) /*! * @brief Enable the specified USART interrupts * - * @param usart: Select the USART or the UART peripheral + * @param usart: Select the USART or the UART peripheral * - * @param interrupt: Specifies the USART interrupts sources - * The parameter can be one of following values: - * @arg USART_INT_PE: Parity error interrupt - * @arg USART_INT_TXBE: Tansmit data buffer empty interrupt - * @arg USART_INT_TXC: Transmission complete interrupt - * @arg USART_INT_RXBNE: Receive data buffer not empty interrupt - * @arg USART_INT_IDLE: Idle line detection interrupt - * @arg USART_INT_LBD: LIN break detection interrupt - * @arg USART_INT_CTS: CTS change interrupt - * @arg USART_INT_ERR: Error interrupt(Frame error, noise error, overrun error) + * @param interrupt: Specifies the USART interrupts sources + * The parameter can be one of following values: + * @arg USART_INT_PE: Parity error interrupt + * @arg USART_INT_TXBE: Tansmit data buffer empty interrupt + * @arg USART_INT_TXC: Transmission complete interrupt + * @arg USART_INT_RXBNE: Receive data buffer not empty interrupt + * @arg USART_INT_IDLE: Idle line detection interrupt + * @arg USART_INT_LBD: LIN break detection interrupt + * @arg USART_INT_CTS: CTS change interrupt + * @arg USART_INT_ERR: Error interrupt(Frame error, noise error, overrun error) * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_EnableInterrupt(USART_T *usart, USART_INT_T interrupt) +void USART_EnableInterrupt(USART_T* usart, USART_INT_T interrupt) { uint32_t temp; @@ -660,26 +661,26 @@ void USART_EnableInterrupt(USART_T *usart, USART_INT_T interrupt) } /*! - * @brief Disables the specified USART interrupts + * @brief Disable the specified USART interrupts * - * @param usart: Select the USART or the UART peripheral + * @param usart: Select the USART or the UART peripheral * - * @param interrupt: Specifies the USART interrupts sources - * The parameter can be one of following values: - * @arg USART_INT_PE: Parity error interrupt - * @arg USART_INT_TXBE: Tansmit data buffer empty interrupt - * @arg USART_INT_TXC: Transmission complete interrupt - * @arg USART_INT_RXBNE: Receive data buffer not empty interrupt - * @arg USART_INT_IDLE: Idle line detection interrupt - * @arg USART_INT_LBD: LIN break detection interrupt - * @arg USART_INT_CTS: CTS change interrupt - * @arg USART_INT_ERR: Error interrupt(Frame error, noise error, overrun error) + * @param interrupt: Specifies the USART interrupts sources + * The parameter can be one of following values: + * @arg USART_INT_PE: Parity error interrupt + * @arg USART_INT_TXBE: Tansmit data buffer empty interrupt + * @arg USART_INT_TXC: Transmission complete interrupt + * @arg USART_INT_RXBNE: Receive data buffer not empty interrupt + * @arg USART_INT_IDLE: Idle line detection interrupt + * @arg USART_INT_LBD: LIN break detection interrupt + * @arg USART_INT_CTS: CTS change interrupt + * @arg USART_INT_ERR: Error interrupt(Frame error, noise error, overrun error) * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_DisableInterrupt(USART_T *usart, USART_INT_T interrupt) +void USART_DisableInterrupt(USART_T* usart, USART_INT_T interrupt) { uint32_t temp; @@ -706,45 +707,45 @@ void USART_DisableInterrupt(USART_T *usart, USART_INT_T interrupt) * * @param usart: Select the USART or the UART peripheral * - * @param flag: Specifies the flag to check - * The parameter can be one of following values: - * @arg USART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5) - * @arg USART_FLAG_LBD: LIN Break detection flag - * @arg USART_FLAG_TXBE: Transmit data buffer empty flag - * @arg USART_FLAG_TXC: Transmission Complete flag - * @arg USART_FLAG_RXBNE: Receive data buffer not empty flag - * @arg USART_FLAG_IDLE: Idle Line detection flag - * @arg USART_FLAG_OVRE: OverRun Error flag - * @arg USART_FLAG_NE: Noise Error flag - * @arg USART_FLAG_FE: Framing Error flag - * @arg USART_FLAG_PE: Parity Error flag + * @param flag: Specifies the flag to check + * The parameter can be one of following values: + * @arg USART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5) + * @arg USART_FLAG_LBD: LIN Break detection flag + * @arg USART_FLAG_TXBE: Transmit data buffer empty flag + * @arg USART_FLAG_TXC: Transmission Complete flag + * @arg USART_FLAG_RXBNE: Receive data buffer not empty flag + * @arg USART_FLAG_IDLE: Idle Line detection flag + * @arg USART_FLAG_OVRE: OverRun Error flag + * @arg USART_FLAG_NE: Noise Error flag + * @arg USART_FLAG_FE: Framing Error flag + * @arg USART_FLAG_PE: Parity Error flag * * @retval The new state of flag (SET or RESET) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -uint8_t USART_ReadStatusFlag(USART_T *usart, USART_FLAG_T flag) +uint8_t USART_ReadStatusFlag(USART_T* usart, USART_FLAG_T flag) { return (usart->STS & flag) ? SET : RESET; } /*! - * @brief Clears the USARTx's pending flags + * @brief Clear the USARTx's pending flags * - * @param usart: Select the USART or the UART peripheral + * @param usart: Select the USART or the UART peripheral * - * @param flag: Specifies the flag to clear - * The parameter can be one of following values: - * @arg USART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5) - * @arg USART_FLAG_LBD: LIN Break detection flag - * @arg USART_FLAG_TXC: Transmission Complete flag - * @arg USART_FLAG_RXBNE: Receive data buffer not empty flag + * @param flag: Specifies the flag to clear + * The parameter can be one of following values: + * @arg USART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5) + * @arg USART_FLAG_LBD: LIN Break detection flag + * @arg USART_FLAG_TXC: Transmission Complete flag + * @arg USART_FLAG_RXBNE: Receive data buffer not empty flag * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_ClearStatusFlag(USART_T *usart, USART_FLAG_T flag) +void USART_ClearStatusFlag(USART_T* usart, USART_FLAG_T flag) { usart->STS &= (uint32_t)~flag; } @@ -755,23 +756,23 @@ void USART_ClearStatusFlag(USART_T *usart, USART_FLAG_T flag) * @param usart: Select the USART or the UART peripheral * * @param flag: Specifies the USART interrupt source to check - * The parameter can be one of following values: - * @arg USART_INT_TXBE: Tansmit data buffer empty interrupt - * @arg USART_INT_TXC: Transmission complete interrupt - * @arg USART_INT_RXBNE: Receive data buffer not empty interrupt - * @arg USART_INT_IDLE: Idle line detection interrupt - * @arg USART_INT_LBD: LIN break detection interrupt - * @arg USART_INT_CTS: CTS change interrupt - * @arg USART_INT_OVRE: OverRun Error interruptpt - * @arg USART_INT_NE: Noise Error interrupt - * @arg USART_INT_FE: Framing Error interrupt - * @arg USART_INT_PE: Parity error interrupt + * The parameter can be one of following values: + * @arg USART_INT_TXBE: Tansmit data buffer empty interrupt + * @arg USART_INT_TXC: Transmission complete interrupt + * @arg USART_INT_RXBNE: Receive data buffer not empty interrupt + * @arg USART_INT_IDLE: Idle line detection interrupt + * @arg USART_INT_LBD: LIN break detection interrupt + * @arg USART_INT_CTS: CTS change interrupt + * @arg USART_INT_OVRE: OverRun Error interruptpt + * @arg USART_INT_NE: Noise Error interrupt + * @arg USART_INT_FE: Framing Error interrupt + * @arg USART_INT_PE: Parity error interrupt * * @retval The new state of flag (SET or RESET) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -uint8_t USART_ReadIntFlag(USART_T *usart, USART_INT_T flag) +uint8_t USART_ReadIntFlag(USART_T* usart, USART_INT_T flag) { uint32_t itFlag, srFlag; @@ -801,22 +802,22 @@ uint8_t USART_ReadIntFlag(USART_T *usart, USART_INT_T flag) } /*! - * @brief Clears the USART interrupt pending bits + * @brief Clear the USART interrupt pending bits * * @param usart: Select the USART or the UART peripheral * - * @param flag: Specifies the interrupt pending bit to clear - * The parameter can be one of following values: - * @arg USART_INT_RXBNE: Receive data buffer not empty interrupt - * @arg USART_INT_TXC: Transmission complete interrupt - * @arg USART_INT_LBD: LIN break detection interrupt - * @arg USART_INT_CTS: CTS change interrupt + * @param flag: Specifies the interrupt pending bit to clear + * The parameter can be one of following values: + * @arg USART_INT_RXBNE: Receive data buffer not empty interrupt + * @arg USART_INT_TXC: Transmission complete interrupt + * @arg USART_INT_LBD: LIN break detection interrupt + * @arg USART_INT_CTS: CTS change interrupt * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ -void USART_ClearIntFlag(USART_T *usart, USART_INT_T flag) +void USART_ClearIntFlag(USART_T* usart, USART_INT_T flag) { uint32_t srFlag; @@ -826,6 +827,6 @@ void USART_ClearIntFlag(USART_T *usart, USART_INT_T flag) usart->STS &= (uint32_t)~srFlag; } -/**@} end of group USART_Fuctions*/ -/**@} end of group USART_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group USART_Functions */ +/**@} end of group USART_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_wwdt.c b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_wwdt.c index e7a65ea69d..93e6a7e4dd 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_wwdt.c +++ b/bsp/apm32/libraries/APM32F10x_Library/APM32F10x_StdPeriphDriver/src/apm32f10x_wwdt.c @@ -3,9 +3,9 @@ * * @brief This file contains all the functions for the WWDT peripheral * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,24 +26,25 @@ #include "apm32f10x_wwdt.h" #include "apm32f10x_rcm.h" -/** @addtogroup Peripherals_Library Standard Peripheral Library +/** @addtogroup APM32F10x_StdPeriphDriver @{ */ -/** @addtogroup WWDT_Driver WWDT Driver +/** @defgroup WWDT_Driver WWDT Driver + * @brief WWDT driver modules @{ */ -/** @addtogroup WWDT_Fuctions Fuctions +/** @defgroup WWDT_Functions Functions @{ */ /*! - * @brief Reset the WWDT peripheral registers + * @brief Reset the WWDT peripheral registers * - * @param None + * @param None * - * @retval None + * @retval None */ void WWDT_Reset(void) { @@ -52,16 +53,16 @@ void WWDT_Reset(void) } /*! - * @brief Config the WWDT Timebase + * @brief Configures the WWDT Timebase * - * @param timebase: WWDT Prescaler - * The parameter can be one of following values: - * @arg WWDT_TIME_BASE_1: WWDT counter clock = (PCLK1/4096)/1 - * @arg WWDT_TIME_BASE_2: WWDT counter clock = (PCLK1/4096)/2 - * @arg WWDT_TIME_BASE_4: WWDT counter clock = (PCLK1/4096)/4 - * @arg WWDT_TIME_BASE_8: WWDT counter clock = (PCLK1/4096)/8 + * @param timebase: WWDT Prescaler + * The parameter can be one of following values: + * @arg WWDT_TIME_BASE_1: WWDT counter clock = (PCLK1/4096)/1 + * @arg WWDT_TIME_BASE_2: WWDT counter clock = (PCLK1/4096)/2 + * @arg WWDT_TIME_BASE_4: WWDT counter clock = (PCLK1/4096)/4 + * @arg WWDT_TIME_BASE_8: WWDT counter clock = (PCLK1/4096)/8 * - * @retval None + * @retval None */ void WWDT_ConfigTimebase(WWDT_TIME_BASE_T timeBase) { @@ -73,13 +74,13 @@ void WWDT_ConfigTimebase(WWDT_TIME_BASE_T timeBase) } /*! - * @brief Config the WWDT Window data + * @brief Configures the WWDT Window data * - * @param windowdata: window data which compare with the downcounter + * @param windowdata: window data which compare with the downcounter * - * @retval None + * @retval None * - * @note The windowdata must be lower than 0x80 + * @note The windowdata must be lower than 0x80 */ void WWDT_ConfigWindowData(uint8_t windowData) { @@ -91,7 +92,7 @@ void WWDT_ConfigWindowData(uint8_t windowData) } /*! - * @brief Config the WWDT counter value + * @brief Configures the WWDT counter value * * @param counter: Specifies the watchdog counter value * @@ -105,11 +106,11 @@ void WWDT_ConfigCounter(uint8_t counter) } /*! - * @brief Enable the WWDT Early Wakeup interrupt + * @brief Enable the WWDT Early Wakeup interrupt * - * @param None + * @param None * - * @retval None + * @retval None */ void WWDT_EnableEWI(void) { @@ -117,13 +118,13 @@ void WWDT_EnableEWI(void) } /*! - * @brief Enable WWDT and set the counter value + * @brief Enable WWDT and set the counter value * - * @param counter: the window watchdog counter value + * @param counter: the window watchdog counter value * - * @retval None + * @retval None * - * @note The counter between 0x40 and 0x7F + * @note The counter between 0x40 and 0x7F */ void WWDT_Enable(uint8_t counter) { @@ -131,11 +132,11 @@ void WWDT_Enable(uint8_t counter) } /*! - * @brief Read the Early Wakeup interrupt flag + * @brief Read the Early Wakeup interrupt flag * - * @param None + * @param None * - * @retval the state of the Early Wakeup interrupt flagte + * @retval the state of the Early Wakeup interrupt flagte */ uint8_t WWDT_ReadFlag(void) { @@ -143,17 +144,17 @@ uint8_t WWDT_ReadFlag(void) } /*! - * @brief Clear the Early Wakeup interrupt flag + * @brief Clear the Early Wakeup interrupt flag * - * @param None + * @param None * - * @retval None + * @retval None */ void WWDT_ClearFlag(void) { WWDT->STS_B.EWIFLG = RESET; } -/**@} end of group WWDT_Fuctions*/ -/**@} end of group WWDT_Driver*/ -/**@} end of group Peripherals_Library*/ +/**@} end of group WWDT_Functions */ +/**@} end of group WWDT_Driver */ +/**@} end of group APM32F10x_StdPeriphDriver */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/CMSIS/Include/cmsis_gcc.h b/bsp/apm32/libraries/APM32F10x_Library/CMSIS/Include/cmsis_gcc.h index cd374afaef..67bda4ef3c 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/CMSIS/Include/cmsis_gcc.h +++ b/bsp/apm32/libraries/APM32F10x_Library/CMSIS/Include/cmsis_gcc.h @@ -1,11 +1,11 @@ /**************************************************************************//** * @file cmsis_gcc.h * @brief CMSIS compiler GCC header file - * @version V5.0.4 - * @date 09. April 2018 + * @version V5.4.1 + * @date 27. May 2021 ******************************************************************************/ /* - * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -113,6 +113,826 @@ #ifndef __RESTRICT #define __RESTRICT __restrict #endif +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START + +/** + \brief Initializes data and bss sections + \details This default implementations initialized all data and additional bss + sections relying on .copy.table and .zero.table specified properly + in the used linker script. + + */ +__STATIC_FORCEINLINE __NO_RETURN void __cmsis_start(void) +{ + extern void _start(void) __NO_RETURN; + + typedef struct { + uint32_t const* src; + uint32_t* dest; + uint32_t wlen; + } __copy_table_t; + + typedef struct { + uint32_t* dest; + uint32_t wlen; + } __zero_table_t; + + extern const __copy_table_t __copy_table_start__; + extern const __copy_table_t __copy_table_end__; + extern const __zero_table_t __zero_table_start__; + extern const __zero_table_t __zero_table_end__; + + for (__copy_table_t const* pTable = &__copy_table_start__; pTable < &__copy_table_end__; ++pTable) { + for(uint32_t i=0u; iwlen; ++i) { + pTable->dest[i] = pTable->src[i]; + } + } + + for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) { + for(uint32_t i=0u; iwlen; ++i) { + pTable->dest[i] = 0u; + } + } + + _start(); +} + +#define __PROGRAM_START __cmsis_start +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP __StackTop +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT __StackLimit +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section(".vectors"))) +#endif + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#ifndef __STACK_SEAL +#define __STACK_SEAL __StackSeal +#endif + +#ifndef __TZ_STACK_SEAL_SIZE +#define __TZ_STACK_SEAL_SIZE 8U +#endif + +#ifndef __TZ_STACK_SEAL_VALUE +#define __TZ_STACK_SEAL_VALUE 0xFEF5EDA5FEF5EDA5ULL +#endif + + +__STATIC_FORCEINLINE void __TZ_set_STACKSEAL_S (uint32_t* stackTop) { + *((uint64_t *)stackTop) = __TZ_STACK_SEAL_VALUE; +} +#endif + + +/* ########################## 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":::"memory") + + +/** + \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":::"memory") + + +/** + \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 ("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 ("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 ("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 ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value != 0U; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return result; +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM GCC 7.3 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +__STATIC_FORCEINLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1, ARG2) \ +__extension__ \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM volatile ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ + __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 volatile ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ + __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) : "memory" ); + 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) : "memory" ); + 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) : "memory" ); + 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) : "memory" ); +} + + +/** + \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) : "memory" ); +} + + +/** + \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) : "memory" ); +} + + +/** + \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) : "memory" ); + 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) : "memory" ); + 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) : "memory" ); + 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) : "memory" ); + 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) : "memory" ); + 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) : "memory" ); + 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 */ /* ########################### Core Function Access ########################### */ @@ -123,7 +943,7 @@ /** \brief Enable IRQ Interrupts - \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. Can only be executed in Privileged modes. */ __STATIC_FORCEINLINE void __enable_irq(void) @@ -134,7 +954,7 @@ __STATIC_FORCEINLINE void __enable_irq(void) /** \brief Disable IRQ Interrupts - \details Disables IRQ interrupts by setting the I-bit in the CPSR. + \details Disables IRQ interrupts by setting special-purpose register PRIMASK. Can only be executed in Privileged modes. */ __STATIC_FORCEINLINE void __disable_irq(void) @@ -181,6 +1001,7 @@ __STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) __STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) { __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); + __ISB(); } @@ -193,6 +1014,7 @@ __STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) __STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) { __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); + __ISB(); } #endif @@ -383,7 +1205,7 @@ __STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) { uint32_t result; - __ASM volatile ("MRS %0, primask" : "=r" (result) :: "memory"); + __ASM volatile ("MRS %0, primask" : "=r" (result) ); return(result); } @@ -398,7 +1220,7 @@ __STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) { uint32_t result; - __ASM volatile ("MRS %0, primask_ns" : "=r" (result) :: "memory"); + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); return(result); } #endif @@ -433,7 +1255,7 @@ __STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) (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. + \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. Can only be executed in Privileged modes. */ __STATIC_FORCEINLINE void __enable_fault_irq(void) @@ -444,7 +1266,7 @@ __STATIC_FORCEINLINE void __enable_fault_irq(void) /** \brief Disable FIQ - \details Disables FIQ interrupts by setting the F-bit in the CPSR. + \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. Can only be executed in Privileged modes. */ __STATIC_FORCEINLINE void __disable_fault_irq(void) @@ -810,723 +1632,6 @@ __STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr) /*@} 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 @@ -1547,7 +1652,7 @@ __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) ); + __ASM ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1555,7 +1660,7 @@ __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) ); + __ASM ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1571,7 +1676,7 @@ __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) ); + __ASM ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1579,7 +1684,7 @@ __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) ); + __ASM ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1596,7 +1701,7 @@ __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) ); + __ASM ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1604,7 +1709,7 @@ __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) ); + __ASM ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1620,7 +1725,7 @@ __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) ); + __ASM ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1628,7 +1733,7 @@ __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) ); + __ASM ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1645,7 +1750,7 @@ __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) ); + __ASM ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1653,7 +1758,7 @@ __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) ); + __ASM ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1669,7 +1774,7 @@ __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) ); + __ASM ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1677,7 +1782,7 @@ __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) ); + __ASM ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1693,7 +1798,7 @@ __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) ); + __ASM ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1701,7 +1806,7 @@ __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) ); + __ASM ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1717,7 +1822,7 @@ __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) ); + __ASM ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1725,7 +1830,7 @@ __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) ); + __ASM ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1741,7 +1846,7 @@ __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) ); + __ASM ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1749,7 +1854,7 @@ __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) ); + __ASM ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1765,7 +1870,7 @@ __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) ); + __ASM ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1773,7 +1878,7 @@ __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) ); + __ASM ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1789,7 +1894,7 @@ __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) ); + __ASM ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1797,7 +1902,7 @@ __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) ); + __ASM ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1813,7 +1918,7 @@ __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) ); + __ASM ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1821,7 +1926,7 @@ __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) ); + __ASM ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1829,7 +1934,7 @@ __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) ); + __ASM ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1837,21 +1942,23 @@ __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) ); + __ASM ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); return(result); } -#define __SSAT16(ARG1,ARG2) \ +#define __SSAT16(ARG1, ARG2) \ +__extension__ \ ({ \ int32_t __RES, __ARG1 = (ARG1); \ - __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __ASM volatile ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ __RES; \ }) -#define __USAT16(ARG1,ARG2) \ +#define __USAT16(ARG1, ARG2) \ +__extension__ \ ({ \ uint32_t __RES, __ARG1 = (ARG1); \ - __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __ASM volatile ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ __RES; \ }) @@ -1859,7 +1966,7 @@ __STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) { uint32_t result; - __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + __ASM ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); return(result); } @@ -1867,7 +1974,7 @@ __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) ); + __ASM ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } @@ -1875,18 +1982,41 @@ __STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) { uint32_t result; - __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + __ASM ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); return(result); } +__STATIC_FORCEINLINE uint32_t __SXTB16_RORn(uint32_t op1, uint32_t rotate) +{ + uint32_t result; + if (__builtin_constant_p(rotate) && ((rotate == 8U) || (rotate == 16U) || (rotate == 24U))) { + __ASM volatile ("sxtb16 %0, %1, ROR %2" : "=r" (result) : "r" (op1), "i" (rotate) ); + } else { + result = __SXTB16(__ROR(op1, rotate)) ; + } + 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) ); + __ASM ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } +__STATIC_FORCEINLINE uint32_t __SXTAB16_RORn(uint32_t op1, uint32_t op2, uint32_t rotate) +{ + uint32_t result; + if (__builtin_constant_p(rotate) && ((rotate == 8U) || (rotate == 16U) || (rotate == 24U))) { + __ASM volatile ("sxtab16 %0, %1, %2, ROR %3" : "=r" (result) : "r" (op1) , "r" (op2) , "i" (rotate)); + } else { + result = __SXTAB16(op1, __ROR(op2, rotate)); + } + return result; +} + + __STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) { uint32_t result; @@ -2043,8 +2173,9 @@ __STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) return(result); } -#if 0 + #define __PKHBT(ARG1,ARG2,ARG3) \ +__extension__ \ ({ \ uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ @@ -2052,6 +2183,7 @@ __STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) }) #define __PKHTB(ARG1,ARG2,ARG3) \ +__extension__ \ ({ \ uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ if (ARG3 == 0) \ @@ -2060,19 +2192,13 @@ __STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) __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) ); + __ASM ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); return(result); } diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Include/apm32f10x.h b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Include/apm32f10x.h index d0466dc46f..20e6c0f2be 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Include/apm32f10x.h +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Include/apm32f10x.h @@ -5,9 +5,9 @@ * * @details This file contains all the peripheral register's definitions, bits definitions and memory mapping * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -17,7 +17,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,209 +25,293 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __APM32F10X_H #define __APM32F10X_H #ifdef __cplusplus - extern "C" { +extern "C" { #endif /*! * APM32F10X_LD: APM32 Low density devices, the Flash memory density ranges between 16 and 32 Kbytes. * APM32F10X_MD: APM32 Medium density devices, the Flash memory density ranges between 64 and 128 Kbytes. * APM32F10X_HD: APM32 High density devices, the Flash memory density ranges between 256 and 512 Kbytes. + * APM32F10X_CL: APM32 Connectivity line devices, such as APM32F105xx and APM32F107xx serial devices. */ -#if !defined (APM32F10X_LD) && !defined (APM32F10X_MD) && !defined (APM32F10X_HD) +#if !defined (APM32F10X_LD) && !defined (APM32F10X_MD) && !defined (APM32F10X_HD) && !defined (APM32F10X_CL) #error "Please select a the target APM32F10x device used in your application (in apm32f10x.h file)" #endif +/** @addtogroup CMSIS + @{ +*/ + +/** @addtogroup APM32F10x + * @brief Peripheral Access Layer + @{ +*/ + +/** @defgroup HSE_Macros + @{ +*/ + /** * @brief Define Value of the External oscillator in Hz */ #ifndef HSE_VALUE - #define HSE_VALUE ((uint32_t)8000000) +#ifndef APM32F10X_CL +#define HSE_VALUE ((uint32_t)8000000) +#else +#define HSE_VALUE ((uint32_t)25000000) +#endif #endif -/** Time out for HSE start up */ +/* Time out for HSE start up */ #define HSE_STARTUP_TIMEOUT ((uint16_t)0x05000) -/** Value of the Internal oscillator in Hz */ +/* Value of the Internal oscillator in Hz */ #define HSI_VALUE ((uint32_t)8000000) +/**@} end of group HSE_Macros */ + +/** @defgroup APM32F10x_StdPeripheral_Library_Version + @{ +*/ + /** * @brief APM32F10x Standard Peripheral Library version number */ #define __APM32F10X_STDPERIPH_VERSION_MAIN (0x01) /*!< [31:24] main version */ #define __APM32F10X_STDPERIPH_VERSION_SUB1 (0x00) /*!< [23:16] sub1 version */ -#define __APM32F10X_STDPERIPH_VERSION_SUB2 (0x02) /*!< [15:8] sub2 version */ +#define __APM32F10X_STDPERIPH_VERSION_SUB2 (0x07) /*!< [15:8] sub2 version */ #define __APM32F10X_STDPERIPH_VERSION_RC (0x00) /*!< [7:0] release candidate */ #define __APM32F10X_STDPERIPH_VERSION ( (__APM32F10X_STDPERIPH_VERSION_MAIN << 24)\ |(__APM32F10X_STDPERIPH_VERSION_SUB1 << 16)\ |(__APM32F10X_STDPERIPH_VERSION_SUB2 << 8)\ |(__APM32F10X_STDPERIPH_VERSION_RC)) +/**@} end of group APM32F0xx_StdPeripheral_Library_Version */ -/** APM32 devices does not provide an MPU */ - #define __MPU_PRESENT 0 -/** APM32 uses 4 Bits for the Priority Levels */ +/** @defgroup Configuraion_for_CMSIS + @{ +*/ + +/* APM32 devices does not provide an MPU */ +#define __MPU_PRESENT 0 +/* APM32 uses 4 Bits for the Priority Levels */ #define __NVIC_PRIO_BITS 4 -/** Set to 1 if different SysTick Config is used */ +/* Set to 1 if different SysTick Config is used */ #define __Vendor_SysTickConfig 0 +/**@} end of group Configuraion_for_CMSIS */ + +/** @defgroup Peripheral_Enumerations + @{ +*/ + /** * @brief APM32F10x Interrupt Number Definition, according to the selected device * in @ref Library_configuration_section */ typedef enum IRQn { -/****** Cortex-M3 Processor Exceptions Numbers ***************************************************/ - NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ - MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */ - BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */ - UsageFault_IRQn = -10, /*!< 6 Cortex-M3 Usage Fault Interrupt */ - SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV Call Interrupt */ - DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 Debug Monitor Interrupt */ - PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */ - SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */ + /****** Cortex-M3 Processor Exceptions Numbers ***************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M3 Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */ -/****** APM32 specific Interrupt Numbers *********************************************************/ - WWDT_IRQn = 0, /*!< Window WatchDog Interrupt */ - PVD_IRQn = 1, /*!< PVD through EINT Line detection Interrupt */ - TAMPER_IRQn = 2, /*!< Tamper Interrupt */ - RTC_IRQn = 3, /*!< RTC global Interrupt */ - FLASH_IRQn = 4, /*!< FLASH global Interrupt */ - RCM_IRQn = 5, /*!< RCM global Interrupt */ - EINT0_IRQn = 6, /*!< EINT Line0 Interrupt */ - EINT1_IRQn = 7, /*!< EINT Line1 Interrupt */ - EINT2_IRQn = 8, /*!< EINT Line2 Interrupt */ - EINT3_IRQn = 9, /*!< EINT Line3 Interrupt */ - EINT4_IRQn = 10, /*!< EINT 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 */ + /****** APM32 specific Interrupt Numbers *********************************************************/ + WWDT_IRQn = 0, /*!< Window WatchDog Interrupt */ + PVD_IRQn = 1, /*!< PVD through EINT Line detection Interrupt */ + TAMPER_IRQn = 2, /*!< Tamper Interrupt */ + RTC_IRQn = 3, /*!< RTC global Interrupt */ + FLASH_IRQn = 4, /*!< FLASH global Interrupt */ + RCM_IRQn = 5, /*!< RCM global Interrupt */ + EINT0_IRQn = 6, /*!< EINT Line0 Interrupt */ + EINT1_IRQn = 7, /*!< EINT Line1 Interrupt */ + EINT2_IRQn = 8, /*!< EINT Line2 Interrupt */ + EINT3_IRQn = 9, /*!< EINT Line3 Interrupt */ + EINT4_IRQn = 10, /*!< EINT 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 */ #if defined (APM32F10X_LD) - /** APM32F10X Low-density devices specific Interrupt Numbers */ - ADC1_2_IRQn = 18, /*!< ADC1 and ADC2 global Interrupt */ - USBD1_HP_CAN1_TX_IRQn = 19, /*!< USB Device 1 High Priority or CAN1 TX Interrupts */ - USBD1_LP_CAN1_RX0_IRQn = 20, /*!< USB Device 1 Low Priority or CAN1 RX0 Interrupts */ - CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ - CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ - EINT9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ - TMR1_BRK_IRQn = 24, /*!< TMR1 Break Interrupt */ - TMR1_UP_IRQn = 25, /*!< TMR1 Update Interrupt */ - TMR1_TRG_COM_IRQn = 26, /*!< TMR1 Trigger and Commutation Interrupt */ - TMR1_CC_IRQn = 27, /*!< TMR1 Capture Compare Interrupt */ - TMR2_IRQn = 28, /*!< TMR2 global Interrupt */ - TMR3_IRQn = 29, /*!< TMR3 global Interrupt */ - I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ - I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ - SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ - USART1_IRQn = 37, /*!< USART1 global Interrupt */ - USART2_IRQn = 38, /*!< USART2 global Interrupt */ - EINT15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ - RTCAlarm_IRQn = 41, /*!< RTC Alarm through EINT Line Interrupt */ - USBDWakeUp_IRQn = 42, /*!< USB Device WakeUp from suspend through EINT Line Interrupt */ - FPU_IRQn = 43, /*!< FPU Global Interrupt */ - QSPI_IRQn = 44, /*!< QSPI Global Interrupt */ - USBD2_HP_IRQn = 45, /*!< USB Device 2 High Priority */ - USBD2_LP_IRQn = 46 /*!< USB Device 2 Low Priority */ + /* APM32F10X Low-density devices specific Interrupt Numbers */ + ADC1_2_IRQn = 18, /*!< ADC1 and ADC2 global Interrupt */ + USBD1_HP_CAN1_TX_IRQn = 19, /*!< USB Device 1 High Priority or CAN1 TX Interrupts */ + USBD1_LP_CAN1_RX0_IRQn = 20, /*!< USB Device 1 Low Priority or CAN1 RX0 Interrupts */ + CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ + CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ + EINT9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TMR1_BRK_IRQn = 24, /*!< TMR1 Break Interrupt */ + TMR1_UP_IRQn = 25, /*!< TMR1 Update Interrupt */ + TMR1_TRG_COM_IRQn = 26, /*!< TMR1 Trigger and Commutation Interrupt */ + TMR1_CC_IRQn = 27, /*!< TMR1 Capture Compare Interrupt */ + TMR2_IRQn = 28, /*!< TMR2 global Interrupt */ + TMR3_IRQn = 29, /*!< TMR3 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + EINT15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTCAlarm_IRQn = 41, /*!< RTC Alarm through EINT Line Interrupt */ + USBDWakeUp_IRQn = 42, /*!< USB Device WakeUp from suspend through EINT Line Interrupt */ + FPU_IRQn = 43, /*!< FPU Global Interrupt */ + QSPI_IRQn = 44, /*!< QSPI Global Interrupt */ + USBD2_HP_IRQn = 45, /*!< USB Device 2 High Priority */ + USBD2_LP_IRQn = 46 /*!< USB Device 2 Low Priority */ #elif defined (APM32F10X_MD) - /** APM32F10X Medium-density devices specific Interrupt Numbers */ - ADC1_2_IRQn = 18, /*!< ADC1 and ADC2 global Interrupt */ - USBD1_HP_CAN1_TX_IRQn = 19, /*!< USB Device 1 High Priority or CAN1 TX Interrupts */ - USBD1_LP_CAN1_RX0_IRQn = 20, /*!< USB Device 1 Low Priority or CAN1 RX0 Interrupts */ - CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ - CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ - EINT9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ - TMR1_BRK_IRQn = 24, /*!< TMR1 Break Interrupt */ - TMR1_UP_IRQn = 25, /*!< TMR1 Update Interrupt */ - TMR1_TRG_COM_IRQn = 26, /*!< TMR1 Trigger and Commutation Interrupt */ - TMR1_CC_IRQn = 27, /*!< TMR1 Capture Compare Interrupt */ - TMR2_IRQn = 28, /*!< TMR2 global Interrupt */ - TMR3_IRQn = 29, /*!< TMR3 global Interrupt */ - TMR4_IRQn = 30, /*!< TMR4 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 */ - EINT15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ - RTCAlarm_IRQn = 41, /*!< RTC Alarm through EINT Line Interrupt */ - USBDWakeUp_IRQn = 42, /*!< USB Device WakeUp from suspend through EINT Line Interrupt */ - FPU_IRQn = 43, /*!< FPU Global Interrupt */ - QSPI_IRQn = 44, /*!< QSPI Global Interrupt */ - USBD2_HP_IRQn = 45, /*!< USB Device 2 High Priority */ - USBD2_LP_IRQn = 46 /*!< USB Device 2 Low Priority */ + /* APM32F10X Medium-density devices specific Interrupt Numbers */ + ADC1_2_IRQn = 18, /*!< ADC1 and ADC2 global Interrupt */ + USBD1_HP_CAN1_TX_IRQn = 19, /*!< USB Device 1 High Priority or CAN1 TX Interrupts */ + USBD1_LP_CAN1_RX0_IRQn = 20, /*!< USB Device 1 Low Priority or CAN1 RX0 Interrupts */ + CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ + CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ + EINT9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TMR1_BRK_IRQn = 24, /*!< TMR1 Break Interrupt */ + TMR1_UP_IRQn = 25, /*!< TMR1 Update Interrupt */ + TMR1_TRG_COM_IRQn = 26, /*!< TMR1 Trigger and Commutation Interrupt */ + TMR1_CC_IRQn = 27, /*!< TMR1 Capture Compare Interrupt */ + TMR2_IRQn = 28, /*!< TMR2 global Interrupt */ + TMR3_IRQn = 29, /*!< TMR3 global Interrupt */ + TMR4_IRQn = 30, /*!< TMR4 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 */ + EINT15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTCAlarm_IRQn = 41, /*!< RTC Alarm through EINT Line Interrupt */ + USBDWakeUp_IRQn = 42, /*!< USB Device WakeUp from suspend through EINT Line Interrupt */ + FPU_IRQn = 43, /*!< FPU Global Interrupt */ + QSPI_IRQn = 44, /*!< QSPI Global Interrupt */ + USBD2_HP_IRQn = 45, /*!< USB Device 2 High Priority */ + USBD2_LP_IRQn = 46 /*!< USB Device 2 Low Priority */ #elif defined (APM32F10X_HD) - /** APM32F10X High-density devices specific Interrupt Numbers */ - ADC1_2_IRQn = 18, /*!< ADC1 and ADC2 global Interrupt */ - USBD1_HP_CAN1_TX_IRQn = 19, /*!< USB Device 1 High Priority or CAN1 TX Interrupts */ - USBD1_LP_CAN1_RX0_IRQn = 20, /*!< USB Device 1 Low Priority or CAN1 RX0 Interrupts */ - CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ - CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ - EINT9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ - TMR1_BRK_IRQn = 24, /*!< TMR1 Break Interrupt */ - TMR1_UP_IRQn = 25, /*!< TMR1 Update Interrupt */ - TMR1_TRG_COM_IRQn = 26, /*!< TMR1 Trigger and Commutation Interrupt */ - TMR1_CC_IRQn = 27, /*!< TMR1 Capture Compare Interrupt */ - TMR2_IRQn = 28, /*!< TMR2 global Interrupt */ - TMR3_IRQn = 29, /*!< TMR3 global Interrupt */ - TMR4_IRQn = 30, /*!< TMR4 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 */ - EINT15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ - RTCAlarm_IRQn = 41, /*!< RTC Alarm through EINT Line Interrupt */ - USBDWakeUp_IRQn = 42, /*!< USB Device WakeUp from suspend through EINT Line Interrupt */ - TMR8_BRK_IRQn = 43, /*!< TMR8 Break Interrupt */ - TMR8_UP_IRQn = 44, /*!< TMR8 Update Interrupt */ - TMR8_TRG_COM_IRQn = 45, /*!< TMR8 Trigger and Commutation Interrupt */ - TMR8_CC_IRQn = 46, /*!< TMR8 Capture Compare Interrupt */ - ADC3_IRQn = 47, /*!< ADC3 global Interrupt */ - EMMC_IRQn = 48, /*!< EMMC global Interrupt */ - SDIO_IRQn = 49, /*!< SDIO global Interrupt */ - TMR5_IRQn = 50, /*!< TMR5 global Interrupt */ - SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ - UART4_IRQn = 52, /*!< UART4 global Interrupt */ - UART5_IRQn = 53, /*!< UART5 global Interrupt */ - TMR6_IRQn = 54, /*!< TMR6 global Interrupt */ - TMR7_IRQn = 55, /*!< TMR7 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_5_IRQn = 59, /*!< DMA2 Channel 4 and Channel 5 global Interrupt */ - USBD2_HP_CAN2_TX_IRQn = 61, /*!< USB Device 2 High Priority or CAN2 TX Interrupts */ - USBD2_LP_CAN2_RX0_IRQn = 62, /*!< USB Device 2 Low Priority or CAN2 RX0 Interrupts */ - CAN2_RX1_IRQn = 63, /*!< CAN2 RX1 Interrupts */ - CAN2_SCE_IRQn = 64, /*!< CAN2 SCE Interrupts */ + /* APM32F10X High-density devices specific Interrupt Numbers */ + ADC1_2_IRQn = 18, /*!< ADC1 and ADC2 global Interrupt */ + USBD1_HP_CAN1_TX_IRQn = 19, /*!< USB Device 1 High Priority or CAN1 TX Interrupts */ + USBD1_LP_CAN1_RX0_IRQn = 20, /*!< USB Device 1 Low Priority or CAN1 RX0 Interrupts */ + CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ + CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ + EINT9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TMR1_BRK_IRQn = 24, /*!< TMR1 Break Interrupt */ + TMR1_UP_IRQn = 25, /*!< TMR1 Update Interrupt */ + TMR1_TRG_COM_IRQn = 26, /*!< TMR1 Trigger and Commutation Interrupt */ + TMR1_CC_IRQn = 27, /*!< TMR1 Capture Compare Interrupt */ + TMR2_IRQn = 28, /*!< TMR2 global Interrupt */ + TMR3_IRQn = 29, /*!< TMR3 global Interrupt */ + TMR4_IRQn = 30, /*!< TMR4 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 */ + EINT15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTCAlarm_IRQn = 41, /*!< RTC Alarm through EINT Line Interrupt */ + USBDWakeUp_IRQn = 42, /*!< USB Device WakeUp from suspend through EINT Line Interrupt */ + TMR8_BRK_IRQn = 43, /*!< TMR8 Break Interrupt */ + TMR8_UP_IRQn = 44, /*!< TMR8 Update Interrupt */ + TMR8_TRG_COM_IRQn = 45, /*!< TMR8 Trigger and Commutation Interrupt */ + TMR8_CC_IRQn = 46, /*!< TMR8 Capture Compare Interrupt */ + ADC3_IRQn = 47, /*!< ADC3 global Interrupt */ + EMMC_IRQn = 48, /*!< EMMC global Interrupt */ + SDIO_IRQn = 49, /*!< SDIO global Interrupt */ + TMR5_IRQn = 50, /*!< TMR5 global Interrupt */ + SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ + UART4_IRQn = 52, /*!< UART4 global Interrupt */ + UART5_IRQn = 53, /*!< UART5 global Interrupt */ + TMR6_IRQn = 54, /*!< TMR6 global Interrupt */ + TMR7_IRQn = 55, /*!< TMR7 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_5_IRQn = 59, /*!< DMA2 Channel 4 and Channel 5 global Interrupt */ + USBD2_HP_CAN2_TX_IRQn = 61, /*!< USB Device 2 High Priority or CAN2 TX Interrupts */ + USBD2_LP_CAN2_RX0_IRQn = 62, /*!< USB Device 2 Low Priority or CAN2 RX0 Interrupts */ + CAN2_RX1_IRQn = 63, /*!< CAN2 RX1 Interrupts */ + CAN2_SCE_IRQn = 64, /*!< CAN2 SCE Interrupts */ +#elif defined (APM32F10X_CL) + /* APM32F10X Connectivity-line devices specific Interrupt Numbers */ + ADC1_2_IRQn = 18, /*!< ADC1 and ADC2 global Interrupt */ + CAN1_TX_IRQn = 19, /*!< CAN1 TX Interrupts */ + CAN1_RX0_IRQn = 20, /*!< CAN1 RX0 Interrupts */ + CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ + CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ + EINT9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TMR1_BRK_IRQn = 24, /*!< TMR1 Break Interrupt */ + TMR1_UP_IRQn = 25, /*!< TMR1 Update Interrupt */ + TMR1_TRG_COM_IRQn = 26, /*!< TMR1 Trigger and Commutation Interrupt */ + TMR1_CC_IRQn = 27, /*!< TMR1 Capture Compare Interrupt */ + TMR2_IRQn = 28, /*!< TMR2 global Interrupt */ + TMR3_IRQn = 29, /*!< TMR3 global Interrupt */ + TMR4_IRQn = 30, /*!< TMR4 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 */ + EINT15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTCAlarm_IRQn = 41, /*!< RTC Alarm through EINT Line Interrupt */ + OTG_FS_WKUP_IRQn = 42, /*!< USB Device WakeUp from suspend through EINT Line Interrupt */ + TMR5_IRQn = 50, /*!< TMR5 global Interrupt */ + SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ + UART4_IRQn = 52, /*!< UART4 global Interrupt */ + UART5_IRQn = 53, /*!< UART5 global Interrupt */ + TMR6_IRQn = 54, /*!< TMR6 global Interrupt */ + TMR7_IRQn = 55, /*!< TMR7 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, /*!< ETH global Interrupt */ + ETH_WKUP_IRQn = 62, /*!< ETH Wake up Interrupt */ + CAN2_TX_IRQn = 63, /*!< CAN2 TX Interrupts */ + CAN2_RX0_IRQn = 64, /*!< CAN2 RX0 Interrupts */ + CAN2_RX1_IRQn = 65, /*!< CAN2 RX1 Interrupts */ + CAN2_SCE_IRQn = 66, /*!< CAN2 SCE Interrupts */ + OTG_FS_IRQn = 67, /*!< OTG FS Interrupts */ #endif } IRQn_Type; -/** - * @} - */ +/**@} end of group Peripheral_Enumerations */ + +/* Includes */ #include "core_cm3.h" #include "system_apm32f10x.h" #include +/** @defgroup Exported_Types + @{ +*/ typedef int32_t s32; typedef int16_t s16; @@ -262,13 +346,13 @@ typedef __I uint16_t vuc16; typedef __I uint8_t vuc8; #ifndef __IM - #define __IM __I +#define __IM __I #endif #ifndef __OM - #define __OM __O +#define __OM __O #endif #ifndef __IOM - #define __IOM __IO +#define __IOM __IO #endif enum {BIT_RESET, BIT_SET}; @@ -284,12 +368,18 @@ enum {ERROR, SUCCESS}; #pragma anon_unions #endif +/**@} end of group Exported_types */ + +/** @defgroup Peripheral_registers_structures + @{ +*/ + /** * @brief Reset and clock management unit (RCM) */ typedef struct { - /** Clock control register */ + /* Clock control register */ union { __IOM uint32_t CTRL; @@ -306,13 +396,17 @@ typedef struct __IOM uint32_t HSEBCFG : 1; __IOM uint32_t CSSEN : 1; __IM uint32_t RESERVED2 : 4; - __IOM uint32_t PLLEN : 1; - __IM uint32_t PLLRDYFLG : 1; - __IM uint32_t RESERVED3 : 6; + __IOM uint32_t PLL1EN : 1; + __IM uint32_t PLL1RDYFLG : 1; + __IOM uint32_t PLL2EN : 1; + __IM uint32_t PLL2RDYFLG : 1; + __IOM uint32_t PLL3EN : 1; + __IM uint32_t PLL3RDYFLG : 1; + __IM uint32_t RESERVED3 : 2; } CTRL_B; }; - /** Clock configuration register */ + /* Clock configuration register */ union { __IOM uint32_t CFG; @@ -325,17 +419,26 @@ typedef struct __IOM uint32_t APB1PSC : 3; __IOM uint32_t APB2PSC : 3; __IOM uint32_t ADCPSC : 2; - __IOM uint32_t PLLSRCSEL : 1; + __IOM uint32_t PLL1SRCSEL : 1; +#ifdef APM32F10X_CL + __IOM uint32_t PLLPSC1L : 1; + __IOM uint32_t PLL1MULCFG : 4; + __IOM uint32_t OTGFSPSC : 2; + __IOM uint32_t MCOSEL : 4; + __IM uint32_t RESERVED : 4; +#else __IOM uint32_t PLLHSEPSC : 1; - __IOM uint32_t PLLMULCFG : 4; + __IOM uint32_t PLL1MULCFG : 4; __IOM uint32_t USBDPSC : 2; __IOM uint32_t MCOSEL : 3; __IOM uint32_t FPUPSC : 1; - __IM uint32_t RESERVED : 4; + __IOM uint32_t SDRAMPSC : 2; + __IM uint32_t RESERVED : 2; +#endif } CFG_B; } ; - /** Clock interrupt control register */ + /* Clock interrupt control register */ union { __IOM uint32_t INT; @@ -346,177 +449,187 @@ typedef struct __IM uint32_t LSERDYFLG : 1; __IM uint32_t HSIRDYFLG : 1; __IM uint32_t HSERDYFLG : 1; - __IM uint32_t PLLRDYFLG : 1; - __IM uint32_t RESERVED1 : 2; - __IM uint32_t CSSIF : 1; + __IM uint32_t PLL1RDYFLG : 1; + __IM uint32_t PLL2RDYFLG : 1; + __IM uint32_t PLL3RDYFLG : 1; + __IM uint32_t CSSFLG : 1; __IOM uint32_t LSIRDYEN : 1; __IOM uint32_t LSERDYEN : 1; __IOM uint32_t HSIRDYEN : 1; __IOM uint32_t HSERDYEN : 1; - __IOM uint32_t PLLRDYEN : 1; - __IM uint32_t RESERVED2 : 3; + __IOM uint32_t PLL1RDYEN : 1; + __IOM uint32_t PLL2RDYEN : 1; + __IOM uint32_t PLL3RDYEN : 1; + __IM uint32_t RESERVED1 : 1; __OM uint32_t LSIRDYCLR : 1; __OM uint32_t LSERDYCLR : 1; __OM uint32_t HSIRDYCLR : 1; __OM uint32_t HSERDYCLR : 1; - __OM uint32_t PLLRDYCLR : 1; - __IM uint32_t RESERVED3 : 2; + __OM uint32_t PLL1RDYCLR : 1; + __OM uint32_t PLL2RDYCLR : 1; + __OM uint32_t PLL3RDYCLR : 1; __OM uint32_t CSSCLR : 1; - __IM uint32_t RESERVED4 : 8; + __IM uint32_t RESERVED2 : 8; } INT_B; } ; - /** APB2 peripheral reset register */ + /* APB2 peripheral reset register */ union { __IOM uint32_t APB2RST; struct { - __IOM uint32_t AFIO : 1; + __IOM uint32_t AFIORST : 1; __IM uint32_t RESERVED1 : 1; - __IOM uint32_t PA : 1; - __IOM uint32_t PB : 1; - __IOM uint32_t PC : 1; - __IOM uint32_t PD : 1; - __IOM uint32_t PE : 1; - __IOM uint32_t PF : 1; - __IOM uint32_t PG : 1; - __IOM uint32_t ADC1 : 1; - __IOM uint32_t ADC2 : 1; - __IOM uint32_t TMR1 : 1; - __IOM uint32_t SPI1 : 1; - __IOM uint32_t TMR8 : 1; - __IOM uint32_t USART1 : 1; - __IOM uint32_t ADC3 : 1; + __IOM uint32_t PARST : 1; + __IOM uint32_t PBRST : 1; + __IOM uint32_t PCRST : 1; + __IOM uint32_t PDRST : 1; + __IOM uint32_t PERST : 1; + __IOM uint32_t PFRST : 1; + __IOM uint32_t PGRST : 1; + __IOM uint32_t ADC1RST : 1; + __IOM uint32_t ADC2RST : 1; + __IOM uint32_t TMR1RST : 1; + __IOM uint32_t SPI1RST : 1; + __IOM uint32_t TMR8RST : 1; + __IOM uint32_t USART1RST : 1; + __IOM uint32_t ADC3RST : 1; __IM uint32_t RESERVED2 : 16; } APB2RST_B; } ; - /** APB1 peripheral reset register */ + /* APB1 peripheral reset register */ union { __IOM uint32_t APB1RST; struct { - __IOM uint32_t TMR2 : 1; - __IOM uint32_t TMR3 : 1; - __IOM uint32_t TMR4 : 1; - __IOM uint32_t TMR5 : 1; - __IOM uint32_t TMR6 : 1; - __IOM uint32_t TMR7 : 1; + __IOM uint32_t TMR2RST : 1; + __IOM uint32_t TMR3RST : 1; + __IOM uint32_t TMR4RST : 1; + __IOM uint32_t TMR5RST : 1; + __IOM uint32_t TMR6RST : 1; + __IOM uint32_t TMR7RST : 1; __IM uint32_t RESERVED1 : 5; - __IOM uint32_t WWDT : 1; + __IOM uint32_t WWDTRST : 1; __IM uint32_t RESERVED2 : 2; - __IOM uint32_t SPI2 : 1; - __IOM uint32_t SPI3 : 1; + __IOM uint32_t SPI2RST : 1; + __IOM uint32_t SPI3RST : 1; __IM uint32_t RESERVED3 : 1; - __IOM uint32_t USART2 : 1; - __IOM uint32_t USART3 : 1; - __IOM uint32_t UART4 : 1; - __IOM uint32_t UART5 : 1; - __IOM uint32_t I2C1 : 1; - __IOM uint32_t I2C2 : 1; - __IOM uint32_t USBD : 1; + __IOM uint32_t USART2RST : 1; + __IOM uint32_t USART3RST : 1; + __IOM uint32_t UART4RST : 1; + __IOM uint32_t UART5RST : 1; + __IOM uint32_t I2C1RST : 1; + __IOM uint32_t I2C2RST : 1; + __IOM uint32_t USBDRST : 1; __IM uint32_t RESERVED4 : 1; - __IOM uint32_t CAN1 : 1; - __IM uint32_t CAN2 : 1; - __IOM uint32_t BAKP : 1; - __IOM uint32_t PMU : 1; - __IOM uint32_t DAC : 1; + __IOM uint32_t CAN1RST : 1; + __IOM uint32_t CAN2RST : 1; + __IOM uint32_t BAKPRST : 1; + __IOM uint32_t PMURST : 1; + __IOM uint32_t DACRST : 1; __IM uint32_t RESERVED5 : 2; } APB1RST_B; } ; - /** AHB clock enable register */ + /* AHB clock enable register */ union { __IOM uint32_t AHBCLKEN; struct { - __IOM uint32_t DMA1 : 1; - __IOM uint32_t DMA2 : 1; - __IOM uint32_t SRAM : 1; - __IOM uint32_t FPU : 1; - __IOM uint32_t FMC : 1; - __IOM uint32_t QSPI : 1; - __IOM uint32_t CRC : 1; + __IOM uint32_t DMA1EN : 1; + __IOM uint32_t DMA2EN : 1; + __IOM uint32_t SRAMEN : 1; + __IOM uint32_t FPUEN : 1; + __IOM uint32_t FMCEN : 1; + __IOM uint32_t QSPIEN : 1; + __IOM uint32_t CRCEN : 1; __IM uint32_t RESERVED1 : 1; - __IOM uint32_t EMMC : 1; + __IOM uint32_t EMMCEN : 1; __IM uint32_t RESERVED2 : 1; - __IOM uint32_t SDIO : 1; - __IM uint32_t RESERVED3 : 21; + __IOM uint32_t SDIOEN : 1; + __IM uint32_t RESERVED3 : 1; + __IOM uint32_t OTGFSEN : 1; + __IM uint32_t RESERVED4 : 1; + __IOM uint32_t MACEN : 1; + __IOM uint32_t MACTXEN : 1; + __IOM uint32_t MACRXEN : 1; + __IM uint32_t RESERVED5 : 15; } AHBCLKEN_B; } ; - /** APB2 clock enable register */ + /* APB2 clock enable register */ union { __IOM uint32_t APB2CLKEN; struct { - __IOM uint32_t AFIO : 1; + __IOM uint32_t AFIOEN : 1; __IM uint32_t RESERVED1 : 1; - __IOM uint32_t PA : 1; - __IOM uint32_t PB : 1; - __IOM uint32_t PC : 1; - __IOM uint32_t PD : 1; - __IOM uint32_t PE : 1; - __IOM uint32_t PF : 1; - __IOM uint32_t PG : 1; - __IOM uint32_t ADC1 : 1; - __IOM uint32_t ADC2 : 1; - __IOM uint32_t TMR1 : 1; - __IOM uint32_t SPI1 : 1; - __IOM uint32_t TMR8 : 1; - __IOM uint32_t USART1 : 1; - __IOM uint32_t ADC3 : 1; + __IOM uint32_t PAEN : 1; + __IOM uint32_t PBEN : 1; + __IOM uint32_t PCEN : 1; + __IOM uint32_t PDEN : 1; + __IOM uint32_t PEEN : 1; + __IOM uint32_t PFEN : 1; + __IOM uint32_t PGEN : 1; + __IOM uint32_t ADC1EN : 1; + __IOM uint32_t ADC2EN : 1; + __IOM uint32_t TMR1EN : 1; + __IOM uint32_t SPI1EN : 1; + __IOM uint32_t TMR8EN : 1; + __IOM uint32_t USART1EN : 1; + __IOM uint32_t ADC3EN : 1; __IM uint32_t RESERVED2 : 16; } APB2CLKEN_B; }; - /** APB1 clock enable register */ + /* APB1 clock enable register */ union { __IOM uint32_t APB1CLKEN; struct { - __IOM uint32_t TMR2 : 1; - __IOM uint32_t TMR3 : 1; - __IOM uint32_t TMR4 : 1; - __IOM uint32_t TMR5 : 1; - __IOM uint32_t TMR6 : 1; - __IOM uint32_t TMR7 : 1; + __IOM uint32_t TMR2EN : 1; + __IOM uint32_t TMR3EN : 1; + __IOM uint32_t TMR4EN : 1; + __IOM uint32_t TMR5EN : 1; + __IOM uint32_t TMR6EN : 1; + __IOM uint32_t TMR7EN : 1; __IM uint32_t RESERVED1 : 5; - __IOM uint32_t WWDT : 1; + __IOM uint32_t WWDTEN : 1; __IM uint32_t RESERVED2 : 2; - __IOM uint32_t SPI2 : 1; - __IOM uint32_t SPI3 : 1; + __IOM uint32_t SPI2EN : 1; + __IOM uint32_t SPI3EN : 1; __IM uint32_t RESERVED3 : 1; - __IOM uint32_t USART2 : 1; - __IOM uint32_t USART3 : 1; - __IOM uint32_t UART4 : 1; - __IOM uint32_t UART5 : 1; - __IOM uint32_t I2C1 : 1; - __IOM uint32_t I2C2 : 1; - __IOM uint32_t USBD : 1; + __IOM uint32_t USART2EN : 1; + __IOM uint32_t USART3EN : 1; + __IOM uint32_t UART4EN : 1; + __IOM uint32_t UART5EN : 1; + __IOM uint32_t I2C1EN : 1; + __IOM uint32_t I2C2EN : 1; + __IOM uint32_t USBDEN : 1; __IM uint32_t RESERVED4 : 1; - __IOM uint32_t CAN1 : 1; - __IM uint32_t CAN2 : 1; - __IOM uint32_t BAKP : 1; - __IOM uint32_t PMU : 1; - __IOM uint32_t DAC : 1; + __IOM uint32_t CAN1EN : 1; + __IOM uint32_t CAN2EN : 1; + __IOM uint32_t BAKPEN : 1; + __IOM uint32_t PMUEN : 1; + __IOM uint32_t DACEN : 1; __IM uint32_t RESERVED5 : 2; } APB1CLKEN_B; } ; - /** Backup domain control register */ + /* Backup domain control register */ union - { + { __IOM uint32_t BDCTRL; struct @@ -533,7 +646,7 @@ typedef struct } BDCTRL_B; } ; - /** Control/status register */ + /* Control/status register */ union { __IOM uint32_t CSTS; @@ -553,6 +666,39 @@ typedef struct __IOM uint32_t LPWRRSTFLG : 1; } CSTS_B; } ; + + /* AHB peripheral reset register */ + union + { + __IOM uint32_t AHBRST; + + struct + { + __IM uint32_t RESERVED1 : 12; + __IOM uint32_t OTGFSRST : 1; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t MACRST : 1; + __IM uint32_t RESERVED3 : 17; + } AHBRST_B; + } ; + + /* Clock configuration register2 */ + union + { + __IOM uint32_t CFG2; + + struct + { + __IOM uint32_t PLLPSC1 : 4; + __IOM uint32_t PLLPSC2 : 4; + __IOM uint32_t PLL2MUL : 4; + __IOM uint32_t PLL3MUL : 4; + __IOM uint32_t PLLPSC1SRC : 1; + __IOM uint32_t I2S2SRCSEL : 1; + __IOM uint32_t I2S3SRCSEL : 1; + __IM uint32_t RESERVED1 : 13; + } CFG2_B; + } ; } RCM_T; /** @@ -560,7 +706,7 @@ typedef struct */ typedef struct { - /** Port configure register low */ + /* Port configure register low */ union { __IOM uint32_t CFGLOW; @@ -586,7 +732,7 @@ typedef struct } CFGLOW_B; } ; - /** Port configure register high */ + /* Port configure register high */ union { __IOM uint32_t CFGHIG; @@ -612,7 +758,7 @@ typedef struct } CFGHIG_B; } ; - /** Port data in register */ + /* Port data in register */ union { __IM uint32_t IDATA; @@ -639,7 +785,7 @@ typedef struct } IDATA_B; } ; - /** Port data output register */ + /* Port data output register */ union { __IOM uint32_t ODATA; @@ -666,7 +812,7 @@ typedef struct } ODATA_B; } ; - /** Port bit set/clear register */ + /* Port bit set/clear register */ union { __OM uint32_t BSC; @@ -708,7 +854,7 @@ typedef struct } BSC_B; } ; - /** Port bit clear register */ + /* Port bit clear register */ union { __OM uint32_t BC; @@ -735,7 +881,7 @@ typedef struct } BC_B; } ; - /** Port configuration lock register */ + /* Port configuration lock register */ union { __IOM uint32_t LOCK; @@ -769,7 +915,7 @@ typedef struct */ typedef struct { - /** Event control register */ + /* Event control register */ union { __IOM uint32_t EVCTRL; @@ -783,38 +929,51 @@ typedef struct } EVCTRL_B; } ; - /** Alternate function IO remap and Serial wire JTAG configuration register */ + /* Alternate function IO remap and Serial wire JTAG configuration register */ union { __IOM uint32_t REMAP1; struct { - __IOM uint32_t SPI1RMP : 1; - __IOM uint32_t I2C1RMP : 1; - __IOM uint32_t USART1RMP : 1; - __IOM uint32_t USART2RMP : 1; - __IOM uint32_t USART3RMP : 2; - __IOM uint32_t TMR1RMP : 2; - __IOM uint32_t TMR2RMP : 2; - __IOM uint32_t TMR3RMP : 2; - __IOM uint32_t TMR4RMP : 1; - __IOM uint32_t CAN1RMP : 2; - __IOM uint32_t PD01RMP : 1; - __IOM uint32_t TMR5CH4IRMP : 1; + __IOM uint32_t SPI1RMP : 1; + __IOM uint32_t I2C1RMP : 1; + __IOM uint32_t USART1RMP : 1; + __IOM uint32_t USART2RMP : 1; + __IOM uint32_t USART3RMP : 2; + __IOM uint32_t TMR1RMP : 2; + __IOM uint32_t TMR2RMP : 2; + __IOM uint32_t TMR3RMP : 2; + __IOM uint32_t TMR4RMP : 1; + __IOM uint32_t CAN1RMP : 2; + __IOM uint32_t PD01RMP : 1; + __IOM uint32_t TMR5CH4IRMP : 1; +#if defined(APM32F10X_CL) + __IM uint32_t RESERVED1 : 4; + __IOM uint32_t MACRMP : 1; + __IOM uint32_t CAN2RMP : 1; + __IOM uint32_t MACEISEL : 1; + __IOM uint32_t SWJCFG : 3; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t SPI3RMP : 1; + __IOM uint32_t TMR2ITR1RMP : 1; + __IOM uint32_t PTPPPSRMP : 1; + __IM uint32_t RESERVED3 : 1; +#else __IOM uint32_t ADC1_ETRGINJC_RMP : 1; __IOM uint32_t ADC1_ETRGREGC_RMP : 1; __IOM uint32_t ADC2_ETRGINJC_RMP : 1; __IOM uint32_t ADC2_ETRGREGC_RMP : 1; - __IM uint32_t RESERVED1 : 1; - __IOM uint32_t CAN2RMP : 1; - __IM uint32_t RESERVED2 : 1; - __OM uint32_t SWJCFG : 3; - __IM uint32_t RESERVED3 : 5; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t CAN2RMP : 1; + __IM uint32_t RESERVED2 : 1; + __OM uint32_t SWJCFG : 3; + __IM uint32_t RESERVED3 : 5; +#endif } REMAP1_B; } ; - /** External interrupt select register1 */ + /* External interrupt select register1 */ union { __IOM uint32_t EINTSEL1; @@ -829,7 +988,7 @@ typedef struct } EINTSEL1_B; } ; - /** External interrupt select register2 */ + /* External interrupt select register2 */ union { __IOM uint32_t EINTSEL2; @@ -844,7 +1003,7 @@ typedef struct } EINTSEL2_B; } ; - /** External interrupt select register3 */ + /* External interrupt select register3 */ union { __IOM uint32_t EINTSEL3; @@ -859,7 +1018,7 @@ typedef struct } EINTSEL3_B; } ; - /** External interrupt select register4 */ + /* External interrupt select register4 */ union { __IOM uint32_t EINTSEL4; @@ -875,7 +1034,7 @@ typedef struct } ; __IM uint32_t RESERVED; - /** Alternate function IO remap register2 */ + /* Alternate function IO remap register2 */ union { __IOM uint32_t REMAP2; @@ -894,7 +1053,7 @@ typedef struct */ typedef struct { - /** Status register */ + /* Status register */ union { __IOM uint32_t STS; @@ -915,7 +1074,7 @@ typedef struct } STS_B; } ; - /** TX Buffer Data Register */ + /* TX Buffer Data Register */ union { __IOM uint32_t DATA; @@ -927,7 +1086,7 @@ typedef struct } DATA_B; } ; - /** Baud rate register */ + /* Baud rate register */ union { __IOM uint32_t BR; @@ -940,7 +1099,7 @@ typedef struct } BR_B; } ; - /** Control register 1 */ + /* Control register 1 */ union { __IOM uint32_t CTRL1; @@ -965,7 +1124,7 @@ typedef struct } CTRL1_B; } ; - /** Control register 2 */ + /* Control register 2 */ union { __IOM uint32_t CTRL2; @@ -987,7 +1146,7 @@ typedef struct } CTRL2_B; } ; - /** Control register 3 */ + /* Control register 3 */ union { __IOM uint32_t CTRL3; @@ -1009,7 +1168,7 @@ typedef struct } CTRL3_B; } ; - /** Guard TMRe and divider number register */ + /* Guard TMRe and divider number register */ union { __IOM uint32_t GTPSC; @@ -1028,7 +1187,7 @@ typedef struct */ typedef struct { - /** FMC access control register */ + /* FMC access control register */ union { __IOM uint32_t CTRL1; @@ -1043,7 +1202,7 @@ typedef struct } CTRL1_B; } ; - /** key register */ + /* key register */ union { __OM uint32_t KEY; @@ -1054,7 +1213,7 @@ typedef struct } KEY_B; } ; - /** option byte key register */ + /* option byte key register */ union { __OM uint32_t OBKEY; @@ -1065,7 +1224,7 @@ typedef struct } OBKEY_B; }; - /** status register */ + /* status register */ union { __IOM uint32_t STS; @@ -1082,7 +1241,7 @@ typedef struct } STS_B; }; - /** status register */ + /* status register */ union { __IOM uint32_t CTRL2; @@ -1106,7 +1265,7 @@ typedef struct } CTRL2_B; } ; - /** address register */ + /* address register */ union { __OM uint32_t ADDR; @@ -1119,7 +1278,7 @@ typedef struct __IM uint32_t RESERVED; - /** Option byte register */ + /* Option byte register */ union { __IOM uint32_t OBCS; @@ -1138,7 +1297,7 @@ typedef struct } OBCS_B; }; - /** Write protection register */ + /* Write protection register */ union { __IM uint32_t WRTPROT; @@ -1155,7 +1314,7 @@ typedef struct */ typedef struct { - /** @brief DATA register */ + /* @brief DATA register */ union { __IOM uint32_t DATA; @@ -1166,7 +1325,7 @@ typedef struct } DATA_B; } ; - /** @brief independent DATA register */ + /* @brief independent DATA register */ union { __IOM uint32_t INDATA; @@ -1178,7 +1337,7 @@ typedef struct } INDATA_B; }; - /** @brief Countrol register */ + /* @brief Countrol register */ union { __IOM uint32_t CTRL; @@ -1196,7 +1355,7 @@ typedef struct */ typedef struct { - /** @brief Control register */ + /* @brief Control register */ union { __IOM uint32_t CTRL; @@ -1210,7 +1369,7 @@ typedef struct } CTRL_B; }; - /** @brief Control and State register */ + /* @brief Control and State register */ union { __IOM uint32_t CSTS; @@ -1227,7 +1386,7 @@ typedef struct } CSTS_B; }; - /** @brief RTC predivision loading register High Bit */ + /* @brief RTC predivision loading register High Bit */ union { __OM uint32_t PSCRLDH; @@ -1239,7 +1398,7 @@ typedef struct } PSCRLDH_B; }; - /** @brief RTC predivision loading register Low Bit */ + /* @brief RTC predivision loading register Low Bit */ union { __OM uint32_t PSCRLDL; @@ -1251,7 +1410,7 @@ typedef struct } PSCRLDL_B; }; - /** @brief RTC predivider remainder register High Bit */ + /* @brief RTC predivider remainder register High Bit */ union { __IM uint32_t PSCH; @@ -1263,7 +1422,7 @@ typedef struct } PSCH_B; }; - /** @brief RTC predivider remainder register Low Bit */ + /* @brief RTC predivider remainder register Low Bit */ union { __IM uint32_t PSCL; @@ -1275,7 +1434,7 @@ typedef struct } PSCL_B; }; - /** @brief RTC count register High Bit */ + /* @brief RTC count register High Bit */ union { __IOM uint32_t CNTH; @@ -1287,7 +1446,7 @@ typedef struct } CNTH_B; }; - /** @brief RTC count register Low Bit */ + /* @brief RTC count register Low Bit */ union { __IOM uint32_t CNTL; @@ -1299,7 +1458,7 @@ typedef struct } CNTL_B; }; - /** @brief RTC alarm clock register High Bit */ + /* @brief RTC alarm clock register High Bit */ union { __OM uint32_t ALRH; @@ -1311,7 +1470,7 @@ typedef struct } ALRH_B; }; - /** @brief RTC alarm clock register Low Bit */ + /* @brief RTC alarm clock register Low Bit */ union { __OM uint32_t ALRL; @@ -1329,7 +1488,7 @@ typedef struct */ typedef struct { - /** @brief Control register */ + /* @brief Control register */ union { __IOM uint32_t CTRL; @@ -1347,7 +1506,7 @@ typedef struct } CTRL_B; }; - /** @brief PMU Status register */ + /* @brief PMU Status register */ union { __IOM uint32_t CSTS; @@ -1371,7 +1530,7 @@ typedef struct { __IM uint32_t RESERVED; - /** @brief BAKPR DATA1 register */ + /* @brief BAKPR DATA1 register */ union { __IOM uint32_t DATA1; @@ -1383,7 +1542,7 @@ typedef struct } DATA1_B; }; - /** @brief BAKPR DATA2 register */ + /* @brief BAKPR DATA2 register */ union { __IOM uint32_t DATA2; @@ -1395,7 +1554,7 @@ typedef struct } DATA2_B; }; - /** @brief BAKPR DATA3 register */ + /* @brief BAKPR DATA3 register */ union { __IOM uint32_t DATA3; @@ -1407,7 +1566,7 @@ typedef struct } DATA3_B; }; - /** @brief BAKPR DATA4 register */ + /* @brief BAKPR DATA4 register */ union { __IOM uint32_t DATA4; @@ -1419,7 +1578,7 @@ typedef struct } DATA4_B; }; - /** @brief BAKPR DATA5 register */ + /* @brief BAKPR DATA5 register */ union { __IOM uint32_t DATA5; @@ -1431,7 +1590,7 @@ typedef struct } DATA5_B; }; - /** @brief BAKPR DATA6 register */ + /* @brief BAKPR DATA6 register */ union { __IOM uint32_t DATA6; @@ -1443,7 +1602,7 @@ typedef struct } DATA6_B; }; - /** @brief BAKPR DATA7 register */ + /* @brief BAKPR DATA7 register */ union { __IOM uint32_t DATA7; @@ -1455,7 +1614,7 @@ typedef struct } DATA7_B; }; - /** @brief BAKPR DATA8 register */ + /* @brief BAKPR DATA8 register */ union { __IOM uint32_t DATA8; @@ -1467,7 +1626,7 @@ typedef struct } DATA8_B; }; - /** @brief BAKPR DATA9 register */ + /* @brief BAKPR DATA9 register */ union { __IOM uint32_t DATA9; @@ -1479,7 +1638,7 @@ typedef struct } DATA9_B; }; - /** @brief BAKPR DATA10 register */ + /* @brief BAKPR DATA10 register */ union { __IOM uint32_t DATA10; @@ -1491,7 +1650,7 @@ typedef struct } DATA10_B; }; - /** @brief BAKPR Clock Calibration register */ + /* @brief BAKPR Clock Calibration register */ union { __IOM uint32_t CLKCAL; @@ -1506,7 +1665,7 @@ typedef struct } CLKCAL_B; } ; - /** @brief BAKPR Control register */ + /* @brief BAKPR Control register */ union { __IOM uint32_t CTRL; @@ -1519,7 +1678,7 @@ typedef struct } CTRL_B; }; - /** @brief BAKPR Control register */ + /* @brief BAKPR Control register */ union { __IOM uint32_t CSTS; @@ -1538,7 +1697,7 @@ typedef struct __IM uint32_t RESERVED1[2]; - /** @briefBAKPR DATA11 register */ + /* @briefBAKPR DATA11 register */ union { __IOM uint32_t DATA11; @@ -1550,7 +1709,7 @@ typedef struct } DATA11_B; }; - /** @briefBAKPR DATA12 register */ + /* @briefBAKPR DATA12 register */ union { __IOM uint32_t DATA12; @@ -1562,7 +1721,7 @@ typedef struct } DATA12_B; }; - /** @briefBAKPR DATA13 register */ + /* @briefBAKPR DATA13 register */ union { __IOM uint32_t DATA13; @@ -1574,7 +1733,7 @@ typedef struct } DATA13_B; }; - /** @briefBAKPR DATA14 register */ + /* @briefBAKPR DATA14 register */ union { __IOM uint32_t DATA14; @@ -1586,7 +1745,7 @@ typedef struct } DATA14_B; }; - /** @briefBAKPR DATA15 register */ + /* @briefBAKPR DATA15 register */ union { __IOM uint32_t DATA15; @@ -1598,7 +1757,7 @@ typedef struct } DATA15_B; }; - /** @briefBAKPR DATA16 register */ + /* @briefBAKPR DATA16 register */ union { __IOM uint32_t DATA16; @@ -1610,7 +1769,7 @@ typedef struct } DATA16_B; }; - /** @briefBAKPR DATA17 register */ + /* @briefBAKPR DATA17 register */ union { __IOM uint32_t DATA17; @@ -1622,7 +1781,7 @@ typedef struct } DATA17_B; }; - /** @briefBAKPR DATA18 register */ + /* @briefBAKPR DATA18 register */ union { __IOM uint32_t DATA18; @@ -1634,7 +1793,7 @@ typedef struct } DATA18_B; }; - /** @briefBAKPR DATA19 register */ + /* @briefBAKPR DATA19 register */ union { __IOM uint32_t DATA19; @@ -1646,7 +1805,7 @@ typedef struct } DATA19_B; }; - /** @briefBAKPR DATA20 register */ + /* @briefBAKPR DATA20 register */ union { __IOM uint32_t DATA20; @@ -1658,7 +1817,7 @@ typedef struct } DATA20_B; }; - /** @briefBAKPR DATA21 register */ + /* @briefBAKPR DATA21 register */ union { __IOM uint32_t DATA21; @@ -1670,7 +1829,7 @@ typedef struct } DATA21_B; }; - /** @briefBAKPR DATA22 register */ + /* @briefBAKPR DATA22 register */ union { __IOM uint32_t DATA22; @@ -1682,7 +1841,7 @@ typedef struct } DATA22_B; }; - /** @briefBAKPR DATA23 register */ + /* @briefBAKPR DATA23 register */ union { __IOM uint32_t DATA23; @@ -1694,7 +1853,7 @@ typedef struct } DATA23_B; }; - /** @briefBAKPR DATA24 register */ + /* @briefBAKPR DATA24 register */ union { __IOM uint32_t DATA24; @@ -1706,7 +1865,7 @@ typedef struct } DATA24_B; }; - /** @briefBAKPR DATA25 register */ + /* @briefBAKPR DATA25 register */ union { __IOM uint32_t DATA25; @@ -1718,7 +1877,7 @@ typedef struct } DATA25_B; }; - /** @briefBAKPR DATA26 register */ + /* @briefBAKPR DATA26 register */ union { __IOM uint32_t DATA26; @@ -1730,7 +1889,7 @@ typedef struct } DATA26_B; }; - /** @briefBAKPR DATA27 register */ + /* @briefBAKPR DATA27 register */ union { __IOM uint32_t DATA27; @@ -1742,7 +1901,7 @@ typedef struct } DATA27_B; }; - /** @briefBAKPR DATA28 register */ + /* @briefBAKPR DATA28 register */ union { __IOM uint32_t DATA28; @@ -1754,7 +1913,7 @@ typedef struct } DATA28_B; }; - /** @briefBAKPR DATA29 register */ + /* @briefBAKPR DATA29 register */ union { __IOM uint32_t DATA29; @@ -1766,7 +1925,7 @@ typedef struct } DATA29_B; }; - /** @briefBAKPR DATA30 register */ + /* @briefBAKPR DATA30 register */ union { __IOM uint32_t DATA30; @@ -1778,7 +1937,7 @@ typedef struct } DATA30_B; }; - /** @briefBAKPR DATA31 register */ + /* @briefBAKPR DATA31 register */ union { __IOM uint32_t DATA31; @@ -1790,7 +1949,7 @@ typedef struct } DATA31_B; }; - /** @briefBAKPR DATA32 register */ + /* @briefBAKPR DATA32 register */ union { __IOM uint32_t DATA32; @@ -1802,7 +1961,7 @@ typedef struct } DATA32_B; }; - /** @briefBAKPR DATA33 register */ + /* @briefBAKPR DATA33 register */ union { __IOM uint32_t DATA33; @@ -1814,7 +1973,7 @@ typedef struct } DATA33_B; }; - /** @briefBAKPR DATA34 register */ + /* @briefBAKPR DATA34 register */ union { __IOM uint32_t DATA34; @@ -1826,7 +1985,7 @@ typedef struct } DATA34_B; }; - /** @briefBAKPR DATA35 register */ + /* @briefBAKPR DATA35 register */ union { __IOM uint32_t DATA35; @@ -1838,7 +1997,7 @@ typedef struct } DATA35_B; }; - /** @briefBAKPR DATA36 register */ + /* @briefBAKPR DATA36 register */ union { __IOM uint32_t DATA36; @@ -1850,7 +2009,7 @@ typedef struct } DATA36_B; }; - /** @briefBAKPR DATA37 register */ + /* @briefBAKPR DATA37 register */ union { __IOM uint32_t DATA37; @@ -1862,7 +2021,7 @@ typedef struct } DATA37_B; }; - /** @briefBAKPR DATA38 register */ + /* @briefBAKPR DATA38 register */ union { __IOM uint32_t DATA38; @@ -1874,7 +2033,7 @@ typedef struct } DATA38_B; }; - /** @briefBAKPR DATA39 register */ + /* @briefBAKPR DATA39 register */ union { __IOM uint32_t DATA39; @@ -1886,7 +2045,7 @@ typedef struct } DATA39_B; }; - /** @briefBAKPR DATA40 register */ + /* @briefBAKPR DATA40 register */ union { __IOM uint32_t DATA40; @@ -1898,7 +2057,7 @@ typedef struct } DATA40_B; }; - /** @briefBAKPR DATA41 register */ + /* @briefBAKPR DATA41 register */ union { __IOM uint32_t DATA41; @@ -1910,7 +2069,7 @@ typedef struct } DATA41_B; }; - /** @briefBAKPR DATA42 register */ + /* @briefBAKPR DATA42 register */ union { __IOM uint32_t DATA42; @@ -1928,7 +2087,7 @@ typedef struct */ typedef struct { - /** @brief Countrol register 1 */ + /* @brief Countrol register 1 */ union { __IOM uint32_t CTRL1; @@ -1947,7 +2106,7 @@ typedef struct } CTRL1_B; }; - /** @brief Countrol register 2 */ + /* @brief Countrol register 2 */ union { __IOM uint32_t CTRL2; @@ -1971,7 +2130,7 @@ typedef struct } CTRL2_B; }; - /** @brief Control register from mode */ + /* @brief Control register from mode */ union { __IOM uint32_t SMCTRL; @@ -1990,7 +2149,7 @@ typedef struct } SMCTRL_B; }; - /** @brief DMA and Interrupt enable register */ + /* @brief DMA and Interrupt enable register */ union { __IOM uint32_t DIEN; @@ -2016,7 +2175,7 @@ typedef struct } DIEN_B; }; - /** @brief Status register */ + /* @brief Status register */ union { __IOM uint32_t STS; @@ -2040,7 +2199,7 @@ typedef struct } STS_B; }; - /** @brief Software controls event generation registers */ + /* @brief Software controls event generation registers */ union { __OM uint32_t CEG; @@ -2059,12 +2218,12 @@ typedef struct } CEG_B; }; - /** @brief Capture the compare mode register 1 */ + /* @brief Capture the compare mode register 1 */ union { __IOM uint32_t CCM1; - /** @brief Compare mode */ + /* @brief Compare mode */ struct { __IOM uint32_t CC1SEL : 2; @@ -2080,7 +2239,7 @@ typedef struct __IM uint32_t RESERVED : 16; } CCM1_COMPARE_B; - /** @brief Capture mode */ + /* @brief Capture mode */ struct { __IOM uint32_t CC1SEL : 2; @@ -2093,12 +2252,12 @@ typedef struct } CCM1_CAPTURE_B; }; - /** @brief Capture the compare mode register 2 */ + /* @brief Capture the compare mode register 2 */ union { __IOM uint32_t CCM2; - /** @brief Compare mode */ + /* @brief Compare mode */ struct { __IOM uint32_t CC3SEL : 2; @@ -2114,7 +2273,7 @@ typedef struct __IM uint32_t RESERVED : 16; } CCM2_COMPARE_B; - /** @brief Capture mode */ + /* @brief Capture mode */ struct { __IOM uint32_t CC3SEL : 2; @@ -2127,7 +2286,7 @@ typedef struct } CCM2_CAPTURE_B; }; - /** @brief Channel control register */ + /* @brief Channel control register */ union { __IOM uint32_t CCEN; @@ -2152,7 +2311,7 @@ typedef struct } CCEN_B; }; - /** @brief Counting register */ + /* @brief Counting register */ union { __IOM uint32_t CNT; @@ -2164,7 +2323,7 @@ typedef struct } CNT_B; }; - /** @brief Division register */ + /* @brief Division register */ union { __IOM uint32_t PSC; @@ -2176,7 +2335,7 @@ typedef struct } PSC_B; }; - /** @brief Automatic reload register */ + /* @brief Automatic reload register */ union { __IOM uint32_t AUTORLD; @@ -2188,7 +2347,7 @@ typedef struct } AUTORLD_B; }; - /** @brief Repeat count register */ + /* @brief Repeat count register */ union { __IOM uint32_t REPCNT; @@ -2200,7 +2359,7 @@ typedef struct } REPCNT_B; }; - /** @brief Capture comparison register channel 1 */ + /* @brief Capture comparison register channel 1 */ union { __IOM uint32_t CC1; @@ -2212,7 +2371,7 @@ typedef struct } CC1_B; }; - /** @brief Capture comparison register channel 2 */ + /* @brief Capture comparison register channel 2 */ union { __IOM uint32_t CC2; @@ -2224,7 +2383,7 @@ typedef struct } CC2_B; }; - /** @brief Capture comparison register channel 3 */ + /* @brief Capture comparison register channel 3 */ union { __IOM uint32_t CC3; @@ -2236,7 +2395,7 @@ typedef struct } CC3_B; }; - /** @brief Capture comparison register channel 4 */ + /* @brief Capture comparison register channel 4 */ union { __IOM uint32_t CC4; @@ -2248,7 +2407,7 @@ typedef struct } CC4_B; }; - /** @brief Brake and dead zone registers */ + /* @brief Brake and dead zone registers */ union { __IOM uint32_t BDT; @@ -2267,7 +2426,7 @@ typedef struct } BDT_B; }; - /** @brief DMA control register */ + /* @brief DMA control register */ union { __IOM uint32_t DCTRL; @@ -2281,7 +2440,7 @@ typedef struct } DCTRL_B; }; - /** @brief Consecutive DMA addresses */ + /* @brief Consecutive DMA addresses */ union { __IOM uint32_t DMADDR; @@ -2298,7 +2457,7 @@ typedef struct */ typedef struct { - /** @brief Interrupt status register */ + /* @brief Interrupt status register */ union { __IM uint32_t INTSTS; @@ -2337,7 +2496,7 @@ typedef struct } INTSTS_B; }; - /** @brief Interrupt reset register */ + /* @brief Interrupt reset register */ union { __OM uint32_t INTFCLR; @@ -2382,7 +2541,7 @@ typedef struct */ typedef struct { - /** @brief DMA Channel setup register */ + /* @brief DMA Channel setup register */ union { @@ -2406,7 +2565,7 @@ typedef struct } CHCFG_B; }; - /** @brief DMA Channel transfer number register*/ + /* @brief DMA Channel transfer number register*/ union { __IOM uint32_t CHNDATA; @@ -2418,7 +2577,7 @@ typedef struct } CHNDATA_B; }; - /** @brief DMA Channel peripheral address register */ + /* @brief DMA Channel peripheral address register */ union { __IOM uint32_t CHPADDR; @@ -2429,7 +2588,7 @@ typedef struct } CHPADDR_B; }; - /** @brief DMA Channel memory address register */ + /* @brief DMA Channel memory address register */ union { __IOM uint32_t CHMADDR; @@ -2446,7 +2605,7 @@ typedef struct */ typedef struct { - /** @brief CAN Each mailbox contains the sending mailbox identifier register */ + /* @brief CAN Each mailbox contains the sending mailbox identifier register */ union { __IOM uint32_t TXMID; @@ -2461,7 +2620,7 @@ typedef struct } TXMID_B; }; - /** @brief CAN Send the mailbox data length and timestamp register */ + /* @brief CAN Send the mailbox data length and timestamp register */ union { __IOM uint32_t TXDLEN; @@ -2473,7 +2632,7 @@ typedef struct } TXDLEN_B; }; - /** @brief CAN Send mailbox low byte data register */ + /* @brief CAN Send mailbox low byte data register */ union { __IOM uint32_t TXMDL; @@ -2487,7 +2646,7 @@ typedef struct } TXMDL_B; }; - /** @brief CAN Send mailbox High byte data register */ + /* @brief CAN Send mailbox High byte data register */ union { __IOM uint32_t TXMDH; @@ -2507,7 +2666,7 @@ typedef struct */ typedef struct { - /** @brief CAN Each mailbox contains the receive mailbox identifier register */ + /* @brief CAN Each mailbox contains the receive mailbox identifier register */ union { __IM uint32_t RXMID; @@ -2522,7 +2681,7 @@ typedef struct } RXMID_B; }; - /** @brief CAN receive the mailbox data length and timestamp register */ + /* @brief CAN receive the mailbox data length and timestamp register */ union { __IM uint32_t RXDLEN; @@ -2536,7 +2695,7 @@ typedef struct } RXDLEN_B; }; - /** @brief CAN receive mailbox low byte data register */ + /* @brief CAN receive mailbox low byte data register */ union { __IM uint32_t RXMDL; @@ -2550,7 +2709,7 @@ typedef struct } RXMDL_B; }; - /** @briefCAN receive mailbox High byte data register */ + /* @briefCAN receive mailbox High byte data register */ union { __IOM uint32_t RXMDH; @@ -2570,7 +2729,7 @@ typedef struct */ typedef struct { - /** @brief CAN Filter bank register 1 */ + /* @brief CAN Filter bank register 1 */ union { __IOM uint32_t FBANK1; @@ -2612,7 +2771,7 @@ typedef struct } FBANK1_B; }; - /** @brief CAN Filter bank register 2 */ + /* @brief CAN Filter bank register 2 */ union { __IOM uint32_t FBANK2; @@ -2660,7 +2819,7 @@ typedef struct */ typedef struct { - /** @brief CAN Master control register */ + /* @brief CAN Master control register */ union { __IOM uint32_t MCTRL; @@ -2681,7 +2840,7 @@ typedef struct } MCTRL_B; }; - /** @brief CAN Master States register */ + /* @brief CAN Master States register */ union { __IOM uint32_t MSTS; @@ -2702,7 +2861,7 @@ typedef struct } MSTS_B; }; - /** @brief CAN Send States register */ + /* @brief CAN Send States register */ union { __IOM uint32_t TXSTS; @@ -2737,7 +2896,7 @@ typedef struct } TXSTS_B; }; - /** @brief CAN Receive FIFO 0 register */ + /* @brief CAN Receive FIFO 0 register */ union { __IOM uint32_t RXF0; @@ -2753,7 +2912,7 @@ typedef struct } RXF0_B; }; - /** @brief CAN Receive FIFO 1 register */ + /* @brief CAN Receive FIFO 1 register */ union { __IOM uint32_t RXF1; @@ -2769,7 +2928,7 @@ typedef struct } RXF1_B; }; - /** @brief CAN Interrupts register */ + /* @brief CAN Interrupts register */ union { __IOM uint32_t INTEN; @@ -2796,7 +2955,7 @@ typedef struct } INTEN_B; }; - /** @brief CAN Error States register */ + /* @brief CAN Error States register */ union { __IOM uint32_t ERRSTS; @@ -2814,7 +2973,7 @@ typedef struct } ERRSTS_B; }; - /** @brief CAN Bit Time register */ + /* @brief CAN Bit Time register */ union { __IOM uint32_t BITTIM; @@ -2840,7 +2999,7 @@ typedef struct __IM uint32_t RESERVED1[12]; - /** @brief CAN Filter the master control register */ + /* @brief CAN Filter the master control register */ union { __IOM uint32_t FCTRL; @@ -2854,7 +3013,7 @@ typedef struct } FCTRL_B; }; - /** @brief CAN Filter register */ + /* @brief CAN Filter register */ union { __IOM uint32_t FMCFG; @@ -2895,7 +3054,7 @@ typedef struct __IM uint32_t RESERVED2; - /** @brief CAN Filter bit scale register */ + /* @brief CAN Filter bit scale register */ union { __IOM uint32_t FSCFG; @@ -2931,12 +3090,12 @@ typedef struct __IOM uint32_t FSCFG26 : 1; __IOM uint32_t FSCFG27 : 1; __IM uint32_t RESERVED : 4; - }FSCFG_B; + } FSCFG_B; }; __IM uint32_t RESERVED3; - /** @brief CAN Filter FIFO associated registers */ + /* @brief CAN Filter FIFO associated registers */ union { __IOM uint32_t FFASS; @@ -2977,7 +3136,7 @@ typedef struct __IM uint32_t RESERVED4; - /** @brief CAN Filter activation register */ + /* @brief CAN Filter activation register */ union { __IOM uint32_t FACT; @@ -3027,7 +3186,7 @@ typedef struct */ typedef struct { - /** @brief Control register 1 */ + /* @brief Control register 1 */ union { __IOM uint32_t CTRL1; @@ -3054,7 +3213,7 @@ typedef struct } CTRL1_B; } ; - /** @brief Control register 2 */ + /* @brief Control register 2 */ union { __IOM uint32_t CTRL2; @@ -3072,7 +3231,7 @@ typedef struct } CTRL2_B; } ; - /** @brief Slave machine address register 1 */ + /* @brief Slave machine address register 1 */ union { __IOM uint32_t SADDR1; @@ -3088,7 +3247,7 @@ typedef struct } SADDR1_B; }; - /** @brief Slave machine address register 2 */ + /* @brief Slave machine address register 2 */ union { __IOM uint32_t SADDR2; @@ -3101,7 +3260,7 @@ typedef struct } SADDR2_B; }; - /** @brief Cache data register */ + /* @brief Cache data register */ union { __IOM uint32_t DATA; @@ -3113,7 +3272,7 @@ typedef struct } DATA_B; }; - /** @brief Status register 1 */ + /* @brief Status register 1 */ union { __IOM uint32_t STS1; @@ -3140,7 +3299,7 @@ typedef struct } STS1_B; }; - /** @brief Status register 2 */ + /* @brief Status register 2 */ union { __IOM uint32_t STS2; @@ -3160,7 +3319,7 @@ typedef struct } STS2_B; }; - /** @brief Clock control register */ + /* @brief Clock control register */ union { __IOM uint32_t CLKCTRL; @@ -3175,7 +3334,7 @@ typedef struct } CLKCTRL_B; }; - /** @brief Maximum rise time */ + /* @brief Maximum rise time */ union { __IOM uint32_t RISETMAX; @@ -3189,7 +3348,7 @@ typedef struct __IM uint32_t RESERVED[55]; - /** @brief I2C Switching register */ + /* @brief I2C Switching register */ union { __IOM uint32_t SWITCH; @@ -3221,7 +3380,7 @@ typedef struct typedef struct { - /** Status register */ + /* Status register */ union { __IOM uint32_t STS; @@ -3237,7 +3396,7 @@ typedef struct } STS_B; }; - /** Control register1*/ + /* Control register1*/ union { __IOM uint32_t CTRL1; @@ -3262,7 +3421,7 @@ typedef struct } CTRL1_B; }; - /** Control register2*/ + /* Control register2*/ union { __IOM uint32_t CTRL2; @@ -3289,7 +3448,7 @@ typedef struct } CTRL2_B; }; - /** Sample time register1*/ + /* Sample time register1*/ union { __IOM uint32_t SMPTIM1; @@ -3308,7 +3467,7 @@ typedef struct } SMPTIM1_B; }; - /** Sample time register2*/ + /* Sample time register2*/ union { __IOM uint32_t SMPTIM2; @@ -3329,7 +3488,7 @@ typedef struct } SMPTIM2_B; }; - /** Injected channel Data offset register1*/ + /* Injected channel Data offset register1*/ union { __IOM uint32_t INJDOF1; @@ -3341,7 +3500,7 @@ typedef struct } INJDOF1_B; }; - /** Injected channel Data offset register2*/ + /* Injected channel Data offset register2*/ union { __IOM uint32_t INJDOF2; @@ -3353,7 +3512,7 @@ typedef struct } INJDOF2_B; }; - /** Injected channel Data offset register3*/ + /* Injected channel Data offset register3*/ union { __IOM uint32_t INJDOF3; @@ -3365,7 +3524,7 @@ typedef struct } INJDOF3_B; }; - /** Injected channel Data offset register4*/ + /* Injected channel Data offset register4*/ union { __IOM uint32_t INJDOF4; @@ -3377,7 +3536,7 @@ typedef struct } INJDOF4_B; }; - /** Analog watchdog high threshold register*/ + /* Analog watchdog high threshold register*/ union { __IOM uint32_t AWDHT; @@ -3389,7 +3548,7 @@ typedef struct } AWDHT_B; }; - /** Analog watchdog low threshold register*/ + /* Analog watchdog low threshold register*/ union { __IOM uint32_t AWDLT; @@ -3401,7 +3560,7 @@ typedef struct } AWDLT_B; }; - /** Regular channel sequence register1*/ + /* Regular channel sequence register1*/ union { __IOM uint32_t REGSEQ1; @@ -3417,7 +3576,7 @@ typedef struct } REGSEQ1_B; }; - /** Regular channel sequence register2*/ + /* Regular channel sequence register2*/ union { __IOM uint32_t REGSEQ2; @@ -3434,7 +3593,7 @@ typedef struct } REGSEQ2_B; }; - /** Regular channel sequence register3*/ + /* Regular channel sequence register3*/ union { __IOM uint32_t REGSEQ3; @@ -3451,7 +3610,7 @@ typedef struct } REGSEQ3_B; }; - /** Injected sequence register*/ + /* Injected sequence register*/ union { __IOM uint32_t INJSEQ; @@ -3467,7 +3626,7 @@ typedef struct } INJSEQ_B; }; - /** Injected Data register1*/ + /* Injected Data register1*/ union { __IM uint32_t INJDATA1; @@ -3479,7 +3638,7 @@ typedef struct } INJDATA1_B; }; - /** Injected Data register2*/ + /* Injected Data register2*/ union { __IM uint32_t INJDATA2; @@ -3491,7 +3650,7 @@ typedef struct } INJDATA2_B; }; - /** Injected Data register3*/ + /* Injected Data register3*/ union { __IM uint32_t INJDATA3; @@ -3503,7 +3662,7 @@ typedef struct } INJDATA3_B; }; - /** Injected Data register4*/ + /* Injected Data register4*/ union { __IM uint32_t INJDATA4; @@ -3515,7 +3674,7 @@ typedef struct } INJDATA4_B; }; - /** Regular Data register*/ + /* Regular Data register*/ union { __IOM uint32_t REGDATA; @@ -3526,14 +3685,14 @@ typedef struct __IM uint32_t ADC2DATA : 16; } REGDATA_B; }; -}ADC_T; +} ADC_T; /** * @brief External Interrupt(EINT) */ typedef struct { - /** Interrupt mask register */ + /* Interrupt mask register */ union { __IOM uint32_t IMASK; @@ -3563,7 +3722,7 @@ typedef struct } IMASK_B; }; - /** Event mask register */ + /* Event mask register */ union { __IOM uint32_t EMASK; @@ -3593,7 +3752,7 @@ typedef struct } EEN_B; }; - /** Rising Trigger Event Enable register */ + /* Rising Trigger Event Enable register */ union { __IOM uint32_t RTEN; @@ -3623,7 +3782,7 @@ typedef struct } RTEN_B; }; - /** Falling Trigger Event Enable register */ + /* Falling Trigger Event Enable register */ union { __IOM uint32_t FTEN; @@ -3653,7 +3812,7 @@ typedef struct } FTEN_B; }; - /** Software Interrupt Enable register */ + /* Software Interrupt Enable register */ union { __IOM uint32_t SWINTE; @@ -3683,7 +3842,7 @@ typedef struct } SWINTE_B; }; - /** Interrupt Flag Enable register */ + /* Interrupt Flag Enable register */ union { __IOM uint32_t IPEND; @@ -3712,7 +3871,7 @@ typedef struct __IM uint32_t RESERVED : 12; } IF_B; }; -}EINT_T; +} EINT_T; /** * @brief Independent watchdog(IWDT) @@ -3720,7 +3879,7 @@ typedef struct typedef struct { - /** Keyword register */ + /* Keyword register */ union { __OM uint32_t KEY; @@ -3732,7 +3891,7 @@ typedef struct } KEY_B; }; - /** Frequency Divider register */ + /* Frequency Divider register */ union { __IOM uint32_t PSC; @@ -3744,7 +3903,7 @@ typedef struct } DIV_B; }; - /** Reload values register */ + /* Reload values register */ union { __IOM uint32_t CNTRLD; @@ -3756,7 +3915,7 @@ typedef struct } CNTRLD_B; }; - /** Status register */ + /* Status register */ union { __IM uint32_t STS; @@ -3768,14 +3927,14 @@ typedef struct __IM uint32_t RESERVED : 30; } STS_B; }; -}IWDT_T; +} IWDT_T; /** * @brief Serial peripheral interface(SPI) */ typedef struct { - /** Control register 1 */ + /* Control register 1 */ union { __IOM uint32_t CTRL1; @@ -3800,7 +3959,7 @@ typedef struct } CTRL1_B; }; - /** Control register 2 */ + /* Control register 2 */ union { __IOM uint32_t CTRL2; @@ -3818,7 +3977,7 @@ typedef struct } CTRL2_B; }; - /** Status register */ + /* Status register */ union { __IOM uint32_t STS; @@ -3837,7 +3996,7 @@ typedef struct } STS_B; }; - /** Data register */ + /* Data register */ union { __IOM uint32_t DATA; @@ -3849,7 +4008,7 @@ typedef struct } DATA_B; }; - /** CRC polynomial register */ + /* CRC polynomial register */ union { __IOM uint32_t CRCPOLY; @@ -3861,7 +4020,7 @@ typedef struct } CRCPOLY_B; }; - /** Receive CRC register */ + /* Receive CRC register */ union { __IM uint32_t RXCRC; @@ -3870,10 +4029,10 @@ typedef struct { __IM uint32_t RXCRC : 16; __IM uint32_t RESERVED : 16; - }RXCRC_B; + } RXCRC_B; }; - /** Transmit CRC register */ + /* Transmit CRC register */ union { __IM uint32_t TXCRC; @@ -3882,10 +4041,10 @@ typedef struct { __IM uint32_t TXCRC : 16; __IM uint32_t RESERVED : 16; - }TXCRC_B; + } TXCRC_B; }; - /** Transmit I2S CTRL register */ + /* Transmit I2S CTRL register */ union { __IOM uint32_t I2SCFG; @@ -3902,10 +4061,10 @@ typedef struct __IOM uint32_t I2SEN : 1; __IOM uint32_t MODESEL : 1; __IM uint32_t RESERVED2 : 20; - }I2SCFG_B; + } I2SCFG_B; }; - /** Transmit I2S DIV register */ + /* Transmit I2S DIV register */ union { __IOM uint32_t I2SPSC; @@ -3916,9 +4075,9 @@ typedef struct __IOM uint32_t ODDPSC : 1; __IOM uint32_t MCIEN : 1; __IM uint32_t RESERVED1 : 22; - }I2SPSC_B; + } I2SPSC_B; }; -}SPI_T; +} SPI_T; /** * @brief Window watchdog (WWDT) @@ -3926,7 +4085,7 @@ typedef struct typedef struct { - /** Control register */ + /* Control register */ union { __IOM uint32_t CTRL; @@ -3939,7 +4098,7 @@ typedef struct } CTRL_B; }; - /** Configure register */ + /* Configure register */ union { __IOM uint32_t CFG; @@ -3953,7 +4112,7 @@ typedef struct } CFG_B; }; - /** Status register */ + /* Status register */ union { __IOM uint32_t STS; @@ -3964,14 +4123,14 @@ typedef struct __IM uint32_t RESERVED : 31; } STS_B; }; -}WWDT_T; +} WWDT_T; /** * @brief Secure digital input/output interface (SDIO) */ typedef struct { - /** Power control register */ + /* Power control register */ union { __IOM uint32_t PWRCTRL; @@ -3983,7 +4142,7 @@ typedef struct } PWRCTRL_B; }; - /** Clock control register */ + /* Clock control register */ union { __IOM uint32_t CLKCTRL; @@ -4001,7 +4160,7 @@ typedef struct } CLKCTRL_B; }; - /** Argument register */ + /* Argument register */ union { __IOM uint32_t ARG; @@ -4012,7 +4171,7 @@ typedef struct } ARG_B; }; - /** Command register */ + /* Command register */ union { __IOM uint32_t CMD; @@ -4032,7 +4191,7 @@ typedef struct } CMD_B; }; - /** Command response register */ + /* Command response register */ union { __IM uint32_t CMDRES; @@ -4044,7 +4203,7 @@ typedef struct } CMDRES_B; }; - /** SDIO response register1 */ + /* SDIO response register1 */ union { __IM uint32_t RES1; @@ -4055,7 +4214,7 @@ typedef struct } RES1_B; }; - /** SDIO response register2 */ + /* SDIO response register2 */ union { __IM uint32_t RES2; @@ -4066,7 +4225,7 @@ typedef struct } RES2_B; }; - /** SDIO response register3 */ + /* SDIO response register3 */ union { __IM uint32_t RES3; @@ -4077,7 +4236,7 @@ typedef struct } RES3_B; }; - /** SDIO response register4 */ + /* SDIO response register4 */ union { __IM uint32_t RES4; @@ -4088,7 +4247,7 @@ typedef struct } RES4_B; }; - /** Data timer register */ + /* Data timer register */ union { __IOM uint32_t DATATIME; @@ -4099,7 +4258,7 @@ typedef struct } DTMR_B; }; - /** Data length register */ + /* Data length register */ union { __IOM uint32_t DATALEN; @@ -4111,7 +4270,7 @@ typedef struct } DLEN_B; }; - /** Data control register */ + /* Data control register */ union { __IOM uint32_t DCTRL; @@ -4131,7 +4290,7 @@ typedef struct } DCTRL_B; }; - /** Data count register */ + /* Data count register */ union { __IM uint32_t DCNT; @@ -4143,7 +4302,7 @@ typedef struct } DCNT_B; }; - /** SDIO status register */ + /* SDIO status register */ union { __IM uint32_t STS; @@ -4178,7 +4337,7 @@ typedef struct } STS_B; }; - /** SDIO interrupt clear register */ + /* SDIO interrupt clear register */ union { __IOM uint32_t ICF; @@ -4203,7 +4362,7 @@ typedef struct } ICF_B; }; - /** SDIO interrupt mask register */ + /* SDIO interrupt mask register */ union { __IOM uint32_t MASK; @@ -4240,7 +4399,7 @@ typedef struct __IM uint32_t RESERVED[2]; - /** SDIO FIFO count register */ + /* SDIO FIFO count register */ union { __IM uint32_t FIFOCNT; @@ -4254,7 +4413,7 @@ typedef struct __IM uint32_t RESERVED1[13]; - /** SDIO data FIFO register */ + /* SDIO data FIFO register */ union { __IOM uint32_t FIFODATA; @@ -4264,14 +4423,14 @@ typedef struct __IOM uint32_t FIFODATA : 32; } FIFODATA_B; }; -}SDIO_T; +} SDIO_T; /** * @brief Digital to Analog Converter(DAC) */ typedef struct { - /** Control register */ + /* Control register */ union { __IOM uint32_t CTRL; @@ -4297,7 +4456,7 @@ typedef struct } CTRL_B; }; - /** Software trigger register */ + /* Software trigger register */ union { __OM uint32_t SWTRG; @@ -4310,7 +4469,7 @@ typedef struct } SWTRG_B; }; - /** Channel1 12-bit right-aligned register */ + /* Channel1 12-bit right-aligned register */ union { __IOM uint32_t DH12R1; @@ -4322,7 +4481,7 @@ typedef struct } DH12R1_B; }; - /** Channel1 12-bit left-aligned register */ + /* Channel1 12-bit left-aligned register */ union { __IOM uint32_t DH12L1; @@ -4335,7 +4494,7 @@ typedef struct } DH12L1_B; }; - /** Channel1 8-bit right-aligned register */ + /* Channel1 8-bit right-aligned register */ union { __IOM uint32_t DH8R1; @@ -4347,19 +4506,19 @@ typedef struct } DH8R1_B; }; - /** Channel2 12-bit right-aligned register */ - union - { - __IOM uint32_t DH12R2; + /* Channel2 12-bit right-aligned register */ + union + { + __IOM uint32_t DH12R2; - struct - { + struct + { __IOM uint32_t DATA : 12; __IM uint32_t RESERVED : 20; } DH12R2_B; }; - /** Channel2 12-bit left-aligned register */ + /* Channel2 12-bit left-aligned register */ union { __IOM uint32_t DH12L2; @@ -4369,10 +4528,10 @@ typedef struct __IM uint32_t RESERVED1 : 4; __IOM uint32_t DATA : 12; __IM uint32_t RESERVED2 : 16; - }DH12L2_B; + } DH12L2_B; }; - /** Channel2 8-bit right-aligned register */ + /* Channel2 8-bit right-aligned register */ union { __IOM uint32_t DH8R2; @@ -4384,7 +4543,7 @@ typedef struct } DH8R2_B; }; - /** Channel1,Channel2 12-bit right-aligned register */ + /* Channel1,Channel2 12-bit right-aligned register */ union { __IOM uint32_t DH12RDUAL; @@ -4398,7 +4557,7 @@ typedef struct } DH12RDUAL_B; }; - /** Channel1,Channel2 12-bit left-aligned register */ + /* Channel1,Channel2 12-bit left-aligned register */ union { __IOM uint32_t DH12LDUAL; @@ -4412,7 +4571,7 @@ typedef struct } DH12LDUAL_B; }; - /** Channel1,Channel2 8-bit right-aligned register */ + /* Channel1,Channel2 8-bit right-aligned register */ union { __IOM uint32_t DH8RDUAL; @@ -4425,7 +4584,7 @@ typedef struct } DH8RDUAL_B; }; - /** Channel1 data output register */ + /* Channel1 data output register */ union { __IM uint32_t DATAOCH1; @@ -4437,7 +4596,7 @@ typedef struct } DATAOCH1_B; }; - /** Channel2 data output register */ + /* Channel2 data output register */ union { __IM uint32_t DATAOCH2; @@ -4448,14 +4607,14 @@ typedef struct __IM uint32_t RESERVED : 20; } DATAOCH2_B; }; -}DAC_T; +} DAC_T; /** - * @brief EMMC Register + * @brief SMC Register */ typedef struct { - /** SRAM/NOR-Flash chip-select control register */ + /* SRAM/NOR-Flash chip-select control register */ union { __IOM uint32_t CSCTRL; @@ -4479,13 +4638,13 @@ typedef struct __IOM uint32_t CRAMPSIZECFG : 3; __IOM uint32_t WRBURSTEN : 1; __IOM uint32_t RESERVED2 : 12; - }CSCTRL_B; + } CSCTRL_B; }; -}SNCTRL_T; +} SNCTRL_T; typedef struct { - /** SRAM/NOR-Flash write timing registers */ + /* SRAM/NOR-Flash write timing registers */ union { __IOM uint32_t WRTTIM; @@ -4500,9 +4659,9 @@ typedef struct __IOM uint32_t DATALATCFG : 4; __IOM uint32_t ACCMODECFG : 2; __IM uint32_t RESERVED2 : 2; - }WRTTIM_T; + } WRTTIM_T; }; -}SNWCLK_T; +} SNWCLK_T; /** * @brief Flexible Static Memory Controller @@ -4510,7 +4669,7 @@ typedef struct typedef struct { __IO uint32_t SNCTRL_T[8]; -} EMMC_Bank1_T; +} SMC_Bank1_T; /** * @brief Flexible Static Memory Controller Bank1E @@ -4518,14 +4677,14 @@ typedef struct typedef struct { __IO uint32_t WRTTIM[7]; -} EMMC_Bank1E_T; +} SMC_Bank1E_T; /** * @brief Flexible Static Memory Controller Bank 2 */ typedef struct { - /** PC Card/NAND Flash control register 2 */ + /* PC Card/NAND Flash control register 2 */ union { __IOM uint32_t CTRL2; @@ -4543,10 +4702,10 @@ typedef struct __IOM uint32_t A2RDCFG : 4; __IOM uint32_t ECCPSCFG : 3; __IM uint32_t RESERVED3 : 12; - }CTRL2_B; + } CTRL2_B; }; - /** FIFO status and interrupt register 2 */ + /* FIFO status and interrupt register 2 */ union { __IOM uint32_t STSINT2; @@ -4560,10 +4719,10 @@ typedef struct __IOM uint32_t IHLDEN : 1; __IOM uint32_t IFEDEN : 1; __IM uint32_t FEFLG : 1; - __IM uint32_t RESERVED :25; - }STSINT2_B; + __IM uint32_t RESERVED : 25; + } STSINT2_B; }; - /** Common memory space timing register 2 */ + /* Common memory space timing register 2 */ union { __IOM uint32_t CMSTIM2; @@ -4574,10 +4733,10 @@ typedef struct __IOM uint32_t WAIT2 : 8; __IOM uint32_t HLD2 : 8; __IOM uint32_t HIZ2 : 8; - }CMSTIM2_B; + } CMSTIM2_B; }; - /** Attribute memory space timing register 2 */ + /* Attribute memory space timing register 2 */ union { __IOM uint32_t AMSTIM2; @@ -4588,12 +4747,12 @@ typedef struct __IOM uint32_t WAIT2 : 8; __IOM uint32_t HLD2 : 8; __IOM uint32_t HIZ2 : 8; - }AMSTIM2_B; + } AMSTIM2_B; }; __IOM uint32_t RESERVED; - /** ECC result register 2 */ + /* ECC result register 2 */ union { __IM uint32_t ECCRS2; @@ -4603,14 +4762,14 @@ typedef struct __IM uint32_t ECCRS2 : 32; } ECCRS2_B; }; -}EMMC_Bank2_T; +} SMC_Bank2_T; /** * @brief Flexible Static Memory Controller Bank 3 */ typedef struct { - /** PC Card/NAND Flash control register 3 */ + /* PC Card/NAND Flash control register 3 */ union { __IOM uint32_t CTRL3; @@ -4628,10 +4787,10 @@ typedef struct __IOM uint32_t A2RDCFG : 4; __IOM uint32_t ECCPSCFG : 3; __IM uint32_t RESERVED3 : 12; - }CTRL3_B; + } CTRL3_B; }; - /** FIFO status and interrupt register 3 */ + /* FIFO status and interrupt register 3 */ union { __IOM uint32_t STSINT3; @@ -4645,11 +4804,11 @@ typedef struct __IOM uint32_t IHLDEN : 1; __IOM uint32_t IFEDEN : 1; __IM uint32_t FEFLG : 1; - __IM uint32_t RESERVED :16; - }STSINT3_B; + __IM uint32_t RESERVED : 16; + } STSINT3_B; }; - /** Common memory space timing register 3 */ + /* Common memory space timing register 3 */ union { __IOM uint32_t CMSTIM3; @@ -4660,10 +4819,10 @@ typedef struct __IOM uint32_t WAIT3 : 8; __IOM uint32_t HLD3 : 8; __IOM uint32_t HIZ3 : 8; - }CMSTIM3_B; + } CMSTIM3_B; }; - /** Attribute memory space timing register 3 */ + /* Attribute memory space timing register 3 */ union { __IOM uint32_t AMSTIM3; @@ -4674,12 +4833,12 @@ typedef struct __IOM uint32_t WAIT3 : 8; __IOM uint32_t HLD3 : 8; __IOM uint32_t HIZ3 : 8; - }AMSTIM3_B; + } AMSTIM3_B; }; __IOM uint32_t RESERVED; - /** ECC result register 3 */ + /* ECC result register 3 */ union { __IM uint32_t ECCRS3; @@ -4689,14 +4848,14 @@ typedef struct __IM uint32_t ECCRS3 : 32; } ECCRS3_B; }; -}EMMC_Bank3_T; +} SMC_Bank3_T; /** * @brief Flexible Static Memory Controller Bank 4 */ typedef struct { - /** PC Card/NAND Flash control register 4 */ + /* PC Card/NAND Flash control register 4 */ union { __IOM uint32_t CTRL4; @@ -4714,10 +4873,10 @@ typedef struct __IOM uint32_t A2RDCFG : 4; __IOM uint32_t ECCPSCFG : 3; __IM uint32_t RESERVED3 : 12; - }CTRL4_B; + } CTRL4_B; }; - /** FIFO status and interrupt register 4 */ + /* FIFO status and interrupt register 4 */ union { __IOM uint32_t STSINT4; @@ -4731,11 +4890,11 @@ typedef struct __IOM uint32_t IHLDEN : 1; __IOM uint32_t IFEDEN : 1; __IM uint32_t FEFLG : 1; - __IM uint32_t RESERVED :16; - }STSINT4_B; + __IM uint32_t RESERVED : 16; + } STSINT4_B; }; - /** Common memory space timing register 4 */ + /* Common memory space timing register 4 */ union { __IOM uint32_t CMSTIM4; @@ -4746,10 +4905,10 @@ typedef struct __IOM uint32_t WAIT4 : 8; __IOM uint32_t HLD4 : 8; __IOM uint32_t HIZ4 : 8; - }CMSTIM4_B; + } CMSTIM4_B; }; - /** Attribute memory space timing register 4 */ + /* Attribute memory space timing register 4 */ union { __IOM uint32_t AMSTIM4; @@ -4760,10 +4919,10 @@ typedef struct __IOM uint32_t WAIT4 : 8; __IOM uint32_t HLD4 : 8; __IOM uint32_t HIZ4 : 8; - }AMSTIM4_B; + } AMSTIM4_B; }; - /** I/O space timing register 4 */ + /* I/O space timing register 4 */ union { __IOM uint32_t IOSTIM4; @@ -4774,16 +4933,16 @@ typedef struct __IOM uint32_t WAIT4 : 8; __IOM uint32_t HLD4 : 8; __IOM uint32_t HIZ4 : 8; - }IOSTIM4_B; + } IOSTIM4_B; }; -}EMMC_Bank4_T; +} SMC_Bank4_T; /** * @brief Queued serial peripheral interface(QSPI) */ typedef struct { - /** @brief Control register 1 */ + /* @brief Control register 1 */ union { __IOM uint32_t CTRL1; @@ -4799,10 +4958,10 @@ typedef struct __IM uint32_t RESERVED3 : 7; __IOM uint32_t FRF : 2; __IM uint32_t RESERVED4 : 8; - }CTRL1_B; + } CTRL1_B; }; - /** @brief Control register 2 */ + /* @brief Control register 2 */ union { __IOM uint32_t CTRL2; @@ -4810,10 +4969,10 @@ typedef struct { __IOM uint32_t NDF : 16; __IM uint32_t RESERVED : 16; - }CTRL2_B; + } CTRL2_B; }; - /** @brief QSPI Enable register */ + /* @brief QSPI Enable register */ union { __IOM uint32_t SSIEN; @@ -4821,12 +4980,12 @@ typedef struct { __IOM uint32_t EN : 1; __IM uint32_t RESERVED : 31; - }SSIEN_B; + } SSIEN_B; }; __IM uint32_t RESERVED; - /** @brief QSPI Slave enable register */ + /* @brief QSPI Slave enable register */ union { __IOM uint32_t SLAEN; @@ -4834,10 +4993,10 @@ typedef struct { __IOM uint32_t SLAEN : 1; __IM uint32_t RESERVED : 31; - }SLAEN_B; + } SLAEN_B; }; - /** @brief Baudrate register */ + /* @brief Baudrate register */ union { __IOM uint32_t BR; @@ -4845,10 +5004,10 @@ typedef struct { __IOM uint32_t CLKDIV : 16; __IM uint32_t RESERVED : 16; - }BR_B; + } BR_B; }; - /** @brief Transmission FIFO threshhold level register */ + /* @brief Transmission FIFO threshhold level register */ union { __IOM uint32_t TFTL; @@ -4858,10 +5017,10 @@ typedef struct __IM uint32_t RESERVED1 : 13; __IOM uint32_t TFTH : 3; __IM uint32_t RESERVED2 : 13; - }TFTL_B; + } TFTL_B; }; - /** @brief Reception FIFO threshhold level register */ + /* @brief Reception FIFO threshhold level register */ union { __IOM uint32_t RFTL; @@ -4869,10 +5028,10 @@ typedef struct { __IOM uint32_t RFT : 3; __IM uint32_t RESERVED : 29; - }RFTL_B; + } RFTL_B; }; - /** @brief Transmission FIFO level register */ + /* @brief Transmission FIFO level register */ union { __IOM uint32_t TFL; @@ -4880,10 +5039,10 @@ typedef struct { __IOM uint32_t TFL : 3; __IM uint32_t RESERVED : 29; - }TFL_B; + } TFL_B; }; - /** @brief Reception FIFO level register */ + /* @brief Reception FIFO level register */ union { __IOM uint32_t RFL; @@ -4891,10 +5050,10 @@ typedef struct { __IOM uint32_t RFL : 3; __IM uint32_t RESERVED : 29; - }RFL_B; + } RFL_B; }; - /** @brief Status register */ + /* @brief Status register */ union { __IOM uint32_t STS; @@ -4908,10 +5067,10 @@ typedef struct __IM uint32_t RESERVED1 : 1; __IOM uint32_t DCEF : 1; __IM uint32_t RESERVED2 : 25; - }STS_B; + } STS_B; }; - /** @brief Interrupt enable register */ + /* @brief Interrupt enable register */ union { __IOM uint32_t INTEN; @@ -4924,10 +5083,10 @@ typedef struct __IOM uint32_t RFFIE : 1; __IOM uint32_t MSTIE : 1; __IM uint32_t RESERVED : 26; - }INTEN_B; + } INTEN_B; }; - /** @brief Interrupt status register */ + /* @brief Interrupt status register */ union { __IM uint32_t ISTS; @@ -4940,10 +5099,10 @@ typedef struct __IM uint32_t RFFIF : 1; __IM uint32_t MSTIF : 1; __IM uint32_t RESERVED : 26; - }ISTS_B; + } ISTS_B; }; - /** @brief Raw interrupt register */ + /* @brief Raw interrupt register */ union { __IM uint32_t RIS; @@ -4956,10 +5115,10 @@ typedef struct __IM uint32_t RXFIR : 1; __IM uint32_t MSTIR : 1; __IM uint32_t RESERVED : 26; - }RIS_B; + } RIS_B; }; - /** @brief Transmission FIFO overflow interrupt clear register */ + /* @brief Transmission FIFO overflow interrupt clear register */ union { __IM uint32_t TFOIC; @@ -4967,10 +5126,10 @@ typedef struct { __IM uint32_t TFOIC : 1; __IM uint32_t RESERVED : 31; - }TFOIC_B; + } TFOIC_B; }; - /** @brief Reception FIFO overflow interrupt clear register */ + /* @brief Reception FIFO overflow interrupt clear register */ union { __IM uint32_t RFOIC; @@ -4978,10 +5137,10 @@ typedef struct { __IM uint32_t RFOIC : 1; __IM uint32_t RESERVED : 31; - }RFOIC_B; + } RFOIC_B; }; - /** @brief Reception FIFO underflow interrupt clear register */ + /* @brief Reception FIFO underflow interrupt clear register */ union { __IM uint32_t RFUIC; @@ -4989,10 +5148,10 @@ typedef struct { __IM uint32_t RFUIC : 1; __IM uint32_t RESERVED : 31; - }RFUIC_B; + } RFUIC_B; }; - /** @brief Master interrupt clear register */ + /* @brief Master interrupt clear register */ union { __IM uint32_t MIC; @@ -5000,10 +5159,10 @@ typedef struct { __IM uint32_t MIC : 1; __IM uint32_t RESERVED : 31; - }MIC_B; + } MIC_B; }; - /** @brief Interrupt clear register */ + /* @brief Interrupt clear register */ union { __IM uint32_t ICF; @@ -5011,24 +5170,24 @@ typedef struct { __IM uint32_t ICF : 1; __IM uint32_t RESERVED : 31; - }ICF_B; + } ICF_B; }; __IM uint32_t RESERVED1[5]; - /** @brief Data register */ + /* @brief Data register */ union { __IOM uint32_t DATA; struct { __IOM uint32_t DATA : 32; - }DATA_B; + } DATA_B; }; __IM uint32_t RESERVED2[35]; - /** @brief Reception sample register */ + /* @brief Reception sample register */ union { __IOM uint32_t RSD; @@ -5038,10 +5197,10 @@ typedef struct __IM uint32_t RESERVED1 : 8; __IOM uint32_t RSE : 1; __IM uint32_t RESERVED2 : 15; - }RSD_B; + } RSD_B; }; - /** @brief Reception sample register */ + /* @brief Reception sample register */ union { __IOM uint32_t CTRL3; @@ -5056,12 +5215,12 @@ typedef struct __IM uint32_t RESERVED3 : 14; __IOM uint32_t CSEN : 1; __IM uint32_t RESERVED4 : 1; - }CTRL3_B; + } CTRL3_B; }; __IM uint32_t RESERVED3[66]; - /** @brief IO switch register */ + /* @brief IO switch register */ union { __IOM uint32_t IOSW; @@ -5069,16 +5228,16 @@ typedef struct { __IOM uint32_t IOSW : 1; __IM uint32_t RESERVED : 31; - }IOSW_B; + } IOSW_B; }; -}QSPI_T; +} QSPI_T; /** * @brief SEC Inter-integrated circuit (SCI2C) */ typedef struct { - /** @brief Control register 1 */ + /* @brief Control register 1 */ union { __IOM uint32_t CTRL1; @@ -5095,10 +5254,10 @@ typedef struct __IOM uint32_t RFFIE : 1; __IOM uint32_t DSMA : 1; __IM uint32_t RESERVED2 : 21; - }CTRL1_B; + } CTRL1_B; }; - /** @brief Master address register */ + /* @brief Master address register */ union { __IOM uint32_t TARADDR; @@ -5109,10 +5268,10 @@ typedef struct __IOM uint32_t GCEN : 1; __IOM uint32_t MAM : 1; __IM uint32_t RESERVED : 19; - }TARADDR_B; + } TARADDR_B; }; - /** @brief Slave address register */ + /* @brief Slave address register */ union { __IOM uint32_t SLAADDR; @@ -5120,10 +5279,10 @@ typedef struct { __IOM uint32_t ADDR : 10; __IM uint32_t RESERVED : 22; - }SLAADDR_B; + } SLAADDR_B; }; - /** @brief High speed master code register */ + /* @brief High speed master code register */ union { __IOM uint32_t HSMC; @@ -5131,10 +5290,10 @@ typedef struct { __IOM uint32_t HSMC : 4; __IM uint32_t RESERVED : 28; - }HSMC_B; + } HSMC_B; }; - /** @brief Data register */ + /* @brief Data register */ union { __IOM uint32_t DATA; @@ -5144,10 +5303,10 @@ typedef struct __IOM uint32_t CMD : 1; __IOM uint32_t STOP : 1; __IM uint32_t RESERVED : 22; - }DATA_B; + } DATA_B; }; - /** @brief Standard speed clock high counter register */ + /* @brief Standard speed clock high counter register */ union { __IOM uint32_t SSCHC; @@ -5155,10 +5314,10 @@ typedef struct { __IOM uint32_t CNT : 16; __IM uint32_t RESERVED : 16; - }SSCHC_B; + } SSCHC_B; }; - /** @brief Standard speed clock low counter register */ + /* @brief Standard speed clock low counter register */ union { __IOM uint32_t SSCLC; @@ -5166,10 +5325,10 @@ typedef struct { __IOM uint32_t CNT : 16; __IM uint32_t RESERVED : 16; - }SSCLC_B; + } SSCLC_B; }; - /** @brief Fast speed clock high counter register */ + /* @brief Fast speed clock high counter register */ union { __IOM uint32_t FSCHC; @@ -5177,10 +5336,10 @@ typedef struct { __IOM uint32_t CNT : 16; __IM uint32_t RESERVED : 16; - }FSCHC_B; + } FSCHC_B; }; - /** @brief Fast speed clock low counter register */ + /* @brief Fast speed clock low counter register */ union { __IOM uint32_t FSCLC; @@ -5188,10 +5347,10 @@ typedef struct { __IOM uint32_t CNT : 16; __IM uint32_t RESERVED : 16; - }FSCLC_B; + } FSCLC_B; }; - /** @brief High speed clock high counter */ + /* @brief High speed clock high counter */ union { __IOM uint32_t HSCHC; @@ -5199,10 +5358,10 @@ typedef struct { __IOM uint32_t CNT : 16; __IM uint32_t RESERVED : 16; - }HSCHC_B; + } HSCHC_B; }; - /** @brief High speed clock low counter register */ + /* @brief High speed clock low counter register */ union { __IOM uint32_t HSCLC; @@ -5210,10 +5369,10 @@ typedef struct { __IOM uint32_t CNT : 16; __IM uint32_t RESERVED : 16; - }HSCLC_B; + } HSCLC_B; }; - /** @brief Interrupt status register */ + /* @brief Interrupt status register */ union { __IM uint32_t INTSTS; @@ -5234,10 +5393,10 @@ typedef struct __IM uint32_t RSTADIF : 1; __IM uint32_t MOHIF : 1; __IM uint32_t RESERVED : 18; - }INTSTS_B; + } INTSTS_B; }; - /** @brief Interrupt enable register */ + /* @brief Interrupt enable register */ union { __IOM uint32_t INTEN; @@ -5258,10 +5417,10 @@ typedef struct __IOM uint32_t RSTADIE : 1; __IOM uint32_t MOHIE : 1; __IM uint32_t RESERVED : 18; - }INTEN_B; + } INTEN_B; }; - /** @brief Raw interrupt status register */ + /* @brief Raw interrupt status register */ union { __IM uint32_t RIS; @@ -5282,10 +5441,10 @@ typedef struct __IM uint32_t RSTADIF : 1; __IM uint32_t MOHIF : 1; __IM uint32_t RESERVED : 18; - }RIS_B; + } RIS_B; }; - /** @brief Reception FIFO threshold register */ + /* @brief Reception FIFO threshold register */ union { __IOM uint32_t RFT; @@ -5293,10 +5452,10 @@ typedef struct { __IOM uint32_t RFT : 8; __IM uint32_t RESERVED : 24; - }RFT_B; + } RFT_B; }; - /** @brief Transmission FIFO threshold register */ + /* @brief Transmission FIFO threshold register */ union { __IOM uint32_t TFT; @@ -5304,10 +5463,10 @@ typedef struct { __IOM uint32_t TFT : 8; __IM uint32_t RESERVED : 24; - }TFT_B; + } TFT_B; }; - /** @brief Interruption clear register */ + /* @brief Interruption clear register */ union { __IM uint32_t INTCLR; @@ -5315,10 +5474,10 @@ typedef struct { __IM uint32_t INTCLR : 1; __IM uint32_t RESERVED : 31; - }INTCLR_B; + } INTCLR_B; }; - /** @brief Reception FIFO underflow interruption clear register */ + /* @brief Reception FIFO underflow interruption clear register */ union { __IM uint32_t RFUIC; @@ -5326,10 +5485,10 @@ typedef struct { __IM uint32_t RFUIC : 1; __IM uint32_t RESERVED : 31; - }RFUIC_B; + } RFUIC_B; }; - /** @brief Reception FIFO overflow interruption clear register */ + /* @brief Reception FIFO overflow interruption clear register */ union { __IM uint32_t RFOIC; @@ -5337,10 +5496,10 @@ typedef struct { __IM uint32_t RFOIC : 1; __IM uint32_t RESERVED : 31; - }RFOIC_B; + } RFOIC_B; }; - /** @brief Transmission FIFO overflow interruption clear register */ + /* @brief Transmission FIFO overflow interruption clear register */ union { __IM uint32_t TFOIC; @@ -5348,10 +5507,10 @@ typedef struct { __IM uint32_t TFOIC : 1; __IM uint32_t RESERVED : 31; - }TFOIC_B; + } TFOIC_B; }; - /** @brief Reception request interruption clear register */ + /* @brief Reception request interruption clear register */ union { __IM uint32_t RRIC; @@ -5359,10 +5518,10 @@ typedef struct { __IM uint32_t RRIC : 1; __IM uint32_t RESERVED : 31; - }RRIC_B; + } RRIC_B; }; - /** @brief Transmission abort interruption clear register */ + /* @brief Transmission abort interruption clear register */ union { __IM uint32_t TAIC; @@ -5370,10 +5529,10 @@ typedef struct { __IM uint32_t TAIC : 1; __IM uint32_t RESERVED : 31; - }TAIC_B; + } TAIC_B; }; - /** @brief Receive done interruption clear register */ + /* @brief Receive done interruption clear register */ union { __IM uint32_t RDIC; @@ -5381,10 +5540,10 @@ typedef struct { __IM uint32_t RDIC : 1; __IM uint32_t RESERVED : 31; - }RDIC_B; + } RDIC_B; }; - /** @brief Activity interruption clear register */ + /* @brief Activity interruption clear register */ union { __IM uint32_t AIC; @@ -5392,10 +5551,10 @@ typedef struct { __IM uint32_t AIC : 1; __IM uint32_t RESERVED : 31; - }AIC_B; + } AIC_B; }; - /** @brief Stop detection interruption clear register */ + /* @brief Stop detection interruption clear register */ union { __IM uint32_t STPDIC; @@ -5403,10 +5562,10 @@ typedef struct { __IM uint32_t STPDIC : 1; __IM uint32_t RESERVED : 31; - }STPDIC_B; + } STPDIC_B; }; - /** @brief Start detection interruption clear register */ + /* @brief Start detection interruption clear register */ union { __IM uint32_t STADIC; @@ -5414,10 +5573,10 @@ typedef struct { __IM uint32_t STADIC : 1; __IM uint32_t RESERVED : 31; - }STADIC_B; + } STADIC_B; }; - /** @brief General call interruption clear register */ + /* @brief General call interruption clear register */ union { __IM uint32_t GCIC; @@ -5425,10 +5584,10 @@ typedef struct { __IM uint32_t GCIC : 1; __IM uint32_t RESERVED : 31; - }GCIC_B; + } GCIC_B; }; - /** @brief Control register 2 */ + /* @brief Control register 2 */ union { __IOM uint32_t CTRL2; @@ -5438,10 +5597,10 @@ typedef struct __IOM uint32_t ABR : 1; __IOM uint32_t TCB : 1; __IM uint32_t RESERVED : 29; - }CTRL2_B; + } CTRL2_B; }; - /** @brief Status register 1 */ + /* @brief Status register 1 */ union { __IM uint32_t STS1; @@ -5455,10 +5614,10 @@ typedef struct __IM uint32_t MAF : 1; __IM uint32_t SAF : 1; __IM uint32_t RESERVED : 24; - }STS1_B; + } STS1_B; }; - /** @brief Transmission FIFO level */ + /* @brief Transmission FIFO level */ union { __IOM uint32_t TFL; @@ -5466,10 +5625,10 @@ typedef struct { __IOM uint32_t TFL : 4; __IM uint32_t RESERVED : 28; - }TFL_B; + } TFL_B; }; - /** @brief Reception FIFO level */ + /* @brief Reception FIFO level */ union { __IOM uint32_t RFL; @@ -5477,10 +5636,10 @@ typedef struct { __IOM uint32_t RFL : 4; __IM uint32_t RESERVED : 28; - }RFL_B; + } RFL_B; }; - /** @brief SDA hold time length register */ + /* @brief SDA hold time length register */ union { __IOM uint32_t SDAHOLD; @@ -5489,10 +5648,10 @@ typedef struct __IOM uint32_t TXHOLD : 16; __IOM uint32_t RXHOLD : 8; __IM uint32_t RESERVED : 8; - }SDAHOLD_B; + } SDAHOLD_B; }; - /** @brief Transmission abort source register */ + /* @brief Transmission abort source register */ union { __IM uint32_t TAS; @@ -5515,10 +5674,10 @@ typedef struct __IM uint32_t USRARB : 1; __IM uint32_t FLUCNT : 1; __IM uint32_t RESERVED : 16; - }TAS_B; + } TAS_B; }; - /** @brief Slave data NACK only register */ + /* @brief Slave data NACK only register */ union { __IOM uint32_t SDNO; @@ -5526,10 +5685,10 @@ typedef struct { __IOM uint32_t NACK : 1; __IM uint32_t RESERVED : 31; - }SDNO_B; + } SDNO_B; }; - /** @brief DMA control register */ + /* @brief DMA control register */ union { __IOM uint32_t DMACTRL; @@ -5538,10 +5697,10 @@ typedef struct __IOM uint32_t RXEN : 1; __IOM uint32_t TXEN : 1; __IM uint32_t RESERVED : 30; - }DMACTRL_B; + } DMACTRL_B; }; - /** @brief DMA transmission data level register */ + /* @brief DMA transmission data level register */ union { __IOM uint32_t DTDL; @@ -5549,10 +5708,10 @@ typedef struct { __IOM uint32_t DTDL : 4; __IM uint32_t RESERVED : 28; - }DTDL_B; + } DTDL_B; }; - /** @brief DMA teception data level register */ + /* @brief DMA teception data level register */ union { __IOM uint32_t DRDL; @@ -5560,10 +5719,10 @@ typedef struct { __IOM uint32_t DRDL : 4; __IM uint32_t RESERVED : 28; - }DRDL_B; + } DRDL_B; }; - /** @brief SDA delay register */ + /* @brief SDA delay register */ union { __IOM uint32_t SDADLY; @@ -5571,10 +5730,10 @@ typedef struct { __IOM uint32_t SDADLY : 8; __IM uint32_t RESERVED : 24; - }SDADLY_B; + } SDADLY_B; }; - /** @brief Genernal call ACK register */ + /* @brief Genernal call ACK register */ union { __IOM uint32_t GCA; @@ -5582,10 +5741,10 @@ typedef struct { __IOM uint32_t GCA : 1; __IM uint32_t RESERVED : 31; - }GCA_B; + } GCA_B; }; - /** @brief Status register 2 */ + /* @brief Status register 2 */ union { __IM uint32_t STS2; @@ -5595,10 +5754,10 @@ typedef struct __IM uint32_t SDWB : 1; __IM uint32_t SRDL : 1; __IM uint32_t RESERVED : 29; - }STS2_B; + } STS2_B; }; - /** @brief Low speed spike suppression limit */ + /* @brief Low speed spike suppression limit */ union { __IOM uint32_t LSSSL; @@ -5606,10 +5765,10 @@ typedef struct { __IOM uint32_t LSSSL : 8; __IM uint32_t RESERVED : 24; - }LSSSL_B; + } LSSSL_B; }; - /** @brief High speed spike suppression limit */ + /* @brief High speed spike suppression limit */ union { __IOM uint32_t HSSSL; @@ -5617,12 +5776,12 @@ typedef struct { __IOM uint32_t HSSSL : 8; __IM uint32_t RESERVED : 24; - }HSSSL_B; + } HSSSL_B; }; uint32_t RESERVED[22]; - /** @brief Switch register */ + /* @brief Switch register */ union { __IOM uint32_t SW; @@ -5630,16 +5789,16 @@ typedef struct { __IOM uint32_t SW : 1; __IM uint32_t RESERVED : 31; - }SW_B; + } SW_B; }; -}SCI2C_T; +} SCI2C_T; /** * @brief Dynamic memory controler (DMC) */ typedef struct { - /** @brief Configuraion register */ + /* @brief Configuraion register */ union { __IOM uint32_t CFG; @@ -5651,10 +5810,10 @@ typedef struct __IOM uint32_t CAWCFG : 4; __IOM uint32_t DWCFG : 2; __IM uint32_t RESERVED2 : 17; - }CFG_B; + } CFG_B; }; - /** @brief Timing register 0 */ + /* @brief Timing register 0 */ union { __IOM uint32_t TIM0; @@ -5670,10 +5829,10 @@ typedef struct __IOM uint32_t ATACP : 4; __IOM uint32_t ECASLSEL1 : 1; __IOM uint32_t EXSR1 : 5; - }TIM0_B; + } TIM0_B; }; - /** @brief Timing register 1 */ + /* @brief Timing register 1 */ union { __IOM uint32_t TIM1; @@ -5682,10 +5841,10 @@ typedef struct __IOM uint32_t STBTIM : 16; __IOM uint32_t ARNUMCFG : 4; __IM uint32_t RESERVED : 12; - }TIM1_B; + } TIM1_B; }; - /** @brief Control register 1 */ + /* @brief Control register 1 */ union { __IOM uint32_t CTRL1; @@ -5703,10 +5862,10 @@ typedef struct __IM uint32_t SRMFLG : 1; __IOM uint32_t BANKNUMCFG : 5; __IM uint32_t RESERVED2 : 15; - }CTRL1_B; + } CTRL1_B; }; - /** @brief Refresh register */ + /* @brief Refresh register */ union { __IOM uint32_t REF; @@ -5714,10 +5873,10 @@ typedef struct { __IOM uint32_t RCYCCFG : 16; __IM uint32_t RESERVED : 16; - }REF_B; + } REF_B; }; - /** @brief Chip select register */ + /* @brief Chip select register */ union { __IOM uint32_t CHIPSEL; @@ -5726,12 +5885,12 @@ typedef struct __IM uint32_t RESERVED : 16; __IOM uint32_t BACHIPSEL : 16; - }CHIPSEL_B; + } CHIPSEL_B; }; __IM uint32_t RESERVED[15]; - /** @brief Mask register */ + /* @brief Mask register */ union { __IOM uint32_t MASK; @@ -5740,12 +5899,12 @@ typedef struct __IOM uint32_t MSIZESEL : 5; __IOM uint32_t MTYPESEL : 3; __IM uint32_t RESERVED : 24; - }MASK_B; + } MASK_B; }; __IM uint32_t RESERVED1[234]; - /** @brief Switch register */ + /* @brief Switch register */ union { __IOM uint32_t SW; @@ -5753,10 +5912,10 @@ typedef struct { __IOM uint32_t MCSW : 1; __IM uint32_t RESERVED : 31; - }SW_B; + } SW_B; }; - /** @brief Control register 2 */ + /* @brief Control register 2 */ union { __IOM uint32_t CTRL2; @@ -5769,16 +5928,16 @@ typedef struct __IOM uint32_t BUFFEN : 1; __IOM uint32_t WRPBSEL : 1; __IM uint32_t RESERVED : 24; - }CTRL2_B; + } CTRL2_B; }; -}DMC_T; +} DMC_T; /** * @brief Debug MCU(DBGMCU) */ typedef struct { - /** @brief ID register */ + /* @brief ID register */ union { __IOM uint32_t IDCODE; @@ -5787,10 +5946,10 @@ typedef struct __IOM uint32_t EQR : 12; __IM uint32_t RESERVED : 4; __IOM uint32_t WVR : 16; - }IDCODE_B; + } IDCODE_B; }; - /** @brief Control register */ + /* @brief Control register */ union { __IOM uint32_t CFG; @@ -5824,9 +5983,9 @@ typedef struct __IOM uint32_t TMR10_STS : 1; __IOM uint32_t TMR11_STS : 1; __IM uint32_t RESERVED3 : 1; - }CFG_B; + } CFG_B; }; -}DBGMCU_T; +} DBGMCU_T; /** * @brief USB Device controler(USBD) @@ -5848,17 +6007,17 @@ typedef union __IOM uint32_t RXDTOG : 1; __IOM uint32_t CTFR : 1; __IM uint32_t RESERVED : 16; - }EP_B; -}USBD_EP_REG_T; + } EP_B; +} USBD_EP_REG_T; typedef struct { - /** Endpoint */ + /* Endpoint */ USBD_EP_REG_T EP[8]; __IM uint32_t RESERVED[8]; - /** @brief Control register */ + /* @brief Control register */ union { __IOM uint32_t CTRL; @@ -5880,10 +6039,10 @@ typedef struct __IOM uint32_t PMAOUIEN : 1; __IOM uint32_t CTRIEN : 1; __IM uint32_t RESERVED2 : 16; - }CTRL_B; + } CTRL_B; }; - /** @brief Interrupt status register */ + /* @brief Interrupt status register */ union { __IOM uint32_t INTSTS; @@ -5902,10 +6061,10 @@ typedef struct __IOM uint32_t PMOFLG : 1; __IOM uint32_t CTFLG : 1; __IM uint32_t RESERVED2 : 16; - }INTSTS_B; + } INTSTS_B; }; - /** @brief Frame number register */ + /* @brief Frame number register */ union { __IM uint32_t FRANUM; @@ -5918,10 +6077,10 @@ typedef struct __IM uint32_t RXDMSTS : 1; __IM uint32_t RXDPSTS : 1; __IM uint32_t RESERVED : 16; - }FRANUM_B; + } FRANUM_B; }; - /** @brief Device address register */ + /* @brief Device address register */ union { __IOM uint32_t ADDR; @@ -5931,10 +6090,10 @@ typedef struct __IOM uint32_t ADDR : 7; __IOM uint32_t USBDEN : 1; __IM uint32_t RESERVED : 24; - }ADDR_B; + } ADDR_B; }; - /** @brief Buffer table address register */ + /* @brief Buffer table address register */ union { __IOM uint32_t BUFFTB; @@ -5944,12 +6103,12 @@ typedef struct __IM uint32_t RESERVED1 : 3; __IOM uint32_t BUFFTB : 13; __IM uint32_t RESERVED2 : 16; - }BUFFTB_B; + } BUFFTB_B; }; __IM uint32_t RESERVED1[43]; - /** @brief Buffer table address register */ + /* @brief Buffer table address register */ union { __IOM uint32_t SWITCH; @@ -5958,30 +6117,743 @@ typedef struct { __IOM uint32_t SWITCH : 1; __IM uint32_t RESERVED : 31; - }SWITCH_B; + } SWITCH_B; }; -}USBD_T; +} USBD_T; -/** FMC base address in the alias region */ +/** + * @brief Ethernet: media access control (Ethernet_MAC) + */ + +typedef struct +{ + + union + { + __IOM uint32_t CFG; + + struct + { + __IM uint32_t RESERVED1 : 2; + __IOM uint32_t RXEN : 1; + __IOM uint32_t TXEN : 1; + __IOM uint32_t DC : 1; + __IOM uint32_t BL : 2; + __IOM uint32_t ACS : 1; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t DISR : 1; + __IOM uint32_t IPC : 1; + __IOM uint32_t DM : 1; + __IOM uint32_t LBM : 1; + __IOM uint32_t DISRXO : 1; + __IOM uint32_t SSEL : 1; + __IM uint32_t RESERVED3 : 1; + __IOM uint32_t DISCRS : 1; + __IOM uint32_t IFG : 3; + __IM uint32_t RESERVED4 : 2; + __IOM uint32_t JDIS : 1; + __IOM uint32_t WDTDIS : 1; + } CFG_B; + } ; + + union + { + __IOM uint32_t FRAF; + + struct + { + __IOM uint32_t PR : 1; + __IOM uint32_t HUC : 1; + __IOM uint32_t HMC : 1; + __IOM uint32_t DAIF : 1; + __IOM uint32_t PM : 1; + __IOM uint32_t DISBF : 1; + __IOM uint32_t PCTRLF : 1; + __IOM uint32_t SAIF : 1; + __IOM uint32_t SAFEN : 1; + __IOM uint32_t HPF : 1; + __IM uint32_t RESERVED1 : 21; + __IOM uint32_t RXA : 1; + } FRAF_B; + } ; + + union + { + __IOM uint32_t HTH; + + struct + { + __IOM uint32_t HTH : 32; + } HTH_B; + } ; + + union + { + __IOM uint32_t HTL; + + struct + { + __IOM uint32_t HTL : 32; + } HTL_B; + } ; + + union + { + __IOM uint32_t ADDR; + + struct + { + __IOM uint32_t MB : 1; + __IOM uint32_t MW : 1; + __IOM uint32_t CR : 3; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t MR : 5; + __IOM uint32_t PA : 5; + } ADDR_B; + } ; + + union + { + __IOM uint32_t DATA; + + struct + { + __IOM uint32_t MD : 16; + } DATA_B; + } ; + + union + { + __IOM uint32_t FCTRL; + + struct + { + __IOM uint32_t FCTRLB : 1; + __IOM uint32_t TXFCTRLEN : 1; + __IOM uint32_t RXFCTRLEN : 1; + __IOM uint32_t UNPFDETE : 1; + __IOM uint32_t PTSEL : 2; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t ZQPDIS : 1; + __IM uint32_t RESERVED2 : 8; + __IOM uint32_t PT : 16; + } FCTRL_B; + } ; + + union + { + __IOM uint32_t VLANT; + + struct + { + __IOM uint32_t VLANTID : 16; + __IOM uint32_t VLANTCOMP : 1; + } VLANT_B; + } ; + __IM uint32_t RESERVED[2]; + __IOM uint32_t REMWKUPFFL; + + union + { + __IOM uint32_t PMTCTRLSTS; + + struct + { + __IOM uint32_t PD : 1; + __IOM uint32_t MPEN : 1; + __IOM uint32_t WKUPFEN : 1; + __IM uint32_t RESERVED1 : 2; + __IOM uint32_t MPRX : 1; + __IOM uint32_t WKUPFRX : 1; + __IM uint32_t RESERVED2 : 2; + __IOM uint32_t GUN : 1; + __IM uint32_t RESERVED3 : 21; + __IOM uint32_t WKUPFRST : 1; + } PMTCTRLSTS_B; + } ; + __IM uint32_t RESERVED1[2]; + + union + { + __IOM uint32_t ISTS; + + struct + { + __IM uint32_t RESERVED1 : 3; + __IM uint32_t PMTIS : 1; + __IM uint32_t MMCIS : 1; + __IM uint32_t MMCRXIS : 1; + __IM uint32_t MMCTXIS : 1; + __IM uint32_t RESERVED2 : 2; + __IOM uint32_t TSIS : 1; + } ISTS_B; + } ; + + union + { + __IOM uint32_t IMASK; + + struct + { + __IM uint32_t RESERVED1 : 3; + __IOM uint32_t PMTIM : 1; + __IM uint32_t RESERVED2 : 5; + __IOM uint32_t TSTIM : 1; + } IMASK_B; + } ; + + union + { + __IOM uint32_t ADDR0H; + + struct + { + __IOM uint32_t ADDR0H : 16; + __IM uint32_t RESERVED1 : 15; + __IM uint32_t AL1 : 1; + } ADDR0H_B; + } ; + + union + { + __IOM uint32_t ADDR0L; + + struct + { + __IOM uint32_t ADDR0L : 32; + } ADDR0L_B; + } ; + + union + { + __IOM uint32_t ADDR1H; + + struct + { + __IOM uint32_t ADDR1H : 16; + __IM uint32_t RESERVED1 : 8; + __IOM uint32_t MASKBCTRL : 6; + __IOM uint32_t ADDRSEL : 1; + __IOM uint32_t ADDREN : 1; + } ADDR1H_B; + } ; + + union + { + __IOM uint32_t ADDR1L; + + struct + { + __IOM uint32_t ADDR1L : 32; + } ADDR1L_B; + } ; + + union + { + __IOM uint32_t ADDR2H; + + struct + { + __IOM uint32_t ADDR2H : 16; + __IM uint32_t RESERVED1 : 8; + __IOM uint32_t MASKBCTRL : 6; + __IOM uint32_t ADDRSEL : 1; + __IOM uint32_t ADDREN : 1; + } ADDR2H_B; + } ; + + union + { + __IOM uint32_t ADDR2L; + + struct + { + __IOM uint32_t ADDR2L : 31; + } ADDR2L_B; + } ; + + union + { + __IOM uint32_t ADDR3H; + + struct + { + __IOM uint32_t ADDR3H : 16; + __IM uint32_t RESERVED1 : 8; + __IOM uint32_t MASKBCTRL : 6; + __IOM uint32_t ADDRSEL : 1; + __IOM uint32_t ADDREN : 1; + } ADDR3H_B; + } ; + + union + { + __IOM uint32_t ADDR3L; + + struct + { + __IOM uint32_t ADDR3L : 32; + } ADDR3L_B; + } ; + __IM uint32_t RESERVED2[40]; + + union + { + __IOM uint32_t CTRL; + + struct + { + __IOM uint32_t CNTRST : 1; + __IOM uint32_t CNTSTOPRO : 1; + __IOM uint32_t RSTOR : 1; + __IOM uint32_t MCNTF : 1; + __IM uint32_t RESERVED1 : 28; + } CTRL_B; + } ; + + union + { + __IOM uint32_t RXINT; + + struct + { + __IM uint32_t RESERVED1 : 5; + __IOM uint32_t RXFCE : 1; + __IOM uint32_t RXFAE : 1; + __IM uint32_t RESERVED2 : 10; + __IOM uint32_t RXGUNF : 1; + } RXINT_B; + } ; + + union + { + __IOM uint32_t TXINT; + + struct + { + __IM uint32_t RESERVED1 : 14; + __IOM uint32_t TXGFSCOL : 1; + __IOM uint32_t TXGFMCOL : 1; + __IM uint32_t RESERVED2 : 5; + __IOM uint32_t TXGF : 1; + } TXINT_B; + } ; + + union + { + __IOM uint32_t RXINTMASK; + + struct + { + __IM uint32_t RESERVED1 : 5; + __IOM uint32_t RXFCEM : 1; + __IOM uint32_t RXFAEM : 1; + __IM uint32_t RESERVED2 : 10; + __IOM uint32_t RXGUNFM : 1; + } RXINTMASK_B; + } ; + + union + { + __IOM uint32_t TXINTMASK; + + struct + { + __IM uint32_t RESERVED1 : 14; + __IOM uint32_t TXGFSCOLM : 1; + __IOM uint32_t TXGFMCOLM : 1; + __IM uint32_t RESERVED2 : 5; + __IOM uint32_t TXGFM : 1; + } TXINTMASK_B; + } ; + __IM uint32_t RESERVED3[14]; + + union + { + __IM uint32_t TXGFSCCNT; + + struct + { + __IM uint32_t TXGFSCCNT : 32; + } TXGFSCCNT_B; + } ; + + union + { + __IM uint32_t TXGFMCCNT; + + struct + { + __IM uint32_t TXGFMCCNT : 32; + } TXGFMCCNT_B; + } ; + __IM uint32_t RESERVED4[5]; + + union + { + __IM uint32_t TXGFCNT; + + struct + { + __IM uint32_t TXGFCNT : 32; + } TXGFCNT_B; + } ; + __IM uint32_t RESERVED5[10]; + + union + { + __IM uint32_t RXFCECNT; + + struct + { + __IM uint32_t RXFCECNT : 32; + } RXFCECNT_B; + } ; + + union + { + __IM uint32_t RXFAECNT; + + struct + { + __IM uint32_t RXFAECNT : 32; + } RXFAECNT_B; + } ; + __IM uint32_t RESERVED6[10]; + + union + { + __IM uint32_t RXGUNCNT; + + struct + { + __IM uint32_t RXGUNCNT : 32; + } RXGUNCNT_B; + } ; + __IM uint32_t RESERVED7[334]; + + union + { + __IOM uint32_t TSCTRL; + + struct + { + __IOM uint32_t TSEN : 1; + __IOM uint32_t TSUDSEL : 1; + __IOM uint32_t TSSTINIT : 1; + __IOM uint32_t TSSTUD : 1; + __IOM uint32_t TSTRGIEN : 1; + __IOM uint32_t TSADDUD : 1; + } TSCTRL_B; + } ; + + union + { + __IOM uint32_t SUBSECI; + + struct + { + __IOM uint32_t STSUBSECI : 8; + } SUBSECI_B; + } ; + + union + { + __IM uint32_t TSH; + + struct + { + __IM uint32_t STSEC : 32; + } TSH_B; + } ; + + union + { + __IM uint32_t TSL; + + struct + { + __IM uint32_t STSUBSEC : 31; + __IM uint32_t STSEL : 1; + } TSL_B; + } ; + + union + { + __IOM uint32_t TSHUD; + + struct + { + __IOM uint32_t TSUDSEC : 32; + } TSHUD_B; + } ; + + union + { + __IOM uint32_t TSLUD; + + struct + { + __IOM uint32_t TSUDSUBSEC : 31; + __IOM uint32_t TSUDSEL : 1; + } TSLUD_B; + } ; + + union + { + __IOM uint32_t TSA; + + struct + { + __IOM uint32_t TSA : 32; + } TSA_B; + } ; + + union + { + __IOM uint32_t TTSH; + + struct + { + __IOM uint32_t TTSH : 32; + } TTSH_B; + } ; + + union + { + __IOM uint32_t TTSL; + + struct + { + __IOM uint32_t TTSL : 32; + } TTSL_B; + } ; + __IM uint32_t RESERVED8[567]; + + union + { + __IOM uint32_t DMABMOD; + + struct + { + __IOM uint32_t SWR : 1; + __IOM uint32_t DAS : 1; + __IOM uint32_t DSL : 5; + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t PBL : 6; + __IOM uint32_t PR : 2; + __IOM uint32_t FB : 1; + __IOM uint32_t RPBL : 6; + __IOM uint32_t USP : 1; + __IOM uint32_t PBLx4 : 1; + __IOM uint32_t AAL : 1; + } DMABMOD_B; + } ; + + union + { + __IOM uint32_t DMATXPD; + + struct + { + __IOM uint32_t TXPD : 32; + } DMATXPD_B; + } ; + + union + { + __IOM uint32_t DMARXPD; + + struct + { + __IOM uint32_t RXPD : 32; + } DMARXPD_B; + } ; + + union + { + __IOM uint32_t DMARXDLADDR; + + struct + { + __IOM uint32_t RXSTA : 32; + } DMARXDLADDR_B; + } ; + + union + { + __IOM uint32_t DMATXDLADDR; + + struct + { + __IOM uint32_t TXSTA : 32; + } DMATXDLADDR_B; + } ; + + union + { + __IOM uint32_t DMASTS; + + struct + { + __IOM uint32_t TXFLG : 1; + __IOM uint32_t TXSFLG : 1; + __IOM uint32_t TXBU : 1; + __IOM uint32_t TXJTO : 1; + __IOM uint32_t RXOVF : 1; + __IOM uint32_t TXUNF : 1; + __IOM uint32_t RXFLG : 1; + __IOM uint32_t RXBU : 1; + __IOM uint32_t RXSFLG : 1; + __IOM uint32_t RXWTOFLG : 1; + __IOM uint32_t ETXFLG : 1; + __IM uint32_t RESERVED1 : 2; + __IOM uint32_t FBERRFLG : 1; + __IOM uint32_t ERXFLG : 1; + __IOM uint32_t AINTS : 1; + __IOM uint32_t NINTS : 1; + __IM uint32_t RXSTS : 3; + __IM uint32_t TXSTS : 3; + __IM uint32_t ERRB : 3; + __IM uint32_t RESERVED2 : 1; + __IM uint32_t MMCFLG : 1; + __IM uint32_t PMTFLG : 1; + __IM uint32_t TSTFLG : 1; + } DMASTS_B; + } ; + + union + { + __IOM uint32_t DMAOPMOD; + + struct + { + __IM uint32_t RESERVED1 : 1; + __IOM uint32_t STRX : 1; + __IOM uint32_t OSECF : 1; + __IOM uint32_t RXTHCTRL : 2; + __IM uint32_t RESERVED2 : 1; + __IOM uint32_t FUF : 1; + __IOM uint32_t FERRF : 1; + __IM uint32_t RESERVED3 : 5; + __IOM uint32_t STTX : 1; + __IOM uint32_t TXTHCTRL : 3; + __IM uint32_t RESERVED4 : 3; + __IOM uint32_t FTXF : 1; + __IOM uint32_t TXSF : 1; + __IM uint32_t RESERVED5 : 2; + __IOM uint32_t DISFRXF : 1; + __IOM uint32_t RXSF : 1; + __IOM uint32_t DISDT : 1; + } DMAOPMOD_B; + } ; + + union + { + __IOM uint32_t DMAINTEN; + + struct + { + __IOM uint32_t TXIEN : 1; + __IOM uint32_t TXSEN : 1; + __IOM uint32_t TXBUEN : 1; + __IOM uint32_t TXJTOEN : 1; + __IOM uint32_t RXOVFEN : 1; + __IOM uint32_t TXUNFEN : 1; + __IOM uint32_t RXIEN : 1; + __IOM uint32_t RXBUEN : 1; + __IOM uint32_t RXSEN : 1; + __IOM uint32_t RXWTOEN : 1; + __IOM uint32_t ETXIEN : 1; + __IM uint32_t RESERVED1 : 2; + __IOM uint32_t FBERREN : 1; + __IOM uint32_t ERXIEN : 1; + __IOM uint32_t AINTSEN : 1; + __IOM uint32_t NINTSEN : 1; + } DMAINTEN_B; + } ; + + union + { + __IM uint32_t DMAMFABOCNT; + + struct + { + __IM uint32_t MISFCNT : 16; + __IM uint32_t MISFCNTOVF : 1; + __IM uint32_t AMISFCNT : 11; + __IM uint32_t OVFCNTOVF : 1; + } DMAMFABOCNT_B; + } ; + __IM uint32_t RESERVED9[9]; + + union + { + __IM uint32_t DMAHTXD; + + struct + { + __IM uint32_t HTXDADDRP : 32; + } DMAHTXD_B; + } ; + + union + { + __IM uint32_t DMAHRXD; + + struct + { + __IM uint32_t HRXDADDRP : 32; + } DMAHRXD_B; + } ; + + union + { + __IM uint32_t DMAHTXBADDR; + + struct + { + __IM uint32_t HTXBADDRP : 32; + } DMAHTXBADDR_B; + } ; + + union + { + __IM uint32_t DMAHRXBADDR; + + struct + { + __IM uint32_t HRXBADDRP : 32; + } DMAHRXBADDR_B; + } ; +} ETH_T; + +/**@} end of group Peripheral_registers_structures*/ + +/** @defgroup Peripheral_memory_map + @{ +*/ + +/* FMC base address in the alias region */ #define FMC_BASE ((uint32_t)0x08000000) -/** SRAM base address in the alias region */ +/* SRAM base address in the alias region */ #define SRAM_BASE ((uint32_t)0x20000000) -/** Peripheral base address in the alias region */ +/* Peripheral base address in the alias region */ #define PERIPH_BASE ((uint32_t)0x40000000) -/** SRAM base address in the bit-band region */ +/* SRAM base address in the bit-band region */ #define SRAM_BB_BASE ((uint32_t)0x22000000) -/** Peripheral base address in the bit-band region */ +/* Peripheral base address in the bit-band region */ #define PERIPH_BB_BASE ((uint32_t)0x42000000) -/** EMMC registers base address */ -#define EMMC_R_BASE ((uint32_t)0xA0000000) -/** QSPI registers base address */ +/* SMC registers base address */ +#define SMC_R_BASE ((uint32_t)0xA0000000) +/* QSPI registers base address */ #define QSPI_BASE ((uint32_t)0xA0000000) -/** DMC registers base address */ +/* DMC registers base address */ #define DMC_BASE ((uint32_t)0xA0000000) -/** Peripheral memory map */ +/* Peripheral memory map */ #define APB1PERIPH_BASE PERIPH_BASE #define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) #define AHBPERIPH_BASE (PERIPH_BASE + 0x20000) @@ -6056,25 +6928,36 @@ typedef struct #define RCM_BASE (AHBPERIPH_BASE + 0x1000) #define CRC_BASE (AHBPERIPH_BASE + 0x3000) -/** FMC registers base address */ +#define ETH_BASE (AHBPERIPH_BASE + 0x8000) +#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) +/* FMC registers base address */ #define FMC_R_BASE (AHBPERIPH_BASE + 0x2000) -/** FMC Option Bytes base address */ +/* FMC Option Bytes base address */ #define OB_BASE ((uint32_t)0x1FFFF800) -/** EMMC Bank1 registers base address */ -#define EMMC_Bank1_R_BASE (EMMC_R_BASE + 0x0000) -/** EMMC Bank1E registers base address */ -#define EMMC_Bank1E_R_BASE (EMMC_R_BASE + 0x0104) -/** EMMC Bank2 registers base address */ -#define EMMC_Bank2_R_BASE (EMMC_R_BASE + 0x0060) -/** EMMC Bank3 registers base address */ -#define EMMC_Bank3_R_BASE (EMMC_R_BASE + 0x0080) -/**EMMC Bank4 registers base address */ -#define EMMC_Bank4_R_BASE (EMMC_R_BASE + 0x00A0) +/* SMC Bank1 registers base address */ +#define SMC_Bank1_R_BASE (SMC_R_BASE + 0x0000) +/* SMC Bank1E registers base address */ +#define SMC_Bank1E_R_BASE (SMC_R_BASE + 0x0104) +/* SMC Bank2 registers base address */ +#define SMC_Bank2_R_BASE (SMC_R_BASE + 0x0060) +/* SMC Bank3 registers base address */ +#define SMC_Bank3_R_BASE (SMC_R_BASE + 0x0080) +/*SMC Bank4 registers base address */ +#define SMC_Bank4_R_BASE (SMC_R_BASE + 0x00A0) -/** Debug MCU registers base address */ +/* Debug MCU registers base address */ #define DBGMCU_BASE ((uint32_t)0xE0042000) +/**@} end of group Peripheral_memory_map*/ + +/** @defgroup Peripheral_declaration + @{ +*/ + #define CRC ((CRC_T *) CRC_BASE) #define RTC ((RTC_T *) RTC_BASE) #define PMU ((PMU_T *) PMU_BASE) @@ -6154,11 +7037,11 @@ typedef struct #define FMC ((FMC_T *) FMC_R_BASE) #define USBD ((USBD_T *)USBD_BASE) -#define EMMC_Bank1 ((EMMC_Bank1_T *) EMMC_Bank1_R_BASE) -#define EMMC_Bank1E ((EMMC_Bank1E_T *)EMMC_Bank1E_R_BASE) -#define EMMC_Bank2 ((EMMC_Bank2_T *) EMMC_Bank2_R_BASE) -#define EMMC_Bank3 ((EMMC_Bank3_T *) EMMC_Bank3_R_BASE) -#define EMMC_Bank4 ((EMMC_Bank4_T *) EMMC_Bank4_R_BASE) +#define SMC_Bank1 ((SMC_Bank1_T *) SMC_Bank1_R_BASE) +#define SMC_Bank1E ((SMC_Bank1E_T *)SMC_Bank1E_R_BASE) +#define SMC_Bank2 ((SMC_Bank2_T *) SMC_Bank2_R_BASE) +#define SMC_Bank3 ((SMC_Bank3_T *) SMC_Bank3_R_BASE) +#define SMC_Bank4 ((SMC_Bank4_T *) SMC_Bank4_R_BASE) #define DBGMCU ((DBGMCU_T *) DBGMCU_BASE) @@ -6172,7 +7055,17 @@ typedef struct #define DMC ((DMC_T *)DMC_BASE) #endif -/** Define one bit mask */ +#if defined (APM32F10X_CL) +#define ETH ((ETH_T *) ETH_BASE) +#endif + +/**@} end of group Peripheral_declaration*/ + +/** @defgroup Exported_Macros + @{ +*/ + +/* Define one bit mask */ #define BIT0 ((uint32_t)0x00000001) #define BIT1 ((uint32_t)0x00000002) #define BIT2 ((uint32_t)0x00000004) @@ -6220,11 +7113,12 @@ typedef struct #define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK))) +/**@} end of group Exported_Macros*/ +/**@} end of group APM32F10x */ +/**@} end of group CMSIS */ #ifdef __cplusplus } #endif #endif /* __APM32F10X_H */ - - diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Include/system_apm32f10x.h b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Include/system_apm32f10x.h index dfc9df718f..2526840737 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Include/system_apm32f10x.h +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Include/system_apm32f10x.h @@ -3,9 +3,9 @@ * * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Source File * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,21 +23,40 @@ * and limitations under the License. */ +/* Define to prevent recursive inclusion */ #ifndef __SYSTEM_APM32F10X_H #define __SYSTEM_APM32F10X_H +/* Includes */ +#include "apm32f10x.h" + #ifdef __cplusplus - extern "C" { +extern "C" { #endif +/** @addtogroup CMSIS + @{ +*/ + +/** @addtogroup APM32F10x_System + @{ +*/ + +/** @defgroup System_Variables + @{ +*/ + extern uint32_t SystemCoreClock; extern void SystemInit(void); extern void SystemCoreClockUpdate(void); +/**@} end of group System_Functions */ +/**@} end of group APM32F10x_System */ +/**@} end of group CMSIS */ + #ifdef __cplusplus } #endif #endif /*__SYSTEM_APM32F10X_H */ - diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/arm/startup_apm32f10x_cl.s b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/arm/startup_apm32f10x_cl.s new file mode 100644 index 0000000000..5ad9c62bd4 --- /dev/null +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/arm/startup_apm32f10x_cl.s @@ -0,0 +1,365 @@ +;/*! +; * @file startup_apm32f10x_cl.s +; * +; * @brief CMSIS Cortex-M3 based Core Device Startup File for Device startup_apm32f10x_cl +; * +; * @version V1.0.0 +; * +; * @date 2022-07-25 +; * +; * @attention +; * +; * Copyright (C) 2020-2022 Geehy Semiconductor +; * +; * You may not use this file except in compliance with the +; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). +; * +; * The program is only for reference, which is distributed in the hope +; * that it will be useful and instructional for customers to develop +; * their software. Unless required by applicable law or agreed to in +; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT +; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. +; * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions +; * and limitations under the License. +; */ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + 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 0x00000200 + + 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 WWDT_IRQHandler ; Window Watchdog + DCD PVD_IRQHandler ; PVD through EINT Line detect + DCD TAMPER_IRQHandler ; Tamper + DCD RTC_IRQHandler ; RTC + DCD FLASH_IRQHandler ; Flash + DCD RCM_IRQHandler ; RCM + DCD EINT0_IRQHandler ; EINT Line 0 + DCD EINT1_IRQHandler ; EINT Line 1 + DCD EINT2_IRQHandler ; EINT Line 2 + DCD EINT3_IRQHandler ; EINT Line 3 + DCD EINT4_IRQHandler ; EINT 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 CAN1_TX_IRQHandler ; CAN1 TX + DCD CAN1_RX0_IRQHandler ; CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; CAN1 RX1 + DCD CAN1_SCE_IRQHandler ; CAN1 SCE + DCD EINT9_5_IRQHandler ; EINT Line 9..5 + DCD TMR1_BRK_IRQHandler ; TMR1 Break + DCD TMR1_UP_IRQHandler ; TMR1 Update + DCD TMR1_TRG_COM_IRQHandler ; TMR1 Trigger and Commutation + DCD TMR1_CC_IRQHandler ; TMR1 Capture Compare + DCD TMR2_IRQHandler ; TMR2 + DCD TMR3_IRQHandler ; TMR3 + DCD TMR4_IRQHandler ; TMR4 + 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 EINT15_10_IRQHandler ; EINT Line 15..10 + DCD RTCAlarm_IRQHandler ; RTC Alarm through EINT Line + DCD OTG_FS_WKUP_IRQHandler ; USBD Wakeup from suspend + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD TMR5_IRQHandler ; TMR5 + DCD SPI3_IRQHandler ; SPI3 + DCD UART4_IRQHandler ; UART4 + DCD UART5_IRQHandler ; UART5 + DCD TMR6_IRQHandler ; TMR6 + DCD TMR7_IRQHandler ; TMR7 + 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 ; ETH + DCD ETH_WKUP_IRQHandler ; ETH Wake up + 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 OTG_FS_IRQHandler ; OTG FS +__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 WWDT_IRQHandler [WEAK] + EXPORT PVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCM_IRQHandler [WEAK] + EXPORT EINT0_IRQHandler [WEAK] + EXPORT EINT1_IRQHandler [WEAK] + EXPORT EINT2_IRQHandler [WEAK] + EXPORT EINT3_IRQHandler [WEAK] + EXPORT EINT4_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_IRQHandler [WEAK] + EXPORT DMA1_Channel4_IRQHandler [WEAK] + EXPORT DMA1_Channel5_IRQHandler [WEAK] + EXPORT DMA1_Channel6_IRQHandler [WEAK] + EXPORT DMA1_Channel7_IRQHandler [WEAK] + EXPORT ADC1_2_IRQHandler [WEAK] + EXPORT CAN1_TX_IRQHandler [WEAK] + EXPORT CAN1_RX0_IRQHandler [WEAK] + EXPORT CAN1_RX1_IRQHandler [WEAK] + EXPORT CAN1_SCE_IRQHandler [WEAK] + EXPORT EINT9_5_IRQHandler [WEAK] + EXPORT TMR1_BRK_IRQHandler [WEAK] + EXPORT TMR1_UP_IRQHandler [WEAK] + EXPORT TMR1_TRG_COM_IRQHandler [WEAK] + EXPORT TMR1_CC_IRQHandler [WEAK] + EXPORT TMR2_IRQHandler [WEAK] + EXPORT TMR3_IRQHandler [WEAK] + EXPORT TMR4_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 EINT15_10_IRQHandler [WEAK] + EXPORT RTCAlarm_IRQHandler [WEAK] + EXPORT OTG_FS_WKUP_IRQHandler [WEAK] + EXPORT TMR5_IRQHandler [WEAK] + EXPORT SPI3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT UART5_IRQHandler [WEAK] + EXPORT TMR6_IRQHandler [WEAK] + EXPORT TMR7_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 OTG_FS_IRQHandler [WEAK] + +WWDT_IRQHandler +PVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FLASH_IRQHandler +RCM_IRQHandler +EINT0_IRQHandler +EINT1_IRQHandler +EINT2_IRQHandler +EINT3_IRQHandler +EINT4_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_IRQHandler +DMA1_Channel4_IRQHandler +DMA1_Channel5_IRQHandler +DMA1_Channel6_IRQHandler +DMA1_Channel7_IRQHandler +ADC1_2_IRQHandler +CAN1_TX_IRQHandler +CAN1_RX0_IRQHandler +CAN1_RX1_IRQHandler +CAN1_SCE_IRQHandler +EINT9_5_IRQHandler +TMR1_BRK_IRQHandler +TMR1_UP_IRQHandler +TMR1_TRG_COM_IRQHandler +TMR1_CC_IRQHandler +TMR2_IRQHandler +TMR3_IRQHandler +TMR4_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +I2C2_EV_IRQHandler +I2C2_ER_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +USART3_IRQHandler +EINT15_10_IRQHandler +RTCAlarm_IRQHandler +OTG_FS_WKUP_IRQHandler +TMR5_IRQHandler +SPI3_IRQHandler +UART4_IRQHandler +UART5_IRQHandler +TMR6_IRQHandler +TMR7_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 +OTG_FS_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 + +;*******************************END OF FILE************************************ + diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/arm/startup_apm32f10x_hd.s b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/arm/startup_apm32f10x_hd.s index 956b00b8aa..683165208e 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/arm/startup_apm32f10x_hd.s +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/arm/startup_apm32f10x_hd.s @@ -3,9 +3,9 @@ ; * ; * @brief CMSIS Cortex-M3 based Core Device Startup File for Device startup_apm32f10x_hd ; * -; * @version V1.0.2 +; * @version V1.0.3 ; * -; * @date 2022-01-05 +; * @date 2022-07-25 ; * ; * @attention ; * @@ -15,7 +15,7 @@ ; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). ; * ; * The program is only for reference, which is distributed in the hope -; * that it will be usefull and instructional for customers to develop +; * that it will be useful and instructional for customers to develop ; * their software. Unless required by applicable law or agreed to in ; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT ; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/arm/startup_apm32f10x_md.s b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/arm/startup_apm32f10x_md.s index b8c17b31cd..155181bba6 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/arm/startup_apm32f10x_md.s +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/arm/startup_apm32f10x_md.s @@ -3,9 +3,9 @@ ; * ; * @brief CMSIS Cortex-M3 based Core Device Startup File for Device startup_apm32f10x_md ; * -; * @version V1.0.2 +; * @version V1.0.3 ; * -; * @date 2022-01-05 +; * @date 2022-07-25 ; * ; * @attention ; * @@ -15,7 +15,7 @@ ; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). ; * ; * The program is only for reference, which is distributed in the hope -; * that it will be usefull and instructional for customers to develop +; * that it will be useful and instructional for customers to develop ; * their software. Unless required by applicable law or agreed to in ; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT ; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xx4.ld b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xx4.ld new file mode 100644 index 0000000000..1494fff267 --- /dev/null +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xx4.ld @@ -0,0 +1,164 @@ +/*! + * @file gcc_APM32F10xx4.ld + * + * @brief Linker script for APM32F10xx4 Device with + * 16KByte FLASH, 6KByte RAM + * + * @version V1.0.0 + * + * @date 2022-12-01 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Flash Configuration*/ +/* Flash Base Address */ +_rom_base = 0x8000000; +/*Flash Size (in Bytes) */ +_rom_size = 0x0004000; + +/* Embedded RAM Configuration */ +/* RAM Base Address */ +_ram_base = 0x20000000; +/* RAM Size (in Bytes) */ +_ram_size = 0x00001800; + +/* Stack / Heap Configuration */ +_end_stack = 0x20001800; +/* Heap Size (in Bytes) */ +_heap_size = 0x200; +/* Stack Size (in Bytes) */ +_stack_size = 0x400; + +MEMORY +{ +FLASH (rx) : ORIGIN = _rom_base, LENGTH = _rom_size +RAM (xrw) : ORIGIN = _ram_base, LENGTH = _ram_size +} + +SECTIONS +{ + .apm32_isr_vector : + { + . = ALIGN(4); + KEEP(*(.apm32_isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = 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 + + _start_address_init_data = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _start_address_data = .; + *(.data) + *(.data*) + + . = ALIGN(4); + _end_address_data = .; + } >RAM AT> FLASH + + + . = ALIGN(4); + .bss : + { + + _start_address_bss = .; + __bss_start__ = _start_address_bss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _end_address_bss = .; + __bss_end__ = _end_address_bss; + } >RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _heap_size; + . = . + _stack_size; + . = ALIGN(8); + } >RAM + + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xx6.ld b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xx6.ld new file mode 100644 index 0000000000..cb6062538d --- /dev/null +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xx6.ld @@ -0,0 +1,164 @@ +/*! + * @file gcc_APM32F10xx6.ld + * + * @brief Linker script for APM32F10xx6 Device with + * 32KByte FLASH, 10KByte RAM + * + * @version V1.0.0 + * + * @date 2022-12-01 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Flash Configuration*/ +/* Flash Base Address */ +_rom_base = 0x8000000; +/*Flash Size (in Bytes) */ +_rom_size = 0x0008000; + +/* Embedded RAM Configuration */ +/* RAM Base Address */ +_ram_base = 0x20000000; +/* RAM Size (in Bytes) */ +_ram_size = 0x00002800; + +/* Stack / Heap Configuration */ +_end_stack = 0x20002800; +/* Heap Size (in Bytes) */ +_heap_size = 0x200; +/* Stack Size (in Bytes) */ +_stack_size = 0x400; + +MEMORY +{ +FLASH (rx) : ORIGIN = _rom_base, LENGTH = _rom_size +RAM (xrw) : ORIGIN = _ram_base, LENGTH = _ram_size +} + +SECTIONS +{ + .apm32_isr_vector : + { + . = ALIGN(4); + KEEP(*(.apm32_isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = 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 + + _start_address_init_data = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _start_address_data = .; + *(.data) + *(.data*) + + . = ALIGN(4); + _end_address_data = .; + } >RAM AT> FLASH + + + . = ALIGN(4); + .bss : + { + + _start_address_bss = .; + __bss_start__ = _start_address_bss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _end_address_bss = .; + __bss_end__ = _end_address_bss; + } >RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _heap_size; + . = . + _stack_size; + . = ALIGN(8); + } >RAM + + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xx8.ld b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xx8.ld new file mode 100644 index 0000000000..c6e015782d --- /dev/null +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xx8.ld @@ -0,0 +1,164 @@ +/*! + * @file gcc_APM32F10xx8.ld + * + * @brief Linker script for APM32F103xE Device with + * 64KByte FLASH, 20KByte RAM + * + * @version V1.0.0 + * + * @date 2022-12-01 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Flash Configuration*/ +/* Flash Base Address */ +_rom_base = 0x8000000; +/*Flash Size (in Bytes) */ +_rom_size = 0x0010000; + +/* Embedded RAM Configuration */ +/* RAM Base Address */ +_ram_base = 0x20000000; +/* RAM Size (in Bytes) */ +_ram_size = 0x00005000; + +/* Stack / Heap Configuration */ +_end_stack = 0x20005000; +/* Heap Size (in Bytes) */ +_heap_size = 0x200; +/* Stack Size (in Bytes) */ +_stack_size = 0x400; + +MEMORY +{ +FLASH (rx) : ORIGIN = _rom_base, LENGTH = _rom_size +RAM (xrw) : ORIGIN = _ram_base, LENGTH = _ram_size +} + +SECTIONS +{ + .apm32_isr_vector : + { + . = ALIGN(4); + KEEP(*(.apm32_isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = 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 + + _start_address_init_data = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _start_address_data = .; + *(.data) + *(.data*) + + . = ALIGN(4); + _end_address_data = .; + } >RAM AT> FLASH + + + . = ALIGN(4); + .bss : + { + + _start_address_bss = .; + __bss_start__ = _start_address_bss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _end_address_bss = .; + __bss_end__ = _end_address_bss; + } >RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _heap_size; + . = . + _stack_size; + . = ALIGN(8); + } >RAM + + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xxB.ld b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xxB.ld new file mode 100644 index 0000000000..a22aa0d0ce --- /dev/null +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xxB.ld @@ -0,0 +1,164 @@ +/*! + * @file gcc_APM32F10xxB.ld + * + * @brief Linker script for APM32F10xxB Device with + * 128KByte FLASH, 20KByte RAM + * + * @version V1.0.0 + * + * @date 2022-12-01 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Flash Configuration*/ +/* Flash Base Address */ +_rom_base = 0x8000000; +/*Flash Size (in Bytes) */ +_rom_size = 0x0020000; + +/* Embedded RAM Configuration */ +/* RAM Base Address */ +_ram_base = 0x20000000; +/* RAM Size (in Bytes) */ +_ram_size = 0x00005000; + +/* Stack / Heap Configuration */ +_end_stack = 0x20005000; +/* Heap Size (in Bytes) */ +_heap_size = 0x200; +/* Stack Size (in Bytes) */ +_stack_size = 0x400; + +MEMORY +{ +FLASH (rx) : ORIGIN = _rom_base, LENGTH = _rom_size +RAM (xrw) : ORIGIN = _ram_base, LENGTH = _ram_size +} + +SECTIONS +{ + .apm32_isr_vector : + { + . = ALIGN(4); + KEEP(*(.apm32_isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = 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 + + _start_address_init_data = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _start_address_data = .; + *(.data) + *(.data*) + + . = ALIGN(4); + _end_address_data = .; + } >RAM AT> FLASH + + + . = ALIGN(4); + .bss : + { + + _start_address_bss = .; + __bss_start__ = _start_address_bss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _end_address_bss = .; + __bss_end__ = _end_address_bss; + } >RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _heap_size; + . = . + _stack_size; + . = ALIGN(8); + } >RAM + + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xxC.ld b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xxC.ld new file mode 100644 index 0000000000..f63d5fb2ca --- /dev/null +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xxC.ld @@ -0,0 +1,164 @@ +/*! + * @file gcc_APM32F10xxC.ld + * + * @brief Linker script for APM32F10xxC Device with + * 256KByte FLASH, 64KByte RAM + * + * @version V1.0.0 + * + * @date 2022-12-01 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Flash Configuration*/ +/* Flash Base Address */ +_rom_base = 0x8000000; +/*Flash Size (in Bytes) */ +_rom_size = 0x0040000; + +/* Embedded RAM Configuration */ +/* RAM Base Address */ +_ram_base = 0x20000000; +/* RAM Size (in Bytes) */ +_ram_size = 0x00010000; + +/* Stack / Heap Configuration */ +_end_stack = 0x20010000; +/* Heap Size (in Bytes) */ +_heap_size = 0x200; +/* Stack Size (in Bytes) */ +_stack_size = 0x400; + +MEMORY +{ +FLASH (rx) : ORIGIN = _rom_base, LENGTH = _rom_size +RAM (xrw) : ORIGIN = _ram_base, LENGTH = _ram_size +} + +SECTIONS +{ + .apm32_isr_vector : + { + . = ALIGN(4); + KEEP(*(.apm32_isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = 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 + + _start_address_init_data = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _start_address_data = .; + *(.data) + *(.data*) + + . = ALIGN(4); + _end_address_data = .; + } >RAM AT> FLASH + + + . = ALIGN(4); + .bss : + { + + _start_address_bss = .; + __bss_start__ = _start_address_bss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _end_address_bss = .; + __bss_end__ = _end_address_bss; + } >RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _heap_size; + . = . + _stack_size; + . = ALIGN(8); + } >RAM + + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xxD.ld b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xxD.ld new file mode 100644 index 0000000000..aa5f7d7be8 --- /dev/null +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xxD.ld @@ -0,0 +1,164 @@ +/*! + * @file gcc_APM32F10xxD.ld + * + * @brief Linker script for APM32F10xxD Device with + * 384KByte FLASH, 64KByte RAM + * + * @version V1.0.0 + * + * @date 2022-12-01 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Flash Configuration*/ +/* Flash Base Address */ +_rom_base = 0x8000000; +/*Flash Size (in Bytes) */ +_rom_size = 0x0080000; + +/* Embedded RAM Configuration */ +/* RAM Base Address */ +_ram_base = 0x20000000; +/* RAM Size (in Bytes) */ +_ram_size = 0x00010000; + +/* Stack / Heap Configuration */ +_end_stack = 0x20010000; +/* Heap Size (in Bytes) */ +_heap_size = 0x200; +/* Stack Size (in Bytes) */ +_stack_size = 0x400; + +MEMORY +{ +FLASH (rx) : ORIGIN = _rom_base, LENGTH = _rom_size +RAM (xrw) : ORIGIN = _ram_base, LENGTH = _ram_size +} + +SECTIONS +{ + .apm32_isr_vector : + { + . = ALIGN(4); + KEEP(*(.apm32_isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = 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 + + _start_address_init_data = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _start_address_data = .; + *(.data) + *(.data*) + + . = ALIGN(4); + _end_address_data = .; + } >RAM AT> FLASH + + + . = ALIGN(4); + .bss : + { + + _start_address_bss = .; + __bss_start__ = _start_address_bss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _end_address_bss = .; + __bss_end__ = _end_address_bss; + } >RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _heap_size; + . = . + _stack_size; + . = ALIGN(8); + } >RAM + + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xxE.ld b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xxE.ld new file mode 100644 index 0000000000..f54b580502 --- /dev/null +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/gcc_APM32F10xxE.ld @@ -0,0 +1,164 @@ +/*! + * @file gcc_APM32F10xxE.ld + * + * @brief Linker script for APM32F10xxE Device with + * 512KByte FLASH, 128KByte RAM + * + * @version V1.0.0 + * + * @date 2022-12-01 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Flash Configuration*/ +/* Flash Base Address */ +_rom_base = 0x8000000; +/*Flash Size (in Bytes) */ +_rom_size = 0x0080000; + +/* Embedded RAM Configuration */ +/* RAM Base Address */ +_ram_base = 0x20000000; +/* RAM Size (in Bytes) */ +_ram_size = 0x00020000; + +/* Stack / Heap Configuration */ +_end_stack = 0x20020000; +/* Heap Size (in Bytes) */ +_heap_size = 0x200; +/* Stack Size (in Bytes) */ +_stack_size = 0x400; + +MEMORY +{ +FLASH (rx) : ORIGIN = _rom_base, LENGTH = _rom_size +RAM (xrw) : ORIGIN = _ram_base, LENGTH = _ram_size +} + +SECTIONS +{ + .apm32_isr_vector : + { + . = ALIGN(4); + KEEP(*(.apm32_isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = 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 + + _start_address_init_data = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _start_address_data = .; + *(.data) + *(.data*) + + . = ALIGN(4); + _end_address_data = .; + } >RAM AT> FLASH + + + . = ALIGN(4); + .bss : + { + + _start_address_bss = .; + __bss_start__ = _start_address_bss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _end_address_bss = .; + __bss_end__ = _end_address_bss; + } >RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _heap_size; + . = . + _stack_size; + . = ALIGN(8); + } >RAM + + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/startup_apm32f10x_cl.S b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/startup_apm32f10x_cl.S new file mode 100644 index 0000000000..ccc0657e34 --- /dev/null +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/startup_apm32f10x_cl.S @@ -0,0 +1,397 @@ +/*! + * @file startup_apm32f103_hd.S + * + * @brief CMSIS Cortex-M3 based Core Device Startup File for Device startup_apm32f103_hd + * + * @version V1.0.1 + * + * @date 2022-12-01 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + + .syntax unified + .cpu cortex-m3 + .fpu softvfp + .thumb + +.global g_apm32_Vectors +.global Default_Handler + +.word _start_address_init_data +.word _start_address_data +.word _end_address_data +.word _start_address_bss +.word _end_address_bss + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +// Reset handler routine +Reset_Handler: + + ldr r0, =_start_address_data + ldr r1, =_end_address_data + ldr r2, =_start_address_init_data + movs r3, #0 + b L_loop0_0 + +L_loop0: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +L_loop0_0: + adds r4, r0, r3 + cmp r4, r1 + bcc L_loop0 + + ldr r2, =_start_address_bss + ldr r4, =_end_address_bss + movs r3, #0 + b L_loop1 + +L_loop2: + str r3, [r2] + adds r2, r2, #4 + +L_loop1: + cmp r2, r4 + bcc L_loop2 + + bl SystemInit + bl __libc_init_array + bl main + bx lr +.size Reset_Handler, .-Reset_Handler + +// This is the code that gets called when the processor receives an unexpected interrupt. + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +L_Loop_infinite: + b L_Loop_infinite + .size Default_Handler, .-Default_Handler + +// The minimal vector table for a Cortex M3. + .section .apm32_isr_vector,"a",%progbits + .type g_apm32_Vectors, %object + .size g_apm32_Vectors, .-g_apm32_Vectors + +// Vector Table Mapped to Address 0 at Reset +g_apm32_Vectors: + + .word _end_stack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + .word WWDT_IRQHandler // Window Watchdog + .word PVD_IRQHandler // PVD through EINT Line detect + .word TAMPER_IRQHandler // Tamper + .word RTC_IRQHandler // RTC + .word FLASH_IRQHandler // Flash + .word RCM_IRQHandler // RCM + .word EINT0_IRQHandler // EINT Line 0 + .word EINT1_IRQHandler // EINT Line 1 + .word EINT2_IRQHandler // EINT Line 2 + .word EINT3_IRQHandler // EINT Line 3 + .word EINT4_IRQHandler // EINT Line 4 + .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 CAN1_TX_IRQHandler // CAN1 TX + .word CAN1_RX0_IRQHandler // CAN1 RX0 + .word CAN1_RX1_IRQHandler // CAN1 RX1 + .word CAN1_SCE_IRQHandler // CAN1 SCE + .word EINT9_5_IRQHandler // EINT Line 9..5 + .word TMR1_BRK_IRQHandler // TMR1 Break + .word TMR1_UP_IRQHandler // TMR1 Update + .word TMR1_TRG_COM_IRQHandler // TMR1 Trigger and Commutation + .word TMR1_CC_IRQHandler // TMR1 Capture Compare + .word TMR2_IRQHandler // TMR2 + .word TMR3_IRQHandler // TMR3 + .word TMR4_IRQHandler // TMR4 + .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 EINT15_10_IRQHandler // EINT Line 15..10 + .word RTC_Alarm_IRQHandler // RTC Alarm through EINT Line + .word OTG_FS_WKUP_IRQHandler // USBD Wakeup from suspend + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word TMR5_IRQHandler // TMR5 + .word SPI3_IRQHandler // SPI3 + .word UART4_IRQHandler // UART4 + .word UART5_IRQHandler // UART5 + .word TMR6_IRQHandler // TMR6 + .word TMR7_IRQHandler // TMR7 + .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 // ETH + .word ETH_WKUP_IRQHandler // ETH Wake up + .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 OTG_FS_IRQHandler // OTG FS + +// Default exception/interrupt handler + + .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 WWDT_IRQHandler + .thumb_set WWDT_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMPER_IRQHandler + .thumb_set TAMPER_IRQHandler,Default_Handler + + .weak RTC_IRQHandler + .thumb_set RTC_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCM_IRQHandler + .thumb_set RCM_IRQHandler,Default_Handler + + .weak EINT0_IRQHandler + .thumb_set EINT0_IRQHandler,Default_Handler + + .weak EINT1_IRQHandler + .thumb_set EINT1_IRQHandler,Default_Handler + + .weak EINT2_IRQHandler + .thumb_set EINT2_IRQHandler,Default_Handler + + .weak EINT3_IRQHandler + .thumb_set EINT3_IRQHandler,Default_Handler + + .weak EINT4_IRQHandler + .thumb_set EINT4_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 USBD_HP_CAN1_TX_IRQHandler + .thumb_set USBD_HP_CAN1_TX_IRQHandler,Default_Handler + + .weak USBD_LP_CAN1_RX0_IRQHandler + .thumb_set USBD_LP_CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_TX_IRQHandler + .thumb_set CAN1_TX_IRQHandler,Default_Handler + + .weak CAN1_RX0_IRQHandler + .thumb_set 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 EINT9_5_IRQHandler + .thumb_set EINT9_5_IRQHandler,Default_Handler + + .weak TMR1_BRK_IRQHandler + .thumb_set TMR1_BRK_IRQHandler,Default_Handler + + .weak TMR1_UP_IRQHandler + .thumb_set TMR1_UP_IRQHandler,Default_Handler + + .weak TMR1_TRG_COM_IRQHandler + .thumb_set TMR1_TRG_COM_IRQHandler,Default_Handler + + .weak TMR1_CC_IRQHandler + .thumb_set TMR1_CC_IRQHandler,Default_Handler + + .weak TMR2_IRQHandler + .thumb_set TMR2_IRQHandler,Default_Handler + + .weak TMR3_IRQHandler + .thumb_set TMR3_IRQHandler,Default_Handler + + .weak TMR4_IRQHandler + .thumb_set TMR4_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 EINT15_10_IRQHandler + .thumb_set EINT15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak OTG_FS_WKUP_IRQHandler + .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler + + .weak TMR5_IRQHandler + .thumb_set TMR5_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 TMR6_IRQHandler + .thumb_set TMR6_IRQHandler,Default_Handler + + .weak TMR7_IRQHandler + .thumb_set TMR7_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 OTG_FS_IRQHandler + .thumb_set OTG_FS_IRQHandler,Default_Handler diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/startup_apm32f10x_hd.s b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/startup_apm32f10x_hd.s index 1f0b8fd4b4..70654b22b6 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/startup_apm32f10x_hd.s +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/startup_apm32f10x_hd.s @@ -1,281 +1,398 @@ -;/*! -; * @file startup_apm32f10x_hd.s -; * -; * @brief CMSIS Cortex-M3 based Core Device Startup File for Device startup_apm32f10x_hd -; * -; * @version V1.0.0 -; * -; * @date 2022-01-05 -; * -; * @attention -; * -; * Copyright (C) 2020-2022 Geehy Semiconductor -; * -; * You may not use this file except in compliance with the -; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). -; * -; * The program is only for reference, which is distributed in the hope -; * that it will be usefull and instructional for customers to develop -; * their software. Unless required by applicable law or agreed to in -; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT -; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. -; * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions -; * and limitations under the License. -; */ +/*! + * @file startup_apm32f103_hd.S + * + * @brief CMSIS Cortex-M3 based Core Device Startup File for Device startup_apm32f103_hd + * + * @version V1.0.1 + * + * @date 2022-12-01 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ -.syntax unified -.cpu cortex-m3 -.fpu softvfp -.thumb + .syntax unified + .cpu cortex-m3 + .fpu softvfp + .thumb -.global g_pfnVectors -.global Default_Handler +.global g_apm32_Vectors +.global Default_Handler - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object +.word _start_address_init_data +.word _start_address_data +.word _end_address_data +.word _start_address_bss +.word _end_address_bss -g_pfnVectors: - .word _estack // Top of Stack - .word Reset_Handler // Reset Handler - .word NMI_Handler // NMI Handler - .word HardFault_Handler // Hard Fault Handler - .word MemManage_Handler // MPU Fault Handler - .word BusFault_Handler // Bus Fault Handler - .word UsageFault_Handler // Usage Fault Handler - .word 0 // Reserved - .word 0 // Reserved - .word 0 // Reserved - .word 0 // Reserved - .word SVC_Handler // SVCall Handler - .word DebugMon_Handler // Debug Monitor Handler - .word 0 // Reserved - .word PendSV_Handler // PendSV Handler - .word SysTick_Handler // SysTick Handler - - // external interrupts handler - .word WWDT_IRQHandler // Window Watchdog - .word PVD_IRQHandler // PVD through EINT Line detect - .word TAMPER_IRQHandler // Tamper - .word RTC_IRQHandler // RTC - .word FLASH_IRQHandler // Flash - .word RCM_IRQHandler // RCM - .word EINT0_IRQHandler // EINT Line 0 - .word EINT1_IRQHandler // EINT Line 1 - .word EINT2_IRQHandler // EINT Line 2 - .word EINT3_IRQHandler // EINT Line 3 - .word EINT4_IRQHandler // EINT Line 4 - .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 USBD1_HP_CAN1_TX_IRQHandler // USBD1 High Priority or CAN1 TX - .word USBD1_LP_CAN1_RX0_IRQHandler // USBD1 Low Priority or CAN1 RX0 - .word CAN1_RX1_IRQHandler // CAN1 RX1 - .word CAN1_SCE_IRQHandler // CAN1 SCE - .word EINT9_5_IRQHandler // EINT Line 9..5 - .word TMR1_BRK_IRQHandler // TMR1 Break - .word TMR1_UP_IRQHandler // TMR1 Update - .word TMR1_TRG_COM_IRQHandler // TMR1 Trigger and Commutation - .word TMR1_CC_IRQHandler // TMR1 Capture Compare - .word TMR2_IRQHandler // TMR2 - .word TMR3_IRQHandler // TMR3 - .word TMR4_IRQHandler // TMR4 - .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 EINT15_10_IRQHandler // EINT Line 15..10 - .word RTCAlarm_IRQHandler // RTC Alarm through EINT Line - .word USBDWakeUp_IRQHandler // USBD Wakeup from suspend - .word TMR8_BRK_IRQHandler // TMR8 Break - .word TMR8_UP_IRQHandler // TMR8 Update - .word TMR8_TRG_COM_IRQHandler // TMR8 Trigger and Commutation - .word TMR8_CC_IRQHandler // TMR8 Capture Compare - .word ADC3_IRQHandler // ADC3 - .word EMMC_IRQHandler // EMMC - .word SDIO_IRQHandler // SDIO - .word TMR5_IRQHandler // TMR5 - .word SPI3_IRQHandler // SPI3 - .word UART4_IRQHandler // UART4 - .word UART5_IRQHandler // UART5 - .word TMR6_IRQHandler // TMR6 - .word TMR7_IRQHandler // TMR7 - .word DMA2_Channel1_IRQHandler // DMA2 Channel1 - .word DMA2_Channel2_IRQHandler // DMA2 Channel2 - .word DMA2_Channel3_IRQHandler // DMA2 Channel3 - .word DMA2_Channel4_5_IRQHandler // DMA2 Channel4 & Channel5 - .word 0 // Reserved - .word USBD2_HP_CAN2_TX_IRQHandler // USBD2 High Priority or CAN2 TX - .word USBD2_LP_CAN2_RX0_IRQHandler // USBD2 Low Priority or CAN2 RX0 - .word CAN2_RX1_IRQHandler // CAN2 RX1 - .word CAN2_SCE_IRQHandler // CAN2 SCE - - .size g_pfnVectors, .-g_pfnVectors - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +// Reset handler routine Reset_Handler: - ldr r1, =_sidata - ldr r2, =_sdata - ldr r3, =_edata - subs r3, r2 - ble fill_bss_start + ldr r0, =_start_address_data + ldr r1, =_end_address_data + ldr r2, =_start_address_init_data + movs r3, #0 + b L_loop0_0 -loop_copy_data: - subs r3, #4 - ldr r0, [r1,r3] - str r0, [r2,r3] - bgt loop_copy_data +L_loop0: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 -fill_bss_start: - ldr r1, =__bss_start - ldr r2, =__bss_end - movs r0, 0 - subs r2, r1 - ble startup_enter +L_loop0_0: + adds r4, r0, r3 + cmp r4, r1 + bcc L_loop0 + + ldr r2, =_start_address_bss + ldr r4, =_end_address_bss + movs r3, #0 + b L_loop1 -loop_fill_bss: - subs r2, #4 - str r0, [r1, r2] - bgt loop_fill_bss +L_loop2: + str r3, [r2] + adds r2, r2, #4 -startup_enter: - bl SystemInit - bl entry +L_loop1: + cmp r2, r4 + bcc L_loop2 - /* Exception Handlers */ - .weak NMI_Handler - .type NMI_Handler, %function -NMI_Handler: - b . - .size NMI_Handler, . - NMI_Handler + bl SystemInit + bl __libc_init_array + bl main + bx lr +.size Reset_Handler, .-Reset_Handler - .weak MemManage_Handler - .type MemManage_Handler, %function -MemManage_Handler: - b . - .size MemManage_Handler, . - MemManage_Handler - - .weak BusFault_Handler - .type BusFault_Handler, %function -BusFault_Handler: - b . - .size BusFault_Handler, . - BusFault_Handler - - .weak UsageFault_Handler - .type UsageFault_Handler, %function -UsageFault_Handler: - b . - .size UsageFault_Handler, . - UsageFault_Handler - - .weak SVC_Handler - .type SVC_Handler, %function -SVC_Handler: - b . - .size SVC_Handler, . - SVC_Handler - - .weak DebugMon_Handler - .type DebugMon_Handler, %function -DebugMon_Handler: - b . - .size DebugMon_Handler, . - DebugMon_Handler - - .weak PendSV_Handler - .type PendSV_Handler, %function -PendSV_Handler: - b . - .size PendSV_Handler, . - PendSV_Handler - - .weak SysTick_Handler - .type SysTick_Handler, %function -SysTick_Handler: - b . - .size SysTick_Handler, . - SysTick_Handler - - /* IQR Handler */ - .section .text.Default_Handler,"ax",%progbits - .type Default_Handler, %function +// This is the code that gets called when the processor receives an unexpected interrupt. + .section .text.Default_Handler,"ax",%progbits Default_Handler: - b . - .size Default_Handler, . - Default_Handler +L_Loop_infinite: + b L_Loop_infinite + .size Default_Handler, .-Default_Handler - .macro IRQ handler - .weak \handler - .set \handler, Default_Handler - .endm +// The minimal vector table for a Cortex M3. + .section .apm32_isr_vector,"a",%progbits + .type g_apm32_Vectors, %object + .size g_apm32_Vectors, .-g_apm32_Vectors + +// Vector Table Mapped to Address 0 at Reset +g_apm32_Vectors: + + .word _end_stack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + .word WWDT_IRQHandler // Window Watchdog + .word PVD_IRQHandler // PVD through EINT Line detect + .word TAMPER_IRQHandler // Tamper + .word RTC_IRQHandler // RTC + .word FLASH_IRQHandler // Flash + .word RCM_IRQHandler // RCM + .word EINT0_IRQHandler // EINT Line 0 + .word EINT1_IRQHandler // EINT Line 1 + .word EINT2_IRQHandler // EINT Line 2 + .word EINT3_IRQHandler // EINT Line 3 + .word EINT4_IRQHandler // EINT Line 4 + .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 USBD1_HP_CAN1_TX_IRQHandler // USBD1 High Priority or CAN1 TX + .word USBD1_LP_CAN1_RX0_IRQHandler // USBD1 Low Priority or CAN1 RX0 + .word CAN1_RX1_IRQHandler // CAN1 RX1 + .word CAN1_SCE_IRQHandler // CAN1 SCE + .word EINT9_5_IRQHandler // EINT Line 9..5 + .word TMR1_BRK_IRQHandler // TMR1 Break + .word TMR1_UP_IRQHandler // TMR1 Update + .word TMR1_TRG_COM_IRQHandler // TMR1 Trigger and Commutation + .word TMR1_CC_IRQHandler // TMR1 Capture Compare + .word TMR2_IRQHandler // TMR2 + .word TMR3_IRQHandler // TMR3 + .word TMR4_IRQHandler // TMR4 + .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 EINT15_10_IRQHandler // EINT Line 15..10 + .word RTC_Alarm_IRQHandler // RTC Alarm through EINT Line + .word USBDWakeUp_IRQHandler // USBD Wakeup from suspend + .word TMR8_BRK_IRQHandler // TMR8 Break + .word TMR8_UP_IRQHandler // TMR8 Update + .word TMR8_TRG_COM_IRQHandler // TMR8 Trigger and Commutation + .word TMR8_CC_IRQHandler // TMR8 Capture Compare + .word ADC3_IRQHandler // ADC3 + .word FSMC_IRQHandler // EMMC + .word SDIO_IRQHandler // SDIO + .word TMR5_IRQHandler // TMR5 + .word SPI3_IRQHandler // SPI3 + .word UART4_IRQHandler // UART4 + .word UART5_IRQHandler // UART5 + .word TMR6_IRQHandler // TMR6 + .word TMR7_IRQHandler // TMR7 + .word DMA2_Channel1_IRQHandler // DMA2 Channel1 + .word DMA2_Channel2_IRQHandler // DMA2 Channel2 + .word DMA2_Channel3_IRQHandler // DMA2 Channel3 + .word DMA2_Channel4_5_IRQHandler // DMA2 Channel4 & Channel5 + .word 0 // Reserved + .word USBD2_HP_CAN2_TX_IRQHandler // USBD2 High Priority or CAN2 TX + .word USBD2_LP_CAN2_RX0_IRQHandler // USBD2 Low Priority or CAN2 RX0 + .word CAN2_RX1_IRQHandler // CAN2 RX1 + .word CAN2_SCE_IRQHandler // CAN2 SCE + +// Default exception/interrupt handler + + .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 WWDT_IRQHandler + .thumb_set WWDT_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMPER_IRQHandler + .thumb_set TAMPER_IRQHandler,Default_Handler + + .weak RTC_IRQHandler + .thumb_set RTC_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCM_IRQHandler + .thumb_set RCM_IRQHandler,Default_Handler + + .weak EINT0_IRQHandler + .thumb_set EINT0_IRQHandler,Default_Handler + + .weak EINT1_IRQHandler + .thumb_set EINT1_IRQHandler,Default_Handler + + .weak EINT2_IRQHandler + .thumb_set EINT2_IRQHandler,Default_Handler + + .weak EINT3_IRQHandler + .thumb_set EINT3_IRQHandler,Default_Handler + + .weak EINT4_IRQHandler + .thumb_set EINT4_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 USBD1_HP_CAN1_TX_IRQHandler + .thumb_set USBD1_HP_CAN1_TX_IRQHandler,Default_Handler + + .weak USBD1_LP_CAN1_RX0_IRQHandler + .thumb_set USBD1_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 EINT9_5_IRQHandler + .thumb_set EINT9_5_IRQHandler,Default_Handler + + .weak TMR1_BRK_IRQHandler + .thumb_set TMR1_BRK_IRQHandler,Default_Handler + + .weak TMR1_UP_IRQHandler + .thumb_set TMR1_UP_IRQHandler,Default_Handler + + .weak TMR1_TRG_COM_IRQHandler + .thumb_set TMR1_TRG_COM_IRQHandler,Default_Handler + + .weak TMR1_CC_IRQHandler + .thumb_set TMR1_CC_IRQHandler,Default_Handler + + .weak TMR2_IRQHandler + .thumb_set TMR2_IRQHandler,Default_Handler + + .weak TMR3_IRQHandler + .thumb_set TMR3_IRQHandler,Default_Handler + + .weak TMR4_IRQHandler + .thumb_set TMR4_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 EINT15_10_IRQHandler + .thumb_set EINT15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak USBDWakeUp_IRQHandler + .thumb_set USBDWakeUp_IRQHandler,Default_Handler + + .weak TMR8_BRK_IRQHandler + .thumb_set TMR8_BRK_IRQHandler,Default_Handler + + .weak TMR8_UP_IRQHandler + .thumb_set TMR8_UP_IRQHandler,Default_Handler + + .weak TMR8_TRG_COM_IRQHandler + .thumb_set TMR8_TRG_COM_IRQHandler,Default_Handler + + .weak TMR8_CC_IRQHandler + .thumb_set TMR8_CC_IRQHandler,Default_Handler + + .weak ADC3_IRQHandler + .thumb_set ADC3_IRQHandler,Default_Handler + + .weak FSMC_IRQHandler + .thumb_set FSMC_IRQHandler,Default_Handler + + .weak SDIO_IRQHandler + .thumb_set SDIO_IRQHandler,Default_Handler + + .weak TMR5_IRQHandler + .thumb_set TMR5_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 TMR6_IRQHandler + .thumb_set TMR6_IRQHandler,Default_Handler + + .weak TMR7_IRQHandler + .thumb_set TMR7_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_5_IRQHandler + .thumb_set DMA2_Channel4_5_IRQHandler,Default_Handler + + .weak USBD2_HP_CAN2_TX_IRQHandler + .thumb_set USBD2_HP_CAN2_TX_IRQHandler,Default_Handler + + .weak USBD2_LP_CAN2_RX0_IRQHandler + .thumb_set USBD2_LP_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 - IRQ WWDT_IRQHandler - IRQ PVD_IRQHandler - IRQ TAMPER_IRQHandler - IRQ RTC_IRQHandler - IRQ FLASH_IRQHandler - IRQ RCM_IRQHandler - IRQ EINT0_IRQHandler - IRQ EINT1_IRQHandler - IRQ EINT2_IRQHandler - IRQ EINT3_IRQHandler - IRQ EINT4_IRQHandler - IRQ DMA1_Channel1_IRQHandler - IRQ DMA1_Channel2_IRQHandler - IRQ DMA1_Channel3_IRQHandler - IRQ DMA1_Channel4_IRQHandler - IRQ DMA1_Channel5_IRQHandler - IRQ DMA1_Channel6_IRQHandler - IRQ DMA1_Channel7_IRQHandler - IRQ ADC1_2_IRQHandler - IRQ USBD1_HP_CAN1_TX_IRQHandler - IRQ USBD1_LP_CAN1_RX0_IRQHandler - IRQ CAN1_RX1_IRQHandler - IRQ CAN1_SCE_IRQHandler - IRQ EINT9_5_IRQHandler - IRQ TMR1_BRK_IRQHandler - IRQ TMR1_UP_IRQHandler - IRQ TMR1_TRG_COM_IRQHandler - IRQ TMR1_CC_IRQHandler - IRQ TMR2_IRQHandler - IRQ TMR3_IRQHandler - IRQ TMR4_IRQHandler - IRQ I2C1_EV_IRQHandler - IRQ I2C1_ER_IRQHandler - IRQ I2C2_EV_IRQHandler - IRQ I2C2_ER_IRQHandler - IRQ SPI1_IRQHandler - IRQ SPI2_IRQHandler - IRQ USART1_IRQHandler - IRQ USART2_IRQHandler - IRQ USART3_IRQHandler - IRQ EINT15_10_IRQHandler - IRQ RTCAlarm_IRQHandler - IRQ USBDWakeUp_IRQHandler - IRQ TMR8_BRK_IRQHandler - IRQ TMR8_UP_IRQHandler - IRQ TMR8_TRG_COM_IRQHandler - IRQ TMR8_CC_IRQHandler - IRQ ADC3_IRQHandler - IRQ EMMC_IRQHandler - IRQ SDIO_IRQHandler - IRQ TMR5_IRQHandler - IRQ SPI3_IRQHandler - IRQ UART4_IRQHandler - IRQ UART5_IRQHandler - IRQ TMR6_IRQHandler - IRQ TMR7_IRQHandler - IRQ DMA2_Channel1_IRQHandler - IRQ DMA2_Channel2_IRQHandler - IRQ DMA2_Channel3_IRQHandler - IRQ DMA2_Channel4_5_IRQHandler - IRQ USBD2_HP_CAN2_TX_IRQHandler - IRQ USBD2_LP_CAN2_RX0_IRQHandler - IRQ CAN2_RX1_IRQHandler - IRQ CAN2_SCE_IRQHandler diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/startup_apm32f10x_md.s b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/startup_apm32f10x_md.s index 3bddc6ee7d..9bcbdf0269 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/startup_apm32f10x_md.s +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/gcc/startup_apm32f10x_md.s @@ -1,246 +1,327 @@ -;/*! -; * @file startup_apm32f10x_hd.s -; * -; * @brief CMSIS Cortex-M3 based Core Device Startup File for Device startup_apm32f10x_hd -; * -; * @version V1.0.0 -; * -; * @date 2022-01-05 -; * -; * @attention -; * -; * Copyright (C) 2020-2022 Geehy Semiconductor -; * -; * You may not use this file except in compliance with the -; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). -; * -; * The program is only for reference, which is distributed in the hope -; * that it will be usefull and instructional for customers to develop -; * their software. Unless required by applicable law or agreed to in -; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT -; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. -; * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions -; * and limitations under the License. -; */ +/*! + * @file startup_apm32f103_hd.S + * + * @brief CMSIS Cortex-M3 based Core Device Startup File for Device startup_apm32f103_hd + * + * @version V1.0.1 + * + * @date 2022-12-01 + * + * @attention + * + * Copyright (C) 2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be useful and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ -.syntax unified -.cpu cortex-m3 -.fpu softvfp -.thumb + .syntax unified + .cpu cortex-m3 + .fpu softvfp + .thumb -.global g_pfnVectors -.global Default_Handler +.global g_apm32_Vectors +.global Default_Handler - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object +.word _start_address_init_data +.word _start_address_data +.word _end_address_data +.word _start_address_bss +.word _end_address_bss -g_pfnVectors: - .word _estack // Top of Stack - .word Reset_Handler // Reset Handler - .word NMI_Handler // NMI Handler - .word HardFault_Handler // Hard Fault Handler - .word MemManage_Handler // MPU Fault Handler - .word BusFault_Handler // Bus Fault Handler - .word UsageFault_Handler // Usage Fault Handler - .word 0 // Reserved - .word 0 // Reserved - .word 0 // Reserved - .word 0 // Reserved - .word SVC_Handler // SVCall Handler - .word DebugMon_Handler // Debug Monitor Handler - .word 0 // Reserved - .word PendSV_Handler // PendSV Handler - .word SysTick_Handler // SysTick Handler - - // external interrupts handler - .word WWDT_IRQHandler // Window Watchdog - .word PVD_IRQHandler // PVD through EINT Line detect - .word TAMPER_IRQHandler // Tamper - .word RTC_IRQHandler // RTC - .word FLASH_IRQHandler // Flash - .word RCM_IRQHandler // RCM - .word EINT0_IRQHandler // EINT Line 0 - .word EINT1_IRQHandler // EINT Line 1 - .word EINT2_IRQHandler // EINT Line 2 - .word EINT3_IRQHandler // EINT Line 3 - .word EINT4_IRQHandler // EINT Line 4 - .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_2 - .word USBD1_HP_CAN1_TX_IRQHandler // USBD1 High Priority or CAN1 TX - .word USBD1_LP_CAN1_RX0_IRQHandler // USBD1 Low Priority or CAN1 RX0 - .word CAN1_RX1_IRQHandler // CAN1 RX1 - .word CAN1_SCE_IRQHandler // CAN1 SCE - .word EINT9_5_IRQHandler // EINT Line 9..5 - .word TMR1_BRK_IRQHandler // TMR1 Break - .word TMR1_UP_IRQHandler // TMR1 Update - .word TMR1_TRG_COM_IRQHandler // TMR1 Trigger and Commutation - .word TMR1_CC_IRQHandler // TMR1 Capture Compare - .word TMR2_IRQHandler // TMR2 - .word TMR3_IRQHandler // TMR3 - .word TMR4_IRQHandler // TMR4 - .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 EINT15_10_IRQHandler // EINT Line 15..10 - .word RTCAlarm_IRQHandler // RTC Alarm through EINT Line - .word USBDWakeUp_IRQHandler // USBD Wakeup from suspend - .word FPU_IRQHandler // FPU - .word QSPI_IRQHandler // QSPI - .word USBD2_HP_IRQHandler // USBD2 High Priority - .word USBD2_LP_IRQHandler // USBD2 Low Priority - - .size g_pfnVectors, .-g_pfnVectors - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +// Reset handler routine Reset_Handler: - ldr r1, =_sidata - ldr r2, =_sdata - ldr r3, =_edata - subs r3, r2 - ble fill_bss_start + ldr r0, =_start_address_data + ldr r1, =_end_address_data + ldr r2, =_start_address_init_data + movs r3, #0 + b L_loop0_0 -loop_copy_data: - subs r3, #4 - ldr r0, [r1,r3] - str r0, [r2,r3] - bgt loop_copy_data +L_loop0: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 -fill_bss_start: - ldr r1, =__bss_start - ldr r2, =__bss_end - movs r0, 0 - subs r2, r1 - ble startup_enter +L_loop0_0: + adds r4, r0, r3 + cmp r4, r1 + bcc L_loop0 + + ldr r2, =_start_address_bss + ldr r4, =_end_address_bss + movs r3, #0 + b L_loop1 -loop_fill_bss: - subs r2, #4 - str r0, [r1, r2] - bgt loop_fill_bss +L_loop2: + str r3, [r2] + adds r2, r2, #4 -startup_enter: - bl SystemInit - bl entry +L_loop1: + cmp r2, r4 + bcc L_loop2 - /* Exception Handlers */ - .weak NMI_Handler - .type NMI_Handler, %function -NMI_Handler: - b . - .size NMI_Handler, . - NMI_Handler + bl SystemInit + bl __libc_init_array + bl main + bx lr +.size Reset_Handler, .-Reset_Handler - .weak MemManage_Handler - .type MemManage_Handler, %function -MemManage_Handler: - b . - .size MemManage_Handler, . - MemManage_Handler - - .weak BusFault_Handler - .type BusFault_Handler, %function -BusFault_Handler: - b . - .size BusFault_Handler, . - BusFault_Handler - - .weak UsageFault_Handler - .type UsageFault_Handler, %function -UsageFault_Handler: - b . - .size UsageFault_Handler, . - UsageFault_Handler - - .weak SVC_Handler - .type SVC_Handler, %function -SVC_Handler: - b . - .size SVC_Handler, . - SVC_Handler - - .weak DebugMon_Handler - .type DebugMon_Handler, %function -DebugMon_Handler: - b . - .size DebugMon_Handler, . - DebugMon_Handler - - .weak PendSV_Handler - .type PendSV_Handler, %function -PendSV_Handler: - b . - .size PendSV_Handler, . - PendSV_Handler - - .weak SysTick_Handler - .type SysTick_Handler, %function -SysTick_Handler: - b . - .size SysTick_Handler, . - SysTick_Handler - - /* IQR Handler */ - .section .text.Default_Handler,"ax",%progbits - .type Default_Handler, %function +// This is the code that gets called when the processor receives an unexpected interrupt. + .section .text.Default_Handler,"ax",%progbits Default_Handler: - b . - .size Default_Handler, . - Default_Handler +L_Loop_infinite: + b L_Loop_infinite + .size Default_Handler, .-Default_Handler - .macro IRQ handler - .weak \handler - .set \handler, Default_Handler - .endm +// The minimal vector table for a Cortex M3. + .section .apm32_isr_vector,"a",%progbits + .type g_apm32_Vectors, %object + .size g_apm32_Vectors, .-g_apm32_Vectors - IRQ WWDT_IRQHandler - IRQ PVD_IRQHandler - IRQ TAMPER_IRQHandler - IRQ RTC_IRQHandler - IRQ FLASH_IRQHandler - IRQ RCM_IRQHandler - IRQ EINT0_IRQHandler - IRQ EINT1_IRQHandler - IRQ EINT2_IRQHandler - IRQ EINT3_IRQHandler - IRQ EINT4_IRQHandler - IRQ DMA1_Channel1_IRQHandler - IRQ DMA1_Channel2_IRQHandler - IRQ DMA1_Channel3_IRQHandler - IRQ DMA1_Channel4_IRQHandler - IRQ DMA1_Channel5_IRQHandler - IRQ DMA1_Channel6_IRQHandler - IRQ DMA1_Channel7_IRQHandler - IRQ ADC1_2_IRQHandler - IRQ USBD1_HP_CAN1_TX_IRQHandler - IRQ USBD1_LP_CAN1_RX0_IRQHandler - IRQ CAN1_RX1_IRQHandler - IRQ CAN1_SCE_IRQHandler - IRQ EINT9_5_IRQHandler - IRQ TMR1_BRK_IRQHandler - IRQ TMR1_UP_IRQHandler - IRQ TMR1_TRG_COM_IRQHandler - IRQ TMR1_CC_IRQHandler - IRQ TMR2_IRQHandler - IRQ TMR3_IRQHandler - IRQ TMR4_IRQHandler - IRQ I2C1_EV_IRQHandler - IRQ I2C1_ER_IRQHandler - IRQ I2C2_EV_IRQHandler - IRQ I2C2_ER_IRQHandler - IRQ SPI1_IRQHandler - IRQ SPI2_IRQHandler - IRQ USART1_IRQHandler - IRQ USART2_IRQHandler - IRQ USART3_IRQHandler - IRQ EINT15_10_IRQHandler - IRQ RTCAlarm_IRQHandler - IRQ USBDWakeUp_IRQHandler - IRQ FPU_IRQHandler - IRQ QSPI_IRQHandler - IRQ USBD2_HP_IRQHandler - IRQ USBD2_LP_IRQHandler +// Vector Table Mapped to Address 0 at Reset +g_apm32_Vectors: + + .word _end_stack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + .word WWDT_IRQHandler // Window Watchdog + .word PVD_IRQHandler // PVD through EINT Line detect + .word TAMPER_IRQHandler // Tamper + .word RTC_IRQHandler // RTC + .word FLASH_IRQHandler // Flash + .word RCM_IRQHandler // RCM + .word EINT0_IRQHandler // EINT Line 0 + .word EINT1_IRQHandler // EINT Line 1 + .word EINT2_IRQHandler // EINT Line 2 + .word EINT3_IRQHandler // EINT Line 3 + .word EINT4_IRQHandler // EINT Line 4 + .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_2 + .word USBD1_HP_CAN1_TX_IRQHandler // USBD1 High Priority or CAN1 TX + .word USBD1_LP_CAN1_RX0_IRQHandler // USBD1 Low Priority or CAN1 RX0 + .word CAN1_RX1_IRQHandler // CAN1 RX1 + .word CAN1_SCE_IRQHandler // CAN1 SCE + .word EINT9_5_IRQHandler // EINT Line 9..5 + .word TMR1_BRK_IRQHandler // TMR1 Break + .word TMR1_UP_IRQHandler // TMR1 Update + .word TMR1_TRG_COM_IRQHandler // TMR1 Trigger and Commutation + .word TMR1_CC_IRQHandler // TMR1 Capture Compare + .word TMR2_IRQHandler // TMR2 + .word TMR3_IRQHandler // TMR3 + .word TMR4_IRQHandler // TMR4 + .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 EINT15_10_IRQHandler // EINT Line 15..10 + .word RTC_Alarm_IRQHandler // RTC Alarm through EINT Line + .word USBDWakeUp_IRQHandler // USBD Wakeup from suspend + .word FPU_IRQHandler // FPU + .word QSPI_IRQHandler // QSPI + .word USBD2_HP_IRQHandler // USBD2 High Priority + .word USBD2_LP_IRQHandler // USBD2 Low Priority +// Default exception/interrupt handler + + .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 WWDT_IRQHandler + .thumb_set WWDT_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMPER_IRQHandler + .thumb_set TAMPER_IRQHandler,Default_Handler + + .weak RTC_IRQHandler + .thumb_set RTC_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCM_IRQHandler + .thumb_set RCM_IRQHandler,Default_Handler + + .weak EINT0_IRQHandler + .thumb_set EINT0_IRQHandler,Default_Handler + + .weak EINT1_IRQHandler + .thumb_set EINT1_IRQHandler,Default_Handler + + .weak EINT2_IRQHandler + .thumb_set EINT2_IRQHandler,Default_Handler + + .weak EINT3_IRQHandler + .thumb_set EINT3_IRQHandler,Default_Handler + + .weak EINT4_IRQHandler + .thumb_set EINT4_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 USBD1_HP_CAN1_TX_IRQHandler + .thumb_set USBD1_HP_CAN1_TX_IRQHandler,Default_Handler + + .weak USBD1_LP_CAN1_RX0_IRQHandler + .thumb_set USBD1_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 EINT9_5_IRQHandler + .thumb_set EINT9_5_IRQHandler,Default_Handler + + .weak TMR1_BRK_IRQHandler + .thumb_set TMR1_BRK_IRQHandler,Default_Handler + + .weak TMR1_UP_IRQHandler + .thumb_set TMR1_UP_IRQHandler,Default_Handler + + .weak TMR1_TRG_COM_IRQHandler + .thumb_set TMR1_TRG_COM_IRQHandler,Default_Handler + + .weak TMR1_CC_IRQHandler + .thumb_set TMR1_CC_IRQHandler,Default_Handler + + .weak TMR2_IRQHandler + .thumb_set TMR2_IRQHandler,Default_Handler + + .weak TMR3_IRQHandler + .thumb_set TMR3_IRQHandler,Default_Handler + + .weak TMR4_IRQHandler + .thumb_set TMR4_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 EINT15_10_IRQHandler + .thumb_set EINT15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak USBDWakeUp_IRQHandler + .thumb_set USBDWakeUp_IRQHandler,Default_Handler + + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler + + .weak QSPI_IRQHandler + .thumb_set QSPI_IRQHandler,Default_Handler + + .weak USBD2_HP_IRQHandler + .thumb_set USBD2_HP_IRQHandler,Default_Handler + + .weak USBD2_LP_IRQHandler + .thumb_set USBD2_LP_IRQHandler,Default_Handler diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/iar/startup_apm32f10x_cl.s b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/iar/startup_apm32f10x_cl.s new file mode 100644 index 0000000000..86ee43329b --- /dev/null +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/iar/startup_apm32f10x_cl.s @@ -0,0 +1,492 @@ +;/*! +; * @file startup_apm32f10x_cl.s +; * +; * @brief CMSIS Cortex-M3 based Core Device Startup File for Device APM32F103 +; * +; * @version V1.0.0 +; * +; * @date 2022-07-25 +; * +; * @attention +; * +; * Copyright (C) 2020-2022 Geehy Semiconductor +; * +; * You may not use this file except in compliance with the +; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). +; * +; * The program is only for reference, which is distributed in the hope +; * that it will be useful and instructional for customers to develop +; * their software. Unless required by applicable law or agreed to in +; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT +; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. +; * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions +; * and limitations under the License. +; */ + + 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 WWDT_IRQHandler ; Window Watchdog + DCD PVD_IRQHandler ; PVD through EINT Line detect + DCD TAMPER_IRQHandler ; Tamper + DCD RTC_IRQHandler ; RTC + DCD FLASH_IRQHandler ; Flash + DCD RCM_IRQHandler ; RCM + DCD EINT0_IRQHandler ; EINT Line 0 + DCD EINT1_IRQHandler ; EINT Line 1 + DCD EINT2_IRQHandler ; EINT Line 2 + DCD EINT3_IRQHandler ; EINT Line 3 + DCD EINT4_IRQHandler ; EINT 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 CAN1_TX_IRQHandler ; CAN1 TX + DCD CAN1_RX0_IRQHandler ; CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; CAN1 RX1 + DCD CAN1_SCE_IRQHandler ; CAN1 SCE + DCD EINT9_5_IRQHandler ; EINT Line 9..5 + DCD TMR1_BRK_IRQHandler ; TMR1 Break + DCD TMR1_UP_IRQHandler ; TMR1 Update + DCD TMR1_TRG_COM_IRQHandler ; TMR1 Trigger and Commutation + DCD TMR1_CC_IRQHandler ; TMR1 Capture Compare + DCD TMR2_IRQHandler ; TMR2 + DCD TMR3_IRQHandler ; TMR3 + DCD TMR4_IRQHandler ; TMR4 + 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 EINT15_10_IRQHandler ; EINT Line 15..10 + DCD RTCAlarm_IRQHandler ; RTC Alarm through EINT Line + DCD OTG_FS_WKUP_IRQHandler ; USBD Wakeup from suspend + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD TMR5_IRQHandler ; TMR5 + DCD SPI3_IRQHandler ; SPI3 + DCD UART4_IRQHandler ; UART4 + DCD UART5_IRQHandler ; UART5 + DCD TMR6_IRQHandler ; TMR6 + DCD TMR7_IRQHandler ; TMR7 + 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 ; ETH + DCD ETH_WKUP_IRQHandler ; ETH Wake up + 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 OTG_FS_IRQHandler ; OTG FS +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; 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 WWDT_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +WWDT_IRQHandler + B WWDT_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_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FLASH_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +FLASH_IRQHandler + B FLASH_IRQHandler + + PUBWEAK RCM_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +RCM_IRQHandler + B RCM_IRQHandler + + PUBWEAK EINT0_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +EINT0_IRQHandler + B EINT0_IRQHandler + + PUBWEAK EINT1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +EINT1_IRQHandler + B EINT1_IRQHandler + + PUBWEAK EINT2_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +EINT2_IRQHandler + B EINT2_IRQHandler + + PUBWEAK EINT3_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +EINT3_IRQHandler + B EINT3_IRQHandler + + PUBWEAK EINT4_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +EINT4_IRQHandler + B EINT4_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 CAN1_TX_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +CAN1_TX_IRQHandler + B CAN1_TX_IRQHandler + + PUBWEAK CAN1_RX0_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +CAN1_RX0_IRQHandler + B 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 EINT9_5_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +EINT9_5_IRQHandler + B EINT9_5_IRQHandler + + PUBWEAK TMR1_BRK_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TMR1_BRK_IRQHandler + B TMR1_BRK_IRQHandler + + PUBWEAK TMR1_UP_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TMR1_UP_IRQHandler + B TMR1_UP_IRQHandler + + PUBWEAK TMR1_TRG_COM_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TMR1_TRG_COM_IRQHandler + B TMR1_TRG_COM_IRQHandler + + PUBWEAK TMR1_CC_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TMR1_CC_IRQHandler + B TMR1_CC_IRQHandler + + PUBWEAK TMR2_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TMR2_IRQHandler + B TMR2_IRQHandler + + PUBWEAK TMR3_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TMR3_IRQHandler + B TMR3_IRQHandler + + PUBWEAK TMR4_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TMR4_IRQHandler + B TMR4_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 EINT15_10_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +EINT15_10_IRQHandler + B EINT15_10_IRQHandler + + PUBWEAK RTCAlarm_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +RTCAlarm_IRQHandler + B RTCAlarm_IRQHandler + + PUBWEAK OTG_FS_WKUP_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +OTG_FS_WKUP_IRQHandler + B OTG_FS_WKUP_IRQHandler + + PUBWEAK TMR5_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TMR5_IRQHandler + B TMR5_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 TMR6_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TMR6_IRQHandler + B TMR6_IRQHandler + + PUBWEAK TMR7_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +TMR7_IRQHandler + B TMR7_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 OTG_FS_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +OTG_FS_IRQHandler + B OTG_FS_IRQHandler + + END + diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/iar/startup_apm32f10x_hd.s b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/iar/startup_apm32f10x_hd.s index 4c0a8fa9b0..a038553107 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/iar/startup_apm32f10x_hd.s +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/iar/startup_apm32f10x_hd.s @@ -5,7 +5,7 @@ ; * ; * @version V1.0.0 ; * -; * @date 2022-01-05 +; * @date 2022-07-25 ; * ; * @attention ; * @@ -15,7 +15,7 @@ ; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). ; * ; * The program is only for reference, which is distributed in the hope -; * that it will be usefull and instructional for customers to develop +; * that it will be useful and instructional for customers to develop ; * their software. Unless required by applicable law or agreed to in ; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT ; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/iar/startup_apm32f10x_md.s b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/iar/startup_apm32f10x_md.s index 8028032f16..5d18204679 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/iar/startup_apm32f10x_md.s +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/iar/startup_apm32f10x_md.s @@ -5,7 +5,7 @@ ; * ; * @version V1.0.0 ; * -; * @date 2022-01-05 +; * @date 2022-07-25 ; * ; * @attention ; * @@ -15,7 +15,7 @@ ; * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). ; * ; * The program is only for reference, which is distributed in the hope -; * that it will be usefull and instructional for customers to develop +; * that it will be useful and instructional for customers to develop ; * their software. Unless required by applicable law or agreed to in ; * writing, the program is distributed on an "AS IS" BASIS, WITHOUT ; * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/system_apm32f10x.c b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/system_apm32f10x.c index 2fae0cb90a..671e6710c0 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/system_apm32f10x.c +++ b/bsp/apm32/libraries/APM32F10x_Library/Device/Geehy/APM32F10x/Source/system_apm32f10x.c @@ -3,9 +3,9 @@ * * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Source File * - * @version V1.0.2 + * @version V1.0.4 * - * @date 2022-01-05 + * @date 2022-12-01 * * @attention * @@ -15,7 +15,7 @@ * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope - * that it will be usefull and instructional for customers to develop + * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,12 +23,21 @@ * and limitations under the License. */ +/*Includes*/ #include "apm32f10x.h" -/***************************************************************** - * If SYSCLK source is PLL,SystemCoreClock will contain the * - * HSE_VALUE or HSI_VALUE multiplied/divided by the PLL factors. * -******************************************************************/ +/** @addtogroup CMSIS + @{ +*/ + +/** @addtogroup APM32F10x_System + * @brief APM32F10x system configuration + @{ +*/ + +/** @defgroup System_Macros + @{ +*/ //#define SYSTEM_CLOCK_HSE HSE_VALUE //#define SYSTEM_CLOCK_24MHz (24000000) @@ -38,10 +47,15 @@ #define SYSTEM_CLOCK_72MHz (72000000) //#define SYSTEM_CLOCK_96MHz (96000000) - -/** #define VECT_TAB_SRAM */ +/* #define VECT_TAB_SRAM */ #define VECT_TAB_OFFSET 0x00 +/**@} end of group System_Macros*/ + +/** @defgroup System_Variables + @{ +*/ + #ifdef SYSTEM_CLOCK_HSE uint32_t SystemCoreClock = SYSTEM_CLOCK_HSE; #elif defined SYSTEM_CLOCK_24MHz @@ -58,6 +72,11 @@ uint32_t SystemCoreClock = SYSTEM_CLOCK_96MHz; #endif +/**@} end of group System_Variables */ + +/** @defgroup System_Functions + @{ +*/ static void SystemClockConfig(void); @@ -87,18 +106,34 @@ static void SystemClockConfig(void); */ void SystemInit(void) { - /** Set HSIEN bit */ + /* Set HSIEN bit */ RCM->CTRL_B.HSIEN = BIT_SET; - /** Reset SCLKSEL, AHBPSC, APB1PSC, APB2PSC, ADCPSC and MCOSEL bits */ - RCM->CFG &= (uint32_t)0xF8FF0000; - /** Reset HSEEN, CSSEN and PLLEN bits */ - RCM->CTRL &= (uint32_t)0xFEF6FFFF; - /** Reset HSEBCFG bit */ + +#ifdef APM32F10X_CL + RCM->CFG &= (uint32_t) 0xF0FF0000; +#else + /* Reset SCLKSEL, AHBPSC, APB1PSC, APB2PSC, ADCPSC and MCOSEL bits */ + RCM->CFG &= (uint32_t) 0xF8FF0000; +#endif /* APM32F10X_CL */ + + /* Reset HSEEN, CSSEN and PLLEN bits */ + RCM->CTRL &= (uint32_t) 0xFEF6FFFF; + /* Reset HSEBCFG bit */ RCM->CTRL_B.HSEBCFG = BIT_RESET; - /** Reset PLLSRCSEL, PLLHSEPSC, PLLMULCFG and USBDIV bits */ - RCM->CFG &= (uint32_t)0xFF80FFFF; - /** Disable all interrupts and clear pending bits */ + /* Reset PLLSRCSEL, PLLHSEPSC, PLLMULCFG and USBDIV bits */ + RCM->CFG &= (uint32_t) 0xFF80FFFF; + +#ifdef APM32F10X_CL + /* Reset PLL2ON and PLL3ON bits */ + RCM->CTRL &= (uint32_t) 0xEBFFFFFF; + /* Disable all interrupts and clear pending bits */ + RCM->INT = 0x00FF0000; + /* Reset CFG2 register */ + RCM->CFG2 = 0x00000000; +#else + /* Disable all interrupts and clear pending bits */ RCM->INT = 0x009F0000; +#endif /* APM32F10X_CL */ SystemClockConfig(); @@ -120,53 +155,98 @@ void SystemInit(void) */ void SystemCoreClockUpdate(void) { - uint32_t sysClock, pllMull, pllSource, Prescaler; - uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; +#ifdef APM32F10X_CL + uint32_t sysClock, pllMull, pllSource, pll2Mull, pllPsc1, pllPsc2; +#else + uint32_t sysClock, pllMull, pllSource; +#endif - sysClock = RCM->CFG_B.SCLKSELSTS; + /* get sys clock */ + sysClock = RCM->CFG_B.SCLKSEL; switch (sysClock) { - /** sys clock is HSI */ - case 0: - SystemCoreClock = HSI_VALUE; - break; + /* sys clock is HSI */ + case 0: + sysClock = HSI_VALUE; + break; - /** sys clock is HSE */ - case 1: - SystemCoreClock = HSE_VALUE; - break; + /* sys clock is HSE */ + case 1: + sysClock = HSE_VALUE; + break; - /** sys clock is PLL */ - case 2: - pllMull = RCM->CFG_B.PLLMULCFG + 2; - pllSource = RCM->CFG_B.PLLSRCSEL; + /* sys clock is PLL */ + case 2: +#ifdef APM32F10X_CL + /* NOTE : PLL is the same as PLL1 */ + pllSource = RCM->CFG_B.PLL1SRCSEL; - /** PLL entry clock source is HSE */ - if (pllSource == BIT_SET) - { - SystemCoreClock = HSE_VALUE * pllMull; - - /** HSE clock divided by 2 */ - if (pllSource == RCM->CFG_B.PLLHSEPSC) + /* PLL entry clock source is HSE */ + if (pllSource) { - SystemCoreClock >>= 1; - } - } - /** PLL entry clock source is HSI/2 */ - else - { - SystemCoreClock = (HSI_VALUE >> 1) * pllMull; - } - break; + /* PLLPSC1 prescaler factor */ + pllPsc1 = (RCM->CFG2_B.PLLPSC1 + 1); - default: - SystemCoreClock = HSI_VALUE; - break; + /* PLL entry clock source is PLL2 */ + if (RCM->CFG2_B.PLLPSC1SRC) + { + pll2Mull = (RCM->CFG2_B.PLL2MUL != 15) ? (RCM->CFG2_B.PLL2MUL + 2) : 20; + pllPsc2 = RCM->CFG2_B.PLLPSC2 + 1; + + pllSource = ((HSE_VALUE / pllPsc2) * pll2Mull) / pllPsc1; + } + /* PLL entry clock source is HSE */ + else + { + pllSource = HSE_VALUE / pllPsc1; + } + } + /* PLL entry clock source is HSI/2 */ + else + { + pllSource = HSI_VALUE >> 1; + } + + pllMull = RCM->CFG_B.PLL1MULCFG; + if (pllMull == 13) + { + /* For 6.5 multiplication factor */ + sysClock = pllSource * pllMull / 2; + } + else + { + sysClock = pllSource * (pllMull + 2); + } +#else + pllMull = RCM->CFG_B.PLL1MULCFG + 2; + pllSource = RCM->CFG_B.PLL1SRCSEL; + + /* PLL entry clock source is HSE */ + if (pllSource == BIT_SET) + { + sysClock = HSE_VALUE * pllMull; + + /* HSE clock divided by 2 */ + if (pllSource == RCM->CFG_B.PLLHSEPSC) + { + sysClock >>= 1; + } + } + /* PLL entry clock source is HSI/2 */ + else + { + sysClock = (HSI_VALUE >> 1) * pllMull; + } +#endif + break; + + default: + sysClock = HSI_VALUE; + break; } - Prescaler = AHBPrescTable[RCM->CFG_B.AHBPSC]; - SystemCoreClock >>= Prescaler; + SystemCoreClock = sysClock; } /*! @@ -221,27 +301,42 @@ static void SystemClockHSE(void) if (RCM->CTRL_B.HSERDYFLG) { - /** Enable Prefetch Buffer */ + /* Enable Prefetch Buffer */ FMC->CTRL1_B.PBEN = BIT_SET; - /** Flash 0 wait state */ - FMC->CTRL1_B.WS = 0; - /** HCLK = SYSCLK */ +#ifdef APM32F10X_CL + + if (HSE_VALUE <= 24000000) + { + /* Flash 0 wait state */ + FMC->CTRL1_B.WS = 0; + } + else + { + /* Flash 1 wait state */ + FMC->CTRL1_B.WS = 1; + } + +#else + /* Flash 0 wait state */ + FMC->CTRL1_B.WS = 0; +#endif /* APM32F10X_CL */ + + /* HCLK = SYSCLK */ RCM->CFG_B.AHBPSC = 0X00; - /** PCLK2 = HCLK */ + /* PCLK2 = HCLK */ RCM->CFG_B.APB2PSC = 0; - /** PCLK1 = HCLK */ + /* PCLK1 = HCLK */ RCM->CFG_B.APB1PSC = 0; - /** Select HSE as system clock source */ + /* Select HSE as system clock source */ RCM->CFG_B.SCLKSEL = 1; - /** Wait till HSE is used as system clock source */ + /* Wait till HSE is used as system clock source */ while (RCM->CFG_B.SCLKSELSTS != 0x01); } } - #elif defined SYSTEM_CLOCK_24MHz /*! * @brief Sets System clock frequency to 24MHz and configure HCLK, PCLK2 and PCLK1 prescalers @@ -267,31 +362,53 @@ static void SystemClock24M(void) if (RCM->CTRL_B.HSERDYFLG) { - /** Enable Prefetch Buffer */ + /* Enable Prefetch Buffer */ FMC->CTRL1_B.PBEN = BIT_SET; - /** Flash 0 wait state */ + /* Flash 0 wait state */ FMC->CTRL1_B.WS = 0; - /** HCLK = SYSCLK */ + /* HCLK = SYSCLK */ RCM->CFG_B.AHBPSC = 0X00; - /** PCLK2 = HCLK */ + /* PCLK2 = HCLK */ RCM->CFG_B.APB2PSC = 0; - /** PCLK1 = HCLK */ + /* PCLK1 = HCLK */ RCM->CFG_B.APB1PSC = 0; - /** PLL: (HSE / 2) * 6 */ - RCM->CFG_B.PLLSRCSEL = 1; +#ifdef APM32F10X_CL + /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz (HSE is 25MHz for APM32F10X_CL) */ + /* PLL configuration: PLLCLK = (PLL2 / 10) * 6 = 24 MHz */ + + RCM->CFG2_B.PLLPSC2 = 4; + RCM->CFG2_B.PLL2MUL = 0x06; + + RCM->CFG2_B.PLLPSC1SRC = 1; + RCM->CFG2_B.PLLPSC1 = 9; + + /* Enable PLL2 */ + RCM->CTRL_B.PLL2EN = 1; + /* Wait till PLL2 is ready */ + while (RCM->CTRL_B.PLL2RDYFLG == BIT_RESET); + + RCM->CFG_B.PLL1SRCSEL = 1; + RCM->CFG_B.PLL1MULCFG = 4; +#else + /* PLL configuration: PLLCLK = (HSE / 2) * 6 = 24 MHz */ + /* PLL: (HSE / 2) * 6 */ + RCM->CFG_B.PLL1SRCSEL = 1; RCM->CFG_B.PLLHSEPSC = 1; - RCM->CFG_B.PLLMULCFG = 4; + RCM->CFG_B.PLL1MULCFG = 4; +#endif /* APM32F10X_CL */ - /** Enable PLL */ - RCM->CTRL_B.PLLEN = 1; - /** Wait PLL Ready */ - while (RCM->CTRL_B.PLLRDYFLG == BIT_RESET); + /* Enable PLL */ + RCM->CTRL_B.PLL1EN = 1; - /** Select PLL as system clock source */ + /* Wait PLL Ready */ + while (RCM->CTRL_B.PLL1RDYFLG == BIT_RESET); + + /* Select PLL as system clock source */ RCM->CFG_B.SCLKSEL = 2; - /** Wait till PLL is used as system clock source */ + + /* Wait till PLL is used as system clock source */ while (RCM->CFG_B.SCLKSELSTS != 0x02); } } @@ -321,31 +438,53 @@ static void SystemClock36M(void) if (RCM->CTRL_B.HSERDYFLG) { - /** Enable Prefetch Buffer */ + /* Enable Prefetch Buffer */ FMC->CTRL1_B.PBEN = BIT_SET; - /** Flash 1 wait state */ + /* Flash 1 wait state */ FMC->CTRL1_B.WS = 1; - /** HCLK = SYSCLK */ + /* HCLK = SYSCLK */ RCM->CFG_B.AHBPSC = 0X00; - /** PCLK2 = HCLK */ + /* PCLK2 = HCLK */ RCM->CFG_B.APB2PSC = 0; - /** PCLK1 = HCLK */ + /* PCLK1 = HCLK */ RCM->CFG_B.APB1PSC = 0; - /** PLL: (HSE / 2) * 9 */ - RCM->CFG_B.PLLSRCSEL = 1; +#ifdef APM32F10X_CL + /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz (HSE is 25MHz for APM32F10X_CL) */ + /* PLL configuration: PLLCLK = (PLL2 / 10) * 9 = 36 MHz */ + + RCM->CFG2_B.PLLPSC2 = 4; + RCM->CFG2_B.PLL2MUL = 0x06; + + RCM->CFG2_B.PLLPSC1SRC = 1; + RCM->CFG2_B.PLLPSC1 = 9; + + /* Enable PLL2 */ + RCM->CTRL_B.PLL2EN = 1; + /* Wait till PLL2 is ready */ + while (RCM->CTRL_B.PLL2RDYFLG == BIT_RESET); + + RCM->CFG_B.PLL1SRCSEL = 1; + RCM->CFG_B.PLL1MULCFG = 7; +#else + /* PLL configuration: PLLCLK = (HSE / 2) * 9 = 36 MHz */ + /* PLL: (HSE / 2) * 9 */ + RCM->CFG_B.PLL1SRCSEL = 1; RCM->CFG_B.PLLHSEPSC = 1; - RCM->CFG_B.PLLMULCFG = 7; + RCM->CFG_B.PLL1MULCFG = 7; +#endif - /** Enable PLL */ - RCM->CTRL_B.PLLEN = 1; - /** Wait PLL Ready */ - while (RCM->CTRL_B.PLLRDYFLG == BIT_RESET); + /* Enable PLL */ + RCM->CTRL_B.PLL1EN = 1; - /** Select PLL as system clock source */ + /* Wait PLL Ready */ + while (RCM->CTRL_B.PLL1RDYFLG == BIT_RESET); + + /* Select PLL as system clock source */ RCM->CFG_B.SCLKSEL = 2; - /** Wait till PLL is used as system clock source */ + + /* Wait till PLL is used as system clock source */ while (RCM->CFG_B.SCLKSELSTS != 0x02); } } @@ -375,30 +514,51 @@ static void SystemClock48M(void) if (RCM->CTRL_B.HSERDYFLG) { - /** Enable Prefetch Buffer */ + /* Enable Prefetch Buffer */ FMC->CTRL1_B.PBEN = BIT_SET; - /** Flash 1 wait state */ + /* Flash 1 wait state */ FMC->CTRL1_B.WS = 1; - /** HCLK = SYSCLK */ + /* HCLK = SYSCLK */ RCM->CFG_B.AHBPSC = 0X00; - /** PCLK2 = HCLK */ + /* PCLK2 = HCLK */ RCM->CFG_B.APB2PSC = 0; - /** PCLK1 = HCLK / 2 */ + /* PCLK1 = HCLK / 2 */ RCM->CFG_B.APB1PSC = 4; - /** PLL: HSE * 6 */ - RCM->CFG_B.PLLSRCSEL = 1; - RCM->CFG_B.PLLMULCFG = 4; +#ifdef APM32F10X_CL + /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz (HSE is 25MHz for APM32F10X_CL) */ + /* PLL configuration: PLLCLK = (PLL2 / 5) * 6 = 48 MHz */ - /** Enable PLL */ - RCM->CTRL_B.PLLEN = 1; - /** Wait PLL Ready */ - while (RCM->CTRL_B.PLLRDYFLG == BIT_RESET); + RCM->CFG2_B.PLLPSC2 = 4; + RCM->CFG2_B.PLL2MUL = 0x06; - /** Select PLL as system clock source */ + RCM->CFG2_B.PLLPSC1SRC = 1; + RCM->CFG2_B.PLLPSC1 = 0x4; + + /* Enable PLL2 */ + RCM->CTRL_B.PLL2EN = 1; + /* Wait till PLL2 is ready */ + while (RCM->CTRL_B.PLL2RDYFLG == BIT_RESET); + + RCM->CFG_B.PLL1SRCSEL = 1; + RCM->CFG_B.PLL1MULCFG = 4; +#else + /* PLL: HSE * 6 */ + RCM->CFG_B.PLL1SRCSEL = 1; + RCM->CFG_B.PLL1MULCFG = 4; +#endif + + /* Enable PLL */ + RCM->CTRL_B.PLL1EN = 1; + + /* Wait PLL Ready */ + while (RCM->CTRL_B.PLL1RDYFLG == BIT_RESET); + + /* Select PLL as system clock source */ RCM->CFG_B.SCLKSEL = 2; - /** Wait till PLL is used as system clock source */ + + /* Wait till PLL is used as system clock source */ while (RCM->CFG_B.SCLKSELSTS != 0x02); } } @@ -428,30 +588,51 @@ static void SystemClock56M(void) if (RCM->CTRL_B.HSERDYFLG) { - /** Enable Prefetch Buffer */ + /* Enable Prefetch Buffer */ FMC->CTRL1_B.PBEN = BIT_SET; - /** Flash 2 wait state */ + /* Flash 2 wait state */ FMC->CTRL1_B.WS = 2; - /** HCLK = SYSCLK */ + /* HCLK = SYSCLK */ RCM->CFG_B.AHBPSC = 0X00; - /** PCLK2 = HCLK */ + /* PCLK2 = HCLK */ RCM->CFG_B.APB2PSC = 0; - /** PCLK1 = HCLK / 2 */ + /* PCLK1 = HCLK / 2 */ RCM->CFG_B.APB1PSC = 4; - /** PLL: HSE * 7 */ - RCM->CFG_B.PLLSRCSEL = 1; - RCM->CFG_B.PLLMULCFG = 5; +#ifdef APM32F10X_CL + /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz (HSE is 25MHz for APM32F10X_CL) */ + /* PLL configuration: PLLCLK = (PLL2 / 5) * 7 = 56 MHz */ - /** Enable PLL */ - RCM->CTRL_B.PLLEN = 1; - /** Wait PLL Ready */ - while (RCM->CTRL_B.PLLRDYFLG == BIT_RESET); + RCM->CFG2_B.PLLPSC2 = 4; + RCM->CFG2_B.PLL2MUL = 0x06; - /** Select PLL as system clock source */ + RCM->CFG2_B.PLLPSC1SRC = 1; + RCM->CFG2_B.PLLPSC1 = 0x4; + + /* Enable PLL2 */ + RCM->CTRL_B.PLL2EN = 1; + /* Wait till PLL2 is ready */ + while (RCM->CTRL_B.PLL2RDYFLG == BIT_RESET); + + RCM->CFG_B.PLL1SRCSEL = 1; + RCM->CFG_B.PLL1MULCFG = 5; +#else + /* PLL: HSE * 7 */ + RCM->CFG_B.PLL1SRCSEL = 1; + RCM->CFG_B.PLL1MULCFG = 5; +#endif + + /* Enable PLL */ + RCM->CTRL_B.PLL1EN = 1; + + /* Wait PLL Ready */ + while (RCM->CTRL_B.PLL1RDYFLG == BIT_RESET); + + /* Select PLL as system clock source */ RCM->CFG_B.SCLKSEL = 2; - /** Wait till PLL is used as system clock source */ + + /* Wait till PLL is used as system clock source */ while (RCM->CFG_B.SCLKSELSTS != 0x02); } } @@ -481,30 +662,51 @@ static void SystemClock72M(void) if (RCM->CTRL_B.HSERDYFLG) { - /** Enable Prefetch Buffer */ + /* Enable Prefetch Buffer */ FMC->CTRL1_B.PBEN = BIT_SET; - /** Flash 2 wait state */ + /* Flash 2 wait state */ FMC->CTRL1_B.WS = 2; - /** HCLK = SYSCLK */ + /* HCLK = SYSCLK */ RCM->CFG_B.AHBPSC = 0X00; - /** PCLK2 = HCLK */ + /* PCLK2 = HCLK */ RCM->CFG_B.APB2PSC = 0; - /** PCLK1 = HCLK / 2 */ + /* PCLK1 = HCLK / 2 */ RCM->CFG_B.APB1PSC = 4; - /** PLL: HSE * 9 */ - RCM->CFG_B.PLLSRCSEL = 1; - RCM->CFG_B.PLLMULCFG = 7; +#ifdef APM32F10X_CL + /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz (HSE is 25MHz for APM32F10X_CL) */ + /* PLL configuration: PLLCLK = (PLL2 / 5) * 9 = 72 MHz */ - /** Enable PLL */ - RCM->CTRL_B.PLLEN = 1; - /** Wait PLL Ready */ - while (RCM->CTRL_B.PLLRDYFLG == BIT_RESET); + RCM->CFG2_B.PLLPSC2 = 4; + RCM->CFG2_B.PLL2MUL = 0x06; - /** Select PLL as system clock source */ + RCM->CFG2_B.PLLPSC1SRC = 1; + RCM->CFG2_B.PLLPSC1 = 0x4; + + /* Enable PLL2 */ + RCM->CTRL_B.PLL2EN = 1; + /* Wait till PLL2 is ready */ + while (RCM->CTRL_B.PLL2RDYFLG == BIT_RESET); + + RCM->CFG_B.PLL1SRCSEL = 1; + RCM->CFG_B.PLL1MULCFG = 7; +#else + /* PLL: HSE * 9 */ + RCM->CFG_B.PLL1SRCSEL = 1; + RCM->CFG_B.PLL1MULCFG = 7; +#endif + + /* Enable PLL */ + RCM->CTRL_B.PLL1EN = 1; + + /* Wait PLL Ready */ + while (RCM->CTRL_B.PLL1RDYFLG == BIT_RESET); + + /* Select PLL as system clock source */ RCM->CFG_B.SCLKSEL = 2; - /** Wait till PLL is used as system clock source */ + + /* Wait till PLL is used as system clock source */ while (RCM->CFG_B.SCLKSELSTS != 0x02); } @@ -535,32 +737,56 @@ static void SystemClock96M(void) if (RCM->CTRL_B.HSERDYFLG) { - /** Enable Prefetch Buffer */ + /* Enable Prefetch Buffer */ FMC->CTRL1_B.PBEN = BIT_SET; - /** Flash 3 wait state */ + /* Flash 3 wait state */ FMC->CTRL1_B.WS = 3; - /** HCLK = SYSCLK */ + /* HCLK = SYSCLK */ RCM->CFG_B.AHBPSC = 0X00; - /** PCLK2 = HCLK */ + /* PCLK2 = HCLK */ RCM->CFG_B.APB2PSC = 0; - /** PCLK1 = HCLK / 2 */ + /* PCLK1 = HCLK / 2 */ RCM->CFG_B.APB1PSC = 4; - /** PLL: HSE * 12 */ - RCM->CFG_B.PLLSRCSEL = 1; - RCM->CFG_B.PLLMULCFG = 10; +#ifdef APM32F10X_CL + /* PLL2 configuration: PLL2CLK = (HSE / 5) * 12 = 60 MHz (HSE is 25MHz for APM32F10X_CL) */ + /* PLL configuration: PLLCLK = (PLL2 / 5) * 8 = 96 MHz */ - /** Enable PLL */ - RCM->CTRL_B.PLLEN = 1; - /** Wait PLL Ready */ - while (RCM->CTRL_B.PLLRDYFLG == BIT_RESET); + RCM->CFG2_B.PLLPSC2 = 4; + RCM->CFG2_B.PLL2MUL = 10; - /** Select PLL as system clock source */ + RCM->CFG2_B.PLLPSC1SRC = 1; + RCM->CFG2_B.PLLPSC1 = 4; + + /* Enable PLL2 */ + RCM->CTRL_B.PLL2EN = 1; + /* Wait till PLL2 is ready */ + while (RCM->CTRL_B.PLL2RDYFLG == BIT_RESET); + + RCM->CFG_B.PLL1SRCSEL = 1; + RCM->CFG_B.PLL1MULCFG = 6; +#else + /* PLL: HSE * 12 */ + RCM->CFG_B.PLL1SRCSEL = 1; + RCM->CFG_B.PLL1MULCFG = 10; +#endif + + /* Enable PLL */ + RCM->CTRL_B.PLL1EN = 1; + + /* Wait PLL Ready */ + while (RCM->CTRL_B.PLL1RDYFLG == BIT_RESET); + + /* Select PLL as system clock source */ RCM->CFG_B.SCLKSEL = 2; - /** Wait till PLL is used as system clock source */ + + /* Wait till PLL is used as system clock source */ while (RCM->CFG_B.SCLKSELSTS != 0x02); } } #endif +/**@} end of group System_Functions */ +/**@} end of group APM32F10x_System */ +/**@} end of group CMSIS */ diff --git a/bsp/apm32/libraries/APM32F10x_Library/SConscript b/bsp/apm32/libraries/APM32F10x_Library/SConscript index a95e30d56a..022b665adc 100644 --- a/bsp/apm32/libraries/APM32F10x_Library/SConscript +++ b/bsp/apm32/libraries/APM32F10x_Library/SConscript @@ -35,9 +35,13 @@ if GetDepend(['RT_USING_WDT']): src += ['APM32F10x_StdPeriphDriver/src/apm32f10x_wwdt.c'] src += ['APM32F10x_StdPeriphDriver/src/apm32f10x_iwdt.c'] +if GetDepend(['BSP_USING_ETH']): + src += ['APM32F10x_ETH_Driver/src/apm32f10x_eth.c'] + path = [cwd + '/Device/Geehy/APM32F10x/Include', cwd + '/APM32F10x_StdPeriphDriver/inc', - cwd + '/CMSIS/Include'] + cwd + '/CMSIS/Include', + cwd + '/APM32F10x_ETH_Driver/inc'] CPPDEFINES = ['USE_STDPERIPH_DRIVER'] group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) diff --git a/bsp/apm32/libraries/APM32F4xx_Library/APM32F4xx_ETH_Driver/inc/apm32f4xx_eth.h b/bsp/apm32/libraries/APM32F4xx_Library/APM32F4xx_ETH_Driver/inc/apm32f4xx_eth.h new file mode 100644 index 0000000000..628f125e4c --- /dev/null +++ b/bsp/apm32/libraries/APM32F4xx_Library/APM32F4xx_ETH_Driver/inc/apm32f4xx_eth.h @@ -0,0 +1,1424 @@ +/*! + * @file apm32f4xx_eth.c + * + * @brief This file provides all the ETH firmware functions + * + * @version V1.0.2 + * + * @date 2022-06-23 + * + * @attention + * + * Copyright (C) 2021-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be usefull and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +/* Define to prevent recursive inclusion */ +#ifndef __APM32F4xx_ETH_H +#define __APM32F4xx_ETH_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes */ +#include "apm32f4xx.h" + +/** @addtogroup APM32F4xx_ETHDriver + @{ +*/ + +/** @addtogroup ETH_Driver + @{ +*/ + +/** @defgroup ETH_Enumerations + @{ +*/ + +/** + * @brief ETH AutoNegotiation + */ +typedef enum +{ + ETH_AUTONEGOTIATION_DISABLE, /*!< Disable negotiation */ + ETH_AUTONEGOTIATION_ENABLE /*!< Enable negotiation */ +} ETH_AUTONEGOTIATION_T; + +/** + * @brief ETH Watchdog + */ +typedef enum +{ + ETH_WATCHDOG_ENABLE, /*!< Enable watch dog */ + ETH_WATCHDOG_DISABLE /*!< Disable watch dog */ +} ETH_WATCHDOG_T; + +/** + * @brief ETH Jabber + */ +typedef enum +{ + ETH_JABBER_ENABLE, /*!< Enable jabber */ + ETH_JABBER_DISABLE /*!< Disable jabber */ +} ETH_JABBER_T; + +/** + * @brief ETH Inter Frame Gap + */ +typedef enum +{ + ETH_INTERFRAMEGAP_96BIT = 0x00, /*!< Inter-Frame gap = 96-bit */ + ETH_INTERFRAMEGAP_88BIT = 0x01, /*!< Inter-Frame gap = 88-bit */ + ETH_INTERFRAMEGAP_80BIT = 0x02, /*!< Inter-Frame gap = 80-bit */ + ETH_INTERFRAMEGAP_72BIT = 0x03, /*!< Inter-Frame gap = 72-bit */ + ETH_INTERFRAMEGAP_64BIT = 0x04, /*!< Inter-Frame gap = 64-bit */ + ETH_INTERFRAMEGAP_56BIT = 0x05, /*!< Inter-Frame gap = 56-bit */ + ETH_INTERFRAMEGAP_48BIT = 0x06, /*!< Inter-Frame gap = 48-bit */ + ETH_INTERFRAMEGAP_40BIT = 0x07 /*!< Inter-Frame gap = 40-bit */ +} ETH_INTERFRAMEGAP_T; + +/** + * @brief ETH Carrier Sense + */ +typedef enum +{ + ETH_CARRIERSENCE_ENABLE, /*!< Disable carrier sense during transmission */ + ETH_CARRIERSENCE_DISABLE /*!< Ignore MII CRS signal */ +} ETH_CARRIERSENCE_T; + +/** + * @brief ETH Speed + */ +typedef enum +{ + ETH_SPEED_10M, /*!< 10M speed */ + ETH_SPEED_100M /*!< 100M speed */ +} ETH_SPEED_T; + +/** + * @brief ETH Receive Own + */ +typedef enum +{ + ETH_RECEIVEOWN_ENABLE, /*!< Enable receive own */ + ETH_RECEIVEOWN_DISABLE /*!< Disable receive own */ +} ETH_RECEIVEOWN_T; + +/** + * @brief ETH Loop Back Mode + */ +typedef enum +{ + ETH_LOOPBACKMODE_DISABLE, /*!< Disable loopback mode */ + ETH_LOOPBACKMODE_ENABLE /*!< Enable loopback mode */ +} ETH_LOOPBACKMODE_T; + +/** + * @brief ETH Duplex Mode + */ +typedef enum +{ + ETH_MODE_HALFDUPLEX, /*!< Half-Duplex */ + ETH_MODE_FULLDUPLEX /*!< Full-Duplex */ +} ETH_MODE_T; + +/** + * @brief ETH Checksum Offload + */ +typedef enum +{ + ETH_CHECKSUMOFFLAOD_DISABLE, /*!< Disable IPv4 checksum offload */ + ETH_CHECKSUMOFFLAOD_ENABLE /*!< Enable Ipv4 checksum offload */ +} ETH_CHECKSUMOFFLAOD_T; + +/** + * @brief ETH Retry Transmission + */ +typedef enum +{ + ETH_RETRYTRANSMISSION_ENABLE, /*!< Enable retry */ + ETH_RETRYTRANSMISSION_DISABLE /*!< Disable retry */ +} ETH_RETRYTRANSMISSION_T; + +/** + * @brief ETH Automatic Pad CRC Strip + */ +typedef enum +{ + ETH_AUTOMATICPADCRCSTRIP_DISABLE, /*!< Disable automatic pad or CRC stripping */ + ETH_AUTOMATICPADCRCSTRIP_ENABLE /*!< Enable automatic pad or CRC stripping */ +} ETH_AUTOMATICPADCRCSTRIP_T; + +/** + * @brief ETH Back Off Limit + */ +typedef enum +{ + ETH_BACKOFFLIMIT_10, /*!< Set back off limit to 10 */ + ETH_BACKOFFLIMIT_8, /*!< Set back off limit to 18 */ + ETH_BACKOFFLIMIT_4, /*!< Set back off limit to 4 */ + ETH_BACKOFFLIMIT_1 /*!< Set back off limit to 1 */ +} ETH_BACKOFFLIMIT_T; + +/** + * @brief ETH Deferral Check + */ +typedef enum +{ + ETH_DEFFERRALCHECK_DISABLE, /*!< Disable deferral check */ + ETH_DEFFERRALCHECK_ENABLE /*!< Enable deferral check */ +} ETH_DEFFERRALCHECK_T; + +/** + * @brief ETH Receive All + */ +typedef enum +{ + ETH_RECEIVEAll_DISABLE, /*!< Disable receive all */ + ETH_RECEIVEALL_ENABLE /*!< Enable receive all */ +} ETH_RECEIVEAll_T; + +/** + * @brief ETH Source Addr Filter + */ +typedef enum +{ + ETH_SOURCEADDRFILTER_DISABLE, /*!< Disable source address filter */ + ETH_SOURCEADDRFILTER_NORMAL_ENABLE = BIT9, /*!< Enable normal source address filter */ + ETH_SOURCEADDRFILTER_INVERSE_ENABLE = BIT8 | BIT9, /*!< Enable inverse source address filter */ +} ETH_SOURCEADDRFILTER_T; + +/** + * @brief ETH Pass Control Frames + */ +typedef enum +{ + ETH_PASSCONTROLFRAMES_BLOCKALL = 1, /*!< Even if all control frames except pause frames fail the + address filter, MAC forwards them to the application */ + ETH_PASSCONTROLFRAMES_FORWARDALL, /*!< MAC forwards control frames to the application even if + they do not pass the address filter */ + ETH_PASSCONTROLFRAMES_FORWARDPASSEDADDRFILTER /*!< MAC forwards control frames that pass through the address filter */ +} ETH_PASSCONTROLFRAMES_T; + +/** + * @brief ETH Broadcast Frames Reception + */ +typedef enum +{ + ETH_BROADCASTFRAMESRECEPTION_ENABLE, /*!< Enable broadcast frames */ + ETH_BROADCASTFRAMESRECEPTION_DISABLE /*!< Disable broadcast frames */ +} ETH_BROADCASTFRAMESRECEPTION_T; + +/** + * @brief ETH Destination Addr Filter + */ +typedef enum +{ + ETH_DESTINATIONADDRFILTER_NORMAL, /*!< Normal destination address filter */ + ETH_DESTINATIONADDRFILTER_INVERSE /*!< Inverse destination address filter */ +} ETH_DESTINATIONADDRFILTER_T; + +/** + * @brief ETH Destination Addr Filter + */ +typedef enum +{ + ETH_PROMISCUOUS_MODE_DISABLE, /*!< Disable promiscuous mode */ + ETH_PROMISCUOUS_MODE_ENABLE /*!< Enable promiscuous mode */ +} ETH_PROMISCUOUS_MODE_T; + +/** + * @brief ETH Multicast Frames Filter + */ +typedef enum +{ + ETH_MULTICASTFRAMESFILTER_PERFECT, /*!< Multicast perfect filter */ + ETH_MULTICASTFRAMESFILTER_NONE = BIT4, /*!< Multicast pass all multicast */ + ETH_MULTICASTFRAMESFILTER_HASHTABLE = BIT2, /*!< Multicast hash multicast */ + ETH_MULTICASTFRAMESFILTER_PERFECTHASHTABLE = BIT2|BIT10 /*!< Multicast perfect hash table */ +} ETH_MULTICASTFRAMESFILTER_T; + +/** + * @brief ETH Unicast Frames Filter + */ +typedef enum +{ + ETH_UNICASTFRAMESFILTER_PERFECT, /*!< Unicast perfect filter */ + ETH_UNICASTFRAMESFILTER_HASHTABLE = BIT1, /*!< Unicast hash table */ + ETH_UNICASTFRAMESFILTER_PERFECTHASHTABLE = BIT1|BIT10 /*!< Unicast perfect hash table */ +} ETH_UNICASTFRAMESFILTER_T; + +/** + * @brief ETH Zero Quanta Pause + */ +typedef enum +{ + ETH_ZEROQUANTAPAUSE_ENABLE, /*!< Enable zero-quanta pause */ + ETH_ZEROQUANTAPAUSE_DISABLE /*!< Disable zero-quanta pause */ +} ETH_ZEROQUANTAPAUSE_T; + +/** + * @brief ETH Pause Low Threshold + */ +typedef enum +{ + ETH_PAUSELOWTHRESHOLD_MINUS4, /*!< Minus 4 slot-time */ + ETH_PAUSELOWTHRESHOLD_MINUS28, /*!< Minus 28 slot-time */ + ETH_PAUSELOWTHRESHOLD_MINUS144, /*!< Minus 144 slot-time */ + ETH_PAUSELOWTHRESHOLD_MINUS256 /*!< Minus 256 slot-time */ +} ETH_PAUSELOWTHRESHOLD_T; + +/** + * @brief ETH Unicast Pause Frame Detect + */ +typedef enum +{ + ETH_UNICASTPAUSEFRAMEDETECT_DISABLE, /*!< Disable unicast pause frame detect */ + ETH_UNICASTPAUSEFRAMEDETECT_ENABLE /*!< Enable unicast pause frame detect */ +} ETH_UNICASTPAUSEFRAMEDETECT_T; + +/** + * @brief ETH Receive Flow Control + */ +typedef enum +{ + ETH_RECEIVEFLOWCONTROL_DISABLE, /*!< Disable receive flow control */ + ETH_RECEIVEFLOWCONTROL_ENABLE /*!< Enable receive flow control */ +} ETH_RECEIVEFLOWCONTROL_T; + +/** + * @brief ETH Transmit Flow Control + */ +typedef enum +{ + ETH_TRANSMITFLOWCONTROL_DISABLE, /*!< Disable transmit flow control */ + ETH_TRANSMITFLOWCONTROL_ENABLE /*!< Enable transmit flow control */ +} ETH_TRANSMITFLOWCONTROL_T; + +/** + * @brief ETH VLAN Tag Comparison + */ +typedef enum +{ + ETH_VLANTAGCOMPARISON_16BIT, /*!< 16-bit VLAN tag comparison */ + ETH_VLANTAGCOMPARISON_12BIT /*!< 12-bit VLAN tag comparison */ +} ETH_VLANTAGCOMPARISON_T; + +/** + * @brief ETH MAC Flags + */ +typedef enum +{ + ETH_MAC_FLAG_TST = 0x00000200, /*!< Time stamp trigger flag */ + ETH_MAC_FLAG_MMCT = 0x00000040, /*!< MMC transmit flag */ + ETH_MAC_FLAG_MMCR = 0x00000020, /*!< MMC receive flag */ + ETH_MAC_FLAG_MMC = 0x00000010, /*!< MMC flag */ + ETH_MAC_FLAG_PMT = 0x00000008 /*!< PMT flag */ +} ETH_MAC_FLAG_T; + +/** + * @brief ETH MAC Interrupts + */ +typedef enum +{ + ETH_MAC_INT_TST = 0x00000200, /*!< Time stamp trigger interrupt */ + ETH_MAC_INT_MMCT = 0x00000040, /*!< MMC transmit interrupt */ + ETH_MAC_INT_MMCR = 0x00000020, /*!< MMC receive interrupt */ + ETH_MAC_INT_MMC = 0x00000010, /*!< MMC interrupt */ + ETH_MAC_INT_PMT = 0x00000008 /*!< PMT interrupt */ +} ETH_MAC_INT_T; + +/** + * @brief ETH MAC Interrupts + */ +typedef enum +{ + ETH_MAC_ADDRESS0 = 0x00000000, /*!< MAC Address0 */ + ETH_MAC_ADDRESS1 = 0x00000008, /*!< MAC Address1 */ + ETH_MAC_ADDRESS2 = 0x00000010, /*!< MAC Address2 */ + ETH_MAC_ADDRESS3 = 0x00000018 /*!< MAC Address3 */ +} ETH_MAC_ADDRESS_T; + +/** + * @brief ETH MAC addresses filter SA/DA + */ +typedef enum +{ + ETH_MAC_ADDRESSFILTER_SA, /*!< MAC Address is used to compare with the + SA fields of the received frame */ + ETH_MAC_ADDRESSFILTER_DA = BIT30 /*!< MAC Address is used to compare with the + DA fields of the received frame */ +} ETH_MAC_ADDRESSFILTER_T; + +/** + * @brief ETH MAC addresses filter Mask bytes + */ +typedef enum +{ + ETH_MAC_ADDRESSMASK_BYTE6 = 0x20000000, /*!< Mask MAC Address high reg bits [15:8] */ + ETH_MAC_ADDRESSMASK_BYTE5 = 0x10000000, /*!< Mask MAC Address high reg bits [7:0] */ + ETH_MAC_ADDRESSMASK_BYTE4 = 0x08000000, /*!< Mask MAC Address low reg bits [31:24] */ + ETH_MAC_ADDRESSMASK_BYTE3 = 0x04000000, /*!< Mask MAC Address low reg bits [23:16] */ + ETH_MAC_ADDRESSMASK_BYTE2 = 0x02000000, /*!< Mask MAC Address low reg bits [15:8] */ + ETH_MAC_ADDRESSMASK_BYTE1 = 0x01000000 /*!< Mask MAC Address low reg bits [70] */ +} ETH_MAC_ADDRESSMASK_T; + +/** + * @brief DMA Tx descriptor flags + */ +typedef enum +{ + ETH_DMATXDESC_OWN = (int)0x80000000, /*!< Descriptor is owned by DMA engine */ + ETH_DMATXDESC_INTC = 0x40000000, /*!< Interrupt on completion */ + ETH_DMATXDESC_LS = 0x20000000, /*!< Last Segment */ + ETH_DMATXDESC_FS = 0x10000000, /*!< First Segment */ + ETH_DMATXDESC_DISC = 0x08000000, /*!< Disable CRC */ + ETH_DMATXDESC_DISP = 0x04000000, /*!< Disable Pad */ + ETH_DMATXDESC_TXTSEN = 0x02000000, /*!< Transmit Time Stamp Enable */ + ETH_DMATXDESC_TXENDR = 0x00200000, /*!< Transmit End of Ring */ + ETH_DMATXDESC_TXCH = 0x00100000, /*!< Second Address Chained */ + ETH_DMATXDESC_TXTSS = 0x00020000, /*!< Tx Time Stamp Status */ + ETH_DMATXDESC_IHERR = 0x00010000, /*!< IP Header Error */ + ETH_DMATXDESC_ERRS = 0x00008000, /*!< Error summary */ + ETH_DMATXDESC_JTO = 0x00004000, /*!< Jabber Timeout */ + ETH_DMATXDESC_FF = 0x00002000, /*!< Frame Flushed: DMA/MTL flushed the frame due to SW flush */ + ETH_DMATXDESC_IPERR = 0x00001000, /*!< Payload Checksum Error */ + ETH_DMATXDESC_LSC = 0x00000800, /*!< Loss of Carrier: carrier lost during transmission */ + ETH_DMATXDESC_NC = 0x00000400, /*!< No Carrier: no carrier signal from the transceiver */ + ETH_DMATXDESC_LC = 0x00000200, /*!< Late Collision: transmission aborted due to collision */ + ETH_DMATXDESC_EC = 0x00000100, /*!< Excessive Collision: transmission aborted after 16 collisions */ + ETH_DMATXDESC_VLANF = 0x00000080, /*!< VLAN Frame */ + ETH_DMATXDESC_CCNT = 0x00000078, /*!< Collision Count */ + ETH_DMATXDESC_EDEF = 0x00000004, /*!< Excessive Deferral */ + ETH_DMATXDESC_UFERR = 0x00000002, /*!< Underflow Error: late data arrival from the memory */ + ETH_DMATXDESC_DEF = 0x00000001 /*!< Deferred Bit */ +} ETH_DMATXDESC_FLAG_T; + +/** + * @brief ETH DMA Tx descriptor segment + */ +typedef enum +{ + ETH_DMATXDESC_LASTSEGMENTS = BIT30, /*!< Actual Tx desc contain last segment */ + ETH_DMATXDESC_FIRSTSEGMENT = BIT29 /*!< Actual Tx desc contain first segment */ +} ETH_DMATXDESC_SEGMENTS_T; + +/** + * @brief ETH DMA Tx descriptor Checksum Insertion Control + */ +typedef enum +{ + ETH_DMATXDESC_CHECKSUMBYPASS, /*!< Checksum bypass */ + ETH_DMATXDESC_CHECKSUMIPV4HEADER = BIT22, /*!< IPv4 header checksum */ + ETH_DMATXDESC_CHECKSUMTCPUDPICMPSEGMENT = BIT23, /*!< TCP/UDP/ICMP checksum. Pseudo header + checksum is assumed to be present */ + ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL = BIT22|BIT23 /*!< TCP/UDP/ICMP checksum fully in hardware + including pseudo header */ +} ETH_DMATXDESC_CHECKSUMB_T; + +/** + * @brief DMA Rx descriptor status + */ +typedef enum +{ + ETH_DMARXDESC_OWN = (int)0x80000000U, /*!< Descriptor is owned by DMA engine */ + ETH_DMARXDESC_ADDRF = 0x40000000, /*!< DA Filter Fail for the rx frame */ + ETH_DMARXDESC_ERRS = 0x00008000, /*!< Error summary */ + ETH_DMARXDESC_DESERR = 0x00004000, /*!< Descriptor error: no more descriptors for receive frame */ + ETH_DMARXDESC_SADDRF = 0x00002000, /*!< SA Filter Fail for the received frame */ + ETH_DMARXDESC_LERR = 0x00001000, /*!< Frame size not matching with length field */ + ETH_DMARXDESC_OFERR = 0x00000800, /*!< Overflow Error: Frame was damaged due to buffer overflow */ + ETH_DMARXDESC_VLANF = 0x00000400, /*!< VLAN Tag: received frame is a VLAN frame */ + ETH_DMARXDESC_FDES = 0x00000200, /*!< First descriptor of the frame */ + ETH_DMARXDESC_LDES = 0x00000100, /*!< Last descriptor of the frame */ + ETH_DMARXDESC_IPV4HCE = 0x00000080, /*!< IPC Checksum Error/Giant Frame: Rx Ipv4 header checksum error */ + ETH_DMARXDESC_LC = 0x00000040, /*!< Late collision occurred during reception */ + ETH_DMARXDESC_FT = 0x00000020, /*!< Frame type - Ethernet, otherwise 802.3 */ + ETH_DMARXDESC_RXWDTTO = 0x00000010, /*!< Receive Watchdog Timeout: watchdog timer expired during reception */ + ETH_DMARXDESC_RERR = 0x00000008, /*!< Receive error: error reported by MII interface */ + ETH_DMARXDESC_DERR = 0x00000004, /*!< Dribble bit error: frame contains non int multiple of 8 bits */ + ETH_DMARXDESC_CERR = 0x00000002, /*!< CRC error */ + ETH_DMARXDESC_MAMPCE = 0x00000001 /*!< Rx MAC Address/Payload Checksum Error: + Rx MAC address matched/ Rx Payload Checksum Error */ +} ETH_DMARXDESC_FLAG_T; + +/** + * @brief DMA Rx descriptor extended flags + */ +typedef enum +{ + ETH_DMAPTPRXDESC_PTPV = 0x00002000, /*!< PTP version */ + ETH_DMAPTPRXDESC_PTPFT = 0x00001000, /*!< PTP frame type */ + ETH_DMAPTPRXDESC_PTPMT = 0x00000F00, /*!< PTP message type */ + ETH_DMAPTPRXDESC_IPV6P = 0x00000080, /*!< IPv6 packet received */ + ETH_DMAPTPRXDESC_IPV4P = 0x00000040, /*!< IPv4 packet received */ + ETH_DMAPTPRXDESC_IPCBP = 0x00000020, /*!< IP checksum bypassed */ + ETH_DMAPTPRXDESC_IPPERR = 0x00000010, /*!< IP payload error */ + ETH_DMAPTPRXDESC_IPHERR = 0x00000008, /*!< IP header error */ + ETH_DMAPTPRXDESC_IPPT = 0x00000007 /*!< IP payload type */ +} ETH_DMAPTPRXDESC_FLAG_T; + +/** + * @brief ETH DMA Rx descriptor buffers + */ +typedef enum +{ + ETH_DMARXDESC_BUFFER1, /*!< DMA Rx Desc Buffer1 */ + ETH_DMARXDESC_BUFFER2 /*!< DMA Rx Desc Buffer2 */ +} ETH_DMARXDESC_BUFFER_T; + +/** + * @brief ETH Drop TCP IP Checksum Error Frame + */ +typedef enum +{ + ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE, /*!< Enable dropping of TCP/IP checksum error frame */ + ETH_DROPTCPIPCHECKSUMERRORFRAME_DISABLE /*!< Disable dropping of TCP/IP checksum error frame */ +} ETH_DROPTCPIPCHECKSUMERRORFRAME_T; + +/** + * @brief ETH Receive Store Forward + */ +typedef enum +{ + ETH_RECEIVESTOREFORWARD_DISABLE, /*!< Disable receive store and forward */ + ETH_RECEIVESTOREFORWARD_ENABLE /*!< Enable receive store and forward */ +} ETH_RECEIVESTOREFORWARD_T; + +/** + * @brief ETH Flush Received Frame + */ +typedef enum +{ + ETH_FLUSHRECEIVEDFRAME_ENABLE, /*!< Enable flushing of received frames */ + ETH_FLUSHRECEIVEDFRAME_DISABLE /*!< Disable flushing of received frames */ +} ETH_FLUSHRECEIVEDFRAME_T; + +/** + * @brief ETH Transmit Store Forward + */ +typedef enum +{ + ETH_TRANSMITSTOREFORWARD_DISABLE, /*!< Disable transmit store and forward */ + ETH_TRANSMITSTOREFORWARD_ENABLE /*!< Enable transmit store and forward */ +} ETH_TRANSMITSTOREFORWARD_T; + +/** + * @brief ETH Transmit Threshold Control + */ +typedef enum +{ + ETH_TRANSMITTHRESHOLDCONTROL_64BYTES, /*!< Select 64 bytes transmit threshild level */ + ETH_TRANSMITTHRESHOLDCONTROL_128BYTES, /*!< Select 128 bytes transmit threshild level */ + ETH_TRANSMITTHRESHOLDCONTROL_192BYTES, /*!< Select 192 bytes transmit threshild level */ + ETH_TRANSMITTHRESHOLDCONTROL_256BYTES, /*!< Select 256 bytes transmit threshild level */ + ETH_TRANSMITTHRESHOLDCONTROL_40BYTES, /*!< Select 40 bytes transmit threshild level */ + ETH_TRANSMITTHRESHOLDCONTROL_32BYTES, /*!< Select 32 bytes transmit threshild level */ + ETH_TRANSMITTHRESHOLDCONTROL_24BYTES, /*!< Select 24 bytes transmit threshild level */ + ETH_TRANSMITTHRESHOLDCONTROL_16BYTES /*!< Select 16 bytes transmit threshild level */ +} ETH_TRANSMITTHRESHOLDCONTROL_T; + +/** + * @brief ETH Forward Error Frames + */ +typedef enum +{ + ETH_FORWARDERRORFRAMES_DISABLE, /*!< Disable forward error frames */ + ETH_FORWARDERRORFRAMES_ENABLE /*!< Enable forward error frames */ +} ETH_FORWARDERRORFRAMES_T; + +/** + * @brief ETH Forward Undersized Good Frames + */ +typedef enum +{ + ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE, /*!< Disable forward undersized good frames */ + ETH_FORWARDUNDERSIZEDGOODFRAMES_ENABLE /*!< Enable forward undersized good frames */ +} ETH_FORWARDUNDERSIZEDGOODFRAMES_T; + +/** + * @brief ETH Receive Threshold Control + */ +typedef enum +{ + ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES, /*!< Select 64 bytes receive threshold level */ + ETH_RECEIVEDTHRESHOLDCONTROL_32BYTES, /*!< Select 32 bytes receive threshold level */ + ETH_RECEIVEDTHRESHOLDCONTROL_96BYTES, /*!< Select 96 bytes receive threshold level */ + ETH_RECEIVEDTHRESHOLDCONTROL_128BYTES /*!< Select 128 bytes receive threshold level */ +} ETH_RECEIVEDTHRESHOLDCONTROL_T; + +/** + * @brief ETH Second Frame Operate + */ +typedef enum +{ + ETH_SECONDFRAMEOPERARTE_DISABLE, /*!< Disable second frame operate */ + ETH_SECONDFRAMEOPERARTE_ENABLE /*!< Enable second frame operate */ +} ETH_SECONDFRAMEOPERARTE_T; + +/** + * @brief ETH Address Aligned Beats + */ +typedef enum +{ + ETH_ADDRESSALIGNEDBEATS_DISABLE, /*!< Disable address aligned beats */ + ETH_ADDRESSALIGNEDBEATS_ENABLE /*!< Enable address aligned beats */ +} ETH_ADDRESSALIGNEDBEATS_T; + +/** + * @brief ETH Fixed Burst + */ +typedef enum +{ + ETH_FIXEDBURST_DISABLE, /*!< Disable fixed burst */ + ETH_FIXEDBURST_ENABLE /*!< Enable fixed burst */ +} ETH_FIXEDBURST_T; + +/** + * @brief ETH Rx DMA Burst Length + */ +typedef enum +{ + ETH_RXDMABURSTLENGTH_1BEAT = BIT17, /*!< Maxnum number of Rx DMA transaction = 1 beat */ + ETH_RXDMABURSTLENGTH_2BEAT = BIT18, /*!< Maxnum number of Rx DMA transaction = 2 beat */ + ETH_RXDMABURSTLENGTH_4BEAT = BIT19, /*!< Maxnum number of Rx DMA transaction = 4 beat */ + ETH_RXDMABURSTLENGTH_8BEAT = BIT20, /*!< Maxnum number of Rx DMA transaction = 8 beat */ + ETH_RXDMABURSTLENGTH_16BEAT = BIT21, /*!< Maxnum number of Rx DMA transaction = 16 beat */ + ETH_RXDMABURSTLENGTH_32BEAT = BIT22, /*!< Maxnum number of Rx DMA transaction = 32 beat */ + ETH_RXDMABURSTLENGTH_4XPBL_4BEAT = BIT17|BIT24, /*!< Maxnum number of Rx DMA transaction = 4 beat */ + ETH_RXDMABURSTLENGTH_4XPBL_8BEAT = BIT18|BIT24, /*!< Maxnum number of Rx DMA transaction = 8 beat */ + ETH_RXDMABURSTLENGTH_4XPBL_16BEAT = BIT19|BIT24, /*!< Maxnum number of Rx DMA transaction = 16 beat */ + ETH_RXDMABURSTLENGTH_4XPBL_32BEAT = BIT20|BIT24, /*!< Maxnum number of Rx DMA transaction = 32 beat */ + ETH_RXDMABURSTLENGTH_4XPBL_64BEAT = BIT21|BIT24, /*!< Maxnum number of Rx DMA transaction = 64 beat */ + ETH_RXDMABURSTLENGTH_4XPBL_128BEAT= BIT22|BIT24 /*!< Maxnum number of Rx DMA transaction = 128 beat */ +} ETH_RXDMABURSTLENGTH_T; + +/** + * @brief ETH Tx DMA Burst Length + */ +typedef enum +{ + ETH_TXDMABURSTLENGTH_1BEAT = BIT8, /*!< Maxnum number of Tx DMA transaction = 1 beat */ + ETH_TXDMABURSTLENGTH_2BEAT = BIT9, /*!< Maxnum number of Tx DMA transaction = 2 beat */ + ETH_TXDMABURSTLENGTH_4BEAT = BIT10, /*!< Maxnum number of Tx DMA transaction = 4 beat */ + ETH_TXDMABURSTLENGTH_8BEAT = BIT11, /*!< Maxnum number of Tx DMA transaction = 8 beat */ + ETH_TXDMABURSTLENGTH_16BEAT = BIT12, /*!< Maxnum number of Tx DMA transaction = 16 beat */ + ETH_TXDMABURSTLENGTH_32BEAT = BIT13, /*!< Maxnum number of Tx DMA transaction = 32 beat */ + ETH_TXDMABURSTLENGTH_4XPBL_4BEAT = BIT8|BIT24, /*!< Maxnum number of Tx DMA transaction = 4 beat */ + ETH_TXDMABURSTLENGTH_4XPBL_8BEAT = BIT9|BIT24, /*!< Maxnum number of Tx DMA transaction = 8 beat */ + ETH_TXDMABURSTLENGTH_4XPBL_16BEAT = BIT10|BIT24, /*!< Maxnum number of Tx DMA transaction = 16 beat */ + ETH_TXDMABURSTLENGTH_4XPBL_32BEAT = BIT11|BIT24, /*!< Maxnum number of Tx DMA transaction = 32 beat */ + ETH_TXDMABURSTLENGTH_4XPBL_64BEAT = BIT12|BIT24, /*!< Maxnum number of Tx DMA transaction = 64 beat */ + ETH_TXDMABURSTLENGTH_4XPBL_128BEAT= BIT13|BIT24 /*!< Maxnum number of Tx DMA transaction = 128 beat */ +} ETH_TXDMABURSTLENGTH_T; + +/** + * @brief ETH DMA Arbitration + */ +typedef enum +{ + ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1, /*!< Priority ratio RX : TX = 1 : 1 */ + ETH_DMAARBITRATION_ROUNDROBIN_RXTX_2_1 = BIT14, /*!< Priority ratio RX : TX = 2 : 1 */ + ETH_DMAARBITRATION_ROUNDROBIN_RXTX_3_1 = BIT15, /*!< Priority ratio RX : TX = 3 : 1 */ + ETH_DMAARBITRATION_ROUNDROBIN_RXTX_4_1 = BIT14|BIT15, /*!< Priority ratio RX : TX = 4 : 1 */ + ETH_DMAARBITRATION_RXPRIORTX = BIT1 /*!< Rx priority ratio higher than Tx */ +} ETH_DMAARBITRATION_T; + +/** + * @brief ETH DMA Flags + */ +typedef enum +{ + ETH_DMA_FLAG_TST = 0x20000000, /*!< Time-stamp trigger interrupt (on DMA) */ + ETH_DMA_FLAG_PMT = 0x10000000, /*!< PMT interrupt (on DMA) */ + ETH_DMA_FLAG_MMC = 0x08000000, /*!< MMC interrupt (on DMA) */ + ETH_DMA_FLAG_DATATRANSFERERROR = 0x00800000, /*!< Error bits 0-Rx DMA, 1-Tx DMA */ + ETH_DMA_FLAG_READWRITEERROR = 0x01000000, /*!< Error bits 0-write transfer, 1-read transfer */ + ETH_DMA_FLAG_ACCESSERROR = 0x02000000, /*!< Error bits 0-data buffer, 1-desc. access */ + ETH_DMA_FLAG_NIS = 0x00010000, /*!< Normal interrupt summary flag */ + ETH_DMA_FLAG_AIS = 0x00008000, /*!< Abnormal interrupt summary flag */ + ETH_DMA_FLAG_ER = 0x00004000, /*!< Early receive flag */ + ETH_DMA_FLAG_FBE = 0x00002000, /*!< Fatal bus error flag */ + ETH_DMA_FLAG_ET = 0x00000400, /*!< Early transmit flag */ + ETH_DMA_FLAG_RWT = 0x00000200, /*!< Receive watchdog timeout flag */ + ETH_DMA_FLAG_RPS = 0x00000100, /*!< Receive process stopped flag */ + ETH_DMA_FLAG_RBU = 0x00000080, /*!< Receive buffer unavailable flag */ + ETH_DMA_FLAG_RX = 0x00000040, /*!< Receive flag */ + ETH_DMA_FLAG_TU = 0x00000020, /*!< Underflow flag */ + ETH_DMA_FLAG_RO = 0x00000010, /*!< Overflow flag */ + ETH_DMA_FLAG_TJT = 0x00000008, /*!< Transmit jabber timeout flag */ + ETH_DMA_FLAG_TBU = 0x00000004, /*!< Transmit buffer unavailable flag */ + ETH_DMA_FLAG_TPS = 0x00000002, /*!< Transmit process stopped flag */ + ETH_DMA_FLAG_TX = 0x00000001 /*!< Transmit flag */ +} ETH_DMA_FLAG_T; + +/** + * @brief ETH DMA Interrupts + */ +typedef enum +{ + ETH_DMA_INT_TST = 0x20000000, /*!< Time-stamp trigger interrupt (on DMA) */ + ETH_DMA_INT_PMT = 0x10000000, /*!< PMT interrupt (on DMA) */ + ETH_DMA_INT_MMC = 0x08000000, /*!< MMC interrupt (on DMA) */ + ETH_DMA_INT_NIS = 0x00010000, /*!< Normal interrupt summary */ + ETH_DMA_INT_AIS = 0x00008000, /*!< Abnormal interrupt summary */ + ETH_DMA_INT_ER = 0x00004000, /*!< Early receive interrupt */ + ETH_DMA_INT_FBE = 0x00002000, /*!< Fatal bus error interrupt */ + ETH_DMA_INT_ET = 0x00000400, /*!< Early transmit interrupt */ + ETH_DMA_INT_RWT = 0x00000200, /*!< Receive watchdog timeout interrupt */ + ETH_DMA_INT_RPS = 0x00000100, /*!< Receive process stopped interrupt */ + ETH_DMA_INT_RBU = 0x00000080, /*!< Receive buffer unavailable interrupt */ + ETH_DMA_INT_RX = 0x00000040, /*!< Receive interrupt */ + ETH_DMA_INT_TU = 0x00000020, /*!< Underflow interrupt */ + ETH_DMA_INT_RO = 0x00000010, /*!< Overflow interrupt */ + ETH_DMA_INT_TJT = 0x00000008, /*!< Transmit jabber timeout interrupt */ + ETH_DMA_INT_TBU = 0x00000004, /*!< Transmit buffer unavailable interrupt */ + ETH_DMA_INT_TPS = 0x00000002, /*!< Transmit process stopped interrupt */ + ETH_DMA_INT_TX = 0x00000001 /*!< Transmit interrupt */ +} ETH_DMA_INT_T; + +/** + * @brief ETH DMA transmit process state + */ +typedef enum +{ + ETH_DMA_TRANSMITPROCESS_STOPPED, /*!< Stopped - Reset or Stop Tx Command issued */ + ETH_DMA_TRANSMITPROCESS_FETCHING, /*!< Running - fetching the Tx descriptor */ + ETH_DMA_TRANSMITPROCESS_WAITING, /*!< Running - waiting for status */ + ETH_DMA_TRANSMITPROCESS_READING, /*!< Running - reading the data from host memory */ + ETH_DMA_TRANSMITPROCESS_SUSPENDED = 0x06, /*!< Suspended - Tx Descriptor unavailable */ + ETH_DMA_TRANSMITPROCESS_CLOSING = 0x07, /*!< Running - closing Rx descriptor */ +} ETH_DMA_TRANSMITPROCESS_T; + +/** + * @brief ETH DMA receive process state + */ +typedef enum +{ + ETH_DMA_RECEIVEPROCESS_STOPPED, /*!< Stopped - Reset or Stop Rx Command issued */ + ETH_DMA_RECEIVEPROCESS_FETCHING = 0x02, /*!< Running - fetching the Rx descriptor */ + ETH_DMA_RECEIVEPROCESS_WAITING = 0x06, /*!< Running - waiting for packet */ + ETH_DMA_RECEIVEPROCESS_SUSPENDED = 0x08, /*!< Suspended - Rx Descriptor unavailable */ + ETH_DMA_RECEIVEPROCESS_CLOSING = 0x0A, /*!< Running - closing descriptor */ + ETH_DMA_RECEIVEPROCESS_QUEUING = 0x0E /*!< Running - queuing the receive frame into host memory */ +} ETH_DMA_RECEIVEPROCESS_T; + +/** + * @brief ETH DMA overflow + */ +typedef enum +{ + ETH_DMA_OVERFLOW_RXFIFOCOUNTER = BIT28, /*!< Overflow for FIFO Overflows Counter */ + ETH_DMA_OVERFLOW_MISSEDFRAMECOUNTER = BIT16 /*!< Overflow for Buffer Unavailable Missed Frame Counter */ +} ETH_DMA_OVERFLOW_T; + +/** + * @brief ETH PMT Flags + */ +typedef enum +{ + ETH_PMT_FLAG_WUFFRPR = (int)BIT31, /*!< Wake-Up Frame Filter Register Pointer Reset */ + ETH_PMT_FLAG_WUFR = BIT6, /*!< Wake-Up Frame Received */ + ETH_PMT_FLAG_MPR = BIT5 /*!< Magic Packet Received */ +} ETH_PMT_FLAG_T; + +/** + * @brief ETH MMC Tx/RX Interrupts + */ +typedef enum +{ + ETH_MMC_INT_TGF = BIT21, /*!< When Tx good frame counter reaches half the maximum value */ + ETH_MMC_INT_TGFMSC = BIT15, /*!< When Tx good multi col counter reaches half the maximum value */ + ETH_MMC_INT_TGFSC = BIT14, /*!< When Tx good single col counter reaches half the maximum value */ + ETH_MMC_INT_RGUF = BIT21|BIT30, /*!< When Rx good unicast frames counter reaches half the maximum value */ + ETH_MMC_INT_RFAE = BIT6|BIT30, /*!< When Rx alignment error counter reaches half the maximum value */ + ETH_MMC_INT_RFCE = BIT5|BIT30 /*!< When Rx crc error counter reaches half the maximum value */ +} ETH_MMC_INT_T; + +/** + * @brief ETH MMC Registers + */ +typedef enum +{ + ETH_MMC_CTRL = 0x00000100, /*!< MMC CTRL register */ + ETH_MMC_RXINT = 0x00000104, /*!< MMC RXINT register */ + ETH_MMC_TXINT = 0x00000108, /*!< MMC TXINT register */ + ETH_MMC_RXINTMASK = 0x0000010C, /*!< MMC RXINTMASK register */ + ETH_MMC_TXINTMASK = 0x00000110, /*!< MMC TXINTMASK register */ + ETH_MMC_TXGFSCCNT = 0x0000014C, /*!< MMC TXGFSCCNT register */ + ETH_MMC_TXGFMCCNT = 0x00000150, /*!< MMC TXGFMCCNT register */ + ETH_MMC_TXGFCNT = 0x00000168, /*!< MMC TXGFCNT register */ + ETH_MMC_RXFCECNT = 0x00000194, /*!< MMC RXFCECNT register */ + ETH_MMC_RXFAECNT = 0x00000198, /*!< MMC RXFAECNT register */ + ETH_MMC_RXGUNCNT = 0x000001C4 /*!< MMC RXGUNCNT register */ +} ETH_MMC_REG_T; + +/**@} end of group ETH_Enumerations*/ + + +/** @defgroup ETH_DMA_TX_Descriptor ETH DMA TX Descriptor + @{ + */ + +/** +* DMA Tx Descriptor +* ----------------------------------------------------------------------------------------------- +* TXDES0 | OWN(31) | CTRL[30:25] | Reserved(24) | CTRL[23:20] | Reserved[19:18] | Status[17:0] | +* ----------------------------------------------------------------------------------------------- +* TXDES1 | Reserved[31:29] | Buffer2 Size[28:16] | Reserved[15:13] | Buffer1 Size[12:0] | +* ----------------------------------------------------------------------------------------------- +* TXDES2 | Buffer1 Address [31:0] | +* ----------------------------------------------------------------------------------------------- +* TXDES3 | Buffer2 Address [31:0] / Next Descriptor Address [31:0] | +* ----------------------------------------------------------------------------------------------- +*/ + +/** + * @brief Bit definition of TXDES0 register: DMA Tx descriptor status register + */ +#define ETH_DMATXDESC_OWN 0x80000000U /*!< OWN bit: descriptor is owned by DMA engine */ +#define ETH_DMATXDESC_INTC 0x40000000U /*!< Interrupt on Completion */ +#define ETH_DMATXDESC_LS 0x20000000U /*!< Last Segment */ +#define ETH_DMATXDESC_FS 0x10000000U /*!< First Segment */ +#define ETH_DMATXDESC_DISC 0x08000000U /*!< Disable CRC */ +#define ETH_DMATXDESC_DISP 0x04000000U /*!< Disable Padding */ +#define ETH_DMATXDESC_TXTSEN 0x02000000U /*!< Transmit Time Stamp Enable */ +#define ETH_DMATXDESC_CIC 0x00C00000U /*!< Checksum Insertion Control: 4 cases */ +#define ETH_DMATXDESC_CIC_BYPASS 0x00000000U /*!< Do Nothing: Checksum Engine is bypassed */ +#define ETH_DMATXDESC_CIC_IPV4HEADER 0x00400000U /*!< IPV4 header Checksum Insertion */ +#define ETH_DMATXDESC_CIC_TCPUDPICMP_SEGMENT 0x00800000U /*!< TCP/UDP/ICMP Checksum Insertion calculated over segment only */ +#define ETH_DMATXDESC_CIC_TCPUDPICMP_FULL 0x00C00000U /*!< TCP/UDP/ICMP Checksum Insertion fully calculated */ +#define ETH_DMATXDESC_TXENDR 0x00200000U /*!< Transmit End of Ring */ +#define ETH_DMATXDESC_TXCH 0x00100000U /*!< Second Address Chained */ +#define ETH_DMATXDESC_TXTSS 0x00020000U /*!< Tx Time Stamp Status */ +#define ETH_DMATXDESC_IHERR 0x00010000U /*!< IP Header Error */ +#define ETH_DMATXDESC_ERRS 0x00008000U /*!< Error summary: OR of the following bits: UFERR || EDEF || EC || LC || NC || LSC || FF || JTO */ +#define ETH_DMATXDESC_JTO 0x00004000U /*!< Jabber Timeout */ +#define ETH_DMATXDESC_FF 0x00002000U /*!< Frame Flushed: DMA/MTL flushed the frame due to SW flush */ +#define ETH_DMATXDESC_IPERR 0x00001000U /*!< Payload Checksum Error */ +#define ETH_DMATXDESC_LSC 0x00000800U /*!< Loss of Carrier: carrier lost during transmission */ +#define ETH_DMATXDESC_NC 0x00000400U /*!< No Carrier: no carrier signal from the transceiver */ +#define ETH_DMATXDESC_LC 0x00000200U /*!< Late Collision: transmission aborted due to collision */ +#define ETH_DMATXDESC_EC 0x00000100U /*!< Excessive Collision: transmission aborted after 16 collisions */ +#define ETH_DMATXDESC_VLANF 0x00000080U /*!< VLAN Frame */ +#define ETH_DMATXDESC_CCNT 0x00000078U /*!< Collision Count */ +#define ETH_DMATXDESC_EDEF 0x00000004U /*!< Excessive Deferral */ +#define ETH_DMATXDESC_UFERR 0x00000002U /*!< Underflow Error: late data arrival from the memory */ +#define ETH_DMATXDESC_DEF 0x00000001U /*!< Deferred Bit */ + +/** + * @brief Bit definition of TXDES1 register + */ +#define ETH_DMATXDESC_TXBS2 0x1FFF0000U /*!< Transmit Buffer2 Size */ +#define ETH_DMATXDESC_TXBS1 0x00001FFFU /*!< Transmit Buffer1 Size */ + +/** + * @brief Bit definition of TXDES2 register + */ +#define ETH_DMATXDESC_B1AP 0xFFFFFFFFU /*!< Buffer1 Address Pointer */ + +/** + * @brief Bit definition of TXDES3 register + */ +#define ETH_DMATXDESC_B2AP 0xFFFFFFFFU /*!< Buffer2 Address Pointer */ + +/** +* --------------------------------------------------------------------------------------------- +* TXDES6 | Transmit Time Stamp Low [31:0] | +* --------------------------------------------------------------------------------------------- +* TXDES7 | Transmit Time Stamp High [31:0] | +* ---------------------------------------------------------------------------------------------- +*/ + +/** Bit definition of TXDES6 register */ +#define ETH_DMAPTPTXDESC_TXTSL 0xFFFFFFFFU /*!< Transmit Time Stamp Low */ + +/** Bit definition of TXDES7 register */ +#define ETH_DMAPTPTXDESC_TXTSH 0xFFFFFFFFU /*!< Transmit Time Stamp High */ + +/** + * @} + */ +/** @defgroup ETH_DMA_RX_Descriptor ETH DMA RX Descriptor + @{ + */ + +/** + *DMA Rx Descriptor + *-------------------------------------------------------------------------------------------------------------------- + *RXDES0 | OWN(31) | Status [30:0] | + *--------------------------------------------------------------------------------------------------------------------- + *RXDES1 | CTRL(31) | Reserved[30:29] | Buffer2 Size[28:16] | CTRL[15:14] | Reserved(13) | Buffer1 Size[12:0] | + *--------------------------------------------------------------------------------------------------------------------- + *RXDES2 | Buffer1 Address [31:0] | + *--------------------------------------------------------------------------------------------------------------------- + *RXDES3 | Buffer2 Address [31:0] / Next Descriptor Address [31:0] | + *--------------------------------------------------------------------------------------------------------------------- +*/ + +/** + * @brief Bit definition of RXDES0 register: DMA Rx descriptor status register + */ +#define ETH_DMARXDESC_OWN 0x80000000U /*!< OWN bit: descriptor is owned by DMA engine */ +#define ETH_DMARXDESC_ADDRF 0x40000000U /*!< DA Filter Fail for the rx frame */ +#define ETH_DMARXDESC_FL 0x3FFF0000U /*!< Receive descriptor frame length */ +#define ETH_DMARXDESC_ERRS 0x00008000U /*!< Error summary: OR of the following bits: DE || OE || IPC || LC || RWT || RE || CE */ +#define ETH_DMARXDESC_DESERR 0x00004000U /*!< Descriptor error: no more descriptors for receive frame */ +#define ETH_DMARXDESC_SADDRF 0x00002000U /*!< SA Filter Fail for the received frame */ +#define ETH_DMARXDESC_LERR 0x00001000U /*!< Frame size not matching with length field */ +#define ETH_DMARXDESC_OFERR 0x00000800U /*!< Overflow Error: Frame was damaged due to buffer overflow */ +#define ETH_DMARXDESC_VLANF 0x00000400U /*!< VLAN Tag: received frame is a VLAN frame */ +#define ETH_DMARXDESC_FDES 0x00000200U /*!< First descriptor of the frame */ +#define ETH_DMARXDESC_LDES 0x00000100U /*!< Last descriptor of the frame */ +#define ETH_DMARXDESC_IPV4HCE 0x00000080U /*!< IPC Checksum Error: Rx Ipv4 header checksum error */ +#define ETH_DMARXDESC_LC 0x00000040U /*!< Late collision occurred during reception */ +#define ETH_DMARXDESC_FT 0x00000020U /*!< Frame type - Ethernet, otherwise 802.3 */ +#define ETH_DMARXDESC_RXWWTTO 0x00000010U /*!< Receive Watchdog Timeout: watchdog timer expired during reception */ +#define ETH_DMARXDESC_RERR 0x00000008U /*!< Receive error: error reported by MII interface */ +#define ETH_DMARXDESC_DERR 0x00000004U /*!< Dribble bit error: frame contains non int multiple of 8 bits */ +#define ETH_DMARXDESC_CERR 0x00000002U /*!< CRC error */ +#define ETH_DMARXDESC_MAMPCE 0x00000001U /*!< Rx MAC Address/Payload Checksum Error: Rx MAC address matched/ Rx Payload Checksum Error */ + +/** + * @brief Bit definition of RXDES1 register + */ +#define ETH_DMARXDESC_DINTC 0x80000000U /*!< Disable Interrupt on Completion */ +#define ETH_DMARXDESC_RXBS2 0x1FFF0000U /*!< Receive Buffer2 Size */ +#define ETH_DMARXDESC_RXER 0x00008000U /*!< Receive End of Ring */ +#define ETH_DMARXDESC_RXCH 0x00004000U /*!< Second Address Chained */ +#define ETH_DMARXDESC_RXBS1 0x00001FFFU /*!< Receive Buffer1 Size */ + +/** + * @brief Bit definition of RXDES2 register + */ +#define ETH_DMARXDESC_B1AP 0xFFFFFFFFU /*!< Buffer1 Address Pointer */ + +/** + * @brief Bit definition of RXDES3 register + */ +#define ETH_DMARXDESC_B2AP 0xFFFFFFFFU /*!< Buffer2 Address Pointer */ + +/** + *--------------------------------------------------------------------------------------------------------------------- + *RXDES4 | Reserved[31:14] | Extended Status [13:0] | + *--------------------------------------------------------------------------------------------------------------------- + *RXDES5 | Reserved[31:0] | + *--------------------------------------------------------------------------------------------------------------------- + *RXDES6 | Receive Time Stamp Low [31:0] | + *--------------------------------------------------------------------------------------------------------------------- + *RXDES7 | Receive Time Stamp High [31:0] | + *--------------------------------------------------------------------------------------------------------------------- +*/ + +/** Bit definition of RXDES4 register */ +#define ETH_DMAPTPRXDESC_PTPV 0x00002000U /*!< PTP Version */ +#define ETH_DMAPTPRXDESC_PTPFT 0x00001000U /*!< PTP Frame Type */ +#define ETH_DMAPTPRXDESC_PTPMT 0x00000F00U /*!< PTP Message Type */ +#define ETH_DMAPTPRXDESC_PTPMT_SYNC 0x00000100U /*!< SYNC message (all clock types) */ +#define ETH_DMAPTPRXDESC_PTPMT_FOLLOWUP 0x00000200U /*!< FollowUp message (all clock types) */ +#define ETH_DMAPTPRXDESC_PTPMT_DELAYREQ 0x00000300U /*!< DelayReq message (all clock types) */ +#define ETH_DMAPTPRXDESC_PTPMT_DELAYRESP 0x00000400U /*!< DelayResp message (all clock types) */ +#define ETH_DMAPTPRXDESC_PTPMT_PDELAYREQ_ANNOUNCE 0x00000500U /*!< PdelayReq message (peer-to-peer transparent clock) or Announce message (Ordinary or Boundary clock) */ +#define ETH_DMAPTPRXDESC_PTPMT_PDELAYRESP_MANAG 0x00000600U /*!< PdelayResp message (peer-to-peer transparent clock) or Management message (Ordinary or Boundary clock) */ +#define ETH_DMAPTPRXDESC_PTPMT_PDELAYRESPFOLLOWUP_SIGNAL 0x00000700U /*!< PdelayRespFollowUp message (peer-to-peer transparent clock) or Signaling message (Ordinary or Boundary clock) */ +#define ETH_DMAPTPRXDESC_IPV6P 0x00000080U /*!< IPv6 Packet Received */ +#define ETH_DMAPTPRXDESC_IPV4P 0x00000040U /*!< IPv4 Packet Received */ +#define ETH_DMAPTPRXDESC_IPCBP 0x00000020U /*!< IP Checksum Bypassed */ +#define ETH_DMAPTPRXDESC_IPPERR 0x00000010U /*!< IP Payload Error */ +#define ETH_DMAPTPRXDESC_IPHERR 0x00000008U /*!< IP Header Error */ +#define ETH_DMAPTPRXDESC_IPPT 0x00000007U /*!< IP Payload Type */ +#define ETH_DMAPTPRXDESC_IPPT_UDP 0x00000001U /*!< UDP payload encapsulated in the IP datagram */ +#define ETH_DMAPTPRXDESC_IPPT_TCP 0x00000002U /*!< TCP payload encapsulated in the IP datagram */ +#define ETH_DMAPTPRXDESC_IPPT_ICMP 0x00000003U /*!< ICMP payload encapsulated in the IP datagram */ + +/** Bit definition of RXDES6 register */ +#define ETH_DMAPTPRXDESC_RXTSL 0xFFFFFFFFU /*!< Receive Time Stamp Low */ + +/** Bit definition of RXDES7 register */ +#define ETH_DMAPTPRXDESC_RXTSH 0xFFFFFFFFU /*!< Receive Time Stamp High */ +/** + * @} + */ + + +/** @addtogroup ETH_Macros Macros + *@{ + */ + +/** ETH Frames defines */ + +/** Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /*!< buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /*!< buffer size for transmit */ +#define ETH_RXBUFNB (10U) /*!< 10 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB (10U) /*!< 10 Tx buffers of size ETH_TX_BUF_SIZE */ + +/** ETH_Buffers_setting ETH Buffers setting */ +#define ETH_MAX_PACKET_SIZE 1524U /*!< ETH_HEADER + ETH_EXTRA + ETH_VLAN_TAG + ETH_MAX_ETH_PAYLOAD + ETH_CRC */ +#define ETH_HEADER 14U /*!< 6 byte Dest addr, 6 byte Src addr, 2 byte length/type */ +#define ETH_CRC 4U /*!< Ethernet CRC */ +#define ETH_EXTRA 2U /*!< Extra bytes in some cases */ +#define ETH_VLAN_TAG 4U /*!< optional 802.1q VLAN Tag */ +#define ETH_MIN_ETH_PAYLOAD 46U /*!< Minimum Ethernet payload size */ +#define ETH_MAX_ETH_PAYLOAD 1500U /*!< Maximum Ethernet payload size */ +#define ETH_JUMBO_FRAME_PAYLOAD 9000U /*!< Jumbo frame payload size */ + +/** +* Ethernet driver receive buffers are organized in a chained linked-list, when +* an ethernet packet is received, the Rx-DMA will transfer the packet from RxFIFO +* to the driver receive buffers memory. +* +* Depending on the size of the received ethernet packet and the size of +* each ethernet driver receive buffer, the received packet can take one or more +* ethernet driver receive buffer. +* +* In below are defined the size of one ethernet driver receive buffer ETH_RX_BUF_SIZE +* and the total count of the driver receive buffers ETH_RXBUFNB. +* +* The configured value for ETH_RX_BUF_SIZE and ETH_RXBUFNB are only provided as +* example, they can be reconfigured in the application layer to fit the application +* needs +*/ + +/** Here we configure each Ethernet driver receive buffer to fit the Max size Ethernet +* packet +*/ +#ifndef ETH_RX_BUF_SIZE +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE +#endif + +/** 5 Ethernet driver receive buffers are used (in a chained linked list)*/ +#ifndef ETH_RXBUFNB +#define ETH_RXBUFNB 5U /*!< 5 Rx buffers of size ETH_RX_BUF_SIZE */ +#endif + +/** +* Ethernet driver transmit buffers are organized in a chained linked-list, when +* an ethernet packet is transmitted, Tx-DMA will transfer the packet from the +* driver transmit buffers memory to the TxFIFO. +* +* Depending on the size of the Ethernet packet to be transmitted and the size of +* each ethernet driver transmit buffer, the packet to be transmitted can take +* one or more ethernet driver transmit buffer. +* +* In below are defined the size of one ethernet driver transmit buffer ETH_TX_BUF_SIZE +* and the total count of the driver transmit buffers ETH_TXBUFNB. +* +* The configured value for ETH_TX_BUF_SIZE and ETH_TXBUFNB are only provided as +* example, they can be reconfigured in the application layer to fit the application +* needs +*/ + +/** Here we configure each Ethernet driver transmit buffer to fit the Max size Ethernet +* packet +*/ +#ifndef ETH_TX_BUF_SIZE +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE +#endif + +/** 5 ethernet driver transmit buffers are used (in a chained linked list)*/ +#ifndef ETH_TXBUFNB +#define ETH_TXBUFNB 5U /*!< 5 Tx buffers of size ETH_TX_BUF_SIZE */ +#endif + +/** 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 Errors */ +#define ETH_SUCCESS 1U +#define ETH_ERROR 0U + +/** ETHERNET DMA Tx descriptors Collision Count Shift */ +#define ETH_DMATXDESC_COLLISION_COUNTSHIFT 3U + +/** ETHERNET DMA Tx descriptors Buffer2 Size Shift */ +#define ETH_DMATXDESC_BUFFER2_SIZESHIFT 16U + +/** ETHERNET DMA Rx descriptors Frame Length Shift */ +#define ETH_DMARXDESC_FRAME_LENGTHSHIFT 16U + +/** ETHERNET DMA Rx descriptors Buffer2 Size Shift */ +#define ETH_DMARXDESC_BUFFER2_SIZESHIFT 16U + +/** ETHERNET DMA Rx descriptors Frame length Shift */ +#define ETH_DMARXDESC_FRAMELENGTHSHIFT 16U + +/** ETHERNET MACMIIAR register Mask */ +#define ETH_MACMIIAR_CR_MASK 0xFFFFFFE3U + +/** ETHERNET MACCR register Mask */ +#define ETH_MACCR_CLEAR_MASK 0xFF20010FU + +/** ETHERNET MACFCR register Mask */ +#define ETH_MACFCR_CLEAR_MASK 0x0000FF41U + +/** ETHERNET DMAOMR register Mask */ +#define ETH_DMAOMR_CLEAR_MASK 0xF8DE3F23U + +/** ETHERNET Remote Wake-up frame register length */ +#define ETH_WAKEUP_REGISTER_LENGTH 8U + +/** ETHERNET Missed frames counter Shift */ +#define ETH_DMA_RX_OVERFLOW_MISSEDFRAMES_COUNTERSHIFT 17U + +/** PHY registers defines */ + +/** PHY Read write Timeouts */ +#define PHY_READ_TIMEOUT ((uint32_t)0x0004FFFF) +#define PHY_WRITE_TIMEOUT ((uint32_t)0x0004FFFF) + +/** PHY Register address */ +#define PHY_BCR 0 /*!< Transceiver Basic Control Register */ +#define PHY_BSR 1 /*!< Transceiver Basic Status Register */ +#define PHY_SR 16 /*!< Transceiver Status Register for dp83848 */ + +/** PHY Status Register (PHYSTS), address 0x10 */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< for dp83848 ((uint16_t)0x0010) */ +#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< for dp83848 ((uint16_t)0x0004) */ + +/** PHY basic status register */ +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ + +/** PHY basic Control register */ +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ +#define PHY_RESTAET_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ + +/** PHY Delay */ +#define PHY_RESET_DELAY ((uint32_t)0x000FFFFF) /*!< PHY reset delay */ +#define PHY_CONFIG_DELAY ((uint32_t)0x00FFFFFF) /*!< PHY configuration delay */ +/** Delay to wait when writing to some Ethernet registers */ +#define ETH_REG_WRITE_DELAY ((uint32_t)0x0000FFFF) + +/** Ethernet MAC MII Address Clock Range*/ +#define ETH_MACMIIAR_CR_DIV42 ((uint8_t)0x00) /*!< HCLK:60-100 MHz; MDC clock = HCLK/42 */ +#define ETH_MACMIIAR_CR_DIV62 ((uint8_t)0x01) /*!< HCLK:100-150 MHz; MDC clock = HCLK/62 */ +#define ETH_MACMIIAR_CR_DIV16 ((uint8_t)0x02) /*!< HCLK:20-35 MHz; MDC clock = HCLK/16 */ +#define ETH_MACMIIAR_CR_DIV26 ((uint8_t)0x03) /*!< HCLK:35-60 MHz; MDC clock = HCLK/26 */ +#define ETH_MACMIIAR_CR_DIV102 ((uint8_t)0x04) /*!< HCLK:150-168 MHz; MDC clock = HCLK/102 */ + +/** Control the Enhanced DMA descriptors */ +#define USE_ENHANCED_DMA_DESCRIPTORS 1 + +/**@} end of group ETH_Macros */ + + +/** @addtogroup ETH_Structure Data Structure + @{ +*/ + +/** + * @brief ETH MAC Config structure types + */ +typedef struct +{ + /** MAC Configuration */ + ETH_AUTONEGOTIATION_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) */ + + ETH_WATCHDOG_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. */ + + ETH_JABBER_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. */ + ETH_INTERFRAMEGAP_T interFrameGap; /*!< Selects the minimum IFG between frames during transmission */ + + ETH_CARRIERSENCE_T carrierSense; /*!< Selects or not the Carrier Sense */ + + ETH_SPEED_T speed; /*!< Sets the Ethernet speed: 10/100 Mbps */ + + ETH_RECEIVEOWN_T receiveOwn; /*!< Selects or not the ReceiveOwn + ReceiveOwn allows the reception of frames when the TX_EN signal is asserted + in Half-Duplex mode */ + + ETH_LOOPBACKMODE_T loopbackMode; /*!< Selects or not the internal MAC MII Loopback mode */ + + ETH_MODE_T mode; /*!< Selects the MAC duplex mode: Half-Duplex or Full-Duplex mode */ + + ETH_CHECKSUMOFFLAOD_T checksumOffload; /*!< Selects or not the IPv4 checksum checking for received frame payloads' TCP/UDP/ICMP headers. */ + + ETH_RETRYTRANSMISSION_T retryTransmission; /*!< Selects or not the MAC attempt retries transmission, based on the settings of BL, + when a collision occurs (Half-Duplex mode) */ + + ETH_AUTOMATICPADCRCSTRIP_T automaticPadCRCStrip; /*!< Selects or not the Automatic MAC Pad/CRC Stripping */ + + ETH_BACKOFFLIMIT_T backOffLimit; /*!< Selects the BackOff limit value */ + + ETH_DEFFERRALCHECK_T deferralCheck; /*!< Selects or not the deferral check function (Half-Duplex mode) */ + + ETH_RECEIVEAll_T receiveAll; /*!< Selects or not all frames reception by the MAC (No filtering) */ + + ETH_SOURCEADDRFILTER_T sourceAddrFilter; /*!< Selects the Source Address Filter mode */ + + ETH_PASSCONTROLFRAMES_T passControlFrames; /*!< Sets the forwarding mode of the control frames (including unicast and multicast PAUSE frames) */ + + ETH_BROADCASTFRAMESRECEPTION_T broadcastFramesReception; /*!< Selects or not the reception of Broadcast Frames */ + + ETH_DESTINATIONADDRFILTER_T destinationAddrFilter; /*!< Sets the destination filter mode for both unicast and multicast frames */ + + ETH_PROMISCUOUS_MODE_T promiscuousMode; /*!< Selects or not the Promiscuous Mode */ + + ETH_MULTICASTFRAMESFILTER_T multicastFramesFilter; /*!< Selects the Multicast Frames filter mode */ + + ETH_UNICASTFRAMESFILTER_T unicastFramesFilter; /*!< Selects the Unicast Frames filter mode */ + + + 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<=0xFFFF) to be used in the Pause Time */ + + ETH_ZEROQUANTAPAUSE_T zeroQuantaPause; /*!< Selects or not the automatic generation of Zero-Quanta Pause Control frames */ + + ETH_PAUSELOWTHRESHOLD_T pauseLowThreshold; /*!< This field configures the threshold of the PAUSE to be checked for + automatic retransmission of PAUSE Frame */ + + ETH_UNICASTPAUSEFRAMEDETECT_T unicastPauseFrameDetect; /*!< Selects or not the MAC detection of the Pause frames (with MAC Address0 + unicast address and unique multicast address) */ + + ETH_RECEIVEFLOWCONTROL_T receiveFlowControl; /*!< Enables or disables the MAC to decode the received Pause frame and + disable its transmitter for a specified time (Pause Time) */ + + ETH_TRANSMITFLOWCONTROL_T transmitFlowControl; /*!< Enables or disables the MAC to transmit Pause frames (Full-Duplex mode) + or the MAC back-pressure operation (Half-Duplex mode) */ + + ETH_VLANTAGCOMPARISON_T VLANTagComparison; /*!< Selects the 12-bit VLAN identifier or the complete 16-bit VLAN tag for + comparison and filtering */ + + uint32_t VLANTagIdentifier; /*!< Holds the (value <=0xFFFF) VLAN tag identifier for receive frames */ + + /** DMA Configuration */ + ETH_DROPTCPIPCHECKSUMERRORFRAME_T dropTCPIPChecksumErrorFrame; /*!< Selects or not the Dropping of TCP/IP Checksum Error Frames */ + + ETH_RECEIVESTOREFORWARD_T receiveStoreForward; /*!< Enables or disables the Receive store and forward mode */ + + ETH_FLUSHRECEIVEDFRAME_T flushReceivedFrame; /*!< Enables or disables the flushing of received frames */ + + ETH_TRANSMITSTOREFORWARD_T transmitStoreForward; /*!< Enables or disables Transmit store and forward mode */ + + ETH_TRANSMITTHRESHOLDCONTROL_T transmitThresholdControl; /*!< Selects or not the Transmit Threshold Control */ + + ETH_FORWARDERRORFRAMES_T forwardErrorFrames; /*!< Selects or not the forward to the DMA of erroneous frames */ + + ETH_FORWARDUNDERSIZEDGOODFRAMES_T forwardUndersizedGoodFrames; /*!< Enables or disables the Rx FIFO to forward Undersized frames (frames with no Error + and length less than 64 bytes) including pad-bytes and CRC) */ + + ETH_RECEIVEDTHRESHOLDCONTROL_T receiveThresholdControl; /*!< Selects the threshold level of the Receive FIFO */ + + ETH_SECONDFRAMEOPERARTE_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. */ + + ETH_ADDRESSALIGNEDBEATS_T addressAlignedBeats; /*!< Enables or disables the Address Aligned Beats */ + + ETH_FIXEDBURST_T fixedBurst; /*!< Enables or disables the AHB Master interface fixed burst transfers */ + + ETH_RXDMABURSTLENGTH_T rxDMABurstLength; /*!< Indicates the maximum number of beats to be transferred in one Rx DMA transaction */ + + ETH_TXDMABURSTLENGTH_T txDMABurstLength; /*!< Indicates the maximum number of beats to be transferred in one Tx DMA transaction */ + + uint32_t descriptorSkipLength; /*!< Specifies the number of word to skip between two unchained descriptors (Ring mode) (value <= 0x1F) */ + + ETH_DMAARBITRATION_T DMAArbitration; /*!< Selects the DMA Tx/Rx arbitration */ +} ETH_Config_T; + +/** + * @brief ETH DMA Descriptors data structure types + */ +typedef struct +{ + __IO uint32_t Status; /*!< Status */ + uint32_t ControlBufferSize; /*!< Control and Buffer1, Buffer2 lengths */ + uint32_t Buffer1Addr; /*!< Buffer1 address pointer */ + uint32_t Buffer2NextDescAddr; /*!< Buffer2 or next descriptor address pointer */ + /* Enhanced ETHERNET DMA PTP Descriptors */ + #if USE_ENHANCED_DMA_DESCRIPTORS + uint32_t ExtendedStatus; /*!< Extended status for PTP receive descriptor */ + uint32_t Reserved1; /*!< Reserved */ + uint32_t TimeStampLow; /*!< Time Stamp Low value for transmit and receive */ + uint32_t TimeStampHigh; /*!< Time Stamp High value for transmit and receive */ + #endif /* USE_ENHANCED_DMA_DESCRIPTORS */ +} ETH_DMADescConfig_T; + +/** + * @brief ETH DMA Descriptors data structure types + */ +typedef struct +{ + uint32_t length; /*!< Data length */ + uint32_t buffer; /*!< Data buffer */ + __IO ETH_DMADescConfig_T *descriptor; /*!< DMA descriptor */ +} ETH_Frame_T; + +/** + * @brief ETH DMA Descriptors Received Frame Informations structure types + */ +typedef struct { + __IO ETH_DMADescConfig_T *FS_RxDesc; /*!< First Segment Rx Desc */ + __IO ETH_DMADescConfig_T *LS_RxDesc; /*!< Last Segment Rx Desc */ + __IO uint32_t segCount; /*!< Segment count */ +} ETH_DMARxFrameInformations; + +/**@} end of group ETH_Structure*/ + +/** @defgroup ETH_Functions + @{ +*/ + +/* ETH Configuration */ +void ETH_Reset(void); +void ETH_ConfigStructInit(ETH_Config_T* ethConfig); +uint32_t ETH_Config(ETH_Config_T* ethConfig, uint16_t addr); +void ETH_SoftwareReset(void); +uint8_t ETH_ReadSoftwareReset(void); +void ETH_Start(void); +void ETH_Stop(void); +uint32_t ETH_ReadRxPacketSize(ETH_DMADescConfig_T *DMARxDesc); +#if USE_ENHANCED_DMA_DESCRIPTORS +void ETH_EnableEnhancedDescriptor(void); +void ETH_DisableEnhancedDescriptor(void); +#endif /*!< USE_ENHANCED_DMA_DESCRIPTORS */ + +/* PHY */ +uint16_t ETH_ReadPHYRegister(uint16_t addr, uint16_t reg); +uint32_t ETH_WritePHYRegister(uint16_t addr, uint16_t reg, uint16_t data); +uint32_t ETH_EnablePHYLoopBack(uint16_t addr); +uint32_t ETH_DisablePHYLoopBack(uint16_t addr); + +/* MAC */ +void ETH_EnableMACTransmission(void); +void ETH_DisableMACTransmission(void); +void ETH_EnableMACReceiver(void); +void ETH_DisableMACReceiver(void); +uint8_t ETH_ReadFlowControlBusyStatus(void); +void ETH_SetPauseControlFrame(void); +void ETH_EnableBackPressureActivation(void); +void ETH_DisableBackPressureActivation(void); +uint8_t ETH_ReadMACFlagStatus(ETH_MAC_FLAG_T flag); +void ETH_EnableMACInterrupt(uint32_t interrupt); +void ETH_DisableMACInterrupt(uint32_t interrupt); +void ETH_ConfigMACAddress(ETH_MAC_ADDRESS_T macAddr, uint8_t *addr); +void ETH_ReadMACAddress(ETH_MAC_ADDRESS_T macAddr, uint8_t *addr); +void ETH_EnableMACAddressPerfectFilter(ETH_MAC_ADDRESS_T macAddr); +void ETH_DisableMACAddressPerfectFilter(ETH_MAC_ADDRESS_T macAddr); +void ETH_ConfigMACAddressFilter(ETH_MAC_ADDRESS_T macAddr, ETH_MAC_ADDRESSFILTER_T filter); +void ETH_ConfigMACAddressMaskBytesFilter(ETH_MAC_ADDRESS_T macAddr, uint32_t maskByte); + +/* DMA descriptors */ +void ETH_ConfigDMARxDescChain(ETH_DMADescConfig_T *DMARxDescTab, uint8_t *rxBuff, uint32_t rxBuffcount); +void ETH_ConfigDMATxDescChain(ETH_DMADescConfig_T *DMATxDescTab, uint8_t* txBuff, uint32_t txBuffcount); +uint32_t ETH_CheckReceivedFrame(void); +uint32_t ETH_Transmit_Descriptors(u16 frameLength); +ETH_Frame_T ETH_ReadReceivedFrame(void); +uint8_t ETH_ReadDMATxDescFlagStatus(ETH_DMADescConfig_T *DMATxDesc, ETH_DMATXDESC_FLAG_T flag); +uint32_t ETH_ReadDMATxDescCollisionCount(ETH_DMADescConfig_T *DMATxDesc); +void ETH_ConfigDMATxDescOwnBit(ETH_DMADescConfig_T *DMATxDesc); +void ETH_EnableDMATxDescTransmitInterrupt(ETH_DMADescConfig_T *DMATxDesc); +void ETH_DisableDMATxDescTransmitInterrupt(ETH_DMADescConfig_T *DMATxDesc); +void ETH_ConfigDMATxDescFrameSegment(ETH_DMADescConfig_T *DMATxDesc, ETH_DMATXDESC_SEGMENTS_T frameSegment); +void ETH_ConfigDMATxDescChecksumInsertion(ETH_DMADescConfig_T *DMATxDesc, ETH_DMATXDESC_CHECKSUMB_T checksum); +void ETH_EnableDMATxDescCRC(ETH_DMADescConfig_T *DMATxDesc); +void ETH_DisableDMATxDescCRC(ETH_DMADescConfig_T *DMATxDesc); +void ETH_EnableDMATxDescSecondAddressChained(ETH_DMADescConfig_T *DMATxDesc); +void ETH_DisableDMATxDescSecondAddressChained(ETH_DMADescConfig_T *DMATxDesc); +void ETH_EnableDMATxDescShortFramePadding(ETH_DMADescConfig_T *DMATxDesc); +void ETH_DisableDMATxDescShortFramePadding(ETH_DMADescConfig_T *DMATxDesc); +void ETH_ConfigDMATxDescBufferSize(ETH_DMADescConfig_T *DMATxDesc, uint32_t bufferSize1, uint32_t bufferSize2); +uint8_t ETH_ReadDMARxDescFlagStatus(ETH_DMADescConfig_T *DMARxDesc, ETH_DMARXDESC_FLAG_T flag); +#if USE_ENHANCED_DMA_DESCRIPTORS +uint8_t ETH_ReadDMAPTPRxDescExtendedFlagStatus(ETH_DMADescConfig_T *DMAPTPRxDesc, ETH_DMAPTPRXDESC_FLAG_T flag); +#endif +void ETH_ConfigDMARxDescOwnBit(ETH_DMADescConfig_T *DMARxDesc); +uint32_t ETH_ReadDMARxDescFrameLength(ETH_DMADescConfig_T *DMARxDesc); +void ETH_EnableDMARxDescReceiveInterrupt(ETH_DMADescConfig_T *DMARxDesc); +void ETH_DisableDMARxDescReceiveInterrupt(ETH_DMADescConfig_T *DMATxDesc); +uint32_t ETH_ReadDMARxDescBufferSize(ETH_DMADescConfig_T *DMARxDesc, ETH_DMARXDESC_BUFFER_T buffer); +ETH_Frame_T ETH_ReadReceivedFrameInterrupt(void); + +/* DMA */ +uint8_t ETH_ReadDMAFlagStatus(ETH_DMA_FLAG_T flag); +void ETH_ClearDMAFlag(uint32_t flag); +uint8_t ETH_ReadDMAIntFlag(ETH_DMA_INT_T flag); +void ETH_ClearDMAIntFlag(uint32_t flag); +uint32_t ETH_ReadTransmitProcessState(void); +uint32_t ETH_ReadReceiveProcessState(void); +void ETH_FlushTransmitFIFO(void); +uint8_t ETH_ReadFlushTransmitFIFOStatus(void); +void ETH_EnableDMATransmission(void); +void ETH_DisableDMATransmission(void); +void ETH_EnableDMAReceiver(void); +void ETH_DisableDMAReceiver(void); +void ETH_EnableDMAInterrupt(uint32_t interrupt); +void ETH_DisableDMAInterrupt(uint32_t interrupt); +uint8_t ETH_ReadDMAOverflowStatus(ETH_DMA_OVERFLOW_T overflow); +uint32_t ETH_ReadRxOverflowMissedFrameCounter(void); +uint32_t ETH_ReadBufferUnavailableMissedFrameCounter(void); +uint32_t ETH_ReadCurrentTxDescStartAddress(void); +uint32_t ETH_ReadCurrentRxDescStartAddress(void); +uint32_t ETH_ReadCurrentTxBufferAddress(void); +uint32_t ETH_ReadCurrentRxBufferAddress(void); +void ETH_ResetDMATransmission(void); +void ETH_ResetDMAReception(void); +void ETH_ConfigReceiveWatchdogTimer(uint8_t value); + +/* PMT */ +void ETH_ResetWakeUpFrameFilterRegisterPointer(void); +void ETH_ConfigWakeUpFrameFilterRegister(uint32_t *buffer); +void ETH_EnableGlobalUnicastWakeUp(void); +void ETH_DisableGlobalUnicastWakeUp(void); +uint8_t ETH_ReadPMTFlagStatus(ETH_PMT_FLAG_T flag); +void ETH_EnableWakeUpFrameDetection(void); +void ETH_DisableWakeUpFrameDetection(void); +void ETH_EnableMagicPacketDetection(void); +void ETH_DisableMagicPacketDetection(void); +void ETH_EnablePowerDown(void); +void ETH_DisablePowerDown(void); + +/* MMC */ +void ETH_PresetMMCCounterFull(void); +void ETH_PresetMMCCounterHalf(void); +void ETH_EnableMMCCounterFreeze(void); +void ETH_DisableMMCCounterFreeze(void); +void ETH_EnableMMCResetOnRead(void); +void ETH_DisableMMCResetOnRead(void); +void ETH_EnableMMCCounterRollover(void); +void ETH_DisableMMCCounterRollover(void); +void ETH_ResetMMCCounters(void); +void ETH_EnableMMCInterrupt(uint32_t interrupt); +void ETH_DisableMMCInterrupt(uint32_t interrupt); +uint8_t ETH_ReadMMCIntFlag(uint32_t flag); +uint32_t ETH_ReadMMCRegister(ETH_MMC_REG_T MMCReg); + +#ifdef __cplusplus +} +#endif + +#endif /** __APM32F4xx_ETH_H */ + +/**@} end of group ETH_Functions */ +/**@} end of group ETH_Driver */ +/**@} end of group APM32F4xx_ETHDriver */ diff --git a/bsp/apm32/libraries/APM32F4xx_Library/APM32F4xx_ETH_Driver/src/apm32f4xx_eth.c b/bsp/apm32/libraries/APM32F4xx_Library/APM32F4xx_ETH_Driver/src/apm32f4xx_eth.c new file mode 100644 index 0000000000..58ec0c7bf5 --- /dev/null +++ b/bsp/apm32/libraries/APM32F4xx_Library/APM32F4xx_ETH_Driver/src/apm32f4xx_eth.c @@ -0,0 +1,2303 @@ +/*! + * @file apm32f4xx_eth.c + * + * @brief This file provides all the ETH firmware functions + * + * @version V1.0.2 + * + * @date 2022-06-23 + * + * @attention + * + * Copyright (C) 2021-2022 Geehy Semiconductor + * + * You may not use this file except in compliance with the + * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). + * + * The program is only for reference, which is distributed in the hope + * that it will be usefull and instructional for customers to develop + * their software. Unless required by applicable law or agreed to in + * writing, the program is distributed on an "AS IS" BASIS, WITHOUT + * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. + * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions + * and limitations under the License. + */ + +#include "apm32f4xx_eth.h" +#include "apm32f4xx_rcm.h" + +/** @addtogroup APM32F4xx_ETHDriver + @{ +*/ + +/** @defgroup ETH_Driver + * @brief ETH driver modules + @{ +*/ + +#if defined (__CC_ARM) /*!< ARM Compiler */ +__align(4) +ETH_DMADescConfig_T DMARxDscrTab[ETH_RXBUFNB]; /*!< Ethernet Rx MA Descriptor */ +__align(4) +ETH_DMADescConfig_T DMATxDscrTab[ETH_TXBUFNB]; /*!< Ethernet Tx DMA Descriptor */ +__align(4) +uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE]; /*!< Ethernet Receive Buffer */ +__align(4) +uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE]; /*!< Ethernet Transmit Buffer */ + +#elif defined ( __ICCARM__ ) + +ETH_DMADescConfig_T DMARxDscrTab[ETH_RXBUFNB]; /*!< Ethernet Rx MA Descriptor */ +ETH_DMADescConfig_T DMATxDscrTab[ETH_TXBUFNB]; /*!< Ethernet Tx DMA Descriptor */ +uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE]; /*!< Ethernet Receive Buffer */ +uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE]; /*!< Ethernet Transmit Buffer */ + +#endif + +/** @defgroup Global_Definition + @{ +*/ + +/* Global pointers on Tx and Rx descriptor used to transmit and receive descriptors */ +__IO ETH_DMADescConfig_T *DMATxDescToSet; +__IO ETH_DMADescConfig_T *DMARxDescToGet; + +/* Structure used to hold the last received packet descriptors info */ +ETH_DMARxFrameInformations RxFrameDescriptor; +__IO ETH_DMARxFrameInformations *DMARxFraminfos; +__IO uint32_t FrameRxindex; + +/** + * @} + */ + +/** @defgroup ETH_Functions + @{ +*/ + +/*! + * @brief Inserts a delay time. + * + * @param count: specifies the delay time length. + * + * @retval None + */ +static void ETH_Delay(__IO uint32_t count) +{ + __IO uint32_t i = 0; + for(i = count; i!= 0; i--) + { + } +} + +/** ETH Configuration */ + +/*! + * @brief Reset ETH peripheral registers to their default reset values. + * + * @param None + * + * @retval None + */ +void ETH_Reset(void) +{ + RCM_EnableAHB1PeriphReset(RCM_AHB1_PERIPH_ETH_MAC); + RCM_DisableAHB1PeriphReset(RCM_AHB1_PERIPH_ETH_MAC); +} + +/*! + * @brief Config ETH_Config_T member with its default value. + * + * @param ethConfig: pointer to a ETH_Config_T structure which will be initialized. + * + * @retval None + */ +void ETH_ConfigStructInit(ETH_Config_T* ethConfig) +{ + /* MAC Configuration */ + ethConfig->autoNegotiation = ETH_AUTONEGOTIATION_ENABLE; + ethConfig->watchDog = ETH_WATCHDOG_ENABLE; + ethConfig->jabber = ETH_JABBER_ENABLE; + ethConfig->interFrameGap = ETH_INTERFRAMEGAP_96BIT; + ethConfig->carrierSense = ETH_CARRIERSENCE_ENABLE; + ethConfig->speed = ETH_SPEED_100M; + ethConfig->receiveOwn = ETH_RECEIVEOWN_ENABLE; + ethConfig->loopbackMode = ETH_LOOPBACKMODE_DISABLE; + ethConfig->mode = ETH_MODE_FULLDUPLEX; + ethConfig->checksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE; + ethConfig->retryTransmission = ETH_RETRYTRANSMISSION_ENABLE; + ethConfig->automaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE; + ethConfig->backOffLimit = ETH_BACKOFFLIMIT_10; + ethConfig->deferralCheck = ETH_DEFFERRALCHECK_DISABLE; + ethConfig->receiveAll = ETH_RECEIVEAll_DISABLE; + ethConfig->sourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE; + ethConfig->passControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL; + ethConfig->broadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_DISABLE; + ethConfig->destinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL; + ethConfig->promiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE; + ethConfig->multicastFramesFilter = ETH_MULTICASTFRAMESFILTER_PERFECT; + ethConfig->unicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT; + ethConfig->hashTableHigh = 0x0000; + ethConfig->hashTableLow = 0x0000; + ethConfig->pauseTime = 0x0000; + ethConfig->zeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE; + ethConfig->pauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4; + ethConfig->unicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE; + ethConfig->receiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE; + ethConfig->transmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE; + ethConfig->VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT; + ethConfig->VLANTagIdentifier = 0x0000; + /* DMA Configuration */ + ethConfig->dropTCPIPChecksumErrorFrame = ETH_DROPTCPIPCHECKSUMERRORFRAME_DISABLE; + ethConfig->receiveStoreForward = ETH_RECEIVESTOREFORWARD_ENABLE; + ethConfig->flushReceivedFrame = ETH_FLUSHRECEIVEDFRAME_ENABLE; + ethConfig->transmitStoreForward = ETH_TRANSMITSTOREFORWARD_ENABLE; + ethConfig->transmitThresholdControl = ETH_TRANSMITTHRESHOLDCONTROL_64BYTES; + ethConfig->forwardErrorFrames = ETH_FORWARDERRORFRAMES_DISABLE; + ethConfig->forwardUndersizedGoodFrames = ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE; + ethConfig->receiveThresholdControl = ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES; + ethConfig->secondFrameOperate = ETH_SECONDFRAMEOPERARTE_DISABLE; + ethConfig->addressAlignedBeats = ETH_ADDRESSALIGNEDBEATS_ENABLE; + ethConfig->fixedBurst = ETH_FIXEDBURST_ENABLE; + ethConfig->rxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT; + ethConfig->txDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT; + ethConfig->descriptorSkipLength = 0x00; + ethConfig->DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1; +} + +/*! + * @brief Config the ETH peripheral parameters in the ethConfig. + * + * @param ethConfig: pointer to a ETH_Config_T structure. + * + * @param addr: external PHY address + * + * @retval ETH_ERROR: Ethernet initialization error + * ETH_SUCCESS: Ethernet initialization success + */ +uint32_t ETH_Config(ETH_Config_T* ethConfig, uint16_t addr) +{ + uint32_t regValue = 0; + uint32_t hclk = 60000000; + __IO uint32_t timeout = 0, err = ETH_SUCCESS; + + hclk = RCM_ReadHCLKFreq(); + + if((hclk >= 20000000) && (hclk <= 35000000)) + { + ETH->ADDR_B.CR = ETH_MACMIIAR_CR_DIV16; + } + else if((hclk >= 35000000)&&(hclk < 60000000)) + { + ETH->ADDR_B.CR = ETH_MACMIIAR_CR_DIV26; + } + else if((hclk >= 60000000)&&(hclk < 100000000)) + { + ETH->ADDR_B.CR = ETH_MACMIIAR_CR_DIV42; + } + else if((hclk >= 100000000)&&(hclk < 150000000)) + { + ETH->ADDR_B.CR = ETH_MACMIIAR_CR_DIV62; + } + else + { + ETH->ADDR_B.CR = ETH_MACMIIAR_CR_DIV102; + } + + /* PHY initialization and configuration */ + if(!(ETH_WritePHYRegister(addr, PHY_BCR, PHY_RESET))) + { + /* Return ERROR in case of write timeout */ + err = ETH_ERROR; + goto error; + } + + ETH_Delay(PHY_RESET_DELAY); + + if(ethConfig->autoNegotiation == ETH_AUTONEGOTIATION_ENABLE) + { + /* Wait for linked status */ + do + { + timeout++ ; + } while(!(ETH_ReadPHYRegister(addr,PHY_BSR) & PHY_LINKED_STATUS) && (timeout < PHY_READ_TIMEOUT)); + + /* Return ERROR in case of timeout */ + if(timeout == PHY_READ_TIMEOUT) + { + err = ETH_ERROR; + goto error; + } + + timeout = 0; + /* Enable Auto-Negotiation */ + if(!(ETH_WritePHYRegister(addr, PHY_BCR, PHY_AUTONEGOTIATION))) + { + /* Return ERROR in case of write timeout */ + err = ETH_ERROR; + } + + /* Wait until the auto-negotiation will be completed */ + do + { + timeout++; + } while (!(ETH_ReadPHYRegister(addr, PHY_BSR) & PHY_AUTONEGO_COMPLETE) && (timeout < (uint32_t)PHY_READ_TIMEOUT)); + + /* Return ERROR in case of timeout */ + if(timeout == PHY_READ_TIMEOUT) + { + err = ETH_ERROR; + goto error; + } + + timeout = 0; + /* Read the result of the auto-negotiation */ + regValue = ETH_ReadPHYRegister(addr, PHY_SR); + + if((regValue & PHY_DUPLEX_STATUS) != (uint32_t)RESET) + { + ethConfig->mode = ETH_MODE_FULLDUPLEX; + } + else + { + ethConfig->mode = ETH_MODE_HALFDUPLEX; + } + if(regValue & PHY_SPEED_STATUS) + { + ethConfig->speed = ETH_SPEED_10M; + } + else + { + ethConfig->speed = ETH_SPEED_100M; + } + } + else + { + if(!ETH_WritePHYRegister(addr, PHY_BCR,((uint16_t)(ethConfig->speed << 8) | + (uint16_t)(ethConfig->mode << 13)))) + { + err = ETH_ERROR; + } + + ETH_Delay(PHY_CONFIG_DELAY); + } +error: + if(err == ETH_ERROR) + { + ethConfig->speed = ETH_SPEED_100M; + ethConfig->mode = ETH_MODE_FULLDUPLEX; + } + + /* ETHERNET MAC_CFG Configuration */ + ETH->CFG_B.WDTDIS = ethConfig->watchDog; + ETH->CFG_B.JDIS = ethConfig->jabber; + ETH->CFG_B.IFG = ethConfig->interFrameGap; + ETH->CFG_B.DISCRS = ethConfig->carrierSense; + ETH->CFG_B.SSEL = ethConfig->speed; + ETH->CFG_B.DISRXO = ethConfig->receiveOwn; + ETH->CFG_B.LBM = ethConfig->loopbackMode; + ETH->CFG_B.DM = ethConfig->mode; + ETH->CFG_B.IPC = ethConfig->checksumOffload; + ETH->CFG_B.DISR = ethConfig->retryTransmission; + ETH->CFG_B.ACS = ethConfig->automaticPadCRCStrip; + ETH->CFG_B.BL = ethConfig->backOffLimit; + ETH->CFG_B.DC = ethConfig->deferralCheck; + ETH_Delay(ETH_REG_WRITE_DELAY); + + /* ETHERNET MAC_FRAF Configuration */ + ETH->FRAF_B.RXA = ethConfig->receiveAll; + ETH->FRAF |= ethConfig->sourceAddrFilter; + ETH->FRAF_B.PCTRLF = ethConfig->passControlFrames; + ETH->FRAF_B.DISBF = ethConfig->broadcastFramesReception; + ETH->FRAF_B.DAIF = ethConfig->destinationAddrFilter; + ETH->FRAF_B.PR = ethConfig->promiscuousMode; + ETH->FRAF |= ethConfig->multicastFramesFilter; + ETH->FRAF |= ethConfig->unicastFramesFilter; + ETH_Delay(ETH_REG_WRITE_DELAY); + + /* ETHERNET MAC_HTH/HTL Configuration */ + ETH->HTH = ethConfig->hashTableHigh; + ETH->HTL = ethConfig->hashTableLow; + + /* ETHERNET MAC_FCTRL Configuration */ + ETH->FCTRL_B.PT = ethConfig->pauseTime; + ETH->FCTRL_B.ZQPDIS = ethConfig->zeroQuantaPause; + ETH->FCTRL_B.PTSEL = ethConfig->pauseLowThreshold; + ETH->FCTRL_B.UNPFDETE = ethConfig->unicastPauseFrameDetect; + ETH->FCTRL_B.RXFCTRLEN = ethConfig->receiveFlowControl; + ETH->FCTRL_B.TXFCTRLEN = ethConfig->transmitFlowControl; + ETH_Delay(ETH_REG_WRITE_DELAY); + + /* ETHERNET MAC_VLANT Configuration */ + ETH->VLANT_B.VLANTCOMP = ethConfig->VLANTagComparison; + ETH->VLANT_B.VLANTID = ethConfig->VLANTagIdentifier; + ETH_Delay(ETH_REG_WRITE_DELAY); + + /* ETHERNET DMA_OPMOD Configuration */ + ETH->DMAOPMOD_B.DISDT = ethConfig->dropTCPIPChecksumErrorFrame; + ETH->DMAOPMOD_B.RXSF = ethConfig->receiveStoreForward; + ETH->DMAOPMOD_B.DISFRXF = ethConfig->flushReceivedFrame; + ETH->DMAOPMOD_B.TXSF = ethConfig->transmitStoreForward; + ETH->DMAOPMOD_B.TXTHCTRL = ethConfig->transmitThresholdControl; + ETH->DMAOPMOD_B.FERRF = ethConfig->forwardErrorFrames; + ETH->DMAOPMOD_B.FUF = ethConfig->forwardUndersizedGoodFrames; + ETH->DMAOPMOD_B.RXTHCTRL = ethConfig->receiveThresholdControl; + ETH->DMAOPMOD_B.OSECF = ethConfig->secondFrameOperate; + ETH_Delay(ETH_REG_WRITE_DELAY); + + /* ETHERNET DMA_BMOD Configuration */ + ETH->DMABMOD = RESET; + ETH->DMABMOD_B.AAL = ethConfig->addressAlignedBeats; + ETH->DMABMOD_B.FB = ethConfig->fixedBurst; + ETH->DMABMOD |= ethConfig->rxDMABurstLength; + ETH->DMABMOD |= ethConfig->txDMABurstLength; + ETH->DMABMOD_B.DSL = ethConfig->descriptorSkipLength; + ETH->DMABMOD |= ethConfig->DMAArbitration; + ETH->DMABMOD_B.USP = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); + +#if USE_ENHANCED_DMA_DESCRIPTORS + ETH->DMABMOD_B.EDFEN = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +#endif + + if(err == ETH_SUCCESS) + { + return ETH_SUCCESS; + } + else + { + return ETH_ERROR; + } +} + +/*! + * @brief Resets all MAC subsystem internal registers and logic. + * + * @param None + * + * @retval None + */ +void ETH_SoftwareReset(void) +{ + ETH->DMABMOD_B.SWR = SET; +} + +/*! + * @brief Read the ETH software reset bit. + * + * @param None + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadSoftwareReset(void) +{ + return ETH->DMABMOD_B.SWR; +} + +/*! + * @brief Enables ETH MAC and DMA reception/transmission + * + * @param None + * + * @retval None + */ +void ETH_Start(void) +{ + ETH_EnableMACTransmission(); + ETH_EnableMACReceiver(); + ETH_FlushTransmitFIFO(); + ETH_EnableDMATransmission(); + ETH_EnableDMAReceiver(); +} + +/*! + * @brief Disables ETH MAC and DMA reception/transmission + * + * @param None + * + * @retval None + */ +void ETH_Stop(void) +{ + ETH_DisableDMATransmission(); + ETH_DisableDMAReceiver(); + ETH_DisableMACReceiver(); + ETH_FlushTransmitFIFO(); + ETH_DisableMACTransmission(); +} + +/*! + * @brief Read the size of the received packet. + * + * @param None + * + * @retval frameLength: received packet size + */ +uint32_t ETH_ReadRxPacketSize(ETH_DMADescConfig_T *DMARxDesc) +{ + uint32_t frameLength = 0; + if(((DMARxDesc->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET) && + ((DMARxDesc->Status & ETH_DMARXDESC_ERRS) == (uint32_t)RESET) && + ((DMARxDesc->Status & ETH_DMARXDESC_LDES) != (uint32_t)RESET)) + { + frameLength = ETH_ReadDMARxDescFrameLength(DMARxDesc); + } + return frameLength; +} + +#if USE_ENHANCED_DMA_DESCRIPTORS +/*! + * @brief Enable the Enhanced descriptor structure. + * + * @param None + * + * @retval None + */ +void ETH_EnableEnhancedDescriptor(void) +{ + ETH->DMABMOD_B.EDFEN = SET; +} + +/*! + * @brief Disable the Enhanced descriptor structure. + * + * @param None + * + * @retval None + */ +void ETH_DisableEnhancedDescriptor(void) +{ + ETH->DMABMOD_B.EDFEN = RESET; +} +#endif /** USE_ENHANCED_DMA_DESCRIPTORS */ + +/** PHY functions */ + +/*! + * @brief Read a PHY register + * + * @param addr: PHY device address + * This parameter can be one of the following values: 0,..,31 + * + * @param reg: PHY register + * This parameter can be one of the following values: + * @arg PHY_BCR : Transceiver Basic Control Register + * @arg PHY_BSR : Transceiver Basic Status Register + * @arg PHY_SR : Transceiver Status Register + * + * @retval ETH_ERROR: in case of timeout + * MAC DATA register value: Data read from the selected PHY register + */ +uint16_t ETH_ReadPHYRegister(uint16_t addr, uint16_t reg) +{ + __IO uint32_t timeout = 0; + + ETH->ADDR_B.PA = addr; + ETH->ADDR_B.MR = reg; + ETH->ADDR_B.MW = RESET; + ETH->ADDR_B.MB = SET; + /* Check for the Busy flag */ + do + { + timeout++ ; + } while ((ETH->ADDR_B.MB == SET) && (timeout < PHY_READ_TIMEOUT)); + /* Return ERROR in case of timeout */ + if(timeout == PHY_READ_TIMEOUT) + { + return ETH_ERROR; + } + /* Return data register value */ + return (uint16_t)(ETH->DATA); +} + +/*! + * @brief Write to a PHY register + * + * @param addr: PHY device address + * This parameter can be one of the following values: 0,..,31 + + * @param reg: PHY register + * This parameter can be one of the following values: + * @arg PHY_BCR : Transceiver Basic Control Register + + * @param data: the data to write + * + * @retval ETH_ERROR: write timeout + * ETH_SUCCESS: write success + */ +uint32_t ETH_WritePHYRegister(uint16_t addr, uint16_t reg, uint16_t data) +{ + __IO uint32_t timeout = 0; + + ETH->DATA = data; + ETH->ADDR_B.PA = addr; + ETH->ADDR_B.MR = reg; + ETH->ADDR_B.MW = SET; + ETH->ADDR_B.MB = SET; + + /* Check for the Busy flag */ + do + { + timeout++ ; + } while ((ETH->ADDR_B.MB == SET) && (timeout < PHY_WRITE_TIMEOUT)); + /* Return ERROR in case of timeout */ + if(timeout == PHY_WRITE_TIMEOUT) + { + return ETH_ERROR; + } + /* Return data register value */ + return ETH_SUCCESS; +} + +/*! + * @brief Enable the PHY loopBack mode. + * + * @param addr: PHY device address + * This parameter can be one of the following values: 0,..,31 + * + * @retval ETH_ERROR or ETH_SUCCESS + */ +uint32_t ETH_EnablePHYLoopBack(uint16_t addr) +{ + uint16_t temp = 0; + + temp = ETH_ReadPHYRegister(addr,PHY_BCR); + temp |= PHY_LOOPBACK; + + if(ETH_WritePHYRegister(addr,PHY_BCR,temp) == SET) + { + return ETH_SUCCESS; + } + else + { + return ETH_ERROR; + } +} + +/*! + * @brief Disable the PHY loopBack mode. + * + * @param addr: PHY device address + * This parameter can be one of the following values: 0,..,31 + * + * @retval ETH_ERROR or ETH_SUCCESS + */ +uint32_t ETH_DisablePHYLoopBack(uint16_t addr) +{ + uint16_t temp = 0; + + temp = ETH_ReadPHYRegister(addr,PHY_BCR); + temp &= ((uint16_t)~PHY_LOOPBACK); + + if(ETH_WritePHYRegister(addr,PHY_BCR,temp) == SET) + { + return ETH_SUCCESS; + } + else + { + return ETH_ERROR; + } +} + +/* MAC functions */ + +/*! + * @brief Enable the MAC transmission. + * + * @param None + * + * @retval None + */ +void ETH_EnableMACTransmission(void) +{ + ETH->CFG_B.TXEN = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable the MAC transmission. + * + * @param None + * + * @retval None + */ +void ETH_DisableMACTransmission(void) +{ + ETH->CFG_B.TXEN = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Enable the MAC receiver. + * + * @param None + * + * @retval None + */ +void ETH_EnableMACReceiver(void) +{ + ETH->CFG_B.RXEN = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable the MAC receiver. + * + * @param None + * + * @retval None + */ +void ETH_DisableMACReceiver(void) +{ + ETH->CFG_B.RXEN = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Read the ETH flow control busy status + * + * @param None + * + * @retval SET or RESET + */ +uint8_t ETH_ReadFlowControlBusyStatus(void) +{ + return ETH->FCTRL_B.FCTRLB; +} + +/*! + * @brief Set a Pause Control Frame (Full-duplex only). + * + * @param None + * + * @retval None + */ +void ETH_SetPauseControlFrame(void) +{ + ETH->FCTRL_B.FCTRLB = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Enable the MAC Back Pressure operation activation (Half-duplex only). + * + * @param None + * + * @retval None + */ +void ETH_EnableBackPressureActivation(void) +{ + ETH->FCTRL_B.FCTRLB = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable the MAC Back Pressure operation activation (Half-duplex only). + * + * @param None + * + * @retval None + */ +void ETH_DisableBackPressureActivation(void) +{ + ETH->FCTRL_B.FCTRLB = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Read the specified ETH MAC flag + * + * @param flag: Ethernet MAC flag: + * This parameter can be one of the following values: + * @arg ETH_MAC_FLAG_TST : Time stamp trigger flag + * @arg ETH_MAC_FLAG_MMCT : MMC transmit flag + * @arg ETH_MAC_FLAG_MMCR : MMC receive flag + * @arg ETH_MAC_FLAG_MMC : MMC flag + * @arg ETH_MAC_FLAG_PMT : PMT flag + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadMACFlagStatus(ETH_MAC_FLAG_T flag) +{ + return (ETH->ISTS & flag) ? SET : RESET; +} + +/*! + * @brief Enable the specified ETH MAC interrupts. + * + * @param interrupt: Ethernet MAC interrupt flag: + * 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 + * + * @retval None + */ +void ETH_EnableMACInterrupt(uint32_t interrupt) +{ + ETH->IMASK |= interrupt; +} + +/*! + * @brief Disable the specified ETH MAC interrupts. + * + * @param interrupt: Ethernet MAC interrupt flag: + * 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 + * + * @retval None + */ +void ETH_DisableMACInterrupt(uint32_t interrupt) +{ + ETH->IMASK &= (~(uint32_t)interrupt); +} + +/*! + * @brief Config the MAC address. + * + * @param macAddr: The MAC address. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDRESS0 : MAC Address0 + * @arg ETH_MAC_ADDRESS1 : MAC Address1 + * @arg ETH_MAC_ADDRESS2 : MAC Address2 + * @arg ETH_MAC_ADDRESS3 : MAC Address3 + * + * @param addr: Pointer on MAC address buffer data (6 bytes). + * + * @retval None + */ +void ETH_ConfigMACAddress(ETH_MAC_ADDRESS_T macAddr, uint8_t *addr) +{ + uint32_t temp; + + temp = ((uint32_t)addr[5] << 8) | (uint32_t)addr[4]; + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + macAddr)) = temp; + + temp = ((uint32_t)addr[3] << 24) | ((uint32_t)addr[2] << 16) | ((uint32_t)addr[1] << 8) | addr[0]; + (*(__IO uint32_t *) (ETH_MAC_ADDR_LBASE + macAddr)) = temp; +} + +/*! + * @brief Read the MAC address. + * + * @param macAddr: The MAC address. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDRESS0 : MAC Address0 + * @arg ETH_MAC_ADDRESS1 : MAC Address1 + * @arg ETH_MAC_ADDRESS2 : MAC Address2 + * @arg ETH_MAC_ADDRESS3 : MAC Address3 + * + * @param addr: Pointer on MAC address buffer data (6 bytes). + * + * @retval None + */ +void ETH_ReadMACAddress(ETH_MAC_ADDRESS_T macAddr, uint8_t *addr) +{ + uint32_t temp; + + temp = (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + macAddr)); + + addr[5] = ((temp >> 8) & 0xFF); + addr[4] = (temp & 0xFF); + + temp = (*(__IO uint32_t *) (ETH_MAC_ADDR_LBASE + macAddr)); + addr[3] = ((temp >> 24) & 0xFF); + addr[2] = ((temp >> 16) & 0xFF); + addr[1] = ((temp >> 8) & 0xFF); + addr[0] = (temp & 0xFF); +} + +/*! + * @brief Enable address filters module uses the MAC address for perfect filtering. + * + * @param macAddr: The MAC address. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDRESS1 : MAC Address1 + * @arg ETH_MAC_ADDRESS2 : MAC Address2 + * @arg ETH_MAC_ADDRESS3 : MAC Address3 + * + * @retval None + */ +void ETH_EnableMACAddressPerfectFilter(ETH_MAC_ADDRESS_T macAddr) +{ + __IO uint32_t temp = 0; + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + macAddr)) |= BIT31; + ETH_Delay(ETH_REG_WRITE_DELAY); + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + macAddr)) = temp; +} + +/*! + * @brief Disable address filters module uses the MAC address for perfect filtering. + * + * @param macAddr: The MAC address. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDRESS1 : MAC Address1 + * @arg ETH_MAC_ADDRESS2 : MAC Address2 + * @arg ETH_MAC_ADDRESS3 : MAC Address3 + * + * @retval None + */ +void ETH_DisableMACAddressPerfectFilter(ETH_MAC_ADDRESS_T macAddr) +{ + __IO uint32_t temp = 0; + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + macAddr)) &= (~BIT31); + ETH_Delay(ETH_REG_WRITE_DELAY); + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + macAddr)) = temp; +} + +/*! + * @brief Config the filter type for the MAC address + * + * @param macAddr: The MAC address. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDRESS1 : MAC Address1 + * @arg ETH_MAC_ADDRESS2 : MAC Address2 + * @arg ETH_MAC_ADDRESS3 : MAC Address3 + * + * @param filter: Comparison with the SA/DA fields of the received frame. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDRESSFILTER_SA : MAC Address is used to compare with the + * SA fields of the received frame. + * @arg ETH_MAC_ADDRESSFILTER_DA : MAC Address is used to compare with the + * DA fields of the received frame. + * @retval None + */ +void ETH_ConfigMACAddressFilter(ETH_MAC_ADDRESS_T macAddr, ETH_MAC_ADDRESSFILTER_T filter) +{ + if(filter == ETH_MAC_ADDRESSFILTER_SA) + { + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + macAddr)) |= ETH_MAC_ADDRESSFILTER_SA; + } + else + { + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + macAddr)) |= ETH_MAC_ADDRESSFILTER_DA; + } + +} + +/*! + * @brief Config the filter type for the ETH MAC address. + * + * @param macAddr: The MAC address. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDRESS1 : MAC Address1 + * @arg ETH_MAC_ADDRESS2 : MAC Address2 + * @arg ETH_MAC_ADDRESS3 : MAC Address3 + * + * @param MaskByte: specifies the used address bytes for comparison + * This parameter can be any combination of the following values: + * @arg ETH_MAC_ADDRESSMASK_BYTE6 : Mask MAC Address high reg bits [15:8]. + * @arg ETH_MAC_ADDRESSMASK_BYTE5 : Mask MAC Address high reg bits [7:0]. + * @arg ETH_MAC_ADDRESSMASK_BYTE4 : Mask MAC Address low reg bits [31:24]. + * @arg ETH_MAC_ADDRESSMASK_BYTE3 : Mask MAC Address low reg bits [23:16]. + * @arg ETH_MAC_ADDRESSMASK_BYTE2 : Mask MAC Address low reg bits [15:8]. + * @arg ETH_MAC_ADDRESSMASK_BYTE1 : Mask MAC Address low reg bits [7:0]. + * + * @retval None + */ +void ETH_ConfigMACAddressMaskBytesFilter(ETH_MAC_ADDRESS_T macAddr, uint32_t maskByte) +{ + __IO uint32_t temp = 0; + + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + macAddr)) &=(~(uint32_t)0x3F000000); + + temp = (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + macAddr)); + ETH_Delay(ETH_REG_WRITE_DELAY); + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + macAddr)) = temp; + + /* Set the selected Filter mask bytes */ + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + macAddr)) |= maskByte; + + temp = (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + macAddr)); + ETH_Delay(ETH_REG_WRITE_DELAY); + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + macAddr)) = temp; +} + +/** DMA Descriptors functions */ + +/*! + * @brief Config 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 rxBuffcount: Number of the used Rx desc in the list + * + * @retval None + */ +void ETH_ConfigDMARxDescChain(ETH_DMADescConfig_T *DMARxDescTab, uint8_t *rxBuff, uint32_t rxBuffcount) +{ + uint32_t i = 0; + ETH_DMADescConfig_T *DMARxDesc; + DMARxDescToGet = DMARxDescTab; + + for(i=0; i< rxBuffcount; i++) + { + DMARxDesc = DMARxDescTab+i; + DMARxDesc->Status = ETH_DMARXDESC_OWN; + DMARxDesc->ControlBufferSize = ETH_DMARXDESC_RXCH | ETH_RX_BUF_SIZE; + DMARxDesc->Buffer1Addr = (uint32_t)(&rxBuff[i*ETH_RX_BUF_SIZE]); + if(i < (rxBuffcount-1)) + { + DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab+i+1); + } + else + { + DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab); + } + } + + + ETH->DMARXDLADDR = (uint32_t) DMARxDescTab; + DMARxFraminfos =&RxFrameDescriptor; +} + +/*! + * @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 txBuffcount: Number of the used Tx desc in the list + * + * @retval None + */ +void ETH_ConfigDMATxDescChain(ETH_DMADescConfig_T *DMATxDescTab, uint8_t* txBuff, uint32_t txBuffcount) +{ + uint32_t i = 0; + ETH_DMADescConfig_T *DMATxDesc; + DMATxDescToSet = DMATxDescTab; + + for(i=0; i< txBuffcount; i++) + { + DMATxDesc = DMATxDescTab+i; + DMATxDesc->Status = ETH_DMATXDESC_TXCH; + DMATxDesc->Buffer1Addr = (uint32_t)(&txBuff[i*ETH_TX_BUF_SIZE]); + if(i < (txBuffcount-1)) + { + DMATxDesc->Buffer2NextDescAddr = (uint32_t)(DMATxDescTab+i+1); + } + else + { + DMATxDesc->Buffer2NextDescAddr = (uint32_t)(DMATxDescTab); + } + } + + ETH->DMATXDLADDR = (uint32_t) DMATxDescTab; +} + +/*! + * @brief This function polls for a frame receiver + * + * @param None + * + * @retval Returns 1 when a frame is received, 0 if none. + */ +uint32_t ETH_CheckReceivedFrame(void) +{ + if(((DMARxDescToGet->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARXDESC_LDES) != (uint32_t)RESET)) + { + DMARxFraminfos->segCount++; + if(DMARxFraminfos->segCount == 1) + { + DMARxFraminfos->FS_RxDesc = DMARxDescToGet; + } + DMARxFraminfos->LS_RxDesc = DMARxDescToGet; + return 1; + } + else if(((DMARxDescToGet->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARXDESC_FDES) != (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARXDESC_LDES) == (uint32_t)RESET)) + { + DMARxFraminfos->FS_RxDesc = DMARxDescToGet; + DMARxFraminfos->LS_RxDesc = NULL; + DMARxFraminfos->segCount = 1; + DMARxDescToGet = (ETH_DMADescConfig_T*) (DMARxDescToGet->Buffer2NextDescAddr); + } + else if(((DMARxDescToGet->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARXDESC_FDES) == (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARXDESC_LDES) == (uint32_t)RESET)) + { + (DMARxFraminfos->segCount) ++; + DMARxDescToGet = (ETH_DMADescConfig_T*) (DMARxDescToGet->Buffer2NextDescAddr); + } + return 0; +} + +/*! + * @brief Prepares DMA Tx descriptors to transmit an ethernet frame + * + * @param FrameLength : length of the frame to send + * + * @retval ETH_ERROR or ETH_SUCCESS + */ +uint32_t ETH_Transmit_Descriptors(u16 frameLength) +{ + uint32_t count=0, size=0, i=0; + __IO ETH_DMADescConfig_T *DMATxDesc; + + if((DMATxDescToSet->Status & ETH_DMATXDESC_OWN) == SET) + { + return ETH_ERROR; + } + + DMATxDesc = DMATxDescToSet; + + if(frameLength > ETH_TX_BUF_SIZE) + { + count = frameLength/ETH_TX_BUF_SIZE; + if(frameLength%ETH_TX_BUF_SIZE) count++; + } + else count =1; + + if(count == 1) + { + DMATxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS; + DMATxDesc->ControlBufferSize = (frameLength & ETH_DMATXDESC_TXBS1); + DMATxDesc->Status |= ETH_DMATXDESC_OWN; + DMATxDesc = (ETH_DMADescConfig_T*) (DMATxDesc->Buffer2NextDescAddr); + } + else + { + for(i=0; iStatus &= ~(ETH_DMATXDESC_FS | ETH_DMATXDESC_LS); + + if(i==0) + { + DMATxDesc->Status |= ETH_DMATXDESC_FS; + } + DMATxDesc->ControlBufferSize =(ETH_TX_BUF_SIZE & ETH_DMATXDESC_TXBS1); + + if(i== (count-1)) + { + DMATxDesc->Status |= ETH_DMATXDESC_LS; + size = frameLength - (count-1)*ETH_TX_BUF_SIZE; + DMATxDesc->ControlBufferSize =(size & ETH_DMATXDESC_TXBS1); + } + + DMATxDesc->Status |= ETH_DMATXDESC_OWN; + DMATxDesc = (ETH_DMADescConfig_T*) (DMATxDesc->Buffer2NextDescAddr); + } + } + DMATxDescToSet = DMATxDesc; + + if(ETH->DMASTS_B.TXBU == SET) + { + ETH->DMASTS = BIT2; + ETH->DMATXPD = 0; + } + + return ETH_SUCCESS; +} + +/*! + * @brief Read the received frame. + * + * @param none + * + * @retval Structure of type ETH_Frame_T + */ +ETH_Frame_T ETH_ReadReceivedFrame(void) +{ + uint32_t frameLength = 0; + ETH_Frame_T frame = {0,0,0}; + + frameLength = ((DMARxDescToGet->Status & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAMELENGTHSHIFT) - 4; + frame.length = frameLength; + + frame.descriptor = DMARxFraminfos->FS_RxDesc; + frame.buffer = (DMARxFraminfos->FS_RxDesc)->Buffer1Addr; + DMARxDescToGet = (ETH_DMADescConfig_T*) (DMARxDescToGet->Buffer2NextDescAddr); + + return(frame); +} + +/*! + * @brief Read ETH DMA Tx Descriptor flag. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @param flag: Specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_DMATXDESC_OWN : Descriptor is owned by DMA engine + * @arg ETH_DMATXDESC_INTC : Interrupt on completion + * @arg ETH_DMATXDESC_LS : Last Segment + * @arg ETH_DMATXDESC_FS : First Segment + * @arg ETH_DMATXDESC_DISC : Disable CRC + * @arg ETH_DMATXDESC_DISP : Disable Pad + * @arg ETH_DMATXDESC_TXTSEN: Transmit Time Stamp Enable + * @arg ETH_DMATXDESC_TXENDR: Transmit End of Ring + * @arg ETH_DMATXDESC_TXCH : Second Address Chained + * @arg ETH_DMATXDESC_TXTSS : Tx Time Stamp Status + * @arg ETH_DMATXDESC_IHERR : IP Header Error + * @arg ETH_DMATXDESC_ERRS : Error summary + * @arg ETH_DMATXDESC_JTO : Jabber Timeout + * @arg ETH_DMATXDESC_FF : Frame Flushed: DMA/MTL flushed the frame due to SW flush + * @arg ETH_DMATXDESC_IPERR : Payload Checksum Error + * @arg ETH_DMATXDESC_LSC : Loss of Carrier: carrier lost during transmission + * @arg ETH_DMATXDESC_NC : No Carrier: no carrier signal from the transceiver + * @arg ETH_DMATXDESC_LC : Late Collision: transmission aborted due to collision + * @arg ETH_DMATXDESC_EC : Excessive Collision: transmission aborted after 16 collisions + * @arg ETH_DMATXDESC_VLANF : VLAN Frame + * @arg ETH_DMATXDESC_CCNT : Collision Count + * @arg ETH_DMATXDESC_EDEF : Excessive Deferral + * @arg ETH_DMATXDESC_UFERR : Underflow Error: late data arrival from the memory + * @arg ETH_DMATXDESC_DEF : Deferred Bit + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadDMATxDescFlagStatus(ETH_DMADescConfig_T *DMATxDesc, ETH_DMATXDESC_FLAG_T flag) +{ + return (DMATxDesc->Status & flag) ? SET : RESET; +} + +/*! + * @brief Returns ETH DMA Tx Descriptor collision count. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval The Transmit descriptor collision counter value. + */ +uint32_t ETH_ReadDMATxDescCollisionCount(ETH_DMADescConfig_T *DMATxDesc) +{ + return ((DMATxDesc->Status & ETH_DMATXDESC_CCNT) >> ETH_DMATXDESC_COLLISION_COUNTSHIFT); +} + +/*! + * @brief Config the ETH DMA Tx Descriptor Own bit. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_ConfigDMATxDescOwnBit(ETH_DMADescConfig_T *DMATxDesc) +{ + DMATxDesc->Status |= ETH_DMATXDESC_OWN; +} + +/*! + * @brief Enable the ETH DMA Tx Descriptor Transmit interrupt. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_EnableDMATxDescTransmitInterrupt(ETH_DMADescConfig_T *DMATxDesc) +{ + DMATxDesc->Status |= ETH_DMATXDESC_INTC; +} + +/*! + * @brief Disable the ETH DMA Tx Descriptor Transmit interrupt. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_DisableDMATxDescTransmitInterrupt(ETH_DMADescConfig_T *DMATxDesc) +{ + DMATxDesc->Status &= (~(uint32_t)ETH_DMATXDESC_INTC); +} + +/*! + * @brief Config Tx descriptor as last or first segment + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @param frameSegment: Tx desc contain last or first segment. + * This parameter can be one of the following values: + * @arg ETH_DMATXDESC_LASTSEGMENTS : Actual Tx desc contain last segment + * @arg ETH_DMATXDESC_FIRSTSEGMENT : Actual Tx desc contain first segment + * + * @retval None + */ +void ETH_ConfigDMATxDescFrameSegment(ETH_DMADescConfig_T *DMATxDesc, ETH_DMATXDESC_SEGMENTS_T frameSegment) +{ + DMATxDesc->Status |= frameSegment; +} +/*! + * @brief Config ETH DMA Tx Desc Checksum Insertion. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @param checksum: specifies is the DMA Tx desc checksum insertion. + * This parameter can be one of the following values: + * @arg ETH_DMATXDESC_CHECKSUMBYPASS : Checksum bypass + * @arg ETH_DMATXDESC_CHECKSUMIPV4HEADER : IPv4 header checksum + * @arg ETH_DMATXDESC_CHECKSUMTCPUDPICMPSEGMENT : TCP/UDP/ICMP checksum. Pseudo header checksum is assumed to be present + * @arg ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL : TCP/UDP/ICMP checksum fully in hardware including pseudo header + * + * @retval None + */ +void ETH_ConfigDMATxDescChecksumInsertion(ETH_DMADescConfig_T *DMATxDesc, ETH_DMATXDESC_CHECKSUMB_T checksum) +{ + DMATxDesc->Status |= checksum; +} + +/*! + * @brief Enable the DMA Tx Desc CRC. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_EnableDMATxDescCRC(ETH_DMADescConfig_T *DMATxDesc) +{ + DMATxDesc->Status &= (~(uint32_t)ETH_DMATXDESC_DISC); +} + +/*! + * @brief Disable the DMA Tx Desc CRC. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_DisableDMATxDescCRC(ETH_DMADescConfig_T *DMATxDesc) +{ + DMATxDesc->Status |= ETH_DMATXDESC_DISC; +} + +/*! + * @brief Enable the DMA Tx Desc second address chained. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_EnableDMATxDescSecondAddressChained(ETH_DMADescConfig_T *DMATxDesc) +{ + DMATxDesc->Status |= ETH_DMATXDESC_TXCH; +} + +/*! + * @brief Disable the DMA Tx Desc second address chained. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_DisableDMATxDescSecondAddressChained(ETH_DMADescConfig_T *DMATxDesc) +{ + DMATxDesc->Status &=(~(uint32_t)ETH_DMATXDESC_TXCH); +} + +/*! + * @brief Enable the DMA Tx Desc padding for frame shorter than 64 bytes. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_EnableDMATxDescShortFramePadding(ETH_DMADescConfig_T *DMATxDesc) +{ + DMATxDesc->Status &= (~(uint32_t)ETH_DMATXDESC_DISP); +} + +/*! + * @brief Disable the DMA Tx Desc padding for frame shorter than 64 bytes. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @retval None + */ +void ETH_DisableDMATxDescShortFramePadding(ETH_DMADescConfig_T *DMATxDesc) +{ + DMATxDesc->Status |= ETH_DMATXDESC_DISP; +} + +/*! + * @brief Config the ETH DMA Tx Desc buffer1 and buffer2 sizes. + * + * @param DMATxDesc: pointer on a DMA Tx descriptor + * + * @param bufferSize1: specifies the Tx desc buffer1 size. + * + * @param bufferSize2: specifies the Tx desc buffer2 size. + * + * @retval None + */ +void ETH_ConfigDMATxDescBufferSize(ETH_DMADescConfig_T *DMATxDesc, uint32_t bufferSize1, uint32_t bufferSize2) +{ + DMATxDesc->ControlBufferSize |= (bufferSize1 | (bufferSize2 << ETH_DMATXDESC_BUFFER2_SIZESHIFT)); +} + +/*! + * @brief Checks whether the specified ETHERNET Rx Desc flag is set or not. + * + * @param DMARxDesc: pointer on a DMA Rx descriptor + + * @param flag: specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_DMARXDESC_OWN : Descriptor is owned by DMA engine + * @arg ETH_DMARXDESC_ADDRF : DA Filter Fail for the rx frame + * @arg ETH_DMARXDESC_ERRS : Error summary + * @arg ETH_DMARXDESC_DESERR : Descriptor error: no more descriptors for receive frame + * @arg ETH_DMARXDESC_SADDRF : SA Filter Fail for the received frame + * @arg ETH_DMARXDESC_LERR : Frame size not matching with length field + * @arg ETH_DMARXDESC_OFERR : Overflow Error: Frame was damaged due to buffer overflow + * @arg ETH_DMARXDESC_VLANF : VLAN Tag: received frame is a VLAN frame + * @arg ETH_DMARXDESC_FDES : First descriptor of the frame + * @arg ETH_DMARXDESC_LDES : Last descriptor of the frame + * @arg ETH_DMARXDESC_IPV4HCE: IPC Checksum Error/Giant Frame: Rx Ipv4 header checksum error + * @arg ETH_DMARXDESC_LC : Late collision occurred during reception + * @arg ETH_DMARXDESC_FT : Frame type - Ethernet, otherwise 802.3 + * @arg ETH_DMARXDESC_RXWDTTO: Receive Watchdog Timeout: watchdog timer expired during reception + * @arg ETH_DMARXDESC_RERR : Receive error: error reported by MII interface + * @arg ETH_DMARXDESC_DERR : Dribble bit error: frame contains non int multiple of 8 bits + * @arg ETH_DMARXDESC_CERR : CRC error + * @arg ETH_DMARXDESC_MAMPCE : Rx MAC Address/Payload Checksum Error: Rx MAC address matched/ Rx Payload Checksum Error + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadDMARxDescFlagStatus(ETH_DMADescConfig_T *DMARxDesc, ETH_DMARXDESC_FLAG_T flag) +{ + return (DMARxDesc->Status & flag) ? SET : RESET; +} + +#if USE_ENHANCED_DMA_DESCRIPTORS +/*! + * @brief Checks whether the specified ETHERNET PTP Rx Desc extended flag is set or not. + * + * @param DMAPTPRxDesc: pointer on a DMA PTP Rx descriptor + * + * @param flag: specifies the extended flag to check. + * This parameter can be one of the following values: + * @arg ETH_DMAPTPRXDESC_PTPV : PTP version + * @arg ETH_DMAPTPRXDESC_PTPFT : PTP frame type + * @arg ETH_DMAPTPRXDESC_PTPMT : PTP message type + * @arg ETH_DMAPTPRXDESC_IPV6P : IPv6 packet received + * @arg ETH_DMAPTPRXDESC_IPV4P : IPv4 packet received + * @arg ETH_DMAPTPRXDESC_IPCBP : IP checksum bypassed + * @arg ETH_DMAPTPRXDESC_IPPERR: IP payload error + * @arg ETH_DMAPTPRXDESC_IPHERR: IP header error + * @arg ETH_DMAPTPRXDESC_IPPT : IP payload type + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadDMAPTPRxDescExtendedFlagStatus(ETH_DMADescConfig_T *DMAPTPRxDesc, ETH_DMAPTPRXDESC_FLAG_T flag) +{ + return (DMAPTPRxDesc->Status & flag) ? SET : RESET; +} +#endif + +/*! + * @brief Config the ETH DMA Rx Desc Own bit. + * + * @param DMARxDesc: pointer on a DMA Rx descriptor + * + * @retval None + */ +void ETH_ConfigDMARxDescOwnBit(ETH_DMADescConfig_T *DMARxDesc) +{ + DMARxDesc->Status |= ETH_DMARXDESC_OWN; +} + +/*! + * @brief Returns the ETH DMA Rx descriptor frame length. + * + * @param DMARxDesc: pointer on a DMA Rx descriptor + * + * @retval The Rx descriptor received frame length. + */ +uint32_t ETH_ReadDMARxDescFrameLength(ETH_DMADescConfig_T *DMARxDesc) +{ + return ((DMARxDesc->Status & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAME_LENGTHSHIFT); +} + +/*! + * @brief Enable the ETH DMA Rx Desc receive interrupt. + * + * @param DMARxDesc: pointer on a DMA Rx descriptor + * + * @retval None + */ +void ETH_EnableDMARxDescReceiveInterrupt(ETH_DMADescConfig_T *DMARxDesc) +{ + DMARxDesc->ControlBufferSize &=(~(uint32_t)ETH_DMARXDESC_DINTC); +} + +/*! + * @brief Disable the ETH DMA Rx Desc receive interrupt. + * + * @param DMARxDesc: pointer on a DMA Rx descriptor + * + * @retval None + */ +void ETH_DisableDMARxDescReceiveInterrupt(ETH_DMADescConfig_T *DMARxDesc) +{ + DMARxDesc->ControlBufferSize |= ETH_DMARXDESC_DINTC; +} + +/*! + * @brief Returns the ETH DMA Rx Desc buffer size. + * + * @param DMARxDesc: pointer on a DMA Rx descriptor + * + * @param buffer: specifies the DMA Rx Desc buffer. + * This parameter can be one of the following values: + * @arg ETH_DMARxDesc_Buffer1 : DMA Rx Desc Buffer1 + * @arg ETH_DMARxDesc_Buffer2 : DMA Rx Desc Buffer2 + * + * @retval The Receive descriptor frame length. + */ +uint32_t ETH_ReadDMARxDescBufferSize(ETH_DMADescConfig_T *DMARxDesc, ETH_DMARXDESC_BUFFER_T buffer) +{ + if(buffer == ETH_DMARXDESC_BUFFER1) + { + return (DMARxDesc->ControlBufferSize & ETH_DMARXDESC_RXBS1); + } + else + { + return ((DMARxDesc->ControlBufferSize & ETH_DMARXDESC_RXBS2) >> ETH_DMARXDESC_BUFFER2_SIZESHIFT); + } +} + +/*! + * @brief Read frame using DMA Receive interrupt. + * it allows scanning of Rx descriptors to get the the receive frame + * + * @param None + * + * @retval Structure of type ETH_Frame_T + */ +ETH_Frame_T ETH_ReadReceivedFrameInterrupt(void) +{ + __IO uint32_t count = 0; + ETH_Frame_T frame = {0,0,0}; + + while (((DMARxDescToGet->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET)&& (count < ETH_RXBUFNB)) + { + count ++; + + if(((DMARxDescToGet->Status & ETH_DMARXDESC_FDES) != (uint32_t)RESET)&& + ((DMARxDescToGet->Status & ETH_DMARXDESC_LDES) == (uint32_t)RESET)) + { + DMARxFraminfos->FS_RxDesc = DMARxDescToGet; + DMARxFraminfos->segCount = 1; + DMARxDescToGet = (ETH_DMADescConfig_T*) (DMARxDescToGet->Buffer2NextDescAddr); + } + else if (((DMARxDescToGet->Status & ETH_DMARXDESC_FDES) == (uint32_t)RESET)&& + ((DMARxDescToGet->Status & ETH_DMARXDESC_LDES) == (uint32_t)RESET)) + { + (DMARxFraminfos->segCount) ++; + DMARxDescToGet = (ETH_DMADescConfig_T*) (DMARxDescToGet->Buffer2NextDescAddr); + } + else + { + DMARxFraminfos->LS_RxDesc = DMARxDescToGet; + (DMARxFraminfos->segCount)++; + + if ((DMARxFraminfos->segCount)==1) + DMARxFraminfos->FS_RxDesc = DMARxDescToGet; + + frame.length = ((DMARxDescToGet->Status & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAMELENGTHSHIFT) - 4; + + if(DMARxFraminfos->segCount >1) + { + frame.buffer = (DMARxFraminfos->FS_RxDesc)->Buffer1Addr; + } + else + { + frame.buffer = DMARxDescToGet->Buffer1Addr; + } + + frame.descriptor = DMARxFraminfos->FS_RxDesc; + DMARxDescToGet = (ETH_DMADescConfig_T*) (DMARxDescToGet->Buffer2NextDescAddr); + + return (frame); + } + } + return (frame); +} + +/** DMA functions */ + +/*! + * @brief Read the ETH DMA flag. + * + * @param 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_DATATRANSFERERROR : Error bits 0-data buffer, 1-desc. access + * @arg ETH_DMA_FLAG_READWRITEERROR : Error bits 0-write trnsf, 1-read transfr + * @arg ETH_DMA_FLAG_ACCESSERROR : 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_ER : Early receive flag + * @arg ETH_DMA_FLAG_FBE : Fatal bus error flag + * @arg ETH_DMA_FLAG_ET : Early transmit flag + * @arg ETH_DMA_FLAG_RWT : Receive watchdog timeout flag + * @arg ETH_DMA_FLAG_RPS : Receive process stopped flag + * @arg ETH_DMA_FLAG_RBU : Receive buffer unavailable flag + * @arg ETH_DMA_FLAG_RX : Receive flag + * @arg ETH_DMA_FLAG_TU : Underflow flag + * @arg ETH_DMA_FLAG_RO : Overflow flag + * @arg ETH_DMA_FLAG_TJT : Transmit jabber timeout flag + * @arg ETH_DMA_FLAG_TBU : Transmit buffer unavailable flag + * @arg ETH_DMA_FLAG_TPS : Transmit process stopped flag + * @arg ETH_DMA_FLAG_TX : Transmit flag + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadDMAFlagStatus(ETH_DMA_FLAG_T flag) +{ + return (ETH->DMASTS & flag) ? SET : RESET; +} + +/*! + * @brief Clears the ETH DMA flag. + * + * @param 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_ER : Early receive flag + * @arg ETH_DMA_FLAG_FBE : Fatal bus error flag + * @arg ETH_DMA_FLAG_ET : Early transmit flag + * @arg ETH_DMA_FLAG_RWT : Receive watchdog timeout flag + * @arg ETH_DMA_FLAG_RPS : Receive process stopped flag + * @arg ETH_DMA_FLAG_RBU : Receive buffer unavailable flag + * @arg ETH_DMA_FLAG_RX : Receive flag + * @arg ETH_DMA_FLAG_TU : Transmit Underflow flag + * @arg ETH_DMA_FLAG_RO : Receive Overflow flag + * @arg ETH_DMA_FLAG_TJT : Transmit jabber timeout flag + * @arg ETH_DMA_FLAG_TBU : Transmit buffer unavailable flag + * @arg ETH_DMA_FLAG_TPS : Transmit process stopped flag + * @arg ETH_DMA_FLAG_TX : Transmit flag + * + * @retval None + */ +void ETH_ClearDMAFlag(uint32_t flag) +{ + ETH->DMASTS = flag; +} + +/*! + * @brief Read the ETH DMA interrupt flag. + * + * @param flag: 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_ER : Early receive interrupt + * @arg ETH_DMA_INT_FBE : Fatal bus error interrupt + * @arg ETH_DMA_INT_ET : Early transmit interrupt + * @arg ETH_DMA_INT_RWT : Receive watchdog timeout interrupt + * @arg ETH_DMA_INT_RPS : Receive process stopped interrupt + * @arg ETH_DMA_INT_RBU : Receive buffer unavailable interrupt + * @arg ETH_DMA_INT_RX : Receive interrupt + * @arg ETH_DMA_INT_TU : Underflow interrupt + * @arg ETH_DMA_INT_RO : Overflow interrupt + * @arg ETH_DMA_INT_TJT : Transmit jabber timeout interrupt + * @arg ETH_DMA_INT_TBU : Transmit buffer unavailable interrupt + * @arg ETH_DMA_INT_TPS : Transmit process stopped interrupt + * @arg ETH_DMA_INT_TX : Transmit interrupt + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadDMAIntFlag(ETH_DMA_INT_T flag) +{ + return (ETH->DMASTS & flag) ? SET : RESET; +} + +/*! + * @brief Clears the ETH DMA interrupt flag. + * + * @param flag: specifies the interrupt flag 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_ER : Early receive interrupt + * @arg ETH_DMA_INT_FBE : Fatal bus error interrupt + * @arg ETH_DMA_INT_ET : Early transmit interrupt + * @arg ETH_DMA_INT_RWT : Receive watchdog timeout interrupt + * @arg ETH_DMA_INT_RPS : Receive process stopped interrupt + * @arg ETH_DMA_INT_RBU : Receive buffer unavailable interrupt + * @arg ETH_DMA_INT_RX : Receive interrupt + * @arg ETH_DMA_INT_TU : Transmit Underflow interrupt + * @arg ETH_DMA_INT_RO : Receive Overflow interrupt + * @arg ETH_DMA_INT_TJT : Transmit jabber timeout interrupt + * @arg ETH_DMA_INT_TBU : Transmit buffer unavailable interrupt + * @arg ETH_DMA_INT_TPS : Transmit process stopped interrupt + * @arg ETH_DMA_INT_TX : Transmit interrupt + * + * @retval None + */ +void ETH_ClearDMAIntFlag(uint32_t flag) +{ + ETH->DMASTS = flag; +} + +/*! + * @brief Returns the ETH DMA Transmit Process State. + * + * @param None + + * @retval The new ETH DMA Transmit Process State: + * This can be one of the following values: + * - ETH_DMA_TRANSMITPROCESS_STOPPED : Stopped - Reset or Stop Tx Command issued + * - ETH_DMA_TRANSMITPROCESS_FETCHING : Running - fetching the Tx descriptor + * - ETH_DMA_TRANSMITPROCESS_WAITING : Running - waiting for status + * - ETH_DMA_TRANSMITPROCESS_READING : Running - reading the data from host memory + * - ETH_DMA_TRANSMITPROCESS_SUSPENDED : Suspended - Tx Descriptor unavailable + * - ETH_DMA_TRANSMITPROCESS_CLOSING : Running - closing Rx descriptor + */ +uint32_t ETH_ReadTransmitProcessState(void) +{ + return ((uint32_t)(ETH->DMASTS & BIT0) ? SET : RESET); +} + +/*! + * @brief Returns the ETH DMA Receive Process State. + * + * @param None + * + * @retval The new ETH DMA Receive Process State: + * This can be one of the following values: + * - ETH_DMA_RECEIVEPROCESS_STOPPED : Stopped - Reset or Stop Rx Command issued + * - ETH_DMA_RECEIVEPROCESS_FETCHING : Running - fetching the Rx descriptor + * - ETH_DMA_RECEIVEPROCESS_WAITING : Running - waiting for packet + * - ETH_DMA_RECEIVEPROCESS_SUSPENDED : Suspended - Rx Descriptor unavailable + * - ETH_DMA_RECEIVEPROCESS_CLOSING : Running - closing descriptor + * - ETH_DMA_RECEIVEPROCESS_QUEUING : Running - queuing the receive frame into host memory + */ +uint32_t ETH_ReadReceiveProcessState(void) +{ + return ((uint32_t)(ETH->DMASTS & BIT6) ? SET : RESET); +} + +/*! + * @brief Flush the ETH transmit FIFO. + * + * @param None + * + * @retval None + */ +void ETH_FlushTransmitFIFO(void) +{ + ETH->DMAOPMOD_B.FTXF = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Read the ETH flush transmit FIFO status. + * + * @param None + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadFlushTransmitFIFOStatus(void) +{ + return ETH->DMAOPMOD_B.FTXF; +} + +/*! + * @brief Enable the DMA transmission. + * + * @param None + * + * @retval None + */ +void ETH_EnableDMATransmission(void) +{ + ETH->DMAOPMOD_B.STTX = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable the DMA transmission. + * + * @param None + * + * @retval None + */ +void ETH_DisableDMATransmission(void) +{ + ETH->DMAOPMOD_B.STTX = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Enable the DMA receiver. + * + * @param None + * + * @retval None + */ +void ETH_EnableDMAReceiver(void) +{ + ETH->DMAOPMOD_B.STRX = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable the DMA receiver. + * + * @param None + * + * @retval None + */ +void ETH_DisableDMAReceiver(void) +{ + ETH->DMAOPMOD_B.STRX = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Enable the ETH DMA interrupts. + * + * @param interrupt: specifies the ETH DMA interrupt sources. + * 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_ER : Early receive interrupt + * @arg ETH_DMA_INT_FBE : Fatal bus error interrupt + * @arg ETH_DMA_INT_ET : Early transmit interrupt + * @arg ETH_DMA_INT_RWT : Receive watchdog timeout interrupt + * @arg ETH_DMA_INT_RPS : Receive process stopped interrupt + * @arg ETH_DMA_INT_RBU : Receive buffer unavailable interrupt + * @arg ETH_DMA_INT_RX : Receive interrupt + * @arg ETH_DMA_INT_TU : Underflow interrupt + * @arg ETH_DMA_INT_RO : Overflow interrupt + * @arg ETH_DMA_INT_TJT : Transmit jabber timeout interrupt + * @arg ETH_DMA_INT_TBU : Transmit buffer unavailable interrupt + * @arg ETH_DMA_INT_TPS : Transmit process stopped interrupt + * @arg ETH_DMA_INT_TX : Transmit interrupt + * + * @retval None + */ +void ETH_EnableDMAInterrupt(uint32_t interrupt) +{ + ETH->DMAINTEN |= interrupt; +} + +/*! + * @brief Disable the ETH DMA interrupts. + * + * @param interrupt: specifies the ETH DMA interrupt sources. + * 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_ER : Early receive interrupt + * @arg ETH_DMA_INT_FBE : Fatal bus error interrupt + * @arg ETH_DMA_INT_ET : Early transmit interrupt + * @arg ETH_DMA_INT_RWT : Receive watchdog timeout interrupt + * @arg ETH_DMA_INT_RPS : Receive process stopped interrupt + * @arg ETH_DMA_INT_RBU : Receive buffer unavailable interrupt + * @arg ETH_DMA_INT_RX : Receive interrupt + * @arg ETH_DMA_INT_TU : Underflow interrupt + * @arg ETH_DMA_INT_RO : Overflow interrupt + * @arg ETH_DMA_INT_TJT : Transmit jabber timeout interrupt + * @arg ETH_DMA_INT_TBU : Transmit buffer unavailable interrupt + * @arg ETH_DMA_INT_TPS : Transmit process stopped interrupt + * @arg ETH_DMA_INT_TX : Transmit interrupt + * + * @retval None + */ +void ETH_DisableDMAInterrupt(uint32_t interrupt) +{ + ETH->DMAINTEN &= ((uint32_t)~interrupt); +} + +/*! + * @brief Read the ETH DMA overflow flag. + * + * @param overflow: specifies the DMA overflow flag to check. + * This parameter can be one of the following values: + * @arg ETH_DMA_OVERFLOW_RXFIFOCOUNTER : Overflow for FIFO Overflows Counter + * @arg ETH_DMA_OVERFLOW_MISSEDFRAMECOUNTER : Overflow for Buffer Unavailable Missed Frame Counter + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadDMAOverflowStatus(ETH_DMA_OVERFLOW_T overflow) +{ + return (ETH->DMAMFABOCNT & overflow) ? SET : RESET; +} + +/*! + * @brief Read the ETH DMA Rx Overflow Missed Frame Counter value. + * + * @param None + * + * @retval The value of Rx overflow Missed Frame Counter. + */ +uint32_t ETH_ReadRxOverflowMissedFrameCounter(void) +{ + return (uint32_t)(ETH->DMAMFABOCNT_B.AMISFCNT); +} + +/*! + * @brief Read the ETH DMA Buffer Unavailable Missed Frame Counter value. + * + * @param None + * + * @retval The value of Buffer unavailable Missed Frame Counter. + */ +uint32_t ETH_ReadBufferUnavailableMissedFrameCounter(void) +{ + return (uint32_t)(ETH->DMAMFABOCNT_B.MISFCNT); +} + +/*! + * @brief Read the ETH DMA DMAHTXD register value. + * + * @param None + * + * @retval The value of the current Tx desc start address. + */ +uint32_t ETH_ReadCurrentTxDescStartAddress(void) +{ + return ((uint32_t)(ETH->DMAHTXD)); +} + +/*! + * @brief Read the ETHERNET DMA DMAHRXD register value. + * + * @param None + * + * @retval The value of the current Rx desc start address. + */ +uint32_t ETH_ReadCurrentRxDescStartAddress(void) +{ + return ((uint32_t)(ETH->DMAHRXD)); +} + +/*! + * @brief Read the ETH DMA DMAHTXBADDR register value. + * + * @param None + * + * @retval The value of the current transmit descriptor data buffer address. + */ +uint32_t ETH_ReadCurrentTxBufferAddress(void) +{ + return ((uint32_t)(ETH->DMAHTXBADDR)); +} + +/*! + * @brief Read the ETH DMA DMAHRXBADDR register value. + * + * @param None + * + * @retval The value of the current receive descriptor data buffer address. + */ +uint32_t ETH_ReadCurrentRxBufferAddress(void) +{ + return ((uint32_t)(ETH->DMAHRXBADDR)); +} + +/*! + * @brief Reset the DMA Transmission by writing to the DmaTxPollDemand register + * + * @param None + + * @retval None. + */ +void ETH_ResetDMATransmission(void) +{ + ETH->DMATXPD = 0; +} + +/*! + * @brief Reset the DMA Transmission by writing to the DmaRxPollDemand register + * + * @param None + * + * @retval None. + */ +void ETH_ResetDMAReception(void) +{ + ETH->DMARXPD = 0; +} + +/*! + * @brief Config the DMA Receive status watchdog timer register value + * + * @param value: watchdog timer register value + * + * @retval None + */ +void ETH_ConfigReceiveWatchdogTimer(uint8_t value) +{ + ETH->DMARXFLGWDT_B.RXWDTCNT = value; +} + +/** Power Management(PMT) functions */ + +/*! + * @brief Reset Wakeup frame filter register pointer. + * + * @param None + * + * @retval None + */ +void ETH_ResetWakeUpFrameFilterRegisterPointer(void) +{ + ETH->PMTCTRLSTS_B.WKUPFRST = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Populates the remote wakeup frame registers. + * + * @param buffer: WakeUp Frame Filter Register buffer data (8 words). + * + * @retval None + */ +void ETH_ConfigWakeUpFrameFilterRegister(uint32_t *buffer) +{ + uint32_t i = 0; + __IO uint32_t temp = 0; + + for(i = 0; i < ETH_WAKEUP_REGISTER_LENGTH; i++) + { + ETH->WKUPFFL = buffer[i]; + + temp = ETH->WKUPFFL; + ETH_Delay(ETH_REG_WRITE_DELAY); + ETH->WKUPFFL = temp; + } +} + +/*! + * @brief Enable any unicast packet filtered by the MAC address + * recognition to be a wake-up frame. + * + * @retval None + */ +void ETH_EnableGlobalUnicastWakeUp(void) +{ + ETH->PMTCTRLSTS_B.GUN = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable any unicast packet filtered by the MAC address + * recognition to be a wake-up frame. + * + * @retval None + */ +void ETH_DisableGlobalUnicastWakeUp(void) +{ + ETH->PMTCTRLSTS_B.GUN = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Read the ETH PMT flag. + * + * @param flag: specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_PMT_FLAG_WUFFRPR : Wake-Up Frame Filter Register Pointer Reset + * @arg ETH_PMT_FLAG_WUFR : Wake-Up Frame Received + * @arg ETH_PMT_FLAG_MPR : Magic Packet Received + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadPMTFlagStatus(ETH_PMT_FLAG_T flag) +{ + return (ETH->PMTCTRLSTS & flag) ? SET : RESET; +} + +/*! + * @brief Enable the MAC Wake-Up Frame Detection. + * + * @param None + * + * @retval None + */ +void ETH_EnableWakeUpFrameDetection(void) +{ + ETH->PMTCTRLSTS_B.WKUPFEN = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable the MAC Wake-Up Frame Detection. + * + * @param None + * + * @retval None + */ +void ETH_DisableWakeUpFrameDetection(void) +{ + ETH->PMTCTRLSTS_B.WKUPFEN = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Enable the MAC Magic Packet Detection. + * + * @param None + * + * @retval None + */ +void ETH_EnableMagicPacketDetection(void) +{ + ETH->PMTCTRLSTS_B.MPEN = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable the MAC Magic Packet Detection. + * + * @param None + * + * @retval None + */ +void ETH_DisableMagicPacketDetection(void) +{ + ETH->PMTCTRLSTS_B.MPEN = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Enable the MAC Power Down. + * + * @param None + * + * @retval None + */ +void ETH_EnablePowerDown(void) +{ + ETH->PMTCTRLSTS_B.PD = SET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/*! + * @brief Disable the MAC Power Down. + * + * @param None + * + * @retval None + */ +void ETH_DisablePowerDown(void) +{ + ETH->PMTCTRLSTS_B.PD = RESET; + ETH_Delay(ETH_REG_WRITE_DELAY); +} + +/** MMC functions */ + +/** + * @brief Preset and Initialize the MMC counters to almost-full value: 0xFFFF_FFF0 (full - 16) + * @param None + * @retval None + */ +void ETH_PresetMMCCounterFull(void) +{ + ETH->CTRL_B.MCNTP = SET; + ETH->CTRL_B.MCNTVALP = SET; +} + +/** + * @brief Preset and Initialize the MMC counters to almost-hal value: 0x7FFF_FFF0 (half - 16) + * @param None + * @retval None + */ +void ETH_PresetMMCCounterHalf(void) +{ + ETH->CTRL_B.MCNTP = SET; + ETH->CTRL_B.MCNTVALP = RESET; +} + +/*! + * @brief Enable the MMC Counter Freeze. + * + * @param None + * + * @retval None + */ +void ETH_EnableMMCCounterFreeze(void) +{ + ETH->CTRL_B.MCNTF = SET; +} + +/*! + * @brief Disable the MMC Counter Freeze. + * + * @param None + * + * @retval None + */ +void ETH_DisableMMCCounterFreeze(void) +{ + ETH->CTRL_B.MCNTF = RESET; +} + +/*! + * @brief Enable the MMC Reset On Read. + * + * @param None + * + * @retval None + */ +void ETH_EnableMMCResetOnRead(void) +{ + ETH->CTRL_B.RSTOR = SET; +} + +/*! + * @brief Disable the MMC Reset On Read. + * + * @param None + * + * @retval None + */ +void ETH_DisableMMCResetOnRead(void) +{ + ETH->CTRL_B.RSTOR = RESET; +} + +/*! + * @brief Enble the MMC Counter Stop Rollover. + * + * @param None + * + * @retval None + */ +void ETH_EnableMMCCounterRollover(void) +{ + ETH->CTRL_B.CNTSTOPRO = RESET; +} + +/*! + * @brief Disable the MMC Counter Stop Rollover. + * + * @param None + * + * @retval None + */ +void ETH_DisableMMCCounterRollover(void) +{ + ETH->CTRL_B.CNTSTOPRO = SET; +} + +/** + * @brief Resets the MMC Counters. + * @param None + * @retval None + */ +void ETH_ResetMMCCounters(void) +{ + ETH->CTRL_B.CNTRST = SET; +} + +/*! + * @brief Enable the ETH MMC interrupts. + * + * @param interrupt: specifies the ETH MMC interrupt sources. + * 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_TGF : When Tx good frame counter reaches half the maximum value + * @arg ETH_MMC_INT_TGFMSC: When Tx good multi col counter reaches half the maximum value + * @arg ETH_MMC_INT_TGFSC : When Tx good single col counter reaches half the maximum value + * @arg ETH_MMC_INT_RGUF : When Rx good unicast frames counter reaches half the maximum value + * @arg ETH_MMC_INT_RFAE : When Rx alignment error counter reaches half the maximum value + * @arg ETH_MMC_INT_RFCE : When Rx crc error counter reaches half the maximum value + * + * @retval None + */ +void ETH_EnableMMCInterrupt(uint32_t interrupt) +{ + if((interrupt & 0x10000000) == SET) + { + ETH->RXINTMASK &= (~(uint32_t)interrupt); + } + else + { + ETH->TXINTMASK &= (~(uint32_t)interrupt); + } +} + +/*! + * @brief Disable the ETH MMC interrupts. + * + * @param interrupt: specifies the ETH MMC interrupt sources. + * 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_TGF : When Tx good frame counter reaches half the maximum value + * @arg ETH_MMC_INT_TGFMSC: When Tx good multi col counter reaches half the maximum value + * @arg ETH_MMC_INT_TGFSC : When Tx good single col counter reaches half the maximum value + * @arg ETH_MMC_INT_RGUF : When Rx good unicast frames counter reaches half the maximum value + * @arg ETH_MMC_INT_RFAE : When Rx alignment error counter reaches half the maximum value + * @arg ETH_MMC_INT_RFCE : When Rx crc error counter reaches half the maximum value + * + * @retval None + */ +void ETH_DisableMMCInterrupt(uint32_t interrupt) +{ + if((interrupt & 0x10000000) == SET) + { + ETH->RXINTMASK |= interrupt; + } + else + { + ETH->TXINTMASK |= interrupt; + } +} + +/*! + * @brief Read the ETH MMC interrupt flag. + * + * @param flag: specifies the ETH MMC interrupt. + * This parameter can be one of the following values: + * @arg ETH_MMC_INT_TGF : When Tx good frame counter reaches half the maximum value + * @arg ETH_MMC_INT_TGFMSC: When Tx good multi col counter reaches half the maximum value + * @arg ETH_MMC_INT_TGFSC : When Tx good single col counter reaches half the maximum value + * @arg ETH_MMC_INT_RGUF : When Rx good unicast frames counter reaches half the maximum value + * @arg ETH_MMC_INT_RFAE : When Rx alignment error counter reaches half the maximum value + * @arg ETH_MMC_INT_RFCE : When Rx crc error counter reaches half the maximum value + * + * @retval SET or RESET. + */ +uint8_t ETH_ReadMMCIntFlag(uint32_t flag) +{ + if((flag & 0x10000000) == SET) + { + return ((((ETH->RXINT & flag) != RESET)) && ((ETH->RXINTMASK & flag) == RESET)); + } + else + { + return ((((ETH->TXINT & flag) != RESET)) && ((ETH->TXINTMASK & flag) == RESET)); + } +} + +/*! + * @brief Read the ETH MMC register value. + * + * @param MMCReg: specifies the ETH MMC register. + * This parameter can be one of the following values: + * @arg ETH_MMC_CTRL : MMC CTRL register + * @arg ETH_MMC_RXINT : MMC RXINT register + * @arg ETH_MMC_TXINT : MMC TXINT register + * @arg ETH_MMC_RXINTMASK : MMC RXINTMASK register + * @arg ETH_MMC_TXINTMASK : MMC TXINTMASK register + * @arg ETH_MMC_TXGFSCCNT : MMC TXGFSCCNT register + * @arg ETH_MMC_TXGFMCCNT : MMC TXGFMCCNT register + * @arg ETH_MMC_TXGFCNT : MMC TXGFCNT register + * @arg ETH_MMC_RXFCECNT : MMC RXFCECNT register + * @arg ETH_MMC_RXFAECNT : MMC RXFAECNT register + * @arg ETH_MMC_RXGUNCNT : MMC RXGUNCNT register + * + * @retval Return ETH MMC Register value. + */ +uint32_t ETH_ReadMMCRegister(ETH_MMC_REG_T MMCReg) +{ + return (*(__IO uint32_t *)(ETH_MAC_BASE + MMCReg)); +} + +/**@} end of group ETH_Functions */ +/**@} end of group ETH_Driver */ +/**@} end of group APM32F4xx_ETHDriver */ diff --git a/bsp/apm32/libraries/APM32F4xx_Library/SConscript b/bsp/apm32/libraries/APM32F4xx_Library/SConscript index 8785ae70e9..74d77c1e55 100644 --- a/bsp/apm32/libraries/APM32F4xx_Library/SConscript +++ b/bsp/apm32/libraries/APM32F4xx_Library/SConscript @@ -9,6 +9,7 @@ cwd = GetCurrentDir() src = Split(""" Device/Geehy/APM32F4xx/Source/system_apm32f4xx.c APM32F4xx_StdPeriphDriver/src/apm32f4xx_gpio.c +APM32F4xx_StdPeriphDriver/src/apm32f4xx_syscfg.c APM32F4xx_StdPeriphDriver/src/apm32f4xx_misc.c APM32F4xx_StdPeriphDriver/src/apm32f4xx_rcm.c APM32F4xx_StdPeriphDriver/src/apm32f4xx_usart.c @@ -35,9 +36,13 @@ if GetDepend(['RT_USING_WDT']): src += ['APM32F4xx_StdPeriphDriver/src/apm32f4xx_wwdt.c'] src += ['APM32F4xx_StdPeriphDriver/src/apm32f4xx_iwdt.c'] +if GetDepend(['BSP_USING_ETH']): + src += ['APM32F4xx_ETH_Driver/src/apm32f4xx_eth.c'] + path = [cwd + '/Device/Geehy/APM32F4xx/Include', cwd + '/APM32F4xx_StdPeriphDriver/inc', - cwd + '/CMSIS/Include'] + cwd + '/CMSIS/Include', + cwd + '/APM32F4xx_ETH_Driver/inc'] CPPDEFINES = ['USE_STDPERIPH_DRIVER'] group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) diff --git a/bsp/apm32/libraries/Drivers/SConscript b/bsp/apm32/libraries/Drivers/SConscript index 61cdb7ab9b..128c5e3cd6 100644 --- a/bsp/apm32/libraries/Drivers/SConscript +++ b/bsp/apm32/libraries/Drivers/SConscript @@ -27,7 +27,8 @@ if GetDepend('BSP_USING_ONCHIP_RTC'): src += ['drv_rtc.c'] if GetDepend(['RT_USING_I2C']): - src += ['drv_soft_i2c.c'] + if GetDepend('BSP_USING_I2C1') or GetDepend('BSP_USING_I2C2') or GetDepend('BSP_USING_I2C3') or GetDepend('BSP_USING_I2C4'): + src += ['drv_soft_i2c.c'] if GetDepend(['RT_USING_SPI']): src += ['drv_spi.c'] @@ -38,9 +39,12 @@ if GetDepend(['RT_USING_HWTIMER']): if GetDepend(['RT_USING_PWM']): src += ['drv_pwm.c'] -if GetDepend(['RT_USING_WDT']): +if GetDepend(['BSP_USING_WDT']): src += ['drv_wdt.c'] +if GetDepend(['BSP_USING_ETH', 'RT_USING_LWIP']): + src += ['drv_eth.c'] + src += ['drv_common.c'] path = [cwd] diff --git a/bsp/apm32/libraries/Drivers/drv_adc.c b/bsp/apm32/libraries/Drivers/drv_adc.c index 40b796db06..8952bb8b14 100644 --- a/bsp/apm32/libraries/Drivers/drv_adc.c +++ b/bsp/apm32/libraries/Drivers/drv_adc.c @@ -7,22 +7,22 @@ * Date Author Notes * 2022-03-04 stevetong459 first version * 2022-07-15 Aligagago add apm32F4 serie MCU support + * 2022-12-26 luobeihai add apm32F0 serie MCU support */ #include #if defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3) -//#define DRV_DEBUG -#define LOG_TAG "drv.adc" +#define DBG_TAG "drv.adc" #define DBG_LVL DBG_INFO #include -#define DRV_ADC_CHANNEL_MAX_NUM 14 +#define DRV_ADC_CHANNEL_MAX_NUM 16 #define DRV_ADC_TIME_OUT 0xFFF -#define _ADC_GET_PORT(pin_num) ((GPIO_T *)(GPIOA_BASE + (0x400u * (((pin_num) >> 4) & 0xFu)))) -#define _ADC_GET_PIN(pin_num) ((uint16_t)(1u << ((pin_num) & 0xFu))) +#define APM32_ADC_GET_PORT(pin_num) ((GPIO_T *)(GPIOA_BASE + (0x400u * (((pin_num) >> 4) & 0xFu)))) +#define APM32_ADC_GET_PIN(pin_num) ((uint16_t)(1u << ((pin_num) & 0xFu))) struct apm32_adc { @@ -32,7 +32,8 @@ struct apm32_adc rt_base_t channel_pin[DRV_ADC_CHANNEL_MAX_NUM]; struct rt_adc_device adc_dev; }; -#ifdef APM32F10X_HD + +#if defined(SOC_SERIES_APM32F1) static struct apm32_adc adc_config[] = { #ifdef BSP_USING_ADC1 @@ -95,7 +96,7 @@ static struct apm32_adc adc_config[] = }, #endif }; -#elif APM32F40X +#elif defined(SOC_SERIES_APM32F4) static struct apm32_adc adc_config[] = { #ifdef BSP_USING_ADC1 @@ -162,11 +163,37 @@ static struct apm32_adc adc_config[] = }, #endif }; +#elif defined(SOC_SERIES_APM32F0) +static struct apm32_adc adc_config[] = +{ +#ifdef BSP_USING_ADC1 + { + "adc1", + ADC, + { + ADC_RESOLUTION_12B, + ADC_DATA_ALIGN_RIGHT, + ADC_SCAN_DIR_UPWARD, + ADC_CONVERSION_SINGLE, + ADC_EXT_TRIG_CONV_TRG0, + ADC_EXT_TRIG_EDGE_NONE + }, + { + GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3), GET_PIN(A, 4), + GET_PIN(A, 5), GET_PIN(A, 6), GET_PIN(A, 7), GET_PIN(B, 0), GET_PIN(B, 1), + GET_PIN(C, 0), GET_PIN(C, 1), GET_PIN(C, 2), GET_PIN(C, 3), GET_PIN(C, 4), + GET_PIN(C, 5) + }, + RT_NULL + }, #endif -static rt_err_t _adc_channel_check(struct rt_adc_device *device, rt_uint32_t channel) +}; +#endif + +static rt_err_t apm32_adc_channel_check(struct rt_adc_device *device, rt_uint32_t channel) { struct apm32_adc *adc_cfg = ((struct apm32_adc *)device->parent.user_data); -#ifdef APM32F10X_HD +#if defined(SOC_SERIES_APM32F1) if (adc_cfg->adc == ADC3) { if (channel <= 8) @@ -181,34 +208,42 @@ static rt_err_t _adc_channel_check(struct rt_adc_device *device, rt_uint32_t cha return RT_EOK; } } -#elif APM32F40X +#elif defined(SOC_SERIES_APM32F4) if (channel <= 13) { return RT_EOK; } +#elif defined(SOC_SERIES_APM32F0) + if (channel <= 16) + { + return RT_EOK; + } #endif LOG_E("channel %d of %s is not supported.", channel, adc_cfg->name); return -RT_ERROR; } -static rt_err_t _adc_gpio_init(struct rt_adc_device *device, rt_uint32_t channel) +static rt_err_t apm32_adc_gpio_init(struct rt_adc_device *device, rt_uint32_t channel) { struct apm32_adc *adc_cfg = ((struct apm32_adc *)device->parent.user_data); GPIO_Config_T hw_gpio_config; - if (_adc_channel_check(device, channel) != RT_EOK) + if (apm32_adc_channel_check(device, channel) != RT_EOK) { return -RT_ERROR; } -#ifdef APM32F10X_HD +#if defined(SOC_SERIES_APM32F1) RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA << ((adc_cfg->channel_pin[channel] >> 4) & 0xFu)); hw_gpio_config.mode = GPIO_MODE_ANALOG; -#elif APM32F40X +#elif defined(SOC_SERIES_APM32F4) RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA << ((adc_cfg->channel_pin[channel] >> 4) & 0xFu)); hw_gpio_config.mode = GPIO_MODE_AN; +#elif defined(SOC_SERIES_APM32F0) + RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA << ((adc_cfg->channel_pin[channel] >> 4) & 0xFu)); + hw_gpio_config.mode = GPIO_MODE_AN; #endif - hw_gpio_config.pin = _ADC_GET_PIN(adc_cfg->channel_pin[channel]); - GPIO_Config(_ADC_GET_PORT(adc_cfg->channel_pin[channel]), &hw_gpio_config); + hw_gpio_config.pin = APM32_ADC_GET_PIN(adc_cfg->channel_pin[channel]); + GPIO_Config(APM32_ADC_GET_PORT(adc_cfg->channel_pin[channel]), &hw_gpio_config); return RT_EOK; } @@ -224,12 +259,28 @@ static rt_err_t _adc_gpio_init(struct rt_adc_device *device, rt_uint32_t channel * * @return RT_EOK indicates successful enable or disable adc, other value indicates failed. */ -static rt_err_t _adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled) +static rt_err_t apm32_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled) { struct apm32_adc *adc_cfg = ((struct apm32_adc *)device->parent.user_data); RT_ASSERT(device != RT_NULL); +#if defined(SOC_SERIES_APM32F0) + if (enabled) + { + RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1); + if (apm32_adc_gpio_init(device, channel) != RT_EOK) + { + return -RT_ERROR; + } + ADC_Config(&adc_cfg->adc_config); + ADC_Enable(); + } + else + { + ADC_Disable(); + } +#else if (enabled) { if (adc_cfg->adc == ADC1) @@ -244,7 +295,7 @@ static rt_err_t _adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, { RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC3); } - if (_adc_gpio_init(device, channel) != RT_EOK) + if (apm32_adc_gpio_init(device, channel) != RT_EOK) { return -RT_ERROR; } @@ -257,6 +308,7 @@ static rt_err_t _adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, { ADC_Disable(adc_cfg->adc); } +#endif return RT_EOK; } @@ -272,19 +324,22 @@ static rt_err_t _adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, * * @return RT_EOK indicates successful get adc value, other value indicates failed. */ -static rt_err_t _adc_get_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value) +static rt_err_t apm32_adc_get_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value) { +#if !defined(SOC_SERIES_APM32F0) struct apm32_adc *adc_cfg = ((struct apm32_adc *)device->parent.user_data); +#endif volatile rt_uint32_t counter = 0; RT_ASSERT(device != RT_NULL); RT_ASSERT(value != RT_NULL); - if (_adc_channel_check(device, channel) != RT_EOK) + if (apm32_adc_channel_check(device, channel) != RT_EOK) { return -RT_ERROR; } -#ifdef APM32F10X_HD + +#if defined(SOC_SERIES_APM32F1) ADC_ConfigRegularChannel(adc_cfg->adc, channel, 1, ADC_SAMPLETIME_13CYCLES5); ADC_StartCalibration(adc_cfg->adc); @@ -298,11 +353,7 @@ static rt_err_t _adc_get_value(struct rt_adc_device *device, rt_uint32_t channel } ADC_EnableSoftwareStartConv(adc_cfg->adc); -#elif APM32F40X - ADC_ConfigRegularChannel(adc_cfg->adc, channel, 1, ADC_SAMPLETIME_15CYCLES); - ADC_SoftwareStartConv(adc_cfg->adc); -#endif - counter = 0; + while (!ADC_ReadStatusFlag(adc_cfg->adc, ADC_FLAG_EOC)) { if (++counter > DRV_ADC_TIME_OUT) @@ -310,16 +361,41 @@ static rt_err_t _adc_get_value(struct rt_adc_device *device, rt_uint32_t channel return RT_ETIMEOUT; } } - *value = ADC_ReadConversionValue(adc_cfg->adc); - +#elif defined(SOC_SERIES_APM32F4) + ADC_ConfigRegularChannel(adc_cfg->adc, channel, 1, ADC_SAMPLETIME_15CYCLES); + ADC_SoftwareStartConv(adc_cfg->adc); + + while (!ADC_ReadStatusFlag(adc_cfg->adc, ADC_FLAG_EOC)) + { + if (++counter > DRV_ADC_TIME_OUT) + { + return RT_ETIMEOUT; + } + } + *value = ADC_ReadConversionValue(adc_cfg->adc); +#elif defined(SOC_SERIES_APM32F0) + ADC_ConfigChannel((uint16_t)(1u << ((channel) & 0xFu)), ADC_SAMPLE_TIME_239_5); + + ADC_StartConversion(); + + while (!ADC_ReadStatusFlag(ADC_FLAG_CC)) + { + if (++counter > DRV_ADC_TIME_OUT) + { + return RT_ETIMEOUT; + } + } + *value = ADC_ReadConversionValue(); +#endif + return RT_EOK; } -static const struct rt_adc_ops _adc_ops = +static const struct rt_adc_ops apm32_adc_ops = { - .enabled = _adc_enabled, - .convert = _adc_get_value, + .enabled = apm32_adc_enabled, + .convert = apm32_adc_get_value, }; /** @@ -336,7 +412,7 @@ static int rt_hw_adc_init(void) for (i = 0; i < obj_num; i++) { /* register ADC device */ - if (rt_hw_adc_register(&adc_config[i].adc_dev, adc_config[i].name, &_adc_ops, adc_config)) + if (rt_hw_adc_register(&adc_config[i].adc_dev, adc_config[i].name, &apm32_adc_ops, &adc_config[i]) == RT_EOK) { LOG_D("%s init success", adc_config[i].name); } diff --git a/bsp/apm32/libraries/Drivers/drv_common.c b/bsp/apm32/libraries/Drivers/drv_common.c index 0e62a55ccf..9d04818f80 100644 --- a/bsp/apm32/libraries/Drivers/drv_common.c +++ b/bsp/apm32/libraries/Drivers/drv_common.c @@ -93,7 +93,7 @@ void rt_hw_us_delay(rt_uint32_t us) /** * This function will config the board for initialization. */ -rt_weak void rt_hw_board_init() +rt_weak void rt_hw_board_init(void) { /* Systick initialization */ rt_hw_systick_init(); diff --git a/bsp/apm32/libraries/Drivers/drv_dac.c b/bsp/apm32/libraries/Drivers/drv_dac.c index 0091b8ada4..c6d0bba057 100644 --- a/bsp/apm32/libraries/Drivers/drv_dac.c +++ b/bsp/apm32/libraries/Drivers/drv_dac.c @@ -7,14 +7,15 @@ * Date Author Notes * 2022-03-04 stevetong459 first version * 2022-07-15 Aligagago add apm32F4 serie MCU support + * 2022-12-26 luobeihai add apm32F0 serie MCU support */ #include #if defined(BSP_USING_DAC1) -#define LOG_TAG "drv.dac" -#define DBG_LVL DBG_INFO +#define DBG_TAG "drv.dac" +#define DBG_LVL DBG_LOG//DBG_INFO #include struct apm32_dac @@ -27,8 +28,20 @@ struct apm32_dac static struct apm32_dac dac_config[] = { -#if defined(BSP_USING_DAC1) + +#if defined (BSP_USING_DAC1) { +#if defined (SOC_SERIES_APM32F0) + "dac1", + DAC, + { + DAC_TRIGGER_SOFTWARE, + DAC_OUTPUTBUFF_DISABLE, + DAC_WAVE_GENERATION_NONE, + DAC_TRIANGLEAMPLITUDE_4095, + }, + RT_NULL, +#elif defined (SOC_SERIES_APM32F1) || defined (SOC_SERIES_APM32F4) "dac1", DAC, { @@ -37,7 +50,8 @@ static struct apm32_dac dac_config[] = DAC_WAVE_GENERATION_NONE, DAC_TRIANGLE_AMPLITUDE_4095, }, - RT_NULL + RT_NULL, +#endif } #endif }; @@ -51,16 +65,19 @@ static struct apm32_dac dac_config[] = * * @return RT_EOK indicates successful enable dac, other value indicates failed. */ -static rt_err_t _dac_enabled(struct rt_dac_device *device, rt_uint32_t channel) +static rt_err_t apm32_dac_enabled(struct rt_dac_device *device, rt_uint32_t channel) { GPIO_Config_T GPIO_ConfigStruct; struct apm32_dac *cfg = (struct apm32_dac *)device->parent.user_data; -#ifdef APM32F10X_HD +#if defined (SOC_SERIES_APM32F1) RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA); GPIO_ConfigStruct.mode = GPIO_MODE_ANALOG; -#elif APM32F40X +#elif defined (SOC_SERIES_APM32F4) RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA); GPIO_ConfigStruct.mode = GPIO_MODE_AN; +#elif defined (SOC_SERIES_APM32F0) + RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA); + GPIO_ConfigStruct.mode = GPIO_MODE_AN; #endif if (channel == 1) { @@ -96,7 +113,7 @@ static rt_err_t _dac_enabled(struct rt_dac_device *device, rt_uint32_t channel) * * @return RT_EOK indicates successful disable dac, other value indicates failed. */ -static rt_err_t _dac_disabled(struct rt_dac_device *device, rt_uint32_t channel) +static rt_err_t apm32_dac_disabled(struct rt_dac_device *device, rt_uint32_t channel) { if (channel == 1) { @@ -126,8 +143,25 @@ static rt_err_t _dac_disabled(struct rt_dac_device *device, rt_uint32_t channel) * * @return RT_EOK indicates successful set dac value, other value indicates failed. */ -static rt_err_t _dac_set_value(struct rt_dac_device *device, rt_uint32_t channel, rt_uint32_t *value) +static rt_err_t apm32_dac_set_value(struct rt_dac_device *device, rt_uint32_t channel, rt_uint32_t *value) { +#if defined (SOC_SERIES_APM32F0) + if (channel == 1) + { + DAC_ConfigChannel1Data(DAC_ALIGN_12B_R, *value); + DAC_EnableSoftwareTrigger(DAC_CHANNEL_1); + } + else if (channel == 2) + { + DAC_ConfigChannel2Data(DAC_ALIGN_12B_R, *value); + DAC_EnableSoftwareTrigger(DAC_CHANNEL_2); + } + else + { + LOG_E("dac channel must be 1 or 2."); + return -RT_ERROR; + } +#elif defined (SOC_SERIES_APM32F1) || defined (SOC_SERIES_APM32F4) if (channel == 1) { DAC_ConfigChannel1Data(DAC_ALIGN_12BIT_R, *value); @@ -143,15 +177,15 @@ static rt_err_t _dac_set_value(struct rt_dac_device *device, rt_uint32_t channel LOG_E("dac channel must be 1 or 2."); return -RT_ERROR; } - +#endif return RT_EOK; } -static const struct rt_dac_ops _dac_ops = +static const struct rt_dac_ops apm32_dac_ops = { - .disabled = _dac_disabled, - .enabled = _dac_enabled, - .convert = _dac_set_value, + .disabled = apm32_dac_disabled, + .enabled = apm32_dac_enabled, + .convert = apm32_dac_set_value, }; /** @@ -170,7 +204,7 @@ static int rt_hw_dac_init(void) for (i = 0; i < obj_num; i++) { /* register dac device */ - if (rt_hw_dac_register(&dac_config[i].dac_dev, dac_config[i].name, &_dac_ops, dac_config) == RT_EOK) + if (rt_hw_dac_register(&dac_config[i].dac_dev, dac_config[i].name, &apm32_dac_ops, dac_config) == RT_EOK) { LOG_D("%s init success", dac_config[i].name); } diff --git a/bsp/apm32/libraries/Drivers/drv_eth.c b/bsp/apm32/libraries/Drivers/drv_eth.c new file mode 100644 index 0000000000..4936b7be14 --- /dev/null +++ b/bsp/apm32/libraries/Drivers/drv_eth.c @@ -0,0 +1,766 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-10-20 luobeihai first version + */ + +#include + +#ifdef BSP_USING_ETH + +#include +#include +#include +#include "lwipopts.h" + +/* debug option */ +//#define DRV_DEBUG +//#define ETH_RX_DUMP +//#define ETH_TX_DUMP +#define LOG_TAG "drv.emac" +#include "drv_eth.h" + +/* Global pointers on Tx and Rx descriptor used to transmit and receive descriptors */ +extern ETH_DMADescConfig_T *DMATxDescToSet, *DMARxDescToGet; + +/* Ethernet Rx & Tx DMA Descriptors */ +static ETH_DMADescConfig_T DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB]; +/* Ethernet Receive and Transmit buffers */ +static rt_uint8_t Rx_Buff[ETH_RXBUFNB][ETH_MAX_PACKET_SIZE], Tx_Buff[ETH_TXBUFNB][ETH_MAX_PACKET_SIZE]; +/* phy address */ +static uint8_t phy_addr = 0xFF; + +#define MAX_ADDR_LEN 6 +struct rt_apm32_eth +{ + /* inherit from ethernet device */ + struct eth_device parent; + + rt_timer_t poll_link_timer; + + /* interface address info. */ + rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */ + + uint32_t ETH_Speed; /*!< @ref ETH_Speed */ + uint32_t ETH_Mode; /*!< @ref ETH_Duplex_Mode */ + + uint32_t ETH_HashTableHigh; + uint32_t ETH_HashTableLow; +}; +static struct rt_apm32_eth apm32_eth_device; +static struct rt_semaphore tx_wait; +static rt_bool_t tx_is_waiting = RT_FALSE; + +#if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP) +#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ') +static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen) +{ + unsigned char *buf = (unsigned char *)ptr; + int i, j; + + for (i = 0; i < buflen; i += 16) + { + rt_kprintf("%08X: ", i); + + for (j = 0; j < 16; j++) + if (i + j < buflen) + rt_kprintf("%02X ", buf[i + j]); + else + rt_kprintf(" "); + rt_kprintf(" "); + + for (j = 0; j < 16; j++) + if (i + j < buflen) + rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.'); + rt_kprintf("\n"); + } +} +#endif + +/* interrupt service routine */ +void ETH_IRQHandler(void) +{ + rt_uint32_t status, ier; + + /* enter interrupt */ + rt_interrupt_enter(); + + /* ETH DMA status registor */ + status = ETH->DMASTS; + /* ETH DMA interrupt resgitor */ + ier = ETH->DMAINTEN; + + if(status & ETH_DMA_INT_MMC) + { + ETH_ClearDMAIntFlag(ETH_DMA_INT_MMC); + } + + if(status & ETH_DMA_INT_NIS) + { + rt_uint32_t nis_clear = ETH_DMA_INT_NIS; + + /* [0]:Transmit Interrupt. */ + if((status & ier) & ETH_DMA_INT_TX) /* packet transmission */ + { + if (tx_is_waiting == RT_TRUE) + { + tx_is_waiting = RT_FALSE; + rt_sem_release(&tx_wait); + } + + nis_clear |= ETH_DMA_INT_TX; + } + + /* [2]:Transmit Buffer Unavailable. */ + + /* [6]:Receive Interrupt. */ + if((status & ier) & ETH_DMA_INT_RX) /* packet reception */ + { + /* a frame has been received */ + eth_device_ready(&(apm32_eth_device.parent)); + + nis_clear |= ETH_DMA_INT_RX; + } + + /* [14]:Early Receive Interrupt. */ + + ETH_ClearDMAIntFlag(nis_clear); + } + + if(status & ETH_DMA_INT_AIS) + { + rt_uint32_t ais_clear = ETH_DMA_INT_AIS; + + /* [1]:Transmit Process Stopped. */ + if(status & ETH_DMA_INT_TPS) + { + ais_clear |= ETH_DMA_INT_TPS; + } + + /* [3]:Transmit Jabber Timeout. */ + if(status & ETH_DMA_INT_TJT) + { + ais_clear |= ETH_DMA_INT_TJT; + } + + /* [4]: Receive FIFO Overflow. */ + if(status & ETH_DMA_INT_RO) + { + ais_clear |= ETH_DMA_INT_RO; + } + + /* [5]: Transmit Underflow. */ + if(status & ETH_DMA_INT_TU) + { + ais_clear |= ETH_DMA_INT_TU; + } + + /* [7]: Receive Buffer Unavailable. */ + if(status & ETH_DMA_INT_RBU) + { + ais_clear |= ETH_DMA_INT_RBU; + } + + /* [8]: Receive Process Stopped. */ + if(status & ETH_DMA_INT_RPS) + { + ais_clear |= ETH_DMA_INT_RPS; + } + + /* [9]: Receive Watchdog Timeout. */ + if(status & ETH_DMA_INT_RWT) + { + ais_clear |= ETH_DMA_INT_RWT; + } + + /* [10]: Early Transmit Interrupt. */ + + /* [13]: Fatal Bus Error. */ + if(status & ETH_DMA_INT_FBE) + { + ais_clear |= ETH_DMA_INT_FBE; + } + + ETH_ClearDMAIntFlag(ais_clear); + } + + /* leave interrupt */ + rt_interrupt_leave(); +} + +#if (LWIP_IPV4 && LWIP_IGMP) || (LWIP_IPV6 && LWIP_IPV6_MLD) +/* polynomial: 0x04C11DB7 */ +static uint32_t ethcrc(const uint8_t *data, size_t length) +{ + uint32_t crc = 0xffffffff; + size_t i; + int j; + + for (i = 0; i < length; i++) + { + for (j = 0; j < 8; j++) + { + if (((crc >> 31) ^ (data[i] >> j)) & 0x01) + { + /* x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 */ + crc = (crc << 1) ^ 0x04C11DB7; + } + else + { + crc = crc << 1; + } + } + } + + return ~crc; +} + +#define HASH_BITS 6 /* #bits in hash */ +static void register_multicast_address(struct rt_apm32_eth *apm32_eth, const uint8_t *mac) +{ + uint32_t crc; + uint8_t hash; + + /* calculate crc32 value of mac address */ + crc = ethcrc(mac, 6); + + /* only upper 6 bits (HASH_BITS) are used + * which point to specific bit in he hash registers + */ + hash = (crc >> 26) & 0x3F; + //rt_kprintf("register_multicast_address crc: %08X hash: %02X\n", crc, hash); + + if (hash > 31) + { + apm32_eth->ETH_HashTableHigh |= 1 << (hash - 32); + ETH->HTH = apm32_eth->ETH_HashTableHigh; + } + else + { + apm32_eth->ETH_HashTableLow |= 1 << hash; + ETH->HTL = apm32_eth->ETH_HashTableLow; + } +} +#endif /* (LWIP_IPV4 && LWIP_IGMP) || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_IPV4 && LWIP_IGMP +static err_t igmp_mac_filter( struct netif *netif, const ip4_addr_t *ip4_addr, enum netif_mac_filter_action action ) +{ + uint8_t mac[6]; + const uint8_t *p = (const uint8_t *)ip4_addr; + struct rt_apm32_eth *apm32_eth = (struct rt_apm32_eth *)netif->state; + + mac[0] = 0x01; + mac[1] = 0x00; + mac[2] = 0x5E; + mac[3] = *(p+1) & 0x7F; + mac[4] = *(p+2); + mac[5] = *(p+3); + + register_multicast_address(apm32_eth, mac); + + if(1) + { + rt_kprintf("%s %s %s ", __FUNCTION__, (action==NETIF_ADD_MAC_FILTER)?"add":"del", ip4addr_ntoa(ip4_addr)); + rt_kprintf("%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } + + return 0; +} +#endif /* LWIP_IPV4 && LWIP_IGMP */ + +#if LWIP_IPV6 && LWIP_IPV6_MLD +static err_t mld_mac_filter( struct netif *netif, const ip6_addr_t *ip6_addr, enum netif_mac_filter_action action ) +{ + uint8_t mac[6]; + const uint8_t *p = (const uint8_t *)&ip6_addr->addr[3]; + struct rt_apm32_eth *apm32_eth = (struct rt_apm32_eth *)netif->state; + + mac[0] = 0x33; + mac[1] = 0x33; + mac[2] = *(p+0); + mac[3] = *(p+1); + mac[4] = *(p+2); + mac[5] = *(p+3); + + register_multicast_address(apm32_eth, mac); + + if(1) + { + rt_kprintf("%s %s %s ", __FUNCTION__, (action==NETIF_ADD_MAC_FILTER)?"add":"del", ip6addr_ntoa(ip6_addr)); + rt_kprintf("%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } + + return 0; +} +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + +/* initialize the interface */ +static rt_err_t rt_apm32_eth_init(rt_device_t dev) +{ + struct rt_apm32_eth * apm32_eth = (struct rt_apm32_eth *)dev; + ETH_Config_T ETH_InitStructure; + + /* Enable ETHERNET clock */ + RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_ETH_MAC | RCM_AHB1_PERIPH_ETH_MAC_Tx | + RCM_AHB1_PERIPH_ETH_MAC_Rx); + + /* Reset ETHERNET on AHB Bus */ + ETH_Reset(); + + /* Software reset */ + ETH_SoftwareReset(); + + /* Wait for software reset */ + while(ETH_ReadSoftwareReset() == SET); + + /* ETHERNET Configuration --------------------------------------------------*/ + /* Call ETH_StructInit if you don't like to configure all ETH_InitStructure parameter */ + ETH_ConfigStructInit(Ð_InitStructure); + + /* Fill ETH_InitStructure parametrs */ + /*------------------------ MAC -----------------------------------*/ + ETH_InitStructure.autoNegotiation = ETH_AUTONEGOTIATION_ENABLE; + ETH_InitStructure.speed = (ETH_SPEED_T)apm32_eth->ETH_Speed; + ETH_InitStructure.mode = (ETH_MODE_T)apm32_eth->ETH_Mode; + + ETH_InitStructure.loopbackMode = ETH_LOOPBACKMODE_DISABLE; + ETH_InitStructure.retryTransmission = ETH_RETRYTRANSMISSION_DISABLE; + ETH_InitStructure.automaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE; + ETH_InitStructure.receiveAll = ETH_RECEIVEAll_DISABLE; + ETH_InitStructure.broadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE; + ETH_InitStructure.promiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE; + ETH_InitStructure.multicastFramesFilter = ETH_MULTICASTFRAMESFILTER_HASHTABLE; + ETH_InitStructure.hashTableHigh = apm32_eth->ETH_HashTableHigh; + ETH_InitStructure.hashTableLow = apm32_eth->ETH_HashTableLow; + ETH_InitStructure.unicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT; +#ifdef HARDWARE_CHECKSUM + ETH_InitStructure.checksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE; +#endif + + /*------------------------ DMA -----------------------------------*/ + + /* When we use the Checksum offload feature, we need to enable the Store and Forward mode: + the store and forward guarantee that a whole frame is stored in the FIFO, so the MAC can insert/verify the checksum, + if the checksum is OK the DMA can handle the frame otherwise the frame is dropped */ + ETH_InitStructure.dropTCPIPChecksumErrorFrame = ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE; + ETH_InitStructure.receiveStoreForward = ETH_RECEIVESTOREFORWARD_ENABLE; + ETH_InitStructure.flushReceivedFrame = ETH_FLUSHRECEIVEDFRAME_DISABLE; + ETH_InitStructure.transmitStoreForward = ETH_TRANSMITSTOREFORWARD_ENABLE; + + ETH_InitStructure.forwardErrorFrames = ETH_FORWARDERRORFRAMES_DISABLE; + ETH_InitStructure.forwardUndersizedGoodFrames = ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE; + ETH_InitStructure.secondFrameOperate = ETH_SECONDFRAMEOPERARTE_ENABLE; + ETH_InitStructure.addressAlignedBeats = ETH_ADDRESSALIGNEDBEATS_ENABLE; + ETH_InitStructure.fixedBurst = ETH_FIXEDBURST_ENABLE; + ETH_InitStructure.rxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT; + ETH_InitStructure.txDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT; + ETH_InitStructure.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_2_1; + + /* configure Ethernet */ + ETH_Config(Ð_InitStructure, phy_addr); + + /* Enable DMA Receive interrupt (need to enable in this case Normal interrupt) */ + ETH_EnableDMAInterrupt(ETH_DMA_INT_NIS | ETH_DMA_INT_RX | ETH_DMA_INT_TX); + NVIC_EnableIRQ(ETH_IRQn); + + /* Initialize Tx Descriptors list: Chain Mode */ + ETH_ConfigDMATxDescChain(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); + /* Initialize Rx Descriptors list: Chain Mode */ + ETH_ConfigDMARxDescChain(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); + + /* MAC address configuration */ + ETH_ConfigMACAddress(ETH_MAC_ADDRESS0, (u8*)&apm32_eth_device.dev_addr[0]); + + /* Enable MAC and DMA transmission and reception */ + ETH_Start(); + +#if LWIP_IPV4 && LWIP_IGMP + netif_set_igmp_mac_filter(apm32_eth->parent.netif, igmp_mac_filter); +#endif /* LWIP_IPV4 && LWIP_IGMP */ + +#if LWIP_IPV6 && LWIP_IPV6_MLD + netif_set_mld_mac_filter(apm32_eth->parent.netif, mld_mac_filter); +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + + return RT_EOK; +} + +static rt_err_t rt_apm32_eth_open(rt_device_t dev, rt_uint16_t oflag) +{ + return RT_EOK; +} + +static rt_err_t rt_apm32_eth_close(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_size_t rt_apm32_eth_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) +{ + rt_set_errno(-RT_ENOSYS); + return 0; +} + +static rt_size_t rt_apm32_eth_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) +{ + rt_set_errno(-RT_ENOSYS); + return 0; +} + +static rt_err_t rt_apm32_eth_control(rt_device_t dev, int cmd, void *args) +{ + switch(cmd) + { + case NIOCTL_GADDR: + /* get mac address */ + if(args) rt_memcpy(args, apm32_eth_device.dev_addr, 6); + else return -RT_ERROR; + break; + + default : + break; + } + + return RT_EOK; +} + +/* ethernet device interface */ +/* transmit packet. */ +rt_err_t rt_apm32_eth_tx( rt_device_t dev, struct pbuf* p) +{ + struct pbuf* q; + rt_uint32_t offset; + + /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */ + while ((DMATxDescToSet->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) + { + rt_err_t result; + rt_uint32_t level; + + level = rt_hw_interrupt_disable(); + tx_is_waiting = RT_TRUE; + rt_hw_interrupt_enable(level); + + /* it's own bit set, wait it */ + result = rt_sem_take(&tx_wait, RT_WAITING_FOREVER); + if (result == RT_EOK) break; + if (result == -RT_ERROR) return -RT_ERROR; + } + + offset = 0; + for (q = p; q != NULL; q = q->next) + { + uint8_t *to; + + /* Copy the frame to be sent into memory pointed by the current ETHERNET DMA Tx descriptor */ + to = (uint8_t*)((DMATxDescToSet->Buffer1Addr) + offset); + memcpy(to, q->payload, q->len); + offset += q->len; + } +#ifdef ETH_TX_DUMP + rt_kprintf("tx_dump, len:%d\r\n", p->tot_len); + dump_hex((rt_uint8_t*)(DMATxDescToSet->Buffer1Addr), p->tot_len); +#endif + + /* Setting the Frame Length: bits[12:0] */ + DMATxDescToSet->ControlBufferSize = (p->tot_len & ETH_DMATXDESC_TXBS1); + /* Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) */ + DMATxDescToSet->Status |= ETH_DMATXDESC_LS | ETH_DMATXDESC_FS; + /* Enable TX Completion Interrupt */ + DMATxDescToSet->Status |= ETH_DMATXDESC_INTC; +#ifdef CHECKSUM_BY_HARDWARE + DMATxDescToSet->Status |= ETH_DMATxDesc_ChecksumTCPUDPICMPFull; + /* clean ICMP checksum APM32F need */ + { + struct eth_hdr *ethhdr = (struct eth_hdr *)(DMATxDescToSet->Buffer1Addr); + /* is IP ? */ + if( ethhdr->type == htons(ETHTYPE_IP) ) + { + struct ip_hdr *iphdr = (struct ip_hdr *)(DMATxDescToSet->Buffer1Addr + SIZEOF_ETH_HDR); + /* is ICMP ? */ + if( IPH_PROTO(iphdr) == IP_PROTO_ICMP ) + { + struct icmp_echo_hdr *iecho = (struct icmp_echo_hdr *)(DMATxDescToSet->Buffer1Addr + SIZEOF_ETH_HDR + sizeof(struct ip_hdr) ); + iecho->chksum = 0; + } + } + } +#endif + /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ + DMATxDescToSet->Status |= ETH_DMATXDESC_OWN; + /* When Tx Buffer unavailable flag is set: clear it and resume transmission */ + if ((ETH->DMASTS & BIT2) != (u32)RESET) + { + /** Clear TBUS ETHERNET DMA flag */ + ETH->DMASTS = BIT2; + /** Resume DMA transmission*/ + ETH->DMATXPD = 0; + } + + /* Update the ETHERNET DMA global Tx descriptor with next Tx decriptor */ + /* Chained Mode */ + /* Selects the next DMA Tx descriptor list for next buffer to send */ + DMATxDescToSet = (ETH_DMADescConfig_T*) (DMATxDescToSet->Buffer2NextDescAddr); + + /* Return SUCCESS */ + return RT_EOK; +} + +/* reception packet. */ +struct pbuf *rt_apm32_eth_rx(rt_device_t dev) +{ + struct pbuf* p; + rt_uint32_t offset = 0, framelength = 0; + + /* init p pointer */ + p = RT_NULL; + + /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */ + if(((DMARxDescToGet->Status & ETH_DMARXDESC_OWN) != (uint32_t)RESET)) + return p; + + if (((DMARxDescToGet->Status & ETH_DMARXDESC_ERRS) == (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARXDESC_LDES) != (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARXDESC_FDES) != (uint32_t)RESET)) + { + /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */ + framelength = ((DMARxDescToGet->Status & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAME_LENGTHSHIFT) - 4; + + /* allocate buffer */ + p = pbuf_alloc(PBUF_LINK, framelength, PBUF_RAM); + if (p != RT_NULL) + { + struct pbuf* q; + + for (q = p; q != RT_NULL; q= q->next) + { + /* Copy the received frame into buffer from memory pointed by the current ETHERNET DMA Rx descriptor */ + memcpy(q->payload, (uint8_t *)((DMARxDescToGet->Buffer1Addr) + offset), q->len); + offset += q->len; + } +#ifdef ETH_RX_DUMP + rt_kprintf("rx_dump, len:%d\r\n", p->tot_len); + dump_hex((rt_uint8_t*)(DMARxDescToGet->Buffer1Addr), p->tot_len); +#endif + } + } + + /* Set Own bit of the Rx descriptor Status: gives the buffer back to ETHERNET DMA */ + DMARxDescToGet->Status = ETH_DMARXDESC_OWN; + + /* When Rx Buffer unavailable flag is set: clear it and resume reception */ + if ((ETH->DMASTS & BIT7) != (u32)RESET) + { + /* Clear RBUS ETHERNET DMA flag */ + ETH->DMASTS = BIT7; + /* Resume DMA reception */ + ETH->DMARXPD = 0; + } + + /* Update the ETHERNET DMA global Rx descriptor with next Rx decriptor */ + /* Chained Mode */ + if((DMARxDescToGet->ControlBufferSize & ETH_DMARXDESC_RXCH) != (uint32_t)RESET) + { + /* Selects the next DMA Rx descriptor list for next buffer to read */ + DMARxDescToGet = (ETH_DMADescConfig_T*) (DMARxDescToGet->Buffer2NextDescAddr); + } + else /* Ring Mode */ + { + if((DMARxDescToGet->ControlBufferSize & ETH_DMARXDESC_RXER) != (uint32_t)RESET) + { + /* Selects the first DMA Rx descriptor for next buffer to read: last Rx descriptor was used */ + DMARxDescToGet = (ETH_DMADescConfig_T*) (ETH->DMARXDLADDR); + } + else + { + /* Selects the next DMA Rx descriptor list for next buffer to read */ + DMARxDescToGet = (ETH_DMADescConfig_T*) ((uint32_t)DMARxDescToGet + 0x10 + ((ETH->DMABMOD & 0x0000007C) >> 2)); + } + } + + return p; +} + +enum { + PHY_LINK_MASK = (1 << 0), + PHY_100M_MASK = (1 << 1), + PHY_DUPLEX_MASK = (1 << 2), +}; + +static void phy_linkchange(void) +{ + uint8_t phy_speed_new = 0; + static uint8_t phy_speed = 0; + uint16_t status = ETH_ReadPHYRegister(phy_addr, PHY_BSR); + + LOG_D("phy basic status reg is 0x%X", status); + + if(status & (PHY_AUTONEGO_COMPLETE | PHY_LINKED_STATUS)) + { + uint16_t SR; + + phy_speed_new |= PHY_LINK_MASK; + + SR = ETH_ReadPHYRegister(phy_addr, PHY_Status_REG); + LOG_D("phy control status reg is 0x%X", SR); + + if (PHY_Status_SPEED_100M(SR)) + { + phy_speed_new |= PHY_100M_MASK; + } + + if (PHY_Status_FULL_DUPLEX(SR)) + { + phy_speed_new |= PHY_DUPLEX_MASK; + } + } + + /* linkchange */ + if(phy_speed_new != phy_speed) + { + if(phy_speed_new & PHY_LINK_MASK) + { + LOG_D("link up "); + + if(phy_speed_new & PHY_100M_MASK) + { + LOG_D("100Mbps"); + apm32_eth_device.ETH_Speed = ETH_SPEED_100M; + } + else + { + apm32_eth_device.ETH_Speed = ETH_SPEED_10M; + LOG_D("10Mbps"); + } + + if(phy_speed_new & PHY_DUPLEX_MASK) + { + LOG_D("full-duplex\r\n"); + apm32_eth_device.ETH_Mode = ETH_MODE_FULLDUPLEX; + } + else + { + LOG_D("half-duplex\r\n"); + apm32_eth_device.ETH_Mode = ETH_MODE_HALFDUPLEX; + } + rt_apm32_eth_init((rt_device_t)&apm32_eth_device); + + /* send link up. */ + eth_device_linkchange(&apm32_eth_device.parent, RT_TRUE); + } /* link up. */ + else + { + LOG_I("link down\r\n"); + /* send link down. */ + eth_device_linkchange(&apm32_eth_device.parent, RT_FALSE); + } /* link down. */ + + phy_speed = phy_speed_new; + } /* linkchange */ +} + +static void phy_monitor_thread_entry(void *parameter) +{ + uint8_t detected_count = 0; + + while(phy_addr == 0xFF) + { + /* phy search */ + rt_uint32_t i, temp; + for (i = 0; i <= 0x1F; i++) + { + temp = ETH_ReadPHYRegister(i, PHY_ID1_REG); + + if (temp != 0xFFFF && temp != 0x00) + { + phy_addr = i; + break; + } + } + + detected_count++; + rt_thread_mdelay(1000); + + if (detected_count > 10) + { + LOG_E("No PHY device was detected, please check hardware!"); + } + } + + LOG_D("Found a phy, address:0x%02X", phy_addr); + + /* RESET PHY */ + LOG_D("RESET PHY!\r\n"); + ETH_WritePHYRegister(phy_addr, PHY_BCR, PHY_RESET); + rt_thread_delay(RT_TICK_PER_SECOND * 2); + ETH_WritePHYRegister(phy_addr, PHY_BCR, PHY_AUTONEGOTIATION); + + phy_linkchange(); + + apm32_eth_device.poll_link_timer = rt_timer_create("phylnk", (void (*)(void*))phy_linkchange, + NULL, RT_TICK_PER_SECOND, RT_TIMER_FLAG_PERIODIC); + if (!apm32_eth_device.poll_link_timer || rt_timer_start(apm32_eth_device.poll_link_timer) != RT_EOK) + { + LOG_E("Start link change detection timer failed"); + } +} + +static int rt_hw_apm32_eth_init(void) +{ + extern void phy_reset(void); + phy_reset(); + + void ETH_GPIO_Configuration(void); + ETH_GPIO_Configuration(); + + apm32_eth_device.ETH_Speed = ETH_SPEED_100M; + apm32_eth_device.ETH_Mode = ETH_MODE_FULLDUPLEX; + + /* set mac address. */ + apm32_eth_device.dev_addr[0] = 0x00; + apm32_eth_device.dev_addr[1] = 0x00; + apm32_eth_device.dev_addr[2] = 0x00; + apm32_eth_device.dev_addr[3] = 0x00; + apm32_eth_device.dev_addr[4] = 0x00; + apm32_eth_device.dev_addr[5] = 0x08; + + apm32_eth_device.parent.parent.init = rt_apm32_eth_init; + apm32_eth_device.parent.parent.open = rt_apm32_eth_open; + apm32_eth_device.parent.parent.close = rt_apm32_eth_close; + apm32_eth_device.parent.parent.read = rt_apm32_eth_read; + apm32_eth_device.parent.parent.write = rt_apm32_eth_write; + apm32_eth_device.parent.parent.control = rt_apm32_eth_control; + apm32_eth_device.parent.parent.user_data = RT_NULL; + + apm32_eth_device.parent.eth_rx = rt_apm32_eth_rx; + apm32_eth_device.parent.eth_tx = rt_apm32_eth_tx; + + /* init tx semaphore */ + rt_sem_init(&tx_wait, "tx_wait", 0, RT_IPC_FLAG_FIFO); + + /* register eth device */ + eth_device_init(&(apm32_eth_device.parent), "e0"); + + /* start phy monitor */ + { + rt_thread_t tid; + tid = rt_thread_create("phy", + phy_monitor_thread_entry, + RT_NULL, + 512, + RT_THREAD_PRIORITY_MAX - 2, + 2); + if (tid != RT_NULL) + rt_thread_startup(tid); + } + + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_apm32_eth_init); + +#endif /* BSP_USING_ETH */ diff --git a/bsp/apm32/libraries/Drivers/drv_eth.h b/bsp/apm32/libraries/Drivers/drv_eth.h new file mode 100644 index 0000000000..9d70f5be46 --- /dev/null +++ b/bsp/apm32/libraries/Drivers/drv_eth.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-10-20 luobeihai first version + */ + +#ifndef __DRV_ETH_H__ +#define __DRV_ETH_H__ + +#include +#include +#include +#include + +#ifndef LOG_TAG +#define DBG_TAG "drv" +#else +#define DBG_TAG LOG_TAG +#endif /* LOG_TAG */ + +#ifdef DRV_DEBUG +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO +#endif /* DRV_DEBUG */ + +#include + + +/* The PHY ID one register */ +#define PHY_ID1_REG 0x02U + + +#ifdef PHY_USING_LAN8720A +/* The PHY interrupt source flag register. */ +#define PHY_INTERRUPT_FLAG_REG 0x1DU +/* The PHY interrupt mask register. */ +#define PHY_INTERRUPT_MASK_REG 0x1EU +#define PHY_LINK_DOWN_MASK (1<<4) +#define PHY_AUTO_NEGO_COMPLETE_MASK (1<<6) + +/* The PHY status register. */ +#define PHY_Status_REG 0x1FU +#define PHY_10M_MASK (1<<2) +#define PHY_100M_MASK (1<<3) +#define PHY_FULL_DUPLEX_MASK (1<<4) +#define PHY_Status_SPEED_10M(sr) ((sr) & PHY_10M_MASK) +#define PHY_Status_SPEED_100M(sr) ((sr) & PHY_100M_MASK) +#define PHY_Status_FULL_DUPLEX(sr) ((sr) & PHY_FULL_DUPLEX_MASK) + +#elif defined(PHY_USING_DM9161CEP) +#define PHY_Status_REG 0x11U +#define PHY_10M_MASK ((1<<12) || (1<<13)) +#define PHY_100M_MASK ((1<<14) || (1<<15)) +#define PHY_FULL_DUPLEX_MASK ((1<<15) || (1<<13)) +#define PHY_Status_SPEED_10M(sr) ((sr) & PHY_10M_MASK) +#define PHY_Status_SPEED_100M(sr) ((sr) & PHY_100M_MASK) +#define PHY_Status_FULL_DUPLEX(sr) ((sr) & PHY_FULL_DUPLEX_MASK) +/* The PHY interrupt source flag register. */ +#define PHY_INTERRUPT_FLAG_REG 0x15U +/* The PHY interrupt mask register. */ +#define PHY_INTERRUPT_MASK_REG 0x15U +#define PHY_LINK_CHANGE_FLAG (1<<2) +#define PHY_LINK_CHANGE_MASK (1<<9) +#define PHY_INT_MASK 0 + +#elif defined(PHY_USING_DP83848C) +#define PHY_Status_REG 0x10U +#define PHY_10M_MASK (1<<1) +#define PHY_FULL_DUPLEX_MASK (1<<2) +#define PHY_Status_SPEED_10M(sr) ((sr) & PHY_10M_MASK) +#define PHY_Status_SPEED_100M(sr) (!PHY_Status_SPEED_10M(sr)) +#define PHY_Status_FULL_DUPLEX(sr) ((sr) & PHY_FULL_DUPLEX_MASK) +/* The PHY interrupt source flag register. */ +#define PHY_INTERRUPT_FLAG_REG 0x12U +#define PHY_LINK_CHANGE_FLAG (1<<13) +/* The PHY interrupt control register. */ +#define PHY_INTERRUPT_CTRL_REG 0x11U +#define PHY_INTERRUPT_EN ((1<<0)|(1<<1)) +/* The PHY interrupt mask register. */ +#define PHY_INTERRUPT_MASK_REG 0x12U +#define PHY_INT_MASK (1<<5) +#endif + +#ifdef PHY_USING_LAN8742A +/* The PHY interrupt source flag register. */ +#define PHY_INTERRUPT_FLAG_REG 0x1DU +/* The PHY interrupt mask register. */ +#define PHY_INTERRUPT_MASK_REG 0x1EU +#define PHY_LINK_DOWN_MASK (1<<4) +#define PHY_AUTO_NEGO_COMPLETE_MASK (1<<6) + +/* The PHY status register. */ +#define PHY_Status_REG 0x1FU +#define PHY_10M_MASK (1<<2) +#define PHY_100M_MASK (1<<3) +#define PHY_FULL_DUPLEX_MASK (1<<4) +#define PHY_Status_SPEED_10M(sr) ((sr) & PHY_10M_MASK) +#define PHY_Status_SPEED_100M(sr) ((sr) & PHY_100M_MASK) +#define PHY_Status_FULL_DUPLEX(sr) ((sr) & PHY_FULL_DUPLEX_MASK) +#endif /* PHY_USING_LAN8742A */ + +#endif /* __DRV_ETH_H__ */ diff --git a/bsp/apm32/libraries/Drivers/drv_gpio.c b/bsp/apm32/libraries/Drivers/drv_gpio.c index eb3f8e3ed3..3e3e14907b 100644 --- a/bsp/apm32/libraries/Drivers/drv_gpio.c +++ b/bsp/apm32/libraries/Drivers/drv_gpio.c @@ -7,6 +7,7 @@ * Date Author Notes * 2020-08-20 Abbcc first version * 2022-07-15 Aligagago add apm32F4 serie MCU support + * 2022-12-26 luobeihai add apm32F0 serie MCU support */ #include @@ -19,7 +20,6 @@ #define PIN_NO(pin) ((uint8_t)((pin) & 0xFu)) #define PIN_APMPORT(pin) ((GPIO_T *)(GPIOA_BASE + (0x400u * PIN_PORT(pin)))) - #define PIN_APMPIN(pin) ((uint16_t)(1u << PIN_NO(pin))) #if defined(GPIOZ) @@ -55,6 +55,24 @@ static const struct pin_irq_map pin_irq_map[] = { +#if defined(SOC_SERIES_APM32F0) + {GPIO_PIN_0, EINT0_1_IRQn}, + {GPIO_PIN_1, EINT0_1_IRQn}, + {GPIO_PIN_2, EINT2_3_IRQn}, + {GPIO_PIN_3, EINT2_3_IRQn}, + {GPIO_PIN_4, EINT4_15_IRQn}, + {GPIO_PIN_5, EINT4_15_IRQn}, + {GPIO_PIN_6, EINT4_15_IRQn}, + {GPIO_PIN_7, EINT4_15_IRQn}, + {GPIO_PIN_8, EINT4_15_IRQn}, + {GPIO_PIN_9, EINT4_15_IRQn}, + {GPIO_PIN_10, EINT4_15_IRQn}, + {GPIO_PIN_11, EINT4_15_IRQn}, + {GPIO_PIN_12, EINT4_15_IRQn}, + {GPIO_PIN_13, EINT4_15_IRQn}, + {GPIO_PIN_14, EINT4_15_IRQn}, + {GPIO_PIN_15, EINT4_15_IRQn}, +#else {GPIO_PIN_0, EINT0_IRQn}, {GPIO_PIN_1, EINT1_IRQn}, {GPIO_PIN_2, EINT2_IRQn}, @@ -71,6 +89,7 @@ static const struct pin_irq_map pin_irq_map[] = {GPIO_PIN_13, EINT15_10_IRQn}, {GPIO_PIN_14, EINT15_10_IRQn}, {GPIO_PIN_15, EINT15_10_IRQn}, +#endif }; static struct rt_pin_irq_hdr pin_irq_hdr_tab[] = @@ -96,7 +115,7 @@ static uint32_t pin_irq_enable_mask = 0; #define ITEM_NUM(items) sizeof(items) / sizeof(items[0]) -static rt_base_t _pin_get(const char *name) +static rt_base_t apm32_pin_get(const char *name) { rt_base_t pin = 0; int hw_port_num, hw_pin_num = 0; @@ -133,7 +152,7 @@ static rt_base_t _pin_get(const char *name) return pin; } -static void _pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) +static void apm32_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) { GPIO_T *gpio_port; uint16_t gpio_pin; @@ -142,12 +161,15 @@ static void _pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) { gpio_port = PIN_APMPORT(pin); gpio_pin = PIN_APMPIN(pin); - +#if defined(SOC_SERIES_APM32F0) + GPIO_WriteBitValue(gpio_port, gpio_pin, (GPIO_BSRET_T)value); +#else GPIO_WriteBitValue(gpio_port, gpio_pin, (uint8_t)value); +#endif } } -static int _pin_read(rt_device_t dev, rt_base_t pin) +static int apm32_pin_read(rt_device_t dev, rt_base_t pin) { GPIO_T *gpio_port; uint16_t gpio_pin; @@ -163,7 +185,7 @@ static int _pin_read(rt_device_t dev, rt_base_t pin) return value; } -static void _pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) +static void apm32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) { GPIO_Config_T gpioConfig; @@ -173,7 +195,7 @@ static void _pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) } /* Configure gpioConfigure */ -#if defined(APM32F10X_HD) +#if defined(SOC_SERIES_APM32F1) gpioConfig.pin = PIN_APMPIN(pin); gpioConfig.mode = GPIO_MODE_OUT_PP; gpioConfig.speed = GPIO_SPEED_50MHz; @@ -203,7 +225,7 @@ static void _pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) /* output setting: od. */ gpioConfig.mode = GPIO_MODE_OUT_OD; } -#elif defined( APM32F40X) +#elif defined(SOC_SERIES_APM32F4) gpioConfig.pin = PIN_APMPIN(pin); gpioConfig.mode = GPIO_MODE_OUT; gpioConfig.otype = GPIO_OTYPE_PP; @@ -239,6 +261,43 @@ static void _pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) gpioConfig.mode = GPIO_MODE_OUT; gpioConfig.otype = GPIO_OTYPE_OD; } +#elif defined(SOC_SERIES_APM32F0) + gpioConfig.pin = PIN_APMPIN(pin); + gpioConfig.mode = GPIO_MODE_OUT; + gpioConfig.outtype = GPIO_OUT_TYPE_PP; + gpioConfig.pupd = GPIO_PUPD_NO; + gpioConfig.speed = GPIO_SPEED_50MHz; + + if (mode == PIN_MODE_OUTPUT) + { + /* output setting */ + gpioConfig.mode = GPIO_MODE_OUT; + gpioConfig.outtype = GPIO_OUT_TYPE_PP; + } + else if (mode == PIN_MODE_INPUT) + { + /* input setting: not pull. */ + gpioConfig.mode = GPIO_MODE_IN; + gpioConfig.pupd = GPIO_PUPD_NO; + } + else if (mode == PIN_MODE_INPUT_PULLUP) + { + /* input setting: pull up. */ + gpioConfig.mode = GPIO_MODE_IN; + gpioConfig.pupd = GPIO_PUPD_PU; + } + else if (mode == PIN_MODE_INPUT_PULLDOWN) + { + /* input setting: pull down. */ + gpioConfig.mode = GPIO_MODE_IN; + gpioConfig.pupd = GPIO_PUPD_PD; + } + else if (mode == PIN_MODE_OUTPUT_OD) + { + /* output setting: od. */ + gpioConfig.mode = GPIO_MODE_OUT; + gpioConfig.outtype = GPIO_OUT_TYPE_OD; + } #endif GPIO_Config(PIN_APMPORT(pin), &gpioConfig); } @@ -266,7 +325,7 @@ rt_inline const struct pin_irq_map *get_pin_irq_map(uint32_t pinbit) return &pin_irq_map[mapindex]; }; -static rt_err_t _pin_attach_irq(struct rt_device *device, rt_int32_t pin, +static rt_err_t apm32_pin_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args) { rt_base_t level; @@ -306,7 +365,7 @@ static rt_err_t _pin_attach_irq(struct rt_device *device, rt_int32_t pin, return RT_EOK; } -static rt_err_t _pin_dettach_irq(struct rt_device *device, rt_int32_t pin) +static rt_err_t apm32_pin_dettach_irq(struct rt_device *device, rt_int32_t pin) { rt_base_t level; rt_int32_t irqindex = -1; @@ -337,13 +396,14 @@ static rt_err_t _pin_dettach_irq(struct rt_device *device, rt_int32_t pin) return RT_EOK; } -static rt_err_t _pin_irq_enable(struct rt_device *device, rt_base_t pin, +static rt_err_t apm32_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled) { const struct pin_irq_map *irqmap; rt_base_t level; rt_int32_t irqindex = -1; GPIO_Config_T gpioConfig; + EINT_Config_T eintConfig; if (PIN_PORT(pin) >= PIN_APMPORT_MAX) { @@ -373,34 +433,75 @@ static rt_err_t _pin_irq_enable(struct rt_device *device, rt_base_t pin, gpioConfig.speed = GPIO_SPEED_50MHz; switch (pin_irq_hdr_tab[irqindex].mode) { -#if defined(APM32F10X_HD) +#if defined(SOC_SERIES_APM32F0) + case PIN_IRQ_MODE_RISING: + gpioConfig.mode = GPIO_MODE_IN; + gpioConfig.pupd = GPIO_PUPD_PD; + eintConfig.trigger = EINT_TRIGGER_RISING; + break; + case PIN_IRQ_MODE_FALLING: + gpioConfig.mode = GPIO_MODE_IN; + gpioConfig.pupd = GPIO_PUPD_PU; + eintConfig.trigger = EINT_TRIGGER_FALLING; + break; + case PIN_IRQ_MODE_RISING_FALLING: + gpioConfig.mode = GPIO_MODE_IN; + gpioConfig.pupd = GPIO_PUPD_NO; + eintConfig.trigger = EINT_TRIGGER_ALL; + break; +#elif defined(SOC_SERIES_APM32F1) case PIN_IRQ_MODE_RISING: gpioConfig.mode = GPIO_MODE_IN_PD; + eintConfig.trigger = EINT_TRIGGER_RISING; break; case PIN_IRQ_MODE_FALLING: gpioConfig.mode = GPIO_MODE_IN_PU; + eintConfig.trigger = EINT_TRIGGER_FALLING; break; case PIN_IRQ_MODE_RISING_FALLING: gpioConfig.mode = GPIO_MODE_IN_FLOATING; + eintConfig.trigger = EINT_TRIGGER_RISING_FALLING; break; -#elif defined( APM32F40X) +#elif defined(SOC_SERIES_APM32F4) case PIN_IRQ_MODE_RISING: gpioConfig.mode = GPIO_MODE_IN; gpioConfig.pupd = GPIO_PUPD_DOWN; + eintConfig.trigger = EINT_TRIGGER_RISING; break; case PIN_IRQ_MODE_FALLING: gpioConfig.mode = GPIO_MODE_IN; gpioConfig.pupd = GPIO_PUPD_UP; + eintConfig.trigger = EINT_TRIGGER_FALLING; break; case PIN_IRQ_MODE_RISING_FALLING: gpioConfig.mode = GPIO_MODE_IN; gpioConfig.pupd = GPIO_PUPD_NOPULL; + eintConfig.trigger = EINT_TRIGGER_RISING_FALLING; break; #endif } GPIO_Config(PIN_APMPORT(pin), &gpioConfig); - + +#if defined(SOC_SERIES_APM32F0) + RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG); + SYSCFG_EINTLine((SYSCFG_PORT_T)(((pin) >> 4) & 0xFu), (SYSCFG_PIN_T)irqindex); +#elif defined(SOC_SERIES_APM32F1) + RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_AFIO); + GPIO_ConfigEINTLine((GPIO_PORT_SOURCE_T)(((pin) >> 4) & 0xFu), (GPIO_PIN_SOURCE_T)irqindex); +#elif defined(SOC_SERIES_APM32F4) + RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG); + SYSCFG_ConfigEINTLine((SYSCFG_PORT_T)(((pin) >> 4) & 0xFu), (SYSCFG_PIN_T)irqindex); +#endif + eintConfig.line = (EINT_LINE_T)(1u << PIN_NO(pin)); + eintConfig.mode = EINT_MODE_INTERRUPT; + eintConfig.lineCmd = ENABLE; + EINT_Config(&eintConfig); + +#if defined(SOC_SERIES_APM32F0) + NVIC_EnableIRQRequest(irqmap->irqno, 5); +#else NVIC_EnableIRQRequest(irqmap->irqno, 5, 0); +#endif pin_irq_enable_mask |= irqmap->pinbit; rt_hw_interrupt_enable(level); @@ -416,7 +517,35 @@ static rt_err_t _pin_irq_enable(struct rt_device *device, rt_base_t pin, level = rt_hw_interrupt_disable(); pin_irq_enable_mask &= ~irqmap->pinbit; - + +#if defined(SOC_SERIES_APM32F0) + if ((irqmap->pinbit >= GPIO_PIN_0) && (irqmap->pinbit <= GPIO_PIN_1)) + { + if (!(pin_irq_enable_mask & (GPIO_PIN_0 | GPIO_PIN_1))) + { + NVIC_DisableIRQRequest(irqmap->irqno); + } + } + else if ((irqmap->pinbit >= GPIO_PIN_2) && (irqmap->pinbit <= GPIO_PIN_3)) + { + if (!(pin_irq_enable_mask & (GPIO_PIN_2 | GPIO_PIN_3))) + { + NVIC_DisableIRQRequest(irqmap->irqno); + } + } + else if ((irqmap->pinbit >= GPIO_PIN_4) && (irqmap->pinbit <= GPIO_PIN_15)) + { + if (!(pin_irq_enable_mask & (GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | + GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15))) + { + NVIC_DisableIRQRequest(irqmap->irqno); + } + } + else + { + NVIC_DisableIRQRequest(irqmap->irqno); + } +#else 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))) @@ -435,6 +564,7 @@ static rt_err_t _pin_irq_enable(struct rt_device *device, rt_base_t pin, { NVIC_DisableIRQRequest(irqmap->irqno); } +#endif rt_hw_interrupt_enable(level); } else @@ -444,15 +574,16 @@ static rt_err_t _pin_irq_enable(struct rt_device *device, rt_base_t pin, return RT_EOK; } -const static struct rt_pin_ops _apm32_pin_ops = + +const static struct rt_pin_ops apm32_pin_ops = { - _pin_mode, - _pin_write, - _pin_read, - _pin_attach_irq, - _pin_dettach_irq, - _pin_irq_enable, - _pin_get, + apm32_pin_mode, + apm32_pin_write, + apm32_pin_read, + apm32_pin_attach_irq, + apm32_pin_dettach_irq, + apm32_pin_irq_enable, + apm32_pin_get, }; rt_inline void pin_irq_hdr(int irqno) @@ -463,140 +594,115 @@ rt_inline void pin_irq_hdr(int irqno) } } - -void GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin) +void GPIO_EXTI_IRQHandler(uint8_t exti_line) { - pin_irq_hdr(bit2bitno(GPIO_Pin)); +#if defined(SOC_SERIES_APM32F0) + if (EINT_ReadIntFlag(1U << exti_line) != RESET) +#else + if (EINT_ReadIntFlag((EINT_LINE_T)(1U << exti_line)) != RESET) +#endif + { + EINT_ClearIntFlag(1U << exti_line); + pin_irq_hdr(exti_line); + } } +#if defined(SOC_SERIES_APM32F0) +void EINT0_1_IRQHandler(void) +{ + rt_interrupt_enter(); + GPIO_EXTI_IRQHandler(0); + GPIO_EXTI_IRQHandler(1); + rt_interrupt_leave(); +} +void EINT2_3_IRQHandler(void) +{ + rt_interrupt_enter(); + GPIO_EXTI_IRQHandler(2); + GPIO_EXTI_IRQHandler(3); + rt_interrupt_leave(); +} +void EINT4_15_IRQHandler(void) +{ + rt_interrupt_enter(); + GPIO_EXTI_IRQHandler(4); + GPIO_EXTI_IRQHandler(5); + GPIO_EXTI_IRQHandler(6); + GPIO_EXTI_IRQHandler(7); + GPIO_EXTI_IRQHandler(8); + GPIO_EXTI_IRQHandler(9); + GPIO_EXTI_IRQHandler(10); + GPIO_EXTI_IRQHandler(11); + GPIO_EXTI_IRQHandler(12); + GPIO_EXTI_IRQHandler(13); + GPIO_EXTI_IRQHandler(14); + GPIO_EXTI_IRQHandler(15); + rt_interrupt_leave(); +} +#else void EINT0_IRQHandler(void) { rt_interrupt_enter(); - - if (EINT_ReadIntFlag(EINT_LINE_0)) - { - EINT_ClearIntFlag(EINT_LINE_0); - GPIO_EXTI_IRQHandler(GPIO_PIN_0); - } - + GPIO_EXTI_IRQHandler(0); rt_interrupt_leave(); } void EINT1_IRQHandler(void) { rt_interrupt_enter(); - if (EINT_ReadIntFlag(EINT_LINE_1)) - { - EINT_ClearIntFlag(EINT_LINE_1); - GPIO_EXTI_IRQHandler(GPIO_PIN_1); - } + GPIO_EXTI_IRQHandler(1); rt_interrupt_leave(); } void EINT2_IRQHandler(void) { rt_interrupt_enter(); - if (EINT_ReadIntFlag(EINT_LINE_2)) - { - EINT_ClearIntFlag(EINT_LINE_2); - GPIO_EXTI_IRQHandler(GPIO_PIN_2); - } + GPIO_EXTI_IRQHandler(2); rt_interrupt_leave(); } void EINT3_IRQHandler(void) { rt_interrupt_enter(); - if (EINT_ReadIntFlag(EINT_LINE_3)) - { - EINT_ClearIntFlag(EINT_LINE_3); - GPIO_EXTI_IRQHandler(GPIO_PIN_3); - } + GPIO_EXTI_IRQHandler(3); rt_interrupt_leave(); } void EINT4_IRQHandler(void) { rt_interrupt_enter(); - if (EINT_ReadIntFlag(EINT_LINE_4)) - { - EINT_ClearIntFlag(EINT_LINE_4); - GPIO_EXTI_IRQHandler(GPIO_PIN_4); - } + GPIO_EXTI_IRQHandler(4); rt_interrupt_leave(); } void EINT9_5_IRQHandler(void) { rt_interrupt_enter(); - if (EINT_ReadIntFlag(EINT_LINE_5)) - { - EINT_ClearIntFlag(EINT_LINE_5); - GPIO_EXTI_IRQHandler(GPIO_PIN_5); - } - if (EINT_ReadIntFlag(EINT_LINE_6)) - { - EINT_ClearIntFlag(EINT_LINE_6); - GPIO_EXTI_IRQHandler(GPIO_PIN_6); - } - if (EINT_ReadIntFlag(EINT_LINE_7)) - { - EINT_ClearIntFlag(EINT_LINE_7); - GPIO_EXTI_IRQHandler(GPIO_PIN_7); - } - if (EINT_ReadIntFlag(EINT_LINE_8)) - { - EINT_ClearIntFlag(EINT_LINE_8); - GPIO_EXTI_IRQHandler(GPIO_PIN_8); - } - if (EINT_ReadIntFlag(EINT_LINE_9)) - { - EINT_ClearIntFlag(EINT_LINE_9); - GPIO_EXTI_IRQHandler(GPIO_PIN_9); - } + GPIO_EXTI_IRQHandler(5); + GPIO_EXTI_IRQHandler(6); + GPIO_EXTI_IRQHandler(7); + GPIO_EXTI_IRQHandler(8); + GPIO_EXTI_IRQHandler(9); rt_interrupt_leave(); } void EINT15_10_IRQHandler(void) { rt_interrupt_enter(); - if (EINT_ReadIntFlag(EINT_LINE_10)) - { - EINT_ClearIntFlag(EINT_LINE_10); - GPIO_EXTI_IRQHandler(GPIO_PIN_10); - } - if (EINT_ReadIntFlag(EINT_LINE_11)) - { - EINT_ClearIntFlag(EINT_LINE_11); - GPIO_EXTI_IRQHandler(GPIO_PIN_11); - } - if (EINT_ReadIntFlag(EINT_LINE_12)) - { - EINT_ClearIntFlag(EINT_LINE_12); - GPIO_EXTI_IRQHandler(GPIO_PIN_12); - } - if (EINT_ReadIntFlag(EINT_LINE_13)) - { - EINT_ClearIntFlag(EINT_LINE_13); - GPIO_EXTI_IRQHandler(GPIO_PIN_13); - } - if (EINT_ReadIntFlag(EINT_LINE_14)) - { - EINT_ClearIntFlag(EINT_LINE_14); - GPIO_EXTI_IRQHandler(GPIO_PIN_14); - } - if (EINT_ReadIntFlag(EINT_LINE_15)) - { - EINT_ClearIntFlag(EINT_LINE_15); - GPIO_EXTI_IRQHandler(GPIO_PIN_15); - } + GPIO_EXTI_IRQHandler(10); + GPIO_EXTI_IRQHandler(11); + GPIO_EXTI_IRQHandler(12); + GPIO_EXTI_IRQHandler(13); + GPIO_EXTI_IRQHandler(14); + GPIO_EXTI_IRQHandler(15); rt_interrupt_leave(); } +#endif int rt_hw_pin_init(void) { -#if defined(APM32F10X_HD) +#if defined(SOC_SERIES_APM32F1) #ifdef GPIOA RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA); #endif @@ -619,7 +725,7 @@ int rt_hw_pin_init(void) RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOG); #endif RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_AFIO); -#elif defined(APM32F40X) +#elif defined(SOC_SERIES_APM32F4) #ifdef GPIOA RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA); #endif @@ -653,9 +759,30 @@ int rt_hw_pin_init(void) #ifdef GPIOK RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOK); #endif + +#elif defined(SOC_SERIES_APM32F0) +#ifdef GPIOA + RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA); +#endif +#ifdef GPIOB + RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOB); +#endif +#ifdef GPIOC + RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOC); +#endif +#ifdef GPIOD + RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOD); +#endif +#ifdef GPIOE + RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOE); +#endif +#ifdef GPIOF + RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOF); #endif - return rt_device_pin_register("pin", &_apm32_pin_ops, RT_NULL); +#endif /* SOC_SERIES_APM32F0 */ + + return rt_device_pin_register("pin", &apm32_pin_ops, RT_NULL); } #endif /* RT_USING_PIN */ diff --git a/bsp/apm32/libraries/Drivers/drv_hwtimer.c b/bsp/apm32/libraries/Drivers/drv_hwtimer.c index 2f1ff05c61..40285f767c 100644 --- a/bsp/apm32/libraries/Drivers/drv_hwtimer.c +++ b/bsp/apm32/libraries/Drivers/drv_hwtimer.c @@ -7,17 +7,18 @@ * Date Author Notes * 2022-03-04 stevetong459 first version * 2022-07-15 Aligagago add apm32F4 serie MCU support + * 2022-12-26 luobeihai add apm32F0 serie MCU support */ #include -#define LOG_TAG "drv.hwtimer" +#define DBG_TAG "drv.hwtimer" #define DBG_LVL DBG_INFO #include #ifdef RT_USING_HWTIMER -static const struct rt_hwtimer_info _info = +static const struct rt_hwtimer_info apm32_timer_info = { .maxfreq = 1000000, .minfreq = 2000, @@ -78,6 +79,15 @@ enum #ifdef BSP_USING_TMR14 TMR14_INDEX, #endif +#ifdef BSP_USING_TMR15 + TMR15_INDEX, +#endif +#ifdef BSP_USING_TMR16 + TMR16_INDEX, +#endif +#ifdef BSP_USING_TMR17 + TMR17_INDEX, +#endif }; static struct apm32_timer tmr_config[] = @@ -86,10 +96,12 @@ static struct apm32_timer tmr_config[] = { "timer1", TMR1, -#ifdef APM32F10X_HD +#if defined(SOC_SERIES_APM32F1) TMR1_UP_IRQn, -#elif APM32F40X +#elif defined(SOC_SERIES_APM32F4) TMR1_UP_TMR10_IRQn, +#elif defined(SOC_SERIES_APM32F0) + TMR1_BRK_UP_TRG_COM_IRQn #endif }, #endif @@ -125,9 +137,11 @@ static struct apm32_timer tmr_config[] = { "timer6", TMR6, -#ifdef APM32F10X_HD +#if defined(SOC_SERIES_APM32F1) || defined(APM32F030) || defined(APM32F070) TMR6_IRQn, -#elif APM32F40X +#elif defined(SOC_SERIES_APM32F4) + TMR6_DAC_IRQn +#elif defined(SOC_SERIES_APM32F0) && !defined(APM32F030) && !defined(APM32F070) TMR6_DAC_IRQn #endif }, @@ -143,9 +157,9 @@ static struct apm32_timer tmr_config[] = { "timer8", TMR8, -#ifdef APM32F10X_HD +#if defined(SOC_SERIES_APM32F1) TMR8_UP_IRQn, -#elif APM32F40X +#elif defined(SOC_SERIES_APM32F4) TMR8_UP_TMR13_IRQn, #endif }, @@ -189,30 +203,122 @@ static struct apm32_timer tmr_config[] = { "timer14", TMR14, +#if defined(SOC_SERIES_APM32F0) + TMR14_IRQn, +#elif defined(SOC_SERIES_APM32F4) TMR8_TRG_COM_TMR14_IRQn, +#endif + }, +#endif +#ifdef BSP_USING_TMR15 + { + "timer15", + TMR15, + TMR15_IRQn, + }, +#endif +#ifdef BSP_USING_TMR16 + { + "timer16", + TMR16, + TMR16_IRQn, + }, +#endif +#ifdef BSP_USING_TMR17 + { + "timer17", + TMR17, + TMR17_IRQn, }, #endif }; -static rt_uint32_t _hwtimer_clock_get(TMR_T *tmr) +static rt_uint32_t apm32_hwtimer_clock_get(TMR_T *tmr) { +#if defined(SOC_SERIES_APM32F0) + uint32_t pclk1; + + pclk1 = RCM_ReadPCLKFreq(); + + return (rt_uint32_t)(pclk1 * ((RCM->CFG1_B.APB1PSC != 0) ? 2 : 1)); +#else uint32_t pclk1, pclk2; RCM_ReadPCLKFreq(&pclk1, &pclk2); if (tmr == TMR1 || tmr == TMR8 || tmr == TMR9 || tmr == TMR10 || tmr == TMR11) { - return (rt_uint32_t)(pclk2 * ((RCM->CFG_B.APB2PSC != RCM_APB_DIV_1) ? 2 : 1)); + return (rt_uint32_t)(pclk2 * ((RCM->CFG_B.APB2PSC != 0) ? 2 : 1)); } else { - return (rt_uint32_t)(pclk1 * ((RCM->CFG_B.APB1PSC != RCM_APB_DIV_1) ? 2 : 1)); + return (rt_uint32_t)(pclk1 * ((RCM->CFG_B.APB1PSC != 0) ? 2 : 1)); } +#endif } -static void _hwtimer_init(struct rt_hwtimer_device *timer, rt_uint32_t state) +static void apm32_hwtimer_enable_clock(void) { +#ifdef BSP_USING_TMR1 + RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR1); +#endif +#ifdef BSP_USING_TMR2 + RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR2); +#endif +#ifdef BSP_USING_TMR3 + RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR3); +#endif +#ifdef BSP_USING_TMR4 + RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR4); +#endif +#ifdef BSP_USING_TMR5 + RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR5); +#endif +#ifdef BSP_USING_TMR6 + RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR6); +#endif +#ifdef BSP_USING_TMR7 + RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR7); +#endif +#ifdef BSP_USING_TMR8 + RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR8); +#endif +#ifdef BSP_USING_TMR9 + RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR9); +#endif +#ifdef BSP_USING_TMR10 + RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR10); +#endif +#ifdef BSP_USING_TMR11 + RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR11); +#endif +#ifdef BSP_USING_TMR12 + RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR12); +#endif +#ifdef BSP_USING_TMR13 + RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR13); +#endif +#ifdef BSP_USING_TMR14 + RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR14); +#endif +#ifdef BSP_USING_TMR15 + RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR15); +#endif +#ifdef BSP_USING_TMR16 + RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR16); +#endif +#ifdef BSP_USING_TMR17 + RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR17); +#endif +} + +static void apm32_hwtimer_init(struct rt_hwtimer_device *timer, rt_uint32_t state) +{ +#if defined(SOC_SERIES_APM32F0) + TMR_TimeBase_T base_config; +#else TMR_BaseConfig_T base_config; +#endif uint32_t prescaler = 0; struct apm32_timer *timer_config; @@ -221,77 +327,24 @@ static void _hwtimer_init(struct rt_hwtimer_device *timer, rt_uint32_t state) if (state) { timer_config = (struct apm32_timer *)timer->parent.user_data; - if (timer_config->tmr == TMR2) - { - RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR2); - } - else if (timer_config->tmr == TMR3) - { - RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR3); - } - else if (timer_config->tmr == TMR4) - { - RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR4); - } - else if (timer_config->tmr == TMR5) - { - RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR5); - } - else if (timer_config->tmr == TMR6) - { - RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR6); - } - else if (timer_config->tmr == TMR7) - { - RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR7); - } -#ifdef APM32F10X_HD - else if (timer_config->tmr == TMR1) - { - RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR1); - } - else if (timer_config->tmr == TMR8) - { - RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR8); - } -#endif -#ifdef APM32F40X - else if (timer_config->tmr == TMR1) - { - RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR1); - } - else if (timer_config->tmr == TMR8) - { - RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR8); - } - else if (timer_config->tmr == TMR9) - { - RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR9); - } - else if (timer_config->tmr == TMR10) - { - RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR10); - } - else if (timer_config->tmr == TMR11) - { - RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR11); - } - else if (timer_config->tmr == TMR12) - { - RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR12); - } - else if (timer_config->tmr == TMR13) - { - RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR13); - } - else if (timer_config->tmr == TMR14) - { - RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR14); - } -#endif - prescaler = (uint32_t)(_hwtimer_clock_get(timer_config->tmr) / 10000) - 1; + + apm32_hwtimer_enable_clock(); + + prescaler = (uint32_t)(apm32_hwtimer_clock_get(timer_config->tmr) / 10000) - 1; base_config.period = 10000 - 1; +#if defined(SOC_SERIES_APM32F0) + base_config.div = prescaler; + base_config.clockDivision = TMR_CKD_DIV1; + if (timer->info->cntmode == HWTIMER_CNTMODE_UP) + { + base_config.counterMode = TMR_COUNTER_MODE_UP; + } + else + { + base_config.counterMode = TMR_COUNTER_MODE_DOWN; + } +#else base_config.division = prescaler; base_config.clockDivision = TMR_CLOCK_DIV_1; if (timer->info->cntmode == HWTIMER_CNTMODE_UP) @@ -302,21 +355,28 @@ static void _hwtimer_init(struct rt_hwtimer_device *timer, rt_uint32_t state) { base_config.countMode = TMR_COUNTER_MODE_DOWN; } +#endif base_config.repetitionCounter = 0; TMR_ConfigTimeBase(timer_config->tmr, &base_config); - + +#if defined(SOC_SERIES_APM32F0) + /* set the TIMx priority */ + NVIC_EnableIRQRequest(timer_config->irqn, 3); + /* enable update request source */ + TMR_ConfigUPdateRequest(timer_config->tmr, TMR_UPDATE_SOURCE_REGULAR); +#else /* set the TIMx priority */ NVIC_EnableIRQRequest(timer_config->irqn, 3, 0); - - /* clear update flag */ - TMR_ClearStatusFlag(timer_config->tmr, TMR_FLAG_UPDATE); /* enable update request source */ TMR_ConfigUpdateRequest(timer_config->tmr, TMR_UPDATE_SOURCE_REGULAR); +#endif + /* clear update flag */ + TMR_ClearStatusFlag(timer_config->tmr, TMR_FLAG_UPDATE); LOG_D("%s init success", timer_config->name); } } -static rt_err_t _hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t t, rt_hwtimer_mode_t opmode) +static rt_err_t apm32_hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t t, rt_hwtimer_mode_t opmode) { rt_err_t result = RT_EOK; struct apm32_timer *timer_config = RT_NULL; @@ -326,41 +386,46 @@ static rt_err_t _hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t t, rt_hwtimer_mo timer_config = (struct apm32_timer *)timer->parent.user_data; /* set timer_config counter */ - TMR_ConfigCounter(timer_config->tmr, 0); + timer_config->tmr->CNT = 0; /* set timer_config autoReload */ - TMR_ConfigAutoreload(timer_config->tmr, t - 1); + timer_config->tmr->AUTORLD = t - 1; if (opmode == HWTIMER_MODE_ONESHOT) { /* set timer to single mode */ - TMR_ConfigSinglePulseMode(timer_config->tmr, TMR_SPM_SINGLE); + timer_config->tmr->CTRL1_B.SPMEN = 1; } else { - TMR_ConfigSinglePulseMode(timer_config->tmr, TMR_SPM_REPETITIVE); + timer_config->tmr->CTRL1_B.SPMEN = 0; } TMR_EnableInterrupt(timer_config->tmr, TMR_INT_UPDATE); - if (timer_config->tmr == TMR1 || timer_config->tmr == TMR8 || timer_config->tmr == TMR2 || \ - timer_config->tmr == TMR3 || timer_config->tmr == TMR4 || timer_config->tmr == TMR5 || \ - timer_config->tmr == TMR9 || timer_config->tmr == TMR12) +#if defined(SOC_SERIES_APM32F0) + if (timer_config->tmr == TMR1 || timer_config->tmr == TMR2 || timer_config->tmr == TMR3 || \ + timer_config->tmr == TMR15) +#else + if (timer_config->tmr == TMR1 || timer_config->tmr == TMR2 || timer_config->tmr == TMR3 || \ + timer_config->tmr == TMR4 || timer_config->tmr == TMR5 || timer_config->tmr == TMR8 || \ + timer_config->tmr == TMR9 || timer_config->tmr == TMR12) +#endif { - if (timer_config->tmr->SMCTRL_B.SMFSEL != TMR_SLAVE_MODE_TRIGGER) + if (timer_config->tmr->SMCTRL_B.SMFSEL != 0x06) { TMR_Enable(timer_config->tmr); - result = -RT_EOK; + result = RT_EOK; } } else { TMR_Enable(timer_config->tmr); - result = -RT_EOK; + result = RT_EOK; } return result; } -static void _hwtimer_stop(rt_hwtimer_t *timer) +static void apm32_hwtimer_stop(rt_hwtimer_t *timer) { struct apm32_timer *timer_config = RT_NULL; RT_ASSERT(timer != RT_NULL); @@ -368,10 +433,10 @@ static void _hwtimer_stop(rt_hwtimer_t *timer) TMR_DisableInterrupt(timer_config->tmr, TMR_INT_UPDATE); TMR_Enable(timer_config->tmr); - TMR_ConfigCounter(timer_config->tmr, 0); + timer_config->tmr->CNT = 0; } -static rt_err_t _hwtimer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg) +static rt_err_t apm32_hwtimer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg) { struct apm32_timer *timer_config = RT_NULL; rt_err_t result = RT_EOK; @@ -389,18 +454,21 @@ static rt_err_t _hwtimer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg) /* set timer frequence */ freq = *((rt_uint32_t *)arg); - val = _hwtimer_clock_get(timer_config->tmr) / freq; + val = apm32_hwtimer_clock_get(timer_config->tmr) / freq; - TMR_ConfigPrescaler(timer_config->tmr, val - 1, TMR_PSC_RELOAD_IMMEDIATE); + /* Configures the timer prescaler */ + timer_config->tmr->PSC_B.PSC = val - 1; + timer_config->tmr->CEG_B.UEG = 1; break; default: + LOG_E("invalid cmd: 0x%x\n", cmd); result = -RT_ENOSYS; break; } return result; } -static rt_uint32_t _hwtimer_counter_get(rt_hwtimer_t *timer) +static rt_uint32_t apm32_hwtimer_counter_get(rt_hwtimer_t *timer) { struct apm32_timer *timer_config = RT_NULL; RT_ASSERT(timer != RT_NULL); @@ -409,16 +477,27 @@ static rt_uint32_t _hwtimer_counter_get(rt_hwtimer_t *timer) return timer_config->tmr->CNT; } -static const struct rt_hwtimer_ops _hwtimer_ops = +static const struct rt_hwtimer_ops apm32_hwtimer_ops = { - .init = _hwtimer_init, - .start = _hwtimer_start, - .stop = _hwtimer_stop, - .count_get = _hwtimer_counter_get, - .control = _hwtimer_ctrl, + .init = apm32_hwtimer_init, + .start = apm32_hwtimer_start, + .stop = apm32_hwtimer_stop, + .count_get = apm32_hwtimer_counter_get, + .control = apm32_hwtimer_ctrl, }; -#ifdef APM32F10X_HD + +#if defined(SOC_SERIES_APM32F0) +#ifdef BSP_USING_TMR1 +void TMR1_BRK_UP_TRG_COM_IRQHandler(void) +{ + rt_interrupt_enter(); + rt_device_hwtimer_isr(&tmr_config[TMR1_INDEX].device); + TMR_ClearIntFlag(TMR1, TMR_INT_UPDATE); + rt_interrupt_leave(); +} +#endif +#elif defined(SOC_SERIES_APM32F1) #ifdef BSP_USING_TMR1 void TMR1_UP_IRQHandler(void) { @@ -428,7 +507,7 @@ void TMR1_UP_IRQHandler(void) rt_interrupt_leave(); } #endif -#elif APM32F40X +#elif defined(SOC_SERIES_APM32F4) #if (defined(BSP_USING_TMR1) || defined(BSP_USING_TMR10)) void TMR1_UP_TMR10_IRQHandler(void) { @@ -489,9 +568,11 @@ void TMR5_IRQHandler(void) #endif #ifdef BSP_USING_TMR6 -#ifdef APM32F10X_HD +#if defined(SOC_SERIES_APM32F1) || defined(APM32F030) || defined(APM32F070) void TMR6_IRQHandler(void) -#elif APM32F40X +#elif defined(SOC_SERIES_APM32F4) + void TMR6_DAC_IRQHandler(void) +#elif defined(SOC_SERIES_APM32F0) && !defined(APM32F030) && !defined(APM32F070) void TMR6_DAC_IRQHandler(void) #endif { @@ -512,7 +593,7 @@ void TMR7_IRQHandler(void) } #endif -#ifdef APM32F10X_HD +#if defined(SOC_SERIES_APM32F1) #ifdef BSP_USING_TMR8 void TMR8_UP_IRQHandler(void) { @@ -522,7 +603,7 @@ void TMR8_UP_IRQHandler(void) rt_interrupt_leave(); } #endif -#elif APM32F40X +#elif defined(SOC_SERIES_APM32F4) #if (defined(BSP_USING_TMR8) || defined(BSP_USING_TMR13)) void TMR8_UP_TMR13_IRQHandler(void) { @@ -573,7 +654,11 @@ void TMR8_BRK_TMR12_IRQHandler(void) #endif #ifdef BSP_USING_TMR14 -void TMR8_TRG_COM_TMR14_IRQHandler(void) +#if defined(SOC_SERIES_APM32F0) + void TMR14_IRQHandler(void) +#elif defined(SOC_SERIES_APM32F4) + void TMR8_TRG_COM_TMR14_IRQHandler(void) +#endif { rt_interrupt_enter(); rt_device_hwtimer_isr(&tmr_config[TMR14_INDEX].device); @@ -582,6 +667,36 @@ void TMR8_TRG_COM_TMR14_IRQHandler(void) } #endif +#ifdef BSP_USING_TMR15 +void TMR15_IRQHandler(void) +{ + rt_interrupt_enter(); + rt_device_hwtimer_isr(&tmr_config[TMR15_INDEX].device); + TMR_ClearIntFlag(TMR15, TMR_INT_UPDATE); + rt_interrupt_leave(); +} +#endif + +#ifdef BSP_USING_TMR16 +void TMR16_IRQHandler(void) +{ + rt_interrupt_enter(); + rt_device_hwtimer_isr(&tmr_config[TMR16_INDEX].device); + TMR_ClearIntFlag(TMR16, TMR_INT_UPDATE); + rt_interrupt_leave(); +} +#endif + +#ifdef BSP_USING_TMR17 +void TMR17_IRQHandler(void) +{ + rt_interrupt_enter(); + rt_device_hwtimer_isr(&tmr_config[TMR17_INDEX].device); + TMR_ClearIntFlag(TMR17, TMR_INT_UPDATE); + rt_interrupt_leave(); +} +#endif + static int rt_hw_hwtimer_init(void) { int i = 0; @@ -589,8 +704,8 @@ static int rt_hw_hwtimer_init(void) for (i = 0; i < sizeof(tmr_config) / sizeof(tmr_config[0]); i++) { - tmr_config[i].device.info = &_info; - tmr_config[i].device.ops = &_hwtimer_ops; + tmr_config[i].device.info = &apm32_timer_info; + tmr_config[i].device.ops = &apm32_hwtimer_ops; if (rt_device_hwtimer_register(&tmr_config[i].device, tmr_config[i].name, &tmr_config[i]) == RT_EOK) { LOG_D("%s register success", tmr_config[i].name); diff --git a/bsp/apm32/libraries/Drivers/drv_log.h b/bsp/apm32/libraries/Drivers/drv_log.h new file mode 100644 index 0000000000..dcdb7fc212 --- /dev/null +++ b/bsp/apm32/libraries/Drivers/drv_log.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-12-19 first version + */ + +/* + * NOTE: DO NOT include this file on the header file. + */ + +#ifndef LOG_TAG +#define DBG_TAG "drv" +#else +#define DBG_TAG LOG_TAG +#endif /* LOG_TAG */ + +#ifdef DRV_DEBUG +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO +#endif /* DRV_DEBUG */ + +#include diff --git a/bsp/apm32/libraries/Drivers/drv_pwm.c b/bsp/apm32/libraries/Drivers/drv_pwm.c index da0a793750..ff712222ad 100644 --- a/bsp/apm32/libraries/Drivers/drv_pwm.c +++ b/bsp/apm32/libraries/Drivers/drv_pwm.c @@ -7,6 +7,7 @@ * Date Author Notes * 2022-03-04 stevetong459 first version * 2022-07-15 Aligagago add apm32F4 serie MCU support + * 2022-12-26 luobeihai add apm32F0 serie MCU support */ #include @@ -14,7 +15,7 @@ #ifdef RT_USING_PWM #include -#define LOG_TAG "drv.pwm" +#define DBG_TAG "drv.pwm" #define DBG_LVL DBG_INFO #include @@ -22,28 +23,8 @@ #define MIN_PERIOD 3 #define MIN_PULSE 2 -#ifdef APM32F10X_HD -#define _PWM_GPIO_INIT(port_num, pin_num) \ -do \ -{ \ - RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIO##port_num); \ - gpio_config->pin = GPIO_PIN_##pin_num; \ - gpio_config->mode = GPIO_MODE_AF_PP; \ - gpio_config->speed = GPIO_SPEED_50MHz; \ - GPIO_Config(GPIO##port_num, gpio_config); \ -} while (0) -#elif APM32F40X -#define _PWM_GPIO_INIT(port_num, pin_num) \ -do \ -{ \ - RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIO##port_num); \ - gpio_config->pin = GPIO_PIN_##pin_num; \ - gpio_config->mode = GPIO_MODE_AF; \ - gpio_config->otype = GPIO_OTYPE_PP; \ - gpio_config->speed = GPIO_SPEED_50MHz; \ - GPIO_Config(GPIO##port_num, gpio_config); \ -} while (0) -#endif +/* Init timer gpio and enable clock */ +extern void apm32_msp_timer_init(void *Instance); enum { @@ -83,6 +64,15 @@ enum #ifdef BSP_USING_PWM14 PWM14_INDEX, #endif +#ifdef BSP_USING_PWM15 + PWM15_INDEX, +#endif +#ifdef BSP_USING_PWM16 + PWM16_INDEX, +#endif +#ifdef BSP_USING_PWM17 + PWM17_INDEX, +#endif }; struct apm32_pwm @@ -179,207 +169,200 @@ static struct apm32_pwm pwm_config[] = 0, }, #endif +#ifdef BSP_USING_PWM15 + { + "pwm15", + TMR15, + 0, + }, +#endif +#ifdef BSP_USING_PWM16 + { + "pwm16", + TMR16, + 0, + }, +#endif +#ifdef BSP_USING_PWM17 + { + "pwm17", + TMR17, + 0, + }, +#endif }; -static void _pwm_channel_init(GPIO_Config_T *gpio_config) +static void pwm_channel_init(void) { #ifdef BSP_USING_PWM1_CH1 pwm_config[PWM1_INDEX].channel |= 1 << 0; - _PWM_GPIO_INIT(A, 8); #endif #ifdef BSP_USING_PWM1_CH2 pwm_config[PWM1_INDEX].channel |= 1 << 1; - _PWM_GPIO_INIT(A, 9); #endif #ifdef BSP_USING_PWM1_CH3 pwm_config[PWM1_INDEX].channel |= 1 << 2; - _PWM_GPIO_INIT(A, 10); #endif #ifdef BSP_USING_PWM1_CH4 pwm_config[PWM1_INDEX].channel |= 1 << 3; - _PWM_GPIO_INIT(A, 11); #endif #ifdef BSP_USING_PWM2_CH1 pwm_config[PWM2_INDEX].channel |= 1 << 0; - _PWM_GPIO_INIT(A, 0); #endif #ifdef BSP_USING_PWM2_CH2 pwm_config[PWM2_INDEX].channel |= 1 << 1; - _PWM_GPIO_INIT(A, 1); #endif #ifdef BSP_USING_PWM2_CH3 pwm_config[PWM2_INDEX].channel |= 1 << 2; - _PWM_GPIO_INIT(A, 2); #endif #ifdef BSP_USING_PWM2_CH4 pwm_config[PWM2_INDEX].channel |= 1 << 3; - _PWM_GPIO_INIT(A, 3); #endif - -#ifdef APM32F10X_HD #ifdef BSP_USING_PWM3_CH1 pwm_config[PWM3_INDEX].channel |= 1 << 0; - GPIO_ConfigPinRemap(GPIO_FULL_REMAP_TMR3); - _PWM_GPIO_INIT(C, 6); #endif #ifdef BSP_USING_PWM3_CH2 pwm_config[PWM3_INDEX].channel |= 1 << 1; - GPIO_ConfigPinRemap(GPIO_FULL_REMAP_TMR3); - _PWM_GPIO_INIT(C, 7); #endif #ifdef BSP_USING_PWM3_CH3 pwm_config[PWM3_INDEX].channel |= 1 << 2; - GPIO_ConfigPinRemap(GPIO_FULL_REMAP_TMR3); - _PWM_GPIO_INIT(C, 8); #endif #ifdef BSP_USING_PWM3_CH4 pwm_config[PWM3_INDEX].channel |= 1 << 3; - GPIO_ConfigPinRemap(GPIO_FULL_REMAP_TMR3); - _PWM_GPIO_INIT(C, 9); #endif -#elif APM32F40X -#ifdef BSP_USING_PWM3_CH1 - pwm_config[PWM3_INDEX].channel |= 1 << 0; - GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_6, GPIO_AF_TMR3); - _PWM_GPIO_INIT(C, 6); -#endif -#ifdef BSP_USING_PWM3_CH2 - pwm_config[PWM3_INDEX].channel |= 1 << 1; - GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_7, GPIO_AF_TMR3); - _PWM_GPIO_INIT(C, 7); -#endif -#ifdef BSP_USING_PWM3_CH3 - pwm_config[PWM3_INDEX].channel |= 1 << 2; - GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_8, GPIO_AF_TMR3); - _PWM_GPIO_INIT(C, 8); -#endif -#ifdef BSP_USING_PWM3_CH4 - pwm_config[PWM3_INDEX].channel |= 1 << 3; - GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_9, GPIO_AF_TMR3); - _PWM_GPIO_INIT(C, 9); -#endif -#endif - #ifdef BSP_USING_PWM4_CH1 pwm_config[PWM4_INDEX].channel |= 1 << 0; - _PWM_GPIO_INIT(B, 6); #endif #ifdef BSP_USING_PWM4_CH2 pwm_config[PWM4_INDEX].channel |= 1 << 1; - _PWM_GPIO_INIT(B, 7); #endif #ifdef BSP_USING_PWM4_CH3 pwm_config[PWM4_INDEX].channel |= 1 << 2; - _PWM_GPIO_INIT(B, 8); #endif #ifdef BSP_USING_PWM4_CH4 pwm_config[PWM4_INDEX].channel |= 1 << 3; - _PWM_GPIO_INIT(B, 9); #endif #ifdef BSP_USING_PWM5_CH1 pwm_config[PWM5_INDEX].channel |= 1 << 0; - _PWM_GPIO_INIT(A, 0); #endif #ifdef BSP_USING_PWM5_CH2 pwm_config[PWM5_INDEX].channel |= 1 << 1; - _PWM_GPIO_INIT(A, 1); #endif #ifdef BSP_USING_PWM5_CH3 pwm_config[PWM5_INDEX].channel |= 1 << 2; - _PWM_GPIO_INIT(A, 2); #endif #ifdef BSP_USING_PWM5_CH4 pwm_config[PWM5_INDEX].channel |= 1 << 3; - _PWM_GPIO_INIT(A, 3); #endif #ifdef BSP_USING_PWM8_CH1 pwm_config[PWM8_INDEX].channel |= 1 << 0; - _PWM_GPIO_INIT(C, 6); #endif #ifdef BSP_USING_PWM8_CH2 pwm_config[PWM8_INDEX].channel |= 1 << 1; - _PWM_GPIO_INIT(C, 7); #endif #ifdef BSP_USING_PWM8_CH3 pwm_config[PWM8_INDEX].channel |= 1 << 2; - _PWM_GPIO_INIT(C, 8); #endif #ifdef BSP_USING_PWM8_CH4 pwm_config[PWM8_INDEX].channel |= 1 << 3; - _PWM_GPIO_INIT(C, 9); #endif -#ifdef APM32F40X #ifdef BSP_USING_PWM9_CH1 pwm_config[PWM9_INDEX].channel |= 1 << 0; - _PWM_GPIO_INIT(E, 5); #endif #ifdef BSP_USING_PWM9_CH2 pwm_config[PWM9_INDEX].channel |= 1 << 1; - _PWM_GPIO_INIT(E, 6); #endif #ifdef BSP_USING_PWM10_CH1 pwm_config[PWM10_INDEX].channel |= 1 << 0; - _PWM_GPIO_INIT(F, 6); #endif #ifdef BSP_USING_PWM11_CH1 pwm_config[PWM11_INDEX].channel |= 1 << 0; - _PWM_GPIO_INIT(F, 7); #endif #ifdef BSP_USING_PWM12_CH1 - pwm_config[PWM9_INDEX].channel |= 1 << 0; - _PWM_GPIO_INIT(H, 6); + pwm_config[PWM12_INDEX].channel |= 1 << 0; #endif #ifdef BSP_USING_PWM12_CH2 - pwm_config[PWM9_INDEX].channel |= 1 << 1; - _PWM_GPIO_INIT(H, 9); + pwm_config[PWM12_INDEX].channel |= 1 << 1; #endif #ifdef BSP_USING_PWM13_CH1 - pwm_config[PWM10_INDEX].channel |= 1 << 0; - _PWM_GPIO_INIT(F, 8); + pwm_config[PWM13_INDEX].channel |= 1 << 0; #endif #ifdef BSP_USING_PWM14_CH1 - pwm_config[PWM11_INDEX].channel |= 1 << 0; - _PWM_GPIO_INIT(F, 9); + pwm_config[PWM14_INDEX].channel |= 1 << 0; #endif +#ifdef BSP_USING_PWM15_CH1 + pwm_config[PWM15_INDEX].channel |= 1 << 0; +#endif +#ifdef BSP_USING_PWM15_CH2 + pwm_config[PWM15_INDEX].channel |= 1 << 1; +#endif +#ifdef BSP_USING_PWM16_CH1 + pwm_config[PWM16_INDEX].channel |= 1 << 0; +#endif +#ifdef BSP_USING_PWM17_CH1 + pwm_config[PWM17_INDEX].channel |= 1 << 0; #endif } -static rt_err_t _pwm_hw_init(struct apm32_pwm *device) +static rt_err_t apm32_pwm_hw_init(struct apm32_pwm *device) { rt_err_t result = RT_EOK; TMR_T *tmr = RT_NULL; + + RT_ASSERT(device != RT_NULL); + tmr = (TMR_T *)device->tmr; + + /* Init timer gpio and enable clock */ + apm32_msp_timer_init(tmr); + +#if defined(SOC_SERIES_APM32F0) + TMR_TimeBase_T base_config; + TMR_OCConfig_T oc_config; + + /* configure the tmrer to pwm mode */ + base_config.div = 0; + base_config.counterMode = TMR_COUNTER_MODE_UP; + base_config.period = 0; + base_config.clockDivision = TMR_CKD_DIV1; + TMR_ConfigTimeBase(tmr, &base_config); + + TMR_SelectOutputTrigger(tmr, TMR_TRGOSOURCE_RESET); + TMR_DisableMasterSlaveMode(tmr); + + oc_config.OC_Mode = TMR_OC_MODE_PWM1; + oc_config.Pulse = 0; + oc_config.OC_Polarity = TMR_OC_POLARITY_HIGH; + oc_config.OC_NIdlestate = TMR_OCNIDLESTATE_RESET; + oc_config.OC_Idlestate = TMR_OCIDLESTATE_RESET; + oc_config.OC_OutputState = TMR_OUTPUT_STATE_ENABLE; + + /* config pwm channel */ + if (device->channel & 0x01) + { + TMR_OC1Config(tmr, &oc_config); + } + + if (device->channel & 0x02) + { + TMR_OC2Config(tmr, &oc_config); + } + + if (device->channel & 0x04) + { + TMR_OC3Config(tmr, &oc_config); + } + + if (device->channel & 0x08) + { + TMR_OC4Config(tmr, &oc_config); + } + + /* enable update request source */ + TMR_ConfigUPdateRequest(tmr, TMR_UPDATE_SOURCE_REGULAR); +#else TMR_BaseConfig_T base_config; TMR_OCConfig_T oc_config; - RT_ASSERT(device != RT_NULL); - - tmr = (TMR_T *)device->tmr; - - if (tmr == TMR1) - { - RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR1); - } - else if (tmr == TMR8) - { - RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR8); - } - else if (tmr == TMR2) - { - RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR2); - } - else if (tmr == TMR3) - { - RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR3); - } - else if (tmr == TMR4) - { - RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR4); - } - else if (tmr == TMR5) - { - RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR5); - } - /* configure the tmrer to pwm mode */ base_config.division = 0; base_config.countMode = TMR_COUNTER_MODE_UP; @@ -420,20 +403,36 @@ static rt_err_t _pwm_hw_init(struct apm32_pwm *device) /* enable update request source */ TMR_ConfigUpdateRequest(tmr, TMR_UPDATE_SOURCE_REGULAR); +#endif return result; } -static rt_uint32_t _pwm_timer_clock_get(TMR_T *tmr) +static rt_uint32_t timer_clock_get(TMR_T *tmr) { +#if defined(SOC_SERIES_APM32F0) uint32_t pclk1; + + pclk1 = RCM_ReadPCLKFreq(); + + return (rt_uint32_t)(pclk1 * ((RCM->CFG1_B.APB1PSC != 0) ? 2 : 1)); +#else + uint32_t pclk1, pclk2; - RCM_ReadPCLKFreq(&pclk1, NULL); + RCM_ReadPCLKFreq(&pclk1, &pclk2); - return (rt_uint32_t)(pclk1 * ((RCM->CFG_B.APB1PSC != RCM_APB_DIV_1) ? 2 : 1)); + if (tmr == TMR1 || tmr == TMR8 || tmr == TMR9 || tmr == TMR10 || tmr == TMR11) + { + return (rt_uint32_t)(pclk2 * ((RCM->CFG_B.APB2PSC != 0) ? 2 : 1)); + } + else + { + return (rt_uint32_t)(pclk1 * ((RCM->CFG_B.APB1PSC != 0) ? 2 : 1)); + } +#endif } -static rt_err_t _pwm_enable(TMR_T *tmr, struct rt_pwm_configuration *configuration, rt_bool_t enable) +static rt_err_t drv_pwm_enable(TMR_T *tmr, struct rt_pwm_configuration *configuration, rt_bool_t enable) { rt_uint32_t channel = (configuration->channel - 1) << 2; @@ -447,7 +446,11 @@ static rt_err_t _pwm_enable(TMR_T *tmr, struct rt_pwm_configuration *configurati { TMR_EnableCCxChannel(tmr, (TMR_CHANNEL_T)(0x01 << (channel & 0x1FU))); } +#if defined(SOC_SERIES_APM32F0) + if (tmr == TMR1 || tmr == TMR15 || tmr == TMR16 || tmr == TMR17) +#else if (tmr == TMR1 || tmr == TMR8) +#endif { TMR_EnablePWMOutputs(tmr); } @@ -463,7 +466,11 @@ static rt_err_t _pwm_enable(TMR_T *tmr, struct rt_pwm_configuration *configurati { TMR_DisableCCxChannel(tmr, (TMR_CHANNEL_T)(0x01 << (channel & 0x1FU))); } +#if defined(SOC_SERIES_APM32F0) + if (tmr == TMR1 || tmr == TMR15 || tmr == TMR16 || tmr == TMR17) +#else if (tmr == TMR1 || tmr == TMR8) +#endif { TMR_DisablePWMOutputs(tmr); } @@ -473,24 +480,32 @@ static rt_err_t _pwm_enable(TMR_T *tmr, struct rt_pwm_configuration *configurati return RT_EOK; } -static rt_err_t _pwm_get(TMR_T *tmr, struct rt_pwm_configuration *configuration) +static rt_err_t drv_pwm_get(TMR_T *tmr, struct rt_pwm_configuration *configuration) { /* Converts the channel number to the channel number of library */ rt_uint32_t channel = (configuration->channel - 1) << 2; rt_uint64_t timer_clock; rt_uint32_t timer_reload, timer_psc; - timer_clock = _pwm_timer_clock_get(tmr); - + timer_clock = timer_clock_get(tmr); + +#if defined(SOC_SERIES_APM32F0) + if (tmr->CTRL1_B.CLKDIV == TMR_CKD_DIV2) +#else if (tmr->CTRL1_B.CLKDIV == TMR_CLOCK_DIV_2) +#endif { - timer_clock <<= 1; + timer_clock = timer_clock / 2; } +#if defined(SOC_SERIES_APM32F0) + if (tmr->CTRL1_B.CLKDIV == TMR_CKD_DIV4) +#else else if (tmr->CTRL1_B.CLKDIV == TMR_CLOCK_DIV_4) +#endif { - timer_clock <<= 2; + timer_clock = timer_clock / 4; } - + uint32_t temp; temp = (uint32_t)tmr; temp += (uint32_t)(0x34 + channel); @@ -501,18 +516,18 @@ static rt_err_t _pwm_get(TMR_T *tmr, struct rt_pwm_configuration *configuration) timer_psc = tmr->PSC; configuration->period = (timer_reload + 1) * (timer_psc + 1) * 1000UL / timer_clock; configuration->pulse = ((*(__IO uint32_t *)temp) + 1) * (timer_psc + 1) * 1000UL / timer_clock; - + return RT_EOK; } -static rt_err_t _pwm_set(TMR_T *tmr, struct rt_pwm_configuration *configuration) +static rt_err_t drv_pwm_set(TMR_T *tmr, struct rt_pwm_configuration *configuration) { rt_uint32_t period, pulse; rt_uint64_t timer_clock, psc; rt_uint32_t channel = 0x04 * (configuration->channel - 1); uint32_t temp = (uint32_t)tmr; - - timer_clock = _pwm_timer_clock_get(tmr); + + timer_clock = timer_clock_get(tmr); /* Convert nanosecond to frequency and duty cycle. */ timer_clock /= 1000000UL; @@ -548,7 +563,7 @@ static rt_err_t _pwm_set(TMR_T *tmr, struct rt_pwm_configuration *configuration) return RT_EOK; } -static rt_err_t _pwm_control(struct rt_device_pwm *device, int cmd, void *arg) +static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg) { struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg; TMR_T *tmr = (TMR_T *)device->parent.user_data; @@ -558,37 +573,36 @@ static rt_err_t _pwm_control(struct rt_device_pwm *device, int cmd, void *arg) case PWMN_CMD_ENABLE: configuration->complementary = RT_TRUE; case PWM_CMD_ENABLE: - return _pwm_enable(tmr, configuration, RT_TRUE); + return drv_pwm_enable(tmr, configuration, RT_TRUE); case PWMN_CMD_DISABLE: configuration->complementary = RT_FALSE; case PWM_CMD_DISABLE: - return _pwm_enable(tmr, configuration, RT_FALSE); + return drv_pwm_enable(tmr, configuration, RT_FALSE); case PWM_CMD_SET: - return _pwm_set(tmr, configuration); + return drv_pwm_set(tmr, configuration); case PWM_CMD_GET: - return _pwm_get(tmr, configuration); + return drv_pwm_get(tmr, configuration); default: return RT_EINVAL; } } -static const struct rt_pwm_ops _pwm_ops = +static const struct rt_pwm_ops drv_pwm_ops = { - _pwm_control + drv_pwm_control }; static int rt_hw_pwm_init(void) { rt_uint32_t i = 0; rt_err_t result = RT_EOK; - GPIO_Config_T gpio_config; - _pwm_channel_init(&gpio_config); + pwm_channel_init(); for (i = 0; i < sizeof(pwm_config) / sizeof(pwm_config[0]); i++) { /* pwm init */ - if (_pwm_hw_init(&pwm_config[i]) != RT_EOK) + if (apm32_pwm_hw_init(&pwm_config[i]) != RT_EOK) { LOG_E("%s init failed", pwm_config[i].name); return -RT_ERROR; @@ -598,7 +612,7 @@ static int rt_hw_pwm_init(void) LOG_D("%s init success", pwm_config[i].name); /* register pwm device */ - if (rt_device_pwm_register(&pwm_config[i].pwm_device, pwm_config[i].name, &_pwm_ops, pwm_config[i].tmr) == RT_EOK) + if (rt_device_pwm_register(&pwm_config[i].pwm_device, pwm_config[i].name, &drv_pwm_ops, pwm_config[i].tmr) == RT_EOK) { LOG_D("%s register success", pwm_config[i].name); } diff --git a/bsp/apm32/libraries/Drivers/drv_rtc.c b/bsp/apm32/libraries/Drivers/drv_rtc.c index 39573c7be7..6138963c1c 100644 --- a/bsp/apm32/libraries/Drivers/drv_rtc.c +++ b/bsp/apm32/libraries/Drivers/drv_rtc.c @@ -7,6 +7,7 @@ * Date Author Notes * 2022-03-04 stevetong459 first version * 2022-07-15 Aligagago add apm32F4 serie MCU support + * 2022-12-26 luobeihai add apm32F0 serie MCU support */ #include "board.h" @@ -14,7 +15,7 @@ #ifdef BSP_USING_ONCHIP_RTC -#define LOG_TAG "drv.rtc" +#define DBG_TAG "drv.rtc" #define DBG_LVL DBG_INFO #include @@ -25,7 +26,7 @@ #define LSE_VALUE ((uint32_t)32768) #endif -#define DRV_RTC_TIME_OUT 0xFFF +#define DRV_RTC_TIME_OUT 0xFFFFF static rt_rtc_dev_t apm32_rtc_dev; static rt_uint8_t rtc_init_flag = RESET; @@ -35,17 +36,17 @@ static rt_uint8_t rtc_init_flag = RESET; * * @return RT_EOK indicates successful initialize, other value indicates failed; */ -static rt_err_t _rtc_init(void) +static rt_err_t apm32_rtc_init(void) { volatile rt_uint32_t counter = 0; - + /* Enable RTC Clock */ -#ifdef APM32F10X_HD +#if defined(SOC_SERIES_APM32F1) RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU | RCM_APB1_PERIPH_BAKR); -#elif APM32F40X +#elif defined(SOC_SERIES_APM32F0) || defined(SOC_SERIES_APM32F4) RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU); #endif - + PMU_EnableBackupAccess(); /* Config RTC clock */ @@ -60,6 +61,7 @@ static rt_err_t _rtc_init(void) } RCM_ConfigRTCCLK(RCM_RTCCLK_LSI); #else + RCM_DisableLSI(); RCM_ConfigLSE(RCM_LSE_OPEN); while (!RCM_ReadStatusFlag(RCM_FLAG_LSERDY)) { @@ -69,12 +71,12 @@ static rt_err_t _rtc_init(void) } } RCM_ConfigRTCCLK(RCM_RTCCLK_LSE); -#endif +#endif /* BSP_RTC_USING_LSI */ RCM_EnableRTCCLK(); RTC_WaitForSynchro(); -#ifdef APM32F10X_HD +#if defined(SOC_SERIES_APM32F1) counter = 0; while (!RTC_ReadStatusFlag(RTC_FLAG_OC)) { @@ -92,13 +94,29 @@ static rt_err_t _rtc_init(void) RTC_ConfigPrescaler(LSI_VALUE - 1); #else RTC_ConfigPrescaler(LSE_VALUE - 1); -#endif -#elif APM32F40X +#endif /* BSP_RTC_USING_LSI */ + +#elif defined(SOC_SERIES_APM32F4) RTC_EnableInit(); RTC_Config_T rtcConfig; RTC_ConfigStructInit(&rtcConfig); RTC_Config(&rtcConfig); -#endif + +#elif defined(SOC_SERIES_APM32F0) + RTC_EnableInit(); + RTC_Config_T rtcConfig; + RTC_ConfigStructInit(&rtcConfig); + +#ifdef BSP_RTC_USING_LSI + rtcConfig.AsynchPrediv = 0x63; + rtcConfig.SynchPrediv = 0x18F; +#else + rtcConfig.AsynchPrediv = 0x7F; + rtcConfig.SynchPrediv = 0x130; +#endif /* BSP_RTC_USING_LSI */ + RTC_Config(&rtcConfig); + +#endif /* SOC_SERIES_APM32F1 */ if (!rtc_init_flag) { @@ -107,13 +125,13 @@ static rt_err_t _rtc_init(void) return RT_EOK; } -#ifdef APM32F10X_HD +#if defined(SOC_SERIES_APM32F1) /** * @brief This function will initialize the rtc on chip. * * @return RT_EOK indicates successful initialize, other value indicates failed; */ -static rt_err_t _rtc_get_secs(void *args) +static rt_err_t apm32_rtc_get_secs(time_t *sec) { volatile rt_uint32_t counter = 0; @@ -125,18 +143,18 @@ static rt_err_t _rtc_get_secs(void *args) } } - *(rt_uint32_t *) args = RTC_ReadCounter(); + *(timer_t *) sec = RTC_ReadCounter(); return RT_EOK; } -static rt_err_t _rtc_set_secs(void *args) +static rt_err_t apm32_rtc_set_secs(time_t *sec) { volatile rt_uint32_t counter = 0; if (!rtc_init_flag) { - _rtc_init(); + apm32_rtc_init(); } while (!RTC_ReadStatusFlag(RTC_FLAG_OC)) @@ -147,15 +165,21 @@ static rt_err_t _rtc_set_secs(void *args) } } - RTC_ConfigCounter(*(rt_uint32_t *)args); + RTC_ConfigCounter(*(rt_uint32_t *)sec); return RT_EOK; } -#elif APM32F40X -static void get_rtc_timeval(struct timeval *tv) +#elif defined(SOC_SERIES_APM32F0) || defined(SOC_SERIES_APM32F4) +static rt_err_t apm32_rtc_get_timeval(struct timeval *tv) { +#if defined(SOC_SERIES_APM32F0) + RTC_TIME_T timeConfig; + RTC_DATE_T dateConfig; +#elif defined(SOC_SERIES_APM32F4) RTC_TimeConfig_T timeConfig; RTC_DateConfig_T dateConfig; +#endif + struct tm tm_new = {0}; RTC_ReadTime(RTC_FORMAT_BIN, &timeConfig); @@ -167,19 +191,27 @@ static void get_rtc_timeval(struct timeval *tv) tm_new.tm_mday = dateConfig.date; tm_new.tm_mon = dateConfig.month - 1; tm_new.tm_year = dateConfig.year + 100; - + tv->tv_sec = timegm(&tm_new); + + return RT_EOK; } -static rt_err_t set_rtc_timeval(time_t time_stamp) +static rt_err_t set_rtc_time_stamp(time_t time_stamp) { +#if defined(SOC_SERIES_APM32F0) + RTC_TIME_T timeConfig; + RTC_DATE_T dateConfig; +#elif defined(SOC_SERIES_APM32F4) RTC_TimeConfig_T timeConfig; RTC_DateConfig_T dateConfig; +#endif + struct tm tm = {0}; if (!rtc_init_flag) { - _rtc_init(); + apm32_rtc_init(); } gmtime_r(&time_stamp, &tm); @@ -192,12 +224,21 @@ static rt_err_t set_rtc_timeval(time_t time_stamp) timeConfig.minutes = tm.tm_min ; timeConfig.hours = tm.tm_hour; dateConfig.date = tm.tm_mday; +#if defined(SOC_SERIES_APM32F4) + dateConfig.month = (RTC_MONTH_T)(tm.tm_mon + 1); + dateConfig.weekday = (RTC_WEEKDAY_T)(tm.tm_wday + 1); +#else dateConfig.month = tm.tm_mon + 1 ; - dateConfig.year = tm.tm_year - 100; dateConfig.weekday = tm.tm_wday + 1; +#endif + dateConfig.year = tm.tm_year - 100; + RTC_ConfigTime(RTC_FORMAT_BIN, &timeConfig); RTC_ConfigDate(RTC_FORMAT_BIN, &dateConfig); + + /* wait for set time completed */ + for (int i = 0; i < 0xFFFF; i++); return RT_EOK; } @@ -207,20 +248,20 @@ static rt_err_t set_rtc_timeval(time_t time_stamp) * * @return RT_EOK indicates successful initialize, other value indicates failed; */ -static rt_err_t _rtc_get_secs(void *args) +static rt_err_t apm32_rtc_get_secs(time_t *sec) { struct timeval tv; - get_rtc_timeval(&tv); - *(rt_uint32_t *) args = tv.tv_sec; + apm32_rtc_get_timeval(&tv); + *(time_t *) sec = tv.tv_sec; return RT_EOK; } -static rt_err_t _rtc_set_secs(void *args) +static rt_err_t apm32_rtc_set_secs(time_t *sec) { rt_err_t result = RT_EOK; - if (set_rtc_timeval(*(rt_uint32_t *)args)) + if (set_rtc_time_stamp(*sec)) { result = -RT_ERROR; } @@ -229,14 +270,18 @@ static rt_err_t _rtc_set_secs(void *args) } #endif -static const struct rt_rtc_ops _rtc_ops = +static const struct rt_rtc_ops apm32_rtc_ops = { - _rtc_init, - _rtc_get_secs, - _rtc_set_secs, + apm32_rtc_init, + apm32_rtc_get_secs, + apm32_rtc_set_secs, RT_NULL, RT_NULL, +#if defined(SOC_SERIES_APM32F0) || defined(SOC_SERIES_APM32F4) + apm32_rtc_get_timeval, +#else RT_NULL, +#endif RT_NULL, }; @@ -249,7 +294,7 @@ static int rt_hw_rtc_init(void) { rt_err_t result = RT_EOK; - apm32_rtc_dev.ops = &_rtc_ops; + apm32_rtc_dev.ops = &apm32_rtc_ops; if (rt_hw_rtc_register(&apm32_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL) != RT_EOK) { @@ -263,7 +308,6 @@ static int rt_hw_rtc_init(void) return result; } - INIT_DEVICE_EXPORT(rt_hw_rtc_init); #endif /* BSP_USING_ONCHIP_RTC */ diff --git a/bsp/apm32/libraries/Drivers/drv_soft_i2c.c b/bsp/apm32/libraries/Drivers/drv_soft_i2c.c index 8911da89ad..c4a7844e16 100644 --- a/bsp/apm32/libraries/Drivers/drv_soft_i2c.c +++ b/bsp/apm32/libraries/Drivers/drv_soft_i2c.c @@ -13,7 +13,7 @@ #ifdef RT_USING_I2C -#define LOG_TAG "drv.i2c" +#define DBG_TAG "drv.i2c" #define DBG_LVL DBG_INFO #include @@ -43,28 +43,28 @@ static const struct apm32_soft_i2c_config soft_i2c_config[] = BSP_I2C1_SCL_PIN, BSP_I2C1_SDA_PIN, "i2c1" - } + }, #endif #ifdef BSP_USING_I2C2 { BSP_I2C2_SCL_PIN, BSP_I2C2_SDA_PIN, "i2c2" - } + }, #endif #ifdef BSP_USING_I2C3 { BSP_I2C3_SCL_PIN, BSP_I2C3_SDA_PIN, "i2c3" - } + }, #endif #ifdef BSP_USING_I2C4 { BSP_I2C4_SCL_PIN, BSP_I2C4_SDA_PIN, "i2c4" - } + }, #endif }; @@ -75,7 +75,7 @@ static struct apm32_soft_i2c i2c_obj[sizeof(soft_i2c_config) / sizeof(soft_i2c_c * * @param i2c is a pointer to the object of soft i2c. */ -static void _soft_i2c_gpio_init(struct apm32_soft_i2c *i2c) +static void apm32_soft_i2c_gpio_init(struct apm32_soft_i2c *i2c) { struct apm32_soft_i2c_config *cfg = (struct apm32_soft_i2c_config *)i2c->ops.data; @@ -93,7 +93,7 @@ static void _soft_i2c_gpio_init(struct apm32_soft_i2c *i2c) * * @param state is the level of sda pin. */ -static void _soft_i2c_set_sda(void *data, rt_int32_t state) +static void apm32_soft_i2c_set_sda(void *data, rt_int32_t state) { struct apm32_soft_i2c_config *cfg = (struct apm32_soft_i2c_config *)data; @@ -107,7 +107,7 @@ static void _soft_i2c_set_sda(void *data, rt_int32_t state) * * @param state is the level of scl pin. */ -static void _soft_i2c_set_scl(void *data, rt_int32_t state) +static void apm32_soft_i2c_set_scl(void *data, rt_int32_t state) { struct apm32_soft_i2c_config *cfg = (struct apm32_soft_i2c_config *)data; @@ -119,7 +119,7 @@ static void _soft_i2c_set_scl(void *data, rt_int32_t state) * * @param data is a pointer to the i2c config class. */ -static rt_int32_t _soft_i2c_get_sda(void *data) +static rt_int32_t apm32_soft_i2c_get_sda(void *data) { struct apm32_soft_i2c_config *cfg = (struct apm32_soft_i2c_config *)data; return rt_pin_read(cfg->sda_pin); @@ -130,7 +130,7 @@ static rt_int32_t _soft_i2c_get_sda(void *data) * * @param data is a pointer to the i2c config class. */ -static rt_int32_t _soft_i2c_get_scl(void *data) +static rt_int32_t apm32_soft_i2c_get_scl(void *data) { struct apm32_soft_i2c_config *cfg = (struct apm32_soft_i2c_config *)data; return rt_pin_read(cfg->scl_pin); @@ -141,7 +141,7 @@ static rt_int32_t _soft_i2c_get_scl(void *data) * * @param us is the microseconds to delay. */ -static void _soft_i2c_udelay(rt_uint32_t us) +static void apm32_soft_i2c_udelay(rt_uint32_t us) { rt_uint32_t count_old = SysTick->VAL; rt_uint32_t count_now; @@ -183,9 +183,9 @@ static rt_err_t apm32_i2c_bus_unlock(const struct apm32_soft_i2c_config *cfg) while (i++ < 9) { rt_pin_write(cfg->scl_pin, PIN_HIGH); - _soft_i2c_udelay(100); + apm32_soft_i2c_udelay(100); rt_pin_write(cfg->scl_pin, PIN_LOW); - _soft_i2c_udelay(100); + apm32_soft_i2c_udelay(100); } } if (PIN_LOW == rt_pin_read(cfg->sda_pin)) @@ -199,11 +199,11 @@ static rt_err_t apm32_i2c_bus_unlock(const struct apm32_soft_i2c_config *cfg) static const struct rt_i2c_bit_ops apm32_bit_ops_default = { .data = RT_NULL, - .set_sda = _soft_i2c_set_sda, - .set_scl = _soft_i2c_set_scl, - .get_sda = _soft_i2c_get_sda, - .get_scl = _soft_i2c_get_scl, - .udelay = _soft_i2c_udelay, + .set_sda = apm32_soft_i2c_set_sda, + .set_scl = apm32_soft_i2c_set_scl, + .get_sda = apm32_soft_i2c_get_sda, + .get_scl = apm32_soft_i2c_get_scl, + .udelay = apm32_soft_i2c_udelay, .delay_us = 1, .timeout = 100 }; @@ -223,7 +223,7 @@ int rt_hw_i2c_init(void) i2c_obj[i].ops = apm32_bit_ops_default; i2c_obj[i].ops.data = (void *)&soft_i2c_config[i]; i2c_obj[i].i2c2_bus.priv = &i2c_obj[i].ops; - _soft_i2c_gpio_init(&i2c_obj[i]); + apm32_soft_i2c_gpio_init(&i2c_obj[i]); result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c2_bus, soft_i2c_config[i].bus_name); @@ -231,10 +231,10 @@ int rt_hw_i2c_init(void) apm32_i2c_bus_unlock(&soft_i2c_config[i]); - LOG_D("software simulation %s init done, pin scl: %s, pin sda: %s", + LOG_D("software simulation %s init done, pin scl: %d, pin sda: %d", soft_i2c_config[i].bus_name, - soft_i2c_config[i].scl_pin_name, - soft_i2c_config[i].sda_pin_name); + soft_i2c_config[i].scl_pin, + soft_i2c_config[i].sda_pin); } return RT_EOK; diff --git a/bsp/apm32/libraries/Drivers/drv_spi.c b/bsp/apm32/libraries/Drivers/drv_spi.c index e64be39e4c..fde1f7f0a0 100644 --- a/bsp/apm32/libraries/Drivers/drv_spi.c +++ b/bsp/apm32/libraries/Drivers/drv_spi.c @@ -7,34 +7,128 @@ * Date Author Notes * 2022-03-04 stevetong459 first version * 2022-07-15 Aligagago add apm32F4 serie MCU support + * 2022-12-26 luobeihai add apm32F0 serie MCU support */ #include "drv_spi.h" +//#define DRV_DEBUG #define LOG_TAG "drv.spi" -#define DBG_LVL DBG_INFO -#include +#include "drv_log.h" #if defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2) || defined(BSP_USING_SPI3) -static rt_err_t _spi_configure(struct rt_spi_device *spi_drv, struct rt_spi_configuration *cfg) +static struct apm32_spi_config spi_config[] = { +#ifdef BSP_USING_SPI1 + {SPI1, "spi1"}, +#endif + +#ifdef BSP_USING_SPI2 + {SPI2, "spi2"}, +#endif + +#ifdef BSP_USING_SPI3 + {SPI3, "spi3"}, +#endif +}; + +static struct apm32_spi spi_bus_obj[sizeof(spi_config) / sizeof(spi_config[0])] = {0}; + +/** + * Attach the spi device to SPI bus, this function must be used after initialization. + */ +rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, GPIO_T *cs_gpiox, uint16_t cs_gpio_pin) { - RT_ASSERT(spi_drv != RT_NULL); + RT_ASSERT(bus_name != RT_NULL); + RT_ASSERT(device_name != RT_NULL); + + rt_err_t result; + struct rt_spi_device *spi_device; + struct apm32_spi_cs *cs_pin; + GPIO_Config_T GPIO_InitStructure; + + /* initialize the cs pin && select the slave */ +#if defined(SOC_SERIES_APM32F0) + GPIO_ConfigStructInit(&GPIO_InitStructure); + GPIO_InitStructure.pin = cs_gpio_pin; + GPIO_InitStructure.speed = GPIO_SPEED_50MHz; + GPIO_InitStructure.mode = GPIO_MODE_OUT; + GPIO_InitStructure.outtype = GPIO_OUT_TYPE_PP; + GPIO_InitStructure.pupd = GPIO_PUPD_NO; + GPIO_Config(cs_gpiox, &GPIO_InitStructure); + GPIO_WriteBitValue(cs_gpiox, cs_gpio_pin, Bit_SET); +#elif defined(SOC_SERIES_APM32F1) + GPIO_ConfigStructInit(&GPIO_InitStructure); + GPIO_InitStructure.pin = cs_gpio_pin; + GPIO_InitStructure.mode = GPIO_MODE_OUT_PP; + GPIO_InitStructure.speed = GPIO_SPEED_50MHz; + GPIO_Config(cs_gpiox, &GPIO_InitStructure); + GPIO_WriteBitValue(cs_gpiox, cs_gpio_pin, BIT_SET); +#elif defined(SOC_SERIES_APM32F4) + GPIO_ConfigStructInit(&GPIO_InitStructure); + GPIO_InitStructure.pin = cs_gpio_pin; + GPIO_InitStructure.speed = GPIO_SPEED_100MHz; + GPIO_InitStructure.mode = GPIO_MODE_OUT; + GPIO_InitStructure.otype = GPIO_OTYPE_PP; + GPIO_InitStructure.pupd = GPIO_PUPD_NOPULL; + GPIO_Config(cs_gpiox, &GPIO_InitStructure); + GPIO_WriteBitValue(cs_gpiox, cs_gpio_pin, BIT_SET); +#endif + + /* attach the device to spi bus */ + spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device)); + RT_ASSERT(spi_device != RT_NULL); + cs_pin = (struct apm32_spi_cs *)rt_malloc(sizeof(struct apm32_spi_cs)); + RT_ASSERT(cs_pin != RT_NULL); + cs_pin->GPIOx = cs_gpiox; + cs_pin->GPIO_Pin = cs_gpio_pin; + result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin); + + if (result != RT_EOK) + { + LOG_E("%s attach to %s faild, %d\n", device_name, bus_name, result); + } + + RT_ASSERT(result == RT_EOK); + + LOG_D("%s attach to %s done", device_name, bus_name); + + return result; +} + +static rt_err_t apm32_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg) +{ + RT_ASSERT(device != RT_NULL); RT_ASSERT(cfg != RT_NULL); + SPI_Config_T hw_spi_config; - SPI_T *spi = (SPI_T *)spi_drv->bus->parent.user_data; + + struct rt_spi_bus * apm32_spi_bus = (struct rt_spi_bus *)device->bus; + struct apm32_spi *spi_device = (struct apm32_spi *)apm32_spi_bus->parent.user_data; + SPI_T *spi = spi_device->config->spi_x; + uint32_t hw_spi_apb_clock; #if (DBG_LVL == DBG_LOG) uint32_t hw_spi_sys_clock = RCM_ReadSYSCLKFreq(); #endif + + /* apm32 spi gpio init and enable clock */ + extern void apm32_msp_spi_init(void *Instance); + apm32_msp_spi_init(spi); + /* apm32 spi init */ hw_spi_config.mode = (cfg->mode & RT_SPI_SLAVE) ? SPI_MODE_SLAVE : SPI_MODE_MASTER; hw_spi_config.direction = (cfg->mode & RT_SPI_3WIRE) ? SPI_DIRECTION_1LINE_RX : SPI_DIRECTION_2LINES_FULLDUPLEX; hw_spi_config.phase = (cfg->mode & RT_SPI_CPHA) ? SPI_CLKPHA_2EDGE : SPI_CLKPHA_1EDGE; hw_spi_config.polarity = (cfg->mode & RT_SPI_CPOL) ? SPI_CLKPOL_HIGH : SPI_CLKPOL_LOW; +#if defined(SOC_SERIES_APM32F0) + hw_spi_config.slaveSelect = (cfg->mode & RT_SPI_NO_CS) ? SPI_SSC_DISABLE : SPI_SSC_ENABLE; + hw_spi_config.firstBit = (cfg->mode & RT_SPI_MSB) ? SPI_FIRST_BIT_MSB : SPI_FIRST_BIT_LSB; +#else hw_spi_config.nss = (cfg->mode & RT_SPI_NO_CS) ? SPI_NSS_HARD : SPI_NSS_SOFT; hw_spi_config.firstBit = (cfg->mode & RT_SPI_MSB) ? SPI_FIRSTBIT_MSB : SPI_FIRSTBIT_LSB; - +#endif + if (cfg->data_width == 8) { hw_spi_config.length = SPI_DATA_LENGTH_8B; @@ -48,7 +142,18 @@ static rt_err_t _spi_configure(struct rt_spi_device *spi_drv, struct rt_spi_conf return RT_EIO; } - RCM_ReadPCLKFreq(NULL, &hw_spi_apb_clock); +#if defined(SOC_SERIES_APM32F0) + hw_spi_apb_clock = RCM_ReadPCLKFreq(); +#else + if (spi == SPI1) + { + RCM_ReadPCLKFreq(NULL, &hw_spi_apb_clock); + } + else + { + RCM_ReadPCLKFreq(&hw_spi_apb_clock, NULL); + } +#endif if (cfg->max_hz >= hw_spi_apb_clock / 2) { @@ -80,32 +185,46 @@ static rt_err_t _spi_configure(struct rt_spi_device *spi_drv, struct rt_spi_conf } else { - /* min prescaler 256 */ + /* min prescaler 256 */ hw_spi_config.baudrateDiv = SPI_BAUDRATE_DIV_256; } LOG_D("sys freq: %d, pclk2 freq: %d, SPI limiting freq: %d, BaudRatePrescaler: %d", hw_spi_sys_clock, hw_spi_apb_clock, cfg->max_hz, hw_spi_config.baudrateDiv); - + +#if defined(SOC_SERIES_APM32F0) + SPI_DisableCRC(spi); + SPI_EnableSSoutput(spi); + SPI_ConfigFIFOThreshold(spi, SPI_RXFIFO_QUARTER); +#endif + SPI_Config(spi, &hw_spi_config); SPI_Enable(spi); return RT_EOK; } -static rt_uint32_t _spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message) +static rt_uint32_t apm32_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message) { RT_ASSERT(device != NULL); RT_ASSERT(message != NULL); - rt_base_t cs_pin = (rt_base_t)device->parent.user_data; - SPI_T *spi = (SPI_T *)device->bus->parent.user_data; struct rt_spi_configuration *config = &device->config; + + struct apm32_spi_cs *cs = device->parent.user_data; + + struct rt_spi_bus * apm32_spi_bus = (struct rt_spi_bus *)device->bus; + struct apm32_spi *spi_device = (struct apm32_spi *)apm32_spi_bus->parent.user_data; + SPI_T *spi = spi_device->config->spi_x; /* take CS */ if (message->cs_take) { - rt_pin_write(cs_pin, PIN_LOW); +#if defined(SOC_SERIES_APM32F0) + GPIO_WriteBitValue(cs->GPIOx, cs->GPIO_Pin, (GPIO_BSRET_T)RESET); +#else + GPIO_WriteBitValue(cs->GPIOx, cs->GPIO_Pin, RESET); +#endif LOG_D("spi take cs\n"); } @@ -126,16 +245,24 @@ static rt_uint32_t _spi_xfer(struct rt_spi_device *device, struct rt_spi_message data = *send_ptr++; } +#if defined(SOC_SERIES_APM32F0) + /* Wait until the transmit buffer is empty */ + while (SPI_ReadStatusFlag(spi, SPI_FLAG_TXBE) == RESET); + SPI_TxData8(spi, data); + + /* Wait until a data is received */ + while (SPI_ReadStatusFlag(spi, SPI_FLAG_RXBNE) == RESET); + data = SPI_RxData8(spi); +#else /* Wait until the transmit buffer is empty */ while (SPI_I2S_ReadStatusFlag(spi, SPI_FLAG_TXBE) == RESET); - SPI_I2S_TxData(spi, data); /* Wait until a data is received */ while (SPI_I2S_ReadStatusFlag(spi, SPI_FLAG_RXBNE) == RESET); - data = SPI_I2S_RxData(spi); - +#endif + if (recv_ptr != RT_NULL) { *recv_ptr++ = data; @@ -157,17 +284,27 @@ static rt_uint32_t _spi_xfer(struct rt_spi_device *device, struct rt_spi_message { data = *send_ptr++; } - - /*Wait until the transmit buffer is empty */ + +#if defined(SOC_SERIES_APM32F0) + /* Wait until the transmit buffer is empty */ + while (SPI_ReadStatusFlag(spi, SPI_FLAG_TXBE) == RESET); + SPI_I2S_TxData16(spi, data); + + /* Wait until a data is received */ + while (SPI_ReadStatusFlag(spi, SPI_FLAG_RXBNE) == RESET); + data = SPI_I2S_RxData16(spi); +#else + /* Wait until the transmit buffer is empty */ while (SPI_I2S_ReadStatusFlag(spi, SPI_FLAG_TXBE) == RESET); /* Send the byte */ SPI_I2S_TxData(spi, data); - /*Wait until a data is received */ + /* Wait until a data is received */ while (SPI_I2S_ReadStatusFlag(spi, SPI_FLAG_RXBNE) == RESET); /* Get the received data */ data = SPI_I2S_RxData(spi); - +#endif + if (recv_ptr != RT_NULL) { *recv_ptr++ = data; @@ -178,164 +315,37 @@ static rt_uint32_t _spi_xfer(struct rt_spi_device *device, struct rt_spi_message /* release CS */ if (message->cs_release) { - rt_pin_write(cs_pin, PIN_HIGH); +#if defined(SOC_SERIES_APM32F0) + GPIO_WriteBitValue(cs->GPIOx, cs->GPIO_Pin, (GPIO_BSRET_T)SET); +#else + GPIO_WriteBitValue(cs->GPIOx, cs->GPIO_Pin, SET); +#endif LOG_D("spi release cs\n"); } return message->length; }; -static const struct rt_spi_ops _spi_ops = +static const struct rt_spi_ops apm32_spi_ops = { - _spi_configure, - _spi_xfer + apm32_spi_configure, + apm32_spi_xfer }; static int rt_hw_spi_init(void) { - int result = 0; - GPIO_Config_T gpio_config; + rt_err_t result; + + for (int i = 0; i < sizeof(spi_config) / sizeof(spi_config[0]); i++) + { + spi_bus_obj[i].config = &spi_config[i]; + spi_bus_obj[i].spi_bus.parent.user_data = (void *)&spi_bus_obj[i]; + result = rt_spi_bus_register(&spi_bus_obj[i].spi_bus, spi_config[i].spi_bus_name, &apm32_spi_ops); + RT_ASSERT(result == RT_EOK); -#ifdef APM32F10X_HD -#ifdef BSP_USING_SPI1 - static struct rt_spi_bus spi_bus1; - spi_bus1.parent.user_data = (void *)SPI1; + LOG_D("%s bus init done", spi_config[i].spi_bus_name); + } - result = rt_spi_bus_register(&spi_bus1, "spi1", &_spi_ops); - - RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA); - RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SPI1); - - /* SPI1_SCK(PA5) SPI1_MOSI(PA7) */ - gpio_config.mode = GPIO_MODE_AF_PP; - gpio_config.speed = GPIO_SPEED_50MHz; - gpio_config.pin = (GPIO_PIN_5 | GPIO_PIN_7); - GPIO_Config(GPIOA, &gpio_config); - /* SPI1_MISO(PA6) */ - gpio_config.mode = GPIO_MODE_IN_FLOATING; - gpio_config.speed = GPIO_SPEED_50MHz; - gpio_config.pin = GPIO_PIN_6; - GPIO_Config(GPIOA, &gpio_config); -#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); - - RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOB); - RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_SPI2); - - /* SPI2_SCK(PB13) SPI2_MOSI(PB15) */ - gpio_config.mode = GPIO_MODE_AF_PP; - gpio_config.speed = GPIO_SPEED_50MHz; - gpio_config.pin = (GPIO_PIN_13 | GPIO_PIN_15); - GPIO_Config(GPIOB, &gpio_config); - /* SPI2_MISO(PB14) */ - gpio_config.mode = GPIO_MODE_IN_FLOATING; - gpio_config.speed = GPIO_SPEED_50MHz; - gpio_config.pin = GPIO_PIN_14; - GPIO_Config(GPIOB, &gpio_config); -#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); - - RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOB); - RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_SPI3); - - /* SPI3_SCK(PB3) SPI3_MOSI(PB5) */ - gpio_config.mode = GPIO_MODE_AF_PP; - gpio_config.speed = GPIO_SPEED_50MHz; - gpio_config.pin = (GPIO_PIN_3 | GPIO_PIN_5); - GPIO_Config(GPIOB, &gpio_config); - /* SPI3_MISO(PB4) */ - gpio_config.mode = GPIO_MODE_IN_FLOATING; - gpio_config.speed = GPIO_SPEED_50MHz; - gpio_config.pin = GPIO_PIN_4; - GPIO_Config(GPIOB, &gpio_config); -#endif -#elif APM32F40X -#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); - - RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA); - RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SPI1); - - /* Config SPI1 PinAF */ - GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_4, GPIO_AF_SPI1); - GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_5, GPIO_AF_SPI1); - GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_6, GPIO_AF_SPI1); - GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_7, GPIO_AF_SPI1); - - /* SPI1_NSS(PA4) SPI1_SCK(PA5) SPI1_MISO(PA6) SPI1_MOSI(PA7) */ - gpio_config.mode = GPIO_MODE_AF; - gpio_config.speed = GPIO_SPEED_100MHz; - gpio_config.otype = GPIO_OTYPE_PP; - gpio_config.pupd = GPIO_PUPD_NOPULL; - gpio_config.pin = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7; - GPIO_Config(GPIOA, &gpio_config); -#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); - - RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOB); - RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_SPI2); - - /* Config SPI2 PinAF */ - GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_12, GPIO_AF_SPI2); - GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_13, GPIO_AF_SPI2); - GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_14, GPIO_AF_SPI2); - GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_15, GPIO_AF_SPI2); - - /* SPI2_NSS(PB12) SPI2_SCK(PB13) SPI2_MISO(PB14) SPI2_MOSI(PB15) */ - gpio_config.mode = GPIO_MODE_AF; - gpio_config.speed = GPIO_SPEED_100MHz; - gpio_config.otype = GPIO_OTYPE_PP; - gpio_config.pupd = GPIO_PUPD_NOPULL; - gpio_config.pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; - GPIO_Config(GPIOB, &gpio_config); -#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); - - RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA); - RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOB); - RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_SPI3); - - /* Config SPI3 PinAF */ - GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_4, GPIO_AF_SPI3); - GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_3, GPIO_AF_SPI3); - GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_4, GPIO_AF_SPI3); - GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_5, GPIO_AF_SPI3); - - /* SPI3_SCK(PB3) SPI3_MISO(PB4) SPI3_MOSI(PB5) */ - gpio_config.mode = GPIO_MODE_AF; - gpio_config.speed = GPIO_SPEED_100MHz; - gpio_config.otype = GPIO_OTYPE_PP; - gpio_config.pupd = GPIO_PUPD_NOPULL; - gpio_config.pin = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5; - GPIO_Config(GPIOB, &gpio_config); - /* SPI3_NSS(PA4) */ - gpio_config.pin = GPIO_PIN_4; - GPIO_Config(GPIOA, &gpio_config); -#endif -#endif return result; } INIT_BOARD_EXPORT(rt_hw_spi_init); diff --git a/bsp/apm32/libraries/Drivers/drv_spi.h b/bsp/apm32/libraries/Drivers/drv_spi.h index e4591352f5..e66643ed53 100644 --- a/bsp/apm32/libraries/Drivers/drv_spi.h +++ b/bsp/apm32/libraries/Drivers/drv_spi.h @@ -13,10 +13,24 @@ #include "board.h" +struct apm32_spi_config +{ + SPI_T *spi_x; + char *spi_bus_name; +}; + +struct apm32_spi +{ + struct apm32_spi_config *config; + struct rt_spi_bus spi_bus; +}; + struct apm32_spi_cs { GPIO_T *GPIOx; uint16_t GPIO_Pin; }; +rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, GPIO_T *cs_gpiox, uint16_t cs_gpio_pin); + #endif /*__DRV_SPI_H__ */ diff --git a/bsp/apm32/libraries/Drivers/drv_usart.c b/bsp/apm32/libraries/Drivers/drv_usart.c index d7d27de8a6..9261510031 100644 --- a/bsp/apm32/libraries/Drivers/drv_usart.c +++ b/bsp/apm32/libraries/Drivers/drv_usart.c @@ -6,14 +6,16 @@ * Change Logs: * Date Author Notes * 2020-08-20 Abbcc first version + * 2022-12-26 luobeihai add apm32F0 serie MCU support */ #include "board.h" #include "drv_usart.h" - #ifdef RT_USING_SERIAL -#if !defined(BSP_USING_UART1) && !defined(BSP_USING_UART2) +#if !defined(BSP_USING_UART1) && !defined(BSP_USING_UART2) && \ + !defined(BSP_USING_UART3) && !defined(BSP_USING_UART4) && \ + !defined(BSP_USING_UART5) && !defined(BSP_USING_UART6) #error "Please define at least one BSP_USING_UARTx" /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */ #endif @@ -34,6 +36,18 @@ enum #ifdef BSP_USING_UART2 UART2_INDEX, #endif +#ifdef BSP_USING_UART3 + UART3_INDEX, +#endif +#ifdef BSP_USING_UART4 + UART4_INDEX, +#endif +#ifdef BSP_USING_UART5 + UART5_INDEX, +#endif +#ifdef BSP_USING_UART6 + UART6_INDEX, +#endif }; static struct apm32_usart usart_config[] = @@ -52,9 +66,39 @@ static struct apm32_usart usart_config[] = USART2_IRQn, }, #endif +#if defined(SOC_SERIES_APM32F1) || defined(SOC_SERIES_APM32F4) +#ifdef BSP_USING_UART3 + { + "uart3", + USART3, + USART3_IRQn, + }, +#endif +#ifdef BSP_USING_UART4 + { + "uart4", + UART4, + UART4_IRQn, + }, +#endif +#ifdef BSP_USING_UART5 + { + "uart5", + UART5, + UART5_IRQn, + }, +#endif +#ifdef BSP_USING_UART6 + { + "uart6", + USART6, + USART6_IRQn, + }, +#endif +#endif }; -static rt_err_t _uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +static rt_err_t apm32_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) { USART_Config_T USART_ConfigStruct; RT_ASSERT(serial != RT_NULL); @@ -64,10 +108,38 @@ static rt_err_t _uart_configure(struct rt_serial_device *serial, struct serial_c apm32_usart_init(); - USART_ConfigStruct.baudRate = cfg->baud_rate;; - USART_ConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE; + USART_ConfigStruct.baudRate = cfg->baud_rate; USART_ConfigStruct.mode = USART_MODE_TX_RX; USART_ConfigStruct.parity = USART_PARITY_NONE; + +#if defined(SOC_SERIES_APM32F0) + switch (cfg->flowcontrol) + { + case RT_SERIAL_FLOWCONTROL_NONE: + + USART_ConfigStruct.hardwareFlowCtrl = USART_FLOW_CTRL_NONE; + break; + case RT_SERIAL_FLOWCONTROL_CTSRTS: + USART_ConfigStruct.hardwareFlowCtrl = USART_FLOW_CTRL_RTS_CTS; + break; + default: + USART_ConfigStruct.hardwareFlowCtrl = USART_FLOW_CTRL_NONE; + break; + } +#else + switch (cfg->flowcontrol) + { + case RT_SERIAL_FLOWCONTROL_NONE: + USART_ConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE; + break; + case RT_SERIAL_FLOWCONTROL_CTSRTS: + USART_ConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_RTS_CTS; + break; + default: + USART_ConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE; + break; + } +#endif switch (cfg->data_bits) { @@ -120,7 +192,7 @@ static rt_err_t _uart_configure(struct rt_serial_device *serial, struct serial_c return RT_EOK; } -static rt_err_t _uart_control(struct rt_serial_device *serial, int cmd, void *arg) +static rt_err_t apm32_uart_control(struct rt_serial_device *serial, int cmd, void *arg) { struct apm32_usart *usart; @@ -129,6 +201,30 @@ static rt_err_t _uart_control(struct rt_serial_device *serial, int cmd, void *ar usart = (struct apm32_usart *) serial->parent.user_data; RT_ASSERT(usart != RT_NULL); +#if defined(SOC_SERIES_APM32F0) + switch (cmd) + { + /* disable interrupt */ + case RT_DEVICE_CTRL_CLR_INT: + + /* disable rx irq */ + NVIC_DisableIRQRequest(usart->irq_type); + + /* disable interrupt */ + USART_DisableInterrupt(usart->usartx, USART_INT_RXBNEIE); + + break; + + /* enable interrupt */ + case RT_DEVICE_CTRL_SET_INT: + /* enable rx irq */ + NVIC_EnableIRQRequest(usart->irq_type, 1); + + /* enable interrupt */ + USART_EnableInterrupt(usart->usartx, USART_INT_RXBNEIE); + break; + } +#else switch (cmd) { /* disable interrupt */ @@ -150,12 +246,12 @@ static rt_err_t _uart_control(struct rt_serial_device *serial, int cmd, void *ar /* enable interrupt */ USART_EnableInterrupt(usart->usartx, USART_INT_RXBNE); break; - } +#endif return RT_EOK; } -static int _uart_putc(struct rt_serial_device *serial, char c) +static int apm32_uart_putc(struct rt_serial_device *serial, char c) { struct apm32_usart *usart; RT_ASSERT(serial != RT_NULL); @@ -171,7 +267,7 @@ static int _uart_putc(struct rt_serial_device *serial, char c) return 1; } -static int _uart_getc(struct rt_serial_device *serial) +static int apm32_uart_getc(struct rt_serial_device *serial) { int ch; struct apm32_usart *usart; @@ -197,33 +293,75 @@ static void usart_isr(struct rt_serial_device *serial) { struct apm32_usart *usart; - RT_ASSERT(serial != RT_NULL); RT_ASSERT(serial != RT_NULL); usart = (struct apm32_usart *) serial->parent.user_data; RT_ASSERT(usart != RT_NULL); /* UART in mode Receiver */ +#if defined(SOC_SERIES_APM32F0) + if ((USART_ReadStatusFlag(usart->usartx, USART_FLAG_RXBNE) != RESET) && + (USART_ReadIntFlag(usart->usartx, USART_INT_FLAG_RXBNE) != RESET)) +#else if ((USART_ReadStatusFlag(usart->usartx, USART_FLAG_RXBNE) != RESET) && (USART_ReadIntFlag(usart->usartx, USART_INT_RXBNE) != RESET)) +#endif { rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); - USART_ClearStatusFlag(usart->usartx, USART_FLAG_RXBNE); - USART_ClearIntFlag(usart->usartx, USART_INT_RXBNE); } - else { +#if defined(SOC_SERIES_APM32F0) + if (USART_ReadStatusFlag(usart->usartx, USART_FLAG_OVRE) != RESET) + { + USART_ClearStatusFlag(usart->usartx, USART_FLAG_OVRE); + } + if (USART_ReadStatusFlag(usart->usartx, USART_FLAG_NEF) != RESET) + { + USART_ClearStatusFlag(usart->usartx, USART_FLAG_NEF); + } + if (USART_ReadStatusFlag(usart->usartx, USART_FLAG_FEF) != RESET) + { + USART_ClearStatusFlag(usart->usartx, USART_FLAG_FEF); + } + if (USART_ReadStatusFlag(usart->usartx, USART_FLAG_PEF) != RESET) + { + USART_ClearStatusFlag(usart->usartx, USART_FLAG_PEF); + } + if (USART_ReadStatusFlag(usart->usartx, USART_FLAG_CTSF) != RESET) + { + USART_ClearStatusFlag(usart->usartx, USART_FLAG_CTSF); + } + if (USART_ReadStatusFlag(usart->usartx, USART_FLAG_LBDF) != RESET) + { + USART_ClearStatusFlag(usart->usartx, USART_FLAG_LBDF); + } +#else + if (USART_ReadStatusFlag(usart->usartx, USART_FLAG_OVRE) != RESET) + { + USART_ClearStatusFlag(usart->usartx, USART_FLAG_OVRE); + } + if (USART_ReadStatusFlag(usart->usartx, USART_FLAG_NE) != RESET) + { + USART_ClearStatusFlag(usart->usartx, USART_FLAG_NE); + } + if (USART_ReadStatusFlag(usart->usartx, USART_FLAG_FE) != RESET) + { + USART_ClearStatusFlag(usart->usartx, USART_FLAG_FE); + } + if (USART_ReadStatusFlag(usart->usartx, USART_FLAG_PE) != RESET) + { + USART_ClearStatusFlag(usart->usartx, USART_FLAG_PE); + } if (USART_ReadStatusFlag(usart->usartx, USART_FLAG_CTS) != RESET) { USART_ClearStatusFlag(usart->usartx, USART_FLAG_CTS); } - if (USART_ReadStatusFlag(usart->usartx, USART_FLAG_LBD) != RESET) { USART_ClearStatusFlag(usart->usartx, USART_FLAG_LBD); } - +#endif if (USART_ReadStatusFlag(usart->usartx, USART_FLAG_TXBE) != RESET) { USART_ClearStatusFlag(usart->usartx, USART_FLAG_TXBE); @@ -256,15 +394,66 @@ void USART2_IRQHandler(void) /* leave interrupt */ rt_interrupt_leave(); } - #endif /* BSP_USING_UART2 */ +#if defined(BSP_USING_UART3) +void USART3_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + usart_isr(&(usart_config[UART3_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* BSP_USING_UART3 */ + +#if defined(BSP_USING_UART4) +void UART4_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + usart_isr(&(usart_config[UART4_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* BSP_USING_UART4 */ + +#if defined(BSP_USING_UART5) +void UART5_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + usart_isr(&(usart_config[UART5_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* BSP_USING_UART5 */ + +#if defined(BSP_USING_UART6) +void USART6_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + usart_isr(&(usart_config[UART6_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* BSP_USING_UART6 */ + static const struct rt_uart_ops apm32_usart_ops = { - .configure = _uart_configure, - .control = _uart_control, - .putc = _uart_putc, - .getc = _uart_getc, + .configure = apm32_uart_configure, + .control = apm32_uart_control, + .putc = apm32_uart_putc, + .getc = apm32_uart_getc, .dma_transmit = RT_NULL }; diff --git a/bsp/apm32/libraries/Drivers/drv_wdt.c b/bsp/apm32/libraries/Drivers/drv_wdt.c index 829ba48ca5..11e87ae727 100644 --- a/bsp/apm32/libraries/Drivers/drv_wdt.c +++ b/bsp/apm32/libraries/Drivers/drv_wdt.c @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2022-03-04 stevetong459 first version + * 2022-12-26 luobeihai add apm32F0 serie MCU support */ #include @@ -33,7 +34,7 @@ typedef struct static apm32_wdt_t wdt_config; -static rt_err_t _iwdt_init(rt_watchdog_t *wdt) +static rt_err_t apm32_iwdt_init(rt_watchdog_t *wdt) { rt_uint32_t counter = 0; @@ -54,7 +55,11 @@ static rt_err_t _iwdt_init(rt_watchdog_t *wdt) wdt_config.min_threshold, wdt_config.max_threshold); +#if defined(SOC_SERIES_APM32F0) + while (IWDT_ReadStatusFlag(IWDT_FLAG_DIVU)) +#else while (IWDT_ReadStatusFlag(IWDT_FLAG_PSCU)) +#endif { if (++counter > DRV_WDT_TIME_OUT) { @@ -62,8 +67,15 @@ static rt_err_t _iwdt_init(rt_watchdog_t *wdt) return -RT_ERROR; } } + IWDT_EnableWriteAccess(); + +#if defined(SOC_SERIES_APM32F0) + IWDT_ConfigDivider(IWDT_DIV_256); +#else IWDT_ConfigDivider(IWDT_DIVIDER_256); +#endif + IWDT_DisableWriteAccess(); return RT_EOK; @@ -76,7 +88,7 @@ static rt_err_t _iwdt_init(rt_watchdog_t *wdt) * * @return RT_EOK indicates successful , other value indicates failed. */ -static rt_err_t _iwdt_control(rt_watchdog_t *wdt, int cmd, void *arg) +static rt_err_t apm32_iwdt_control(rt_watchdog_t *wdt, int cmd, void *arg) { volatile rt_uint32_t param, counter = 0; @@ -125,15 +137,15 @@ static rt_err_t _iwdt_control(rt_watchdog_t *wdt, int cmd, void *arg) return RT_EOK; } -static struct rt_watchdog_ops _wdt_ops = +static struct rt_watchdog_ops apm32_wdt_ops = { - _iwdt_init, - _iwdt_control, + apm32_iwdt_init, + apm32_iwdt_control, }; static int rt_hw_wdt_init(void) { - wdt_config.wdt.ops = &_wdt_ops; + wdt_config.wdt.ops = &apm32_wdt_ops; /* register watchdog device */ if (rt_hw_watchdog_register(&wdt_config.wdt, "wdt", \ RT_DEVICE_FLAG_DEACTIVATE, RT_NULL) != RT_EOK) diff --git a/bsp/apm32/libraries/Kconfig b/bsp/apm32/libraries/Kconfig index 8ebcd050fd..73e938b2c0 100644 --- a/bsp/apm32/libraries/Kconfig +++ b/bsp/apm32/libraries/Kconfig @@ -1,6 +1,11 @@ config SOC_FAMILY_APM32 bool +config SOC_SERIES_APM32F0 + bool + select ARCH_ARM_CORTEX_M0 + select SOC_FAMILY_APM32 + config SOC_SERIES_APM32F1 bool select ARCH_ARM_CORTEX_M3