From 0e254652aaa12f711b8b4e2383a638fd30dfc7fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=93=E7=9B=B9=E7=9A=84=E6=B6=88=E9=98=B2=E8=BD=A6?= <1473454180@qq.com> Date: Tue, 8 Mar 2022 12:04:17 +0800 Subject: [PATCH] add:air105 bsp (#5607) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add:air105 bsp * add:去掉注释代码 * add:注释修改 * fix:格式化一遍代码格式 * add:main函数添加闪灯 * add:完善bsp * add:添加一些信息 * add:使用工作队列喂狗 * add:整理目录 * add:去掉乱码部分 * add:修改readme * add:更新readme说明 * add:去掉bootloader.bin和soc_download.exe,README.md中添加标注 * fix:去除多余文件 * add:补充license * add:支持scons --dist * add:更新soc_download.exe连接地址 --- bsp/airm2m/README.md | 20 + bsp/airm2m/air105/.config | 666 ++ bsp/airm2m/air105/Kconfig | 21 + bsp/airm2m/air105/README.md | 119 + bsp/airm2m/air105/SConscript | 14 + bsp/airm2m/air105/SConstruct | 51 + bsp/airm2m/air105/applications/SConscript | 12 + bsp/airm2m/air105/applications/main.c | 48 + bsp/airm2m/air105/board/Kconfig | 175 + bsp/airm2m/air105/board/SConscript | 35 + bsp/airm2m/air105/board/board.c | 82 + bsp/airm2m/air105/board/board.h | 33 + .../air105/board/linker_scripts/link.icf | 28 + .../air105/board/linker_scripts/link.lds | 156 + .../air105/board/linker_scripts/link.sct | 15 + .../air105/board/ports/spi_flash_init.c | 31 + bsp/airm2m/air105/board/ports/w5500_device.c | 17 + bsp/airm2m/air105/board/wdt_feed.c | 53 + bsp/airm2m/air105/figures/board.png | Bin 0 -> 826999 bytes .../air105/libraries/HAL_Driver/Inc/air105.h | 2087 +++++ .../libraries/HAL_Driver/Inc/air105_adc.h | 147 + .../libraries/HAL_Driver/Inc/air105_bpk.h | 66 + .../libraries/HAL_Driver/Inc/air105_cache.h | 114 + .../libraries/HAL_Driver/Inc/air105_conf.h | 51 + .../libraries/HAL_Driver/Inc/air105_crc.h | 74 + .../libraries/HAL_Driver/Inc/air105_dac.h | 98 + .../libraries/HAL_Driver/Inc/air105_dcmi.h | 360 + .../libraries/HAL_Driver/Inc/air105_dma.h | 219 + .../libraries/HAL_Driver/Inc/air105_exti.h | 119 + .../libraries/HAL_Driver/Inc/air105_gpio.h | 231 + .../libraries/HAL_Driver/Inc/air105_hspim.h | 321 + .../libraries/HAL_Driver/Inc/air105_i2c.h | 357 + .../libraries/HAL_Driver/Inc/air105_it.h | 52 + .../libraries/HAL_Driver/Inc/air105_kcu.h | 72 + .../libraries/HAL_Driver/Inc/air105_lcdi.h | 140 + .../libraries/HAL_Driver/Inc/air105_otp.h | 80 + .../libraries/HAL_Driver/Inc/air105_qspi.h | 155 + .../libraries/HAL_Driver/Inc/air105_rtc.h | 67 + .../libraries/HAL_Driver/Inc/air105_sci.h | 54 + .../libraries/HAL_Driver/Inc/air105_sensor.h | 229 + .../libraries/HAL_Driver/Inc/air105_spi.h | 497 ++ .../libraries/HAL_Driver/Inc/air105_ssc.h | 159 + .../libraries/HAL_Driver/Inc/air105_sysctrl.h | 138 + .../libraries/HAL_Driver/Inc/air105_timer.h | 96 + .../libraries/HAL_Driver/Inc/air105_trng.h | 68 + .../libraries/HAL_Driver/Inc/air105_uart.h | 299 + .../libraries/HAL_Driver/Inc/air105_wdt.h | 53 + .../air105/libraries/HAL_Driver/Inc/app_inc.h | 36 + .../HAL_Driver/Inc/arm_common_tables.h | 136 + .../HAL_Driver/Inc/arm_const_structs.h | 79 + .../libraries/HAL_Driver/Inc/arm_math.h | 7154 +++++++++++++++++ .../air105/libraries/HAL_Driver/Inc/bl_inc.h | 44 + .../libraries/HAL_Driver/Inc/bsp_common.h | 399 + .../libraries/HAL_Driver/Inc/cmsis_armcc.h | 865 ++ .../libraries/HAL_Driver/Inc/cmsis_armcc_V6.h | 1800 +++++ .../libraries/HAL_Driver/Inc/cmsis_armclang.h | 1869 +++++ .../libraries/HAL_Driver/Inc/cmsis_compiler.h | 266 + .../libraries/HAL_Driver/Inc/cmsis_gcc.h | 2085 +++++ .../libraries/HAL_Driver/Inc/cmsis_iccarm.h | 935 +++ .../libraries/HAL_Driver/Inc/cmsis_version.h | 39 + .../libraries/HAL_Driver/Inc/core_adc.h | 46 + .../libraries/HAL_Driver/Inc/core_armv8mbl.h | 1918 +++++ .../libraries/HAL_Driver/Inc/core_armv8mml.h | 2927 +++++++ .../libraries/HAL_Driver/Inc/core_cm4.h | 2129 +++++ .../libraries/HAL_Driver/Inc/core_cmFunc.h | 87 + .../libraries/HAL_Driver/Inc/core_cmInstr.h | 87 + .../libraries/HAL_Driver/Inc/core_cmSimd.h | 96 + .../libraries/HAL_Driver/Inc/core_dac.h | 27 + .../libraries/HAL_Driver/Inc/core_dcmi.h | 58 + .../libraries/HAL_Driver/Inc/core_debug.h | 26 + .../libraries/HAL_Driver/Inc/core_dma.h | 71 + .../libraries/HAL_Driver/Inc/core_flash.h | 26 + .../libraries/HAL_Driver/Inc/core_gpio.h | 105 + .../libraries/HAL_Driver/Inc/core_hwtimer.h | 120 + .../libraries/HAL_Driver/Inc/core_i2c.h | 87 + .../libraries/HAL_Driver/Inc/core_irq.h | 43 + .../libraries/HAL_Driver/Inc/core_keyboard.h | 42 + .../libraries/HAL_Driver/Inc/core_otp.h | 47 + .../libraries/HAL_Driver/Inc/core_rng.h | 31 + .../libraries/HAL_Driver/Inc/core_rtc.h | 35 + .../libraries/HAL_Driver/Inc/core_sc000.h | 1022 +++ .../libraries/HAL_Driver/Inc/core_sc300.h | 1915 +++++ .../libraries/HAL_Driver/Inc/core_service.h | 70 + .../libraries/HAL_Driver/Inc/core_spi.h | 42 + .../libraries/HAL_Driver/Inc/core_task.h | 40 + .../libraries/HAL_Driver/Inc/core_tick.h | 30 + .../libraries/HAL_Driver/Inc/core_timer.h | 48 + .../libraries/HAL_Driver/Inc/core_uart.h | 105 + .../HAL_Driver/Inc/core_usb_ll_driver.h | 50 + .../libraries/HAL_Driver/Inc/core_wdt.h | 28 + .../libraries/HAL_Driver/Inc/cs_types.h | 22 + .../libraries/HAL_Driver/Inc/global_config.h | 46 + .../air105/libraries/HAL_Driver/Inc/io_map.h | 58 + .../air105/libraries/HAL_Driver/Inc/misc.h | 116 + .../libraries/HAL_Driver/Inc/mpu_armv7.h | 270 + .../libraries/HAL_Driver/Inc/mpu_armv8.h | 333 + .../HAL_Driver/Inc/platform_define.h | 317 + .../HAL_Driver/Inc/pulse_encoder_config.h | 68 + .../libraries/HAL_Driver/Inc/resource_map.h | 60 + .../libraries/HAL_Driver/Inc/system_air105.h | 63 + .../libraries/HAL_Driver/Inc/tz_context.h | 70 + .../air105/libraries/HAL_Driver/Inc/user.h | 28 + .../libraries/HAL_Driver/Inc/w25q80bv.h | 159 + .../libraries/HAL_Driver/Src/bsp_common.c | 1261 +++ .../libraries/HAL_Driver/Src/core_adc.c | 232 + .../libraries/HAL_Driver/Src/core_dac.c | 113 + .../libraries/HAL_Driver/Src/core_dcmi.c | 198 + .../libraries/HAL_Driver/Src/core_dma.c | 389 + .../libraries/HAL_Driver/Src/core_flash.c | 139 + .../libraries/HAL_Driver/Src/core_gpio.c | 260 + .../libraries/HAL_Driver/Src/core_hwtimer.c | 465 ++ .../libraries/HAL_Driver/Src/core_i2c.c | 436 + .../libraries/HAL_Driver/Src/core_irq.c | 91 + .../libraries/HAL_Driver/Src/core_keyboard.c | 94 + .../libraries/HAL_Driver/Src/core_otp.c | 67 + .../libraries/HAL_Driver/Src/core_rng.c | 52 + .../libraries/HAL_Driver/Src/core_rtc.c | 179 + .../libraries/HAL_Driver/Src/core_spi.c | 1150 +++ .../libraries/HAL_Driver/Src/core_tick.c | 95 + .../libraries/HAL_Driver/Src/core_uart.c | 601 ++ .../HAL_Driver/Src/core_usb_ll_driver.c | 1929 +++++ .../libraries/HAL_Driver/Src/core_wdt.c | 45 + .../HAL_Driver/Startup/gcc/startup_gcc.s | 271 + bsp/airm2m/air105/libraries/SConscript | 29 + .../rt_drivers/config/air105/spi_config.h | 81 + .../rt_drivers/config/air105/uart_config.h | 71 + .../libraries/rt_drivers/config/drv_config.h | 30 + .../air105/libraries/rt_drivers/drv_common.c | 107 + .../air105/libraries/rt_drivers/drv_common.h | 36 + .../air105/libraries/rt_drivers/drv_gpio.c | 213 + .../air105/libraries/rt_drivers/drv_gpio.h | 29 + .../air105/libraries/rt_drivers/drv_i2c.c | 125 + .../air105/libraries/rt_drivers/drv_log.h | 24 + .../air105/libraries/rt_drivers/drv_rtc.c | 87 + .../air105/libraries/rt_drivers/drv_spi.c | 181 + .../air105/libraries/rt_drivers/drv_spi.h | 38 + .../libraries/rt_drivers/drv_usart_v2.c | 316 + .../libraries/rt_drivers/drv_usart_v2.h | 36 + .../air105/libraries/rt_drivers/drv_wdt.c | 68 + bsp/airm2m/air105/makesoc.py | 29 + bsp/airm2m/air105/pack/info.json | 61 + bsp/airm2m/air105/rtconfig.h | 204 + bsp/airm2m/air105/rtconfig.py | 182 + 143 files changed, 46668 insertions(+) create mode 100644 bsp/airm2m/README.md create mode 100644 bsp/airm2m/air105/.config create mode 100644 bsp/airm2m/air105/Kconfig create mode 100644 bsp/airm2m/air105/README.md create mode 100644 bsp/airm2m/air105/SConscript create mode 100644 bsp/airm2m/air105/SConstruct create mode 100644 bsp/airm2m/air105/applications/SConscript create mode 100644 bsp/airm2m/air105/applications/main.c create mode 100644 bsp/airm2m/air105/board/Kconfig create mode 100644 bsp/airm2m/air105/board/SConscript create mode 100644 bsp/airm2m/air105/board/board.c create mode 100644 bsp/airm2m/air105/board/board.h create mode 100644 bsp/airm2m/air105/board/linker_scripts/link.icf create mode 100644 bsp/airm2m/air105/board/linker_scripts/link.lds create mode 100644 bsp/airm2m/air105/board/linker_scripts/link.sct create mode 100644 bsp/airm2m/air105/board/ports/spi_flash_init.c create mode 100644 bsp/airm2m/air105/board/ports/w5500_device.c create mode 100644 bsp/airm2m/air105/board/wdt_feed.c create mode 100644 bsp/airm2m/air105/figures/board.png create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_adc.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_bpk.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_cache.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_conf.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_crc.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_dac.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_dcmi.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_dma.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_exti.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_gpio.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_hspim.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_i2c.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_it.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_kcu.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_lcdi.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_otp.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_qspi.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_rtc.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_sci.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_sensor.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_spi.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_ssc.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_sysctrl.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_timer.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_trng.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_uart.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_wdt.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/app_inc.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/arm_common_tables.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/arm_const_structs.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/arm_math.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/bl_inc.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/bsp_common.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_armcc.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_armcc_V6.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_armclang.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_compiler.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_gcc.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_iccarm.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_version.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_adc.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_armv8mbl.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_armv8mml.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_cm4.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_cmFunc.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_cmInstr.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_cmSimd.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_dac.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_dcmi.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_debug.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_dma.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_flash.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_gpio.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_hwtimer.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_i2c.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_irq.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_keyboard.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_otp.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_rng.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_rtc.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_sc000.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_sc300.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_service.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_spi.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_task.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_tick.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_timer.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_uart.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_usb_ll_driver.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_wdt.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/cs_types.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/global_config.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/io_map.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/misc.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/mpu_armv7.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/mpu_armv8.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/platform_define.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/pulse_encoder_config.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/resource_map.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/system_air105.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/tz_context.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/user.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Inc/w25q80bv.h create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/bsp_common.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_adc.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_dac.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_dcmi.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_dma.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_flash.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_gpio.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_hwtimer.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_i2c.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_irq.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_keyboard.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_otp.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_rng.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_rtc.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_spi.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_tick.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_uart.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_usb_ll_driver.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Src/core_wdt.c create mode 100644 bsp/airm2m/air105/libraries/HAL_Driver/Startup/gcc/startup_gcc.s create mode 100644 bsp/airm2m/air105/libraries/SConscript create mode 100644 bsp/airm2m/air105/libraries/rt_drivers/config/air105/spi_config.h create mode 100644 bsp/airm2m/air105/libraries/rt_drivers/config/air105/uart_config.h create mode 100644 bsp/airm2m/air105/libraries/rt_drivers/config/drv_config.h create mode 100644 bsp/airm2m/air105/libraries/rt_drivers/drv_common.c create mode 100644 bsp/airm2m/air105/libraries/rt_drivers/drv_common.h create mode 100644 bsp/airm2m/air105/libraries/rt_drivers/drv_gpio.c create mode 100644 bsp/airm2m/air105/libraries/rt_drivers/drv_gpio.h create mode 100644 bsp/airm2m/air105/libraries/rt_drivers/drv_i2c.c create mode 100644 bsp/airm2m/air105/libraries/rt_drivers/drv_log.h create mode 100644 bsp/airm2m/air105/libraries/rt_drivers/drv_rtc.c create mode 100644 bsp/airm2m/air105/libraries/rt_drivers/drv_spi.c create mode 100644 bsp/airm2m/air105/libraries/rt_drivers/drv_spi.h create mode 100644 bsp/airm2m/air105/libraries/rt_drivers/drv_usart_v2.c create mode 100644 bsp/airm2m/air105/libraries/rt_drivers/drv_usart_v2.h create mode 100644 bsp/airm2m/air105/libraries/rt_drivers/drv_wdt.c create mode 100644 bsp/airm2m/air105/makesoc.py create mode 100644 bsp/airm2m/air105/pack/info.json create mode 100644 bsp/airm2m/air105/rtconfig.h create mode 100644 bsp/airm2m/air105/rtconfig.py diff --git a/bsp/airm2m/README.md b/bsp/airm2m/README.md new file mode 100644 index 0000000000..9ae2b24cf4 --- /dev/null +++ b/bsp/airm2m/README.md @@ -0,0 +1,20 @@ +### 本文档为 合宙 开发团队为 airm2m bsp 提供的资料、介绍说明。 + +**合宙官网:https://openluat.com** + +**wiki教程文档:https://wiki.luatos.com/** + +**luatos仓库:https://gitee.com/openLuat/LuatOS** + +**Luatos RTthread 软件包仓库:https://github.com/openLuat/luatos-soc-rtt** + +**API手册:https://wiki.luatos.com/api/index.html** + +**社区:https://doc.openluat.com/** + +**air105仓库:https://gitee.com/openLuat/luatos-soc-air105** + +**购买地址:https://luat.taobao.com/index.htm?spm=a1z10.5-c-s.w5002-24045920810.2.457f5bcdtkiPyX** + +**如有问题提问请详细说明现象,提供日志以及最新复现工程,在https://gitee.com/openLuat/LuatOS/issues报问题** + diff --git a/bsp/airm2m/air105/.config b/bsp/airm2m/air105/.config new file mode 100644 index 0000000000..932a9f5d32 --- /dev/null +++ b/bsp/airm2m/air105/.config @@ -0,0 +1,666 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=1000 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_HOOK_USING_FUNC_PTR=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=256 +# CONFIG_RT_USING_TIMER_SOFT is not set + +# +# kservice optimization +# +# CONFIG_RT_KSERVICE_USING_STDLIB is not set +# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set +# CONFIG_RT_USING_TINY_FFS is not set +# CONFIG_RT_PRINTF_LONGLONG is not set +CONFIG_RT_DEBUG=y +# CONFIG_RT_DEBUG_COLOR is not set +# 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_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=256 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" +CONFIG_RT_VER_NUM=0x40100 +CONFIG_ARCH_ARM=y +CONFIG_RT_USING_CPU_FFS=y +CONFIG_ARCH_ARM_CORTEX_M=y +CONFIG_ARCH_ARM_CORTEX_M4=y +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 +# CONFIG_RT_USING_LEGACY is not set + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_RT_USING_MSH=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 + +# +# Device virtual file system +# +# CONFIG_RT_USING_DFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_USING_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 +CONFIG_RT_USING_SERIAL=y +# CONFIG_RT_USING_SERIAL_V1 is not set +CONFIG_RT_USING_SERIAL_V2=y +CONFIG_RT_SERIAL_USING_DMA=y +# 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_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +CONFIG_RT_USING_WDT=y +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB is not set +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# POSIX layer and C standard library +# +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 +# + +# +# 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 + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS 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_LWP is not set + +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# 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_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_LIBMODBUS is not set +# CONFIG_PKG_USING_FREEMODBUS is not set +# CONFIG_PKG_USING_LJSON is not set +# CONFIG_PKG_USING_EZXML 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_NIMBLE 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_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN 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_RAPIDJSON is not set +# CONFIG_PKG_USING_BSAL is not set +# CONFIG_PKG_USING_AGILE_MODBUS is not set +# CONFIG_PKG_USING_AGILE_FTP is not set +# CONFIG_PKG_USING_EMBEDDEDPROTO is not set +# CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_LORA_PKT_FWD is not set +# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set +# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set +# CONFIG_PKG_USING_HM is not set +# CONFIG_PKG_USING_SMALL_MODBUS is not set +# CONFIG_PKG_USING_NET_SERVER is not set + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_LIBSODIUM 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 +# +# 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 + +# +# 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 + +# +# 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 + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_SEGGER_RTT is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ULOG_FILE is not set +# CONFIG_PKG_USING_LOGMGR is not set +# CONFIG_PKG_USING_ADBD is not set +# CONFIG_PKG_USING_COREMARK is not set +# CONFIG_PKG_USING_DHRYSTONE is not set +# CONFIG_PKG_USING_MEMORYPERF is not set +# CONFIG_PKG_USING_NR_MICRO_SHELL is not set +# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set +# CONFIG_PKG_USING_LUNAR_CALENDAR is not set +# CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set +# CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_REGEX is not set +# CONFIG_PKG_USING_MEM_SANDBOX is not set +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set +# CONFIG_PKG_USING_FDT is not set + +# +# 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 + +# +# POSIX extension functions +# +# CONFIG_PKG_USING_POSIX_GETLINE is not set +# CONFIG_PKG_USING_POSIX_WCWIDTH is not set +# CONFIG_PKG_USING_POSIX_ITOA is not set +# CONFIG_PKG_USING_POSIX_STRINGS 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_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_RT_USING_ARDUINO is not set +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_PERSIMMON 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_FAL 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_USB_STACK is not set + +# +# peripheral libraries and drivers +# +# CONFIG_PKG_USING_SENSORS_DRIVERS is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_BUTTON is not set +# CONFIG_PKG_USING_PCF8574 is not set +# CONFIG_PKG_USING_SX12XX is not set +# CONFIG_PKG_USING_SIGNAL_LED is not set +# CONFIG_PKG_USING_LEDBLINK is not set +# CONFIG_PKG_USING_LITTLED is not set +# CONFIG_PKG_USING_LKDGUI is not set +# CONFIG_PKG_USING_NRF5X_SDK is not set +# CONFIG_PKG_USING_NRFX is not set +# CONFIG_PKG_USING_WM_LIBRARIES is not set +# CONFIG_PKG_USING_KENDRYTE_SDK is not set +# CONFIG_PKG_USING_INFRARED is not set +# CONFIG_PKG_USING_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set +# CONFIG_PKG_USING_AT24CXX is not set +# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_AD7746 is not set +# CONFIG_PKG_USING_PCA9685 is not set +# CONFIG_PKG_USING_I2C_TOOLS is not set +# CONFIG_PKG_USING_NRF24L01 is not set +# CONFIG_PKG_USING_TOUCH_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# CONFIG_PKG_USING_AS608 is not set +# CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set +# CONFIG_PKG_USING_EMBARC_BSP is not set +# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set +# CONFIG_PKG_USING_MULTI_RTIMER is not set +# CONFIG_PKG_USING_MAX7219 is not set +# CONFIG_PKG_USING_BEEP is not set +# CONFIG_PKG_USING_EASYBLINK is not set +# CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set +# CONFIG_PKG_USING_LY68L6400 is not set +# CONFIG_PKG_USING_DM9051 is not set +# CONFIG_PKG_USING_SSD1306 is not set +# CONFIG_PKG_USING_QKEY is not set +# CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set +# CONFIG_PKG_USING_NES is not set +# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set +# CONFIG_PKG_USING_VDEVICE is not set +# CONFIG_PKG_USING_SGM706 is not set +# CONFIG_PKG_USING_STM32WB55_SDK is not set +# CONFIG_PKG_USING_RDA58XX is not set +# CONFIG_PKG_USING_LIBNFC is not set +# CONFIG_PKG_USING_MFOC is not set +# CONFIG_PKG_USING_TMC51XX is not set +# CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set +# CONFIG_PKG_USING_MCP23008 is not set +# CONFIG_PKG_USING_BLUETRUM_SDK is not set +# CONFIG_PKG_USING_MISAKA_AT24CXX is not set +# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set +# CONFIG_PKG_USING_BL_MCU_SDK is not set +# CONFIG_PKG_USING_SOFT_SERIAL is not set +# CONFIG_PKG_USING_MB85RS16 is not set +# CONFIG_PKG_USING_CW2015 is not set + +# +# AI packages +# +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_QUEST is not set +# CONFIG_PKG_USING_NAXOS is not set + +# +# miscellaneous packages +# + +# +# 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_DSTR is not set +# CONFIG_PKG_USING_TINYFRAME is not set +# CONFIG_PKG_USING_KENDRYTE_DEMO is not set +# CONFIG_PKG_USING_DIGITALCTRL is not set +# CONFIG_PKG_USING_UPACKER is not set +# CONFIG_PKG_USING_UPARAM is not set +# CONFIG_PKG_USING_HELLO is not set +# CONFIG_PKG_USING_VI is not set +# CONFIG_PKG_USING_KI is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_DESIGN_PATTERN is not set +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set + +# +# Hardware Drivers Config +# +CONFIG_SOC_AIR105=y + +# +# Onboard Peripheral Drivers +# +CONFIG_BSP_USING_SHELL_TO_USART=y +# CONFIG_BSP_USING_SPI_FLASH is not set +# CONFIG_BSP_USING_ETH is not set + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART0=y +CONFIG_BSP_UART0_RX_BUFSIZE=256 +CONFIG_BSP_UART0_TX_BUFSIZE=0 +# CONFIG_BSP_USING_UART1 is not set +# CONFIG_BSP_USING_UART2 is not set +# CONFIG_BSP_USING_UART3 is not set +# CONFIG_BSP_USING_I2C is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_ONCHIP_RTC is not set +CONFIG_BSP_USING_WDT=y diff --git a/bsp/airm2m/air105/Kconfig b/bsp/airm2m/air105/Kconfig new file mode 100644 index 0000000000..bb3c3adb17 --- /dev/null +++ b/bsp/airm2m/air105/Kconfig @@ -0,0 +1,21 @@ +mainmenu "RT-Thread Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../../.." + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" +source "board/Kconfig" + diff --git a/bsp/airm2m/air105/README.md b/bsp/airm2m/air105/README.md new file mode 100644 index 0000000000..332bcece76 --- /dev/null +++ b/bsp/airm2m/air105/README.md @@ -0,0 +1,119 @@ +# AIR105开发板 BSP 说明 + +## 简介 + +本文档为 合宙 开发团队为 AIR105开发板提供的 BSP (板级支持包) 说明。 + +主要内容如下: + +- 开发板资源介绍 +- BSP 快速上手 +- 进阶使用方法 + +通过阅读快速上手章节开发者可以快速地上手该 BSP,将 RT-Thread 运行在开发板上。在进阶使用指南章节,将会介绍更多高级功能,帮助开发者利用 RT-Thread 驱动更多板载资源。 + +## 开发板介绍 + +AIR105 是合宙推出的一款基于 ARM Cortex-M4 内核的10mm x 10mm 大小的MCU,最高主频为 204Mhz,不仅提供UART/GPIO/I2C/ADC/SPI等基础外设,更提供DAC/USB/DCMI/HSPI等高级外设接口,内置充电功能,支持5V/3.3V供电,同时自带5v转3.3V的LDO,4M字节Flash,640K字节RAM。 + +开发板外观如下图所示: + +![board](figures/board.png) + +该开发板常用 **板载资源** 如下: + +- MCU:Air105,主频 204MHz,4M FLASH ,640KB RAM +- 调试下载接口,UART0 To Type-c USB 接口 + +开发板更多详细信息请参考合宙Air105 [合宙Air105开发板介绍](https://wiki.luatos.com/chips/air105/board.html)。 + +## 外设支持 + +本 BSP 目前对外设的支持情况如下: + +| 片上外设 | **支持情况** | +| -------- | ------------ | +| GPIO | 支持 | +| UART | 支持 | +| SPI | 支持 | +| I2C | 支持 | +| RTC | 支持 | +| WDT | 支持 | + + +## 使用说明 + +使用说明分为如下两个章节: + +- 快速上手 + + 本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。 + +- 进阶使用 + + 本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。 + + +### 快速上手 + +本 BSP 为开发者提供 GCC 工程,支持 GCC 开发环境。下面介绍如何将系统运行起来。 + +#### 硬件连接 + +使用数据线连接开发板到 PC。 + +#### 编译下载 + +1. 在 bsp 下打开 env 工具。 +2. 输入`menuconfig`。 +3. 输入`scons`进行编译。 + +编译完成会自动打包bl : bootloader.bin和下载工具:soc_download.exe在bsp目录下生成rtthread_air105.soc,使用[Luatools](http://cdndownload.openluat.com/Luat_tool_src/last_release/Luatools_v2.exe)下载进开发板即可。 + +#### 运行结果 + +下载程序成功之后,系统会自动运行。 + +连接开发板对应串口到 PC , 在终端工具里打开相应的串口(1500000-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息: + + +```bash + \ | / +- RT - Thread Operating System + / | \ 4.1.0 build Feb 22 2022 09:53:22 + 2006 - 2022 Copyright by RT-Thread team +msh > +``` +### 进阶使用 + +此 BSP 默认只开启了 GPIO 和 串口0 的功能,如果需使用更多高级功能,需要利用 ENV 工具对BSP 进行配置,步骤如下: + +1. 在 bsp 下打开 env 工具。 + +2. 输入`menuconfig`命令配置工程,配置好之后保存退出。 + +3. 输入`pkgs --update`命令更新软件包。 + +4. 输入`scons`进行编译。 + + + +**Luatos同样也上线了RTthread 软件包,仓库:https://github.com/openLuat/luatos-soc-rtt** + +## 注意事项 + +**bootloader.bin和soc_download.exe如不存在会自动下载,请保持网络通畅** + +**烧录前请设置波特率为1500000** + +**air105必须启用看门狗,默认启用** + +**更多资料参考[WIKI](https://wiki.luatos.com/)** + +## 联系人信息 + +维护人: + +- [**合宙Luat**](https://gitee.com/openLuat) +- [**淘宝地址**](https://item.taobao.com/item.htm?spm=a1z10.5-c-s.w4002-24045920841.15.29395bcdUExSHR&id=666216389131) + diff --git a/bsp/airm2m/air105/SConscript b/bsp/airm2m/air105/SConscript new file mode 100644 index 0000000000..c7ef7659ec --- /dev/null +++ b/bsp/airm2m/air105/SConscript @@ -0,0 +1,14 @@ +# for module compiling +import os +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/airm2m/air105/SConstruct b/bsp/airm2m/air105/SConstruct new file mode 100644 index 0000000000..70225dbaa6 --- /dev/null +++ b/bsp/airm2m/air105/SConstruct @@ -0,0 +1,51 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, 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 == 'iar': + env.Replace(CCCOM = ['$CC $CFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map') + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/airm2m/air105/applications/SConscript b/bsp/airm2m/air105/applications/SConscript new file mode 100644 index 0000000000..6f66f7ab73 --- /dev/null +++ b/bsp/airm2m/air105/applications/SConscript @@ -0,0 +1,12 @@ +import rtconfig +from building import * + +cwd = GetCurrentDir() +CPPPATH = [cwd, str(Dir('#'))] +src = Split(""" +main.c +""") + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/airm2m/air105/applications/main.c b/bsp/airm2m/air105/applications/main.c new file mode 100644 index 0000000000..4c109724fd --- /dev/null +++ b/bsp/airm2m/air105/applications/main.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + +#include +#include +#include +#include "drv_gpio.h" + +/* defined the LED2 pin: PD14 */ +#define LED0_PIN GPIOD_14 +/* defined the LED3 pin: PD15 */ +#define LED1_PIN GPIOD_15 +/* defined the LED4 pin: PC3 */ +#define LED2_PIN GPIOC_03 + +int main(void) +{ + uint32_t Speed = 200; + /* set LED2 pin mode to output */ + rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); + /* set LED3 pin mode to output */ + rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT); + /* set LED4 pin mode to output */ + rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT); + + while (1) + { + rt_pin_write(LED0_PIN, PIN_LOW); + rt_thread_mdelay(Speed); + rt_pin_write(LED1_PIN, PIN_LOW); + rt_thread_mdelay(Speed); + rt_pin_write(LED2_PIN, PIN_LOW); + rt_thread_mdelay(Speed); + rt_pin_write(LED0_PIN, PIN_HIGH); + rt_thread_mdelay(Speed); + rt_pin_write(LED1_PIN, PIN_HIGH); + rt_thread_mdelay(Speed); + rt_pin_write(LED2_PIN, PIN_HIGH); + rt_thread_mdelay(Speed); + } +} diff --git a/bsp/airm2m/air105/board/Kconfig b/bsp/airm2m/air105/board/Kconfig new file mode 100644 index 0000000000..24a8415127 --- /dev/null +++ b/bsp/airm2m/air105/board/Kconfig @@ -0,0 +1,175 @@ +menu "Hardware Drivers Config" + +config SOC_AIR105 + bool + select ARCH_ARM_CORTEX_M4 + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + select BSP_USING_WDT + default y + +menu "Onboard Peripheral Drivers" + + config BSP_USING_SHELL_TO_USART + bool "Enable SHELL TO USART (uart0)" + select BSP_USING_UART + select BSP_USING_UART0 + default y + + config BSP_USING_SPI_FLASH + bool "Enable SPI FLASH (W25Q64 spi1)" + select BSP_USING_SPI + select RT_USING_SFUD + select RT_SFUD_USING_SFDP + default n + + config BSP_USING_ETH + bool "Enable Ethernet Driver" + select PKG_USING_WIZNET + select BSP_USING_SPI + default n + if BSP_USING_ETH + config EXTERNAL_PHY_ADDRESS + hex + default 0x00 + config WIZ_SPI_BUS + string "WIZ SPI bus name" + default "spi2" + config WIZ_SPI_CS + int "WIZ SPI bus cs pin" + default 19 + endif + +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 + menuconfig BSP_USING_UART0 + bool "Enable UART0 (Debugger)" + default n + if BSP_USING_UART0 + config BSP_UART0_RX_BUFSIZE + int "Set UART0 RX buffer size" + range 64 65535 + depends on RT_USING_SERIAL_V2 + default 256 + + config BSP_UART0_TX_BUFSIZE + int "Set UART0 TX buffer size" + range 0 65535 + depends on RT_USING_SERIAL_V2 + default 0 + endif + + menuconfig BSP_USING_UART1 + bool "Enable UART1" + default n + if BSP_USING_UART1 + config BSP_UART1_RX_BUFSIZE + int "Set UART1 RX buffer size" + range 64 65535 + depends on RT_USING_SERIAL_V2 + default 256 + + config BSP_UART1_TX_BUFSIZE + int "Set UART1 TX buffer size" + range 0 65535 + depends on RT_USING_SERIAL_V2 + default 0 + endif + + menuconfig BSP_USING_UART2 + bool "Enable UART2" + default n + if BSP_USING_UART2 + config BSP_UART2_RX_BUFSIZE + int "Set UART2 RX buffer size" + range 64 65535 + depends on RT_USING_SERIAL_V2 + default 256 + + config BSP_UART2_TX_BUFSIZE + int "Set UART2 TX buffer size" + range 0 65535 + depends on RT_USING_SERIAL_V2 + default 256 + endif + + menuconfig BSP_USING_UART3 + bool "Enable UART3" + default n + if BSP_USING_UART3 + config BSP_UART3_RX_BUFSIZE + int "Set UART3 RX buffer size" + range 64 65535 + depends on RT_USING_SERIAL_V2 + default 256 + + config BSP_UART3_TX_BUFSIZE + int "Set UART3 TX buffer size" + range 0 65535 + depends on RT_USING_SERIAL_V2 + default 256 + endif + endif + + config BSP_USING_I2C + bool "Enable HW I2C" + select RT_USING_I2C + default n + if BSP_USING_I2C + config I2C_BUS_NAME + string "HW I2C bus name" + default "i2c" + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI BUS" + default n + select RT_USING_SPI + if BSP_USING_SPI + config BSP_USING_HSPI0 + bool "Enable HSPI0 BUS" + default n + + config BSP_USING_SPI0 + bool "Enable SPI0 BUS" + default n + + config BSP_USING_SPI1 + bool "Enable SPI1 BUS" + default n + + config BSP_USING_SPI2 + bool "Enable SPI2 BUS" + default n + + config BSP_USING_SPI0S + bool "Enable SPI0S BUS" + default n + endif + + config BSP_USING_ONCHIP_RTC + bool "Enable HW onchip rtc" + select RT_USING_ONCHIP_RTC + default n + + config BSP_USING_WDT + bool "Enable Watchdog Timer" + select RT_USING_WDT + select RT_USING_DEVICE_IPC + select RT_USING_SYSTEM_WORKQUEUE + default n + +endmenu + +endmenu diff --git a/bsp/airm2m/air105/board/SConscript b/bsp/airm2m/air105/board/SConscript new file mode 100644 index 0000000000..e47f1b8b09 --- /dev/null +++ b/bsp/airm2m/air105/board/SConscript @@ -0,0 +1,35 @@ +import os +import rtconfig +from building import * + +Import('SDK_LIB') + +cwd = GetCurrentDir() +CPPDEFINES = ['__USE_XTL__'] +# add general drivers +src = Split(''' +board.c +''') + +if GetDepend(['BSP_USING_ETH']): + src += Glob('ports/w5500_device.c') + +if GetDepend(['BSP_USING_SPI_FLASH']): + src += Glob('ports/spi_flash_init.c') + +if GetDepend(['BSP_USING_WDT']): + src += Glob('wdt_feed.c') + +path = [cwd] + +startup_path_prefix = SDK_LIB + +if rtconfig.CROSS_TOOL == 'gcc': + src += [startup_path_prefix + '/HAL_Driver/Startup/gcc/startup_gcc.s'] +elif rtconfig.CROSS_TOOL == 'keil': + src += [startup_path_prefix + '/HAL_Driver/Startup/arm/startup_gcc.s'] +elif rtconfig.CROSS_TOOL == 'iar': + src += [startup_path_prefix + '/HAL_Driver/Startup/iar/startup_gcc.s'] + +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) +Return('group') diff --git a/bsp/airm2m/air105/board/board.c b/bsp/airm2m/air105/board/board.c new file mode 100644 index 0000000000..4d6a04b2ad --- /dev/null +++ b/bsp/airm2m/air105/board/board.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + +#include "board.h" +uint32_t SystemCoreClock; +extern const uint32_t __isr_start_address; + + +const uint32_t __attribute__((section (".app_info"))) + g_CAppInfo[256] = +{ + __APP_START_MAGIC__, + sizeof(g_CAppInfo), + 0, + 0, +}; + +void SystemInit(void) +{ +#ifdef __USE_XTL__ + SYSCTRL->FREQ_SEL = 0x20000000 | SYSCTRL_FREQ_SEL_HCLK_DIV_1_2 | (1 << 13) | SYSCTRL_FREQ_SEL_CLOCK_SOURCE_EXT | SYSCTRL_FREQ_SEL_XTAL_192Mhz; +#else + SYSCTRL->FREQ_SEL = 0x20000000 | SYSCTRL_FREQ_SEL_HCLK_DIV_1_2 | (1 << 13) | SYSCTRL_FREQ_SEL_CLOCK_SOURCE_INC | SYSCTRL_FREQ_SEL_XTAL_192Mhz; +#endif + SCB->VTOR = (uint32_t)(&__isr_start_address); + SYSCTRL->CG_CTRL1 = SYSCTRL_APBPeriph_ALL; + SYSCTRL->SOFT_RST1 = SYSCTRL_APBPeriph_ALL; + SYSCTRL->PHER_CTRL &= ~(1 << 20); + SYSCTRL->SOFT_RST2 &= ~SYSCTRL_USB_RESET; + SYSCTRL->LOCK_R |= SYSCTRL_USB_RESET; + __enable_irq(); +} + +void SystemCoreClockUpdate (void) /* Get Core Clock Frequency */ +{ + SystemCoreClock = HSE_VALUE * (((SYSCTRL->FREQ_SEL & SYSCTRL_FREQ_SEL_XTAL_Mask) >> SYSCTRL_FREQ_SEL_XTAL_Pos) + 1); +} + +void rt_hw_board_init(void) +{ + GPIO_Config(GPIOC_03, 0, 0); + GPIO_Config(GPIOD_14, 0, 0); + GPIO_Config(GPIOD_15, 0, 0); + __NVIC_SetPriorityGrouping(7 - __NVIC_PRIO_BITS); + SystemCoreClockUpdate(); +#ifdef RT_USING_HEAP + rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); +#endif + rt_hw_systick_init(); + DMA_GlobalInit(); + Uart_GlobalInit(); + DMA_TakeStream(DMA1_STREAM_1);//for qspi + CoreTick_Init(); +#ifdef RT_USING_PIN + rt_hw_pin_init(); +#endif + + /* USART driver initialization is open by default */ +#ifdef RT_USING_SERIAL + rt_hw_usart_init(); +#endif + + /* Set the shell console output device */ +#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE) + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + + /* Board underlying hardware initialization */ +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +} + + diff --git a/bsp/airm2m/air105/board/board.h b/bsp/airm2m/air105/board/board.h new file mode 100644 index 0000000000..f5723caba2 --- /dev/null +++ b/bsp/airm2m/air105/board/board.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "app_inc.h" +#include +#include "rtconfig.h" + +#ifdef __CC_ARM +extern int Image$$RW_IRAM1$$ZI$$Limit; +#define HEAP_BEGIN ((void *)&Image$$RW_IRAM1$$ZI$$Limit) +#elif __ICCARM__ +#pragma section="HEAP" +#define HEAP_BEGIN (__segment_end("HEAP")) +#else +extern int __bss_end; +#define HEAP_BEGIN ((void *)&__bss_end) +#endif +#define HEAP_END (void*)(0x20000000 + 0xA0000) + +void rt_hw_board_init(void); +int rt_vbus_do_init(void); + +#endif diff --git a/bsp/airm2m/air105/board/linker_scripts/link.icf b/bsp/airm2m/air105/board/linker_scripts/link.icf new file mode 100644 index 0000000000..46124d5a81 --- /dev/null +++ b/bsp/airm2m/air105/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__ = 0x01000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x0102FFFF; +define symbol __ICFEDIT_region_RAM1_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM1_end__ = 0x2009FFFF; +/*-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 RAM1_region = mem:[from __ICFEDIT_region_RAM1_start__ to __ICFEDIT_region_RAM1_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 RAM1_region { readwrite, last block CSTACK }; diff --git a/bsp/airm2m/air105/board/linker_scripts/link.lds b/bsp/airm2m/air105/board/linker_scripts/link.lds new file mode 100644 index 0000000000..9b49ab1c3f --- /dev/null +++ b/bsp/airm2m/air105/board/linker_scripts/link.lds @@ -0,0 +1,156 @@ +/* Program Entry, set to mark it as "used" and avoid gc */ +MEMORY +{ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 640K + FLASH (rx) : ORIGIN = 0x1010000, LENGTH = 3008K +} +ENTRY(Reset_Handler) +_system_stack_size = 0x4000; + +SECTIONS +{ + .app_info : + { + . = ALIGN(512); + KEEP(*(.app_info)) + . = ALIGN(512); + } >FLASH + .text : + { + . = ALIGN(4); + __isr_start_address = .; + _stext = .; + KEEP(*(.isr_vector)) /* Startup code */ + + . = ALIGN(4); + *startup_gcc.o(.text .text.*) + *(.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 = .; + } > FLASH + + /* .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 = .; + } > FLASH + __exidx_end = .; + + /* .data section which is used for initialized data */ + + .data : AT (_sidata) + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _sdata = . ; + + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + *(.RamFunc) /* .RamFunc sections */ + *(.RamFunc*) /* .RamFunc* sections */ + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _edata = . ; + } >RAM + + .stack : + { + . = ALIGN(4); + _sstack = .; + . = . + _system_stack_size; + . = ALIGN(4); + _estack = .; + } >RAM + + __bss_start = .; + .bss : + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; + + *(.bss) + *(.bss.*) + *(COMMON) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _ebss = . ; + + *(.bss.init) + } > RAM + __bss_end = .; + + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/airm2m/air105/board/linker_scripts/link.sct b/bsp/airm2m/air105/board/linker_scripts/link.sct new file mode 100644 index 0000000000..25a3067875 --- /dev/null +++ b/bsp/airm2m/air105/board/linker_scripts/link.sct @@ -0,0 +1,15 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x01010000 0x002F0000 { ; load region size_region + ER_IROM1 0x01010000 0x002F0000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x20000000 0x000A0000 { ; RW data + .ANY (+RW +ZI) + } +} + diff --git a/bsp/airm2m/air105/board/ports/spi_flash_init.c b/bsp/airm2m/air105/board/ports/spi_flash_init.c new file mode 100644 index 0000000000..9885bef4d7 --- /dev/null +++ b/bsp/airm2m/air105/board/ports/spi_flash_init.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + +#include +#include "spi_flash.h" +#include "spi_flash_sfud.h" +#include "drv_spi.h" + +#if defined(BSP_USING_SPI_FLASH) +static int rt_hw_spi_flash_init(void) +{ + __HAL_RCC_GPIOA_CLK_ENABLE(); + rt_hw_spi_device_attach("spi1", "spi10", GPIOA, GPIO_PIN_4); + + if (RT_NULL == rt_sfud_flash_probe("W25Q64", "spi10")) + { + return -RT_ERROR; + }; + + return RT_EOK; +} +INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init); +#endif + diff --git a/bsp/airm2m/air105/board/ports/w5500_device.c b/bsp/airm2m/air105/board/ports/w5500_device.c new file mode 100644 index 0000000000..fed57e01fa --- /dev/null +++ b/bsp/airm2m/air105/board/ports/w5500_device.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + +#include "drv_spi.h" +#include "board.h" +int w5500_spi_device_init(void) +{ + return rt_hw_spi_device_attach(WIZ_SPI_BUS,WIZ_SPI_DEVICE, WIZ_SPI_CS); +} +INIT_DEVICE_EXPORT(w5500_spi_device_init); diff --git a/bsp/airm2m/air105/board/wdt_feed.c b/bsp/airm2m/air105/board/wdt_feed.c new file mode 100644 index 0000000000..6a608275a9 --- /dev/null +++ b/bsp/airm2m/air105/board/wdt_feed.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + +#include +#include + +static char device_name[] = "wdt"; +static rt_device_t wdg_dev; + +static struct rt_work wdt_feed; +static void wdt_feed_func(struct rt_work *work, void *work_data) +{ + rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, RT_NULL); + rt_work_submit(&wdt_feed, 1200); +} + +static int wdt_feed_init(void) +{ + rt_err_t ret = RT_EOK; + rt_uint32_t timeout = 2; + + wdg_dev = rt_device_find(device_name); + if (!wdg_dev) + { + rt_kprintf("find %s failed!\n", device_name); + return RT_ERROR; + } + + ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout); + if (ret != RT_EOK) + { + rt_kprintf("set %s timeout failed!\n", device_name); + return RT_ERROR; + } + ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_START, RT_NULL); + if (ret != RT_EOK) + { + rt_kprintf("start %s failed!\n", device_name); + return -RT_ERROR; + } + + rt_work_init(&wdt_feed, wdt_feed_func, RT_NULL); + rt_work_submit(&wdt_feed, 1200); + return RT_EOK; +} +INIT_COMPONENT_EXPORT(wdt_feed_init); diff --git a/bsp/airm2m/air105/figures/board.png b/bsp/airm2m/air105/figures/board.png new file mode 100644 index 0000000000000000000000000000000000000000..0991e7ca572e35d942f93ecba11559c34e972d69 GIT binary patch literal 826999 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

8ttFbN|vXiiK1Ro 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

|JaHz?DvfZpb}GUl&)iZB#@7IHQrf!GT<< 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

=7LKYZeWVGOJ`+8Ycr8Sh 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%0AUmkaa|NJWU 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


-=^oUrn{>9+6#0w^*}|C<%o?*b2RVU& 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

UB%bfraHQ|A}PNy}9dNO7Lt1jl8 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 X{@^03C8fOCAiBc`k9gO5o%rz|@?eMR literal 0 HcmV?d00001 diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105.h new file mode 100644 index 0000000000..e0dd1af1c0 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105.h @@ -0,0 +1,2087 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef __AIR105_H__ +#define __AIR105_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* ToDo: replace '' with your device name; add your doxyGen comment */ +/** @addtogroup _Definitions Definitions + This file defines all structures and symbols for : + - registers and bitfields + - peripheral base address + - peripheral ID + - Peripheral definitions + @{ +*/ + + +/******************************************************************************/ +/* Processor and Core Peripherals */ +/******************************************************************************/ +/** @addtogroup _CMSIS Device CMSIS Definitions + Configuration of the Cortex-M# Processor and Core Peripherals + @{ +*/ +/* + * ========================================================================== + * ---------- Interrupt Number Definition ----------------------------------- + * ========================================================================== + */ +typedef enum IRQn +{ +/****** Cortex-M# Processor Exceptions Numbers ***************************************************/ + +/* ToDo: use this Cortex interrupt numbers if your device is a CORTEX-M3 / Cortex-M4 device */ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 System Tick Interrupt */ + +/****** Device Specific Interrupt Numbers ********************************************************/ +/* ToDo: add here your device specific external interrupt numbers + according the interrupt handlers defined in startup_Device.s + eg.: Interrupt for Timer#1 TIM1_IRQHandler -> TIM1_IRQn */ + DMA_IRQn = 0, + USB_IRQn = 1, + USBDMA_IRQn = 2, + LCD_IRQn = 3, + SCI0_IRQn = 4, + UART0_IRQn = 5, + UART1_IRQn = 6, + SPI0_IRQn = 7, + CRYPT0_IRQn = 8, + TIM0_0_IRQn = 9, + TIM0_1_IRQn = 10, + TIM0_2_IRQn = 11, + TIM0_3_IRQn = 12, + EXTI0_IRQn = 13, + EXTI1_IRQn = 14, + EXTI2_IRQn = 15, + RTC_IRQn = 16, + SENSOR_IRQn = 17, + TRNG_IRQn = 18, + ADC0_IRQn = 19, + SSC_IRQn = 20, + TIM0_4_IRQn = 21, + TIM0_5_IRQn = 22, + KBD_IRQn = 23, + MSR_IRQn = 24, + EXTI3_IRQn = 25, + SPI1_IRQn = 26, + SPI2_IRQn = 27, + + SCI2_IRQn = 29, + + UART2_IRQn = 32, + UART3_IRQn = 33, + QSPI_IRQn = 35, + I2C0_IRQn = 36, + EXTI4_IRQn = 37, + EXTI5_IRQn = 38, + TIM0_6_IRQn = 39, + TIM0_7_IRQn = 40, + DCMI_IRQn = 42, + + QR_IRQn = 46, + GPU_IRQn = 47, + + AWD_IRQn = 49, + DAC_IRQn = 50, + SPI5_IRQn = 51 +} IRQn_Type; + + +/* + * ========================================================================== + * ----------- Processor and Core Peripheral Section ------------------------ + * ========================================================================== + */ + +/* Configuration of the Cortex-M# Processor and Core Peripherals */ +/* ToDo: set the defines according your Device */ +/* ToDo: define the correct core revision + __CM0_REV if your device is a CORTEX-M0 device + __CM3_REV if your device is a CORTEX-M3 device + __CM4_REV if your device is a CORTEX-M4 device */ +//#define __CM3_REV 0x0201 /*!< Core Revision r2p1 */ +//#define __CM3_REV 0x0200 /*!< Core Revision r2p0 */ +#define __CM4_REV 0x0001 /*!< Core Revision r2p0 */ +#define __NVIC_PRIO_BITS 3 /*!< Number of Bits used for Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ +#define __MPU_PRESENT 1 /*!< MPU present or not */ +/* ToDo: define __FPU_PRESENT if your devise is a CORTEX-M4 */ +#define __FPU_PRESENT 1 /*!< FPU present or not */ + +/*@}*/ /* end of group _CMSIS */ + + +/* ToDo: include the correct core_cm#.h file + core_cm0.h if your device is a CORTEX-M0 device + core_cm3.h if your device is a CORTEX-M3 device + core_cm4.h if your device is a CORTEX-M4 device */ +#include "core_cm4.h" /* Cortex-M# processor and core peripherals */ +/* ToDo: include your system_.h file + replace '' with your device name */ +#include "system_air105.h" /* System include file */ + + +/******************************************************************************/ +/* Device Specific Peripheral registers structures */ +/******************************************************************************/ +/** @addtogroup _Peripherals Peripherals + Device Specific Peripheral registers structures + @{ +*/ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +#include + +/** @addtogroup Exported_types + * @{ + */ + +typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; + +typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; +#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE)) + +typedef enum {FALSE = 0, TRUE = !FALSE} Boolean; + +typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus; + +/* ToDo: add here your device specific peripheral access structure typedefs + following is an example for a timer */ +#define BIT0 (0x00000001U) +#define BIT1 (0x00000002U) +#define BIT2 (0x00000004U) +#define BIT3 (0x00000008U) +#define BIT4 (0x00000010U) +#define BIT5 (0x00000020U) +#define BIT6 (0x00000040U) +#define BIT7 (0x00000080U) +#define BIT8 (0x00000100U) +#define BIT9 (0x00000200U) +#define BIT10 (0x00000400U) +#define BIT11 (0x00000800U) +#define BIT12 (0x00001000U) +#define BIT13 (0x00002000U) +#define BIT14 (0x00004000U) +#define BIT15 (0x00008000U) +#define BIT16 (0x00010000U) +#define BIT17 (0x00020000U) +#define BIT18 (0x00040000U) +#define BIT19 (0x00080000U) +#define BIT20 (0x00100000U) +#define BIT21 (0x00200000U) +#define BIT22 (0x00400000U) +#define BIT23 (0x00800000U) +#define BIT24 (0x01000000U) +#define BIT25 (0x02000000U) +#define BIT26 (0x04000000U) +#define BIT27 (0x08000000U) +#define BIT28 (0x10000000U) +#define BIT29 (0x20000000U) +#define BIT30 (0x40000000U) +#define BIT31 (0x80000000U) + +#define BIT(n) (1UL << (n)) + +typedef struct +{ + __IO uint32_t FREQ_SEL; + __IO uint32_t CG_CTRL1; + __IO uint32_t CG_CTRL2; + __O uint32_t SOFT_RST1; + __O uint32_t SOFT_RST2; + __IO uint32_t LOCK_R; + __IO uint32_t PHER_CTRL; + __I uint32_t SYS_RSVD[(0x2C-0x1C) >> 2]; + __I uint32_t HCLK_1MS_VAL; + __I uint32_t PCLK_1MS_VAL; + __IO uint32_t ANA_CTRL; + __IO uint32_t DMA_CHAN; + __IO uint32_t SCI0_GLF; + __IO uint32_t SW_RSV1; + __IO uint32_t SW_RSV2; + __IO uint32_t CARD_RSVD; + __IO uint32_t LDO25_CR; + __IO uint32_t DMA_CHAN1; + __I uint32_t SYS_RSVD2[(0x100-0x54) >> 2]; + __IO uint32_t MSR_CR1; + __IO uint32_t MSR_CR2; + __IO uint32_t USBPHY_CR1; + __IO uint32_t USBPHY_CR2; + __IO uint32_t USBPHY_CR3; + __IO uint32_t ISO7816_CR; + __IO uint32_t LDO_CR; + __IO uint32_t CHG_CSR; + __I uint32_t SYS_RSVD3[(0x204-0x120) >> 2]; + __IO uint32_t RSVD_POR; + __I uint32_t SYS_RSVD4[(0x3EC-0x208) >> 2]; + __IO uint32_t PM2_WK_FLAG; + __IO uint32_t CALIB_CSR; + __IO uint32_t DBG_CR; + __IO uint32_t CHIP_ID; +} SYSCTRL_TypeDef; + +typedef struct +{ + union + { + __I uint32_t RBR; + __O uint32_t THR; + __IO uint32_t DLL; + } OFFSET_0; + union + { + __IO uint32_t DLH; + __IO uint32_t IER; + } OFFSET_4; + union + { + __I uint32_t IIR; + __O uint32_t FCR; + } OFFSET_8; + __IO uint32_t LCR; + __IO uint32_t MCR; + __I uint32_t LSR; + __I uint32_t MSR; + __IO uint32_t SCR; + __IO uint32_t LPDLL; + __IO uint32_t LPDLH; + __I uint32_t RES0[2]; + union + { + __I uint32_t SRBR[16]; + __O uint32_t STHR[16]; + } OFFSET_48; + __IO uint32_t FAR; + __I uint32_t TFR; + __O uint32_t RFW; + __I uint32_t USR; + __I uint32_t TFL; + __I uint32_t RFL; + __O uint32_t SRR; + __IO uint32_t SRTS; + __IO uint32_t SBCR; + __IO uint32_t SDMAM; + __IO uint32_t SFE; + __IO uint32_t SRT; + __IO uint32_t STET; + __IO uint32_t HTX; + __O uint32_t DMASA; + __I uint32_t RES1[18]; + __I uint32_t CPR; + __I uint32_t UCV; + __I uint32_t CTR; + +} UART_TypeDef; + +typedef struct +{ + __IO uint16_t CTRLR0; + uint16_t RESERVED0; + __IO uint16_t CTRLR1; + uint16_t RESERVED1; + __IO uint32_t SSIENR; + __IO uint32_t MWCR; + __IO uint32_t SER; + __IO uint32_t BAUDR; + __IO uint32_t TXFTLR; + __IO uint32_t RXFTLR; + __I uint32_t TXFLR; + __I uint32_t RXFLR; + __I uint32_t SR; + __IO uint32_t IMR; + __I uint32_t ISR; + __I uint32_t RISR; + __I uint32_t TXOICR; + __I uint32_t RXOICR; + __I uint32_t RXUICR; + __I uint32_t MSTICR; + __IO uint32_t ICR; + __IO uint32_t DMACR; + __IO uint32_t DMATDLR; + __IO uint32_t DMARDLR; + __I uint32_t IDR; + __I uint32_t SSI_COMP_VERSION; + __IO uint32_t DR; + __IO uint32_t DR_Array[35]; + __IO uint32_t RX_SAMPLE_DLY; +} SPI_TypeDef; + +typedef struct +{ + __IO uint32_t FCU_CMD; + __O uint32_t ADDRES; + __IO uint32_t BYTE_NUM; + __O uint32_t WR_FIFO; + __I uint32_t RD_FIFO; + __IO uint32_t DEVICE_PARA; + __IO uint32_t REG_WDATA; + __O uint32_t REG_RDATA; + __IO uint32_t INT_MASK; + __IO uint32_t INT_UMASK; + __IO uint32_t INT_MASK_STATUS; + __IO uint32_t INT_STATUS; + __IO uint32_t INT_RAWSTATUS; + __IO uint32_t INT_CLEAR; + __IO uint32_t CACHE_INTF_CMD; + __IO uint32_t DMA_CNTL; + __IO uint32_t FIFO_CNTL; +} QSPI_TypeDef; + +typedef struct +{ + __IO uint32_t CACHE_I0; + __IO uint32_t CACHE_I1; + __IO uint32_t CACHE_I2; + __IO uint32_t CACHE_I3; + __IO uint32_t CACHE_K0; + __IO uint32_t CACHE_K1; + __IO uint32_t CACHE_K2; + __IO uint32_t CACHE_K3; + __IO uint32_t CACHE_CS; + __IO uint32_t CACHE_REF; + __I uint32_t CACHE_RSVD0[(0x40-0x28) >> 2]; + __IO uint32_t CACHE_CONFIG; + __I uint32_t CACHE_RSVD1[(0x74-0x44) >> 2]; + __IO uint32_t CACHE_SADDR; + __IO uint32_t CACHE_EADDR; + +} CACHE_TypeDef; + +typedef struct +{ + __IO uint32_t CR0; /*!< HSPIM Control register0 */ + __IO uint32_t FLCR; /*!< HSPIM Flow Control register */ + __IO uint32_t FLSR; /*!< HSPIM Flow Status register */ + __IO uint32_t FCR; /*!< HSPIM FIFO Control register */ + __I uint32_t RDR; /*!< HSPIM Read Data register */ + __O uint32_t WDR; /*!< HSPIM Write Data register */ + __I uint32_t SR; /*!< HSPIM Status register */ + __IO uint32_t CR1; /*!< HSPIM Control register1 */ + __IO uint32_t FSR; /*!< HSPIM FIFO Status register */ + __IO uint32_t DCR; /*!< HSPIM DMA Control register */ + __I uint32_t TISR; /*!< HSPIM TX Interrput Status register */ + __I uint32_t RISR; /*!< HSPIM RX Interrput Status register */ +}HSPIM_TypeDef; + +typedef struct +{ + __IO uint32_t SMU_CTRL; + __IO uint32_t FPM_CTRL; + __O uint32_t INTR_STAT; + __IO uint32_t INTR_CTRL; + __IO uint32_t RESERVED1[12]; + __IO uint32_t SMU_OP1; + __IO uint32_t SMU_OP2; + __O uint32_t SMU_RES; + __IO uint32_t RESERVED2[13]; + __IO float MATRIX1_00; + __IO float MATRIX1_01; + __IO float MATRIX1_02; + __IO float MATRIX1_10; + __IO float MATRIX1_11; + __IO float MATRIX1_12; + __IO float MATRIX1_20; + __IO float MATRIX1_21; + __IO float MATRIX1_22; + __IO uint32_t RESERVED3[7]; + __IO float MATRIX2_00; + __IO float MATRIX2_01; + __IO float MATRIX2_02; + __IO uint32_t RESERVED4[13]; + __IO uint32_t TABLE1_LEN; + __IO uint32_t TABLE2_LEN; + __IO uint32_t ACC; + __IO uint32_t POSITION; + __IO uint32_t VAL3; + __IO uint32_t RESERVED5[443]; + __IO uint32_t TABLE1_RAM; + __IO uint32_t RESERVED6[255]; + __IO uint32_t TABLE2_RAM; + __IO uint32_t RESERVED7[63]; +}QRCODE_TypeDef; + + +typedef struct +{ + __IO uint32_t WDT_CR; + __IO uint32_t RESERVED0; + __I uint32_t WDT_CCVR; + __O uint32_t WDT_CRR; + __I uint32_t WDT_STAT; + __I uint32_t WDT_EOI; + __I uint32_t RESERVED1; + __IO uint32_t WDT_RLD; + __I uint32_t RESERVED[53]; + __I uint32_t WDT_COMP_PARAMS_1; + __I uint32_t WDT_COMP_VERSION; + __I uint32_t WDT_COMP_TYPE; +} WDT_TypeDef; + +typedef struct +{ + __IO uint32_t CRC_CSR; + __O uint32_t CRC_INI; + union + { + __I uint32_t DOUT; + __O uint8_t DIN; + } CRC_DATA; +} CRC_TypeDef; + +typedef struct +{ + __IO uint32_t LoadCount; + __I uint32_t CurrentValue; + __IO uint32_t ControlReg; + __IO uint32_t EOI; + __I uint32_t IntStatus; +} TIM_TypeDef; + +#define TIM_NUM 8 +typedef struct +{ + TIM_TypeDef TIM[TIM_NUM]; + __I uint32_t TIM_IntStatus; + __I uint32_t TIM_EOI; + __I uint32_t TIM_RawIntStatus; + __I uint32_t TIM_Comp; + __IO uint32_t TIM_ReloadCount[TIM_NUM]; +} TIM_Module_TypeDef; + +typedef struct +{ + __IO uint32_t ADC_CR1; + __I uint32_t ADC_SR; + __IO uint32_t ADC_FIFO; + __I uint32_t ADC_DATA; + __I uint32_t ADC_FIFO_FL; + __IO uint32_t ADC_FIFO_THR; + __IO uint32_t ADC_CR2; +} ADC_TypeDef; + +typedef struct +{ + __IO uint32_t DAC_CR1; + __IO uint32_t DAC_DATA; + __IO uint32_t DAC_TIMER; + __I uint32_t DAC_FIFO_FL; + __IO uint32_t DAC_FIFO_THR; +} DAC_TypeDef; + +typedef struct +{ + __IO uint32_t AWD_CR1; + __IO uint32_t AWD_CR2; + __I uint32_t AWD_SR; +} AWD_TypeDef; + +typedef struct +{ + __IO uint32_t IODR; + __IO uint32_t BSRR; + __IO uint32_t OEN; + __IO uint32_t PUE; +} GPIO_TypeDef; + +typedef struct +{ + __IO uint32_t INTP_TYPE; + __IO uint32_t INTP_STA; +} GPIO_INTP_TypeDef; + +#define GPIO_GROUP_NUM 6 +typedef struct +{ + GPIO_TypeDef GPIO[GPIO_GROUP_NUM]; + __I uint32_t RSVD0[(0x114 - 0x060)>>2]; + __I uint32_t INTP[GPIO_GROUP_NUM]; + __I uint32_t RSVD1[(0x180 - 0x12C)>>2]; + __IO uint32_t ALT[GPIO_GROUP_NUM]; + __I uint32_t RSVD2[(0x200 - 0x198)>>2]; + __IO uint32_t SYS_CR1; + __I uint32_t RSVD3[(0x220 - 0x204)>>2]; + __IO uint32_t WAKE_TYPE_EN; + __IO uint32_t WAKE_P0_EN; + __IO uint32_t WAKE_P1_EN; + __IO uint32_t WAKE_P2_EN; + __IO uint32_t WAKE_P3_EN; + __I uint32_t RSVD5[(0x800 - 0x234)>>2]; + GPIO_INTP_TypeDef INTP_TYPE_STA[GPIO_GROUP_NUM]; +} GPIO_MODULE_TypeDef; + + +typedef struct +{ + __IO uint32_t FLAG[(0x0174 - 0x00164) >> 2]; +} FLAG_TypeDef; + +#define BPK_KEY_NUM 16 +typedef struct +{ + __IO uint32_t KEY[BPK_KEY_NUM]; + __I uint32_t BPK_RSVD0[(0x80-0x40)>>2]; + __IO uint32_t BPK_RDY; + __IO uint32_t BPK_CLR; + __IO uint32_t BPK_LRA; + __IO uint32_t BPK_LWA; + __I uint32_t BPK_RSVD1; + __IO uint32_t BPK_LR; + __IO uint32_t BPK_SCR; + __IO uint32_t BPK_POWER; + + __IO uint32_t RTC_CS; + __IO uint32_t RTC_REF; + __IO uint32_t RTC_ARM; + __I uint32_t RTC_TIM; + __O uint32_t RTC_INTCLR; + __IO uint32_t OSC32K_CR; + __IO uint32_t RTC_ATTA_TIM; + + __IO uint32_t BPK_RR; + __IO uint32_t SEN_EXT_TYPE; + __IO uint32_t SEN_EXT_CFG; + __IO uint32_t SEN_SOFT_EN; + __IO uint32_t SEN_STATE; + __IO uint32_t SEN_BRIDGE; + __IO uint32_t SEN_SOFT_ATTACK; + __IO uint32_t SEN_SOFT_LOCK; + __IO uint32_t SEN_ATTACK_CNT; + __IO uint32_t SEN_ATTACK_TYP; + __IO uint32_t SEN_VG_DETECT; + __IO uint32_t SEN_RNG_INI; + __IO uint32_t RESERVED3[(0x0104 - 0x00EC) >> 2]; + __IO uint32_t SEN_EN[19]; + __IO uint32_t SEN_EXTS_START; + __IO uint32_t SEN_LOCK; + __IO uint32_t SEN_ANA0; + __IO uint32_t SEN_ANA1; + __IO uint32_t SEN_ATTCLR; + FLAG_TypeDef SEN_FLAG; + __IO uint32_t SEN_DEBUG; + __I uint32_t BPU_RSVD4[(0x200- 0x178) >> 2]; + __IO uint32_t BPK_RAM[(0x600-0x200) >> 2]; +} BPU_TypeDef; + +typedef struct +{ + __IO uint32_t KEY[BPK_KEY_NUM]; + __I uint32_t BPK_RSVD0[(0x80-0x40) >> 2]; + __IO uint32_t BPK_RDY; + __IO uint32_t BPK_CLR; + __IO uint32_t BPK_LRA; + __IO uint32_t BPK_LWA; + __I uint32_t BPK_RSVD1; + __IO uint32_t BPK_LR; + __IO uint32_t BPK_SCR; + __IO uint32_t BPK_POWER; +} BPK_TypeDef; + +typedef struct +{ + __IO uint32_t RTC_CS; + __IO uint32_t RTC_REF; + __IO uint32_t RTC_ARM; + __I uint32_t RTC_TIM; + __O uint32_t RTC_INTCLR; + __IO uint32_t OSC32K_CR; + __IO uint32_t RTC_ATTA_TIM; +} RTC_TypeDef; + +#define EXT_SENSOR_NUM 8 +#define INNER_SENSOR_NUM 7 +typedef struct +{ + __IO uint32_t BPK_RR; + __IO uint32_t SEN_EXT_TYPE; + __IO uint32_t SEN_EXT_CFG; + __IO uint32_t SEN_SOFT_EN; + __IO uint32_t SEN_STATE; + __IO uint32_t SEN_BRIDGE; + __IO uint32_t SEN_SOFT_ATTACK; + __IO uint32_t SEN_SOFT_LOCK; + __IO uint32_t SEN_ATTACK_CNT; + __IO uint32_t SEN_ATTACK_TYP; + __IO uint32_t SEN_VG_DETECT; + __IO uint32_t SEN_RNG_INI; + __IO uint32_t RESERVED3[(0x0104-0x00EC) >> 2]; + __IO uint32_t SEN_EN[19]; + __IO uint32_t SEN_EXTS_START; + __IO uint32_t SEN_LOCK; + __IO uint32_t SEN_ANA0; + __IO uint32_t SEN_ANA1; + __IO uint32_t SEN_ATTCLR; + FLAG_TypeDef SEN_FLAG; + __IO uint32_t SEN_DEBUG; + __I uint32_t RESERVED4[(0x200- 0x178) >> 2]; + __IO uint32_t BPK_RAM[(0x600-0x200) >> 2]; +} SEN_TypeDef; + + +typedef struct +{ + __IO uint32_t RNG_CSR; + __IO uint32_t RNG_DATA[1]; + __I uint32_t RES; + __IO uint32_t RNG_ANA; + __IO uint32_t RNG_PN; + __IO uint32_t RNG_INDEX; +} TRNG_TypeDef; + +typedef struct +{ + __IO uint32_t IC_CON; + __IO uint32_t IC_TAR; + __IO uint32_t IC_SAR; + __IO uint32_t IC_HS_MADDR; + __IO uint32_t IC_DATA_CMD; + __IO uint32_t IC_SS_SCL_HCNT; + __IO uint32_t IC_SS_SCL_LCNT; + __IO uint32_t IC_FS_SCL_HCNT; + __IO uint32_t IC_FS_SCL_LCNT; + __IO uint32_t IC_HS_SCL_HCNT; + __IO uint32_t IC_HS_SCL_LCNT; + __I uint32_t IC_INTR_STAT; + __IO uint32_t IC_INTR_MASK; + __I uint32_t IC_RAW_INTR_STAT; + __IO uint32_t IC_RX_TL; + __IO uint32_t IC_TX_TL; + __I uint32_t IC_CLR_INTR; + __I uint32_t IC_CLR_RX_UNDER; + __I uint32_t IC_CLR_RX_OVER; + __I uint32_t IC_CLR_TX_OVER; + __I uint32_t IC_CLR_RD_REQ; + __I uint32_t IC_CLR_TX_ABRT; + __I uint32_t IC_CLR_RX_DONE; + __I uint32_t IC_CLR_ACTIVITY; + __I uint32_t IC_CLR_STOP_DET; + __I uint32_t IC_CLR_START_DET; + __I uint32_t IC_CLR_GEN_CALL; + __IO uint32_t IC_ENABLE; + __I uint32_t IC_STATUS; + __I uint32_t IC_TXFLR; + __I uint32_t IC_RXFLR; + __IO uint32_t IC_SDA_HOLD; + __I uint32_t IC_TX_ABRT_SOURCE; + __IO uint32_t IC_SLV_DATA_NACK_ONLY; + __IO uint32_t IC_DMA_CR; + __IO uint32_t IC_DMA_TDLR; + __IO uint32_t IC_DMA_RDLR; + __IO uint32_t IC_SDA_SETUP; + __IO uint32_t IC_ACK_GENERAL_CALL; + __I uint32_t IC_ENABLE_STATUS; + __IO uint32_t IC_FS_SPKLEN; + __IO uint32_t IC_HS_SPKLEN; +} I2C_TypeDef; + +typedef struct +{ + __IO uint32_t KCU_CTRL0; + __IO uint32_t KCU_CTRL1; + __I uint32_t KCU_STATUS; + __I uint32_t KCU_EVENT; + __IO uint32_t KCU_RNG; +} KCU_TypeDef; + +typedef struct +{ + __IO uint32_t SAR_L; + __IO uint32_t SAR_H; + __IO uint32_t DAR_L; + __IO uint32_t DAR_H; + __IO uint32_t LLP_L; + __IO uint32_t LLP_H; + __IO uint32_t CTL_L; + __IO uint32_t CTL_H; + __IO uint32_t SSTAT_L; + __IO uint32_t SSTAT_H; + __IO uint32_t DSTAT_L; + __IO uint32_t DSTAT_H; + __IO uint32_t SSTATAR_L; + __IO uint32_t SSTATAR_H; + __IO uint32_t DSTATAR_L; + __IO uint32_t DSTATAR_H; + __IO uint32_t CFG_L; + __IO uint32_t CFG_H; + __IO uint32_t SGR_L; + __IO uint32_t SGR_H; + __IO uint32_t DSR_L; + __IO uint32_t DSR_H; +} DMA_TypeDef; + +typedef struct +{ + DMA_TypeDef DMA_Channel[8]; + + __I uint32_t RawTfr_L; + __I uint32_t RawTfr_H; + __I uint32_t RawBlock_L; + __I uint32_t RawBlock_H; + __I uint32_t RawSrcTran_L; + __I uint32_t RawSrcTran_H; + __I uint32_t RawDstTran_L; + __I uint32_t RawDstTran_H; + __I uint32_t RawErr_L; + __I uint32_t RawErr_H; + + __I uint32_t StatusTfr_L; + __I uint32_t StatusTfr_H; + __I uint32_t StatusBlock_L; + __I uint32_t StatusBlock_H; + __I uint32_t StatusSrcTran_L; + __I uint32_t StatusSrcTran_H; + __I uint32_t StatusDstTran_L; + __I uint32_t StatusDstTran_H; + __I uint32_t StatusErr_L; + __I uint32_t StatusErr_H; + + __IO uint32_t MaskTfr_L; + __IO uint32_t MaskTfr_H; + __IO uint32_t MaskBlock_L; + __IO uint32_t MaskBlock_H; + __IO uint32_t MaskSrcTran_L; + __IO uint32_t MaskSrcTran_H; + __IO uint32_t MaskDstTran_L; + __IO uint32_t MaskDstTran_H; + __IO uint32_t MaskErr_L; + __IO uint32_t MaskErr_H; + + __O uint32_t ClearTfr_L; + __O uint32_t ClearTfr_H; + __O uint32_t ClearBlock_L; + __O uint32_t ClearBlock_H; + __O uint32_t ClearSrcTran_L; + __O uint32_t ClearSrcTran_H; + __O uint32_t ClearDstTran_L; + __O uint32_t ClearDstTran_H; + __O uint32_t ClearErr_L; + __O uint32_t ClearErr_H; + + __I uint32_t StatusInt_L; + __I uint32_t StatusInt_H; + + __IO uint32_t ReqSrcReg_L; + __IO uint32_t ReqSrcReg_H; + __IO uint32_t ReqDstReg_L; + __IO uint32_t ReqDstReg_H; + __IO uint32_t SglReqSrcReg_L; + __IO uint32_t SglReqSrcReg_H; + __IO uint32_t SglReqDstReg_L; + __IO uint32_t SglReqDstReg_H; + __IO uint32_t LstSrcReg_L; + __IO uint32_t LstSrcReg_H; + __IO uint32_t LstDstReg_L; + __IO uint32_t LstDstReg_H; + + __IO uint32_t DmaCfgReg_L; + __IO uint32_t DmaCfgReg_H; + __IO uint32_t ChEnReg_L; + __IO uint32_t ChEnReg_H; + __I uint32_t DmaIdReg_L; + __I uint32_t DmaIdReg_H; + __IO uint32_t DmaTestReg_L; + __IO uint32_t DmaTestReg_H; + + __IO uint32_t RESERVED2[4]; + + __I uint32_t DMA_COMP_PARAMS_6_L; + __I uint32_t DMA_COMP_PARAMS_6_H; + __I uint32_t DMA_COMP_PARAMS_5_L; + __I uint32_t DMA_COMP_PARAMS_5_H; + __I uint32_t DMA_COMP_PARAMS_4_L; + __I uint32_t DMA_COMP_PARAMS_4_H; + __I uint32_t DMA_COMP_PARAMS_3_L; + __I uint32_t DMA_COMP_PARAMS_3_H; + __I uint32_t DMA_COMP_PARAMS_2_L; + __I uint32_t DMA_COMP_PARAMS_2_H; + __I uint32_t DMA_COMP_PARAMS_1_L; + __I uint32_t DMA_COMP_PARAMS_1_H; + __I uint32_t DMA_Component_ID_Register_L; + __I uint32_t DMA_Component_ID_Register_H; + +} DMA_MODULE_TypeDef; + +typedef struct +{ + __IO uint32_t lcdi_ctrl; + __IO uint32_t lcdi_cycle; + __IO uint32_t lcdi_status; + __IO uint32_t lcdi_data; + __IO uint32_t lcdi_fifolevel; + __IO uint32_t lcdi_fifothr; +} LCD_TypeDef; + +typedef struct +{ + __IO uint32_t SCI_DATA; + __IO uint32_t SCI_CR0; + __IO uint32_t SCI_CR1; + __IO uint32_t SCI_CR2; + __IO uint32_t SCI_IER; + __IO uint32_t SCI_RETRY; + __IO uint32_t SCI_TIDE; + __IO uint32_t SCI_TXCOUNT; + __IO uint32_t SCI_RXCOUNT; + __I uint32_t SCI_FR; + __IO uint32_t SCI_RXTIME; + __IO uint32_t SCI_ISTAT; + __IO uint32_t SCI_STABLE; + __IO uint32_t SCI_ATIME; + __IO uint32_t SCI_DTIME; + + __IO uint32_t SCI_ATRSTIME; + __IO uint32_t SCI_ATRDTIME; + __IO uint32_t SCI_BLKTIME; + __IO uint32_t SCI_CHTIME; + __IO uint32_t SCI_CLKICC; + __IO uint32_t SCI_BAUD; + __IO uint32_t SCI_VALUE; + __IO uint32_t SCI_CHGUARD; + __IO uint32_t SCI_BLKGUARD; + __IO uint32_t SCI_SYNCCR; + __IO uint32_t SCI_SYNCDATA; + __IO uint32_t SCI_RAWSTAT; + __IO uint32_t SCI_IIR; + __I uint32_t SCI_RES1[4]; + __I uint32_t SCI_RES2[32]; +} SCI_TypeDef; + + + +/** + * @brief DCMI&IMG COP + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DCMI control register 1, Address offset: 0x00 */ + __IO uint32_t SR; /*!< DCMI status register, Address offset: 0x04 */ + __IO uint32_t RISR; /*!< DCMI raw interrupt status register, Address offset: 0x08 */ + __IO uint32_t IER; /*!< DCMI interrupt enable register, Address offset: 0x0C */ + __IO uint32_t MISR; /*!< DCMI masked interrupt status register, Address offset: 0x10 */ + __IO uint32_t ICR; /*!< DCMI interrupt clear register, Address offset: 0x14 */ + __IO uint32_t RESERVED1[2]; + __IO uint32_t CWSTRTR; /*!< DCMI crop window start, Address offset: 0x20 */ + __IO uint32_t CWSIZER; /*!< DCMI crop window size, Address offset: 0x24 */ + __IO uint32_t DR; /*!< DCMI data register, Address offset: 0x28 */ +} DCMI_TypeDef; +typedef struct +{ + __IO uint32_t RESERVED[(0x2000-0x0000)/4]; + __IO uint32_t CFG; + __IO uint32_t CS; + __IO uint32_t PROT; + __IO uint32_t ADDR; + __IO uint32_t PDATA; + __IO uint32_t RO; + __IO uint32_t ROL; + __IO uint32_t RSVD; + __IO uint32_t TIM; + __IO uint32_t TIM_EN; +} OTP_TypeDef; + +typedef struct +{ + __IO uint32_t RESERVED0[(0x0008-0x0000) >> 2]; + __IO uint32_t SSC_CR3; + __O uint32_t RESERVED1[(0x0104-0x000C) >> 2]; + __IO uint32_t SSC_SR; + __IO uint32_t SSC_SR_CLR; + __IO uint32_t SSC_ACK; + __O uint32_t RESERVED2[(0x0184-0x0110) >> 2]; + __IO uint32_t DATARAM_SCR; + __O uint32_t RESERVED3[(0x01FC-0x0188) >> 2]; + __IO uint32_t BPU_RWC; + __O uint32_t RESERVED4[(0x03EC-0x0200) >> 2]; + __IO uint32_t MAIN_SEN_LOCK; + __IO uint32_t MAIN_SEN_EN; +} SSC_TypeDef; + +typedef struct +{ + __IO uint32_t TST_JTAG; + __IO uint32_t TST_ROM; + __IO uint32_t TST_FLASH; +} MH_SMCU_TST_TypeDef; + + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +/*@}*/ /* end of group _Peripherals */ + + +/******************************************************************************/ +/* Peripheral memory map */ +/******************************************************************************/ +/* ToDo: add here your device peripherals base addresses + following is an example for timer */ +/** @addtogroup _MemoryMap Memory Mapping + @{ +*/ + +/* Peripheral and SRAM base address */ +#define AIR105_FLASH_BASE (0x01000000UL) /*!< (FLASH ) Base Address */ +#define AIR105_SRAM_BASE (0x20000000UL) /*!< (SRAM ) Base Address */ +#define AIR105_PERIPH_BASE (0x40000000UL) /*!< (Peripheral) Base Address */ + +#define AIR105_SRAM_SIZE (0xA0000) + +#define AIR105_OTP_BASE (0x40008000UL) +#define AIR105_OTP_SIZE (1UL << 13) + +/* Peripheral memory map */ +#define AIR105_AHB_BASE (AIR105_PERIPH_BASE) +#define AIR105_APB0_BASE (AIR105_PERIPH_BASE + 0x10000) +#define AIR105_APB1_BASE (AIR105_PERIPH_BASE + 0x20000) +#define AIR105_APB2_BASE (AIR105_PERIPH_BASE + 0x30000) +#define AIR105_APB3_BASE (AIR105_PERIPH_BASE + 0x40000) + +#define SSC_BASE (AIR105_AHB_BASE + 0x0000) +#define TST_BASE (AIR105_AHB_BASE + 0x03F4) +#define DMA_BASE (AIR105_AHB_BASE + 0x0800) +#define USB_BASE (AIR105_AHB_BASE + 0x0C00) +#define LCD_BASE (AIR105_AHB_BASE + 0x1000) +#define OTP_BASE (AIR105_AHB_BASE + 0x8000) +#define DCMI_BASE (AIR105_AHB_BASE + 0x60000) +#define CACHE_BASE (AIR105_AHB_BASE + 0x80000) +#define QRCODE_BASE (AIR105_AHB_BASE + 0x90000) +#define GPU_BASE (AIR105_AHB_BASE + 0xA1000) +#define QSPI_BASE (AIR105_AHB_BASE + 0xA2000) +#define HSPI_BASE (AIR105_AHB_BASE + 0xA3000) + +#define SCI0_BASE (AIR105_APB0_BASE) +#define CRC_BASE (AIR105_APB0_BASE + 0x2000) +#define TIMM0_BASE (AIR105_APB0_BASE + 0x3000) +#define ADC_BASE (AIR105_APB0_BASE + 0x4000) +#define DAC_BASE (AIR105_APB0_BASE + 0x4100) +#define AWD_BASE (AIR105_APB0_BASE + 0x4200) +#define SCI2_BASE (AIR105_APB0_BASE + 0x5000) +#define UART0_BASE (AIR105_APB0_BASE + 0x6000) +#define UART1_BASE (AIR105_APB0_BASE + 0x7000) +#define SPIM1_BASE (AIR105_APB0_BASE + 0x8000) +#define SPIM2_BASE (AIR105_APB0_BASE + 0x9000) +#define SPIM0_BASE (AIR105_APB0_BASE + 0xA000) +#define SPIS0_BASE (AIR105_APB0_BASE + 0xB000) +#define WDG_BASE (AIR105_APB0_BASE + 0xC000) +#define GPIO_BASE (AIR105_APB0_BASE + 0xD000) +#define TRNG_BASE (AIR105_APB0_BASE + 0xE000) +#define SYSCTRL_BASE (AIR105_APB0_BASE + 0xF000) + +#define MSR_BASE (AIR105_APB1_BASE) + +#define BPU_BASE (AIR105_APB2_BASE) + + +#define UART2_BASE (AIR105_APB3_BASE + 0x4000) +#define UART3_BASE (AIR105_APB3_BASE + 0x5000) +#define KEYBOARD_BASE (AIR105_APB3_BASE + 0x8000) +#define I2C0_BASE (AIR105_APB3_BASE + 0x9000) + +#define HSPIM_BASE (AIR105_AHB_BASE + 0xA3020) + +/*@}*/ /* end of group _MemoryMap */ + + +/******************************************************************************/ +/* Peripheral declaration */ +/******************************************************************************/ +/* ToDo: add here your device peripherals pointer definitions + following is an example for timer */ + +/** @addtogroup _PeripheralDecl Peripheral Declaration + @{ +*/ +#define SYSCTRL ((SYSCTRL_TypeDef *) SYSCTRL_BASE) + +#define UART0 ((UART_TypeDef *) UART0_BASE) +#define UART1 ((UART_TypeDef *) UART1_BASE) +#define UART2 ((UART_TypeDef *) UART2_BASE) +#define UART3 ((UART_TypeDef *) UART3_BASE) + +#define SPIM0 ((SPI_TypeDef *) SPIM0_BASE) +#define SPIM1 ((SPI_TypeDef *) SPIM1_BASE) +#define SPIM2 ((SPI_TypeDef *) SPIM2_BASE) + +#define SPIS0 ((SPI_TypeDef *) SPIS0_BASE) + +#define QSPI ((QSPI_TypeDef *) QSPI_BASE) + +#define HSPIM ((HSPIM_TypeDef *) HSPIM_BASE) +#define CACHE ((CACHE_TypeDef *)CACHE_BASE) +#define QRCODE ((QRCODE_TypeDef *)QRCODE_BASE) +#define GPU ((GPU_TypeDef *)GPU_BASE) +#define SCI0 ((SCI_TypeDef *) SCI0_BASE) +#define SCI2 ((SCI_TypeDef *) SCI2_BASE) + +#define TIMM0 ((TIM_Module_TypeDef *)TIMM0_BASE) + +#define ADC0 ((ADC_TypeDef *)ADC_BASE) +#define DAC ((DAC_TypeDef *)DAC_BASE) +#define AWD ((AWD_TypeDef *)AWD_BASE) + +#define TRNG ((TRNG_TypeDef *)TRNG_BASE) +#define LCD ((LCD_TypeDef *)LCD_BASE) +#define KCU ((KCU_TypeDef *)KEYBOARD_BASE) +#define CRC ((CRC_TypeDef *)CRC_BASE) +#define OTP ((OTP_TypeDef *)OTP_BASE) + +#define I2C0 ((I2C_TypeDef *)I2C0_BASE) + +#define DMA ((DMA_MODULE_TypeDef *)DMA_BASE) +#define DMA_Channel_0 ((DMA_TypeDef *)DMA_BASE) +#define DMA_Channel_1 ((DMA_TypeDef *)(DMA_BASE + 0x58)) +#define DMA_Channel_2 ((DMA_TypeDef *)(DMA_BASE + 0x58*2)) +#define DMA_Channel_3 ((DMA_TypeDef *)(DMA_BASE + 0x58*3)) +#define DMA_Channel_4 ((DMA_TypeDef *)(DMA_BASE + 0x58*4)) +#define DMA_Channel_5 ((DMA_TypeDef *)(DMA_BASE + 0x58*5)) +#define DMA_Channel_6 ((DMA_TypeDef *)(DMA_BASE + 0x58*6)) +#define DMA_Channel_7 ((DMA_TypeDef *)(DMA_BASE + 0x58*7)) + + +#define GPIO ((GPIO_MODULE_TypeDef *)GPIO_BASE) +#define GPIOA ((GPIO_TypeDef *)GPIO_BASE) +#define GPIOB ((GPIO_TypeDef *)(GPIO_BASE + 0x0010)) +#define GPIOC ((GPIO_TypeDef *)(GPIO_BASE + 0x0020)) +#define GPIOD ((GPIO_TypeDef *)(GPIO_BASE + 0x0030)) +#define GPIOE ((GPIO_TypeDef *)(GPIO_BASE + 0x0040)) +#define GPIOF ((GPIO_TypeDef *)(GPIO_BASE + 0x0050)) +#define GPIO_GROUP ((GPIO_TypeDef *)GPIO_BASE) +#define GPIO_ALT_GROUP ((__IO uint32_t *)(GPIO_BASE + 0x180)) +#define GPIO_WKEN_TYPE_EN ((__IO uint32_t *)(GPIO_BASE + 0x220)) +#define GPIO_WKEN_P0_EN ((__IO uint32_t *)(GPIO_BASE + 0x224)) +#define GPIO_WKEN_P1_EN ((__IO uint32_t *)(GPIO_BASE + 0x228)) +#define GPIO_WKEN_P2_EN ((__IO uint32_t *)(GPIO_BASE + 0x22C)) + +#define WDT ((WDT_TypeDef *)WDG_BASE) +#define SSC ((SSC_TypeDef *)SSC_BASE) +#define TST ((MH_SMCU_TST_TypeDef *)TST_BASE) + +#define DCMI ((DCMI_TypeDef *)DCMI_BASE) +#define BPU ((BPU_TypeDef *)BPU_BASE) +#define BPK ((BPK_TypeDef *)BPU_BASE) +#define RTC ((RTC_TypeDef *)(BPU_BASE + 0xA0)) +#define SENSOR ((SEN_TypeDef *)(BPU_BASE + 0xBC)) +#define SEN_FLAG ((FLAG_TypeDef*)(BPU_BASE + 0x164)) + + +/** @addtogroup Exported_constants + * @{ + */ + + /** @addtogroup Peripheral_Registers_Bits_Definition + * @{ + */ + +/******************************************************************************/ +/* Peripheral Registers_Bits_Definition */ +/******************************************************************************/ + +/******************************************************************************/ +/* */ +/* System Control Unit */ +/* */ +/******************************************************************************/ + +/******************* Bit definition for FREQ_SEL register *******************/ +#define SYSCTRL_FREQ_SEL_XTAL_Pos (16) +#define SYSCTRL_FREQ_SEL_XTAL_Mask (0x1F << SYSCTRL_FREQ_SEL_XTAL_Pos) +#define SYSCTRL_FREQ_SEL_XTAL_108Mhz (0x08 << SYSCTRL_FREQ_SEL_XTAL_Pos) +#define SYSCTRL_FREQ_SEL_XTAL_120Mhz (0x09 << SYSCTRL_FREQ_SEL_XTAL_Pos) +#define SYSCTRL_FREQ_SEL_XTAL_132Mhz (0x0a << SYSCTRL_FREQ_SEL_XTAL_Pos) +#define SYSCTRL_FREQ_SEL_XTAL_144Mhz (0x0b << SYSCTRL_FREQ_SEL_XTAL_Pos) +#define SYSCTRL_FREQ_SEL_XTAL_156Mhz (0x0c << SYSCTRL_FREQ_SEL_XTAL_Pos) +#define SYSCTRL_FREQ_SEL_XTAL_168Mhz (0x0d << SYSCTRL_FREQ_SEL_XTAL_Pos) +#define SYSCTRL_FREQ_SEL_XTAL_180Mhz (0x0e << SYSCTRL_FREQ_SEL_XTAL_Pos) +#define SYSCTRL_FREQ_SEL_XTAL_192Mhz (0x0f << SYSCTRL_FREQ_SEL_XTAL_Pos) +#define SYSCTRL_FREQ_SEL_XTAL_204Mhz (0x10 << SYSCTRL_FREQ_SEL_XTAL_Pos) + +#define SYSCTRL_FREQ_SEL_CLOCK_SOURCE_Pos (12) +#define SYSCTRL_FREQ_SEL_CLOCK_SOURCE_Mask (0x01 << SYSCTRL_FREQ_SEL_CLOCK_SOURCE_Pos) +#define SYSCTRL_FREQ_SEL_CLOCK_SOURCE_EXT (0x00 << SYSCTRL_FREQ_SEL_CLOCK_SOURCE_Pos) +#define SYSCTRL_FREQ_SEL_CLOCK_SOURCE_INC (0x01 << SYSCTRL_FREQ_SEL_CLOCK_SOURCE_Pos) + +#define SYSCTRL_FREQ_SEL_PLL_DIV_Pos (8) +#define SYSCTRL_FREQ_SEL_PLL_DIV_Mask (0x03 << SYSCTRL_FREQ_SEL_PLL_DIV_Pos) +#define SYSCTRL_FREQ_SEL_PLL_DIV_1_0 (0x00 << SYSCTRL_FREQ_SEL_PLL_DIV_Pos) +#define SYSCTRL_FREQ_SEL_PLL_DIV_1_2 (0x01 << SYSCTRL_FREQ_SEL_PLL_DIV_Pos) +#define SYSCTRL_FREQ_SEL_PLL_DIV_1_4 (0x02 << SYSCTRL_FREQ_SEL_PLL_DIV_Pos) + +#define SYSCTRL_FREQ_SEL_HCLK_DIV_Pos (4) +#define SYSCTRL_FREQ_SEL_HCLK_DIV_Mask (0x01 << SYSCTRL_FREQ_SEL_HCLK_DIV_Pos) +#define SYSCTRL_FREQ_SEL_HCLK_DIV_1_0 (0x00 << SYSCTRL_FREQ_SEL_HCLK_DIV_Pos) +#define SYSCTRL_FREQ_SEL_HCLK_DIV_1_2 (0x01 << SYSCTRL_FREQ_SEL_HCLK_DIV_Pos) + +#define SYSCTRL_FREQ_SEL_PCLK_DIV_Pos (0) +#define SYSCTRL_FREQ_SEL_PCLK_DIV_Mask (0x01 << SYSCTRL_FREQ_SEL_PCLK_DIV_Pos) +#define SYSCTRL_FREQ_SEL_PCLK_DIV_1_2 (0x00 << SYSCTRL_FREQ_SEL_PCLK_DIV_Pos) +#define SYSCTRL_FREQ_SEL_PCLK_DIV_1_4 (0x01 << SYSCTRL_FREQ_SEL_PCLK_DIV_Pos) + +/******************* Bit definition for CG_CTRL2 register *******************/ +#define SYSCTRL_AHBPeriph_DMA ((uint32_t)0x20000000) +#define SYSCTRL_AHBPeriph_USB ((uint32_t)0x10000000) +#define SYSCTRL_AHBPeriph_QR ((uint32_t)0x00000020) +#define SYSCTRL_AHBPeriph_OTP ((uint32_t)0x00000008) +#define SYSCTRL_AHBPeriph_GPU ((uint32_t)0x00000004) +#define SYSCTRL_AHBPeriph_LCD ((uint32_t)0x00000002) +#define SYSCTRL_AHBPeriph_CRYPT ((uint32_t)0x00000001) +#define SYSCTRL_AHBPeriph_ALL ((uint32_t)0x3000002F) +#define IS_SYSCTRL_AHB_PERIPH(PERIPH) ((((PERIPH) & ~SYSCTRL_AHBPeriph_ALL) == 0x00) && ((PERIPH) != 0x00)) + +/******************* Bit definition for CG_CTRL1 register *******************/ +#define SYSCTRL_APBPeriph_TRNG ((uint32_t)0x80000000) +#define SYSCTRL_APBPeriph_ADC ((uint32_t)0x40000000) +#define SYSCTRL_APBPeriph_CRC ((uint32_t)0x20000000) +#define SYSCTRL_APBPeriph_KBD ((uint32_t)0x08000000) +#define SYSCTRL_APBPeriph_BPU ((uint32_t)0x04000000) +#define SYSCTRL_APBPeriph_DCMIS ((uint32_t)0x00800000) +#define SYSCTRL_APBPeriph_TIMM0 ((uint32_t)0x00200000) +#define SYSCTRL_APBPeriph_GPIO ((uint32_t)0x00100000) +#define SYSCTRL_APBPeriph_I2C0 ((uint32_t)0x00040000) +#define SYSCTRL_APBPeriph_SCI2 ((uint32_t)0x00010000) +#define SYSCTRL_APBPeriph_SCI0 ((uint32_t)0x00004000) +#define SYSCTRL_APBPeriph_HSPI ((uint32_t)0x00002000) +#define SYSCTRL_APBPeriph_SPI2 ((uint32_t)0x00000400) +#define SYSCTRL_APBPeriph_SPI1 ((uint32_t)0x00000200) +#define SYSCTRL_APBPeriph_SPI0 ((uint32_t)0x00000100) +#define SYSCTRL_APBPeriph_UART3 ((uint32_t)0x00000008) +#define SYSCTRL_APBPeriph_UART2 ((uint32_t)0x00000004) +#define SYSCTRL_APBPeriph_UART1 ((uint32_t)0x00000002) +#define SYSCTRL_APBPeriph_UART0 ((uint32_t)0x00000001) +#define SYSCTRL_APBPeriph_ALL ((uint32_t)0xECB5670F) +#define IS_SYSCTRL_APB_PERIPH(PERIPH) ((((PERIPH) & ~SYSCTRL_APBPeriph_ALL) == 0x00) && ((PERIPH) != 0x00)) + +/******************* Bit definition for SOFT_RST2 register *******************/ +#define SYSCTRL_GLB_RESET ((uint32_t)0x80000000) +#define SYSCTRL_CM3_RESET ((uint32_t)0x40000000) +#define SYSCTRL_DMA_RESET ((uint32_t)0x20000000) +#define SYSCTRL_USB_RESET ((uint32_t)0x10000000) +#define SYSCTRL_QR_RESET ((uint32_t)0x00000020) +#define SYSCTRL_OTP_RESET ((uint32_t)0x00000008) +#define SYSCTRL_GPU_RESET ((uint32_t)0x00000004) +#define SYSCTRL_LCD_RESET ((uint32_t)0x00000002) +#define SYSCTRL_CRYPT_RESET ((uint32_t)0x00000001) +#define SYSCTRL_AHBPeriph_RESET_ALL ((uint32_t)0xF000002F) +#define IS_SYSCTRL_AHB_PERIPH_RESET(PERIPH) ((((PERIPH) & ~SYSCTRL_AHBPeriph_RESET_ALL) == 0x00) && ((PERIPH) != 0x00)) + +/******************* Bit definition for PHER_CTRL register *******************/ +#define SYSCTRL_PHER_CTRL_SPI0_SLV_EN ((uint32_t)0x01000000) /* 0:MASTER 1:SLAVE */ +#define SYSCTRL_PHER_CTRL_SCI2_VCCEN_INV ((uint32_t)0x00400000) +#define SYSCTRL_PHER_CTRL_SCI0_VCCEN_INV ((uint32_t)0x00100000) +#define SYSCTRL_PHER_CTRL_SCI2_CDET_INV ((uint32_t)0x00040000) +#define SYSCTRL_PHER_CTRL_SCI0_CDET_INV ((uint32_t)0x00010000) + +/******************* Bit definition for DMA_CHAN REGISTER ********************/ +#define SYSCTRL_PHER_CTRL_DMA_CH0_IF_Pos (0) +#define SYSCTRL_PHER_CTRL_DMA_CH0_IF_Mask (0x3FU<> CACHE_CODE_BUS_TAG_POS) & CACHE_CODE_BUS_TAG_MASK) +#define CACHE_SET_NUM(x) ((x >> CACHE_CODE_BUS_SET_POS) & CACHE_CODE_BUS_SET_MASK) +#define CACHE_OFF_NUM(x) ((x >> CACHE_CODE_BUS_OFFSET_POS) & CACHE_CODE_BUS_OFFSET_MASK) + +typedef enum +{ + CACHE_Encrypt_Mode_All = 0x0, + CACHE_Encrypt_Mode_Zone, +}CACHE_EncryptModeTypeDef; +#define IS_CACHE_ENCRYPT_MODE(MODE) (((MODE) == CACHE_Encrypt_Mode_All) || \ + ((MODE) == CACHE_Encrypt_Mode_Zone)) + +typedef struct +{ + uint32_t I[4]; + uint32_t K[4]; + uint32_t AES_CS; + uint32_t CONFIG; + + uint32_t aes_enable; + uint32_t Address; + uint32_t size; + uint32_t algorithm; + + uint32_t encrypt_mode; + uint32_t encrypt_saddr; + uint32_t encrypt_eaddr; +}CACHE_InitTypeDef; + +void CACHE_Init(CACHE_TypeDef *Cache, CACHE_InitTypeDef *CACHE_InitStruct); +void CACHE_Clean(CACHE_TypeDef *Cache, CACHE_InitTypeDef *CACHE_InitStruct); +void CACHE_CleanAll(CACHE_TypeDef *Cache); + + +#ifdef __cplusplus +} +#endif + +#endif + + +/************************** (C) COPYRIGHT Megahunt *****END OF FILE****/ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_conf.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_conf.h new file mode 100644 index 0000000000..cf2ec9688c --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_conf.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __AIR105_CONF_H +#define __AIR105_CONF_H + +/* Includes ------------------------------------------------------------------*/ +/* Uncomment the line below to enable peripheral header file inclusion */ +#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */ + +#include "string.h" + +#include "air105_cache.h" +#include "air105_dcmi.h" +#include "air105_dma.h" +#include "air105_gpio.h" +#include "air105_i2c.h" +#include "air105_qspi.h" +#include "air105_sysctrl.h" +#include "air105_timer.h" +#include "air105_uart.h" +#include "air105_wdt.h" +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Uncomment the line below to expanse the "assert_param" macro in the + Standard Peripheral Library drivers code */ +/* #define USE_FULL_ASSERT 1 */ + + +#endif + diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_crc.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_crc.h new file mode 100644 index 0000000000..74e632aa82 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_crc.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef __AIR105_CRC_H +#define __AIR105_CRC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + +/* Exported types ------------------------------------------------------------*/ +typedef enum +{ + CRC_16 = 0x01, + CRC_16_Modbus = 0x02, + CRC_CCITT_0xffff = 0x03, + CRC_CCITT_XModem = 0x04, + CRC_32 = 0x05 +}CRC_Param_TypeDef; + +typedef enum +{ + CRC_Poly_16_1021 = 0x01, + CRC_Poly_16_8005 = 0x02, + CRC_Poly_32_04C11DB7 = 0x03 +}CRC_Poly_TypeDef; + +typedef enum +{ + CRC_PolyMode_Normal = 0x01, + CRC_PolyMode_Reversed = 0x02, +}CRC_PolyMode_TypeDef; + +typedef struct +{ + CRC_Poly_TypeDef CRC_Poly; + CRC_PolyMode_TypeDef CRC_PolyMode; + uint32_t CRC_Init_Value; + uint32_t CRC_Xor_Value; +}CRC_ConfigTypeDef; + + +uint32_t CRC_CalcBlockCRC(uint32_t CRC_type, uint8_t *pData, uint32_t len); +uint32_t CRC_Calc(CRC_ConfigTypeDef *CRC_Config, uint8_t *pData, uint32_t len); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_dac.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_dac.h new file mode 100644 index 0000000000..254d36f01a --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_dac.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef __AIR105_DAC_H__ +#define __AIR105_DAC_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Include ------------------------------------------------------------------*/ +#include "air105.h" + + +#define DAC_CR1_IS_RUNNING ((uint32_t)0x20000000) +#define DAC_CR1_POWER_DOWN ((uint32_t)0x00000010) +#define DAC_CR1_FIFO_RESET ((uint32_t)0x00000008) +#define DAC_CR1_DMA_ENABLE ((uint32_t)0x00000004) + + +#define IS_DAC_DATA(DATA) ((DATA) <= 0x3FF) + + +#define DAC_CURR_SEL_MASK ((uint32_t)0x00000020) +#define DAC_CURR_SEL_20K ((uint32_t)0x00000000) +#define DAC_CURR_SEL_2K ((uint32_t)0x00000020) +#define IS_DAC_CURR_SEL(CURR) (((CURR) == DAC_CURR_SEL_20K) || \ + ((CURR) == DAC_CURR_SEL_2K)) + +#define IS_DAC_FIFO_THR(THR) ((THR) <= 0xF) + + +typedef struct _DAC_InitTypeDef +{ + uint32_t DAC_CurrSel; /* DAC mode select */ + uint32_t DAC_TimerExp; /* DAC timer expectation */ + uint32_t DAC_FIFOThr; /* DAC FIFO Threshold */ +} DAC_InitTypeDef; + + +#define DAC_FIFO_DEPTH (16) +#define DAC_IT_STATUS_SHIFT (30) + +#define DAC_IT_FIFO_THR ((uint32_t)0x0002) +#define DAC_IT_FIFO_OVERFLOW ((uint32_t)0x0001) +#define IS_DAC_IT(IT) (((IT) == DAC_IT_FIFO_THR) || \ + ((IT) == DAC_IT_FIFO_OVERFLOW)) + +#define DAC_FLAG_RUNNING (DAC_CR1_IS_RUNNING) +#define DAC_FLAG_OVERFLOW ((uint32_t)0x40000000) +#define IS_DAC_FLAG(FLAG) (((FLAG) == DAC_FLAG_RUNNING) || \ + ((FLAG) == DAC_FLAG_OVERFLOW)) + + +/* Exported functions -------------------------------------------------------*/ +void DAC_Init(DAC_InitTypeDef *DAC_InitStruct); +void DAC_StructInit(DAC_InitTypeDef *DAC_InitStruct); +void DAC_FIFOReset(void); + +void DAC_Cmd(FunctionalState NewState); +void DAC_DMACmd(FunctionalState NewState); + +void DAC_SetData(uint16_t Data); + +FlagStatus DAC_GetFlagStatus(uint32_t DAC_Flag); +void DAC_ClearFlag(uint32_t DAC_Flag); + +void DAC_ITConfig(uint32_t DAC_IT, FunctionalState NewState); +ITStatus DAC_GetITStatus(uint32_t DAC_IT); +void DAC_ClearITPendingBit(uint32_t DAC_IT); + + +#ifdef __cplusplus +} +#endif + +#endif /* __AIR105_DAC_H__ */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_dcmi.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_dcmi.h new file mode 100644 index 0000000000..c2fb2d5970 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_dcmi.h @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef __AIR105_DCMI_H +#define __AIR105_DCMI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + + +/* Exported types ------------------------------------------------------------*/ +/** + * @brief DCMI Init structure definition + */ +typedef struct +{ + uint16_t DCMI_CaptureMode; /*!< Specifies the Capture Mode: Continuous or Snapshot. + This parameter can be a value of @ref DCMI_Capture_Mode */ + + uint16_t DCMI_SynchroMode; /*!< Specifies the Synchronization Mode: Hardware or Embedded. + This parameter can be a value of @ref DCMI_Synchronization_Mode */ + + uint16_t DCMI_PCKPolarity; /*!< Specifies the Pixel clock polarity: Falling or Rising. + This parameter can be a value of @ref DCMI_PIXCK_Polarity */ + + uint16_t DCMI_VSPolarity; /*!< Specifies the Vertical synchronization polarity: High or Low. + This parameter can be a value of @ref DCMI_VSYNC_Polarity */ + + uint16_t DCMI_HSPolarity; /*!< Specifies the Horizontal synchronization polarity: High or Low. + This parameter can be a value of @ref DCMI_HSYNC_Polarity */ + + uint16_t DCMI_CaptureRate; /*!< Specifies the frequency of frame capture: All, 1/2 or 1/4. + This parameter can be a value of @ref DCMI_Capture_Rate */ + + uint16_t DCMI_ExtendedDataMode; /*!< Specifies the data width: 8-bit, 10-bit, 12-bit or 14-bit. + This parameter can be a value of @ref DCMI_Extended_Data_Mode */ + uint32_t DCMI_ByteSelectMode; /*!< Specifies the Capture Select Byte Mode: Select All Bytes, 1 of 2, 1 of 4 or 2 of 4 + This parameter can be a value of @ref DCMI_ByteSelect_Mode */ + uint32_t DCMI_LineSelectMode; /*!< Specifies the Capture Select Line Mode: Select All Lines, Odd Line or Even Line + This parameter can be a value of @ref DCMI_ByteLine_Mode */ + uint32_t DCMI_ClockDiv; /*!< Specifies the DCMI Slave Clock Div: 2~16 from HCLK + This parameter can be a value of @ref DCMI_Clock_Div */ +} DCMI_InitTypeDef; + +/** + * @brief DCMI CROP Init structure definition + */ +typedef struct +{ + uint16_t DCMI_VerticalStartLine; /*!< Specifies the Vertical start line count from which the image capture + will start. This parameter can be a value between 0x00 and 0x1FFF */ + + uint16_t DCMI_HorizontalOffsetCount; /*!< Specifies the number of pixel clocks to count before starting a capture. + This parameter can be a value between 0x00 and 0x3FFF */ + + uint16_t DCMI_VerticalLineCount; /*!< Specifies the number of lines to be captured from the starting point. + This parameter can be a value between 0x00 and 0x3FFF */ + + uint16_t DCMI_CaptureCount; /*!< Specifies the number of pixel clocks to be captured from the starting + point on the same line. + This parameter can be a value between 0x00 and 0x3FFF */ +} DCMI_CROPInitTypeDef; + +/** + * @brief DCMI Embedded Synchronisation CODE Init structure definition + */ +typedef struct +{ + uint8_t DCMI_FrameStartCode; /*!< Specifies the code of the frame start delimiter. */ + uint8_t DCMI_LineStartCode; /*!< Specifies the code of the line start delimiter. */ + uint8_t DCMI_LineEndCode; /*!< Specifies the code of the line end delimiter. */ + uint8_t DCMI_FrameEndCode; /*!< Specifies the code of the frame end delimiter. */ +} DCMI_CodesInitTypeDef; + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup DCMI_Exported_Constants + * @{ + */ + +/** @defgroup DCMI_Capture_Mode + * @{ + */ +#define DCMI_CaptureMode_Continuous ((uint16_t)0x0000) /*!< The received data are transferred continuously + into the destination memory through the DMA */ +#define DCMI_CaptureMode_SnapShot ((uint16_t)0x0002) /*!< Once activated, the interface waits for the start of + frame and then transfers a single frame through the DMA */ +#define IS_DCMI_CAPTURE_MODE(MODE)(((MODE) == DCMI_CaptureMode_Continuous) || \ + ((MODE) == DCMI_CaptureMode_SnapShot)) +/** + * @} + */ + + +/** @defgroup DCMI_Synchronization_Mode + * @{ + */ +#define DCMI_SynchroMode_Hardware ((uint16_t)0x0000) /*!< Hardware synchronization data capture (frame/line start/stop) + is synchronized with the HSYNC/VSYNC signals */ +#define DCMI_SynchroMode_Embedded ((uint16_t)0x0010) /*!< Embedded synchronization data capture is synchronized with + synchronization codes embedded in the data flow */ +#define IS_DCMI_SYNCHRO(MODE)(((MODE) == DCMI_SynchroMode_Hardware) || \ + ((MODE) == DCMI_SynchroMode_Embedded)) +/** + * @} + */ + + +/** @defgroup DCMI_PIXCK_Polarity + * @{ + */ +#define DCMI_PCKPolarity_Falling ((uint16_t)0x0000) /*!< Pixel clock active on Falling edge */ +#define DCMI_PCKPolarity_Rising ((uint16_t)0x0020) /*!< Pixel clock active on Rising edge */ +#define IS_DCMI_PCKPOLARITY(POLARITY)(((POLARITY) == DCMI_PCKPolarity_Falling) || \ + ((POLARITY) == DCMI_PCKPolarity_Rising)) +/** + * @} + */ + + +/** @defgroup DCMI_VSYNC_Polarity + * @{ + */ +#define DCMI_VSPolarity_Low ((uint16_t)0x0000) /*!< Vertical synchronization active Low */ +#define DCMI_VSPolarity_High ((uint16_t)0x0080) /*!< Vertical synchronization active High */ +#define IS_DCMI_VSPOLARITY(POLARITY)(((POLARITY) == DCMI_VSPolarity_Low) || \ + ((POLARITY) == DCMI_VSPolarity_High)) +/** + * @} + */ + + +/** @defgroup DCMI_HSYNC_Polarity + * @{ + */ +#define DCMI_HSPolarity_Low ((uint16_t)0x0000) /*!< Horizontal synchronization active Low */ +#define DCMI_HSPolarity_High ((uint16_t)0x0040) /*!< Horizontal synchronization active High */ +#define IS_DCMI_HSPOLARITY(POLARITY)(((POLARITY) == DCMI_HSPolarity_Low) || \ + ((POLARITY) == DCMI_HSPolarity_High)) +/** + * @} + */ + + +/** @defgroup DCMI_Capture_Rate + * @{ + */ +#define DCMI_CaptureRate_All_Frame ((uint16_t)0x0000) /*!< All frames are captured */ +#define DCMI_CaptureRate_1of2_Frame ((uint16_t)0x0100) /*!< Every alternate frame captured */ +#define DCMI_CaptureRate_1of4_Frame ((uint16_t)0x0200) /*!< One frame in 4 frames captured */ +#define IS_DCMI_CAPTURE_RATE(RATE) (((RATE) == DCMI_CaptureRate_All_Frame) || \ + ((RATE) == DCMI_CaptureRate_1of2_Frame) ||\ + ((RATE) == DCMI_CaptureRate_1of4_Frame)) + +/** @defgroup DCMI_Clock_Div + * @{ + */ +#define DCMI_Clock_Div2 ((uint32_t)0x00000000) +#define DCMI_Clock_Div4 ((uint32_t)0x20000000) +#define DCMI_Clock_Div6 ((uint32_t)0x40000000) +#define DCMI_Clock_Div8 ((uint32_t)0x60000000) +#define DCMI_Clock_Div10 ((uint32_t)0x80000000) +#define DCMI_Clock_Div12 ((uint32_t)0xA0000000) +#define DCMI_Clock_Div14 ((uint32_t)0xC0000000) +#define DCMI_Clock_Div16 ((uint32_t)0xE0000000) +#define IS_DCMI_CLOCK_DIV(DIV) (((DIV) == DCMI_Clock_Div2) ||\ + ((DIV) == DCMI_Clock_Div4) ||\ + ((DIV) == DCMI_Clock_Div6) ||\ + ((DIV) == DCMI_Clock_Div8) ||\ + ((DIV) == DCMI_Clock_Div10) ||\ + ((DIV) == DCMI_Clock_Div12) ||\ + ((DIV) == DCMI_Clock_Div14) ||\ + ((DIV) == DCMI_Clock_Div16)) +#define DCMI_Clock_Div_MSK ((uint32_t)0xE0000000) + +/** + * @} + */ + + +/** @defgroup DCMI_Extended_Data_Mode + * @{ + */ +#define DCMI_ExtendedDataMode_8b ((uint16_t)0x0000) /*!< Interface captures 8-bit data on every pixel clock */ +#define DCMI_ExtendedDataMode_10b ((uint16_t)0x0400) /*!< Interface captures 10-bit data on every pixel clock */ +#define DCMI_ExtendedDataMode_12b ((uint16_t)0x0800) /*!< Interface captures 12-bit data on every pixel clock */ +#define DCMI_ExtendedDataMode_14b ((uint16_t)0x0C00) /*!< Interface captures 14-bit data on every pixel clock */ +#define IS_DCMI_EXTENDED_DATA(DATA) (((DATA) == DCMI_ExtendedDataMode_8b) || \ + ((DATA) == DCMI_ExtendedDataMode_10b) ||\ + ((DATA) == DCMI_ExtendedDataMode_12b) ||\ + ((DATA) == DCMI_ExtendedDataMode_14b)) + +/** @defgroup DCMI_ByteSelectMode + * @{ + */ +#define DCMI_ByteSelect_Mode_AllByte ((uint32_t)0x00000000) +#define DCMI_ByteSelect_Mode_1of2_OddStart ((uint32_t)0x00010000) +#define DCMI_ByteSelect_Mode_1of4_OddStart ((uint32_t)0x00020000) +#define DCMI_ByteSelect_Mode_2of4_OddStart ((uint32_t)0x00030000) +#define DCMI_ByteSelect_Mode_1of2_EvenStart ((uint32_t)0x00050000) +#define DCMI_ByteSelect_Mode_1of4_EvenStart ((uint32_t)0x00060000) +#define DCMI_ByteSelect_Mode_2of4_EvenStart ((uint32_t)0x00070000) +#define IS_DCMI_BYTESELECT_MODE(MODE) (((MODE) == DCMI_ByteSelect_Mode_AllByte) ||\ + ((MODE) == DCMI_ByteSelect_Mode_1of2_OddStart) ||\ + ((MODE) == DCMI_ByteSelect_Mode_1of4_OddStart) ||\ + ((MODE) == DCMI_ByteSelect_Mode_2of4_OddStart) ||\ + ((MODE) == DCMI_ByteSelect_Mode_1of2_EvenStart) ||\ + ((MODE) == DCMI_ByteSelect_Mode_1of4_EvenStart) ||\ + ((MODE) == DCMI_ByteSelect_Mode_2of4_EvenStart)) + +/** @defgroup DCMI_ByteSelectMode + * @{ + */ +#define DCMI_LineSelect_Mode_AllLine ((uint32_t)0x00000000) +#define DCMI_LineSelect_Mode_OddLine ((uint32_t)0x00080000) +#define DCMI_LineSelect_Mode_EvenLine ((uint32_t)0x00180000) +#define IS_DCMI_LINESELECT_MODE(MODE) (((MODE) == DCMI_LineSelect_Mode_AllLine) ||\ + ((MODE) == DCMI_LineSelect_Mode_OddLine) ||\ + ((MODE) == DCMI_LineSelect_Mode_EvenLine)) + +/** + * @} + */ + + +/** @defgroup DCMI_DMA_Request_FIFO_Size + * @{ + */ +#define DCMI_DMARequestFIFOSize_1Word ((uint32_t)0x20000000) /*!< DCMI FIFO DMARequest*/ +#define DCMI_DMARequestFIFOSize_2Word ((uint32_t)0x40000000) /*!< DCMI FIFO DMARequest*/ +#define DCMI_DMARequestFIFOSize_4Word ((uint32_t)0x80000000) /*!< DCMI FIFO DMARequest*/ +#define DCMI_DMARequestFIFOSize_MSK ((uint32_t)0xE0000000) +#define IS_DCMI_DMAREQUESTFIFO_SIZE(SIZE) (((SIZE) == DCMI_DMARequestFIFOSize_1Word) ||\ + ((SIZE) == DCMI_DMARequestFIFOSize_2Word) ||\ + ((SIZE) == DCMI_DMARequestFIFOSize_4Word)) +/** + * @} + */ + + +/** @defgroup DCMI_interrupt_sources + * @{ + */ +#define DCMI_IT_FRAME ((uint16_t)0x0001) +#define DCMI_IT_OVF ((uint16_t)0x0002) +#define DCMI_IT_ERR ((uint16_t)0x0004) +#define DCMI_IT_VSYNC ((uint16_t)0x0008) +#define DCMI_IT_LINE ((uint16_t)0x0010) +#define IS_DCMI_CONFIG_IT(IT) ((((IT) & (uint16_t)0xFFE0) == 0x0000) && ((IT) != 0x0000)) +#define IS_DCMI_GET_IT(IT) (((IT) == DCMI_IT_FRAME) || \ + ((IT) == DCMI_IT_OVF) || \ + ((IT) == DCMI_IT_ERR) || \ + ((IT) == DCMI_IT_VSYNC) || \ + ((IT) == DCMI_IT_LINE)) +/** + * @} + */ + + +/** @defgroup DCMI_Flags + * @{ + */ +/** + * @brief DCMI SR register + */ +#define DCMI_FLAG_HSYNC ((uint16_t)0x2001) +#define DCMI_FLAG_VSYNC ((uint16_t)0x2002) +#define DCMI_FLAG_FNE ((uint16_t)0x2004) +/** + * @brief DCMI RISR register + */ +#define DCMI_FLAG_FRAMERI ((uint16_t)0x0001) +#define DCMI_FLAG_OVFRI ((uint16_t)0x0002) +#define DCMI_FLAG_ERRRI ((uint16_t)0x0004) +#define DCMI_FLAG_VSYNCRI ((uint16_t)0x0008) +#define DCMI_FLAG_LINERI ((uint16_t)0x0010) +/** + * @brief DCMI MISR register + */ +#define DCMI_FLAG_FRAMEMI ((uint16_t)0x1001) +#define DCMI_FLAG_OVFMI ((uint16_t)0x1002) +#define DCMI_FLAG_ERRMI ((uint16_t)0x1004) +#define DCMI_FLAG_VSYNCMI ((uint16_t)0x1008) +#define DCMI_FLAG_LINEMI ((uint16_t)0x1010) +#define IS_DCMI_GET_FLAG(FLAG) (((FLAG) == DCMI_FLAG_HSYNC) || \ + ((FLAG) == DCMI_FLAG_VSYNC) || \ + ((FLAG) == DCMI_FLAG_FNE) || \ + ((FLAG) == DCMI_FLAG_FRAMERI) || \ + ((FLAG) == DCMI_FLAG_OVFRI) || \ + ((FLAG) == DCMI_FLAG_ERRRI) || \ + ((FLAG) == DCMI_FLAG_VSYNCRI) || \ + ((FLAG) == DCMI_FLAG_LINERI) || \ + ((FLAG) == DCMI_FLAG_FRAMEMI) || \ + ((FLAG) == DCMI_FLAG_OVFMI) || \ + ((FLAG) == DCMI_FLAG_ERRMI) || \ + ((FLAG) == DCMI_FLAG_VSYNCMI) || \ + ((FLAG) == DCMI_FLAG_LINEMI)) + +#define IS_DCMI_CLEAR_FLAG(FLAG) ((((FLAG) & (uint16_t)0xFFE0) == 0x0000) && ((FLAG) != 0x0000)) + +/** + * @brief set dcmi input from out signal + */ +#define DCMI_FROM_OUT (0x1<<13) + +/* Function used to set the DCMI configuration to the default reset state ****/ +void DCMI_DeInit(void); + +/* Initialization and Configuration functions *********************************/ +void DCMI_Init(DCMI_InitTypeDef* DCMI_InitStruct); +void DCMI_StructInit(DCMI_InitTypeDef* DCMI_InitStruct); +void DCMI_CROPConfig(DCMI_CROPInitTypeDef* DCMI_CROPInitStruct); +void DCMI_CROPCmd(FunctionalState NewState); +void DCMI_JPEGCmd(FunctionalState NewState); +void DCMI_SetDMARequsetFIFOSize(uint32_t NewFIFOSize); +void DCMI_SetExtInput(void); + +/* Image capture functions ****************************************************/ +void DCMI_Cmd(FunctionalState NewState); +void DCMI_CaptureCmd(FunctionalState NewState); +uint32_t DCMI_ReadData(void); +uint32_t DCMI_GetFIFODataWordNum(void); + +/* Interrupts and flags management functions **********************************/ +void DCMI_ITConfig(uint16_t DCMI_IT, FunctionalState NewState); +FlagStatus DCMI_GetFlagStatus(uint16_t DCMI_FLAG); +void DCMI_ClearFlag(uint16_t DCMI_FLAG); +ITStatus DCMI_GetITStatus(uint16_t DCMI_IT); +void DCMI_ClearITPendingBit(uint16_t DCMI_IT); + +#ifdef __cplusplus +} +#endif + +#endif /*__AIR105_DCMI_H */ + + diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_dma.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_dma.h new file mode 100644 index 0000000000..b7638b349e --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_dma.h @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef __AIR105_DMA_H +#define __AIR105_DMA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + +typedef struct +{ + uint32_t DMA_Peripheral; + + uint32_t DMA_PeripheralBaseAddr; /*!< Specifies the peripheral base address for DMAy Channelx. */ + + uint32_t DMA_MemoryBaseAddr; /*!< Specifies the memory base address for DMAy Channelx. */ + + uint32_t DMA_DIR; /*!< Specifies if the peripheral is the source or destination. + This parameter can be a value of @ref DMA_data_transfer_direction */ + + uint32_t DMA_PeripheralInc; /*!< Specifies whether the Peripheral address register is incremented or not. + This parameter can be a value of @ref DMA_incremented_mode */ + + uint32_t DMA_MemoryInc; /*!< Specifies whether the memory address register is incremented or not. + This parameter can be a value of @ref DMA_incremented_mode */ + + uint32_t DMA_PeripheralDataSize; /*!< Specifies the Peripheral data item width. + This parameter can be a value of @ref DMA_data_size */ + + uint32_t DMA_MemoryDataSize; /*!< Specifies the Memory data item width. + This parameter can be a value of @ref DMA_data_size */ + + uint32_t DMA_PeripheralBurstSize; /*!< Specifies the Peripheral Number of data items during per burst transaction. + read or write from the Peripheral every time a burst transaction request + This parameter can be a value of @ref DMA_burst_size */ + + uint32_t DMA_MemoryBurstSize; /*!< Specifies the Memory Number of data items during per burst transaction. + read or write from the Memory every time a burst transaction request + This parameter can be a value of @ref DMA_burst_size */ + + uint32_t DMA_PeripheralHandShake; /*!< Specifies the HandShake to control the DMA transacation. + This parameter can be a value of @ref DMA_peripheral_handshake */ + + uint32_t DMA_BlockSize; /*!< Specifies the Total Number of data items during the transaction. */ + + uint32_t DMA_Priority; /*!< Specifies the software priority for the DMAy Channelx. + This parameter can be a value of @ref DMA_priority_level */ +}DMA_InitTypeDef; + +/** + * DMA多块传输内存表 + * + */ +typedef struct _lli +{ + uint32_t SAR; + uint32_t DAR; + uint32_t LLP; + uint32_t CTL_L; + uint32_t CTL_H; + uint32_t DSTAT; +}LLI; + +/**多块传输模式 + * @} + */ +#define Multi_Block_MODE01 (uint8_t)0x00 /*Single-block or last transfer of multi-block*/ +#define Multi_Block_MODE02 (uint8_t)0x01 /*Auto-reload multi-block transfer with contiguous SAR*/ +#define Multi_Block_MODE03 (uint8_t)0x02 /*Auto-reload multi-block transfer with contiguous DAR*/ +#define Multi_Block_MODE04 (uint8_t)0x03 /*Auto-reload multi-block transfer*/ +#define Multi_Block_MODE05 (uint8_t)0x04 /*Single-block or last transfer of multi-block*/ +#define Multi_Block_MODE06 (uint8_t)0x05 /*Linked list multi-block transfer with contiguous SAR*/ +#define Multi_Block_MODE07 (uint8_t)0x06 /*Linked list multi-block transfer with auto-reload SAR*/ +#define Multi_Block_MODE08 (uint8_t)0x07 /*Linked list multi-block transfer with contiguous DAR*/ +#define Multi_Block_MODE09 (uint8_t)0x08 /*Linked list multi-block transfer with auto-reload DAR*/ +#define Multi_Block_MODE10 (uint8_t)0x09 /*Linked list multi-block transfer*/ + +/** @defgroup DMA_data_transfer_direction + * @{ + */ + +#define DMA_DIR_Memory_To_Memory ((uint32_t)0x0000) +#define DMA_DIR_Memory_To_Peripheral ((uint32_t)0x0001) +#define DMA_DIR_Peripheral_To_Memory ((uint32_t)0x0002) + +/** + * @} + */ + +/** @defgroup DMA_incremented_mode + * @{ + */ + +#define DMA_Inc_Increment ((uint32_t)0x00000000) +#define DMA_Inc_Decrement ((uint32_t)0x00000001) +#define DMA_Inc_Nochange ((uint32_t)0x00000002) +#define IS_DMA_INC_STATE(STATE) (((STATE) == DMA_Inc_Increment) || \ + ((STATE) == DMA_Inc_Decrement) || \ + ((STATE) == DMA_Inc_Nochange)) +/** + * @} + */ + +/** @defgroup DMA_data_size + * @{ + */ + +#define DMA_DataSize_Byte ((uint32_t)0x0000) +#define DMA_DataSize_HalfWord ((uint32_t)0x0001) +#define DMA_DataSize_Word ((uint32_t)0x0002) +#define IS_DMA_DATA_SIZE(SIZE) (((SIZE) == DMA_DataSize_Byte) || \ + ((SIZE) == DMA_DataSize_HalfWord) || \ + ((SIZE) == DMA_DataSize_Word)) +/** + * @} + */ + +/** @defgroup DMA_burst_size + * @{ + */ +#define DMA_BurstSize_1 ((uint32_t)0x00) +#define DMA_BurstSize_4 ((uint32_t)0x01) +#define DMA_BurstSize_8 ((uint32_t)0x02) +#define DMA_BurstSize_16 ((uint32_t)0x03) +#define DMA_BurstSize_32 ((uint32_t)0x04) +/** + * @} + */ + +/** @defgroup DMA_peripheral_handshake + * @{ + */ +#define DMA_PeripheralHandShake_Hardware ((uint32_t)0x0000) +#define DMA_PeripheralHandShake_Software ((uint32_t)0x0001) +/** + * @} + */ + +/** @defgroup DMA_Priority + * @{ + */ +#define DMA_Priority_0 ((uint32_t)0x00000000) +#define DMA_Priority_1 ((uint32_t)0x00000020) +#define DMA_Priority_2 ((uint32_t)0x00000040) +#define DMA_Priority_3 ((uint32_t)0x00000060) +#define DMA_Priority_4 ((uint32_t)0x00000080) +#define DMA_Priority_5 ((uint32_t)0x000000A0) +#define DMA_Priority_6 ((uint32_t)0x000000C0) + +/** + * @} + */ + +/** @defgroup DMA_IT + * @{ + */ +#define DMA_IT_BlockTransferComplete ((uint32_t)0x01) +#define DMA_IT_DestinationTransactionComplete ((uint32_t)0x02) +#define DMA_IT_Error ((uint32_t)0x04) +#define DMA_IT_SourceTransactionComplete ((uint32_t)0x08) +#define DMA_IT_DMATransferComplete ((uint32_t)0x10) +/** + * @} + */ + +void DMA_Init(DMA_TypeDef* DMA_Channelx, DMA_InitTypeDef* DMA_InitStruct); +void DMA_ChannelCmd(DMA_TypeDef* DMA_Channelx, FunctionalState NewState); +void DMA_Cmd(FunctionalState NewState); +void DMA_ChannelConfig(DMA_TypeDef* DMA_Channelx, uint32_t DMA_Peripheral, uint32_t DMA_DIR); +void DMA_SetSRCAddress(DMA_TypeDef* DMA_Channelx, uint32_t Address); +void DMA_SetDSRAddress(DMA_TypeDef* DMA_Channelx, uint32_t Address); + +void DMA_ITConfig(DMA_TypeDef* DMA_Channelx, uint32_t DMA_IT, FunctionalState NewState); + +FlagStatus DMA_GetFlagStatus(uint32_t DMA_FLAG); +void DMA_ClearFlag(uint32_t DMA_FLAG); + +FunctionalState DMA_IsChannelEnabled(DMA_TypeDef* DMA_Channelx); + +ITStatus DMA_GetITStatus(DMA_TypeDef* DMA_Channelx,uint32_t DMA_IT); +FlagStatus DMA_GetRawStatus(DMA_TypeDef* DMA_Channelx,uint32_t DMA_IT); +void DMA_ClearITPendingBit(DMA_TypeDef* DMA_Channelx,uint32_t DMA_IT); + +void DMA_MultiBlockInit(DMA_TypeDef* DMA_Channelx, DMA_InitTypeDef* DMA_InitStruct ,\ + LLI *first_lli,uint8_t Multi_Block_Mode); +void DMA_InitLLI(DMA_TypeDef* DMA_Channelx,LLI *lli,LLI *next_lli, + void *src_addr,void *dest_addr,uint16_t btsize); +uint32_t DMA_GetTransferNum(DMA_TypeDef* DMA_Channelx, uint32_t first_adr); + +#ifdef __cplusplus +} +#endif + +#endif + +/************************** (C) COPYRIGHT Megahunt *****END OF FILE****/ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_exti.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_exti.h new file mode 100644 index 0000000000..392135e75e --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_exti.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef __AIR105_EXTI_H +#define __AIR105_EXTI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes -----------------------------------------------------------------*/ +#include "air105.h" + + +/** + * @brief EXTI Trigger enumeration + */ +typedef enum +{ + EXTI_Trigger_Off = (uint32_t)0x00, + EXTI_Trigger_Rising = (uint32_t)0x01, + EXTI_Trigger_Falling = (uint32_t)0x02, + EXTI_Trigger_Rising_Falling = (uint32_t)0x03 +}EXTI_TriggerTypeDef; + +#define IS_EXTI_TRIGGER(TRIGGER) (((TRIGGER) == EXTI_Trigger_Off) || \ + ((TRIGGER) == EXTI_Trigger_Rising) || \ + ((TRIGGER) == EXTI_Trigger_Falling) || \ + ((TRIGGER) == EXTI_Trigger_Rising_Falling)) +/** + * @} + */ + + +/** @defgroup EXTI_Lines + * @{ + */ +#define EXTI_Line0 ((uint32_t)0x0000) /*!< External interrupt line 0 */ +#define EXTI_Line1 ((uint32_t)0x0001) /*!< External interrupt line 1 */ +#define EXTI_Line2 ((uint32_t)0x0002) /*!< External interrupt line 2 */ +#define EXTI_Line3 ((uint32_t)0x0003) /*!< External interrupt line 3 */ +#define EXTI_Line4 ((uint32_t)0x0004) /*!< External interrupt line 4 */ +#define EXTI_Line5 ((uint32_t)0x0005) /*!< External interrupt line 5 */ + +#define IS_EXTI_LINE(LINE) (((LINE) == EXTI_Line0) || ((LINE) == EXTI_Line1) || \ + ((LINE) == EXTI_Line2) || ((LINE) == EXTI_Line3) || \ + ((LINE) == EXTI_Line4) || ((LINE) == EXTI_Line5)) +/** + * @} + */ + +/** @defgroup EXTI_PinSource + * @{ + */ +#define EXTI_PinSource0 ((uint32_t)0x0001) /*!< Pin 0 selected */ +#define EXTI_PinSource1 ((uint32_t)0x0002) /*!< Pin 1 selected */ +#define EXTI_PinSource2 ((uint32_t)0x0004) /*!< Pin 2 selected */ +#define EXTI_PinSource3 ((uint32_t)0x0008) /*!< Pin 3 selected */ +#define EXTI_PinSource4 ((uint32_t)0x0010) /*!< Pin 4 selected */ +#define EXTI_PinSource5 ((uint32_t)0x0020) /*!< Pin 5 selected */ +#define EXTI_PinSource6 ((uint32_t)0x0040) /*!< Pin 6 selected */ +#define EXTI_PinSource7 ((uint32_t)0x0080) /*!< Pin 7 selected */ +#define EXTI_PinSource8 ((uint32_t)0x0100) /*!< Pin 8 selected */ +#define EXTI_PinSource9 ((uint32_t)0x0200) /*!< Pin 9 selected */ +#define EXTI_PinSource10 ((uint32_t)0x0400) /*!< Pin 10 selected */ +#define EXTI_PinSource11 ((uint32_t)0x0800) /*!< Pin 11 selected */ +#define EXTI_PinSource12 ((uint32_t)0x1000) /*!< Pin 12 selected */ +#define EXTI_PinSource13 ((uint32_t)0x2000) /*!< Pin 13 selected */ +#define EXTI_PinSource14 ((uint32_t)0x4000) /*!< Pin 14 selected */ +#define EXTI_PinSource15 ((uint32_t)0x8000) /*!< Pin 15 selected */ +#define EXTI_PinSourceAll ((uint32_t)0xffff) /*!< Pin All selected */ + +#define IS_EXTI_PIN_SOURCE(PIN) (((((PIN) & ~(uint32_t)0xFFFF)) == 0x00) && ((PIN) != (uint32_t)0x00)) +/** + * @} + */ + + +/** @defgroup EXTI_Exported_Functions + * @{ + */ + +void EXTI_DeInit(void); +void EXTI_LineConfig(uint32_t EXTI_Line, uint32_t EXTI_PinSource, EXTI_TriggerTypeDef EXTI_Trigger); +uint32_t EXTI_GetITStatus(void); +uint32_t EXTI_GetITLineStatus(uint32_t EXTI_Line); +void EXTI_ClearITPendingBit(uint32_t EXTI_Line); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif // __AIR105_EXTI_H + +/************************** (C) COPYRIGHT Megahunt *****END OF FILE****/ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_gpio.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_gpio.h new file mode 100644 index 0000000000..88f15d9e99 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_gpio.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef __AIR105_GPIO_H +#define __AIR105_GPIO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + + +/** + * @brief Configuration Mode enumeration + */ +typedef enum +{ + GPIO_Mode_IN_FLOATING = 0x01, + GPIO_Mode_IPU = 0x02, + GPIO_Mode_Out_OD = 0x03, + GPIO_Mode_Out_OD_PU = 0x04, + GPIO_Mode_Out_PP = 0x05 +}GPIO_ModeTypeDef; +#define IS_GPIO_MODE(MODE) (((MODE) == GPIO_Mode_IN_FLOATING) || \ + ((MODE) == GPIO_Mode_IPU) || \ + ((MODE) == GPIO_Mode_Out_OD) || \ + ((MODE) == GPIO_Mode_Out_PP) || \ + ((MODE) == GPIO_Mode_Out_OD_PU)) + +/** + * @brief GPIO Remap Type definition + */ +typedef enum +{ + GPIO_Remap_0 = 0x01, + GPIO_Remap_1 = 0x02, + GPIO_Remap_2 = 0x03, + GPIO_Remap_3 = 0x04, +}GPIO_RemapTypeDef; +#define IS_GET_GPIO_REMAP(REMAP) (((REMAP) == GPIO_Remap_0) || \ + ((REMAP) == GPIO_Remap_1) || \ + ((REMAP) == GPIO_Remap_2) || \ + ((REMAP) == GPIO_Remap_3) ) + +/** + * @brief GPIO Init structure definition + */ +typedef struct +{ + uint32_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured. + This parameter can be any value of @ref GPIO_pins_define */ + GPIO_ModeTypeDef GPIO_Mode; + + GPIO_RemapTypeDef GPIO_Remap; +}GPIO_InitTypeDef; + +/** + * @brief Bit_SET and Bit_RESET enumeration + */ +typedef enum +{ + Bit_RESET = 0, + Bit_SET +}BitAction; + +/** + * @} + */ + +/** @defgroup GPIO_Exported_Constants + * @{ + */ + +/** @defgroup GPIO_pins_define + * @{ + */ +#define IS_GPIO_PERIPH(PERIPH) (((PERIPH) == GPIOA) || \ + ((PERIPH) == GPIOB) || \ + ((PERIPH) == GPIOC) || \ + ((PERIPH) == GPIOD) || \ + ((PERIPH) == GPIOE) || \ + ((PERIPH) == GPIOF)) + +#define GPIO_Pin_0 ((uint16_t)0x0001) /*!< Pin 0 selected */ +#define GPIO_Pin_1 ((uint16_t)0x0002) /*!< Pin 1 selected */ +#define GPIO_Pin_2 ((uint16_t)0x0004) /*!< Pin 2 selected */ +#define GPIO_Pin_3 ((uint16_t)0x0008) /*!< Pin 3 selected */ +#define GPIO_Pin_4 ((uint16_t)0x0010) /*!< Pin 4 selected */ +#define GPIO_Pin_5 ((uint16_t)0x0020) /*!< Pin 5 selected */ +#define GPIO_Pin_6 ((uint16_t)0x0040) /*!< Pin 6 selected */ +#define GPIO_Pin_7 ((uint16_t)0x0080) /*!< Pin 7 selected */ +#define GPIO_Pin_8 ((uint16_t)0x0100) /*!< Pin 8 selected */ +#define GPIO_Pin_9 ((uint16_t)0x0200) /*!< Pin 9 selected */ +#define GPIO_Pin_10 ((uint16_t)0x0400) /*!< Pin 10 selected */ +#define GPIO_Pin_11 ((uint16_t)0x0800) /*!< Pin 11 selected */ +#define GPIO_Pin_12 ((uint16_t)0x1000) /*!< Pin 12 selected */ +#define GPIO_Pin_13 ((uint16_t)0x2000) /*!< Pin 13 selected */ +#define GPIO_Pin_14 ((uint16_t)0x4000) /*!< Pin 14 selected */ +#define GPIO_Pin_15 ((uint16_t)0x8000) /*!< Pin 15 selected */ +#define GPIO_Pin_All ((uint16_t)0xffff) /*!< Pin All selected */ + +#define IS_GPIO_PIN(PIN) (((((PIN) & ~(uint16_t)0xFFFF)) == 0x00) && ((PIN) != (uint16_t)0x00)) + +#define IS_GET_GPIO_PIN(PIN) (((PIN) == GPIO_Pin_0) || \ + ((PIN) == GPIO_Pin_1) || \ + ((PIN) == GPIO_Pin_2) || \ + ((PIN) == GPIO_Pin_3) || \ + ((PIN) == GPIO_Pin_4) || \ + ((PIN) == GPIO_Pin_5) || \ + ((PIN) == GPIO_Pin_6) || \ + ((PIN) == GPIO_Pin_7) || \ + ((PIN) == GPIO_Pin_8) || \ + ((PIN) == GPIO_Pin_9) || \ + ((PIN) == GPIO_Pin_10) || \ + ((PIN) == GPIO_Pin_11) || \ + ((PIN) == GPIO_Pin_12) || \ + ((PIN) == GPIO_Pin_13) || \ + ((PIN) == GPIO_Pin_14) || \ + ((PIN) == GPIO_Pin_15)) +/** + * @} + */ + +#define GPIO_PinSource0 0x00 +#define GPIO_PinSource1 0x01 +#define GPIO_PinSource2 0x02 +#define GPIO_PinSource3 0x03 +#define GPIO_PinSource4 0x04 +#define GPIO_PinSource5 0x05 +#define GPIO_PinSource6 0x06 +#define GPIO_PinSource7 0x07 +#define GPIO_PinSource8 0x08 +#define GPIO_PinSource9 0x09 +#define GPIO_PinSource10 0x0A +#define GPIO_PinSource11 0x0B +#define GPIO_PinSource12 0x0C +#define GPIO_PinSource13 0x0D +#define GPIO_PinSource14 0x0E +#define GPIO_PinSource15 0x0F + +/** @defgroup GPIO_Port_Sources + * @{ + */ +#define GPIO_PortSourceGPIOA ((uint32_t)0x00) +#define GPIO_PortSourceGPIOB ((uint32_t)0x01) +#define GPIO_PortSourceGPIOC ((uint32_t)0x02) +#define GPIO_PortSourceGPIOD ((uint32_t)0x03) +#define GPIO_PortSourceGPIOE ((uint32_t)0x04) +#define GPIO_PortSourceGPIOF ((uint32_t)0x05) + + +#define IS_GPIO_PORT_SOURCE(PORTSOURCE) (((PORTSOURCE) == GPIO_PortSourceGPIOA) || \ + ((PORTSOURCE) == GPIO_PortSourceGPIOB) || \ + ((PORTSOURCE) == GPIO_PortSourceGPIOC) || \ + ((PORTSOURCE) == GPIO_PortSourceGPIOD) || \ + ((PORTSOURCE) == GPIO_PortSourceGPIOE) || \ + ((PORTSOURCE) == GPIO_PortSourceGPIOF)) + +/** + * @} + */ + +/** @defgroup GPIO_WakeMode + * @{ + */ +typedef enum +{ + GPIO_WakeMode_Now = (uint32_t)0x00, + GPIO_WakeMode_AfterGlitch = (uint32_t)0x01 +}GPIO_WakeModeTypeDef; + +#define IS_GPIO_WAKE_MODE(MODE) (((MODE) == GPIO_WakeMode_Now) || \ + ((MODE) == GPIO_WakeMode_AfterGlitch)) +/** + * @} + */ + +/** @defgroup GPIO_Exported_Functions + * @{ + */ + +void GPIO_DeInit(void); +void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct); +void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct); + +uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx); + +uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx); + +void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal); +void GPIO_PullUpCmd(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, FunctionalState NewState); + +void GPIO_PinRemapConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_RemapTypeDef GPIO_Remap); + +void GPIO_WakeEvenDeInit(void); +void GPIO_WakeEvenConfig(uint32_t GPIO_PortSource, uint32_t GPIO_Pin, FunctionalState NewState); +void GPIO_WakeModeConfig(GPIO_WakeModeTypeDef GPIO_WakeMode); + +#ifdef __cplusplus +} +#endif + +#endif + +/************************** (C) COPYRIGHT Megahunt *****END OF FILE****/ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_hspim.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_hspim.h new file mode 100644 index 0000000000..0c14b34149 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_hspim.h @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef __AIR105_HSPIM_H +#define __AIR105_HSPIM_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "air105.h" + +typedef struct +{ + uint8_t HSPIM_Enable; + uint8_t HSPIM_Mode; + uint8_t HSPIM_FirstBit; + uint8_t HSPIM_CPOL; + uint8_t HSPIM_CPHA; + uint8_t HSPIM_DivideEnable; + uint8_t HSPIM_BaudRatePrescaler; + uint8_t HSPIM_ReceiveDataLength; + uint8_t HSPIM_RXFIFOFullThreshold; + uint8_t HSPIM_TXFIFOEmptyThreshold; +}HSPIM_InitTypeDef; + +typedef struct +{ + uint8_t HSPIM_DMAReceiveEnable; + uint8_t HSPIM_DMATransmitEnable; + uint8_t HSPIM_DMAReceiveLevel; + uint8_t HSPIM_DMATransmitLevel; +}HSPIM_DMAInitTypeDef; + + +/** @defgroup HSPIM_Mode + * @{ + */ + +#define HSPIM_MODE_STANDARD (0x01) +#define HSPIM_MODE_DUAL_RECEIVE (0x02) +#define HSPIM_MODE_DUAL_TRANSMIT (0x03) +#define HSPIM_MODE_QUAD_RECEIVE (0x04) +#define HSPIM_MODE_QUAD_TRANSMIT (0x05) +#define IS_HSPIM_MODE(MODE) (((MODE) == HSPIM_MODE_STANDARD) || \ + ((MODE) == HSPIM_MODE_DUAL_RECEIVE) || \ + ((MODE) == HSPIM_MODE_DUAL_TRANSMIT) || \ + ((MODE) == HSPIM_MODE_QUAD_RECEIVE) || \ + ((MODE) == HSPIM_MODE_QUAD_TRANSMIT)) +/** + * @} + */ + +/** @defgroup HSPIM_Clock_Polarity + * @{ + */ + +#define HSPIM_CPOL_LOW (0x00) +#define HSPIM_CPOL_HIGH (0x01) +#define IS_HSPIM_CPOL(CPOL) (((CPOL) == HSPIM_CPOL_LOW)|| \ + ((CPOL) == HSPIM_CPOL_HIGH)) +/** + * @} + */ + + +/** @defgroup HSPIM_Clock_Phase + * @{ + */ + +#define HSPIM_CPHA_1EDGE (0x00) +#define HSPIM_CPHA_2EDGE (0x01) +#define IS_HSPIM_CPHA(CPHA) (((CPHA) == HSPIM_CPHA_1EDGE) || \ + (CPHA) == HSPIM_CPHA_2EDGE) +/** + * @} + */ + +/** @defgroup HSPIM_First_Bit + * @{ + */ + +#define HSPIM_FIRST_BIT_MSB (0x00) +#define HSPIM_FIRST_BIT_LSB (0x01) +#define IS_HSPIM_FIRST_BIT(BIT) (((BIT) == HSPIM_FIRST_BIT_MSB) || \ + ((BIT) == HSPIM_FIRST_BIT_LSB)) +/** + * @} + */ + +/** @defgroup HSPIM_BaudRate_Prescaler + * @{ + */ +#define HSPIM_BAUDRATE_PRESCALER_2 (0x01) +#define HSPIM_BAUDRATE_PRESCALER_4 (0x02) +#define HSPIM_BAUDRATE_PRESCALER_8 (0x04) +#define HSPIM_BAUDRATE_PRESCALER_16 (0x08) +#define HSPIM_BAUDRATE_PRESCALER_32 (0x10) +#define IS_HSPIM_BAUDRATE_PRESCALER(PRESCALER) (((PRESCALER) == HSPIM_BAUDRATE_PRESCALER_2) || \ + ((PRESCALER) == HSPIM_BAUDRATE_PRESCALER_4) || \ + ((PRESCALER) == HSPIM_BAUDRATE_PRESCALER_8) || \ + ((PRESCALER) == HSPIM_BAUDRATE_PRESCALER_16) || \ + ((PRESCALER) == HSPIM_BAUDRATE_PRESCALER_32)) +/** + * @} + */ + +/** @defgroup HSPIM_Receive_Data_Length + * @{ + */ +#define HSPIM_RECEIVE_DATA_LENGTH_1_BYTE (0x00) +#define HSPIM_RECEIVE_DATA_LENGTH_2_BYTE (0x01) +#define HSPIM_RECEIVE_DATA_LENGTH_3_BYTE (0x02) +#define HSPIM_RECEIVE_DATA_LENGTH_4_BYTE (0x03) +#define HSPIM_RECEIVE_DATA_LENGTH_5_BYTE (0x04) +#define HSPIM_RECEIVE_DATA_LENGTH_6_BYTE (0x05) +#define HSPIM_RECEIVE_DATA_LENGTH_7_BYTE (0x06) +#define HSPIM_RECEIVE_DATA_LENGTH_8_BYTE (0x07) +#define HSPIM_RECEIVE_DATA_LENGTH_9_BYTE (0x08) +#define HSPIM_RECEIVE_DATA_LENGTH_10_BYTE (0x09 +#define HSPIM_RECEIVE_DATA_LENGTH_11_BYTE (0x0A) +#define HSPIM_RECEIVE_DATA_LENGTH_12_BYTE (0x0B) +#define HSPIM_RECEIVE_DATA_LENGTH_13_BYTE (0x0C) +#define HSPIM_RECEIVE_DATA_LENGTH_14_BYTE (0x0D) +#define HSPIM_RECEIVE_DATA_LENGTH_15_BYTE (0x0E) +#define HSPIM_RECEIVE_DATA_LENGTH_16_BYTE (0x0F) +#define HSPIM_RECEIVE_DATA_LENGTH_32_BYTE (0x1F) + +/** + * @} + */ + +/** @defgroup HSPIM_TXFIFOEmptyThreshold + * @{ + */ +#define HSPIM_TX_FIFO_EMPTY_THRESHOLD_1 ((uint32_t)0x0001) +#define HSPIM_TX_FIFO_EMPTY_THRESHOLD_2 ((uint32_t)0x0002) +#define HSPIM_TX_FIFO_EMPTY_THRESHOLD_3 ((uint32_t)0x0003) +#define HSPIM_TX_FIFO_EMPTY_THRESHOLD_4 ((uint32_t)0x0004) +#define HSPIM_TX_FIFO_EMPTY_THRESHOLD_5 ((uint32_t)0x0005) +#define HSPIM_TX_FIFO_EMPTY_THRESHOLD_6 ((uint32_t)0x0006) +#define HSPIM_TX_FIFO_EMPTY_THRESHOLD_7 ((uint32_t)0x0007) +#define HSPIM_TX_FIFO_EMPTY_THRESHOLD_8 ((uint32_t)0x0008) +#define HSPIM_TX_FIFO_EMPTY_THRESHOLD_9 ((uint32_t)0x0009) +#define HSPIM_TX_FIFO_EMPTY_THRESHOLD_10 ((uint32_t)0x000A) +#define HSPIM_TX_FIFO_EMPTY_THRESHOLD_11 ((uint32_t)0x000B) +#define HSPIM_TX_FIFO_EMPTY_THRESHOLD_12 ((uint32_t)0x000C) +#define HSPIM_TX_FIFO_EMPTY_THRESHOLD_13 ((uint32_t)0x000D) +#define HSPIM_TX_FIFO_EMPTY_THRESHOLD_14 ((uint32_t)0x000E) +#define HSPIM_TX_FIFO_EMPTY_THRESHOLD_15 ((uint32_t)0x000F) +#define HSPIM_TX_FIFO_EMPTY_THRESHOLD_31 ((uint32_t)0x001F) +#define HSPIM_TX_FIFO_EMPTY_THRESHOLD_63 ((uint32_t)0x003F) + +#define IS_HSPIM_TX_FIFO_EMPTY_THRESHOLD(THRESHOLD) ((((int32_t)(THRESHOLD)) >= HSPIM_TX_FIFO_EMPTY_THRESHOLD_1) && \ + (((uint32_t)(THRESHOLD)) <= HSPIM_TX_FIFO_EMPTY_THRESHOLD_63)) +/** + * @} + */ + + +/** @defgroup HSPIM_RXFIFOFullThreshold + * @{ + */ +#define HSPIM_RX_FIFO_FULL_THRESHOLD_1 ((uint32_t)0x0001) +#define HSPIM_RX_FIFO_FULL_THRESHOLD_2 ((uint32_t)0x0002) +#define HSPIM_RX_FIFO_FULL_THRESHOLD_3 ((uint32_t)0x0003) +#define HSPIM_RX_FIFO_FULL_THRESHOLD_4 ((uint32_t)0x0004) +#define HSPIM_RX_FIFO_FULL_THRESHOLD_5 ((uint32_t)0x0005) +#define HSPIM_RX_FIFO_FULL_THRESHOLD_6 ((uint32_t)0x0006) +#define HSPIM_RX_FIFO_FULL_THRESHOLD_7 ((uint32_t)0x0007) +#define HSPIM_RX_FIFO_FULL_THRESHOLD_8 ((uint32_t)0x0008) +#define HSPIM_RX_FIFO_FULL_THRESHOLD_9 ((uint32_t)0x0009) +#define HSPIM_RX_FIFO_FULL_THRESHOLD_10 ((uint32_t)0x000A) +#define HSPIM_RX_FIFO_FULL_THRESHOLD_11 ((uint32_t)0x000B) +#define HSPIM_RX_FIFO_FULL_THRESHOLD_12 ((uint32_t)0x000C) +#define HSPIM_RX_FIFO_FULL_THRESHOLD_13 ((uint32_t)0x000D) +#define HSPIM_RX_FIFO_FULL_THRESHOLD_14 ((uint32_t)0x000E) +#define HSPIM_RX_FIFO_FULL_THRESHOLD_15 ((uint32_t)0x000F) +#define HSPIM_RX_FIFO_FULL_THRESHOLD_16 ((uint32_t)0x0010) +#define HSPIM_RX_FIFO_FULL_THRESHOLD_32 ((uint32_t)0x0020) +#define HSPIM_RX_FIFO_FULL_THRESHOLD_63 ((uint32_t)0x003F) + + +#define IS_HSPIM_RX_FIFO_FULL_THRESHOLD(THRESHOLD) ((((uint32_t)(THRESHOLD)) >= HSPIM_RX_FIFO_FULL_THRESHOLD_1) && \ + (((uint32_t)(THRESHOLD)) <= HSPIM_RX_FIFO_FULL_THRESHOLD_63)) + +/** + * @} + */ + +/** @defgroup SPI_DMAReceiveLevel + * @{ + */ +#define HSPIM_DMA_RECEIVE_LEVEL_1 ((uint32_t)0x0001) +#define HSPIM_DMA_RECEIVE_LEVEL_2 ((uint32_t)0x0002) +#define HSPIM_DMA_RECEIVE_LEVEL_3 ((uint32_t)0x0003) +#define HSPIM_DMA_RECEIVE_LEVEL_4 ((uint32_t)0x0004) +#define HSPIM_DMA_RECEIVE_LEVEL_5 ((uint32_t)0x0005) +#define HSPIM_DMA_RECEIVE_LEVEL_6 ((uint32_t)0x0006) +#define HSPIM_DMA_RECEIVE_LEVEL_7 ((uint32_t)0x0007) +#define HSPIM_DMA_RECEIVE_LEVEL_8 ((uint32_t)0x0008) +#define HSPIM_DMA_RECEIVE_LEVEL_9 ((uint32_t)0x0009) +#define HSPIM_DMA_RECEIVE_LEVEL_10 ((uint32_t)0x000A) +#define HSPIM_DMA_RECEIVE_LEVEL_11 ((uint32_t)0x000B) +#define HSPIM_DMA_RECEIVE_LEVEL_12 ((uint32_t)0x000C) +#define HSPIM_DMA_RECEIVE_LEVEL_13 ((uint32_t)0x000D) +#define HSPIM_DMA_RECEIVE_LEVEL_14 ((uint32_t)0x000E) +#define HSPIM_DMA_RECEIVE_LEVEL_15 ((uint32_t)0x000F) +#define HSPIM_DMA_RECEIVE_LEVEL_16 ((uint32_t)0x0010) +#define HSPIM_DMA_RECEIVE_LEVEL_32 ((uint32_t)0x0020) +#define HSPIM_DMA_RECEIVE_LEVEL_64 ((uint32_t)0x0040) + +#define IS_HSPIM_DMA_RECEIVE_LEVEL(LEVEL) ((((uint32_t)(LEVEL)) >= HSPIM_DMA_RECEIVE_LEVEL_1) && \ + (((uint32_t)(LEVEL)) <= HSPIM_DMA_RECEIVE_LEVEL_64)) +/** + * @} + */ + +/** @defgroup SPI_DMATransmitLevel + * @{ + */ +#define HSPIM_DMA_TRANSMIT_LEVEL_1 ((uint32_t)0x0001) +#define HSPIM_DMA_TRANSMIT_LEVEL_2 ((uint32_t)0x0002) +#define HSPIM_DMA_TRANSMIT_LEVEL_3 ((uint32_t)0x0003) +#define HSPIM_DMA_TRANSMIT_LEVEL_4 ((uint32_t)0x0004) +#define HSPIM_DMA_TRANSMIT_LEVEL_5 ((uint32_t)0x0005) +#define HSPIM_DMA_TRANSMIT_LEVEL_6 ((uint32_t)0x0006) +#define HSPIM_DMA_TRANSMIT_LEVEL_7 ((uint32_t)0x0007) +#define HSPIM_DMA_TRANSMIT_LEVEL_8 ((uint32_t)0x0008) +#define HSPIM_DMA_TRANSMIT_LEVEL_9 ((uint32_t)0x0009) +#define HSPIM_DMA_TRANSMIT_LEVEL_10 ((uint32_t)0x000A) +#define HSPIM_DMA_TRANSMIT_LEVEL_11 ((uint32_t)0x000B) +#define HSPIM_DMA_TRANSMIT_LEVEL_12 ((uint32_t)0x000C) +#define HSPIM_DMA_TRANSMIT_LEVEL_13 ((uint32_t)0x000D) +#define HSPIM_DMA_TRANSMIT_LEVEL_14 ((uint32_t)0x000E) +#define HSPIM_DMA_TRANSMIT_LEVEL_15 ((uint32_t)0x000F) +#define HSPIM_DMA_TRANSMIT_LEVEL_31 ((uint32_t)0x001F) +#define HSPIM_DMA_TRANSMIT_LEVEL_63 ((uint32_t)0x003F) + +#define IS_HSPIM_DMA_TRANSMIT_LEVEL(LEVEL) ((((uint32_t)(LEVEL)) >= HSPIM_DMA_TRANSMIT_LEVEL_1) && \ + (((uint32_t)(LEVEL)) <= HSPIM_DMA_TRANSMIT_LEVEL_63)) +/** + * @} + */ + +/** @defgroup HSPIM_Interrupt Mask and Status Flag + * @{ + */ + +#define HSPIM_IT_RX ((uint32_t)0x8000) +#define HSPIM_IT_TX ((uint32_t)0x4000) +#define HSPIM_IT_EN ((uint32_t)0x2000) + +#define HSPIM_IT_ID_RXF ((uint32_t)0x0080) +#define HSPIM_IT_ID_RXTF ((uint32_t)0x0040) +#define HSPIM_IT_ID_RXE ((uint32_t)0x0020) + +#define HSPIM_IT_ID_TXF ((uint32_t)0x0008) +#define HSPIM_IT_ID_TXE ((uint32_t)0x0002) +#define HSPIM_IT_ID_TXTF ((uint32_t)0x0001) + +#define HSPIM_FLAG_TXE ((uint32_t)0x0004) +#define HSPIM_FLAG_TXF ((uint32_t)0x0010) +#define HSPIM_FLAG_TXTF ((uint32_t)0x0020) + +#define HSPIM_FLAG_RXE ((uint32_t)0x0400) +#define HSPIM_FLAG_RXF ((uint32_t)0x1000) +#define HSPIM_FLAG_RXTF ((uint32_t)0x2000) + +#define HSPIM_FIFO_TX ((uint32_t)0x0080) +#define HSPIM_FIFO_RX ((uint32_t)0x0040) + +/** + * @} + */ + +void HSPIM_Init(HSPIM_InitTypeDef* HSPIM_InitStruct); +void HSPIM_DMAInit(HSPIM_DMAInitTypeDef* HSPIM_DMAInitStruct); +void HSPIM_Cmd(FunctionalState NewState); +void HSPIM_TransmitCmd(FunctionalState NewState); +void HSPIM_DualQuadReceiveCmd(FunctionalState NewState); +void HSPIM_SendData(uint8_t Data); +uint8_t HSPIM_ReceiveData(void); +void HSPIM_ITConfig(uint32_t HSPIM_IT, FunctionalState NewState); +void HSPIM_FIFOReset(uint32_t HSPIM_IT); +FlagStatus HSPIM_IsTransmitDone(void); +FlagStatus HSPIM_IsReady(void); +FlagStatus HSPIM_GetFlagStatus(uint32_t HSPIM_Flag); +ITStatus HSPIM_GetITStatus(uint32_t HSPIM_IT); + +void HSPIM_ModeSwitch(uint8_t Mode); +void HSPIM_WriteBuff(uint8_t Mode, uint16_t Size, uint8_t* Buff); +void HSPIM_ReadBuff(uint8_t Mode, uint16_t Size, uint8_t* Buff); + +#ifdef __cplusplus +} +#endif +#endif + +/************************** (C) COPYRIGHT Megahunt *****END OF FILE***********************************************************************/ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_i2c.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_i2c.h new file mode 100644 index 0000000000..bfcfea0053 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_i2c.h @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef __AIR105_I2C_H +#define __AIR105_I2C_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + + +/** @defgroup I2C_mode + * @{ + */ +typedef enum +{ + I2C_Mode_Master =((uint32_t)0x0001), + I2C_Mode_Slave =((uint32_t)0x0002) +}I2CMode_TypeDef; + +#define IS_I2C_MODE(MODE) (((MODE) == I2C_Mode_Master) || \ + ((MODE) == I2C_Mode_Slave)) +/** + * @} + */ + +typedef struct +{ + uint32_t I2C_ClockSpeed; /*!< Specifies the clock frequency. */ + + I2CMode_TypeDef I2C_Mode; + + uint32_t I2C_DutyCycle; /*!< Specifies the I2C fast mode duty cycle. + This parameter can be a value of @ref I2C_duty_cycle_in_fast_mode */ + uint32_t I2C_SDASetupTime; + + uint32_t I2C_SDAHoldTime; + + uint32_t I2C_TargetAddress; + + uint32_t I2C_TargetAddressMode; + + uint32_t I2C_OwnAddress; /*!< Specifies the slave mode own address. + This parameter can be a 7-bit or 10-bit address. */ + + uint32_t I2C_AcknowledgedAddress; /*!< Specifies if 7-bit or 10-bit address is acknowledged. + This parameter can be a value of @ref I2C_acknowledged_address */ + + uint32_t I2C_RXFIFOFullThreshold; + + uint32_t I2C_TXFIFOEmptyThreshold; + + FunctionalState I2C_GenerateRestartEnable; +}I2C_InitTypeDef; + + +typedef struct +{ + uint32_t I2C_DMAReq; + uint32_t I2C_DMAReceiveLevel; + uint32_t I2C_DMATransmitLevel; + FunctionalState I2C_DMAEnCmd; +}I2C_DMAInitTypeDef; + + +#define I2C_ClockSpeed_100KHz (100000) +#define I2C_ClockSpeed_400KHz (400000) + + +/** @defgroup I2C_duty_cycle_in_fast_mode + * @{ + */ +/*Tlow/Thigh = ((I2C_DutyCycle_x_y & 0xFF00) >> 8) / (I2C_DutyCycle_x_y & 0x00FF)*/ +#define I2C_DutyCycle_1 ((uint16_t)0x0101) /*!< I2C standard mode Tlow/Thigh = 1 */ +#define I2C_DutyCycle_16_9 ((uint16_t)0x1009) /*!< I2C fast mode Tlow/Thigh = 16/9 */ +#define I2C_DutyCycle_2 ((uint16_t)0x0201) /*!< I2C fast mode Tlow/Thigh = 2 */ +#define I2C_DutyCycle_8_3 ((uint16_t)0x0803) /*!< I2C high mode Tlow/Thigh = 8/3 */ +#define IS_I2C_DUTY_CYCLE(CYCLE) (((CYCLE) == I2C_DutyCycle_16_9) || \ + ((CYCLE) == I2C_DutyCycle_2)) +/** + * @} + */ + +#define IS_I2C_SDA_SETUP_TIME(TIME) ((TIME) <= 0x000000FF) +#define IS_I2C_SDA_HOLD_TIME(TIME) ((TIME) <= 0x0000FFFF) + +/** @defgroup I2C_acknowledged_address + * @{ + */ +#define I2C_AcknowledgedAddress_7bit ((uint16_t)0x0001) +#define I2C_AcknowledgedAddress_10bit ((uint16_t)0x0002) +#define IS_I2C_ACKNOWLEDGE_ADDRESS(ADDRESS) (((ADDRESS) == I2C_AcknowledgedAddress_7bit) || \ + ((ADDRESS) == I2C_AcknowledgedAddress_10bit)) +/** + * @} + */ + +/** @defgroup Target_Address_Bit + * @{ + */ +#define I2C_TargetAddressMode_7bit ((uint16_t)0x0001) +#define I2C_TargetAddressMode_10bit ((uint16_t)0x0002) +#define IS_I2C_TARGET_ADDRESS_MODE(ADDRESS) (((ADDRESS) == I2C_TargetAddressMode_7bit) || \ + ((ADDRESS) == I2C_TargetAddressMode_10bit)) +/** + * @} + */ + + +/** @defgroup SPI_RXFIFOFullThreshold + * @{ + */ +#define I2C_RXFIFOFullThreshold_1 ((uint32_t)0x0000) +#define I2C_RXFIFOFullThreshold_2 ((uint32_t)0x0001) +#define I2C_RXFIFOFullThreshold_3 ((uint32_t)0x0002) +#define I2C_RXFIFOFullThreshold_4 ((uint32_t)0x0003) +#define I2C_RXFIFOFullThreshold_5 ((uint32_t)0x0004) +#define I2C_RXFIFOFullThreshold_6 ((uint32_t)0x0005) +#define I2C_RXFIFOFullThreshold_7 ((uint32_t)0x0006) +#define I2C_RXFIFOFullThreshold_8 ((uint32_t)0x0007) + +#define IS_I2C_RX_FIFO_FULL_THRESHOLD(THRESHOLD) (THRESHOLD <= I2C_RXFIFOFullThreshold_8) +/** + * @} + */ + +/** @defgroup SPI_TXFIFOEmptyThreshold + * @{ + */ +#define I2C_TXFIFOEmptyThreshold_0 ((uint32_t)0x0000) +#define I2C_TXFIFOEmptyThreshold_1 ((uint32_t)0x0001) +#define I2C_TXFIFOEmptyThreshold_2 ((uint32_t)0x0002) +#define I2C_TXFIFOEmptyThreshold_3 ((uint32_t)0x0003) +#define I2C_TXFIFOEmptyThreshold_4 ((uint32_t)0x0004) +#define I2C_TXFIFOEmptyThreshold_5 ((uint32_t)0x0005) +#define I2C_TXFIFOEmptyThreshold_6 ((uint32_t)0x0006) +#define I2C_TXFIFOEmptyThreshold_7 ((uint32_t)0x0007) +#define I2C_TXFIFOEmptyThreshold_8 ((uint32_t)0x0008) + +#define IS_I2C_TX_FIFO_EMPTY_THRESHOLD(THRESHOLD) (THRESHOLD <= I2C_TXFIFOEmptyThreshold_8) +/** + * @} + */ + + +/** @defgroup I2C_DMAReceiveLevel + * @{ + */ +#define I2C_DMAReceiveLevel_1 ((uint32_t)0x0000) +#define I2C_DMAReceiveLevel_2 ((uint32_t)0x0001) +#define I2C_DMAReceiveLevel_3 ((uint32_t)0x0002) +#define I2C_DMAReceiveLevel_4 ((uint32_t)0x0003) +#define I2C_DMAReceiveLevel_5 ((uint32_t)0x0004) +#define I2C_DMAReceiveLevel_6 ((uint32_t)0x0005) +#define I2C_DMAReceiveLevel_7 ((uint32_t)0x0006) +#define I2C_DMAReceiveLevel_8 ((uint32_t)0x0007) + +#define IS_I2C_DMA_RECEIVE_LEVEL(LEVEL) (LEVEL <= I2C_DMAReceiveLevel_8) +/** + * @} + */ + +/** @defgroup I2C_DMATransmitLevel + * @{ + */ +#define I2C_DMATransmitLevel_0 ((uint32_t)0x0000) +#define I2C_DMATransmitLevel_1 ((uint32_t)0x0001) +#define I2C_DMATransmitLevel_2 ((uint32_t)0x0002) +#define I2C_DMATransmitLevel_3 ((uint32_t)0x0003) +#define I2C_DMATransmitLevel_4 ((uint32_t)0x0004) +#define I2C_DMATransmitLevel_5 ((uint32_t)0x0005) +#define I2C_DMATransmitLevel_6 ((uint32_t)0x0006) +#define I2C_DMATransmitLevel_7 ((uint32_t)0x0007) + +#define IS_I2C_DMA_TRANSMIT_LEVEL(LEVEL) (LEVEL <= I2C_DMATransmitLevel_7) +/** + * @} + */ + +/** @defgroup I2C_DMA_transfer_requests + * @{ + */ +#define I2C_DMAReq_Rx ((uint32_t)0x0001) +#define I2C_DMAReq_Tx ((uint32_t)0x0002) +#define IS_I2C_DMAREQ(DMAREQ) (((DMAREQ) & I2C_DMAReq_Tx) || \ + ((DMAREQ) & I2C_DMAReq_Rx)) +/** + * @} + */ + +#define I2C_IT_RXUDF ((uint32_t)0x0001) //clear by hardware +#define I2C_IT_RXOVF ((uint32_t)0x0002) //clear by read +#define I2C_IT_RXF ((uint32_t)0x0004) //clear by read +#define I2C_IT_TXOVF ((uint32_t)0x0008) //clear by read +#define I2C_IT_TXE ((uint32_t)0x0010) //clear by hardware +#define I2C_IT_RD_REQ ((uint32_t)0x0020) //clear by read +#define I2C_IT_TX_ABRT ((uint32_t)0x0040) //clear by read +#define I2C_IT_RX_DONE ((uint32_t)0x0080) //clear by read +#define I2C_IT_ACTIVITY ((uint32_t)0x0100) //clear by read +#define I2C_IT_STOP_DET ((uint32_t)0x0200) //clear by read +#define I2C_IT_START_DET ((uint32_t)0x0400) +#define I2C_IT_GEN_CALL ((uint32_t)0x0800) +#define I2C_IT_ALL ((uint32_t)0x0FFF) + +#define IS_I2C_CONFIG_IT(IT) ((((IT) & (~(uint32_t)0x0FFF)) == 0x00) && ((IT) != 0x00)) +#define IS_I2C_CLEAR_IT(IT) ((((IT) & (~(uint32_t)0x0FFF)) == 0x00) && ((IT) != 0x00)) +#define IS_I2C_GET_IT(IT) (((IT) == I2C_IT_RXUDF) || \ + ((IT) == I2C_IT_RXOVF) || \ + ((IT) == I2C_IT_RXF) || \ + ((IT) == I2C_IT_TXOVF) || \ + ((IT) == I2C_IT_TXE) || \ + ((IT) == I2C_IT_RD_REQ) || \ + ((IT) == I2C_IT_TX_ABRT) || \ + ((IT) == I2C_IT_RX_DONE) || \ + ((IT) == I2C_IT_ACTIVITY) || \ + ((IT) == I2C_IT_STOP_DET) || \ + ((IT) == I2C_IT_START_DET) || \ + ((IT) == I2C_IT_GEN_CALL) || \ + ((IT) == I2C_IT_ALL)) + +#define I2C_FLAG_ACTIVITY ((uint32_t)0x0001) +#define I2C_FLAG_TXNF ((uint32_t)0x0002) +#define I2C_FLAG_TXE ((uint32_t)0x0004) +#define I2C_FLAG_RXNE ((uint32_t)0x0008) +#define I2C_FLAG_RXF ((uint32_t)0x0010) +#define I2C_FLAG_MST_ACTIVITY ((uint32_t)0x0020) +#define I2C_FLAG_SLV_ACTIVITY ((uint32_t)0x0040) +#define I2C_FLAG_ALL ((uint32_t)0x007F) +#define IS_I2C_GET_FLAG(FLAG) (((FLAG) == I2C_FLAG_ACTIVITY) || \ + ((FLAG) == I2C_FLAG_TXNF) || \ + ((FLAG) == I2C_FLAG_TXE) || \ + ((FLAG) == I2C_FLAG_RXNE) || \ + ((FLAG) == I2C_FLAG_RXF) || \ + ((FLAG) == I2C_FLAG_MST_ACTIVITY) || \ + ((FLAG) == I2C_FLAG_SLV_ACTIVITY) || \ + ((FLAG) == I2C_FLAG_ALL)) + +#define I2C_TX_ABRT_7BIT_ADDR_NOACK ((uint32_t)0x00000001) +#define I2C_TX_ABRT_10BIT_ADDR1_NOACK ((uint32_t)0x00000002) +#define I2C_TX_ABRT_10BIT_ADDR2_NOACK ((uint32_t)0x00000004) +#define I2C_TX_ABRT_TXDATA_NOACK ((uint32_t)0x00000008) +#define I2C_TX_ABRT_GEN_CALL_NOACK ((uint32_t)0x00000010) +#define I2C_TX_ABRT_GEN_CALL_READ ((uint32_t)0x00000020) +#define I2C_TX_ABRT_HIGH_SPEED_ACKDET ((uint32_t)0x00000040) +#define I2C_TX_ABRT_START_BYTE_ACKDET ((uint32_t)0x00000080) +#define I2C_TX_ABRT_HIGH_SPEED_NORSTRT ((uint32_t)0x00000100) +#define I2C_TX_ABRT_START_BYTE_NORSTRT ((uint32_t)0x00000200) +#define I2C_TX_ABRT_10BIT_RD_NORSTRT ((uint32_t)0x00000400) +#define I2C_TX_ABRT_LOST_ARB ((uint32_t)0x00000800) +#define I2C_TX_ABRT_SLVFLUSH_TXFIFO ((uint32_t)0x00001000) +#define I2C_TX_ABRT_SLV_LOST_ARB ((uint32_t)0x00002000) +#define I2C_TX_ABRT_SLV_RD_INTX ((uint32_t)0x00004000) +#define I2C_TX_ABRT_MASTER_DISABLE ((uint32_t)0x00008000) +#define I2C_TX_ABRT_USER_ABRT ((uint32_t)0x00010000) +#define I2C_TX_ABRT_TX_FLUSH_CNT ((uint32_t)0x00020000) +#define IS_I2C_TX_ABRT(ABRT) (((ABRT) == I2C_TX_ABRT_7BIT_ADDR_NOACK) || \ + ((ABRT) == I2C_TX_ABRT_10BIT_ADDR1_NOACK) || \ + ((FLAG) == I2C_TX_ABRT_10BIT_ADDR2_NOACK) || \ + ((FLAG) == I2C_TX_ABRT_TXDATA_NOACK) || \ + ((FLAG) == I2C_TX_ABRT_GEN_CALL_NOACK) || \ + ((FLAG) == I2C_TX_ABRT_GEN_CALL_READ) || \ + ((FLAG) == I2C_TX_ABRT_HIGH_SPEED_ACKDET) || \ + ((FLAG) == I2C_TX_ABRT_START_BYTE_ACKDET) || \ + ((FLAG) == I2C_TX_ABRT_HIGH_SPEED_NORSTRT) || \ + ((FLAG) == I2C_TX_ABRT_START_BYTE_NORSTRT) || \ + ((FLAG) == I2C_TX_ABRT_10BIT_RD_NORSTRT) || \ + ((FLAG) == I2C_TX_ABRT_LOST_ARB) || \ + ((FLAG) == I2C_TX_ABRT_SLVFLUSH_TXFIFO) || \ + ((FLAG) == I2C_TX_ABRT_SLV_LOST_ARB) || \ + ((FLAG) == I2C_TX_ABRT_SLV_RD_INTX) || \ + ((FLAG) == I2C_TX_ABRT_MASTER_DISABLE) || \ + ((FLAG) == I2C_TX_ABRT_USER_ABRT) || \ + ((FLAG) == I2C_TX_ABRT_TX_FLUSH_CNT)) + +typedef enum +{ + I2C_DataCMD_Write = (uint32_t)0x01, + I2C_DataCMD_Read = (uint32_t)0x02 +}I2CDataCMD_TypeDef; +#define IS_I2C_DATA_CMD(CMD) (((CMD) == I2C_DataCMD_Write) || \ + ((CMD) == I2C_DataCMD_Read)) + +typedef enum +{ + I2C_DataEndCondition_None = (uint32_t)0x01, + I2C_DataEndCondition_Stop = (uint32_t)0x02, + I2C_DataEndCondition_Restart = (uint32_t)0x03 +}I2CDataEndCondition_TypeDef; +#define IS_I2C_DATA_END_CONDITION(CONDITION) (((CONDITION) == I2C_DataEndCondition_None) || \ + ((CONDITION) == I2C_DataEndCondition_Stop) || \ + ((CONDITION) == I2C_DataEndCondition_Restart)) + + +void I2C_DeInit(I2C_TypeDef* I2Cx); +void I2C_Init(I2C_TypeDef* I2Cx,I2C_InitTypeDef* I2C_InitStruct); +void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct); +void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_SetTargetAddress(I2C_TypeDef* I2Cx, uint32_t TargetAddress, uint32_t TargetAddressMode); +void I2C_DMAInit(I2C_TypeDef* I2Cx, I2C_DMAInitTypeDef* I2C_DMAInitStruct); +void I2C_DMAStructInit(I2C_DMAInitTypeDef* I2C_DMAInitStruct); +void I2C_DMACmd(I2C_TypeDef* I2Cx, uint32_t I2C_DMAReq, FunctionalState NewState); +void I2C_SetSDASetupTime(I2C_TypeDef* I2Cx,uint32_t PCLKCycles); +void I2C_SetSDAHoldTime(I2C_TypeDef* I2Cx,uint32_t PCLKCycles); + +void I2C_ITConfig(I2C_TypeDef* I2Cx,uint32_t I2C_IT, FunctionalState NewState); +ITStatus I2C_GetITStatus(I2C_TypeDef* I2Cx,uint32_t I2C_IT); +ITStatus I2C_GetRawITStatus(I2C_TypeDef* I2Cx,uint32_t I2C_IT); +void I2C_ClearITPendingBit(I2C_TypeDef* I2Cx,uint32_t I2C_IT); +FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx,uint32_t I2C_FLAG); +uint32_t I2C_GetFlagStatusReg(I2C_TypeDef* I2Cx); +FlagStatus I2C_GetTXAbortSource(I2C_TypeDef* I2Cx,uint32_t I2C_TX_ABRT); +uint32_t I2C_GetTXAbortSourceReg(I2C_TypeDef* I2Cx); +I2CMode_TypeDef I2C_GetI2CMode(I2C_TypeDef* I2Cx); + +void I2C_MasterGenerateReceiveSCL(I2C_TypeDef* I2Cx, I2CDataEndCondition_TypeDef DataCondition); +uint16_t I2C_ExtendData(uint8_t Data, I2CDataCMD_TypeDef DataCMD, I2CDataEndCondition_TypeDef DataCondition); +void I2C_WriteDataToDR(I2C_TypeDef* I2Cx, uint16_t ExtendData); +uint8_t I2C_ReadDataFromDR(I2C_TypeDef* I2Cx); +void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data, I2CDataEndCondition_TypeDef DataCondition); +uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx, I2CDataEndCondition_TypeDef DataCondition); +void I2C_SendBytes(I2C_TypeDef* I2Cx, uint8_t* Data, uint32_t DataLen, I2CDataEndCondition_TypeDef DataCondition); +void I2C_ReceiveBytes(I2C_TypeDef* I2Cx, uint8_t* Data, uint32_t DataLen, I2CDataEndCondition_TypeDef DataCondition); + +void I2C_SlaveGeneralNACKOnlyCmd(I2C_TypeDef* I2Cx, FunctionalState NewState); + +FlagStatus I2C_IsEnable(I2C_TypeDef* I2Cx); + + +#ifdef __cplusplus +} +#endif + +#endif + +/************************** (C) COPYRIGHT Megahunt *****END OF FILE****/ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_it.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_it.h new file mode 100644 index 0000000000..c688d508af --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_it.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __AIR105_IT_H +#define __AIR105_IT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + +void NMI_Handler(void); +void HardFault_Handler(void); +void MemManage_Handler(void); +void BusFault_Handler(void); +void UsageFault_Handler(void); +void SVC_Handler(void); +void DebugMon_Handler(void); +void PendSV_Handler(void); +void SysTick_Handler(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_kcu.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_kcu.h new file mode 100644 index 0000000000..d72fed08ad --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_kcu.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef __AIR105_KCU_H +#define __AIR105_KCU_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + +/** + * @brief KCU Init structure definition + */ +typedef struct +{ + uint32_t KCU_DebounceTimeLevel; + uint32_t KCU_PortInput; + uint32_t KCU_PortOutput; + uint32_t KCU_Rand; +}KCU_InitTypeDef; + + +#define KCU_IT_PUSH (KCU_CTRL1_PUSH_IT) +#define KCU_IT_RELEASE (KCU_CTRL1_RELEASE_IT) +#define KCU_IT_OVERRUN (KCU_CTRL1_OVERRUN_IT) + +void KCU_DeInit(void); + +void KCU_Init(KCU_InitTypeDef *KCU_InitStruct); +void KCU_StructInit(KCU_InitTypeDef *KCU_InitStruct); + +void KCU_Cmd(FunctionalState NewState); + +uint32_t KCU_SetRand(uint32_t rand); + +void KCU_ITConfig(uint32_t KCU_IT, FunctionalState NewState); +FlagStatus KCU_GetITStatus(uint32_t KCU_IT); +void KCU_ClearITPending(void); + +uint32_t KCU_GetEvenReg(void); + + +#ifdef __cplusplus +} +#endif + +#endif + + +/************************** (C) COPYRIGHT Megahunt *****END OF FILE****/ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_lcdi.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_lcdi.h new file mode 100644 index 0000000000..a9a4e4aba3 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_lcdi.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef __AIR105_LCDI_H +#define __AIR105_LCDI_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + +#include "air105.h" + + +#define LCDI_CMD (0) +#define LCDI_DAT (1) + +#define LCDI_MODE_6800 (0) +#define LCDI_MODE_8080 (1) + +#define LCD_CMD_BUFF_SIZE (64) +#define LCD_READ_BUFF_SIZE (512) +#define LCD_WRITE_BUFF_SIZE (512) + +//LCD module +#define LCDI_FIFO_OV_IE (1 << 12) +#define LCDI_FIFO_RST (1 << 11) +#define LCDI_WR_DMA_EN (1 << 10) +#define LCDI_WR_FIFO_EN (1 << 9) + +#define LCDI_CTRL_AUTO_READ (1 << 8) +#define LCDI_CTRL_TYPE_8080 (1 << 7) +#define LCDI_CTRL_EN_RD (1 << 6) +#define LCDI_CTRL_RW_WR (1 << 5) +#define LCDI_CTRL_CD (1 << 4) +#define LCDI_CTRL_WIDTH_4BIT (1 << 3) +#define LCDI_CTRL_AUTO (1 << 2) +#define LCDI_CTRL_RD_IE (1 << 1) +#define LCDI_CTRL_WR_IE (1 << 0) + +#define LCDI_STATUS_READY (1 << 2) +#define LCDI_STATUS_RD_IS (1 << 1) +#define LCDI_STATUS_WR_IS (1 << 0) + +#define RNG_BUF_IS_FULL(pBuf) ((pBuf)->u32Tail == (pBuf)->u32Head) +#define RNG_BUF_NEXT_HEAD(pBuf) (((pBuf)->u32Head + 1) % ((pBuf)->u32BuffSize)) +#define RNG_BUF_NEXT_TAIL(pBuf) (((pBuf)->u32Tail + 1) % ((pBuf)->u32BuffSize)) +#define RNG_BUF_LEN(pBuf) (((pBuf)->u32Tail + (pBuf)->u32BuffSize - 1 - (pBuf)->u32Head) % (pBuf)->u32BuffSize) +#define RNG_BUF_PERI_TAIL(pBuf) (((pBuf)->u32Tail + (pBuf)->u32BuffSize - 1) % ((pBuf)->u32BuffSize)) + +typedef struct +{ + uint32_t volatile u32Head; + uint32_t volatile u32Tail; + uint32_t volatile u32BuffSize; + uint32_t volatile u32Stat; + uint8_t volatile *pu8Buff; +} RNG_BUF8, *RNG_BUF8_ID; + +typedef struct +{ + uint32_t volatile u32Head; + uint32_t volatile u32Tail; + uint32_t volatile u32BuffSize; + uint32_t volatile u32Stat; + uint32_t volatile *pu32Buff; +} RNG_BUF32, *RNG_BUF32_ID; + +typedef struct +{ + uint8_t lcd_ReadBuff[LCD_READ_BUFF_SIZE]; + uint8_t lcd_WriteBuff[LCD_WRITE_BUFF_SIZE]; + uint32_t lcd_CmdBuff[LCD_CMD_BUFF_SIZE]; + RNG_BUF8 rbRead; + RNG_BUF8 rbWrite; + RNG_BUF32 rbCmd; + RNG_BUF32_ID prbCmd; + RNG_BUF8_ID prbRead; + RNG_BUF8_ID prbWrite; + volatile uint32_t u32OpCount; +} RING_BUF; + +typedef struct +{ + uint8_t LCD_BusMode; //Bus mode(8080/6800) + uint8_t LCD_IntRead; //Read interrupt Enable + uint8_t LCD_IntWrite; //Read interrupt Enable + uint8_t fifo_level; + uint32_t LCD_MaxQTR; //Max qaurter cylce of read/write. + uint32_t fifo_ov_ie_enable; + uint32_t fifo_rst_enable; + uint32_t wr_dma_enable; + uint32_t wr_fifo_enable; + uint32_t opt; + RING_BUF ring_buf; +} LCD_InitTypeDef; + +//Operate the bus signal +void LCD_BusRead(LCD_TypeDef *LCDx,uint8_t u8CD); +void LCD_BusWrite(LCD_TypeDef *LCDx,uint8_t u8CD, uint8_t value); + +void LCD_Read(LCD_TypeDef *LCDx,uint8_t u8CD, uint8_t *dat); +void LCD_Write(LCD_TypeDef *LCDx,uint8_t u8CD, uint8_t u8Value); + +//Buffer mode only can used in interrupt mode. +int32_t LCD_ReadBuff(LCD_TypeDef *LCDx, LCD_InitTypeDef *pLcdInit, uint8_t *pu8Buff, uint32_t u32BuffLen); +int32_t LCD_WriteBuff(LCD_TypeDef *LCDx, LCD_InitTypeDef *pLcdInit, uint8_t *pu8Buff, uint32_t u32BuffLen); + +void LCD_Init(LCD_TypeDef *LCDx, LCD_InitTypeDef *pLcdInit); +void LCD_FIFODMAconfig(LCD_TypeDef *LCDx, LCD_InitTypeDef *LCD_InitType); + + +#ifdef __cplusplus +} +#endif + +#endif + + +/************************** (C) COPYRIGHT Megahunt *****END OF FILE****/ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_otp.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_otp.h new file mode 100644 index 0000000000..6791042053 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_otp.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef __AIR105_OTP_H +#define __AIR105_OTP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + +/* Exported types ------------------------------------------------------------*/ +typedef enum +{ + OTP_Complete = 0, + OTP_ReadOnProgramOrSleep, //�ڱ�̡�����״̬�¶�OTP���ж����� + OTP_ProgramIn_HiddenOrRO_Block, //��ֻ�������б�� + OTP_ProgramOutOfAddr, //��̷�Χ����OTP��Χ + OTP_ProgramOnSleep, //������״̬���б�̲��� + OTP_WakeUpOnNoSleep, //�ڷ�����״̬�½��л��Ѳ��� + OTP_TimeOut, //OTP��ɱ�־λ��ʱû����λ + OTP_DataWrong, +}OTP_StatusTypeDef; + +#define IS_OTP_ADDRESS(ADDRESS) (((ADDRESS) > AIR105_OTP_SIZE - 1) && ((ADDRESS) < AIR105_OTP_BASE + AIR105_OTP_SIZE)) + + +void OTP_WakeUp(void); +void OTP_Unlock(void); +void OTP_Lock(void); +void OTP_ClearStatus(void); +void OTP_SetLatency(uint8_t u8_1UsClk, uint8_t u8_10NsCLK); +void OTP_TimCmd(FunctionalState NewState); + +void OTP_SetProtect(uint32_t u32Addr); +void OTP_SetProtectLock(uint32_t u32Addr); +void OTP_UnProtect(uint32_t u32Addr); +uint32_t OTP_GetProtect(void); +uint32_t OTP_GetProtectLock(void); + +void OTP_PowerOn(void); + +Boolean OTP_IsReadReady(void); +Boolean OTP_IsWriteDone(void); + +OTP_StatusTypeDef OTP_GetFlag(void); + +Boolean OTP_IsProtect(uint32_t u32Addr); +Boolean OTP_IsProtectLock(uint32_t u32Addr); + +OTP_StatusTypeDef OTP_WriteWord(uint32_t addr, uint32_t w); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_qspi.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_qspi.h new file mode 100644 index 0000000000..7233647766 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_qspi.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef AIRMCU_FLASH +#define AIRMCU_FLASH + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include "air105.h" + + +/* Size of the flash */ +#define X25Q_PAGE_SIZE 0x100 + +// Identification Operations +/***Command Definitions***/ + +// Program Operations +#define PAGE_PROG_CMD 0x02 +#define QUAD_INPUT_PAGE_PROG_CMD 0x32 + + +// Erase Operations +#define SECTOR_ERASE_CMD 0x20 +#define CHIP_ERASE_CMD 0xC7 + +#define PROG_ERASE_RESUME_CMD 0x7A +#define PROG_ERASE_SUSPEND_CMD 0x75 + +#define SET_BURST_WITH_WRAP 0x77 +#define RELEASE_FROM_DEEP_POWER_DOWN 0xAB +#define DEEP_POWER_DOWN 0xB9 + +/***End Cmd***/ + + +#define QSPI_DEVICE_PARA_SAMPLE_DLY_Pos 15 +#define QSPI_DEVICE_PARA_SAMPLE_PHA_Pos 14 +#define QSPI_DEVICE_PARA_PROTOCOL_Pos 8 +#define QSPI_DEVICE_PARA_DUMMY_CYCLE_Pos 4 + + +#define ROM_QSPI_Init (*((void (*)(QSPI_InitTypeDef *))(*(uint32_t *)0x8010))) +#define ROM_QSPI_ReadID (*((uint32_t (*)(QSPI_CommandTypeDef *))(*(uint32_t *)0x8014))) +#define ROM_QSPI_WriteParam (*((uint8_t (*)(QSPI_CommandTypeDef *, uint16_t))(*(uint32_t *)0x8018))) +#define ROM_QSPI_EraseSector (*((uint8_t (*)(QSPI_CommandTypeDef *, uint32_t))(*(uint32_t *)0x801C))) +#define ROM_QSPI_ProgramPage (*((uint8_t (*)(QSPI_CommandTypeDef *, DMA_TypeDef *, uint32_t, uint32_t, uint8_t *))(*(uint32_t *)0x8024))) +#define ROM_QSPI_ReleaseDeepPowerDown (*((uint8_t (*)(QSPI_CommandTypeDef *))(*(uint32_t *)0x802C))) +#define ROM_QSPI_StatusReg (*((uint16_t (*)(QSPI_CommandTypeDef *))(*(uint32_t *)0x8034))) + + +typedef enum +{ + QSPI_BUSMODE_111 = 0x00, //CMD-ADDR-DATA = 1-1-1 + QSPI_BUSMODE_114 = 0x01, //CMD-ADDR-DATA = 1-1-4 + QSPI_BUSMODE_144 = 0x02, //CMD-ADDR-DATA = 1-4-4 + QSPI_BUSMODE_444 = 0x03, //CMD-ADDR-DATA = 4-4-4 +}QSPI_BusModeTypeDef; + + +typedef enum +{ + QSPI_CMDFORMAT_CMD8 = 0x00, + QSPI_CMDFORMAT_CMD8_RREG8 = 0x01, + QSPI_CMDFORMAT_CMD8_RREG16 = 0x02, + QSPI_CMDFORMAT_CMD8_RREG24 = 0x03, + QSPI_CMDFORMAT_CMD8_DMY24_WREG8 = 0x04, + QSPI_CMDFORMAT_CMD8_ADDR24_RREG8 = 0x05, + QSPI_CMDFORMAT_CMD8_ADDR24_RREG16 = 0x06, + QSPI_CMDFORMAT_CMD8_WREG8 = 0x07, + QSPI_CMDFORMAT_CMD8_WREG16 = 0x08, + QSPI_CMDFORMAT_CMD8_ADDR24 = 0x09, + QSPI_CMDFORMAT_CMD8_ADDR24_RDAT = 0x0A, + QSPI_CMDFORMAT_CMD8_ADDR24_DMY_RDAT = 0x0B, + QSPI_CMDFORMAT_CMD8_ADDR24_M8_DMY_RDAT = 0x0C, + QSPI_CMDFORMAT_CMD8_ADDR24_PDAT = 0x0D +}QSPI_CmdFormatTypeDef; + + +typedef enum +{ + QSPI_PROTOCOL_CLPL = 0x00, + QSPI_PROTOCOL_CHPH = 0x03 +}QSPI_ProtocolTypedef; + +typedef enum +{ + QSPI_FREQSEL_HCLK_DIV2 = 0x01, + QSPI_FREQSEL_HCLK_DIV3 = 0x02, + QSPI_FREQSEL_HCLK_DIV4 = 0x03 +}QSPI_FreqSelTypeDef; + +typedef struct +{ + //Device Para + uint8_t SampleDly; //Default:0 + uint8_t SamplePha; //Default:0 + uint8_t ProToCol; //Defualt: QSPI_PROTOCOL_CLPL + uint8_t DummyCycles; //Include M7:0 Defualt: 6 + uint8_t FreqSel; //Defualt: QSPI_FREQSEL_HCLK_DIV4 + + //Setting Cache + uint8_t Cache_Cmd_ReleaseDeepInstruction; //Defualt: 0xAB + uint8_t Cache_Cmd_DeepInstruction; //Defualt: 0xB9 + uint8_t Cache_Cmd_ReadBusMode; //Defualt: QSPI_BUSMODE_144 + uint8_t Cache_Cmd_ReadFormat; //Defualt: QSPI_CMDFORMAT_CMD8_ADDR24_DMY_RDAT + uint8_t Cache_Cmd_ReadInstruction; //Defualt: 0xEB + +}QSPI_InitTypeDef; + +typedef struct +{ + uint8_t Instruction; + uint32_t BusMode; + uint32_t CmdFormat; + +}QSPI_CommandTypeDef; + + +void QSPI_Init(QSPI_InitTypeDef *mhqspi); +void QSPI_SetLatency(uint32_t u32UsClk); + +uint8_t FLASH_EraseSector(uint32_t sectorAddress); +uint8_t FLASH_ProgramPage(uint32_t addr, uint32_t size, uint8_t *buffer); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_rtc.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_rtc.h new file mode 100644 index 0000000000..e545383c78 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_rtc.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef __AIR105_RTC_H +#define __AIR105_RTC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + +#define RTC_32K_EXT_INC_SELECT (0x00000400U) + +typedef enum +{ + SELECT_EXT32K, + SELECT_INC32K +} RTCCLK_SOURCE_TypeDef; +#define IS_RTCCLK_SOURCE(FREQ) (((FREQ) == SELECT_EXT32K) || \ + ((FREQ) == SELECT_INC32K)) + +FlagStatus RTC_IsReady(void); + +void RTC_ResetCounter(void); +uint32_t RTC_GetCounter(void); + +void RTC_SetRefRegister(uint32_t RefValue); +uint32_t RTC_GetRefRegister(void); + +void RTC_SetAlarm(uint32_t AlarmValue); + +uint32_t RTC_GetAttrackTime(void); + +void RTC_ITConfig(FunctionalState NewState); +void RTC_ClearITPendingBit(void); +ITStatus RTC_GetITStatus(void); +void RTC_CLKSourceSelect(RTCCLK_SOURCE_TypeDef source); + +#ifdef __cplusplus +} +#endif + +#endif + +/************************** (C) COPYRIGHT Megahunt *****END OF FILE****/ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_sci.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_sci.h new file mode 100644 index 0000000000..273e69d55d --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_sci.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef __AIR105_SCI_H +#define __AIR105_SCI_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "air105.h" +#include + + +#define SCI_UNCONFIG (-1) +#define SCI_ICC_CLOCK_ERR (-2) +#define SCI_REF_CLOCK_ERR (-3) +#define SCI_IMPRECISION_CLK (-4) +#define SCI_EMV_F_D_ERR (-5) +#define SCI_EMV_TS_ERR (-6) +#define SCI_EMV_ATR_ERR (-7) +#define SCI_CARD_OUT_ERR (-8) + + +int32_t SCI_ConfigEMV(uint8_t SCI_Bitmap, uint32_t SCIx_Clk); + + +#ifdef __cplusplus +} +#endif + +#endif ///< __AIR105_SCI_H + diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_sensor.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_sensor.h new file mode 100644 index 0000000000..a9d5b1c40a --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_sensor.h @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef __AIR105_SENSOR_H +#define __AIR105_SENSOR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + +typedef struct +{ + uint32_t SENSOR_Port_Pull; + uint32_t SENSOR_Port_Static; + uint32_t SENSOR_Port_Dynamic; + FunctionalState SENSOR_Port_Enable; + uint32_t SENSOR_DynamicFrequency; + FunctionalState SENSOR_GlitchEnable; + uint32_t SENSOR_PUPU_Frequency; + uint32_t SENSOR_PUPU_DetectTime; + uint32_t SENSOR_PUPU_HoldTime; + FunctionalState SENSOR_PUPU_Enable; + FunctionalState SENSOR_Trig_Hold_Enable; + uint32_t SENSOR_Dynamic_Sample; + uint32_t SENSOR_Static_Sample; + +}SENSOR_EXTInitTypeDef; + +#define SENSOR_Port_S0 ((uint32_t)0x0001) +#define SENSOR_Port_S1 ((uint32_t)0x0002) +#define SENSOR_Port_S2 ((uint32_t)0x0004) +#define SENSOR_Port_S3 ((uint32_t)0x0008) +#define SENSOR_Port_S4 ((uint32_t)0x0010) +#define SENSOR_Port_S5 ((uint32_t)0x0020) +#define SENSOR_Port_S6 ((uint32_t)0x0040) +#define SENSOR_Port_S7 ((uint32_t)0x0080) +#define SENSOR_Port_All ((uint32_t)0x00FF) + +#define SENSOR_Port_S01 (SENSOR_Port_S0 | SENSOR_Port_S1) +#define SENSOR_Port_S23 (SENSOR_Port_S2 | SENSOR_Port_S3) +#define SENSOR_Port_S45 (SENSOR_Port_S4 | SENSOR_Port_S5) +#define SENSOR_Port_S67 (SENSOR_Port_S6 | SENSOR_Port_S7) +#define IS_SENSOR_PORT(PORT) ((((PORT) & (uint32_t)0xFFFFFF00) == 0x00) && ((PORT) != (uint32_t)0x00)) + +/* �ⲿ��̬��������������Ƶ�� */ +#define SENSOR_PUPU_Frequency_Default ((uint32_t)0x0000) +#define SENSOR_PUPU_Frequency_500ms ((uint32_t)0x0000) +#define SENSOR_PUPU_Frequency_1s ((uint32_t)0x0001) +#define IS_SENSOR_EXT_PUPU_FREQ(FREQ) ((FREQ) == SENSOR_PUPU_Frequency_500ms ||\ + (FREQ) == SENSOR_PUPU_Frequency_1s) + +/* �ⲿ��̬�������������� */ +#define SENSOR_STATIC_SAMPLE_Default ((uint32_t)0x0001) +#define SENSOR_STATIC_SAMPLE_1 ((uint32_t)0x0000) +#define SENSOR_STATIC_SAMPLE_2 ((uint32_t)0x0001) +#define SENSOR_STATIC_SAMPLE_3 ((uint32_t)0x0002) +#define SENSOR_STATIC_SAMPLE_4 ((uint32_t)0x0003) +#define IS_SENSOR_EXT_STATIC_SAMPLE(COUNT) ((COUNT) >= SENSOR_STATIC_SAMPLE_1 &&\ + (COUNT) <= SENSOR_STATIC_SAMPLE_4) + +/* �ⲿ��̬�������������� */ +#define SENSOR_DYNAMIC_SAMPLE_Default ((uint32_t)0x0002) +#define SENSOR_DYNAMIC_SAMPLE_1 ((uint32_t)0x0000) +#define SENSOR_DYNAMIC_SAMPLE_2 ((uint32_t)0x0001) +#define SENSOR_DYNAMIC_SAMPLE_3 ((uint32_t)0x0002) +#define SENSOR_DYNAMIC_SAMPLE_4 ((uint32_t)0x0003) +#define IS_SENSOR_EXT_DYNAMIC_SAMPLE(COUNT) ((COUNT) >= SENSOR_DYNAMIC_SAMPLE_1 &&\ + (COUNT) <= SENSOR_DYNAMIC_SAMPLE_4) + + +/* �ⲿ��̬�����������������裬������Чʱ�� */ +#define SENSOR_PUPU_HoldTime_Default ((uint32_t)0x0002) +#define SENSOR_PUPU_HoldTime_1_2 ((uint32_t)0x0000) +#define SENSOR_PUPU_HoldTime_1_4 ((uint32_t)0x0001) +#define SENSOR_PUPU_HoldTime_1_8 ((uint32_t)0x0002) +#define SENSOR_PUPU_HoldTime_1_16 ((uint32_t)0x0003) +#define IS_SENSOR_EXT_PUPU_HOLD_TIME(TIME) ((TIME) == SENSOR_PUPU_HoldTime_1_2 ||\ + (TIME) == SENSOR_PUPU_HoldTime_1_4 ||\ + (TIME) == SENSOR_PUPU_HoldTime_1_8 ||\ + (TIME) == SENSOR_PUPU_HoldTime_1_16) + +/* ��̬���������Ƶ�� */ +#define SENSOR_DynamicFrequency_Default ((uint32_t)0x0003) +#define SENSOR_DynamicFrequency_31_25ms ((uint32_t)0x0000) +#define SENSOR_DynamicFrequency_125ms ((uint32_t)0x0001) +#define SENSOR_DynamicFrequency_500ms ((uint32_t)0x0002) +#define SENSOR_DynamicFrequency_1s ((uint32_t)0x0003) +#define IS_SENSOR_EXT_DYNAMIC_FREQ(FREQ) ((FREQ) == SENSOR_DynamicFrequency_Default ||\ + (FREQ) == SENSOR_DynamicFrequency_31_25ms ||\ + (FREQ) == SENSOR_DynamicFrequency_125ms ||\ + (FREQ) == SENSOR_DynamicFrequency_500ms ||\ + (FREQ) == SENSOR_DynamicFrequency_1s) + + +#define SENSOR_ANA_VOL_HIGH ((uint32_t)0x00000001) +#define SENSOR_ANA_VOL_LOW ((uint32_t)0x00000002) +#define SENSOR_ANA_TEMPER_HIGH ((uint32_t)0x00000004) +#define SENSOR_ANA_TEMPER_LOW ((uint32_t)0x00000008) +#define SENSOR_ANA_XTAL32K ((uint32_t)0x00000010) +#define SENSOR_ANA_MESH ((uint32_t)0x00000020) +#define SENSOR_ANA_VOLGLITCH ((uint32_t)0x00000040) +#define SENSOR_ANA_ALL ((uint32_t)0x0000007F) +#define IS_SENSOR_ANA(ANA) ((((ANA) & (uint32_t)0xFFFFFF80) == 0x00) && ((ANA) != (uint32_t)0x00)) + +#define SENSOR_LOCK_EXTS ((uint32_t)0x00000001) +#define SENSOR_LOCK_VOL_HIGH ((uint32_t)0x00000002) +#define SENSOR_LOCK_VOL_LOW ((uint32_t)0x00000004) +#define SENSOR_LOCK_TEMPER_HIGH ((uint32_t)0x00000008) +#define SENSOR_LOCK_TEMPER_LOW ((uint32_t)0x00000010) +#define SENSOR_LOCK_VOLGLITCH ((uint32_t)0x00000020) +#define SENSOR_LOCK_XTAL32K ((uint32_t)0x00000040) +#define SENSOR_LOCK_MESH ((uint32_t)0x00000080) +#define IS_SENSOR_LOCK(LOCK) ((((LOCK) & (uint32_t)0xFFFFFF00) == 0x00) && ((LOCK) != (uint32_t)0x00)) + + +#define SENSOR_IT_EXTS ((uint32_t)0x00000FFF) +#define SENSOR_IT_VOL_HIGH ((uint32_t)0x00001000) +#define SENSOR_IT_VOL_LOW ((uint32_t)0x00002000) +#define SENSOR_IT_TEMPER_HIGH ((uint32_t)0x00004000) +#define SENSOR_IT_TEMPER_LOW ((uint32_t)0x00008000) +#define SENSOR_IT_GLITCH ((uint32_t)0x00010000) +#define SENSOR_IT_XTAL32K ((uint32_t)0x00020000) +#define SENSOR_IT_MESH ((uint32_t)0x00040000) +#define SENSOR_IT_SSC ((uint32_t)0x00100000) +#define IS_SENSOR_IT(IT) ((IT) == SENSOR_IT_EXTS || \ + (IT) == SENSOR_IT_VOL_HIGH || \ + (IT) == SENSOR_IT_VOL_LOW || \ + (IT) == SENSOR_IT_TEMPER_HIGH || \ + (IT) == SENSOR_IT_TEMPER_LOW || \ + (IT) == SENSOR_IT_GLITCH || \ + (IT) == SENSOR_IT_XTAL32K || \ + (IT) == SENSOR_IT_MESH || \ + (IT) == SENSOR_IT_SSC) + +typedef enum +{ + SENSOR_CPUReset = 0, + SENSOR_Interrupt = 1 +}SENSOR_RespModeTypeDef; +#define IS_SENSOR_RESP_MODE(Mode) ((Mode) == SENSOR_CPUReset ||\ + (Mode) == SENSOR_Interrupt) + +uint32_t SENSOR_SetRand(uint32_t Rand); +uint32_t SENSOR_EXTInit(SENSOR_EXTInitTypeDef *SENSOR_EXTInitStruct); +uint32_t SENSOR_EXTPortCmd(uint32_t SENSOR_Port, FunctionalState NewState); +uint32_t SENSOR_EXTCmd(FunctionalState NewState); +FlagStatus SENSOR_EXTIsRuning(void); +uint32_t SENSOR_ANACmd(uint32_t SENSOR_ANA, FunctionalState NewState); +void SENSOR_Lock(uint32_t SENSOR_LOCK); +void SENSOR_AttackRespMode(SENSOR_RespModeTypeDef SENSOR_RespMode); + +int32_t SENSOR_GetITStatus(uint32_t ITState); +int32_t SENSOR_GetITStatusReg(void); +void SENSOR_ClearITPendingBit(void); + + +FunctionalState SENSOR_GetEXTTrigPull(void); +FunctionalState SENSOR_SetEXTTrigPull(FunctionalState NewState); + +FunctionalState SENSOR_GetEXTFilter(void); +FunctionalState SENSOR_SetEXTFilter(FunctionalState NewState); + + +#define SENSOR_STATIC_PULSE_PERIOD_500MS (0) +#define SENSOR_STATIC_PULSE_PERIOD_1S (1) + +uint32_t SENSOR_GetEXTPulsePeriod(void); +uint32_t SENSOR_SetEXTPulsePeriod(uint32_t u32Period); + + + +#define SENSOR_STATIC_PULSE_HOLD_1_2 (0) +#define SENSOR_STATIC_PULSE_HOLD_1_4 (1) +#define SENSOR_STATIC_PULSE_HOLD_1_8 (2) +#define SENSOR_STATIC_PULSE_HOLD_1_16 (3) + +uint32_t SENSOR_GetEXTPulseHold(void); +uint32_t SENSOR_SetEXTPulseHold(uint32_t u32Hold); + + +FunctionalState SENSOR_GetEXTPulsePull(void); +FunctionalState SENSOR_SetEXTPulsePull(FunctionalState NewState); + + +#define SENSOR_SAMPLE_COUNT_1 (0) +#define SENSOR_SAMPLE_COUNT_2 (1) +#define SENSOR_SAMPLE_COUNT_3 (2) +#define SENSOR_SAMPLE_COUNT_4 (3) + + +uint32_t SENSOR_GetEXTStaticSample(void); +uint32_t SENSOR_SetEXTStaticSample(uint32_t u32Count); +uint32_t SENSOR_GetEXTDynamicSample(void); +uint32_t SENSOR_SetEXTDynamicSample(uint32_t u32Count); + + +uint32_t SENSOR_GetEXTDynamicFreq(void); +uint32_t SENSOR_SetEXTDynamicFreq(uint32_t u32Freq); + +#ifdef __cplusplus +} +#endif + +#endif + +/************************** (C) COPYRIGHT Megahunt *****END OF FILE****/ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_spi.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_spi.h new file mode 100644 index 0000000000..34ba9cace2 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_spi.h @@ -0,0 +1,497 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef __AIR105_SPI_H +#define __AIR105_SPI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + +#define SPI_DMACR_RDMAE_Pos (0) +#define SPI_DMACR_RDMAE_Mask (0x01U << SPI_DMACR_RDMAE_Pos) + +#define SPI_DMACR_TDMAE_Pos (1) +#define SPI_DMACR_TDMAE_Mask (0x01U << SPI_DMACR_TDMAE_Pos) + + +/** @defgroup SPI_Exported_Types + * @{ + */ + +/** + * @brief SPI Init structure definition + */ +typedef struct +{ + uint32_t SPI_Direction; /*!< Specifies the SPI unidirectional or bidirectional data mode. + This parameter can be a value of @ref SPI_data_direction */ + uint32_t SPI_Mode; /*!< Specifies the SPI operating mode. + This parameter can be a value of @ref SPI_mode */ + uint32_t SPI_DataSize; /*!< Specifies the SPI data size. + This parameter can be a value of @ref SPI_data_size */ + + uint32_t SPI_CPOL; /*!< Specifies the serial clock steady state. + This parameter can be a value of @ref SPI_Clock_Polarity */ + + uint32_t SPI_CPHA; /*!< Specifies the clock active edge for the bit capture. + This parameter can be a value of @ref SPI_Clock_Phase */ + + uint32_t SPI_NSS; /*!< Specifies whether the NSS signal is managed by + hardware (NSS pin) or by software using the SSI bit. + This parameter can be a value of @ref SPI_Slave_Select_management */ + + uint32_t SPI_BaudRatePrescaler; /*!< Specifies the Baud Rate prescaler value which will be + used to configure the transmit and receive SCK clock. + This parameter can be a value of @ref SPI_BaudRate_Prescaler. + @note The communication clock is derived from the master + clock. The slave clock does not need to be set. */ + uint32_t SPI_RXFIFOFullThreshold; + + uint32_t SPI_TXFIFOEmptyThreshold; +}SPI_InitTypeDef; + + +/** + * @brief Texas Instruments Synchronous Serial Protocol (SSP) Init structure definition + */ +typedef struct +{ + uint32_t SSP_Direction; /*!< Specifies the SPI unidirectional or bidirectional data mode. + This parameter can be a value of @ref SPI_data_direction */ + + uint32_t SSP_DataSize; /*!< Specifies the SPI data size. + This parameter can be a value of @ref SPI_data_size */ + + uint32_t SSP_NSS; /*!< Specifies whether the NSS signal is managed by + hardware (NSS pin) or by software using the SSI bit. + This parameter can be a value of @ref SPI_Slave_Select_management */ + + uint32_t SSP_BaudRatePrescaler; /*!< Specifies the Baud Rate prescaler value which will be + used to configure the transmit and receive SCK clock. + This parameter can be a value of @ref SPI_BaudRate_Prescaler. + @note The communication clock is derived from the master + clock. The slave clock does not need to be set. */ + + uint32_t SSP_RXFIFOFullThreshold; + + uint32_t SSP_TXFIFOEmptyThreshold; +}SSP_InitTypeDef; + + +/** + * @brief National Semiconductor Microwire (NSM) Init structure definition + */ +typedef struct +{ + uint32_t NSM_Direction; + + uint32_t NSM_TransferMode; + + uint32_t NSM_DataSize; /*!< Specifies the SPI data size. + This parameter can be a value of @ref SPI_data_size */ + uint32_t NSM_ControlDataSize; + + uint32_t NSM_NSS; /*!< Specifies whether the NSS signal is managed by + hardware (NSS pin) or by software using the SSI bit. + This parameter can be a value of @ref SPI_Slave_Select_management */ + + uint32_t NSM_BaudRatePrescaler; /*!< Specifies the Baud Rate prescaler value which will be + used to configure the transmit and receive SCK clock. + This parameter can be a value of @ref SPI_BaudRate_Prescaler. + @note The communication clock is derived from the master + clock. The slave clock does not need to be set. */ + + FunctionalState NSM_HandShakingCmd; + + uint32_t NSM_RXFIFOFullThreshold; + + uint32_t NSM_TXFIFOEmptyThreshold; +}NSM_InitTypeDef; + + +/** + * @brief SPI DMA Init structure definition + */ +typedef struct +{ + uint32_t SPI_DMAReq; + uint32_t SPI_DMAReceiveLevel; + uint32_t SPI_DMATransmitLevel; + FunctionalState SPI_DMAEnCmd; +}SPI_DMAInitTypeDef; + + +/** @defgroup SPI_data_direction + * @{ + */ +#define SPI_Direction_2Lines_FullDuplex ((uint32_t)0x0000) +#define SPI_Direction_1Line_Tx ((uint32_t)0x0100) +#define SPI_Direction_1Line_Rx ((uint32_t)0x0200) +#define SPI_Direction_EEPROM_Read ((uint32_t)0x0300) +#define IS_SPI_DIRECTION_MODE(MODE) (((MODE) == SPI_Direction_2Lines_FullDuplex) || \ + ((MODE) == SPI_Direction_1Line_Tx) || \ + ((MODE) == SPI_Direction_1Line_Rx) || \ + ((MODE) == SPI_Direction_EEPROM_Read)) +/** + * @} + */ + +#define SPI_Mode_Master ((uint32_t)0x0001) +#define SPI_Mode_Slave ((uint32_t)0x0000) +#define IS_SPI_MODE(MODE) (((MODE) == SPI_Mode_Master) || \ + ((MODE) == SPI_Mode_Slave)) + +/** @defgroup SPI_data_size + * @{ + */ +#define SPI_DataSize_8b ((uint32_t)0x0007) +#define SPI_DataSize_16b ((uint32_t)0x000F) +#define IS_SPI_DATASIZE(DATASIZE) (((DATASIZE) == SPI_DataSize_16b) || \ + ((DATASIZE) == SPI_DataSize_8b)) +/** + * @} + */ + +/** @defgroup SPI_Clock_Polarity + * @{ + */ + +#define SPI_CPOL_Low ((uint32_t)0x0000) +#define SPI_CPOL_High ((uint32_t)0x0080) +#define IS_SPI_CPOL(CPOL) (((CPOL) == SPI_CPOL_Low) || \ + ((CPOL) == SPI_CPOL_High)) +/** + * @} + */ + +/** @defgroup SPI_Clock_Phase + * @{ + */ +#define SPI_CPHA_1Edge ((uint32_t)0x0000) +#define SPI_CPHA_2Edge ((uint32_t)0x0040) +#define IS_SPI_CPHA(CPHA) (((CPHA) == SPI_CPHA_1Edge) || \ + ((CPHA) == SPI_CPHA_2Edge)) +/** + * @} + */ + +#define SPI_NSS_0 ((uint32_t)0x0001) +#define SPI_NSS_Null ((uint32_t)0x0000) +#define IS_SPI_NSS(NSS) (((NSS) == SPI_NSS_0) || \ + ((NSS) == SPI_NSS_Null)) + +/** @defgroup SPI_BaudRate_Prescaler + * @{ + */ +#define SPI_BaudRatePrescaler_2 ((uint32_t)0x0002) +#define SPI_BaudRatePrescaler_4 ((uint32_t)0x0004) +#define SPI_BaudRatePrescaler_8 ((uint32_t)0x0008) +#define SPI_BaudRatePrescaler_16 ((uint32_t)0x0010) +#define SPI_BaudRatePrescaler_32 ((uint32_t)0x0020) +#define SPI_BaudRatePrescaler_64 ((uint32_t)0x0040) +#define SPI_BaudRatePrescaler_128 ((uint32_t)0x0080) +#define SPI_BaudRatePrescaler_256 ((uint32_t)0x0100) +#define IS_SPI_BAUDRATE_PRESCALER(PRESCALER) (((PRESCALER) == SPI_BaudRatePrescaler_2) || \ + ((PRESCALER) == SPI_BaudRatePrescaler_4) || \ + ((PRESCALER) == SPI_BaudRatePrescaler_8) || \ + ((PRESCALER) == SPI_BaudRatePrescaler_16) || \ + ((PRESCALER) == SPI_BaudRatePrescaler_32) || \ + ((PRESCALER) == SPI_BaudRatePrescaler_64) || \ + ((PRESCALER) == SPI_BaudRatePrescaler_128) || \ + ((PRESCALER) == SPI_BaudRatePrescaler_256)) +/** + * @} + */ + +/** @defgroup SPI_RXFIFOFullThreshold + * @{ + */ +#define SPI_RXFIFOFullThreshold_1 ((uint32_t)0x0000) +#define SPI_RXFIFOFullThreshold_2 ((uint32_t)0x0001) +#define SPI_RXFIFOFullThreshold_3 ((uint32_t)0x0002) +#define SPI_RXFIFOFullThreshold_4 ((uint32_t)0x0003) +#define SPI_RXFIFOFullThreshold_5 ((uint32_t)0x0004) +#define SPI_RXFIFOFullThreshold_6 ((uint32_t)0x0005) +#define SPI_RXFIFOFullThreshold_7 ((uint32_t)0x0006) +#define SPI_RXFIFOFullThreshold_8 ((uint32_t)0x0007) +#define SPI_RXFIFOFullThreshold_9 ((uint32_t)0x0008) +#define SPI_RXFIFOFullThreshold_10 ((uint32_t)0x0009) +#define SPI_RXFIFOFullThreshold_11 ((uint32_t)0x000A) +#define SPI_RXFIFOFullThreshold_12 ((uint32_t)0x000B) +#define SPI_RXFIFOFullThreshold_13 ((uint32_t)0x000C) +#define SPI_RXFIFOFullThreshold_14 ((uint32_t)0x000D) +#define SPI_RXFIFOFullThreshold_15 ((uint32_t)0x000E) +#define SPI_RXFIFOFullThreshold_16 ((uint32_t)0x000F) + +#define IS_SPI_RX_FIFO_FULL_THRESHOLD(THRESHOLD) (((THRESHOLD) == SPI_RXFIFOFullThreshold_1) || \ + ((THRESHOLD) == SPI_RXFIFOFullThreshold_2) || \ + ((THRESHOLD) == SPI_RXFIFOFullThreshold_3) || \ + ((THRESHOLD) == SPI_RXFIFOFullThreshold_4) || \ + ((THRESHOLD) == SPI_RXFIFOFullThreshold_5) || \ + ((THRESHOLD) == SPI_RXFIFOFullThreshold_6) || \ + ((THRESHOLD) == SPI_RXFIFOFullThreshold_7) || \ + ((THRESHOLD) == SPI_RXFIFOFullThreshold_8) || \ + ((THRESHOLD) == SPI_RXFIFOFullThreshold_9) || \ + ((THRESHOLD) == SPI_RXFIFOFullThreshold_10) || \ + ((THRESHOLD) == SPI_RXFIFOFullThreshold_11) || \ + ((THRESHOLD) == SPI_RXFIFOFullThreshold_12) || \ + ((THRESHOLD) == SPI_RXFIFOFullThreshold_13) || \ + ((THRESHOLD) == SPI_RXFIFOFullThreshold_14) || \ + ((THRESHOLD) == SPI_RXFIFOFullThreshold_15) || \ + ((THRESHOLD) == SPI_RXFIFOFullThreshold_16)) +/** + * @} + */ + +/** @defgroup SPI_TXFIFOEmptyThreshold + * @{ + */ +#define SPI_TXFIFOEmptyThreshold_0 ((uint32_t)0x0000) +#define SPI_TXFIFOEmptyThreshold_1 ((uint32_t)0x0001) +#define SPI_TXFIFOEmptyThreshold_2 ((uint32_t)0x0002) +#define SPI_TXFIFOEmptyThreshold_3 ((uint32_t)0x0003) +#define SPI_TXFIFOEmptyThreshold_4 ((uint32_t)0x0004) +#define SPI_TXFIFOEmptyThreshold_5 ((uint32_t)0x0005) +#define SPI_TXFIFOEmptyThreshold_6 ((uint32_t)0x0006) +#define SPI_TXFIFOEmptyThreshold_7 ((uint32_t)0x0007) +#define SPI_TXFIFOEmptyThreshold_8 ((uint32_t)0x0008) +#define SPI_TXFIFOEmptyThreshold_9 ((uint32_t)0x0009) +#define SPI_TXFIFOEmptyThreshold_10 ((uint32_t)0x000A) +#define SPI_TXFIFOEmptyThreshold_11 ((uint32_t)0x000B) +#define SPI_TXFIFOEmptyThreshold_12 ((uint32_t)0x000C) +#define SPI_TXFIFOEmptyThreshold_13 ((uint32_t)0x000D) +#define SPI_TXFIFOEmptyThreshold_14 ((uint32_t)0x000E) +#define SPI_TXFIFOEmptyThreshold_15 ((uint32_t)0x000F) + +#define IS_SPI_TX_FIFO_EMPTY_THRESHOLD(THRESHOLD) (((THRESHOLD) == SPI_TXFIFOEmptyThreshold_0) || \ + ((THRESHOLD) == SPI_TXFIFOEmptyThreshold_1) || \ + ((THRESHOLD) == SPI_TXFIFOEmptyThreshold_2) || \ + ((THRESHOLD) == SPI_TXFIFOEmptyThreshold_3) || \ + ((THRESHOLD) == SPI_TXFIFOEmptyThreshold_4) || \ + ((THRESHOLD) == SPI_TXFIFOEmptyThreshold_5) || \ + ((THRESHOLD) == SPI_TXFIFOEmptyThreshold_6) || \ + ((THRESHOLD) == SPI_TXFIFOEmptyThreshold_7) || \ + ((THRESHOLD) == SPI_TXFIFOEmptyThreshold_8) || \ + ((THRESHOLD) == SPI_TXFIFOEmptyThreshold_9) || \ + ((THRESHOLD) == SPI_TXFIFOEmptyThreshold_10) || \ + ((THRESHOLD) == SPI_TXFIFOEmptyThreshold_11) || \ + ((THRESHOLD) == SPI_TXFIFOEmptyThreshold_12) || \ + ((THRESHOLD) == SPI_TXFIFOEmptyThreshold_13) || \ + ((THRESHOLD) == SPI_TXFIFOEmptyThreshold_14) || \ + ((THRESHOLD) <= SPI_TXFIFOEmptyThreshold_15)) +/** + * @} + */ + +/** @defgroup SPI_DMAReceiveLevel + * @{ + */ +#define SPI_DMAReceiveLevel_1 ((uint32_t)0x0000) +#define SPI_DMAReceiveLevel_2 ((uint32_t)0x0001) +#define SPI_DMAReceiveLevel_3 ((uint32_t)0x0002) +#define SPI_DMAReceiveLevel_4 ((uint32_t)0x0003) +#define SPI_DMAReceiveLevel_5 ((uint32_t)0x0004) +#define SPI_DMAReceiveLevel_6 ((uint32_t)0x0005) +#define SPI_DMAReceiveLevel_7 ((uint32_t)0x0006) +#define SPI_DMAReceiveLevel_8 ((uint32_t)0x0007) +#define SPI_DMAReceiveLevel_9 ((uint32_t)0x0008) +#define SPI_DMAReceiveLevel_10 ((uint32_t)0x0009) +#define SPI_DMAReceiveLevel_11 ((uint32_t)0x000A) +#define SPI_DMAReceiveLevel_12 ((uint32_t)0x000B) +#define SPI_DMAReceiveLevel_13 ((uint32_t)0x000C) +#define SPI_DMAReceiveLevel_14 ((uint32_t)0x000D) +#define SPI_DMAReceiveLevel_15 ((uint32_t)0x000E) +#define SPI_DMAReceiveLevel_16 ((uint32_t)0x000F) + +#define IS_SPI_DMA_RECEIVE_LEVEL(LEVEL) ((((int32_t)(LEVEL)) >= SPI_DMAReceiveLevel_1) && \ + (((int32_t)(LEVEL)) <= SPI_DMAReceiveLevel_16)) +/** + * @} + */ + +/** @defgroup SPI_DMATransmitLevel + * @{ + */ +#define SPI_DMATransmitLevel_0 ((uint32_t)0x0000) +#define SPI_DMATransmitLevel_1 ((uint32_t)0x0001) +#define SPI_DMATransmitLevel_2 ((uint32_t)0x0002) +#define SPI_DMATransmitLevel_3 ((uint32_t)0x0003) +#define SPI_DMATransmitLevel_4 ((uint32_t)0x0004) +#define SPI_DMATransmitLevel_5 ((uint32_t)0x0005) +#define SPI_DMATransmitLevel_6 ((uint32_t)0x0006) +#define SPI_DMATransmitLevel_7 ((uint32_t)0x0007) +#define SPI_DMATransmitLevel_8 ((uint32_t)0x0008) +#define SPI_DMATransmitLevel_9 ((uint32_t)0x0009) +#define SPI_DMATransmitLevel_10 ((uint32_t)0x000A) +#define SPI_DMATransmitLevel_11 ((uint32_t)0x000B) +#define SPI_DMATransmitLevel_12 ((uint32_t)0x000C) +#define SPI_DMATransmitLevel_13 ((uint32_t)0x000D) +#define SPI_DMATransmitLevel_14 ((uint32_t)0x000E) +#define SPI_DMATransmitLevel_15 ((uint32_t)0x000F) + +#define IS_SPI_DMA_TRANSMIT_LEVEL(LEVEL) ((((int32_t)(LEVEL)) >= SPI_DMATransmitLevel_0) && \ + (((int32_t)(LEVEL)) <= SPI_DMATransmitLevel_15)) +/** + * @} + */ + + +/** @defgroup SPI_DMA_transfer_requests + * @{ + */ +#define SPI_DMAReq_Rx ((uint32_t)0x0001) +#define SPI_DMAReq_Tx ((uint32_t)0x0002) +#define IS_SPI_DMAREQ(DMAREQ) ((((DMAREQ) & (uint32_t)0xFFFC) == (uint32_t)0x00) && \ + ((DMAREQ) != (uint32_t)0x00)) +/** + * @} + */ + +/** @defgroup SPI_Interrupt Mask and Status Flag + * @{ + */ +#define SPI_IT_TXE ((uint32_t)0x0001) //clear by hardware +#define SPI_IT_TXOVF ((uint32_t)0x0002) //clear by read TXOICR register +#define SPI_IT_RXF ((uint32_t)0x0010) //clear by hardware +#define SPI_IT_RXOVF ((uint32_t)0x0008) //clear by read RXOICR register +#define SPI_IT_RXUDF ((uint32_t)0x0004) //clear by read RXURCR register +#define SPI_IT_MMC ((uint32_t)0x0020) //clear by read MSTICR register +#define SPI_IT_All ((uint32_t)0x002E) +#define IS_SPI_GET_IT(IT) (((IT) == SPI_IT_TXE) || \ + ((IT) == SPI_IT_TXOVF) || \ + ((IT) == SPI_IT_RXF) || \ + ((IT) == SPI_IT_RXUDF) || \ + ((IT) == SPI_IT_RXOVF) || \ + ((IT) == SPI_IT_MMC)) + +#define SPI_FLAG_BSY ((uint32_t)0x0001) +#define SPI_FLAG_TXNF ((uint32_t)0x0002) //clear by hardware +#define SPI_FLAG_TXE ((uint32_t)0x0004) //clear by hardware +#define SPI_FLAG_RXNE ((uint32_t)0x0008) //clear by hardware +#define SPI_FLAG_RXF ((uint32_t)0x0010) //clear by hardware +#define SPI_FLAG_TXERR ((uint32_t)0x0020) //read clear +#define SPI_FLAG_DCERR ((uint32_t)0x0040) //read clear +#define IS_SPI_GET_FLAG(FLAG) (((FLAG) == SPI_SR_RFNE) || \ + ((FLAG) == SPI_SR_RFF) || \ + ((FLAG) == SPI_SR_TFE) || \ + ((FLAG) == SPI_SR_TFNF) || \ + ((FLAG) == SPI_SR_BUSY)) +/** + * @} + */ + +/** @defgroup NSM_Direction + * @{ + */ +#define NSM_Direction_Data_Transmit ((uint32_t)(0x0001)) +#define NSM_Direction_Data_Receive ((uint32_t)(0x0002)) +#define IS_NSM_DIRECTION_MODE(MODE) (((MODE) == NSM_Direction_Data_Transmit) || \ + ((MODE) == NSM_Direction_Data_Receive)) +/** + * @} + */ + + +/** @defgroup NSM_TransferMode + * @{ + */ +#define NSM_TransferMode_Non_Sequential ((uint32_t)(0x0001)) +#define NSM_TransferMode_Sequential ((uint32_t)(0x0002)) +#define IS_NSM_TRANSFER_MODE(MODE) (((MODE) == NSM_TransferMode_Non_Sequential) || \ + ((MODE) == NSM_TransferMode_Sequential)) +/** + * @} + */ + + +/** @defgroup NSM_DataSize + * @{ + */ +#define NSM_DataSize_8b ((uint32_t)0x0007) +#define NSM_DataSize_16b ((uint32_t)0x000F) +#define IS_NSM_DATASIZE(DATASIZE) (((DATASIZE) == NSM_DataSize_8b) || \ + ((DATASIZE) == NSM_DataSize_16b)) +/** + * @} + */ + + +/** @defgroup NSM_ControlDataSize + * @{ + */ +#define NSM_ControlDataSize_8b ((uint32_t)0x0007) +#define NSM_ControlDataSize_16b ((uint32_t)0x000F) +#define IS_NSM_CONTROL_DATASIZE(DATASIZE) (((DATASIZE) == NSM_ControlDataSize_8b) || \ + ((DATASIZE) == NSM_ControlDataSize_16b)) +/** + * @} + */ + +void SPI_DeInit(SPI_TypeDef* SPIx); +void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct); +void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct); +void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState); + +void SPI_DMAInit(SPI_TypeDef* SPIx, SPI_DMAInitTypeDef* SPI_DMAInitStruct); +void SPI_DMAStructInit(SPI_DMAInitTypeDef* SPI_DMAInitStruct); +void SPI_DMACmd(SPI_TypeDef* SPIx, uint32_t SPI_DMAReq, FunctionalState NewState); + +void SPI_ITConfig(SPI_TypeDef* SPIx, uint32_t SPI_IT, FunctionalState NewState); +void SPI_SendData(SPI_TypeDef* SPIx, uint16_t Data); +uint16_t SPI_ReceiveData(SPI_TypeDef* SPIx); +void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint32_t SPI_DataSize); +void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, uint32_t SPI_Direction); + +ITStatus SPI_GetITStatus(SPI_TypeDef* SPIx, uint32_t SPI_IT); +void SPI_ClearITPendingBit(SPI_TypeDef* SPIx, uint32_t SPI_IT); + +FlagStatus SPI_GetFlagStatus(SPI_TypeDef* SPIx, uint32_t SPI_FLAG); +uint32_t SPI_GetFlagStatusReg(SPI_TypeDef* SPIx); + +FlagStatus SPI_IsBusy(SPI_TypeDef* SPIx); +FlagStatus SPI_IsTXErr(SPI_TypeDef* SPIx); +FlagStatus SPI_IsDataCollisionErr(SPI_TypeDef* SPIx); + +void SSP_Init(SPI_TypeDef* SPIx, SSP_InitTypeDef* SSP_InitStruct); +void SSP_StructInit(SSP_InitTypeDef* SSP_InitStruct); + +void NSM_Init(SPI_TypeDef* SPIx, NSM_InitTypeDef* NSM_InitStruct); +void NSM_StructInit(NSM_InitTypeDef* NSM_InitStruct); + + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /*__MSSCPU_SPI_H */ + + +/************************** (C) COPYRIGHT Megahunt *****END OF FILE****/ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_ssc.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_ssc.h new file mode 100644 index 0000000000..f23b7b1099 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_ssc.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef __AIR105_SSC_H +#define __AIR105_SSC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + + +#define SSC_ITSysXTAL12M BIT(18) //ϵͳ��12Mʱ�ӱ�־ +#define SSC_ITSysGlitch BIT(17) //����Դë�̱�־ +#define SSC_ITSysVolHigh BIT(16) //����Դ��ѹ��־ +#define SSC_ITSysVolLow BIT(15) //����ԴǷѹ��־ + +typedef struct +{ + FunctionalState ParityCheck; //��żУ��ʹ�� +}SSC_InitTypeDef; + + +/* + * ��BPK��Ϊ4��ÿ��256����Ϊ��λ���ö�дȨ�� + * SSC_BPKAccessCtrBlock_0Ϊ��ʼ0��ַ�� + */ +#define SSC_BPKAccessCtrBlock_0 (0x01) +#define SSC_BPKAccessCtrBlock_1 (0x02) +#define SSC_BPKAccessCtrBlock_All (0x03) + +typedef enum +{ + SSC_BPKReadOnly = 0x01, //BPK��ֻ�� + SSC_BPKWriteOnly = 0x02, //BPK��ֻд + SSC_BPKReadWrite = 0x03 //BPK���д +}SSC_BPKAccessCtrlTypeDef; +#define IS_BPK_ACCESS_CTRL(CTRL) (((CTRL) == SSC_BPKReadOnly) || ((CTRL) == SSC_BPKWriteOnly) || \ + ((CTRL) == SSC_BPKReadWrite)) + +#define SSC_SENSOR_XTAL12M ((uint32_t)0x00000001) +#define SSC_SENSOR_VOL_LOW ((uint32_t)0x00000002) +#define SSC_SENSOR_VOL_HIGH ((uint32_t)0x00000004) +#define SSC_SENSOR_VOLGLITCH ((uint32_t)0x00000008) +#define IS_SSC_SENSOR(SENSOR) ((((SENSOR) & (uint32_t)0xFFFFFFF0) == 0x00) && ((SENSOR) != (uint32_t)0x00)) + +typedef enum +{ + SSC_SENSOR_CPUReset = 0, + SSC_SENSOR_Interrupt = 1 +}SSC_SENSOR_RespModeTypeDef; +#define IS_SSC_SENSOR_RESP_MODE(Mode) ((Mode) == SSC_SENSOR_CPUReset ||\ + (Mode) == SSC_SENSOR_Interrupt) + +/** + * @method SSC_Init + * @brief SSC��ȫ���Գ�ʼ�� + * @param SSC_InitTypeDef SSC_InitStruct + * @retval void + */ +void SSC_Init(SSC_InitTypeDef *SSC_InitStruct); + + +/** + * @method SSC_GetITStatus + * @brief SSC��ȫ�ж�״̬ + * @param uint32_t SSC_IT + * @retval ITStatus + */ +ITStatus SSC_GetITStatus(uint32_t SSC_IT); + + +/** + * @method SSC_ClearITPendingBit + * @brief SSC��ȫ�ж���� + * @param uint32_t SSC_IT + * @retval void + */ +void SSC_ClearITPendingBit( uint32_t SSC_IT); + + +/** + * @method SSC_SetDataRAMScrambler + * @brief ��������RAM���� + * @param uint32_t Scrambler + * @retval void + */ +void SSC_SetDataRAMScrambler(uint32_t Scrambler); + + +/** + * @method SSC_BPKAccessCtrConfig + * @brief ����BPK����Ȩ�� + * @param uint32_t SSC_BPKAccessCtrBlock + * @param SSC_BPKAccessCtrlTypeDef SSC_BPKAccessCtr + * @retval void + */ +void SSC_BPKAccessCtrlConfig(uint32_t SSC_BPKAccessCtrBlock, SSC_BPKAccessCtrlTypeDef SSC_BPKAccessCtr); + + +/** + * @method SSC_SENSOR_Enable + * @brief ����ϵͳSensor + * @param SSC_SENSOR + * @retval + */ +uint32_t SSC_SENSORCmd(uint32_t SSC_SENSOR, FunctionalState NewState); + + +/** + * @method SSC_SENSORLock + * @brief ����ϵͳSensor����״̬ + * @param SSC_SENSOR + * @retval + */ +void SSC_SENSORLock(uint32_t SSC_SENSOR); + + +/** + * @method SSC_SENSOR_AttackRespMode + * @brief ϵͳSensor��Ӧ��ʽ + * @param SSC_SENSOR_RespMode + * @retval + */ +void SSC_SENSORAttackRespMode(SSC_SENSOR_RespModeTypeDef SSC_SENSOR_RespMode); + + +void SSC_SENSORKeyClearCmd(uint32_t SSC_SENSOR, FunctionalState KeyClearEn); + + +#ifdef __cplusplus +} +#endif + +#endif + +/************************** (C) COPYRIGHT Megahunt *****END OF FILE****/ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_sysctrl.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_sysctrl.h new file mode 100644 index 0000000000..10a4d700de --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_sysctrl.h @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef __AIR105_SYSCTRL_H +#define __AIR105_SYSCTRL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + +#define SYSCTRL_FREQ_SEL_POWERMODE_Pos (24) +#define SYSCTRL_FREQ_SEL_POWERMODE_Mask (0x07 << SYSCTRL_FREQ_SEL_POWERMODE_Pos) +#define SYSCTRL_FREQ_SEL_POWERMODE_CLOSE_CPU (0x00 << SYSCTRL_FREQ_SEL_POWERMODE_Pos) +#define SYSCTRL_FREQ_SEL_POWERMODE_CLOSE_CPU_MEM (0x01 << SYSCTRL_FREQ_SEL_POWERMODE_Pos) + + +/** @defgroup SYSCTRL_Exported_Types + * @{ + */ +typedef struct +{ + uint32_t PLL_Frequency; /*!< returns PLL frequency expressed in Hz */ + uint32_t CPU_Frequency; /*!< returns CPU frequency expressed in Hz */ + uint32_t HCLK_Frequency; /*!< returns HCLK frequency expressed in Hz */ + uint32_t PCLK_Frequency; /*!< returns PCLK frequency expressed in Hz */ +}SYSCTRL_ClocksTypeDef; + +typedef enum +{ + SleepMode_CpuOff = 0, /*!< CPU Sleep */ + SleepMode_DeepSleep, /*!< Deep Sleep */ + SleepMode_Invalid +}SleepMode_TypeDef; +#define IS_ALL_SLEEP_MODE(MODE) ((MODE) < SleepMode_Invalid) + +typedef enum +{ + SELECT_EXT12M, + SELECT_INC12M +} SYSCLK_SOURCE_TypeDef; +#define IS_SYSCLK_SOURCE(FREQ) (((FREQ) == SELECT_EXT12M) || \ + ((FREQ) == SELECT_INC12M)) +typedef enum +{ + SYSCTRL_PLL_108MHz = (uint32_t)0x01, + SYSCTRL_PLL_120MHz = (uint32_t)0x02, + SYSCTRL_PLL_132MHz = (uint32_t)0x03, + SYSCTRL_PLL_144MHz = (uint32_t)0x04, + SYSCTRL_PLL_156MHz = (uint32_t)0x05, + SYSCTRL_PLL_168MHz = (uint32_t)0x06, + SYSCTRL_PLL_180MHz = (uint32_t)0x07, + SYSCTRL_PLL_192MHz = (uint32_t)0x08, + SYSCTRL_PLL_204MHz = (uint32_t)0x09 +}SYSCTRL_PLL_TypeDef; +#define IS_PLL_FREQ(FREQ) (((FREQ) == SYSCTRL_PLL_108MHz) || \ + ((FREQ) == SYSCTRL_PLL_120MHz) || \ + ((FREQ) == SYSCTRL_PLL_132MHz) || \ + ((FREQ) == SYSCTRL_PLL_144MHz) || \ + ((FREQ) == SYSCTRL_PLL_156MHz) || \ + ((FREQ) == SYSCTRL_PLL_168MHz) || \ + ((FREQ) == SYSCTRL_PLL_180MHz) || \ + ((FREQ) == SYSCTRL_PLL_192MHz) || \ + ((FREQ) == SYSCTRL_PLL_204MHz)) +/** + * @} + */ + +#define SYSCTRL_PLL_Div_None ((uint32_t)0x00) +#define SYSCTRL_PLL_Div2 ((uint32_t)0x01) +#define SYSCTRL_PLL_Div4 ((uint32_t)0x10) +#define IS_GET_SYSCTRL_PLL_DIV(DIV) (((DIV) == SYSCTRL_PLL_Div_None) || \ + ((DIV) == SYSCTRL_PLL_Div2) || \ + ((DIV) == SYSCTRL_PLL_Div4)) + +#define SYSCTRL_HCLK_Div_None ((uint32_t)0x00) +#define SYSCTRL_HCLK_Div2 ((uint32_t)0x01) +#define IS_GET_SYSCTRL_HCLK_DIV(DIV) (((DIV) == SYSCTRL_HCLK_Div_None) || \ + ((DIV) == SYSCTRL_HCLK_Div2)) + +#define SYSCTRL_PCLK_Div2 ((uint32_t)0x01) +#define SYSCTRL_PCLK_Div4 ((uint32_t)0x02) +#define IS_GET_SYSCTRL_PCLK_DIV(DIV) (((DIV) == SYSCTRL_PCLK_Div2) || \ + ((DIV) == SYSCTRL_PCLK_Div4)) + +#define SYSCTRL_CHIP_SN_ADDR ((uint32_t)0x40008804) +#define SYSCTRL_CHIP_SN_LEN ((uint32_t)0x10) + +#define SYSCTRL_USB_DOWNLOAD_FLAG ((uint32_t)0X55) + +void SYSCTRL_AHBPeriphClockCmd(uint32_t SYSCTRL_AHBPeriph, FunctionalState NewState); +void SYSCTRL_AHBPeriphResetCmd(uint32_t SYSCTRL_AHBPeriph, FunctionalState NewState); +void SYSCTRL_APBPeriphClockCmd(uint32_t SYSCTRL_APBPeriph, FunctionalState NewState); +void SYSCTRL_APBPeriphResetCmd(uint32_t SYSCTRL_APBPeriph, FunctionalState NewState); + +void SYSCTRL_EnterSleep(SleepMode_TypeDef SleepMode); + +void SYSCTRL_SYSCLKSourceSelect(SYSCLK_SOURCE_TypeDef source_select); +void SYSCTRL_PLLConfig(SYSCTRL_PLL_TypeDef PLL_Freq); +void SYSCTRL_PLLDivConfig(uint32_t PLL_Div); +void SYSCTRL_HCLKConfig(uint32_t HCLK_Div); +void SYSCTRL_PCLKConfig(uint32_t PCLK_Div); + +void SYSCTRL_GetClocksFreq(SYSCTRL_ClocksTypeDef* SYSCTRL_Clocks); +void SYSCTRL_GetChipSN(unsigned char *ChipSN); + +void SYSCTRL_SoftReset(void); +void SYSCTRL_EnterUSBDownload(void); + +#ifdef __cplusplus +} +#endif + +#endif + +/************************** (C) COPYRIGHT Megahunt *****END OF FILE****/ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_timer.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_timer.h new file mode 100644 index 0000000000..36b24ee2a0 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_timer.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef __AIR105_TIMER_H +#define __AIR105_TIMER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + +/* Exported types ------------------------------------------------------------*/ +typedef enum +{ + TIM_0 = 0, + TIM_1, + TIM_2, + TIM_3, + TIM_4, + TIM_5, + TIM_6, + TIM_7, +}TIM_NumTypeDef; + +typedef struct +{ + TIM_NumTypeDef TIMx; + uint32_t TIM_Period; /*!< Specifies the period value to be loaded into the active + Auto-Reload Register at the next update event. + This parameter must be a number between 0x0000 and 0xFFFFFFFF. */ +}TIM_InitTypeDef; + +typedef struct +{ + TIM_NumTypeDef TIMx; + uint32_t TIM_LowLevelPeriod; + uint32_t TIM_HighLevelPeriod; +}TIM_PWMInitTypeDef; + +typedef enum +{ + TIM_Mode_General = 0, + TIM_Mode_PWM = 1 +}TIM_ModeTypeDef; +#define IS_TIM_MODE(MODE) (MODE == TIM_Mode_General || MODE == TIM_Mode_PWM) + + +void TIM_DeInit(TIM_Module_TypeDef *TIMMx); +void TIM_Init(TIM_Module_TypeDef* TIMMx, TIM_InitTypeDef* TIM_InitStruct); + +void TIM_PWMInit(TIM_Module_TypeDef* TIMMx, TIM_PWMInitTypeDef* TIM_PWMInitStruct); +void TIM_Cmd(TIM_Module_TypeDef* TIMMx, TIM_NumTypeDef TIMx, FunctionalState NewState); +void TIM_ModeConfig(TIM_Module_TypeDef* TIMMx, TIM_NumTypeDef TIMx, TIM_ModeTypeDef TIM_Mode); +void TIM_SetPeriod(TIM_Module_TypeDef* TIMMx, TIM_NumTypeDef TIMx, uint32_t Period); +void TIM_SetPWMPeriod(TIM_Module_TypeDef* TIMMx, TIM_NumTypeDef TIMx, uint32_t PWM_LowLevelPeriod, uint32_t PWM_HighLevelPeriod); +void TIM_ITConfig(TIM_Module_TypeDef* TIMMx, TIM_NumTypeDef TIMx, FunctionalState NewState); +void TIM_ClearITPendingBit(TIM_Module_TypeDef* TIMMx, TIM_NumTypeDef TIMx); +void TIM_PWMSinglePulseConfig(TIM_Module_TypeDef* TIMMx, TIM_NumTypeDef TIMx, FunctionalState NewState); +void TIM_PWMReloadSinglePulse(TIM_Module_TypeDef *TIMMx, TIM_NumTypeDef TIMx); + +ITStatus TIM_GetITStatus(TIM_Module_TypeDef* TIMMx, TIM_NumTypeDef TIMx); +uint32_t TIM_GetAllITStatus(TIM_Module_TypeDef* TIMMx); +ITStatus TIM_GetRawITStatus(TIM_Module_TypeDef* TIMMx, TIM_NumTypeDef TIMx); +uint32_t TIM_GetAllRawITStatus(TIM_Module_TypeDef* TIMMx); + +uint32_t TIM_GetCounter(TIM_Module_TypeDef *TIMMx, TIM_NumTypeDef TIMx); + +#ifdef __cplusplus +} +#endif + +#endif + +/************************** (C) COPYRIGHT Megahunt *****END OF FILE****/ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_trng.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_trng.h new file mode 100644 index 0000000000..4c91a28921 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_trng.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef __AIR105_TRNG_H +#define __AIR105_TRNG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + +/** @defgroup RNG_Exported_Types + * @{ + */ +typedef enum{ + TRNG0 +} TRNG_ChannelTypeDef; +#define IS_TRNG_CHANNEL(CHANNEL) (((CHANNEL) == TRNG0)) + + +#define TRNG_IT_RNG0_S128 ((uint32_t)0x00000001) +#define TRNG_IT_RNG0_ATTACK ((uint32_t)0x00000004) +#define IS_TRNG_GET_IT(IT) (((IT) == TRNG_IT_RNG0_S128) || \ + ((IT) == TRNG_IT_RNG0_ATTACK)) + +/** @defgroup RNG_Exported_Functions + * @{ + */ +void TRNG_Start(TRNG_ChannelTypeDef TRNGx); +void TRNG_Stop(TRNG_ChannelTypeDef TRNGx); +uint32_t TRNG_Get(uint32_t rand[4], TRNG_ChannelTypeDef TRNGx); +void TRNG_SetPseudoRandom(uint32_t PseudoRandom); +void TRNG_DirectOutANA(TRNG_ChannelTypeDef TRNGx, FunctionalState NewState); + +void TRNG_ITConfig(FunctionalState NewState); +ITStatus TRNG_GetITStatus(uint32_t TRNG_IT); +void TRNG_ClearITPendingBit(uint32_t TRNG_IT); + + +#ifdef __cplusplus +} +#endif + +#endif + +/************************** (C) COPYRIGHT Megahunt *****END OF FILE****/ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_uart.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_uart.h new file mode 100644 index 0000000000..25fe0f8f24 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_uart.h @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef __AIR105_UART_H +#define __AIR105_UART_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + +/** + * @brief UART Init Structure definition + */ + +typedef struct +{ + uint32_t UART_BaudRate; /*!< This member configures the UART communication baud rate. + The baud rate is computed using the following formula: + - IntegerDivider = ((PCLKx) / (16 * (UART_InitStruct->UART_BaudRate))) + - FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */ + + uint32_t UART_WordLength; /*!< Specifies the number of data bits transmitted or received in a frame. + This parameter can be a value of @ref UART_Word_Length */ + + uint32_t UART_StopBits; /*!< Specifies the number of stop bits transmitted. + This parameter can be a value of @ref UART_Stop_Bits */ + + uint32_t UART_Parity; /*!< Specifies the parity mode. + This parameter can be a value of @ref UART_Parity + @note When parity is enabled, the computed parity is inserted + at the MSB position of the transmitted data (9th bit when + the word length is set to 9 data bits; 8th bit when the + word length is set to 8 data bits). */ + +} UART_InitTypeDef; +/** + * @} + */ + +#define IS_UART_PERIPH(PERIPH) (((PERIPH) == UART0) || \ + ((PERIPH) == UART1) || \ + ((PERIPH) == UART2) || \ + ((PERIPH) == UART3)) + +/** + * @brief UART FIFO Init Structure definition + */ +typedef struct +{ + FunctionalState FIFO_Enable; + uint32_t FIFO_DMA_Mode; + uint32_t FIFO_RX_Trigger; + uint32_t FIFO_TX_Trigger; + uint32_t FIFO_TX_TriggerIntEnable; +}UART_FIFOInitTypeDef; +/** + * @} + */ + +/** @defgroup UART_Word_Length + * @{ + */ + +#define UART_WordLength_5b (0x00000000) +#define UART_WordLength_6b (0x00000001) +#define UART_WordLength_7b (0x00000002) +#define UART_WordLength_8b (0x00000003) + +#define IS_UART_WORD_LENGTH(LENGTH) (((LENGTH) == UART_WordLength_5b) || \ + ((LENGTH) == UART_WordLength_6b) || \ + ((LENGTH) == UART_WordLength_7b) || \ + ((LENGTH) == UART_WordLength_8b)) +/** + * @} + */ + +/** @defgroup UART_Stop_Bits + * @{ + */ + +#define UART_StopBits_1 (0x00000000) +#define UART_StopBits_1_5 (0x00000004) +#define UART_StopBits_2 (0x00000004) +#define IS_UART_STOPBITS(STOPBITS, DATALENGTH) (((STOPBITS) == UART_StopBits_1) || \ + ((STOPBITS) == UART_StopBits_1_5 && DATALENGTH == UART_WordLength_5b) || \ + ((STOPBITS) == UART_StopBits_2 && DATALENGTH != UART_WordLength_5b)) +/** + * @} + */ + +/** @defgroup UART_Parity + * @{ + */ + +#define UART_Parity_No (0x00000000) +#define UART_Parity_Even (0x00000018) +#define UART_Parity_Odd (0x00000008) +#define IS_UART_PARITY(PARITY) (((PARITY) == UART_Parity_No) || \ + ((PARITY) == UART_Parity_Even) || \ + ((PARITY) == UART_Parity_Odd)) +/** + * @} + */ + +/** @defgroup UART_Mode + * @{ + */ + +#define UART_Mode_Rx ((uint16_t)0x0001) +#define UART_Mode_Tx ((uint16_t)0x0002) +#define IS_UART_MODE(MODE) ((((MODE) & (uint16_t)0xFFFC) == 0x00) && ((MODE) != (uint16_t)0x00)) +/** + * @} + */ + +/** @defgroup UART_Set_Check_define + * @{ + */ + +#define IS_UART_DATA(DATA) ((DATA) <= 0x000001FF) +#define IS_UART_BAUDRATE(BAUDRATE) (((BAUDRATE) > 0) && ((BAUDRATE) < 0x0044AA21)) + +/** + * @} + */ + +/** @defgroup UART_Interrupt_definition + * @{ + */ + +#define UART_IT_RX_RECVD (UART_IER_ERBFI) +#define UART_IT_TX_EMPTY (UART_IER_ETBEI) +#define UART_IT_LINE_STATUS (UART_IER_ELSI) +#define UART_IT_MODEM_STATUS (UART_IER_EDSSI) + +/** + * @} + */ + + +/** @defgroup UART_Interrupt_identity + * @{ + */ + +#define UART_IT_ID_MODEM_STATUS ((uint32_t)0x0000) +#define UART_IT_ID_NO_INTERRUPT ((uint32_t)0x0001) +#define UART_IT_ID_TX_EMPTY ((uint32_t)0x0002) +#define UART_IT_ID_RX_RECVD ((uint32_t)0x0004) +#define UART_IT_ID_LINE_STATUS ((uint32_t)0x0006) +#define UART_IT_ID_BUSY_DETECT ((uint32_t)0x0007) +#define UART_IT_ID_CHAR_TIMEOUT ((uint32_t)0x000C) + +/** + * @} + */ + + +/** @defgroup UART_FIFO_Control_define + * @{ + */ + +#define UART_FIFO_DEPTH (16) + +#define UART_FIFO_RX ((uint32_t)0x0000) +#define UART_FIFO_TX ((uint32_t)0x0001) + +#define UART_FIFO_DMA_Mode_0 ((uint32_t)0x0000) +#define UART_FIFO_DMA_Mode_1 ((uint32_t)0x0001) + +#define UART_FIFO_RX_Trigger_1_Char ((uint32_t)0x0000) +#define UART_FIFO_RX_Trigger_1_4_Full ((uint32_t)0x0001) +#define UART_FIFO_RX_Trigger_1_2_Full ((uint32_t)0x0002) +#define UART_FIFO_RX_Trigger_2_CharLessFull ((uint32_t)0x0003) + +#define UART_FIFO_TX_Trigger_Empty ((uint32_t)0x0000) +#define UART_FIFO_TX_Trigger_2_Chars ((uint32_t)0x0001) +#define UART_FIFO_TX_Trigger_1_4_Full ((uint32_t)0x0002) +#define UART_FIFO_TX_Trigger_1_2_Full ((uint32_t)0x0003) + +/** + * @} + */ + + +/** @defgroup UART_Line_Status_Flag_define + * @{ + */ +#define UART_LINE_STATUS_RX_RECVD (UART_LSR_DR) +#define UART_LINE_STATUS_RX_OVERRUN_ERROR (UART_LSR_OE) +#define UART_LINE_STATUS_RX_PARITY_ERROR (UART_LSR_PE) +#define UART_LINE_STATUS_RX_FRAMING_ERROR (UART_LSR_FE) +#define UART_LINE_STATUS_RX_BREAK_INTERRUPT (UART_LSR_BI) +#define UART_LINE_STATUS_TX_HOLDING_REGISTER_EMPTY (UART_LSR_THRE) +#define UART_LINE_STATUS_TX_EMPTY (UART_LSR_TEMT) +#define UART_LINE_STATUS_RX_FIFO_ERROR (UART_LSR_PFE) + +/** + * @} + */ + + +/** @defgroup UART_Modem_Status_Flag_define + * @{ + */ +#define UART_MODEM_STATUS_CTS_CHANGED (UART_MSR_DCTS) +#define UART_MODEM_STATUS_DSR_CHANGED (UART_MSR_DDSR) +#define UART_MODEM_STATUS_RI_CHANGED (UART_MSR_TERI) +#define UART_MODEM_STATUS_DCD_CHANGED (UART_MSR_DDCD) +#define UART_MODEM_STATUS_CTS (UART_MSR_CTS) +#define UART_MODEM_STATUS_DSR (UART_MSR_DSR) +#define UART_MODEM_STATUS_RI (UART_MSR_RI) +#define UART_MODEM_STATUS_DCD (UART_MSR_DCD) +/** + * @} + */ + + +/** @defgroup UART_Status_Flag_define + * @{ + */ +#define UART_STATUS_BUSY (UART_USR_BUSY) +#define UART_STATUS_TX_FIFO_NOT_FULL (UART_USR_TFNF) +#define UART_STATUS_TX_FIFO_EMPTY (UART_USR_TFE) +#define UART_STATUS_RX_FIFO_NOT_EMPTY (UART_USR_RFNE) +#define UART_STATUS_RX_FIFO_FULL (UART_USR_RFF) + + + +/** + * @} + */ + +void UART_DeInit(UART_TypeDef* UARTx); +void UART_Init(UART_TypeDef* UARTx, UART_InitTypeDef* UART_InitStruct); +void UART_StructInit(UART_InitTypeDef* UART_InitStruct); +void UART_ITConfig(UART_TypeDef* UARTx, uint32_t UART_IT, FunctionalState NewState); +void UART_SendData(UART_TypeDef* UARTx, uint8_t Data); +uint8_t UART_ReceiveData(UART_TypeDef* UARTx); +void UART_FIFOInit(UART_TypeDef* UARTx, UART_FIFOInitTypeDef* UART_FIFOInitStruct); +void UART_FIFOStructInit(UART_FIFOInitTypeDef* UART_FIFOInitStruct); +void UART_FIFOReset(UART_TypeDef* UARTx, uint32_t UART_FIFO); +void UART_FIFOCmd(UART_TypeDef* UARTx,FunctionalState NewState); +void UART_SetRTS(UART_TypeDef* UARTx); +void UART_ResetRTS(UART_TypeDef* UARTx); +void UART_SetDTR(UART_TypeDef* UARTx); +void UART_ResetDTR(UART_TypeDef* UARTx); +void UART_SendBreak(UART_TypeDef* UARTx); +void UART_AutoFlowCtrlCmd(UART_TypeDef* UARTx, FunctionalState NewState); +void UART_IrDACmd(UART_TypeDef* UARTx, FunctionalState NewState); + +uint32_t UART_GetLineStatus(UART_TypeDef* UARTx); +uint32_t UART_GetModemStatus(UART_TypeDef* UARTx); +uint32_t UART_GetITIdentity(UART_TypeDef* UARTx); + +Boolean UART_IsTXEmpty(UART_TypeDef* UARTx); +Boolean UART_IsTXHoldingRegisterEmpty(UART_TypeDef* UARTx); + +Boolean UART_IsRXFIFOFull(UART_TypeDef* UARTx); +Boolean UART_IsRXFIFONotEmpty(UART_TypeDef* UARTx); +Boolean UART_IsTXFIFOEmpty(UART_TypeDef* UARTx); +Boolean UART_IsTXFIFONotFull(UART_TypeDef* UARTx); +Boolean UART_IsBusy(UART_TypeDef* UARTx); + +void UART_DMAGenerateSoftAck(UART_TypeDef* UARTx); + +void UART_TXHaltCmd(UART_TypeDef* UARTx, FunctionalState NewStatus); +void UART_FIFOAccessModeCmd(UART_TypeDef* UARTx, FunctionalState NewStatus); +uint8_t UART_FIFOTxRead(UART_TypeDef* UARTx); + + +#ifdef __cplusplus +} +#endif + +#endif // __AIR105_UART_H + +/************************** (C) COPYRIGHT Megahunt *****END OF FILE****/ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_wdt.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_wdt.h new file mode 100644 index 0000000000..e84faee492 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/air105_wdt.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef __AIR105_WDT_H +#define __AIR105_WDT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + +typedef enum +{ + WDT_Mode_CPUReset = 0, + WDT_Mode_Interrupt = 1 +}WDT_ModeTypeDef; + +void WDT_SetReload(uint32_t Reload); +void WDT_ReloadCounter(void); +void WDT_Enable(void); +void WDT_ModeConfig(WDT_ModeTypeDef WDT_Mode); + +ITStatus WDT_GetITStatus(void); +void WDT_ClearITPendingBit(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/app_inc.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/app_inc.h new file mode 100644 index 0000000000..6edd151571 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/app_inc.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __APP_INC_H__ +#define __APP_INC_H__ +#include "bl_inc.h" + +#include "core_hwtimer.h" +#include "core_spi.h" +#include "core_adc.h" +#include "core_dac.h" +#include "core_wdt.h" +#include "core_usb_ll_driver.h" +#include "core_keyboard.h" +#include "core_dcmi.h" +#include "core_rng.h" + +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/arm_common_tables.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/arm_common_tables.h new file mode 100644 index 0000000000..03153851b8 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/arm_common_tables.h @@ -0,0 +1,136 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. October 2015 +* $Revision: V.1.4.5 a +* +* Project: CMSIS DSP Library +* Title: arm_common_tables.h +* +* Description: This file has extern declaration for common tables like Bitreverse, reciprocal etc which are used across different functions +* +* Target Processor: Cortex-M4/Cortex-M3 +* +* 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 LIMITED nor the names of its contributors +* may be used to endorse or promote products derived from this +* software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* -------------------------------------------------------------------- */ + +#ifndef _ARM_COMMON_TABLES_H +#define _ARM_COMMON_TABLES_H + +#include "arm_math.h" + +extern const uint16_t armBitRevTable[1024]; +extern const q15_t armRecipTableQ15[64]; +extern const q31_t armRecipTableQ31[64]; +/* extern const q31_t realCoefAQ31[1024]; */ +/* extern const q31_t realCoefBQ31[1024]; */ +extern const float32_t twiddleCoef_16[32]; +extern const float32_t twiddleCoef_32[64]; +extern const float32_t twiddleCoef_64[128]; +extern const float32_t twiddleCoef_128[256]; +extern const float32_t twiddleCoef_256[512]; +extern const float32_t twiddleCoef_512[1024]; +extern const float32_t twiddleCoef_1024[2048]; +extern const float32_t twiddleCoef_2048[4096]; +extern const float32_t twiddleCoef_4096[8192]; +#define twiddleCoef twiddleCoef_4096 +extern const q31_t twiddleCoef_16_q31[24]; +extern const q31_t twiddleCoef_32_q31[48]; +extern const q31_t twiddleCoef_64_q31[96]; +extern const q31_t twiddleCoef_128_q31[192]; +extern const q31_t twiddleCoef_256_q31[384]; +extern const q31_t twiddleCoef_512_q31[768]; +extern const q31_t twiddleCoef_1024_q31[1536]; +extern const q31_t twiddleCoef_2048_q31[3072]; +extern const q31_t twiddleCoef_4096_q31[6144]; +extern const q15_t twiddleCoef_16_q15[24]; +extern const q15_t twiddleCoef_32_q15[48]; +extern const q15_t twiddleCoef_64_q15[96]; +extern const q15_t twiddleCoef_128_q15[192]; +extern const q15_t twiddleCoef_256_q15[384]; +extern const q15_t twiddleCoef_512_q15[768]; +extern const q15_t twiddleCoef_1024_q15[1536]; +extern const q15_t twiddleCoef_2048_q15[3072]; +extern const q15_t twiddleCoef_4096_q15[6144]; +extern const float32_t twiddleCoef_rfft_32[32]; +extern const float32_t twiddleCoef_rfft_64[64]; +extern const float32_t twiddleCoef_rfft_128[128]; +extern const float32_t twiddleCoef_rfft_256[256]; +extern const float32_t twiddleCoef_rfft_512[512]; +extern const float32_t twiddleCoef_rfft_1024[1024]; +extern const float32_t twiddleCoef_rfft_2048[2048]; +extern const float32_t twiddleCoef_rfft_4096[4096]; + + +/* floating-point bit reversal tables */ +#define ARMBITREVINDEXTABLE__16_TABLE_LENGTH ((uint16_t)20 ) +#define ARMBITREVINDEXTABLE__32_TABLE_LENGTH ((uint16_t)48 ) +#define ARMBITREVINDEXTABLE__64_TABLE_LENGTH ((uint16_t)56 ) +#define ARMBITREVINDEXTABLE_128_TABLE_LENGTH ((uint16_t)208 ) +#define ARMBITREVINDEXTABLE_256_TABLE_LENGTH ((uint16_t)440 ) +#define ARMBITREVINDEXTABLE_512_TABLE_LENGTH ((uint16_t)448 ) +#define ARMBITREVINDEXTABLE1024_TABLE_LENGTH ((uint16_t)1800) +#define ARMBITREVINDEXTABLE2048_TABLE_LENGTH ((uint16_t)3808) +#define ARMBITREVINDEXTABLE4096_TABLE_LENGTH ((uint16_t)4032) + +extern const uint16_t armBitRevIndexTable16[ARMBITREVINDEXTABLE__16_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable32[ARMBITREVINDEXTABLE__32_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable64[ARMBITREVINDEXTABLE__64_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable128[ARMBITREVINDEXTABLE_128_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable256[ARMBITREVINDEXTABLE_256_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable512[ARMBITREVINDEXTABLE_512_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable1024[ARMBITREVINDEXTABLE1024_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable2048[ARMBITREVINDEXTABLE2048_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable4096[ARMBITREVINDEXTABLE4096_TABLE_LENGTH]; + +/* fixed-point bit reversal tables */ +#define ARMBITREVINDEXTABLE_FIXED___16_TABLE_LENGTH ((uint16_t)12 ) +#define ARMBITREVINDEXTABLE_FIXED___32_TABLE_LENGTH ((uint16_t)24 ) +#define ARMBITREVINDEXTABLE_FIXED___64_TABLE_LENGTH ((uint16_t)56 ) +#define ARMBITREVINDEXTABLE_FIXED__128_TABLE_LENGTH ((uint16_t)112 ) +#define ARMBITREVINDEXTABLE_FIXED__256_TABLE_LENGTH ((uint16_t)240 ) +#define ARMBITREVINDEXTABLE_FIXED__512_TABLE_LENGTH ((uint16_t)480 ) +#define ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH ((uint16_t)992 ) +#define ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH ((uint16_t)1984) +#define ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH ((uint16_t)4032) + +extern const uint16_t armBitRevIndexTable_fixed_16[ARMBITREVINDEXTABLE_FIXED___16_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_32[ARMBITREVINDEXTABLE_FIXED___32_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_64[ARMBITREVINDEXTABLE_FIXED___64_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_128[ARMBITREVINDEXTABLE_FIXED__128_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_256[ARMBITREVINDEXTABLE_FIXED__256_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_512[ARMBITREVINDEXTABLE_FIXED__512_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_1024[ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_2048[ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_4096[ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH]; + +/* Tables for Fast Math Sine and Cosine */ +extern const float32_t sinTable_f32[FAST_MATH_TABLE_SIZE + 1]; +extern const q31_t sinTable_q31[FAST_MATH_TABLE_SIZE + 1]; +extern const q15_t sinTable_q15[FAST_MATH_TABLE_SIZE + 1]; + +#endif /* ARM_COMMON_TABLES_H */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/arm_const_structs.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/arm_const_structs.h new file mode 100644 index 0000000000..2927e49b34 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/arm_const_structs.h @@ -0,0 +1,79 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. March 2015 +* $Revision: V.1.4.5 +* +* Project: CMSIS DSP Library +* Title: arm_const_structs.h +* +* Description: This file has constant structs that are initialized for +* user convenience. For example, some can be given as +* arguments to the arm_cfft_f32() function. +* +* Target Processor: Cortex-M4/Cortex-M3 +* +* 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 LIMITED nor the names of its contributors +* may be used to endorse or promote products derived from this +* software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* -------------------------------------------------------------------- */ + +#ifndef _ARM_CONST_STRUCTS_H +#define _ARM_CONST_STRUCTS_H + +#include "arm_math.h" +#include "arm_common_tables.h" + + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len16; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len32; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len64; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len128; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len256; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len512; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len1024; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len2048; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len4096; + + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len16; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len32; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len64; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len128; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len256; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len512; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len1024; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len2048; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len4096; + + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len16; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len32; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len64; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len128; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len256; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len512; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len1024; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len2048; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len4096; + +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/arm_math.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/arm_math.h new file mode 100644 index 0000000000..d33f8a9b3b --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/arm_math.h @@ -0,0 +1,7154 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2015 ARM Limited. All rights reserved. +* +* $Date: 20. October 2015 +* $Revision: V1.4.5 b +* +* Project: CMSIS DSP Library +* Title: arm_math.h +* +* Description: Public header file for CMSIS DSP Library +* +* Target Processor: Cortex-M7/Cortex-M4/Cortex-M3/Cortex-M0 +* +* 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 LIMITED nor the names of its contributors +* may be used to endorse or promote products derived from this +* software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. + * -------------------------------------------------------------------- */ + +/** + \mainpage CMSIS DSP Software Library + * + * Introduction + * ------------ + * + * This user manual describes the CMSIS DSP software library, + * a suite of common signal processing functions for use on Cortex-M processor based devices. + * + * The library is divided into a number of functions each covering a specific category: + * - Basic math functions + * - Fast math functions + * - Complex math functions + * - Filters + * - Matrix functions + * - Transforms + * - Motor control functions + * - Statistical functions + * - Support functions + * - Interpolation functions + * + * The library has separate functions for operating on 8-bit integers, 16-bit integers, + * 32-bit integer and 32-bit floating-point values. + * + * Using the Library + * ------------ + * + * The library installer contains prebuilt versions of the libraries in the Lib folder. + * - arm_cortexM7lfdp_math.lib (Little endian and Double Precision Floating Point Unit on Cortex-M7) + * - arm_cortexM7bfdp_math.lib (Big endian and Double Precision Floating Point Unit on Cortex-M7) + * - arm_cortexM7lfsp_math.lib (Little endian and Single Precision Floating Point Unit on Cortex-M7) + * - arm_cortexM7bfsp_math.lib (Big endian and Single Precision Floating Point Unit on Cortex-M7) + * - arm_cortexM7l_math.lib (Little endian on Cortex-M7) + * - arm_cortexM7b_math.lib (Big endian on Cortex-M7) + * - arm_cortexM4lf_math.lib (Little endian and Floating Point Unit on Cortex-M4) + * - arm_cortexM4bf_math.lib (Big endian and Floating Point Unit on Cortex-M4) + * - arm_cortexM4l_math.lib (Little endian on Cortex-M4) + * - arm_cortexM4b_math.lib (Big endian on Cortex-M4) + * - arm_cortexM3l_math.lib (Little endian on Cortex-M3) + * - arm_cortexM3b_math.lib (Big endian on Cortex-M3) + * - arm_cortexM0l_math.lib (Little endian on Cortex-M0 / CortexM0+) + * - arm_cortexM0b_math.lib (Big endian on Cortex-M0 / CortexM0+) + * + * The library functions are declared in the public file arm_math.h which is placed in the Include folder. + * Simply include this file and link the appropriate library in the application and begin calling the library functions. The Library supports single + * public header file arm_math.h for Cortex-M7/M4/M3/M0/M0+ with little endian and big endian. Same header file will be used for floating point unit(FPU) variants. + * Define the appropriate pre processor MACRO ARM_MATH_CM7 or ARM_MATH_CM4 or ARM_MATH_CM3 or + * ARM_MATH_CM0 or ARM_MATH_CM0PLUS depending on the target processor in the application. + * + * Examples + * -------- + * + * The library ships with a number of examples which demonstrate how to use the library functions. + * + * Toolchain Support + * ------------ + * + * The library has been developed and tested with MDK-ARM version 5.14.0.0 + * The library is being tested in GCC and IAR toolchains and updates on this activity will be made available shortly. + * + * Building the Library + * ------------ + * + * The library installer contains a project file to re build libraries on MDK-ARM Tool chain in the CMSIS\\DSP_Lib\\Source\\ARM folder. + * - arm_cortexM_math.uvprojx + * + * + * The libraries can be built by opening the arm_cortexM_math.uvprojx project in MDK-ARM, selecting a specific target, and defining the optional pre processor MACROs detailed above. + * + * Pre-processor Macros + * ------------ + * + * Each library project have differant pre-processor macros. + * + * - UNALIGNED_SUPPORT_DISABLE: + * + * Define macro UNALIGNED_SUPPORT_DISABLE, If the silicon does not support unaligned memory access + * + * - ARM_MATH_BIG_ENDIAN: + * + * Define macro ARM_MATH_BIG_ENDIAN to build the library for big endian targets. By default library builds for little endian targets. + * + * - ARM_MATH_MATRIX_CHECK: + * + * Define macro ARM_MATH_MATRIX_CHECK for checking on the input and output sizes of matrices + * + * - ARM_MATH_ROUNDING: + * + * Define macro ARM_MATH_ROUNDING for rounding on support functions + * + * - ARM_MATH_CMx: + * + * Define macro ARM_MATH_CM4 for building the library on Cortex-M4 target, ARM_MATH_CM3 for building library on Cortex-M3 target + * and ARM_MATH_CM0 for building library on Cortex-M0 target, ARM_MATH_CM0PLUS for building library on Cortex-M0+ target, and + * ARM_MATH_CM7 for building the library on cortex-M7. + * + * - __FPU_PRESENT: + * + * Initialize macro __FPU_PRESENT = 1 when building on FPU supported Targets. Enable this macro for M4bf and M4lf libraries + * + *


+ * CMSIS-DSP in ARM::CMSIS Pack + * ----------------------------- + * + * The following files relevant to CMSIS-DSP are present in the ARM::CMSIS Pack directories: + * |File/Folder |Content | + * |------------------------------|------------------------------------------------------------------------| + * |\b CMSIS\\Documentation\\DSP | This documentation | + * |\b CMSIS\\DSP_Lib | Software license agreement (license.txt) | + * |\b CMSIS\\DSP_Lib\\Examples | Example projects demonstrating the usage of the library functions | + * |\b CMSIS\\DSP_Lib\\Source | Source files for rebuilding the library | + * + *
+ * Revision History of CMSIS-DSP + * ------------ + * Please refer to \ref ChangeLog_pg. + * + * Copyright Notice + * ------------ + * + * Copyright (C) 2010-2015 ARM Limited. All rights reserved. + */ + + +/** + * @defgroup groupMath Basic Math Functions + */ + +/** + * @defgroup groupFastMath Fast Math Functions + * This set of functions provides a fast approximation to sine, cosine, and square root. + * As compared to most of the other functions in the CMSIS math library, the fast math functions + * operate on individual values and not arrays. + * There are separate functions for Q15, Q31, and floating-point data. + * + */ + +/** + * @defgroup groupCmplxMath Complex Math Functions + * This set of functions operates on complex data vectors. + * The data in the complex arrays is stored in an interleaved fashion + * (real, imag, real, imag, ...). + * In the API functions, the number of samples in a complex array refers + * to the number of complex values; the array contains twice this number of + * real values. + */ + +/** + * @defgroup groupFilters Filtering Functions + */ + +/** + * @defgroup groupMatrix Matrix Functions + * + * This set of functions provides basic matrix math operations. + * The functions operate on matrix data structures. For example, + * the type + * definition for the floating-point matrix structure is shown + * below: + *
+ *     typedef struct
+ *     {
+ *       uint16_t numRows;     // number of rows of the matrix.
+ *       uint16_t numCols;     // number of columns of the matrix.
+ *       float32_t *pData;     // points to the data of the matrix.
+ *     } arm_matrix_instance_f32;
+ * 
+ * There are similar definitions for Q15 and Q31 data types. + * + * The structure specifies the size of the matrix and then points to + * an array of data. The array is of size numRows X numCols + * and the values are arranged in row order. That is, the + * matrix element (i, j) is stored at: + *
+ *     pData[i*numCols + j]
+ * 
+ * + * \par Init Functions + * There is an associated initialization function for each type of matrix + * data structure. + * The initialization function sets the values of the internal structure fields. + * Refer to the function arm_mat_init_f32(), arm_mat_init_q31() + * and arm_mat_init_q15() for floating-point, Q31 and Q15 types, respectively. + * + * \par + * Use of the initialization function is optional. However, if initialization function is used + * then the instance structure cannot be placed into a const data section. + * To place the instance structure in a const data + * section, manually initialize the data structure. For example: + *
+ * arm_matrix_instance_f32 S = {nRows, nColumns, pData};
+ * arm_matrix_instance_q31 S = {nRows, nColumns, pData};
+ * arm_matrix_instance_q15 S = {nRows, nColumns, pData};
+ * 
+ * where nRows specifies the number of rows, nColumns + * specifies the number of columns, and pData points to the + * data array. + * + * \par Size Checking + * By default all of the matrix functions perform size checking on the input and + * output matrices. For example, the matrix addition function verifies that the + * two input matrices and the output matrix all have the same number of rows and + * columns. If the size check fails the functions return: + *
+ *     ARM_MATH_SIZE_MISMATCH
+ * 
+ * Otherwise the functions return + *
+ *     ARM_MATH_SUCCESS
+ * 
+ * There is some overhead associated with this matrix size checking. + * The matrix size checking is enabled via the \#define + *
+ *     ARM_MATH_MATRIX_CHECK
+ * 
+ * within the library project settings. By default this macro is defined + * and size checking is enabled. By changing the project settings and + * undefining this macro size checking is eliminated and the functions + * run a bit faster. With size checking disabled the functions always + * return ARM_MATH_SUCCESS. + */ + +/** + * @defgroup groupTransforms Transform Functions + */ + +/** + * @defgroup groupController Controller Functions + */ + +/** + * @defgroup groupStats Statistics Functions + */ +/** + * @defgroup groupSupport Support Functions + */ + +/** + * @defgroup groupInterpolation Interpolation Functions + * These functions perform 1- and 2-dimensional interpolation of data. + * Linear interpolation is used for 1-dimensional data and + * bilinear interpolation is used for 2-dimensional data. + */ + +/** + * @defgroup groupExamples Examples + */ +#ifndef _ARM_MATH_H +#define _ARM_MATH_H + +/* ignore some GCC warnings */ +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +#define __CMSIS_GENERIC /* disable NVIC and Systick functions */ + +#if defined(ARM_MATH_CM7) + #include "core_cm7.h" +#elif defined (ARM_MATH_CM4) + #include "core_cm4.h" +#elif defined (ARM_MATH_CM3) + #include "core_cm3.h" +#elif defined (ARM_MATH_CM0) + #include "core_cm0.h" + #define ARM_MATH_CM0_FAMILY +#elif defined (ARM_MATH_CM0PLUS) + #include "core_cm0plus.h" + #define ARM_MATH_CM0_FAMILY +#else + #error "Define according the used Cortex core ARM_MATH_CM7, ARM_MATH_CM4, ARM_MATH_CM3, ARM_MATH_CM0PLUS or ARM_MATH_CM0" +#endif + +#undef __CMSIS_GENERIC /* enable NVIC and Systick functions */ +#include "string.h" +#include "math.h" +#ifdef __cplusplus +extern "C" +{ +#endif + + + /** + * @brief Macros required for reciprocal calculation in Normalized LMS + */ + +#define DELTA_Q31 (0x100) +#define DELTA_Q15 0x5 +#define INDEX_MASK 0x0000003F +#ifndef PI +#define PI 3.14159265358979f +#endif + + /** + * @brief Macros required for SINE and COSINE Fast math approximations + */ + +#define FAST_MATH_TABLE_SIZE 512 +#define FAST_MATH_Q31_SHIFT (32 - 10) +#define FAST_MATH_Q15_SHIFT (16 - 10) +#define CONTROLLER_Q31_SHIFT (32 - 9) +#define TABLE_SIZE 256 +#define TABLE_SPACING_Q31 0x400000 +#define TABLE_SPACING_Q15 0x80 + + /** + * @brief Macros required for SINE and COSINE Controller functions + */ + /* 1.31(q31) Fixed value of 2/360 */ + /* -1 to +1 is divided into 360 values so total spacing is (2/360) */ +#define INPUT_SPACING 0xB60B61 + + /** + * @brief Macro for Unaligned Support + */ +#ifndef UNALIGNED_SUPPORT_DISABLE + #define ALIGN4 +#else + #if defined (__GNUC__) + #define ALIGN4 __attribute__((aligned(4))) + #else + #define ALIGN4 __align(4) + #endif +#endif /* #ifndef UNALIGNED_SUPPORT_DISABLE */ + + /** + * @brief Error status returned by some functions in the library. + */ + + typedef enum + { + ARM_MATH_SUCCESS = 0, /**< No error */ + ARM_MATH_ARGUMENT_ERROR = -1, /**< One or more arguments are incorrect */ + ARM_MATH_LENGTH_ERROR = -2, /**< Length of data buffer is incorrect */ + ARM_MATH_SIZE_MISMATCH = -3, /**< Size of matrices is not compatible with the operation. */ + ARM_MATH_NANINF = -4, /**< Not-a-number (NaN) or infinity is generated */ + ARM_MATH_SINGULAR = -5, /**< Generated by matrix inversion if the input matrix is singular and cannot be inverted. */ + ARM_MATH_TEST_FAILURE = -6 /**< Test Failed */ + } arm_status; + + /** + * @brief 8-bit fractional data type in 1.7 format. + */ + typedef int8_t q7_t; + + /** + * @brief 16-bit fractional data type in 1.15 format. + */ + typedef int16_t q15_t; + + /** + * @brief 32-bit fractional data type in 1.31 format. + */ + typedef int32_t q31_t; + + /** + * @brief 64-bit fractional data type in 1.63 format. + */ + typedef int64_t q63_t; + + /** + * @brief 32-bit floating-point type definition. + */ + typedef float float32_t; + + /** + * @brief 64-bit floating-point type definition. + */ + typedef double float64_t; + + /** + * @brief definition to read/write two 16 bit values. + */ +#if defined __CC_ARM + #define __SIMD32_TYPE int32_t __packed + #define CMSIS_UNUSED __attribute__((unused)) + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED __attribute__((unused)) + +#elif defined __GNUC__ + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED __attribute__((unused)) + +#elif defined __ICCARM__ + #define __SIMD32_TYPE int32_t __packed + #define CMSIS_UNUSED + +#elif defined __CSMC__ + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED + +#elif defined __TASKING__ + #define __SIMD32_TYPE __unaligned int32_t + #define CMSIS_UNUSED + +#else + #error Unknown compiler +#endif + +#define __SIMD32(addr) (*(__SIMD32_TYPE **) & (addr)) +#define __SIMD32_CONST(addr) ((__SIMD32_TYPE *)(addr)) +#define _SIMD32_OFFSET(addr) (*(__SIMD32_TYPE *) (addr)) +#define __SIMD64(addr) (*(int64_t **) & (addr)) + +#if defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) + /** + * @brief definition to pack two 16 bit values. + */ +#define __PKHBT(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0x0000FFFF) | \ + (((int32_t)(ARG2) << ARG3) & (int32_t)0xFFFF0000) ) +#define __PKHTB(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0xFFFF0000) | \ + (((int32_t)(ARG2) >> ARG3) & (int32_t)0x0000FFFF) ) + +#endif + + + /** + * @brief definition to pack four 8 bit values. + */ +#ifndef ARM_MATH_BIG_ENDIAN + +#define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v0) << 0) & (int32_t)0x000000FF) | \ + (((int32_t)(v1) << 8) & (int32_t)0x0000FF00) | \ + (((int32_t)(v2) << 16) & (int32_t)0x00FF0000) | \ + (((int32_t)(v3) << 24) & (int32_t)0xFF000000) ) +#else + +#define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v3) << 0) & (int32_t)0x000000FF) | \ + (((int32_t)(v2) << 8) & (int32_t)0x0000FF00) | \ + (((int32_t)(v1) << 16) & (int32_t)0x00FF0000) | \ + (((int32_t)(v0) << 24) & (int32_t)0xFF000000) ) + +#endif + + + /** + * @brief Clips Q63 to Q31 values. + */ + static __INLINE q31_t clip_q63_to_q31( + q63_t x) + { + return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ? + ((0x7FFFFFFF ^ ((q31_t) (x >> 63)))) : (q31_t) x; + } + + /** + * @brief Clips Q63 to Q15 values. + */ + static __INLINE q15_t clip_q63_to_q15( + q63_t x) + { + return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ? + ((0x7FFF ^ ((q15_t) (x >> 63)))) : (q15_t) (x >> 15); + } + + /** + * @brief Clips Q31 to Q7 values. + */ + static __INLINE q7_t clip_q31_to_q7( + q31_t x) + { + return ((q31_t) (x >> 24) != ((q31_t) x >> 23)) ? + ((0x7F ^ ((q7_t) (x >> 31)))) : (q7_t) x; + } + + /** + * @brief Clips Q31 to Q15 values. + */ + static __INLINE q15_t clip_q31_to_q15( + q31_t x) + { + return ((q31_t) (x >> 16) != ((q31_t) x >> 15)) ? + ((0x7FFF ^ ((q15_t) (x >> 31)))) : (q15_t) x; + } + + /** + * @brief Multiplies 32 X 64 and returns 32 bit result in 2.30 format. + */ + + static __INLINE q63_t mult32x64( + q63_t x, + q31_t y) + { + return ((((q63_t) (x & 0x00000000FFFFFFFF) * y) >> 32) + + (((q63_t) (x >> 32) * y))); + } + +/* + #if defined (ARM_MATH_CM0_FAMILY) && defined ( __CC_ARM ) + #define __CLZ __clz + #endif + */ +/* note: function can be removed when all toolchain support __CLZ for Cortex-M0 */ +#if defined (ARM_MATH_CM0_FAMILY) && ((defined (__ICCARM__)) ) + static __INLINE uint32_t __CLZ( + q31_t data); + + static __INLINE uint32_t __CLZ( + q31_t data) + { + uint32_t count = 0; + uint32_t mask = 0x80000000; + + while((data & mask) == 0) + { + count += 1u; + mask = mask >> 1u; + } + + return (count); + } +#endif + + /** + * @brief Function to Calculates 1/in (reciprocal) value of Q31 Data type. + */ + + static __INLINE uint32_t arm_recip_q31( + q31_t in, + q31_t * dst, + q31_t * pRecipTable) + { + q31_t out; + uint32_t tempVal; + uint32_t index, i; + uint32_t signBits; + + if(in > 0) + { + signBits = ((uint32_t) (__CLZ( in) - 1)); + } + else + { + signBits = ((uint32_t) (__CLZ(-in) - 1)); + } + + /* Convert input sample to 1.31 format */ + in = (in << signBits); + + /* calculation of index for initial approximated Val */ + index = (uint32_t)(in >> 24); + index = (index & INDEX_MASK); + + /* 1.31 with exp 1 */ + out = pRecipTable[index]; + + /* calculation of reciprocal value */ + /* running approximation for two iterations */ + for (i = 0u; i < 2u; i++) + { + tempVal = (uint32_t) (((q63_t) in * out) >> 31); + tempVal = 0x7FFFFFFFu - tempVal; + /* 1.31 with exp 1 */ + /* out = (q31_t) (((q63_t) out * tempVal) >> 30); */ + out = clip_q63_to_q31(((q63_t) out * tempVal) >> 30); + } + + /* write output */ + *dst = out; + + /* return num of signbits of out = 1/in value */ + return (signBits + 1u); + } + + + /** + * @brief Function to Calculates 1/in (reciprocal) value of Q15 Data type. + */ + static __INLINE uint32_t arm_recip_q15( + q15_t in, + q15_t * dst, + q15_t * pRecipTable) + { + q15_t out = 0; + uint32_t tempVal = 0; + uint32_t index = 0, i = 0; + uint32_t signBits = 0; + + if(in > 0) + { + signBits = ((uint32_t)(__CLZ( in) - 17)); + } + else + { + signBits = ((uint32_t)(__CLZ(-in) - 17)); + } + + /* Convert input sample to 1.15 format */ + in = (in << signBits); + + /* calculation of index for initial approximated Val */ + index = (uint32_t)(in >> 8); + index = (index & INDEX_MASK); + + /* 1.15 with exp 1 */ + out = pRecipTable[index]; + + /* calculation of reciprocal value */ + /* running approximation for two iterations */ + for (i = 0u; i < 2u; i++) + { + tempVal = (uint32_t) (((q31_t) in * out) >> 15); + tempVal = 0x7FFFu - tempVal; + /* 1.15 with exp 1 */ + out = (q15_t) (((q31_t) out * tempVal) >> 14); + /* out = clip_q31_to_q15(((q31_t) out * tempVal) >> 14); */ + } + + /* write output */ + *dst = out; + + /* return num of signbits of out = 1/in value */ + return (signBits + 1); + } + + + /* + * @brief C custom defined intrinisic function for only M0 processors + */ +#if defined(ARM_MATH_CM0_FAMILY) + static __INLINE q31_t __SSAT( + q31_t x, + uint32_t y) + { + int32_t posMax, negMin; + uint32_t i; + + posMax = 1; + for (i = 0; i < (y - 1); i++) + { + posMax = posMax * 2; + } + + if(x > 0) + { + posMax = (posMax - 1); + + if(x > posMax) + { + x = posMax; + } + } + else + { + negMin = -posMax; + + if(x < negMin) + { + x = negMin; + } + } + return (x); + } +#endif /* end of ARM_MATH_CM0_FAMILY */ + + + /* + * @brief C custom defined intrinsic function for M3 and M0 processors + */ +#if defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) + + /* + * @brief C custom defined QADD8 for M3 and M0 processors + */ + static __INLINE uint32_t __QADD8( + uint32_t x, + uint32_t y) + { + q31_t r, s, t, u; + + r = __SSAT(((((q31_t)x << 24) >> 24) + (((q31_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((q31_t)x << 16) >> 24) + (((q31_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((q31_t)x << 8) >> 24) + (((q31_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((q31_t)x ) >> 24) + (((q31_t)y ) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r ))); + } + + + /* + * @brief C custom defined QSUB8 for M3 and M0 processors + */ + static __INLINE uint32_t __QSUB8( + uint32_t x, + uint32_t y) + { + q31_t r, s, t, u; + + r = __SSAT(((((q31_t)x << 24) >> 24) - (((q31_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((q31_t)x << 16) >> 24) - (((q31_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((q31_t)x << 8) >> 24) - (((q31_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((q31_t)x ) >> 24) - (((q31_t)y ) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r ))); + } + + + /* + * @brief C custom defined QADD16 for M3 and M0 processors + */ + static __INLINE uint32_t __QADD16( + uint32_t x, + uint32_t y) + { +/* q31_t r, s; without initialisation 'arm_offset_q15 test' fails but 'intrinsic' tests pass! for armCC */ + q31_t r = 0, s = 0; + + r = __SSAT(((((q31_t)x << 16) >> 16) + (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) + (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHADD16 for M3 and M0 processors + */ + static __INLINE uint32_t __SHADD16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) + (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) + (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QSUB16 for M3 and M0 processors + */ + static __INLINE uint32_t __QSUB16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) - (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) - (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHSUB16 for M3 and M0 processors + */ + static __INLINE uint32_t __SHSUB16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) - (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) - (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QASX for M3 and M0 processors + */ + static __INLINE uint32_t __QASX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) - (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) + (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHASX for M3 and M0 processors + */ + static __INLINE uint32_t __SHASX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) - (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) + (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QSAX for M3 and M0 processors + */ + static __INLINE uint32_t __QSAX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) + (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) - (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHSAX for M3 and M0 processors + */ + static __INLINE uint32_t __SHSAX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) + (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) - (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SMUSDX for M3 and M0 processors + */ + static __INLINE uint32_t __SMUSDX( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) )); + } + + /* + * @brief C custom defined SMUADX for M3 and M0 processors + */ + static __INLINE uint32_t __SMUADX( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) )); + } + + + /* + * @brief C custom defined QADD for M3 and M0 processors + */ + static __INLINE int32_t __QADD( + int32_t x, + int32_t y) + { + return ((int32_t)(clip_q63_to_q31((q63_t)x + (q31_t)y))); + } + + + /* + * @brief C custom defined QSUB for M3 and M0 processors + */ + static __INLINE int32_t __QSUB( + int32_t x, + int32_t y) + { + return ((int32_t)(clip_q63_to_q31((q63_t)x - (q31_t)y))); + } + + + /* + * @brief C custom defined SMLAD for M3 and M0 processors + */ + static __INLINE uint32_t __SMLAD( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLADX for M3 and M0 processors + */ + static __INLINE uint32_t __SMLADX( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLSDX for M3 and M0 processors + */ + static __INLINE uint32_t __SMLSDX( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLALD for M3 and M0 processors + */ + static __INLINE uint64_t __SMLALD( + uint32_t x, + uint32_t y, + uint64_t sum) + { +/* return (sum + ((q15_t) (x >> 16) * (q15_t) (y >> 16)) + ((q15_t) x * (q15_t) y)); */ + return ((uint64_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) + + ( ((q63_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLALDX for M3 and M0 processors + */ + static __INLINE uint64_t __SMLALDX( + uint32_t x, + uint32_t y, + uint64_t sum) + { +/* return (sum + ((q15_t) (x >> 16) * (q15_t) y)) + ((q15_t) x * (q15_t) (y >> 16)); */ + return ((uint64_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q63_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMUAD for M3 and M0 processors + */ + static __INLINE uint32_t __SMUAD( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) )); + } + + + /* + * @brief C custom defined SMUSD for M3 and M0 processors + */ + static __INLINE uint32_t __SMUSD( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) )); + } + + + /* + * @brief C custom defined SXTB16 for M3 and M0 processors + */ + static __INLINE uint32_t __SXTB16( + uint32_t x) + { + return ((uint32_t)(((((q31_t)x << 24) >> 24) & (q31_t)0x0000FFFF) | + ((((q31_t)x << 8) >> 8) & (q31_t)0xFFFF0000) )); + } + +#endif /* defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) */ + + + /** + * @brief Instance structure for the Q7 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q7_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + } arm_fir_instance_q7; + + /** + * @brief Instance structure for the Q15 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + } arm_fir_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + } arm_fir_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + } arm_fir_instance_f32; + + + /** + * @brief Processing function for the Q7 FIR filter. + * @param[in] S points to an instance of the Q7 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q7( + const arm_fir_instance_q7 * S, + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q7 FIR filter. + * @param[in,out] S points to an instance of the Q7 FIR structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed. + */ + void arm_fir_init_q7( + arm_fir_instance_q7 * S, + uint16_t numTaps, + q7_t * pCoeffs, + q7_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR filter. + * @param[in] S points to an instance of the Q15 FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q15( + const arm_fir_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the fast Q15 FIR filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_fast_q15( + const arm_fir_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR filter. + * @param[in,out] S points to an instance of the Q15 FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. Must be even and greater than or equal to 4. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + * @return The function returns ARM_MATH_SUCCESS if initialization was successful or ARM_MATH_ARGUMENT_ERROR if + * numTaps is not a supported value. + */ + arm_status arm_fir_init_q15( + arm_fir_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR filter. + * @param[in] S points to an instance of the Q31 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q31( + const arm_fir_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the fast Q31 FIR filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_fast_q31( + const arm_fir_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR filter. + * @param[in,out] S points to an instance of the Q31 FIR structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + */ + void arm_fir_init_q31( + arm_fir_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point FIR filter. + * @param[in] S points to an instance of the floating-point FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_f32( + const arm_fir_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR filter. + * @param[in,out] S points to an instance of the floating-point FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + */ + void arm_fir_init_f32( + arm_fir_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 Biquad cascade filter. + */ + typedef struct + { + int8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q15_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + q15_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + int8_t postShift; /**< Additional shift, in bits, applied to each output sample. */ + } arm_biquad_casd_df1_inst_q15; + + /** + * @brief Instance structure for the Q31 Biquad cascade filter. + */ + typedef struct + { + uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q31_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + q31_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + uint8_t postShift; /**< Additional shift, in bits, applied to each output sample. */ + } arm_biquad_casd_df1_inst_q31; + + /** + * @brief Instance structure for the floating-point Biquad cascade filter. + */ + typedef struct + { + uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + float32_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_casd_df1_inst_f32; + + + /** + * @brief Processing function for the Q15 Biquad cascade filter. + * @param[in] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_q15( + const arm_biquad_casd_df1_inst_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 Biquad cascade filter. + * @param[in,out] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cascade_df1_init_q15( + arm_biquad_casd_df1_inst_q15 * S, + uint8_t numStages, + q15_t * pCoeffs, + q15_t * pState, + int8_t postShift); + + + /** + * @brief Fast but less precise processing function for the Q15 Biquad cascade filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_fast_q15( + const arm_biquad_casd_df1_inst_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 Biquad cascade filter + * @param[in] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_q31( + const arm_biquad_casd_df1_inst_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fast but less precise processing function for the Q31 Biquad cascade filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_fast_q31( + const arm_biquad_casd_df1_inst_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 Biquad cascade filter. + * @param[in,out] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cascade_df1_init_q31( + arm_biquad_casd_df1_inst_q31 * S, + uint8_t numStages, + q31_t * pCoeffs, + q31_t * pState, + int8_t postShift); + + + /** + * @brief Processing function for the floating-point Biquad cascade filter. + * @param[in] S points to an instance of the floating-point Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_f32( + const arm_biquad_casd_df1_inst_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point Biquad cascade filter. + * @param[in,out] S points to an instance of the floating-point Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df1_init_f32( + arm_biquad_casd_df1_inst_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Instance structure for the floating-point matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + float32_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_f32; + + + /** + * @brief Instance structure for the floating-point matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + float64_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_f64; + + /** + * @brief Instance structure for the Q15 matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + q15_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_q15; + + /** + * @brief Instance structure for the Q31 matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + q31_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_q31; + + + /** + * @brief Floating-point matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pScratch); + + + /** + * @brief Q31, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_f32( + const arm_matrix_instance_f32 * pSrc, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_q15( + const arm_matrix_instance_q15 * pSrc, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_q31( + const arm_matrix_instance_q31 * pSrc, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @param[in] pState points to the array for storing intermediate results + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pState); + + + /** + * @brief Q15 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @param[in] pState points to the array for storing intermediate results + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_fast_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pState); + + + /** + * @brief Q31 matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Q31 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_fast_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix scaling. + * @param[in] pSrc points to the input matrix + * @param[in] scale scale factor + * @param[out] pDst points to the output matrix + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_f32( + const arm_matrix_instance_f32 * pSrc, + float32_t scale, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix scaling. + * @param[in] pSrc points to input matrix + * @param[in] scaleFract fractional portion of the scale factor + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to output matrix + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_q15( + const arm_matrix_instance_q15 * pSrc, + q15_t scaleFract, + int32_t shift, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix scaling. + * @param[in] pSrc points to input matrix + * @param[in] scaleFract fractional portion of the scale factor + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_q31( + const arm_matrix_instance_q31 * pSrc, + q31_t scaleFract, + int32_t shift, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Q31 matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_q31( + arm_matrix_instance_q31 * S, + uint16_t nRows, + uint16_t nColumns, + q31_t * pData); + + + /** + * @brief Q15 matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_q15( + arm_matrix_instance_q15 * S, + uint16_t nRows, + uint16_t nColumns, + q15_t * pData); + + + /** + * @brief Floating-point matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_f32( + arm_matrix_instance_f32 * S, + uint16_t nRows, + uint16_t nColumns, + float32_t * pData); + + + + /** + * @brief Instance structure for the Q15 PID Control. + */ + typedef struct + { + q15_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ +#ifdef ARM_MATH_CM0_FAMILY + q15_t A1; + q15_t A2; +#else + q31_t A1; /**< The derived gain A1 = -Kp - 2Kd | Kd.*/ +#endif + q15_t state[3]; /**< The state array of length 3. */ + q15_t Kp; /**< The proportional gain. */ + q15_t Ki; /**< The integral gain. */ + q15_t Kd; /**< The derivative gain. */ + } arm_pid_instance_q15; + + /** + * @brief Instance structure for the Q31 PID Control. + */ + typedef struct + { + q31_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ + q31_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */ + q31_t A2; /**< The derived gain, A2 = Kd . */ + q31_t state[3]; /**< The state array of length 3. */ + q31_t Kp; /**< The proportional gain. */ + q31_t Ki; /**< The integral gain. */ + q31_t Kd; /**< The derivative gain. */ + } arm_pid_instance_q31; + + /** + * @brief Instance structure for the floating-point PID Control. + */ + typedef struct + { + float32_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ + float32_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */ + float32_t A2; /**< The derived gain, A2 = Kd . */ + float32_t state[3]; /**< The state array of length 3. */ + float32_t Kp; /**< The proportional gain. */ + float32_t Ki; /**< The integral gain. */ + float32_t Kd; /**< The derivative gain. */ + } arm_pid_instance_f32; + + + + /** + * @brief Initialization function for the floating-point PID Control. + * @param[in,out] S points to an instance of the PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_f32( + arm_pid_instance_f32 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the floating-point PID Control. + * @param[in,out] S is an instance of the floating-point PID Control structure + */ + void arm_pid_reset_f32( + arm_pid_instance_f32 * S); + + + /** + * @brief Initialization function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q15 PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_q31( + arm_pid_instance_q31 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q31 PID Control structure + */ + + void arm_pid_reset_q31( + arm_pid_instance_q31 * S); + + + /** + * @brief Initialization function for the Q15 PID Control. + * @param[in,out] S points to an instance of the Q15 PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_q15( + arm_pid_instance_q15 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the Q15 PID Control. + * @param[in,out] S points to an instance of the q15 PID Control structure + */ + void arm_pid_reset_q15( + arm_pid_instance_q15 * S); + + + /** + * @brief Instance structure for the floating-point Linear Interpolate function. + */ + typedef struct + { + uint32_t nValues; /**< nValues */ + float32_t x1; /**< x1 */ + float32_t xSpacing; /**< xSpacing */ + float32_t *pYData; /**< pointer to the table of Y values */ + } arm_linear_interp_instance_f32; + + /** + * @brief Instance structure for the floating-point bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + float32_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_f32; + + /** + * @brief Instance structure for the Q31 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q31_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q31; + + /** + * @brief Instance structure for the Q15 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q15_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q15; + + /** + * @brief Instance structure for the Q15 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q7_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q7; + + + /** + * @brief Q7 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q15_t *pTwiddle; /**< points to the Sin twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix2_instance_q15; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_q15( + arm_cfft_radix2_instance_q15 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_q15( + const arm_cfft_radix2_instance_q15 * S, + q15_t * pSrc); + + + /** + * @brief Instance structure for the Q15 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q15_t *pTwiddle; /**< points to the twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix4_instance_q15; + +/* Deprecated */ + arm_status arm_cfft_radix4_init_q15( + arm_cfft_radix4_instance_q15 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix4_q15( + const arm_cfft_radix4_instance_q15 * S, + q15_t * pSrc); + + /** + * @brief Instance structure for the Radix-2 Q31 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q31_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix2_instance_q31; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_q31( + arm_cfft_radix2_instance_q31 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_q31( + const arm_cfft_radix2_instance_q31 * S, + q31_t * pSrc); + + /** + * @brief Instance structure for the Q31 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q31_t *pTwiddle; /**< points to the twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix4_instance_q31; + +/* Deprecated */ + void arm_cfft_radix4_q31( + const arm_cfft_radix4_instance_q31 * S, + q31_t * pSrc); + +/* Deprecated */ + arm_status arm_cfft_radix4_init_q31( + arm_cfft_radix4_instance_q31 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + float32_t onebyfftLen; /**< value of 1/fftLen. */ + } arm_cfft_radix2_instance_f32; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_f32( + arm_cfft_radix2_instance_f32 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_f32( + const arm_cfft_radix2_instance_f32 * S, + float32_t * pSrc); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + float32_t onebyfftLen; /**< value of 1/fftLen. */ + } arm_cfft_radix4_instance_f32; + +/* Deprecated */ + arm_status arm_cfft_radix4_init_f32( + arm_cfft_radix4_instance_f32 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix4_f32( + const arm_cfft_radix4_instance_f32 * S, + float32_t * pSrc); + + /** + * @brief Instance structure for the fixed-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const q15_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_q15; + +void arm_cfft_q15( + const arm_cfft_instance_q15 * S, + q15_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the fixed-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const q31_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_q31; + +void arm_cfft_q31( + const arm_cfft_instance_q31 * S, + q31_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_f32; + + void arm_cfft_f32( + const arm_cfft_instance_f32 * S, + float32_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the Q15 RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + q15_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + q15_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + const arm_cfft_instance_q15 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_q15; + + arm_status arm_rfft_init_q15( + arm_rfft_instance_q15 * S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_q15( + const arm_rfft_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst); + + /** + * @brief Instance structure for the Q31 RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + q31_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + q31_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + const arm_cfft_instance_q31 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_q31; + + arm_status arm_rfft_init_q31( + arm_rfft_instance_q31 * S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_q31( + const arm_rfft_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst); + + /** + * @brief Instance structure for the floating-point RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint16_t fftLenBy2; /**< length of the complex FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + float32_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + float32_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_f32; + + arm_status arm_rfft_init_f32( + arm_rfft_instance_f32 * S, + arm_cfft_radix4_instance_f32 * S_CFFT, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_f32( + const arm_rfft_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst); + + /** + * @brief Instance structure for the floating-point RFFT/RIFFT function. + */ +typedef struct + { + arm_cfft_instance_f32 Sint; /**< Internal CFFT structure. */ + uint16_t fftLenRFFT; /**< length of the real sequence */ + float32_t * pTwiddleRFFT; /**< Twiddle factors real stage */ + } arm_rfft_fast_instance_f32 ; + +arm_status arm_rfft_fast_init_f32 ( + arm_rfft_fast_instance_f32 * S, + uint16_t fftLen); + +void arm_rfft_fast_f32( + arm_rfft_fast_instance_f32 * S, + float32_t * p, float32_t * pOut, + uint8_t ifftFlag); + + /** + * @brief Instance structure for the floating-point DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + float32_t normalize; /**< normalizing factor. */ + float32_t *pTwiddle; /**< points to the twiddle factor table. */ + float32_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_f32 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_f32; + + + /** + * @brief Initialization function for the floating-point DCT4/IDCT4. + * @param[in,out] S points to an instance of floating-point DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of floating-point RFFT/RIFFT structure. + * @param[in] S_CFFT points to an instance of floating-point CFFT/CIFFT structure. + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if fftLenReal is not a supported transform length. + */ + arm_status arm_dct4_init_f32( + arm_dct4_instance_f32 * S, + arm_rfft_instance_f32 * S_RFFT, + arm_cfft_radix4_instance_f32 * S_CFFT, + uint16_t N, + uint16_t Nby2, + float32_t normalize); + + + /** + * @brief Processing function for the floating-point DCT4/IDCT4. + * @param[in] S points to an instance of the floating-point DCT4/IDCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_f32( + const arm_dct4_instance_f32 * S, + float32_t * pState, + float32_t * pInlineBuffer); + + + /** + * @brief Instance structure for the Q31 DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + q31_t normalize; /**< normalizing factor. */ + q31_t *pTwiddle; /**< points to the twiddle factor table. */ + q31_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_q31 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_q31 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_q31; + + + /** + * @brief Initialization function for the Q31 DCT4/IDCT4. + * @param[in,out] S points to an instance of Q31 DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of Q31 RFFT/RIFFT structure + * @param[in] S_CFFT points to an instance of Q31 CFFT/CIFFT structure + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. + */ + arm_status arm_dct4_init_q31( + arm_dct4_instance_q31 * S, + arm_rfft_instance_q31 * S_RFFT, + arm_cfft_radix4_instance_q31 * S_CFFT, + uint16_t N, + uint16_t Nby2, + q31_t normalize); + + + /** + * @brief Processing function for the Q31 DCT4/IDCT4. + * @param[in] S points to an instance of the Q31 DCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_q31( + const arm_dct4_instance_q31 * S, + q31_t * pState, + q31_t * pInlineBuffer); + + + /** + * @brief Instance structure for the Q15 DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + q15_t normalize; /**< normalizing factor. */ + q15_t *pTwiddle; /**< points to the twiddle factor table. */ + q15_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_q15 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_q15 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_q15; + + + /** + * @brief Initialization function for the Q15 DCT4/IDCT4. + * @param[in,out] S points to an instance of Q15 DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of Q15 RFFT/RIFFT structure. + * @param[in] S_CFFT points to an instance of Q15 CFFT/CIFFT structure. + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. + */ + arm_status arm_dct4_init_q15( + arm_dct4_instance_q15 * S, + arm_rfft_instance_q15 * S_RFFT, + arm_cfft_radix4_instance_q15 * S_CFFT, + uint16_t N, + uint16_t Nby2, + q15_t normalize); + + + /** + * @brief Processing function for the Q15 DCT4/IDCT4. + * @param[in] S points to an instance of the Q15 DCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_q15( + const arm_dct4_instance_q15 * S, + q15_t * pState, + q15_t * pInlineBuffer); + + + /** + * @brief Floating-point vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a floating-point vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scale scale factor to be applied + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_f32( + float32_t * pSrc, + float32_t scale, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q7 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q7( + q7_t * pSrc, + q7_t scaleFract, + int8_t shift, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q15 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q15( + q15_t * pSrc, + q15_t scaleFract, + int8_t shift, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q31 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q31( + q31_t * pSrc, + q31_t scaleFract, + int8_t shift, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Dot product of floating-point vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_f32( + float32_t * pSrcA, + float32_t * pSrcB, + uint32_t blockSize, + float32_t * result); + + + /** + * @brief Dot product of Q7 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q7( + q7_t * pSrcA, + q7_t * pSrcB, + uint32_t blockSize, + q31_t * result); + + + /** + * @brief Dot product of Q15 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q15( + q15_t * pSrcA, + q15_t * pSrcB, + uint32_t blockSize, + q63_t * result); + + + /** + * @brief Dot product of Q31 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q31( + q31_t * pSrcA, + q31_t * pSrcB, + uint32_t blockSize, + q63_t * result); + + + /** + * @brief Shifts the elements of a Q7 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q7( + q7_t * pSrc, + int8_t shiftBits, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Shifts the elements of a Q15 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q15( + q15_t * pSrc, + int8_t shiftBits, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Shifts the elements of a Q31 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q31( + q31_t * pSrc, + int8_t shiftBits, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a floating-point vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_f32( + float32_t * pSrc, + float32_t offset, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q7 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q7( + q7_t * pSrc, + q7_t offset, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q15 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q15( + q15_t * pSrc, + q15_t offset, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q31 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q31( + q31_t * pSrc, + q31_t offset, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a floating-point vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q7 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q15 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q31 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a floating-point vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q7 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q15 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q31 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a floating-point vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_f32( + float32_t value, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q7 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q7( + q7_t value, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q15 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q15( + q15_t value, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q31 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q31( + q31_t value, + q31_t * pDst, + uint32_t blockSize); + + +/** + * @brief Convolution of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + */ + void arm_conv_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst); + + + /** + * @brief Convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + */ + void arm_conv_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + +/** + * @brief Convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + */ + void arm_conv_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + */ + void arm_conv_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Convolution of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + */ + void arm_conv_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst); + + + /** + * @brief Partial convolution of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Partial convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Partial convolution of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q7 sequences + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + +/** + * @brief Partial convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Instance structure for the Q15 FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_f32; + + + /** + * @brief Processing function for the floating-point FIR decimator. + * @param[in] S points to an instance of the floating-point FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_f32( + const arm_fir_decimate_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR decimator. + * @param[in,out] S points to an instance of the floating-point FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_f32( + arm_fir_decimate_instance_f32 * S, + uint16_t numTaps, + uint8_t M, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR decimator. + * @param[in] S points to an instance of the Q15 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_q15( + const arm_fir_decimate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_fast_q15( + const arm_fir_decimate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR decimator. + * @param[in,out] S points to an instance of the Q15 FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_q15( + arm_fir_decimate_instance_q15 * S, + uint16_t numTaps, + uint8_t M, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR decimator. + * @param[in] S points to an instance of the Q31 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_q31( + const arm_fir_decimate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + /** + * @brief Processing function for the Q31 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_fast_q31( + arm_fir_decimate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR decimator. + * @param[in,out] S points to an instance of the Q31 FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_q31( + arm_fir_decimate_instance_q31 * S, + uint16_t numTaps, + uint8_t M, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + q15_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */ + } arm_fir_interpolate_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + q31_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */ + } arm_fir_interpolate_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + float32_t *pState; /**< points to the state variable array. The array is of length phaseLength+numTaps-1. */ + } arm_fir_interpolate_instance_f32; + + + /** + * @brief Processing function for the Q15 FIR interpolator. + * @param[in] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_q15( + const arm_fir_interpolate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR interpolator. + * @param[in,out] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_q15( + arm_fir_interpolate_instance_q15 * S, + uint8_t L, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR interpolator. + * @param[in] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_q31( + const arm_fir_interpolate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR interpolator. + * @param[in,out] S points to an instance of the Q31 FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_q31( + arm_fir_interpolate_instance_q31 * S, + uint8_t L, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point FIR interpolator. + * @param[in] S points to an instance of the floating-point FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_f32( + const arm_fir_interpolate_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR interpolator. + * @param[in,out] S points to an instance of the floating-point FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_f32( + arm_fir_interpolate_instance_f32 * S, + uint8_t L, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the high precision Q31 Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q63_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */ + q31_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + uint8_t postShift; /**< additional shift, in bits, applied to each output sample. */ + } arm_biquad_cas_df1_32x64_ins_q31; + + + /** + * @param[in] S points to an instance of the high precision Q31 Biquad cascade filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cas_df1_32x64_q31( + const arm_biquad_cas_df1_32x64_ins_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @param[in,out] S points to an instance of the high precision Q31 Biquad cascade filter structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cas_df1_32x64_init_q31( + arm_biquad_cas_df1_32x64_ins_q31 * S, + uint8_t numStages, + q31_t * pCoeffs, + q63_t * pState, + uint8_t postShift); + + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */ + float32_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_df2T_instance_f32; + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */ + float32_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_stereo_df2T_instance_f32; + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float64_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */ + float64_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_df2T_instance_f64; + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df2T_f32( + const arm_biquad_cascade_df2T_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. 2 channels + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_stereo_df2T_f32( + const arm_biquad_cascade_stereo_df2T_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df2T_f64( + const arm_biquad_cascade_df2T_instance_f64 * S, + float64_t * pSrc, + float64_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df2T_init_f32( + arm_biquad_cascade_df2T_instance_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_stereo_df2T_init_f32( + arm_biquad_cascade_stereo_df2T_instance_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df2T_init_f64( + arm_biquad_cascade_df2T_instance_f64 * S, + uint8_t numStages, + float64_t * pCoeffs, + float64_t * pState); + + + /** + * @brief Instance structure for the Q15 FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + q15_t *pState; /**< points to the state variable array. The array is of length numStages. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + q31_t *pState; /**< points to the state variable array. The array is of length numStages. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + float32_t *pState; /**< points to the state variable array. The array is of length numStages. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_f32; + + + /** + * @brief Initialization function for the Q15 FIR lattice filter. + * @param[in] S points to an instance of the Q15 FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_q15( + arm_fir_lattice_instance_q15 * S, + uint16_t numStages, + q15_t * pCoeffs, + q15_t * pState); + + + /** + * @brief Processing function for the Q15 FIR lattice filter. + * @param[in] S points to an instance of the Q15 FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_q15( + const arm_fir_lattice_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR lattice filter. + * @param[in] S points to an instance of the Q31 FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_q31( + arm_fir_lattice_instance_q31 * S, + uint16_t numStages, + q31_t * pCoeffs, + q31_t * pState); + + + /** + * @brief Processing function for the Q31 FIR lattice filter. + * @param[in] S points to an instance of the Q31 FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_q31( + const arm_fir_lattice_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + +/** + * @brief Initialization function for the floating-point FIR lattice filter. + * @param[in] S points to an instance of the floating-point FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_f32( + arm_fir_lattice_instance_f32 * S, + uint16_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Processing function for the floating-point FIR lattice filter. + * @param[in] S points to an instance of the floating-point FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_f32( + const arm_fir_lattice_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + q15_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + q15_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_q15; + + /** + * @brief Instance structure for the Q31 IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + q31_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + q31_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_q31; + + /** + * @brief Instance structure for the floating-point IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + float32_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + float32_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_f32; + + + /** + * @brief Processing function for the floating-point IIR lattice filter. + * @param[in] S points to an instance of the floating-point IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_f32( + const arm_iir_lattice_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point IIR lattice filter. + * @param[in] S points to an instance of the floating-point IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to the state buffer. The array is of length numStages+blockSize-1. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_init_f32( + arm_iir_lattice_instance_f32 * S, + uint16_t numStages, + float32_t * pkCoeffs, + float32_t * pvCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 IIR lattice filter. + * @param[in] S points to an instance of the Q31 IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_q31( + const arm_iir_lattice_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 IIR lattice filter. + * @param[in] S points to an instance of the Q31 IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to the state buffer. The array is of length numStages+blockSize. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_init_q31( + arm_iir_lattice_instance_q31 * S, + uint16_t numStages, + q31_t * pkCoeffs, + q31_t * pvCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 IIR lattice filter. + * @param[in] S points to an instance of the Q15 IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_q15( + const arm_iir_lattice_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + +/** + * @brief Initialization function for the Q15 IIR lattice filter. + * @param[in] S points to an instance of the fixed-point Q15 IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to state buffer. The array is of length numStages+blockSize. + * @param[in] blockSize number of samples to process per call. + */ + void arm_iir_lattice_init_q15( + arm_iir_lattice_instance_q15 * S, + uint16_t numStages, + q15_t * pkCoeffs, + q15_t * pvCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the floating-point LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + float32_t mu; /**< step size that controls filter coefficient updates. */ + } arm_lms_instance_f32; + + + /** + * @brief Processing function for floating-point LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_f32( + const arm_lms_instance_f32 * S, + float32_t * pSrc, + float32_t * pRef, + float32_t * pOut, + float32_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for floating-point LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to the coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_init_f32( + arm_lms_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + float32_t mu, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q15_t mu; /**< step size that controls filter coefficient updates. */ + uint32_t postShift; /**< bit shift applied to coefficients. */ + } arm_lms_instance_q15; + + + /** + * @brief Initialization function for the Q15 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to the coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_init_q15( + arm_lms_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + q15_t mu, + uint32_t blockSize, + uint32_t postShift); + + + /** + * @brief Processing function for Q15 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_q15( + const arm_lms_instance_q15 * S, + q15_t * pSrc, + q15_t * pRef, + q15_t * pOut, + q15_t * pErr, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q31 LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q31_t mu; /**< step size that controls filter coefficient updates. */ + uint32_t postShift; /**< bit shift applied to coefficients. */ + } arm_lms_instance_q31; + + + /** + * @brief Processing function for Q31 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_q31( + const arm_lms_instance_q31 * S, + q31_t * pSrc, + q31_t * pRef, + q31_t * pOut, + q31_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q31 LMS filter. + * @param[in] S points to an instance of the Q31 LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_init_q31( + arm_lms_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + q31_t mu, + uint32_t blockSize, + uint32_t postShift); + + + /** + * @brief Instance structure for the floating-point normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + float32_t mu; /**< step size that control filter coefficient updates. */ + float32_t energy; /**< saves previous frame energy. */ + float32_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_f32; + + + /** + * @brief Processing function for floating-point normalized LMS filter. + * @param[in] S points to an instance of the floating-point normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_f32( + arm_lms_norm_instance_f32 * S, + float32_t * pSrc, + float32_t * pRef, + float32_t * pOut, + float32_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for floating-point normalized LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_init_f32( + arm_lms_norm_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + float32_t mu, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q31 normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q31_t mu; /**< step size that controls filter coefficient updates. */ + uint8_t postShift; /**< bit shift applied to coefficients. */ + q31_t *recipTable; /**< points to the reciprocal initial value table. */ + q31_t energy; /**< saves previous frame energy. */ + q31_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_q31; + + + /** + * @brief Processing function for Q31 normalized LMS filter. + * @param[in] S points to an instance of the Q31 normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_q31( + arm_lms_norm_instance_q31 * S, + q31_t * pSrc, + q31_t * pRef, + q31_t * pOut, + q31_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q31 normalized LMS filter. + * @param[in] S points to an instance of the Q31 normalized LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_norm_init_q31( + arm_lms_norm_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + q31_t mu, + uint32_t blockSize, + uint8_t postShift); + + + /** + * @brief Instance structure for the Q15 normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< Number of coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q15_t mu; /**< step size that controls filter coefficient updates. */ + uint8_t postShift; /**< bit shift applied to coefficients. */ + q15_t *recipTable; /**< Points to the reciprocal initial value table. */ + q15_t energy; /**< saves previous frame energy. */ + q15_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_q15; + + + /** + * @brief Processing function for Q15 normalized LMS filter. + * @param[in] S points to an instance of the Q15 normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_q15( + arm_lms_norm_instance_q15 * S, + q15_t * pSrc, + q15_t * pRef, + q15_t * pOut, + q15_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q15 normalized LMS filter. + * @param[in] S points to an instance of the Q15 normalized LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_norm_init_q15( + arm_lms_norm_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + q15_t mu, + uint32_t blockSize, + uint8_t postShift); + + + /** + * @brief Correlation of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst); + + + /** + * @brief Correlation of Q15 sequences + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + */ + void arm_correlate_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch); + + + /** + * @brief Correlation of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + + void arm_correlate_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + + void arm_correlate_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + */ + void arm_correlate_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch); + + + /** + * @brief Correlation of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Correlation of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Correlation of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + */ + void arm_correlate_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Correlation of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst); + + + /** + * @brief Instance structure for the floating-point sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + float32_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_f32; + + /** + * @brief Instance structure for the Q31 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q31_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q31; + + /** + * @brief Instance structure for the Q15 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q15_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q15; + + /** + * @brief Instance structure for the Q7 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q7_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q7; + + + /** + * @brief Processing function for the floating-point sparse FIR filter. + * @param[in] S points to an instance of the floating-point sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_f32( + arm_fir_sparse_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + float32_t * pScratchIn, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point sparse FIR filter. + * @param[in,out] S points to an instance of the floating-point sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_f32( + arm_fir_sparse_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 sparse FIR filter. + * @param[in] S points to an instance of the Q31 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q31( + arm_fir_sparse_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + q31_t * pScratchIn, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 sparse FIR filter. + * @param[in,out] S points to an instance of the Q31 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q31( + arm_fir_sparse_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 sparse FIR filter. + * @param[in] S points to an instance of the Q15 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] pScratchOut points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q15( + arm_fir_sparse_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + q15_t * pScratchIn, + q31_t * pScratchOut, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 sparse FIR filter. + * @param[in,out] S points to an instance of the Q15 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q15( + arm_fir_sparse_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q7 sparse FIR filter. + * @param[in] S points to an instance of the Q7 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] pScratchOut points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q7( + arm_fir_sparse_instance_q7 * S, + q7_t * pSrc, + q7_t * pDst, + q7_t * pScratchIn, + q31_t * pScratchOut, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q7 sparse FIR filter. + * @param[in,out] S points to an instance of the Q7 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q7( + arm_fir_sparse_instance_q7 * S, + uint16_t numTaps, + q7_t * pCoeffs, + q7_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Floating-point sin_cos function. + * @param[in] theta input value in degrees + * @param[out] pSinVal points to the processed sine output. + * @param[out] pCosVal points to the processed cos output. + */ + void arm_sin_cos_f32( + float32_t theta, + float32_t * pSinVal, + float32_t * pCosVal); + + + /** + * @brief Q31 sin_cos function. + * @param[in] theta scaled input value in degrees + * @param[out] pSinVal points to the processed sine output. + * @param[out] pCosVal points to the processed cosine output. + */ + void arm_sin_cos_q31( + q31_t theta, + q31_t * pSinVal, + q31_t * pCosVal); + + + /** + * @brief Floating-point complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + /** + * @brief Q31 complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @ingroup groupController + */ + + /** + * @defgroup PID PID Motor Control + * + * A Proportional Integral Derivative (PID) controller is a generic feedback control + * loop mechanism widely used in industrial control systems. + * A PID controller is the most commonly used type of feedback controller. + * + * This set of functions implements (PID) controllers + * for Q15, Q31, and floating-point data types. The functions operate on a single sample + * of data and each call to the function returns a single processed value. + * S points to an instance of the PID control data structure. in + * is the input sample value. The functions return the output value. + * + * \par Algorithm: + *
+   *    y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2]
+   *    A0 = Kp + Ki + Kd
+   *    A1 = (-Kp ) - (2 * Kd )
+   *    A2 = Kd  
+ * + * \par + * where \c Kp is proportional constant, \c Ki is Integral constant and \c Kd is Derivative constant + * + * \par + * \image html PID.gif "Proportional Integral Derivative Controller" + * + * \par + * The PID controller calculates an "error" value as the difference between + * the measured output and the reference input. + * The controller attempts to minimize the error by adjusting the process control inputs. + * The proportional value determines the reaction to the current error, + * the integral value determines the reaction based on the sum of recent errors, + * and the derivative value determines the reaction based on the rate at which the error has been changing. + * + * \par Instance Structure + * The Gains A0, A1, A2 and state variables for a PID controller are stored together in an instance data structure. + * A separate instance structure must be defined for each PID Controller. + * There are separate instance structure declarations for each of the 3 supported data types. + * + * \par Reset Functions + * There is also an associated reset function for each data type which clears the state array. + * + * \par Initialization Functions + * There is also an associated initialization function for each data type. + * The initialization function performs the following operations: + * - Initializes the Gains A0, A1, A2 from Kp,Ki, Kd gains. + * - Zeros out the values in the state buffer. + * + * \par + * Instance structure cannot be placed into a const data section and it is recommended to use the initialization function. + * + * \par Fixed-Point Behavior + * Care must be taken when using the fixed-point versions of the PID Controller functions. + * In particular, the overflow and saturation behavior of the accumulator used in each function must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup PID + * @{ + */ + + /** + * @brief Process function for the floating-point PID Control. + * @param[in,out] S is an instance of the floating-point PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + */ + static __INLINE float32_t arm_pid_f32( + arm_pid_instance_f32 * S, + float32_t in) + { + float32_t out; + + /* y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2] */ + out = (S->A0 * in) + + (S->A1 * S->state[0]) + (S->A2 * S->state[1]) + (S->state[2]); + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + + } + + /** + * @brief Process function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q31 PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 64-bit accumulator. + * The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit. + * Thus, if the accumulator result overflows it wraps around rather than clip. + * In order to avoid overflows completely the input signal must be scaled down by 2 bits as there are four additions. + * After all multiply-accumulates are performed, the 2.62 accumulator is truncated to 1.32 format and then saturated to 1.31 format. + */ + static __INLINE q31_t arm_pid_q31( + arm_pid_instance_q31 * S, + q31_t in) + { + q63_t acc; + q31_t out; + + /* acc = A0 * x[n] */ + acc = (q63_t) S->A0 * in; + + /* acc += A1 * x[n-1] */ + acc += (q63_t) S->A1 * S->state[0]; + + /* acc += A2 * x[n-2] */ + acc += (q63_t) S->A2 * S->state[1]; + + /* convert output to 1.31 format to add y[n-1] */ + out = (q31_t) (acc >> 31u); + + /* out += y[n-1] */ + out += S->state[2]; + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + } + + + /** + * @brief Process function for the Q15 PID Control. + * @param[in,out] S points to an instance of the Q15 PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using a 64-bit internal accumulator. + * Both Gains and state variables are represented in 1.15 format and multiplications yield a 2.30 result. + * The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format. + * There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved. + * After all additions have been performed, the accumulator is truncated to 34.15 format by discarding low 15 bits. + * Lastly, the accumulator is saturated to yield a result in 1.15 format. + */ + static __INLINE q15_t arm_pid_q15( + arm_pid_instance_q15 * S, + q15_t in) + { + q63_t acc; + q15_t out; + +#ifndef ARM_MATH_CM0_FAMILY + __SIMD32_TYPE *vstate; + + /* Implementation of PID controller */ + + /* acc = A0 * x[n] */ + acc = (q31_t) __SMUAD((uint32_t)S->A0, (uint32_t)in); + + /* acc += A1 * x[n-1] + A2 * x[n-2] */ + vstate = __SIMD32_CONST(S->state); + acc = (q63_t)__SMLALD((uint32_t)S->A1, (uint32_t)*vstate, (uint64_t)acc); +#else + /* acc = A0 * x[n] */ + acc = ((q31_t) S->A0) * in; + + /* acc += A1 * x[n-1] + A2 * x[n-2] */ + acc += (q31_t) S->A1 * S->state[0]; + acc += (q31_t) S->A2 * S->state[1]; +#endif + + /* acc += y[n-1] */ + acc += (q31_t) S->state[2] << 15; + + /* saturate the output */ + out = (q15_t) (__SSAT((acc >> 15), 16)); + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + } + + /** + * @} end of PID group + */ + + + /** + * @brief Floating-point matrix inverse. + * @param[in] src points to the instance of the input floating-point matrix structure. + * @param[out] dst points to the instance of the output floating-point matrix structure. + * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. + * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. + */ + arm_status arm_mat_inverse_f32( + const arm_matrix_instance_f32 * src, + arm_matrix_instance_f32 * dst); + + + /** + * @brief Floating-point matrix inverse. + * @param[in] src points to the instance of the input floating-point matrix structure. + * @param[out] dst points to the instance of the output floating-point matrix structure. + * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. + * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. + */ + arm_status arm_mat_inverse_f64( + const arm_matrix_instance_f64 * src, + arm_matrix_instance_f64 * dst); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup clarke Vector Clarke Transform + * Forward Clarke transform converts the instantaneous stator phases into a two-coordinate time invariant vector. + * Generally the Clarke transform uses three-phase currents Ia, Ib and Ic to calculate currents + * in the two-phase orthogonal stator axis Ialpha and Ibeta. + * When Ialpha is superposed with Ia as shown in the figure below + * \image html clarke.gif Stator current space vector and its components in (a,b). + * and Ia + Ib + Ic = 0, in this condition Ialpha and Ibeta + * can be calculated using only Ia and Ib. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html clarkeFormula.gif + * where Ia and Ib are the instantaneous stator phases and + * pIalpha and pIbeta are the two coordinates of time invariant vector. + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Clarke transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup clarke + * @{ + */ + + /** + * + * @brief Floating-point Clarke transform + * @param[in] Ia input three-phase coordinate a + * @param[in] Ib input three-phase coordinate b + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + */ + static __INLINE void arm_clarke_f32( + float32_t Ia, + float32_t Ib, + float32_t * pIalpha, + float32_t * pIbeta) + { + /* Calculate pIalpha using the equation, pIalpha = Ia */ + *pIalpha = Ia; + + /* Calculate pIbeta using the equation, pIbeta = (1/sqrt(3)) * Ia + (2/sqrt(3)) * Ib */ + *pIbeta = ((float32_t) 0.57735026919 * Ia + (float32_t) 1.15470053838 * Ib); + } + + + /** + * @brief Clarke transform for Q31 version + * @param[in] Ia input three-phase coordinate a + * @param[in] Ib input three-phase coordinate b + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition, hence there is no risk of overflow. + */ + static __INLINE void arm_clarke_q31( + q31_t Ia, + q31_t Ib, + q31_t * pIalpha, + q31_t * pIbeta) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + + /* Calculating pIalpha from Ia by equation pIalpha = Ia */ + *pIalpha = Ia; + + /* Intermediate product is calculated by (1/(sqrt(3)) * Ia) */ + product1 = (q31_t) (((q63_t) Ia * 0x24F34E8B) >> 30); + + /* Intermediate product is calculated by (2/sqrt(3) * Ib) */ + product2 = (q31_t) (((q63_t) Ib * 0x49E69D16) >> 30); + + /* pIbeta is calculated by adding the intermediate products */ + *pIbeta = __QADD(product1, product2); + } + + /** + * @} end of clarke group + */ + + /** + * @brief Converts the elements of the Q7 vector to Q31 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_q7_to_q31( + q7_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup inv_clarke Vector Inverse Clarke Transform + * Inverse Clarke transform converts the two-coordinate time invariant vector into instantaneous stator phases. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html clarkeInvFormula.gif + * where pIa and pIb are the instantaneous stator phases and + * Ialpha and Ibeta are the two coordinates of time invariant vector. + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Clarke transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup inv_clarke + * @{ + */ + + /** + * @brief Floating-point Inverse Clarke transform + * @param[in] Ialpha input two-phase orthogonal vector axis alpha + * @param[in] Ibeta input two-phase orthogonal vector axis beta + * @param[out] pIa points to output three-phase coordinate a + * @param[out] pIb points to output three-phase coordinate b + */ + static __INLINE void arm_inv_clarke_f32( + float32_t Ialpha, + float32_t Ibeta, + float32_t * pIa, + float32_t * pIb) + { + /* Calculating pIa from Ialpha by equation pIa = Ialpha */ + *pIa = Ialpha; + + /* Calculating pIb from Ialpha and Ibeta by equation pIb = -(1/2) * Ialpha + (sqrt(3)/2) * Ibeta */ + *pIb = -0.5f * Ialpha + 0.8660254039f * Ibeta; + } + + + /** + * @brief Inverse Clarke transform for Q31 version + * @param[in] Ialpha input two-phase orthogonal vector axis alpha + * @param[in] Ibeta input two-phase orthogonal vector axis beta + * @param[out] pIa points to output three-phase coordinate a + * @param[out] pIb points to output three-phase coordinate b + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the subtraction, hence there is no risk of overflow. + */ + static __INLINE void arm_inv_clarke_q31( + q31_t Ialpha, + q31_t Ibeta, + q31_t * pIa, + q31_t * pIb) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + + /* Calculating pIa from Ialpha by equation pIa = Ialpha */ + *pIa = Ialpha; + + /* Intermediate product is calculated by (1/(2*sqrt(3)) * Ia) */ + product1 = (q31_t) (((q63_t) (Ialpha) * (0x40000000)) >> 31); + + /* Intermediate product is calculated by (1/sqrt(3) * pIb) */ + product2 = (q31_t) (((q63_t) (Ibeta) * (0x6ED9EBA1)) >> 31); + + /* pIb is calculated by subtracting the products */ + *pIb = __QSUB(product2, product1); + } + + /** + * @} end of inv_clarke group + */ + + /** + * @brief Converts the elements of the Q7 vector to Q15 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_q7_to_q15( + q7_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup park Vector Park Transform + * + * Forward Park transform converts the input two-coordinate vector to flux and torque components. + * The Park transform can be used to realize the transformation of the Ialpha and the Ibeta currents + * from the stationary to the moving reference frame and control the spatial relationship between + * the stator vector current and rotor flux vector. + * If we consider the d axis aligned with the rotor flux, the diagram below shows the + * current vector and the relationship from the two reference frames: + * \image html park.gif "Stator current space vector and its component in (a,b) and in the d,q rotating reference frame" + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html parkFormula.gif + * where Ialpha and Ibeta are the stator vector components, + * pId and pIq are rotor vector components and cosVal and sinVal are the + * cosine and sine values of theta (rotor flux position). + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Park transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup park + * @{ + */ + + /** + * @brief Floating-point Park transform + * @param[in] Ialpha input two-phase vector coordinate alpha + * @param[in] Ibeta input two-phase vector coordinate beta + * @param[out] pId points to output rotor reference frame d + * @param[out] pIq points to output rotor reference frame q + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * The function implements the forward Park transform. + * + */ + static __INLINE void arm_park_f32( + float32_t Ialpha, + float32_t Ibeta, + float32_t * pId, + float32_t * pIq, + float32_t sinVal, + float32_t cosVal) + { + /* Calculate pId using the equation, pId = Ialpha * cosVal + Ibeta * sinVal */ + *pId = Ialpha * cosVal + Ibeta * sinVal; + + /* Calculate pIq using the equation, pIq = - Ialpha * sinVal + Ibeta * cosVal */ + *pIq = -Ialpha * sinVal + Ibeta * cosVal; + } + + + /** + * @brief Park transform for Q31 version + * @param[in] Ialpha input two-phase vector coordinate alpha + * @param[in] Ibeta input two-phase vector coordinate beta + * @param[out] pId points to output rotor reference frame d + * @param[out] pIq points to output rotor reference frame q + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition and subtraction, hence there is no risk of overflow. + */ + static __INLINE void arm_park_q31( + q31_t Ialpha, + q31_t Ibeta, + q31_t * pId, + q31_t * pIq, + q31_t sinVal, + q31_t cosVal) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + q31_t product3, product4; /* Temporary variables used to store intermediate results */ + + /* Intermediate product is calculated by (Ialpha * cosVal) */ + product1 = (q31_t) (((q63_t) (Ialpha) * (cosVal)) >> 31); + + /* Intermediate product is calculated by (Ibeta * sinVal) */ + product2 = (q31_t) (((q63_t) (Ibeta) * (sinVal)) >> 31); + + + /* Intermediate product is calculated by (Ialpha * sinVal) */ + product3 = (q31_t) (((q63_t) (Ialpha) * (sinVal)) >> 31); + + /* Intermediate product is calculated by (Ibeta * cosVal) */ + product4 = (q31_t) (((q63_t) (Ibeta) * (cosVal)) >> 31); + + /* Calculate pId by adding the two intermediate products 1 and 2 */ + *pId = __QADD(product1, product2); + + /* Calculate pIq by subtracting the two intermediate products 3 from 4 */ + *pIq = __QSUB(product4, product3); + } + + /** + * @} end of park group + */ + + /** + * @brief Converts the elements of the Q7 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q7_to_float( + q7_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @ingroup groupController + */ + + /** + * @defgroup inv_park Vector Inverse Park transform + * Inverse Park transform converts the input flux and torque components to two-coordinate vector. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html parkInvFormula.gif + * where pIalpha and pIbeta are the stator vector components, + * Id and Iq are rotor vector components and cosVal and sinVal are the + * cosine and sine values of theta (rotor flux position). + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Park transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup inv_park + * @{ + */ + + /** + * @brief Floating-point Inverse Park transform + * @param[in] Id input coordinate of rotor reference frame d + * @param[in] Iq input coordinate of rotor reference frame q + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + */ + static __INLINE void arm_inv_park_f32( + float32_t Id, + float32_t Iq, + float32_t * pIalpha, + float32_t * pIbeta, + float32_t sinVal, + float32_t cosVal) + { + /* Calculate pIalpha using the equation, pIalpha = Id * cosVal - Iq * sinVal */ + *pIalpha = Id * cosVal - Iq * sinVal; + + /* Calculate pIbeta using the equation, pIbeta = Id * sinVal + Iq * cosVal */ + *pIbeta = Id * sinVal + Iq * cosVal; + } + + + /** + * @brief Inverse Park transform for Q31 version + * @param[in] Id input coordinate of rotor reference frame d + * @param[in] Iq input coordinate of rotor reference frame q + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition, hence there is no risk of overflow. + */ + static __INLINE void arm_inv_park_q31( + q31_t Id, + q31_t Iq, + q31_t * pIalpha, + q31_t * pIbeta, + q31_t sinVal, + q31_t cosVal) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + q31_t product3, product4; /* Temporary variables used to store intermediate results */ + + /* Intermediate product is calculated by (Id * cosVal) */ + product1 = (q31_t) (((q63_t) (Id) * (cosVal)) >> 31); + + /* Intermediate product is calculated by (Iq * sinVal) */ + product2 = (q31_t) (((q63_t) (Iq) * (sinVal)) >> 31); + + + /* Intermediate product is calculated by (Id * sinVal) */ + product3 = (q31_t) (((q63_t) (Id) * (sinVal)) >> 31); + + /* Intermediate product is calculated by (Iq * cosVal) */ + product4 = (q31_t) (((q63_t) (Iq) * (cosVal)) >> 31); + + /* Calculate pIalpha by using the two intermediate products 1 and 2 */ + *pIalpha = __QSUB(product1, product2); + + /* Calculate pIbeta by using the two intermediate products 3 and 4 */ + *pIbeta = __QADD(product4, product3); + } + + /** + * @} end of Inverse park group + */ + + + /** + * @brief Converts the elements of the Q31 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_float( + q31_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + /** + * @ingroup groupInterpolation + */ + + /** + * @defgroup LinearInterpolate Linear Interpolation + * + * Linear interpolation is a method of curve fitting using linear polynomials. + * Linear interpolation works by effectively drawing a straight line between two neighboring samples and returning the appropriate point along that line + * + * \par + * \image html LinearInterp.gif "Linear interpolation" + * + * \par + * A Linear Interpolate function calculates an output value(y), for the input(x) + * using linear interpolation of the input values x0, x1( nearest input values) and the output values y0 and y1(nearest output values) + * + * \par Algorithm: + *
+   *       y = y0 + (x - x0) * ((y1 - y0)/(x1-x0))
+   *       where x0, x1 are nearest values of input x
+   *             y0, y1 are nearest values to output y
+   * 
+ * + * \par + * This set of functions implements Linear interpolation process + * for Q7, Q15, Q31, and floating-point data types. The functions operate on a single + * sample of data and each call to the function returns a single processed value. + * S points to an instance of the Linear Interpolate function data structure. + * x is the input sample value. The functions returns the output value. + * + * \par + * if x is outside of the table boundary, Linear interpolation returns first value of the table + * if x is below input range and returns last value of table if x is above range. + */ + + /** + * @addtogroup LinearInterpolate + * @{ + */ + + /** + * @brief Process function for the floating-point Linear Interpolation Function. + * @param[in,out] S is an instance of the floating-point Linear Interpolation structure + * @param[in] x input sample to process + * @return y processed output sample. + * + */ + static __INLINE float32_t arm_linear_interp_f32( + arm_linear_interp_instance_f32 * S, + float32_t x) + { + float32_t y; + float32_t x0, x1; /* Nearest input values */ + float32_t y0, y1; /* Nearest output values */ + float32_t xSpacing = S->xSpacing; /* spacing between input values */ + int32_t i; /* Index variable */ + float32_t *pYData = S->pYData; /* pointer to output table */ + + /* Calculation of index */ + i = (int32_t) ((x - S->x1) / xSpacing); + + if(i < 0) + { + /* Iniatilize output for below specified range as least output value of table */ + y = pYData[0]; + } + else if((uint32_t)i >= S->nValues) + { + /* Iniatilize output for above specified range as last output value of table */ + y = pYData[S->nValues - 1]; + } + else + { + /* Calculation of nearest input values */ + x0 = S->x1 + i * xSpacing; + x1 = S->x1 + (i + 1) * xSpacing; + + /* Read of nearest output values */ + y0 = pYData[i]; + y1 = pYData[i + 1]; + + /* Calculation of output */ + y = y0 + (x - x0) * ((y1 - y0) / (x1 - x0)); + + } + + /* returns output value */ + return (y); + } + + + /** + * + * @brief Process function for the Q31 Linear Interpolation Function. + * @param[in] pYData pointer to Q31 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + * + */ + static __INLINE q31_t arm_linear_interp_q31( + q31_t * pYData, + q31_t x, + uint32_t nValues) + { + q31_t y; /* output */ + q31_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + int32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + index = ((x & (q31_t)0xFFF00000) >> 20); + + if(index >= (int32_t)(nValues - 1)) + { + return (pYData[nValues - 1]); + } + else if(index < 0) + { + return (pYData[0]); + } + else + { + /* 20 bits for the fractional part */ + /* shift left by 11 to keep fract in 1.31 format */ + fract = (x & 0x000FFFFF) << 11; + + /* Read two nearest output values from the index in 1.31(q31) format */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract) and y is in 2.30 format */ + y = ((q31_t) ((q63_t) y0 * (0x7FFFFFFF - fract) >> 32)); + + /* Calculation of y0 * (1-fract) + y1 *fract and y is in 2.30 format */ + y += ((q31_t) (((q63_t) y1 * fract) >> 32)); + + /* Convert y to 1.31 format */ + return (y << 1u); + } + } + + + /** + * + * @brief Process function for the Q15 Linear Interpolation Function. + * @param[in] pYData pointer to Q15 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + * + */ + static __INLINE q15_t arm_linear_interp_q15( + q15_t * pYData, + q31_t x, + uint32_t nValues) + { + q63_t y; /* output */ + q15_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + int32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + index = ((x & (int32_t)0xFFF00000) >> 20); + + if(index >= (int32_t)(nValues - 1)) + { + return (pYData[nValues - 1]); + } + else if(index < 0) + { + return (pYData[0]); + } + else + { + /* 20 bits for the fractional part */ + /* fract is in 12.20 format */ + fract = (x & 0x000FFFFF); + + /* Read two nearest output values from the index */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract) and y is in 13.35 format */ + y = ((q63_t) y0 * (0xFFFFF - fract)); + + /* Calculation of (y0 * (1-fract) + y1 * fract) and y is in 13.35 format */ + y += ((q63_t) y1 * (fract)); + + /* convert y to 1.15 format */ + return (q15_t) (y >> 20); + } + } + + + /** + * + * @brief Process function for the Q7 Linear Interpolation Function. + * @param[in] pYData pointer to Q7 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + */ + static __INLINE q7_t arm_linear_interp_q7( + q7_t * pYData, + q31_t x, + uint32_t nValues) + { + q31_t y; /* output */ + q7_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + uint32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + if (x < 0) + { + return (pYData[0]); + } + index = (x >> 20) & 0xfff; + + if(index >= (nValues - 1)) + { + return (pYData[nValues - 1]); + } + else + { + /* 20 bits for the fractional part */ + /* fract is in 12.20 format */ + fract = (x & 0x000FFFFF); + + /* Read two nearest output values from the index and are in 1.7(q7) format */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract ) and y is in 13.27(q27) format */ + y = ((y0 * (0xFFFFF - fract))); + + /* Calculation of y1 * fract + y0 * (1-fract) and y is in 13.27(q27) format */ + y += (y1 * fract); + + /* convert y to 1.7(q7) format */ + return (q7_t) (y >> 20); + } + } + + /** + * @} end of LinearInterpolate group + */ + + /** + * @brief Fast approximation to the trigonometric sine function for floating-point data. + * @param[in] x input value in radians. + * @return sin(x). + */ + float32_t arm_sin_f32( + float32_t x); + + + /** + * @brief Fast approximation to the trigonometric sine function for Q31 data. + * @param[in] x Scaled input value in radians. + * @return sin(x). + */ + q31_t arm_sin_q31( + q31_t x); + + + /** + * @brief Fast approximation to the trigonometric sine function for Q15 data. + * @param[in] x Scaled input value in radians. + * @return sin(x). + */ + q15_t arm_sin_q15( + q15_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for floating-point data. + * @param[in] x input value in radians. + * @return cos(x). + */ + float32_t arm_cos_f32( + float32_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for Q31 data. + * @param[in] x Scaled input value in radians. + * @return cos(x). + */ + q31_t arm_cos_q31( + q31_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for Q15 data. + * @param[in] x Scaled input value in radians. + * @return cos(x). + */ + q15_t arm_cos_q15( + q15_t x); + + + /** + * @ingroup groupFastMath + */ + + + /** + * @defgroup SQRT Square Root + * + * Computes the square root of a number. + * There are separate functions for Q15, Q31, and floating-point data types. + * The square root function is computed using the Newton-Raphson algorithm. + * This is an iterative algorithm of the form: + *
+   *      x1 = x0 - f(x0)/f'(x0)
+   * 
+ * where x1 is the current estimate, + * x0 is the previous estimate, and + * f'(x0) is the derivative of f() evaluated at x0. + * For the square root function, the algorithm reduces to: + *
+   *     x0 = in/2                         [initial guess]
+   *     x1 = 1/2 * ( x0 + in / x0)        [each iteration]
+   * 
+ */ + + + /** + * @addtogroup SQRT + * @{ + */ + + /** + * @brief Floating-point square root function. + * @param[in] in input value. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + static __INLINE arm_status arm_sqrt_f32( + float32_t in, + float32_t * pOut) + { + if(in >= 0.0f) + { + +#if (__FPU_USED == 1) && defined ( __CC_ARM ) + *pOut = __sqrtf(in); +#elif (__FPU_USED == 1) && (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) + *pOut = __builtin_sqrtf(in); +#elif (__FPU_USED == 1) && defined(__GNUC__) + *pOut = __builtin_sqrtf(in); +#elif (__FPU_USED == 1) && defined ( __ICCARM__ ) && (__VER__ >= 6040000) + __ASM("VSQRT.F32 %0,%1" : "=t"(*pOut) : "t"(in)); +#else + *pOut = sqrtf(in); +#endif + + return (ARM_MATH_SUCCESS); + } + else + { + *pOut = 0.0f; + return (ARM_MATH_ARGUMENT_ERROR); + } + } + + + /** + * @brief Q31 square root function. + * @param[in] in input value. The range of the input value is [0 +1) or 0x00000000 to 0x7FFFFFFF. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + arm_status arm_sqrt_q31( + q31_t in, + q31_t * pOut); + + + /** + * @brief Q15 square root function. + * @param[in] in input value. The range of the input value is [0 +1) or 0x0000 to 0x7FFF. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + arm_status arm_sqrt_q15( + q15_t in, + q15_t * pOut); + + /** + * @} end of SQRT group + */ + + + /** + * @brief floating-point Circular write function. + */ + static __INLINE void arm_circularWrite_f32( + int32_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const int32_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if(wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + + /** + * @brief floating-point Circular Read function. + */ + static __INLINE void arm_circularRead_f32( + int32_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + int32_t * dst, + int32_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if(dst == (int32_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update rOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if(rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Q15 Circular write function. + */ + static __INLINE void arm_circularWrite_q15( + q15_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const q15_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if(wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + /** + * @brief Q15 Circular Read function. + */ + static __INLINE void arm_circularRead_q15( + q15_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + q15_t * dst, + q15_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if(dst == (q15_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update wOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if(rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Q7 Circular write function. + */ + static __INLINE void arm_circularWrite_q7( + q7_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const q7_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if(wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + /** + * @brief Q7 Circular Read function. + */ + static __INLINE void arm_circularRead_q7( + q7_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + q7_t * dst, + q7_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if(dst == (q7_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update rOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if(rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Sum of the squares of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q31( + q31_t * pSrc, + uint32_t blockSize, + q63_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q15( + q15_t * pSrc, + uint32_t blockSize, + q63_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q7( + q7_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Mean value of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * pResult); + + + /** + * @brief Mean value of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Mean value of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Mean value of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Variance of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Variance of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Variance of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Standard deviation of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Standard deviation of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Standard deviation of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Floating-point complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_q15( + q15_t * pSrcA, + q15_t * pSrcB, + uint32_t numSamples, + q31_t * realResult, + q31_t * imagResult); + + + /** + * @brief Q31 complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_q31( + q31_t * pSrcA, + q31_t * pSrcB, + uint32_t numSamples, + q63_t * realResult, + q63_t * imagResult); + + + /** + * @brief Floating-point complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_f32( + float32_t * pSrcA, + float32_t * pSrcB, + uint32_t numSamples, + float32_t * realResult, + float32_t * imagResult); + + + /** + * @brief Q15 complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_q15( + q15_t * pSrcCmplx, + q15_t * pSrcReal, + q15_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_q31( + q31_t * pSrcCmplx, + q31_t * pSrcReal, + q31_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_f32( + float32_t * pSrcCmplx, + float32_t * pSrcReal, + float32_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Minimum value of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] result is output pointer + * @param[in] index is the array index of the minimum value in the input buffer. + */ + void arm_min_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * result, + uint32_t * index); + + + /** + * @brief Minimum value of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[in] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Minimum value of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[out] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Minimum value of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[out] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q7 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q15 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q31 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a floating-point vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Q15 complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Converts the elements of the floating-point vector to Q31 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q31 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q31( + float32_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the floating-point vector to Q15 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q15 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q15( + float32_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the floating-point vector to Q7 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q7 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q7( + float32_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q31 vector to Q15 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_q15( + q31_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q31 vector to Q7 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_q7( + q31_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_float( + q15_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to Q31 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_q31( + q15_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to Q7 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_q7( + q15_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @ingroup groupInterpolation + */ + + /** + * @defgroup BilinearInterpolate Bilinear Interpolation + * + * Bilinear interpolation is an extension of linear interpolation applied to a two dimensional grid. + * The underlying function f(x, y) is sampled on a regular grid and the interpolation process + * determines values between the grid points. + * Bilinear interpolation is equivalent to two step linear interpolation, first in the x-dimension and then in the y-dimension. + * Bilinear interpolation is often used in image processing to rescale images. + * The CMSIS DSP library provides bilinear interpolation functions for Q7, Q15, Q31, and floating-point data types. + * + * Algorithm + * \par + * The instance structure used by the bilinear interpolation functions describes a two dimensional data table. + * For floating-point, the instance structure is defined as: + *
+   *   typedef struct
+   *   {
+   *     uint16_t numRows;
+   *     uint16_t numCols;
+   *     float32_t *pData;
+   * } arm_bilinear_interp_instance_f32;
+   * 
+ * + * \par + * where numRows specifies the number of rows in the table; + * numCols specifies the number of columns in the table; + * and pData points to an array of size numRows*numCols values. + * The data table pTable is organized in row order and the supplied data values fall on integer indexes. + * That is, table element (x,y) is located at pTable[x + y*numCols] where x and y are integers. + * + * \par + * Let (x, y) specify the desired interpolation point. Then define: + *
+   *     XF = floor(x)
+   *     YF = floor(y)
+   * 
+ * \par + * The interpolated output point is computed as: + *
+   *  f(x, y) = f(XF, YF) * (1-(x-XF)) * (1-(y-YF))
+   *           + f(XF+1, YF) * (x-XF)*(1-(y-YF))
+   *           + f(XF, YF+1) * (1-(x-XF))*(y-YF)
+   *           + f(XF+1, YF+1) * (x-XF)*(y-YF)
+   * 
+ * Note that the coordinates (x, y) contain integer and fractional components. + * The integer components specify which portion of the table to use while the + * fractional components control the interpolation processor. + * + * \par + * if (x,y) are outside of the table boundary, Bilinear interpolation returns zero output. + */ + + /** + * @addtogroup BilinearInterpolate + * @{ + */ + + + /** + * + * @brief Floating-point bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate. + * @param[in] Y interpolation coordinate. + * @return out interpolated value. + */ + static __INLINE float32_t arm_bilinear_interp_f32( + const arm_bilinear_interp_instance_f32 * S, + float32_t X, + float32_t Y) + { + float32_t out; + float32_t f00, f01, f10, f11; + float32_t *pData = S->pData; + int32_t xIndex, yIndex, index; + float32_t xdiff, ydiff; + float32_t b1, b2, b3, b4; + + xIndex = (int32_t) X; + yIndex = (int32_t) Y; + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if(xIndex < 0 || xIndex > (S->numRows - 1) || yIndex < 0 || yIndex > (S->numCols - 1)) + { + return (0); + } + + /* Calculation of index for two nearest points in X-direction */ + index = (xIndex - 1) + (yIndex - 1) * S->numCols; + + + /* Read two nearest points in X-direction */ + f00 = pData[index]; + f01 = pData[index + 1]; + + /* Calculation of index for two nearest points in Y-direction */ + index = (xIndex - 1) + (yIndex) * S->numCols; + + + /* Read two nearest points in Y-direction */ + f10 = pData[index]; + f11 = pData[index + 1]; + + /* Calculation of intermediate values */ + b1 = f00; + b2 = f01 - f00; + b3 = f10 - f00; + b4 = f00 - f01 - f10 + f11; + + /* Calculation of fractional part in X */ + xdiff = X - xIndex; + + /* Calculation of fractional part in Y */ + ydiff = Y - yIndex; + + /* Calculation of bi-linear interpolated output */ + out = b1 + b2 * xdiff + b3 * ydiff + b4 * xdiff * ydiff; + + /* return to application */ + return (out); + } + + + /** + * + * @brief Q31 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + static __INLINE q31_t arm_bilinear_interp_q31( + arm_bilinear_interp_instance_q31 * S, + q31_t X, + q31_t Y) + { + q31_t out; /* Temporary output */ + q31_t acc = 0; /* output */ + q31_t xfract, yfract; /* X, Y fractional parts */ + q31_t x1, x2, y1, y2; /* Nearest output values */ + int32_t rI, cI; /* Row and column indices */ + q31_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if(rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* shift left xfract by 11 to keep 1.31 format */ + xfract = (X & 0x000FFFFF) << 11u; + + /* Read two nearest output values from the index */ + x1 = pYData[(rI) + (int32_t)nCols * (cI) ]; + x2 = pYData[(rI) + (int32_t)nCols * (cI) + 1]; + + /* 20 bits for the fractional part */ + /* shift left yfract by 11 to keep 1.31 format */ + yfract = (Y & 0x000FFFFF) << 11u; + + /* Read two nearest output values from the index */ + y1 = pYData[(rI) + (int32_t)nCols * (cI + 1) ]; + y2 = pYData[(rI) + (int32_t)nCols * (cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 3.29(q29) format */ + out = ((q31_t) (((q63_t) x1 * (0x7FFFFFFF - xfract)) >> 32)); + acc = ((q31_t) (((q63_t) out * (0x7FFFFFFF - yfract)) >> 32)); + + /* x2 * (xfract) * (1-yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) x2 * (0x7FFFFFFF - yfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (xfract) >> 32)); + + /* y1 * (1 - xfract) * (yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) y1 * (0x7FFFFFFF - xfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (yfract) >> 32)); + + /* y2 * (xfract) * (yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) y2 * (xfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (yfract) >> 32)); + + /* Convert acc to 1.31(q31) format */ + return ((q31_t)(acc << 2)); + } + + + /** + * @brief Q15 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + static __INLINE q15_t arm_bilinear_interp_q15( + arm_bilinear_interp_instance_q15 * S, + q31_t X, + q31_t Y) + { + q63_t acc = 0; /* output */ + q31_t out; /* Temporary output */ + q15_t x1, x2, y1, y2; /* Nearest output values */ + q31_t xfract, yfract; /* X, Y fractional parts */ + int32_t rI, cI; /* Row and column indices */ + q15_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if(rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* xfract should be in 12.20 format */ + xfract = (X & 0x000FFFFF); + + /* Read two nearest output values from the index */ + x1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) ]; + x2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) + 1]; + + /* 20 bits for the fractional part */ + /* yfract should be in 12.20 format */ + yfract = (Y & 0x000FFFFF); + + /* Read two nearest output values from the index */ + y1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) ]; + y2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 13.51 format */ + + /* x1 is in 1.15(q15), xfract in 12.20 format and out is in 13.35 format */ + /* convert 13.35 to 13.31 by right shifting and out is in 1.31 */ + out = (q31_t) (((q63_t) x1 * (0xFFFFF - xfract)) >> 4u); + acc = ((q63_t) out * (0xFFFFF - yfract)); + + /* x2 * (xfract) * (1-yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) x2 * (0xFFFFF - yfract)) >> 4u); + acc += ((q63_t) out * (xfract)); + + /* y1 * (1 - xfract) * (yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) y1 * (0xFFFFF - xfract)) >> 4u); + acc += ((q63_t) out * (yfract)); + + /* y2 * (xfract) * (yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) y2 * (xfract)) >> 4u); + acc += ((q63_t) out * (yfract)); + + /* acc is in 13.51 format and down shift acc by 36 times */ + /* Convert out to 1.15 format */ + return ((q15_t)(acc >> 36)); + } + + + /** + * @brief Q7 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + static __INLINE q7_t arm_bilinear_interp_q7( + arm_bilinear_interp_instance_q7 * S, + q31_t X, + q31_t Y) + { + q63_t acc = 0; /* output */ + q31_t out; /* Temporary output */ + q31_t xfract, yfract; /* X, Y fractional parts */ + q7_t x1, x2, y1, y2; /* Nearest output values */ + int32_t rI, cI; /* Row and column indices */ + q7_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if(rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* xfract should be in 12.20 format */ + xfract = (X & (q31_t)0x000FFFFF); + + /* Read two nearest output values from the index */ + x1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) ]; + x2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) + 1]; + + /* 20 bits for the fractional part */ + /* yfract should be in 12.20 format */ + yfract = (Y & (q31_t)0x000FFFFF); + + /* Read two nearest output values from the index */ + y1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) ]; + y2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 16.47 format */ + out = ((x1 * (0xFFFFF - xfract))); + acc = (((q63_t) out * (0xFFFFF - yfract))); + + /* x2 * (xfract) * (1-yfract) in 2.22 and adding to acc */ + out = ((x2 * (0xFFFFF - yfract))); + acc += (((q63_t) out * (xfract))); + + /* y1 * (1 - xfract) * (yfract) in 2.22 and adding to acc */ + out = ((y1 * (0xFFFFF - xfract))); + acc += (((q63_t) out * (yfract))); + + /* y2 * (xfract) * (yfract) in 2.22 and adding to acc */ + out = ((y2 * (yfract))); + acc += (((q63_t) out * (xfract))); + + /* acc in 16.47 format and down shift by 40 to convert to 1.7 format */ + return ((q7_t)(acc >> 40)); + } + + /** + * @} end of BilinearInterpolate group + */ + + +/* SMMLAR */ +#define multAcc_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((((q63_t) a) << 32) + ((q63_t) x * y) + 0x80000000LL ) >> 32) + +/* SMMLSR */ +#define multSub_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((((q63_t) a) << 32) - ((q63_t) x * y) + 0x80000000LL ) >> 32) + +/* SMMULR */ +#define mult_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((q63_t) x * y + 0x80000000LL ) >> 32) + +/* SMMLA */ +#define multAcc_32x32_keep32(a, x, y) \ + a += (q31_t) (((q63_t) x * y) >> 32) + +/* SMMLS */ +#define multSub_32x32_keep32(a, x, y) \ + a -= (q31_t) (((q63_t) x * y) >> 32) + +/* SMMUL */ +#define mult_32x32_keep32(a, x, y) \ + a = (q31_t) (((q63_t) x * y ) >> 32) + + +#if defined ( __CC_ARM ) + /* Enter low optimization region - place directly above function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define LOW_OPTIMIZATION_ENTER \ + _Pragma ("push") \ + _Pragma ("O1") + #else + #define LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define LOW_OPTIMIZATION_EXIT \ + _Pragma ("pop") + #else + #define LOW_OPTIMIZATION_EXIT + #endif + + /* Enter low optimization region - place directly above function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + + /* Exit low optimization region - place directly after end of function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__GNUC__) + #define LOW_OPTIMIZATION_ENTER __attribute__(( optimize("-O1") )) + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__ICCARM__) + /* Enter low optimization region - place directly above function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define LOW_OPTIMIZATION_ENTER \ + _Pragma ("optimize=low") + #else + #define LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #define LOW_OPTIMIZATION_EXIT + + /* Enter low optimization region - place directly above function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER \ + _Pragma ("optimize=low") + #else + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__CSMC__) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__TASKING__) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#endif + + +#ifdef __cplusplus +} +#endif + + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +#endif /* _ARM_MATH_H */ + +/** + * + * End of file. + */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/bl_inc.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/bl_inc.h new file mode 100644 index 0000000000..2984c86e86 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/bl_inc.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __BL_INC_H__ +#define __BL_INC_H__ +#include "global_config.h" + +#include "air105.h" +#include "air105_conf.h" + +#include "bsp_common.h" +#include "platform_define.h" + +#include "resource_map.h" +#include "core_dma.h" +#include "core_tick.h" +#include "core_debug.h" +#include "core_flash.h" +#include "core_gpio.h" +#include "core_timer.h" +#include "core_otp.h" +#include "core_uart.h" +#include "core_rtc.h" +#include "core_i2c.h" + +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/bsp_common.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/bsp_common.h new file mode 100644 index 0000000000..3aa87ccc46 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/bsp_common.h @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __BSP_COMMON_H__ +#define __BSP_COMMON_H__ +#include +#include +#include +#include +#include +#include "cmsis_gcc.h" + + +typedef struct +{ + uint32_t param_max_num; + uint32_t param_max_len; + uint32_t param_num; + int8_t *param_str; +}CmdParam; + +typedef struct +{ + uint8_t Sec; + uint8_t Min; + uint8_t Hour; + uint8_t Week;//表示日期0~6,sun~sat,表示预约时,bit0~bit6,sun~sat +}Time_UserDataStruct; + +typedef struct +{ + uint16_t Year; + uint8_t Mon; + uint8_t Day; +}Date_UserDataStruct; + +typedef union +{ + uint32_t dwTime; + Time_UserDataStruct Time; +}Time_Union; + +typedef union +{ + uint32_t dwDate; + Date_UserDataStruct Date; +}Date_Union; + +typedef struct +{ + uint8_t *Data; + uint32_t Len; + uint32_t Offset; + uint32_t MaxLength; + uint32_t DataSize; +}Loop_Buffer; + +typedef struct +{ + uint8_t *Data; + uint32_t Pos; + uint32_t MaxLen; +}Buffer_Struct; + +typedef union +{ + void *p; + char *pc8; + uint8_t *pu8; + uint16_t *pu16; + uint32_t *pu32; + uint32_t u32; + uint8_t u8[4]; + uint16_t u16[2]; +}PV_Union; + +enum +{ + ERROR_NONE, + ERROR_NO_SUCH_ID, + ERROR_PERMISSION_DENIED, + ERROR_PARAM_INVALID, + ERROR_PARAM_OVERFLOW, + ERROR_DEVICE_BUSY, + ERROR_OPERATION_FAILED, + ERROR_BUFFER_FULL, + ERROR_NO_MEMORY, + ERROR_CMD_NOT_SUPPORT, + ERROR_NO_DATA, + ERROR_NO_FLASH, + ERROR_NO_TIMER, + ERROR_TIMEOUT, + ERROR_SSL_HANDSHAKE, + ERROR_PROTOCL, + ERROR_ID_INVALID, + ERROR_MID_INVALID, + ERROR_RETRY_TOO_MUCH, + ERROR_CMD_BLOCK, + LIST_FIND = 1, + LIST_PASS = 0, + LIST_DEL = -1, + + DMA_CB_DONE = 0, + UART_CB_TX_BUFFER_DONE, + UART_CB_TX_ALL_DONE, + UART_CB_RX_NEW, + UART_CB_RX_TIMEOUT, + UART_CB_RX_BUFFER_FULL, + UART_CB_ERROR, + UART_CB_CONNECTED, //串口工具对方已经打开 + DMA_CB_ERROR = 0xffffffff, + + CORE_EVENT_ID_START = 0, + CORE_EVENT_ID_ANY = 0, + CORE_EVENT_TIMEOUT, + CORE_TIMER_TIMEOUT = 0x00010000, + SERVICE_EVENT_ID_START = 0x00100000, + USER_EVENT_ID_START = 0x10000000, + INVALID_EVENT_ID = 0xffffffff, +}; + +#define INVALID_HANDLE_VALUE ((void *)0xffffffff) +#define INVALID_PARAM (0xffffffff) +#define CRC32_GEN (0x04C11DB7) +#define CRC32_START (0xffffffff) +#define CRC16_CCITT_GEN (0x1021) +#define CRC16_MODBUS_GEN (0x8005) +#define CRC16_START (0xffff) +#define CRC16_IBM_SEED (0xffff) +#define CRC16_CCITT_SEED (0x1D0F) +#define HANDLE void * + +#define MIN(X,Y) (((X) < (Y))?(X):(Y)) + +typedef void (* TaskFun_t)( void * ); +typedef void(* CBDataFun_t)(uint8_t *Data, uint32_t Len); +typedef int32_t(*CBFuncEx_t)(void *pData, void *pParam); +typedef uint64_t LongInt; + +typedef struct +{ + CBFuncEx_t CB; + union { + void *pParam; //用户回调模式 + uint32_t MaxCnt; //设置捕获模式时的最大tick,捕获时的tick + }uParam; + + union { + struct { + uint8_t Level; //IO输入输出电平,捕获模式下中断时IO电平 + uint8_t PullMode; //IO上下拉控制 + } IOArg; + struct { + uint8_t ExtiMode; //中断模式 + uint8_t PullMode; //IO上下拉控制 + } ExitArg; + uint16_t Time; //delay时间,us + } uArg; + uint8_t Operation; //操作类型 + uint8_t Arg1; //IO操作时为IOpin,delay操作时则为微调值,0~47,48为1us +}OPQueue_CmdStruct; + +__attribute__((weak)) uint8_t OS_CheckInIrq(void); + +uint32_t OS_EnterCritical(void); +void OS_ExitCritical(uint32_t Critical); +void *OS_Malloc(uint32_t Size); +void *OS_Zalloc(uint32_t Size); +void OS_Free(void *p); +void *OS_Realloc(void *buf, uint32_t size); +void OS_MemInfo(uint32_t *curalloc, uint32_t *totfree, uint32_t *maxfree); +int32_t OS_InitBuffer(Buffer_Struct *Buf, uint32_t Size); +void OS_DeInitBuffer(Buffer_Struct *Buf); +int32_t OS_ReInitBuffer(Buffer_Struct *Buf, uint32_t Size); +int32_t OS_ReSizeBuffer(Buffer_Struct *Buf, uint32_t Size); +int32_t OS_BufferWrite(Buffer_Struct *Buf, void *Data, uint32_t Len); +int32_t OS_BufferWriteLimit(Buffer_Struct *Buf, void *Data, uint32_t Len); +void OS_BufferRemove(Buffer_Struct *Buf, uint32_t Len); + +void Buffer_StaticInit(Buffer_Struct *Buf, void *Src, uint32_t MaxLen); +int32_t Buffer_StaticWrite(Buffer_Struct *Buf, void *Data, uint32_t Len); +void Buffer_Remove(Buffer_Struct *Buf, uint32_t Len); +void LoopBuffer_Init(Loop_Buffer *Buf, void *Src, uint32_t MaxLen, uint32_t DataSize); +uint32_t LoopBuffer_Query(Loop_Buffer *Buf, void *Src, uint32_t Len); +uint32_t LoopBuffer_Read(Loop_Buffer *Buf, void *Src, uint32_t Len); +void LoopBuffer_Del(Loop_Buffer *Buf, uint32_t Len); +uint32_t LoopBuffer_Write(Loop_Buffer *Buf, void *Src, uint32_t Len); +int32_t BSP_SetBit(uint8_t *Data, uint32_t Sn, uint8_t Value); +int32_t BSP_GetBit(uint8_t *Data, uint32_t Sn, uint8_t *Value); +uint8_t BSP_TestBit(uint8_t *Data, uint32_t Sn); +uint8_t XorCheck(void *Src, uint32_t Len, uint8_t CheckStart); +uint8_t SumCheck(uint8_t *Data, uint32_t Len); +uint16_t CRC16Cal(void *Data, uint16_t Len, uint16_t CRC16Last, uint16_t CRCRoot, uint8_t IsReverse); +uint32_t AsciiToU32(uint8_t *Src, uint32_t Len); +void CRC32_CreateTable(uint32_t *Tab, uint32_t Gen); +uint32_t CRC32_Cal(uint32_t * CRC32_Table, uint8_t *Buf, uint32_t Size, uint32_t CRC32Last); +uint32_t CmdParseParam(int8_t* pStr, CmdParam *CmdParam, int8_t Cut); +uint8_t IsLeapYear(uint32_t Year); +LongInt UTC2Tamp(Date_UserDataStruct *Date, Time_UserDataStruct *Time); +uint32_t Tamp2UTC(LongInt Sec, Date_UserDataStruct *Date, Time_UserDataStruct *Time, uint32_t LastDDay); +/* + * 转义解包 + * 标识Flag,即包头包尾加入Flag + * 数据中遇到Code F1 -> Flag + * 数据中遇到Code F2 -> Code + * 数据中遇到Flag 出错返回0 + */ + +uint32_t TransferUnpack(uint8_t Flag, uint8_t Code, uint8_t F1, uint8_t F2, uint8_t *InBuf, uint32_t Len, uint8_t *OutBuf); +/* + * llist相关代码,大部分来自linux内核 + */ +/** + * container_of - cast a member of a structure out to the containing structure + * + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + + +/* + * These are non-NULL pointers that will result in page faults + * under normal circumstances, used to verify that nobody uses + * non-initialized llist entries. + */ +#define LLIST_POISON1 (0) +#define LLIST_POISON2 (0) + +/* + * Simple doubly linked llist implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole llists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +typedef struct llist_head_t{ + struct llist_head_t *next, *prev; +}llist_head; + +#define LLIST_HEAD_INIT(name) { &(name), &(name) } + +#define LLIST_HEAD(name) \ + llist_head name = LLIST_HEAD_INIT(name) + +#define INIT_LLIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal llist manipulation where we know + * the prev/next entries already! + */ +void __llist_add(llist_head *p, + llist_head *prev, + llist_head *next); + +/** + * llist_add - add a new entry + * @new: new entry to be added + * @head: llist head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +void llist_add(llist_head *p, llist_head *head); + +/** + * llist_add_tail - add a new entry + * @new: new entry to be added + * @head: llist head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +void llist_add_tail(llist_head *p, llist_head *head); + + +/* + * Delete a llist entry by making the prev/next entries + * point to each other. + * + * This is only for internal llist manipulation where we know + * the prev/next entries already! + */ +void __llist_del(llist_head * prev, llist_head * next); + +/** + * llist_del - deletes entry from llist. + * @entry: the element to delete from the llist. + * Note: llist_empty on entry does not return true after this, the entry is + * in an undefined state. + */ +void llist_del(llist_head *entry); + +/** + * llist_del_init - deletes entry from llist and reinitialize it. + * @entry: the element to delete from the llist. + */ +void llist_del_init(llist_head *entry); + +/** + * llist_move - delete from one llist and add as another's head + * @llist: the entry to move + * @head: the head that will precede our entry + */ +void llist_move(llist_head *llist, llist_head *head); + +/** + * llist_move_tail - delete from one llist and add as another's tail + * @llist: the entry to move + * @head: the head that will follow our entry + */ +void llist_move_tail(llist_head *llist, + llist_head *head); + +/** + * llist_empty - tests whether a llist is empty + * @head: the llist to test. + */ +int llist_empty(const llist_head *head); + +uint32_t llist_num(const llist_head *head); + +void *llist_traversal(llist_head *head, CBFuncEx_t cb, void *pData); +/** + * llist_entry - get the struct for this entry + * @ptr: the &llist_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the llist_struct within the struct. + */ +#define llist_entry(ptr, type, member) \ + container_of(ptr, type, member) + + +uint8_t BytesGet8(const void *ptr); +void BytesPut8(void *ptr, uint8_t v); +uint16_t BytesGetBe16(const void *ptr); +void BytesPutBe16(void *ptr, uint16_t v); +uint32_t BytesGetBe32(const void *ptr); +void BytesPutBe32(void *ptr, uint32_t v); +uint16_t BytesGetLe16(const void *ptr); +void BytesPutLe16(void *ptr, uint16_t v); +uint32_t BytesGetLe32(const void *ptr); +void BytesPutLe32(void *ptr, uint32_t v); +uint64_t BytesGetLe64(const void *ptr); +void BytesPutLe64(void *ptr, uint64_t v); +uint8_t BytesGet8FromBuf(Buffer_Struct *Buf); +void BytesPut8ToBuf(Buffer_Struct *Buf, uint8_t v); +uint16_t BytesGetBe16FromBuf(Buffer_Struct *Buf); +void BytesPutBe16ToBuf(Buffer_Struct *Buf, uint16_t v); +uint32_t BytesGetBe32FromBuf(Buffer_Struct *Buf); +void BytesPutBe32ToBuf(Buffer_Struct *Buf, uint32_t v); +uint16_t BytesGetLe16FromBuf(Buffer_Struct *Buf); +void BytesPutLe16ToBuf(Buffer_Struct *Buf, uint16_t v); +uint32_t BytesGetLe32FromBuf(Buffer_Struct *Buf); +void BytesPutLe32ToBuf(Buffer_Struct *Buf, uint32_t v); +uint64_t BytesGetLe64FromBuf(Buffer_Struct *Buf); +void BytesPutLe64ToBuf(Buffer_Struct *Buf, uint64_t v); +float BytesGetFloatFromBuf(Buffer_Struct *Buf); +void BytesPutFloatToBuf(Buffer_Struct *Buf, float v); +double BytesGetDoubleFromBuf(Buffer_Struct *Buf); +void BytesPutDoubleToBuf(Buffer_Struct *Buf, double v); +/*************************************************************************/ + + +#define malloc OS_Malloc +#define free OS_Free +#define realloc OS_Realloc +#define zalloc OS_Zalloc +#define calloc OS_Calloc +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_armcc.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_armcc.h new file mode 100644 index 0000000000..a4c67e0268 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_armcc.h @@ -0,0 +1,865 @@ +/**************************************************************************//** + * @file cmsis_armcc.h + * @brief CMSIS compiler ARMCC (Arm Compiler 5) header file + * @version V5.0.4 + * @date 10. January 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_ARMCC_H +#define __CMSIS_ARMCC_H + + +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677) + #error "Please use Arm Compiler Toolchain V4.0.677 or later!" +#endif + +/* CMSIS compiler control architecture macros */ +#if ((defined (__TARGET_ARCH_6_M ) && (__TARGET_ARCH_6_M == 1)) || \ + (defined (__TARGET_ARCH_6S_M ) && (__TARGET_ARCH_6S_M == 1)) ) + #define __ARM_ARCH_6M__ 1 +#endif + +#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M == 1)) + #define __ARM_ARCH_7M__ 1 +#endif + +#if (defined (__TARGET_ARCH_7E_M) && (__TARGET_ARCH_7E_M == 1)) + #define __ARM_ARCH_7EM__ 1 +#endif + + /* __ARM_ARCH_8M_BASE__ not applicable */ + /* __ARM_ARCH_8M_MAIN__ not applicable */ + + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE __inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static __inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE static __forceinline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __declspec(noreturn) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed)) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT __packed struct +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION __packed union +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x))) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr))) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr))) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +/* intrinsic void __enable_irq(); */ + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +/* intrinsic void __disable_irq(); */ + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xFFU); +} + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + register uint32_t __regBasePriMax __ASM("basepri_max"); + __regBasePriMax = (basePri & 0xFFU); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1U); +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0U); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#else + (void)fpscr; +#endif +} + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() do {\ + __schedule_barrier();\ + __isb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() do {\ + __schedule_barrier();\ + __dsb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() do {\ + __schedule_barrier();\ + __dmb(0xF);\ + __schedule_barrier();\ + } while (0U) + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __breakpoint(value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + #define __RBIT __rbit +#else +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value != 0U; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ + return result; +} +#endif + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) +#else + #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) +#else + #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) +#else + #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXB(value, ptr) __strex(value, ptr) +#else + #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXH(value, ptr) __strex(value, ptr) +#else + #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXW(value, ptr) __strex(value, ptr) +#else + #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __clrex + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value) +{ + rrx r0, r0 + bx lr +} +#endif + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr)) + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRBT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRHT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRT(value, ptr) __strt(value, ptr) + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__attribute__((always_inline)) __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + +#define __SADD8 __sadd8 +#define __QADD8 __qadd8 +#define __SHADD8 __shadd8 +#define __UADD8 __uadd8 +#define __UQADD8 __uqadd8 +#define __UHADD8 __uhadd8 +#define __SSUB8 __ssub8 +#define __QSUB8 __qsub8 +#define __SHSUB8 __shsub8 +#define __USUB8 __usub8 +#define __UQSUB8 __uqsub8 +#define __UHSUB8 __uhsub8 +#define __SADD16 __sadd16 +#define __QADD16 __qadd16 +#define __SHADD16 __shadd16 +#define __UADD16 __uadd16 +#define __UQADD16 __uqadd16 +#define __UHADD16 __uhadd16 +#define __SSUB16 __ssub16 +#define __QSUB16 __qsub16 +#define __SHSUB16 __shsub16 +#define __USUB16 __usub16 +#define __UQSUB16 __uqsub16 +#define __UHSUB16 __uhsub16 +#define __SASX __sasx +#define __QASX __qasx +#define __SHASX __shasx +#define __UASX __uasx +#define __UQASX __uqasx +#define __UHASX __uhasx +#define __SSAX __ssax +#define __QSAX __qsax +#define __SHSAX __shsax +#define __USAX __usax +#define __UQSAX __uqsax +#define __UHSAX __uhsax +#define __USAD8 __usad8 +#define __USADA8 __usada8 +#define __SSAT16 __ssat16 +#define __USAT16 __usat16 +#define __UXTB16 __uxtb16 +#define __UXTAB16 __uxtab16 +#define __SXTB16 __sxtb16 +#define __SXTAB16 __sxtab16 +#define __SMUAD __smuad +#define __SMUADX __smuadx +#define __SMLAD __smlad +#define __SMLADX __smladx +#define __SMLALD __smlald +#define __SMLALDX __smlaldx +#define __SMUSD __smusd +#define __SMUSDX __smusdx +#define __SMLSD __smlsd +#define __SMLSDX __smlsdx +#define __SMLSLD __smlsld +#define __SMLSLDX __smlsldx +#define __SEL __sel +#define __QADD __qadd +#define __QSUB __qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ + ((int64_t)(ARG3) << 32U) ) >> 32U)) + +#endif /* ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCC_H */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_armcc_V6.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_armcc_V6.h new file mode 100644 index 0000000000..04b41ed69c --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_armcc_V6.h @@ -0,0 +1,1800 @@ +/**************************************************************************//** + * @file cmsis_armcc_V6.h + * @brief CMSIS Cortex-M Core Function/Instruction Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 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 __CMSIS_ARMCC_V6_H +#define __CMSIS_ARMCC_V6_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get IPSR Register (non-secure) + \details Returns the content of the non-secure IPSR Register when in secure state. + \return IPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_IPSR_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Get APSR Register + \details 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); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get APSR Register (non-secure) + \details Returns the content of the non-secure APSR Register when in secure state. + \return APSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_APSR_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Get xPSR Register + \details 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); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get xPSR Register (non-secure) + \details Returns the content of the non-secure xPSR Register when in secure state. + \return xPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_xPSR_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Get Process Stack Pointer + \details 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" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSP_NS(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : "sp"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : "sp"); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details 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" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSP_NS(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : "sp"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : "sp"); +} +#endif + + +/** + \brief Get Priority Mask + \details 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); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ + +/** + \brief Enable FIQ + \details 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 + \details 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 + \details 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" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_NS(uint32_t value) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (value) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Base Priority with condition (non_secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_MAX_NS(uint32_t value) +{ + __ASM volatile ("MSR basepri_max_ns, %0" : : "r" (value) : "memory"); +} +#endif + + +/** + \brief Get Fault Mask + \details 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); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + + +#endif /* ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ + + +#if (__ARM_ARCH_8M__ == 1U) + +/** + \brief Get Process Stack Pointer Limit + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSPLIM(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Get Process Stack Pointer Limit (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSPLIM(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Get Main Stack Pointer Limit (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Set Main Stack Pointer Limit (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +} +#endif + +#endif /* (__ARM_ARCH_8M__ == 1U) */ + + +#if ((__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=4 */ + +/** + \brief Get FPSCR + \details eturns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +#define __get_FPSCR __builtin_arm_get_fpscr +#if 0 +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + uint32_t result; + + __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} +#endif + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get FPSCR (non-secure) + \details Returns the current value of the non-secure Floating Point Status/Control register when in secure state. + \return Floating Point Status/Control register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FPSCR_NS(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + uint32_t result; + + __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile ("VMRS %0, fpscr_ns" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} +#endif + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +#define __set_FPSCR __builtin_arm_set_fpscr +#if 0 +__attribute__((always_inline)) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} +#endif + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set FPSCR (non-secure) + \details Assigns the given value to the non-secure Floating Point Status/Control register when in secure state. + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FPSCR_NS(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile ("VMSR fpscr_ns, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} +#endif + +#endif /* ((__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ + + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __builtin_arm_nop + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __builtin_arm_wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __builtin_arm_wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __builtin_arm_sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __builtin_arm_isb(0xF); + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __builtin_arm_dsb(0xF); + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __builtin_arm_dmb(0xF); + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __builtin_bswap32 + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV16 __builtin_bswap16 /* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */ +#if 0 +__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); +} +#endif + + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ + /* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */ +__attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ + int32_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \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 + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + 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 + */ + /* ToDo: ARMCC_V6: check if __builtin_arm_rbit is supported */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value; 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 __builtin_clz + + +#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB (uint8_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH (uint16_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW (uint32_t)__builtin_arm_ldrex + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW (uint32_t)__builtin_arm_strex + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __builtin_arm_clrex + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +/*#define __SSAT __builtin_arm_ssat*/ +#define __SSAT(ARG1,ARG2) \ +({ \ + 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] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __builtin_arm_usat +#if 0 +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) +#endif + + +/** + \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 + */ +__attribute__((always_inline)) __STATIC_INLINE 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) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE 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 + */ +__attribute__((always_inline)) __STATIC_INLINE 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 + */ +__attribute__((always_inline)) __STATIC_INLINE 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 + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#endif /* ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ + + +#if (__ARM_ARCH_8M__ == 1U) + +/** + \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) + */ +__attribute__((always_inline)) __STATIC_INLINE 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) + */ +__attribute__((always_inline)) __STATIC_INLINE 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) + */ +__attribute__((always_inline)) __STATIC_INLINE 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 + */ +__attribute__((always_inline)) __STATIC_INLINE 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 + */ +__attribute__((always_inline)) __STATIC_INLINE 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 + */ +__attribute__((always_inline)) __STATIC_INLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDAEXB (uint8_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDAEXH (uint16_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDAEX (uint32_t)__builtin_arm_ldaex + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXB (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXH (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEX (uint32_t)__builtin_arm_stlex + +#endif /* (__ARM_ARCH_8M__ == 1U) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (__ARM_FEATURE_DSP == 1U) /* ToDo: ARMCC_V6: This should be ARCH >= ARMv7-M + SIMD */ + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1U) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCC_V6_H */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_armclang.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_armclang.h new file mode 100644 index 0000000000..a1722f87a8 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_armclang.h @@ -0,0 +1,1869 @@ +/**************************************************************************//** + * @file cmsis_armclang.h + * @brief CMSIS compiler armclang (Arm Compiler 6) header file + * @version V5.0.4 + * @date 10. January 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */ + +#ifndef __CMSIS_ARMCLANG_H +#define __CMSIS_ARMCLANG_H + +#pragma clang system_header /* treat file as system include file */ + +#ifndef __ARM_COMPAT_H +#include /* Compatibility header for Arm Compiler 5 intrinsics */ +#endif + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE __inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static __inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __attribute__((__noreturn__)) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */ + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */ + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +/* intrinsic void __enable_irq(); see arm_compat.h */ + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +/* intrinsic void __disable_irq(); see arm_compat.h */ + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq /* see arm_compat.h */ + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq /* see arm_compat.h */ + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr +#else +#define __get_FPSCR() ((uint32_t)0U) +#endif + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __set_FPSCR __builtin_arm_set_fpscr +#else +#define __set_FPSCR(x) ((void)(x)) +#endif + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __builtin_arm_nop + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __builtin_arm_wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __builtin_arm_wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __builtin_arm_sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __builtin_arm_isb(0xF); + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __builtin_arm_dsb(0xF); + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __builtin_arm_dmb(0xF); + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV(value) __builtin_bswap32(value) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV16(value) __ROR(__REV(value), 16) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REVSH(value) (int16_t)__builtin_bswap16(value) + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __builtin_arm_rbit + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ (uint8_t)__builtin_clz + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB (uint8_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH (uint16_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW (uint32_t)__builtin_arm_ldrex + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW (uint32_t)__builtin_arm_strex + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __builtin_arm_clrex + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __builtin_arm_ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __builtin_arm_usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDAEXB (uint8_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDAEXH (uint16_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDAEX (uint32_t)__builtin_arm_ldaex + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXB (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXH (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEX (uint32_t)__builtin_arm_stlex + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + +__STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#if 0 +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) +#endif + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCLANG_H */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_compiler.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_compiler.h new file mode 100644 index 0000000000..94212eb87a --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_compiler.h @@ -0,0 +1,266 @@ +/**************************************************************************//** + * @file cmsis_compiler.h + * @brief CMSIS compiler generic header file + * @version V5.0.4 + * @date 10. January 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_COMPILER_H +#define __CMSIS_COMPILER_H + +#include + +/* + * Arm Compiler 4/5 + */ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + + +/* + * Arm Compiler 6 (armclang) + */ +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armclang.h" + + +/* + * GNU Compiler + */ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + + +/* + * IAR Compiler + */ +#elif defined ( __ICCARM__ ) + #include + + +/* + * TI Arm Compiler + */ +#elif defined ( __TI_ARM__ ) + #include + + #ifndef __ASM + #define __ASM __asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + #define __NO_RETURN __attribute__((noreturn)) + #endif + #ifndef __USED + #define __USED __attribute__((used)) + #endif + #ifndef __WEAK + #define __WEAK __attribute__((weak)) + #endif + #ifndef __PACKED + #define __PACKED __attribute__((packed)) + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed)) + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed)) + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) + #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif + + +/* + * TASKING Compiler + */ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + + #ifndef __ASM + #define __ASM __asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + #define __NO_RETURN __attribute__((noreturn)) + #endif + #ifndef __USED + #define __USED __attribute__((used)) + #endif + #ifndef __WEAK + #define __WEAK __attribute__((weak)) + #endif + #ifndef __PACKED + #define __PACKED __packed__ + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __packed__ + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION union __packed__ + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + struct __packed__ T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #define __ALIGNED(x) __align(x) + #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif + + +/* + * COSMIC Compiler + */ +#elif defined ( __CSMC__ ) + #include + + #ifndef __ASM + #define __ASM _asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + // NO RETURN is automatically detected hence no warning here + #define __NO_RETURN + #endif + #ifndef __USED + #warning No compiler specific solution for __USED. __USED is ignored. + #define __USED + #endif + #ifndef __WEAK + #define __WEAK __weak + #endif + #ifndef __PACKED + #define __PACKED @packed + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT @packed struct + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION @packed union + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + @packed struct T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. + #define __ALIGNED(x) + #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif + + +#else + #error Unknown compiler. +#endif + + +#endif /* __CMSIS_COMPILER_H */ + diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_gcc.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_gcc.h new file mode 100644 index 0000000000..cd374afaef --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_gcc.h @@ -0,0 +1,2085 @@ +/**************************************************************************//** + * @file cmsis_gcc.h + * @brief CMSIS compiler GCC header file + * @version V5.0.4 + * @date 09. April 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_GCC_H +#define __CMSIS_GCC_H + +/* ignore some GCC warnings */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +/* Fallback for __has_builtin */ +#ifndef __has_builtin + #define __has_builtin(x) (0) +#endif + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __attribute__((__noreturn__)) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) :: "memory"); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) :: "memory"); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_FORCEINLINE uint32_t __get_FPSCR(void) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_get_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + return __builtin_arm_get_fpscr(); +#else + uint32_t result; + + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + return(result); +#endif +#else + return(0U); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_set_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + __builtin_arm_set_fpscr(fpscr); +#else + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory"); +#endif +#else + (void)fpscr; +#endif +} + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_RW_REG(r) "+l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_RW_REG(r) "+r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP() __ASM volatile ("nop") + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI() __ASM volatile ("wfi") + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE() __ASM volatile ("wfe") + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV() __ASM volatile ("sev") + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +__STATIC_FORCEINLINE void __ISB(void) +{ + __ASM volatile ("isb 0xF":::"memory"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__STATIC_FORCEINLINE void __DSB(void) +{ + __ASM volatile ("dsb 0xF":::"memory"); +} + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__STATIC_FORCEINLINE void __DMB(void) +{ + __ASM volatile ("dmb 0xF":::"memory"); +} + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +#endif +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE int16_t __REVSH(int16_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (int16_t)__builtin_bswap16(value); +#else + int16_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +#endif +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value != 0U; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return result; +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ (uint8_t)__builtin_clz + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +__STATIC_FORCEINLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +__extension__ \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ + __extension__ \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAEXB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaexb %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAEXH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaexh %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDAEX(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaex %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlexb %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlexh %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlex %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + +__STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#if 0 +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) +#endif + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#pragma GCC diagnostic pop + +#endif /* __CMSIS_GCC_H */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_iccarm.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_iccarm.h new file mode 100644 index 0000000000..11c4af0eba --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_iccarm.h @@ -0,0 +1,935 @@ +/**************************************************************************//** + * @file cmsis_iccarm.h + * @brief CMSIS compiler ICCARM (IAR Compiler for Arm) header file + * @version V5.0.7 + * @date 19. June 2018 + ******************************************************************************/ + +//------------------------------------------------------------------------------ +// +// Copyright (c) 2017-2018 IAR Systems +// +// Licensed under the Apache License, Version 2.0 (the "License") +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------ + + +#ifndef __CMSIS_ICCARM_H__ +#define __CMSIS_ICCARM_H__ + +#ifndef __ICCARM__ + #error This file should only be compiled by ICCARM +#endif + +#pragma system_include + +#define __IAR_FT _Pragma("inline=forced") __intrinsic + +#if (__VER__ >= 8000000) + #define __ICCARM_V8 1 +#else + #define __ICCARM_V8 0 +#endif + +#ifndef __ALIGNED + #if __ICCARM_V8 + #define __ALIGNED(x) __attribute__((aligned(x))) + #elif (__VER__ >= 7080000) + /* Needs IAR language extensions */ + #define __ALIGNED(x) __attribute__((aligned(x))) + #else + #warning No compiler specific solution for __ALIGNED.__ALIGNED is ignored. + #define __ALIGNED(x) + #endif +#endif + + +/* Define compiler macros for CPU architecture, used in CMSIS 5. + */ +#if __ARM_ARCH_6M__ || __ARM_ARCH_7M__ || __ARM_ARCH_7EM__ || __ARM_ARCH_8M_BASE__ || __ARM_ARCH_8M_MAIN__ +/* Macros already defined */ +#else + #if defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__) + #define __ARM_ARCH_8M_MAIN__ 1 + #elif defined(__ARM8M_BASELINE__) + #define __ARM_ARCH_8M_BASE__ 1 + #elif defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE == 'M' + #if __ARM_ARCH == 6 + #define __ARM_ARCH_6M__ 1 + #elif __ARM_ARCH == 7 + #if __ARM_FEATURE_DSP + #define __ARM_ARCH_7EM__ 1 + #else + #define __ARM_ARCH_7M__ 1 + #endif + #endif /* __ARM_ARCH */ + #endif /* __ARM_ARCH_PROFILE == 'M' */ +#endif + +/* Alternativ core deduction for older ICCARM's */ +#if !defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_7M__) && !defined(__ARM_ARCH_7EM__) && \ + !defined(__ARM_ARCH_8M_BASE__) && !defined(__ARM_ARCH_8M_MAIN__) + #if defined(__ARM6M__) && (__CORE__ == __ARM6M__) + #define __ARM_ARCH_6M__ 1 + #elif defined(__ARM7M__) && (__CORE__ == __ARM7M__) + #define __ARM_ARCH_7M__ 1 + #elif defined(__ARM7EM__) && (__CORE__ == __ARM7EM__) + #define __ARM_ARCH_7EM__ 1 + #elif defined(__ARM8M_BASELINE__) && (__CORE == __ARM8M_BASELINE__) + #define __ARM_ARCH_8M_BASE__ 1 + #elif defined(__ARM8M_MAINLINE__) && (__CORE == __ARM8M_MAINLINE__) + #define __ARM_ARCH_8M_MAIN__ 1 + #elif defined(__ARM8EM_MAINLINE__) && (__CORE == __ARM8EM_MAINLINE__) + #define __ARM_ARCH_8M_MAIN__ 1 + #else + #error "Unknown target." + #endif +#endif + + + +#if defined(__ARM_ARCH_6M__) && __ARM_ARCH_6M__==1 + #define __IAR_M0_FAMILY 1 +#elif defined(__ARM_ARCH_8M_BASE__) && __ARM_ARCH_8M_BASE__==1 + #define __IAR_M0_FAMILY 1 +#else + #define __IAR_M0_FAMILY 0 +#endif + + +#ifndef __ASM + #define __ASM __asm +#endif + +#ifndef __INLINE + #define __INLINE inline +#endif + +#ifndef __NO_RETURN + #if __ICCARM_V8 + #define __NO_RETURN __attribute__((__noreturn__)) + #else + #define __NO_RETURN _Pragma("object_attribute=__noreturn") + #endif +#endif + +#ifndef __PACKED + #if __ICCARM_V8 + #define __PACKED __attribute__((packed, aligned(1))) + #else + /* Needs IAR language extensions */ + #define __PACKED __packed + #endif +#endif + +#ifndef __PACKED_STRUCT + #if __ICCARM_V8 + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) + #else + /* Needs IAR language extensions */ + #define __PACKED_STRUCT __packed struct + #endif +#endif + +#ifndef __PACKED_UNION + #if __ICCARM_V8 + #define __PACKED_UNION union __attribute__((packed, aligned(1))) + #else + /* Needs IAR language extensions */ + #define __PACKED_UNION __packed union + #endif +#endif + +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif + +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline +#endif + +#ifndef __FORCEINLINE + #define __FORCEINLINE _Pragma("inline=forced") +#endif + +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __FORCEINLINE __STATIC_INLINE +#endif + +#ifndef __UNALIGNED_UINT16_READ +#pragma language=save +#pragma language=extended +__IAR_FT uint16_t __iar_uint16_read(void const *ptr) +{ + return *(__packed uint16_t*)(ptr); +} +#pragma language=restore +#define __UNALIGNED_UINT16_READ(PTR) __iar_uint16_read(PTR) +#endif + + +#ifndef __UNALIGNED_UINT16_WRITE +#pragma language=save +#pragma language=extended +__IAR_FT void __iar_uint16_write(void const *ptr, uint16_t val) +{ + *(__packed uint16_t*)(ptr) = val;; +} +#pragma language=restore +#define __UNALIGNED_UINT16_WRITE(PTR,VAL) __iar_uint16_write(PTR,VAL) +#endif + +#ifndef __UNALIGNED_UINT32_READ +#pragma language=save +#pragma language=extended +__IAR_FT uint32_t __iar_uint32_read(void const *ptr) +{ + return *(__packed uint32_t*)(ptr); +} +#pragma language=restore +#define __UNALIGNED_UINT32_READ(PTR) __iar_uint32_read(PTR) +#endif + +#ifndef __UNALIGNED_UINT32_WRITE +#pragma language=save +#pragma language=extended +__IAR_FT void __iar_uint32_write(void const *ptr, uint32_t val) +{ + *(__packed uint32_t*)(ptr) = val;; +} +#pragma language=restore +#define __UNALIGNED_UINT32_WRITE(PTR,VAL) __iar_uint32_write(PTR,VAL) +#endif + +#ifndef __UNALIGNED_UINT32 /* deprecated */ +#pragma language=save +#pragma language=extended +__packed struct __iar_u32 { uint32_t v; }; +#pragma language=restore +#define __UNALIGNED_UINT32(PTR) (((struct __iar_u32 *)(PTR))->v) +#endif + +#ifndef __USED + #if __ICCARM_V8 + #define __USED __attribute__((used)) + #else + #define __USED _Pragma("__root") + #endif +#endif + +#ifndef __WEAK + #if __ICCARM_V8 + #define __WEAK __attribute__((weak)) + #else + #define __WEAK _Pragma("__weak") + #endif +#endif + + +#ifndef __ICCARM_INTRINSICS_VERSION__ + #define __ICCARM_INTRINSICS_VERSION__ 0 +#endif + +#if __ICCARM_INTRINSICS_VERSION__ == 2 + + #if defined(__CLZ) + #undef __CLZ + #endif + #if defined(__REVSH) + #undef __REVSH + #endif + #if defined(__RBIT) + #undef __RBIT + #endif + #if defined(__SSAT) + #undef __SSAT + #endif + #if defined(__USAT) + #undef __USAT + #endif + + #include "iccarm_builtin.h" + + #define __disable_fault_irq __iar_builtin_disable_fiq + #define __disable_irq __iar_builtin_disable_interrupt + #define __enable_fault_irq __iar_builtin_enable_fiq + #define __enable_irq __iar_builtin_enable_interrupt + #define __arm_rsr __iar_builtin_rsr + #define __arm_wsr __iar_builtin_wsr + + + #define __get_APSR() (__arm_rsr("APSR")) + #define __get_BASEPRI() (__arm_rsr("BASEPRI")) + #define __get_CONTROL() (__arm_rsr("CONTROL")) + #define __get_FAULTMASK() (__arm_rsr("FAULTMASK")) + + #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) + #define __get_FPSCR() (__arm_rsr("FPSCR")) + #define __set_FPSCR(VALUE) (__arm_wsr("FPSCR", (VALUE))) + #else + #define __get_FPSCR() ( 0 ) + #define __set_FPSCR(VALUE) ((void)VALUE) + #endif + + #define __get_IPSR() (__arm_rsr("IPSR")) + #define __get_MSP() (__arm_rsr("MSP")) + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + #define __get_MSPLIM() (0U) + #else + #define __get_MSPLIM() (__arm_rsr("MSPLIM")) + #endif + #define __get_PRIMASK() (__arm_rsr("PRIMASK")) + #define __get_PSP() (__arm_rsr("PSP")) + + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + #define __get_PSPLIM() (0U) + #else + #define __get_PSPLIM() (__arm_rsr("PSPLIM")) + #endif + + #define __get_xPSR() (__arm_rsr("xPSR")) + + #define __set_BASEPRI(VALUE) (__arm_wsr("BASEPRI", (VALUE))) + #define __set_BASEPRI_MAX(VALUE) (__arm_wsr("BASEPRI_MAX", (VALUE))) + #define __set_CONTROL(VALUE) (__arm_wsr("CONTROL", (VALUE))) + #define __set_FAULTMASK(VALUE) (__arm_wsr("FAULTMASK", (VALUE))) + #define __set_MSP(VALUE) (__arm_wsr("MSP", (VALUE))) + + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + #define __set_MSPLIM(VALUE) ((void)(VALUE)) + #else + #define __set_MSPLIM(VALUE) (__arm_wsr("MSPLIM", (VALUE))) + #endif + #define __set_PRIMASK(VALUE) (__arm_wsr("PRIMASK", (VALUE))) + #define __set_PSP(VALUE) (__arm_wsr("PSP", (VALUE))) + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + #define __set_PSPLIM(VALUE) ((void)(VALUE)) + #else + #define __set_PSPLIM(VALUE) (__arm_wsr("PSPLIM", (VALUE))) + #endif + + #define __TZ_get_CONTROL_NS() (__arm_rsr("CONTROL_NS")) + #define __TZ_set_CONTROL_NS(VALUE) (__arm_wsr("CONTROL_NS", (VALUE))) + #define __TZ_get_PSP_NS() (__arm_rsr("PSP_NS")) + #define __TZ_set_PSP_NS(VALUE) (__arm_wsr("PSP_NS", (VALUE))) + #define __TZ_get_MSP_NS() (__arm_rsr("MSP_NS")) + #define __TZ_set_MSP_NS(VALUE) (__arm_wsr("MSP_NS", (VALUE))) + #define __TZ_get_SP_NS() (__arm_rsr("SP_NS")) + #define __TZ_set_SP_NS(VALUE) (__arm_wsr("SP_NS", (VALUE))) + #define __TZ_get_PRIMASK_NS() (__arm_rsr("PRIMASK_NS")) + #define __TZ_set_PRIMASK_NS(VALUE) (__arm_wsr("PRIMASK_NS", (VALUE))) + #define __TZ_get_BASEPRI_NS() (__arm_rsr("BASEPRI_NS")) + #define __TZ_set_BASEPRI_NS(VALUE) (__arm_wsr("BASEPRI_NS", (VALUE))) + #define __TZ_get_FAULTMASK_NS() (__arm_rsr("FAULTMASK_NS")) + #define __TZ_set_FAULTMASK_NS(VALUE)(__arm_wsr("FAULTMASK_NS", (VALUE))) + + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + #define __TZ_get_PSPLIM_NS() (0U) + #define __TZ_set_PSPLIM_NS(VALUE) ((void)(VALUE)) + #else + #define __TZ_get_PSPLIM_NS() (__arm_rsr("PSPLIM_NS")) + #define __TZ_set_PSPLIM_NS(VALUE) (__arm_wsr("PSPLIM_NS", (VALUE))) + #endif + + #define __TZ_get_MSPLIM_NS() (__arm_rsr("MSPLIM_NS")) + #define __TZ_set_MSPLIM_NS(VALUE) (__arm_wsr("MSPLIM_NS", (VALUE))) + + #define __NOP __iar_builtin_no_operation + + #define __CLZ __iar_builtin_CLZ + #define __CLREX __iar_builtin_CLREX + + #define __DMB __iar_builtin_DMB + #define __DSB __iar_builtin_DSB + #define __ISB __iar_builtin_ISB + + #define __LDREXB __iar_builtin_LDREXB + #define __LDREXH __iar_builtin_LDREXH + #define __LDREXW __iar_builtin_LDREX + + #define __RBIT __iar_builtin_RBIT + #define __REV __iar_builtin_REV + #define __REV16 __iar_builtin_REV16 + + __IAR_FT int16_t __REVSH(int16_t val) + { + return (int16_t) __iar_builtin_REVSH(val); + } + + #define __ROR __iar_builtin_ROR + #define __RRX __iar_builtin_RRX + + #define __SEV __iar_builtin_SEV + + #if !__IAR_M0_FAMILY + #define __SSAT __iar_builtin_SSAT + #endif + + #define __STREXB __iar_builtin_STREXB + #define __STREXH __iar_builtin_STREXH + #define __STREXW __iar_builtin_STREX + + #if !__IAR_M0_FAMILY + #define __USAT __iar_builtin_USAT + #endif + + #define __WFE __iar_builtin_WFE + #define __WFI __iar_builtin_WFI + + #if __ARM_MEDIA__ + #define __SADD8 __iar_builtin_SADD8 + #define __QADD8 __iar_builtin_QADD8 + #define __SHADD8 __iar_builtin_SHADD8 + #define __UADD8 __iar_builtin_UADD8 + #define __UQADD8 __iar_builtin_UQADD8 + #define __UHADD8 __iar_builtin_UHADD8 + #define __SSUB8 __iar_builtin_SSUB8 + #define __QSUB8 __iar_builtin_QSUB8 + #define __SHSUB8 __iar_builtin_SHSUB8 + #define __USUB8 __iar_builtin_USUB8 + #define __UQSUB8 __iar_builtin_UQSUB8 + #define __UHSUB8 __iar_builtin_UHSUB8 + #define __SADD16 __iar_builtin_SADD16 + #define __QADD16 __iar_builtin_QADD16 + #define __SHADD16 __iar_builtin_SHADD16 + #define __UADD16 __iar_builtin_UADD16 + #define __UQADD16 __iar_builtin_UQADD16 + #define __UHADD16 __iar_builtin_UHADD16 + #define __SSUB16 __iar_builtin_SSUB16 + #define __QSUB16 __iar_builtin_QSUB16 + #define __SHSUB16 __iar_builtin_SHSUB16 + #define __USUB16 __iar_builtin_USUB16 + #define __UQSUB16 __iar_builtin_UQSUB16 + #define __UHSUB16 __iar_builtin_UHSUB16 + #define __SASX __iar_builtin_SASX + #define __QASX __iar_builtin_QASX + #define __SHASX __iar_builtin_SHASX + #define __UASX __iar_builtin_UASX + #define __UQASX __iar_builtin_UQASX + #define __UHASX __iar_builtin_UHASX + #define __SSAX __iar_builtin_SSAX + #define __QSAX __iar_builtin_QSAX + #define __SHSAX __iar_builtin_SHSAX + #define __USAX __iar_builtin_USAX + #define __UQSAX __iar_builtin_UQSAX + #define __UHSAX __iar_builtin_UHSAX + #define __USAD8 __iar_builtin_USAD8 + #define __USADA8 __iar_builtin_USADA8 + #define __SSAT16 __iar_builtin_SSAT16 + #define __USAT16 __iar_builtin_USAT16 + #define __UXTB16 __iar_builtin_UXTB16 + #define __UXTAB16 __iar_builtin_UXTAB16 + #define __SXTB16 __iar_builtin_SXTB16 + #define __SXTAB16 __iar_builtin_SXTAB16 + #define __SMUAD __iar_builtin_SMUAD + #define __SMUADX __iar_builtin_SMUADX + #define __SMMLA __iar_builtin_SMMLA + #define __SMLAD __iar_builtin_SMLAD + #define __SMLADX __iar_builtin_SMLADX + #define __SMLALD __iar_builtin_SMLALD + #define __SMLALDX __iar_builtin_SMLALDX + #define __SMUSD __iar_builtin_SMUSD + #define __SMUSDX __iar_builtin_SMUSDX + #define __SMLSD __iar_builtin_SMLSD + #define __SMLSDX __iar_builtin_SMLSDX + #define __SMLSLD __iar_builtin_SMLSLD + #define __SMLSLDX __iar_builtin_SMLSLDX + #define __SEL __iar_builtin_SEL + #define __QADD __iar_builtin_QADD + #define __QSUB __iar_builtin_QSUB + #define __PKHBT __iar_builtin_PKHBT + #define __PKHTB __iar_builtin_PKHTB + #endif + +#else /* __ICCARM_INTRINSICS_VERSION__ == 2 */ + + #if __IAR_M0_FAMILY + /* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */ + #define __CLZ __cmsis_iar_clz_not_active + #define __SSAT __cmsis_iar_ssat_not_active + #define __USAT __cmsis_iar_usat_not_active + #define __RBIT __cmsis_iar_rbit_not_active + #define __get_APSR __cmsis_iar_get_APSR_not_active + #endif + + + #if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) )) + #define __get_FPSCR __cmsis_iar_get_FPSR_not_active + #define __set_FPSCR __cmsis_iar_set_FPSR_not_active + #endif + + #ifdef __INTRINSICS_INCLUDED + #error intrinsics.h is already included previously! + #endif + + #include + + #if __IAR_M0_FAMILY + /* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */ + #undef __CLZ + #undef __SSAT + #undef __USAT + #undef __RBIT + #undef __get_APSR + + __STATIC_INLINE uint8_t __CLZ(uint32_t data) + { + if (data == 0U) { return 32U; } + + uint32_t count = 0U; + uint32_t mask = 0x80000000U; + + while ((data & mask) == 0U) + { + count += 1U; + mask = mask >> 1U; + } + return count; + } + + __STATIC_INLINE uint32_t __RBIT(uint32_t v) + { + uint8_t sc = 31U; + uint32_t r = v; + for (v >>= 1U; v; v >>= 1U) + { + r <<= 1U; + r |= v & 1U; + sc--; + } + return (r << sc); + } + + __STATIC_INLINE uint32_t __get_APSR(void) + { + uint32_t res; + __asm("MRS %0,APSR" : "=r" (res)); + return res; + } + + #endif + + #if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) )) + #undef __get_FPSCR + #undef __set_FPSCR + #define __get_FPSCR() (0) + #define __set_FPSCR(VALUE) ((void)VALUE) + #endif + + #pragma diag_suppress=Pe940 + #pragma diag_suppress=Pe177 + + #define __enable_irq __enable_interrupt + #define __disable_irq __disable_interrupt + #define __NOP __no_operation + + #define __get_xPSR __get_PSR + + #if (!defined(__ARM_ARCH_6M__) || __ARM_ARCH_6M__==0) + + __IAR_FT uint32_t __LDREXW(uint32_t volatile *ptr) + { + return __LDREX((unsigned long *)ptr); + } + + __IAR_FT uint32_t __STREXW(uint32_t value, uint32_t volatile *ptr) + { + return __STREX(value, (unsigned long *)ptr); + } + #endif + + + /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */ + #if (__CORTEX_M >= 0x03) + + __IAR_FT uint32_t __RRX(uint32_t value) + { + uint32_t result; + __ASM("RRX %0, %1" : "=r"(result) : "r" (value) : "cc"); + return(result); + } + + __IAR_FT void __set_BASEPRI_MAX(uint32_t value) + { + __asm volatile("MSR BASEPRI_MAX,%0"::"r" (value)); + } + + + #define __enable_fault_irq __enable_fiq + #define __disable_fault_irq __disable_fiq + + + #endif /* (__CORTEX_M >= 0x03) */ + + __IAR_FT uint32_t __ROR(uint32_t op1, uint32_t op2) + { + return (op1 >> op2) | (op1 << ((sizeof(op1)*8)-op2)); + } + + #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + + __IAR_FT uint32_t __get_MSPLIM(void) + { + uint32_t res; + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + res = 0U; + #else + __asm volatile("MRS %0,MSPLIM" : "=r" (res)); + #endif + return res; + } + + __IAR_FT void __set_MSPLIM(uint32_t value) + { + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)value; + #else + __asm volatile("MSR MSPLIM,%0" :: "r" (value)); + #endif + } + + __IAR_FT uint32_t __get_PSPLIM(void) + { + uint32_t res; + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + res = 0U; + #else + __asm volatile("MRS %0,PSPLIM" : "=r" (res)); + #endif + return res; + } + + __IAR_FT void __set_PSPLIM(uint32_t value) + { + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)value; + #else + __asm volatile("MSR PSPLIM,%0" :: "r" (value)); + #endif + } + + __IAR_FT uint32_t __TZ_get_CONTROL_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,CONTROL_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_CONTROL_NS(uint32_t value) + { + __asm volatile("MSR CONTROL_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_PSP_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,PSP_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_PSP_NS(uint32_t value) + { + __asm volatile("MSR PSP_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_MSP_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,MSP_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_MSP_NS(uint32_t value) + { + __asm volatile("MSR MSP_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_SP_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,SP_NS" : "=r" (res)); + return res; + } + __IAR_FT void __TZ_set_SP_NS(uint32_t value) + { + __asm volatile("MSR SP_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_PRIMASK_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,PRIMASK_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_PRIMASK_NS(uint32_t value) + { + __asm volatile("MSR PRIMASK_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_BASEPRI_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,BASEPRI_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_BASEPRI_NS(uint32_t value) + { + __asm volatile("MSR BASEPRI_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_FAULTMASK_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,FAULTMASK_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_FAULTMASK_NS(uint32_t value) + { + __asm volatile("MSR FAULTMASK_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_PSPLIM_NS(void) + { + uint32_t res; + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + res = 0U; + #else + __asm volatile("MRS %0,PSPLIM_NS" : "=r" (res)); + #endif + return res; + } + + __IAR_FT void __TZ_set_PSPLIM_NS(uint32_t value) + { + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)value; + #else + __asm volatile("MSR PSPLIM_NS,%0" :: "r" (value)); + #endif + } + + __IAR_FT uint32_t __TZ_get_MSPLIM_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,MSPLIM_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_MSPLIM_NS(uint32_t value) + { + __asm volatile("MSR MSPLIM_NS,%0" :: "r" (value)); + } + + #endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */ + +#endif /* __ICCARM_INTRINSICS_VERSION__ == 2 */ + +#define __BKPT(value) __asm volatile ("BKPT %0" : : "i"(value)) + +#if __IAR_M0_FAMILY + __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat) + { + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; + } + + __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat) + { + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; + } +#endif + +#if (__CORTEX_M >= 0x03) /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */ + + __IAR_FT uint8_t __LDRBT(volatile uint8_t *addr) + { + uint32_t res; + __ASM("LDRBT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); + return ((uint8_t)res); + } + + __IAR_FT uint16_t __LDRHT(volatile uint16_t *addr) + { + uint32_t res; + __ASM("LDRHT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); + return ((uint16_t)res); + } + + __IAR_FT uint32_t __LDRT(volatile uint32_t *addr) + { + uint32_t res; + __ASM("LDRT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); + return res; + } + + __IAR_FT void __STRBT(uint8_t value, volatile uint8_t *addr) + { + __ASM("STRBT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory"); + } + + __IAR_FT void __STRHT(uint16_t value, volatile uint16_t *addr) + { + __ASM("STRHT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory"); + } + + __IAR_FT void __STRT(uint32_t value, volatile uint32_t *addr) + { + __ASM("STRT %1, [%0]" : : "r" (addr), "r" (value) : "memory"); + } + +#endif /* (__CORTEX_M >= 0x03) */ + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + + + __IAR_FT uint8_t __LDAB(volatile uint8_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint8_t)res); + } + + __IAR_FT uint16_t __LDAH(volatile uint16_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint16_t)res); + } + + __IAR_FT uint32_t __LDA(volatile uint32_t *ptr) + { + uint32_t res; + __ASM volatile ("LDA %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return res; + } + + __IAR_FT void __STLB(uint8_t value, volatile uint8_t *ptr) + { + __ASM volatile ("STLB %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); + } + + __IAR_FT void __STLH(uint16_t value, volatile uint16_t *ptr) + { + __ASM volatile ("STLH %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); + } + + __IAR_FT void __STL(uint32_t value, volatile uint32_t *ptr) + { + __ASM volatile ("STL %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); + } + + __IAR_FT uint8_t __LDAEXB(volatile uint8_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAEXB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint8_t)res); + } + + __IAR_FT uint16_t __LDAEXH(volatile uint16_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAEXH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint16_t)res); + } + + __IAR_FT uint32_t __LDAEX(volatile uint32_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAEX %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return res; + } + + __IAR_FT uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) + { + uint32_t res; + __ASM volatile ("STLEXB %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); + return res; + } + + __IAR_FT uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) + { + uint32_t res; + __ASM volatile ("STLEXH %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); + return res; + } + + __IAR_FT uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) + { + uint32_t res; + __ASM volatile ("STLEX %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); + return res; + } + +#endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */ + +#undef __IAR_FT +#undef __IAR_M0_FAMILY +#undef __ICCARM_V8 + +#pragma diag_default=Pe940 +#pragma diag_default=Pe177 + +#endif /* __CMSIS_ICCARM_H__ */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_version.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_version.h new file mode 100644 index 0000000000..660f612aa3 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cmsis_version.h @@ -0,0 +1,39 @@ +/**************************************************************************//** + * @file cmsis_version.h + * @brief CMSIS Core(M) Version definitions + * @version V5.0.2 + * @date 19. April 2017 + ******************************************************************************/ +/* + * Copyright (c) 2009-2017 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CMSIS_VERSION_H +#define __CMSIS_VERSION_H + +/* CMSIS Version definitions */ +#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ +#define __CM_CMSIS_VERSION_SUB ( 1U) /*!< [15:0] CMSIS Core(M) sub version */ +#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ + __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_adc.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_adc.h new file mode 100644 index 0000000000..a7ce0bb88d --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_adc.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_ADC_H__ +#define __CORE_ADC_H__ +#define ADC_VALUE_ERROR (0xffffffff) +void ADC_GlobalInit(void); +/** + * @brief 通道开关,在globalinit时只打开了0,0也无法被关闭,目前已经废弃,ADC_GetChannelValue的时候临时打开 + * + * @param Channel 通道号 + * @param OnOff 开关 + */ +void ADC_ChannelOnOff(uint8_t Channel, uint8_t OnOff); +/** + * @brief 获取通道的原始ADC值,12bit,1.8V参考电压,通道0内部9:5分压,其他关闭 + * + * @param Channel 通道号 + * @return != ADC_VALUE_ERROR 为有效值 + */ +uint32_t ADC_GetChannelValue(uint8_t Channel); +/** + * @brief 开关内部分压,1~5都是1:1 6就不确定了,手册和demo不一致 + * + * @param OnOff 开关 + */ +void ADC_IntelResistance(uint8_t OnOff); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_armv8mbl.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_armv8mbl.h new file mode 100644 index 0000000000..251e4ede3a --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_armv8mbl.h @@ -0,0 +1,1918 @@ +/**************************************************************************//** + * @file core_armv8mbl.h + * @brief CMSIS Armv8-M Baseline Core Peripheral Access Layer Header File + * @version V5.0.7 + * @date 22. June 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_ARMV8MBL_H_GENERIC +#define __CORE_ARMV8MBL_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_ARMv8MBL + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS definitions */ +#define __ARMv8MBL_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __ARMv8MBL_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __ARMv8MBL_CMSIS_VERSION ((__ARMv8MBL_CMSIS_VERSION_MAIN << 16U) | \ + __ARMv8MBL_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M ( 2U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_ARMV8MBL_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_ARMV8MBL_H_DEPENDANT +#define __CORE_ARMV8MBL_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __ARMv8MBL_REV + #define __ARMv8MBL_REV 0x0000U + #warning "__ARMv8MBL_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __SAUREGION_PRESENT + #define __SAUREGION_PRESENT 0U + #warning "__SAUREGION_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __VTOR_PRESENT + #define __VTOR_PRESENT 0U + #warning "__VTOR_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif + + #ifndef __ETM_PRESENT + #define __ETM_PRESENT 0U + #warning "__ETM_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MTB_PRESENT + #define __MTB_PRESENT 0U + #warning "__MTB_PRESENT not defined in device header file; using default!" + #endif + +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group ARMv8MBL */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core SAU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[16U]; + __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[16U]; + __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[16U]; + __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[16U]; + __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[16U]; + __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ + uint32_t RESERVED5[16U]; + __IOM uint32_t IPR[124U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ +#else + uint32_t RESERVED0; +#endif + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHPR[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ +#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ + +#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ +#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ + +#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ +#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ +#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ +#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ + +#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ +#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ + +#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ +#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ +#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ + +#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ +#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ +#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ +#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ + +#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ +#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + uint32_t RESERVED0[6U]; + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + uint32_t RESERVED3[1U]; + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED4[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + uint32_t RESERVED5[1U]; + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED6[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + uint32_t RESERVED7[1U]; + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED8[1U]; + __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ + uint32_t RESERVED9[1U]; + __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ + uint32_t RESERVED10[1U]; + __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ + uint32_t RESERVED11[1U]; + __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ + uint32_t RESERVED12[1U]; + __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ + uint32_t RESERVED13[1U]; + __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ + uint32_t RESERVED14[1U]; + __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ + uint32_t RESERVED15[1U]; + __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ + uint32_t RESERVED16[1U]; + __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ + uint32_t RESERVED17[1U]; + __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ + uint32_t RESERVED18[1U]; + __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ + uint32_t RESERVED19[1U]; + __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ + uint32_t RESERVED20[1U]; + __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ + uint32_t RESERVED21[1U]; + __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ + uint32_t RESERVED22[1U]; + __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ + uint32_t RESERVED23[1U]; + __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ + uint32_t RESERVED24[1U]; + __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ + uint32_t RESERVED25[1U]; + __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ + uint32_t RESERVED26[1U]; + __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ + uint32_t RESERVED27[1U]; + __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ + uint32_t RESERVED28[1U]; + __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ + uint32_t RESERVED29[1U]; + __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ + uint32_t RESERVED30[1U]; + __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ + uint32_t RESERVED31[1U]; + __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ +#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ + +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ +#define DWT_FUNCTION_ACTION_Msk (0x3UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ + +#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ +#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Sizes Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Sizes Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */ + uint32_t RESERVED3[809U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) Software Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) Software Lock Status Register */ + uint32_t RESERVED4[4U]; + __IM uint32_t TYPE; /*!< Offset: 0xFC8 (R/ ) Device Identifier Register */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Register */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_SWOSCALER_Pos 0U /*!< TPI ACPR: SWOSCALER Position */ +#define TPI_ACPR_SWOSCALER_Msk (0xFFFFUL /*<< TPI_ACPR_SWOSCALER_Pos*/) /*!< TPI ACPR: SWOSCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */ +#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI Periodic Synchronization Control Register Definitions */ +#define TPI_PSCR_PSCount_Pos 0U /*!< TPI PSCR: PSCount Position */ +#define TPI_PSCR_PSCount_Msk (0x1FUL /*<< TPI_PSCR_PSCount_Pos*/) /*!< TPI PSCR: TPSCount Mask */ + +/* TPI Software Lock Status Register Definitions */ +#define TPI_LSR_nTT_Pos 1U /*!< TPI LSR: Not thirty-two bit. Position */ +#define TPI_LSR_nTT_Msk (0x1UL << TPI_LSR_nTT_Pos) /*!< TPI LSR: Not thirty-two bit. Mask */ + +#define TPI_LSR_SLK_Pos 1U /*!< TPI LSR: Software Lock status Position */ +#define TPI_LSR_SLK_Msk (0x1UL << TPI_LSR_SLK_Pos) /*!< TPI LSR: Software Lock status Mask */ + +#define TPI_LSR_SLI_Pos 0U /*!< TPI LSR: Software Lock implemented Position */ +#define TPI_LSR_SLI_Msk (0x1UL /*<< TPI_LSR_SLI_Pos*/) /*!< TPI LSR: Software Lock implemented Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFO depth Position */ +#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFO depth Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ + uint32_t RESERVED0[7U]; + union { + __IOM uint32_t MAIR[2]; + struct { + __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ + __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ + }; + }; +} MPU_Type; + +#define MPU_TYPE_RALIASES 1U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */ +#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */ + +#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ +#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ + +#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ +#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ + +#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ +#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ + +/* MPU Region Limit Address Register Definitions */ +#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ +#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ + +#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ +#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ + +#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: EN Position */ +#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: EN Mask */ + +/* MPU Memory Attribute Indirection Register 0 Definitions */ +#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ +#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ + +#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ +#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ + +#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ +#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ + +#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ +#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ + +/* MPU Memory Attribute Indirection Register 1 Definitions */ +#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ +#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ + +#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ +#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ + +#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ +#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ + +#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ +#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SAU Security Attribution Unit (SAU) + \brief Type definitions for the Security Attribution Unit (SAU) + @{ + */ + +/** + \brief Structure type to access the Security Attribution Unit (SAU). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ + __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ +#endif +} SAU_Type; + +/* SAU Control Register Definitions */ +#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ +#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ + +#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ +#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ + +/* SAU Type Register Definitions */ +#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ +#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ + +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) +/* SAU Region Number Register Definitions */ +#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ +#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ + +/* SAU Region Base Address Register Definitions */ +#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ +#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ + +/* SAU Region Limit Address Register Definitions */ +#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ +#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ + +#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ +#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ + +#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ +#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ + +#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ + +/*@} end of group CMSIS_SAU */ +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + uint32_t RESERVED4[1U]; + __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ + __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ +#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register */ +#define CoreDebug_DEMCR_DWTENA_Pos 24U /*!< CoreDebug DEMCR: DWTENA Position */ +#define CoreDebug_DEMCR_DWTENA_Msk (1UL << CoreDebug_DEMCR_DWTENA_Pos) /*!< CoreDebug DEMCR: DWTENA Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/* Debug Authentication Control Register Definitions */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ + +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ + +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ + +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ + +/* Debug Security Control and Status Register Definitions */ +#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ +#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ + +#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ +#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ + +#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ +#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ + #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ + #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ + #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ + #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ + #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ + #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ + #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + + + #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ + #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ + #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ + #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ + #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ + #endif + + #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ + #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ + #endif + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ + #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ + #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ + #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ + #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ + + #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ + #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ + #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ + #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ + #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ + #endif + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* Special LR values for Secure/Non-Secure call handling and exception handling */ + +/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */ +#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */ + +/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */ +#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */ +#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */ +#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */ +#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ +#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */ +#define EXC_RETURN_SPSEL (0x00000002UL) /* bit [1] stack pointer used to restore context: 0=MSP 1=PSP */ +#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */ + +/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */ +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */ +#else +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */ +#endif + + +/* Interrupt Priorities are WORD accessible only under Armv6-M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + +#define __NVIC_SetPriorityGrouping(X) (void)(X) +#define __NVIC_GetPriorityGrouping() (0U) + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Interrupt Target State + \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + \return 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Target State + \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Clear Interrupt Target State + \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((SCB->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + If VTOR is not present address 0 must be mapped to SRAM. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + uint32_t *vectors = (uint32_t *)SCB->VTOR; +#else + uint32_t *vectors = (uint32_t *)0x0U; +#endif + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + uint32_t *vectors = (uint32_t *)SCB->VTOR; +#else + uint32_t *vectors = (uint32_t *)0x0U; +#endif + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Enable Interrupt (non-secure) + \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status (non-secure) + \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt (non-secure) + \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Pending Interrupt (non-secure) + \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt (non-secure) + \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt (non-secure) + \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt (non-secure) + \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority (non-secure) + \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every non-secure processor exception. + */ +__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC_NS->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB_NS->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB_NS->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority (non-secure) + \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((SCB_NS->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv8.h" + +#endif + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## SAU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SAUFunctions SAU Functions + \brief Functions that configure the SAU. + @{ + */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + +/** + \brief Enable SAU + \details Enables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Enable(void) +{ + SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); +} + + + +/** + \brief Disable SAU + \details Disables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Disable(void) +{ + SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); +} + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_SAUFunctions */ + + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief System Tick Configuration (non-secure) + \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function TZ_SysTick_Config_NS is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_ARMV8MBL_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_armv8mml.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_armv8mml.h new file mode 100644 index 0000000000..3a3148ea31 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_armv8mml.h @@ -0,0 +1,2927 @@ +/**************************************************************************//** + * @file core_armv8mml.h + * @brief CMSIS Armv8-M Mainline Core Peripheral Access Layer Header File + * @version V5.0.7 + * @date 06. July 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_ARMV8MML_H_GENERIC +#define __CORE_ARMV8MML_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_ARMv8MML + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS Armv8MML definitions */ +#define __ARMv8MML_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __ARMv8MML_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __ARMv8MML_CMSIS_VERSION ((__ARMv8MML_CMSIS_VERSION_MAIN << 16U) | \ + __ARMv8MML_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (81U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_ARMV8MML_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_ARMV8MML_H_DEPENDANT +#define __CORE_ARMV8MML_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __ARMv8MML_REV + #define __ARMv8MML_REV 0x0000U + #warning "__ARMv8MML_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __SAUREGION_PRESENT + #define __SAUREGION_PRESENT 0U + #warning "__SAUREGION_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DSP_PRESENT + #define __DSP_PRESENT 0U + #warning "__DSP_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group ARMv8MML */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core SAU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ + uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */ + uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */ + uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */ +#define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */ + +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[16U]; + __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[16U]; + __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[16U]; + __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[16U]; + __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[16U]; + __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ + uint32_t RESERVED5[16U]; + __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED6[580U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */ + uint32_t RESERVED3[92U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ + uint32_t RESERVED7[6U]; + __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ + __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ + __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ + __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ + __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ + uint32_t RESERVED8[1U]; + __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ +#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ + +#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ +#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ + +#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ +#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ +#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ +#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ + +#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ +#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ +#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ +#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ + +#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ +#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ +#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */ +#define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */ +#define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */ + +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ +#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ + +#define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */ +#define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ +#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */ +#define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/* SCB Non-Secure Access Control Register Definitions */ +#define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */ +#define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */ + +#define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */ +#define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */ + +#define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */ +#define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */ + +/* SCB Cache Level ID Register Definitions */ +#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ +#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ + +#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ +#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ + +/* SCB Cache Type Register Definitions */ +#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ +#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ + +#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ +#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ + +#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ +#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ + +#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ +#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ + +#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ +#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ + +/* SCB Cache Size ID Register Definitions */ +#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ +#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ + +#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ +#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ + +#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ +#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ + +#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ +#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ + +#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ +#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ + +#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ +#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ + +#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ +#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ + +/* SCB Cache Size Selection Register Definitions */ +#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ +#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ + +#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ +#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ + +/* SCB Software Triggered Interrupt Register Definitions */ +#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ +#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ + +/* SCB D-Cache Invalidate by Set-way Register Definitions */ +#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ +#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ + +#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ +#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ + +/* SCB D-Cache Clean by Set-way Register Definitions */ +#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ +#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ + +#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ +#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ + +/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ +#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ +#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ + +#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ +#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ + +/* Instruction Tightly-Coupled Memory Control Register Definitions */ +#define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */ +#define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */ + +#define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */ +#define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */ + +#define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */ +#define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */ + +#define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */ +#define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */ + +/* Data Tightly-Coupled Memory Control Register Definitions */ +#define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */ +#define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */ + +#define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */ +#define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */ + +#define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */ +#define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */ + +#define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */ +#define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */ + +/* AHBP Control Register Definitions */ +#define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */ +#define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */ + +#define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */ +#define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */ + +/* L1 Cache Control Register Definitions */ +#define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */ +#define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */ + +#define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */ +#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */ + +#define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */ +#define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */ + +/* AHBS Control Register Definitions */ +#define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */ +#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */ + +#define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */ +#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */ + +#define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/ +#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */ + +/* Auxiliary Bus Fault Status Register Definitions */ +#define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/ +#define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */ + +#define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/ +#define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */ + +#define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/ +#define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */ + +#define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/ +#define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */ + +#define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/ +#define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */ + +#define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/ +#define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ + __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */ + uint32_t RESERVED6[4U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Stimulus Port Register Definitions */ +#define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */ +#define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */ + +#define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */ +#define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */ + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */ +#define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */ + +#define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */ +#define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + uint32_t RESERVED3[1U]; + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED4[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + uint32_t RESERVED5[1U]; + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED6[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + uint32_t RESERVED7[1U]; + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED8[1U]; + __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ + uint32_t RESERVED9[1U]; + __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ + uint32_t RESERVED10[1U]; + __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ + uint32_t RESERVED11[1U]; + __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ + uint32_t RESERVED12[1U]; + __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ + uint32_t RESERVED13[1U]; + __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ + uint32_t RESERVED14[1U]; + __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ + uint32_t RESERVED15[1U]; + __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ + uint32_t RESERVED16[1U]; + __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ + uint32_t RESERVED17[1U]; + __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ + uint32_t RESERVED18[1U]; + __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ + uint32_t RESERVED19[1U]; + __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ + uint32_t RESERVED20[1U]; + __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ + uint32_t RESERVED21[1U]; + __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ + uint32_t RESERVED22[1U]; + __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ + uint32_t RESERVED23[1U]; + __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ + uint32_t RESERVED24[1U]; + __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ + uint32_t RESERVED25[1U]; + __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ + uint32_t RESERVED26[1U]; + __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ + uint32_t RESERVED27[1U]; + __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ + uint32_t RESERVED28[1U]; + __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ + uint32_t RESERVED29[1U]; + __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ + uint32_t RESERVED30[1U]; + __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ + uint32_t RESERVED31[1U]; + __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ + uint32_t RESERVED32[934U]; + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ + uint32_t RESERVED33[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */ +#define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ +#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ + +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ +#define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ + +#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ +#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Sizes Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Sizes Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */ + uint32_t RESERVED3[809U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) Software Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) Software Lock Status Register */ + uint32_t RESERVED4[4U]; + __IM uint32_t TYPE; /*!< Offset: 0xFC8 (R/ ) Device Identifier Register */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Register */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_SWOSCALER_Pos 0U /*!< TPI ACPR: SWOSCALER Position */ +#define TPI_ACPR_SWOSCALER_Msk (0xFFFFUL /*<< TPI_ACPR_SWOSCALER_Pos*/) /*!< TPI ACPR: SWOSCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */ +#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI Periodic Synchronization Control Register Definitions */ +#define TPI_PSCR_PSCount_Pos 0U /*!< TPI PSCR: PSCount Position */ +#define TPI_PSCR_PSCount_Msk (0x1FUL /*<< TPI_PSCR_PSCount_Pos*/) /*!< TPI PSCR: TPSCount Mask */ + +/* TPI Software Lock Status Register Definitions */ +#define TPI_LSR_nTT_Pos 1U /*!< TPI LSR: Not thirty-two bit. Position */ +#define TPI_LSR_nTT_Msk (0x1UL << TPI_LSR_nTT_Pos) /*!< TPI LSR: Not thirty-two bit. Mask */ + +#define TPI_LSR_SLK_Pos 1U /*!< TPI LSR: Software Lock status Position */ +#define TPI_LSR_SLK_Msk (0x1UL << TPI_LSR_SLK_Pos) /*!< TPI LSR: Software Lock status Mask */ + +#define TPI_LSR_SLI_Pos 0U /*!< TPI LSR: Software Lock implemented Position */ +#define TPI_LSR_SLI_Msk (0x1UL /*<< TPI_LSR_SLI_Pos*/) /*!< TPI LSR: Software Lock implemented Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFO depth Position */ +#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFO depth Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */ + __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */ + __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */ + __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */ + uint32_t RESERVED0[1]; + union { + __IOM uint32_t MAIR[2]; + struct { + __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ + __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ + }; + }; +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */ +#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */ + +#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ +#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ + +#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ +#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ + +#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ +#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ + +/* MPU Region Limit Address Register Definitions */ +#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ +#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ + +#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ +#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ + +#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */ +#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */ + +/* MPU Memory Attribute Indirection Register 0 Definitions */ +#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ +#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ + +#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ +#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ + +#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ +#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ + +#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ +#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ + +/* MPU Memory Attribute Indirection Register 1 Definitions */ +#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ +#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ + +#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ +#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ + +#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ +#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ + +#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ +#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SAU Security Attribution Unit (SAU) + \brief Type definitions for the Security Attribution Unit (SAU) + @{ + */ + +/** + \brief Structure type to access the Security Attribution Unit (SAU). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ + __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ +#else + uint32_t RESERVED0[3]; +#endif + __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */ + __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */ +} SAU_Type; + +/* SAU Control Register Definitions */ +#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ +#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ + +#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ +#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ + +/* SAU Type Register Definitions */ +#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ +#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ + +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) +/* SAU Region Number Register Definitions */ +#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ +#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ + +/* SAU Region Base Address Register Definitions */ +#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ +#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ + +/* SAU Region Limit Address Register Definitions */ +#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ +#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ + +#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ +#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ + +#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ +#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ + +#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ + +/* Secure Fault Status Register Definitions */ +#define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */ +#define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */ + +#define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */ +#define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */ + +#define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */ +#define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */ + +#define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */ +#define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */ + +#define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */ +#define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */ + +#define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */ +#define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */ + +#define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */ +#define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */ + +#define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */ +#define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */ + +/*@} end of group CMSIS_SAU */ +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */ +#define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */ + +#define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */ +#define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */ + +#define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */ +#define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */ + +#define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */ +#define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */ + +#define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */ +#define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */ + +#define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */ +#define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */ +#define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */ +#define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + uint32_t RESERVED4[1U]; + __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ + __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ +#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/* Debug Authentication Control Register Definitions */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ + +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ + +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ + +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ + +/* Debug Security Control and Status Register Definitions */ +#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ +#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ + +#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ +#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ + +#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ +#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ + #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ + #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ + #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ + #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ + #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ + #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ + #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ + #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + + #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ + #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ + #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ + #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ + #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ + #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ + #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ + #endif + + #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ + #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ + #endif + + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ + #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ + #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ + #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ + #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ + + #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */ + #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ + #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ + #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ + #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ + #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ + #endif + + #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */ + #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */ + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* Special LR values for Secure/Non-Secure call handling and exception handling */ + +/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */ +#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */ + +/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */ +#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */ +#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */ +#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */ +#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ +#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */ +#define EXC_RETURN_SPSEL (0x00000002UL) /* bit [1] stack pointer used to restore context: 0=MSP 1=PSP */ +#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */ + +/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */ +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */ +#else +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */ +#endif + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Interrupt Target State + \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + \return 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Target State + \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Clear Interrupt Target State + \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Priority Grouping (non-secure) + \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB_NS->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB_NS->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping (non-secure) + \details Reads the priority grouping field from the non-secure NVIC when in secure state. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void) +{ + return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt (non-secure) + \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status (non-secure) + \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt (non-secure) + \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Pending Interrupt (non-secure) + \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt (non-secure) + \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt (non-secure) + \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt (non-secure) + \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority (non-secure) + \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every non-secure processor exception. + */ +__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority (non-secure) + \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv8.h" + +#endif + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) + { + return 2U; /* Double + Single precision FPU */ + } + else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## SAU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SAUFunctions SAU Functions + \brief Functions that configure the SAU. + @{ + */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + +/** + \brief Enable SAU + \details Enables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Enable(void) +{ + SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); +} + + + +/** + \brief Disable SAU + \details Disables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Disable(void) +{ + SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); +} + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_SAUFunctions */ + + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief System Tick Configuration (non-secure) + \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function TZ_SysTick_Config_NS is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_ARMV8MML_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_cm4.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_cm4.h new file mode 100644 index 0000000000..7d56873532 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_cm4.h @@ -0,0 +1,2129 @@ +/**************************************************************************//** + * @file core_cm4.h + * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File + * @version V5.0.8 + * @date 04. June 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM4_H_GENERIC +#define __CORE_CM4_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M4 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM4 definitions */ +#define __CM4_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM4_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \ + __CM4_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (4U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM4_H_DEPENDANT +#define __CORE_CM4_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM4_REV + #define __CM4_REV 0x0000U + #warning "__CM4_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M4 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */ +#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ + +#define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */ +#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ +#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ +#define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */ + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_cmFunc.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_cmFunc.h new file mode 100644 index 0000000000..652a48af07 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_cmFunc.h @@ -0,0 +1,87 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 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 */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ +*/ + +/*------------------ RealView Compiler -----------------*/ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + +/*------------------ ARM Compiler V6 -------------------*/ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armcc_V6.h" + +/*------------------ GNU Compiler ----------------------*/ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + +/*------------------ ICC Compiler ----------------------*/ +#elif defined ( __ICCARM__ ) + #include + +/*------------------ TI CCS Compiler -------------------*/ +#elif defined ( __TMS470__ ) + #include + +/*------------------ TASKING Compiler ------------------*/ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +/*------------------ COSMIC Compiler -------------------*/ +#elif defined ( __CSMC__ ) + #include + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + +#endif /* __CORE_CMFUNC_H */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_cmInstr.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_cmInstr.h new file mode 100644 index 0000000000..f474b0e6f3 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_cmInstr.h @@ -0,0 +1,87 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 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 */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/*------------------ RealView Compiler -----------------*/ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + +/*------------------ ARM Compiler V6 -------------------*/ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armcc_V6.h" + +/*------------------ GNU Compiler ----------------------*/ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + +/*------------------ ICC Compiler ----------------------*/ +#elif defined ( __ICCARM__ ) + #include + +/*------------------ TI CCS Compiler -------------------*/ +#elif defined ( __TMS470__ ) + #include + +/*------------------ TASKING Compiler ------------------*/ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +/*------------------ COSMIC Compiler -------------------*/ +#elif defined ( __CSMC__ ) + #include + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_cmSimd.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_cmSimd.h new file mode 100644 index 0000000000..66bf5c2a72 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_cmSimd.h @@ -0,0 +1,96 @@ +/**************************************************************************//** + * @file core_cmSimd.h + * @brief CMSIS Cortex-M SIMD Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 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 */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CMSIMD_H +#define __CORE_CMSIMD_H + +#ifdef __cplusplus + extern "C" { +#endif + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +/*------------------ RealView Compiler -----------------*/ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + +/*------------------ ARM Compiler V6 -------------------*/ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armcc_V6.h" + +/*------------------ GNU Compiler ----------------------*/ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + +/*------------------ ICC Compiler ----------------------*/ +#elif defined ( __ICCARM__ ) + #include + +/*------------------ TI CCS Compiler -------------------*/ +#elif defined ( __TMS470__ ) + #include + +/*------------------ TASKING Compiler ------------------*/ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +/*------------------ COSMIC Compiler -------------------*/ +#elif defined ( __CSMC__ ) + #include + +#endif + +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CMSIMD_H */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_dac.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_dac.h new file mode 100644 index 0000000000..d37cfff1b4 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_dac.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_DAC_H__ +#define __CORE_DAC_H__ +void DAC_Init(uint8_t Stream); +void DAC_Setup(uint32_t Freq, uint32_t OutRMode); +void DAC_Send(const uint16_t *Data, uint32_t Len, CBFuncEx_t Callback, void *pParam); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_dcmi.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_dcmi.h new file mode 100644 index 0000000000..ca5f23c463 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_dcmi.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_DCMI_H__ +#define __CORE_DCMI_H__ + +/** + * @brief 对摄像头做基本的初始化工作 + * + * @param VsyncLevel 垂直同步极性 0: VSYNC 低电平有效 1: VSYNC 高电平有效 + * @param HsyncLevel 水平同步极性 0: HSYNC 低电平有效 1: HSYNC 高电平有效 + * @param PclkPOL Pixel时钟极性 0:下降沿有效 1:上升沿有效 + * @param DataBits 数据位8~14 + * @param FrameRate 帧率控制,0不控制,1减少为50%,2减少为25% + */ +void DCMI_Setup(uint8_t VsyncLevel, uint8_t HsyncLevel, uint8_t PclkPOL, uint8_t DataBit, uint32_t FrameRate); + +/** + * @brief 摄像头捕获开关 + * + * @param OnOff 0: 关 1: 开 + * @param BufLen 缓存大小,注意单位是4byte,如果为0,看下面的参数自动生成,如果不为0,必须是行数据量的倍数,且能被总行数整除,比如320*240,16bit数据,那么就是320*2/4的N倍,比如8倍的1280 + * @param ImageW 输出图像一行的像素点数 + * @param ImageW 输出图像行数 + * @param DataByte 1个像素点的数据量byte + * @param OutH 自动计算出的单次回调行数 + */ +void DCMI_CaptureSwitch(uint8_t OnOff, uint32_t BufLen, uint32_t ImageW, uint32_t ImageH, uint8_t DataByte, uint32_t *OutH); +void DCMI_SetCallback(CBFuncEx_t CB, void *pData); +/** + * @brief 摄像头裁剪功能 + * + * @param OnOff 0: 关 1: 开 + * @param VStart 裁剪从第几行开始 + * @param HStart 裁剪每行从第几个像素数据开始,如果是16bit数据,则要*2,依次类推 + * @param VLen 裁剪保留的行数,最小1 + * @param HLen 裁剪每行保留的像素数据,如果是16bit数据,则要*2,依次类推 + */ +void DCMI_SetCROPConfig(uint8_t OnOff, uint32_t VStart, uint32_t HStart, uint32_t VLen, uint32_t HLen); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_debug.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_debug.h new file mode 100644 index 0000000000..f619138525 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_debug.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_DEBUG_H__ +#define __CORE_DEBUG_H__ +#include "stdint.h" +#include "bsp_common.h" +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_dma.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_dma.h new file mode 100644 index 0000000000..4b83dbbf56 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_dma.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_DMA_H__ +#define __CORE_DMA_H__ + +enum +{ + DMA1_STREAM_0, + DMA1_STREAM_1, + DMA1_STREAM_2, + DMA1_STREAM_3, + DMA1_STREAM_4, + DMA1_STREAM_5, + DMA1_STREAM_6, + DMA1_STREAM_7, +// DMA1_STREAM_QTY, +// DMA2_STREAM_0 = DMA1_STREAM_QTY, +// DMA2_STREAM_1, +// DMA2_STREAM_2, +// DMA2_STREAM_3, +// DMA2_STREAM_4, +// DMA2_STREAM_5, +// DMA2_STREAM_6, +// DMA2_STREAM_7, + DMA2_STREAM_QTY, + DMA_STREAM_QTY = DMA2_STREAM_QTY, +}; +void DMA_GlobalInit(void); +void *DMA_TakeStream(uint8_t Stream); +int DMA_CheckStreamLock(uint8_t Stream); +void DMA_ReleaseStream(uint8_t Stream); +uint8_t DMA_CheckStreamBusy(uint8_t Stream); +int DMA_ConfigStream(uint8_t Stream, void *Config); +int DMA_StartStream(uint8_t Stream, const void *Data, uint32_t Len, CBFuncEx_t CB, void *pUserData, uint8_t NeedIrq); +/** + * @brief 强制启动DMA传输 + * @param Stream DMA流序号 + * @param Data DMA缓存 + * @param Len DMA缓存长度 + * @param CB 完成或者出错回调。完成时,回调函数参数pParam为0,出错为0xffffffff + * @param NeedIrq 是否需要中断 + * @return 无 + */ +void DMA_ForceStartStream(uint8_t Stream, const void *Data, uint32_t Len, CBFuncEx_t CB, void *pUserData, uint8_t NeedIrq); +void DMA_ClearStreamFlag(uint8_t Stream); +void DMA_StopStream(uint8_t Stream); +uint32_t DMA_GetRemainingDataLength(uint8_t Stream); +uint32_t DMA_GetDataLength(uint8_t Stream, uint32_t FirstAddress); +void DMA_BaseConfig(void *Config); +void DMA_PrintGlobalReg(void); +void DMA_PrintReg(uint8_t Stream); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_flash.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_flash.h new file mode 100644 index 0000000000..7016a116b6 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_flash.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_FLASH_H__ +#define __CORE_FLASH_H__ +int Flash_EraseSector(uint32_t address, uint8_t NeedCheck); +int Flash_ProgramData(uint32_t address, uint32_t *Data, uint32_t Len, uint8_t NeedCheck); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_gpio.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_gpio.h new file mode 100644 index 0000000000..47a662635b --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_gpio.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_GPIO_H__ +#define __CORE_GPIO_H__ +#include "bsp_common.h" +/** + * @brief GPIO全局初始化 + * + * @param Fun 中断回调函数,回调时,PIN序号是pData,void *->uint32_t + + */ +void GPIO_GlobalInit(CBFuncEx_t Fun); + +/** + * @brief GPIO初始化 + * + * @param Pin Pin序号 + * @param IsInput 是否为输入功能,1是,0否 + * @param InitValue 初始电平,1高,0低,只对输出有效 + + */ +void GPIO_Config(uint32_t Pin, uint8_t IsInput, uint8_t InitValue); +/** + * @brief GPIO上下拉控制 + * + * @param Pin Pin序号 + * @param IsPull 是否需要上下拉 + * @param IsUp 是否上拉 + + */ +void GPIO_PullConfig(uint32_t Pin, uint8_t IsPull, uint8_t IsUp); + +/** + * @brief GPIO外部中断初始化 + * + * @param Pin Pin序号 + * @param IsLevel 是否是电平中断,0边沿型,1电平型 + * @param IsRiseHigh 上升沿或者高电平 + * @param IsFallLow 下降沿或者低电平 + */ +void GPIO_ExtiConfig(uint32_t Pin, uint8_t IsLevel, uint8_t IsRiseHigh, uint8_t IsFallLow); + +/** + * @brief GPIO复用功能 + * + * @param Pin Pin序号 + * @param Function 复用功能,这个需要根据芯片实际情况决定,当前是0~3,注意GPIO功能是1 + */ +void GPIO_Iomux(uint32_t Pin, uint32_t Function); + +/** + * @brief GPIO输出电平 + * + * @param Pin Pin序号 + * @param Level 1高电平,0低电平 + */ +void GPIO_Output(uint32_t Pin, uint8_t Level); + +/** + * @brief 读取GPIO输入电平 + * + * @param Pin Pin序号 + * @return 1高电平, 0低电平,其他无效 + */ +uint8_t GPIO_Input(uint32_t Pin); + +/** + * @brief GPIO同一端口多个pin输出电平,针对类似STM32GPIO分布有效 + * + * @param Port 端口号 + * @param Pins Pin序号组合 + * @param Level 1高电平,0低电平 + */ +void GPIO_OutputMulti(uint32_t Port, uint32_t Pins, uint32_t Level); + +/** + * @brief 读取GPIO同一端口多个pin输入电平 + * + * @param Port 端口号 + * @return + */ +uint32_t GPIO_InputMulti(uint32_t Port); + +void GPIO_ExtiSetHWTimerCB(CBFuncEx_t CB, void *pParam); +void GPIO_ODConfig(uint32_t Pin, uint8_t InitValue); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_hwtimer.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_hwtimer.h new file mode 100644 index 0000000000..1261da425c --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_hwtimer.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_HWTIMER_H__ +#define __CORE_HWTIMER_H__ + + +/** + * @brief 硬件定时器按照周期和占空比设置成PWM并启动 + * + * @param HWTimerID 硬件定时器ID + * @param Period 周期,最大24M, + * @param Duty 占空比,0.1%,只有50KHz以下才能达到这个精度,500KHz到1% + * @param IsOnePulse 只触发一次脉冲 + */ +void HWTimer_SetPWM(uint8_t HWTimerID, uint32_t Period, uint16_t Duty, uint8_t IsOnePulse); + +/** + * @brief 硬件定时器按照高低电平分辨率设置成PWM并启动,时钟48M + * + * @param HWTimerID 硬件定时器ID + * @param HighCnt 高电平时钟周期数 + * @param LowCnt 低电平时钟周期数 + * @param IsOnePulse 只触发一次脉冲 + */ +void HWTimer_StartPWM(uint8_t HWTimerID, uint32_t HighCnt, uint32_t LowCnt, uint8_t IsOnePulse); + +/** + * @brief 硬件定时器关闭 + * + * @param HWTimerID 硬件定时器ID + */ +void HWTimer_Stop(uint8_t HWTimerID); +/** + * @brief 初始化IO操作序列,会完全清除之前保留的操作序列 + * + * @param HWTimerID 硬件定时器ID + * @param nCount 操作步骤总数 + * @param Repeat 重复次数 + * @param InputByte IO读取的次数,注意每8次1个byte,不足8个也算1个byte + * @param CmdDoneCB 全部完成后回调函数 + * @param pCmdDoneParam 回调函数的用户参数 + * + */ +void HWTimer_InitOperationQueue(uint8_t HWTimerID, uint32_t nCount, uint32_t Repeat, uint32_t InputByte, CBFuncEx_t CmdDoneCB, void *pCmdDoneParam); +/** + * @brief 加入IO操作序列 + * + * @param HWTimerID 硬件定时器ID + * @param pCmd IO操作 + */ +void HWTimer_AddOperation(uint8_t HWTimerID, OPQueue_CmdStruct *pCmd); +/** + * @brief 启动IO操作序列 + * + * @param HWTimerID 硬件定时器ID + */ +void HWTimer_StartOperationQueue(uint8_t HWTimerID); +/** + * @brief 清空IO操作序列,需要重新AddOperation,但是不需要init + * + * @param HWTimerID 硬件定时器ID + */ +void HWTimer_ClearOperationQueue(uint8_t HWTimerID); +/** + * @brief 完全释放IO操作序列,下次使用需要重新init,必须在HWTimer_CheckOperationQueueDone确认完成的情况下调用 + * + * @param HWTimerID 硬件定时器ID + */ +void HWTimer_FreeOperationQueue(uint8_t HWTimerID); +/** + * @brief 在OP_QUEUE_CMD_CB时,需要在CB里调用本函数来安全的结束序列操作,只能在OP_QUEUE_CMD_CB时调用 + * + * @param HWTimerID 硬件定时器ID + */ +void HWTimer_AddEndCmdInOperationQueue(uint8_t HWTimerID); +/** + * @brief 检查IO操作序列是否完成 + * + * @param HWTimerID 硬件定时器ID + * @return =0未完成,其他已完成 + */ +uint8_t HWTimer_CheckOperationQueueDone(uint8_t HWTimerID); +/** + * @brief 获取IO操作序列中IO读取的值 + * + * @param HWTimerID 硬件定时器ID + * @param Value copy的空间 + * @return 获取的byte数,和init时InputByte一致 + */ +int HWTimer_GetOperationQueueInputResult(uint8_t HWTimerID, uint8_t *Value); + +/** + * @brief 获取IO操作序列中捕获状态 + * + * @param HWTimerID 硬件定时器ID + * @param CB 捕获回调函数 + * @param CB 捕获回调函数的用户参数 + * @return 捕获次数 + */ +uint32_t HWTimer_GetOperationQueueCaptureResult(uint8_t HWTimerID, CBFuncEx_t CB, void *pParam); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_i2c.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_i2c.h new file mode 100644 index 0000000000..e31ad323aa --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_i2c.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_I2C_H__ +#define __CORE_I2C_H__ +#include "bsp_common.h" +typedef struct +{ + uint8_t Data[2]; +}I2C_CommonRegDataStruct; + +void I2C_GlobalInit(void); +/** + * @brief i2c主机配置 + * + * @param I2CID I2C通道号 + * @param Speed 速度,只有100000和400000 + */ +void I2C_MasterSetup(uint8_t I2CID, uint32_t Speed); +/* + * @brief i2c传输前配置,如果配置和上次一致,则不用设置 + * + * @param I2CID I2C通道号 + * @param ChipAddress I2C设备地址 + * @param ChipAddressLen I2C设备地址长度 ,1或者2 + * @param CB 完成后回调函数 + * @param pParam 完成后回调函数中的pParam + */ +void I2C_Prepare(uint8_t I2CID, uint16_t ChipAddress, uint8_t ChipAddressLen, CBFuncEx_t CB, void *pParam); +/** + * @brief i2c主机传输,兼容直接读写和先写寄存器地址后读数据 + * + * @param I2CID I2C通道号 + * @param Operate 操作类型 + * I2C_OP_READ_REG = 0, //i2c通用读寄存器,一写一读,自动带start信号 + I2C_OP_READ, //i2c通用读,只读 + I2C_OP_WRITE, //i2c通用写,只写 + * @param RegAddress 寄存器地址,在通用读写时忽略 + * @param Data 读写数据缓存,直接使用用户的空间,在完成前不可以释放空间 + * @param Len 读写数据长度 + * @param Toms 传输单个字节超时时间,单位ms + */ +void I2C_MasterXfer(uint8_t I2CID, uint8_t Operate, uint8_t RegAddress, uint8_t *Data, uint32_t Len, uint16_t Toms); + +/** + * @brief i2c主机传输,多个单一寄存器写入 + * + * @param I2CID I2C通道号 + * @param RegQueue 寄存器序列 + * @param TotalNum 序列长度 + * @param Toms 传输单个字节超时时间,单位ms + * @param IsBlock 是否要阻塞 + * @return =0 传输成功,其他失败 IsBlock=1才有效,IsBlock=0直接返回0 + */ +int32_t I2C_MasterWriteRegQueue(uint8_t I2CID, I2C_CommonRegDataStruct *RegQueue, uint32_t TotalNum, uint16_t Toms, uint8_t IsBlock); + +/** + * @brief i2c主机传输结果查询 + * + * @param I2CID I2C通道号 + * @param Result 传输结果 =0成功,其他失败,只有return != 0才有效 + * @return =0 传输还未完成 其他已完成 + */ +int I2C_WaitResult(uint8_t I2CID, int32_t *Result); + +int32_t I2C_BlockWrite(uint8_t I2CID, uint8_t ChipAddress, const uint8_t *Data, uint32_t Len, uint16_t Toms, CBFuncEx_t CB, void *pParam); + +int32_t I2C_BlockRead(uint8_t I2CID, uint8_t ChipAddress, uint8_t *Reg, uint8_t *Data, uint32_t Len, uint16_t Toms, CBFuncEx_t CB, void *pParam); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_irq.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_irq.h new file mode 100644 index 0000000000..3833dc234b --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_irq.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_IRQ_H__ +#define __CORE_IRQ_H__ + +/** + * @brief 设置中断回调函数 + * + * @param Irq 中断号 0~IRQ_LINE_MAX + * @param Handler 中断回调函数,如 void Irq_Handler(uint32_t IrqLine, void *pData); 可以多个中断号对应1个中断函数,回调时传入中断号和用户数据 + */ +void ISR_SetHandler(int32_t Irq, void *Handler); +/** + * @brief 设置中断优先级 + * + * @param Irq 中断号 0~IRQ_LINE_MAX + * @param PriorityLevel 优先级范围根据芯片实际情况决定 + */ +void ISR_SetPriority(int32_t Irq, uint32_t PriorityLevel); + +void ISR_OnOff(int32_t Irq, uint32_t OnOff); +void ISR_Clear(int32_t Irq); +void ISR_PrintCallback(int32_t Irq); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_keyboard.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_keyboard.h new file mode 100644 index 0000000000..5aa53c0e83 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_keyboard.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_KEYBOARD_H__ +#define __CORE_KEYBOARD_H__ +/** + * @brief 键盘扫描配置 + * + * @param PinConfigMap 硬盘扫描通道配置,bit0~bit8对应通道0到8,0为输入,1为输出,开发板配置为0x0f0 + * @param Debounce 按键滤波,目前强制为7 + 0: 5ms~75ms; + 1: 17.5ms~75ms; + 2: 27.5ms~75ms; + 3: 37.5 ms~75ms; + 4: 45ms~75ms; + 5: 50ms~75ms; + 6: 60ms~75ms; + 7: 70ms~75ms。 + * @param CB 按键中断回调,pData为按键参数32bit,pParam为用户数据,按键参数中bit16=1按下0释放,bit0~3,输入通道值,bit4~bit7,输出通道值 + * @param pParam 按键中断回调用户数据 + */ +void KB_Setup(uint16_t PinConfigMap, uint16_t Debounce, CBFuncEx_t CB, void *pParam); +void KB_Stop(void); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_otp.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_otp.h new file mode 100644 index 0000000000..acffc38490 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_otp.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_OTP_H__ +#define __CORE_OTP_H__ +/** + * @brief 写OTP区 + * + * @param Address 写入首地址,注意从0开始,一共3KB,必须4字节对齐 + * @param Data 写入数据,必须4字节对齐 + * @param Len 写入数据长度,单位4字节,比如写入128字节,这里填32 + */ +void OTP_Write(uint32_t Address, const uint32_t *Data, uint32_t Len); +/** + * @brief 读OTP区 + * + * @param Address 首地址,注意从0开始,一共3KB + * @param Data 缓存数据 + * @param Len 读出长度 + */ +void OTP_Read(uint32_t Address, uint8_t *Data, uint32_t Len); +/** + * @brief 锁定全部OTP区,变成只读,只能重启恢复 + * + */ +void OTP_Lock(void); + +void OTP_GetSn(uint8_t *ChipSN); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_rng.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_rng.h new file mode 100644 index 0000000000..f21fe5e867 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_rng.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_RNG_H__ +#define __CORE_RNG_H__ +void RNG_Init(void); +/** + * @brief 获取随机数 + * + * @param Buf,一次获取4个32bit数据 + */ +void RNG_GetData(uint32_t Buf[4]); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_rtc.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_rtc.h new file mode 100644 index 0000000000..521d07cd15 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_rtc.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_RTC_H__ +#define __CORE_RTC_H__ +#include "bsp_common.h" +void RTC_GlobalInit(void); + +void RTC_SetDateTime(Date_UserDataStruct *pDate, Time_UserDataStruct *pTime, uint8_t isForce); + +void RTC_GetDateTime(Date_UserDataStruct *pDate, Time_UserDataStruct *pTime); + +uint64_t RTC_GetUTC(void); + + +void RTC_SetStamp(uint32_t Stamp); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_sc000.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_sc000.h new file mode 100644 index 0000000000..9b67c92f3b --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_sc000.h @@ -0,0 +1,1022 @@ +/**************************************************************************//** + * @file core_sc000.h + * @brief CMSIS SC000 Core Peripheral Access Layer Header File + * @version V5.0.5 + * @date 28. May 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_SC000_H_GENERIC +#define __CORE_SC000_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup SC000 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS SC000 definitions */ +#define __SC000_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __SC000_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __SC000_CMSIS_VERSION ((__SC000_CMSIS_VERSION_MAIN << 16U) | \ + __SC000_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_SC (000U) /*!< Cortex secure core */ + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC000_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_SC000_H_DEPENDANT +#define __CORE_SC000_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __SC000_REV + #define __SC000_REV 0x0000U + #warning "__SC000_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group SC000 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t _reserved0:1; /*!< bit: 0 Reserved */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED0[1U]; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + uint32_t RESERVED1[154U]; + __IOM uint32_t SFCR; /*!< Offset: 0x290 (R/W) Security Features Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 8U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief SC000 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. + Therefore they are not covered by the SC000 header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else +/*#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping not available for SC000 */ +/*#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping not available for SC000 */ + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +/*#define NVIC_GetActive __NVIC_GetActive not available for SC000 */ + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ + + +/* Interrupt Priorities are WORD accessible only under Armv6-M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC000_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_sc300.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_sc300.h new file mode 100644 index 0000000000..3e8a47109a --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_sc300.h @@ -0,0 +1,1915 @@ +/**************************************************************************//** + * @file core_sc300.h + * @brief CMSIS SC300 Core Peripheral Access Layer Header File + * @version V5.0.6 + * @date 04. June 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_SC300_H_GENERIC +#define __CORE_SC300_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup SC3000 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS SC300 definitions */ +#define __SC300_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __SC300_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __SC300_CMSIS_VERSION ((__SC300_CMSIS_VERSION_MAIN << 16U) | \ + __SC300_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_SC (300U) /*!< Cortex secure core */ + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC300_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_SC300_H_DEPENDANT +#define __CORE_SC300_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __SC300_REV + #define __SC300_REV 0x0000U + #warning "__SC300_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group SC300 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t _reserved1:8; /*!< bit: 16..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + uint32_t RESERVED1[129U]; + __IOM uint32_t SFCR; /*!< Offset: 0x290 (R/W) Security Features Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + uint32_t RESERVED1[1U]; +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ + + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC300_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_service.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_service.h new file mode 100644 index 0000000000..3e1e48c82b --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_service.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_SERVICE_H__ +#define __CORE_SERVICE_H__ +#include "bsp_common.h" + +typedef struct +{ + uint32_t Speed; + uint32_t x1; + uint32_t y1; + uint32_t x2; + uint32_t y2; + uint32_t xoffset; + uint32_t yoffset; + uint32_t Size; + uint32_t DCDelay; + uint8_t *Data; + uint8_t SpiID; + uint8_t Mode; + uint8_t CSPin; + uint8_t DCPin; + uint8_t ColorMode; +}LCD_DrawStruct; + +void Core_ServiceInit(void); +void Core_LCDDraw(LCD_DrawStruct *Draw); +void Core_CameraDraw(LCD_DrawStruct *Draw); +void Core_DecodeQR(uint8_t *ImageData, uint16_t ImageW, uint16_t ImageH, CBDataFun_t CB); +uint32_t Core_LCDDrawCacheLen(void); +void Core_USBDefaultDeviceStart(uint8_t USB_ID); +void Core_USBAction(uint8_t USB_ID, uint8_t Action, void *pParam); +void Core_PrintMemInfo(void); +void Core_PrintServiceStack(void); +void Core_DebugMem(uint8_t HeapID, const char *FuncName, uint32_t Line); + +uint8_t Core_GetSleepFlag(void); +void Core_SetSleepEnable(uint8_t OnOff); + +void Core_VUartInit(uint8_t UartID, uint32_t BaudRate, uint8_t IsRxCacheEnable, uint8_t DataBits, uint8_t Parity, uint8_t StopBits, CBFuncEx_t CB); +void Core_VUartDeInit(uint8_t UartID); +void Core_VUartSetRxTimeout(uint8_t UartID, uint32_t TimeoutUS); +void Core_VUartSetCb(uint8_t UartID, CBFuncEx_t CB); +uint32_t Core_VUartRxBufferRead(uint8_t UartID, uint8_t *Data, uint32_t Len); +int32_t Core_VUartBufferTx(uint8_t UartID, const uint8_t *Data, uint32_t Len); +void Core_VUartBufferTxStop(uint8_t UartID); + +void Core_VHIDInit(uint8_t USB_ID, CBFuncEx_t CB); +void Core_VHIDUploadData(uint8_t USB_ID, uint8_t *Data, uint16_t Len); +void Core_VHIDUploadStop(uint8_t USB_ID); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_spi.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_spi.h new file mode 100644 index 0000000000..2821babfe4 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_spi.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_SPI_H__ +#define __CORE_SPI_H__ +#include "bsp_common.h" +void SPI_MasterInit(uint8_t SpiID, uint8_t DataBit, uint8_t Mode, uint32_t Speed, CBFuncEx_t CB, void *pUserData); +int32_t SPI_Transfer(uint8_t SpiID, const uint8_t *TxData, uint8_t *RxData, uint32_t Len, uint8_t UseDMA); +/* + * polling传输,不发生线程调度 + */ +int32_t SPI_BlockTransfer(uint8_t SpiID, const uint8_t *TxData, uint8_t *RxData, uint32_t Len); +/* + * 类似spiflash的cmd+data型传输用,先发WLen数据,忽略Rx数据,再接收RLen数据 + */ +int32_t SPI_FlashBlockTransfer(uint8_t SpiID, const uint8_t *TxData, uint32_t WLen, uint8_t *RxData, uint32_t RLen); +void SPI_DMATxInit(uint8_t SpiID, uint8_t Stream, uint32_t Channel); +void SPI_DMARxInit(uint8_t SpiID, uint8_t Stream, uint32_t Channel); +void SPI_TransferStop(uint8_t UartID); +uint8_t SPI_IsTransferBusy(uint8_t UartID); +void SPI_SetNewConfig(uint8_t SpiID, uint32_t Speed, uint8_t NewMode); +void SPI_SetCallbackFun(uint8_t SpiID, CBFuncEx_t CB, void *pUserData); +void SPI_SetTxOnlyFlag(uint8_t SpiID, uint8_t OnOff); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_task.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_task.h new file mode 100644 index 0000000000..f5ab5d01cd --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_task.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_TASK_H__ +#define __CORE_TASK_H__ +typedef struct +{ + uint32_t ID; + uint32_t Param1; + uint32_t Param2; + uint32_t Param3; +}Task_EventStruct; +#define OS_EVENT Task_EventStruct +HANDLE Task_Create(TaskFun_t EntryFunction, void *Param, uint32_t StackSize, uint32_t Priority, const char *Name); +void Task_SendEvent(HANDLE TaskHandle, uint32_t ID, uint32_t P1, uint32_t P2, uint32_t P3); +int32_t Task_GetEvent(HANDLE TaskHandle, uint32_t TargetEventID, Task_EventStruct *OutEvent, CBFuncEx_t Callback, uint64_t Tick); +int32_t Task_GetEventByMS(HANDLE TaskHandle, uint32_t TargetEventID, Task_EventStruct *OutEvent, CBFuncEx_t Callback, uint32_t ms); +HANDLE Task_GetCurrent(void); +void Task_DelayTick(uint64_t Tick); +void Task_DelayUS(uint32_t US); +void Task_DelayMS(uint32_t MS); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_tick.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_tick.h new file mode 100644 index 0000000000..34e941ea0b --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_tick.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_TICK_H__ +#define __CORE_TICK_H__ +uint64_t GetSysTick(void); +void SysTickDelay(uint32_t Tick); +void SysTickDelayUntil(uint64_t StartTick, uint32_t Tick); +void CoreTick_Init(void); +uint64_t GetSysTickMS(void); +uint64_t GetSysTickUS(void); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_timer.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_timer.h new file mode 100644 index 0000000000..bb012cc306 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_timer.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_TIMER_H__ +#define __CORE_TIMER_H__ + +typedef enum +{ + TIMER_SN_START = 0, + TIMER_SN_MAX, +}STATIC_TIMER_ENUM; + +typedef struct Timer_InfoStruct Timer_t; + +/*********************************TimerList*****************************************/ + +void Timer_Init(void); +//void Timer_Task(void *Param); +//void Timer_Run(void); +Timer_t * Timer_Create(CBFuncEx_t CB, void *Param, void *NotifyTask); +Timer_t * Timer_GetStatic(uint32_t Sn, CBFuncEx_t CB, void *Param, void *NotifyTask); +int Timer_Start(Timer_t *Timer, uint64_t Tick, uint8_t IsRepeat); +int Timer_StartMS(Timer_t *Timer, uint32_t MS, uint8_t IsRepeat); +int Timer_StartUS(Timer_t *Timer, uint32_t US, uint8_t IsRepeat); +void Timer_Stop(Timer_t *Timer); +void Timer_Release(Timer_t *Timer); +uint32_t Timer_NextToRest(void); +uint8_t Timer_IsRunning(Timer_t *Timer); +void Timer_PrintAll(void); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_uart.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_uart.h new file mode 100644 index 0000000000..213f5a3cb4 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_uart.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_UART_H__ +#define __CORE_UART_H__ +#include "bsp_common.h" +/** + * @brief 对串口做基本的初始化工作,不开启任何中断和DMA + * + * @param UartID 串口号 0~MAX,对应USART1~UARTX,0默认用于log输出 + * @param BaudRate 波特率 + * @param IsRxCacheEnable 是否打开RX缓存功能,打开后,只有接收超时中断才会返回,否则每次数据到来都会返回 + * @param DataBits 数据位5~8 + * @param Parity 奇偶校验,可选下列 + * UART_PARITY_NONE, + UART_PARITY_ODD, + UART_PARITY_EVEN, + * @param StopBits 停止位 + * UART_STOP_BIT1, + UART_STOP_BIT1_5, + UART_STOP_BIT2, + * @param CB 回调函数,用于通知是否有新数据达到,DMA TX或者RX完成,是否有错误 + */ +void Uart_BaseInit(uint8_t UartID, uint32_t BaudRate, uint8_t IsRxCacheEnable, uint8_t DataBits, uint8_t Parity, uint8_t StopBits, CBFuncEx_t CB); + + +void Uart_SetCb(uint8_t UartID, CBFuncEx_t CB); + +void Uart_DeInit(uint8_t UartID); +/** + * @brief 串口做阻塞输出,一般用于bootloader或者紧急场合 + * + * @param UartID 串口号 0~MAX,对应USART1~UARTX,0默认用于log输出 + * @param Data + * @param Len + */ +void Uart_BlockTx(uint8_t UartID, uint8_t *Data, uint32_t Len); + +void Uart_NoBlockTx(uint8_t UartID, uint8_t Data); + +void Uart_EnableRxIrq(uint8_t UartID); + +void Uart_EnableTxDoneIrq(uint8_t UartID); +/** + * @brief 串口的DMA配置 + * + * @param UartID 串口号 0~5 + * @param Stream DMA流序号 + * @param Channel DMA通道 + * @return >0 成功返回中断号,其他失败 + */ +int Uart_DMATxInit(uint8_t UartID, uint8_t Stream, uint32_t Channel); + +int Uart_DMARxInit(uint8_t UartID, uint8_t Stream, uint32_t Channel); + +/** + * @brief 串口做DMA非阻塞输出,只能用于APP + * + * @param UartID 串口号 0~5 + * @param Stream DMA流序号 + * @param Data + * @param Len + */ +void Uart_DMATx(uint8_t UartID, uint8_t Stream, const uint8_t *Data, uint32_t Len); + +void Uart_DMARx(uint8_t UartID, uint8_t Stream, uint8_t *Data, uint32_t Len); + +uint32_t Uart_RxBufferRead(uint8_t UartID, uint8_t *Data, uint32_t Len); + +void Uart_RxBufferCB(uint8_t UartID, CBFuncEx_t CB); + +uint32_t Uart_FifoRead(uint8_t UartID, uint8_t *Data); +/** + * @brief 串口做FIFO非阻塞输出 + * + * @param UartID 串口号 0~5 + * @param Data + * @param Len + * @return <0 失败 =0 所有数据传入fifo,不再回调buffer_done,直接回调all_done >0 还有数据没有传入fifo + */ +int32_t Uart_BufferTx(uint8_t UartID, const uint8_t *Data, uint32_t Len); +void Uart_BufferTxStop(uint8_t UartID); +void Uart_PrintReg(uint8_t UartID); +void Uart_ChangeBR(uint8_t UartID, uint32_t BaudRate); +uint32_t Uart_GetLastError(uint8_t UartID); +void Uart_GlobalInit(void); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_usb_ll_driver.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_usb_ll_driver.h new file mode 100644 index 0000000000..67815b391a --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_usb_ll_driver.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_USB_LL_DRIVER_H__ +#define __CORE_USB_LL_DRIVER_H__ + +void USB_GlobalInit(void); +void USB_PowerOnOff(HANDLE hUSB, uint8_t OnOff); +void USB_Stop(HANDLE hUSB); +void USB_ResetStart(HANDLE hUSB); +void USB_ResetEnd(HANDLE hUSB); +void USB_SetWorkMode(HANDLE hUSB, uint8_t Mode); +void USB_SetDeviceAddress(HANDLE hUSB, uint8_t Address); +int USB_InitEpCfg(HANDLE hUSB); +int USB_ReInitEpCfg(HANDLE hUSB); +void USB_Start(HANDLE hUSB); +void USB_TxPacket(HANDLE hUSB, uint8_t EpIndex, const uint8_t *Data, uint16_t Len); +void USB_DeviceXfer(HANDLE hUSB, uint8_t EpIndex); +void USB_DeviceXferStop(HANDLE hUSB, uint8_t EpIndex); +void USB_EpIntOnOff(HANDLE hUSB, uint8_t EpIndex, uint8_t IsToDevice, uint8_t OnOff); +void USB_SetDeviceNoDataSetup(HANDLE hUSB); +void USB_FlushFifo(HANDLE hUSB, uint8_t EpIndex, uint8_t IsRxFifo); + +void USB_SetDeviceEPStatus (HANDLE hUSB, uint8_t Index, uint8_t IsToDevice, uint8_t Status); +uint8_t USB_GetDeviceEPStatus (HANDLE hUSB, uint8_t Index, uint8_t IsToDevice); + +int32_t USB_SetISOCHDelay(HANDLE hUSB, uint16_t DelayNS); +int32_t USB_ExitLatency(HANDLE hUSB, uint8_t Config[6]); + +void USB_ResumeStart(HANDLE hUSB); +void USB_ResumeEnd(HANDLE hUSB); +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_wdt.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_wdt.h new file mode 100644 index 0000000000..6523d3a35b --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/core_wdt.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CORE_WDT_H__ +#define __CORE_WDT_H__ + +void WDT_SetTimeout(uint32_t ms); +void WDT_Feed(void); + +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cs_types.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cs_types.h new file mode 100644 index 0000000000..f44fa11f2f --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/cs_types.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "bsp_common.h" diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/global_config.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/global_config.h new file mode 100644 index 0000000000..bfe3d405ae --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/global_config.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __GLOBAL_CONFIG_H__ +#define __GLOBAL_CONFIG_H__ +#ifndef HSE_VALUE +#define HSE_VALUE ((uint32_t)12000000) /*!< Value of the HSE oscillator in Hz */ +#endif +//#define __DEBUG__ +#define IRQ_LINE_OFFSET (16) //如果想要用sys_tick,改成15 +#define IRQ_LINE_MAX (52) +#define CORE_TICK_BASE (1000) +#define HW_TICK_BASE (48000000) +#define __WDT_TO_MS__ (15000) +#define __FLASH_SECTOR_SIZE__ (0x00001000) +#define __FLASH_PAGE_SIZE__ (0x00000100) +#define __CORE_FLASH_SECTOR_NUM__ (768) //__FLASH_BASE_ADDR__ + __CORE_FLASH_SECTOR_NUM__ * __FLASH_SECTOR_SIZE__,是脚本区, 3M开始 +#define __SCRIPT_FLASH_SECTOR_NUM__ (128) //__SCRIPT_FLASH_SECTOR_NUM__ * __FLASH_SECTOR_SIZE__,是脚本区长度,512K,剩余512K是文件区 +#define __FLASH_BASE_ADDR__ (0x01000000) +#define __RAMRUN_ISR_ADDR__ (0x20004000) +#define __SRAM_BASE_ADDR__ (0x20000000) +#define __APP_START_MAGIC__ (0x5ae1f0b5) +#ifndef __BUILD_OS__ +#define __FUNC_IN_RAM__ +#else +#define __FUNC_IN_RAM__ __attribute__((section (".RamFunc"))) +#endif +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/io_map.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/io_map.h new file mode 100644 index 0000000000..4c231d3d70 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/io_map.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __IO_MAP_H__ +#define __IO_MAP_H__ +#define DBG_UART_TX_PIN HAL_GPIO_1 +#define DBG_UART_TX_AF 0 + +#define DBG_UART_RX_PIN HAL_GPIO_0 +#define DBG_UART_RX_AF 0 + +//#define FLASH_SPI_TX_PORT GPIOB +//#define FLASH_SPI_TX_PIN LL_GPIO_PIN_5 +//#define FLASH_SPI_TX_AF LL_GPIO_AF_5 +//#define FLASH_SPI_RX_PORT GPIOB +//#define FLASH_SPI_RX_PIN LL_GPIO_PIN_4 +//#define FLASH_SPI_RX_AF LL_GPIO_AF_5 +//#define FLASH_SPI_CLK_PORT GPIOB +//#define FLASH_SPI_CLK_PIN LL_GPIO_PIN_3 +//#define FLASH_SPI_CLK_AF LL_GPIO_AF_5 +//#define FLASH_SPI_CS_PORT GPIOE +//#define FLASH_SPI_CS_PIN LL_GPIO_PIN_2 +//#define FLASH_SPI_CS_AF LL_GPIO_AF_0 +// +// +//#define UART2_TX_PORT GPIOA +//#define UART2_TX_PIN LL_GPIO_PIN_9 +//#define UART2_TX_AF LL_GPIO_AF_7 +//#define UART2_RX_PORT GPIOA +//#define UART2_RX_PIN LL_GPIO_PIN_9 +//#define UART2_RX_AF LL_GPIO_AF_7 +// +//#define UART3_TX_PORT GPIOA +//#define UART3_TX_PIN LL_GPIO_PIN_9 +//#define UART3_TX_AF LL_GPIO_AF_7 +//#define UART3_RX_PORT GPIOA +//#define UART3_RX_PIN LL_GPIO_PIN_9 +//#define UART3_RX_AF LL_GPIO_AF_7 + +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/misc.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/misc.h new file mode 100644 index 0000000000..5124799dbf --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/misc.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __MISC_H +#define __MISC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "air105.h" + + + +typedef struct +{ + uint32_t NVIC_IRQChannel; /*!< Specifies the IRQ channel to be enabled or disabled. + This parameter can be a value of @ref IRQn_Type + (For the complete SCPU Devices IRQ Channels list, please + refer to cpu.h file) */ + + uint32_t NVIC_IRQChannelPreemptionPriority; /*!< Specifies the pre-emption priority for the IRQ channel + specified in NVIC_IRQChannel. This parameter can be a value + between 0 and 15 as described in the table @ref NVIC_Priority_Table */ + + uint32_t NVIC_IRQChannelSubPriority; /*!< Specifies the subpriority level for the IRQ channel specified + in NVIC_IRQChannel. This parameter can be a value + between 0 and 15 as described in the table @ref NVIC_Priority_Table */ + + FunctionalState NVIC_IRQChannelCmd; /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel + will be enabled or disabled. + This parameter can be set either to ENABLE or DISABLE */ +} NVIC_InitTypeDef; + + + +#define NVIC_VectTab_RAM ((uint32_t)0x20000000) +#define NVIC_VectTab_FLASH ((uint32_t)0x01000000) +#define IS_NVIC_VECTTAB(VECTTAB) (((VECTTAB) == NVIC_VectTab_RAM) || \ + ((VECTTAB) == NVIC_VectTab_FLASH)) + + +#define NVIC_PriorityGroup_0 ((uint32_t)0x07) /*!< 0 bits for pre-emption priority + 3 bits for subpriority */ +#define NVIC_PriorityGroup_1 ((uint32_t)0x06) /*!< 1 bits for pre-emption priority + 2 bits for subpriority */ +#define NVIC_PriorityGroup_2 ((uint32_t)0x05) /*!< 2 bits for pre-emption priority + 1 bits for subpriority */ +#define NVIC_PriorityGroup_3 ((uint32_t)0x04) /*!< 3 bits for pre-emption priority + 0 bits for subpriority */ + +#define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PriorityGroup_0) || \ + ((GROUP) == NVIC_PriorityGroup_1) || \ + ((GROUP) == NVIC_PriorityGroup_2) || \ + ((GROUP) == NVIC_PriorityGroup_3)) + +#define IS_NVIC_PREEMPTION_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) + +#define IS_NVIC_SUB_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) + +#define IS_NVIC_OFFSET(OFFSET) ((OFFSET) < 0x000FFFFF) + + +/** @defgroup MISC_SysTick_clock_source + * @{ + */ + +#define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB) +#define SysTick_CLKSource_HCLK ((uint32_t)0x00000004) +#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \ + ((SOURCE) == SysTick_CLKSource_HCLK_Div8)) + + +//void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); +void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct); +void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset); +void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource); + +#ifdef __cplusplus +} +#endif + +#endif /* __MISC_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT MEGAHUNT *****END OF FILE****/ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/mpu_armv7.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/mpu_armv7.h new file mode 100644 index 0000000000..be73de161f --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/mpu_armv7.h @@ -0,0 +1,270 @@ +/****************************************************************************** + * @file mpu_armv7.h + * @brief CMSIS MPU API for Armv7-M MPU + * @version V5.0.4 + * @date 10. January 2018 + ******************************************************************************/ +/* + * Copyright (c) 2017-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef ARM_MPU_ARMV7_H +#define ARM_MPU_ARMV7_H + +#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes +#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes +#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes +#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes +#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes +#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte +#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes +#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes +#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes +#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes +#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes +#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes +#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes +#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes +#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes +#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte +#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes +#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes +#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes +#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes +#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes +#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes +#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes +#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes +#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes +#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte +#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes +#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes + +#define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access +#define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only +#define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only +#define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access +#define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only +#define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access + +/** MPU Region Base Address Register Value +* +* \param Region The region to be configured, number 0 to 15. +* \param BaseAddress The base address for the region. +*/ +#define ARM_MPU_RBAR(Region, BaseAddress) \ + (((BaseAddress) & MPU_RBAR_ADDR_Msk) | \ + ((Region) & MPU_RBAR_REGION_Msk) | \ + (MPU_RBAR_VALID_Msk)) + +/** +* MPU Memory Access Attributes +* +* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. +* \param IsShareable Region is shareable between multiple bus masters. +* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. +* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. +*/ +#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \ + ((((TypeExtField ) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \ + (((IsShareable ) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \ + (((IsCacheable ) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \ + (((IsBufferable ) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk)) + +/** +* MPU Region Attribute and Size Register Value +* +* \param DisableExec Instruction access disable bit, 1= disable instruction fetches. +* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. +* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_. +* \param SubRegionDisable Sub-region disable field. +* \param Size Region size of the region to be configured, for example 4K, 8K. +*/ +#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \ + ((((DisableExec ) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \ + (((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \ + (((AccessAttributes) ) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) + +/** +* MPU Region Attribute and Size Register Value +* +* \param DisableExec Instruction access disable bit, 1= disable instruction fetches. +* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. +* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. +* \param IsShareable Region is shareable between multiple bus masters. +* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. +* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. +* \param SubRegionDisable Sub-region disable field. +* \param Size Region size of the region to be configured, for example 4K, 8K. +*/ +#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \ + ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size) + +/** +* MPU Memory Access Attribute for strongly ordered memory. +* - TEX: 000b +* - Shareable +* - Non-cacheable +* - Non-bufferable +*/ +#define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U) + +/** +* MPU Memory Access Attribute for device memory. +* - TEX: 000b (if non-shareable) or 010b (if shareable) +* - Shareable or non-shareable +* - Non-cacheable +* - Bufferable (if shareable) or non-bufferable (if non-shareable) +* +* \param IsShareable Configures the device memory as shareable or non-shareable. +*/ +#define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U)) + +/** +* MPU Memory Access Attribute for normal memory. +* - TEX: 1BBb (reflecting outer cacheability rules) +* - Shareable or non-shareable +* - Cacheable or non-cacheable (reflecting inner cacheability rules) +* - Bufferable or non-bufferable (reflecting inner cacheability rules) +* +* \param OuterCp Configures the outer cache policy. +* \param InnerCp Configures the inner cache policy. +* \param IsShareable Configures the memory as shareable or non-shareable. +*/ +#define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) & 2U), ((InnerCp) & 1U)) + +/** +* MPU Memory Access Attribute non-cacheable policy. +*/ +#define ARM_MPU_CACHEP_NOCACHE 0U + +/** +* MPU Memory Access Attribute write-back, write and read allocate policy. +*/ +#define ARM_MPU_CACHEP_WB_WRA 1U + +/** +* MPU Memory Access Attribute write-through, no write allocate policy. +*/ +#define ARM_MPU_CACHEP_WT_NWA 2U + +/** +* MPU Memory Access Attribute write-back, no write allocate policy. +*/ +#define ARM_MPU_CACHEP_WB_NWA 3U + + +/** +* Struct for a single MPU Region +*/ +typedef struct { + uint32_t RBAR; //!< The region base address register value (RBAR) + uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR +} ARM_MPU_Region_t; + +/** Enable the MPU. +* \param MPU_Control Default access permissions for unconfigured regions. +*/ +__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) +{ + __DSB(); + __ISB(); + MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; +#endif +} + +/** Disable the MPU. +*/ +__STATIC_INLINE void ARM_MPU_Disable(void) +{ + __DSB(); + __ISB(); +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; +#endif + MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; +} + +/** Clear and disable the given MPU region. +* \param rnr Region number to be cleared. +*/ +__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) +{ + MPU->RNR = rnr; + MPU->RASR = 0U; +} + +/** Configure an MPU region. +* \param rbar Value for RBAR register. +* \param rsar Value for RSAR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr) +{ + MPU->RBAR = rbar; + MPU->RASR = rasr; +} + +/** Configure the given MPU region. +* \param rnr Region number to be configured. +* \param rbar Value for RBAR register. +* \param rsar Value for RSAR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr) +{ + MPU->RNR = rnr; + MPU->RBAR = rbar; + MPU->RASR = rasr; +} + +/** Memcopy with strictly ordered memory access, e.g. for register targets. +* \param dst Destination data is copied to. +* \param src Source data is copied from. +* \param len Amount of data words to be copied. +*/ +__STATIC_INLINE void orderedCpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len) +{ + uint32_t i; + for (i = 0U; i < len; ++i) + { + dst[i] = src[i]; + } +} + +/** Load the given number of MPU regions from a table. +* \param table Pointer to the MPU configuration table. +* \param cnt Amount of regions to be configured. +*/ +__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt) +{ + const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U; + while (cnt > MPU_TYPE_RALIASES) { + orderedCpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize); + table += MPU_TYPE_RALIASES; + cnt -= MPU_TYPE_RALIASES; + } + orderedCpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize); +} + +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/mpu_armv8.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/mpu_armv8.h new file mode 100644 index 0000000000..b182643664 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/mpu_armv8.h @@ -0,0 +1,333 @@ +/****************************************************************************** + * @file mpu_armv8.h + * @brief CMSIS MPU API for Armv8-M MPU + * @version V5.0.4 + * @date 10. January 2018 + ******************************************************************************/ +/* + * Copyright (c) 2017-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef ARM_MPU_ARMV8_H +#define ARM_MPU_ARMV8_H + +/** \brief Attribute for device memory (outer only) */ +#define ARM_MPU_ATTR_DEVICE ( 0U ) + +/** \brief Attribute for non-cacheable, normal memory */ +#define ARM_MPU_ATTR_NON_CACHEABLE ( 4U ) + +/** \brief Attribute for normal memory (outer and inner) +* \param NT Non-Transient: Set to 1 for non-transient data. +* \param WB Write-Back: Set to 1 to use write-back update policy. +* \param RA Read Allocation: Set to 1 to use cache allocation on read miss. +* \param WA Write Allocation: Set to 1 to use cache allocation on write miss. +*/ +#define ARM_MPU_ATTR_MEMORY_(NT, WB, RA, WA) \ + (((NT & 1U) << 3U) | ((WB & 1U) << 2U) | ((RA & 1U) << 1U) | (WA & 1U)) + +/** \brief Device memory type non Gathering, non Re-ordering, non Early Write Acknowledgement */ +#define ARM_MPU_ATTR_DEVICE_nGnRnE (0U) + +/** \brief Device memory type non Gathering, non Re-ordering, Early Write Acknowledgement */ +#define ARM_MPU_ATTR_DEVICE_nGnRE (1U) + +/** \brief Device memory type non Gathering, Re-ordering, Early Write Acknowledgement */ +#define ARM_MPU_ATTR_DEVICE_nGRE (2U) + +/** \brief Device memory type Gathering, Re-ordering, Early Write Acknowledgement */ +#define ARM_MPU_ATTR_DEVICE_GRE (3U) + +/** \brief Memory Attribute +* \param O Outer memory attributes +* \param I O == ARM_MPU_ATTR_DEVICE: Device memory attributes, else: Inner memory attributes +*/ +#define ARM_MPU_ATTR(O, I) (((O & 0xFU) << 4U) | (((O & 0xFU) != 0U) ? (I & 0xFU) : ((I & 0x3U) << 2U))) + +/** \brief Normal memory non-shareable */ +#define ARM_MPU_SH_NON (0U) + +/** \brief Normal memory outer shareable */ +#define ARM_MPU_SH_OUTER (2U) + +/** \brief Normal memory inner shareable */ +#define ARM_MPU_SH_INNER (3U) + +/** \brief Memory access permissions +* \param RO Read-Only: Set to 1 for read-only memory. +* \param NP Non-Privileged: Set to 1 for non-privileged memory. +*/ +#define ARM_MPU_AP_(RO, NP) (((RO & 1U) << 1U) | (NP & 1U)) + +/** \brief Region Base Address Register value +* \param BASE The base address bits [31:5] of a memory region. The value is zero extended. Effective address gets 32 byte aligned. +* \param SH Defines the Shareability domain for this memory region. +* \param RO Read-Only: Set to 1 for a read-only memory region. +* \param NP Non-Privileged: Set to 1 for a non-privileged memory region. +* \oaram XN eXecute Never: Set to 1 for a non-executable memory region. +*/ +#define ARM_MPU_RBAR(BASE, SH, RO, NP, XN) \ + ((BASE & MPU_RBAR_BASE_Msk) | \ + ((SH << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk) | \ + ((ARM_MPU_AP_(RO, NP) << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk) | \ + ((XN << MPU_RBAR_XN_Pos) & MPU_RBAR_XN_Msk)) + +/** \brief Region Limit Address Register value +* \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended. +* \param IDX The attribute index to be associated with this memory region. +*/ +#define ARM_MPU_RLAR(LIMIT, IDX) \ + ((LIMIT & MPU_RLAR_LIMIT_Msk) | \ + ((IDX << MPU_RLAR_AttrIndx_Pos) & MPU_RLAR_AttrIndx_Msk) | \ + (MPU_RLAR_EN_Msk)) + +/** +* Struct for a single MPU Region +*/ +typedef struct { + uint32_t RBAR; /*!< Region Base Address Register value */ + uint32_t RLAR; /*!< Region Limit Address Register value */ +} ARM_MPU_Region_t; + +/** Enable the MPU. +* \param MPU_Control Default access permissions for unconfigured regions. +*/ +__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) +{ + __DSB(); + __ISB(); + MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; +#endif +} + +/** Disable the MPU. +*/ +__STATIC_INLINE void ARM_MPU_Disable(void) +{ + __DSB(); + __ISB(); +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; +#endif + MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; +} + +#ifdef MPU_NS +/** Enable the Non-secure MPU. +* \param MPU_Control Default access permissions for unconfigured regions. +*/ +__STATIC_INLINE void ARM_MPU_Enable_NS(uint32_t MPU_Control) +{ + __DSB(); + __ISB(); + MPU_NS->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB_NS->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; +#endif +} + +/** Disable the Non-secure MPU. +*/ +__STATIC_INLINE void ARM_MPU_Disable_NS(void) +{ + __DSB(); + __ISB(); +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB_NS->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; +#endif + MPU_NS->CTRL &= ~MPU_CTRL_ENABLE_Msk; +} +#endif + +/** Set the memory attribute encoding to the given MPU. +* \param mpu Pointer to the MPU to be configured. +* \param idx The attribute index to be set [0-7] +* \param attr The attribute value to be set. +*/ +__STATIC_INLINE void ARM_MPU_SetMemAttrEx(MPU_Type* mpu, uint8_t idx, uint8_t attr) +{ + const uint8_t reg = idx / 4U; + const uint32_t pos = ((idx % 4U) * 8U); + const uint32_t mask = 0xFFU << pos; + + if (reg >= (sizeof(mpu->MAIR) / sizeof(mpu->MAIR[0]))) { + return; // invalid index + } + + mpu->MAIR[reg] = ((mpu->MAIR[reg] & ~mask) | ((attr << pos) & mask)); +} + +/** Set the memory attribute encoding. +* \param idx The attribute index to be set [0-7] +* \param attr The attribute value to be set. +*/ +__STATIC_INLINE void ARM_MPU_SetMemAttr(uint8_t idx, uint8_t attr) +{ + ARM_MPU_SetMemAttrEx(MPU, idx, attr); +} + +#ifdef MPU_NS +/** Set the memory attribute encoding to the Non-secure MPU. +* \param idx The attribute index to be set [0-7] +* \param attr The attribute value to be set. +*/ +__STATIC_INLINE void ARM_MPU_SetMemAttr_NS(uint8_t idx, uint8_t attr) +{ + ARM_MPU_SetMemAttrEx(MPU_NS, idx, attr); +} +#endif + +/** Clear and disable the given MPU region of the given MPU. +* \param mpu Pointer to MPU to be used. +* \param rnr Region number to be cleared. +*/ +__STATIC_INLINE void ARM_MPU_ClrRegionEx(MPU_Type* mpu, uint32_t rnr) +{ + mpu->RNR = rnr; + mpu->RLAR = 0U; +} + +/** Clear and disable the given MPU region. +* \param rnr Region number to be cleared. +*/ +__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) +{ + ARM_MPU_ClrRegionEx(MPU, rnr); +} + +#ifdef MPU_NS +/** Clear and disable the given Non-secure MPU region. +* \param rnr Region number to be cleared. +*/ +__STATIC_INLINE void ARM_MPU_ClrRegion_NS(uint32_t rnr) +{ + ARM_MPU_ClrRegionEx(MPU_NS, rnr); +} +#endif + +/** Configure the given MPU region of the given MPU. +* \param mpu Pointer to MPU to be used. +* \param rnr Region number to be configured. +* \param rbar Value for RBAR register. +* \param rlar Value for RLAR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegionEx(MPU_Type* mpu, uint32_t rnr, uint32_t rbar, uint32_t rlar) +{ + mpu->RNR = rnr; + mpu->RBAR = rbar; + mpu->RLAR = rlar; +} + +/** Configure the given MPU region. +* \param rnr Region number to be configured. +* \param rbar Value for RBAR register. +* \param rlar Value for RLAR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rnr, uint32_t rbar, uint32_t rlar) +{ + ARM_MPU_SetRegionEx(MPU, rnr, rbar, rlar); +} + +#ifdef MPU_NS +/** Configure the given Non-secure MPU region. +* \param rnr Region number to be configured. +* \param rbar Value for RBAR register. +* \param rlar Value for RLAR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegion_NS(uint32_t rnr, uint32_t rbar, uint32_t rlar) +{ + ARM_MPU_SetRegionEx(MPU_NS, rnr, rbar, rlar); +} +#endif + +/** Memcopy with strictly ordered memory access, e.g. for register targets. +* \param dst Destination data is copied to. +* \param src Source data is copied from. +* \param len Amount of data words to be copied. +*/ +__STATIC_INLINE void orderedCpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len) +{ + uint32_t i; + for (i = 0U; i < len; ++i) + { + dst[i] = src[i]; + } +} + +/** Load the given number of MPU regions from a table to the given MPU. +* \param mpu Pointer to the MPU registers to be used. +* \param rnr First region number to be configured. +* \param table Pointer to the MPU configuration table. +* \param cnt Amount of regions to be configured. +*/ +__STATIC_INLINE void ARM_MPU_LoadEx(MPU_Type* mpu, uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt) +{ + const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U; + if (cnt == 1U) { + mpu->RNR = rnr; + orderedCpy(&(mpu->RBAR), &(table->RBAR), rowWordSize); + } else { + uint32_t rnrBase = rnr & ~(MPU_TYPE_RALIASES-1U); + uint32_t rnrOffset = rnr % MPU_TYPE_RALIASES; + + mpu->RNR = rnrBase; + while ((rnrOffset + cnt) > MPU_TYPE_RALIASES) { + uint32_t c = MPU_TYPE_RALIASES - rnrOffset; + orderedCpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), c*rowWordSize); + table += c; + cnt -= c; + rnrOffset = 0U; + rnrBase += MPU_TYPE_RALIASES; + mpu->RNR = rnrBase; + } + + orderedCpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), cnt*rowWordSize); + } +} + +/** Load the given number of MPU regions from a table. +* \param rnr First region number to be configured. +* \param table Pointer to the MPU configuration table. +* \param cnt Amount of regions to be configured. +*/ +__STATIC_INLINE void ARM_MPU_Load(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt) +{ + ARM_MPU_LoadEx(MPU, rnr, table, cnt); +} + +#ifdef MPU_NS +/** Load the given number of MPU regions from a table to the Non-secure MPU. +* \param rnr First region number to be configured. +* \param table Pointer to the MPU configuration table. +* \param cnt Amount of regions to be configured. +*/ +__STATIC_INLINE void ARM_MPU_Load_NS(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt) +{ + ARM_MPU_LoadEx(MPU_NS, rnr, table, cnt); +} +#endif + +#endif + diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/platform_define.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/platform_define.h new file mode 100644 index 0000000000..4527493839 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/platform_define.h @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __PLATFORM_DEFINE_H__ +#define __PLATFORM_DEFINE_H__ +enum +{ + UART_DATA_BIT5 = 5, + UART_DATA_BIT6 = 6, + UART_DATA_BIT7 = 7, + UART_DATA_BIT8 = 8, + UART_PARITY_NONE = 0, + UART_PARITY_ODD, + UART_PARITY_EVEN, + UART_STOP_BIT1 = 0, + UART_STOP_BIT1_5, + UART_STOP_BIT2, + + I2C_OP_READ_REG = 0, //i2c通用读寄存器,一写一读,自动带start信号 + I2C_OP_READ, //i2c通用读,只读 + I2C_OP_WRITE, //i2c通用写,只写 + + OP_QUEUE_CMD_END = 0, + OP_QUEUE_CMD_ONE_TIME_DELAY, //只有一次delay + OP_QUEUE_CMD_CONTINUE_DELAY, //连续delay,配合OP_QUEUE_CMD_REPEAT_DELAY使用 + OP_QUEUE_CMD_REPEAT_DELAY, //重复OP_QUEUE_CMD_CONTINUE_DELAY + OP_QUEUE_CMD_SET_GPIO_DIR_OUT, + OP_QUEUE_CMD_SET_GPIO_DIR_IN, + OP_QUEUE_CMD_GPIO_OUT, + OP_QUEUE_CMD_GPIO_IN, + OP_QUEUE_CMD_CB, + OP_QUEUE_CMD_CAPTURE_SET, + OP_QUEUE_CMD_CAPTURE, + OP_QUEUE_CMD_CAPTURE_END, + OP_QUEUE_CMD_IO_PULL_NONE = 0, + OP_QUEUE_CMD_IO_PULL_UP, + OP_QUEUE_CMD_IO_PULL_DOWN, + OP_QUEUE_CMD_IO_EXTI_BOTH = 0, //双边沿中断 + OP_QUEUE_CMD_IO_EXTI_UP, //上升沿中断 + OP_QUEUE_CMD_IO_EXTI_DOWN, //下降沿中断 + + COLOR_MODE_RGB_565 = 0, + COLOR_MODE_GRAY, + COLOR_MODE_YCBCR_422_UYVY, + COLOR_MODE_YCBCR_422_YUYV, + + CORE_OTA_MODE_FULL = 0, + CORE_OTA_MODE_DIFF, + CORE_OTA_IN_FLASH = 0, + CORE_OTA_OUT_SPI_FLASH, + CORE_OTA_IN_FILE, +}; + +enum +{ + USB_ID0 = 0, + USB_MAX, + I2C_ID0 = 0, + I2C_MAX, + UART_ID0 = 0, + UART_ID1, + UART_ID2, + UART_ID3, +// UART_ID4, +// UART_ID5, + UART_MAX, + VIRTUAL_UART0 = 0, + VIRTUAL_UART_MAX, + HSPI_ID0 = 0, + SPI_ID0, + SPI_ID1, + SPI_ID2, + SPI_ID3, + SPI_MAX, + + SPI_MODE_0 = 0, + SPI_MODE_1, + SPI_MODE_2, + SPI_MODE_3, + + HW_TIMER0 = 0, + HW_TIMER1, + HW_TIMER2, + HW_TIMER3, + HW_TIMER4, + HW_TIMER5, + HW_TIMER_MAX, + + ADC_CHANNEL_0 = 0, + ADC_CHANNEL_1, + ADC_CHANNEL_2, + ADC_CHANNEL_3, + ADC_CHANNEL_4, + ADC_CHANNEL_5, + ADC_CHANNEL_6, + ADC_CHANNEL_MAX, + + HAL_GPIO_0 = 0, + HAL_GPIO_1, + HAL_GPIO_2, + HAL_GPIO_3, + HAL_GPIO_4, + HAL_GPIO_5, + HAL_GPIO_6, + HAL_GPIO_7, + HAL_GPIO_8, + HAL_GPIO_9, + HAL_GPIO_10, + HAL_GPIO_11, + HAL_GPIO_12, + HAL_GPIO_13, + HAL_GPIO_14, + HAL_GPIO_15, + HAL_GPIO_16, + HAL_GPIO_17, + HAL_GPIO_18, + HAL_GPIO_19, + HAL_GPIO_20, + HAL_GPIO_21, + HAL_GPIO_22, + HAL_GPIO_23, + HAL_GPIO_24, + HAL_GPIO_25, + HAL_GPIO_26, + HAL_GPIO_27, + HAL_GPIO_28, + HAL_GPIO_29, + HAL_GPIO_30, + HAL_GPIO_31, + HAL_GPIO_32, + HAL_GPIO_33, + HAL_GPIO_34, + HAL_GPIO_35, + HAL_GPIO_36, + HAL_GPIO_37, + HAL_GPIO_38, + HAL_GPIO_39, + HAL_GPIO_40, + HAL_GPIO_41, + HAL_GPIO_42, + HAL_GPIO_43, + HAL_GPIO_44, + HAL_GPIO_45, + HAL_GPIO_46, + HAL_GPIO_47, + HAL_GPIO_48, + HAL_GPIO_49, + HAL_GPIO_50, + HAL_GPIO_51, + HAL_GPIO_52, + HAL_GPIO_53, + HAL_GPIO_54, + HAL_GPIO_55, + HAL_GPIO_56, + HAL_GPIO_57, + HAL_GPIO_58, + HAL_GPIO_59, + HAL_GPIO_60, + HAL_GPIO_61, + HAL_GPIO_62, + HAL_GPIO_63, + HAL_GPIO_64, + HAL_GPIO_65, + HAL_GPIO_66, + HAL_GPIO_67, + HAL_GPIO_68, + HAL_GPIO_69, + HAL_GPIO_70, + HAL_GPIO_71, + HAL_GPIO_72, + HAL_GPIO_73, + HAL_GPIO_74, + HAL_GPIO_75, + HAL_GPIO_76, + HAL_GPIO_77, + HAL_GPIO_78, + HAL_GPIO_79, + HAL_GPIO_80, + HAL_GPIO_81, + HAL_GPIO_82, + HAL_GPIO_83, + HAL_GPIO_84, + HAL_GPIO_85, + HAL_GPIO_86, + HAL_GPIO_87, + HAL_GPIO_88, + HAL_GPIO_89, + HAL_GPIO_90, + HAL_GPIO_91, + HAL_GPIO_92, + HAL_GPIO_93, + HAL_GPIO_94, + HAL_GPIO_95, + HAL_GPIO_MAX, + HAL_GPIO_NONE = HAL_GPIO_MAX, //大于等于HAL_GPIO_NONE,说明不存在 +}; +enum +{ + GPIOA_00 = 0, + GPIOA_01, + GPIOA_02, + GPIOA_03, + GPIOA_04, + GPIOA_05, + GPIOA_06, + GPIOA_07, + GPIOA_08, + GPIOA_09, + GPIOA_10, + GPIOA_11, + GPIOA_12, + GPIOA_13, + GPIOA_14, + GPIOA_15, + GPIOB_00, + GPIOB_01, + GPIOB_02, + GPIOB_03, + GPIOB_04, + GPIOB_05, + GPIOB_06, + GPIOB_07, + GPIOB_08, + GPIOB_09, + GPIOB_10, + GPIOB_11, + GPIOB_12, + GPIOB_13, + GPIOB_14, + GPIOB_15, + GPIOC_00, + GPIOC_01, + GPIOC_02, + GPIOC_03, + GPIOC_04, + GPIOC_05, + GPIOC_06, + GPIOC_07, + GPIOC_08, + GPIOC_09, + GPIOC_10, + GPIOC_11, + GPIOC_12, + GPIOC_13, + GPIOC_14, + GPIOC_15, + GPIOD_00, + GPIOD_01, + GPIOD_02, + GPIOD_03, + GPIOD_04, + GPIOD_05, + GPIOD_06, + GPIOD_07, + GPIOD_08, + GPIOD_09, + GPIOD_10, + GPIOD_11, + GPIOD_12, + GPIOD_13, + GPIOD_14, + GPIOD_15, + GPIOE_00, + GPIOE_01, + GPIOE_02, + GPIOE_03, + GPIOE_04, + GPIOE_05, + GPIOE_06, + GPIOE_07, + GPIOE_08, + GPIOE_09, + GPIOE_10, + GPIOE_11, + GPIOE_12, + GPIOE_13, + GPIOE_14, + GPIOE_15, + GPIOF_00, + GPIOF_01, + GPIOF_02, + GPIOF_03, + GPIOF_04, + GPIOF_05, + GPIOF_06, + GPIOF_07, + GPIOF_08, + GPIOF_09, + GPIOF_10, + GPIOF_11, + GPIOF_12, + GPIOF_13, + GPIOF_14, + GPIOF_15, + GPIO_MAX, + GPIO_NONE = GPIO_MAX, //大于等于GPIO_NONE,说明不存在 +}; + +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/pulse_encoder_config.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/pulse_encoder_config.h new file mode 100644 index 0000000000..46ed63cd95 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/pulse_encoder_config.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-23 balanceTWK first version + */ + +#ifndef __PULSE_ENCODER_CONFIG_H__ +#define __PULSE_ENCODER_CONFIG_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef BSP_USING_PULSE_ENCODER1 +#ifndef PULSE_ENCODER1_CONFIG +#define PULSE_ENCODER1_CONFIG \ + { \ + .tim_handler.Instance = TIM1, \ + .encoder_irqn = TIM1_UP_TIM10_IRQn, \ + .name = "pulse1" \ + } +#endif /* PULSE_ENCODER1_CONFIG */ +#endif /* BSP_USING_PULSE_ENCODER1 */ + +#ifdef BSP_USING_PULSE_ENCODER2 +#ifndef PULSE_ENCODER2_CONFIG +#define PULSE_ENCODER2_CONFIG \ + { \ + .tim_handler.Instance = TIM2, \ + .encoder_irqn = TIM2_IRQn, \ + .name = "pulse2" \ + } +#endif /* PULSE_ENCODER2_CONFIG */ +#endif /* BSP_USING_PULSE_ENCODER2 */ + +#ifdef BSP_USING_PULSE_ENCODER3 +#ifndef PULSE_ENCODER3_CONFIG +#define PULSE_ENCODER3_CONFIG \ + { \ + .tim_handler.Instance = TIM3, \ + .encoder_irqn = TIM3_IRQn, \ + .name = "pulse3" \ + } +#endif /* PULSE_ENCODER3_CONFIG */ +#endif /* BSP_USING_PULSE_ENCODER3 */ + +#ifdef BSP_USING_PULSE_ENCODER4 +#ifndef PULSE_ENCODER4_CONFIG +#define PULSE_ENCODER4_CONFIG \ + { \ + .tim_handler.Instance = TIM4, \ + .encoder_irqn = TIM4_IRQn, \ + .name = "pulse4" \ + } +#endif /* PULSE_ENCODER4_CONFIG */ +#endif /* BSP_USING_PULSE_ENCODER4 */ + +#ifdef __cplusplus +} +#endif + +#endif /* __PULSE_ENCODER_CONFIG_H__ */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/resource_map.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/resource_map.h new file mode 100644 index 0000000000..21fc95e68f --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/resource_map.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __RESOURCE_MAP_H__ +#define __RESOURCE_MAP_H__ +#include "io_map.h" +#define CORE_TICK_TIM 7 +#define CORE_TICK_IRQ TIM0_7_IRQn +#define CORE_TICK_1US (48) +#define CORE_TICK_1MS (48000) +#define CORE_TICK_1S (48000000) +#define CORE_TICK_IRQ_LEVEL 1 +#define HWTIMER_IRQ_LEVEL 0 + +#define SYS_TIMER_TIM 6 +#define SYS_TIMER_IRQ TIM0_6_IRQn +#define SYS_TIMER_1US (48) +#define SYS_TIMER_1MS (48000) +#define SYS_TIMER_1S (48000000) +#define SYS_TIMER_IRQ_LEVEL 6 + +#define DBG_UART_ID UART_ID0 +#define DBG_UART_BR 1500000 +#define BL_UART_BR 3000000 +#define DBG_UART_IRQ_LEVEL 6 +#define DBG_UART_TX_DMA_STREAM DMA1_STREAM_2 +#define DBG_UART_RX_DMA_STREAM DMA1_STREAM_2 +#define DBG_UART_TX_DMA_CHANNEL SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART0_TX +#define DBG_UART_RX_DMA_CHANNEL SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART0_RX + +#define EFLASH_QSPI_TX_DMA_STREAM DMA1_STREAM_1 +#define DAC_TX_DMA_STREAM DMA1_STREAM_0 +#define DCMI_RX_DMA_STREAM DMA1_STREAM_3 +#define FLASH_SPI_TX_DMA_STREAM DMA1_STREAM_4 +#define FLASH_SPI_RX_DMA_STREAM DMA1_STREAM_5 +#define LCD_SPI_TX_DMA_STREAM DMA1_STREAM_6 +#define LCD_SPI_RX_DMA_STREAM DMA1_STREAM_7 + +#define LUATOS_TASK_PRO (configMAX_PRIORITIES - 2) +#define HW_TASK_PRO (configMAX_PRIORITIES - 1) +#define SERVICE_TASK_PRO (configMAX_PRIORITIES - 4) +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/system_air105.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/system_air105.h new file mode 100644 index 0000000000..549ffa7263 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/system_air105.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef __SYSTEM_AIR105_H_ /* ToDo: replace '' with your device name */ +#define __SYSTEM_AIR105_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "air105.h" +#define assert_param(x) +extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ + + +/** + * Initialize the system + * + * @param none + * @return none + * + * @brief Setup the microcontroller system. + * Initialize the System and update the SystemCoreClock variable. + */ +extern void SystemInit (void); + +/** + * Update SystemCoreClock variable + * + * @param none + * @return none + * + * @brief Updates the SystemCoreClock with current core Clock + * retrieved from cpu registers. + */ +extern void SystemCoreClockUpdate (void); + +#ifdef __cplusplus +} +#endif + +#endif /* SYSTEM__H */ diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/tz_context.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/tz_context.h new file mode 100644 index 0000000000..facc2c9a47 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/tz_context.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * @file tz_context.h + * @brief Context Management for Armv8-M TrustZone + * @version V1.0.1 + * @date 10. January 2018 + ******************************************************************************/ +/* + * Copyright (c) 2017-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef TZ_CONTEXT_H +#define TZ_CONTEXT_H + +#include + +#ifndef TZ_MODULEID_T +#define TZ_MODULEID_T +/// \details Data type that identifies secure software modules called by a process. +typedef uint32_t TZ_ModuleId_t; +#endif + +/// \details TZ Memory ID identifies an allocated memory slot. +typedef uint32_t TZ_MemoryId_t; + +/// Initialize secure context memory system +/// \return execution status (1: success, 0: error) +uint32_t TZ_InitContextSystem_S (void); + +/// Allocate context memory for calling secure software modules in TrustZone +/// \param[in] module identifies software modules called from non-secure mode +/// \return value != 0 id TrustZone memory slot identifier +/// \return value 0 no memory available or internal error +TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module); + +/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S +/// \param[in] id TrustZone memory slot identifier +/// \return execution status (1: success, 0: error) +uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id); + +/// Load secure context (called on RTOS thread context switch) +/// \param[in] id TrustZone memory slot identifier +/// \return execution status (1: success, 0: error) +uint32_t TZ_LoadContext_S (TZ_MemoryId_t id); + +/// Store secure context (called on RTOS thread context switch) +/// \param[in] id TrustZone memory slot identifier +/// \return execution status (1: success, 0: error) +uint32_t TZ_StoreContext_S (TZ_MemoryId_t id); + +#endif // TZ_CONTEXT_H diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/user.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/user.h new file mode 100644 index 0000000000..bbc8931f48 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/user.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __USER_H__ +#define __USER_H__ +#include "bl_inc.h" +#include "app_inc.h" +#include "rtdbg.h" +#define DBG LOG_E +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Inc/w25q80bv.h b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/w25q80bv.h new file mode 100644 index 0000000000..f2b27bf1eb --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Inc/w25q80bv.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __W25Q80BV_H +#define __W25Q80BV_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ + +/** @addtogroup BSP + * @{ + */ + +/** @addtogroup Components + * @{ + */ + +/** @addtogroup W25Q80BV + * @{ + */ + +/** @defgroup W25Q80BV_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @defgroup W25Q80BV_Exported_Constants + * @{ + */ + +/** + * @brief W25Q80BV Configuration + */ +#define W25Q80BV_FLASH_SIZE 0x100000 /* 8MBits => 1MBytes */ +#define W25Q80BV_SECTOR_SIZE 0x1000 /* 256 sectors of 4KBytes */ +#define W25Q80BV_SUBSECTOR_SIZE 0x100 /* 4096 subsectors of 4kBytes */ +#define W25Q80BV_PAGE_SIZE 0x100 /* 65536 pages of 256 bytes */ + +#define W25Q80BV_DUMMY_CYCLES_READ 4 +#define W25Q80BV_DUMMY_CYCLES_READ_QUAD 10 + +#define W25Q80BV_BULK_ERASE_MAX_TIME 250000 +#define W25Q80BV_SECTOR_ERASE_MAX_TIME 3000 +#define W25Q80BV_SUBSECTOR_ERASE_MAX_TIME 800 + +/** + * @brief W25Q80BV Commands + */ +/* Reset Operations */ +#define RESET_ENABLE_CMD 0x66 +#define RESET_MEMORY_CMD 0x99 + +#define ENTER_QPI_MODE_CMD 0x38 +#define EXIT_QPI_MODE_CMD 0xFF + +/* Identification Operations */ +#define READ_ID_CMD 0x90 +#define DUAL_READ_ID_CMD 0x92 +#define QUAD_READ_ID_CMD 0x94 +#define READ_JEDEC_ID_CMD 0x9F + +/* Read Operations */ +#define READ_CMD 0x03 +#define FAST_READ_CMD 0x0B +#define DUAL_OUT_FAST_READ_CMD 0x3B +#define DUAL_INOUT_FAST_READ_CMD 0xBB +#define QUAD_OUT_FAST_READ_CMD 0x6B +#define QUAD_INOUT_FAST_READ_CMD 0xEB + +/* Write Operations */ +#define WRITE_ENABLE_CMD 0x06 +#define WRITE_DISABLE_CMD 0x04 + +/* Register Operations */ +#define READ_STATUS_REG1_CMD 0x05 +#define READ_STATUS_REG2_CMD 0x35 +#define READ_STATUS_REG3_CMD 0x15 + +#define WRITE_STATUS_REG1_CMD 0x01 +#define WRITE_STATUS_REG2_CMD 0x31 +#define WRITE_STATUS_REG3_CMD 0x11 + + +/* Program Operations */ +#define PAGE_PROG_CMD 0x02 +#define QUAD_INPUT_PAGE_PROG_CMD 0x32 + + +/* Erase Operations */ +#define SECTOR_ERASE_CMD 0x20 +#define CHIP_ERASE_CMD 0xC7 + +#define PROG_ERASE_RESUME_CMD 0x7A +#define PROG_ERASE_SUSPEND_CMD 0x75 + +#define SET_BURST_WITH_WRAP 0x77 + + +/* Flag Status Register */ +#define W25Q80BV_FSR_BUSY ((uint8_t)0x01) /*!< busy */ +#define W25Q80BV_FSR_WREN ((uint8_t)0x02) /*!< write enable */ +#define W25Q80BV_FSR_QE ((uint8_t)0x02) /*!< quad enable */ + +/** + * @} + */ + +/** @defgroup W25Q80BV_Exported_Functions + * @{ + */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __W25Q80BV_H */ + diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/bsp_common.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/bsp_common.c new file mode 100644 index 0000000000..468da78add --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/bsp_common.c @@ -0,0 +1,1261 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "bsp_common.h" + +const uint8_t ByteToAsciiTable[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + +void LoopBuffer_Init(Loop_Buffer *Buf, void *Src, uint32_t MaxLen, uint32_t DataSize) +{ + uint8_t *Data = (uint8_t *)Src; + Buf->Data = Data; + Buf->Len = 0; + Buf->MaxLength = MaxLen; + Buf->Offset = 0; + Buf->DataSize = DataSize; +} + +uint32_t LoopBuffer_Query(Loop_Buffer *Buf, void *Src, uint32_t Len) +{ + uint32_t i, p; + uint8_t *Data = (uint8_t *)Src; + if (Buf->Len < Len) + { + Len = Buf->Len; + } + if (Buf->DataSize > 1) + { + for (i = 0, p = Buf->Offset; i < Len; i++, p++) + { + if (p >= Buf->MaxLength) + { + p -= Buf->MaxLength; + } + memcpy(Data + (i * Buf->DataSize), Buf->Data + (p * Buf->DataSize), Buf->DataSize); + } + } + else + { + for (i = 0, p = Buf->Offset; i < Len; i++, p++) + { + if (p >= Buf->MaxLength) + { + p -= Buf->MaxLength; + } + Data[i] = Buf->Data[p]; + } + } + + return Len; +} + +uint32_t LoopBuffer_Read(Loop_Buffer *Buf, void *Src, uint32_t Len) +{ + uint32_t l; + uint8_t *Data = (uint8_t *)Src; + l = LoopBuffer_Query(Buf, Data, Len); + Buf->Len -= l; + Buf->Offset += l; + if (Buf->Offset >= Buf->MaxLength) + { + Buf->Offset -= Buf->MaxLength; + + } + if (!Buf->Len) { + Buf->Offset = 0; + } + return l; +} + +void LoopBuffer_Del(Loop_Buffer *Buf, uint32_t Len) +{ + if (Buf->Len < Len) + { + Len = Buf->Len; + } + + Buf->Len -= Len; + Buf->Offset += Len; + if (Buf->Offset >= Buf->MaxLength) + { + Buf->Offset -= Buf->MaxLength; + } + + if (!Buf->Len) { + Buf->Offset = 0; + } +} + +uint32_t LoopBuffer_Write(Loop_Buffer *Buf, void *Src, uint32_t Len) +{ + uint32_t i, p, cut_off = 0; + uint8_t *Data = (uint8_t *)Src; + if (!Buf->Len && !Buf->Offset && (Len <= Buf->Len)) + { + memcpy(Buf->Data, Data, Len); + Buf->Len = Len; + return Len; + } + cut_off = Buf->MaxLength - Buf->Len; + if (cut_off >= Len) + { + cut_off = 0; + } + else + { + cut_off = Len - cut_off; + } + + if (Buf->DataSize > 1) + { + for (i = 0, p = Buf->Offset + Buf->Len; i < Len; i++, p++) + { + if (p >= Buf->MaxLength) + { + p -= Buf->MaxLength; + } + memcpy(Buf->Data + (p * Buf->DataSize), Data + (i * Buf->DataSize), Buf->DataSize); + } + } + else + { + for (i = 0, p = Buf->Offset + Buf->Len; i < Len; i++, p++) + { + if (p >= Buf->MaxLength) + { + p -= Buf->MaxLength; + } + + Buf->Data[p] = Data[i]; + } + } + + + Buf->Offset += cut_off; + if (Buf->Offset >= Buf->MaxLength) + Buf->Offset -= Buf->MaxLength; + + Buf->Len += Len; + if (Buf->Len > Buf->MaxLength) + Buf->Len = Buf->MaxLength; + + return Len; + +} + + +void Buffer_StaticInit(Buffer_Struct *Buf, void *Src, uint32_t MaxLen) +{ + Buf->Data = Src; + Buf->Pos = 0; + Buf->MaxLen = MaxLen; +} + +int32_t Buffer_StaticWrite(Buffer_Struct *Buf, void *Data, uint32_t Len) +{ + if (!Len) + { + return -1; + } + if (!Buf) + { + return -1; + } + if ((Buf->Pos + Len) > Buf->MaxLen) + { + Len = Buf->MaxLen - Buf->Pos; + } + if (Len) + { + memcpy(&Buf->Data[Buf->Pos], Data, Len); + } + Buf->Pos += Len; + return Len; +} + +//void Buffer_Remove(Buffer_Struct *Buf, uint32_t Len) +//{ +// uint32_t RestLen; +// uint32_t i; +// if (!Buf) +// return ; +// if (!Buf->Data) +// return ; +// if (Len >= Buf->Pos) +// { +// Buf->Pos = 0; +// return ; +// } +// RestLen = Buf->Pos - Len; +// memmove(Buf->Data, Buf->Data + Len, RestLen); +// Buf->Pos = RestLen; +//} + + +/***************************************************************************** +* FUNCTION +* command_parse_param() +* DESCRIPTION +* Parse AT command string to parameters +* PARAMETERS +* char* pStr +* RETURNS +* pCmdParam +*****************************************************************************/ +uint32_t CmdParseParam(int8_t* pStr, CmdParam *CP, int8_t Cut) +{ + uint32_t paramStrLen = strlen((char *)pStr); + uint32_t paramIndex = 0; + uint32_t paramCharIndex = 0; + uint32_t index = 0; + + while ((pStr[index] != '\r') + && (index < paramStrLen) + && (paramIndex < CP->param_max_num)) { + if (pStr[index] == Cut) { + /* Next param string */ + paramCharIndex = 0; + paramIndex++; + } + else { + if (pStr[index] != '"') + { + if (paramCharIndex >= CP->param_max_len) + return (0); + + /*Get each of command param char, the param char except char ' " '*/ + CP->param_str[paramIndex * CP->param_max_len + paramCharIndex] = pStr[index]; + paramCharIndex++; + } + } + index++; + } + + CP->param_num = paramIndex + 1; + + return (1); +} + +__attribute__((weak)) uint8_t OS_CheckInIrq(void) +{ + return __get_IPSR(); +} + +__attribute__((weak)) void OS_BufferRemove(Buffer_Struct *Buf, uint32_t Len) +{ + uint32_t RestLen; + uint32_t i; + if (!Buf) + return ; + if (!Buf->Data) + return ; + if (Len >= Buf->Pos) + { + Buf->Pos = 0; + return ; + } + RestLen = Buf->Pos - Len; + memmove(Buf->Data, Buf->Data + Len, RestLen); + Buf->Pos = RestLen; +} + + + +int32_t BSP_SetBit(uint8_t *Data, uint32_t Sn, uint8_t Value) +{ + uint32_t Mask,Pos1,Pos2; + + Pos1 = Sn/8; + Pos2 = Sn%8; + + Mask = ~(1 << Pos2); + if (Value) + { + Value = (1 << Pos2); + } + Data[Pos1] = (Data[Pos1] & Mask) | Value; + //DBG("%d %d %d %d", Sn, Pos1, Pos2, Value); + return 0; +} + +int32_t BSP_GetBit(uint8_t *Data, uint32_t Sn, uint8_t *Value) +{ + uint32_t Mask,Pos1,Pos2; + + Pos1 = Sn/8; + Pos2 = Sn%8; + Mask = (1 << Pos2); + if (Data[Pos1] & Mask) + { + *Value = 1; + } + else + { + *Value = 0; + } + return -1; +} + +uint8_t BSP_TestBit(uint8_t *Data, uint32_t Sn) +{ + uint32_t Mask,Pos1,Pos2; + + Pos1 = Sn/8; + Pos2 = Sn%8; + Mask = (1 << Pos2); + if (Data[Pos1] & Mask) + { + return 1; + } + return 0; +} + +uint8_t XorCheck(void *Src, uint32_t Len, uint8_t CheckStart) +{ + uint8_t Check = CheckStart; + uint8_t *Data = (uint8_t *)Src; + uint32_t i; + for (i = 0; i < Len; i++) + { + Check ^= Data[i]; + } + return Check; +} + +uint8_t SumCheck(uint8_t *Data, uint32_t Len) +{ + uint8_t Check = 0; + uint32_t i; + for (i = 0; i < Len; i++) + { + Check += Data[i]; + } + return Check; +} + + +uint8_t CRC8Cal(void *Data, uint16_t Len, uint8_t CRC8Last, uint8_t CRCRoot, uint8_t IsReverse) +{ + uint16_t i; + uint8_t CRC8 = CRC8Last; + uint8_t wTemp = CRCRoot; + uint8_t *Src = (uint8_t *)Data; + if (IsReverse) + { + CRCRoot = 0; + for (i = 0; i < 8; i++) + { + if (wTemp & (1 << (7 - i))) + { + CRCRoot |= 1 << i; + } + } + while (Len--) + { + + CRC8 ^= *Src++; + for (i = 0; i < 8; i++) + { + if ((CRC8 & 0x01)) + { + CRC8 >>= 1; + CRC8 ^= CRCRoot; + } + else + { + CRC8 >>= 1; + } + } + } + } + else + { + while (Len--) + { + + CRC8 ^= *Src++; + for (i = 8; i > 0; --i) + { + if ((CRC8 & 0x80)) + { + CRC8 <<= 1; + CRC8 ^= CRCRoot; + } + else + { + CRC8 <<= 1; + } + } + } + } + return CRC8; +} + +/************************************************************************/ +/* CRC16 */ +/************************************************************************/ +uint16_t CRC16Cal(void *Data, uint16_t Len, uint16_t CRC16Last, uint16_t CRCRoot, uint8_t IsReverse) +{ + uint16_t i; + uint16_t CRC16 = CRC16Last; + uint16_t wTemp = CRCRoot; + uint8_t *Src = (uint8_t *)Data; + if (IsReverse) + { + CRCRoot = 0; + for (i = 0; i < 16; i++) + { + if (wTemp & (1 << (15 - i))) + { + CRCRoot |= 1 << i; + } + } + while (Len--) + { + for (i = 0; i < 8; i++) + { + if ((CRC16 & 0x0001) != 0) + { + CRC16 >>= 1; + CRC16 ^= CRCRoot; + } + else + { + CRC16 >>= 1; + } + if ((*Src&(1 << i)) != 0) + { + CRC16 ^= CRCRoot; + } + } + Src++; + } + } + else + { + while (Len--) + { + for (i = 8; i > 0; i--) + { + if ((CRC16 & 0x8000) != 0) + { + CRC16 <<= 1; + CRC16 ^= CRCRoot; + } + else + { + CRC16 <<= 1; + } + if ((*Src&(1 << (i - 1))) != 0) + { + CRC16 ^= CRCRoot; + } + } + Src++; + } + } + + return CRC16; +} + +uint32_t AsciiToU32(uint8_t *Src, uint32_t Len) +{ + uint32_t i = 0; + uint32_t Temp = 0; + for (i = 0; i < Len; i++) + { + + if (Src[i]) + { + Temp *= 10; + Temp += Src[i] - '0'; + } + else + { + break; + } + } + return Temp; +} + + +/** +* @brief 反转数据 +* @param ref 需要反转的变量 +* @param ch 反转长度,多少位 +* @retval N反转后的数据 +*/ +static LongInt Reflect(LongInt ref, uint8_t ch) +{ + LongInt value = 0; + LongInt i; + for (i = 1; i < (LongInt)(ch + 1); i++) + { + if (ref & 1) + value |= (LongInt)1 << (ch - i); + ref >>= 1; + } + return value; +} + +/** +* @brief 建立CRC32的查询表 +* @param Tab 表缓冲 +* @param Gen CRC32根 +* @retval None +*/ +void CRC32_CreateTable(uint32_t *Tab, uint32_t Gen) +{ + uint32_t crc; + uint32_t i, j, temp, t1, t2, flag; + if (Tab[1] != 0) + return; + for (i = 0; i < 256; i++) + { + temp = Reflect(i, 8); + Tab[i] = temp << 24; + for (j = 0; j < 8; j++) + { + flag = Tab[i] & 0x80000000; + t1 = Tab[i] << 1; + if (0 == flag) + { + t2 = 0; + } + else + { + t2 = Gen; + } + Tab[i] = t1 ^ t2; + } + crc = Tab[i]; + Tab[i] = Reflect(crc, 32); + } +} + + +/** +* @brief 计算buffer的crc校验码 +* @param CRC32_Table CRC32表 +* @param Buf 缓冲 +* @param Size 缓冲区长度 +* @param CRC32 初始CRC32值 +* @retval 计算后的CRC32 +*/ +uint32_t CRC32_Cal(uint32_t *CRC32_Table, uint8_t *Buf, uint32_t Size, uint32_t CRC32Last) +{ + uint32_t i; + for (i = 0; i < Size; i++) + { + CRC32Last = CRC32_Table[(CRC32Last ^ Buf[i]) & 0xff] ^ (CRC32Last >> 8); + } + return CRC32Last; +} + + +/************************************************************************/ +/*时间与时间戳转换,C语言实现 */ +/************************************************************************/ +/************************************************************************/ +uint8_t IsLeapYear(uint32_t Year) +{ + if ((Year % 400) == 0) + return 1; + if ((((Year % 4) == 0) && (Year % 100) != 0)) + return 1; + else + return 0; +} + +const uint32_t DayTable[2][12] = { { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }, { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 } }; +//const uint32_t DayTable[2][12] = { { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }, { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 } }; +LongInt UTC2Tamp(Date_UserDataStruct *Date, Time_UserDataStruct *Time) +{ + + LongInt DYear, DDay, DSec; + uint32_t Year100; + DYear = Date->Year - 1970; + if (DYear) //1970年以后,1972是第一个闰年,1973年是第一年需要增加一天,2100年是非闰年 + { + DDay = DYear * 365 + ((DYear + 1) / 4) + DayTable[IsLeapYear(Date->Year)][Date->Mon - 1] + (Date->Day - 1); +// if (IsLeapYear(Date->Year)) +// { +// DDay--; +// } + if (Date->Year >= 2100) + { + Year100 = Date->Year - 2100; + DDay -= (1 + Year100 / 100); + if (Date->Year >= 2400) + { + Year100 = Date->Year - 2400; + DDay += 1 + Year100 / 400; + } + + } + + } + else + { + DDay = DayTable[IsLeapYear(Date->Year)][Date->Mon - 1] + (Date->Day - 1); + } + DSec = DDay * 86400 + Time->Hour * 3600 + Time->Min * 60 + Time->Sec; + return DSec; +} +#define YEAR_1_DAY_BEFORE2000 365 +#define YEAR_2_DAY_BEFORE2000 730 +#define YEAR_3_DAY_BEFORE2000 1096 + + +#define YEAR_1_DAY_AFTER2000 365 +#define YEAR_2_DAY_AFTER2000 730 +#define YEAR_3_DAY_AFTER2000 1095 + +#define YEAR_4_DAY 1461 +#define YEAR_31_DAY 11323 + +#define YEAR_100_DAY 36524 +#define YEAR_400_DAY 146097 + +uint32_t Tamp2UTC(LongInt Sec, Date_UserDataStruct *Date, Time_UserDataStruct *Time, uint32_t LastDDay) +{ + + uint32_t DYear,i, LeapFlag, Temp; + uint32_t DDay; + DDay = Sec / 86400; + if (DDay != LastDDay) + { + DYear = 0; + Time->Week = (4 + DDay) % 7; + if (DDay >= YEAR_31_DAY) + { + DDay -= YEAR_31_DAY; + DYear = 31; + + if (DDay >= YEAR_400_DAY) + { + Temp = DDay / YEAR_400_DAY; + DYear += Temp * 400; + DDay -= Temp * YEAR_400_DAY; + } + + if (DDay >= YEAR_100_DAY) + { + Temp = DDay / YEAR_100_DAY; + DYear += Temp * 100; + DDay -= Temp * YEAR_100_DAY; + } + + if (DDay >= YEAR_4_DAY) + { + Temp = DDay / YEAR_4_DAY; + DYear += Temp * 4; + DDay -= Temp * YEAR_4_DAY; + } + + if (DDay >= YEAR_3_DAY_AFTER2000) + { + DYear += 3; + DDay -= YEAR_3_DAY_AFTER2000; + } + else if (DDay >= YEAR_2_DAY_AFTER2000) + { + DYear += 2; + DDay -= YEAR_2_DAY_AFTER2000; + } + else if (DDay >= YEAR_1_DAY_AFTER2000) + { + DYear += 1; + DDay -= YEAR_1_DAY_AFTER2000; + } + + } + else + { + if (DDay >= YEAR_4_DAY) + { + Temp = DDay / YEAR_4_DAY; + DYear += Temp * 4; + DDay -= Temp * YEAR_4_DAY; + } + + if (DDay >= YEAR_3_DAY_BEFORE2000) + { + DYear += 3; + DDay -= YEAR_3_DAY_BEFORE2000; + } + else if (DDay >= YEAR_2_DAY_BEFORE2000) + { + DYear += 2; + DDay -= YEAR_2_DAY_BEFORE2000; + } + else if (DDay >= YEAR_1_DAY_BEFORE2000) + { + DYear += 1; + DDay -= YEAR_1_DAY_BEFORE2000; + } + } + + Date->Year = DYear + 1970; + LeapFlag = IsLeapYear(Date->Year); + Date->Mon = 12; + for (i = 1; i < 12; i++) + { + if (DDay < DayTable[LeapFlag][i]) + { + Date->Mon = i; + break; + } + } + Date->Day = DDay - DayTable[LeapFlag][Date->Mon - 1] + 1; + } + + Sec = Sec % 86400; + Time->Hour = Sec / 3600; + Sec = Sec % 3600; + Time->Min = Sec / 60; + Time->Sec = Sec % 60; + return DDay; +} + + +/** + * \brief get a byte (8bits) from a pointer + * + * Caller should ensure parameters are valid. + * + * \param ptr the pointer + * \return the byte value + */ +uint8_t BytesGet8(const void *ptr) +{ + const uint8_t *p = (const uint8_t *)ptr; + return p[0]; +} + +/** + * \brief put a byte (8bits) to a pointer + * + * Caller should ensure parameters are valid. + * + * \param ptr the pointer + * \param v the byte value + */ +void BytesPut8(void *ptr, uint8_t v) +{ + uint8_t *p = (uint8_t *)ptr; + p[0] = v; +} + +/** + * \brief get a big endian short (16bits) from a pointer + * + * Caller should ensure parameters are valid. + * + * \param ptr the pointer, may be unaligned + * \return the short value + */ +uint16_t BytesGetBe16(const void *ptr) +{ + const uint8_t *p = (const uint8_t *)ptr; + return (p[0] << 8) | p[1]; +} + +/** + * \brief put a big endian short (16bits) to a pointer + * + * Caller should ensure parameters are valid. + * + * \param ptr the pointer, may be unaligned + * \param v the short value + */ +void BytesPutBe16(void *ptr, uint16_t v) +{ + uint8_t *p = (uint8_t *)ptr; + p[0] = (v >> 8) & 0xff; + p[1] = v & 0xff; +} + +/** + * \brief get a big endian word (32bits) from a pointer + * + * Caller should ensure parameters are valid. + * + * \param ptr the pointer, may be unaligned + * \return the word value + */ +uint32_t BytesGetBe32(const void *ptr) +{ + const uint8_t *p = (const uint8_t *)ptr; + return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; +} + +/** + * \brief put a big endian word (32bits) to a pointer + * + * Caller should ensure parameters are valid. + * + * \param ptr the pointer, may be unaligned + * \param v the word value + */ +void BytesPutBe32(void *ptr, uint32_t v) +{ + uint8_t *p = (uint8_t *)ptr; + p[0] = (v >> 24) & 0xff; + p[1] = (v >> 16) & 0xff; + p[2] = (v >> 8) & 0xff; + p[3] = v & 0xff; +} + +/** + * \brief get a little endian short (16bits) from a pointer + * + * Caller should ensure parameters are valid. + * + * \param ptr the pointer, may be unaligned + * \return the short value + */ +uint16_t BytesGetLe16(const void *ptr) +{ + const uint8_t *p = (const uint8_t *)ptr; + return p[0] | (p[1] << 8); +} + +/** + * \brief put a little endian short (16bits) to a pointer + * + * Caller should ensure parameters are valid. + * + * \param ptr the pointer, may be unaligned + * \param v the short value + */ +void BytesPutLe16(void *ptr, uint16_t v) +{ + uint8_t *p = (uint8_t *)ptr; + p[0] = v & 0xff; + p[1] = (v >> 8) & 0xff; +} + +/** + * \brief get a little endian word (32bits) from a pointer + * + * Caller should ensure parameters are valid. + * + * \param ptr the pointer, may be unaligned + * \return the word value + */ +uint32_t BytesGetLe32(const void *ptr) +{ + const uint8_t *p = (const uint8_t *)ptr; + return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); +} + +/** + * \brief put a little endian word (32bits) to a pointer + * + * Caller should ensure parameters are valid. + * + * \param ptr the pointer, may be unaligned + * \param v the word value + */ +void BytesPutLe32(void *ptr, uint32_t v) +{ + uint8_t *p = (uint8_t *)ptr; + p[0] = v & 0xff; + p[1] = (v >> 8) & 0xff; + p[2] = (v >> 16) & 0xff; + p[3] = (v >> 24) & 0xff; +} + +/** + * \brief get a little endian long long (64bits) from a pointer + * + * Caller should ensure parameters are valid. + * + * \param ptr the pointer, may be unaligned + * \return the long long value + */ +uint64_t BytesGetLe64(const void *ptr) +{ + const uint8_t *p = (const uint8_t *)ptr; + return BytesGetLe32(p) | ((uint64_t)BytesGetLe32(p + 4) << 32); +} + +/** + * \brief put a little endian long long (64bits) to a pointer + * + * Caller should ensure parameters are valid. + * + * \param ptr the pointer, may be unaligned + * \param v the long long value + */ +void BytesPutLe64(void *ptr, uint64_t v) +{ + uint8_t *p = (uint8_t *)ptr; + BytesPutLe32(p, v & 0xffffffff); + BytesPutLe32(p + 4, (v >> 32) & 0xffffffff); +} + +uint8_t BytesGet8FromBuf(Buffer_Struct *Buf) +{ + Buf->Pos++; + return Buf->Data[Buf->Pos - 1]; +} + + +void BytesPut8ToBuf(Buffer_Struct *Buf, uint8_t v) +{ + Buf->Data[Buf->Pos] = v; + Buf->Pos++; +} + +uint16_t BytesGetBe16FromBuf(Buffer_Struct *Buf) +{ + Buf->Pos += 2; + return (Buf->Data[Buf->Pos - 2] << 8) | Buf->Data[Buf->Pos - 1]; +} + +void BytesPutBe16ToBuf(Buffer_Struct *Buf, uint16_t v) +{ + Buf->Data[Buf->Pos] = (v >> 8) & 0xff; + Buf->Data[Buf->Pos + 1] = v & 0xff; + Buf->Pos += 2; +} + +uint32_t BytesGetBe32FromBuf(Buffer_Struct *Buf) +{ + Buf->Pos += 4; + return (Buf->Data[Buf->Pos - 4] << 24) | (Buf->Data[Buf->Pos - 3] << 16) | (Buf->Data[Buf->Pos - 2] << 8) | Buf->Data[Buf->Pos - 1]; +} + +void BytesPutBe32ToBuf(Buffer_Struct *Buf, uint32_t v) +{ + Buf->Data[Buf->Pos] = (v >> 24) & 0xff; + Buf->Data[Buf->Pos + 1] = (v >> 16) & 0xff; + Buf->Data[Buf->Pos + 2] = (v >> 8) & 0xff; + Buf->Data[Buf->Pos + 3] = v & 0xff; + Buf->Pos += 4; +} + + +uint16_t BytesGetLe16FromBuf(Buffer_Struct *Buf) +{ + Buf->Pos += 2; + return Buf->Data[Buf->Pos - 2] | (Buf->Data[Buf->Pos - 1] << 8); +} + +void BytesPutLe16ToBuf(Buffer_Struct *Buf, uint16_t v) +{ + Buf->Data[Buf->Pos] = v & 0xff; + Buf->Data[Buf->Pos + 1] = (v >> 8) & 0xff; + Buf->Pos+= 2; +} + +uint32_t BytesGetLe32FromBuf(Buffer_Struct *Buf) +{ + Buf->Pos += 4; + return Buf->Data[Buf->Pos - 4] | (Buf->Data[Buf->Pos - 3] << 8) | (Buf->Data[Buf->Pos - 2] << 16) | (Buf->Data[Buf->Pos - 1] << 24); +} + +void BytesPutLe32ToBuf(Buffer_Struct *Buf, uint32_t v) +{ + Buf->Data[Buf->Pos] = v & 0xff; + Buf->Data[Buf->Pos + 1] = (v >> 8) & 0xff; + Buf->Data[Buf->Pos + 2] = (v >> 16) & 0xff; + Buf->Data[Buf->Pos + 3] = (v >> 24) & 0xff; + Buf->Pos += 4; +} + +uint64_t BytesGetLe64FromBuf(Buffer_Struct *Buf) +{ + uint64_t Temp = BytesGetLe32FromBuf(Buf); + return Temp | ((uint64_t)BytesGetLe32FromBuf(Buf) << 32); +} + +void BytesPutLe64ToBuf(Buffer_Struct *Buf, uint64_t v) +{ + + BytesPutLe32ToBuf(Buf, v & 0xffffffff); + BytesPutLe32ToBuf(Buf, (v >> 32) & 0xffffffff); +} + +float BytesGetFloatFromBuf(Buffer_Struct *Buf) +{ + float Temp; + Buf->Pos += 4; + memcpy(&Temp, &Buf->Data[Buf->Pos - 4], 4); + return Temp; +} + +void BytesPutFloatToBuf(Buffer_Struct *Buf, float v) +{ + memcpy(&Buf->Data[Buf->Pos], &v, 4); + Buf->Pos += 4; +} + +double BytesGetDoubleFromBuf(Buffer_Struct *Buf) +{ + double Temp; + Buf->Pos += 8; + memcpy(&Temp, &Buf->Data[Buf->Pos - 8], 8); + return Temp; +} + +void BytesPutDoubleToBuf(Buffer_Struct *Buf, double v) +{ + memcpy(&Buf->Data[Buf->Pos], &v, 8); + Buf->Pos += 8; +} + +void BytesGetMemoryFromBuf(Buffer_Struct *Buf, uint8_t *Data, uint32_t Len) +{ + memcpy(Data, &Buf->Data[Buf->Pos], Len); + Buf->Pos += Len; +} + +/* + * 转义打包 + * 标识Flag,即包头包尾加入Flag + * 数据中遇到Flag -> Code F1 + * 数据中遇到Code -> Code F2 + */ + +uint32_t TransferPack(uint8_t Flag, uint8_t Code, uint8_t F1, uint8_t F2, uint8_t *InBuf, uint32_t Len, uint8_t *OutBuf) +{ + uint32_t TxLen = 0; + uint32_t i; + OutBuf[0] = Flag; + TxLen = 1; + for (i = 0; i < Len; i++) + { + if (InBuf[i] == Flag) + { + OutBuf[TxLen++] = Code; + OutBuf[TxLen++] = F1; + } + else if (InBuf[i] == Code) + { + OutBuf[TxLen++] = Code; + OutBuf[TxLen++] = F2; + } + else + { + OutBuf[TxLen++] = InBuf[i]; + } + } + OutBuf[TxLen++] = Flag; + return TxLen; +} + + +/* + * 转义解包 + * 标识Flag,即包头包尾加入Flag + * 数据中遇到Code F1 -> Flag + * 数据中遇到Code F2 -> Code + * 数据中遇到Flag 出错返回0 + */ +uint32_t TransferUnpack(uint8_t Flag, uint8_t Code, uint8_t F1, uint8_t F2, uint8_t *InBuf, uint32_t Len, uint8_t *OutBuf) +{ + uint32_t RxLen = 0; + uint32_t i = 0; + while (i < Len) + { + if (InBuf[i] == Code) + { + if (InBuf[i+1] == F1) + { + OutBuf[RxLen++] = Flag; + } + else if (InBuf[i+1] == F2) + { + OutBuf[RxLen++] = Code; + } + else + { + return 0; + } + i += 2; + } + else if (InBuf[i] == Flag) + { + return 0; + } + else + { + OutBuf[RxLen++] = InBuf[i++]; + } + } + return RxLen; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal llist manipulation where we know + * the prev/next entries already! + */ +void __llist_add(llist_head *p, + llist_head *prev, + llist_head *next) +{ + next->prev = p; + p->next = next; + p->prev = prev; + prev->next = p; +} + +/** + * llist_add - add a new entry + * @new: new entry to be added + * @head: llist head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +void llist_add(llist_head *p, llist_head *head) +{ + __llist_add(p, head, head->next); +} + +/** + * llist_add_tail - add a new entry + * @new: new entry to be added + * @head: llist head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +void llist_add_tail(llist_head *p, llist_head *head) +{ + __llist_add(p, head->prev, head); +} + +/* + * Delete a llist entry by making the prev/next entries + * point to each other. + * + * This is only for internal llist manipulation where we know + * the prev/next entries already! + */ +void __llist_del(llist_head * prev, llist_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * llist_del - deletes entry from llist. + * @entry: the element to delete from the llist. + * Note: llist_empty on entry does not return true after this, the entry is + * in an undefined state. + */ +void llist_del(llist_head *entry) +{ + if (entry->prev && entry->next) + { + __llist_del(entry->prev, entry->next); + } + entry->next = LLIST_POISON1; + entry->prev = LLIST_POISON2; +} + +/** + * llist_del_init - deletes entry from llist and reinitialize it. + * @entry: the element to delete from the llist. + */ +void llist_del_init(llist_head *entry) +{ + __llist_del(entry->prev, entry->next); + INIT_LLIST_HEAD(entry); +} + +/** + * llist_move - delete from one llist and add as another's head + * @llist: the entry to move + * @head: the head that will precede our entry + */ +void llist_move(llist_head *llist, llist_head *head) +{ + __llist_del(llist->prev, llist->next); + llist_add(llist, head); +} + +/** + * llist_move_tail - delete from one llist and add as another's tail + * @llist: the entry to move + * @head: the head that will follow our entry + */ +void llist_move_tail(llist_head *llist, + llist_head *head) +{ + __llist_del(llist->prev, llist->next); + llist_add_tail(llist, head); +} + +void *llist_traversal(llist_head *head, CBFuncEx_t cb, void *pData) +{ + llist_head *node = head->next; + llist_head *del; + int32_t result; + while (!llist_empty(head) && (node != head)) + { + result = cb((void *)node, pData); + if (result > 0) + { + return node; + } + else + { + del = node; + node = node->next; + if (result < 0) + { + llist_del(del); + cb((void *)del, NULL); + } + } + } + return NULL; +} + +/** + * llist_empty - tests whether a llist is empty + * @head: the llist to test. + */ +int llist_empty(const llist_head *head) +{ + return head->next == head; +} + +uint32_t llist_num(const llist_head *head) +{ + llist_head *node = head->next; + uint32_t num = 0; + if (!node) + return num; + while(node != head) + { + num++; + node = node->next; + } + return num; +} diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_adc.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_adc.c new file mode 100644 index 0000000000..b84fe6a2ab --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_adc.c @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "user.h" +#define SAMPLE_PER_CH (15) +#if 0 +typedef struct +{ + uint32_t Data[SAMPLE_PER_CH]; + +}Channel_DataStruct; + +typedef struct +{ + Channel_DataStruct ChannelData[ADC_CHANNEL_MAX]; + uint32_t Ctrl; + uint8_t Enable[ADC_CHANNEL_MAX]; + uint8_t CurChannel; +}ADC_CtrlStruct; + +static ADC_CtrlStruct prvADC; + +static void __FUNC_IN_RAM__ ADC_IrqHandle(int32_t IrqLine, void *pData) +{ + int i; + uint8_t NextChannel; + + ADC0->ADC_CR1 = 0; + { + for(i = 0; i < SAMPLE_PER_CH; i++) + { + prvADC.ChannelData[prvADC.CurChannel].Data[i] = ADC0->ADC_DATA & 0x0fff; + } + + + if (prvADC.CurChannel == (ADC_CHANNEL_MAX - 1)) + { + NextChannel = 0; + } + else + { + NextChannel = prvADC.CurChannel + 1; + } + prvADC.CurChannel = 0; + for(i = NextChannel; i < ADC_CHANNEL_MAX; i++) + { + if (prvADC.Enable[i]) + { + prvADC.CurChannel = i; + break; + } + } + ADC0->ADC_FIFO = 3; + ADC0->ADC_CR1 = 0x060 | prvADC.Ctrl | prvADC.CurChannel; + } +} + +void ADC_GlobalInit(void) +{ + int i; +// for(i = 0; i < ADC_CHANNEL_MAX;i++) +// { +// prvADC.Enable[i] = 1; +// } + prvADC.Enable[0] = 1; + prvADC.Ctrl = 2 << 3; + ADC0->ADC_FIFO_THR = SAMPLE_PER_CH - 1; + ADC0->ADC_FIFO = 3; + ADC0->ADC_CR2 &= ~(1 << 14); + ADC0->ADC_CR2 &= ~(1 << 13); + ISR_SetHandler(ADC0_IRQn, ADC_IrqHandle, NULL); +#ifdef __BUILD_OS___ + ISR_SetPriority(ADC0_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY); +#else + ISR_SetPriority(ADC0_IRQn, 6); +#endif + ISR_OnOff(ADC0_IRQn, 1); + ADC0->ADC_CR1 = 0x060 | prvADC.Ctrl | prvADC.CurChannel; +} + +void ADC_SetSpeed(uint8_t Level) +{ + prvADC.Ctrl = Level << 3; +} + +void ADC_IntelResistance(uint8_t OnOff) +{ + if (OnOff) + { + ADC0->ADC_CR2 |= (1 << 13); + } + else + { + ADC0->ADC_CR2 &= ~(1 << 13); + } +} +void ADC_ChannelOnOff(uint8_t Channel, uint8_t OnOff) +{ + if (!Channel) return; + int i; + ISR_OnOff(ADC0_IRQn, 0); + prvADC.Enable[Channel] = OnOff; + ISR_OnOff(ADC0_IRQn, 1); +} +uint32_t ADC_GetChannelValue(uint8_t Channel) +{ + uint32_t total= 0; + uint32_t value = 0; + uint32_t max = 0; + uint32_t min = 0xffff; + uint32_t i; + uint32_t Data[SAMPLE_PER_CH]; + ISR_OnOff(ADC0_IRQn, 0); + memcpy(&Data[10], &prvADC.ChannelData[Channel].Data[10], (SAMPLE_PER_CH - 10) * sizeof(uint32_t)); + ISR_OnOff(ADC0_IRQn, 1); + for (i = 10; i < SAMPLE_PER_CH; i++) + { +// DBG("%d,%d", i, Data[i]); + value = Data[i]; + if(max < value) + max = value; + if(min > value) + min = value; + total += value; + } + + return ((total - max) -min)/(SAMPLE_PER_CH-12); +} + +uint32_t ADC_GetChannelValueBlock(uint8_t Channel) +{ + +} +#else + +typedef struct +{ + uint32_t Data[SAMPLE_PER_CH]; + volatile uint8_t Done; +}ADC_CtrlStruct; +static ADC_CtrlStruct prvADC; +static void ADC_IrqHandle(int32_t IrqLine, void *pData) +{ + int i; + + ADC0->ADC_CR1 = 0; + prvADC.Done = 1; + for(i = 0; i < SAMPLE_PER_CH; i++) + { + prvADC.Data[i] = ADC0->ADC_DATA & 0x0fff; + } + ADC0->ADC_FIFO = 3; +} + +void ADC_GlobalInit(void) +{ + int i; + ADC0->ADC_FIFO_THR = SAMPLE_PER_CH - 1; + ADC0->ADC_FIFO = 3; + ADC0->ADC_CR2 &= ~(1 << 14); + ADC0->ADC_CR2 &= ~(1 << 13); + ADC0->ADC_CR1 = 0; + ISR_SetHandler(ADC0_IRQn, ADC_IrqHandle, NULL); +#ifdef __BUILD_OS___ + ISR_SetPriority(ADC0_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY - 1); +#else + ISR_SetPriority(ADC0_IRQn, 6); +#endif + ISR_OnOff(ADC0_IRQn, 0); +} + +void ADC_IntelResistance(uint8_t OnOff) +{ + if (OnOff) + { + ADC0->ADC_CR2 |= (1 << 13); + } + else + { + ADC0->ADC_CR2 &= ~(1 << 13); + } +} +void ADC_ChannelOnOff(uint8_t Channel, uint8_t OnOff) +{ + +} + +uint32_t ADC_GetChannelValue(uint8_t Channel) +{ + + uint32_t total= 0; + uint32_t value = 0; + uint32_t max = 0; + uint32_t min = 0x0fff; + uint32_t i; + ADC0->ADC_FIFO = 3; + prvADC.Done = 0; + ISR_OnOff(ADC0_IRQn, 1); + ADC0->ADC_CR1 = 0x060 | Channel; + while(!prvADC.Done){;} + for (i = 10; i < SAMPLE_PER_CH; i++) + { +// DBG("%d,%d", i, prvADC.Data[i]); + value = prvADC.Data[i]; + if(max < value) + max = value; + if(min > value) + min = value; + total += value; + } + ADC0->ADC_CR1 = 0; + return ((total - max) -min)/(SAMPLE_PER_CH-12); +} +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_dac.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_dac.c new file mode 100644 index 0000000000..aae8aa10b0 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_dac.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "user.h" + +typedef struct +{ + CBFuncEx_t Callback; + void *pParam; + uint16_t *TxData; + uint32_t Pos; + uint32_t MaxLen; + uint32_t Freq; + uint8_t DMATxStream; + uint8_t IsBusy; +}DAC_ResourceStruct; + +static DAC_ResourceStruct prvDAC; + +static int32_t DAC_DMADoneCB(void *pData, void *pParam) +{ + uint32_t TxLevel; + if (prvDAC.MaxLen > prvDAC.Pos) + { + TxLevel = ((prvDAC.MaxLen - prvDAC.Pos) > 4090)?4000:(prvDAC.MaxLen - prvDAC.Pos); + DMA_ClearStreamFlag(prvDAC.DMATxStream); + DMA_ForceStartStream(prvDAC.DMATxStream, &prvDAC.TxData[prvDAC.Pos], TxLevel, DAC_DMADoneCB, NULL, 1); + prvDAC.Pos += TxLevel; + } + + else + { + prvDAC.IsBusy = 0; + prvDAC.Callback(NULL, prvDAC.pParam); + } + +} + +static int32_t DAC_DummyCB(void *pData, void *pParam) +{ + DBG("!"); + return 0; +} + +void DAC_Init(uint8_t Stream) +{ + DMA_InitTypeDef DMA_InitStruct; + DMA_BaseConfig(&DMA_InitStruct); + DMA_InitStruct.DMA_Peripheral = SYSCTRL_PHER_CTRL_DMA_CHx_IF_DAC; + DMA_InitStruct.DMA_PeripheralBurstSize = DMA_BurstSize_8; + DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&DAC->DAC_DATA; + DMA_InitStruct.DMA_Priority = DMA_Priority_3; + DMA_InitStruct.DMA_MemoryBurstSize = DMA_BurstSize_8; + DMA_InitStruct.DMA_MemoryDataSize = DMA_DataSize_HalfWord; + DMA_InitStruct.DMA_PeripheralDataSize = DMA_DataSize_HalfWord; + DMA_ConfigStream(Stream, &DMA_InitStruct); + prvDAC.DMATxStream = Stream; +} + +void DAC_Setup(uint32_t Freq, uint32_t OutRMode) +{ + uint32_t Ctrl; + while (DAC->DAC_CR1 & (1 << 29)); + + DAC->DAC_CR1 = (OutRMode << 5) | 0x0c; + DAC->DAC_TIMER = ((SystemCoreClock >> 3) / Freq) - 1; + DAC->DAC_FIFO_THR = 7; +} + +void DAC_Send(const uint16_t *Data, uint32_t Len, CBFuncEx_t Callback, void *pParam) +{ + uint32_t TxLevel; + if (prvDAC.IsBusy) + { + DMA_PrintReg(prvDAC.DMATxStream); + return; + } + prvDAC.IsBusy = 1; + prvDAC.TxData = Data; + prvDAC.MaxLen = Len; + prvDAC.Pos = 0; + if (Callback) + { + prvDAC.Callback = Callback; + } + else + { + prvDAC.Callback = DAC_DummyCB; + } + prvDAC.pParam = pParam; + TxLevel = ((prvDAC.MaxLen - prvDAC.Pos) > 4090)?4000:(prvDAC.MaxLen - prvDAC.Pos); + prvDAC.Pos += TxLevel; + DMA_ClearStreamFlag(prvDAC.DMATxStream); + DMA_ForceStartStream(prvDAC.DMATxStream, &prvDAC.TxData[prvDAC.Pos], TxLevel, DAC_DMADoneCB, NULL, 1); +} diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_dcmi.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_dcmi.c new file mode 100644 index 0000000000..53a5ba44d3 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_dcmi.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "user.h" +#define DCMI_BUF_SIZE (1280) +#define DCMI_RXBUF_BAND (2) +typedef struct +{ + PV_Union uBuf[DCMI_RXBUF_BAND]; + CBFuncEx_t CB; + void *pUserData; + uint32_t BufLen; + uint8_t RxDMASn; + +}DCMI_CtrlStruct; + +static DCMI_CtrlStruct prvDCMI; +static int32_t prvDCMI_DMADone(void *pData, void *pParam); +static int32_t prvDCMI_DummyCB(void *pData, void *pParam) +{ + return -1; +} +static void prvDCMI_IrqHandler(int32_t Line, void *pData) +{ + uint32_t SR = DCMI->RISR; + + DCMI->ICR = 0xff; + if (SR & DCMI_IER_VSYNC_IE) + { + prvDCMI.RxDMASn = (prvDCMI.RxDMASn + 1)%DCMI_RXBUF_BAND; + DMA_ClearStreamFlag(DCMI_RX_DMA_STREAM); + DMA_ForceStartStream(DCMI_RX_DMA_STREAM, prvDCMI.uBuf[prvDCMI.RxDMASn].pu32, prvDCMI.BufLen, prvDCMI_DMADone, NULL, 1); + prvDCMI.CB(NULL, prvDCMI.pUserData); + } +} + +static int32_t prvDCMI_DMADone(void *pData, void *pParam) +{ + uint8_t LastRxDMASn; + Buffer_Struct RxBuf; + LastRxDMASn = prvDCMI.RxDMASn; + prvDCMI.RxDMASn = (prvDCMI.RxDMASn + 1)%DCMI_RXBUF_BAND; + DMA_ClearStreamFlag(DCMI_RX_DMA_STREAM); + DMA_ForceStartStream(DCMI_RX_DMA_STREAM, prvDCMI.uBuf[prvDCMI.RxDMASn].pu32, prvDCMI.BufLen, prvDCMI_DMADone, NULL, 1); + Buffer_StaticInit(&RxBuf, prvDCMI.uBuf[LastRxDMASn].pu32, prvDCMI.BufLen); + prvDCMI.CB(&RxBuf, prvDCMI.pUserData); + return 0; +} + +void DCMI_Setup(uint8_t VsyncLevel, uint8_t HsyncLevel, uint8_t PclkPOL, uint8_t DataBit, uint32_t FrameRate) +{ + uint32_t Ctrl = (1 << 29); + Ctrl |= VsyncLevel?DCMI_CR_VSPOL:0; + Ctrl |= HsyncLevel?DCMI_CR_HSPOL:0; + Ctrl |= PclkPOL?DCMI_CR_PCKPOL:0; + Ctrl |= ((DataBit - 8) >> 1) << 10; + Ctrl |= (FrameRate & 0x03 ) << 8; + SYSCTRL->DBG_CR |= DCMI_FROM_OUT; + DCMI->CR = Ctrl | (1 << 21); + DCMI->IER = DCMI_IER_VSYNC_IE|DCMI_IER_OVF_IE|DCMI_IER_ERR_IE; + DCMI->ICR = 0xff; + ISR_OnOff(DCMI_IRQn, 0); + ISR_SetHandler(DCMI_IRQn, prvDCMI_IrqHandler, NULL); +#ifdef __BUILD_OS__ + ISR_SetPriority(DCMI_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY - 2); +#else + ISR_SetPriority(DCMI_IRQn, 5); +#endif + DMA_InitTypeDef DMA_InitStruct; + DMA_BaseConfig(&DMA_InitStruct); + DMA_InitStruct.DMA_Peripheral = SYSCTRL_PHER_CTRL_DMA_CHx_IF_DCMI_TX; + DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&DCMI->DR; + DMA_InitStruct.DMA_MemoryDataSize = DMA_DataSize_Word; + DMA_InitStruct.DMA_PeripheralDataSize = DMA_DataSize_Word; + DMA_InitStruct.DMA_Priority = DMA_Priority_1; + DMA_ConfigStream(DCMI_RX_DMA_STREAM, &DMA_InitStruct); + if (!prvDCMI.CB) + { + prvDCMI.CB = prvDCMI_DummyCB; + } +} + +void DCMI_SetCallback(CBFuncEx_t CB, void *pData) +{ + if (CB) + { + prvDCMI.CB = CB; + } + else + { + prvDCMI.CB = prvDCMI_DummyCB; + } + prvDCMI.pUserData = pData; +} + +void DCMI_SetCROPConfig(uint8_t OnOff, uint32_t VStart, uint32_t HStart, uint32_t VLen, uint32_t HLen) +{ + if (OnOff) + { + /* Sets the CROP window coordinates */ + DCMI->CWSTRTR = (VStart << 16)|HStart; + + /* Sets the CROP window size */ + DCMI->CWSIZER = (VLen << 16)|HLen; + DCMI->CR |= DCMI_CR_CROP; + } + else + { + DCMI->CR &= ~DCMI_CR_CROP; + } +} +/** + * @brief 摄像头捕获开关 + * + * @param OnOff 0: 关 1: 开 + */ +void DCMI_CaptureSwitch(uint8_t OnOff, uint32_t BufLen, uint32_t ImageW, uint32_t ImageH, uint8_t DataByte, uint32_t *OutH) +{ + uint32_t i; + uint32_t WDataLen, HLen; + if (OnOff) + { + if (DCMI->CR & DCMI_CR_CAPTURE) return; + if (!BufLen) + { + WDataLen = (ImageW * DataByte) >> 2; + if (ImageH > 100) + { + if (!(ImageH % 10)) + { + HLen = ImageH / 10; + } + else + { + HLen = ImageH >> 1; + } + } + else + { + HLen = ImageH >> 1; + } + while( (WDataLen * HLen) > 2048) + { + HLen >>= 1; + } + BufLen = WDataLen * HLen; + DBG("buf %u, H %u", BufLen, HLen); + *OutH = HLen; + } + for(i = 0; i < DCMI_RXBUF_BAND; i++) + { + prvDCMI.uBuf[i].pu32 = OS_Malloc(BufLen * sizeof(uint32_t)); + } + prvDCMI.RxDMASn = 0; + prvDCMI.BufLen = BufLen; + DMA_ClearStreamFlag(DCMI_RX_DMA_STREAM); + DMA_ForceStartStream(DCMI_RX_DMA_STREAM, prvDCMI.uBuf[0].pu32, prvDCMI.BufLen, prvDCMI_DMADone, NULL, 1); + DCMI->ICR = 0x1f; + ISR_OnOff(DCMI_IRQn, 1); + DCMI->CR |= DCMI_CR_CAPTURE|DCMI_CR_ENABLE; + } + else + { + DMA_StopStream(DCMI_RX_DMA_STREAM); + DCMI->CR &= ~(DCMI_CR_CAPTURE|DCMI_CR_ENABLE|DCMI_CR_CM); + DCMI->CR |= (1 << 21); + ISR_OnOff(DCMI_IRQn, 0); + DCMI->ICR = 0x1f; + ISR_Clear(DCMI_IRQn); + for(i = 0; i < DCMI_RXBUF_BAND; i++) + { + if (prvDCMI.uBuf[i].pu32) + { + OS_Free(prvDCMI.uBuf[i].pu32); + prvDCMI.uBuf[i].pu32 = 0; + } + } + } +} + diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_dma.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_dma.c new file mode 100644 index 0000000000..4de24a03f1 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_dma.c @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "user.h" +typedef struct +{ + const DMA_TypeDef *RegBase; + const uint32_t Index; + CBFuncEx_t CB; + void *pData; + uint8_t TxDir; +}DMAChannal_struct; + +/************ operation definition for DMA DMA_CTL_H REGISTER ************/ +#define DMA_CTL_BLOCK_TS_Pos (0) +#define DMA_CTL_BLOCK_TS_Mask (0x0fffU<ChEnReg_L & BaseIndex) + { + return 1; + } + + return 0; +} + +void DMA_BaseConfig(void *Config) +{ + DMA_InitTypeDef *DMA_InitStruct = (DMA_InitTypeDef *)Config; + memset(DMA_InitStruct, 0, sizeof(DMA_InitTypeDef)); + DMA_InitStruct->DMA_PeripheralBurstSize = DMA_BurstSize_1; + DMA_InitStruct->DMA_PeripheralDataSize = DMA_DataSize_Byte; + DMA_InitStruct->DMA_PeripheralInc = DMA_Inc_Nochange; + DMA_InitStruct->DMA_MemoryBurstSize = DMA_BurstSize_1; + DMA_InitStruct->DMA_MemoryDataSize = DMA_DataSize_Byte; + DMA_InitStruct->DMA_MemoryInc = DMA_Inc_Increment; +} + +int DMA_ConfigStream(uint8_t Stream, void *Config) +{ + DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase; + uint32_t tmpChannelxBit = hwDMAChannal[Stream].Index; + DMA_InitTypeDef *DMA_InitStruct = (DMA_InitTypeDef *)Config; + if (DMA->ChEnReg_L & tmpChannelxBit) + { + return -1; + } + DMA->ClearTfr_L = tmpChannelxBit; + DMA->ClearBlock_L = tmpChannelxBit; + DMA->ClearSrcTran_L = tmpChannelxBit; + DMA->ClearDstTran_L = tmpChannelxBit; + DMA->ClearErr_L = tmpChannelxBit; + if((DMA->RawBlock_L & tmpChannelxBit) | (DMA->RawDstTran_L & tmpChannelxBit) | (DMA->RawErr_L & tmpChannelxBit) \ + | (DMA->RawSrcTran_L & tmpChannelxBit) | (DMA->RawTfr_L & tmpChannelxBit) | (DMA->StatusBlock_L & tmpChannelxBit) \ + | (DMA->StatusDstTran_L & tmpChannelxBit) | (DMA->StatusErr_L & tmpChannelxBit) | (DMA->StatusSrcTran_L & tmpChannelxBit) \ + | (DMA->StatusTfr_L & tmpChannelxBit) ) + { + return -1; + } + switch(DMA_InitStruct->DMA_Peripheral) + { + case SYSCTRL_PHER_CTRL_DMA_CHx_IF_LCD: + case SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART0_TX: + case SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART1_TX: + case SYSCTRL_PHER_CTRL_DMA_CHx_IF_DAC: + case SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI0_TX: + case SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI1_TX: + case SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI2_TX: + case SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART2_TX: + case SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART3_TX: + case SYSCTRL_PHER_CTRL_DMA_CHx_IF_I2C_TX: + case SYSCTRL_PHER_CTRL_DMA_CHx_IF_QSPI_TX: + case SYSCTRL_PHER_CTRL_DMA_CHx_IF_HSPI_TX: + hwDMA->SAR_L = DMA_InitStruct->DMA_MemoryBaseAddr; + hwDMA->DAR_L = DMA_InitStruct->DMA_PeripheralBaseAddr; + hwDMA->CTL_L = DMA_CTL_TT_FC_Memory_to_Peripheral_Set| + (DMA_InitStruct->DMA_MemoryBurstSize << DMA_CTL_SRC_MSIZE_Pos)| + (DMA_InitStruct->DMA_PeripheralBurstSize << DMA_CTL_DEST_MSIZE_Pos)| + (DMA_InitStruct->DMA_MemoryInc << DMA_CTL_SINC_Pos)| + (DMA_InitStruct->DMA_PeripheralInc << DMA_CTL_DINC_Pos)| + (DMA_InitStruct->DMA_MemoryDataSize << DMA_CTL_SRC_TR_WIDTH_Pos)| + (DMA_InitStruct->DMA_PeripheralDataSize << DMA_CTL_DST_TR_WIDTH_Pos); + + hwDMAChannal[Stream].TxDir = 1; +// hwDMA->CFG_L = (1 << 18); + hwDMA->CFG_L = 0; + break; + default: + hwDMA->SAR_L = DMA_InitStruct->DMA_PeripheralBaseAddr; + hwDMA->DAR_L = DMA_InitStruct->DMA_MemoryBaseAddr; + hwDMA->CTL_L = DMA_CTL_TT_FC_Peripheral_to_Memory_Set| + (DMA_InitStruct->DMA_PeripheralBurstSize << DMA_CTL_SRC_MSIZE_Pos)| + (DMA_InitStruct->DMA_MemoryBurstSize << DMA_CTL_DEST_MSIZE_Pos)| + (DMA_InitStruct->DMA_PeripheralInc << DMA_CTL_SINC_Pos)| + (DMA_InitStruct->DMA_MemoryInc << DMA_CTL_DINC_Pos)| + (DMA_InitStruct->DMA_PeripheralDataSize << DMA_CTL_SRC_TR_WIDTH_Pos)| + (DMA_InitStruct->DMA_MemoryDataSize << DMA_CTL_DST_TR_WIDTH_Pos); + hwDMAChannal[Stream].TxDir = 0; + hwDMA->CFG_L = 0; + break; + } + hwDMA->CFG_L |= DMA_InitStruct->DMA_Priority; + hwDMA->CFG_H |= (Stream << DMA_CFG_DEST_PER_Pos) | (Stream << DMA_CFG_SRC_PER_Pos); + + if (Stream <= DMA1_STREAM_3) + { + tmpChannelxBit = (Stream - DMA1_STREAM_0) * 8; + SYSCTRL->DMA_CHAN = (SYSCTRL->DMA_CHAN & ~(0x0000003f << tmpChannelxBit)) | (DMA_InitStruct->DMA_Peripheral << tmpChannelxBit); + } + else + { + tmpChannelxBit = (Stream - DMA1_STREAM_4) * 8; + SYSCTRL->DMA_CHAN1 = (SYSCTRL->DMA_CHAN1 & ~(0x0000003f << tmpChannelxBit)) | (DMA_InitStruct->DMA_Peripheral << tmpChannelxBit); + } + return 0; +} + +int DMA_StartStream(uint8_t Stream, const void *Data, uint32_t Len, CBFuncEx_t CB, void *pUserData, uint8_t NeedIrq) +{ + uint32_t tmpChannelxBit = hwDMAChannal[Stream].Index; + if (DMA->ChEnReg_L & tmpChannelxBit) + { + return -1; + } + DMA_ForceStartStream(Stream, Data, Len, CB, pUserData, NeedIrq); + return 0; +} + +void DMA_ForceStartStream(uint8_t Stream, const void *Data, uint32_t Len, CBFuncEx_t CB, void *pUserData, uint8_t NeedIrq) +{ + DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase; + volatile uint32_t tmpChannelxBit = hwDMAChannal[Stream].Index; + DMA->ChEnReg_L = (tmpChannelxBit << 8); + while(DMA->ChEnReg_L & tmpChannelxBit) {;} + + if (hwDMAChannal[Stream].TxDir) + { + hwDMA->SAR_L = (uint32_t)Data; + } + else + { + hwDMA->DAR_L = (uint32_t)Data; + } + hwDMA->CTL_H &= ~DMA_CTL_BLOCK_TS_Mask; + hwDMA->CTL_H |= Len; + + tmpChannelxBit = (tmpChannelxBit << 8) + tmpChannelxBit; + if (NeedIrq) + { + hwDMA->CTL_L |= DMA_CTL_INT_EN_Set; + } + else + { + hwDMA->CTL_L &= ~DMA_CTL_INT_EN_Set; + } + hwDMAChannal[Stream].pData = pUserData; + if (CB) + { + hwDMAChannal[Stream].CB = CB; + } + else + { + hwDMAChannal[Stream].CB = DMA_DummyCB; + } + DMA->ChEnReg_L = tmpChannelxBit; +} + +void DMA_ClearStreamFlag(uint8_t Stream) +{ + DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase; + uint32_t tmpChannelxBit = hwDMAChannal[Stream].Index; + DMA->ClearTfr_L = tmpChannelxBit; + DMA->ClearBlock_L = tmpChannelxBit; + DMA->ClearSrcTran_L = tmpChannelxBit; + DMA->ClearDstTran_L = tmpChannelxBit; + DMA->ClearErr_L = tmpChannelxBit; +} + +void DMA_StopStream(uint8_t Stream) +{ + if (Stream >= DMA_STREAM_QTY) return; + DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase; + uint32_t tmpChannelxBit = hwDMAChannal[Stream].Index; + DMA->ChEnReg_L = (tmpChannelxBit << 8); + DMA->ClearTfr_L = tmpChannelxBit; + DMA->ClearBlock_L = tmpChannelxBit; + DMA->ClearSrcTran_L = tmpChannelxBit; + DMA->ClearDstTran_L = tmpChannelxBit; + DMA->ClearErr_L = tmpChannelxBit; +} + +uint32_t DMA_GetRemainingDataLength(uint8_t Stream) +{ + return 0; +} + +uint32_t DMA_GetDataLength(uint8_t Stream, uint32_t FirstAddress) +{ + DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase; + return (hwDMA->CTL_H); +} + +static void DMA_IrqHandle(int32_t IrqLine, void *pData) +{ + uint32_t i; +// DBG("%x", DMA->StatusTfr_L); + if (DMA->StatusInt_L & (1 << 0)) + { + for(i = 0; i < DMA_STREAM_QTY; i++) + { + if (DMA->StatusTfr_L & (1 << i)) + { + DMA->ClearTfr_L = (1 << i); + hwDMAChannal[i].CB(hwDMAChannal[i].pData, 0); + } + } + } + if (DMA->StatusInt_L & (1 << 4)) + { + for(i = 0; i < DMA_STREAM_QTY; i++) + { + if (DMA->StatusErr_L & (1 << i)) + { + DMA->ClearErr_L = (1 << i); + hwDMAChannal[i].CB(hwDMAChannal[i].pData, 0xffffffff); + } + } + } + DMA->ClearBlock_L = 0x000000ff; + DMA->ClearSrcTran_L = 0x000000ff; + DMA->ClearDstTran_L = 0x000000ff; +} + +void DMA_GlobalInit(void) +{ + ISR_SetHandler(DMA_IRQn, DMA_IrqHandle, NULL); +#ifdef __BUILD_OS__ + ISR_SetPriority(DMA_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 2); +#else + ISR_SetPriority(DMA_IRQn, 3); +#endif + DMA->DmaCfgReg_L = 1; + DMA->ChEnReg_L = 0x0000ff00; + ISR_OnOff(DMA_IRQn, 1); + DMA->MaskTfr_L = 0x0000ffff; + DMA->MaskErr_L = 0x0000ffff; +} + +void DMA_PrintReg(uint8_t Stream) +{ + DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase; + DBG("%d, %d, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x", Stream, hwDMAChannal[Stream].TxDir, hwDMA->SAR_L, hwDMA->DAR_L, hwDMA->CTL_H, hwDMA->CTL_L, hwDMA->CFG_L); +} + +void DMA_PrintGlobalReg(void) +{ + DBG("global 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x", SYSCTRL->DMA_CHAN, SYSCTRL->DMA_CHAN1, DMA->StatusTfr_L, + DMA->StatusErr_L, DMA->ChEnReg_L, DMA->DmaCfgReg_L); +} diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_flash.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_flash.c new file mode 100644 index 0000000000..98f6ac81de --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_flash.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "bl_inc.h" +#if 0 +void CACHE_CleanAll(CACHE_TypeDef *Cache) +{ + while (Cache->CACHE_CS & CACHE_IS_BUSY); + + Cache->CACHE_REF = CACHE_REFRESH_ALLTAG; + Cache->CACHE_REF |= CACHE_REFRESH; + while ((Cache->CACHE_REF & CACHE_REFRESH)); +} + +/** + * @brief Flash Erase Sector. + * @param sectorAddress: The sector address to be erased + * @retval FLASH Status: The returned value can be: QSPI_STATUS_ERROR, QSPI_STATUS_OK + */ +uint8_t FLASH_EraseSector(uint32_t sectorAddress) +{ + uint8_t ret; + + __disable_irq(); + //__disable_fault_irq(); + + ret = ROM_QSPI_EraseSector(NULL, sectorAddress); + + //__enable_fault_irq(); + __enable_irq(); + + return ret; +} + +/** + * @brief Flash Program Interface. + * @param addr: specifies the address to be programmed. + * @param size: specifies the size to be programmed. + * @param buffer: pointer to the data to be programmed, need word aligned + * @retval FLASH Status: The returned value can be: QSPI_STATUS_ERROR, QSPI_STATUS_OK + */ +uint8_t FLASH_ProgramPage(uint32_t addr, uint32_t size, uint8_t *buffer) +{ + uint8_t ret; + QSPI_CommandTypeDef cmdType; + + cmdType.Instruction = QUAD_INPUT_PAGE_PROG_CMD; + cmdType.BusMode = QSPI_BUSMODE_114; + cmdType.CmdFormat = QSPI_CMDFORMAT_CMD8_ADDR24_PDAT; + + __disable_irq(); + //__disable_fault_irq(); + + ret = ROM_QSPI_ProgramPage(&cmdType, DMA_Channel_1, addr, size, buffer); + + //__enable_fault_irq(); + __enable_irq(); + + return ret; +} + + +int Flash_EraseSector(uint32_t address, uint8_t NeedCheck) +{ + uint8_t buf[256]; + uint32_t i; + uint8_t retry = 1; + void *res; + memset(buf, 0xff, 256); +BL_ERASESECTOR_AGAIN: + FLASH_EraseSector(address); + CACHE_CleanAll(CACHE); + if (!NeedCheck) return ERROR_NONE; + for(i = 0; i < 4096; i+=256) + { + res = memcmp(address + i, buf, 256); + if (res) + { + DBG_INFO("%x", res); + if (retry) + { + retry = 0; + goto BL_ERASESECTOR_AGAIN; + } + else + { + return -1; + } + } + } + return 0; +} + +int Flash_ProgramData(uint32_t address, uint32_t *Data, uint32_t Len, uint8_t NeedCheck) +{ + void *res; + uint32_t size = (Len + (4 - 1)) & (~(4 - 1)); + if (size > 256) + { + size = 256; + } + FLASH_ProgramPage(address, size, Data); + CACHE_CleanAll(CACHE); + if (!NeedCheck) return ERROR_NONE; + res = memcmp(address, Data, Len); + if (res) + { + DBG_INFO("%x", res); + FLASH_ProgramPage(address, size, Data); + CACHE_CleanAll(CACHE); + res = memcmp(address, Data, size); + if (res) + { + DBG_INFO("%x", res); + return -1; + } + } + return 0; +} + +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_gpio.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_gpio.c new file mode 100644 index 0000000000..9a43a16b80 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_gpio.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "user.h" +typedef struct +{ + volatile GPIO_TypeDef *RegBase; + const int32_t IrqLine; + uint16_t ODBitMap; + +}GPIO_ResourceStruct; + +typedef struct +{ + CBFuncEx_t AllCB; + CBFuncEx_t HWTimerCB; + void *pParam; +}GPIO_CtrlStruct; + +static GPIO_CtrlStruct prvGPIO; + +static GPIO_ResourceStruct prvGPIO_Resource[6] = +{ + { + GPIOA, + EXTI0_IRQn, + 0, + }, + { + GPIOB, + EXTI1_IRQn, + 0, + }, + { + GPIOC, + EXTI2_IRQn, + 0, + }, + { + GPIOD, + EXTI3_IRQn, + 0, + }, + { + GPIOE, + EXTI4_IRQn, + 0, + }, + { + GPIOF, + EXTI5_IRQn, + 0, + }, +}; + +static int32_t GPIO_IrqDummyCB(void *pData, void *pParam) +{ +// DBG("%d", pData); + return 0; +} +static void __FUNC_IN_RAM__ GPIO_IrqHandle(int32_t IrqLine, void *pData) +{ + volatile uint32_t Port = (uint32_t)pData; + volatile uint32_t Sn, i; + if (GPIO->INTP_TYPE_STA[Port].INTP_STA) + { + Sn = GPIO->INTP_TYPE_STA[Port].INTP_STA; + GPIO->INTP_TYPE_STA[Port].INTP_STA = 0xffff; + prvGPIO.HWTimerCB((Port << 16) | Sn, prvGPIO.pParam); + Port = (Port << 4); + + for(i = 0; i < 16; i++) + { + if (Sn & (1 << i)) + { + prvGPIO.AllCB((void *)(Port+i), 0); + } + } + } + ISR_Clear(IrqLine); +} + +void GPIO_GlobalInit(CBFuncEx_t Fun) +{ + uint32_t i; + if (Fun) + { + prvGPIO.AllCB = Fun; + } + else + { + prvGPIO.AllCB = GPIO_IrqDummyCB; + } + prvGPIO.HWTimerCB = GPIO_IrqDummyCB; + for(i = 0; i < 6; i++) + { + GPIO->INTP_TYPE_STA[i].INTP_TYPE = 0; + GPIO->INTP_TYPE_STA[i].INTP_STA = 0xffff; +#ifdef __BUILD_OS__ + ISR_SetPriority(prvGPIO_Resource[i].IrqLine, IRQ_MAX_PRIORITY + 1); +#else + ISR_SetPriority(prvGPIO_Resource[i].IrqLine, 3); +#endif + ISR_SetHandler(prvGPIO_Resource[i].IrqLine, GPIO_IrqHandle, (void *)i); + ISR_OnOff(prvGPIO_Resource[i].IrqLine, 1); + } + +} + +void __FUNC_IN_RAM__ GPIO_Config(uint32_t Pin, uint8_t IsInput, uint8_t InitValue) +{ + uint8_t Port = (Pin >> 4); + uint8_t orgPin = Pin; + Pin = 1 << (Pin & 0x0000000f); + GPIO_Iomux(orgPin, 1); + if (IsInput) + { + prvGPIO_Resource[Port].RegBase->OEN |= Pin; + } + else + { + prvGPIO_Resource[Port].RegBase->BSRR |= InitValue?Pin:(Pin << 16); + prvGPIO_Resource[Port].RegBase->OEN &= ~Pin; + } + prvGPIO_Resource[Port].ODBitMap &= ~Pin; +} + +void __FUNC_IN_RAM__ GPIO_ODConfig(uint32_t Pin, uint8_t InitValue) +{ + uint8_t Port = (Pin >> 4); + uint8_t orgPin = Pin; + Pin = 1 << (Pin & 0x0000000f); + GPIO_Iomux(orgPin, 1); + prvGPIO_Resource[Port].RegBase->OEN |= Pin; + if (InitValue) + { + prvGPIO_Resource[Port].RegBase->PUE |= Pin; + } + else + { + prvGPIO_Resource[Port].RegBase->PUE &= ~Pin; + } + prvGPIO_Resource[Port].ODBitMap |= Pin; +} + +void __FUNC_IN_RAM__ GPIO_PullConfig(uint32_t Pin, uint8_t IsPull, uint8_t IsUp) +{ + uint8_t Port = (Pin >> 4); + Pin = 1 << (Pin & 0x0000000f); + if (IsPull && IsUp) + { + prvGPIO_Resource[Port].RegBase->PUE |= Pin; + } + else + { + prvGPIO_Resource[Port].RegBase->PUE &= ~Pin; + } +} + +void GPIO_ExtiConfig(uint32_t Pin, uint8_t IsLevel, uint8_t IsRiseHigh, uint8_t IsFallLow) +{ + uint8_t Port = (Pin >> 4); + uint32_t Type = 0; + uint32_t Mask = ~(0x03 << ((Pin & 0x0000000f) * 2)); + if (!IsLevel) + { + if (IsRiseHigh && IsFallLow) + { + Type = 0x03 << ((Pin & 0x0000000f) * 2); + } + else if (IsFallLow) + { + Type = 0x02 << ((Pin & 0x0000000f) * 2); + } + else if (IsRiseHigh) + { + Type = 0x01 << ((Pin & 0x0000000f) * 2); + } + } + GPIO->INTP_TYPE_STA[Port].INTP_TYPE = (GPIO->INTP_TYPE_STA[Port].INTP_TYPE & Mask) | Type; +} + +void GPIO_ExtiSetHWTimerCB(CBFuncEx_t CB, void *pParam) +{ + if (CB) + { + prvGPIO.HWTimerCB = CB; + } + else + { + prvGPIO.HWTimerCB = GPIO_IrqDummyCB; + } + prvGPIO.pParam = pParam; +} + +void __FUNC_IN_RAM__ GPIO_Iomux(uint32_t Pin, uint32_t Function) +{ + uint8_t Port = (Pin >> 4); + uint32_t Mask = ~(0x03 << ((Pin & 0x0000000f) * 2)); + Function = Function << ((Pin & 0x0000000f) * 2); + GPIO->ALT[Port] = (GPIO->ALT[Port] & Mask) | Function; +} + +void __FUNC_IN_RAM__ GPIO_Output(uint32_t Pin, uint8_t Level) +{ + uint8_t Port = (Pin >> 4); + Pin = 1 << (Pin & 0x0000000f); + if (prvGPIO_Resource[Port].ODBitMap & Pin) + { + if (Level) + { + prvGPIO_Resource[Port].RegBase->PUE |= Pin; + } + else + { + prvGPIO_Resource[Port].RegBase->PUE &= ~Pin; + } + } + else + { + prvGPIO_Resource[Port].RegBase->BSRR |= Level?Pin:(Pin << 16); + } + +// DBG("%d, %x, %x, %x",Port, Pin, prvGPIO_Resource[Port].RegBase, prvGPIO_Resource[Port].RegBase->IODR); +} + +uint8_t __FUNC_IN_RAM__ GPIO_Input(uint32_t Pin) +{ + uint8_t Port = (Pin >> 4); + Pin = 1 << (Pin & 0x0000000f); + return (prvGPIO_Resource[Port].RegBase->IODR & (Pin << 16))?1:0; +} + +void __FUNC_IN_RAM__ GPIO_OutputMulti(uint32_t Port, uint32_t Pins, uint32_t Level) +{ + prvGPIO_Resource[Port].RegBase->BSRR |= Level?Pins:(Pins << 16); +} + +uint32_t __FUNC_IN_RAM__ GPIO_InputMulti(uint32_t Port) +{ + return (prvGPIO_Resource[Port].RegBase->IODR >> 16); +} diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_hwtimer.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_hwtimer.c new file mode 100644 index 0000000000..1383d1cf94 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_hwtimer.c @@ -0,0 +1,465 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "user.h" +typedef struct +{ +// const I2C_TypeDef *RegBase; + const int IrqLine; + OPQueue_CmdStruct *Cmd; + Buffer_Struct InDataBuf; + CBFuncEx_t CmdDoneCB; + void *pCmdDoneParam; + uint32_t TotalCount; + uint32_t TotalRepeat; + uint32_t CurCount; + uint32_t RepeatCnt; + uint32_t CmdQueuePos; + uint32_t CapturePin; + uint8_t IsQueueRunning; + uint8_t ContinueDelay; +}HWTimer_CtrlStruct; + +static HWTimer_CtrlStruct prvHWTimer[HW_TIMER_MAX] = { + { +// TIMM0, + TIM0_0_IRQn, + NULL, + { + NULL, 0, 0, + } + }, + { +// TIMM0, + TIM0_1_IRQn, + NULL, + { + NULL, 0, 0, + } + }, + { +// TIMM0, + TIM0_2_IRQn, + NULL, + { + NULL, 0, 0, + } + }, + { +// TIMM0, + TIM0_3_IRQn, + NULL, + { + NULL, 0, 0, + } + }, + { +// TIMM0, + TIM0_4_IRQn, + NULL, + { + NULL, 0, 0, + } + }, + { +// TIMM0, + TIM0_5_IRQn, + NULL, + { + NULL, 0, 0, + } + }, +}; + +static void prvHWTimer_IrqHandlerOperationQueue( int32_t Line, void *pData); +static void prvHWTimer_StartOperationQueue(uint8_t HWTimerID, HWTimer_CtrlStruct *HWTimer); + +static int32_t prvHWTimer_DummyCB(void *pData, void *pParam) +{ + return 0; +} + +static void prvHWTimer_IrqHandlerEndOperationQueue( int32_t Line, void *pData) +{ + uint32_t HWTimerID = (uint32_t)pData; + HWTimer_Stop(HWTimerID); + prvHWTimer[HWTimerID].CmdDoneCB(0, prvHWTimer[HWTimerID].pCmdDoneParam); +} + +static int32_t __FUNC_IN_RAM__ prvHWTimer_OperationQueuExti(void *pData, void *pParam) +{ + uint32_t HWTimerID = (uint32_t)pParam; + uint32_t pin = (uint32_t)pData; +// DBG("%x,%x", pin, prvHWTimer[HWTimerID].CapturePin); + if ((pin & prvHWTimer[HWTimerID].CapturePin) == prvHWTimer[HWTimerID].CapturePin) + { + prvHWTimer_StartOperationQueue(HWTimerID, &prvHWTimer[HWTimerID]); + } + return 0; +} + + +static void __FUNC_IN_RAM__ prvHWTimer_StartOperationQueue(uint8_t HWTimerID, HWTimer_CtrlStruct *HWTimer) +{ + volatile uint32_t Period; + while(HWTimer->IsQueueRunning) + { + +// DBG("%u, %u, %u, %u, %u, %u, %u, %u, %u, %x, %x", HWTimer->TotalRepeat, HWTimer->RepeatCnt, +// HWTimer->TotalCount, HWTimer->CurCount, HWTimer->Cmd[HWTimer->CurCount].Operation, +// HWTimer->Cmd[HWTimer->CurCount].Arg1, HWTimer->Cmd[HWTimer->CurCount].uArg.IOArg.Level, +// HWTimer->Cmd[HWTimer->CurCount].uArg.IOArg.PullMode, HWTimer->Cmd[HWTimer->CurCount].uArg.Time, +// HWTimer->Cmd[HWTimer->CurCount].CB, HWTimer->Cmd[HWTimer->CurCount].pParam); + + switch(HWTimer->Cmd[HWTimer->CurCount].Operation) + { + case OP_QUEUE_CMD_GPIO_OUT: + GPIO_Output(HWTimer->Cmd[HWTimer->CurCount].Arg1, HWTimer->Cmd[HWTimer->CurCount].uArg.IOArg.Level); + HWTimer->CurCount++; + break; + case OP_QUEUE_CMD_GPIO_IN: + HWTimer->Cmd[HWTimer->CurCount].uArg.IOArg.Level = GPIO_Input(HWTimer->Cmd[HWTimer->CurCount].Arg1); + BSP_SetBit(HWTimer->InDataBuf.Data, HWTimer->InDataBuf.Pos, HWTimer->Cmd[HWTimer->CurCount].uArg.IOArg.Level); + HWTimer->CurCount++; + break; + case OP_QUEUE_CMD_ONE_TIME_DELAY: + HWTimer->ContinueDelay = 0; + goto START_HWTIMER; + break; + case OP_QUEUE_CMD_REPEAT_DELAY: + HWTimer->CurCount++; + return; + break; + case OP_QUEUE_CMD_CAPTURE: + if (!TIMM0->TIM[HWTimerID].ControlReg) + { + HWTimer->Cmd[HWTimer->CurCount + 1].Operation = OP_QUEUE_CMD_CAPTURE_END; + } + else + { + HWTimer->Cmd[HWTimer->CurCount].uParam.MaxCnt = TIMM0->TIM[HWTimerID].LoadCount - TIMM0->TIM[HWTimerID].CurrentValue; + HWTimer->Cmd[HWTimer->CurCount].uArg.IOArg.Level = GPIO_Input(HWTimer->Cmd[HWTimer->CurCount].Arg1); + } + HWTimer->CurCount++; + if (OP_QUEUE_CMD_CAPTURE_END != HWTimer->Cmd[HWTimer->CurCount + 1].Operation) + { + return; + } + break; + case OP_QUEUE_CMD_CONTINUE_DELAY: + HWTimer->ContinueDelay = 1; + goto START_HWTIMER; + break; + + case OP_QUEUE_CMD_SET_GPIO_DIR_OUT: + GPIO_Config(HWTimer->Cmd[HWTimer->CurCount].Arg1, 0, HWTimer->Cmd[HWTimer->CurCount].uArg.IOArg.Level); + GPIO_PullConfig(HWTimer->Cmd[HWTimer->CurCount].Arg1, HWTimer->Cmd[HWTimer->CurCount].uArg.IOArg.PullMode, (HWTimer->Cmd[HWTimer->CurCount].uArg.IOArg.PullMode > 1)?0:1); + HWTimer->CurCount++; + break; + case OP_QUEUE_CMD_SET_GPIO_DIR_IN: + GPIO_PullConfig(HWTimer->Cmd[HWTimer->CurCount].Arg1, HWTimer->Cmd[HWTimer->CurCount].uArg.IOArg.PullMode, (HWTimer->Cmd[HWTimer->CurCount].uArg.IOArg.PullMode > 1)?0:1); + GPIO_Config(HWTimer->Cmd[HWTimer->CurCount].Arg1, 1, 0); + HWTimer->CurCount++; + break; + case OP_QUEUE_CMD_CB: + HWTimer->Cmd[HWTimer->CurCount].CB(HWTimerID, HWTimer->Cmd[HWTimer->CurCount].uParam.pParam); + HWTimer->CurCount++; + break; + case OP_QUEUE_CMD_CAPTURE_SET: + GPIO_PullConfig(HWTimer->Cmd[HWTimer->CurCount].Arg1, HWTimer->Cmd[HWTimer->CurCount].uArg.ExitArg.PullMode, (HWTimer->Cmd[HWTimer->CurCount].uArg.ExitArg.PullMode > 1)?0:1); + GPIO_Config(HWTimer->Cmd[HWTimer->CurCount].Arg1, 1, 0); + HWTimer->CapturePin = HWTimer->Cmd[HWTimer->CurCount].Arg1 & 0xf0; + HWTimer->CapturePin = (HWTimer->CapturePin << 12) | (1 << (HWTimer->Cmd[HWTimer->CurCount].Arg1 & 0x0000000f)); + TIMM0->TIM[HWTimerID].ControlReg = 0; + TIMM0->TIM[HWTimerID].LoadCount = HWTimer->Cmd[HWTimer->CurCount].uParam.MaxCnt; + TIMM0->TIM[HWTimerID].ControlReg = TIMER_CONTROL_REG_TIMER_ENABLE|TIMER_CONTROL_REG_TIMER_MODE; + GPIO_ExtiSetHWTimerCB(prvHWTimer_OperationQueuExti, HWTimerID); + prvHWTimer[HWTimerID].ContinueDelay = 0; + switch(HWTimer->Cmd[HWTimer->CurCount].uArg.ExitArg.ExtiMode) + { + case OP_QUEUE_CMD_IO_EXTI_BOTH: + GPIO_ExtiConfig(HWTimer->Cmd[HWTimer->CurCount].Arg1, 0, 1, 1); + break; + case OP_QUEUE_CMD_IO_EXTI_UP: + GPIO_ExtiConfig(HWTimer->Cmd[HWTimer->CurCount].Arg1, 0, 1, 0); + break; + case OP_QUEUE_CMD_IO_EXTI_DOWN: + GPIO_ExtiConfig(HWTimer->Cmd[HWTimer->CurCount].Arg1, 0, 0, 1); + break; + } + + HWTimer->CurCount++; + return; + break; + case OP_QUEUE_CMD_CAPTURE_END: + TIMM0->TIM[HWTimerID].ControlReg = 0; + GPIO_ExtiSetHWTimerCB(NULL, NULL); + HWTimer->CurCount++; + break; + case OP_QUEUE_CMD_END: + HWTimer->CurCount = 0; + HWTimer->RepeatCnt++; + if (HWTimer->RepeatCnt >= HWTimer->TotalRepeat) + { + TIMM0->TIM[HWTimerID].ControlReg = 0; + TIMM0->TIM[HWTimerID].LoadCount = 24; + + ISR_SetHandler(prvHWTimer[HWTimerID].IrqLine, prvHWTimer_IrqHandlerEndOperationQueue, HWTimerID); +#ifdef __BUILD_OS__ + ISR_SetPriority(prvHWTimer[HWTimerID].IrqLine, configLIBRARY_LOWEST_INTERRUPT_PRIORITY - 1); +#else + ISR_SetPriority(prvHWTimer[HWTimerID].IrqLine, 6); +#endif + TIMM0->TIM[HWTimerID].ControlReg = TIMER_CONTROL_REG_TIMER_ENABLE|TIMER_CONTROL_REG_TIMER_MODE; + return; + } + break; + } + } + return ; +START_HWTIMER: + TIMM0->TIM[HWTimerID].ControlReg = 0; + Period = HWTimer->Cmd[HWTimer->CurCount].uArg.Time; + Period = Period * SYS_TIMER_1US + HWTimer->Cmd[HWTimer->CurCount].Arg1; + TIMM0->TIM[HWTimerID].LoadCount = Period - 1; + TIMM0->TIM[HWTimerID].ControlReg = TIMER_CONTROL_REG_TIMER_ENABLE|TIMER_CONTROL_REG_TIMER_MODE; + HWTimer->CurCount++; + return ; +} + + + +static void __FUNC_IN_RAM__ prvHWTimer_IrqHandlerOperationQueue( int32_t Line, void *pData) +{ + uint32_t HWTimerID = (uint32_t)pData; + volatile uint32_t clr; + + clr = TIMM0->TIM[HWTimerID].EOI; + if (!prvHWTimer[HWTimerID].ContinueDelay) + { + TIMM0->TIM[HWTimerID].ControlReg = 0; + } + prvHWTimer_StartOperationQueue(HWTimerID, &prvHWTimer[HWTimerID]); +} + +void HWTimer_StartPWM(uint8_t HWTimerID, uint32_t HighCnt, uint32_t LowCnt, uint8_t IsOnePulse) +{ + if (!HighCnt) HighCnt = 1; + if (!LowCnt) LowCnt = 1; + TIMM0->TIM[HWTimerID].LoadCount = LowCnt - 1; + TIMM0->TIM_ReloadCount[HWTimerID] = HighCnt - 1; + if (IsOnePulse) + { + TIMM0->TIM[HWTimerID].ControlReg = TIMER_CONTROL_REG_PWM_SINGLE_PULSE|TIMER_CONTROL_REG_TIMER_PWM|TIMER_CONTROL_REG_TIMER_MODE|TIMER_CONTROL_REG_TIMER_ENABLE|TIMER_CONTROL_REG_TIMER_INTERRUPT;; + } + else + { + TIMM0->TIM[HWTimerID].ControlReg = TIMER_CONTROL_REG_TIMER_PWM|TIMER_CONTROL_REG_TIMER_MODE|TIMER_CONTROL_REG_TIMER_ENABLE|TIMER_CONTROL_REG_TIMER_INTERRUPT; + } +} + +void HWTimer_SetPWM(uint8_t HWTimerID, uint32_t Period, uint16_t Duty, uint8_t IsOnePulse) +{ + uint32_t TotalCnt; + uint32_t LowCnt, HighCnt; + if (Duty >= 999) return; + if (Period > (SystemCoreClock >> 3)) return; + switch(Period) + { + case 24000000: + LowCnt = 1; + HighCnt = 1; + break; + case 12000000: + LowCnt = 2; + HighCnt = 2; + break; + case 6000000: + LowCnt = 3; + HighCnt = 3; + break; + default: + TotalCnt = (SystemCoreClock >> 2) / Period; + HighCnt = (TotalCnt * Duty) / 1000; + if ((TotalCnt - HighCnt) < 1) + { + LowCnt = 1; + HighCnt = TotalCnt - LowCnt; + } + else + { + LowCnt = TotalCnt - HighCnt; + } + break; + } + HWTimer_StartPWM(HWTimerID, HighCnt, LowCnt, IsOnePulse); +// DBG("L %u, H %u", LowCnt, HighCnt); +// TIMM0->TIM[HWTimerID].LoadCount = LowCnt - 1; +// TIMM0->TIM_ReloadCount[HWTimerID] = HighCnt - 1; +// if (IsOnePulse) +// { +// TIMM0->TIM[HWTimerID].ControlReg = TIMER_CONTROL_REG_PWM_SINGLE_PULSE|TIMER_CONTROL_REG_TIMER_PWM|TIMER_CONTROL_REG_TIMER_MODE|TIMER_CONTROL_REG_TIMER_ENABLE|TIMER_CONTROL_REG_TIMER_INTERRUPT;; +// } +// else +// { +// TIMM0->TIM[HWTimerID].ControlReg = TIMER_CONTROL_REG_TIMER_PWM|TIMER_CONTROL_REG_TIMER_MODE|TIMER_CONTROL_REG_TIMER_ENABLE|TIMER_CONTROL_REG_TIMER_INTERRUPT; +// } +} + +void HWTimer_Stop(uint8_t HWTimerID) +{ + volatile uint32_t clr; + ISR_OnOff(prvHWTimer[HWTimerID].IrqLine, 0); + clr = TIMM0->TIM[HWTimerID].EOI; + TIMM0->TIM[HWTimerID].ControlReg = 0; + ISR_Clear(prvHWTimer[HWTimerID].IrqLine); + prvHWTimer[HWTimerID].IsQueueRunning = 0; + prvHWTimer[HWTimerID].ContinueDelay = 0; +} + +void HWTimer_InitOperationQueue(uint8_t HWTimerID, uint32_t nCount, uint32_t Repeat, uint32_t InputByte, CBFuncEx_t CmdDoneCB, void *pCmdDoneParam) +{ + if (prvHWTimer[HWTimerID].IsQueueRunning) + { + HWTimer_Stop(HWTimerID); + prvHWTimer[HWTimerID].CmdDoneCB(-ERROR_OPERATION_FAILED, prvHWTimer[HWTimerID].pCmdDoneParam); + } + prvHWTimer[HWTimerID].TotalCount = nCount; + prvHWTimer[HWTimerID].TotalRepeat = Repeat; + if (InputByte) + { + OS_ReInitBuffer(&prvHWTimer[HWTimerID].InDataBuf, InputByte); + } + else + { + OS_DeInitBuffer(&prvHWTimer[HWTimerID].InDataBuf); + } + if (prvHWTimer[HWTimerID].Cmd) + { + OS_Free(prvHWTimer[HWTimerID].Cmd); + prvHWTimer[HWTimerID].Cmd = NULL; + } + prvHWTimer[HWTimerID].Cmd = OS_Zalloc((nCount + 1) * sizeof(OPQueue_CmdStruct)); + prvHWTimer[HWTimerID].CmdQueuePos = 0; + if (CmdDoneCB) + { + prvHWTimer[HWTimerID].CmdDoneCB = CmdDoneCB; + } + else + { + prvHWTimer[HWTimerID].CmdDoneCB = prvHWTimer_DummyCB; + } + prvHWTimer[HWTimerID].pCmdDoneParam = pCmdDoneParam; +} + +void HWTimer_AddOperation(uint8_t HWTimerID, OPQueue_CmdStruct *pCmd) +{ + if (prvHWTimer[HWTimerID].TotalCount > prvHWTimer[HWTimerID].CmdQueuePos) + { + memcpy(&prvHWTimer[HWTimerID].Cmd[prvHWTimer[HWTimerID].CmdQueuePos], pCmd, sizeof(OPQueue_CmdStruct)); + prvHWTimer[HWTimerID].CmdQueuePos++; + } +} + + +static void HWTimer_ResetOperationQueue(uint8_t HWTimerID) +{ + prvHWTimer[HWTimerID].CurCount = 0; + prvHWTimer[HWTimerID].RepeatCnt = 0; + prvHWTimer[HWTimerID].InDataBuf.Pos = 0; + if (prvHWTimer[HWTimerID].InDataBuf.MaxLen) + { + memset(prvHWTimer[HWTimerID].InDataBuf.Data, 0, prvHWTimer[HWTimerID].InDataBuf.MaxLen); + } +} + + +void HWTimer_StartOperationQueue(uint8_t HWTimerID) +{ + if (prvHWTimer[HWTimerID].IsQueueRunning) + { + HWTimer_Stop(HWTimerID); + prvHWTimer[HWTimerID].CmdDoneCB(-ERROR_OPERATION_FAILED, prvHWTimer[HWTimerID].pCmdDoneParam); + } + else + { + HWTimer_Stop(HWTimerID); + } + ISR_SetHandler(prvHWTimer[HWTimerID].IrqLine, prvHWTimer_IrqHandlerOperationQueue, HWTimerID); + ISR_SetPriority(prvHWTimer[HWTimerID].IrqLine, HWTIMER_IRQ_LEVEL); + + prvHWTimer[HWTimerID].Cmd[prvHWTimer[HWTimerID].CmdQueuePos].Operation = OP_QUEUE_CMD_END; + HWTimer_ResetOperationQueue(HWTimerID); + prvHWTimer[HWTimerID].IsQueueRunning = 1; + prvHWTimer_StartOperationQueue(HWTimerID, &prvHWTimer[HWTimerID]); + ISR_OnOff(prvHWTimer[HWTimerID].IrqLine, 1); +} + +void HWTimer_ClearOperationQueue(uint8_t HWTimerID) +{ +// HWTimer_ResetOperationQueue(HWTimerID); + prvHWTimer[HWTimerID].CmdQueuePos = 0; +} + + +void HWTimer_FreeOperationQueue(uint8_t HWTimerID) +{ + OS_DeInitBuffer(&prvHWTimer[HWTimerID].InDataBuf); + OS_Free(prvHWTimer[HWTimerID].Cmd); + prvHWTimer[HWTimerID].Cmd = NULL; + prvHWTimer[HWTimerID].CmdDoneCB = prvHWTimer_DummyCB; +} + +void HWTimer_AddEndCmdInOperationQueue(uint8_t HWTimerID) +{ + HWTimer_CtrlStruct *HWTimer = &prvHWTimer[HWTimerID]; + if (HWTimer->Cmd[HWTimer->CurCount].Operation != OP_QUEUE_CMD_END) + { + HWTimer->Cmd[HWTimer->CurCount + 1].Operation = OP_QUEUE_CMD_END; + } +} + +uint8_t HWTimer_CheckOperationQueueDone(uint8_t HWTimerID) +{ + return !prvHWTimer[HWTimerID].IsQueueRunning; +} + +int HWTimer_GetOperationQueueInputResult(uint8_t HWTimerID, uint8_t *Value) +{ + memcpy(Value, prvHWTimer[HWTimerID].InDataBuf.Data, prvHWTimer[HWTimerID].InDataBuf.MaxLen); + return prvHWTimer[HWTimerID].InDataBuf.MaxLen; +} + +uint32_t HWTimer_GetOperationQueueCaptureResult(uint8_t HWTimerID, CBFuncEx_t CB, void *pParam) +{ + uint32_t i = 0; + uint32_t Cnt = 0; + if (!prvHWTimer[HWTimerID].Cmd) return 0; + for(i = 0; i < prvHWTimer[HWTimerID].CmdQueuePos; i++) + { + if (OP_QUEUE_CMD_CAPTURE == prvHWTimer[HWTimerID].Cmd[i].Operation) + { + CB(&prvHWTimer[HWTimerID].Cmd[i], pParam); + Cnt++; + } + } + return Cnt; +} diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_i2c.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_i2c.c new file mode 100644 index 0000000000..a1c452903b --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_i2c.c @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "user.h" +//#define IIC_DBG(X,Y...) +#define IIC_DBG DBG +enum +{ + I2C_STATE_FREE, + I2C_STATE_INIT_STOP, + I2C_STATE_ERROR_STOP, + I2C_STATE_WRITE_ADDRESS, + I2C_STATE_WRITE_REG, + I2C_STATE_WRITE_DATA, + I2C_STATE_WRITE_STOP, + I2C_STATE_READ_ADDRESS_WR, + I2C_STATE_READ_REG_WR, + I2C_STATE_READ_ADDRESS_RD, + I2C_STATE_READ_DATA_RD, + I2C_STATE_READ_STOP, +}; + +typedef struct +{ + const I2C_TypeDef *RegBase; + const int IrqLine; + Buffer_Struct DataBuf; + CBFuncEx_t Callback; + void *pParam; + HANDLE Sem; + I2C_CommonRegDataStruct *RegQueue; + uint32_t TotalQueueNum; + uint32_t CurQueuePos; + int32_t Result; + uint16_t TimeoutMs; + uint16_t ChipAddress; + uint8_t ChipAddressLen; + uint8_t RegAddress; + uint8_t State; + uint8_t IsBusy; + uint8_t IsBlockMode; +}I2C_CtrlStruct; +static I2C_CtrlStruct prvI2C = { + I2C0, + I2C0_IRQn, +}; + +static void prvI2C_Done(int32_t Result) +{ + prvI2C.State = I2C_STATE_FREE; + prvI2C.Result = Result; + prvI2C.IsBusy = 0; +#ifdef __BUILD_OS__ + if (prvI2C.IsBlockMode) OS_MutexRelease(prvI2C.Sem); +#endif + prvI2C.Callback(I2C_ID0, prvI2C.pParam); +} + +static int32_t prvI2C_DummyCB(void *pData, void *pParam) +{ + prvI2C.IsBusy = 0; +} + +static void I2C_IrqHandle(int32_t IrqLine, void *pData) +{ + I2C_TypeDef *I2C = prvI2C.RegBase; + uint32_t State = I2C->IC_RAW_INTR_STAT; + uint32_t RegValue = I2C->IC_CLR_INTR; + + switch(prvI2C.State) + { + case I2C_STATE_WRITE_ADDRESS: + case I2C_STATE_WRITE_REG: + case I2C_STATE_WRITE_DATA: + if (State & I2C_IT_TXE) + { + if (prvI2C.DataBuf.Pos >= prvI2C.DataBuf.MaxLen) + { + goto I2C_DONE; + } + else if ((prvI2C.DataBuf.MaxLen - prvI2C.DataBuf.Pos) > 1) + { + I2C->IC_DATA_CMD = prvI2C.DataBuf.Data[prvI2C.DataBuf.Pos]; + } + else + { + I2C->IC_DATA_CMD = prvI2C.DataBuf.Data[prvI2C.DataBuf.Pos]|I2C_IC_DATA_CMD_STOP; + } + prvI2C.DataBuf.Pos++; + } + break; + case I2C_STATE_READ_ADDRESS_WR: + if (State & I2C_IT_TXE) + { + prvI2C.State = I2C_STATE_READ_ADDRESS_RD; + if ((prvI2C.DataBuf.MaxLen - prvI2C.DataBuf.Pos) > 1) + { + I2C->IC_DATA_CMD = I2C_IC_DATA_CMD_CMD; + } + else + { + I2C->IC_DATA_CMD = I2C_IC_DATA_CMD_CMD|I2C_IC_DATA_CMD_STOP; + } + I2C->IC_INTR_MASK = I2C_IC_INTR_MASK_M_RX_FULL|I2C_IC_INTR_MASK_M_STOP_DET; + } + break; + case I2C_STATE_READ_ADDRESS_RD: + prvI2C.State = I2C_STATE_READ_DATA_RD; + case I2C_STATE_READ_DATA_RD: + if (State & I2C_IT_RXF) + { + prvI2C.DataBuf.Data[prvI2C.DataBuf.Pos] = I2C->IC_DATA_CMD & 0x00ff; + prvI2C.DataBuf.Pos++; + if (prvI2C.DataBuf.Pos >= prvI2C.DataBuf.MaxLen) + { + goto I2C_DONE; + } + else if ((prvI2C.DataBuf.MaxLen - prvI2C.DataBuf.Pos) > 1) + { + I2C->IC_DATA_CMD = I2C_IC_DATA_CMD_CMD; + } + else + { + I2C->IC_DATA_CMD = I2C_IC_DATA_CMD_CMD|I2C_IC_DATA_CMD_STOP; + } + } + break; + default: +// IIC_DBG("%x, %u", State, prvI2C.State); + break; + } + return; +I2C_DONE: + I2C->IC_INTR_MASK = 0; + prvI2C_Done(ERROR_NONE); +} + +static void I2C_IrqHandleRegQueue(int32_t IrqLine, void *pData) +{ + I2C_TypeDef *I2C = prvI2C.RegBase; + uint32_t State = I2C->IC_RAW_INTR_STAT; + uint32_t RegValue = I2C->IC_CLR_INTR; + if (State & I2C_IT_TXE) + { + if (prvI2C.DataBuf.Pos >= prvI2C.DataBuf.MaxLen) + { + prvI2C.CurQueuePos++; + if (prvI2C.CurQueuePos >= prvI2C.TotalQueueNum) + { + goto I2C_DONE; + } + else + { + Buffer_StaticInit(&prvI2C.DataBuf, prvI2C.RegQueue[prvI2C.CurQueuePos].Data, 2); + I2C->IC_DATA_CMD = prvI2C.DataBuf.Data[0]; + prvI2C.DataBuf.Pos++; + I2C->IC_INTR_MASK = I2C_IC_INTR_MASK_M_TX_EMPTY|I2C_IC_INTR_MASK_M_STOP_DET; + } + + } + else if ((prvI2C.DataBuf.MaxLen - prvI2C.DataBuf.Pos) > 1) + { + I2C->IC_DATA_CMD = prvI2C.DataBuf.Data[prvI2C.DataBuf.Pos]; + } + else + { + I2C->IC_DATA_CMD = prvI2C.DataBuf.Data[prvI2C.DataBuf.Pos]|I2C_IC_DATA_CMD_STOP; + } + prvI2C.DataBuf.Pos++; + } + return; +I2C_DONE: + I2C->IC_INTR_MASK = 0; + prvI2C_Done(ERROR_NONE); +} + +void I2C_GlobalInit(void) +{ + prvI2C.Callback = prvI2C_DummyCB; + ISR_SetHandler(prvI2C.IrqLine, I2C_IrqHandle, NULL); +#ifdef __BUILD_OS__ + prvI2C.Sem = OS_MutexCreate(); + ISR_SetPriority(prvI2C.IrqLine, configLIBRARY_LOWEST_INTERRUPT_PRIORITY - 1); +#else + ISR_SetPriority(prvI2C.IrqLine, 7); +#endif +} + +void I2C_MasterSetup(uint8_t I2CID, uint32_t Speed) +{ + I2C_TypeDef *I2C = prvI2C.RegBase; + uint32_t Cnt = ((SystemCoreClock >> 3) / Speed); + I2C->IC_ENABLE = 0; + while(I2C->IC_ENABLE_STATUS & I2C_IC_ENABLE_STATUS_IC_EN){;} + I2C->IC_SDA_HOLD = 5; + I2C->IC_SDA_SETUP = Cnt/3; + switch(Speed) + { + case 100000: + I2C->IC_SS_SCL_HCNT = Cnt - I2C->IC_FS_SPKLEN; + I2C->IC_SS_SCL_LCNT = Cnt; + I2C->IC_CON = I2C_IC_CON_RESTART_EN|I2C_IC_CON_SPEED_0|I2C_IC_CON_MASTER_MODE|I2C_IC_CON_SLAVE_DISABLE; + break; + case 400000: + I2C->IC_FS_SCL_HCNT = Cnt - I2C->IC_FS_SPKLEN; + I2C->IC_FS_SCL_LCNT = Cnt; + I2C->IC_CON = I2C_IC_CON_RESTART_EN|I2C_IC_CON_SPEED_1|I2C_IC_CON_MASTER_MODE|I2C_IC_CON_SLAVE_DISABLE; + break; + } + I2C->IC_ENABLE = 1; + I2C->IC_RX_TL = 0; + I2C->IC_TX_TL = 0; + I2C->IC_INTR_MASK = 0; + return; +} + +void I2C_Prepare(uint8_t I2CID, uint16_t ChipAddress, uint8_t ChipAddressLen, CBFuncEx_t CB, void *pParam) +{ + I2C_TypeDef *I2C = prvI2C.RegBase; + I2C->IC_ENABLE = 0; + while(I2C->IC_ENABLE_STATUS & I2C_IC_ENABLE_STATUS_IC_EN){;} + + switch(ChipAddressLen) + { + case 1: + I2C->IC_TAR = ChipAddress & 0x00ff; + I2C->IC_SAR = ChipAddress & 0x00ff; + break; + case 2: + I2C->IC_TAR = I2C_IC_TAR_10BITADDR_MASTER | (ChipAddress & I2C_IC_TAR_TAR); + I2C->IC_SAR = ChipAddress; + break; + } + I2C->IC_ENABLE = 1; + if (CB) + { + prvI2C.Callback = CB; + } + else + { + prvI2C.Callback = prvI2C_DummyCB; + } + prvI2C.pParam = pParam; +} + +void I2C_MasterXfer(uint8_t I2CID, uint8_t Operate, uint8_t RegAddress, uint8_t *Data, uint32_t Len, uint16_t Toms) +{ + I2C_TypeDef *I2C = prvI2C.RegBase; + uint32_t RegValue; + I2C->IC_INTR_MASK = 0; + ISR_OnOff(prvI2C.IrqLine, 0); + if (prvI2C.IsBusy) + { + I2C->IC_ENABLE |= I2C_IC_ENABLE_ABORT; + prvI2C.IsBusy = 0; + prvI2C.Result = -ERROR_OPERATION_FAILED; + prvI2C.Callback(I2C_ID0, prvI2C.pParam); + while(I2C->IC_ENABLE & I2C_IC_ENABLE_ABORT){;} + } + ISR_SetHandler(prvI2C.IrqLine, I2C_IrqHandle, NULL); + prvI2C.IsBusy = 1; + if (Toms) + { + prvI2C.TimeoutMs = Toms; + } + else + { + prvI2C.TimeoutMs = 50; + } + Buffer_StaticInit(&prvI2C.DataBuf, Data, Len); + prvI2C.RegQueue = NULL; + RegValue = I2C->IC_CLR_INTR; + switch(Operate) + { + case I2C_OP_READ_REG: + + prvI2C.State = I2C_STATE_READ_ADDRESS_WR; + I2C->IC_DATA_CMD = I2C_IC_DATA_CMD_RESTART|RegAddress; + I2C->IC_INTR_MASK = I2C_IC_INTR_MASK_M_TX_EMPTY|I2C_IC_INTR_MASK_M_STOP_DET; + break; + case I2C_OP_READ: + prvI2C.State = I2C_STATE_READ_ADDRESS_RD; + if ((prvI2C.DataBuf.MaxLen - prvI2C.DataBuf.Pos) > 1) + { + I2C->IC_DATA_CMD = I2C_IC_DATA_CMD_CMD; + } + else + { + I2C->IC_DATA_CMD = I2C_IC_DATA_CMD_CMD|I2C_IC_DATA_CMD_STOP; + } + I2C->IC_INTR_MASK = I2C_IC_INTR_MASK_M_RX_FULL|I2C_IC_INTR_MASK_M_STOP_DET; + break; + case I2C_OP_WRITE: + prvI2C.State = I2C_STATE_WRITE_ADDRESS; + if ((prvI2C.DataBuf.MaxLen - prvI2C.DataBuf.Pos) > 1) + { + I2C->IC_DATA_CMD = prvI2C.DataBuf.Data[0]; + } + else + { + I2C->IC_DATA_CMD = prvI2C.DataBuf.Data[0]|I2C_IC_DATA_CMD_STOP; + } + prvI2C.DataBuf.Pos++; + I2C->IC_INTR_MASK = I2C_IC_INTR_MASK_M_TX_EMPTY|I2C_IC_INTR_MASK_M_STOP_DET; + break; + default: + prvI2C.IsBusy = 0; + prvI2C.Result = -ERROR_PARAM_INVALID; + prvI2C.Callback(I2C_ID0, prvI2C.pParam); + return; + } + + ISR_OnOff(prvI2C.IrqLine, 1); +} + +int32_t I2C_MasterWriteRegQueue(uint8_t I2CID, I2C_CommonRegDataStruct *RegQueue, uint32_t TotalNum, uint16_t Toms, uint8_t IsBlock) +{ + I2C_TypeDef *I2C = prvI2C.RegBase; + uint32_t RegValue; + int32_t Result; + I2C->IC_INTR_MASK = 0; + ISR_OnOff(prvI2C.IrqLine, 0); + if (prvI2C.IsBusy) + { + I2C->IC_ENABLE |= I2C_IC_ENABLE_ABORT; + prvI2C.IsBusy = 0; + prvI2C.Result = -ERROR_OPERATION_FAILED; + prvI2C.Callback(I2C_ID0, prvI2C.pParam); + while(I2C->IC_ENABLE & I2C_IC_ENABLE_ABORT){;} + } + ISR_SetHandler(prvI2C.IrqLine, I2C_IrqHandleRegQueue, NULL); + prvI2C.IsBusy = 1; + if (Toms) + { + prvI2C.TimeoutMs = Toms; + } + else + { + prvI2C.TimeoutMs = 50; + } + prvI2C.RegQueue = RegQueue; + prvI2C.TotalQueueNum = TotalNum; + prvI2C.CurQueuePos = 0; + RegValue = I2C->IC_CLR_INTR; + Buffer_StaticInit(&prvI2C.DataBuf, prvI2C.RegQueue[prvI2C.CurQueuePos].Data, 2); + I2C->IC_DATA_CMD = prvI2C.DataBuf.Data[0]; + prvI2C.DataBuf.Pos++; + I2C->IC_INTR_MASK = I2C_IC_INTR_MASK_M_TX_EMPTY|I2C_IC_INTR_MASK_M_STOP_DET; + ISR_OnOff(prvI2C.IrqLine, 1); + if (IsBlock) + { + while(!I2C_WaitResult(I2CID, &Result)) {;} + return Result; + } + else + { + return 0; + } +} + + +int I2C_WaitResult(uint8_t I2CID, int32_t *Result) +{ + if (prvI2C.IsBusy) return 0; + *Result = prvI2C.Result; + return 1; +} + +int32_t I2C_BlockWrite(uint8_t I2CID, uint8_t ChipAddress, const uint8_t *Data, uint32_t Len, uint16_t Toms, CBFuncEx_t CB, void *pParam) +{ + int32_t Result; + while(!I2C_WaitResult(I2CID, &Result)) {;} + prvI2C.IsBlockMode = !OS_CheckInIrq(); + I2C_Prepare(I2CID, ChipAddress, 1, CB, pParam); + I2C_MasterXfer(I2CID, I2C_OP_WRITE, 0, Data, Len, Toms); +#ifdef __BUILD_OS__ + if (!OS_CheckInIrq()) + { + OS_MutexLock(prvI2C.Sem); + } +#endif + while(!I2C_WaitResult(I2CID, &Result)) {;} + return Result; +} + +int32_t I2C_BlockRead(uint8_t I2CID, uint8_t ChipAddress, uint8_t *Reg, uint8_t *Data, uint32_t Len, uint16_t Toms, CBFuncEx_t CB, void *pParam) +{ + int32_t Result; + while(!I2C_WaitResult(I2CID, &Result)) {;} + prvI2C.IsBlockMode = !OS_CheckInIrq(); + I2C_Prepare(I2CID, ChipAddress, 1, CB, pParam); + if (Reg) + { + I2C_MasterXfer(I2CID, I2C_OP_READ_REG, *Reg, Data, Len, Toms); + } + else + { + I2C_MasterXfer(I2CID, I2C_OP_READ, 0, Data, Len, Toms); + } +#ifdef __BUILD_OS__ + if (!OS_CheckInIrq()) + { + OS_MutexLock(prvI2C.Sem); + } +#endif + while(!I2C_WaitResult(I2CID, &Result)) {;} + return Result; +} + +void I2C_ForceStop(uint8_t I2CID) +{ + I2C_TypeDef *I2C = prvI2C.RegBase; + IIC_DBG("%d,%x",prvI2C.State, I2C->IC_RAW_INTR_STAT); + I2C->IC_ENABLE |= I2C_IC_ENABLE_ABORT; + I2C->IC_INTR_MASK = 0; + prvI2C_Done(-ERROR_TIMEOUT); + while(I2C->IC_ENABLE & I2C_IC_ENABLE_ABORT){;} +} diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_irq.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_irq.c new file mode 100644 index 0000000000..0e72fe329a --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_irq.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "user.h" +#define __IRQ_IN_RAM__ +#ifdef __IRQ_IN_RAM__ +#else +#define __FUNC_IN_RAM__ +#endif +typedef struct { + void (*Irq_Handler)(int32_t IrqLine, void *pData); + void *pData; +}Irq_Handler_t; + +static Irq_Handler_t Irq_Table[IRQ_LINE_MAX + 16 - IRQ_LINE_OFFSET]; + +static void ISR_DummyHandler(int32_t IrqLine, void *pData) +{ + +} + +void __FUNC_IN_RAM__ ISR_GlobalHandler(void) +{ + int IrqLine = ((SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) >> SCB_ICSR_VECTACTIVE_Pos) - IRQ_LINE_OFFSET; + if (IrqLine < 0 || IrqLine >= IRQ_LINE_MAX) + { + return; + } + rt_interrupt_enter(); + if (Irq_Table[IrqLine].Irq_Handler) + { + Irq_Table[IrqLine].Irq_Handler(IrqLine + IRQ_LINE_OFFSET - 16, Irq_Table[IrqLine].pData); + } + rt_interrupt_leave(); +} + +void ISR_SetHandler(int32_t Irq, void *Handler, void *pData) +{ + Irq_Table[Irq + 16 - IRQ_LINE_OFFSET].Irq_Handler = Handler; + Irq_Table[Irq + 16 - IRQ_LINE_OFFSET].pData = pData; +} + +void ISR_SetPriority(int32_t Irq, uint32_t PriorityLevel) +{ + NVIC_SetPriority(Irq, PriorityLevel); +} + +void __FUNC_IN_RAM__ ISR_OnOff(int32_t Irq, uint32_t OnOff) +{ + if (OnOff) + { + if (!Irq_Table[Irq + 16 - IRQ_LINE_OFFSET].Irq_Handler) + { + Irq_Table[Irq + 16 - IRQ_LINE_OFFSET].Irq_Handler = ISR_DummyHandler; + } + NVIC_EnableIRQ(Irq); + } + else + { + NVIC_DisableIRQ(Irq); + } +} + +void __FUNC_IN_RAM__ ISR_Clear(int32_t Irq) +{ + NVIC_ClearPendingIRQ(Irq); +} + +uint32_t __FUNC_IN_RAM__ ISR_CheckIn(void) +{ + return __get_IPSR(); +} + diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_keyboard.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_keyboard.c new file mode 100644 index 0000000000..45099082f7 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_keyboard.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "user.h" + +typedef struct +{ + const I2C_TypeDef *RegBase; + const int IrqLine; + CBFuncEx_t CB; + void *pParam; +}KB_CtrlStruct; + +static KB_CtrlStruct prvKB = { + KCU, + KBD_IRQn, +}; + +static int32_t prvKB_DummyCB(void *pData, void *pParam) +{ + return 0; +} + + + +static void KB_IrqHandle(int32_t IrqLine, void *pData) +{ + uint32_t Status, Event, i, type, key; + Status = KCU->KCU_STATUS; + Event = KCU->KCU_EVENT; + ISR_Clear(IrqLine); + for(i = 0; i < 4; i++) + { + if (Status & (1 << (2 * i + 5))) + { + type = (Status & (1 << (2 * i + 4)))?1:0; + key = (Event & (0x000000ff << (i * 8))) >> (i * 8); + key |= (type << 16); + prvKB.CB(key, prvKB.pParam); + } + } +} + +void KB_Setup(uint16_t PinConfigMap, uint16_t Debounce, CBFuncEx_t CB, void *pParam) +{ + uint32_t Dummy; + ISR_OnOff(prvKB.IrqLine, 0); + KCU->KCU_CTRL1 &= KCU_CTRL1_KCU_RUNING; + while ((KCU->KCU_CTRL1 & KCU_CTRL1_KCU_RUNING)); + Dummy = KCU->KCU_EVENT; + Debounce &= 0x7; + KCU->KCU_CTRL0 = (PinConfigMap & 0x01ff) | (Debounce << 9); + if (CB) + { + prvKB.CB = CB; + } + else + { + prvKB.CB = prvKB_DummyCB; + } + prvKB.pParam = pParam; + KCU->KCU_CTRL1 |= (KCU_CTRL1_KBD_EN|KCU_CTRL1_PUSH_IT|KCU_CTRL1_RELEASE_IT|KCU_CTRL1_OVERRUN_IT); + ISR_SetHandler(prvKB.IrqLine, KB_IrqHandle, NULL); +#ifdef __BUILD_OS__ + ISR_SetPriority(prvKB.IrqLine, configLIBRARY_LOWEST_INTERRUPT_PRIORITY - 1); +#else + ISR_SetPriority(prvKB.IrqLine, 7); +#endif + ISR_OnOff(prvKB.IrqLine, 1); +} + +void KB_Stop(void) +{ + ISR_OnOff(prvKB.IrqLine, 0); + KCU->KCU_CTRL1 &= KCU_CTRL1_KCU_RUNING; +} diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_otp.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_otp.c new file mode 100644 index 0000000000..c47bee5808 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_otp.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "bl_inc.h" +#define OTP_KEY1 (0xABCD00A5) +#define OTP_KEY2 (0x1234005A) +#define OTP_START_ADDRESS (0x40008000) + +void OTP_Write(uint32_t Address, const uint32_t *Data, uint32_t Len) +{ + uint32_t i; + SYSCTRL->CG_CTRL2 |= SYSCTRL_AHBPeriph_OTP; + OTP->RO = 0; + OTP->CFG = 0; + for(i = 0; i < Len; i++) + { + OTP->PDATA = Data[i]; + OTP->ADDR = Address + (i * 4); + OTP->PROT = OTP_KEY1; + OTP->PROT = OTP_KEY2; + OTP->CS |= 1; + while((OTP->CS & 0x00000001)){;} + OTP->CS &= ~(0x07 << 1); + } + SYSCTRL->CG_CTRL2 &= ~SYSCTRL_AHBPeriph_OTP; +} + +void OTP_Read(uint32_t Address, uint8_t *Data, uint32_t Len) +{ + SYSCTRL->CG_CTRL2 |= SYSCTRL_AHBPeriph_OTP; + OTP->CFG = 0x02; + while(!(OTP->CS & 0x80000000)){;} + memcpy(Data, Address + OTP_START_ADDRESS, Len); + SYSCTRL->CG_CTRL2 &= ~SYSCTRL_AHBPeriph_OTP; +} +void OTP_Lock(void) +{ + SYSCTRL->CG_CTRL2 |= SYSCTRL_AHBPeriph_OTP; + OTP->CFG = 0x02; + OTP->RO = 0xffffffff; + OTP->ROL = 0xffffffff; + OTP->CFG = 0x01; + SYSCTRL->CG_CTRL2 &= ~SYSCTRL_AHBPeriph_OTP; +} + +void OTP_GetSn(uint8_t *ChipSN) +{ + memcpy(ChipSN, (uint32_t *)(SYSCTRL_CHIP_SN_ADDR), SYSCTRL_CHIP_SN_LEN); +} diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_rng.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_rng.c new file mode 100644 index 0000000000..6112acf470 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_rng.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "user.h" + +void RNG_Init(void) +{ + TRNG->RNG_ANA = 0; + TRNG->RNG_CSR = 0; +} +/** + * @brief 获取随机数 + * + * @param Buf,一次获取4个32bit数据 + */ +void RNG_GetData(uint32_t Buf[4]) +{ + if (TRNG->RNG_CSR & TRNG_RNG_CSR_S128_TRNG0_Mask) + { + ; + } + else + { + TRNG->RNG_CSR = 0; + while(!(TRNG->RNG_CSR & TRNG_RNG_CSR_S128_TRNG0_Mask)){;} + } + Buf[0] = TRNG->RNG_DATA[0]; + Buf[1] = TRNG->RNG_DATA[0]; + Buf[2] = TRNG->RNG_DATA[0]; + Buf[3] = TRNG->RNG_DATA[0]; + TRNG->RNG_CSR = 0; + + +} diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_rtc.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_rtc.c new file mode 100644 index 0000000000..35dcabe7bc --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_rtc.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "user.h" + +static int32_t RTC_DummyCB(void *pData, void *pParam) +{ + DBG("!"); + return 0; +} + +static CBFuncEx_t prvRTCCB; +static void *prvParam; + +static void RTC_IrqHandler(int32_t Line, void *pData) +{ + RTC->RTC_INTCLR = 1; + ISR_OnOff(RTC_IRQn, 0); + prvRTCCB(pData, prvParam); +} + +void RTC_GlobalInit(void) +{ + int8_t Buf[4][6]; + LongInt Tamp; + char *strMon[12] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; + int Day,Year,Mon,Hour,Min,Sec,i; + CmdParam CP; + Date_UserDataStruct BuildDate; + Time_UserDataStruct BuildTime; + prvRTCCB = RTC_DummyCB; + if (!RTC->RTC_REF) + { + DBG("rtc lost power!"); + memset(&CP, 0, sizeof(CP)); + memset(Buf, 0, sizeof(Buf)); + CP.param_max_len = 6; + CP.param_max_num = 4; + CP.param_str = (int8_t *)Buf; + CmdParseParam(__DATE__, &CP, ' '); + Mon = 0; + for (i = 0; i < 12; i++) + { + if (!strcmp(strMon[i], Buf[0])) + { + Mon = i + 1; + } + } + + if (Buf[1][0]) + { + Day = strtol(Buf[1], NULL, 10); + Year = strtol(Buf[2], NULL, 10); + } + else + { + Day = strtol(Buf[2], NULL, 10); + Year = strtol(Buf[3], NULL, 10); + } + + + CP.param_num = 0; + memset(Buf, 0, sizeof(Buf)); + + CP.param_str = (int8_t *)Buf; + CmdParseParam(__TIME__, &CP, ':'); + Hour = strtol(Buf[0], NULL, 10); + Min = strtol(Buf[1], NULL, 10); + Sec = strtol(Buf[2], NULL, 10); + BuildDate.Year = Year; + BuildDate.Mon = Mon; + BuildDate.Day = Day; + BuildTime.Hour = Hour; + BuildTime.Min = Min; + BuildTime.Sec = Sec; + RTC_SetDateTime(&BuildDate, &BuildTime, 0); + } +#ifdef __BUILD_OS__ + ISR_SetPriority(RTC_IRQn, IRQ_MAX_PRIORITY + 1); +#else + ISR_SetPriority(RTC_IRQn, 3); +#endif + ISR_SetHandler(RTC_IRQn, RTC_IrqHandler, NULL); +// RTC_GetDateTime(&uBuildDate, &uBuildTime); +// DBG("%04u-%02u-%02u %02u:%02u:%02u", uBuildDate.Date.Year, uBuildDate.Date.Mon, +// uBuildDate.Date.Day, uBuildTime.Time.Hour, uBuildTime.Time.Min, +// uBuildTime.Time.Sec); + +} + +void RTC_SetStamp(uint32_t Stamp) +{ + while (!(RTC->RTC_CS & RTC_CS_READY)) {;} + RTC->RTC_CS |= RTC_CS_CLR; + while (RTC->RTC_CS & RTC_CS_CLR) {;} + RTC->RTC_REF = Stamp; +} + +void RTC_SetDateTime(Date_UserDataStruct *pDate, Time_UserDataStruct *pTime, uint8_t isForce) +{ + uint64_t Tamp = UTC2Tamp(pDate, pTime); + uint32_t curTime; + uint32_t newTime = (uint32_t)Tamp; + while (!(RTC->RTC_CS & RTC_CS_READY)) {;} + if (isForce) + { + RTC->RTC_CS |= RTC_CS_CLR; + while (RTC->RTC_CS & RTC_CS_CLR) {;} + RTC->RTC_REF = newTime; + } + else + { + RTC->RTC_CS |= RTC_CS_LOCK_TIM; + curTime = RTC->RTC_TIM; + RTC->RTC_CS &= ~RTC_CS_LOCK_TIM; + curTime += RTC->RTC_REF; + if (newTime > curTime) + { + RTC->RTC_CS |= RTC_CS_CLR; + while (RTC->RTC_CS & RTC_CS_CLR) {;} + RTC->RTC_REF = newTime; + } + } +} + +void RTC_GetDateTime(Date_UserDataStruct *pDate, Time_UserDataStruct *pTime) +{ + Tamp2UTC(RTC_GetUTC(), pDate, pTime, 0); +} + +uint64_t RTC_GetUTC(void) +{ + uint64_t curTime; + while (!(RTC->RTC_CS & RTC_CS_READY)) {;} + RTC->RTC_CS |= RTC_CS_LOCK_TIM; + curTime = RTC->RTC_TIM; + RTC->RTC_CS &= ~RTC_CS_LOCK_TIM; + curTime += RTC->RTC_REF; + return curTime; +} + +void RTC_SetAlarm(uint32_t TimeSecond, CBFuncEx_t CB, void *pParam) +{ + while (!(RTC->RTC_CS & RTC_CS_READY)) {;} + RTC->RTC_INTCLR = 1; + RTC->RTC_CS &= ~RTC_CS_ALARM_EN; + RTC->RTC_CS |= RTC_CS_LOCK_TIM; + RTC->RTC_ARM = RTC->RTC_TIM + TimeSecond; + RTC->RTC_CS &= ~RTC_CS_LOCK_TIM; + if (CB) + { + prvRTCCB = CB; + } + else + { + prvRTCCB = RTC_DummyCB; + } + prvParam = pParam; + RTC->RTC_CS |= RTC_CS_ALARM_EN; + ISR_OnOff(RTC_IRQn, 1); +} diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_spi.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_spi.c new file mode 100644 index 0000000000..59ae80ea75 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_spi.c @@ -0,0 +1,1150 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "user.h" + +#define HSPIM_CR0_CLEAR_MASK ((uint32_t)~0xFFEEFFFF) +#define HSPIM_CR0_MODE_SELECT_CLEAR_MASK ((uint32_t)~0x1C00) +#define HSPIM_CR1_CLEAR_MASK ((uint32_t)~0xFFFFF) +#define HSPIM_FCR_CLEAR_MASK ((uint32_t)~0x3F3F3F00) +#define HSPIM_DCR_RECEIVE_LEVEL_CLEAR_MASK ((uint32_t)~0x3F80) +#define HSPIM_DCR_TRANSMIT_LEVEL_CLEAR_MASK ((uint32_t)~0x7F) + + +#define HSPIM_CR0_PARAM_ENABLE_POS (0x18) +#define HSPIM_CR0_PARAM_DMA_RECEIVE_ENABLE_POS (0x14) +#define HSPIM_CR0_PARAM_DMA_TRANSMIT_ENABLE_POS (0x10) +#define HSPIM_CR0_PARAM_INTERRPUT_RX_POS (0x0F) +#define HSPIM_CR0_PARAM_INTERRPUT_TX_POS (0x0E) +#define HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS (0x0D) +#define HSPIM_CR0_PARAM_MODEL_SELECT_POS (0x0A) +#define HSPIM_CR0_PARAM_FIRST_BIT_POS (0x09) +#define HSPIM_CR0_PARAM_CPOL_POS (0x08) +#define HSPIM_CR0_PARAM_CPHA_POS (0x07) +#define HSPIM_CR0_PARAM_DIVIDE_ENABLE_POS (0x02) +#define HSPIM_CR0_PARAM_TRANSMIT_ENABLE_POS (0x01) +#define HSPIM_CR0_PARAM_BUSY_POS (0x00) + +#define HSPIM_CR1_PARAM_BAUDRATE_POS (0x0A) +#define HSPIM_CR1_PARAM_RECEIVE_DATA_LENGTH_POS (0x00) + +#define HSPIM_DCR_PARAM_DMA_RECEIVE_LEVEL_POS (0x07) +#define HSPIM_DCR_PARAM_DMA_TRANSMIT_LEVEL_POS (0x00) + +#define HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS (0x08) +#define HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS (0x10) + +#define HSPIM_SR_PUSH_FULL_TX (1 << 4) +#define HSPIM_SR_POP_EMPTY_RX (1 << 10) +#define HSPIM_FIFO_TX_NUM (64) +#define HSPIM_FIFO_RX_NUM (64) +#define HSPIM_FIFO_LEVEL (48) + +#define SPIM_FIFO_TX_NUM (16) +#define SPIM_FIFO_RX_NUM (16) +#define SPIM_FIFO_RX_LEVEL (7) +#define SPIM_FIFO_TX_LEVEL (8) +typedef struct +{ + const volatile void *RegBase; + const int32_t IrqLine; + const uint16_t DMATxChannel; + const uint16_t DMARxChannel; + CBFuncEx_t Callback; + void *pParam; + HANDLE Sem; + Buffer_Struct TxBuf; + Buffer_Struct RxBuf; + uint32_t Speed; + uint8_t DMATxStream; + uint8_t DMARxStream; + uint8_t Is16Bit; + uint8_t IsOnlyTx; + uint8_t IsBusy; + uint8_t IsBlockMode; +}SPI_ResourceStruct; + +static SPI_ResourceStruct prvSPI[SPI_MAX] = { + { + HSPIM, + SPI5_IRQn, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_HSPI_TX, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_HSPI_RX, + }, + { + SPIM0, + SPI0_IRQn, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI0_TX, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI0_RX, + }, + { + SPIM1, + SPI1_IRQn, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI1_TX, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI1_RX, + }, + { + SPIM2, + SPI2_IRQn, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI2_TX, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI2_RX, + }, + { + SPIS0, + SPI0_IRQn, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI0_TX, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI0_RX, + }, +}; + +static void HSPI_IrqHandle(int32_t IrqLine, void *pData) +{ + uint32_t SpiID = HSPI_ID0; + uint32_t RxLevel, i, TxLen; + HSPIM_TypeDef *SPI = HSPIM; + volatile uint32_t DummyData; + if (!prvSPI[SpiID].IsBusy) + { + + ISR_Clear(prvSPI[SpiID].IrqLine); + ISR_OnOff(prvSPI[SpiID].IrqLine, 0); + return; + } + if (prvSPI[SpiID].RxBuf.Data) + { + while (prvSPI[SpiID].RxBuf.Pos < prvSPI[SpiID].RxBuf.MaxLen) + { + if (SPI->SR & HSPIM_SR_POP_EMPTY_RX) + { + break; + } + else + { + prvSPI[SpiID].RxBuf.Data[prvSPI[SpiID].RxBuf.Pos] = SPI->RDR; + prvSPI[SpiID].RxBuf.Pos++; + } + } + } + else + { + while (prvSPI[SpiID].RxBuf.Pos < prvSPI[SpiID].RxBuf.MaxLen) + { + if (SPI->SR & HSPIM_SR_POP_EMPTY_RX) + { + break; + } + else + { + DummyData = SPI->RDR; + prvSPI[SpiID].RxBuf.Pos++; + } + } + } + + + if (prvSPI[SpiID].RxBuf.Pos >= prvSPI[SpiID].RxBuf.MaxLen) + { + SPI->CR0 &= ~(7 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS); + prvSPI[SpiID].IsBusy = 0; + ISR_Clear(prvSPI[SpiID].IrqLine); + ISR_OnOff(prvSPI[SpiID].IrqLine, 0); + if ((prvSPI[SpiID].TxBuf.Pos != prvSPI[SpiID].RxBuf.Pos) || (prvSPI[SpiID].RxBuf.Pos != prvSPI[SpiID].RxBuf.MaxLen)) + { + DBG("%u, %u", prvSPI[SpiID].TxBuf.Pos, prvSPI[SpiID].RxBuf.Pos); + } +#ifdef __BUILD_OS__ + if (prvSPI[SpiID].IsBlockMode) + { + OS_MutexRelease(prvSPI[SpiID].Sem); + } +#endif + prvSPI[SpiID].Callback((void *)SpiID, prvSPI[SpiID].pParam); + return; + } + + if (prvSPI[SpiID].TxBuf.Pos < prvSPI[SpiID].TxBuf.MaxLen) + { + i = 0; + TxLen = (HSPIM_FIFO_TX_NUM - (SPI->FSR & 0x0000003f)); + if (TxLen > (prvSPI[SpiID].TxBuf.MaxLen -prvSPI[SpiID].TxBuf.Pos)) + { + TxLen = prvSPI[SpiID].TxBuf.MaxLen - prvSPI[SpiID].TxBuf.Pos; + } + while((i < TxLen)) + { + SPI->WDR = prvSPI[SpiID].TxBuf.Data[prvSPI[SpiID].TxBuf.Pos + i]; + i++; + } + prvSPI[SpiID].TxBuf.Pos += TxLen; + if (prvSPI[SpiID].TxBuf.Pos >= prvSPI[SpiID].TxBuf.MaxLen) + { + SPI->FCR = (63 << HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS)|(0 << HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS)|(63); + SPI->CR0 &= ~(7 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS); + SPI->CR0 |= (5 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS); + } + } + else + { + SPI->FCR = (63 << HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS)|(0 << HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS)|(63); + SPI->CR0 &= ~(7 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS); + SPI->CR0 |= (5 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS); + } +} + +static int32_t SPI_DMADoneCB(void *pData, void *pParam) +{ + uint32_t SpiID = (uint32_t)pData; + uint32_t RxLevel; + + if (prvSPI[SpiID].RxBuf.MaxLen > prvSPI[SpiID].RxBuf.Pos) + { + RxLevel = ((prvSPI[SpiID].RxBuf.MaxLen - prvSPI[SpiID].RxBuf.Pos) > 4080)?4000:(prvSPI[SpiID].RxBuf.MaxLen - prvSPI[SpiID].RxBuf.Pos); + + DMA_ClearStreamFlag(prvSPI[SpiID].DMATxStream); + + DMA_ClearStreamFlag(prvSPI[SpiID].DMARxStream); + + if (prvSPI[SpiID].IsOnlyTx) + { + DMA_ForceStartStream(prvSPI[SpiID].DMATxStream, &prvSPI[SpiID].TxBuf.Data[prvSPI[SpiID].TxBuf.Pos], RxLevel, SPI_DMADoneCB, (void *)SpiID, 1); + DMA_ForceStartStream(prvSPI[SpiID].DMARxStream, &prvSPI[SpiID].RxBuf.Data[prvSPI[SpiID].RxBuf.Pos], RxLevel, NULL, NULL, 0); + } + else + { + DMA_ForceStartStream(prvSPI[SpiID].DMATxStream, &prvSPI[SpiID].TxBuf.Data[prvSPI[SpiID].TxBuf.Pos], RxLevel, NULL, NULL, 0); + DMA_ForceStartStream(prvSPI[SpiID].DMARxStream, &prvSPI[SpiID].RxBuf.Data[prvSPI[SpiID].RxBuf.Pos], RxLevel, SPI_DMADoneCB, (void *)SpiID, 1); + } + prvSPI[SpiID].RxBuf.Pos += RxLevel; + prvSPI[SpiID].TxBuf.Pos += RxLevel; + } + + else + { + prvSPI[SpiID].IsBusy = 0; + if ((prvSPI[SpiID].TxBuf.Pos != prvSPI[SpiID].RxBuf.Pos) || (prvSPI[SpiID].RxBuf.Pos != prvSPI[SpiID].RxBuf.MaxLen)) + { + DBG("%u, %u", prvSPI[SpiID].TxBuf.Pos, prvSPI[SpiID].RxBuf.Pos); + } +#ifdef __BUILD_OS__ + if (prvSPI[SpiID].IsBlockMode) + { + OS_MutexRelease(prvSPI[SpiID].Sem); + } +#endif + prvSPI[SpiID].Callback((void *)SpiID, prvSPI[SpiID].pParam); + } + + +} + +static void SPI_IrqHandle(int32_t IrqLine, void *pData) +{ + uint32_t SpiID = (uint32_t)pData; + volatile uint32_t DummyData; + uint32_t RxLevel, SR, i, TxLen; + SPI_TypeDef *SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase; + if (!prvSPI[SpiID].IsBusy) + { + SR = SPI->ICR; + SPI->IMR = 0; + SPI->SER = 0; + ISR_Clear(prvSPI[SpiID].IrqLine); + ISR_OnOff(prvSPI[SpiID].IrqLine, 0); + return; + } + TxLen = SPIM_FIFO_TX_NUM - SPI->TXFLR; + + SR = SPI->ICR; + if (prvSPI[SpiID].RxBuf.Data) + { + while(SPI->RXFLR) + { + prvSPI[SpiID].RxBuf.Data[prvSPI[SpiID].RxBuf.Pos] = SPI->DR; + prvSPI[SpiID].RxBuf.Pos++; + } + } + else + { + while(SPI->RXFLR) + { + DummyData = SPI->DR; + prvSPI[SpiID].RxBuf.Pos++; + } + } + + if (prvSPI[SpiID].RxBuf.Pos >= prvSPI[SpiID].RxBuf.MaxLen) + { + + SR = SPI->ICR; + SPI->IMR = 0; + SPI->SER = 0; + prvSPI[SpiID].IsBusy = 0; + ISR_Clear(prvSPI[SpiID].IrqLine); + ISR_OnOff(prvSPI[SpiID].IrqLine, 0); + if (prvSPI[SpiID].TxBuf.Pos != prvSPI[SpiID].RxBuf.Pos) + { + DBG("%u, %u", prvSPI[SpiID].TxBuf.Pos, prvSPI[SpiID].RxBuf.Pos); + } +#ifdef __BUILD_OS__ + if (prvSPI[SpiID].IsBlockMode) + { + OS_MutexRelease(prvSPI[SpiID].Sem); + } +#endif + prvSPI[SpiID].Callback((void *)SpiID, prvSPI[SpiID].pParam); + return; + } + + if (prvSPI[SpiID].TxBuf.Pos < prvSPI[SpiID].TxBuf.MaxLen) + { + i = 0; + if (TxLen > (prvSPI[SpiID].TxBuf.MaxLen -prvSPI[SpiID].TxBuf.Pos)) + { + TxLen = prvSPI[SpiID].TxBuf.MaxLen - prvSPI[SpiID].TxBuf.Pos; + } + while((i < TxLen)) + { + SPI->DR = prvSPI[SpiID].TxBuf.Data[prvSPI[SpiID].TxBuf.Pos + i]; + i++; + } + prvSPI[SpiID].TxBuf.Pos += i; + } + else + { + + if ((prvSPI[SpiID].RxBuf.MaxLen - prvSPI[SpiID].RxBuf.Pos) >= SPIM_FIFO_RX_NUM) + { + SPI->RXFTLR = (SPIM_FIFO_RX_NUM - 1); + } + else + { + SPI->RXFTLR = prvSPI[SpiID].RxBuf.MaxLen - prvSPI[SpiID].RxBuf.Pos - 1; + } + SPI->IMR = SPI_IMR_RXOIM|SPI_IMR_RXFIM; + } +} + +static int32_t SPI_DummyCB(void *pData, void *pParam) +{ + return 0; +} + +static void HSPI_MasterInit(uint8_t SpiID, uint8_t Mode, uint32_t Speed) +{ + HSPIM_TypeDef *SPI = (HSPIM_TypeDef *)prvSPI[SpiID].RegBase; + uint32_t div = (SystemCoreClock / Speed) >> 1; + uint32_t ctrl = (1 << 24) | (1 << 10) | (1 << 2) | (1 << 1); + switch(Mode) + { + case SPI_MODE_0: + break; + case SPI_MODE_1: + ctrl |= (1 << HSPIM_CR0_PARAM_CPHA_POS); + break; + case SPI_MODE_2: + ctrl |= (1 << HSPIM_CR0_PARAM_CPOL_POS); + break; + case SPI_MODE_3: + ctrl |= (1 << HSPIM_CR0_PARAM_CPOL_POS)|(1 << HSPIM_CR0_PARAM_CPHA_POS); + break; + } + SPI->CR1 = (div << HSPIM_CR1_PARAM_BAUDRATE_POS) + 1; + SPI->CR0 = ctrl; + SPI->DCR = 30|(1 << 7); + prvSPI[SpiID].Speed = (SystemCoreClock >> 1) / div; + + ISR_SetHandler(prvSPI[SpiID].IrqLine, HSPI_IrqHandle, (uint32_t)SpiID); +#ifdef __BUILD_OS__ + ISR_SetPriority(prvSPI[SpiID].IrqLine, IRQ_MAX_PRIORITY + 1); +#else + ISR_SetPriority(prvSPI[SpiID].IrqLine, 3); +#endif + ISR_Clear(prvSPI[SpiID].IrqLine); + ISR_OnOff(prvSPI[SpiID].IrqLine, 0); + +} + +void SPI_MasterInit(uint8_t SpiID, uint8_t DataBit, uint8_t Mode, uint32_t Speed, CBFuncEx_t CB, void *pUserData) +{ + SPI_TypeDef *SPI; + uint32_t ctrl; + uint32_t div; + switch(SpiID) + { + case HSPI_ID0: + HSPI_MasterInit(SpiID, Mode, Speed); + break; + case SPI_ID0: + SYSCTRL->PHER_CTRL &= ~SYSCTRL_PHER_CTRL_SPI0_SLV_EN; + case SPI_ID1: + case SPI_ID2: + SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase; + SPI->SSIENR = 0; + SPI->SER = 0; + SPI->IMR = 0; + SPI->DMACR = 0; + ctrl = DataBit - 1; + switch(Mode) + { + case SPI_MODE_0: + break; + case SPI_MODE_1: + ctrl |= SPI_CTRLR0_SCPH; + break; + case SPI_MODE_2: + ctrl |= SPI_CTRLR0_SCPOL; + break; + case SPI_MODE_3: + ctrl |= SPI_CTRLR0_SCPOL|SPI_CTRLR0_SCPH; + break; + } + div = (SystemCoreClock >> 2) / Speed; + if (div % 2) div++; + prvSPI[SpiID].Speed = (SystemCoreClock >> 2) / div; + SPI->CTRLR0 = ctrl; + SPI->BAUDR = div; + SPI->TXFTLR = 0; + SPI->RXFTLR = 0; + SPI->DMATDLR = 7; + SPI->DMARDLR = 0; + ISR_SetHandler(prvSPI[SpiID].IrqLine, SPI_IrqHandle, (uint32_t)SpiID); +#ifdef __BUILD_OS__ + ISR_SetPriority(prvSPI[SpiID].IrqLine, IRQ_LOWEST_PRIORITY - 2); +#else + ISR_SetPriority(prvSPI[SpiID].IrqLine, 5); +#endif + ISR_Clear(prvSPI[SpiID].IrqLine); + ISR_OnOff(prvSPI[SpiID].IrqLine, 0); + SPI->SSIENR = 1; + break; +// case SPI_ID3: +// SYSCTRL->PHER_CTRL |= SYSCTRL_PHER_CTRL_SPI0_SLV_EN; +// break; + default: + return; + } + prvSPI[SpiID].DMATxStream = 0xff; + prvSPI[SpiID].DMARxStream = 0xff; + if (CB) + { + prvSPI[SpiID].Callback = CB; + } + else + { + prvSPI[SpiID].Callback = SPI_DummyCB; + } + prvSPI[SpiID].pParam = pUserData; +#ifdef __BUILD_OS__ + if (!prvSPI[SpiID].Sem) + { + prvSPI[SpiID].Sem = OS_MutexCreate(); + } +#endif +} + + +void SPI_SetTxOnlyFlag(uint8_t SpiID, uint8_t OnOff) +{ + prvSPI[SpiID].IsOnlyTx = OnOff; +} + +void SPI_SetCallbackFun(uint8_t SpiID, CBFuncEx_t CB, void *pUserData) +{ + if (CB) + { + prvSPI[SpiID].Callback = CB; + } + else + { + prvSPI[SpiID].Callback = SPI_DummyCB; + } + prvSPI[SpiID].pParam = pUserData; +} + + +static void SPI_DMATransfer(uint8_t SpiID, uint8_t UseDMA) +{ + uint32_t RxLevel; + + RxLevel = (prvSPI[SpiID].RxBuf.MaxLen > 4080)?4000:prvSPI[SpiID].RxBuf.MaxLen; + prvSPI[SpiID].RxBuf.Pos += RxLevel; + prvSPI[SpiID].TxBuf.Pos += RxLevel; + DMA_StopStream(prvSPI[SpiID].DMATxStream); + DMA_StopStream(prvSPI[SpiID].DMARxStream); + if (prvSPI[SpiID].IsOnlyTx) + { + DMA_ForceStartStream(prvSPI[SpiID].DMATxStream, prvSPI[SpiID].TxBuf.Data, RxLevel, SPI_DMADoneCB, (void *)SpiID, 1); + DMA_ForceStartStream(prvSPI[SpiID].DMARxStream, prvSPI[SpiID].RxBuf.Data, RxLevel, NULL, NULL, 0); + } + else + { + DMA_ForceStartStream(prvSPI[SpiID].DMATxStream, prvSPI[SpiID].TxBuf.Data, RxLevel, NULL, NULL, 0); + DMA_ForceStartStream(prvSPI[SpiID].DMARxStream, prvSPI[SpiID].RxBuf.Data, RxLevel, SPI_DMADoneCB, (void *)SpiID, 1); + } + + +} + +static int32_t HSPI_Transfer(uint8_t SpiID, uint8_t UseDMA) +{ + HSPIM_TypeDef *SPI = (HSPIM_TypeDef *)prvSPI[SpiID].RegBase; + uint32_t TxLen, i; + if (UseDMA) + { + SPI->CR0 &= ~(7 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS); + SPI->CR0 |= (1 << HSPIM_CR0_PARAM_DMA_TRANSMIT_ENABLE_POS)|(1 << HSPIM_CR0_PARAM_DMA_RECEIVE_ENABLE_POS); + SPI->FCR = (32 << HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS)|(0 << HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS)|(3 << 6)|(63); + SPI->FCR &= ~(3 << 6); + SPI_DMATransfer(SpiID, UseDMA); + } + else + { + SPI->CR0 &= ~(7 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS); +// SPI->CR0 &= ~(1 << 10); + SPI->CR0 &= ~((1 << HSPIM_CR0_PARAM_DMA_TRANSMIT_ENABLE_POS)|(1 << HSPIM_CR0_PARAM_DMA_RECEIVE_ENABLE_POS)); + + + + if (prvSPI[SpiID].TxBuf.MaxLen <= HSPIM_FIFO_TX_NUM) + { + TxLen = prvSPI[SpiID].TxBuf.MaxLen; + SPI->FCR = (32 << HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS)|((TxLen - 1) << HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS)|(3 << 6)|(63); + SPI->CR0 |= (5 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS); + } + else + { + TxLen = HSPIM_FIFO_TX_NUM; + SPI->FCR = (32 << HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS)|(63 << HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS)|(3 << 6)|(63); + SPI->CR0 |= (3 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS); + } + + SPI->FCR &= ~(3 << 6); + + for(i = 0; i < TxLen; i++) + { + SPI->WDR = prvSPI[SpiID].TxBuf.Data[i]; + } + prvSPI[SpiID].TxBuf.Pos += TxLen; +// SPI->CR0 |= (1 << 10); + ISR_Clear(prvSPI[SpiID].IrqLine); + ISR_OnOff(prvSPI[SpiID].IrqLine, 1); + return ERROR_NONE; + } + return ERROR_NONE; +} + +int32_t SPI_Transfer(uint8_t SpiID, const uint8_t *TxData, uint8_t *RxData, uint32_t Len, uint8_t UseDMA) +{ + uint32_t SR; + SPI_TypeDef *SPI; + if (prvSPI[SpiID].IsBusy) + { + return -ERROR_DEVICE_BUSY; + } + prvSPI[SpiID].IsBusy = 1; +// + uint32_t RxLevel, i, TxLen; + Buffer_StaticInit(&prvSPI[SpiID].TxBuf, TxData, Len); + Buffer_StaticInit(&prvSPI[SpiID].RxBuf, RxData, Len); + switch(SpiID) + { + case HSPI_ID0: + ISR_Clear(prvSPI[SpiID].IrqLine); + ISR_OnOff(prvSPI[SpiID].IrqLine, 0); + return HSPI_Transfer(SpiID, UseDMA); + case SPI_ID0: + SYSCTRL->PHER_CTRL &= ~SYSCTRL_PHER_CTRL_SPI0_SLV_EN; + case SPI_ID1: + case SPI_ID2: + break; +// case SPI_ID3: +// SYSCTRL->PHER_CTRL |= SYSCTRL_PHER_CTRL_SPI0_SLV_EN; +// break; + default: + return -ERROR_ID_INVALID; + } + SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase; + SPI->SER = 0; + if (UseDMA) + { + + SR = SPI->ICR; + SPI->IMR = 0; + SPI->DMACR = SPI_DMACR_RDMAE|SPI_DMACR_TDMAE; + ISR_Clear(prvSPI[SpiID].IrqLine); + ISR_OnOff(prvSPI[SpiID].IrqLine, 0); + SPI->SER = 1; + SPI_DMATransfer(SpiID, 1); + + } + else + { + ISR_OnOff(prvSPI[SpiID].IrqLine, 0); + + if (prvSPI[SpiID].RxBuf.MaxLen <= SPIM_FIFO_RX_NUM) + { + SPI->RXFTLR = prvSPI[SpiID].RxBuf.MaxLen - 1; + TxLen = prvSPI[SpiID].RxBuf.MaxLen; + SPI->IMR = SPI_IMR_RXOIM|SPI_IMR_RXFIM; + } + else + { + SPI->IMR = SPI_IMR_TXEIM; + SPI->RXFTLR = SPIM_FIFO_RX_LEVEL; + SPI->TXFTLR = SPIM_FIFO_TX_LEVEL; + TxLen = SPIM_FIFO_TX_NUM; + } + for(i = 0; i < TxLen; i++) + { + SPI->DR = prvSPI[SpiID].TxBuf.Data[i]; + } + prvSPI[SpiID].TxBuf.Pos += TxLen; + ISR_Clear(prvSPI[SpiID].IrqLine); + ISR_OnOff(prvSPI[SpiID].IrqLine, 1); + } + SPI->SER = 1; + + return ERROR_NONE; +} + + +static int32_t prvSPI_BlockTransfer(uint8_t SpiID, const uint8_t *TxData, uint8_t *RxData, uint32_t Len) +{ + volatile uint32_t DummyData; + uint32_t TxLen, RxLen, i, To; + HSPIM_TypeDef *HSPI; + SPI_TypeDef *SPI; + prvSPI[SpiID].IsBusy = 1; + switch(SpiID) + { + case HSPI_ID0: + HSPI = (HSPIM_TypeDef *)prvSPI[SpiID].RegBase; + ISR_OnOff(prvSPI[SpiID].IrqLine, 0); + HSPI->FCR = (32 << HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS)|(32 << HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS)|(3 << 6)|(63); + HSPI->FCR &= ~(3 << 6); + HSPI->CR0 &= ~(7 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS); + if (Len <= HSPIM_FIFO_TX_NUM) + { + TxLen = Len; + } + else + { + TxLen = HSPIM_FIFO_TX_NUM; + } + for(i = 0; i < TxLen; i++) + { + HSPI->WDR = TxData[i]; + } + if (RxData) + { + for(RxLen = 0; RxLen < Len; RxLen++) + { + while (HSPI->SR & HSPIM_SR_POP_EMPTY_RX) + { + ; + } + RxData[RxLen] = HSPI->RDR; + if (TxLen < Len) + { + HSPI->WDR = TxData[TxLen]; + TxLen++; + } + } + } + else + { + while(TxLen < Len) + { + while ((HSPI->FSR & 0x7f) > 16) + { + ; + } + HSPI->WDR = TxData[TxLen]; + TxLen++; + } + while ((HSPI->FSR & 0x7f)) + { + ; + } +// for(RxLen = 0; RxLen < Len; RxLen++) +// { +// while (HSPI->SR & HSPIM_SR_POP_EMPTY_RX) +// { +// ; +// } +// DummyData = HSPI->RDR; +// if (TxLen < Len) +// { +// HSPI->WDR = TxData[TxLen]; +// TxLen++; +// } +// } + } + break; + case SPI_ID0: + case SPI_ID1: + case SPI_ID2: + SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase; + ISR_OnOff(prvSPI[SpiID].IrqLine, 0); + SPI->SER = 0; + if (Len <= SPIM_FIFO_TX_NUM) + { + TxLen = Len; + } + else + { + TxLen = SPIM_FIFO_TX_NUM; + } + for(i = 0; i < TxLen; i++) + { + SPI->DR = TxData[i]; + } + SPI->SER = 1; + if (RxData) + { + for(RxLen = 0; RxLen < Len; RxLen++) + { + while (!SPI->RXFLR) + { + ; + } + RxData[RxLen] = SPI->DR; + if (TxLen < Len) + { + SPI->DR = TxData[TxLen]; + TxLen++; + } + } + } + else + { + for(RxLen = 0; RxLen < Len; RxLen++) + { + while (!SPI->RXFLR) + { + ; + } + DummyData = SPI->DR; + if (TxLen < Len) + { + SPI->DR = TxData[TxLen]; + TxLen++; + } + } + } + SPI->SER = 0; + break; + } + prvSPI[SpiID].IsBusy = 0; + prvSPI[SpiID].Callback((void *)SpiID, prvSPI[SpiID].pParam); + return 0; +} + +int32_t SPI_BlockTransfer(uint8_t SpiID, const uint8_t *TxData, uint8_t *RxData, uint32_t Len) +{ +#ifdef __BUILD_OS__ + if ( (prvSPI[SpiID].DMARxStream == 0xff) || (prvSPI[SpiID].DMATxStream == 0xff) || OS_CheckInIrq() || ((prvSPI[SpiID].Speed >> 3) >= (Len * 100000))) + { + prvSPI[SpiID].IsBlockMode = 0; +#endif + return prvSPI_BlockTransfer(SpiID, TxData, RxData, Len); +#ifdef __BUILD_OS__ + } + int32_t Result; + uint32_t Time = (Len * 1000) / (prvSPI[SpiID].Speed >> 3); + prvSPI[SpiID].IsBlockMode = 1; + if (TxData) + { + Result = SPI_Transfer(SpiID, TxData, RxData, Len, 1); + } + else + { + Result = SPI_Transfer(SpiID, RxData, RxData, Len, 1); + } + if (Result) + { + prvSPI[SpiID].IsBlockMode = 0; + DBG("!"); + return Result; + } + if (OS_MutexLockWtihTime(prvSPI[SpiID].Sem, Time + 10)) + { + DBG("!!!"); + SPI_TransferStop(SpiID); + prvSPI[SpiID].IsBlockMode = 0; + return -1; + } + prvSPI[SpiID].IsBlockMode = 0; + return 0; +#endif +} + + +static int32_t prvSPI_FlashBlockTransfer(uint8_t SpiID, const uint8_t *TxData, uint32_t WLen, uint8_t *RxData, uint32_t RLen) +{ + volatile uint32_t DummyData; + uint32_t TxLen, RxLen, i; + HSPIM_TypeDef *HSPI; + SPI_TypeDef *SPI; + prvSPI[SpiID].IsBusy = 1; + switch(SpiID) + { + case HSPI_ID0: + HSPI = (HSPIM_TypeDef *)prvSPI[SpiID].RegBase; + + HSPI->FCR = (32 << HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS)|(32 << HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS)|(3 << 6)|(63); + HSPI->FCR &= ~(3 << 6); + HSPI->CR0 &= ~(7 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS); + if (WLen <= HSPIM_FIFO_TX_NUM) + { + TxLen = WLen; + } + else + { + TxLen = HSPIM_FIFO_TX_NUM; + } + for(i = 0; i < TxLen; i++) + { + HSPI->WDR = TxData[i]; + } + for(RxLen = 0; RxLen < WLen; RxLen++) + { + while (HSPI->SR & HSPIM_SR_POP_EMPTY_RX) + { + ; + } + DummyData = HSPI->RDR; + if (TxLen < WLen) + { + HSPI->WDR = TxData[TxLen]; + TxLen++; + } + } + if (RLen <= HSPIM_FIFO_TX_NUM) + { + TxLen = RLen; + } + else + { + TxLen = HSPIM_FIFO_TX_NUM; + } + for(i = 0; i < TxLen; i++) + { + HSPI->WDR = TxData[i]; + } + for(RxLen = 0; RxLen < RLen; RxLen++) + { + while (HSPI->SR & HSPIM_SR_POP_EMPTY_RX) + { + ; + } + RxData[RxLen] = HSPI->RDR; + if (TxLen < RLen) + { + HSPI->WDR = 0xff; + TxLen++; + } + } + + break; + case SPI_ID0: + case SPI_ID1: + case SPI_ID2: + SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase; + ISR_OnOff(prvSPI[SpiID].IrqLine, 0); + SPI->SER = 0; + if (WLen <= SPIM_FIFO_TX_NUM) + { + TxLen = WLen; + } + else + { + TxLen = SPIM_FIFO_TX_NUM; + } + for(i = 0; i < TxLen; i++) + { + SPI->DR = TxData[i]; + } + SPI->SER = 1; + for(RxLen = 0; RxLen < WLen; RxLen++) + { + while (!SPI->RXFLR) + { + ; + } + DummyData = SPI->DR; + if (TxLen < WLen) + { + SPI->DR = TxData[TxLen]; + TxLen++; + } + } + if (RLen <= SPIM_FIFO_TX_NUM) + { + TxLen = RLen; + } + else + { + TxLen = SPIM_FIFO_TX_NUM; + } + for(i = 0; i < TxLen; i++) + { + SPI->DR = TxData[i]; + } + + for(RxLen = 0; RxLen < RLen; RxLen++) + { + while (!SPI->RXFLR) + { + ; + } + RxData[RxLen] = SPI->DR; + if (TxLen < RLen) + { + SPI->DR = 0xff; + TxLen++; + } + } + SPI->SER = 0; + break; + } + prvSPI[SpiID].IsBusy = 0; + prvSPI[SpiID].Callback((void *)SpiID, prvSPI[SpiID].pParam); + return 0; +} + +int32_t SPI_FlashBlockTransfer(uint8_t SpiID, const uint8_t *TxData, uint32_t WLen, uint8_t *RxData, uint32_t RLen) +{ +#ifdef __BUILD_OS__ + if ( (prvSPI[SpiID].DMARxStream == 0xff) || (prvSPI[SpiID].DMATxStream == 0xff) || OS_CheckInIrq() || ((prvSPI[SpiID].Speed >> 3) >= ((WLen + RLen) * 100000))) + { + prvSPI[SpiID].IsBlockMode = 0; +#endif + return prvSPI_FlashBlockTransfer(SpiID, TxData, WLen, RxData, RLen); +#ifdef __BUILD_OS__ + } + int32_t Result; + uint32_t Time = ((WLen + RLen) * 1000) / (prvSPI[SpiID].Speed >> 3); + uint8_t *Temp = malloc(WLen + RLen); + memcpy(Temp, TxData, WLen); + prvSPI[SpiID].IsBlockMode = 1; + + if (TxData) + { + Result = SPI_Transfer(SpiID, Temp, Temp, WLen + RLen, 1); + } + else + { + Result = SPI_Transfer(SpiID, Temp, Temp, WLen + RLen, 1); + } + if (Result) + { + prvSPI[SpiID].IsBlockMode = 0; + free(Temp); + return Result; + } + if (OS_MutexLockWtihTime(prvSPI[SpiID].Sem, Time + 10)) + { + free(Temp); + DBG("!!!"); + DMA_StopStream(prvSPI[SpiID].DMATxStream); + DMA_StopStream(prvSPI[SpiID].DMARxStream); + SPI_TransferStop(SpiID); + prvSPI[SpiID].IsBlockMode = 0; + return -1; + } + memcpy(RxData, Temp + WLen, RLen); + prvSPI[SpiID].IsBlockMode = 0; + free(Temp); + return 0; +#endif +} + + +void SPI_DMATxInit(uint8_t SpiID, uint8_t Stream, uint32_t Channel) +{ + SPI_TypeDef *SPI; + HSPIM_TypeDef *HSPI; + DMA_InitTypeDef DMA_InitStruct; + DMA_BaseConfig(&DMA_InitStruct); + DMA_InitStruct.DMA_Peripheral = prvSPI[SpiID].DMATxChannel; + DMA_InitStruct.DMA_Priority = DMA_Priority_3; + prvSPI[SpiID].DMATxStream = Stream; + switch(SpiID) + { + case HSPI_ID0: + HSPI = (HSPIM_TypeDef *)prvSPI[SpiID].RegBase; + if (prvSPI[SpiID].IsOnlyTx) + { + DMA_InitStruct.DMA_Priority = DMA_Priority_0; + } + DMA_InitStruct.DMA_PeripheralBurstSize = DMA_BurstSize_32; + DMA_InitStruct.DMA_MemoryBurstSize = DMA_BurstSize_32; + DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&HSPI->WDR; + break; + case SPI_ID0: + case SPI_ID1: + case SPI_ID2: + SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase; + DMA_InitStruct.DMA_PeripheralBurstSize = DMA_BurstSize_8; + DMA_InitStruct.DMA_MemoryBurstSize = DMA_BurstSize_8; + DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&SPI->DR; + break; +// case SPI_ID3: +// SYSCTRL->PHER_CTRL |= SYSCTRL_PHER_CTRL_SPI0_SLV_EN; +// break; + default: + return; + } + DMA_ConfigStream(Stream, &DMA_InitStruct); +} +void SPI_DMARxInit(uint8_t SpiID, uint8_t Stream, uint32_t Channel) +{ + SPI_TypeDef *SPI; + HSPIM_TypeDef *HSPI; + DMA_InitTypeDef DMA_InitStruct; + DMA_BaseConfig(&DMA_InitStruct); + DMA_InitStruct.DMA_Peripheral = prvSPI[SpiID].DMARxChannel; + DMA_InitStruct.DMA_Priority = DMA_Priority_2; + prvSPI[SpiID].DMARxStream = Stream; + switch(SpiID) + { + case HSPI_ID0: + HSPI = (HSPIM_TypeDef *)prvSPI[SpiID].RegBase; + DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&HSPI->RDR; + break; + case SPI_ID0: + case SPI_ID1: + case SPI_ID2: + SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase; + DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&SPI->DR; + break; +// case SPI_ID3: +// SYSCTRL->PHER_CTRL |= SYSCTRL_PHER_CTRL_SPI0_SLV_EN; +// break; + default: + return; + } + DMA_ConfigStream(Stream, &DMA_InitStruct); +} + +void SPI_TransferStop(uint8_t SpiID) +{ + uint16_t Data; + ISR_Clear(prvSPI[SpiID].IrqLine); + ISR_OnOff(prvSPI[SpiID].IrqLine, 0); + SPI_TypeDef *SPI; + HSPIM_TypeDef *HSPI; + uint32_t TxLen, i; + DMA_StopStream(prvSPI[SpiID].DMATxStream); + DMA_StopStream(prvSPI[SpiID].DMARxStream); + switch(SpiID) + { + case HSPI_ID0: + HSPI = (HSPIM_TypeDef *)prvSPI[SpiID].RegBase; + HSPI->CR0 &= ~(7 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS); + HSPI->FCR = (32 << HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS)|(32 << HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS)|(3 << 6)|(63); + HSPI->FCR &= ~(3 << 6); + break; + case SPI_ID0: + SYSCTRL->PHER_CTRL &= ~SYSCTRL_PHER_CTRL_SPI0_SLV_EN; + case SPI_ID1: + case SPI_ID2: + SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase; + while(SPI->TXFLR){;} + while(SPI->RXFLR){Data = SPI->DR;} + SPI->SER = 0; + break; +// case SPI_ID3: +// SYSCTRL->PHER_CTRL |= SYSCTRL_PHER_CTRL_SPI0_SLV_EN; +// break; + default: + return ; + } + + prvSPI[SpiID].IsBusy = 0; + +} + +uint8_t SPI_IsTransferBusy(uint8_t SpiID) +{ + return prvSPI[SpiID].IsBusy; +} + +void SPI_SetNewConfig(uint8_t SpiID, uint32_t Speed, uint8_t NewMode) +{ + HSPIM_TypeDef *HSPI; + SPI_TypeDef *SPI; + uint32_t div; + if (prvSPI[SpiID].IsBusy) return; + + switch(SpiID) + { + case HSPI_ID0: + HSPI = (HSPIM_TypeDef *)prvSPI[SpiID].RegBase; + div = (SystemCoreClock / Speed) >> 1; + HSPI->CR1 = (div << HSPIM_CR1_PARAM_BAUDRATE_POS) + 1; + prvSPI[SpiID].Speed = (SystemCoreClock >> 1) / div; + HSPI->CR0 &= ~((1 << HSPIM_CR0_PARAM_CPOL_POS)|(1 << HSPIM_CR0_PARAM_CPHA_POS)); + switch(NewMode) + { + case SPI_MODE_0: + + break; + case SPI_MODE_1: + HSPI->CR0 |= (1 << HSPIM_CR0_PARAM_CPHA_POS); + break; + case SPI_MODE_2: + HSPI->CR0 |= (1 << HSPIM_CR0_PARAM_CPOL_POS); + break; + case SPI_MODE_3: + HSPI->CR0 |= (1 << HSPIM_CR0_PARAM_CPOL_POS)|(1 << HSPIM_CR0_PARAM_CPHA_POS); + break; + } + break; + case SPI_ID0: + case SPI_ID1: + case SPI_ID2: + SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase; + SPI->SSIENR = 0; + div = (SystemCoreClock >> 2) / Speed; + if (div % 2) div++; + prvSPI[SpiID].Speed = (SystemCoreClock >> 2) / div; + SPI->BAUDR = div; + SPI->CTRLR0 &= ~(SPI_CTRLR0_SCPOL|SPI_CTRLR0_SCPH); + switch(NewMode) + { + case SPI_MODE_0: + break; + case SPI_MODE_1: + SPI->CTRLR0 |= SPI_CTRLR0_SCPH; + break; + case SPI_MODE_2: + SPI->CTRLR0 |= SPI_CTRLR0_SCPOL; + break; + case SPI_MODE_3: + SPI->CTRLR0 |= SPI_CTRLR0_SCPOL|SPI_CTRLR0_SCPH; + break; + } + SPI->SSIENR = 1; + break; + } +} diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_tick.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_tick.c new file mode 100644 index 0000000000..01f293a134 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_tick.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "bl_inc.h" +volatile static uint64_t PowerOnTickCnt; +volatile static uint64_t prvPeriod; +// +static void SystemTickIrqHandler( int32_t Line, void *pData) +{ + volatile uint32_t clr; + clr = TIMM0->TIM[CORE_TICK_TIM].EOI; + PowerOnTickCnt += prvPeriod; +} + +uint64_t GetSysTick(void) +{ + volatile uint32_t clr; + volatile uint64_t PowerOnTick; + ISR_OnOff(CORE_TICK_IRQ, 0); + PowerOnTick = PowerOnTickCnt + prvPeriod - TIMM0->TIM[CORE_TICK_TIM].CurrentValue; + if (TIMM0->TIM[CORE_TICK_TIM].IntStatus) + { + ISR_OnOff(CORE_TICK_IRQ, 1); + while(TIMM0->TIM[CORE_TICK_TIM].IntStatus){;} + PowerOnTick = PowerOnTickCnt + prvPeriod - TIMM0->TIM[CORE_TICK_TIM].CurrentValue; + } + ISR_OnOff(CORE_TICK_IRQ, 1); + return PowerOnTick; +} + +uint64_t GetSysTickUS(void) +{ + return GetSysTick()/CORE_TICK_1US; +} + +uint64_t GetSysTickMS(void) +{ + return GetSysTick()/CORE_TICK_1MS; +} + + +void SysTickDelay(uint32_t Tick) +{ + uint64_t Tick1 = GetSysTick(); + uint64_t Tick2 = Tick1 + Tick; + while(Tick2 > GetSysTick()){;} + return; +} + +void SysTickDelayUntil(uint64_t StartTick, uint32_t Tick) +{ + uint64_t Tick1 = StartTick + Tick; + while(Tick1 > GetSysTick()){;} + return; +} + +uint8_t SysTickCheckTimeout(uint64_t StartTick, uint32_t Tick) +{ + uint64_t Tick1 = StartTick + Tick; + if (Tick1 > GetSysTick()) + { + return 0; + } + return 1; +} + +void CoreTick_Init(void) +{ + prvPeriod = SystemCoreClock; + TIMM0->TIM[CORE_TICK_TIM].ControlReg = 0; + TIMM0->TIM[CORE_TICK_TIM].LoadCount = prvPeriod - 1; + TIMM0->TIM[CORE_TICK_TIM].ControlReg = TIMER_CONTROL_REG_TIMER_ENABLE|TIMER_CONTROL_REG_TIMER_MODE; + ISR_OnOff(CORE_TICK_IRQ, 0); + ISR_SetHandler(CORE_TICK_IRQ, SystemTickIrqHandler, NULL); + ISR_SetPriority(CORE_TICK_IRQ, CORE_TICK_IRQ_LEVEL); + ISR_OnOff(CORE_TICK_IRQ, 1); +} diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_uart.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_uart.c new file mode 100644 index 0000000000..af7de35389 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_uart.c @@ -0,0 +1,601 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "user.h" + +typedef struct +{ + const UART_TypeDef *RegBase; + const int IrqLine; + const uint16_t DMATxChannel; + const uint16_t DMARxChannel; + CBFuncEx_t Callback; + Buffer_Struct TxBuf; + Buffer_Struct RxBuf; + uint32_t LastError; + uint8_t RxCacheMode; + uint8_t DMATxStream; + uint8_t DMARxStream; +}Uart_ResourceStruct; + +static Uart_ResourceStruct prvUart[UART_MAX] = { + { + UART0, + UART0_IRQn, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART0_TX, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART0_RX, + }, + { + UART1, + UART1_IRQn, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART1_TX, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART1_RX, + }, + { + UART2, + UART2_IRQn, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART2_TX, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART2_RX, + }, + { + UART3, + UART3_IRQn, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART3_TX, + SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART3_RX, + }, +}; + +static int32_t prvUart_DummyCB(void *pData, void *pParam) +{ + return 0; +} +static void prvUart_IrqHandle(int32_t IrqLine, void *pData); + + +static int32_t prvUart_DMAIrqCB(void *pData, void *pParam) +{ + uint8_t UartID = (uint32_t)pData; + prvUart[UartID].Callback(pData, pParam); +} + +static void prvUart_FIFOInit(UART_TypeDef *UARTx, UART_FIFOInitTypeDef *UART_FIFOInitStruct) +{ + /************************** FIFO Tx Interrupt Config ******************************/ + if (DISABLE != UART_FIFOInitStruct->FIFO_TX_TriggerIntEnable) + { + UARTx->OFFSET_4.IER |= UART_IER_PTIME; + } + else + { + UARTx->OFFSET_4.IER &= ~UART_IER_PTIME; + } + + /************************** FIFO Config ******************************/ + /* FCR Write Only So Here we Use FCR Shadow Register SDMAM(WR) */ + if (UARTx->SFE | UART_SFE_SFE) + { + UARTx->SFE &= ~UART_SFE_SFE; + } + + if (UART_FIFO_DMA_Mode_0 == UART_FIFOInitStruct->FIFO_DMA_Mode) + { + UARTx->SDMAM &= ~UART_SDMAM_SDMAM; + } + else if(UART_FIFO_DMA_Mode_1 == UART_FIFOInitStruct->FIFO_DMA_Mode) + { + UARTx->SDMAM |= UART_SDMAM_SDMAM; + } + + /* FCR Write Only So Here we Use FCR Shadow Register SRT and STET(WR) */ + UARTx->SRT = UART_FIFOInitStruct->FIFO_RX_Trigger; + UARTx->STET = UART_FIFOInitStruct->FIFO_TX_Trigger; + + if (DISABLE != UART_FIFOInitStruct->FIFO_Enable) + { + UARTx->SFE |= UART_SFE_SFE; + } + else + { + UARTx->SFE &= ~UART_SFE_SFE; + } +} + + +void Uart_GlobalInit(void) +{ + int i, j; + for(i = 0; i < UART_MAX; i++) + { + memset(&prvUart[i].RxBuf, 0, sizeof(Buffer_Struct)); + prvUart[i].RxCacheMode = 0; + } +} + +void Uart_BaseInit(uint8_t UartID, uint32_t BaudRate, uint8_t IsRxCacheEnable, uint8_t DataBits, uint8_t Parity, uint8_t StopBits, CBFuncEx_t CB) +{ + uint32_t tmpBaudRateDiv, LCR; + UART_FIFOInitTypeDef UART_FIFOInitStruct; + UART_TypeDef* Uart = prvUart[UartID].RegBase; + SYSCTRL->SOFT_RST1 = (1 << UartID); + while(SYSCTRL->SOFT_RST1 & (1 << UartID)){;} + UART_FIFOInitStruct.FIFO_Enable = ENABLE; + UART_FIFOInitStruct.FIFO_DMA_Mode = UART_FIFO_DMA_Mode_1; + UART_FIFOInitStruct.FIFO_RX_Trigger = UART_FIFO_RX_Trigger_1_2_Full; + UART_FIFOInitStruct.FIFO_TX_Trigger = UART_FIFO_TX_Trigger_1_4_Full; + UART_FIFOInitStruct.FIFO_TX_TriggerIntEnable = ENABLE; + + ISR_SetHandler(prvUart[UartID].IrqLine, prvUart_IrqHandle, (void *)UartID); +#ifdef __BUILD_OS__ + ISR_SetPriority(prvUart[UartID].IrqLine, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 2); +#else + ISR_SetPriority(prvUart[UartID].IrqLine, 5); +#endif + if (CB) + { + prvUart[UartID].Callback = CB; + } + else + { + prvUart[UartID].Callback = prvUart_DummyCB; + } +// UART_Init(Uart, &UART_InitStruct); + Uart->LCR |= UART_LCR_DLAB; + + // baud rate = (serial clock freq) / (16 * divisor). + tmpBaudRateDiv = (SystemCoreClock >> 6) / BaudRate; + Uart->OFFSET_0.DLL = (tmpBaudRateDiv & 0x00FF); + Uart->OFFSET_4.DLH = ((tmpBaudRateDiv >> 8) & 0x00FF); + + /* LCR = 0 */ + Uart->LCR &= ~UART_LCR_DLAB; + LCR = UART_WordLength_5b + DataBits - UART_DATA_BIT5; + switch(Parity) + { + case UART_STOP_BIT1: + LCR |= UART_StopBits_1; + break; + case UART_STOP_BIT1_5: + LCR |= UART_StopBits_1_5; + break; + case UART_STOP_BIT2: + LCR |= UART_StopBits_2; + break; + } + switch(Parity) + { + case UART_PARITY_NONE: + LCR |= UART_Parity_No; + break; + case UART_PARITY_ODD: + LCR |= UART_Parity_Odd; + break; + case UART_PARITY_EVEN: + LCR |= UART_Parity_Even; + break; + } + Uart->LCR = LCR; + prvUart_FIFOInit(Uart, &UART_FIFOInitStruct); + ISR_OnOff(prvUart[UartID].IrqLine, 0); + Uart->SFE |= UART_SFE_SFE; + Uart->OFFSET_4.IER = UART_IER_ELSI; + prvUart[UartID].RxCacheMode = IsRxCacheEnable; +} + + +void Uart_SetCb(uint8_t UartID, CBFuncEx_t CB) +{ + if (CB) + { + prvUart[UartID].Callback = CB; + } + else + { + prvUart[UartID].Callback = prvUart_DummyCB; + } +} + +void Uart_DeInit(uint8_t UartID) +{ + UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase; + Uart->OFFSET_4.IER = 0; + Uart_BufferTxStop(UartID); + ISR_OnOff(prvUart[UartID].IrqLine, 0); + ISR_Clear(prvUart[UartID].IrqLine); + /* LCR = 1 */ + Uart->LCR |= UART_LCR_DLAB; + Uart->OFFSET_0.DLL = 0; + Uart->OFFSET_4.DLH = 0; + + /* LCR = 0 */ + Uart->LCR &= ~UART_LCR_DLAB; + + +} + +int Uart_DMATxInit(uint8_t UartID, uint8_t Stream, uint32_t Channel) +{ + DMA_InitTypeDef DMA_InitStruct; + UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase; + DMA_BaseConfig(&DMA_InitStruct); + DMA_InitStruct.DMA_Peripheral = prvUart[UartID].DMATxChannel; + DMA_InitStruct.DMA_PeripheralBurstSize = DMA_BurstSize_8; + DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&Uart->OFFSET_0.THR; + DMA_InitStruct.DMA_Priority = DMA_Priority_3; + DMA_InitStruct.DMA_MemoryBurstSize = DMA_BurstSize_8; + prvUart[UartID].DMATxStream = Stream; + return DMA_ConfigStream(Stream, &DMA_InitStruct); +} + +int Uart_DMARxInit(uint8_t UartID, uint8_t Stream, uint32_t Channel) +{ + DMA_InitTypeDef DMA_InitStruct; + UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase; + DMA_BaseConfig(&DMA_InitStruct); + DMA_InitStruct.DMA_Peripheral = prvUart[UartID].DMARxChannel; + DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&Uart->OFFSET_0.RBR; + DMA_InitStruct.DMA_Priority = DMA_Priority_3; + prvUart[UartID].DMARxStream = Stream; + return DMA_ConfigStream(Stream, &DMA_InitStruct); +} + +void Uart_BlockTx(uint8_t UartID, uint8_t *Data, uint32_t Len) +{ + uint32_t i = 0; + UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase; + Uart->OFFSET_4.IER &= ~(UART_IER_PTIME|UART_IER_ETBEI); + while(i < Len) + { + while (Uart->USR & UART_STATUS_TX_FIFO_NOT_FULL) + { + Uart->OFFSET_0.THR = Data[i]; + i++; + } + } +} + +void Uart_NoBlockTx(uint8_t UartID, uint8_t Data) +{ + uint32_t i = 0; + UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase; + while (!(Uart->USR & UART_STATUS_TX_FIFO_NOT_FULL)) + { + + } + Uart->OFFSET_0.THR = Data; +} + +void Uart_EnableRxIrq(uint8_t UartID) +{ + UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase; + Uart->SRT = UART_FIFO_RX_Trigger_1_2_Full; + Uart->OFFSET_4.IER |= UART_IT_RX_RECVD|UART_IER_ELSI; + ISR_OnOff(prvUart[UartID].IrqLine, 1); +} + +void Uart_EnableTxDoneIrq(uint8_t UartID) +{ + + +} + +void Uart_DMATx(uint8_t UartID, uint8_t Stream, const uint8_t *Data, uint32_t Len) +{ + UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase; + Uart->OFFSET_4.IER &= ~(UART_IER_PTIME|UART_IER_ETBEI); + DMA_ClearStreamFlag(Stream); + DMA_ForceStartStream(Stream, Data, Len, prvUart_DMAIrqCB, (uint32_t)UartID, 1); + Uart->OFFSET_4.IER |= UART_IER_PTIME|UART_IER_ETBEI; + ISR_OnOff(prvUart[UartID].IrqLine, 1); +} + +void Uart_DMARx(uint8_t UartID, uint8_t Stream, uint8_t *Data, uint32_t Len) +{ + UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase; + Uart->OFFSET_4.IER |= UART_IT_RX_RECVD; + Uart->SRT = UART_FIFO_RX_Trigger_1_4_Full; + ISR_OnOff(prvUart[UartID].IrqLine, 1); + DMA_ClearStreamFlag(Stream); + DMA_ForceStartStream(Stream, Data, Len, prvUart_DMAIrqCB, (uint32_t)UartID, 1); +} + + +int32_t Uart_BufferTx(uint8_t UartID, const uint8_t *Data, uint32_t Len) +{ + UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase; + + ISR_OnOff(prvUart[UartID].IrqLine, 0); +#ifdef __BUILD_OS__ + if (Data && Len) + { + OS_BufferWrite(&prvUart[UartID].TxCacheBuf, Data, Len); + } +#endif + if (prvUart[UartID].TxBuf.Data || prvUart[UartID].TxBuf.MaxLen) + { + ISR_OnOff(prvUart[UartID].IrqLine, 1); + return 0; + } + Uart->OFFSET_4.IER &= ~(UART_IER_PTIME|UART_IER_ETBEI); +#ifdef __BUILD_OS__ + // 把缓存的Tx指针交给发送的Tx指针,缓存的Tx指针重新建立一个 + Buffer_StaticInit(&prvUart[UartID].TxBuf, prvUart[UartID].TxCacheBuf.Data, prvUart[UartID].TxCacheBuf.Pos); +#else + Buffer_StaticInit(&prvUart[UartID].TxBuf, Data, Len); +#endif + while ((prvUart[UartID].TxBuf.Pos < prvUart[UartID].TxBuf.MaxLen) && (Uart->USR & UART_STATUS_TX_FIFO_NOT_FULL)) + { + Uart->OFFSET_0.THR = prvUart[UartID].TxBuf.Data[prvUart[UartID].TxBuf.Pos]; + prvUart[UartID].TxBuf.Pos++; + } + if (prvUart[UartID].TxBuf.Pos >= prvUart[UartID].TxBuf.MaxLen) + { + // 只有少量数据,只靠FIFO就能填充满,就不需要重新分配内存 + memset(&prvUart[UartID].TxBuf, 0, sizeof(prvUart[UartID].TxBuf)); +#ifdef __BUILD_OS__ + prvUart[UartID].TxCacheBuf.Pos = 0; +#endif + ISR_OnOff(prvUart[UartID].IrqLine, 1); + Uart->OFFSET_4.IER |= UART_IER_ETBEI|UART_IER_ELSI; + return 0; + } + else + { + // 数据多,暂时发不完,就需要为缓存重新分配内存 +#ifdef __BUILD_OS__ + OS_InitBuffer(&prvUart[UartID].TxCacheBuf, TX_BUF_INIT); +#endif + ISR_OnOff(prvUart[UartID].IrqLine, 1); + Uart->OFFSET_4.IER |= UART_IER_PTIME|UART_IER_ETBEI|UART_IER_ELSI; + return 1; + } +} + + +void Uart_BufferTxStop(uint8_t UartID) +{ + UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase; + Uart->OFFSET_4.IER &= ~(UART_IER_PTIME|UART_IER_ETBEI); + ISR_OnOff(prvUart[UartID].IrqLine, 0); + memset(&prvUart[UartID].TxBuf, 0, sizeof(Buffer_Struct)); + ISR_OnOff(prvUart[UartID].IrqLine, 1); +} + + +static uint32_t prvUart_FifoRead(uint8_t UartID, uint8_t *Data, uint8_t Len) +{ + uint32_t i = 0; + UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase; + + while (Uart->USR & UART_STATUS_RX_FIFO_NOT_EMPTY && (--Len)) + { + Data[i] = Uart->OFFSET_0.RBR; + i++; + } + return i; + +} + +uint32_t Uart_FifoRead(uint8_t UartID, uint8_t *Data) +{ + uint32_t i = 0; + UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase; + + while (Uart->USR & UART_STATUS_RX_FIFO_NOT_EMPTY) + { + Data[i] = Uart->OFFSET_0.RBR; + i++; + } + return i; + +} + +int Uart_ReadByte(uint8_t UartID, uint8_t *Data) +{ + UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase; + if (Uart->USR & UART_STATUS_RX_FIFO_NOT_EMPTY) + { + *Data = Uart->OFFSET_0.RBR; + return 0; + } + else + { + return -1; + } +} + +void Uart_RxBufferCB(uint8_t UartID, CBFuncEx_t CB) +{ +#ifdef __BUILD_OS__ + uint32_t ReadLen; + if (!prvUart[UartID].RxCacheMode) + { + return ; + } + ISR_OnOff(prvUart[UartID].IrqLine, 0); + if (!CB(prvUart[UartID].RxBuf.Data, (void *)prvUart[UartID].RxBuf.Pos)) + { + prvUart[UartID].RxBuf.Pos = 0; + if (prvUart[UartID].RxBuf.MaxLen > RX_BUF_HIGH) + { + OS_ReInitBuffer(&prvUart[UartID].RxBuf, RX_BUF_INIT); + } + } + ISR_OnOff(prvUart[UartID].IrqLine, 1); +#endif +} + +uint32_t Uart_RxBufferRead(uint8_t UartID, uint8_t *Data, uint32_t Len) +{ +#ifdef __BUILD_OS__ + uint32_t ReadLen; + if (!prvUart[UartID].RxCacheMode) + { + return 0; + } + ISR_OnOff(prvUart[UartID].IrqLine, 0); + if (!Len) + { + ReadLen = prvUart[UartID].RxBuf.Pos; + ISR_OnOff(prvUart[UartID].IrqLine, 1); + return ReadLen; + } + ReadLen = (prvUart[UartID].RxBuf.Pos < Len)?prvUart[UartID].RxBuf.Pos:Len; + memcpy(Data, prvUart[UartID].RxBuf.Data, ReadLen); + OS_BufferRemove(&prvUart[UartID].RxBuf, ReadLen); + if (!prvUart[UartID].RxBuf.Pos && prvUart[UartID].RxBuf.MaxLen > RX_BUF_HIGH) + { + OS_ReInitBuffer(&prvUart[UartID].RxBuf, RX_BUF_INIT); + } + ISR_OnOff(prvUart[UartID].IrqLine, 1); + return ReadLen; +#else + return 0; +#endif +} + +void Uart_RxBufferClear(uint8_t UartID) +{ + uint32_t ReadLen; + if (!prvUart[UartID].RxCacheMode) + { + return ; + } + ISR_OnOff(prvUart[UartID].IrqLine, 0); + prvUart[UartID].RxBuf.Pos = 0; + ISR_OnOff(prvUart[UartID].IrqLine, 1); +} + +static void prvUart_Tx(uint8_t UartID, UART_TypeDef* Uart) +{ + if (prvUart[UartID].TxBuf.Data) + { + while ((prvUart[UartID].TxBuf.Pos < prvUart[UartID].TxBuf.MaxLen) && (Uart->USR & UART_STATUS_TX_FIFO_NOT_FULL)) + { + Uart->OFFSET_0.THR = prvUart[UartID].TxBuf.Data[prvUart[UartID].TxBuf.Pos]; + prvUart[UartID].TxBuf.Pos++; + } + if (prvUart[UartID].TxBuf.Pos >= prvUart[UartID].TxBuf.MaxLen) + { +#ifdef __BUILD_OS__ + OS_DeInitBuffer(&prvUart[UartID].TxBuf); + Uart_BufferTx(UartID, NULL, 0); +#else + memset(&prvUart[UartID].TxBuf, 0, sizeof(prvUart[UartID].TxBuf)); +#endif + } + } +#ifdef __BUILD_OS__ + else if (prvUart[UartID].TxCacheBuf.Pos) + { + Uart_BufferTx(UartID, NULL, 0); + } + + if (!prvUart[UartID].TxBuf.Data && !prvUart[UartID].TxCacheBuf.Pos) +#else + if (!prvUart[UartID].TxBuf.Data) +#endif + { + if (Uart->OFFSET_4.IER & UART_IER_PTIME) + { + Uart->OFFSET_4.IER &= ~UART_IER_PTIME; + prvUart[UartID].Callback((uint32_t)UartID, (void *)UART_CB_TX_BUFFER_DONE); + } + else + { + Uart->OFFSET_4.IER &= ~UART_IER_ETBEI; + prvUart[UartID].Callback((uint32_t)UartID, (void *)UART_CB_TX_ALL_DONE); + } + } +} + +static void prvUart_IrqHandle(int32_t IrqLine, void *pData) +{ + uint8_t UartID = (uint32_t)pData; + UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase; + uint32_t reg_value, read_len; + switch(Uart->OFFSET_8.IIR & 0x0f) + { + case UART_IT_ID_RX_RECVD: + { + prvUart[UartID].Callback((uint32_t)UartID, (void *)UART_CB_RX_NEW); + } + break; + case UART_IT_ID_TX_EMPTY: + { + + prvUart_Tx(UartID, Uart); + + } + break; + case UART_IT_ID_MODEM_STATUS: + { + reg_value = Uart->MSR; + } + break; + case UART_IT_ID_LINE_STATUS: + { + reg_value = Uart->LSR; + if (reg_value & UART_LSR_TEMT) + { + prvUart_Tx(UartID, Uart); + } + if (reg_value & (UART_LSR_PFE|UART_LSR_BI|UART_LSR_FE|UART_LSR_PE|UART_LSR_OE)) + { + prvUart[UartID].LastError = reg_value; + prvUart[UartID].Callback((uint32_t)UartID, (void *)UART_CB_ERROR); + } + } + break; + case UART_IT_ID_BUSY_DETECT: + { + reg_value = Uart->USR; + } + break; + case UART_IT_ID_CHAR_TIMEOUT: + prvUart[UartID].Callback((uint32_t)UartID, (void *)UART_CB_RX_TIMEOUT); + break; + default: + break; + } +} +void Uart_ChangeBR(uint8_t UartID, uint32_t BaudRate) +{ + UART_TypeDef* Uart = prvUart[UartID].RegBase; + Uart->LCR |= UART_LCR_DLAB; + + // baud rate = (serial clock freq) / (16 * divisor). + uint32_t tmpBaudRateDiv = (SystemCoreClock >> 6) / BaudRate; + Uart->OFFSET_0.DLL = (tmpBaudRateDiv & 0x00FF); + Uart->OFFSET_4.DLH = ((tmpBaudRateDiv >> 8) & 0x00FF); + + /* LCR = 0 */ + Uart->LCR &= ~UART_LCR_DLAB; +} + +uint32_t Uart_GetLastError(uint8_t UartID) +{ + return prvUart[UartID].LastError; +} + +void Uart_IrqOnOff(uint8_t UartID, uint8_t OnOff) +{ + ISR_OnOff(prvUart[UartID].IrqLine, OnOff); +} diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_usb_ll_driver.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_usb_ll_driver.c new file mode 100644 index 0000000000..ae7e20f59f --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_usb_ll_driver.c @@ -0,0 +1,1929 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "user.h" +#if 0 +#define USB_FIFO_MAX (512) +#define USB_FIFO_DW_DAX (128) + +/** + * 结构说明:调试控制寄存器(USBPHY_CR1)结构 + * 偏移地址:0x0108 + * 初 始 值:0x004921AE + * 属 性:RW + * 宽 度:32bit + */ +typedef union _USBPHY_CR1_TypeDef +{ + uint32_t d32; + struct{ + uint32_t txpreemphasistune : 1; /* */ + uint32_t txrisetune : 2; /* */ + uint32_t txvreftune : 4; /* */ + uint32_t txfslstune : 4; /* */ + uint32_t sqrxtune : 3; /* */ + uint32_t compdistune : 3; /* */ + uint32_t otgtune : 3; /* */ + uint32_t loopback_enb : 1; /* */ + uint32_t otg_disable : 1; /* */ + uint32_t commononn : 1; /* */ + uint32_t vatestenb : 1; /* */ + uint32_t lsbist : 1; /* */ + uint32_t fsbist : 1; /* */ + uint32_t hsbist : 1; /* */ + uint32_t bisten : 1; /* */ + uint32_t usb_iddq : 1; /* */ + uint32_t stop_ck_for_suspend : 1; /* */ + uint32_t bist_done : 1; /* */ + uint32_t bist_error : 1; /* */ + } b; +} USBPHY_CR1_TypeDef; + +/** + * 结构说明:调试控制寄存器(USBPHY_CR3)结构 + * 偏移地址:0x010C + * 初 始 值:0x00000000 + * 属 性:RW + * 宽 度:32bit + */ +typedef union _USBPHY_CR3_TypeDef +{ + uint32_t d32; + struct{ + uint32_t idpullup : 1; /* 用于操作 USB PHY的idpullup,启动PHY探测ID状态 */ + uint32_t iddig : 1; /* PHY 输出的ID状态信号,用于软件查询 */ + uint32_t reserved2_31 : 29; + } b; +} USBPHY_CR3_TypeDef; + +typedef struct +{ + // Common USB Registers. 0x00 - 0x0F. + __IO uint8_t FADDR; // Peripheral Mode Only. + union + { + __IO uint8_t POWER; + struct + { + __IO uint8_t en_suspendM : 1; + __IO uint8_t suspend_mode : 1; + __IO uint8_t resume : 1; + __IO uint8_t reset : 1; + __IO uint8_t HS_mode : 1; //不支持 + __IO uint8_t HS_enab : 1; //不支持 + __IO uint8_t soft_conn : 1; /* Periphera mode only */ + __IO uint8_t ISO_update : 1; /* Periphera mode only */ + } POWER_b; + }; + union + { + __IO uint16_t INTRTX; + struct + { + __IO uint16_t EP0_intp : 1; + __IO uint16_t EP1_tx_intp : 1; + __IO uint16_t EP2_tx_intp : 1; + __IO uint16_t EP3_tx_intp : 1; + __IO uint16_t EP4_tx_intp : 1; + __IO uint16_t EP5_tx_intp : 1; + __IO uint16_t EP6_tx_intp : 1; + __IO uint16_t EP7_tx_intp : 1; + __IO uint16_t EP8_tx_intp : 1; + __IO uint16_t EP9_tx_intp : 1; + __IO uint16_t EP10_tx_intp : 1; + __IO uint16_t EP11_tx_intp : 1; + __IO uint16_t EP12_tx_intp : 1; + __IO uint16_t EP13_tx_intp : 1; + __IO uint16_t EP14_tx_intp : 1; + __IO uint16_t EP15_tx_intp : 1; + } INTRTX_b; + }; + union + { + __IO uint16_t INTRRX; + struct + { + uint16_t reserved0 : 1; + uint16_t EP1_rx_intp : 1; + uint16_t EP2_rx_intp : 1; + uint16_t EP3_rx_intp : 1; + uint16_t EP4_rx_intp : 1; + uint16_t EP5_rx_intp : 1; + uint16_t EP6_rx_intp : 1; + uint16_t EP7_rx_intp : 1; + uint16_t EP8_rx_intp : 1; + uint16_t EP9_rx_intp : 1; + uint16_t EP10_rx_intp : 1; + uint16_t EP11_rx_intp : 1; + uint16_t EP12_rx_intp : 1; + uint16_t EP13_rx_intp : 1; + uint16_t EP14_rx_intp : 1; + uint16_t EP15_rx_intp : 1; + } INTRRX_b; + }; + union + { + __IO uint16_t INTRTXE; + struct + { + uint16_t en_EP0_intp : 1; + uint16_t en_EP1_tx_intp : 1; + uint16_t en_EP2_tx_intp : 1; + uint16_t en_EP3_tx_intp : 1; + uint16_t en_EP4_tx_intp : 1; + uint16_t en_EP5_tx_intp : 1; + uint16_t en_EP6_tx_intp : 1; + uint16_t en_EP7_tx_intp : 1; + uint16_t en_EP8_tx_intp : 1; + uint16_t en_EP9_tx_intp : 1; + uint16_t en_EP10_tx_intp : 1; + uint16_t en_EP11_tx_intp : 1; + uint16_t en_EP12_tx_intp : 1; + uint16_t en_EP13_tx_intp : 1; + uint16_t en_EP14_tx_intp : 1; + uint16_t en_EP15_tx_intp : 1; + } INTRTXE_b; + }; + union + { + __IO uint16_t INTRRXE; + struct + { + uint16_t reserved0 : 1; + uint16_t en_EP1_rx_intp : 1; + uint16_t en_EP2_rx_intp : 1; + uint16_t en_EP3_rx_intp : 1; + uint16_t en_EP4_rx_intp : 1; + uint16_t en_EP5_rx_intp : 1; + uint16_t en_EP6_rx_intp : 1; + uint16_t en_EP7_rx_intp : 1; + uint16_t en_EP8_rx_intp : 1; + uint16_t en_EP9_rx_intp : 1; + uint16_t en_EP10_rx_intp : 1; + uint16_t en_EP11_rx_intp : 1; + uint16_t en_EP12_rx_intp : 1; + uint16_t en_EP13_rx_intp : 1; + uint16_t en_EP14_rx_intp : 1; + uint16_t en_EP15_rx_intp : 1; + } INTRRXE_b; + }; + union + { + __IO uint8_t INTRUSB; + struct + { + uint8_t suspend : 1; /* Set when Suspend signaling is detected on the bus. Only valid in Peripheral mode. */ + uint8_t resume : 1; /* Set when Resume signaling is detected on the bus while the MUSBMHDRC is in Suspend mode. */ + uint8_t reset_babble : 1; /* Reset: Set in Peripheral mode when Reset signaling is detected on the bus. + * Babble: Set in Host mode when babble is detected. Note: Only active after first SOF has been sent. + */ + uint8_t sof : 1; /* Set when a new frame starts. */ + uint8_t conn : 1; /* Set when a device connection is detected. Only valid in Host mode. Valid at all transaction speeds. */ + uint8_t discon : 1; /* Set in Host mode when a device disconnect is detected. Set in Peripheral mode when a session ends. Valid at all transaction speeds. */ + uint8_t sess_req : 1; /* Set when Session Request signaling has been detected. Only valid when MUSBMHDRC is A device. */ + uint8_t VBus_error : 1; /* Set when VBus drops below the VBus Valid threshold during a session. Only valid when MUSBMHDRC is A device. */ + } INTRUSB_b; + }; + union + { + __IO uint8_t INTRUSBE; + struct + { + uint8_t en_suspend : 1; + uint8_t en_resume : 1; + uint8_t en_reset_babble : 1; + uint8_t en_sof : 1; + uint8_t en_conn : 1; + uint8_t en_discon : 1; + uint8_t en_sess_req : 1; + uint8_t en_VBus_error : 1; + } INTRUSBE_b; + }; + union + { + __IO uint16_t FRAME; + struct + { + uint16_t frame_number : 11; + uint16_t reserved11_15 : 5; /* Always return 0 */ + } FRAME_b; + }; + __IO uint8_t INDEX; + __IO uint8_t TESTMODE; + // Indexed CSR. 0x10 - 0x1F. + union + { + __IO uint16_t TXMAXP; + struct + { + __IO uint16_t max_payload_tran : 11; /* Bits 10:0 define(in bytes)the maximum payload transmitted in single transaction. + * The value set can be up to 1024 bytes but is subject to the constraints place by + * the USB Specification on packet sizes for Bulk,Interrupt and Isochronous transfers + * in Full-speed and High-speed operations. + */ + __IO uint16_t ex_max : 5; + } TXMAXP_b; + }; + union + { + __IO uint8_t CSR0L; + __IO uint8_t TXCSRL; + struct + { + __IO uint8_t rx_pkt_rdy : 1; /* This bit is set when a data packet has been received. An interrupt is + * generated when this bit is set. The CPU clear this bit by setting the + * ServicedRxPktRdy bit. + */ + __IO uint8_t tx_pkt_rdy : 1; /* The CPU sets this bits after loading a data packet into the FIFO. It is clear + * automatically when a data packet has been transmitted. An interrupt is also + * generated at this point(if enabled). + */ + __IO uint8_t sent_stall : 1; /* This bit is set when a STALL handshake is transmitted. + * The CPU should clear this bit. + */ + __IO uint8_t data_end : 1; /* The CPU sets this bit: + * 1. When setting TxPktRdy for the last data packet. + * 2. When clearing RxPktRdy after unloading the last data packet. + * 3. When setting TxPktRdy for zero length data packet. + * It is cleared automatically. + */ + __IO uint8_t setup_end : 1; /* This bit will be set when a control transaction ends before the DataEnd + * bit has been set. An interrupt will be generated and the FIFO flushed at + * this time.The bit is cleared by the CPU writing a 1 to the ServicedSetupEnd bit. + */ + __IO uint8_t send_stall : 1; /* The CPU write a 1 to this bit to terminate the current transaction. + * The STALL handshake will be transmitted and then this bit will be + * cleared automatically. + */ + __IO uint8_t serviced_rxpktrdy : 1; /* The CPU write a 1 to this bit to clear the RxPktRdy bit. + * It is Cleared automatically. + */ + __IO uint8_t serviced_setupend : 1; /* The CPU write a 1 to this bit to clear the SetupEnd bit. + * It is Cleared automatically. + */ + } CSR0L_DEV_b; + struct + { + __IO uint8_t rx_pkt_rdy : 1; /* This bit is set when a data packet has been received.An interrupt is generated + * (If enabled)when this bit set.The CPU should clear this bit when the packet has + * been read from the FIFO. + */ + __IO uint8_t tx_pkt_rdy : 1; /* The CPU sets this bit after loading a data packet into the FIFO.It is cleared + * automatically when a data packet has been transmitted. An interrupt is also + * generated at this point(If enabled). + */ + __IO uint8_t rx_stall : 1; /* This bit is set when a STALL handshake is received. The CPU should clear this bit. */ + __IO uint8_t setup_pkt : 1; /* The CPU sets this bit,at the TxPktRdy bit is set,to send a SETUP token instead + * of an OUT token for the transaction. Note: Setting this bit also clear the Data + * Toggle. + */ + __IO uint8_t error : 1; /* This bit will be set when three attempts have been made to perform a transaction + * with no response from the peripheral.The CPU should clear this bit.An interrupt + * is generated when this bit is set. + */ + __IO uint8_t req_pkt : 1; /* The CPU sets this bit to request an IN transaction. + * It is cleared when RxPktRdy is set. + */ + __IO uint8_t status_pkt : 1; /* The CPU sets this bit at the same time as the TxPktRdy or ReqPkt bit is set, + * to perform a status stage transaction. Setting this bit ensures that the data + * toggle is set to 1 so that a DATA1 packet is used for the Status Stage transaction. + */ + __IO uint8_t nak_timeout : 1; /* This bit will be set when Endpoint 0 is halted following the receipt for longer + * than the time set by the NAKLimit0 register. The CPU should clear this bit to allow + * the endpoint to continue. + */ + } CSR0L_HOST_b; + struct + { + __IO uint8_t tx_pkt_rdy : 1; /* The CPU sets this bit after loading a data packet into the FIFO. */ + __IO uint8_t fifo_not_empty : 1; /* The USB sets this bit when there is at least 1 packet in the TX FIFO. */ + __IO uint8_t under_run : 1; /* The USB sets this bit if an IN token is received when TxPktRdy is not set. The CPU should clear this bit. */ + __IO uint8_t flush_fifo : 1; /* The CPU writes a 1 to this bit to flush the latest packet from the endpoint TX FIFO */ + __IO uint8_t send_stall : 1; /* The CPU writes a 1 to this bit to issue a STALL handshake to an IN token.The CPU + * clears this bit to terminate the stall condition. + * Note:This bit has no effect where the endpoint is being used for Isochronous transfers. + */ + __IO uint8_t sent_stall : 1; /* This bit is set when a STALL handshake is transmitted.The FIFO is flushed and + * the TxPktRdy bit is cleared(see below).The CPU should clear this bit. + */ + __IO uint8_t clr_data_tog : 1; /* The CPU writes a 1 to this bit to reset the endpoint data toggle to 0. */ + __IO uint8_t incomp_tx : 1; /* When the endpoint is being used for high-bandwidth Isochronous,this bit is set to + * indicate where a large packet has been split into 2 or 3 packets for transmission + * but insufficient IN tokens have been received to send all the parts. + * Note:In anything other than isochronous transfers,this bit will always return 0. + */ + } TXCSRL_DEV_b; + struct + { + __IO uint8_t tx_pkt_rdy : 1; /* The CPU sets this bit after loading a data packet into the FIFO. */ + __IO uint8_t fifo_not_empty : 1; /* The USB sets this bit when there is at least 1 packet in the TX FIFO. */ + __IO uint8_t error : 1; + __IO uint8_t flush_fifo : 1; /* The CPU writes a 1 to this bit to flush the latest packet from the endpoint TX FIFO */ + __IO uint8_t setup_Pkt : 1; + __IO uint8_t Rx_stall : 1; + __IO uint8_t clr_data_tog : 1; /* The CPU writes a 1 to this bit to reset the endpoint data toggle to 0. */ + __IO uint8_t NAK_timeout_incompTx : 1; + } TXCSRL_HOST_b; + + }; + union + { + __IO uint8_t CSR0H; + __IO uint8_t TXCSRH; + struct + { + __IO uint8_t flush_fifo : 1; /* The CPU writes a 1 to this bit to flush the next packet to be transmitted/read from + * the Endpoint 0 FIFO. The FIFO pointer is reset and the TxPktRdy/RxPktRdy bit(below) is + * cleared. Note:FlushFIFO should only be used when TxPktRdy/RxPktRdy is set.At other + * times, it may cause data to be corrupted. + */ + __IO uint8_t reserved1_7 : 7; /* Unused. Return 0 when resd. */ + } CSR0H_DEV_b; + struct + { + __IO uint8_t flush_fifo : 1; /* The CPU writes a 1 to this bit to flush the next packet to be transmitted/read from + * the Endpoint 0 FIFO. The FIFO pointer is reset and the TxPktRdy/RxPktRdy bit(below) is + * cleared. Note:FlushFIFO should only be used when TxPktRdy/RxPktRdy is set.At other + * times, it may cause data to be corrupted. + */ + __IO uint8_t data_toggle : 1; /* When read,this bit indicates the current state of the Endpoint 0 data toggle. If D10 + * is high,this bit may be written with the written with the required setting of the data + * toggle.If D10 is low,any value written to this bit is ignored. + */ + __IO uint8_t data_toggle_wr_en : 1; /* The CPU written a 1 to this bit to enable the current state of Endpoint 0 data toggle + * to be written(see Data Toggle bit,below).This bit is automatically cleared once the new + * value is written. + */ + __IO uint8_t dis_ping : 1; /* The CPU writes a 1 to this bit to instruct the core not to issue PING tokens in data + * and status phases of a high-speed Control transfer(for use with devices that do not + * respond to PING). + */ + __IO uint8_t reserved1_7 : 4; /* Unused. Return 0 when resd. */ + } CSR0H_HOST_b; + struct + { + __IO uint8_t reserved0_1 : 2; + __IO uint8_t dma_req_mode : 1; + __IO uint8_t frc_data_tog : 1; + __IO uint8_t dma_req_enab : 1; + __IO uint8_t mode : 1; + __IO uint8_t iso : 1; + __IO uint8_t auto_set : 1; + } TXCSRH_DEV_b; + struct + { + __IO uint8_t data_toggle : 1; + __IO uint8_t data_toggle_wren : 1; + __IO uint8_t dma_req_mode : 1; + __IO uint8_t frc_data_tog : 1; + __IO uint8_t dma_req_enab : 1; + __IO uint8_t mode : 1; + __IO uint8_t reserved6 : 1; + __IO uint8_t auto_set : 1; + } TXCSRH_HOST_b; + }; + union + { + __IO uint16_t RXMAXP; + struct + { + __IO uint16_t max_payload_tran : 11; + __IO uint16_t ex_max : 5; + } RXMAXP_b; + }; + union + { + __IO uint8_t RXCSRL; + struct + { + __IO uint8_t rx_pkt_rdy : 1; /* This bit is set when a data packet has been received */ + __IO uint8_t fifo_full : 1; /* */ + __IO uint8_t over_run : 1; /* */ + __IO uint8_t data_error : 1; /* */ + __IO uint8_t flush_fifo : 1; + __IO uint8_t send_stall : 1; /* The CPU writes a 1 to this bit to issue a STALL handshake. */ + __IO uint8_t sent_stall : 1; /* This bit is set when a STALL handshake is transmitted. The CPU should clear this bit. */ + __IO uint8_t clr_data_tog : 1; + } RXCSRL_DEV_b; + struct + { + __IO uint8_t rx_pkt_rdy : 1; /* This bit is set when a data packet has been received */ + __IO uint8_t fifo_full : 1; /* */ + __IO uint8_t error : 1; /* */ + __IO uint8_t data_error : 1; /* */ + __IO uint8_t flush_fifo : 1; + __IO uint8_t ReqPkt : 1; + __IO uint8_t RxStall : 1; + __IO uint8_t clr_data_tog : 1; + } RXCSRL_HOST_b; + }; + union + { + __IO uint8_t RXCSRH; + struct + { + __IO uint8_t incomp_rx : 1; + __IO uint8_t reserved1_2 : 2; + __IO uint8_t dma_req_mode : 1; + __IO uint8_t dis_nyet_pid_error : 1; + __IO uint8_t dma_req_enab : 1; + __IO uint8_t iso : 1; + __IO uint8_t auto_clear : 1; + } RXCSRH_DEV_b; + struct + { + __IO uint8_t incomp_rx : 1; + __IO uint8_t data_toggle : 1; + __IO uint8_t data_toggle_wren : 1; + __IO uint8_t dma_req_mode : 1; + __IO uint8_t PID_error : 1; + __IO uint8_t dma_req_enab : 1; + __IO uint8_t auto_req : 1; + __IO uint8_t auto_clear : 1; + } RXCSRH_HOST_b; + }; + + union + { + __IO uint8_t COUNT0; + __IO uint16_t RXCOUNT; + struct + { + __IO uint8_t ep0_rx_count : 7; + __IO uint8_t reserved7 : 1; + } COUNT0_b; + }; + union + { + __IO uint8_t TYPE0; // Host Mode Only. + __IO uint8_t TXTYPE; // Host Mode Only. + struct + { + __IO uint8_t reserved0_5 : 6; /* Reserved */ + __IO uint8_t speed : 2; /* Operating speed of the target device : + * 00:Unused(Note: If selected,the target will be using the same connectionn speed as the core.) + * 01:High + * 10:Full + * 11:Low + */ + } TYPE0_b; + struct + { + __IO uint8_t target_EP_number : 4; /* Operating speed of the target device when the core is configured with the + * multipoint option: + * 00: Unused 01: High + * 10: Full 11: Low + * When the core is not configured with the multipoint option these bits should + * not be accessed. + */ + __IO uint8_t protocol : 2; /* The CPU should set this to select the required protocol for TX endpoint: + * 00: Control 01: Isochronous + * 10: Bulk 11: Interrupt + */ + __IO uint8_t speed : 2; /* Operating speed of the target device when the core is configured with + * the multipoint option: + * 00:Unused 01: High 10: Full 11:Low + * when the core is not configured with the multipoint option these bits + * should not be accessed. + */ + } TXTYPE_b; + }; + union + { + __IO uint8_t NAKLIMIT0; // Host Mode Only. + __IO uint8_t TXINTERVAL; // Host Mode Only. + struct + { + __IO uint8_t Endpoint0_NAK_Limit : 5; /* Endpoint 0 NAK limit (m) */ + __IO uint8_t reserved5_7 : 3; /* Reserve */ + } NAKLIMIT0_b; + struct + { + __IO uint8_t Tx_polling_interval :8; + } TXINTERVAL_b; + }; + union + { + __IO uint8_t RXTYPE; // Host Mode Only. + struct + { + __IO uint8_t target_EP_number : 4; /* Operating speed of the target device when the core is configured with the + * multipoint option: + * 00: Unused 01: High + * 10: Full 11: Low + * When the core is not configured with the multipoint option these bits should + * not be accessed. + */ + __IO uint8_t protocol : 2; /* The CPU should set this to select the required protocol for TX endpoint: + * 00: Control 01: Isochronous + * 10: Bulk 11: Interrupt + */ + __IO uint8_t speed : 2; /* Operating speed of the target device when the core is configured with + * the multipoint option: + * 00:Unused 01: High 10: Full 11:Low + * when the core is not configured with the multipoint option these bits + * should not be accessed. + */ + } RXTYPE_b; + }; + + __IO uint8_t RXINTERVAL; // Host Mode Only. + uint8_t UNUSED0; + union + { + __IO uint8_t CONFIGDATA; + __IO uint8_t FIFOSIZE; + struct + { + __IO uint8_t utmi_data_width : 1; /* Indicates selected UTMI+ data width. Always 0 indicating 8 bits. */ + __IO uint8_t soft_cone : 1; /* Always "1" . Indicates Soft Connect/Disconnect. */ + __IO uint8_t dyn_fifo_sizing : 1; /* When set to "1" indicates Dynamic FIFO Sizing option selected. */ + __IO uint8_t hb_txe : 1; /* When set to "1" indicates High-bandwidth TX ISO Endpoint Support selected */ + __IO uint8_t hb_rxe : 1; /* When set to "1" indicates High-bandwidth Rx ISO Endpoint Support selected. */ + __IO uint8_t big_endian : 1; /* Always "0". Indicates Little Endian ordering. */ + __IO uint8_t mp_txe : 1; /* When set to "1" automatic splitting of bulk packets is selected */ + __IO uint8_t mp_rxe : 1; /* When set to "1" automatic amalgamation of bulk packets is selected */ + } CONFIGDATA_b; + struct + { + __IO uint8_t tx_fifo_size : 4; + __IO uint8_t rx_fifo_size : 4; + } b; + }; + union + { + // FIFOS, EP0 - EP15 0x20 - 0x5F. + __IO uint8_t byte; + __IO uint16_t word; + __IO uint32_t dword; + } FIFOX[16]; + + // OTG, DynFIFO + Version. 0x60 - 0x6F. + union + { + __IO uint8_t DEVCTL; + struct + { + __IO uint8_t session : 1; /* When operation as an 'A' device,this bit is set or cleared by the CPU to + * start or end a session. When operating as a 'B' device,this bit is set/cleared + * by the MUSBMHDRC when a session starts/ends. It is also set by the CPU to initiate + * the Session Request Protocol.When the MUSBMHDRC is in Suspend mode,the bit may be + * cleared by the CPU to perform a software disconnect.Note:Clearing this bit when the + * core is not suspended will result in undefined behavior. + */ + __IO uint8_t host_req : 1; /* When set,the MUSBMHDRC will initiate the Host Negotiation when Suspend + * mode is entered.It is cleared when Host Negotiation is completed. + */ + __IO uint8_t host_mode : 1; /* This Read-only bit is set when the MUSBMHDRC is acting as a Host. */ + __IO uint8_t VBus : 2; /* These Read-only bits encode the current VBus level as follows: + * D4 D3 Meaning + * 0 0 Below SessionEnd + * 0 1 Above SessionEnd,below AValid + * 1 0 Above AValid,below VBus Valid + * 1 1 Above VBus Valid + */ + __IO uint8_t LSDev : 1; /* This Read-only bit is set when a low-speed device has been detected being + * connected to the port. Only valid in Host mode. + */ + __IO uint8_t FSDev : 1; /* This Read-only bit is set when a full-speed or high-speed device has been + * detected being connected to the port.(High-speed device are distinguished + * from full-speed by checking for high-speed chirps when the device is reset.) + * Only valid in Host mode. + */ + __IO uint8_t B_Device : 1; /* This Read-only bit indicates whether the MUSBMHDRC is operating + * as the 'A' device or the 'B' device. + * 0 => 'A' device; 1 => 'B' device. + * Only valid while a session is in progress. To determine the role + * when no session is in progress, set the session bit and read this bit. + * NOTE: If the core is in Force_Host mode(i.e. a session has been started + * with Testmode.D7 = 1),this bit will indicate the state of the HOSTDISCON + * input signal from the PHY. + */ + } DEVCTL_b; + }; + union + { + __IO uint8_t MISC; + struct + { + __IO uint8_t rx_edma : 1; /* 1'b0:DMA_REQ signal for all OUT Endpoints will be de-asserted when MAXP + * bytes have been read to an endpoint.This is late mode. + * 1'b1:DMA_REQ signal for all OUT Endpoints will be de-asserted when MAXP-8 + * bytes have been read to an endpoint.This is early mode. + */ + __IO uint8_t tx_edma : 1; /* 1'b0:DMA_REQ signal for all IN Endpoints will be de-asserted when MAXP + * bytes have been written to an endpoint.This is late mode. + * 1'b1:DMA_REQ signal for all IN Endpoints will be de-asserted when MAXP-8 + * bytes have been written to an endpoint.This is early mode. + */ + __IO uint8_t reserved2_7 : 6; /* These bits are reserved. */ + } MISC_b; + }; + union + { + __IO uint8_t TXFIFOSZ; + struct + { + __IO uint8_t size : 4; + __IO uint8_t double_packet_buffer : 1; + __IO uint8_t reserved5_7 : 3; + } TXFIFOSZ_b; + }; + union + { + __IO uint8_t RXFIFOSZ; + struct + { + __IO uint8_t size : 4; + __IO uint8_t double_packet_buffer : 1; + __IO uint8_t reserved5_7 : 3; + } RXFIFOSZ_b; + }; + __IO uint16_t TXFIFOADD; + __IO uint16_t RXFIFOADD; + + union + { + __O uint32_t VCONTROL; + __IO uint32_t VSTATUS; + }VCONTROL_VSTATUS; + union + { + __IO uint16_t HWVERS; + struct + { + __IO uint16_t minor_version_number : 10; + __IO uint16_t major_version_number : 5; + __IO uint16_t rc : 1; + } HWVERS_b; + }; + + uint8_t UNUSED1[2]; + // ULPI & Addnl. Config. registers. 0x70 - 0x7F. + __IO uint8_t ULPIVBUSCONTROL; + __IO uint8_t ULPICARKITCONTROL; + __IO uint8_t ULPIINTMASK; + __IO uint8_t ULPIINTSRC; + __IO uint8_t ULPIREGDATA; + __IO uint8_t ULPIREGADDR; + __IO uint8_t ULPIREGCONTROL; + __IO uint8_t ULPIRAWDATA; + union + { + __IO uint8_t EPINFO; + struct + { + __IO uint8_t tx_endpoint : 4; + __IO uint8_t rx_endpoint : 4; + } EPINFO_b; + }; + union + { + __IO uint8_t RAMINFO; + struct + { + __IO uint8_t ram_bits : 4; + __IO uint8_t dma_chans : 4; + } RAMINFO_b; + }; + union + { + __IO uint8_t LINKINFO; + struct + { + __IO uint8_t wtid : 4; + __IO uint8_t wtcon : 4; + } LINKINFO_b; + }; + + __IO uint8_t VPLEN; + __IO uint8_t HS_EOF1; + __IO uint8_t FS_EOF1; + __IO uint8_t LS_EOF1; + union + { + __IO uint8_t SOFT_RST; + struct + { + __IO uint8_t nrst : 1; + __IO uint8_t nrstx : 1; + __IO uint8_t reserved2_7 : 6; + } SOFT_RST_b; + }; + + struct + { + // TADDR Epn (n = 0 - 15). 0x80 - 0xFF. + __IO uint8_t TXFUNCADDR; + uint8_t UNUSED0; + __IO uint8_t TXHUBADDR; + __IO uint8_t TXHUBPORT; + __IO uint8_t RXFUNCADDR; + uint8_t UNUSED1; + __IO uint8_t RXHUBADDR; + __IO uint8_t RXHUBPORT; + } AMCS[16]; + struct + { + // CSR EPn (n = 0 - 15). 0x100 - 0x1FF; + union + { + __IO uint16_t TXMAXP; + struct + { + __IO uint16_t max_payload_tran : 11; /* Bits 10:0 define(in bytes)the maximum payload transmitted in single transaction. + * The value set can be up to 1024 bytes but is subject to the constraints place by + * the USB Specification on packet sizes for Bulk,Interrupt and Isochronous transfers + * in Full-speed and High-speed operations. + */ + __IO uint16_t ex_max : 5; + } TXMAXP_b; + }; + union + { + __IO uint8_t CSR0L; + __IO uint8_t TXCSRL; + struct + { + __IO uint8_t rx_pkt_rdy : 1; /* This bit is set when a data packet has been received. An interrupt is + * generated when this bit is set. The CPU clear this bit by setting the + * ServicedRxPktRdy bit. + */ + __IO uint8_t tx_pkt_rdy : 1; /* The CPU sets this bits after loading a data packet into the FIFO. It is clear + * automatically when a data packet has been transmitted. An interrupt is also + * generated at this point(if enabled). + */ + __IO uint8_t sent_stall : 1; /* This bit is set when a STALL handshake is transmitted. + * The CPU should clear this bit. + */ + __IO uint8_t data_end : 1; /* The CPU sets this bit: + * 1. When setting TxPktRdy for the last data packet. + * 2. When clearing RxPktRdy after unloading the last data packet. + * 3. When setting TxPktRdy for zero length data packet. + * It is cleared automatically. + */ + __IO uint8_t setup_end : 1; /* This bit will be set when a control transaction ends before the DataEnd + * bit has been set. An interrupt will be generated and the FIFO flushed at + * this time.The bit is cleared by the CPU writing a 1 to the ServicedSetupEnd bit. + */ + __IO uint8_t send_stall : 1; /* The CPU write a 1 to this bit to terminate the current transaction. + * The STALL handshake will be transmitted and then this bit will be + * cleared automatically. + */ + __IO uint8_t serviced_rxpktrdy : 1; /* The CPU write a 1 to this bit to clear the RxPktRdy bit. + * It is Cleared automatically. + */ + __IO uint8_t serviced_setupend : 1; /* The CPU write a 1 to this bit to clear the SetupEnd bit. + * It is Cleared automatically. + */ + } CSR0L_DEV_b; + struct + { + __IO uint8_t rx_pkt_rdy : 1; /* This bit is set when a data packet has been received.An interrupt is generated + * (If enabled)when this bit set.The CPU should clear this bit when the packet has + * been read from the FIFO. + */ + __IO uint8_t tx_pkt_rdy : 1; /* The CPU sets this bit after loading a data packet into the FIFO.It is cleared + * automatically when a data packet has been transmitted. An interrupt is also + * generated at this point(If enabled). + */ + __IO uint8_t rx_stall : 1; /* This bit is set when a STALL handshake is received. The CPU should clear this bit. */ + __IO uint8_t setup_pkt : 1; /* The CPU sets this bit,at the TxPktRdy bit is set,to send a SETUP token instead + * of an OUT token for the transaction. Note: Setting this bit also clear the Data + * Toggle. + */ + __IO uint8_t error : 1; /* This bit will be set when three attempts have been made to perform a transaction + * with no response from the peripheral.The CPU should clear this bit.An interrupt + * is generated when this bit is set. + */ + __IO uint8_t req_pkt : 1; /* The CPU sets this bit to request an IN transaction. + * It is cleared when RxPktRdy is set. + */ + __IO uint8_t status_pkt : 1; /* The CPU sets this bit at the same time as the TxPktRdy or ReqPkt bit is set, + * to perform a status stage transaction. Setting this bit ensures that the data + * toggle is set to 1 so that a DATA1 packet is used for the Status Stage transaction. + */ + __IO uint8_t nak_timeout : 1; /* This bit will be set when Endpoint 0 is halted following the receipt for longer + * than the time set by the NAKLimit0 register. The CPU should clear this bit to allow + * the endpoint to continue. + */ + } CSR0L_HOST_b; + struct + { + __IO uint8_t tx_pkt_rdy : 1; /* The CPU sets this bit after loading a data packet into the FIFO. */ + __IO uint8_t fifo_not_empty : 1; /* The USB sets this bit when there is at least 1 packet in the TX FIFO. */ + __IO uint8_t under_run : 1; /* The USB sets this bit if an IN token is received when TxPktRdy is not set. The CPU should clear this bit. */ + __IO uint8_t flush_fifo : 1; /* The CPU writes a 1 to this bit to flush the latest packet from the endpoint TX FIFO */ + __IO uint8_t send_stall : 1; /* The CPU writes a 1 to this bit to issue a STALL handshake to an IN token.The CPU + * clears this bit to terminate the stall condition. + * Note:This bit has no effect where the endpoint is being used for Isochronous transfers. + */ + __IO uint8_t sent_stall : 1; /* This bit is set when a STALL handshake is transmitted.The FIFO is flushed and + * the TxPktRdy bit is cleared(see below).The CPU should clear this bit. + */ + __IO uint8_t clr_data_tog : 1; /* The CPU writes a 1 to this bit to reset the endpoint data toggle to 0. */ + __IO uint8_t incomp_tx : 1; /* When the endpoint is being used for high-bandwidth Isochronous,this bit is set to + * indicate where a large packet has been split into 2 or 3 packets for transmission + * but insufficient IN tokens have been received to send all the parts. + * Note:In anything other than isochronous transfers,this bit will always return 0. + */ + } TXCSRL_DEV_b; + struct + { + __IO uint8_t tx_pkt_rdy : 1; /* The CPU sets this bit after loading a data packet into the FIFO. */ + __IO uint8_t fifo_not_empty : 1; /* The USB sets this bit when there is at least 1 packet in the TX FIFO. */ + __IO uint8_t error : 1; + __IO uint8_t flush_fifo : 1; /* The CPU writes a 1 to this bit to flush the latest packet from the endpoint TX FIFO */ + __IO uint8_t setup_Pkt : 1; + __IO uint8_t Rx_stall : 1; + __IO uint8_t clr_data_tog : 1; /* The CPU writes a 1 to this bit to reset the endpoint data toggle to 0. */ + __IO uint8_t NAK_timeout_incompTx : 1; + } TXCSRL_HOST_b; + + }; + union + { + __IO uint8_t CSR0H; + __IO uint8_t TXCSRH; + struct + { + __IO uint8_t flush_fifo : 1; /* The CPU writes a 1 to this bit to flush the next packet to be transmitted/read from + * the Endpoint 0 FIFO. The FIFO pointer is reset and the TxPktRdy/RxPktRdy bit(below) is + * cleared. Note:FlushFIFO should only be used when TxPktRdy/RxPktRdy is set.At other + * times, it may cause data to be corrupted. + */ + __IO uint8_t reserved1_7 : 7; /* Unused. Return 0 when resd. */ + } CSR0H_DEV_b; + struct + { + __IO uint8_t flush_fifo : 1; /* The CPU writes a 1 to this bit to flush the next packet to be transmitted/read from + * the Endpoint 0 FIFO. The FIFO pointer is reset and the TxPktRdy/RxPktRdy bit(below) is + * cleared. Note:FlushFIFO should only be used when TxPktRdy/RxPktRdy is set.At other + * times, it may cause data to be corrupted. + */ + __IO uint8_t data_toggle : 1; /* When read,this bit indicates the current state of the Endpoint 0 data toggle. If D10 + * is high,this bit may be written with the written with the required setting of the data + * toggle.If D10 is low,any value written to this bit is ignored. + */ + __IO uint8_t data_toggle_wr_en : 1; /* The CPU written a 1 to this bit to enable the current state of Endpoint 0 data toggle + * to be written(see Data Toggle bit,below).This bit is automatically cleared once the new + * value is written. + */ + __IO uint8_t dis_ping : 1; /* The CPU writes a 1 to this bit to instruct the core not to issue PING tokens in data + * and status phases of a high-speed Control transfer(for use with devices that do not + * respond to PING). + */ + __IO uint8_t reserved1_7 : 4; /* Unused. Return 0 when resd. */ + } CSR0H_HOST_b; + struct + { + __IO uint8_t reserved0_1 : 2; + __IO uint8_t dma_req_mode : 1; + __IO uint8_t frc_data_tog : 1; + __IO uint8_t dma_req_enab : 1; + __IO uint8_t mode : 1; + __IO uint8_t iso : 1; + __IO uint8_t auto_set : 1; + } TXCSRH_DEV_b; + struct + { + __IO uint8_t data_toggle : 1; + __IO uint8_t data_toggle_wren : 1; + __IO uint8_t dma_req_mode : 1; + __IO uint8_t frc_data_tog : 1; + __IO uint8_t dma_req_enab : 1; + __IO uint8_t mode : 1; + __IO uint8_t reserved6 : 1; + __IO uint8_t auto_set : 1; + } TXCSRH_HOST_b; + }; + union + { + __IO uint16_t RXMAXP; + struct + { + __IO uint16_t max_payload_tran : 11; + __IO uint16_t ex_max : 5; + } RXMAXP_b; + }; + union + { + __IO uint8_t RXCSRL; + struct + { + __IO uint8_t rx_pkt_rdy : 1; /* This bit is set when a data packet has been received */ + __IO uint8_t fifo_full : 1; /* */ + __IO uint8_t over_run : 1; /* */ + __IO uint8_t data_error : 1; /* */ + __IO uint8_t flush_fifo : 1; + __IO uint8_t send_stall : 1; /* The CPU writes a 1 to this bit to issue a STALL handshake. */ + __IO uint8_t sent_stall : 1; /* This bit is set when a STALL handshake is transmitted. The CPU should clear this bit. */ + __IO uint8_t clr_data_tog : 1; + } RXCSRL_DEV_b; + struct + { + __IO uint8_t rx_pkt_rdy : 1; /* This bit is set when a data packet has been received */ + __IO uint8_t fifo_full : 1; /* */ + __IO uint8_t error : 1; /* */ + __IO uint8_t data_error : 1; /* */ + __IO uint8_t flush_fifo : 1; + __IO uint8_t ReqPkt : 1; + __IO uint8_t RxStall : 1; + __IO uint8_t clr_data_tog : 1; + } RXCSRL_HOST_b; + }; + union + { + __IO uint8_t RXCSRH; + struct + { + __IO uint8_t incomp_rx : 1; + __IO uint8_t reserved1_2 : 2; + __IO uint8_t dma_req_mode : 1; + __IO uint8_t dis_nyet_pid_error : 1; + __IO uint8_t dma_req_enab : 1; + __IO uint8_t iso : 1; + __IO uint8_t auto_clear : 1; + } RXCSRH_DEV_b; + struct + { + __IO uint8_t incomp_rx : 1; + __IO uint8_t data_toggle : 1; + __IO uint8_t data_toggle_wren : 1; + __IO uint8_t dma_req_mode : 1; + __IO uint8_t PID_error : 1; + __IO uint8_t dma_req_enab : 1; + __IO uint8_t auto_req : 1; + __IO uint8_t auto_clear : 1; + } RXCSRH_HOST_b; + }; + + union + { + __IO uint16_t RXCOUNT; + struct + { + __IO uint16_t ep_rx_count : 14; + __IO uint16_t reserved14_15 : 2; + } RXCOUNT_b; + }; + union + { + __IO uint8_t TYPE0; // Host Mode Only. + __IO uint8_t TXTYPE; // Host Mode Only. + struct + { + __IO uint8_t reserved0_5 : 6; /* Reserved */ + __IO uint8_t speed : 2; /* Operating speed of the target device : + * 00:Unused(Note: If selected,the target will be using the same connectionn speed as the core.) + * 01:High + * 10:Full + * 11:Low + */ + } TYPE0_b; + struct + { + __IO uint8_t target_EP_number : 4; /* Operating speed of the target device when the core is configured with the + * multipoint option: + * 00: Unused 01: High + * 10: Full 11: Low + * When the core is not configured with the multipoint option these bits should + * not be accessed. + */ + __IO uint8_t protocol : 2; /* The CPU should set this to select the required protocol for TX endpoint: + * 00: Control 01: Isochronous + * 10: Bulk 11: Interrupt + */ + __IO uint8_t speed : 2; /* Operating speed of the target device when the core is configured with + * the multipoint option: + * 00:Unused 01: High 10: Full 11:Low + * when the core is not configured with the multipoint option these bits + * should not be accessed. + */ + } TXTYPE_b; + }; + union + { + __IO uint8_t NAKLIMIT0; // Host Mode Only. + __IO uint8_t TXINTERVAL; // Host Mode Only. + struct + { + __IO uint8_t Endpoint0_NAK_Limit : 5; /* Endpoint 0 NAK limit (m) */ + __IO uint8_t reserved5_7 : 3; /* Reserve */ + } NAKLIMIT0_b; + struct + { + __IO uint8_t Tx_polling_interval :8; + } TXINTERVAL_b; + }; + union + { + __IO uint8_t RXTYPE; // Host Mode Only. + struct + { + __IO uint8_t target_EP_number : 4; /* Operating speed of the target device when the core is configured with the + * multipoint option: + * 00: Unused 01: High + * 10: Full 11: Low + * When the core is not configured with the multipoint option these bits should + * not be accessed. + */ + __IO uint8_t protocol : 2; /* The CPU should set this to select the required protocol for TX endpoint: + * 00: Control 01: Isochronous + * 10: Bulk 11: Interrupt + */ + __IO uint8_t speed : 2; /* Operating speed of the target device when the core is configured with + * the multipoint option: + * 00:Unused 01: High 10: Full 11:Low + * when the core is not configured with the multipoint option these bits + * should not be accessed. + */ + } RXTYPE_b; + }; + union + { + __IO uint8_t RXINTERVAL; // Host Mode Only. + struct + { + __IO uint8_t Tx_polling_interval :8; + } RXINTERVAL_b; + }; + + uint8_t UNUSED0; + union + { + __IO uint8_t CONFIGDATA; + __IO uint8_t FIFOSIZE; + struct + { + __IO uint8_t utmi_data_width : 1; /* Indicates selected UTMI+ data width. Always 0 indicating 8 bits. */ + __IO uint8_t soft_cone : 1; /* Always "1" . Indicates Soft Connect/Disconnect. */ + __IO uint8_t dyn_fifo_sizing : 1; /* When set to "1" indicates Dynamic FIFO Sizing option selected. */ + __IO uint8_t hb_txe : 1; /* When set to "1" indicates High-bandwidth TX ISO Endpoint Support selected */ + __IO uint8_t hb_rxe : 1; /* When set to "1" indicates High-bandwidth Rx ISO Endpoint Support selected. */ + __IO uint8_t big_endian : 1; /* Always "0". Indicates Little Endian ordering. */ + __IO uint8_t mp_txe : 1; /* When set to "1" automatic splitting of bulk packets is selected */ + __IO uint8_t mp_rxe : 1; /* When set to "1" automatic amalgamation of bulk packets is selected */ + } CONFIGDATA_b; + struct + { + __IO uint8_t tx_fifo_size : 4; + __IO uint8_t rx_fifo_size : 4; + } b; + }; + } CSR[16]; + // Optional DMA Registers. 0x200 - 0x2FF. + __IO uint32_t DMA_INTR; /* Only one DMA INTR register */ + __IO uint32_t DMA_CNTL; + __IO uint32_t DMA_ADDR; + __IO uint32_t DMA_COUNT; + uint32_t UNUSED2[60]; + // Extended Registers. 0x300 - 0x35F. + __IO uint16_t RQPKTCOUNT[16]; // Host Mode Only. + uint16_t UNUSEDRQPK[16]; + union + { + __IO uint16_t RXDPKTBUFDIS; // Rx DPktBufDis. + struct + { + __IO uint16_t reserved0 : 1; + __IO uint16_t ep1_rx_dis : 1; + __IO uint16_t ep2_rx_dis : 1; + __IO uint16_t ep3_rx_dis : 1; + __IO uint16_t ep4_rx_dis : 1; + __IO uint16_t ep5_rx_dis : 1; + __IO uint16_t ep6_rx_dis : 1; + __IO uint16_t ep7_rx_dis : 1; + __IO uint16_t ep8_rx_dis : 1; + __IO uint16_t ep9_rx_dis : 1; + __IO uint16_t ep10_rx_dis : 1; + __IO uint16_t ep11_rx_dis : 1; + __IO uint16_t ep12_rx_dis : 1; + __IO uint16_t ep13_rx_dis : 1; + __IO uint16_t ep14_rx_dis : 1; + __IO uint16_t ep15_rx_dis : 1; + } RXDPKTBUFDIS_b; + }; + union + { + __IO uint16_t TXDPKTBUFDIS; // Tx DPktBufDis. + struct + { + __IO uint16_t reserved0 : 1; + __IO uint16_t ep1_tx_dis : 1; + __IO uint16_t ep2_tx_dis : 1; + __IO uint16_t ep3_tx_dis : 1; + __IO uint16_t ep4_tx_dis : 1; + __IO uint16_t ep5_tx_dis : 1; + __IO uint16_t ep6_tx_dis : 1; + __IO uint16_t ep7_tx_dis : 1; + __IO uint16_t ep8_tx_dis : 1; + __IO uint16_t ep9_tx_dis : 1; + __IO uint16_t ep10_tx_dis : 1; + __IO uint16_t ep11_tx_dis : 1; + __IO uint16_t ep12_tx_dis : 1; + __IO uint16_t ep13_tx_dis : 1; + __IO uint16_t ep14_tx_dis : 1; + __IO uint16_t ep15_tx_dis : 1; + } TXDPKTBUFDIS_b; + }; + + __IO uint16_t C_T_UCH; + __IO uint16_t C_T_HSRTN; + __IO uint16_t C_T_HSBT; + uint16_t UNUSED3[11]; + // LPM Registers. 0x360 - 0x365. + union + { + __IO uint16_t LPM_ATTR; + struct + { + __IO uint16_t link_state : 4; /* This value is provoided by the host to the peripheral to indicate what state the peripheral + * must transition to after the receipt and acceptance of a LPM transaction. + * LinkState = 4'h0 - Reserved + * LinkState = 4'h1 - Slep State(L1) + * LinkState = 4'h2 - Reserved + * LinkState = 4'h3 - Reserved + */ + __IO uint16_t HIRD : 4; /* This is the Host Initiated Resume Duration.This value is the minimum time the host will + * drive resume on the Bus. The value in this register corresponds to an actual resume time + * of: + * Resume Time = 50us + HIRD * 75us.This results a range 50us to 1200us. + */ + __IO uint16_t RmtWak : 1; /* This bit is the remote wakeup enable bit: + * RmtWak = 1'b0:Remote wakeup is not enabled. + * RmtWak = 1'b1:Remote wakeup is enabled. + * This bit is applied on a temporary basis only and is only applied to the current suspend + * state.After the current suspend cycle,the remote wakeup capability that was negotiated + * upon enumeration will apply. + */ + __IO uint16_t reserved9_11 : 3; /* Reserved;Always returns 0 on read */ + __IO uint16_t EndPoint : 4; /* This is the EndPnt that in the Token Packet of the LPM transaction. -*/ + } LPM_ATTR_b; + }; + union + { + __IO uint8_t LPM_CNTRL; + struct + { + __IO uint8_t lpmxmt : 1; + __IO uint8_t lpmres : 1; + __IO uint8_t lpmen : 2; + __IO uint8_t lpmnak : 1; + __IO uint8_t reserved5_7 : 3; + } LPM_CNTRL_DEV_b; + struct + { + __IO uint8_t lpmxmt : 1; + __IO uint8_t lpmres : 1; + __IO uint8_t reserved2_7 : 6; + } LPM_CNTRL_HOST_b; + }; + union + { + __IO uint8_t LPM_INTREN; + struct + { + __IO uint8_t lpmxmt : 1; + __IO uint8_t lpmres : 1; + __IO uint8_t reserved2_7 : 6; + } LPM_INTREN_b; + }; + union + { + __IO uint8_t LPM_INTR; + struct + { + __IO uint8_t lpmst : 1; + __IO uint8_t lpmny : 1; + __IO uint8_t lpmack : 1; + __IO uint8_t lpmnc : 1; + __IO uint8_t lpmres : 1; + __IO uint8_t lpmerr : 1; + __IO uint8_t reserved6_7 : 2; + } LPM_INTR_DEV_b; + struct + { + __IO uint8_t lpmst : 1; + __IO uint8_t lpmny : 1; + __IO uint8_t lpmack : 1; + __IO uint8_t lpmnc : 1; + __IO uint8_t lpmres : 1; + __IO uint8_t reserved5_7 : 3; + } LPM_INTR_HOST_b; + }; + union + { + __IO uint8_t LPM_FADDR; // Relavant in Host mode only. + struct + { + __IO uint8_t function_address : 7; + __IO uint8_t reserved7 : 1; + } LPM_FADDR_b; + }; + +}USB_TypeDef; + +#define USB_OTG ( (USB_TypeDef *) USB_BASE ) +typedef struct +{ + const USB_TypeDef *RegBase; + const int IrqLine; + USB_EndpointCtrlStruct EpCtrl[USB_EP_MAX]; + uint32_t RxData[USB_FIFO_DW_DAX]; + PV_Union pRxData; + uint8_t IsConnect; + uint8_t IsHost; + uint8_t NewDeviceAddress; +}USB_HWCtrlStruct; + +static USB_HWCtrlStruct prvUSB = +{ + .RegBase = USB_BASE, + .IrqLine = USB_IRQn, +}; + +static uint8_t USB_OTG_FifosizeReg(uint16_t fifosiz) +{ + uint8_t register_value = 0; + switch (fifosiz) + { + case 8: + register_value = 0; + break; + case 16: + register_value = 1; + break; + case 32: + register_value = 2; + break; + case 64: + register_value = 3; + break; + case 128: + register_value = 4; + break; + } + return register_value; +} + +static void prvUSB_IrqHandle(int32_t IrqLine, void *pData) +{ + uint32_t USB_ID = (uint32_t)pData; + uint32_t i; + uint32_t Count32b; + uint16_t RxLen; + uint16_t TxBit = USB_OTG->INTRTX; + uint16_t RxBit = USB_OTG->INTRRX; + uint8_t StateBit = USB_OTG->INTRUSB; + uint8_t EpIndex = 1; + USB_OTG->INTRUSB = 0; + USB_OTG->INTRRX = 0; + USB_OTG->INTRTX = 0; + if (prvUSB.IsHost || USB_OTG->DEVCTL_b.host_mode) + { + ; + } + else + { + + if (StateBit & 0x1) + { + USB_StackDeviceBusChange(USB_ID, USBD_BUS_TYPE_SUSPEND); + } + if (StateBit & 0x2) + { + USB_StackDeviceBusChange(USB_ID, USBD_BUS_TYPE_RESUME); + USB_OTG->POWER_b.resume = 1; + } + if (StateBit & 0x4) + { + USB_OTG->FADDR = 0; + USB_OTG->INDEX = 0; + USB_FlushFifo(&prvUSB, 0, 0); + for(i = 1; i < 8; i++) + { + USB_FlushFifo(&prvUSB,i, 0); + USB_FlushFifo(&prvUSB,i, 1); + } + USB_SetDeviceEPStatus(&prvUSB, 0, 0, USB_EP_STATE_ACK); + USB_StackDeviceBusChange(USB_ID, USBD_BUS_TYPE_RESET); + } + if (StateBit & 0x8) + { + USB_StackDeviceBusChange(USB_ID, USBD_BUS_TYPE_NEW_SOF); + } + if (StateBit & 0x20) + { + for(i = 0; i < 8; i++) + { + memset(&prvUSB.EpCtrl[i].TxBuf, 0, sizeof(Buffer_Struct)); + } + USB_StackDeviceBusChange(USB_ID, USBD_BUS_TYPE_DISCONNECT); + } + if (TxBit & 0x01) + { + if (USB_OTG->CSR0L_DEV_b.sent_stall) + { + USB_SetDeviceEPStatus(&prvUSB, 0, 0, USB_EP_STATE_ACK); + } + if (USB_OTG->CSR0L_DEV_b.setup_end) + { + USB_OTG->CSR0L_DEV_b.serviced_setupend = 1; + } + if (prvUSB.NewDeviceAddress & 0x80) + { + USB_OTG->FADDR = prvUSB.NewDeviceAddress & 0x7f; + prvUSB.NewDeviceAddress = 0; + } + if (USB_OTG->CSR0L_DEV_b.rx_pkt_rdy) + { + RxLen = USB_OTG->COUNT0_b.ep0_rx_count; + if (RxLen) + { + Count32b = RxLen >> 2; + for (i = 0; i < Count32b; i++) + { + prvUSB.RxData[i] = USB_OTG->FIFOX[0].dword; + } + for (i = Count32b * 4; i < RxLen; i++) + { + prvUSB.pRxData.pu8[i] = USB_OTG->FIFOX[0].byte; + } + USB_StackPutRxData(USB_ID, 0, prvUSB.pRxData.pu8, RxLen); + } + USB_OTG->CSR0L_DEV_b.serviced_rxpktrdy = 1; + USB_StackAnalyzeDeviceEpRx(USB_ID, 0); + } + else if (!USB_OTG->CSR0L_DEV_b.tx_pkt_rdy) + { + USB_DeviceXfer(&prvUSB, 0); + } + + } + else if (TxBit) + { + TxBit >>= 1; + EpIndex = 1; + while(TxBit) + { + if (TxBit & 0x01) + { + if (!USB_OTG->CSR[EpIndex].TXCSRL_DEV_b.tx_pkt_rdy) + { + USB_DeviceXfer(&prvUSB, EpIndex); + } + USB_OTG->CSR[EpIndex].TXCSRL_DEV_b.sent_stall = prvUSB.EpCtrl[EpIndex].INSTATUS_b.Halt?1:0; + USB_OTG->CSR[EpIndex].TXCSRL_DEV_b.send_stall = 0; + USB_OTG->CSR[EpIndex].TXCSRL_DEV_b.under_run = 0; + } + TxBit >>= 1; + EpIndex++; + } + } + if (RxBit) + { + EpIndex = 1; + RxBit >>= 1; + while(RxBit) + { + if (RxBit & 0x01) + { + if (USB_OTG->CSR[EpIndex].RXCSRL_DEV_b.rx_pkt_rdy) + { + RxLen = USB_OTG->CSR[EpIndex].RXCOUNT_b.ep_rx_count; + if (RxLen) + { + Count32b = RxLen >> 2; + for (i = 0; i < Count32b; i++) + { + prvUSB.RxData[i] = USB_OTG->FIFOX[EpIndex].dword; + } + for (i = Count32b * 4; i < RxLen; i++) + { + prvUSB.pRxData.pu8[i] = USB_OTG->FIFOX[EpIndex].byte; + } + USB_StackPutRxData(USB_ID, EpIndex, prvUSB.pRxData.pu8, RxLen); + } + } + USB_OTG->CSR[EpIndex].RXCSRL = 0; + USB_OTG->CSR[EpIndex].RXCSRL_DEV_b.sent_stall = prvUSB.EpCtrl[EpIndex].OUTSTATUS_b.Halt?1:0; + USB_StackAnalyzeDeviceEpRx(USB_ID, EpIndex); + } + RxBit >>= 1; + EpIndex++; + } + + } + } +} + +static int prvUSB_SetupEPFifo(HANDLE hUSB) +{ + USB_HWCtrlStruct *hwUSB = (USB_HWCtrlStruct *)hUSB; + uint8_t i; + uint8_t Len; + uint16_t FifoStart = (64 >> 3); + uint16_t UseFifo = 64; + //ep0使用默认的64byte + + USB_OTG->INDEX = 0; + USB_OTG->TXFIFOSZ = 3; + USB_OTG->RXFIFOSZ = 3; + USB_OTG->TXFIFOADD = 0; + USB_OTG->RXFIFOADD = 0; + USB_OTG->CSR0H_DEV_b.flush_fifo = 1; //刷新EP0的FIFO + hwUSB->EpCtrl[0].MaxPacketLen = 64; + for(i = 1; i < USB_EP_MAX; i++) + { + USB_OTG->INDEX = i; + if (hwUSB->EpCtrl[i].ToDeviceEnable) + { + Len = USB_OTG_FifosizeReg(hwUSB->EpCtrl[i].MaxPacketLen); + USB_OTG->CSR[i].RXMAXP = hwUSB->EpCtrl[i].MaxPacketLen; + USB_OTG->RXFIFOADD = FifoStart; + USB_OTG->RXFIFOSZ = Len; + USB_OTG->CSR[i].RXCSRL = (1 << 4); + //DBG("%d,%d,%x,%d,%x", i, USB_OTG->CSR[i].RXMAXP, USB_OTG->RXFIFOADD, USB_OTG->RXFIFOSZ, USB_OTG->CSR[i].RXCSRL); + FifoStart += (hwUSB->EpCtrl[i].MaxPacketLen >> 3); + UseFifo += hwUSB->EpCtrl[i].MaxPacketLen; + } + if (UseFifo > 512) + { + return -1; + } + if (hwUSB->EpCtrl[i].ToHostEnable) + { + USB_OTG->CSR[i].TXMAXP = hwUSB->EpCtrl[i].MaxPacketLen; + USB_OTG->TXFIFOADD = FifoStart; + USB_OTG->TXFIFOSZ = Len; + USB_OTG->CSR[i].TXCSRL = (1 << 3); + //DBG("%d,%d,%x,%d,%x", i, USB_OTG->CSR[i].TXMAXP, USB_OTG->TXFIFOADD, USB_OTG->TXFIFOSZ, USB_OTG->CSR[i].TXCSRL); + FifoStart += (hwUSB->EpCtrl[i].MaxPacketLen >> 3); + UseFifo += hwUSB->EpCtrl[i].MaxPacketLen; + } + if (UseFifo > 512) + { + return -1; + } + } + USB_OTG->INDEX = 0; + return 0; +} + +void USB_GlobalInit(void) +{ + USB_HWCapsStruct Caps; + + + ISR_SetHandler(prvUSB.IrqLine, prvUSB_IrqHandle, USB_ID0); +#ifdef __BUILD_OS__ + ISR_SetPriority(prvUSB.IrqLine, configLIBRARY_LOWEST_INTERRUPT_PRIORITY); +#else + ISR_SetPriority(prvUSB.IrqLine, 7); +#endif + prvUSB.IsConnect = 0; + Caps.EpBufMaxLen = 4096; + Caps.Feature = 0; + Caps.FEATURE_b.FullSpeed = 1; + Caps.CtrlMode = USB_MODE_DUAL; + USB_StackSetControl(USB_ID0, &prvUSB, prvUSB.EpCtrl, &Caps); + USB_StackSetDeviceSpeed(USB_ID0, USB_DEVICE_SPEED_FULL_SPEED); + USB_OTG->INTRRXE = 0; + USB_OTG->INTRTXE = 0; + USB_OTG->INTRUSBE = 0; + prvUSB.pRxData.pu32 = prvUSB.RxData; + SYSCTRL->CG_CTRL2 &= ~SYSCTRL_AHBPeriph_USB; + +} + +void USB_PowerOnOff(HANDLE hUSB, uint8_t OnOff) +{ + if (OnOff) + { + SYSCTRL->CG_CTRL2 |= SYSCTRL_AHBPeriph_USB; + } + else + { + SYSCTRL->CG_CTRL2 &= ~SYSCTRL_AHBPeriph_USB; + } +} + +void USB_Stop(HANDLE hUSB) +{ + uint8_t dummy; + USB_HWCtrlStruct *hwUSB = (USB_HWCtrlStruct *)hUSB; + ISR_OnOff(hwUSB->IrqLine, 0); + USB_OTG->POWER = 0; + USB_OTG->INTRRXE = 0; + USB_OTG->INTRTXE = 0; + USB_OTG->INTRUSBE = 0; + USB_OTG->INTRTX = 0; + USB_OTG->INTRRX = 0; + USB_OTG->INTRUSB = 0; + dummy = USB_OTG->INTRUSB; +} + +void USB_ResetStart(HANDLE hUSB) +{ + SYSCTRL->LOCK_R &= ~SYSCTRL_USB_RESET; + SYSCTRL->SOFT_RST2 |= SYSCTRL_USB_RESET; + SYSCTRL->LOCK_R |= SYSCTRL_USB_RESET; +} + +void USB_ResetEnd(HANDLE hUSB) +{ + SYSCTRL->LOCK_R &= ~SYSCTRL_USB_RESET; + SYSCTRL->SOFT_RST2 &= ~SYSCTRL_USB_RESET; + SYSCTRL->LOCK_R |= SYSCTRL_USB_RESET; +} + +void USB_SetWorkMode(HANDLE hUSB, uint8_t Mode) +{ + USB_HWCtrlStruct *hwUSB = (USB_HWCtrlStruct *)hUSB; + USBPHY_CR1_TypeDef CR1; + USBPHY_CR3_TypeDef CR3; + CR1.d32 = SYSCTRL->USBPHY_CR1; + CR1.b.commononn = 0; + CR1.b.stop_ck_for_suspend = 0; + SYSCTRL->USBPHY_CR1 = CR1.d32; + + switch (Mode) + { + case USB_MODE_HOST: + USB_OTG->POWER = 1; + USB_OTG->DEVCTL |= (1 << 0)|(1 << 2); + CR3.d32 = SYSCTRL->USBPHY_CR3; + CR3.b.idpullup = 1; + SYSCTRL->USBPHY_CR3 = CR3.d32; + hwUSB->IsHost = 1; + break; + default: + USB_OTG->DEVCTL &= ~((1 << 0)|(1 << 2)); + USB_OTG->POWER = 1|(1 << 6); + CR3.d32 = SYSCTRL->USBPHY_CR3; + CR3.b.idpullup = 0; + SYSCTRL->USBPHY_CR3 = CR3.d32; + hwUSB->IsHost = 0; + break; + } +} + +void USB_SetDeviceAddress(HANDLE hUSB, uint8_t Address) +{ + prvUSB.NewDeviceAddress = 0x80 | Address; +} + +int USB_ReInitEpCfg(HANDLE hUSB) +{ + return -1; +} + +int USB_InitEpCfg(HANDLE hUSB) +{ + return prvUSB_SetupEPFifo(hUSB); +} + + +void USB_Start(HANDLE hUSB) +{ + USB_HWCtrlStruct *hwUSB = (USB_HWCtrlStruct *)hUSB; + USB_OTG->INTRUSBE = 0xff; + USB_OTG->INTRUSBE_b.en_sof = 0; + USB_OTG->INTRTXE = 0xff; + USB_OTG->INTRRXE = 0xfe; + ISR_OnOff(hwUSB->IrqLine, 1); +} + +void USB_SendZeroPacket(HANDLE hUSB, uint8_t EpIndex) +{ + if (EpIndex) + { + USB_OTG->CSR[EpIndex].TXCSRL_DEV_b.tx_pkt_rdy = 1; + } + else + { + USB_OTG->CSR0L_DEV_b.tx_pkt_rdy = 1; + } +} + +void USB_DeviceXferStop(HANDLE hUSB, uint8_t EpIndex) +{ + USB_HWCtrlStruct *hwUSB = (USB_HWCtrlStruct *)hUSB; + USB_OTG->INTRTXE &= ~(1 << EpIndex); + USB_FlushFifo(hUSB, EpIndex, 0); + USB_OTG->CSR[EpIndex].TXCSRL_DEV_b.send_stall = 0; + USB_OTG->CSR[EpIndex].TXCSRL_DEV_b.sent_stall = 0; + USB_OTG->CSR[EpIndex].TXCSRL_DEV_b.under_run = 0; + USB_OTG->INTRTXE |= (1 << EpIndex); +} + +void USB_EpIntOnOff(HANDLE hUSB, uint8_t EpIndex, uint8_t IsToDevice, uint8_t OnOff) +{ + USB_HWCtrlStruct *hwUSB = (USB_HWCtrlStruct *)hUSB; + if (IsToDevice) + { + if (OnOff) + { + USB_OTG->INTRRXE |= (1 << EpIndex); + } + else + { + USB_OTG->INTRRXE &= ~(1 << EpIndex); + } + } + else + { + if (OnOff) + { + USB_OTG->INTRTXE |= (1 << EpIndex); + } + else + { + USB_OTG->INTRTXE &= ~(1 << EpIndex); + } + } +} + +void USB_DeviceXfer(HANDLE hUSB, uint8_t EpIndex) +{ + USB_HWCtrlStruct *hwUSB = (USB_HWCtrlStruct *)hUSB; + USB_EndpointCtrlStruct *pEpCtrl = &hwUSB->EpCtrl[EpIndex]; + USB_EndpointDataStruct EpData; + uint16_t TxLen, i; + EpData.USB_ID = USB_ID0; + EpData.EpIndex = EpIndex; + EpData.IsToDevice = 0; + if (pEpCtrl->TxBuf.Data) + { + if (pEpCtrl->TxBuf.Pos >= pEpCtrl->TxBuf.MaxLen) + { + if (pEpCtrl->NeedZeroPacket) + { +// DBG("Ep%d %d %d %d need send 0 packet", EpIndex, +// pEpCtrl->ForceZeroPacket, pEpCtrl->TxBuf.Pos, pEpCtrl->XferMaxLen); + if (!pEpCtrl->TxZeroPacket) + { + pEpCtrl->TxZeroPacket = 1; + if (EpIndex) + { + USB_OTG->CSR[EpIndex].TXCSRL_DEV_b.tx_pkt_rdy = 1; + } + else + { + USB_OTG->CSR0L_DEV_b.tx_pkt_rdy = 1; + } + } + else + { + DBG("!"); + } + + } + goto XFER_DONE; + } + else + { + pEpCtrl->TxZeroPacket = 0; + if ((pEpCtrl->TxBuf.MaxLen - pEpCtrl->TxBuf.Pos) > pEpCtrl->MaxPacketLen) + { + TxLen = pEpCtrl->MaxPacketLen; + } + else + { + if (pEpCtrl->ForceZeroPacket) + { + pEpCtrl->NeedZeroPacket = 1; + } + if ((pEpCtrl->TxBuf.MaxLen - pEpCtrl->TxBuf.Pos) == pEpCtrl->MaxPacketLen) + { + if ( pEpCtrl->TxBuf.MaxLen < pEpCtrl->XferMaxLen ) + { + pEpCtrl->NeedZeroPacket = 1; + } + } + TxLen = pEpCtrl->TxBuf.MaxLen - pEpCtrl->TxBuf.Pos; + } + + + for(i = pEpCtrl->TxBuf.Pos; i < pEpCtrl->TxBuf.Pos + TxLen; i++) + { + USB_OTG->FIFOX[EpIndex].byte = pEpCtrl->TxBuf.Data[i]; + } + pEpCtrl->TxBuf.Pos += TxLen; + if (EpIndex) + { + USB_OTG->CSR[EpIndex].TXCSRL_DEV_b.tx_pkt_rdy = 1; + } + else + { + USB_OTG->CSR0L_DEV_b.tx_pkt_rdy = 1; + } + } + } + return; +XFER_DONE: + memset(&pEpCtrl->TxBuf, 0, sizeof(Buffer_Struct)); + if (EpIndex) + { + pEpCtrl->CB(&EpData, pEpCtrl->pData); + } + else + { + USB_StackDeviceEp0TxDone(USB_ID0); + } +} + +void USB_SetDeviceNoDataSetup(HANDLE hUSB) +{ + { + USB_OTG->CSR0L_DEV_b.data_end = 1; + } +} + +void USB_FlushFifo(HANDLE hUSB, uint8_t EpIndex, uint8_t IsToDevice) +{ + if (EpIndex) + { + if (IsToDevice) + { + USB_OTG->CSR[EpIndex].RXCSRL = (1 << 4); + } + else + { + + USB_OTG->CSR[EpIndex].TXCSRL = (1 << 3); + + } + + } + else + { + if (USB_OTG->CSR0L_DEV_b.rx_pkt_rdy || USB_OTG->CSR0L_DEV_b.tx_pkt_rdy) + { + USB_OTG->CSR0H_DEV_b.flush_fifo = 1; + USB_OTG->CSR0L_DEV_b.serviced_rxpktrdy = 1; + USB_OTG->CSR0L_DEV_b.tx_pkt_rdy = 0; + } + } +} + +/** +* @brief returns the EP Status +* @param pdev : Selected device +* ep : endpoint structure +* @retval : EP status +*/ + +uint8_t USB_GetDeviceEPStatus(HANDLE hUSB, uint8_t Index, uint8_t IsToDevice) +{ + if (Index) + { + if (IsToDevice) + { + + if (USB_OTG->CSR[Index].RXCSRL_DEV_b.sent_stall) + { + return USB_EP_STATE_STALL; + } + if (USB_OTG->CSR[Index].RXCSRL_DEV_b.data_error || USB_OTG->CSR[Index].RXCSRL_DEV_b.over_run) + { + return USB_EP_STATE_NAK; + } + return USB_EP_STATE_ACK; + } + else + { + if (USB_OTG->CSR[Index].TXCSRL_DEV_b.sent_stall) + { + return USB_EP_STATE_STALL; + } + if (USB_OTG->CSR[Index].TXCSRL_DEV_b.under_run || USB_OTG->CSR[Index].TXCSRL_DEV_b.tx_pkt_rdy) + { + return USB_EP_STATE_NAK; + } + return USB_EP_STATE_ACK; + } + } + else + { + if (USB_OTG->CSR0L_DEV_b.sent_stall) + { + return USB_EP_STATE_STALL; + } + return USB_EP_STATE_ACK; + } +} + +/** +* @brief Set the EP Status +* @param pdev : Selected device +* Status : new Status +* ep : EP structure +* @retval : None +*/ +void USB_SetDeviceEPStatus (HANDLE hUSB, uint8_t Index, uint8_t IsToDevice, uint8_t Status) +{ + if (Index) + { + if (IsToDevice) + { + switch(Status) + { + case USB_EP_STATE_DISABLE: + case USB_EP_STATE_NAK: + case USB_EP_STATE_NYET: + break; + case USB_EP_STATE_STALL: + DBG("%d", Index); + USB_OTG->CSR[Index].RXCSRL_DEV_b.send_stall = 1; + break; + case USB_EP_STATE_ENABLE: + case USB_EP_STATE_ACK: + USB_OTG->CSR[Index].RXCSRL_DEV_b.send_stall = 0; + USB_OTG->CSR[Index].RXCSRL_DEV_b.sent_stall = 0; + USB_OTG->CSR[Index].RXCSRL_DEV_b.over_run = 0; + USB_OTG->CSR[Index].RXCSRL_DEV_b.data_error = 0; + break; + } + } + else + { + switch(Status) + { + case USB_EP_STATE_DISABLE: + case USB_EP_STATE_NAK: + case USB_EP_STATE_NYET: + break; + case USB_EP_STATE_STALL: + DBG("%d", Index); + USB_OTG->CSR[Index].TXCSRL_DEV_b.send_stall = 1; + break; + case USB_EP_STATE_ENABLE: + case USB_EP_STATE_ACK: + USB_OTG->CSR[Index].TXCSRL_DEV_b.send_stall = 0; + USB_OTG->CSR[Index].TXCSRL_DEV_b.sent_stall = 0; + USB_OTG->CSR[Index].TXCSRL_DEV_b.under_run = 0; + break; + } + } + } + else + { + switch(Status) + { + case USB_EP_STATE_DISABLE: + case USB_EP_STATE_NYET: + case USB_EP_STATE_NAK: + break; + case USB_EP_STATE_STALL: + USB_OTG->CSR0L_DEV_b.send_stall = 1; + break; + case USB_EP_STATE_ACK: + case USB_EP_STATE_ENABLE: + USB_OTG->CSR0L_DEV_b.send_stall = 0; + USB_OTG->CSR0L_DEV_b.sent_stall = 0; + break; + } + } +} + +void USB_ResumeStart(HANDLE hUSB) +{ + USB_OTG->POWER_b.resume = 1; +} + +void USB_ResumeEnd(HANDLE hUSB) +{ + USB_OTG->POWER_b.resume = 0; +} + +int32_t USB_SetISOCHDelay(HANDLE hUSB, uint16_t DelayNS) +{ + return -1; +} + +int32_t USB_ExitLatency(HANDLE hUSB, uint8_t Config[6]) +{ + return -1; +} + +#endif diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_wdt.c b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_wdt.c new file mode 100644 index 0000000000..659344b339 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Src/core_wdt.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "user.h" +#define COUNTER_RELOAD_KEY ((uint32_t)0x76) +void WDT_SetTimeout(uint32_t ms) +{ + WDT->WDT_RLD = SYSCTRL->PCLK_1MS_VAL * ms; +} + +void WDT_Feed(void) +{ + WDT->WDT_CRR = COUNTER_RELOAD_KEY; +} + +void WDT_Enable(void) +{ + WDT->WDT_CR |= WDT_CR_WDT_EN; +} + +void WDT_ModeConfig(WDT_ModeTypeDef WDT_Mode) +{ + if(WDT_Mode == WDT_Mode_Interrupt) + WDT->WDT_CR |= WDT_CR_RMOD; + else if(WDT_Mode == WDT_Mode_CPUReset) + WDT->WDT_CR &= ~WDT_CR_RMOD; +} diff --git a/bsp/airm2m/air105/libraries/HAL_Driver/Startup/gcc/startup_gcc.s b/bsp/airm2m/air105/libraries/HAL_Driver/Startup/gcc/startup_gcc.s new file mode 100644 index 0000000000..1ac7d8fb42 --- /dev/null +++ b/bsp/airm2m/air105/libraries/HAL_Driver/Startup/gcc/startup_gcc.s @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2022 OpenLuat & AirM2M + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + .syntax unified + .cpu cortex-m4 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss +/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ + +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr sp, =_estack /* set stack pointer */ + +/* Copy the data segment initializers from flash to SRAM */ + ldr r0, =_sdata + ldr r1, =_edata + ldr r2, =_sidata + movs r3, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +LoopCopyDataInit: + adds r4, r0, r3 + cmp r4, r1 + bcc CopyDataInit + +/* Zero fill the bss segment. */ + ldr r2, =_sbss + ldr r4, =_ebss + movs r3, #0 + b LoopFillZerobss + +FillZerobss: + str r3, [r2] + adds r2, r2, #4 + +LoopFillZerobss: + cmp r2, r4 + bcc FillZerobss + +/* Call the clock system intitialization function.*/ + bl SystemInit +/* Call static constructors */ + bl __libc_init_array +/* Call the application's entry point.*/ + bl entry + bx lr +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * @param None + * @retval None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M3. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +*******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + + +g_pfnVectors: + .word _estack + .word Reset_Handler + + .word HardFault_Handler + .word HardFault_Handler + .word HardFault_Handler + .word HardFault_Handler + .word HardFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + + /* External Interrupts */ + .word ISR_GlobalHandler /* Window WatchDog */ + .word ISR_GlobalHandler /* PVD through EXTI Line detection */ + .word ISR_GlobalHandler /* Tamper and TimeStamps through the EXTI line */ + .word ISR_GlobalHandler /* RTC Wakeup through the EXTI line */ + .word ISR_GlobalHandler /* FLASH */ + .word ISR_GlobalHandler /* RCC */ + .word ISR_GlobalHandler /* EXTI Line0 */ + .word ISR_GlobalHandler /* EXTI Line1 */ + .word ISR_GlobalHandler /* EXTI Line2 */ + .word ISR_GlobalHandler /* EXTI Line3 */ + .word ISR_GlobalHandler /* EXTI Line4 */ + .word ISR_GlobalHandler /* DMA1 Stream 0 */ + .word ISR_GlobalHandler /* DMA1 Stream 1 */ + .word ISR_GlobalHandler /* DMA1 Stream 2 */ + .word ISR_GlobalHandler /* DMA1 Stream 3 */ + .word ISR_GlobalHandler /* DMA1 Stream 4 */ + .word ISR_GlobalHandler /* DMA1 Stream 5 */ + .word ISR_GlobalHandler /* DMA1 Stream 6 */ + .word ISR_GlobalHandler /* ADC1, ADC2 and ADC3s */ + .word ISR_GlobalHandler /* CAN1 TX */ + .word ISR_GlobalHandler /* CAN1 RX0 */ + .word ISR_GlobalHandler /* CAN1 RX1 */ + .word ISR_GlobalHandler /* CAN1 SCE */ + .word ISR_GlobalHandler /* External Line[9:5]s */ + .word ISR_GlobalHandler /* TIM1 Break and TIM9 */ + .word ISR_GlobalHandler /* TIM1 Update and TIM10 */ + .word ISR_GlobalHandler /* TIM1 Trigger and Commutation and TIM11 */ + .word ISR_GlobalHandler /* TIM1 Capture Compare */ + .word ISR_GlobalHandler /* TIM2 */ + .word ISR_GlobalHandler /* TIM3 */ + .word ISR_GlobalHandler /* TIM4 */ + .word ISR_GlobalHandler /* I2C1 Event */ + .word ISR_GlobalHandler /* I2C1 Error */ + .word ISR_GlobalHandler /* I2C2 Event */ + .word ISR_GlobalHandler /* I2C2 Error */ + .word ISR_GlobalHandler /* SPI1 */ + .word ISR_GlobalHandler /* SPI2 */ + .word ISR_GlobalHandler /* USART1 */ + .word ISR_GlobalHandler /* USART2 */ + .word ISR_GlobalHandler /* USART3 */ + .word ISR_GlobalHandler /* External Line[15:10]s */ + .word ISR_GlobalHandler /* RTC Alarm (A and B) through EXTI Line */ + .word ISR_GlobalHandler /* USB OTG FS Wakeup through EXTI line */ + .word ISR_GlobalHandler /* TIM8 Break and TIM12 */ + .word ISR_GlobalHandler /* TIM8 Update and TIM13 */ + .word ISR_GlobalHandler /* TIM8 Trigger and Commutation and TIM14 */ + .word ISR_GlobalHandler /* TIM8 Capture Compare */ + .word ISR_GlobalHandler /* DMA1 Stream7 */ + .word ISR_GlobalHandler /* FSMC */ + .word ISR_GlobalHandler /* SDIO */ + .word ISR_GlobalHandler /* TIM5 */ + .word ISR_GlobalHandler /* SPI3 */ + .word ISR_GlobalHandler /* UART4 */ + .word ISR_GlobalHandler /* UART5 */ + .word ISR_GlobalHandler /* TIM6 and DAC1&2 underrun errors */ + .word ISR_GlobalHandler /* TIM7 */ + .word ISR_GlobalHandler /* DMA2 Stream 0 */ + .word ISR_GlobalHandler /* DMA2 Stream 1 */ + .word ISR_GlobalHandler /* DMA2 Stream 2 */ + .word ISR_GlobalHandler /* DMA2 Stream 3 */ + .word ISR_GlobalHandler /* DMA2 Stream 4 */ + .word ISR_GlobalHandler /* Ethernet */ + .word ISR_GlobalHandler /* Ethernet Wakeup through EXTI line */ + .word ISR_GlobalHandler /* CAN2 TX */ + .word ISR_GlobalHandler /* CAN2 RX0 */ + .word ISR_GlobalHandler /* CAN2 RX1 */ + .word ISR_GlobalHandler /* CAN2 SCE */ + .word ISR_GlobalHandler /* USB OTG FS */ + .word ISR_GlobalHandler /* DMA2 Stream 5 */ + .word ISR_GlobalHandler /* DMA2 Stream 6 */ + .word ISR_GlobalHandler /* DMA2 Stream 7 */ + .word ISR_GlobalHandler /* USART6 */ + .word ISR_GlobalHandler /* I2C3 event */ + .word ISR_GlobalHandler /* I2C3 error */ + .word ISR_GlobalHandler /* USB OTG HS End Point 1 Out */ + .word ISR_GlobalHandler /* USB OTG HS End Point 1 In */ + .word ISR_GlobalHandler /* USB OTG HS Wakeup through EXTI */ + .word ISR_GlobalHandler /* USB OTG HS */ + .word ISR_GlobalHandler /* DCMI */ + .word ISR_GlobalHandler /* CRYP crypto */ + .word ISR_GlobalHandler /* Hash and Rng */ + .word ISR_GlobalHandler /* FPU */ + .word ISR_GlobalHandler /* UART7 */ + .word ISR_GlobalHandler /* UART8 */ + .word ISR_GlobalHandler /* SPI4 */ + .word ISR_GlobalHandler /* SPI5 */ + .word ISR_GlobalHandler /* SPI6 */ + .word ISR_GlobalHandler /* SAI1 */ + .word ISR_GlobalHandler /* LTDC_IRQHandler */ + .word ISR_GlobalHandler /* LTDC_ER_IRQHandler */ + .word ISR_GlobalHandler /* DMA2D + + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + + diff --git a/bsp/airm2m/air105/libraries/SConscript b/bsp/airm2m/air105/libraries/SConscript new file mode 100644 index 0000000000..33045f2064 --- /dev/null +++ b/bsp/airm2m/air105/libraries/SConscript @@ -0,0 +1,29 @@ +from building import * + + +cwd = GetCurrentDir() +CPPPATH = [cwd+"/HAL_Driver/Inc",cwd+"/rt_drivers",cwd+"/rt_drivers/config"] +CPPDEFINES = ['__USE_XTL__'] +# add general drivers +src = Split(''' +HAL_Driver/Src/bsp_common.c +HAL_Driver/Src/core_uart.c +HAL_Driver/Src/core_dma.c +HAL_Driver/Src/core_gpio.c +HAL_Driver/Src/core_irq.c +HAL_Driver/Src/core_wdt.c +HAL_Driver/Src/core_spi.c +HAL_Driver/Src/core_i2c.c +HAL_Driver/Src/core_tick.c +HAL_Driver/Src/core_rtc.c +rt_drivers/drv_usart_v2.c +rt_drivers/drv_i2c.c +rt_drivers/drv_wdt.c +rt_drivers/drv_gpio.c +rt_drivers/drv_common.c +rt_drivers/drv_spi.c +rt_drivers/drv_rtc.c +''') +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/airm2m/air105/libraries/rt_drivers/config/air105/spi_config.h b/bsp/airm2m/air105/libraries/rt_drivers/config/air105/spi_config.h new file mode 100644 index 0000000000..73fcbff76b --- /dev/null +++ b/bsp/airm2m/air105/libraries/rt_drivers/config/air105/spi_config.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + + +#ifndef __SPI_CONFIG_H__ +#define __SPI_CONFIG_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define HSPI0 0 +#define SPI0 1 +#define SPI1 2 +#define SPI2 3 +#define SPI0S 4 + +#ifdef BSP_USING_HSPI0 +#ifndef HSPI0_BUS_CONFIG +#define HSPI0_BUS_CONFIG \ + { \ + .bus_name = "hspi0", \ + .id = HSPI0, \ + } +#endif /* HSPI0_BUS_CONFIG */ +#endif /* BSP_USING_HSPI0 */ + +#ifdef BSP_USING_SPI0 +#ifndef SPI0_BUS_CONFIG +#define SPI0_BUS_CONFIG \ + { \ + .bus_name = "spi0", \ + .id = SPI0, \ + } +#endif /* SPI0_BUS_CONFIG */ +#endif /* BSP_USING_SPI0 */ + +#ifdef BSP_USING_SPI1 +#ifndef SPI1_BUS_CONFIG +#define SPI1_BUS_CONFIG \ + { \ + .bus_name = "spi1", \ + .id = SPI1, \ + } +#endif /* SPI1_BUS_CONFIG */ +#endif /* BSP_USING_SPI1 */ + +#ifdef BSP_USING_SPI2 +#ifndef SPI2_BUS_CONFIG +#define SPI2_BUS_CONFIG \ + { \ + .bus_name = "spi2", \ + .id = SPI2, \ + } +#endif /* SPI2_BUS_CONFIG */ +#endif /* BSP_USING_SPI2 */ + +#ifdef BSP_USING_SPI0S +#ifndef SPI0S_BUS_CONFIG +#define SPI0S_BUS_CONFIG \ + { \ + .bus_name = "spi0s", \ + .id = SPI0S, \ + } +#endif /* SPI0S_BUS_CONFIG */ +#endif /* BSP_USING_SPI0S */ + +#ifdef __cplusplus +} +#endif + +#endif /*__SPI_CONFIG_H__ */ diff --git a/bsp/airm2m/air105/libraries/rt_drivers/config/air105/uart_config.h b/bsp/airm2m/air105/libraries/rt_drivers/config/air105/uart_config.h new file mode 100644 index 0000000000..4759b145f8 --- /dev/null +++ b/bsp/airm2m/air105/libraries/rt_drivers/config/air105/uart_config.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + + +#ifndef __UART_CONFIG_H__ +#define __UART_CONFIG_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define USART0 0 +#define USART1 1 +#define USART2 2 +#define USART3 3 + +#if defined(BSP_USING_UART0) +#ifndef UART0_CONFIG +#define UART0_CONFIG \ + { \ + .name = "uart0", \ + .id = USART0, \ + } +#endif /* UART0_CONFIG */ +#endif /* BSP_USING_UART0 */ + +#if defined(BSP_USING_UART1) +#ifndef UART1_CONFIG +#define UART1_CONFIG \ + { \ + .name = "uart1", \ + .id = USART1, \ + } +#endif /* UART1_CONFIG */ +#endif /* BSP_USING_UART1 */ + +#if defined(BSP_USING_UART2) +#ifndef UART2_CONFIG +#define UART2_CONFIG \ + { \ + .name = "uart2", \ + .id = USART2, \ + } +#endif /* UART2_CONFIG */ +#endif /* BSP_USING_UART2 */ + +#if defined(BSP_USING_UART3) +#ifndef UART3_CONFIG +#define UART3_CONFIG \ + { \ + .name = "uart3", \ + .id = USART3, \ + } +#endif /* UART3_CONFIG */ +#endif /* BSP_USING_UART3 */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/airm2m/air105/libraries/rt_drivers/config/drv_config.h b/bsp/airm2m/air105/libraries/rt_drivers/config/drv_config.h new file mode 100644 index 0000000000..8edbcce720 --- /dev/null +++ b/bsp/airm2m/air105/libraries/rt_drivers/config/drv_config.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + + +#ifndef __DRV_CONFIG_H__ +#define __DRV_CONFIG_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef SOC_AIR105 +#include "air105/spi_config.h" +#include "air105/uart_config.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif/* __DRV_CONFIG_H__ */ diff --git a/bsp/airm2m/air105/libraries/rt_drivers/drv_common.c b/bsp/airm2m/air105/libraries/rt_drivers/drv_common.c new file mode 100644 index 0000000000..ac43c283b1 --- /dev/null +++ b/bsp/airm2m/air105/libraries/rt_drivers/drv_common.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + +#include "drv_common.h" +#include "board.h" + +#ifdef RT_USING_SERIAL +#ifdef RT_USING_SERIAL_V2 +#include "drv_usart_v2.h" +#else +#include "drv_usart.h" +#endif /* RT_USING_SERIAL */ +#endif /* RT_USING_SERIAL_V2 */ + +#define DBG_TAG "drv_common" +#define DBG_LVL DBG_INFO +#include + +#ifdef RT_USING_FINSH +#include +static void reboot(uint8_t argc, char **argv) +{ + rt_hw_cpu_reset(); +} +MSH_CMD_EXPORT(reboot, Reboot System); +#endif /* RT_USING_FINSH */ + + + +/* SysTick configuration */ +void rt_hw_systick_init(void) +{ + SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + + NVIC_SetPriority(SysTick_IRQn, 0xFF); +} + +/** + * This is the timer interrupt service routine. + * + */ +void SysTick_Handler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + rt_tick_increase(); + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * @brief This function is executed in case of error occurrence. + * @param None + * @retval None + */ +void _Error_Handler(char *s, int num) +{ + /* USER CODE BEGIN Error_Handler */ + /* User can add his own implementation to report the HAL error return state */ + LOG_E("Error_Handler at file:%s num:%d", s, num); + while (1) + { + } + /* USER CODE END Error_Handler */ +} + +/** + * This function will delay for some us. + * + * @param us the delay time of us + */ +void rt_hw_us_delay(rt_uint32_t us) +{ + rt_uint32_t ticks; + rt_uint32_t told, tnow, tcnt = 0; + rt_uint32_t reload = SysTick->LOAD; + + ticks = us * reload / (1000000 / RT_TICK_PER_SECOND); + told = SysTick->VAL; + while (1) + { + tnow = SysTick->VAL; + if (tnow != told) + { + if (tnow < told) + { + tcnt += told - tnow; + } + else + { + tcnt += reload - tnow + told; + } + told = tnow; + if (tcnt >= ticks) + { + break; + } + } + } +} diff --git a/bsp/airm2m/air105/libraries/rt_drivers/drv_common.h b/bsp/airm2m/air105/libraries/rt_drivers/drv_common.h new file mode 100644 index 0000000000..c178b99bb0 --- /dev/null +++ b/bsp/airm2m/air105/libraries/rt_drivers/drv_common.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + +#ifndef __DRV_COMMON_H__ +#define __DRV_COMMON_H__ + +#include +#include +#ifdef RT_USING_DEVICE +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void _Error_Handler(char *s, int num); + +#ifndef Error_Handler +#define Error_Handler() _Error_Handler(__FILE__, __LINE__) +#endif + +#define DMA_NOT_AVAILABLE ((DMA_INSTANCE_TYPE *)0xFFFFFFFFU) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/airm2m/air105/libraries/rt_drivers/drv_gpio.c b/bsp/airm2m/air105/libraries/rt_drivers/drv_gpio.c new file mode 100644 index 0000000000..d3b7126319 --- /dev/null +++ b/bsp/airm2m/air105/libraries/rt_drivers/drv_gpio.c @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + +#include +#include "drv_gpio.h" + +#ifdef RT_USING_PIN + +static struct rt_pin_irq_hdr pin_irq_hdr_tab[GPIO_MAX]; + +static rt_base_t air105_pin_get(const char *name) +{ + rt_base_t pin = 0; + int hw_port_num, hw_pin_num = 0; + int i, name_len; + + name_len = rt_strlen(name); + + if ((name_len < 4) || (name_len >= 6)) + { + return -RT_EINVAL; + } + if ((name[0] != 'P') || (name[2] != '.')) + { + return -RT_EINVAL; + } + + if ((name[1] >= 'A') && (name[1] <= 'Z')) + { + hw_port_num = (int)(name[1] - 'A'); + } + else + { + return -RT_EINVAL; + } + + for (i = 3; i < name_len; i++) + { + hw_pin_num *= 10; + hw_pin_num += name[i] - '0'; + } + + pin = (hw_port_num << 4) + hw_pin_num; + + return pin; +} + +static void air105_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) +{ + if (pin < GPIO_MAX) + { + GPIO_Output(pin, value); + } +} + +static int air105_pin_read(rt_device_t dev, rt_base_t pin) +{ + if (pin < GPIO_MAX) + { + return GPIO_Input(pin); + } + else + { + return -1; + } +} + +static void air105_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) +{ + if (pin >= GPIO_MAX) + { + return; + } + switch(mode) + { + case PIN_MODE_OUTPUT: + GPIO_PullConfig(pin, 0, 0); + GPIO_Config(pin, 0, 0); + break; + case PIN_MODE_INPUT: + case PIN_MODE_INPUT_PULLDOWN: + GPIO_PullConfig(pin, 0, 0); + GPIO_Config(pin, 1, 0); + break; + case PIN_MODE_INPUT_PULLUP: + GPIO_PullConfig(pin, 1, 1); + GPIO_Config(pin, 1, 0); + break; + case PIN_MODE_OUTPUT_OD: + GPIO_ODConfig(pin, 0); + break; + } +} + +static rt_err_t air105_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; + + + level = rt_hw_interrupt_disable(); + if (pin_irq_hdr_tab[pin].pin == pin && + pin_irq_hdr_tab[pin].hdr == hdr && + pin_irq_hdr_tab[pin].mode == mode && + pin_irq_hdr_tab[pin].args == args) + { + rt_hw_interrupt_enable(level); + return RT_EOK; + } + pin_irq_hdr_tab[pin].pin = pin; + pin_irq_hdr_tab[pin].hdr = hdr; + pin_irq_hdr_tab[pin].mode = mode; + pin_irq_hdr_tab[pin].args = args; + rt_hw_interrupt_enable(level); + + return RT_EOK; +} + +static rt_err_t air105_pin_dettach_irq(struct rt_device *device, rt_int32_t pin) +{ + rt_base_t level; + level = rt_hw_interrupt_disable(); + pin_irq_hdr_tab[pin].pin = -1; + pin_irq_hdr_tab[pin].hdr = RT_NULL; + pin_irq_hdr_tab[pin].mode = 0; + pin_irq_hdr_tab[pin].args = RT_NULL; + rt_hw_interrupt_enable(level); + return RT_EOK; +} + +static rt_err_t air105_pin_irq_enable(struct rt_device *device, rt_base_t pin, + rt_uint32_t enabled) +{ + + rt_base_t level; + if (pin >= GPIO_MAX) + { + return -RT_ENOSYS; + } + + if (enabled == PIN_IRQ_ENABLE) + { + + level = rt_hw_interrupt_disable(); + + if (pin_irq_hdr_tab[pin].pin == -1) + { + rt_hw_interrupt_enable(level); + return RT_ENOSYS; + } + switch (pin_irq_hdr_tab[pin].mode) + { + case PIN_IRQ_MODE_RISING: + GPIO_ExtiConfig(pin, 0, 1, 0); + break; + case PIN_IRQ_MODE_FALLING: + GPIO_ExtiConfig(pin, 0, 0, 1); + break; + case PIN_IRQ_MODE_RISING_FALLING: + GPIO_ExtiConfig(pin, 0, 1, 1); + break; + } + rt_hw_interrupt_enable(level); + } + else if (enabled == PIN_IRQ_DISABLE) + { + level = rt_hw_interrupt_disable(); + GPIO_ExtiConfig(pin, 0, 0, 0); + rt_hw_interrupt_enable(level); + } + else + { + return -RT_ENOSYS; + } + + return RT_EOK; +} +const static struct rt_pin_ops _air105_pin_ops = +{ + air105_pin_mode, + air105_pin_write, + air105_pin_read, + air105_pin_attach_irq, + air105_pin_dettach_irq, + air105_pin_irq_enable, + air105_pin_get, +}; + +static int pin_irq_hdr(void *pData, void *pParam) +{ + rt_uint32_t irqno = (rt_uint32_t)pData; + if (pin_irq_hdr_tab[irqno].hdr) + { + pin_irq_hdr_tab[irqno].hdr(pin_irq_hdr_tab[irqno].args); + } + return 0; +} + + +int rt_hw_pin_init(void) +{ + GPIO_GlobalInit(pin_irq_hdr); + return rt_device_pin_register("pin", &_air105_pin_ops, RT_NULL); +} + +#endif /* RT_USING_PIN */ diff --git a/bsp/airm2m/air105/libraries/rt_drivers/drv_gpio.h b/bsp/airm2m/air105/libraries/rt_drivers/drv_gpio.h new file mode 100644 index 0000000000..bf2164c7b4 --- /dev/null +++ b/bsp/airm2m/air105/libraries/rt_drivers/drv_gpio.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + +#ifndef __DRV_GPIO_H__ +#define __DRV_GPIO_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + + +int rt_hw_pin_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __DRV_GPIO_H__ */ + diff --git a/bsp/airm2m/air105/libraries/rt_drivers/drv_i2c.c b/bsp/airm2m/air105/libraries/rt_drivers/drv_i2c.c new file mode 100644 index 0000000000..ed0b43bb52 --- /dev/null +++ b/bsp/airm2m/air105/libraries/rt_drivers/drv_i2c.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + +#include +#include +#include "board.h" +#ifdef BSP_USING_I2C + +static struct rt_i2c_bus_device prv_air105_i2c; +static rt_size_t air105_i2c_mst_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num); +static rt_size_t air105_i2c_slv_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num); +static rt_err_t air105_i2c_bus_control(struct rt_i2c_bus_device *bus, + rt_uint32_t, + rt_uint32_t); + +static const struct rt_i2c_bus_device_ops air105_i2c_ops = +{ + .master_xfer = air105_i2c_mst_xfer, + .slave_xfer = RT_NULL, + .i2c_bus_control = air105_i2c_bus_control +}; + + +static rt_size_t air105_i2c_mst_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + rt_size_t i; + uint64_t tick; + struct rt_i2c_msg *msg = msgs; + RT_ASSERT(bus != RT_NULL); + rt_uint32_t i2c_id = (rt_uint32_t)bus->priv; + rt_int32_t Result; + while(!I2C_WaitResult(i2c_id, &Result)) {;} + for (i = 0; i < num; i++) + { + if (!(msg[i].flags & RT_I2C_NO_START)) + { + if (msg[i].flags & RT_I2C_ADDR_10BIT) + { + I2C_Prepare(i2c_id, msg[i].addr, 2, NULL, NULL); + } + else + { + I2C_Prepare(i2c_id, msg[i].addr, 1, NULL, NULL); + } + } + if (msg[i].flags & RT_I2C_RD) + { + tick = GetSysTick(); + I2C_MasterXfer(i2c_id, I2C_OP_READ, 0, msg[i].buf, msg[i].len, bus->timeout); + while(!I2C_WaitResult(i2c_id, &Result) && !SysTickCheckTimeout(tick, bus->timeout * CORE_TICK_1MS)){;} + if (!I2C_WaitResult(i2c_id, &Result)) + { + I2C_ForceStop(i2c_id); + return -RT_EIO; + } + } + else + { + tick = GetSysTick(); + I2C_MasterXfer(i2c_id, I2C_OP_WRITE, 0, msg[i].buf, msg[i].len, bus->timeout); + while(!I2C_WaitResult(i2c_id, &Result) && !SysTickCheckTimeout(tick, bus->timeout * CORE_TICK_1MS)){;} + if (!I2C_WaitResult(i2c_id, &Result)) + { + I2C_ForceStop(i2c_id); + return -RT_EIO; + } + } + } + return i; +} +static rt_size_t air105_i2c_slv_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + return RT_ERROR; +} +static rt_err_t air105_i2c_bus_control(struct rt_i2c_bus_device *bus, + rt_uint32_t cmd, + rt_uint32_t arg) +{ + + RT_ASSERT(bus != RT_NULL); + rt_uint32_t i2c_id = (rt_uint32_t)bus->priv; + switch (cmd) + { + case RT_I2C_DEV_CTRL_CLK: + I2C_MasterSetup(i2c_id, arg); + break; + default: + return -RT_EIO; + } + + return RT_EOK; +} + +int air105_hw_i2c_init(void) +{ + I2C_GlobalInit(); + prv_air105_i2c.ops = &air105_i2c_ops; + prv_air105_i2c.priv = 0; + I2C_MasterSetup(0, 400000); +#ifdef I2C_BUS_NAME + rt_i2c_bus_device_register(&prv_air105_i2c, I2C_BUS_NAME); +#else + rt_i2c_bus_device_register(&prv_air105_i2c, "i2c"); +#endif + + return 0; +} +INIT_DEVICE_EXPORT(air105_hw_i2c_init); + +#endif /* BSP_USING_I2C */ diff --git a/bsp/airm2m/air105/libraries/rt_drivers/drv_log.h b/bsp/airm2m/air105/libraries/rt_drivers/drv_log.h new file mode 100644 index 0000000000..aed4bf869a --- /dev/null +++ b/bsp/airm2m/air105/libraries/rt_drivers/drv_log.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + + +#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/airm2m/air105/libraries/rt_drivers/drv_rtc.c b/bsp/airm2m/air105/libraries/rt_drivers/drv_rtc.c new file mode 100644 index 0000000000..9c21eb248c --- /dev/null +++ b/bsp/airm2m/air105/libraries/rt_drivers/drv_rtc.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + + +#include +#include +#include "board.h" +#include + +#ifdef BSP_USING_ONCHIP_RTC + +#ifndef RTC_BKP_DR1 +#define RTC_BKP_DR1 RT_NULL +#endif + +//#define DRV_DEBUG +#define LOG_TAG "drv.rtc" +#include + +static rt_err_t air105_rtc_init(void) +{ + RTC_GlobalInit(); + return RT_EOK; +} + +static rt_err_t air105_rtc_get_secs(void *args) +{ + *(rt_uint32_t *) args = RTC_GetUTC(); + LOG_D("RTC: get rtc_time %x\n", *(rt_uint32_t *)args); + + return RT_EOK; +} + +static rt_err_t air105_rtc_set_secs(void *args) +{ + rt_err_t result = RT_EOK; + rt_uint32_t stamp = *(rt_uint32_t *)args; + RTC_SetStamp(stamp); + LOG_D("RTC: set rtc_time %x\n", *(rt_uint32_t *)args); + + return result; +} + +static rt_err_t air105_rtc_get_timeval(void *args) +{ + struct timeval *tv = (struct timeval *) args; + tv->tv_sec = RTC_GetUTC(); + return RT_EOK; +} + +static const struct rt_rtc_ops air105_rtc_ops = +{ + air105_rtc_init, + air105_rtc_get_secs, + air105_rtc_set_secs, + RT_NULL, + RT_NULL, + air105_rtc_get_timeval, + RT_NULL, +}; + +static rt_rtc_dev_t air105_rtc_dev; + +static int rt_hw_rtc_init(void) +{ + rt_err_t result; + + air105_rtc_dev.ops = &air105_rtc_ops; + result = rt_hw_rtc_register(&air105_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL); + if (result != RT_EOK) + { + LOG_E("rtc register err code: %d", result); + return result; + } + LOG_D("rtc init success"); + + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_rtc_init); +#endif /* BSP_USING_ONCHIP_RTC */ diff --git a/bsp/airm2m/air105/libraries/rt_drivers/drv_spi.c b/bsp/airm2m/air105/libraries/rt_drivers/drv_spi.c new file mode 100644 index 0000000000..7765139372 --- /dev/null +++ b/bsp/airm2m/air105/libraries/rt_drivers/drv_spi.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + +#include +#include +#include "board.h" + +#ifdef RT_USING_SPI + +#if !defined(BSP_USING_HSPI0) && !defined(BSP_USING_SPI0) && !defined(BSP_USING_SPI1) && !defined(BSP_USING_SPI2) && !defined(BSP_USING_SPI0S) + #error "Please define at least one BSP_USING_SPIx" + /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */ +#endif + +#include "drv_spi.h" +#include "drv_config.h" +//#define DRV_DEBUG +#define LOG_TAG "drv.spi" +#include + +static struct air_spi spi_config[] = +{ +#ifdef BSP_USING_HSPI0 + HSPI0_BUS_CONFIG, +#endif +#ifdef BSP_USING_SPI0 + SPI0_BUS_CONFIG, +#endif +#ifdef BSP_USING_SPI1 + SPI1_BUS_CONFIG, +#endif +#ifdef BSP_USING_SPI2 + SPI2_BUS_CONFIG, +#endif +#ifdef BSP_USING_SPI0S + SPI0S_BUS_CONFIG, +#endif +}; + +static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message) +{ + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(device->bus != RT_NULL); + RT_ASSERT(message != RT_NULL); + + rt_uint32_t spi_id = device->bus->parent.user_data; + rt_uint32_t cs_pin = device->parent.user_data; + if (message->cs_take && !(device->config.mode & RT_SPI_NO_CS)) + { + if (device->config.mode & RT_SPI_CS_HIGH) + GPIO_Output(cs_pin, 1); + else + GPIO_Output(cs_pin, 0); + } + + + if (message->length) + { + LOG_D("spi%d 0x%X, 0x%X, %d", + spi_id, + (uint32_t)message->send_buf, + (uint32_t)message->recv_buf, message->length); + if (!message->send_buf) + { + SPI_BlockTransfer(spi_id, message->recv_buf, message->recv_buf, message->length); + } + else + { + SPI_BlockTransfer(spi_id, message->send_buf, message->recv_buf, message->length); + } + LOG_D("spi%d done", spi_id); + } + if (message->cs_release && !(device->config.mode & RT_SPI_NO_CS)) + { + if (device->config.mode & RT_SPI_CS_HIGH) + GPIO_Output(cs_pin, 0); + else + GPIO_Output(cs_pin, 1); + } + + return message->length; +} + +static rt_err_t spi_configure(struct rt_spi_device *device, + struct rt_spi_configuration *configuration) +{ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(configuration != RT_NULL); + rt_uint32_t spi_id = device->bus->parent.user_data; + rt_uint8_t mode = configuration->mode & (RT_SPI_CPHA | RT_SPI_CPOL); + if (configuration->mode & RT_SPI_SLAVE) return RT_EINVAL; + switch(spi_id) + { + case 0: + GPIO_Iomux(GPIOC_12,3); + GPIO_Iomux(GPIOC_13,3); + GPIO_Iomux(GPIOC_15,3); + break; + case 1: + GPIO_Iomux(GPIOB_12, 0); + GPIO_Iomux(GPIOB_14, 0); + GPIO_Iomux(GPIOB_15, 0); + break; + case 2: + GPIO_Iomux(GPIOA_06,3); + GPIO_Iomux(GPIOA_08,3); + GPIO_Iomux(GPIOA_09,3); + + break; + case 3: + GPIO_Iomux(GPIOB_02,0); + GPIO_Iomux(GPIOB_04,0); + GPIO_Iomux(GPIOB_05,0); + break; + } + SPI_MasterInit(spi_id, configuration->data_width, mode, configuration->max_hz, RT_NULL, RT_NULL); + + return RT_EOK; +} + +static const struct rt_spi_ops air105_spi_ops = +{ + .configure = spi_configure, + .xfer = spixfer, +}; + +/** + * 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, rt_uint8_t cs_pin) +{ + RT_ASSERT(bus_name != RT_NULL); + RT_ASSERT(device_name != RT_NULL); + + rt_err_t result; + struct rt_spi_device *spi_device; + + /* 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); + GPIO_Config(cs_pin, 0, 1); + + 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; +} + + +int rt_hw_spi_init(void) +{ + rt_err_t result; + rt_size_t obj_num = sizeof(spi_config) / sizeof(struct air_spi); + for (int spi_index = 0; spi_index < obj_num ; spi_index++) + { + result = rt_spi_bus_register(&(spi_config[spi_index].bus), spi_config[spi_index].bus_name, &air105_spi_ops); + RT_ASSERT(result == RT_EOK); + spi_config[spi_index].bus.parent.user_data = spi_config[spi_index].id; + } + return RT_EOK; +} +INIT_BOARD_EXPORT(rt_hw_spi_init); + + +#endif /* RT_USING_SPI */ diff --git a/bsp/airm2m/air105/libraries/rt_drivers/drv_spi.h b/bsp/airm2m/air105/libraries/rt_drivers/drv_spi.h new file mode 100644 index 0000000000..46114d5756 --- /dev/null +++ b/bsp/airm2m/air105/libraries/rt_drivers/drv_spi.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + + +#ifndef __DRV_SPI_H__ +#define __DRV_SPI_H__ + +#include +#include "rtdevice.h" +#include +#include +#include "drv_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct air_spi +{ + const char bus_name[RT_NAME_MAX]; + rt_uint8_t id; + struct rt_spi_bus bus; +}; + +rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint8_t cs_pin); + +#ifdef __cplusplus +} +#endif + +#endif /*__DRV_SPI_H__ */ diff --git a/bsp/airm2m/air105/libraries/rt_drivers/drv_usart_v2.c b/bsp/airm2m/air105/libraries/rt_drivers/drv_usart_v2.c new file mode 100644 index 0000000000..d83fcb3a92 --- /dev/null +++ b/bsp/airm2m/air105/libraries/rt_drivers/drv_usart_v2.c @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + + +#include "board.h" +#include "drv_usart_v2.h" + +#ifdef RT_USING_SERIAL_V2 + +//#define DRV_DEBUG +#define DBG_TAG "drv.usart" +#ifdef DRV_DEBUG +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO +#endif /* DRV_DEBUG */ +#include + +#if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1) && !defined(BSP_USING_UART2) && !defined(BSP_USING_UART3) + #error "Please define at least one BSP_USING_UARTx" + /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */ +#endif + +static struct air_uart_config uart_config[] = +{ +#ifdef BSP_USING_UART0 + UART0_CONFIG, +#endif +#ifdef BSP_USING_UART1 + UART1_CONFIG, +#endif +#ifdef BSP_USING_UART2 + UART2_CONFIG, +#endif +#ifdef BSP_USING_UART3 + UART3_CONFIG, +#endif +}; + +enum +{ +#ifdef BSP_USING_UART0 + UART0_INDEX, +#endif +#ifdef BSP_USING_UART1 + UART1_INDEX, +#endif +#ifdef BSP_USING_UART2 + UART2_INDEX, +#endif +#ifdef BSP_USING_UART3 + UART3_INDEX, +#endif +}; + +static struct air_uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] = {0}; + +static void air_uart_get_config(void) +{ + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + +#ifdef BSP_USING_UART0 + uart_obj[UART0_INDEX].serial.config = config; + uart_obj[UART0_INDEX].serial.config.rx_bufsz = BSP_UART0_RX_BUFSIZE; + uart_obj[UART0_INDEX].serial.config.tx_bufsz = BSP_UART0_TX_BUFSIZE; +#endif +#ifdef BSP_USING_UART1 + uart_obj[UART1_INDEX].serial.config = config; + uart_obj[UART1_INDEX].serial.config.rx_bufsz = BSP_UART1_RX_BUFSIZE; + uart_obj[UART1_INDEX].serial.config.tx_bufsz = BSP_UART1_TX_BUFSIZE; +#endif +#ifdef BSP_USING_UART2 + uart_obj[UART2_INDEX].serial.config = config; + uart_obj[UART2_INDEX].serial.config.rx_bufsz = BSP_UART2_RX_BUFSIZE; + uart_obj[UART2_INDEX].serial.config.tx_bufsz = BSP_UART2_TX_BUFSIZE; +#endif +#ifdef BSP_USING_UART3 + uart_obj[UART3_INDEX].serial.config = config; + uart_obj[UART3_INDEX].serial.config.rx_bufsz = BSP_UART3_RX_BUFSIZE; + uart_obj[UART3_INDEX].serial.config.tx_bufsz = BSP_UART3_TX_BUFSIZE; +#endif +} + +static int air105_uart_irq(void *pData, void *pParam) +{ + rt_uint32_t uartid = (rt_uint32_t)pData; + rt_uint32_t State = (rt_uint32_t)pParam; + uint8_t temp[32]; + rt_uint32_t len; + struct rt_serial_device *serial = NULL; + + rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct air_uart); + for (int i = 0; i < obj_num; i++) + { + if (uart_obj[i].config->id == uartid) + serial = &(uart_obj[i].serial); + } + struct rt_serial_rx_fifo *rx_fifo; + + switch (State){ + case UART_CB_TX_BUFFER_DONE: + break; + case DMA_CB_DONE: + DMA_ClearStreamFlag(DBG_UART_TX_DMA_STREAM); + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DMADONE); + break; + case UART_CB_TX_ALL_DONE: + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DMADONE); + break; + case UART_CB_RX_BUFFER_FULL: + break; + case UART_CB_RX_TIMEOUT: + case UART_CB_RX_NEW: + rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx; + len = Uart_FifoRead(uartid, temp); + if (len) + { + rt_ringbuffer_put(&(rx_fifo->rb), temp, len); + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); + } + break; + case UART_CB_ERROR: + break; + case DMA_CB_ERROR: + break; + } +} + +static rt_err_t air105_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + rt_uint32_t uart_id = serial->parent.user_data; + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(cfg != RT_NULL); + + switch (cfg->stop_bits) + { + case STOP_BITS_1: + cfg->stop_bits = UART_STOP_BIT1; + break; + case STOP_BITS_2: + cfg->stop_bits = UART_STOP_BIT2; + break; + default: + cfg->stop_bits = UART_STOP_BIT1_5; + break; + } + + Uart_BaseInit(uart_id, cfg->baud_rate, 0, cfg->data_bits, cfg->parity, cfg->stop_bits, air105_uart_irq); + switch (uart_id){ + case UART_ID0: + GPIO_Iomux(GPIOA_01, 0); + GPIO_Iomux(GPIOA_00, 0); + break; + case UART_ID1: + GPIO_Iomux(GPIOC_01, 3); + GPIO_Iomux(GPIOC_00, 3); + break; + case UART_ID2: + GPIO_Iomux(GPIOD_13, 0); + GPIO_Iomux(GPIOD_12, 0); + break; + case UART_ID3: + GPIO_Iomux(GPIOE_08, 2); + GPIO_Iomux(GPIOE_09, 2); + break; + default: + break; + } + return RT_EOK; +} + +static rt_err_t air105_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + rt_uint32_t uart_id = serial->parent.user_data; + + rt_ubase_t ctrl_arg = (rt_ubase_t)arg; + RT_ASSERT(serial != RT_NULL); + + switch (cmd) + { + /* disable interrupt */ + case RT_DEVICE_CTRL_CLR_INT: + Uart_IrqOnOff(uart_id, 0); + if (DBG_UART_ID == uart_id) + { + DMA_StopStream(DBG_UART_TX_DMA_STREAM); + } + break; + + case RT_DEVICE_CTRL_SET_INT: + break; + + case RT_DEVICE_CTRL_CONFIG: + if (ctrl_arg & (RT_SERIAL_RX_NON_BLOCKING|RT_SERIAL_RX_BLOCKING)) + { + Uart_EnableRxIrq(uart_id); + } + Uart_IrqOnOff(uart_id, 1); + break; + + case RT_DEVICE_CHECK_OPTMODE: + return RT_SERIAL_TX_BLOCKING_NO_BUFFER; + + case RT_DEVICE_CTRL_CLOSE: + Uart_DeInit(uart_id); + switch (uart_id){ + case UART_ID0: + GPIO_Iomux(GPIOA_01, 1); + GPIO_Iomux(GPIOA_00, 1); + break; + case UART_ID1: + GPIO_Iomux(GPIOC_01, 1); + GPIO_Iomux(GPIOC_00, 1); + break; + case UART_ID2: + GPIO_Iomux(GPIOD_13, 1); + GPIO_Iomux(GPIOD_12, 1); + break; + case UART_ID3: + GPIO_Iomux(GPIOE_08, 1); + GPIO_Iomux(GPIOE_09, 1); + break; + default: + break; + } + break; + default: + return RT_ERROR; + + } + return RT_EOK; +} + +static int air105_putc(struct rt_serial_device *serial, char c) +{ + rt_uint32_t uart_id = serial->parent.user_data; + RT_ASSERT(serial != RT_NULL); + Uart_NoBlockTx(uart_id, c); + return 1; +} + + +static int air105_getc(struct rt_serial_device *serial) +{ + rt_uint32_t uart_id = serial->parent.user_data; + RT_ASSERT(serial != RT_NULL); + uint8_t data; + if (Uart_ReadByte(uart_id, &data) < 0) + { + return -1; + } + else + { + return data; + } +} + +static rt_size_t air105_transmit(struct rt_serial_device *serial, + rt_uint8_t *buf, + rt_size_t size, + rt_uint32_t tx_flag) +{ + rt_uint32_t uart_id = serial->parent.user_data; + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(buf != RT_NULL); + if (DBG_UART_ID == uart_id) + { + Uart_BlockTx(uart_id, buf, size); + } + else + { + Uart_BufferTx(uart_id, buf, size); + } + return size; +} + + +static const struct rt_uart_ops air105_uart_ops = +{ + .configure = air105_configure, + .control = air105_control, + .putc = air105_putc, + .getc = air105_getc, + .transmit = air105_transmit +}; + +int rt_hw_usart_init(void) +{ + rt_err_t result = 0; + rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct air_uart); + + air_uart_get_config(); + for (int i = 0; i < obj_num; i++) + { + /* init UART object */ + uart_obj[i].config = &uart_config[i]; + if (uart_obj[i].config->id == DBG_UART_ID) + uart_obj[i].serial.config.baud_rate = DBG_UART_BR; + uart_obj[i].serial.ops = &air105_uart_ops; + /* register UART device */ + result = rt_hw_serial_register(&uart_obj[i].serial,uart_obj[i].config->name, + RT_DEVICE_FLAG_RDWR, + i); + RT_ASSERT(result == RT_EOK); + } + return result; +} + +#endif /* RT_USING_SERIAL_V2 */ diff --git a/bsp/airm2m/air105/libraries/rt_drivers/drv_usart_v2.h b/bsp/airm2m/air105/libraries/rt_drivers/drv_usart_v2.h new file mode 100644 index 0000000000..7e60c50802 --- /dev/null +++ b/bsp/airm2m/air105/libraries/rt_drivers/drv_usart_v2.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + + +#ifndef __DRV_USART_V2_H__ +#define __DRV_USART_V2_H__ + +#include +#include +#include +#include +#include "drv_config.h" + +/* renesas config class */ +struct air_uart_config +{ + const char *name; + rt_uint8_t id; +}; + +struct air_uart +{ + struct rt_serial_device serial; + struct air_uart_config *config; +}; + +int rt_hw_usart_init(void); + +#endif /* __DRV_USART_H__ */ diff --git a/bsp/airm2m/air105/libraries/rt_drivers/drv_wdt.c b/bsp/airm2m/air105/libraries/rt_drivers/drv_wdt.c new file mode 100644 index 0000000000..310b839722 --- /dev/null +++ b/bsp/airm2m/air105/libraries/rt_drivers/drv_wdt.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-02-22 airm2m first version + */ + +#include "board.h" +#include + +#ifdef RT_USING_WDT + +#define LOG_TAG "drv.wdt" +#include + + +static rt_watchdog_t watchdog; +static struct rt_watchdog_ops ops; + +static rt_err_t wdt_init(rt_watchdog_t *wdt) +{ + return RT_EOK; +} + +static rt_err_t wdt_control(rt_watchdog_t *wdt, int cmd, void *arg) +{ + switch (cmd) + { + /* feed the watchdog */ + case RT_DEVICE_CTRL_WDT_KEEPALIVE: + WDT_Feed(); + break; + /* set watchdog timeout */ + case RT_DEVICE_CTRL_WDT_SET_TIMEOUT: + WDT_SetTimeout((*((rt_uint32_t*)arg))*1000); + break; + case RT_DEVICE_CTRL_WDT_GET_TIMEOUT: + break; + case RT_DEVICE_CTRL_WDT_START: + + break; + default: + LOG_W("This command is not supported."); + return -RT_ERROR; + } + return RT_EOK; +} + +int rt_wdt_init(void) +{ + ops.init = &wdt_init; + ops.control = &wdt_control; + watchdog.ops = &ops; + /* register watchdog device */ + if (rt_hw_watchdog_register(&watchdog, "wdt", RT_DEVICE_FLAG_DEACTIVATE, RT_NULL) != RT_EOK) + { + LOG_E("wdt device register failed."); + return -RT_ERROR; + } + LOG_D("wdt device register success."); + return RT_EOK; +} +INIT_BOARD_EXPORT(rt_wdt_init); + +#endif /* RT_USING_WDT */ diff --git a/bsp/airm2m/air105/makesoc.py b/bsp/airm2m/air105/makesoc.py new file mode 100644 index 0000000000..fb5ebbe08f --- /dev/null +++ b/bsp/airm2m/air105/makesoc.py @@ -0,0 +1,29 @@ + +import os +import sys +import shutil +import urllib + +out_path='./' +bin_file_name='rtthread.bin' +pack_path='./pack' +out_file='./rtthread_air105' + +cwd_path = os.getcwd() +if __name__=='__main__': + + print(cwd_path) + if os.path.exists(out_file+'.soc'): + os.remove(out_file+'.soc') + + if not os.path.exists(pack_path+'/bootloader.bin'): + urllib.urlretrieve("http://cdndownload.openluat.com/rt-thread/airm2m/air105/bootloader.bin", pack_path+'/bootloader.bin') + + if not os.path.exists(pack_path+'/soc_download.exe'): + urllib.urlretrieve("http://cdndownload.openluat.com/rt-thread/airm2m/air105/soc_download.exe", pack_path+'/soc_download.exe') + + shutil.copy(out_path+bin_file_name, pack_path+'/'+bin_file_name) + shutil.make_archive(out_file, 'zip', root_dir=pack_path) + os.remove(pack_path+'/'+bin_file_name) + os.rename(out_file+'.zip',out_file+'.soc') + print('end') diff --git a/bsp/airm2m/air105/pack/info.json b/bsp/airm2m/air105/pack/info.json new file mode 100644 index 0000000000..ad8812c097 --- /dev/null +++ b/bsp/airm2m/air105/pack/info.json @@ -0,0 +1,61 @@ +{ + "version" : 1, + "chip" : { + "type" : "air105", + "ram" : { + "total" : 640, + "sys" : 64, + "lua" : 176 + } + }, + "bl": { + "file" : "bootloader.bin" + }, + "partition": { + "file" : "partition-table.bin" + }, + "rom": { + "file" : "rtthread.bin", + "fs" : { + "script" : { + "offset" : "0", + "size" : 512, + "type": "luadb" + } + }, + "version-core": "v0001", + "version-bsp" : "v0001", + "mark" : "default", + "build" : { + "build_at" : "", + "build_by" : "", + "build_host" : "", + "build_system" : "" + } + }, + "script" : { + "file" : "script.bin", + "lua" : "5.3", + "bitw" : 32, + "use-luac" : true, + "use-debug" : true + }, + "fs" : { + "total_len" : 512, + "format_len" : "0" + }, + "user" : { + "project" : "", + "version" : "" + }, + "download" : { + "bl_addr" : "01001000", + "core_addr" : "01010000", + "app_addr" : "00000000", + "script_addr" : "01300000", + "nvm_addr" : "00000000", + "fs_addr" : "01380000", + "force_br" : "3000000", + "extra_param" : "0002ff00" + } +} diff --git a/bsp/airm2m/air105/rtconfig.h b/bsp/airm2m/air105/rtconfig.h new file mode 100644 index 0000000000..f6415b72bb --- /dev/null +++ b/bsp/airm2m/air105/rtconfig.h @@ -0,0 +1,204 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 1000 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_HOOK_USING_FUNC_PTR +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + +#define RT_DEBUG + +/* 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 256 +#define RT_CONSOLE_DEVICE_NAME "uart0" +#define RT_VER_NUM 0x40100 +#define ARCH_ARM +#define RT_USING_CPU_FFS +#define ARCH_ARM_CORTEX_M +#define ARCH_ARM_CORTEX_M4 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define RT_USING_MSH +#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 virtual file system */ + + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 +#define RT_USING_SERIAL +#define RT_USING_SERIAL_V2 +#define RT_SERIAL_USING_DMA +#define RT_USING_PIN +#define RT_USING_WDT + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_LIBC_DEFAULT_TIMEZONE 8 + +/* POSIX (Portable Operating System Interface) layer */ + + +/* Interprocess Communication (IPC) */ + + +/* Socket is in the 'Network' category */ + +/* Network */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + + +/* RT-Thread Utestcases */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* 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 */ + + +/* POSIX extension functions */ + + +/* acceleration: Assembly language or algorithmic acceleration packages */ + + +/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + + +/* Hardware Drivers Config */ + +#define SOC_AIR105 + +/* Onboard Peripheral Drivers */ + +#define BSP_USING_SHELL_TO_USART + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_GPIO +#define BSP_USING_UART +#define BSP_USING_UART0 +#define BSP_UART0_RX_BUFSIZE 256 +#define BSP_UART0_TX_BUFSIZE 0 +#define BSP_USING_WDT + +#endif diff --git a/bsp/airm2m/air105/rtconfig.py b/bsp/airm2m/air105/rtconfig.py new file mode 100644 index 0000000000..18f2bdc0dc --- /dev/null +++ b/bsp/airm2m/air105/rtconfig.py @@ -0,0 +1,182 @@ +import os + +# toolchains options +ARCH='arm' +CPU='cortex-m4' +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 = 'iar' + EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.0' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + CXX = PREFIX + 'g++' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections' + CFLAGS = DEVICE + ' -Dgcc' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.lds' + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -Og -gdwarf-2 -g' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' + POST_ACTION += 'python ./makesoc.py' +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + CXX = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M4.fp ' + CFLAGS = '-c ' + DEVICE + ' --apcs=interwork --c99' + AFLAGS = DEVICE + ' --apcs=interwork ' + LFLAGS = DEVICE + ' --scatter "board\linker_scripts\link.sct" --info sizes --info totals --info unused --info veneers --list rtthread.map --strict' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCC/include' + LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCC/lib' + + CFLAGS += ' -D__MICROLIB ' + AFLAGS += ' --pd "__MICROLIB SETA 1" ' + LFLAGS += ' --library_type=microlib ' + EXEC_PATH += '/ARM/ARMCC/bin/' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + POST_ACTION += 'python ./makesoc.py' +elif PLATFORM == 'armclang': + # toolchains + CC = 'armclang' + CXX = 'armclang' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M4.fp ' + CFLAGS = ' --target=arm-arm-none-eabi -mcpu=cortex-m4 ' + CFLAGS += ' -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 ' + CFLAGS += ' -mfloat-abi=hard -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' + POST_ACTION += 'python ./makesoc.py' +elif PLATFORM == 'iar': + # toolchains + CC = 'iccarm' + CXX = 'iccarm' + AS = 'iasmarm' + AR = 'iarchive' + LINK = 'ilinkarm' + TARGET_EXT = 'out' + + DEVICE = '-Dewarm' + + CFLAGS = DEVICE + CFLAGS += ' --diag_suppress Pa050' + CFLAGS += ' --no_cse' + CFLAGS += ' --no_unroll' + CFLAGS += ' --no_inline' + CFLAGS += ' --no_code_motion' + CFLAGS += ' --no_tbaa' + CFLAGS += ' --no_clustering' + CFLAGS += ' --no_scheduling' + CFLAGS += ' --endian=little' + CFLAGS += ' --cpu=Cortex-M4' + CFLAGS += ' -e' + CFLAGS += ' --fpu=VFPv4_sp' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' --silent' + + AFLAGS = DEVICE + AFLAGS += ' -s+' + AFLAGS += ' -w+' + AFLAGS += ' -r' + AFLAGS += ' --cpu Cortex-M4' + AFLAGS += ' --fpu VFPv4_sp' + AFLAGS += ' -S' + + if BUILD == 'debug': + CFLAGS += ' --debug' + CFLAGS += ' -On' + else: + CFLAGS += ' -Oh' + + LFLAGS = ' --config "board/linker_scripts/link.icf"' + LFLAGS += ' --entry __iar_program_start' + + CXXFLAGS = CFLAGS + + EXEC_PATH = EXEC_PATH + '/arm/bin/' + POST_ACTION = 'ielftool --bin $TARGET rtthread.bin' + POST_ACTION += 'python ./makesoc.py' +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'))