From 6c3c1c920a14167d96b24a1aca2fc69f950ee01b Mon Sep 17 00:00:00 2001 From: pvvx Date: Sun, 25 Feb 2024 06:41:34 +0300 Subject: [PATCH] =?UTF-8?q?add=20update=20boot,=20=D0=BE=D0=B1=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D0=BA=D1=80=D0=B8?= =?UTF-8?q?=D0=BF=D1=82=D0=BE=D0=B2=20=D1=81=D0=B1=D0=BE=D1=80=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=B8=20=D0=BF=D1=80=D0=BE=D1=88=D0=B8=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 27 +- bin/BTH01_v14.bin | Bin 47716 -> 47716 bytes bin/TH05D_v14.bin | Bin 49268 -> 49268 bytes bin/TH05F_v14.bin | Bin 49236 -> 49236 bytes bin/TH05_v14.bin | Bin 49108 -> 49108 bytes bin/THB1_v14.bin | Bin 49108 -> 49108 bytes bin/THB2_v14.bin | Bin 47652 -> 47652 bytes bthome_phy6222/.gitignore | 2 + bthome_phy6222/Makefile | 8 +- .../SDK/components/driver/flash/flash.c | 23 + bthome_phy6222/SDK/misc/ota_app_phy62x2.ld | 13 +- bthome_phy6222/bin/BTH01_v14.bin | Bin 47716 -> 47716 bytes bthome_phy6222/bin/TH05D_v14.bin | Bin 49268 -> 49268 bytes bthome_phy6222/bin/TH05F_v14.bin | Bin 49236 -> 49236 bytes bthome_phy6222/bin/TH05_v14.bin | Bin 49108 -> 49108 bytes bthome_phy6222/bin/THB1_v14.bin | Bin 49108 -> 49108 bytes bthome_phy6222/bin/THB2_v14.bin | Bin 47652 -> 47652 bytes bthome_phy6222/mk_windows.cmd | 7 + bthome_phy6222/ota_upboot.add | Bin 0 -> 740 bytes bthome_phy6222/phy62x2_ota.py | 47 +- bthome_phy6222/rdwr_phy62x2.py | 4 +- ota_boot/.autotools | 43 + ota_boot/.cproject | 346 + ota_boot/.gitignore | 7 + ota_boot/.project | 34 + ota_boot/.pydevproject | 5 + ota_boot/.settings/language.settings.xml | 15 + .../org.eclipse.cdt.codan.core.prefs | 109 + ota_boot/.settings/org.eclipse.cdt.core.prefs | 6 + .../org.eclipse.cdt.managedbuilder.core.prefs | 13 + .../org.eclipse.core.resources.prefs | 2 + ...embedcdt.managedbuild.cross.arm.core.prefs | 2 + ota_boot/Makefile | 138 + ota_boot/ota_upboot.add | Bin 0 -> 740 bytes ota_boot/phy62x2_ota.py | 242 + ota_boot/rdwr_phy62x2.py | 738 ++ ota_boot/source/include/bus_dev.h | 80 + ota_boot/source/include/core_bumbee_m0.h | 90 + ota_boot/source/include/global_config.h | 233 + ota_boot/source/include/mcu_phy_bumbee.h | 843 ++ ota_boot/source/include/types.h | 156 + ota_boot/source/main.c | 124 + .../misc/CMSIS/device/phyplus/phy6222.h | 116 + .../misc/CMSIS/device/phyplus/phy6222_start.s | 55 + .../CMSIS/device/phyplus/phy6222_vectors.c | 13 + .../misc/CMSIS/include/arm_common_tables.h | 93 + .../misc/CMSIS/include/arm_const_structs.h | 94 + ota_boot/source/misc/CMSIS/include/arm_math.h | 7080 +++++++++++++++++ ota_boot/source/misc/CMSIS/include/core_cm0.h | 690 ++ .../source/misc/CMSIS/include/core_cm0plus.h | 801 ++ .../source/misc/CMSIS/include/core_cmFunc.h | 638 ++ .../source/misc/CMSIS/include/core_cmInstr.h | 677 ++ ota_boot/source/misc/bb_rom_sym_m0.gcc | 1023 +++ ota_boot/source/misc/ota_upboot.ld | 133 + ota_boot/source/misc/rom_sym_def.h | 903 +++ ota_boot/source/ota_boot.h | 59 + rdwr_phy62x2.py | 4 +- update_boot/BOOT_BTH01_v14.bin | Bin 0 -> 48932 bytes update_boot/BOOT_TH05D_v14.bin | Bin 0 -> 50052 bytes update_boot/BOOT_TH05F_v14.bin | Bin 0 -> 50004 bytes update_boot/BOOT_TH05_v14.bin | Bin 0 -> 49956 bytes update_boot/BOOT_THB1_v14.bin | Bin 0 -> 49908 bytes update_boot/BOOT_THB2_v14.bin | Bin 0 -> 48884 bytes 63 files changed, 15697 insertions(+), 39 deletions(-) create mode 100644 bthome_phy6222/ota_upboot.add create mode 100644 ota_boot/.autotools create mode 100644 ota_boot/.cproject create mode 100644 ota_boot/.gitignore create mode 100644 ota_boot/.project create mode 100644 ota_boot/.pydevproject create mode 100644 ota_boot/.settings/language.settings.xml create mode 100644 ota_boot/.settings/org.eclipse.cdt.codan.core.prefs create mode 100644 ota_boot/.settings/org.eclipse.cdt.core.prefs create mode 100644 ota_boot/.settings/org.eclipse.cdt.managedbuilder.core.prefs create mode 100644 ota_boot/.settings/org.eclipse.core.resources.prefs create mode 100644 ota_boot/.settings/org.eclipse.embedcdt.managedbuild.cross.arm.core.prefs create mode 100644 ota_boot/Makefile create mode 100644 ota_boot/ota_upboot.add create mode 100644 ota_boot/phy62x2_ota.py create mode 100644 ota_boot/rdwr_phy62x2.py create mode 100644 ota_boot/source/include/bus_dev.h create mode 100644 ota_boot/source/include/core_bumbee_m0.h create mode 100644 ota_boot/source/include/global_config.h create mode 100644 ota_boot/source/include/mcu_phy_bumbee.h create mode 100644 ota_boot/source/include/types.h create mode 100644 ota_boot/source/main.c create mode 100644 ota_boot/source/misc/CMSIS/device/phyplus/phy6222.h create mode 100644 ota_boot/source/misc/CMSIS/device/phyplus/phy6222_start.s create mode 100644 ota_boot/source/misc/CMSIS/device/phyplus/phy6222_vectors.c create mode 100644 ota_boot/source/misc/CMSIS/include/arm_common_tables.h create mode 100644 ota_boot/source/misc/CMSIS/include/arm_const_structs.h create mode 100644 ota_boot/source/misc/CMSIS/include/arm_math.h create mode 100644 ota_boot/source/misc/CMSIS/include/core_cm0.h create mode 100644 ota_boot/source/misc/CMSIS/include/core_cm0plus.h create mode 100644 ota_boot/source/misc/CMSIS/include/core_cmFunc.h create mode 100644 ota_boot/source/misc/CMSIS/include/core_cmInstr.h create mode 100644 ota_boot/source/misc/bb_rom_sym_m0.gcc create mode 100644 ota_boot/source/misc/ota_upboot.ld create mode 100644 ota_boot/source/misc/rom_sym_def.h create mode 100644 ota_boot/source/ota_boot.h create mode 100644 update_boot/BOOT_BTH01_v14.bin create mode 100644 update_boot/BOOT_TH05D_v14.bin create mode 100644 update_boot/BOOT_TH05F_v14.bin create mode 100644 update_boot/BOOT_TH05_v14.bin create mode 100644 update_boot/BOOT_THB1_v14.bin create mode 100644 update_boot/BOOT_THB2_v14.bin diff --git a/README.md b/README.md index 98e3a8c..d6bab26 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,10 @@ Custom firmware for Tuya devices on the PHY622x2 chipset | [TH05_V1.3](https://pvvx.github.io/TH05-v1.3) | BOOT_TH05D_v14.hex | TH05D_v14.bin | RSH-TH05-V1.3 с чипом BL55072 | | [TH05F](https://pvvx.github.io/TH05F) | BOOT_TH05F_v14.hex | TH05F_v14.bin | TH05Y_V1.1, TH05Y_V1.2 с чипом QD01 2332 NT | +Основные файлы прошивок, BOOT_xxx_vxx.hex для программирования через USB-COM адаптер и xxx_vxx.bin для OTA, находятся в директории [bin](https://github.com/pvvx/THB2/tree/master/bin). + +Файлы для обновления Boot по OTA находятся в директории [update_boot](https://github.com/pvvx/THB2/tree/master/update_boot). Если boot работает нормально, то обновлять на новую версию не требуется. О необходимости замены будет объявлено дополнительно. Актуальная версия boot - v1.4. + ## Основные характеристики ! _При настройках по умолчанию_ ! @@ -44,11 +48,11 @@ Custom firmware for Tuya devices on the PHY622x2 chipset | 1.1 | Добавлен триггер - вывод TX2 срабатывающий по установленным значениям температуры и/или влажности с гистерезисами. Передача состояния вывода RX2 при connect. Для термометров с экраном добавлен показ смайлика с "комфортом". Дополнены: изменение имени и MAC устройства. | | 1.2 | Обработка и передача событий open/close со счетчиком с вывода маркированного "RX2" (для THB2 - "RX1"). | | 1.3 | Добавлен THB1 и TH05V1.3. Следующий этап уменьшения потребления для версий с LCD дисплеем и опция отключения дисплея. | -| 1.4 | Стабилизация соединения для всех вариантов устройств. Добавлен [TH05F](https://pvvx.github.io/TH05F). Коррекция хода RTC. Изменено BLE имя для TH05_V1.3 на "TH05D" | +| 1.4 | Стабилизация соединения для всех вариантов устройств. Добавлен [TH05F](https://pvvx.github.io/TH05F). Коррекция хода RTC. Изменено BLE имя для TH05_V1.3 на "TH05D". Добавлены файлы для обновления Boot по OTA. | ## Прошивка -Прошить устройство програмой Boot-OTA возможно через USB-COM адаптер с выходами на 3.3В: +Прошить устройство програмой Boot возможно через USB-COM адаптер с выходами на 3.3В: 1. Соединить GND, TX, RX, RTS–RESET, VCC (+3.3B). @@ -60,7 +64,7 @@ Custom firmware for Tuya devices on the PHY622x2 chipset | RX | TX1 | | RTS | RESET | -Если на адаптере отсутствует RST пин, во время запуска скрипта следует подключить RESET пин до GND (вомзожно потребуется несколько попыток) +Если на адаптере отсутствует RST пин, тогда следует замкнуть вывод RESET с GND(-Vbat) и быстро разомкнуть при старте скрипта (вомзожно потребуется несколько попыток) Название контактов на устройстве смотреть в описании по ссылкам: [THB1](https://pvvx.github.io/THB1), [THB2](https://pvvx.github.io/THB2), [BTH01](https://pvvx.github.io/BTH01/), [TH05_V1.3](https://pvvx.github.io/TH05-v1.3), [TH05_V1.4](https://pvvx.github.io/TH-05) @@ -70,21 +74,23 @@ Custom firmware for Tuya devices on the PHY622x2 chipset pip3 install -r requirements.txt ``` -3. Запустить: +3. Скачать необходимый для конкретного устройства файл BOOT_xxx_vxx.hex из директории bin. + +4. Запустить: ```txt python3 rdwr_phy62x2.py -p COM11 -e -r wh BOOT_xxx_vxx.hex ``` -4. Прошивка Boot-OTA завершена. Устройство работает. Адаптер можно отсоединить. +5. Прошивка Boot завершена. Устройство работает. Адаптер можно отсоединить. -5. Загружаем полную версию прошивки по OTA. Для этого: +6. Загружаем полную версию прошивки по OTA. Для этого: 1. Подаем питание на датчик (устройство). 2. Переходим на [PHY62x2BTHome.html](https://pvvx.github.io/THB2/web/PHY62x2BTHome.html). - 3. Жмем кнопку `Cоединение`, ищем устройство, подключаемся. + 3. Жмем кнопку `Соединение`, ищем устройство, подключаемся. 4. После подключение переходим на вкладку `OTA`, выбираем необходимую прошивку и жмем `Старт`. -6. Устройство должно перезагрузиться и быть готово для использования. +7. Устройство должно перезагрузиться и быть готово для использования. Дополнительно: @@ -92,6 +98,11 @@ python3 rdwr_phy62x2.py -p COM11 -e -r wh BOOT_xxx_vxx.hex * Для предварительного стирания рабочей области Flash используйте опцию `-e`. +* С помощью USB-COM адаптера возможно сразу дописать основную прошивку (APP) +``` +python3 rdwr_phy62x2.py -p COM11 -r we 0x10000 xxx_vxx.bin +``` + ## Сохранение оригинальной прошивки 1. Соединить GND, TX, RX, RTS–RESET, VCC (+3.3B). diff --git a/bin/BTH01_v14.bin b/bin/BTH01_v14.bin index f81ecaaaa83a9ba4298cd8de869b6b68cb4fdace..19b6cdd057942ca69762b71e10d2a1d3c1d7228f 100644 GIT binary patch delta 21 dcmaFzh3Ux`Ce{FtNHgY*tkJtzj^-E60|01w2=)K~ delta 21 dcmaFzh3Ux`Ce{FtNHdm=tkJtzt||zg0{~}62#5dx diff --git a/bin/TH05D_v14.bin b/bin/TH05D_v14.bin index 8c55569fab8a84a74f9c1ab4699e155a72aa42ed..50dcdf57a795ef65a5c958819e72d226f145c5eb 100644 GIT binary patch delta 21 ccmey;!2G3wnKi&8(u{c{YxV(_U}jw{09MonumAu6 delta 21 dcmey;!2G3wnKi&8(u`#zYxV(_d-uK{003RZ33mVh diff --git a/bin/TH05F_v14.bin b/bin/TH05F_v14.bin index 894469c2a6688cc162c9a5b27d9606470dae6c71..5545ce2314f08f426445787c6a3fecc6482f9d5c 100644 GIT binary patch delta 21 ccmcc8ztxZDIb}08`!vDF6Tf delta 21 ccmcc8ztx8i(9_08_08s{jB1 diff --git a/bin/TH05_v14.bin b/bin/TH05_v14.bin index 5f61923e45f014a356c521708f4af03ff01b4c5c..b7f96ee4310f811a2d6307aca2ee453e56c40a49 100644 GIT binary patch delta 21 dcmccepXthfCe{FtNHgY*tf%+0SQRPr0{~}$2mAm4 delta 21 dcmccepXthfCe{FtNHdm=tf%+0WE}gV3IJ;M31$EQ diff --git a/bin/THB1_v14.bin b/bin/THB1_v14.bin index 26ad6c7c307b314c3bdf2a23451be2f9e4857501..5626edee8cd416e0af35e9b285aa1f273fd2c858 100644 GIT binary patch delta 21 dcmccepXthfCe{FtNHgY*tf%+0yqGS34ghOj35oy! delta 21 dcmccepXthfCe{FtNHdm=tf%+0>{34Q1ORHh38(-7 diff --git a/bin/THB2_v14.bin b/bin/THB2_v14.bin index 915d7a2a7579af8179dd1081aedc9ea975639562..943a0b7d88b8a4b063d16259dc95f0d3637f443d 100644 GIT binary patch delta 21 dcmZ4Tg=xtbCe{FtNHgY*tkSz!c-QaW1^`=)2qXXi delta 21 ccmZ4Tg=xtbCe{FtNHdm=tkSz!`1zgO09aK9ng9R* diff --git a/bthome_phy6222/.gitignore b/bthome_phy6222/.gitignore index 2ad3804..2c69bbe 100644 --- a/bthome_phy6222/.gitignore +++ b/bthome_phy6222/.gitignore @@ -1,3 +1,5 @@ +bin +boot Listings Objects TestTHB2.asm diff --git a/bthome_phy6222/Makefile b/bthome_phy6222/Makefile index e315da9..6d0023d 100644 --- a/bthome_phy6222/Makefile +++ b/bthome_phy6222/Makefile @@ -117,11 +117,13 @@ CFLAGS += -Wl,--gc-sections ifdef BOOT_OTA LDSCRIPT ?= $(SDK_PATH)/misc/boot_ota_phy62x2.ld DEFINES += -DOTA_TYPE=OTA_TYPE_BOOT -BIN_OTA = +BIN_OTA = $(OBJ_DIR)/$(PROJECT_NAME).bin +ADD_OPT = -w 0x2F00 -f ota_upboot.add else LDSCRIPT ?= $(SDK_PATH)/misc/phy6222.ld DEFINES += -DOTA_TYPE=OTA_TYPE_NONE BIN_OTA = $(OBJ_DIR)/$(PROJECT_NAME).bin +ADD_OPT = endif LDFLAGS := $(ARCH_FLAGS) @@ -279,7 +281,7 @@ all: directory $(SRC_O) $(OBJ_DIR)/$(PROJECT_NAME).elf $(OBJ_DIR)/$(PROJECT_NAME %.bin: %.hex @echo Make: $@ - @$(PYTHON) ./phy62x2_ota.py $(OBJ_DIR)/$(PROJECT_NAME).hex + @$(PYTHON) ./phy62x2_ota.py $(ADD_OPT) $(OBJ_DIR)/$(PROJECT_NAME).hex %.asm: %.elf @echo OBJDUMP: $@ @@ -301,7 +303,7 @@ flash: @$(PYTHON) ./rdwr_phy62x2.py -p$(COM_PORT) -b 1000000 -r wh $(OBJ_DIR)/$(PROJECT_NAME).hex flash_ota: - @$(PYTHON) ./rdwr_phy62x2.py -p$(COM_PORT) -b 1000000 -r we 0x10000 $(OBJ_DIR)/$(PROJECT_NAME).bin + @$(PYTHON) ./rdwr_phy62x2.py -p$(COM_PORT) -b 1000000 -r we 0x10000 $(BIN_OTA) erase_and_flash: @$(PYTHON) ./rdwr_phy62x2.py -p$(COM_PORT) -b 1000000 -e -r wh $(OBJ_DIR)/$(PROJECT_NAME).hex diff --git a/bthome_phy6222/SDK/components/driver/flash/flash.c b/bthome_phy6222/SDK/components/driver/flash/flash.c index b3564cb..da80889 100644 --- a/bthome_phy6222/SDK/components/driver/flash/flash.c +++ b/bthome_phy6222/SDK/components/driver/flash/flash.c @@ -49,6 +49,29 @@ static xflash_Ctx_t s_xflashCtx = { .spif_ref_clk = SYS_CLK_DLL_64M, .rd_instr = XFRD_FCMD_READ_DUAL }; +/* +void spif_cmd(uint8_t op, uint8_t addrlen, uint8_t rdlen, uint8_t wrlen, uint8_t mbit, uint8_t dummy) +{ + uint32_t temp = op << 0x18; + if (addrlen != 0) { + temp = temp | 0x80000 | addrlen * 0x10000 - 0x10000; + } + if (rdlen != 0) { + temp = temp | 0x800000 | rdlen * 0x100000 - 0x100000; + } + if (wrlen != 0) { + temp = temp | 0x8000 | wrlen * 0x1000 - 0x1000; + } + if (mbit != 0) { + temp = temp | 0x40000; + } + if (dummy != 0) { + temp = temp | dummy << 7; + } + AP_SPIF->fcmd = temp | 1; + ... +} +*/ __ATTR_SECTION_SRAM__ static inline uint32_t spif_lock() { HAL_ENTER_CRITICAL_SECTION(); diff --git a/bthome_phy6222/SDK/misc/ota_app_phy62x2.ld b/bthome_phy6222/SDK/misc/ota_app_phy62x2.ld index f5bde2c..d64a7ec 100644 --- a/bthome_phy6222/SDK/misc/ota_app_phy62x2.ld +++ b/bthome_phy6222/SDK/misc/ota_app_phy62x2.ld @@ -46,18 +46,7 @@ SECTIONS *.o(_section_standby_code_) *.o(_section_sram_code_) - *patch.o(.text.*) - *patch_ext_adv.o(.text.*) - - *rf_phy_driver.o(.text.*) - *pwrmgr.o(.text .text.*) - *timer.o(.text .text.*) - - *flash.o(.text .text.*) - *clock.o(.text.*) - - *phy_sec_ext.o(.text .text.*) - + *main.o(.text.*) *libgcc.a:*.o(.text .text.*) _etextram = ABSOLUTE(.); diff --git a/bthome_phy6222/bin/BTH01_v14.bin b/bthome_phy6222/bin/BTH01_v14.bin index f81ecaaaa83a9ba4298cd8de869b6b68cb4fdace..19b6cdd057942ca69762b71e10d2a1d3c1d7228f 100644 GIT binary patch delta 21 dcmaFzh3Ux`Ce{FtNHgY*tkJtzj^-E60|01w2=)K~ delta 21 dcmaFzh3Ux`Ce{FtNHdm=tkJtzt||zg0{~}62#5dx diff --git a/bthome_phy6222/bin/TH05D_v14.bin b/bthome_phy6222/bin/TH05D_v14.bin index 8c55569fab8a84a74f9c1ab4699e155a72aa42ed..50dcdf57a795ef65a5c958819e72d226f145c5eb 100644 GIT binary patch delta 21 ccmey;!2G3wnKi&8(u{c{YxV(_U}jw{09MonumAu6 delta 21 dcmey;!2G3wnKi&8(u`#zYxV(_d-uK{003RZ33mVh diff --git a/bthome_phy6222/bin/TH05F_v14.bin b/bthome_phy6222/bin/TH05F_v14.bin index 894469c2a6688cc162c9a5b27d9606470dae6c71..5545ce2314f08f426445787c6a3fecc6482f9d5c 100644 GIT binary patch delta 21 ccmcc8ztxZDIb}08`!vDF6Tf delta 21 ccmcc8ztx8i(9_08_08s{jB1 diff --git a/bthome_phy6222/bin/TH05_v14.bin b/bthome_phy6222/bin/TH05_v14.bin index 5f61923e45f014a356c521708f4af03ff01b4c5c..b7f96ee4310f811a2d6307aca2ee453e56c40a49 100644 GIT binary patch delta 21 dcmccepXthfCe{FtNHgY*tf%+0SQRPr0{~}$2mAm4 delta 21 dcmccepXthfCe{FtNHdm=tf%+0WE}gV3IJ;M31$EQ diff --git a/bthome_phy6222/bin/THB1_v14.bin b/bthome_phy6222/bin/THB1_v14.bin index 26ad6c7c307b314c3bdf2a23451be2f9e4857501..5626edee8cd416e0af35e9b285aa1f273fd2c858 100644 GIT binary patch delta 21 dcmccepXthfCe{FtNHgY*tf%+0yqGS34ghOj35oy! delta 21 dcmccepXthfCe{FtNHdm=tf%+0>{34Q1ORHh38(-7 diff --git a/bthome_phy6222/bin/THB2_v14.bin b/bthome_phy6222/bin/THB2_v14.bin index 915d7a2a7579af8179dd1081aedc9ea975639562..943a0b7d88b8a4b063d16259dc95f0d3637f443d 100644 GIT binary patch delta 21 dcmZ4Tg=xtbCe{FtNHgY*tkSz!c-QaW1^`=)2qXXi delta 21 ccmZ4Tg=xtbCe{FtNHdm=tkSz!`1zgO09aK9ng9R* diff --git a/bthome_phy6222/mk_windows.cmd b/bthome_phy6222/mk_windows.cmd index e4c68a7..926ac78 100644 --- a/bthome_phy6222/mk_windows.cmd +++ b/bthome_phy6222/mk_windows.cmd @@ -3,6 +3,7 @@ @del /Q "build\THB2%SWVER%.hex" @del /Q "build\THB2%SWVER%.bin" @mkdir .\bin +@mkdir .\boot @make -s clean @make -s -j PROJECT_NAME=THB2%SWVER% POJECT_DEF="-DDEVICE=DEVICE_THB2" @if not exist "build\THB2%SWVER%.hex" goto :error @@ -48,36 +49,42 @@ @make -s -j PROJECT_NAME=BOOT_THB2%SWVER% BOOT_OTA=1 POJECT_DEF="-DDEVICE=DEVICE_THB2" @if not exist "build\BOOT_THB2%SWVER%.hex" goto :error @copy "build\BOOT_THB2%SWVER%.hex" .\bin +@copy "build\BOOT_THB2%SWVER%.bin" .\boot @ @del /Q "build\BOOT_BTH01%SWVER%.hex" @make -s clean @make -s -j PROJECT_NAME=BOOT_BTH01%SWVER% BOOT_OTA=1 POJECT_DEF="-DDEVICE=DEVICE_BTH01" @if not exist "build\BOOT_BTH01%SWVER%.hex" goto :error @copy "build\BOOT_BTH01%SWVER%.hex" .\bin +@copy "build\BOOT_BTH01%SWVER%.bin" .\boot @ @del /Q "build\BOOT_TH05%SWVER%.hex" @make -s clean @make -s -j PROJECT_NAME=BOOT_TH05%SWVER% BOOT_OTA=1 POJECT_DEF="-DDEVICE=DEVICE_TH05" @if not exist "build\BOOT_TH05%SWVER%.hex" goto :error @copy "build\BOOT_TH05%SWVER%.hex" .\bin +@copy "build\BOOT_TH05%SWVER%.bin" .\boot @ @del /Q "build\BOOT_TH05D%SWVER%.hex" @make -s clean @make -s -j PROJECT_NAME=BOOT_TH05D%SWVER% BOOT_OTA=1 POJECT_DEF="-DDEVICE=DEVICE_TH05D" @if not exist "build\BOOT_TH05D%SWVER%.hex" goto :error @copy "build\BOOT_TH05D%SWVER%.hex" .\bin +@copy "build\BOOT_TH05D%SWVER%.bin" .\boot @ @del /Q "build\BOOT_TH05F%SWVER%.hex" @make -s clean @make -s -j PROJECT_NAME=BOOT_TH05F%SWVER% BOOT_OTA=1 POJECT_DEF="-DDEVICE=DEVICE_TH05F" @if not exist "build\BOOT_TH05F%SWVER%.hex" goto :error @copy "build\BOOT_TH05F%SWVER%.hex" .\bin +@copy "build\BOOT_TH05F%SWVER%.bin" .\boot @ @del /Q "build\BOOT_THB1%SWVER%.hex" @make -s clean @make -s -j PROJECT_NAME=BOOT_THB1%SWVER% BOOT_OTA=1 POJECT_DEF="-DDEVICE=DEVICE_THB1" @if not exist "build\BOOT_THB1%SWVER%.hex" goto :error @copy "build\BOOT_THB1%SWVER%.hex" .\bin +@copy "build\BOOT_THB1%SWVER%.bin" .\boot @exit :error @echo "Error!" \ No newline at end of file diff --git a/bthome_phy6222/ota_upboot.add b/bthome_phy6222/ota_upboot.add new file mode 100644 index 0000000000000000000000000000000000000000..ce77bf45c58f82010e5cbf3cdc1fa45b1d097c37 GIT binary patch literal 740 zcmWIWh%{qlU|_J2_%Hu}iGhKEk&)pBBZPmA>ul)%VGa!B|I0f{{Fi6)Z2Zj8!SG@3 z4+aL1n6)?a+Pcs@+l>AZ{7<7d%Dta({ z=>DPTC7i)%ESwOkB<~%SEbkp?C6&OSEaxSh(4cgQH8|nl^Z&XGH*^?`S(z>xFfe>5 z`XS-31Tu97!-tq31`J^K2lpQgv&|%>B^f5`N?&+>!0itMqo9KHe|b=PU{GKXRFVEK zuOa>Jc9v)AOi!VU-R4hKFkI2`%F;2HqQ|JziY@ z<*gYQIT*Jvd9=7O?n!WG*gv(HkpY>%osR*9pIV42e>4}BzcQbZ0hVlyKD}K80CEC_ A6951J literal 0 HcmV?d00001 diff --git a/bthome_phy6222/phy62x2_ota.py b/bthome_phy6222/phy62x2_ota.py index d40f6f8..baf4c4c 100644 --- a/bthome_phy6222/phy62x2_ota.py +++ b/bthome_phy6222/phy62x2_ota.py @@ -23,7 +23,7 @@ PHY_WR_BLK_SIZE = 0x2000 __progname__ = 'PHY62x2 OTA Utility' __filename__ = 'phy62x2_ota.py' -__version__ = "23.01.24" +__version__ = "25.02.24" def do_crc(s, c): return zlib.crc32(s, c) & 0xffffffff @@ -84,10 +84,11 @@ class phy_ota: size = 0x100 sections = 15 wfaddr = (wrfaddr & (MAX_FLASH_SIZE-1)) + size + wrfaddr = wfaddr; faddr_min = MAX_FLASH_SIZE-1 # xip addr min faddr_max = 0 # xip addr max rsize = 0 # size ram data - hexf = bytearray(struct.pack(' 4096) or (fbuplen <= 256): + print('Error: Boot update file %s format!' % args.fbup) + exit(2) + datafbup = bytearray(datafbup[0:-4]) + phy = phy_ota() hp = phy.ParseHexFile(args.filename, args.wraddr) if hp == None: - sys.exit(2) + sys.exit(3) hexf = phy.HexfHeader(hp, args.runaddr, args.wraddr, args.idota) if hexf == None: - sys.exit(2) + sys.exit(4) hp[0][1] = hexf print ('---- File Structure -------------------------------------') @@ -182,15 +205,19 @@ def main(): fout = open(outfile, 'wb') except: print('No file opened', outfile) - sys.exit(3) + sys.exit(5) fsize = 0 for ihp in hp: fsize += len(ihp[1]) - fillsize = 16 - fsize % 16 - fsize += fillsize segment = 0 crc = 0 try: + if args.fbup != None: + #print('size: %08x , %08x' % (fsize, fbuplen)) + datafbup[12:16] = int.to_bytes(fsize + fbuplen, 4, byteorder='little') + datafbup[0xfc:0x100] = int.to_bytes((fbuplen + DEF_START_WR_FLASH_ADDR) | 0x11000000, 4, byteorder='little') + crc = do_crc(datafbup, crc) + fout.write(datafbup) for ihp in hp: if ihp[0] == 0: print('Segment Table[%02d] <- Flash addr: %08x, Size: %08x' % (len(hp) - 1, ihp[2], len(ihp[1]))) @@ -204,9 +231,9 @@ def main(): fout.write(bytearray(struct.pack(' 1: hexf = bytearray(b'\xff')*(0x100) - hexf[0:4] = int.to_bytes(len(hp), 4, byteorder='little') + hexf[0:4] = int.to_bytes(len(hp)-1, 4, byteorder='little') hexf[8:12] = int.to_bytes(start, 4, byteorder='little') #sections = 0 faddr_min = MAX_FLASH_SIZE-1 @@ -592,8 +592,6 @@ def main(): print ('Error Flash read Unique ID!') sys.exit(3) print ('Flash Serial Number:', rb.hex()) # Unique ID - - exit(0) if args.operation == 'rc': #filename = "r%08x-%08x.bin" % (addr, length) if args.size == 0: diff --git a/ota_boot/.autotools b/ota_boot/.autotools new file mode 100644 index 0000000..e73513b --- /dev/null +++ b/ota_boot/.autotools @@ -0,0 +1,43 @@ + + + + + diff --git a/ota_boot/.cproject b/ota_boot/.cproject new file mode 100644 index 0000000..043116b --- /dev/null +++ b/ota_boot/.cproject @@ -0,0 +1,346 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${cross_make} + -j24 + all + true + true + true + + + ${cross_make} + -j24 + clean + true + true + true + + + ${cross_make} + -j24 + flash + true + true + true + + + ${cross_make} + -j24 + erase_and_flash + true + true + true + + + ${cross_make} + -j24 + reset + true + true + true + + + ${cross_make} + -j24 + flash_ota + true + true + true + + + + \ No newline at end of file diff --git a/ota_boot/.gitignore b/ota_boot/.gitignore new file mode 100644 index 0000000..a3bb0a0 --- /dev/null +++ b/ota_boot/.gitignore @@ -0,0 +1,7 @@ +bin +Listings +Objects +TestTHB2.asm +TestTHB2.uvguix.* +TestTHB2.uvoptx +build diff --git a/ota_boot/.project b/ota_boot/.project new file mode 100644 index 0000000..8ce4333 --- /dev/null +++ b/ota_boot/.project @@ -0,0 +1,34 @@ + + + ota_boot + + + + + + org.python.pydev.PyDevBuilder + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.autotools.core.autotoolsNatureV2 + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + org.eclipse.cdt.core.ccnature + org.python.pydev.pythonNature + + diff --git a/ota_boot/.pydevproject b/ota_boot/.pydevproject new file mode 100644 index 0000000..2b04565 --- /dev/null +++ b/ota_boot/.pydevproject @@ -0,0 +1,5 @@ + + + Default + python interpreter + diff --git a/ota_boot/.settings/language.settings.xml b/ota_boot/.settings/language.settings.xml new file mode 100644 index 0000000..84095c5 --- /dev/null +++ b/ota_boot/.settings/language.settings.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ota_boot/.settings/org.eclipse.cdt.codan.core.prefs b/ota_boot/.settings/org.eclipse.cdt.codan.core.prefs new file mode 100644 index 0000000..da30759 --- /dev/null +++ b/ota_boot/.settings/org.eclipse.cdt.codan.core.prefs @@ -0,0 +1,109 @@ +eclipse.preferences.version=1 +org.eclipse.cdt.codan.checkers.errnoreturn=Warning +org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return\\")",implicit\=>false} +org.eclipse.cdt.codan.checkers.errreturnvalue=Error +org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused return value\\")"} +org.eclipse.cdt.codan.checkers.localvarreturn=-Warning +org.eclipse.cdt.codan.checkers.localvarreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Returning the address of a local variable\\")"} +org.eclipse.cdt.codan.checkers.nocommentinside=-Error +org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Nesting comments\\")"} +org.eclipse.cdt.codan.checkers.nolinecomment=-Error +org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Line comments\\")"} +org.eclipse.cdt.codan.checkers.noreturn=Error +org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return value\\")",implicit\=>false} +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Abstract class cannot be instantiated\\")"} +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Ambiguous problem\\")"} +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment in condition\\")"} +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"} +org.eclipse.cdt.codan.internal.checkers.BlacklistProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.BlacklistProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function or method is blacklisted\\")",blacklist\=>()} +org.eclipse.cdt.codan.internal.checkers.CStyleCastProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.CStyleCastProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"C-Style cast instead of C++ cast\\")",checkMacro\=>true} +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false,enable_fallthrough_quickfix_param\=>false} +org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning +org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Catching by reference is recommended\\")",unknown\=>false,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Circular inheritance\\")"} +org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning +org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class members should be properly initialized\\")",skip\=>true} +org.eclipse.cdt.codan.internal.checkers.CopyrightProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.CopyrightProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Lack of copyright information\\")",regex\=>".*Copyright.*"} +org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem=Error +org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid 'decltype(auto)' specifier\\")"} +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Field cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.FloatCompareProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.FloatCompareProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Direct float comparison\\")"} +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.GotoStatementProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.GotoStatementProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Goto statement used\\")"} +org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error +org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid arguments\\")"} +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid template argument\\")"} +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Label statement not found\\")"} +org.eclipse.cdt.codan.internal.checkers.MagicNumberProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.MagicNumberProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Avoid magic numbers\\")",checkArray\=>true,checkOperatorParen\=>true,exceptions\=>(1,0,-1,2,1.0,0.0,-1.0)} +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Member declaration not found\\")"} +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Method cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.MissCaseProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.MissCaseProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing cases in switch\\")"} +org.eclipse.cdt.codan.internal.checkers.MissDefaultProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.MissDefaultProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing default in switch\\")",defaultWithAllEnums\=>false} +org.eclipse.cdt.codan.internal.checkers.MissReferenceProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.MissReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing reference return value in assignment operator\\")"} +org.eclipse.cdt.codan.internal.checkers.MissSelfCheckProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.MissSelfCheckProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing self check in assignment operator\\")"} +org.eclipse.cdt.codan.internal.checkers.MultipleDeclarationsProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.MultipleDeclarationsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Multiple variable declaration\\")"} +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Name convention for function\\")",pattern\=>"^[a-z]",macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.NoDiscardProblem=Warning +org.eclipse.cdt.codan.internal.checkers.NoDiscardProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Return value not evaluated\\")",macro\=>true} +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class has a virtual method and non-virtual destructor\\")"} +org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error +org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid overload\\")"} +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redeclaration\\")"} +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redefinition\\")"} +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Return with parenthesis\\")"} +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Format String Vulnerability\\")"} +org.eclipse.cdt.codan.internal.checkers.ShallowCopyProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ShallowCopyProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Miss copy constructor or assignment operator\\")",onlynew\=>false} +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Statement has no effect\\")",macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.StaticVariableInHeaderProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.StaticVariableInHeaderProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Static variable in header file\\")"} +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suggested parenthesis around expression\\")",paramNot\=>false} +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false} +org.eclipse.cdt.codan.internal.checkers.SymbolShadowingProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.SymbolShadowingProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol shadowing\\")",paramFuncParameters\=>true} +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused function declaration\\")",macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused static function\\")",macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused variable declaration in file scope\\")",macro\=>true,exceptions\=>("@(\#)","$Id")} +org.eclipse.cdt.codan.internal.checkers.UsingInHeaderProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.UsingInHeaderProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Using directive in header\\")"} +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol is not resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.VirtualMethodCallProblem=-Error +org.eclipse.cdt.codan.internal.checkers.VirtualMethodCallProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Virtual method call in constructor/destructor\\")"} diff --git a/ota_boot/.settings/org.eclipse.cdt.core.prefs b/ota_boot/.settings/org.eclipse.cdt.core.prefs new file mode 100644 index 0000000..c8ec5df --- /dev/null +++ b/ota_boot/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,6 @@ +doxygen/doxygen_new_line_after_brief=true +doxygen/doxygen_use_brief_tag=false +doxygen/doxygen_use_javadoc_tags=true +doxygen/doxygen_use_pre_tag=false +doxygen/doxygen_use_structural_commands=false +eclipse.preferences.version=1 diff --git a/ota_boot/.settings/org.eclipse.cdt.managedbuilder.core.prefs b/ota_boot/.settings/org.eclipse.cdt.managedbuilder.core.prefs new file mode 100644 index 0000000..4cabf0c --- /dev/null +++ b/ota_boot/.settings/org.eclipse.cdt.managedbuilder.core.prefs @@ -0,0 +1,13 @@ +eclipse.preferences.version=1 +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.toolchain.base.28719871/CPATH/delimiter=; +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.toolchain.base.28719871/CPATH/operation=remove +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.toolchain.base.28719871/CPLUS_INCLUDE_PATH/delimiter=; +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.toolchain.base.28719871/CPLUS_INCLUDE_PATH/operation=remove +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.toolchain.base.28719871/C_INCLUDE_PATH/delimiter=; +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.toolchain.base.28719871/C_INCLUDE_PATH/operation=remove +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.toolchain.base.28719871/append=true +environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.toolchain.base.28719871/appendContributed=true +environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.toolchain.base.28719871/LIBRARY_PATH/delimiter=; +environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.toolchain.base.28719871/LIBRARY_PATH/operation=remove +environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.toolchain.base.28719871/append=true +environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.toolchain.base.28719871/appendContributed=true diff --git a/ota_boot/.settings/org.eclipse.core.resources.prefs b/ota_boot/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..99f26c0 --- /dev/null +++ b/ota_boot/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/ota_boot/.settings/org.eclipse.embedcdt.managedbuild.cross.arm.core.prefs b/ota_boot/.settings/org.eclipse.embedcdt.managedbuild.cross.arm.core.prefs new file mode 100644 index 0000000..2f7e5c4 --- /dev/null +++ b/ota_boot/.settings/org.eclipse.embedcdt.managedbuild.cross.arm.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +toolchain.path.1287942917=D\:\\MCU\\GNU_Tools_ARM_Embedded\\13.2.rel1\\bin diff --git a/ota_boot/Makefile b/ota_boot/Makefile new file mode 100644 index 0000000..63c11a2 --- /dev/null +++ b/ota_boot/Makefile @@ -0,0 +1,138 @@ +############################################################################## +PROJECT_NAME ?= ota_upboot +#POJECT_DEF ?= -DDEVICE=DEVICE_THB2 +############################################################################## +COM_PORT = COM11 +############################################################################## +# Source +SRC_PATH = ./source +SRC_PRJ = main.c + +INCLUDES = -I$(SRC_PATH) +INCLUDES += -I$(SRC_PATH)/include +INCLUDES += -I$(SRC_PATH)/misc +INCLUDES += -I$(SRC_PATH)/misc/CMSIS/include +INCLUDES += -I$(SRC_PATH)/misc/CMSIS/device/phyplus + +STARTUP_ASM = $(SRC_PATH)/misc/CMSIS/device/phyplus/phy6222_start.s + +SRCS = $(addprefix $(SRC_PATH)/, $(SRC_PRJ)) +SRCS += $(SRC_PATH)/misc/CMSIS/device/phyplus/phy6222_vectors.c + +############################################################################## +DEFINES += -D__GCC +DEFINES += $(POJECT_DEF) +DEFINES += -DPHY_MCU_TYPE=MCU_BUMBEE_M0 + +############################################################################## +BIN_DIR = ./bin +OBJ_DIR = ./build +PYTHON = python3 +GCC_PATH = +CC = $(GCC_PATH)arm-none-eabi-gcc +OBJCOPY = $(GCC_PATH)arm-none-eabi-objcopy +OBJDUMP = $(GCC_PATH)arm-none-eabi-objdump +SIZE = $(GCC_PATH)arm-none-eabi-size +READELF = $(GCC_PATH)arm-none-eabi-readelf +############################################################################## +ARCH_FLAGS := -mcpu=cortex-m0 -mthumb -mthumb-interwork +OPT_CFLAGS ?= -Os +DEB_CFLAGS ?= -g3 -ggdb +############################################################################## +ASFLAGS := $(ARCH_FLAGS) $(OPT_CFLAGS) $(DEB_CFLAGS) +CFLAGS := $(ARCH_FLAGS) $(OPT_CFLAGS) $(DEB_CFLAGS) +CFLAGS += -W -Wall --std=gnu99 +CFLAGS += -fno-diagnostics-show-caret +CFLAGS += -fdata-sections -ffunction-sections +CFLAGS += -funsigned-char -funsigned-bitfields +#CFLAGS += -fpack-struct +#CFLAGS += -mno-unaligned-access +#CFLAGS += -munaligned-access +CFLAGS += -fms-extensions +CFLAGS += -specs=nosys.specs +CFLAGS += -Wl,--gc-sections + +LDSCRIPT ?= $(SRC_PATH)/misc/ota_upboot.ld +#BIN_OTA = $(OBJ_DIR)/$(PROJECT_NAME).bin +BIN_OTA = ./$(PROJECT_NAME).add + +LDFLAGS := $(ARCH_FLAGS) +LDFLAGS += --static -nostartfiles -nostdlib +LDFLAGS += -Wl,--gc-sections +LDFLAGS += -Wl,--script=$(LDSCRIPT) +LDFLAGS += -Wl,--just-symbols=$(SRC_PATH)/misc/bb_rom_sym_m0.gcc +LDFLAGS += -Wl,-Map=$(OBJ_DIR)/$(PROJECT_NAME).map +LIBS += -Wl,--start-group -lgcc -lnosys -Wl,--end-group + +############################################################################## + +CFLAGS += $(DEFINES) $(INCLUDES) + +#SRC_O = $(patsubst %.c,%.o,$(patsubst sdk/%, $(SRC_PATH)%, $(SRCS))) + +SRC_O = $(SRCS:%.c=%.o) $(STARTUP_ASM:%.s=%.o) +OBJS = $(patsubst %, $(OBJ_DIR)/%, $(patsubst ./%, %, $(SRC_O))) + +DEPENDENCY_LIST = $(OBJS:%o=%d) + +############################################################################## +.PHONY: all directory clean size flash erase_and_flash + +all: directory $(SRC_O) $(OBJ_DIR)/$(PROJECT_NAME).elf $(OBJ_DIR)/$(PROJECT_NAME).hex $(BIN_OTA) $(OBJ_DIR)/$(PROJECT_NAME).asm size + +%.elf %.map: $(SRC_O) $(LDSCRIPT) Makefile + @echo LD: $@ + @$(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ + +%.hex: %.elf + @echo OBJCOPY: $@ + @$(OBJCOPY) -O ihex $^ $@ + +%.add: %.hex + @echo Make: $@ + $(PYTHON) ./phy62x2_ota.py -o $(BIN_OTA) $(OBJ_DIR)/$(PROJECT_NAME).hex + +%.asm: %.elf + @echo OBJDUMP: $@ + @$(OBJDUMP) -s -S $^ >$@ + +%.o : %.c + @echo CC: $< + @mkdir -p $(OBJ_DIR)/$(dir $@) + @$(CC) $(CFLAGS) $(INCFLAGS) -c $< -o $(OBJ_DIR)/$@ + @$(CC) -MM $(CFLAGS) $(INCFLAGS) $< -MT $@ -MF $(OBJ_DIR)/$(patsubst %.o,%.d,$@) + +%.o : %.s + @echo CC: $< + @mkdir -p $(OBJ_DIR)/$(dir $@) + @$(CC) $(CFLAGS) $(INCFLAGS) -c $< -o $(OBJ_DIR)/$@ + @$(CC) -MM $(CFLAGS) $(INCFLAGS) $< -MT $@ -MF $(OBJ_DIR)/$(patsubst %.o,%.d,$@) + +flash: + @$(PYTHON) ./rdwr_phy62x2.py -p$(COM_PORT) -b 1000000 -r wh $(OBJ_DIR)/$(PROJECT_NAME).hex + +flash_ota: + @$(PYTHON) ./rdwr_phy62x2.py -p$(COM_PORT) -b 1000000 -r we 0x10000 $(BIN_OTA) + +erase_and_flash: + @$(PYTHON) ./rdwr_phy62x2.py -p$(COM_PORT) -b 1000000 -e -r wh $(OBJ_DIR)/$(PROJECT_NAME).hex + +reset: + @$(PYTHON) ./rdwr_phy62x2.py -p$(COM_PORT) -r i + +directory: + @mkdir -p $(OBJ_DIR) + +size: $(OBJ_DIR)/$(PROJECT_NAME).elf + @echo size: + @$(SIZE) -t $^ + @$(READELF) -l $^ + @echo + +clean: + @echo clean + @-rm -rf $(OBJ_DIR) + +-include $(DEPENDENCY_LIST) + +VPATH:=$(OBJ_DIR) diff --git a/ota_boot/ota_upboot.add b/ota_boot/ota_upboot.add new file mode 100644 index 0000000000000000000000000000000000000000..ce77bf45c58f82010e5cbf3cdc1fa45b1d097c37 GIT binary patch literal 740 zcmWIWh%{qlU|_J2_%Hu}iGhKEk&)pBBZPmA>ul)%VGa!B|I0f{{Fi6)Z2Zj8!SG@3 z4+aL1n6)?a+Pcs@+l>AZ{7<7d%Dta({ z=>DPTC7i)%ESwOkB<~%SEbkp?C6&OSEaxSh(4cgQH8|nl^Z&XGH*^?`S(z>xFfe>5 z`XS-31Tu97!-tq31`J^K2lpQgv&|%>B^f5`N?&+>!0itMqo9KHe|b=PU{GKXRFVEK zuOa>Jc9v)AOi!VU-R4hKFkI2`%F;2HqQ|JziY@ z<*gYQIT*Jvd9=7O?n!WG*gv(HkpY>%osR*9pIV42e>4}BzcQbZ0hVlyKD}K80CEC_ A6951J literal 0 HcmV?d00001 diff --git a/ota_boot/phy62x2_ota.py b/ota_boot/phy62x2_ota.py new file mode 100644 index 0000000..baf4c4c --- /dev/null +++ b/ota_boot/phy62x2_ota.py @@ -0,0 +1,242 @@ +#!/usr/bin/env python3 + +# phy62x2_ota.py 22.01.2024 pvvx # + +import argparse +import io +import os +import struct +import sys +import zlib + +START_UP_FLAG = 0x36594850 #"PHY6" + +MAX_FLASH_SIZE = 0x200000 +EXT_FLASH_ADD = 0x400000 + +DEF_START_RUN_APP_ADDR = 0x1FFF1838 +DEF_START_WR_FLASH_ADDR = 0x010000 + +PHY_FLASH_SECTOR_SIZE = 4096 +PHY_FLASH_SECTOR_MASK = 0xfffff000 +PHY_WR_BLK_SIZE = 0x2000 + +__progname__ = 'PHY62x2 OTA Utility' +__filename__ = 'phy62x2_ota.py' +__version__ = "25.02.24" + +def do_crc(s, c): + return zlib.crc32(s, c) & 0xffffffff + +class phy_ota: + def ParseHexFile(self, hexfile, faddr = DEF_START_WR_FLASH_ADDR): + try: + fin = open(hexfile) + except: + print('No file opened', hexfile) + return None + table = [] + result = bytearray() + addr = 0 + naddr = 0 + taddr = 0 + addr_flg = 0 + table.append([0, result, faddr]) + for hexstr in fin.readlines(): + hexstr = hexstr.strip() + if hexstr[7:9] == '04': + if(len(result)): + #print(hex(addr)) + table.append([addr, result, 0]) + addr = int(hexstr[9:13],16) << 16 + addr_flg = 0 + result = bytearray() + continue + if hexstr[7:9] == '05' or hexstr[7:9] == '01': + table.append([addr, result, 0]) + break + taddr = (int(hexstr[3:7],16)) + if addr_flg == 0: + addr_flg = 1 + addr = addr | taddr + naddr = taddr + if taddr != naddr: + addr_flg = 1 + table.append([addr, result, 0]) + addr = (addr & 0xFFFF0000) | taddr + result = bytearray() + #print(hexstr[9:-3]) + result.extend(bytearray.fromhex(hexstr[9:-2])) + naddr = taddr + int(hexstr[1:3],16) + fin.close() + return table + def WriteHexf(self, sn, ph): + offset = ph[2] + offset &= 0x00ffffff + idx = 0 + size = len(ph[1]) + return True + def HexfHeader(self, hp, start = DEF_START_RUN_APP_ADDR, wrfaddr = DEF_START_WR_FLASH_ADDR, otaid = START_UP_FLAG): + if len(hp) > 1: + if len(hp) > 15: + print('Maximum number of segments = 15!') + return None + size = 0x100 + sections = 15 + wfaddr = (wrfaddr & (MAX_FLASH_SIZE-1)) + size + wrfaddr = wfaddr; + faddr_min = MAX_FLASH_SIZE-1 # xip addr min + faddr_max = 0 # xip addr max + rsize = 0 # size ram data + hexf = bytearray(struct.pack(' offset: + faddr_min = offset + send = offset + len(ihp[1]) + if faddr_max <= send: + faddr_max = send + if (wrfaddr + rsize) >= faddr_min: + wrfaddr = (faddr_max + 3) & 0xfffffffc # start wr faddr ram data + #print('Test: Flash addr min: %08x, max: %08x, RAM addr: %08x' % (faddr_min, faddr_max, wrfaddr)) + print ('---- Segments Table -------------------------------------') + + for ihp in hp: + if (ihp[0] & 0x1fff0000) == 0x1fff0000: # SRAM + faddr = wrfaddr # wr faddr ram data + wrfaddr += (len(ihp[1])+3) & 0xfffffffc # next wr faddr ram data + elif (ihp[0] & (~(MAX_FLASH_SIZE-1))) == 0x11000000: # Flash + faddr = ihp[0] & (MAX_FLASH_SIZE-1) + if wfaddr != faddr: + print('Error: The segment Flash addr: 0x%08x, Size: 0x%08x does not match the markup (0x%08x)!' % (ihp[0], len(ihp[1]), wfaddr)) + return None + elif ihp[0] == 0: + continue + else: + print('Error: Invalid Segment Address 0x%08x!' % ihp[0]) + return None + ihp[2] = faddr + sections -= 1 + print('Segment: %08x <- Flash addr: %08x, Size: %08x' % (ihp[0], faddr, len(ihp[1]))) + crc = 0xffffffff - do_crc(ihp[1], 0) + hexf.extend(bytearray(struct.pack(' 0: + hexf.extend(bytearray(b'\xff')*(0x10*sections)) + fill = size % 16 + if fill != 0: + hp[len(hp)-1][1].extend(bytearray(b'\xff')*(16 - fill)) + size += 16 - fill + hexf[12:16] = int.to_bytes(size, 4, byteorder='little') + return hexf + return None + +class FatalError(RuntimeError): + def __init__(self, message): + RuntimeError.__init__(self, message) + + @staticmethod + def WithResult(message, result): + message += " (result was %s)" % hexify(result) + return FatalError(message) + +def arg_auto_int(x): + return int(x, 0) + +def main(): + parser = argparse.ArgumentParser(description='%s version %s' % (__progname__, __version__), prog = __filename__) + parser.add_argument('--idota', '-i', help = 'Flag ID OTA (default: 0x%08x)' % START_UP_FLAG, type = arg_auto_int, default = START_UP_FLAG); + parser.add_argument('--runaddr', '-r', help = 'Application run-start address (default: 0x%08x)' % DEF_START_RUN_APP_ADDR, type = arg_auto_int, default = DEF_START_RUN_APP_ADDR); + parser.add_argument('--wraddr', '-w', help = 'Application write address (default: 0x%08x)' % DEF_START_WR_FLASH_ADDR, type = arg_auto_int, default = DEF_START_WR_FLASH_ADDR); + parser.add_argument('--fbup', '-f', help = 'Boot update file (default: none)', default = None); + parser.add_argument('--outfile', '-o', help = 'Output bin file') + parser.add_argument('filename', help = 'Name of hex file') + + args = parser.parse_args() + + print('=========================================================') + print('%s version %s' % (__progname__, __version__)) + print('---------------------------------------------------------') + + if args.fbup != None: + try: + fbup = open(args.fbup, 'rb') + except Exception as e: + print('Error: Open file %s, %s' % (args.fbup, e)) + exit(1) + try: + datafbup = fbup.read(); + except Exception as e: + print('Error: Read file %s,: %s' % (args.fbup, e)) + exit(1) + fbup.close() + fbupid = int.from_bytes(datafbup[0:4], byteorder='little') + fbuplen = int.from_bytes(datafbup[12:16], byteorder='little') + print("Boot update file id: %08x:%08x" %(fbupid, fbuplen)) + if (fbupid != START_UP_FLAG) or ((fbuplen + 4) != len(datafbup)) or (fbuplen > 4096) or (fbuplen <= 256): + print('Error: Boot update file %s format!' % args.fbup) + exit(2) + datafbup = bytearray(datafbup[0:-4]) + + phy = phy_ota() + + hp = phy.ParseHexFile(args.filename, args.wraddr) + + if hp == None: + sys.exit(3) + hexf = phy.HexfHeader(hp, args.runaddr, args.wraddr, args.idota) + if hexf == None: + sys.exit(4) + hp[0][1] = hexf + + print ('---- File Structure -------------------------------------') + (outfile, ext) = os.path.splitext(args.filename) + outfile += '.bin' + if args.outfile != None: + outfile = args.outfile + try: + fout = open(outfile, 'wb') + except: + print('No file opened', outfile) + sys.exit(5) + fsize = 0 + for ihp in hp: + fsize += len(ihp[1]) + segment = 0 + crc = 0 + try: + if args.fbup != None: + #print('size: %08x , %08x' % (fsize, fbuplen)) + datafbup[12:16] = int.to_bytes(fsize + fbuplen, 4, byteorder='little') + datafbup[0xfc:0x100] = int.to_bytes((fbuplen + DEF_START_WR_FLASH_ADDR) | 0x11000000, 4, byteorder='little') + crc = do_crc(datafbup, crc) + fout.write(datafbup) + for ihp in hp: + if ihp[0] == 0: + print('Segment Table[%02d] <- Flash addr: %08x, Size: %08x' % (len(hp) - 1, ihp[2], len(ihp[1]))) + else: + print('Segment: %08x <- Flash addr: %08x, Size: %08x' % (ihp[0], ihp[2], len(ihp[1]))) + fout.write(ihp[1]) + crc = do_crc(ihp[1], crc) + segment += 1 + crc = 0xffffffff - crc + #print('CRC32: %04x' % crc) + fout.write(bytearray(struct.pack('>:' + def SendResetCmd(self): + return self._port.write(str.encode('reset ')); + def read_reg(self, addr): + pkt = 'rdreg%08x' % addr; + sent = self._port.write(pkt.encode()); + read = self._port.read(17); + if len(read) == 17 and read[0:3] == b'=0x' and read[11:17] == b'#OK>>:': + return int(read[1:11], 16) + return None + def write_reg(self, addr, data): + return self.write_cmd('wrreg%08x %08x ' % (addr, data)) + def ExpFlashSize(self): + if not self.write_reg(0x1fff0898, EXT_FLASH_ADD): + print('Error set ext.Flash size %08x!' % EXT_FLASH_ADD) + return False + return True + def wr_flash_cmd(self, cmd, data = 0, wrlen = 0, addr = 0, addrlen = 0, rdlen = 0, mbit = 0, dummy = 0): + regcmd = cmd << 24 + if wrlen > 0: + regcmd = regcmd | 0x8000 | ((wrlen - 1) << 12) + if not self.write_reg(0x4000c8a8, data): #Flash Command Write Data Register + print('Error write Flash Data Register!') + return False + if addrlen > 0: + regcmd = regcmd | 0x80000 | ((addrlen - 1) << 16) + if not self.write_reg(0x4000c894, addr): #Flash Command Write Addr Register + print('Error write Flash Address Register!') + return False + if rdlen > 0: + regcmd = regcmd | 0x800000 | ((rdlen - 1) << 20) + if mbit > 0: + regcmd = regcmd | 0x40000 + if dummy > 0: + regcmd = regcmd | (dummy << 7); + if not self.write_reg(0x4000c890, regcmd | 1): + print('Error write Flash Command Register!') + return False + return True + def flash_wait_idle(self): + i = 5; + while i > 0: + r = self.read_reg(0x4000c890) + if r == None: + return False + if (r & 2) == 0: + i = 5 + while i > 0: + r = self.read_reg(0x4000c800) + if r == None: + return False + if (r & 0x80000000) != 0: + return True + i -= 1 + return False + i -= 1 + return False + def flash_read_unique_id(self): + if self.wr_flash_cmd(0x4B,0,0,0,4,8): # and self.flash_wait_idle(): + r1 = self.read_reg(0x4000c8a0) + if r1 == None: + return None + r2 = self.read_reg(0x4000c8a4) + if r2 == None: + return None + ret = bytearray(8) + ret[0] = r1 & 0xff + ret[1] = (r1 >> 8) & 0xff + ret[2] = (r1 >> 16) & 0xff + ret[3] = (r1 >> 24) & 0xff + ret[4] = r2 & 0xff + ret[5] = (r2 >> 8) & 0xff + ret[6] = (r2 >> 16) & 0xff + ret[7] = (r2 >> 24) & 0xff + return ret + return None + def flash_read_status(self): + #Flash cmd: Read status + if self.wr_flash_cmd(5,0,0,0,0,1): # and self.flash_wait_idle(): + r = self.read_reg(0x4000c8a0) + if r == None: + return None + return r & 0x0ff + return None + def FlashUnlock(self): + #Flash cmd: Write Enable, Write Status Register 0x00 + return self.wr_flash_cmd(6) and self.wr_flash_cmd(1, 0, 1) + def ReadRevision(self): + #0x001364c8 6222M005 #OK>>: + self._port.write(str.encode('rdrev+ ')); + self._port.timeout = 0.1 + read = self._port.read(26); + if len(read) == 26 and read[0:2] == b'0x' and read[20:26] == b'#OK>>:': + print('Revision:', read[2:19]) + if read[11:15] != b'6222': + print('Wrong Version!') + self.flash_id = int(read[2:11], 16) + self.flash_size = 1 << ((self.flash_id >> 16) & 0xff) + print('FlashID: %06x, size: %d kbytes' % (self.flash_id, self.flash_size >> 10)) + return True + else: + print('Error read Revision!') + return False + def SetBaud(self, baud): + if self._port.baudrate != baud: + print ('Reopen %s port %i baud...' % (self.port, baud), end = ' '), + self._port.write(str.encode("uarts%i" % baud)); + self._port.timeout = 1 + read = self._port.read(3); + if read == b'#OK': + print ('ok') + self._port.close() + self.baud = baud + self._port.baudrate = baud + try: + self._port.open(); + except Exception as e: + print ('Error: Open %s, %d baud! Error: %s' % (self.port, self.baud, e)) + sys.exit(1) + else: + print ('error!') + print ('Error set %i baud on %s port!' % (baud, self.port)) + self._port.close() + sys.exit(3) + return True + def Connect(self, baud=DEF_RUN_BAUD): + self._port.setDTR(True) #TM (lo) + self._port.setRTS(True) #RSTN (lo) + time.sleep(0.1) + self._port.flushOutput() + self._port.flushInput() + time.sleep(0.1) + self._port.setDTR(False) #TM (hi) + self._port.setRTS(False) #RSTN (hi) + self._port.timeout = 0.04 + ttcl = 50; + fct_mode = False + pkt = 'UXTDWU' # UXTL16 UDLL48 UXTDWU + while ttcl > 0: + sent = self._port.write(pkt.encode()); + read = self._port.read(6); + if read == b'cmd>>:' : + break + if read == b'fct>>:' : + fct_mode = True + break + ttcl = ttcl - 1 + if ttcl < 1: + print('PHY62x2 - Error Reset!') + print('Check connection TX->RX, RX<-TX and Chip Power!') + self._port.close() + exit(4) + print('PHY62x2 - Reset Ok') + self._port.close() + self._port.baudrate = DEF_RUN_BAUD + self._port.open(); + self._port.timeout = 0.2 + if fct_mode: + print('PHY62x2 in FCT mode!') + return False + if not self.ReadRevision(): + self._port.close() + exit(4) + if not self.FlashUnlock(): + self._port.close() + exit(4) + if not self.write_reg(0x4000f054, 0): + print('PHY62x2 - Error init1!') + self._port.close() + exit(4) + if not self.write_reg(0x4000f140, 0): + print('PHY62x2 - Error init2!') + self._port.close() + exit(4) + if not self.write_reg(0x4000f144, 0): + print('PHY62x2 - Error init3!') + self._port.close() + exit(4) + print('PHY62x2 - connected Ok') + return self.SetBaud(baud) + def cmd_era4k(self, offset): + print ('Erase sector Flash at 0x%08x...' % offset, end = ' ') + tmp = self._port.timeout + self._port.timeout = 0.5 + ret = self.write_cmd('era4k %X' % (offset | MAX_FLASH_SIZE)) + self._port.timeout = tmp + if not ret: + print ('error!') + else: + print ('ok') + return ret + def cmd_era64k(self, offset): + print ('Erase block 64k Flash at 0x%08x...' % offset, end = ' '), + tmp = self._port.timeout + self._port.timeout = 2 + ret = self.write_cmd('er64k %X' % (offset | MAX_FLASH_SIZE)) + self._port.timeout = tmp + if not ret: + print ('error!') + else: + print ('ok') + return ret + def cmd_er512(self, offset = 0): + print ('Erase block 512k Flash at 0x%08x...' % offset, end = ' '), + tmp = self._port.timeout + self._port.timeout = 2 + ret = self.write_cmd('er512 %X' % (offset | MAX_FLASH_SIZE)) + self._port.timeout = tmp + if not ret: + print ('error!') + else: + print ('ok') + return ret + def cmd_erase_work_flash(self): + print ('Erase Flash work area...', end = ' '), + tmp = self._port.timeout + self._port.timeout = 7 + ret = self.write_cmd('erall ') + self._port.timeout = tmp + if not ret: + print ('error!') + else: + print ('ok') + return ret + def cmd_erase_all_flash(self): + print ('Erase All Chip Flash...', end = ' '), + if self.wr_flash_cmd(6) and self.wr_flash_cmd(0x60): #Write Enable, Chip Erase + i = 77; + while i > 0: + r = self.flash_read_status() + if r == None: + print ('Error!') + return False + if (r & 1) == 0: + print ('ok') + return True + i -= 1 + print ('Timeout!') + return False + def EraseSectorsFlash(self, offset = 0, size = MAX_FLASH_SIZE): + count = int((size + PHY_FLASH_SECTOR_SIZE - 1) / PHY_FLASH_SECTOR_SIZE) + offset &= PHY_FLASH_SECTOR_MASK + if count > 0 and count < 0x10000 and offset >= 0: # 1 byte .. 16 Mbytes + while count > 0: + if offset >= self.old_erase_start and offset < self.old_erase_end: + offset += PHY_FLASH_SECTOR_SIZE + count -= 1 + continue + if (offset & 0x0FFFF) == 0 and count > 15: + if not self.cmd_era64k(offset): + return False + self.old_erase_start = offset + self.old_erase_end = offset + 0x10000 + offset += 0x10000 + count -= 16 + else: + if not self.cmd_era4k(offset): + return False + self.old_erase_start = offset + self.old_erase_end = offset + PHY_FLASH_SECTOR_SIZE + offset += PHY_FLASH_SECTOR_SIZE + count -= 1 + else: + return False + return True + def EraseSectorsFlash2(self, offset = 0, size = MAX_FLASH_SIZE): + count = int((size + PHY_FLASH_SECTOR_SIZE - 1) / PHY_FLASH_SECTOR_SIZE) + offset &= PHY_FLASH_SECTOR_MASK + if count > 0 and count < 0x10000 and offset >= 0: # 1 byte .. 16 Mbytes + while count > 0: + if (offset & 0x0FFFF) == 0 and count > 15: + if not self.cmd_era64k(offset): + return False + offset += 0x10000 + count-=16 + else: + if not self.cmd_era4k(offset): + return False + offset += PHY_FLASH_SECTOR_SIZE + count-=1 + else: + return False + return True + def send_blk(self, stream, offset, size, blkcnt, blknum): + self._port.timeout = 1 + print ('Write 0x%08x bytes to Flash at 0x%08x...' % (size, offset), end = ' '), + if blknum == 0: + if not self.write_cmd('cpnum %d ' % blkcnt): + print ('error!') + return False + self._port.write(str.encode('cpbin c%d %X %X %X' % (blknum, offset | MAX_FLASH_SIZE, size, 0x1FFF0000 + offset))) + read = self._port.read(12) + if read != b'by hex mode:': + print ('error!') + return False + data = stream.read(size) + self._port.write(data) + read = self._port.read(23); #'checksum is: 0x00001d1e' + #print ('%s' % read), + if read[0:15] != b'checksum is: 0x': + print ('error!') + return False + self._port.write(read[15:]) + read = self._port.read(6) + if read != b'#OK>>:': + print ('error!') + return False + print ('ok') + return True + def WriteBlockFlash(self, stream, offset = 0, size = 0x8000): + offset &= 0x00ffffff + if self.autoerase: + if not self.EraseSectorsFlash(offset, size): + return False + sblk = PHY_WR_BLK_SIZE + blkcount = (size + sblk - 1) / sblk + blknum = 0 + while(size > 0): + if size < sblk: + sblk = size + if not self.send_blk(stream, offset, sblk, blkcount, blknum): + return False + blknum+=1 + offset+=sblk + size-=sblk + return True + def ReadBusToFile(self, ff, addr=0x11000000, size=0x80000): + flg = size > 128 + if not flg: + print('\rRead 0x%08x...' % addr, end=' ') #, flush=True + while size > 0: + if flg and addr & 127 == 0: + print('\rRead 0x%08x...' % addr, end=' ') #, flush=True + rw = self.read_reg(addr) + if rw == None: + print('error!') + print('\rError read address 0x%08x!' % addr) + return False + dw = struct.pack(' 0): + if size < sblk: + sblk = size + if not self.send_blk(stream, offset, sblk, blkcount, blknum): + return False + blknum+=1 + offset+=sblk + size-=sblk + return True + def HexStartSend(self): + return self.write_cmd('spifs 0 1 3 0 ') and self.write_cmd('sfmod 2 2 ') and self.write_cmd('cpnum ffffffff ') + def HexfHeader(self, hp, start = DEF_START_RUN_APP_ADDR, raddr = DEF_START_WR_FLASH_ADDR): + if len(hp) > 1: + hexf = bytearray(b'\xff')*(0x100) + hexf[0:4] = int.to_bytes(len(hp)-1, 4, byteorder='little') + hexf[8:12] = int.to_bytes(start, 4, byteorder='little') + #sections = 0 + faddr_min = MAX_FLASH_SIZE-1 + faddr_max = 0 + rsize = 0 + for ihp in hp: + if (ihp[0] & 0x1fff0000) == 0x1fff0000: # SRAM + rsize += len(ihp[1]) + elif (ihp[0] & (~(MAX_FLASH_SIZE-1))) == 0x11000000: # Flash + offset = ihp[0] & (MAX_FLASH_SIZE-1) + if faddr_min > offset: + faddr_min = offset + send = offset + len(ihp[1]) + if faddr_max <= send: + faddr_max = send + if (raddr + rsize) >= faddr_min: + raddr = (faddr_max + 3) & 0xfffffffc + #print('Test: Flash addr min: %08x, max: %08x, RAM addr: %08x' % (faddr_min, faddr_max, raddr)) + print ('---- Segments Table -------------------------------------') + for ihp in hp: + if (ihp[0] & 0x1fff0000) == 0x1fff0000: # SRAM + faddr = raddr + raddr += (len(ihp[1])+3) & 0xfffffffc + elif (ihp[0] & (~(MAX_FLASH_SIZE-1))) == 0x11000000: # Flash + faddr = ihp[0] & (MAX_FLASH_SIZE-1) + elif ihp[0] == 0: + continue + else: + print('Invalid Segment Address 0x%08x!' % ihp[0]) + return None + ihp[2] = faddr + print('Segment: %08x <- Flash addr: %08x, Size: %08x' % (ihp[0], faddr, len(ihp[1]))) + hexf.extend(bytearray(struct.pack(' 1024: + print("%.3f KBytes saved to file '%s'" % (byteSaved/1024, args.filename)) + else: + print("%i Bytes saved to file '%s'" % (byteSaved, args.filename)) + ff.close() + #--------------------------------wr flash bin + if args.operation == 'we' or args.operation == 'wf': + offset = args.address & (MAX_FLASH_SIZE-1) + if offset >= MAX_FLASH_SIZE: + print ('Error Start Flash address!') + sys.exit(1) + stream = open(args.filename, 'rb') + size = os.path.getsize(args.filename) + if size < 1: + stream.close() + print ('Error: File size = 0!') + sys.exit(1) + offset = args.address & (MAX_FLASH_SIZE-1) + if size + offset > MAX_FLASH_SIZE: + size = MAX_FLASH_SIZE - offset + if size < 1: + stream.close() + print ('Error: Write File size = 0!') + sys.exit(1) + aerase = args.operation == 'we' + if args.erase == True or args.allerase == True: + aerase = False; + if args.allerase == True: + if not phy.cmd_erase_all_flash(): + stream.close() + print ('Error: Erase All Flash!') + sys.exit(3) + else: + if args.erase == True: + if not phy.cmd_erase_work_flash(): + stream.close + print ('Error: Erase Flash!') + sys.exit(3) + phy.SetAutoErase(aerase) + print ('Write Flash data 0x%08x to 0x%08x from file: %s ...' % (offset, offset + size, args.filename)) + if not phy.ExpFlashSize(): + exit(4) + if size > 0: + if not phy.WriteBlockFlash(stream, offset, size): + stream.close() + print ('Error: Write Flash!') + sys.exit(2) + stream.close() + print ('----------------------------------------------------------') + print ('Write Flash data 0x%08x to 0x%08x from file: %s - ok.' % (offset, offset + size, args.filename)) + #--------------------------------wr flash hex + if args.operation == 'wh': + hp = ParseHexFile(args.filename) + if hp == None: + sys.exit(2) + hexf = phy.HexfHeader(hp, args.start, args.write) + if hexf == None: + sys.exit(2) + hp[0][1] = hexf + if not phy.HexStartSend(): + sys.exit(2) + print ('----------------------------------------------------------') + aerase = True + if args.erase == True or args.allerase == True: + aerase = False; + if args.allerase == True: + if not phy.cmd_erase_all_flash(): + stream.close() + print ('Error: Erase All Flash!') + sys.exit(3) + else: + if args.erase == True: + if not phy.cmd_erase_work_flash(): + stream.close + print ('Error: Erase Flash!') + sys.exit(3) + phy.SetAutoErase(aerase) + if not phy.ExpFlashSize(): + exit(4) + segment = 0 + for ihp in hp: + if ihp[0] == 0: + print('Segment Table[%02d] <- Flash addr: %08x, Size: %08x' % (len(hp) - 1, ihp[2], len(ihp[1]))) + else: + print('Segment: %08x <- Flash addr: %08x, Size: %08x' % (ihp[0], ihp[2], len(ihp[1]))) + stream = io.BytesIO(ihp[1]) + if not phy.WriteBlockFlash(stream, ihp[2], len(ihp[1])): + stream.close() + sys.exit(2) + stream.close() + segment += 1 + print ('----------------------------------------------------------') + print ('Write Flash from file: %s - ok.' % args.filename) + #--------------------------------erase flash region + if args.operation == 'er': + offset = args.address & (MAX_FLASH_SIZE-1) + if offset >= MAX_FLASH_SIZE: + print ('Error Flash Start address!') + sys.exit(1) + size = args.size & (MAX_FLASH_SIZE-1) + if size >= MAX_FLASH_SIZE: + print ('Error Flash Erase size!') + sys.exit(1) + if size + offset > MAX_FLASH_SIZE: + size = MAX_FLASH_SIZE - offset + if size < 1: + print ('Error Flash Erase size!') + sys.exit(1) + if not phy.ExpFlashSize(): + exit(4) + if not phy.EraseSectorsFlash(offset, size): + sys.exit(2) + #--------------------------------erase flash all + if args.operation == 'ea': + if not phy.cmd_erase_all_flash(): + print ('Error: Erase All Flash!') + sys.exit(3) + if args.operation == 'ew': + if not phy.cmd_erase_work_flash(): + print ('Error: Erase Flash Work Area!') + sys.exit(3) + if args.reset: + phy.SendResetCmd() + print ("Send command 'reset' - ok") + sys.exit(0) + +if __name__ == '__main__': + main() diff --git a/ota_boot/source/include/bus_dev.h b/ota_boot/source/include/bus_dev.h new file mode 100644 index 0000000..921e9f8 --- /dev/null +++ b/ota_boot/source/include/bus_dev.h @@ -0,0 +1,80 @@ +/************************************************************************************************** + Filename: bus_dev.h + Revised: + Revision: + + Description: This file contains the SoC MCU relate definitions + + SDK_LICENSE + + **************************************************************************************************/ + +#ifndef __BUS_DEV_H__ +#define __BUS_DEV_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//#include "mcu.h" + +enum +{ + RSTC_COLD_UP = 0, + RSTC_WARM_UP = 1, + RSTC_OFF_MODE = 2, + RSTC_WAKE_IO = 3, + RSTC_WAKE_RTC = 4, + RSTC_WARM_NDWC = 5 //user mode, no dwc + +}; + +/* ------------------------- Interrupt Number Definition ------------------------ */ + +typedef enum IRQn +{ + /* ------------------- Cortex-M0 Processor Exceptions Numbers ------------------- */ + NonMaskableInt_IRQn = -14, /* 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /* 3 HardFault Interrupt */ + + + + SVCall_IRQn = -5, /* 11 SV Call Interrupt */ + + PendSV_IRQn = -2, /* 14 Pend SV Interrupt */ + SysTick_IRQn = -1, /* 15 System Tick Interrupt */ + + /* ---------------------- PHY BUMBEE M0 Interrupt Numbers --------------------- */ + BB_IRQn = 4, /* Base band Interrupt */ + KSCAN_IRQn = 5, /* Key scan Interrupt */ + RTC_IRQn = 6, /* RTC Timer Interrupt */ + + WDT_IRQn = 10, /* Watchdog Timer Interrupt */ + UART0_IRQn = 11, /* UART0 Interrupt */ + I2C0_IRQn = 12, /* I2C0 Interrupt */ + I2C1_IRQn = 13, /* I2C1 Interrupt */ + SPI0_IRQn = 14, /* SPI0 Interrupt */ + SPI1_IRQn = 15, /* SPI1 Interrupt */ + GPIO_IRQn = 16, /* GPIO Interrupt */ + UART1_IRQn = 17, /* UART1 Interrupt */ + SPIF_IRQn = 18, /* SPIF Interrupt */ + DMAC_IRQn = 19, /* DMAC Interrupt */ + TIM1_IRQn = 20, /* Timer1 Interrupt */ + TIM2_IRQn = 21, /* Timer2 Interrupt */ + TIM3_IRQn = 22, /* Timer3 Interrupt */ + TIM4_IRQn = 23, /* Timer4 Interrupt */ + TIM5_IRQn = 24, /* Timer5 Interrupt */ + TIM6_IRQn = 25, /* Timer6 Interrupt */ + + AES_IRQn = 28, /* AES Interrupt */ + ADCC_IRQn = 29, /* ADC Interrupt */ + QDEC_IRQn = 30, /* QDEC Interrupt */ + RNG_IRQn = 31 /* RNG Interrupt */ +} IRQn_Type; + + +#include "core_bumbee_m0.h" + +#include "mcu_phy_bumbee.h" + +#endif diff --git a/ota_boot/source/include/core_bumbee_m0.h b/ota_boot/source/include/core_bumbee_m0.h new file mode 100644 index 0000000..3ad7038 --- /dev/null +++ b/ota_boot/source/include/core_bumbee_m0.h @@ -0,0 +1,90 @@ + +#ifndef PHY_BUMBEE_M0_H +#define PHY_BUMBEE_M0_H + +#ifdef __cplusplus +extern "C" { +#endif + + + + + +/* ================================================================================ */ +/* ================ Processor and Core Peripheral Section ================ */ +/* ================================================================================ */ + +/* ------- Start of section using anonymous unions and disabling warnings ------- */ +#if defined (__CC_ARM) + #pragma push + #pragma anon_unions +#elif defined (__ICCARM__) + #pragma language=extended +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wc11-extensions" + #pragma clang diagnostic ignored "-Wreserved-id-macro" +#elif defined (__GNUC__) + /* anonymous unions are enabled by default */ +#elif defined (__TMS470__) + /* anonymous unions are enabled by default */ +#elif defined (__TASKING__) + #pragma warning 586 +#elif defined (__CSMC__) + /* anonymous unions are enabled by default */ +#else + #warning Not supported compiler type +#endif + + +/* -------- Configuration of the Cortex-M0 Processor and Core Peripherals ------- */ +//#define __CM0_REV 0x0000U /* Core revision r0p0 */ +//#define __MPU_PRESENT 0U /* MPU present or not */ +//#define __VTOR_PRESENT 0U /* no VTOR present*/ +#define __NVIC_PRIO_BITS 2U /* Number of Bits used for Priority Levels */ +//#define __Vendor_SysTickConfig 0U /* Set to 1 if different SysTick Config is used */ + +#include "core_cm0.h" /* Processor and core peripherals */ +#if defined ( __CC_ARM ) +#include "system_ARMCM0.h" /* System Header */ +#endif /*__CC_ARM*/ + +#define NVIC_GetPendingIRQs() (NVIC->ISPR[0U]) +#define NVIC_ClearPendingIRQs(icpr) (NVIC->ICPR[0U] = (unsigned int)icpr) +#define NVIC_SetPendingIRQs(ispr) (NVIC->ISPR[0U] = (unsigned int)ispr) + +#define NVIC_GetEnableIRQs() (NVIC->ISER[0U]) +#define NVIC_DisableIRQs(irqs) (NVIC->ICER[0U] = (unsigned int)irqs) +#define NVIC_EnableIRQs(iser) (NVIC->ISER[0U] = (unsigned int)iser) + +#define NVIC_ClearWakeupIRQ(irqn) +#define NVIC_SetWakeupIRQ(irqn) + + +/* -------- End of section using anonymous unions and disabling warnings -------- */ +#if defined (__CC_ARM) + #pragma pop +#elif defined (__ICCARM__) + /* leave anonymous unions enabled */ +#elif (__ARMCC_VERSION >= 6010050) + #pragma clang diagnostic pop +#elif defined (__GNUC__) + /* anonymous unions are enabled by default */ +#elif defined (__TMS470__) + /* anonymous unions are enabled by default */ +#elif defined (__TASKING__) + #pragma warning restore +#elif defined (__CSMC__) + /* anonymous unions are enabled by default */ +#else + #warning Not supported compiler type +#endif + + + + +#ifdef __cplusplus +} +#endif + +#endif /* PHY_BUMBEE_M0 */ diff --git a/ota_boot/source/include/global_config.h b/ota_boot/source/include/global_config.h new file mode 100644 index 0000000..42caa73 --- /dev/null +++ b/ota_boot/source/include/global_config.h @@ -0,0 +1,233 @@ +/** + **************************************************************************************** + + @file global_config.h + + @brief This file contains the definitions of index of global configuration which + will be configured in APP project. + + + $Rev: $ + + SDK_LICENSE + + **************************************************************************************** +*/ + + +#ifndef _GLOBAL_CONFIG_H_ +#define _GLOBAL_CONFIG_H_ + +#include "types.h" + +/******************************************************************************* + software configuration parameters definition +*/ + +#define CONFIG_BASE_ADDR 0x1fff0400 + +#define SOFT_PARAMETER_NUM 256 +// parameter index of configuration array +#define ADV_CHANNEL_INTERVAL 0 // interval between adv channel in the same adv event +#define SCAN_RSP_DELAY 1 // to adjust scan req -> scan rsp delay +#define CONN_REQ_TO_SLAVE_DELAY 2 // to calibrate the delay between conn req & 1st slave conn event +#define SLAVE_CONN_DELAY 3 // to adjust the delay between 2 slave connection events +#define SLAVE_CONN_DELAY_BEFORE_SYNC 4 // to adjust the delay between 2 slave connection events before 1st anchor is acquired +#define MAX_SLEEP_TIME 5 // maximum sleep time in us +#define MIN_SLEEP_TIME 6 // minimum sleep time in us +#define WAKEUP_ADVANCE 7 // wakeup advance time, to cover HW delay, crystal settle time, sw delay, ... etc. +#define WAKEUP_DELAY 8 // cycles of SW delay to wait crystal settle + +#define HDC_DIRECT_ADV_INTERVAL 9 +#define LDC_DIRECT_ADV_INTERVAL 10 + + +#define LL_SWITCH 11 // Link Layer switch, 1 enable, 0 disable +#define NON_ADV_CHANNEL_INTERVAL 12 // interval between non-adv channel in the same adv event + +#define CLOCK_SETTING 14 // HCLK +#define LL_HW_BB_DELAY 15 +#define LL_HW_AFE_DELAY 16 +#define LL_HW_PLL_DELAY 17 + +#define LL_HW_RTLP_LOOP_TIMEOUT 18 +#define LL_HW_RTLP_1ST_TIMEOUT 19 + +#define MIN_TIME_TO_STABLE_32KHZ_XOSC 20 + +#define LL_TX_PKTS_PER_CONN_EVT 21 +#define LL_RX_PKTS_PER_CONN_EVT 22 + + +// ============= A1 ROM metal change add +#define DIR_ADV_DELAY 23 + + +#define LL_TX_PWR_TO_REG_BIAS 24 + + +#define LL_SMART_WINDOW_COEF_ALPHA 25 +#define LL_SMART_WINDOW_TARGET 26 +#define LL_SMART_WINDOW_INCREMENT 27 +#define LL_SMART_WINDOW_LIMIT 28 +#define LL_SMART_WINDOW_ACTIVE_THD 29 +#define LL_SMART_WINDOW_ACTIVE_RANGE 30 + +#define LL_SMART_WINDOW_FIRST_WINDOW 31 + +#define LL_HW_Tx_TO_RX_INTV 32 +#define LL_HW_Rx_TO_TX_INTV 33 + +#define INITIAL_STACK_PTR 34 +#define ALLOW_TO_SLEEP_TICK_RC32K 35 + +#define LL_HW_BB_DELAY_ADV 36 +#define LL_HW_AFE_DELAY_ADV 37 +#define LL_HW_PLL_DELAY_ADV 38 + +// For scan & master, add 2018-6-15 +#define LL_ADV_TO_SCAN_REQ_DELAY 39 +#define LL_ADV_TO_CONN_REQ_DELAY 40 + +#define LL_MOVE_TO_MASTER_DELAY 41 + +#define LL_HW_TRLP_LOOP_TIMEOUT 42 + +#define LL_CONN_REQ_WIN_SIZE 43 +#define LL_CONN_REQ_WIN_OFFSET 44 + +#define LL_MASTER_PROCESS_TARGET 45 +#define LL_MASTER_TIRQ_DELAY 46 + + +#define LL_HW_BB_DELAY_2MPHY 47 +#define LL_HW_AFE_DELAY_2MPHY 48 +#define LL_HW_PLL_DELAY_2MPHY 49 + +#define LL_HW_Tx_TO_RX_INTV_2MPHY 50 +#define LL_HW_Rx_TO_TX_INTV_2MPHY 51 + +#define LL_HW_BB_DELAY_500KPHY 52 +#define LL_HW_AFE_DELAY_500KPHY 53 +#define LL_HW_PLL_DELAY_500KPHY 54 + +#define LL_HW_Tx_TO_RX_INTV_500KPHY 55 +#define LL_HW_Rx_TO_TX_INTV_500KPHY 56 + +#define LL_HW_BB_DELAY_125KPHY 57 +#define LL_HW_AFE_DELAY_125KPHY 58 +#define LL_HW_PLL_DELAY_125KPHY 59 + +#define LL_HW_Tx_TO_RX_INTV_125KPHY 60 +#define LL_HW_Rx_TO_TX_INTV_125KPHY 61 + +#define LL_HW_TRLP_TO_GAP 62 +#define LL_HW_RTLP_TO_GAP 63 + +#define LL_TRX_NUM_ADAPTIVE_CONFIG 64 +#define OSAL_SYS_TICK_WAKEUP_TRIM 65 + +// ==== A2 add, for secondary adv/scan +#define LL_NOCONN_ADV_EST_TIME 70 +#define LL_NOCONN_ADV_MARGIN 71 +#define LL_SEC_SCAN_MARGIN 72 +#define LL_MIN_SCAN_TIME 73 +// Bumblebee ROM code +#define LL_CONN_ADV_EST_TIME 74 +#define LL_SCANABLE_ADV_EST_TIME 75 + + + +#define MAC_ADDRESS_LOC 80 + +// ==== For Extended Adv & Periodic adv +#define LL_EXT_ADV_INTER_PRI_CHN_INT 81 +#define LL_EXT_ADV_INTER_AUX_CHN_INT 82 +#define LL_EXT_ADV_RSC_POOL_PERIOD 83 +#define LL_EXT_ADV_RSC_POOL_UNIT 84 + +#define LL_EXT_ADV_TASK_DURATION 86 +#define LL_PRD_ADV_TASK_DURATION 87 +#define LL_CONN_TASK_DURATION 88 + +#define TIMER_ISR_ENTRY_TIME 90 // time from HW timer expiry to ISR entry, unit: us +#define LL_MULTICONN_MASTER_PREEMP 91 +#define LL_MULTICONN_SLAVE_PREEMP 92 + +#define LL_EXT_ADV_INTER_SEC_CHN_INT 93 +#define LL_EXT_ADV_PRI_2_SEC_CHN_INT 94 + +#define LL_EXT_ADV_RSC_PERIOD 95 +#define LL_EXT_ADV_RSC_SLOT_DURATION 96 + +#define LL_PRD_ADV_RSC_PERIOD 97 +#define LL_PRD_ADV_RSC_SLOT_DURATION 98 + +#define LL_EXT_ADV_PROCESS_TARGET 99 +#define LL_PRD_ADV_PROCESS_TARGET 100 + +#define EXT_ADV_AUXSCANRSP_DELAY_1MPHY 101 +#define EXT_ADV_AUXCONNRSP_DELAY_1MPHY 102 + +#define EXT_ADV_AUXSCANRSP_DELAY_2MPHY 103 +#define EXT_ADV_AUXCONNRSP_DELAY_2MPHY 104 + +#define EXT_ADV_AUXSCANRSP_DELAY_500KPHY 105 +#define EXT_ADV_AUXCONNRSP_DELAY_500KPHY 106 + +#define EXT_ADV_AUXSCANRSP_DELAY_125KPHY 107 +#define EXT_ADV_AUXCONNRSP_DELAY_125KPHY 108 + +#define EXT_ADV_AUXSCANREQ_DELAY_1MPHY 109 +#define EXT_ADV_AUXCONNREQ_DELAY_1MPHY 110 + +#define EXT_ADV_AUXSCANREQ_DELAY_2MPHY 111 +#define EXT_ADV_AUXCONNREQ_DELAY_2MPHY 112 + +#define EXT_ADV_AUXSCANREQ_DELAY_125KPHY 113 +#define EXT_ADV_AUXCONNREQ_DELAY_125KPHY 114 + +#define LL_EXT_ADV_INTER_SEC_CHN_INT_2MPHY 115 + +//Open the RX window in advance if the connection interval is too large in sleep mode +#define LL_ENLARGE_ADVANCE_RX_WINDOW_VALUE 116 /// 200 + +#define GARBAGE_DATA_RESOURCE 117 /// 1000 +#define MAXSCANRSPONSES 118 /// 64 + + + + + + + + +// ============== + +#define RC32_TRACKINK_ALLOW 0x00000001 // enable tracking RC 32KHz clock with 16MHz hclk +#define SLAVE_LATENCY_ALLOW 0x00000002 // slave latency allow switch +#define LL_DEBUG_ALLOW 0x00000004 // enable invoke RAM project debug output fucntion +#define LL_WHITELIST_ALLOW 0x00000008 // enable whitelist filter +#define LL_RC32K_SEL 0x00000010 // select RC32K RTC, otherwise select crystal 32K RTC +#define SIMUL_CONN_ADV_ALLOW 0x00000020 // allow send adv in connect state +#define SIMUL_CONN_SCAN_ALLOW 0x00000040 // allow scan in connect state + +#define CONN_CSA2_ALLOW 0x00000080 // allow using CSA2 in connection state + +#define GAP_DUP_RPT_FILTER_DISALLOW 0x00000100 // duplicate report filter in GAP layer, allow default +#define ENH_CONN_CMP_EVENT_ALLOW 0x00000200 // allow LL to send enhanced connection complete event. +// delete 2018-7-17, should use enum H_SYSCLK_SEL +//enum +//{ +// CLOCK_16MHZ = 0, +// CLOCK_32MHZ = 1, +// CLOCK_48MHZ = 2, +// CLOCK_64MHZ = 3, +// CLOCK_96MHZ = 4, +// CLOCK_32MHZ_DBL=5 +//}; + +//extern uint32 global_config[SOFT_PARAMETER_NUM]; +extern uint32* pGlobal_config; // note: app project needn't this variable + +#endif // _GLOBAL_CONFIG_H_ diff --git a/ota_boot/source/include/mcu_phy_bumbee.h b/ota_boot/source/include/mcu_phy_bumbee.h new file mode 100644 index 0000000..d324e48 --- /dev/null +++ b/ota_boot/source/include/mcu_phy_bumbee.h @@ -0,0 +1,843 @@ +/************* + mcu_phy_bumbee.h + SDK_LICENSE +***************/ +#ifndef __MCU_BUMBEE_M0__ +#define __MCU_BUMBEE_M0__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" + +typedef enum +{ + MOD_NONE = 0, MOD_CK802_CPU = 0, + MOD_DMA = 3, + MOD_AES = 4, + MOD_IOMUX = 7, + MOD_UART0 = 8, + MOD_I2C0 = 9, + MOD_I2C1 = 10, + MOD_SPI0 = 11, + MOD_SPI1 = 12, + MOD_GPIO = 13, + MOD_QDEC = 15, + MOD_ADCC = 17, + MOD_PWM = 18, + MOD_SPIF = 19, + MOD_VOC = 20, + MOD_TIMER5 = 21, + MOD_TIMER6 = 22, + MOD_UART1 = 25, + + MOD_CP_CPU = 0+32, + MOD_BB = MOD_CP_CPU+3, + MOD_TIMER = MOD_CP_CPU+4, + MOD_WDT = MOD_CP_CPU+5, + MOD_COM = MOD_CP_CPU+6, + MOD_KSCAN = MOD_CP_CPU+7, + MOD_BBREG = MOD_CP_CPU+9, + BBLL_RST = MOD_CP_CPU+10,//can reset,but not gate in here + BBTX_RST = MOD_CP_CPU+11,//can reset,but not gate in here + BBRX_RST = MOD_CP_CPU+12,//can reset,but not gate in here + BBMIX_RST = MOD_CP_CPU+13,//can reset,but not gate in here + MOD_TIMER1 = MOD_CP_CPU+21, + MOD_TIMER2 = MOD_CP_CPU+22, + MOD_TIMER3 = MOD_CP_CPU+23, + MOD_TIMER4 = MOD_CP_CPU+24, + + MOD_PCLK_CACHE = 0+64, + MOD_HCLK_CACHE = MOD_PCLK_CACHE+1, + + MOD_USR0 = 0+96, + MOD_USR1 = MOD_USR0+1, + MOD_USR2 = MOD_USR0+2, + MOD_USR3 = MOD_USR0+3, + MOD_USR4 = MOD_USR0+4, + MOD_USR5 = MOD_USR0+5, + MOD_USR6 = MOD_USR0+6, + MOD_USR7 = MOD_USR0+7, + MOD_USR8 = MOD_USR0+8, + MOD_SYSTEM = 0xFF, +} MODULE_e; + +//SW_CLK -->0x4000f008 +#define _CLK_NONE (BIT(0)) +#define _CLK_CK802_CPU (BIT(0)) +#define _CLK_DMA (BIT(3)) +#define _CLK_AES (BIT(4)) +#define _CLK_IOMUX (BIT(7)) +#define _CLK_UART0 (BIT(8)) +#define _CLK_I2C0 (BIT(9)) +#define _CLK_I2C1 (BIT(10)) +#define _CLK_SPI0 (BIT(11)) +#define _CLK_SPI1 (BIT(12)) +#define _CLK_GPIO (BIT(13)) +#define _CLK_QDEC (BIT(15)) +#define _CLK_ADCC (BIT(17)) +#define _CLK_PWM (BIT(18)) +#define _CLK_SPIF (BIT(19)) +#define _CLK_VOC (BIT(20)) +#define _CLK_TIMER5 (BIT(21)) +#define _CLK_TIMER6 (BIT(22)) +#define _CLK_UART1 (BIT(25)) + + +//SW_CLK1 -->0x4000f014 +#define _CLK_M0_CPU (BIT(0)) +#define _CLK_BB (BIT(3)) +#define _CLK_TIMER (BIT(4)) +#define _CLK_WDT (BIT(5)) +#define _CLK_COM (BIT(6)) +#define _CLK_KSCAN (BIT(7)) +#define _CLK_BBREG (BIT(9)) +#define _CLK_TIMER1 (BIT(21)) +#define _CLK_TIMER2 (BIT(22)) +#define _CLK_TIMER3 (BIT(23)) +#define _CLK_TIMER4 (BIT(24)) + +#define BB_IRQ_HANDLER V4_IRQ_HANDLER +#define KSCAN_IRQ_HANDLER V5_IRQ_HANDLER +#define RTC_IRQ_HANDLER V6_IRQ_HANDLER +#define CP_COM_IRQ_HANDLER V7_IRQ_HANDLER +#define AP_COM_IRQ_HANDLER V8_IRQ_HANDLER +#define WDT_IRQ_HANDLER V10_IRQ_HANDLER +#define UART0_IRQ_HANDLER V11_IRQ_HANDLER +#define I2C0_IRQ_HANDLER V12_IRQ_HANDLER +#define I2C1_IRQ_HANDLER V13_IRQ_HANDLER +#define SPI0_IRQ_HANDLER V14_IRQ_HANDLER +#define SPI1_IRQ_HANDLER V15_IRQ_HANDLER +#define GPIO_IRQ_HANDLER V16_IRQ_HANDLER +#define UART1_IRQ_HANDLER V17_IRQ_HANDLER +#define SPIF_IRQ_HANDLER V18_IRQ_HANDLER +#define DMAC_IRQ_HANDLER V19_IRQ_HANDLER +#define TIM1_IRQ_HANDLER V20_IRQ_HANDLER +#define TIM2_IRQ_HANDLER V21_IRQ_HANDLER +#define TIM3_IRQ_HANDLER V22_IRQ_HANDLER +#define TIM4_IRQ_HANDLER V23_IRQ_HANDLER +#define TIM5_IRQ_HANDLER V24_IRQ_HANDLER +#define TIM6_IRQ_HANDLER V25_IRQ_HANDLER +#define AES_IRQ_HANDLER V28_IRQ_HANDLER +#define ADCC_IRQ_HANDLER V29_IRQ_HANDLER +#define QDEC_IRQ_HANDLER V30_IRQ_HANDLER + +/******************************************************************************* + TYPEDEFS +*/ +/******************************************************************************/ +/* Device Specific Peripheral registers structures */ +/******************************************************************************/ +typedef struct +{ + __IO uint32_t CH0_AP_MBOX; //0x00 + __IO uint32_t CH0_CP_MBOX; //0x04 + __IO uint32_t CH1_AP_MBOX; //0x08 + __IO uint32_t CH1_CP_MBOX; //0x0c + __IO uint32_t AP_STATUS; //0x10 + __IO uint32_t CP_STATUS; //0x14 + __IO uint32_t AP_INTEN; //0x18 + __IO uint32_t CP_INTEN; //0x1c + __IO uint32_t remap; //0x20 + __IO uint32_t RXEV_EN; //0x24 + __IO uint32_t STCALIB; //0x28 + __IO uint32_t PERI_MASTER_SELECT; //0x2c +} AP_COM_TypeDef; + +typedef struct +{ + __IO uint32_t CTRL0;//0x40 + __IO uint32_t CTRL1;//0x44 + uint32_t reserverd[13]; + __IO uint32_t REMAP_TABLE;//0x7c + __IO uint32_t REMAP_CTRL[32];//0x80 +} AP_CACHE_TypeDef; + +typedef struct +{ + __IO uint8_t CR; //0x0 + uint8_t RESERVED0[3]; + __IO uint32_t TORR; //0x4 + __O uint32_t CCVR; //0x8 + __IO uint32_t CRR; //0xc + uint8_t STAT; //0x10 + uint8_t reserverd1[3]; + __IO uint8_t EOI; //0x14 + uint8_t reserverd2[3]; +} AP_WDT_TypeDef; + + + +typedef struct +{ + __IO uint32_t SW_RESET0; //0x0 + __IO uint32_t SW_RESET1; //0x4 + __IO uint32_t SW_CLK; //0x8 + __IO uint32_t SW_RESET2; //0xc + __IO uint32_t SW_RESET3; //0x10 bit 1: M0 cpu reset pulse, bit 0: M0 system reset pulse. + __IO uint32_t SW_CLK1; //0x14 + __IO uint32_t APB_CLK; //0x18 + __IO uint32_t APB_CLK_UPDATE; //0x1c + __IO uint32_t CACHE_CLOCK_GATE;//0x20 + __IO uint32_t CACHE_RST;//0x24 + __IO uint32_t CACHE_BYPASS;//0x28 +} AP_PCR_TypeDef; + +typedef struct +{ + __IO uint32_t LoadCount; //0x0 + __IO uint32_t CurrentCount; //0x4 + __IO uint32_t ControlReg; //0x8 + __IO uint32_t EOI; //0xc + __IO uint32_t status; //0x10 + +} AP_TIM_TypeDef; + +typedef struct +{ + __IO uint32_t IntStatus; + __IO uint32_t EOI; + __IO uint32_t unMaskIntStatus; + __IO uint32_t version; +} AP_TIM_SYS_TypeDef; + + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/*------------- Universal Asynchronous Receiver Transmitter (UARTx) -----------*/ + +typedef struct +{ + union + { + __I uint8_t RBR; + __IO uint8_t THR; + __IO uint8_t DLL; + uint32_t RESERVED0; //0x0 + }; + union + { + __IO uint8_t DLM; + __IO uint32_t IER; //0x4 + }; + union + { + __I uint32_t IIR; //0x8 + __IO uint8_t FCR; + }; + __IO uint8_t LCR; //0xc + uint8_t RESERVED1[3];//Reserved + __IO uint32_t MCR; //0x10 + __I uint8_t LSR; //0x14 + uint8_t RESERVED2[3];//Reserved + __IO uint32_t MSR; //0x18 + __IO uint8_t SCR; //0x1c + uint8_t RESERVED3[3];//Reserved + __IO uint32_t LPDLL; //0x20 + __IO uint32_t LPDLH; //0x24 + __IO uint32_t recerved[2]; + union + { + __IO uint32_t SRBR[16]; // 0x30~60xc + __IO uint32_t STHR[16]; + }; + __IO uint32_t FAR; //0x70 + __IO uint32_t TFR; //0x74 + __IO uint32_t RFW; // 0x78 + __IO uint32_t USR; // 0x7c + __IO uint32_t TFL; + __IO uint32_t RFL; + __IO 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; //0xa0 + __IO uint32_t HTX; + __IO uint32_t DMASA; //0xa8 + __IO uint32_t reserved[18]; + __IO uint32_t CPR; //0xf4 + __IO uint32_t UCV; + __IO uint32_t CTR; +} AP_UART_TypeDef; + + +/*------------- Inter-Integrated Circuit (I2C) setup by zjp-------------------------------*/ +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; //0x10 + __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; //0x20 + __IO uint32_t IC_HS_SCL_HCNT; + __IO uint32_t IC_HS_SCL_LCNT; + __IO uint32_t IC_INTR_STAT; + __IO uint32_t IC_INTR_MASK; //0x30 + __IO uint32_t IC_RAW_INTR_STAT; + __IO uint32_t IC_RX_TL; + __IO uint32_t IC_TX_TL; + __IO uint32_t IC_CLR_INTR; //0x40 + __IO uint32_t IC_CLR_UNDER; + __IO uint32_t IC_CLR_RX_OVER; + __IO uint32_t IC_CLR_TX_OVER; + __IO uint32_t IC_CLR_RD_REG; //0x50 + __IO uint32_t IC_CLR_TX_ABRT; + __IO uint32_t IC_CLR_RX_DONE; + __IO uint32_t IC_CLR_ACTIVITY; + __IO uint32_t IC_CLR_STOP_DET; //0x60 + __IO uint32_t IC_CLR_START_DET; + __IO uint32_t IC_CLR_GEN_CALL; + __IO uint32_t IC_ENABLE; + __IO uint32_t IC_STATUS; //0x70 + __IO uint32_t IC_TXFLR; + __IO uint32_t IC_RXFLR; + __IO uint32_t IC_SDA_HOLD; + __IO uint32_t IC_TX_ABRT_SOURCE; //0x80 + __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; //0x90 + __IO uint32_t IC_SDA_SETUP; + __IO uint32_t IC_ACK_GENERAL_CALL; + __IO uint32_t IC_ENABLE_STATUS; + __IO uint32_t IC_FS_SPKLEN; //0xa0 + __IO uint32_t IC_HS_SPKLEN; + +} AP_I2C_TypeDef; + + +/*------------- Inter IC Sound (I2S) -----------------------------------------*/ +typedef struct +{ + __IO uint32_t IER; + __IO uint32_t IRER; + __IO uint32_t ITER; + __IO uint32_t CER; + __IO uint32_t CCR; + __IO uint32_t RXFFR; + __IO uint32_t TXFFR; + +} AP_I2S_BLOCK_TypeDef; + +typedef struct +{ + union + { + __IO uint32_t LRBR; //0x20 + __IO uint32_t LTHR; //0x20 + }; + union + { + __IO uint32_t RRBR; // 0x24 + __IO uint32_t RTHR; //0x24 + }; + __IO uint32_t RER; //0x28 + __IO uint32_t TER; //0x2c + __IO uint32_t RCR; //0x30 + __IO uint32_t TCR; //0x34 + __IO uint32_t ISR; //0x38 + __IO uint32_t IMR; //0x3c + __IO uint32_t ROR; //0x40 + __IO uint32_t TOR; //0x44 + __IO uint32_t RFCR; //0x48 + __IO uint32_t TFCR; //0x4c + __IO uint32_t RFF; //0x50 + __IO uint32_t TFF; //0x54 + +} AP_I2S_TypeDef; + + +/*------------- General Purpose Input/Output (GPIO) --------------------------*/ +typedef struct +{ + __IO uint32_t swporta_dr; //0x00 + __IO uint32_t swporta_ddr; //0x04 + __IO uint32_t swporta_ctl; //0x08 + uint32_t reserved8[9]; //0x18-0x2c portC&D + __IO uint32_t inten; //0x30 + __IO uint32_t intmask; //0x34 + __IO uint32_t inttype_level; //0x38 + __IO uint32_t int_polarity; //0x3c + __I uint32_t int_status; //0x40 + __IO uint32_t raw_instatus; //0x44 + __IO uint32_t debounce; //0x48 + __O uint32_t porta_eoi; //0x4c + __I uint32_t ext_porta; //0x50 + uint32_t reserved9[3]; //0x58 0x5c + __IO uint32_t ls_sync; //0x60 + __I uint32_t id_code; //0x64 + uint32_t reserved10[1]; //0x68 + __I uint32_t ver_id_code; //0x6c + __I uint32_t config_reg2; //0x70 + __I uint32_t config_reg1; //0x74 +} AP_GPIO_TypeDef; + + +/*-------------------- (SPI) --------------------------------*/ +typedef struct +{ + __IO uint16_t CR0; //0x0 /*!< Offset: 0x000 Control Register 0 (R/W) */ + uint16_t reserved1; + __IO uint16_t CR1; //0x04 /*!< Offset: 0x004 Control Register 1 (R/W) */ + uint16_t reserved2; + __IO uint8_t SSIEN; //0x08 + uint8_t reserved3[3]; + __IO uint8_t MWCR; // 0x0c + uint8_t reserved4[3]; + __IO uint8_t SER; //0x10 + uint8_t reserved5[3]; + __IO uint32_t BAUDR; //0x14 + __IO uint32_t TXFTLR; //0x18 + __IO uint32_t RXFTLR; //0x1c + __O uint32_t TXFLR; //0x20 + __O uint32_t RXFLR; //0x24 + + __IO uint8_t SR; //0x28 + uint8_t reserved7[3]; + __IO uint32_t IMR; //0x2c + __IO uint32_t ISR; //0x30 + __IO uint32_t RISR; //0x34 + __IO uint32_t TXOICR; //0x38 + __IO uint32_t RXOICR; //0x3c + __IO uint32_t RXUICR; //0x40 + __IO uint32_t MSTICR; //0x44 + __IO uint32_t ICR; //0x48 + __IO uint32_t DMACR; //0x4c + __IO uint32_t DMATDLR; //0x50 + __IO uint32_t DMARDLR; //0x54 + __IO uint32_t IDR; //0x5c + __IO uint32_t SSI_COM_VER; //0x5c + __IO uint32_t DataReg; + +} AP_SSI_TypeDef; + + +typedef struct +{ + __IO uint32_t Analog_IO_en;//0x00 + __IO uint32_t SPI_debug_en;//0x04 + __IO uint32_t debug_mux_en;//0x08 + __IO uint32_t full_mux0_en;//0x0c + __IO uint32_t full_mux1_en;//0x10 reserved in some soc + __IO uint32_t gpio_pad_en; //0x14 + __IO uint32_t gpio_sel[9]; //0x18 + __IO uint32_t pad_pe0;//0x3c + __IO uint32_t pad_pe1;//0x40 + __IO uint32_t pad_ps0;//0x44 + __IO uint32_t pad_ps1;//0x48 + __IO uint32_t keyscan_in_en;//0x4c + __IO uint32_t keyscan_out_en;//0x50 +} IOMUX_TypeDef; + + +// 0x4000f05C - [bit16] 16M [bit8:4] cnt [bit3] track_en_rc32k +// 0x4000f064 - RC 32KHz tracking counter, calculate 16MHz ticks number per RC32KHz cycle +// uint32_t counter_tracking // 24bit tracking counter, read from 0x4000f064 +// counter_tracking = g_counter_traking_avg = STD_RC32_16_CYCLE_16MHZ_CYCLE; hal_rc32k_clk_tracking_init() +// 0x4000f0C0 - SLEEP_R[0] flags =2 RSTC_OFF_MODE, =4 RSTC_WARM_NDWC +// 0x4000f0C4 - SLEEP_R[1] bit7 - first wakeupinit, tracking flags +// 0x4000f0C8 - SLEEP_R[2] использую для сохранения UTC счета времени при перезагрузке +// 0x4000f0CС - SLEEP_R[3] использую для сохранения UTC счета времени при перезагрузке + +typedef struct +{ + __IO uint32_t PWROFF; //0x00 = 0x5a5aa5a5 enter system off mode + __IO uint32_t PWRSLP; //0x04 = 0xa5a55a5a system sleep mode + __IO uint32_t IOCTL[3]; //0x08 0x0c 0x10 + __IO uint32_t PMCTL0; //0x14 + __IO uint32_t PMCTL1; //0x18 + __IO uint32_t PMCTL2_0; //0x1c bit6 enable software control 32k_clk + __IO uint32_t PMCTL2_1; //0x20 + __IO uint32_t RTCCTL; //0x24 bit20 - enable comparator0 envent, bit18 counter overflow interrupt, bit15 enable comparator0 inerrupt, + __IO uint32_t RTCCNT; //0x28 current RTC counter + __IO uint32_t RTCCC0; //0x2c + __IO uint32_t RTCCC1; //0x30 + __IO uint32_t RTCCC2; //0x34 + __IO uint32_t RTCFLAG; //0x38 + __IO uint32_t RTCCLK0; //0x3C bit3:0 = sysclk_t: 1 dll 32m, 2 xtal 16m, 3 dll 48m, 4 dll 64m, 5 dll 96m + __IO uint32_t RTCCLK1; //0x40 bit18 - xtal output to digital enable + __IO uint32_t RTCCFG1; //0x44 - [bit16] enable digclk 96M, [bit7] enable DLL, 25:24 g_rxAdcClkSel 26:25 sel_rxadc_dbl_clk_32M_polarity, 23:22 g_rfPhyClkSel, 6:5 trim dll/dbl ldo vout + __IO uint32_t reserved0[5]; //0x48 4c 50 54 58 + __IO uint32_t RTCCFG2; //0x5C - [bit16] 16M [bit8:4] cnt [bit3] track_en_rc32k + __IO uint32_t reserved1; //0x60 + __IO uint32_t RTCTRCCNT; //0x64 RC 32KHz tracking counter, calculate 16MHz ticks number per RC32KHz cycle, counter_tracking_wakeup + __IO uint32_t RTCTRCNT; //0x68 + __IO uint32_t reserved2[13]; //0x6c 70 74 78 7c 80 84 88 8c 90 94 98 9c + __IO uint32_t REG_S9; //0xa0 + __IO uint32_t REG_S10; //0xa4 + __IO uint32_t REG_S11; //0xa8 bit0 sleep_flag + __IO uint32_t IDLE_REG; //0xac + __IO uint32_t GPIO_WAKEUP_SRC[2]; //0xb0 b4 + __IO uint32_t PCLK_CLK_GATE; //0xb8 bit0 pclk_clk_gate_en + __IO uint32_t XTAL_16M_CTRL; //0xbc + __IO uint32_t SLEEP_R[4]; //0xc0 c4 c8 cc + +} AP_AON_TypeDef; + + +typedef struct +{ + __IO uint32_t RTCCTL; //0x24 + __IO uint32_t RTCCNT; //0x28 + __IO uint32_t RTCCC0; //0x2c + __IO uint32_t RTCCC1; //0x30 + __IO uint32_t RTCCC2; //0x34 + __IO uint32_t RTCFLAG; //0x38 +} AP_RTC_TypeDef; + +typedef struct +{ + __IO uint32_t io_wu_mask_31_0; //0xa0 + __IO uint32_t io_wu_mask_34_32; //0xa4 +} AP_Wakeup_TypeDef; + +typedef struct +{ + __IO uint32_t CLKSEL; //0x3c + __IO uint32_t CLKHF_CTL0; //0x40 + __IO uint32_t CLKHF_CTL1; //0x44 + __IO uint32_t ANA_CTL; //0x48 + __IO uint32_t mem_0_1_dvs; //0x4c + __IO uint32_t mem_2_3_4_dvs; //0x50 + __IO uint32_t efuse_cfg; //0x54 + __IO uint32_t chip_state; //0x58 + __IO uint32_t cal_rw; //0x5c + __IO uint32_t cal_ro0; //0x60 + __IO uint32_t cal_ro1; //0x64 + __IO uint32_t cal_ro2; //0x68 + __IO uint32_t ADC_CTL0; //0x6c + __IO uint32_t ADC_CTL1; //0x70 + __IO uint32_t ADC_CTL2; //0x74 + __IO uint32_t ADC_CTL3; //0x78 + __IO uint32_t ADC_CTL4; //0x7c + uint32_t reserved1[48]; + __IO uint32_t EFUSE_PROG[2];//0x140 + uint32_t reserved2[6]; + __IO uint32_t EFUSE0[2];//0x160 + __IO uint32_t EFUSE1[2];//0x168 + __IO uint32_t EFUSE2[2];//0x170 + __IO uint32_t EFUSE3[2];//0x178 + __IO uint32_t SECURTY_STATE;//0x180 +} AP_PCRM_TypeDef; + +typedef struct +{ + __IO uint32_t enable; //0x00 + __IO uint32_t reserve0[2]; //0x04~0x08 + __IO uint32_t control_1; //0x0c + __IO uint32_t control_2; //0x10 + __IO uint32_t control_3; //0x14 + __IO uint32_t control_4; //0x18 + __IO uint32_t compare_reset; //0x1c + __IO uint32_t int_pointer_ch0_ch3; //0x20 + __IO uint32_t int_pointer_ch4_ch7; //0x24 + //__IO uint32_t int_pointer[2]; //0x20~0x24 + __IO uint32_t reserve1[3]; //0x28~0x30 + __IO uint32_t intr_mask; //0x34 + __IO uint32_t intr_clear; //0x38 + __IO uint32_t intr_status; //0x3c + __IO uint32_t compare_cfg[8]; //0x40~0x5c +} AP_ADCC_TypeDef; + +typedef struct +{ + __IO uint32_t config; //0x0,QSPI Configuration Register,R/W + __IO uint32_t read_instr; //0x4,Device Read Instruction Register,R/W + __IO uint32_t write_instr; //0x8,Device Write Instruction Register,R/W + __IO uint32_t delay; //0xC,QSPI Device Delay Register,R/W + __IO uint32_t rddata_capture; //0x10,Read Data Capture Register,R/W + __IO uint32_t dev_size; //0x14,Device Size Register,R/W + __IO uint32_t sram_part; //0x18,SRAM Partition Register,R/W + __IO uint32_t indirect_ahb_addr_trig; //0x1C,Indirect AHB Address Trigger Register,R/W + __IO uint32_t dma_peripheral; //0x20,DMA Peripheral Register,R/W + __IO uint32_t remap; //0x24,Remap Address Register,R/W + __IO uint32_t mode_bit; //0x28,Mode Bit Register,R/W + __IO uint32_t sram_fill_level; //0x2C,SRAM Fill Level Register,RO + __IO uint32_t tx_threshold; //0x30,TX Threshold Register,R/W + __IO uint32_t rx_threshold; //0x34,RX Threshold Register,R/W + __IO uint32_t wr_completion_ctrl; //0x38,Write Completion Control Register,R/W + __IO uint32_t poll_expire; //0x3C,Polling Expiration Register,R/W + __IO uint32_t int_status; //0x40,Interrupt Status Register,R/W + __IO uint32_t int_mask; //0x44,Interrupt Mask,R/W + __I uint32_t n1[2]; //0x48~0x4c,Empty + __IO uint32_t low_wr_protection; //0x50,Lower Write Protection Register,R/W + __IO uint32_t up_wr_protection; //0x54,Upper Write Protection Register,R/W + __IO uint32_t wr_protection; //0x58,Write Protection Register,R/W + __I uint32_t n2; //0x5c,Empty + __IO uint32_t indirect_rd; //0x60,Indirect Read Transfer Register,R/W + __IO uint32_t indirect_rd_watermark; //0x64,Indirect Read Transfer Watermark Register,R/W + __IO uint32_t indirect_rd_start_addr; //0x68,Indirect Read Transfer Start Address Register,R/W + __IO uint32_t indirect_rd_num; //0x6C,Indirect Read Transfer Number Bytes Register,R/W + __IO uint32_t indirect_wr; //0x70,Indirect Write Transfer Register,R/W + __IO uint32_t indirect_wr_watermark; //0x74,Indirect Write Transfer Watermark Register,R/W + __IO uint32_t indirect_wr_start_addr; //0x78,Indirect Write Transfer Start Address Register,R/W + __IO uint32_t indirect_wr_cnt; //0x7C,Indirect Write Transfer Count Register,R/W + __IO uint32_t indirect_ahb_trig_addr_range; //0x80,Indirect AHB Trigger Address Range Register,R/W + __I uint32_t n3[3]; //0x84~0x8c,Empty + __IO uint32_t fcmd; //0x90,Flash Command Register,R/W + __IO uint32_t fcmd_addr; //0x94,Flash Command Address Registers,R/W + __I uint32_t n4[2]; //0x98~0x9c,Empty + __IO uint32_t fcmd_rddata[2]; //0xA0,Flash Command Read Data Register (low-a0, up-a4),RO + __IO uint32_t fcmd_wrdata[2]; //0xA8,Flash Command Write Data Register (low-a8, up-ac),R/W + __IO uint32_t poll_fstatus; //0xB0,Polling Flash Status Register,RO + //__IO uint32_t ; //0xFC,Module ID Register,RO +} AP_SPIF_TypeDef; + +typedef struct +{ + __IO uint32_t ctrl0; //0xc0 + __IO uint32_t ctrl1; //0xc4 + __IO uint32_t mk_in_en; //0xc8 + __IO uint32_t mkc[6]; //0xcc~0xe0 +} AP_KSCAN_TypeDef; + +typedef struct +{ + __IO uint32_t pwmen; +} AP_PWM_TypeDef; + + +typedef struct +{ + __IO uint32_t ctrl0; + __IO uint32_t ctrl1; +} AP_PWMCTRL_TypeDef; + + + +typedef struct +{ + __IO uint32_t SAR; + __IO uint32_t SAR_H; + __IO uint32_t DAR; + __IO uint32_t DAR_H; + __IO uint32_t LLP; + __IO uint32_t LLP_H; + __IO uint32_t CTL; + __IO uint32_t CTL_H; + __IO uint32_t SSTAT; + __IO uint32_t SSTAT_H; + __IO uint32_t DSTAT; + __IO uint32_t DSTAT_L; + __IO uint32_t SSTATAR; + __IO uint32_t SSTATAR_H; + __IO uint32_t DSTATAR; + __IO uint32_t DSTATAR_H; + __IO uint32_t CFG; + __IO uint32_t CFG_H; + __IO uint32_t rsv[4]; + +} AP_DMA_CH_TypeDef; + +typedef struct +{ + + __IO uint32_t RawTfr; //0x2c0 + __IO uint32_t RawTfr_H; //0x2c4 + __IO uint32_t RawBlock; //0x2c8 + __IO uint32_t RawBlock_H; //0x2cc + __IO uint32_t RawSrcTran; //0x2d0 + __IO uint32_t RawSrcTran_H; //0x2d4 + __IO uint32_t RawDstTran; //0x2d8 + __IO uint32_t RawDstTran_H; //0x2dc + __IO uint32_t RawErr; //0x2e0 + __IO uint32_t RawErr_H; //0x2e4 + + __IO uint32_t StatusTfr; //0x2e8 + __IO uint32_t StatusTfr_H; //0x2ec + __IO uint32_t StatusBlock; //0x2f0 + __IO uint32_t StatusBlock_H; //0x2f4 + __IO uint32_t StatusSrcTran; //0x2f8 + __IO uint32_t StatusSrcTran_H; //0x2fc + __IO uint32_t StatusDstTran; //0x300 + __IO uint32_t StatusDstTran_H; //0x304 + __IO uint32_t StatusErr; //0x308 + __IO uint32_t StatusErr_H; //0x30c + + __IO uint32_t MaskTfr; //0x310 + __IO uint32_t MaskTfr_H; //0x314 + __IO uint32_t MaskBlock; //0x318 + __IO uint32_t MaskBlock_H; //0x31c + __IO uint32_t MaskSrcTran; //0x320 + __IO uint32_t MaskSrcTran_H; //0x324 + __IO uint32_t MaskDstTran; //0x328 + __IO uint32_t MaskDstTran_H; //0x32c + __IO uint32_t MaskErr; //0x330 + __IO uint32_t MaskErr_H; //0x334 + + __IO uint32_t ClearTfr; //0x338 + __IO uint32_t ClearTfr_H; //0x33c + __IO uint32_t ClearBlock; //0x340 + __IO uint32_t ClearBlock_H; //0x344 + __IO uint32_t ClearSrcTran; //0x348 + __IO uint32_t ClearSrcTran_H; //0x34c + __IO uint32_t ClearDstTran; //0x350 + __IO uint32_t ClearDstTran_H; //0x354 + __IO uint32_t ClearErr; //0x358 + __IO uint32_t ClearErr_H; //0x35c + __IO uint32_t StatusInt; //0x360 + __IO uint32_t StatusInt_H; //0x364 + +} AP_DMA_INT_TypeDef; + +typedef struct +{ + __IO uint32_t ReqSrcReg; //0x368 + __IO uint32_t ReqSrcReg_H; //0x36c + __IO uint32_t ReqDstReg; //0x370 + __IO uint32_t ReqDstReg_H; //0x374 + __IO uint32_t SglReqSrcReg; //0x378 + __IO uint32_t SglReqSrcReg_H; //0x37c + __IO uint32_t SglReqDstReg; //0x380 + __IO uint32_t SglReqDstReg_H; //0x384 + __IO uint32_t LstSrcReg; //0x388 + __IO uint32_t LstSrcReg_H; //0x38c + __IO uint32_t LstDstReg; //0x390 + __IO uint32_t LstDstReg_H; //0x394 + +} AP_DMA_SW_HANDSHAKE_TypeDef; + +typedef struct +{ + __IO uint32_t DmaCfgReg; //0x398 + __IO uint32_t DmaCfgReg_H; //0x39c + __IO uint32_t ChEnReg; //0x3a0 + __IO uint32_t ChEnReg_H; //0x3a4 + __IO uint32_t DmaIdReg; //0x3a8 + __IO uint32_t DmaIdReg_H; //0x3ac + __IO uint32_t DmaTestReg; //0x3b0 + __IO uint32_t DmaTestReg_H; //0x3b4 + __IO uint32_t rsv1[4]; + __IO uint32_t DMA_COMP_PARAMS_6; //0x3c8 + __IO uint32_t DMA_COMP_PARAMS_6_H; //0x3cc + __IO uint32_t DMA_COMP_PARAMS_5; //0x3d0 + __IO uint32_t DMA_COMP_PARAMS_5_H; //0x3d4 + __IO uint32_t DMA_COMP_PARAMS_4; //0x3d8 + __IO uint32_t DMA_COMP_PARAMS_4_H; //0x3dc + __IO uint32_t DMA_COMP_PARAMS_3; //0x3e0 + __IO uint32_t DMA_COMP_PARAMS_3_H; //0x3e4 + __IO uint32_t DMA_COMP_PARAMS_2; //0x3e8 + __IO uint32_t DMA_COMP_PARAMS_2_H; //0x3ec + __IO uint32_t DMA_COMP_PARAMS_1; //0x3f0 + __IO uint32_t DMA_COMP_PARAMS_1_H; //0x3f4 + __IO uint32_t DMA_ID; //0x3f8 + __IO uint32_t DMA_ID_H; //0x3fc +} AP_DMA_MISC_TypeDef; + + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + + +/******************************************************************************/ +/* Peripheral memory map(AP) */ +/******************************************************************************/ +/* Base addresses */ +#define AP_APB0_BASE (0x40000000UL) +#define SPIF_BASE_ADDR (0x11000000) /*spif*/ + +#define AP_PCR_BASE (AP_APB0_BASE + 0x0000)/*pcr*//* APB0 peripherals */ + +#define AP_TIM1_BASE (AP_APB0_BASE + 0x1000) +#define AP_TIM2_BASE (AP_APB0_BASE + 0x1014) +#define AP_TIM3_BASE (AP_APB0_BASE + 0x1028) +#define AP_TIM4_BASE (AP_APB0_BASE + 0x103c) +#define AP_TIM5_BASE (AP_APB0_BASE + 0x1050) +#define AP_TIM6_BASE (AP_APB0_BASE + 0x1064) +#define AP_TIM_SYS_BASE (AP_APB0_BASE + 0x10a0) + +#define AP_WDT_BASE (AP_APB0_BASE + 0x2000) +#define AP_COM_BASE (AP_APB0_BASE + 0x3000)/*com*/ +#define AP_IOMUX_BASE (AP_APB0_BASE + 0x3800)/*iomux*/ +#define AP_UART0_BASE (AP_APB0_BASE + 0x4000)/*uart0*/ +#define AP_I2C0_BASE (AP_APB0_BASE + 0x5000)/*i2c0*/ +#define AP_I2C1_BASE (AP_APB0_BASE + 0x5800)/*i2c1*/ +#define AP_SPI0_BASE (AP_APB0_BASE + 0x6000)/*spi0*/ +#define AP_SPI1_BASE (AP_APB0_BASE + 0x7000)/*spi1*/ +#define AP_GPIOA_BASE (AP_APB0_BASE + 0x8000)/*gpio*/ +#define AP_UART1_BASE (AP_APB0_BASE + 0x9000)/*uart1*/ +#define AP_DMIC_BASE (AP_APB0_BASE + 0xA000) +#define AP_QDEC_BASE (AP_APB0_BASE + 0xB000)/*qdec*/ +#define AP_CACHE_BASE (AP_APB0_BASE + 0xC000) +#define AP_SPIF_BASE (AP_APB0_BASE + 0xC800)/*spif*/ +#define AP_KSCAN_BASE (AP_APB0_BASE + 0xD0C0)/*kscan*/ +#define AP_PWM_BASE (AP_APB0_BASE + 0xE000)/*pwm*/ +#define AP_AON_BASE (AP_APB0_BASE + 0xF000)/*aon*/ +#define AP_RTC_BASE (AP_APB0_BASE + 0xF024)/*rtc*/ +#define AP_PCRM_BASE (AP_APB0_BASE + 0xF03c)/*pcrm*/ +#define AP_WAKEUP_BASE (AP_APB0_BASE + 0xF0a0)/*wakeup*/ +#define AP_DMAC_BASE (AP_APB0_BASE + 0x10000)/*dmac*/ +#define ADCC_BASE_ADDR (AP_APB0_BASE + 0x50000)/*adcc*/ + +/*bb_top*/ +/*linklayer*/ + +#define SRAM0_BASE_ADDRESS 0x1FFF0000 +#define SRAM1_BASE_ADDRESS 0x1FFF4000 +#define SRAM2_BASE_ADDRESS 0x1FFF8000 + + +///////////////////////////////////////////////////////////// +#define AP_PCR ((AP_PCR_TypeDef *) AP_PCR_BASE) + +#define AP_TIM1 ((AP_TIM_TypeDef *) AP_TIM1_BASE) +#define AP_TIM2 ((AP_TIM_TypeDef *) AP_TIM2_BASE) +#define AP_TIM3 ((AP_TIM_TypeDef *) AP_TIM3_BASE) +#define AP_TIM4 ((AP_TIM_TypeDef *) AP_TIM4_BASE) +#define AP_TIM5 ((AP_TIM_TypeDef *) AP_TIM5_BASE) +#define AP_TIM6 ((AP_TIM_TypeDef *) AP_TIM6_BASE) +#define AP_TIMS ((AP_TIM_SYS_TypeDef *) AP_TIM_SYS_BASE) + +#define AP_WDT ((AP_WDT_TypeDef *) AP_WDT_BASE) +#define AP_COM ((AP_COM_TypeDef *) AP_COM_BASE) +#define AP_IOMUX ((IOMUX_TypeDef *) AP_IOMUX_BASE) +#define AP_UART0 ((AP_UART_TypeDef *) AP_UART0_BASE) +#define AP_I2C0 ((AP_I2C_TypeDef *) AP_I2C0_BASE) +#define AP_I2C1 ((AP_I2C_TypeDef *) AP_I2C1_BASE) +#define AP_SPI0 ((AP_SSI_TypeDef *) AP_SPI0_BASE) +#define AP_SPI1 ((AP_SSI_TypeDef *) AP_SPI1_BASE) +#define AP_GPIO ((AP_GPIO_TypeDef *) AP_GPIOA_BASE) +#define AP_UART1 ((AP_UART_TypeDef *) AP_UART1_BASE) +#define AP_CACHE ((AP_CACHE_TypeDef *) AP_CACHE_BASE) +#define AP_SPIF ((AP_SPIF_TypeDef *) AP_SPIF_BASE) +#define AP_KSCAN ((AP_KSCAN_TypeDef *) AP_KSCAN_BASE) +#define AP_PWM ((AP_PWM_TypeDef *) AP_PWM_BASE) +#define AP_PWM_CTRL(n) ((AP_PWMCTRL_TypeDef *) (AP_PWM_BASE + 4 + n*12)) +#define AP_AON ((AP_AON_TypeDef *) AP_AON_BASE) +#define AP_RTC ((AP_RTC_TypeDef *) AP_RTC_BASE) +#define AP_PCRM ((AP_PCRM_TypeDef *) AP_PCRM_BASE) +#define AP_WAKEUP ((AP_Wakeup_TypeDef*) AP_WAKEUP_BASE) +#define AP_ADCC ((AP_ADCC_TypeDef *) ADCC_BASE_ADDR) + +#define AP_DMA_CH_CFG(n) ((AP_DMA_CH_TypeDef *) (AP_DMAC_BASE+0x58*n)) +#define AP_DMA_INT ((AP_DMA_INT_TypeDef *) (AP_DMAC_BASE+0x2c0)) +#define AP_DMA_SW_HANDSHAKE ((AP_DMA_SW_HANDSHAKE_TypeDef *) (AP_DMAC_BASE+0x368)) +#define AP_DMA_MISC ((AP_DMA_MISC_TypeDef *) (AP_DMAC_BASE+0x398)) +/* + watchdog enable state,enable or not. +*/ +#define AP_WDT_ENABLE_STATE ((AP_WDT->CR & 0x01))//1:enable 0:disable +#define AP_WDT_FEED do{AP_WDT->CRR = 0x76;}while(0) + +/******************************************************************************/ +/* Peripheral memory map(CP) */ +/******************************************************************************/ +/* Base addresses */ +#define IRQ_PRIO_REALTIME 0 +#define IRQ_PRIO_HIGH 1 +#define IRQ_PRIO_HAL 2 +#define IRQ_PRIO_THREAD 3 +#define IRQ_PRIO_APP 3 + + +#endif diff --git a/ota_boot/source/include/types.h b/ota_boot/source/include/types.h new file mode 100644 index 0000000..541526a --- /dev/null +++ b/ota_boot/source/include/types.h @@ -0,0 +1,156 @@ + +#ifndef _TYPES_H_ +#define _TYPES_H_ + +#include +#include +typedef signed char int8; //!< Signed 8 bit integer +typedef unsigned char uint8; //!< Unsigned 8 bit integer + +typedef signed short int16; //!< Signed 16 bit integer +typedef unsigned short uint16; //!< Unsigned 16 bit integer + +typedef signed long int32; //!< Signed 32 bit integer +typedef unsigned long uint32; //!< Unsigned 32 bit integer + +typedef uint8 halDataAlign_t; //!< Used for byte alignment + +#ifdef __GCC + #define ALIGN4_U8 _Alignas(4) uint8 + #define ALIGN4_U16 _Alignas(4) uint16 + #define ALIGN4_INT8 _Alignas(4) int8 + #define ALIGN4_INT16 _Alignas(4) int16 +#else + #define ALIGN4_U8 __align(4) uint8 + #define ALIGN4_U16 __align(4) uint16 + #define ALIGN4_INT8 __align(4) int8 + #define ALIGN4_INT16 __align(4) int16 +#endif + +#define BIT(n) (1ul << (n)) + +#define write_reg(addr,data) (*(volatile unsigned int *)(addr)=(unsigned int)(data)) +#define read_reg(addr) (*(volatile unsigned int *)(addr)) + +//bit operations +#define BM_SET(addr,bit) ( *(addr) |= (bit) ) //bit set +#define BM_CLR(addr,bit) ( *(addr) &= ~(bit) ) //bit clear +#define BM_IS_SET(addr,bit) ( *(addr) & (bit) ) //judge bit is set + + + +#ifndef BV + #define BV(n) (1 << (n)) +#endif + +#ifndef BF + #define BF(x,b,s) (((x) & (b)) >> (s)) +#endif + +#ifndef MIN + #define MIN(n,m) (((n) < (m)) ? (n) : (m)) +#endif + +#ifndef MAX + #define MAX(n,m) (((n) < (m)) ? (m) : (n)) +#endif + +#ifndef ABS + #define ABS(n) (((n) < 0) ? -(n) : (n)) +#endif + + +/* takes a byte out of a uint32 : var - uint32, ByteNum - byte to take out (0 - 3) */ +#define BREAK_UINT32( var, ByteNum ) \ + (uint8)((uint32)(((var) >>((ByteNum) * 8)) & 0x00FF)) + +#define BUILD_UINT32(Byte0, Byte1, Byte2, Byte3) \ + ((uint32)((uint32)((Byte0) & 0x00FF) \ + + ((uint32)((Byte1) & 0x00FF) << 8) \ + + ((uint32)((Byte2) & 0x00FF) << 16) \ + + ((uint32)((Byte3) & 0x00FF) << 24))) + +#define BUILD_UINT16(loByte, hiByte) \ + ((uint16)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8))) + +#define HI_UINT16(a) (((a) >> 8) & 0xFF) +#define LO_UINT16(a) ((a) & 0xFF) + +#define BUILD_UINT8(hiByte, loByte) \ + ((uint8)(((loByte) & 0x0F) + (((hiByte) & 0x0F) << 4))) + + +// Write the 32bit value of 'val' in little endian format to the buffer pointed +// to by pBuf, and increment pBuf by 4 +#define UINT32_TO_BUF_LITTLE_ENDIAN(pBuf,val) \ + do { \ + *(pBuf)++ = (((val) >> 0) & 0xFF); \ + *(pBuf)++ = (((val) >> 8) & 0xFF); \ + *(pBuf)++ = (((val) >> 16) & 0xFF); \ + *(pBuf)++ = (((val) >> 24) & 0xFF); \ + } while (0) + +// Return the 32bit little-endian formatted value pointed to by pBuf, and increment pBuf by 4 +#define BUF_TO_UINT32_LITTLE_ENDIAN(pBuf) (((pBuf) += 4), BUILD_UINT32((pBuf)[-4], (pBuf)[-3], (pBuf)[-2], (pBuf)[-1])) + +#ifndef GET_BIT + #define GET_BIT(DISCS, IDX) (((DISCS)[((IDX) / 8)] & BV((IDX) % 8)) ? TRUE : FALSE) +#endif +#ifndef SET_BIT + #define SET_BIT(DISCS, IDX) (((DISCS)[((IDX) / 8)] |= BV((IDX) % 8))) +#endif +#ifndef CLR_BIT + #define CLR_BIT(DISCS, IDX) (((DISCS)[((IDX) / 8)] &= (BV((IDX) % 8) ^ 0xFF))) +#endif + + +/* ------------------------------------------------------------------------------------------------ + Standard Defines + ------------------------------------------------------------------------------------------------ +*/ +#ifndef TRUE + #define TRUE 1 +#endif + +#ifndef FALSE + #define FALSE 0 +#endif + +#ifndef NULL + #define NULL 0 +#endif + +#define HAL_WAIT_CONDITION(condition) {while(!(condition)){}} + + +#define HAL_WAIT_CONDITION_TIMEOUT(condition, timeout) {\ + volatile int val = 0;\ + while(!(condition)){\ + if(val ++ > timeout)\ + return PPlus_ERR_TIMEOUT;\ + }\ + } + +#define HAL_WAIT_CONDITION_TIMEOUT_WO_RETURN(condition, timeout) {\ + volatile int val = 0;\ + while(!(condition)){\ + if(val ++ > timeout)\ + break;\ + }\ + } + + +typedef struct _comm_evt_t +{ + unsigned int type; + unsigned char* data; + unsigned int len; +} comm_evt_t; + +typedef void (*comm_cb_t)(comm_evt_t* pev); + +#define __ATTR_SECTION_SRAM__ __attribute__((section("_section_sram_code_"))) +#define __ATTR_SECTION_XIP__ __attribute__((section("_section_xip_code_"))) + +#endif + diff --git a/ota_boot/source/main.c b/ota_boot/source/main.c new file mode 100644 index 0000000..d92c469 --- /dev/null +++ b/ota_boot/source/main.c @@ -0,0 +1,124 @@ +/* + main.c +*/ +#include +#include "global_config.h" +#include "rom_sym_def.h" +#include "ota_boot.h" +#include "bus_dev.h" + + +/*******************************************************************************/ +extern int m_in_critical_region; +extern const uint32_t _sbss; +extern const uint32_t _ebss; + +/**************************************************************************** + Name: c_start + + Description: + This is the reset entry point. + + ****************************************************************************/ + +#define WR_BLK_SIZE 256 + +/* Заголовок OTA */ +typedef struct _app_info_t { + uint32_t flag; // id = START_UP_FLAG + uint32_t seg_count; // кол-во сегментов + uint32_t start_addr; // стартовый/run адрес (if = -1 -> берестя из первого значения != -1 у сегмента) + uint32_t app_size; // размер OTA без 4-х байт CRC32 +} app_info_t; + +app_info_t info_app; + +/* Описание сегментов OTA */ +typedef struct _app_info_seg_t { + uint32_t faddr; // адрес записи в Flash + uint32_t size; // размер сегмента + uint32_t waddr; // рабочий адрес + uint32_t chk; // не используется +} app_info_seg_t; + +app_info_seg_t seg_info; + +uint8_t sector_buf[WR_BLK_SIZE]; + +__attribute__ ((naked)) +void copy_app_code(void) { + uint32_t blksize = WR_BLK_SIZE; + uint32_t rfaddr = FADDR_APP_SEC + 0xfc; + uint32_t dfaddr = 0; + uint32_t wfaddr = FADDR_BOOT_ROM_INFO; + uint32_t count; + __disable_irq(); + spif_read(rfaddr, (uint8_t*)&rfaddr, 4); + spif_read(rfaddr, (uint8_t*)&info_app, sizeof(info_app)); + if(info_app.flag == START_UP_FLAG + && info_app.seg_count + && info_app.seg_count < 16 + && info_app.app_size < FADDR_APP_SEC - FADDR_OTA_SEC + ){ + dfaddr = rfaddr + 0x100; + count = info_app.seg_count; + spif_erase_sector(wfaddr); + spif_write(wfaddr, (uint8_t*)&info_app.seg_count, 4); + spif_write(wfaddr + 8, (uint8_t*)&info_app.start_addr, 4); + wfaddr += 0x100; + while(count--) { + rfaddr += 16; + spif_read(rfaddr, (uint8_t*)&seg_info, 12); + spif_write(wfaddr, (uint8_t*)&seg_info, 12); + wfaddr += 16; + } + wfaddr = FADDR_OTA_SEC; + count = info_app.app_size; + while(count) { + if(count < WR_BLK_SIZE) + blksize = count; + if((wfaddr & (FLASH_SECTOR_SIZE - 1)) == 0) + spif_erase_sector(wfaddr); + spif_read(dfaddr, sector_buf, blksize); + spif_write(wfaddr, sector_buf, blksize); + dfaddr += blksize; + wfaddr += blksize; + count -= blksize; + } + spif_erase_sector(FADDR_APP_SEC); + } + //__disable_irq(); + m_in_critical_region++; + /** + config reset casue as RSTC_WARM_NDWC + reset path walkaround dwc + */ + AP_AON->RTCCC2 = BOOT_FLG_OTA; // [0x4000f034] == 0x55 -> OTA + AP_AON->SLEEP_R[0] = 4; + AP_AON->SLEEP_R[1] = 0; + AP_PCR->SW_RESET1 = 0; + while(1); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// +//xip flash read instrcution +#define XFRD_FCMD_READ 0x0000003 +#define XFRD_FCMD_READ_DUAL 0x801003B +#define XFRD_FCMD_READ_QUAD 0x801006B + +int main(void) { + /* Clear .bss. We'll do this inline (vs. calling memset) just to be + certain that there are no issues with the state of global variables. + */ + uint8_t* dest = (uint8_t*)&_sbss; + uint8_t* edest = (uint8_t*)&_ebss; + + memset(dest, 0, edest - dest); + + g_system_clk = SYS_CLK_XTAL_16M; // SYS_CLK_XTAL_16M, SYS_CLK_DBL_32M, SYS_CLK_DLL_64M + spif_config(SYS_CLK_DLL_64M, 1, XFRD_FCMD_READ_DUAL, 0, 0); + copy_app_code(); + return 0; +} + + diff --git a/ota_boot/source/misc/CMSIS/device/phyplus/phy6222.h b/ota_boot/source/misc/CMSIS/device/phyplus/phy6222.h new file mode 100644 index 0000000..e09f1b4 --- /dev/null +++ b/ota_boot/source/misc/CMSIS/device/phyplus/phy6222.h @@ -0,0 +1,116 @@ + +#ifndef __PHY62XX_H +#define __PHY62XX_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @addtogroup Configuration_section_for_CMSIS + @{ +*/ +/** + @brief Configuration of the Cortex-M0+ Processor and Core Peripherals +*/ +#define __CM0_REV 0 /*!< Core Revision r0p0 */ +#define __MPU_PRESENT 0 /*!< M0 provides an MPU */ +#define __VTOR_PRESENT 0 /*!< Vector Table Register supported */ +#define __NVIC_PRIO_BITS 2 /*!< M0 uses 2 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ + + +/** + @} +*/ + +/** @addtogroup Peripheral_interrupt_number_definition + @{ +*/ + +/** + @brief STM32L0xx Interrupt Number Definition, according to the selected device + in @ref Library_configuration_section +*/ + +/*!< Interrupt Number Definition */ +typedef enum +{ + /****** Cortex-M0 Processor Exceptions Numbers ******************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 3 Cortex-M0+ Hard Fault Interrupt */ + SVC_IRQn = -5, /*!< 11 Cortex-M0+ SV Call Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M0+ Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M0+ System Tick Interrupt */ + + /****** STM32L-0 specific Interrupt Numbers *********************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ + PVD_IRQn = 1, /*!< PVD through EXTI Line detect Interrupt */ + RTC_IRQn = 2, /*!< RTC through EXTI Line Interrupt */ + FLASH_IRQn = 3, /*!< FLASH Interrupt */ + RCC_IRQn = 4, /*!< RCC Interrupt */ + EXTI0_1_IRQn = 5, /*!< EXTI Line 0 and 1 Interrupts */ + EXTI2_3_IRQn = 6, /*!< EXTI Line 2 and 3 Interrupts */ + EXTI4_15_IRQn = 7, /*!< EXTI Line 4 to 15 Interrupts */ + DMA1_Channel1_IRQn = 9, /*!< DMA1 Channel 1 Interrupt */ + DMA1_Channel2_3_IRQn = 10, /*!< DMA1 Channel 2 and Channel 3 Interrupts */ + DMA1_Channel4_5_6_7_IRQn = 11, /*!< DMA1 Channel 4, Channel 5, Channel 6 and Channel 7 Interrupts */ + ADC1_COMP_IRQn = 12, /*!< ADC1, COMP1 and COMP2 Interrupts */ + LPTIM1_IRQn = 13, /*!< LPTIM1 Interrupt */ + TIM2_IRQn = 15, /*!< TIM2 Interrupt */ + TIM6_IRQn = 17, /*!< TIM6 Interrupt */ + TIM21_IRQn = 20, /*!< TIM21 Interrupt */ + TIM22_IRQn = 22, /*!< TIM22 Interrupt */ + I2C1_IRQn = 23, /*!< I2C1 Interrupt */ + I2C2_IRQn = 24, /*!< I2C2 Interrupt */ + SPI1_IRQn = 25, /*!< SPI1 Interrupt */ + SPI2_IRQn = 26, /*!< SPI2 Interrupt */ + USART1_IRQn = 27, /*!< USART1 Interrupt */ + USART2_IRQn = 28, /*!< USART2 Interrupt */ + LPUART1_IRQn = 29, /*!< LPUART1 Interrupts */ +} IRQn_Type; + +/** + @} +*/ + +#include "core_cm0.h" +//#include "system_m0.h" +#include + + + +/** + @} +*/ + +/******************************************************************************/ +/* For a painless codes migration between the STM32L0xx device product */ +/* lines, the aliases defined below are put in place to overcome the */ +/* differences in the interrupt handlers and IRQn definitions. */ +/* No need to update developed interrupt code when moving across */ +/* product lines within the same STM32L0 Family */ +/******************************************************************************/ + +/* Aliases for __IRQn */ + +/** + @} +*/ + +/** + @} +*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __PHY62XX_H */ + + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + diff --git a/ota_boot/source/misc/CMSIS/device/phyplus/phy6222_start.s b/ota_boot/source/misc/CMSIS/device/phyplus/phy6222_start.s new file mode 100644 index 0000000..7d5d08d --- /dev/null +++ b/ota_boot/source/misc/CMSIS/device/phyplus/phy6222_start.s @@ -0,0 +1,55 @@ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + .file "phy6222_start.s" + + /* *.ld: g_top_irqstack = ORIGIN(sram) + LENGTH(sram) */ + .global g_stack + +.text + .align 2 + .code 16 + .globl __start + .thumb_func + .type __start, %function +__start: + + ldr r1, = g_irqstack_top + msr msp, r1 /* r2>>sp */ + bl main /* R0=IRQ, R1=register save area on stack */ + + + .size __start, .-__start + +#if 0 // Implemented in phy6222_vectors.c +.section .isr_vector + .align 4 + .globl __Vectors + .type __Vectors, %object +__Vectors: + .long 0 + .long __start + + .size __Vectors, . - __Vectors +#endif + +.section .irq_stack + + .align 4 + .global g_irqstack_base + .global g_irqstack_top + +g_irqstack_base: + .space 0x400 +g_irqstack_top: + +.end + + diff --git a/ota_boot/source/misc/CMSIS/device/phyplus/phy6222_vectors.c b/ota_boot/source/misc/CMSIS/device/phyplus/phy6222_vectors.c new file mode 100644 index 0000000..cd06fa6 --- /dev/null +++ b/ota_boot/source/misc/CMSIS/device/phyplus/phy6222_vectors.c @@ -0,0 +1,13 @@ + +#define locate_data(n) __attribute__ ((section(n))) +extern unsigned int g_irqstack_top; +extern void __start(void); +const unsigned _vectors[] locate_data(".isr_vector") = +{ + /* Initial stack */ + (unsigned)(&g_irqstack_top), + + /* Reset exception handler */ + (unsigned)(&__start), + +}; diff --git a/ota_boot/source/misc/CMSIS/include/arm_common_tables.h b/ota_boot/source/misc/CMSIS/include/arm_common_tables.h new file mode 100644 index 0000000..437d816 --- /dev/null +++ b/ota_boot/source/misc/CMSIS/include/arm_common_tables.h @@ -0,0 +1,93 @@ +/* ---------------------------------------------------------------------- + Copyright (C) 2010-2013 ARM Limited. All rights reserved. + + $Date: 17. January 2013 + $Revision: V1.4.1 + + 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 twiddleCoefQ31[6144]; +extern const q15_t twiddleCoefQ15[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]; + + +#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]; + +#endif /* ARM_COMMON_TABLES_H */ diff --git a/ota_boot/source/misc/CMSIS/include/arm_const_structs.h b/ota_boot/source/misc/CMSIS/include/arm_const_structs.h new file mode 100644 index 0000000..d3d1d15 --- /dev/null +++ b/ota_boot/source/misc/CMSIS/include/arm_const_structs.h @@ -0,0 +1,94 @@ +/* ---------------------------------------------------------------------- + Copyright (C) 2010-2013 ARM Limited. All rights reserved. + + $Date: 17. January 2013 + $Revision: V1.4.1 + + 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" + +const arm_cfft_instance_f32 arm_cfft_sR_f32_len16 = +{ + 16, twiddleCoef_16, armBitRevIndexTable16, ARMBITREVINDEXTABLE__16_TABLE_LENGTH +}; + +const arm_cfft_instance_f32 arm_cfft_sR_f32_len32 = +{ + 32, twiddleCoef_32, armBitRevIndexTable32, ARMBITREVINDEXTABLE__32_TABLE_LENGTH +}; + +const arm_cfft_instance_f32 arm_cfft_sR_f32_len64 = +{ + 64, twiddleCoef_64, armBitRevIndexTable64, ARMBITREVINDEXTABLE__64_TABLE_LENGTH +}; + +const arm_cfft_instance_f32 arm_cfft_sR_f32_len128 = +{ + 128, twiddleCoef_128, armBitRevIndexTable128, ARMBITREVINDEXTABLE_128_TABLE_LENGTH +}; + +const arm_cfft_instance_f32 arm_cfft_sR_f32_len256 = +{ + 256, twiddleCoef_256, armBitRevIndexTable256, ARMBITREVINDEXTABLE_256_TABLE_LENGTH +}; + +const arm_cfft_instance_f32 arm_cfft_sR_f32_len512 = +{ + 512, twiddleCoef_512, armBitRevIndexTable512, ARMBITREVINDEXTABLE_512_TABLE_LENGTH +}; + +const arm_cfft_instance_f32 arm_cfft_sR_f32_len1024 = +{ + 1024, twiddleCoef_1024, armBitRevIndexTable1024, ARMBITREVINDEXTABLE1024_TABLE_LENGTH +}; + +const arm_cfft_instance_f32 arm_cfft_sR_f32_len2048 = +{ + 2048, twiddleCoef_2048, armBitRevIndexTable2048, ARMBITREVINDEXTABLE2048_TABLE_LENGTH +}; + +const arm_cfft_instance_f32 arm_cfft_sR_f32_len4096 = +{ + 4096, twiddleCoef_4096, armBitRevIndexTable4096, ARMBITREVINDEXTABLE4096_TABLE_LENGTH +}; + +#endif diff --git a/ota_boot/source/misc/CMSIS/include/arm_math.h b/ota_boot/source/misc/CMSIS/include/arm_math.h new file mode 100644 index 0000000..b201dda --- /dev/null +++ b/ota_boot/source/misc/CMSIS/include/arm_math.h @@ -0,0 +1,7080 @@ +/* ---------------------------------------------------------------------- + Copyright (C) 2010-2013 ARM Limited. All rights reserved. + + $Date: 17. January 2013 + $Revision: V1.4.1 + + Project: CMSIS DSP Library + Title: arm_math.h + + Description: Public header file for CMSIS DSP Library + + Target Processor: 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_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) + - arm_cortexM0b_math.lib (Big endian on Cortex-M3) + + 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-M4/M3/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_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 4.60. + 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 project files to re build libraries on MDK Tool chain in the CMSIS\\DSP_Lib\\Source\\ARM folder. + - arm_cortexM0b_math.uvproj + - arm_cortexM0l_math.uvproj + - arm_cortexM3b_math.uvproj + - arm_cortexM3l_math.uvproj + - arm_cortexM4b_math.uvproj + - arm_cortexM4l_math.uvproj + - arm_cortexM4bf_math.uvproj + - arm_cortexM4lf_math.uvproj + + + The project can be built by opening the appropriate project in MDK-ARM 4.60 chain 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. + + - __FPU_PRESENT: + + Initialize macro __FPU_PRESENT = 1 when building on FPU supported Targets. Enable this macro for M4bf and M4lf libraries + + Copyright Notice + + Copyright (C) 2010-2013 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 + +#define __CMSIS_GENERIC /* disable NVIC and Systick functions */ + +#if 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 + #include "ARMCM4.h" + #warning "Define either ARM_MATH_CM4 OR ARM_MATH_CM3...By Default building on ARM_MATH_CM4....." +#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 TABLE_SIZE 256 +#define TABLE_SPACING_Q31 0x800000 +#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 __ICCARM__ +#define CMSIS_UNUSED +#define __SIMD32_TYPE int32_t __packed +#elif defined __GNUC__ +#define __SIMD32_TYPE int32_t +#define CMSIS_UNUSED __attribute__((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 + +#if defined (ARM_MATH_CM0_FAMILY) && ((defined (__ICCARM__)) ||(defined (__GNUC__)) || defined (__TASKING__) ) + +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) +{ + uint32_t out, tempVal; + uint32_t index, i; + uint32_t signBits; + + if(in > 0) + { + signBits = __CLZ(in) - 1; + } + else + { + signBits = __CLZ(-in) - 1; + } + + /* Convert input sample to 1.31 format */ + in = in << signBits; + /* calculation of index for initial approximated Val */ + index = (uint32_t) (in >> 24u); + 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 = (q31_t) (((q63_t) in * out) >> 31u); + tempVal = 0x7FFFFFFF - tempVal; + /* 1.31 with exp 1 */ + //out = (q31_t) (((q63_t) out * tempVal) >> 30u); + out = (q31_t) clip_q63_to_q31(((q63_t) out * tempVal) >> 30u); + } + + /* 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) +{ + uint32_t out = 0, tempVal = 0; + uint32_t index = 0, i = 0; + uint32_t signBits = 0; + + if(in > 0) + { + signBits = __CLZ(in) - 17; + } + else + { + signBits = __CLZ(-in) - 17; + } + + /* Convert input sample to 1.15 format */ + in = in << signBits; + /* calculation of index for initial approximated Val */ + index = 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 = 0; i < 2; i++) + { + tempVal = (q15_t) (((q31_t) in * out) >> 15); + tempVal = 0x7FFF - tempVal; + /* 1.15 with exp 1 */ + out = (q15_t) (((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 q31_t __QADD8( + q31_t x, + q31_t y) +{ + q31_t sum; + q7_t r, s, t, u; + r = (q7_t) x; + s = (q7_t) y; + r = __SSAT((q31_t) (r + s), 8); + s = __SSAT(((q31_t) (((x << 16) >> 24) + ((y << 16) >> 24))), 8); + t = __SSAT(((q31_t) (((x << 8) >> 24) + ((y << 8) >> 24))), 8); + u = __SSAT(((q31_t) ((x >> 24) + (y >> 24))), 8); + sum = + (((q31_t) u << 24) & 0xFF000000) | (((q31_t) t << 16) & 0x00FF0000) | + (((q31_t) s << 8) & 0x0000FF00) | (r & 0x000000FF); + return sum; +} + +/* + @brief C custom defined QSUB8 for M3 and M0 processors +*/ +static __INLINE q31_t __QSUB8( + q31_t x, + q31_t y) +{ + q31_t sum; + q31_t r, s, t, u; + r = (q7_t) x; + s = (q7_t) y; + r = __SSAT((r - s), 8); + s = __SSAT(((q31_t) (((x << 16) >> 24) - ((y << 16) >> 24))), 8) << 8; + t = __SSAT(((q31_t) (((x << 8) >> 24) - ((y << 8) >> 24))), 8) << 16; + u = __SSAT(((q31_t) ((x >> 24) - (y >> 24))), 8) << 24; + sum = + (u & 0xFF000000) | (t & 0x00FF0000) | (s & 0x0000FF00) | (r & + 0x000000FF); + return sum; +} + +/* + @brief C custom defined QADD16 for M3 and M0 processors +*/ + +/* + @brief C custom defined QADD16 for M3 and M0 processors +*/ +static __INLINE q31_t __QADD16( + q31_t x, + q31_t y) +{ + q31_t sum; + q31_t r, s; + r = (short) x; + s = (short) y; + r = __SSAT(r + s, 16); + s = __SSAT(((q31_t) ((x >> 16) + (y >> 16))), 16) << 16; + sum = (s & 0xFFFF0000) | (r & 0x0000FFFF); + return sum; +} + +/* + @brief C custom defined SHADD16 for M3 and M0 processors +*/ +static __INLINE q31_t __SHADD16( + q31_t x, + q31_t y) +{ + q31_t sum; + q31_t r, s; + r = (short) x; + s = (short) y; + r = ((r >> 1) + (s >> 1)); + s = ((q31_t) ((x >> 17) + (y >> 17))) << 16; + sum = (s & 0xFFFF0000) | (r & 0x0000FFFF); + return sum; +} + +/* + @brief C custom defined QSUB16 for M3 and M0 processors +*/ +static __INLINE q31_t __QSUB16( + q31_t x, + q31_t y) +{ + q31_t sum; + q31_t r, s; + r = (short) x; + s = (short) y; + r = __SSAT(r - s, 16); + s = __SSAT(((q31_t) ((x >> 16) - (y >> 16))), 16) << 16; + sum = (s & 0xFFFF0000) | (r & 0x0000FFFF); + return sum; +} + +/* + @brief C custom defined SHSUB16 for M3 and M0 processors +*/ +static __INLINE q31_t __SHSUB16( + q31_t x, + q31_t y) +{ + q31_t diff; + q31_t r, s; + r = (short) x; + s = (short) y; + r = ((r >> 1) - (s >> 1)); + s = (((x >> 17) - (y >> 17)) << 16); + diff = (s & 0xFFFF0000) | (r & 0x0000FFFF); + return diff; +} + +/* + @brief C custom defined QASX for M3 and M0 processors +*/ +static __INLINE q31_t __QASX( + q31_t x, + q31_t y) +{ + q31_t sum = 0; + sum = + ((sum + + clip_q31_to_q15((q31_t) ((short) (x >> 16) + (short) y))) << 16) + + clip_q31_to_q15((q31_t) ((short) x - (short) (y >> 16))); + return sum; +} + +/* + @brief C custom defined SHASX for M3 and M0 processors +*/ +static __INLINE q31_t __SHASX( + q31_t x, + q31_t y) +{ + q31_t sum; + q31_t r, s; + r = (short) x; + s = (short) y; + r = ((r >> 1) - (y >> 17)); + s = (((x >> 17) + (s >> 1)) << 16); + sum = (s & 0xFFFF0000) | (r & 0x0000FFFF); + return sum; +} + + +/* + @brief C custom defined QSAX for M3 and M0 processors +*/ +static __INLINE q31_t __QSAX( + q31_t x, + q31_t y) +{ + q31_t sum = 0; + sum = + ((sum + + clip_q31_to_q15((q31_t) ((short) (x >> 16) - (short) y))) << 16) + + clip_q31_to_q15((q31_t) ((short) x + (short) (y >> 16))); + return sum; +} + +/* + @brief C custom defined SHSAX for M3 and M0 processors +*/ +static __INLINE q31_t __SHSAX( + q31_t x, + q31_t y) +{ + q31_t sum; + q31_t r, s; + r = (short) x; + s = (short) y; + r = ((r >> 1) + (y >> 17)); + s = (((x >> 17) - (s >> 1)) << 16); + sum = (s & 0xFFFF0000) | (r & 0x0000FFFF); + return sum; +} + +/* + @brief C custom defined SMUSDX for M3 and M0 processors +*/ +static __INLINE q31_t __SMUSDX( + q31_t x, + q31_t y) +{ + return ((q31_t) (((short) x * (short) (y >> 16)) - + ((short) (x >> 16) * (short) y))); +} + +/* + @brief C custom defined SMUADX for M3 and M0 processors +*/ +static __INLINE q31_t __SMUADX( + q31_t x, + q31_t y) +{ + return ((q31_t) (((short) x * (short) (y >> 16)) + + ((short) (x >> 16) * (short) y))); +} + +/* + @brief C custom defined QADD for M3 and M0 processors +*/ +static __INLINE q31_t __QADD( + q31_t x, + q31_t y) +{ + return clip_q63_to_q31((q63_t) x + y); +} + +/* + @brief C custom defined QSUB for M3 and M0 processors +*/ +static __INLINE q31_t __QSUB( + q31_t x, + q31_t y) +{ + return clip_q63_to_q31((q63_t) x - y); +} + +/* + @brief C custom defined SMLAD for M3 and M0 processors +*/ +static __INLINE q31_t __SMLAD( + q31_t x, + q31_t y, + q31_t sum) +{ + return (sum + ((short) (x >> 16) * (short) (y >> 16)) + + ((short) x * (short) y)); +} + +/* + @brief C custom defined SMLADX for M3 and M0 processors +*/ +static __INLINE q31_t __SMLADX( + q31_t x, + q31_t y, + q31_t sum) +{ + return (sum + ((short) (x >> 16) * (short) (y)) + + ((short) x * (short) (y >> 16))); +} + +/* + @brief C custom defined SMLSDX for M3 and M0 processors +*/ +static __INLINE q31_t __SMLSDX( + q31_t x, + q31_t y, + q31_t sum) +{ + return (sum - ((short) (x >> 16) * (short) (y)) + + ((short) x * (short) (y >> 16))); +} + +/* + @brief C custom defined SMLALD for M3 and M0 processors +*/ +static __INLINE q63_t __SMLALD( + q31_t x, + q31_t y, + q63_t sum) +{ + return (sum + ((short) (x >> 16) * (short) (y >> 16)) + + ((short) x * (short) y)); +} + +/* + @brief C custom defined SMLALDX for M3 and M0 processors +*/ +static __INLINE q63_t __SMLALDX( + q31_t x, + q31_t y, + q63_t sum) +{ + return (sum + ((short) (x >> 16) * (short) y)) + + ((short) x * (short) (y >> 16)); +} + +/* + @brief C custom defined SMUAD for M3 and M0 processors +*/ +static __INLINE q31_t __SMUAD( + q31_t x, + q31_t y) +{ + return (((x >> 16) * (y >> 16)) + + (((x << 16) >> 16) * ((y << 16) >> 16))); +} + +/* + @brief C custom defined SMUSD for M3 and M0 processors +*/ +static __INLINE q31_t __SMUSD( + q31_t x, + q31_t y) +{ + return (-((x >> 16) * (y >> 16)) + + (((x << 16) >> 16) * ((y << 16) >> 16))); +} + + +/* + @brief C custom defined SXTB16 for M3 and M0 processors +*/ +static __INLINE q31_t __SXTB16( + q31_t x) +{ + return ((((x << 24) >> 24) & 0x0000FFFF) | + (((x << 8) >> 8) & 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. + @return none. +*/ +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. + @return none +*/ +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. + @return none. +*/ +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. + @return none. +*/ +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. + @return none. +*/ +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. + @return none. +*/ +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. + @return none. +*/ +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. + @return none. +*/ +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. + @return none. +*/ +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. + @return none. +*/ + +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 + @return none +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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 + @return none +*/ + +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. + @return none. +*/ + +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. + @return none +*/ + +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 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 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. + @return none +*/ + +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. + @return none +*/ + +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. + @return none +*/ + +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. + @return none. +*/ +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 + @return none +*/ +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. + @return none. +*/ +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 + @return none +*/ + +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. + @return none. +*/ +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 + @return none +*/ +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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; + +arm_status arm_cfft_radix2_init_q15( + arm_cfft_radix2_instance_q15* S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +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; + +arm_status arm_cfft_radix4_init_q15( + arm_cfft_radix4_instance_q15* S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +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; + +arm_status arm_cfft_radix2_init_q31( + arm_cfft_radix2_instance_q31* S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +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; + + +void arm_cfft_radix4_q31( + const arm_cfft_radix4_instance_q31* S, + q31_t* pSrc); + +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 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. */ + uint32_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. */ + q15_t* pTwiddleAReal; /**< points to the real twiddle factor table. */ + q15_t* pTwiddleBReal; /**< points to the imag twiddle factor table. */ + arm_cfft_radix4_instance_q15* pCfft; /**< points to the complex FFT instance. */ +} arm_rfft_instance_q15; + +arm_status arm_rfft_init_q15( + arm_rfft_instance_q15* S, + arm_cfft_radix4_instance_q15* S_CFFT, + 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. */ + uint32_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. */ + q31_t* pTwiddleAReal; /**< points to the real twiddle factor table. */ + q31_t* pTwiddleBReal; /**< points to the imag twiddle factor table. */ + arm_cfft_radix4_instance_q31* pCfft; /**< points to the complex FFT instance. */ +} arm_rfft_instance_q31; + +arm_status arm_rfft_init_q31( + arm_rfft_instance_q31* S, + arm_cfft_radix4_instance_q31* S_CFFT, + 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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ +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 + @return none. +*/ +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 + @return none. +*/ +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 + @return none. +*/ +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 + @return none. +*/ +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 + @return none. +*/ +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 + @return none. +*/ +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 + @return none. +*/ +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. + @return none. +*/ + +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). + @return none. +*/ + + +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. + @return none. +*/ + +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. + @return none. +*/ + +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). + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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). + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none +*/ + +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. + @return none +*/ + +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. + @return none +*/ + +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. + @return none +*/ + +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. + @return none +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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 + @return none +*/ + +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 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. + @return none. +*/ + +void arm_biquad_cascade_df2T_f32( + const arm_biquad_cascade_df2T_instance_f32* S, + float32_t* pSrc, + float32_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. + @return none +*/ + +void arm_biquad_cascade_df2T_init_f32( + arm_biquad_cascade_df2T_instance_f32* S, + uint8_t numStages, + float32_t* pCoeffs, + float32_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. + @return none. +*/ + +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. + @return none. +*/ +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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). + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none +*/ + +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. + @return none. +*/ + +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. + @return none +*/ + +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. + @return none. +*/ + +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. + @return none +*/ + +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. + @return none. +*/ + +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. + @return none +*/ + +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. + @return none. +*/ + +void arm_sin_cos_f32( + float32_t theta, + float32_t* pSinVal, + float32_t* pCcosVal); + +/* + @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. + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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(S->A0, in); + /* acc += A1 * x[n-1] + A2 * x[n-2] */ + vstate = __SIMD32_CONST(S->state); + acc = __SMLALD(S->A1, (q31_t) *vstate, 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); + + + +/** + @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 + @return none. +*/ + +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 + @return none. + + 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 + @return none. +*/ +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 + @return none. +*/ + + +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.5 * Ialpha + (float32_t) 0.8660254039 *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 + @return none. + + 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 + @return none. +*/ +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 + @return none. + + 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 + @return none. + + 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 + @return none. +*/ +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 + @return none. +*/ + +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 + @return none. + + 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 + @return none. +*/ +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 & 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 + 1u]; + /* 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 & 0xFFF00000) >> 20u); + + 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 + 1u]; + /* 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 (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 + 1u]; + /* 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 (y >> 20u); + } +} +/** + @} 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) + { +// #if __FPU_USED + #if (__FPU_USED == 1) && defined ( __CC_ARM ) + *pOut = __sqrtf(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 = 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 = 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 = 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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ +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. + @return none. +*/ +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. + @return none. +*/ +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. + @return none. +*/ + +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. + @return none. +*/ + +void arm_var_q31( + q31_t* pSrc, + uint32_t blockSize, + q63_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. + @return none. +*/ + +void arm_var_q15( + q15_t* pSrc, + uint32_t blockSize, + q31_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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ + +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. + @return none. +*/ +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. + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ + +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 + @return none. +*/ +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 + @return none +*/ +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 + @return none +*/ +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 + @return none. +*/ +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 + @return none. +*/ +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 + @return none. +*/ +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 + @return none. +*/ +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 + @return none. +*/ +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 & 0xFFF00000) >> 20u); + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & 0xFFF00000) >> 20u); + + /* 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) + nCols * (cI)]; + x2 = pYData[(rI) + nCols * (cI) + 1u]; + /* 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) + nCols * (cI + 1)]; + y2 = pYData[(rI) + nCols * (cI + 1) + 1u]; + /* 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 (acc << 2u); +} + +/** + @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 & 0xFFF00000) >> 20); + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & 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[(rI) + nCols * (cI)]; + x2 = pYData[(rI) + nCols * (cI) + 1u]; + /* 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[(rI) + nCols * (cI + 1)]; + y2 = pYData[(rI) + nCols * (cI + 1) + 1u]; + /* 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 (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 & 0xFFF00000) >> 20); + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & 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[(rI) + nCols * (cI)]; + x2 = pYData[(rI) + nCols * (cI) + 1u]; + /* 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[(rI) + nCols * (cI + 1)]; + y2 = pYData[(rI) + nCols * (cI + 1) + 1u]; + /* 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 (acc >> 40); +} + +/** + @} end of BilinearInterpolate group +*/ + + +#if defined ( __CC_ARM ) //Keil +//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) + +//Enter low optimization region - place directly above function definition +#define LOW_OPTIMIZATION_ENTER \ + _Pragma ("push") \ + _Pragma ("O1") + +//Exit low optimization region - place directly after end of function definition +#define LOW_OPTIMIZATION_EXIT \ + _Pragma ("pop") + +//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(__ICCARM__) //IAR +//SMMLA +#define multAcc_32x32_keep32_R(a, x, y) \ + a += (q31_t) (((q63_t) x * y) >> 32) + +//SMMLS +#define multSub_32x32_keep32_R(a, x, y) \ + a -= (q31_t) (((q63_t) x * y) >> 32) + +//SMMUL +#define mult_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((q63_t) x * y ) >> 32) + +//Enter low optimization region - place directly above function definition +#define LOW_OPTIMIZATION_ENTER \ + _Pragma ("optimize=low") + +//Exit low optimization region - place directly after end of function definition +#define LOW_OPTIMIZATION_EXIT + +//Enter low optimization region - place directly above function definition +#define IAR_ONLY_LOW_OPTIMIZATION_ENTER \ + _Pragma ("optimize=low") + +//Exit low optimization region - place directly after end of function definition +#define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__GNUC__) +//SMMLA +#define multAcc_32x32_keep32_R(a, x, y) \ + a += (q31_t) (((q63_t) x * y) >> 32) + +//SMMLS +#define multSub_32x32_keep32_R(a, x, y) \ + a -= (q31_t) (((q63_t) x * y) >> 32) + +//SMMUL +#define mult_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((q63_t) x * y ) >> 32) + +#define LOW_OPTIMIZATION_ENTER __attribute__(( optimize("-O1") )) + +#define LOW_OPTIMIZATION_EXIT + +#define IAR_ONLY_LOW_OPTIMIZATION_ENTER + +#define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#endif + + + + + +#ifdef __cplusplus +} +#endif + + +#endif /* _ARM_MATH_H */ + + +/** + + End of file. +*/ diff --git a/ota_boot/source/misc/CMSIS/include/core_cm0.h b/ota_boot/source/misc/CMSIS/include/core_cm0.h new file mode 100644 index 0000000..5804170 --- /dev/null +++ b/ota_boot/source/misc/CMSIS/include/core_cm0.h @@ -0,0 +1,690 @@ +/**************************************************************************//** + @file core_cm0.h + @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File + @version V3.20 + @date 25. February 2013 + + @note + + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __CORE_CM0_H_GENERIC +#define __CORE_CM0_H_GENERIC + +/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. +*/ + + +/******************************************************************************* + CMSIS definitions + ******************************************************************************/ +/** \ingroup Cortex_M0 + @{ +*/ + +/* CMSIS CM0 definitions */ +#define __CM0_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ +#define __CM0_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ +#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16) | \ + __CM0_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x00) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) +#define __ASM __asm /*!< asm keyword for ARM Compiler */ +#define __INLINE __inline /*!< inline keyword for ARM Compiler */ +#define __STATIC_INLINE static __inline + +#elif defined ( __ICCARM__ ) +#define __ASM __asm /*!< asm keyword for IAR Compiler */ +#define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ +#define __STATIC_INLINE static inline + +#elif defined ( __GNUC__ ) +#define __ASM __asm /*!< asm keyword for GNU Compiler */ +#define __INLINE inline /*!< inline keyword for GNU Compiler */ +#define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) +#define __ASM __asm /*!< asm keyword for TASKING Compiler */ +#define __INLINE inline /*!< inline keyword for TASKING Compiler */ +#define __STATIC_INLINE static inline + +#endif + +/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all +*/ +#define __FPU_USED 0 + +#if defined ( __CC_ARM ) +#if defined __TARGET_FPU_VFP +#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif + +#elif defined ( __ICCARM__ ) +#if defined __ARMVFP__ +#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif + +#elif defined ( __GNUC__ ) +#if defined (__VFP_FP__) && !defined(__SOFTFP__) +#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif + +#elif defined ( __TASKING__ ) +#if defined __FPU_VFP__ +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif +#endif + +#include /* standard types definitions */ +#include /* Core Instruction Access */ +#include /* Core Function Access */ + +#endif /* __CORE_CM0_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM0_H_DEPENDANT +#define __CORE_CM0_H_DEPENDANT + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES +#ifndef __CM0_REV +#define __CM0_REV 0x0000 +#warning "__CM0_REV not defined in device header file; using default!" +#endif + +#ifndef __NVIC_PRIO_BITS +#define __NVIC_PRIO_BITS 2 +#warning "__NVIC_PRIO_BITS not defined in device header file; using default!" +#endif + +#ifndef __Vendor_SysTickConfig +#define __Vendor_SysTickConfig 0 +#warning "__Vendor_SysTickConfig not defined in device header file; using default!" +#endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus +#define __I volatile /*!< Defines 'read only' permissions */ +#else +#define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/*@} end of group Cortex_M0 */ + + + +/******************************************************************************* + Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + ******************************************************************************/ +/** \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ +*/ + +/** \brief Union type to access the Application Program Status Register (APSR). +*/ +typedef union +{ + struct + { + #if (__CORTEX_M != 0x04) + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ + #else + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + #endif + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + + +/** \brief Union type to access the Interrupt Program Status Register (IPSR). +*/ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + + +/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). +*/ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + #if (__CORTEX_M != 0x04) + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + #else + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + #endif + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + + +/** \brief Union type to access the Control Registers (CONTROL). +*/ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/*@} end of group CMSIS_CORE */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ +*/ + +/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). +*/ +typedef struct +{ + __IO uint32_t ISER[1]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31]; + __IO uint32_t ICER[1]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31]; + __IO uint32_t ISPR[1]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31]; + __IO uint32_t ICPR[1]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31]; + uint32_t RESERVED4[64]; + __IO uint32_t IP[8]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ +*/ + +/** \brief Structure type to access the System Control Block (SCB). +*/ +typedef struct +{ + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + uint32_t RESERVED0; + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IO uint32_t SHP[2]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ +*/ + +/** \brief Structure type to access the System Timer (SysTick). +*/ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR) + are only accessible over DAP and not via processor. Therefore + they are not covered by the Cortex-M0 header file. + @{ +*/ +/*@} end of group CMSIS_CoreDebug */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ +*/ + +/* Memory mapping of Cortex-M0 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + + +/*@} */ + + + +/******************************************************************************* + Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ +*/ + +/* Interrupt Priorities are WORD accessible only under ARMv6M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( (((uint32_t)(IRQn) ) & 0x03) * 8 ) +#define _SHP_IDX(IRQn) ( ((((uint32_t)(IRQn) & 0x0F)-8) >> 2) ) +#define _IP_IDX(IRQn) ( ((uint32_t)(IRQn) >> 2) ) + + +/** \brief Enable External Interrupt + + The function enables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. +*/ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Disable External Interrupt + + The function disables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. +*/ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Get Pending Interrupt + + The function reads the pending register in the NVIC and returns the pending bit + for the specified interrupt. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. +*/ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[0] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); +} + + +/** \brief Set Pending Interrupt + + The function sets the pending bit of an external interrupt. + + \param [in] IRQn Interrupt number. Value cannot be negative. +*/ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Clear Pending Interrupt + + The function clears the pending bit of an external interrupt. + + \param [in] IRQn External interrupt number. Value cannot be negative. +*/ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} + + +/** \brief Set Interrupt Priority + + The function sets the priority of an interrupt. + + \note The priority cannot be set for every core interrupt. + + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. +*/ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) + { + SCB->SHP[_SHP_IDX(IRQn)] = (SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) | + (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); + } + else + { + NVIC->IP[_IP_IDX(IRQn)] = (NVIC->IP[_IP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) | + (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); + } +} + + +/** \brief Get Interrupt Priority + + The function reads the priority of an interrupt. The interrupt + number can be positive to specify an external (device specific) + interrupt, or negative to specify an internal (core) interrupt. + + + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented + priority bits of the microcontroller. +*/ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + if(IRQn < 0) + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); + } /* get priority for Cortex-M0 system interrupts */ + else + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); + } /* get priority for device specific interrupts */ +} + + +/** \brief System Reset + + The function initiates a system reset request to reset the MCU. +*/ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + while(1); /* wait until reset */ +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ +*/ + +#if (__Vendor_SysTickConfig == 0) + +/** \brief System Tick Configuration + + The function initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + + \param [in] ticks Number of ticks between two interrupts. + + \return 0 Function succeeded. + \return 1 Function failed. + + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + +*/ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ + + SysTick->LOAD = ticks - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#endif /* __CORE_CM0_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ + +#ifdef __cplusplus +} +#endif diff --git a/ota_boot/source/misc/CMSIS/include/core_cm0plus.h b/ota_boot/source/misc/CMSIS/include/core_cm0plus.h new file mode 100644 index 0000000..a7384af --- /dev/null +++ b/ota_boot/source/misc/CMSIS/include/core_cm0plus.h @@ -0,0 +1,801 @@ +/**************************************************************************//** + @file core_cm0plus.h + @brief CMSIS Cortex-M0+ Core Peripheral Access Layer Header File + @version V3.20 + @date 25. February 2013 + + @note + + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __CORE_CM0PLUS_H_GENERIC +#define __CORE_CM0PLUS_H_GENERIC + +/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. +*/ + + +/******************************************************************************* + CMSIS definitions + ******************************************************************************/ +/** \ingroup Cortex-M0+ + @{ +*/ + +/* CMSIS CM0P definitions */ +#define __CM0PLUS_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ +#define __CM0PLUS_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ +#define __CM0PLUS_CMSIS_VERSION ((__CM0PLUS_CMSIS_VERSION_MAIN << 16) | \ + __CM0PLUS_CMSIS_VERSION_SUB) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x00) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) +#define __ASM __asm /*!< asm keyword for ARM Compiler */ +#define __INLINE __inline /*!< inline keyword for ARM Compiler */ +#define __STATIC_INLINE static __inline + +#elif defined ( __ICCARM__ ) +#define __ASM __asm /*!< asm keyword for IAR Compiler */ +#define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ +#define __STATIC_INLINE static inline + +#elif defined ( __GNUC__ ) +#define __ASM __asm /*!< asm keyword for GNU Compiler */ +#define __INLINE inline /*!< inline keyword for GNU Compiler */ +#define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) +#define __ASM __asm /*!< asm keyword for TASKING Compiler */ +#define __INLINE inline /*!< inline keyword for TASKING Compiler */ +#define __STATIC_INLINE static inline + +#endif + +/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all +*/ +#define __FPU_USED 0 + +#if defined ( __CC_ARM ) +#if defined __TARGET_FPU_VFP +#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif + +#elif defined ( __ICCARM__ ) +#if defined __ARMVFP__ +#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif + +#elif defined ( __GNUC__ ) +#if defined (__VFP_FP__) && !defined(__SOFTFP__) +#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif + +#elif defined ( __TASKING__ ) +#if defined __FPU_VFP__ +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif +#endif + +#include /* standard types definitions */ +#include /* Core Instruction Access */ +#include /* Core Function Access */ + +#endif /* __CORE_CM0PLUS_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM0PLUS_H_DEPENDANT +#define __CORE_CM0PLUS_H_DEPENDANT + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES +#ifndef __CM0PLUS_REV +#define __CM0PLUS_REV 0x0000 +#warning "__CM0PLUS_REV not defined in device header file; using default!" +#endif + +#ifndef __MPU_PRESENT +#define __MPU_PRESENT 0 +#warning "__MPU_PRESENT not defined in device header file; using default!" +#endif + +#ifndef __VTOR_PRESENT +#define __VTOR_PRESENT 0 +#warning "__VTOR_PRESENT not defined in device header file; using default!" +#endif + +#ifndef __NVIC_PRIO_BITS +#define __NVIC_PRIO_BITS 2 +#warning "__NVIC_PRIO_BITS not defined in device header file; using default!" +#endif + +#ifndef __Vendor_SysTickConfig +#define __Vendor_SysTickConfig 0 +#warning "__Vendor_SysTickConfig not defined in device header file; using default!" +#endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus +#define __I volatile /*!< Defines 'read only' permissions */ +#else +#define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/*@} end of group Cortex-M0+ */ + + + +/******************************************************************************* + Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core MPU Register + ******************************************************************************/ +/** \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ +*/ + +/** \brief Union type to access the Application Program Status Register (APSR). +*/ +typedef union +{ + struct + { + #if (__CORTEX_M != 0x04) + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ + #else + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + #endif + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + + +/** \brief Union type to access the Interrupt Program Status Register (IPSR). +*/ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + + +/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). +*/ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + #if (__CORTEX_M != 0x04) + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + #else + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + #endif + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + + +/** \brief Union type to access the Control Registers (CONTROL). +*/ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/*@} end of group CMSIS_CORE */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ +*/ + +/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). +*/ +typedef struct +{ + __IO uint32_t ISER[1]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31]; + __IO uint32_t ICER[1]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31]; + __IO uint32_t ISPR[1]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31]; + __IO uint32_t ICPR[1]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31]; + uint32_t RESERVED4[64]; + __IO uint32_t IP[8]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ +*/ + +/** \brief Structure type to access the System Control Block (SCB). +*/ +typedef struct +{ + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + #if (__VTOR_PRESENT == 1) + __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + #else + uint32_t RESERVED0; + #endif + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IO uint32_t SHP[2]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ + +#if (__VTOR_PRESENT == 1) +/* SCB Interrupt Control State Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 8 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0xFFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ +*/ + +/** \brief Structure type to access the System Timer (SysTick). +*/ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + +#if (__MPU_PRESENT == 1) +/** \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ +*/ + +/** \brief Structure type to access the Memory Protection Unit (MPU). +*/ +typedef struct +{ + __I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register */ +#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register */ +#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register */ +#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register */ +#define MPU_RBAR_ADDR_Pos 8 /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register */ +#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Cortex-M0+ Core Debug Registers (DCB registers, SHCSR, and DFSR) + are only accessible over DAP and not via processor. Therefore + they are not covered by the Cortex-M0 header file. + @{ +*/ +/*@} end of group CMSIS_CoreDebug */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ +*/ + +/* Memory mapping of Cortex-M0+ Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + +#if (__MPU_PRESENT == 1) +#define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ +#define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ +*/ + +/* Interrupt Priorities are WORD accessible only under ARMv6M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( (((uint32_t)(IRQn) ) & 0x03) * 8 ) +#define _SHP_IDX(IRQn) ( ((((uint32_t)(IRQn) & 0x0F)-8) >> 2) ) +#define _IP_IDX(IRQn) ( ((uint32_t)(IRQn) >> 2) ) + + +/** \brief Enable External Interrupt + + The function enables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. +*/ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Disable External Interrupt + + The function disables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. +*/ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Get Pending Interrupt + + The function reads the pending register in the NVIC and returns the pending bit + for the specified interrupt. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. +*/ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[0] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); +} + + +/** \brief Set Pending Interrupt + + The function sets the pending bit of an external interrupt. + + \param [in] IRQn Interrupt number. Value cannot be negative. +*/ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Clear Pending Interrupt + + The function clears the pending bit of an external interrupt. + + \param [in] IRQn External interrupt number. Value cannot be negative. +*/ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} + + +/** \brief Set Interrupt Priority + + The function sets the priority of an interrupt. + + \note The priority cannot be set for every core interrupt. + + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. +*/ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) + { + SCB->SHP[_SHP_IDX(IRQn)] = (SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) | + (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); + } + else + { + NVIC->IP[_IP_IDX(IRQn)] = (NVIC->IP[_IP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) | + (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); + } +} + + +/** \brief Get Interrupt Priority + + The function reads the priority of an interrupt. The interrupt + number can be positive to specify an external (device specific) + interrupt, or negative to specify an internal (core) interrupt. + + + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented + priority bits of the microcontroller. +*/ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + if(IRQn < 0) + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); + } /* get priority for Cortex-M0 system interrupts */ + else + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); + } /* get priority for device specific interrupts */ +} + + +/** \brief System Reset + + The function initiates a system reset request to reset the MCU. +*/ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + while(1); /* wait until reset */ +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ +*/ + +#if (__Vendor_SysTickConfig == 0) + +/** \brief System Tick Configuration + + The function initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + + \param [in] ticks Number of ticks between two interrupts. + + \return 0 Function succeeded. + \return 1 Function failed. + + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + +*/ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ + + SysTick->LOAD = ticks - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#endif /* __CORE_CM0PLUS_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ + +#ifdef __cplusplus +} +#endif diff --git a/ota_boot/source/misc/CMSIS/include/core_cmFunc.h b/ota_boot/source/misc/CMSIS/include/core_cmFunc.h new file mode 100644 index 0000000..dc41093 --- /dev/null +++ b/ota_boot/source/misc/CMSIS/include/core_cmFunc.h @@ -0,0 +1,638 @@ +/**************************************************************************//** + @file core_cmFunc.h + @brief CMSIS Cortex-M Core Function Access Header File + @version V3.20 + @date 25. February 2013 + + @note + + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value +*/ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set +*/ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value +*/ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value +*/ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value +*/ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value +*/ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set +*/ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value +*/ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set +*/ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value +*/ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask +*/ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. +*/ +#define __enable_fault_irq __enable_fiq + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. +*/ +#define __disable_fault_irq __disable_fiq + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value +*/ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set +*/ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xff); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value +*/ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set +*/ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value +*/ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ + #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); + #else + return(0); + #endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set +*/ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ + #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); + #endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief Enable IRQ Interrupts + + This function enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** \brief Disable IRQ Interrupts + + This function disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp"); +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ +// https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Clobbers-and-Scratch-Registers +// The clobber list should not contain the stack pointer register. +// This is because the compiler requires the value of the stack pointer +// to be the same after an asm statement as it was on entry to the statement. +// However, previous versions of GCC did not enforce this rule and allowed the +// stack pointer to appear in the list, with unclear semantics. +// This behavior is deprecated and listing the stack pointer may become an error +// in future versions of GCC. +#if __GNUC__ >= 9 + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack)); +#else + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); +#endif +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); + return(result); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ + #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + uint32_t result; + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + __ASM volatile (""); + return(result); + #else + return(0); + #endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ + #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); + #endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + The CMSIS functions have been implemented as intrinsics in the compiler. + Please use "carm -?i" to get an up to date list of all instrinsics, + Including the CMSIS ones. +*/ + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +#endif /* __CORE_CMFUNC_H */ diff --git a/ota_boot/source/misc/CMSIS/include/core_cmInstr.h b/ota_boot/source/misc/CMSIS/include/core_cmInstr.h new file mode 100644 index 0000000..e02cf77 --- /dev/null +++ b/ota_boot/source/misc/CMSIS/include/core_cmInstr.h @@ -0,0 +1,677 @@ +/**************************************************************************//** + @file core_cmInstr.h + @brief CMSIS Cortex-M Core Instruction Access Header File + @version V3.20 + @date 05. March 2013 + + @note + + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. +*/ +#define __NOP __nop + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. +*/ +#define __WFI __wfi + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. +*/ +#define __WFE __wfe + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. +*/ +#define __SEV __sev + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. +*/ +#define __ISB() __isb(0xF) + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. +*/ +#define __DSB() __dsb(0xF) + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. +*/ +#define __DMB() __dmb(0xF) + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value +*/ +#define __REV __rev + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value +*/ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value +*/ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value +*/ +#define __ROR __ror + + +/** \brief Breakpoint + + This function causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. +*/ +#define __BKPT(value) __breakpoint(value) + + +#if (__CORTEX_M >= 0x03) + + /** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ + #define __RBIT __rbit + + + /** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ + #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) + + + /** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ + #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) + + + /** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ + #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) + + + /** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ + #define __STREXB(value, ptr) __strex(value, ptr) + + + /** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ + #define __STREXH(value, ptr) __strex(value, ptr) + + + /** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ + #define __STREXW(value, ptr) __strex(value, ptr) + + + /** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ + #define __CLREX __clrex + + + /** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ + #define __SSAT __ssat + + + /** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ + #define __USAT __usat + + + /** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ + #define __CLZ __clz + +#endif /* (__CORTEX_M >= 0x03) */ + + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/* Define macros for porting to both thumb1 and thumb2. + For thumb1, use low register (r0-r7), specified by constrant "l" + Otherwise, use general registers, specified by constrant "r" */ +#if defined (__thumb__) && !defined (__thumb2__) + #define __CMSIS_GCC_OUT_REG(r) "=l" (r) + #define __CMSIS_GCC_USE_REG(r) "l" (r) +#else + #define __CMSIS_GCC_OUT_REG(r) "=r" (r) + #define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb"); +} + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb"); +} + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb"); +} + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ + #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); + #else + uint32_t result; + __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); + #endif +} + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ + #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (short)__builtin_bswap16(value); + #else + uint32_t result; + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); + #endif +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32 - op2)); +} + + +/** \brief Breakpoint + + This function causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. +*/ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t* addr) +{ + uint32_t result; + #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); + #else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); + #endif + return(result); +} + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t* addr) +{ + uint32_t result; + #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); + #else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); + #endif + return(result); +} + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t* addr) +{ + uint32_t result; + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t* addr) +{ + uint32_t result; + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t* addr) +{ + uint32_t result; + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t* addr) +{ + uint32_t result; + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value +*/ +#define __SSAT(ARG1,ARG2) \ + ({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value +*/ +#define __USAT(ARG1,ARG2) \ + ({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value +*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value) +{ + uint32_t result; + __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + The CMSIS functions have been implemented as intrinsics in the compiler. + Please use "carm -?i" to get an up to date list of all intrinsics, + Including the CMSIS ones. +*/ + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/ota_boot/source/misc/bb_rom_sym_m0.gcc b/ota_boot/source/misc/bb_rom_sym_m0.gcc new file mode 100644 index 0000000..1c560c2 --- /dev/null +++ b/ota_boot/source/misc/bb_rom_sym_m0.gcc @@ -0,0 +1,1023 @@ +bx_to_application = 0x000000d5; +P256_mul64 = 0x000001f9; +P256_mul128 = 0x0000029d; +P256_mulmod = 0x0000032d; +P256_sqr64 = 0x00000567; +P256_sqr128 = 0x000005c5; +P256_sqrmod = 0x00000641; +P256_addmod = 0x00000735; +P256_submod = 0x00000791; +P256_load_1 = 0x000007c3; +P256_to_montgomery = 0x000007d7; +P256_from_montgomery = 0x00000801; +P256_point_is_on_curve = 0x0000081b; +P256_greater_or_equal_than = 0x0000086d; +P256_negate_mod_m_if = 0x00000887; +P256_copy32 = 0x000008a9; +P256_copy32_unaligned = 0x000008b5; +P256_select = 0x000008c7; +P256_double_j = 0x00000927; +P256_add_j = 0x0000092b; +P256_div2mod = 0x00000983; +P256_interpreter = 0x000009e9; +P256_sqrmod_many_and_mulmod = 0x00000a4d; +P256_modinv = 0x00000a6d; +P256_jacobian_to_affine = 0x00000af7; +P256_abs_int = 0x00000b33; +P256_pointmult = 0x00000b41; +P256_ecdh_keygen = 0x00000d03; +P256_ecdh_shared_secret = 0x00000d0b; +__aeabi_uidiv = 0x00000e09; +__aeabi_uidivmod = 0x00000e09; +__aeabi_idiv = 0x00000e35; +__aeabi_idivmod = 0x00000e35; +__aeabi_memcpy = 0x00000e81; +__aeabi_memcpy4 = 0x00000e81; +__aeabi_memcpy8 = 0x00000e81; +memcpy = 0x00000e81; +__aeabi_memset = 0x00000ea5; +__aeabi_memset4 = 0x00000ea5; +__aeabi_memset8 = 0x00000ea5; +__aeabi_memclr = 0x00000eb3; +__aeabi_memclr4 = 0x00000eb3; +__aeabi_memclr8 = 0x00000eb3; +memset = 0x00000eb7; +strlen = 0x00000ec9; +strcmp = 0x00000ed7; +memcmp = 0x00000ef3; +strncmp = 0x00000f0d; +strtok = 0x00000f2d; +__aeabi_uread4 = 0x00000f75; +__rt_uread4 = 0x00000f75; +_uread4 = 0x00000f75; +strtoul = 0x00000f89; +__rt_ctype_table = 0x00001001; +_strtoul = 0x00001009; +GPIO_IRQHandler = 0x0000112d; +HCI_CommandCompleteEvent = 0x00001175; +HCI_CommandStatusEvent = 0x000011fd; +HCI_DataBufferOverflowEvent = 0x00001251; +HCI_DisconnectCmd = 0x0000128d; +HCI_EXT_AdvEventNoticeCmd = 0x000012a1; +HCI_EXT_BuildRevisionCmd = 0x000012a9; +HCI_EXT_ClkDivOnHaltCmd = 0x000012e5; +HCI_EXT_ConnEventNoticeCmd = 0x0000130d; +HCI_EXT_DeclareNvUsageCmd = 0x00001315; +HCI_EXT_DecryptCmd = 0x00001339; +HCI_EXT_DelaySleepCmd = 0x0000137d; +HCI_EXT_DisconnectImmedCmd = 0x000013a5; +HCI_EXT_EnablePTMCmd = 0x000013cd; +HCI_EXT_EndModemTestCmd = 0x000013e1; +HCI_EXT_HaltDuringRfCmd = 0x00001409; +HCI_EXT_ModemHopTestTxCmd = 0x00001431; +HCI_EXT_ModemTestRxCmd = 0x00001459; +HCI_EXT_ModemTestTxCmd = 0x00001481; +HCI_EXT_NumComplPktsLimitCmd = 0x000014a5; +HCI_EXT_OnePktPerEvtCmd = 0x000014c9; +HCI_EXT_OverlappedProcessingCmd = 0x000014f5; +HCI_EXT_PERbyChanCmd = 0x0000151d; +HCI_EXT_PacketErrorRateCmd = 0x00001541; +HCI_EXT_ResetSystemCmd = 0x00001575; +HCI_EXT_SaveFreqTuneCmd = 0x0000159d; +HCI_EXT_SetBDADDRCmd = 0x000015c5; +HCI_EXT_SetFastTxResponseTimeCmd = 0x00001601; +HCI_EXT_SetFreqTuneCmd = 0x00001629; +HCI_EXT_SetLocalSupportedFeaturesCmd = 0x00001651; +HCI_EXT_SetMaxDtmTxPowerCmd = 0x00001679; +HCI_EXT_SetRxGainCmd = 0x000016a1; +HCI_EXT_SetSCACmd = 0x000016d1; +HCI_EXT_SetSlaveLatencyOverrideCmd = 0x000016f9; +HCI_EXT_SetTxPowerCmd = 0x00001721; +HCI_ExtTaskRegister = 0x00001751; +HCI_GAPTaskRegister = 0x0000175d; +HCI_HardwareErrorEvent = 0x00001769; +HCI_HostBufferSizeCmd = 0x000017b1; +HCI_HostNumCompletedPktCmd = 0x000017e1; +HCI_Init = 0x0000183d; +HCI_L2CAPTaskRegister = 0x00001879; +HCI_LE_AddDevToResolvingListCmd = 0x000018a1; +HCI_LE_AddWhiteListCmd = 0x000018bd; +HCI_LE_ClearAdvSetsCmd = 0x000018e1; +HCI_LE_ClearResolvingListCmd = 0x00001919; +HCI_LE_ClearWhiteListCmd = 0x00001935; +HCI_LE_Connection_CTE_Request_EnableCmd = 0x0000196d; +HCI_LE_Connection_CTE_Response_EnableCmd = 0x00001999; +HCI_LE_ConnectionlessCTE_TransmitEnableCmd = 0x000019c1; +HCI_LE_ConnectionlessCTE_TransmitParamCmd = 0x000019dd; +HCI_LE_ConnectionlessIQ_SampleEnableCmd = 0x00001a01; +HCI_LE_CreateConnCancelCmd = 0x00001a31; +HCI_LE_CreateConnCmd = 0x00001a4d; +HCI_LE_EncryptCmd = 0x00001a89; +HCI_LE_ExtendedCreateConnectionCmd = 0x00001ac1; +HCI_LE_LtkReqNegReplyCmd = 0x00001b09; +HCI_LE_LtkReqReplyCmd = 0x00001b31; +HCI_LE_PeriodicAdvertisingCreateSyncCancelCmd = 0x00001b59; +HCI_LE_PeriodicAdvertisingCreateSyncCmd = 0x00001b75; +HCI_LE_PeriodicAdvertisingTerminateSyncCmd = 0x00001b9d; +HCI_LE_READ_Anatenna_InfoCmd = 0x00001bb9; +HCI_LE_RandCmd = 0x00001bd9; +HCI_LE_ReadAdvChanTxPowerCmd = 0x00001c09; +HCI_LE_ReadBufSizeCmd = 0x00001c29; +HCI_LE_ReadChannelMapCmd = 0x00001c4d; +HCI_LE_ReadLocalSupportedFeaturesCmd = 0x00001c99; +HCI_LE_ReadMaxDataLengthCmd = 0x00001cb9; +HCI_LE_ReadMaximumAdvDataLengthCmd = 0x00001ce9; +HCI_LE_ReadNumberOfSupportAdvSetCmd = 0x00001d11; +HCI_LE_ReadPhyMode = 0x00001d71; +HCI_LE_ReadRemoteUsedFeaturesCmd = 0x00001db1; +HCI_LE_ReadResolvingListSizeCmd = 0x00001dc5; +HCI_LE_ReadSuggestedDefaultDataLengthCmd = 0x00001de5; +HCI_LE_ReadSupportedStatesCmd = 0x00001e15; +HCI_LE_ReadWhiteListSizeCmd = 0x00001e3d; +HCI_LE_ReceiverTestCmd = 0x00001e9d; +HCI_LE_RemoveAdvSetCmd = 0x00001eb1; +HCI_LE_RemoveResolvingListCmd = 0x00001ee9; +HCI_LE_RemoveWhiteListCmd = 0x00001f0d; +HCI_LE_SetAddressResolutionEnableCmd = 0x00001f31; +HCI_LE_SetAdvDataCmd = 0x00001f4d; +HCI_LE_SetAdvEnableCmd = 0x00001f69; +HCI_LE_SetAdvParamCmd = 0x00001f85; +HCI_LE_SetDataLengthCmd = 0x00001fb1; +HCI_LE_SetDefaultPhyMode = 0x00001fd9; +HCI_LE_SetEventMaskCmd = 0x00001ff5; +HCI_LE_SetExtAdvDataCmd = 0x0000202d; +HCI_LE_SetExtAdvEnableCmd = 0x0000204d; +HCI_LE_SetExtAdvParamCmd = 0x0000206d; +HCI_LE_SetExtAdvSetRandomAddressCmd = 0x000020c1; +HCI_LE_SetExtScanRspDataCmd = 0x000020dd; +HCI_LE_SetExtendedScanEnableCmd = 0x000020fd; +HCI_LE_SetExtendedScanParametersCmd = 0x00002119; +HCI_LE_SetHostChanClassificationCmd = 0x0000213d; +HCI_LE_SetPeriodicAdvDataCmd = 0x00002159; +HCI_LE_SetPeriodicAdvEnableCmd = 0x00002175; +HCI_LE_SetPeriodicAdvParameterCmd = 0x00002191; +HCI_LE_SetPhyMode = 0x000021ad; +HCI_LE_SetRandomAddressCmd = 0x000021c5; +HCI_LE_SetResolvablePrivateAddressTimeoutCmd = 0x000021e9; +HCI_LE_SetScanEnableCmd = 0x00002219; +HCI_LE_SetScanParamCmd = 0x00002235; +HCI_LE_SetScanRspDataCmd = 0x00002255; +HCI_LE_Set_ConnectionCTE_ReceiveParamCmd = 0x00002271; +HCI_LE_Set_ConnectionCTE_TransmitParamCmd = 0x0000229d; +HCI_LE_StartEncyptCmd = 0x000022e1; +HCI_LE_TestEndCmd = 0x000022f5; +HCI_LE_TransmitterTestCmd = 0x0000231d; +HCI_LE_WriteSuggestedDefaultDataLengthCmd = 0x00002339; +HCI_NumOfCompletedPacketsEvent = 0x00002371; +HCI_PPLUS_AdvEventDoneNoticeCmd = 0x00002401; +HCI_PPLUS_ConnEventDoneNoticeCmd = 0x00002421; +HCI_PPLUS_DateLengthChangedNoticeCmd = 0x00002461; +HCI_PPLUS_ExtendTRXCmd = 0x000024a1; +HCI_PPLUS_PhyUpdateNoticeCmd = 0x000024bd; +HCI_ProcessEvent = 0x000024fd; +HCI_ReadBDADDRCmd = 0x00002551; +HCI_ReadLocalSupportedCommandsCmd = 0x00002571; +HCI_ReadLocalSupportedFeaturesCmd = 0x00002589; +HCI_ReadLocalVersionInfoCmd = 0x000025ad; +HCI_ReadRemoteVersionInfoCmd = 0x000025f5; +HCI_ReadRssiCmd = 0x00002625; +HCI_ReadTransmitPowerLevelCmd = 0x00002651; +HCI_ResetCmd = 0x0000267d; +HCI_ReverseBytes = 0x000026a9; +HCI_SMPTaskRegister = 0x000026c9; +HCI_SendCommandCompleteEvent = 0x000026d5; +HCI_SendCommandStatusEvent = 0x0000277d; +HCI_SendControllerToHostEvent = 0x0000279d; +HCI_SendDataPkt = 0x000027e9; +HCI_SetControllerToHostFlowCtrlCmd = 0x00002819; +HCI_SetEventMaskCmd = 0x0000285d; +HCI_TestAppTaskRegister = 0x0000288d; +HCI_ValidConnTimeParams = 0x00002899; +HCI_VendorSpecifcCommandCompleteEvent = 0x000028d9; +HCI_bm_alloc = 0x000028e9; +HardFault_Handler = 0x000028f1; +HardFault_IRQHandler = 0x00002909; +LL_AddResolvingListLDevice = 0x000029dd; +LL_AddWhiteListDevice = 0x00002a95; +LL_AdvReportCback = 0x00002b11; +LL_CTE_Report_FailedCback = 0x00002ca1; +LL_ChanMapUpdate = 0x00002d0d; +LL_ClearAdvSets = 0x00002e2d; +LL_ClearResolvingList = 0x00002f41; +LL_ClearWhiteList = 0x00002fbd; +LL_ConnActive = 0x00003011; +LL_ConnParamUpdateCback = 0x00003039; +LL_ConnUpdate = 0x000030e5; +LL_ConnectionCompleteCback = 0x000031b9; +LL_ConnectionIQReportCback = 0x000032d5; +LL_Connection_CTE_Request_Enable = 0x000033e5; +LL_Connection_CTE_Response_Enable = 0x00003499; +LL_ConnectionlessCTE_TransmitEnable = 0x00003505; +LL_ConnectionlessCTE_TransmitParam = 0x000035e5; +LL_ConnectionlessIQReportCback = 0x000036c1; +LL_ConnectionlessIQ_SampleEnable = 0x000037c5; +LL_CreateConn = 0x00003901; +LL_CreateConn0 = 0x00003949; +LL_CreateConnCancel = 0x00003c91; +LL_CtrlToHostFlowControl = 0x00003d59; +LL_DataLengthChangeCback = 0x00003d71; +LL_DirectTestEnd = 0x00003e3d; +LL_DirectTestTxTest = 0x00003e95; +LL_Disconnect = 0x00003eb1; +LL_DisconnectCback = 0x00003f41; +LL_ENC_AES128_Encrypt = 0x00003fc5; +LL_ENC_AES128_Encrypt0 = 0x00003fdd; +LL_ENC_Decrypt = 0x000040ed; +LL_ENC_Decrypt0 = 0x00004105; +LL_ENC_Encrypt = 0x00004261; +LL_ENC_Encrypt0 = 0x00004278; +LL_ENC_GenDeviceIV = 0x000043c1; +LL_ENC_GenDeviceSKD = 0x000043f1; +LL_ENC_GenerateNonce = 0x00004421; +LL_ENC_GeneratePseudoRandNum = 0x00004459; +LL_ENC_GenerateTrueRandNum = 0x00004469; +LL_ENC_LoadKey = 0x00004489; +LL_ENC_ReverseBytes = 0x000044e1; +LL_ENC_sm_ah = 0x00004501; +LL_EXT_AdvEventNotice = 0x00004543; +LL_EXT_BuildRevision = 0x00004547; +LL_EXT_ClkDivOnHalt = 0x0000454b; +LL_EXT_ConnEventNotice = 0x0000454f; +LL_EXT_DeclareNvUsage = 0x00004553; +LL_EXT_Decrypt = 0x00004557; +LL_EXT_DelaySleep = 0x0000455b; +LL_EXT_DisconnectImmed = 0x0000455f; +LL_EXT_EndModemTest = 0x00004563; +LL_EXT_HaltDuringRf = 0x00004567; +LL_EXT_Init_IQ_pBuff = 0x0000456d; +LL_EXT_MapPmIoPort = 0x00004581; +LL_EXT_ModemHopTestTx = 0x00004585; +LL_EXT_ModemTestRx = 0x00004589; +LL_EXT_ModemTestTx = 0x0000458d; +LL_EXT_NumComplPktsLimit = 0x00004591; +LL_EXT_OnePacketPerEvent = 0x000045ad; +LL_EXT_OverlappedProcessing = 0x000045b1; +LL_EXT_PERbyChan = 0x000045b5; +LL_EXT_PacketErrorRate = 0x000045b9; +LL_EXT_PacketErrorRateCback = 0x000045bd; +LL_EXT_ResetSystem = 0x000045f9; +LL_EXT_SaveFreqTune = 0x000045fd; +LL_EXT_SetBDADDR = 0x00004601; +LL_EXT_SetFastTxResponseTime = 0x00004605; +LL_EXT_SetFreqTune = 0x00004609; +LL_EXT_SetLocalSupportedFeatures = 0x0000460d; +LL_EXT_SetMaxDtmTxPower = 0x00004611; +LL_EXT_SetRxGain = 0x00004615; +LL_EXT_SetRxGainCback = 0x00004619; +LL_EXT_SetSCA = 0x00004635; +LL_EXT_SetSlaveLatencyOverride = 0x00004639; +LL_EXT_SetTxPower = 0x0000463d; +LL_EXT_SetTxPowerCback = 0x00004679; +LL_EncChangeCback = 0x00004699; +LL_EncKeyRefreshCback = 0x00004715; +LL_EncLtkNegReply = 0x0000478d; +LL_EncLtkReply = 0x000047d9; +LL_EncLtkReqCback = 0x00004831; +LL_Encrypt = 0x000048e5; +LL_ExtAdvReportCback = 0x00004a8d; +LL_ExtendedCreateConnection = 0x00004bfd; +LL_IRQHandler = 0x00004e25; +LL_Init = 0x00004eb1; +LL_InitConnectContext = 0x00005045; +LL_InitExtendedAdv = 0x0000511d; +LL_InitExtendedScan = 0x000051b5; +LL_InitPeriodicAdv = 0x000051c5; +LL_NumEmptyWlEntries = 0x00005291; +LL_PLUS_DisableSlaveLatency = 0x000052a5; +LL_PLUS_EnableSlaveLatency = 0x00005435; +LL_PLUS_GetAdvDataExtendData = 0x0000548d; +LL_PLUS_GetScanRequestExtendData = 0x00005495; +LL_PLUS_GetScanerAddr = 0x000054bd; +LL_PLUS_PerStasReadByChn = 0x000054d5; +LL_PLUS_PerStatsReset = 0x00005519; +LL_PLUS_PerStats_Init = 0x00005535; +LL_PLUS_SetAdvDataFilterCB = 0x00005545; +LL_PLUS_SetScanRequestData = 0x00005551; +LL_PLUS_SetScanRequestFilterCB = 0x00005579; +LL_PLUS_SetScanRsqData = 0x00005585; +LL_PLUS_SetScanRsqDataByIndex = 0x000055b1; +LL_PeriodicAdvertisingCreateSync = 0x000055bd; +LL_PeriodicAdvertisingCreateSyncCancel = 0x0000560d; +LL_PeriodicAdvertisingTerminateSync = 0x00005635; +LL_PhyUpdate = 0x00005655; +LL_PhyUpdate0 = 0x0000566d; +LL_PhyUpdateCompleteCback = 0x00005725; +LL_PrdAdvReportCback = 0x000057c9; +LL_PrdAdvSyncEstablishedCback = 0x000058b5; +LL_PrdAdvSyncLostCback = 0x00005989; +LL_ProcessEvent = 0x000059f1; +LL_PseudoRand = 0x00005dd9; +LL_READ_Anatenna_Info = 0x00005ddd; +LL_RX_bm_alloc = 0x00005df1; +LL_Rand = 0x00005e05; +LL_RandCback = 0x00005e65; +LL_ReadAdvChanTxPower = 0x00005e89; +LL_ReadBDADDR = 0x00005eb9; +LL_ReadCarrSens = 0x00005edd; +LL_ReadChanMap = 0x00005ef9; +LL_ReadFoff = 0x00005f31; +LL_ReadLocalSupportedFeatures = 0x00005f71; +LL_ReadLocalVersionInfo = 0x00005f8d; +LL_ReadMaximumAdvDataLength = 0x00005fa5; +LL_ReadNumberOfSupportAdvSet = 0x00005fc5; +LL_ReadRemoteUsedFeatures = 0x00006021; +LL_ReadRemoteUsedFeaturesCompleteCback = 0x00006061; +LL_ReadRemoteVersionInfo = 0x000060d5; +LL_ReadRemoteVersionInfoCback = 0x00006131; +LL_ReadResolvingListSize = 0x000061a9; +LL_ReadRssi = 0x000061b1; +LL_ReadSupportedStates = 0x000061e5; +LL_ReadTxPowerLevel = 0x00006269; +LL_ReadWlSize = 0x000062e5; +LL_RemoveAdvSet = 0x00006335; +LL_RemoveResolvingListDevice = 0x000064a5; +LL_RemoveWhiteListDevice = 0x00006561; +LL_Reset = 0x000065f1; +LL_RxDataCompleteCback = 0x00006791; +LL_SetAddressResolutionEnable = 0x00006831; +LL_SetAdvControl = 0x00006881; +LL_SetAdvControl0 = 0x00006899; +LL_SetAdvData = 0x00006a05; +LL_SetAdvParam = 0x00006a6d; +LL_SetAdvParam0 = 0x00006a9d; +LL_SetDataLengh = 0x00006df9; +LL_SetDataLengh0 = 0x00006e11; +LL_SetDefaultPhyMode = 0x00006ead; +LL_SetExtAdvData = 0x00006edd; +LL_SetExtAdvEnable = 0x00006fc5; +LL_SetExtAdvParam = 0x00007205; +LL_SetExtAdvSetRandomAddress = 0x000073a9; +LL_SetExtScanRspData = 0x000073f5; +LL_SetExtendedScanEnable = 0x00007471; +LL_SetExtendedScanParameters = 0x000074b5; +LL_SetPeriodicAdvData = 0x0000751d; +LL_SetPeriodicAdvEnable = 0x000075cd; +LL_SetPeriodicAdvParameter = 0x00007715; +LL_SetPhyMode = 0x000077e1; +LL_SetPhyMode0 = 0x000077fd; +LL_SetRandomAddress = 0x000078c9; +LL_SetResolvablePrivateAddressTimeout = 0x00007929; +LL_SetScanControl = 0x00007935; +LL_SetScanControl0 = 0x0000794d; +LL_SetScanParam = 0x00007a59; +LL_SetScanParam0 = 0x00007a75; +LL_SetScanRspData = 0x00007b15; +LL_SetTxPowerLevel = 0x00007b65; +LL_Set_ConnectionCTE_ReceiveParam = 0x00007b91; +LL_Set_ConnectionCTE_TransmitParam = 0x00007c99; +LL_StartEncrypt = 0x00007e01; +LL_TX_bm_alloc = 0x00007f01; +LL_TxData = 0x00007f1d; +LL_WriteSuggestedDefaultDataLength = 0x00007fb9; +LL_evt_schedule = 0x00007ff9; +LL_extAdvTimerExpProcess = 0x000080b5; +LL_extInitTimerExpProcess = 0x000080b9; +LL_extScanTimerExpProcess = 0x000080bb; +LL_master_conn_event = 0x000080bd; +LL_prdAdvTimerExpProcess = 0x0000826d; +LL_prdScanTimerExpProcess = 0x00008271; +LL_set_default_conn_params = 0x00008275; +LL_set_default_conn_params0 = 0x0000828d; +LL_slave_conn_event = 0x000082b9; +NMI_Handler = 0x00008481; +PendSV_Handler = 0x000084cd; +TIM1_IRQHandler = 0x00008545; +WaitRTCCount = 0x00008901; +__ARM_common_switch8 = 0x00008961; +_spif_read_status_reg = 0x0000961d; +_spif_wait_nobusy = 0x00009645; +app_sleep_process = 0x00009769; +app_wakeup_process = 0x00009779; +ate_fun_test = 0x00009789; +ate_sleep_process = 0x00009d11; +ate_wakeup_process = 0x0000a121; +bit_to_byte = 0x0000a1e9; +ble_crc24_gen = 0x0000a201; +boot_init = 0x0000a361; +boot_init0 = 0x0000a379; +boot_m0 = 0x0000a3c1; +byte_to_bit = 0x0000a535; +calculate_whiten_seed = 0x0000a549; +clear_timer = 0x0000a5c1; +clear_timer_int = 0x0000a5cb; +clk_get_pclk = 0x0000a5d1; +clk_init = 0x0000a5ed; +clk_set_pclk_div = 0x0000a681; +clk_spif_ref_clk = 0x0000a6a1; +config_RTC = 0x0000a6f9; +config_RTC0 = 0x0000a711; +rom_crc16 = 0x0000a755; +debug_print = 0x0000a791; +disableSleep = 0x0000a921; +drv_disable_irq = 0x0000a975; +drv_enable_irq = 0x0000a99d; +drv_irq_init = 0x0000a9c9; +dwc_connect = 0x0000a9fd; +dwc_data_process = 0x0000aa35; +dwc_loop = 0x0000abd1; +efuse_read = 0x0000ace1; +enableSleep = 0x0000aead; +enterSleepProcess = 0x0000aeb9; +enterSleepProcess0 = 0x0000aed1; +enter_sleep_off_mode = 0x0000afa1; +enter_sleep_off_mode0 = 0x0000afb9; +getMcuPrecisionCount = 0x0000afe9; +getPN23RandNumber = 0x0000aff5; +getRxBufferFree = 0x0000b01d; +getRxBufferSize = 0x0000b031; +getSleepMode = 0x0000b051; +getTxBufferFree = 0x0000b05d; +getTxBufferSize = 0x0000b071; +get_rx_read_ptr = 0x0000b0b1; +get_rx_write_ptr = 0x0000b0b9; +get_sleep_flag = 0x0000b0c1; +get_timer_count = 0x0000b0cd; +get_timer_int = 0x0000b0d1; +get_tx_read_ptr = 0x0000b0d9; +get_tx_write_ptr = 0x0000b0e1; +gpio_cfg_analog_io = 0x0000b0e9; +gpio_dir = 0x0000b119; +gpio_fmux_control = 0x0000b15d; +gpio_fmux_set = 0x0000b179; +gpio_in_trigger = 0x0000b1b1; +gpio_init = 0x0000b219; +gpio_interrupt_set = 0x0000b22d; +gpio_pull_set = 0x0000b249; +gpio_read = 0x0000b291; +gpio_wakeup_set = 0x0000b2b5; +gpio_write = 0x0000b319; +hciInitEventMasks = 0x0000b52d; +isSleepAllow = 0x0000b555; +isTimer1Running = 0x0000b561; +isTimer4Running = 0x0000b571; +jump_area_init = 0x0000b581; +ll24BitTimeCompare = 0x0000b5a9; +llAdjSlaveLatencyValue = 0x0000b609; +llAllocConnId = 0x0000b629; +llAllocateSyncHandle = 0x0000b679; +llAtLeastTwoChans = 0x0000b6a9; +llCalcMaxScanTime = 0x0000b6ed; +llCalcScaFactor = 0x0000b745; +llCalcTimerDrift = 0x0000b76d; +llCheckForLstoDuringSL = 0x0000b7b1; +llCheckWhiteListUsage = 0x0000b7ed; +llConnCleanup = 0x0000b809; +llConnTerminate = 0x0000b839; +llConnTerminate0 = 0x0000b851; +llConvertCtrlProcTimeoutToEvent = 0x0000b87d; +llConvertLstoToEvent = 0x0000b899; +llDeleteSyncHandle = 0x0000b8bd; +llDequeueCtrlPkt = 0x0000b8ed; +llDequeueDataQ = 0x0000b929; +llEnqueueCtrlPkt = 0x0000b953; +llEnqueueDataQ = 0x0000b98b; +llEqAlreadyValidAddr = 0x0000b9b1; +llEqSynchWord = 0x0000b9b5; +llEqualBytes = 0x0000b9c9; +llEventDelta = 0x0000b9e9; +llEventInRange = 0x0000b9fd; +llGenerateCRC = 0x0000ba1b; +llGenerateValidAccessAddr = 0x0000ba3d; +llGetNextAdvChn = 0x0000ba6d; +llGetNextAuxAdvChn = 0x0000bac1; +llGetNextDataChan = 0x0000bae5; +llGetNextDataChanCSA2 = 0x0000bb23; +llGtSixConsecZerosOrOnes = 0x0000bb81; +llGtTwentyFourTransitions = 0x0000bbb3; +llInitFeatureSet = 0x0000bbe5; +llInitFeatureSet2MPHY = 0x0000bc1d; +llInitFeatureSetCodedPHY = 0x0000bc45; +llInitFeatureSetDLE = 0x0000bc6d; +llLtTwoChangesInLastSixBits = 0x0000bc89; +llMasterEvt_TaskEndOk = 0x0000bcb9; +llMemCopyDst = 0x0000be05; +llMemCopySrc = 0x0000be1b; +llOneBitSynchWordDiffer = 0x0000be35; +llPduLengthManagmentReset = 0x0000be4d; +llPduLengthUpdate = 0x0000bf01; +llPendingUpdateParam = 0x0000c00d; +llPhyModeCtrlReset = 0x0000c051; +llPhyModeCtrlUpdateNotify = 0x0000c0b9; +llProcessChanMap = 0x0000c185; +llProcessMasterControlPacket = 0x0000c1d1; +llProcessMasterControlProcedures = 0x0000c5b9; +llProcessRxData = 0x0000ca85; +llProcessSlaveControlPacket = 0x0000cc31; +llProcessSlaveControlProcedures = 0x0000d169; +llProcessTxData = 0x0000d4d1; +llProcessTxData0 = 0x0000d4e9; +llReleaseAllConnId = 0x0000d55d; +llReleaseConnId = 0x0000d561; +llReplaceCtrlPkt = 0x0000d5f5; +llResetConnId = 0x0000d60d; +llResetRfCounters = 0x0000d6ed; +llSecAdvAllow = 0x0000d701; +llSetNextDataChan = 0x0000d769; +llSetNextPhyMode = 0x0000d839; +llSetupAdv = 0x0000d8a9; +llSetupAdvExtIndPDU = 0x0000d949; +llSetupAuxAdvIndPDU = 0x0000db4d; +llSetupAuxChainIndPDU = 0x0000dda1; +llSetupAuxConnectReqPDU = 0x0000df91; +llSetupAuxConnectRspPDU = 0x0000e025; +llSetupAuxScanRspPDU = 0x0000e09d; +llSetupAuxSyncIndPDU = 0x0000e109; +llSetupCTEReq = 0x0000e2c1; +llSetupCTERsp = 0x0000e38d; +llSetupConn = 0x0000e457; +llSetupDataLenghtReq = 0x0000e459; +llSetupDataLenghtRsp = 0x0000e4d5; +llSetupDirectedAdvEvt = 0x0000e551; +llSetupEncReq = 0x0000e6a1; +llSetupEncRsp = 0x0000e725; +llSetupExtAdvEvent = 0x0000e7b1; +llSetupExtInit = 0x0000eb09; +llSetupExtScan = 0x0000eb81; +llSetupFeatureSetReq = 0x0000ec01; +llSetupFeatureSetRsp = 0x0000ec63; +llSetupInit = 0x0000ecc1; +llSetupNextMasterEvent = 0x0000ed39; +llSetupNextSlaveEvent = 0x0000ede1; +llSetupNextSlaveEvent0 = 0x0000edf9; +llSetupNonConnectableAdvEvt = 0x0000ef65; +llSetupPauseEncReq = 0x0000f075; +llSetupPauseEncRsp = 0x0000f0c5; +llSetupPhyReq = 0x0000f121; +llSetupPhyRsp = 0x0000f177; +llSetupPhyUpdateInd = 0x0000f1cd; +llSetupPrdAdvEvent = 0x0000f239; +llSetupPrdScan = 0x0000f3b9; +llSetupRejectExtInd = 0x0000f44d; +llSetupRejectInd = 0x0000f479; +llSetupScan = 0x0000f4a5; +llSetupScanInit = 0x0000f54d; +llSetupScannableAdvEvt = 0x0000f55d; +llSetupSecAdvEvt = 0x0000f66d; +llSetupSecConnectableAdvEvt = 0x0000f6e9; +llSetupSecInit = 0x0000f7c1; +llSetupSecNonConnectableAdvEvt = 0x0000f875; +llSetupSecScan = 0x0000f94d; +llSetupSecScannableAdvEvt = 0x0000fa19; +llSetupStartEncReq = 0x0000faf1; +llSetupStartEncRsp = 0x0000fb15; +llSetupSyncInfo = 0x0000fb59; +llSetupTermInd = 0x0000fc2d; +llSetupUndirectedAdvEvt = 0x0000fc91; +llSetupUnknownRsp = 0x0000fda5; +llSetupUpdateChanReq = 0x0000fdf9; +llSetupUpdateParamReq = 0x0000fe6d; +llSetupVersionIndReq = 0x0000ff05; +llSlaveEvt_TaskAbort = 0x0000ff79; +llSlaveEvt_TaskEndOk = 0x0000ff95; +llTrxNumAdaptiveConfig = 0x00010181; +llValidAccessAddr = 0x0001019b; +llWaitUs = 0x000101e1; +llWriteTxData = 0x00010209; +ll_CalcRandomAddr = 0x0001028f; +ll_ResolveRandomAddrs = 0x000102cd; +ll_addTask = 0x00010315; +ll_add_adv_task = 0x00010445; +ll_add_adv_task_periodic = 0x00010461; +ll_adptive_adj_next_time = 0x0001047d; +ll_adptive_smart_window = 0x000104fd; +ll_adv_scheduler = 0x000105ad; +ll_adv_scheduler_periodic = 0x000105c9; +ll_allocAuxAdvTimeSlot = 0x000105e5; +ll_allocAuxAdvTimeSlot_prd = 0x00010679; +_ll_debug_output = 0x00010719; +ll_deleteTask = 0x00010731; +ll_delete_adv_task = 0x00010765; +ll_delete_adv_task_periodic = 0x00010781; +ll_ext_adv_schedule_next_event = 0x0001079d; +ll_ext_init_schedule_next_event = 0x000107c1; +ll_ext_scan_schedule_next_event = 0x000107dd; +ll_generateExtAdvDid = 0x000107f9; +ll_generateTxBuffer = 0x00010801; +ll_getFirstAdvChn = 0x000109c1; +ll_getRPAListEntry = 0x000109cd; +ll_get_next_active_conn = 0x00010a39; +ll_get_next_timer = 0x00010aa1; +ll_hw_clr_irq = 0x00010add; +ll_hw_config = 0x00010aed; +ll_hw_get_anchor = 0x00010b6d; +ll_hw_get_fsm_status = 0x00010b79; +ll_hw_get_iq_RawSample = 0x00010b89; +ll_hw_get_irq_status = 0x00010bbd; +ll_hw_get_last_ack = 0x00010bcd; +ll_hw_get_loop_cycle = 0x00010be9; +ll_hw_get_loop_time = 0x00010bf5; +ll_hw_get_nAck = 0x00010c01; +ll_hw_get_rfifo_depth = 0x00010c11; +ll_hw_get_rfifo_info = 0x00010c25; +ll_hw_get_rxPkt_CrcErr_num = 0x00010c45; +ll_hw_get_rxPkt_CrcOk_num = 0x00010c55; +ll_hw_get_rxPkt_Total_num = 0x00010c69; +ll_hw_get_rxPkt_num = 0x00010c79; +ll_hw_get_rxPkt_stats = 0x00010c85; +ll_hw_get_snNesn = 0x00010c9d; +ll_hw_get_tfifo_info = 0x00010cad; +ll_hw_get_tfifo_wrptr = 0x00010ccd; +ll_hw_get_tr_mode = 0x00010cdd; +ll_hw_get_txAck = 0x00010ced; +ll_hw_go = 0x00010cf9; +ll_hw_ign_rfifo = 0x00010df9; +ll_hw_process_RTO = 0x00010e05; +ll_hw_read_rfifo = 0x00010e6d; +ll_hw_read_rfifo_pplus = 0x00010ee9; +ll_hw_read_rfifo_zb = 0x00010f51; +ll_hw_read_tfifo_packet = 0x00010fad; +ll_hw_read_tfifo_rtlp = 0x00010ff5; +ll_hw_rst_rfifo = 0x000110b1; +ll_hw_rst_tfifo = 0x000110e9; +ll_hw_set_ant_pattern = 0x000110f5; +ll_hw_set_ant_switch_mode = 0x00011101; +ll_hw_set_ant_switch_timing = 0x00011115; +ll_hw_set_crc_fmt = 0x0001112d; +ll_hw_set_cte_rxSupp = 0x0001113d; +ll_hw_set_cte_txSupp = 0x00011155; +ll_hw_set_empty_head = 0x00011169; +ll_hw_set_irq = 0x00011175; +ll_hw_set_loop_nack_num = 0x00011181; +ll_hw_set_loop_timeout = 0x0001118d; +ll_hw_set_pplus_pktfmt = 0x000111a1; +ll_hw_set_rtlp = 0x000111cd; +ll_hw_set_rtlp_1st = 0x0001121d; +ll_hw_set_rtx = 0x00011265; +ll_hw_set_rx_timeout = 0x00011279; +ll_hw_set_rx_timeout_1st = 0x00011285; +ll_hw_set_rx_tx_interval = 0x00011291; +ll_hw_set_srx = 0x000112a5; +ll_hw_set_stx = 0x000112b9; +ll_hw_set_tfifo_space = 0x000112cd; +ll_hw_set_timing = 0x000112e5; +ll_hw_set_trlp = 0x00011381; +ll_hw_set_trx = 0x000113c9; +ll_hw_set_trx_settle = 0x000113dd; +ll_hw_set_tx_rx_interval = 0x000113f1; +ll_hw_set_tx_rx_release = 0x00011405; +ll_hw_trigger = 0x00011421; +ll_hw_trx_settle_config = 0x00011445; +ll_hw_tx2rx_timing_config = 0x00011489; +ll_hw_update = 0x000114dd; +ll_hw_update_rtlp_mode = 0x00011539; +ll_hw_update_trlp_mode = 0x00011579; +ll_hw_write_tfifo = 0x000115c1; +ll_isAddrInWhiteList = 0x00011649; +ll_isFirstAdvChn = 0x000116a9; +ll_isIrkAllZero = 0x000116c7; +ll_isLegacyAdv = 0x000116dd; +ll_parseExtHeader = 0x000116ed; +ll_prd_adv_schedule_next_event = 0x000117a9; +ll_prd_scan_schedule_next_event = 0x000117cd; +ll_processBasicIRQ = 0x000117e9; +ll_processExtAdvIRQ = 0x00013401; +ll_processExtInitIRQ = 0x00013405; +ll_processExtScanIRQ = 0x00013409; +ll_processMissMasterEvt = 0x0001340d; +ll_processMissSlaveEvt = 0x000134ed; +ll_processPrdAdvIRQ = 0x000135f5; +ll_processPrdScanIRQ = 0x000135f9; +ll_readLocalIRK = 0x000135fd; +ll_read_rxfifo = 0x000136c5; +ll_schedule_next_event = 0x00013761; +ll_scheduler = 0x00013771; +ll_scheduler0 = 0x00013789; +ll_updateAuxAdvTimeSlot = 0x00013a11; +ll_updateExtAdvRemainderTime = 0x00013a39; +log_clr_putc = 0x00013ab9; +log_debug_level = 0x00013ac5; +log_get_debug_level = 0x00013ad9; +log_printf = 0x00013ae5; +log_set_putc = 0x00013b05; +log_vsprintf = 0x00013b11; +move_to_master_function = 0x00013f09; +move_to_slave_function = 0x0001406d; +osalAddTimer = 0x00014439; +osalDeleteTimer = 0x000144a9; +osalFindTimer = 0x000144b5; +osalTimeUpdate = 0x000144d5; +osalTimeUpdate1 = 0x00014541; +osalTimerInit = 0x0001457d; +osalTimerUpdate = 0x00014589; +osal_CbTimerInit = 0x00014621; +osal_CbTimerProcessEvent = 0x00014641; +osal_CbTimerStart = 0x000146a9; +osal_CbTimerStop = 0x00014711; +osal_CbTimerUpdate = 0x00014751; +osal_ConvertUTCSecs = 0x000147a1; +osal_ConvertUTCTime = 0x00014841; +osal_GetSystemClock = 0x00014949; +osal_bm_adjust_header = 0x00014955; +osal_bm_adjust_tail = 0x0001497d; +osal_bm_alloc = 0x000149a9; +osal_bm_free = 0x000149d9; +osal_buffer_uint24 = 0x00014a21; +osal_buffer_uint32 = 0x00014a2f; +osal_build_uint16 = 0x00014a41; +osal_build_uint32 = 0x00014a4d; +osal_clear_event = 0x00014a89; +osal_getClock = 0x00014abd; +osal_get_timeoutEx = 0x00014ac9; +osal_init_system = 0x00014aed; +osal_isbufset = 0x00014b1d; +osal_mem_alloc = 0x00014b3d; +osal_mem_free = 0x00014c01; +osal_mem_init = 0x00014c25; +osal_mem_kick = 0x00014c8d; +osal_mem_set_heap = 0x00014cb5; +osal_memcmp = 0x00014ccd; +osal_memcpy = 0x00014ce9; +osal_memdup = 0x00014cf9; +osal_memset = 0x00014d15; +osal_msg_allocate = 0x00014d1d; +osal_msg_deallocate = 0x00014d43; +osal_msg_dequeue = 0x00014d65; +osal_msg_enqueue = 0x00014d91; +osal_msg_enqueue_max = 0x00014dc3; +osal_msg_extract = 0x00014e6d; +osal_msg_find = 0x00014e9d; +osal_msg_push = 0x00014ed1; +osal_msg_push_front = 0x00014eeb; +osal_msg_receive = 0x00014ef5; +osal_msg_send = 0x00014f59; +osal_next_timeout = 0x00014f7d; +osal_pwrmgr_device = 0x00014fa5; +osal_pwrmgr_init = 0x00014fb1; +osal_pwrmgr_powerconserve = 0x00014fc1; +osal_pwrmgr_powerconserve0 = 0x00014fd9; +osal_pwrmgr_task_state = 0x000150f9; +osal_rand = 0x00015129; +osal_revmemcpy = 0x00015145; +osal_run_system = 0x00015159; +osal_self = 0x000151f5; +osal_setClock = 0x00015201; +osal_set_event = 0x0001520d; +osal_start_reload_timer = 0x00015259; +osal_start_system = 0x00015285; +osal_start_timerEx = 0x0001528b; +osal_stop_timerEx = 0x000152b3; +osal_strlen = 0x000152dd; +osal_timer_num_active = 0x000152e5; +phy_sec_app_key = 0x00015315; +phy_sec_decrypt = 0x0001531d; +phy_sec_efuse_lock = 0x0001532d; +phy_sec_encrypt = 0x00015339; +phy_sec_init = 0x00015349; +phy_sec_key_valid = 0x0001540d; +prog_process_data = 0x00015b19; +prog_uart_command = 0x00015c51; +prog_uart_fct_command = 0x00015c71; +prog_uart_handle = 0x00015c8d; +read_LL_remainder_time = 0x00015cbd; +read_current_fine_time = 0x00015cc9; +read_ll_adv_remainder_time = 0x00015cf1; +reset_conn_buf = 0x00015cfd; +rf_calibrate = 0x00015d75; +rf_init = 0x00015ded; +rf_phy_ana_cfg = 0x00015dfd; +rf_phy_bb_cfg = 0x00015f0d; +rf_phy_change_cfg = 0x00016085; +rf_phy_direct_test_ate = 0x00016129; +rf_phy_get_pktFoot = 0x00016669; +rf_phy_ini = 0x000166c1; +rf_phy_set_txPower = 0x000166dd; +rf_rxDcoc_cfg = 0x00016701; +rf_tpCal_cfg = 0x00016811; +rf_tpCal_cfg_avg = 0x0001683d; +rf_tpCal_gen_cap_arrary = 0x000168ed; +rf_tp_cal = 0x00016929; +rom_board_init = 0x00016a09; +rtc_clear = 0x00016ab5; +rtc_config_prescale = 0x00016ad1; +rtc_get_counter = 0x00016b15; +rtc_start = 0x00016b25; +rtc_stop = 0x00016b35; +setSleepMode = 0x00016b45; +set_access_address = 0x00016b51; +set_channel = 0x00016b5d; +set_crc_seed = 0x00016b9d; +set_gpio_pull_down_ate = 0x00016bb5; +set_gpio_pull_up_ate = 0x00016bcb; +set_int = 0x00016be1; +set_max_length = 0x00016bed; +set_sleep_flag = 0x00016c01; +set_timer = 0x00016c2d; +set_whiten_seed = 0x00016cc9; +spif_cmd = 0x00016d49; +spif_config = 0x00016dc5; +spif_erase_all = 0x00016ea1; +spif_erase_block64 = 0x00016ed1; +spif_erase_chip = 0x00016f55; +spif_erase_sector = 0x00016fa9; +spif_flash_size = 0x00017029; +spif_flash_status_reg_0 = 0x0001703d; +spif_flash_status_reg_1 = 0x00017047; +spif_init = 0x00017051; +spif_rddata = 0x0001713d; +spif_read = 0x00017165; +spif_read_dma = 0x0001717d; +spif_release_deep_sleep = 0x000172cd; +spif_set_deep_sleep = 0x00017349; +spif_wrdata = 0x0001736d; +spif_write = 0x00017395; +spif_write_dma = 0x0001744d; +spif_write_protect = 0x000174f9; +sram_ret_patch = 0x00017591; +update_rx_read_ptr = 0x00017609; +update_rx_write_ptr = 0x00017635; +update_tx_read_ptr = 0x00017659; +update_tx_write_ptr = 0x00017685; +wakeupProcess = 0x000176a9; +wakeupProcess0 = 0x000176c5; +wakeup_init = 0x000178a5; +wakeup_init0 = 0x000178bd; +zigbee_crc16_gen = 0x0001798d; +supportedCmdsTable = 0x00017c00; +hciCmdTable = 0x00017c44; +SCA = 0x00017c4c; +hclk_per_us = 0x1fff0818; +hclk_per_us_shift = 0x1fff081c; +s_prog_time_save = 0x1fff0828; +s_prog_timeout = 0x1fff082c; +DFL_ENTRY_BASE = 0x1fff0830; +receive_timeout_flag = 0x1fff0850; +osal_sys_tick = 0x1fff0860; +g_timer4_irq_pending_time = 0x1fff0864; +g_hclk = 0x1fff0874; +m_in_critical_region = 0x1fff0878; +s_rom_debug_level = 0x1fff0888; +s_spif_ctx = 0x1fff0894; +osal_qHead = 0x1fff08b8; +baseTaskID = 0x1fff08c0; +OSAL_timeSeconds = 0x1fff08cc; +ll_remain_time = 0x1fff08e4; +pwrmgr_attribute = 0x1fff08e8; +timerHead = 0x1fff08f0; +hciPTMenabled = 0x1fff08f8; +ctrlToHostEnable = 0x1fff08f9; +numHostBufs = 0x1fff08fa; +hciCtrlCmdToken = 0x1fff08fc; +bleEvtMask = 0x1fff0900; +pHciEvtMask = 0x1fff0904; +hciTaskID = 0x1fff090c; +hciTestTaskID = 0x1fff090d; +hciGapTaskID = 0x1fff090e; +hciL2capTaskID = 0x1fff090f; +hciSmpTaskID = 0x1fff0910; +hciExtTaskID = 0x1fff0911; +g_maxConnNum = 0x1fff0914; +g_maxPktPerEventTx = 0x1fff0915; +g_maxPktPerEventRx = 0x1fff0916; +g_blePktVersion = 0x1fff0917; +g_llRlEnable = 0x1fff0918; +g_llScanMode = 0x1fff0919; +g_llAdvMode = 0x1fff091a; +LL_TaskID = 0x1fff091b; +llState = 0x1fff091c; +numComplPkts = 0x1fff091d; +numComplPktsLimit = 0x1fff091e; +fastTxRespTime = 0x1fff091f; +g_llWlDeviceNum = 0x1fff0920; +g_llRlDeviceNum = 0x1fff0921; +rxFifoFlowCtrl = 0x1fff0922; +llSecondaryState = 0x1fff0923; +g_extAdvNumber = 0x1fff0924; +g_perioAdvNumber = 0x1fff0925; +g_schExtAdvNum = 0x1fff0926; +g_currentExtAdv = 0x1fff0927; +g_schExtAdvNum_periodic = 0x1fff0928; +g_currentExtAdv_periodic = 0x1fff0929; +g_llRlTimeout = 0x1fff092c; +g_advSetMaximumLen = 0x1fff0930; +conn_param = 0x1fff0934; +g_pExtendedAdvInfo = 0x1fff0938; +g_pPeriodicAdvInfo = 0x1fff093c; +g_pLLcteISample = 0x1fff0940; +g_pLLcteQSample = 0x1fff0944; +g_llHdcDirAdvTime = 0x1fff0948; +g_pAdvSchInfo = 0x1fff094c; +g_advPerSlotTick = 0x1fff0950; +g_advSlotPeriodic = 0x1fff0954; +g_pAdvSchInfo_periodic = 0x1fff0958; +g_timerExpiryTick = 0x1fff095c; +chanMapUpdate = 0x1fff0960; +ownPublicAddr = 0x1fff0965; +ownRandomAddr = 0x1fff096b; +verInfo = 0x1fff0972; +peerInfo = 0x1fff0978; +g_currentAdvTimer = 0x1fff0980; +g_currentTimerTask = 0x1fff0984; +g_adv_taskID = 0x1fff0988; +g_conn_taskID = 0x1fff0989; +g_smartWindowRTOCnt = 0x1fff098a; +isPeerRpaStore = 0x1fff098b; +g_same_rf_channel_flag = 0x1fff098c; +g_currentPeerAddrType = 0x1fff098d; +g_currentLocalAddrType = 0x1fff098e; +storeRpaListIndex = 0x1fff098f; +llTaskState = 0x1fff0990; +g_adv_taskEvent = 0x1fff0992; +g_conn_taskEvent = 0x1fff0994; +llWaitingIrq = 0x1fff0998; +ISR_entry_time = 0x1fff099c; +slave_conn_event_recv_delay = 0x1fff09a0; +g_smartWindowLater = 0x1fff09a4; +g_smartWindowActiveCnt = 0x1fff09a8; +g_smartWindowPreAnchPoint = 0x1fff09ac; +g_getPn23_cnt = 0x1fff09b0; +g_getPn23_seed = 0x1fff09b4; +llScanTime = 0x1fff09b8; +p_perStatsByChan = 0x1fff09bc; +LL_PLUS_AdvDataFilterCBack = 0x1fff09c0; +LL_PLUS_ScanRequestFilterCBack = 0x1fff09c4; +g_new_master_delta = 0x1fff09c8; +llScanT1 = 0x1fff09cc; +llCurrentScanChn = 0x1fff09d0; +g_currentLocalRpa = 0x1fff09d4; +g_currentPeerRpa = 0x1fff09da; +currentPeerRpa = 0x1fff09e0; +g_dle_taskID = 0x1fff09e6; +g_dle_taskEvent = 0x1fff09e8; +g_phyChg_taskID = 0x1fff09ea; +g_phyChg_taskEvent = 0x1fff09ec; +g_smartWindowSize = 0x1fff09f0; +g_smartWindowSizeNew = 0x1fff09f4; +g_smartWindowActive = 0x1fff09f8; +g_interAuxPduDuration = 0x1fff09fc; +connUpdateTimer = 0x1fff0a04; +sleep_flag = 0x1fff0a0c; +g_wakeup_rtc_tick = 0x1fff0a10; +g_counter_traking_avg = 0x1fff0a14; +g_TIM2_IRQ_TIM3_CurrCount = 0x1fff0a18; +g_TIM2_IRQ_to_Sleep_DeltTick = 0x1fff0a1c; +g_TIM2_IRQ_PendingTick = 0x1fff0a20; +g_osal_tick_trim = 0x1fff0a24; +g_osalTickTrim_mod = 0x1fff0a28; +rtc_mod_value = 0x1fff0a2c; +g_counter_traking_cnt = 0x1fff0a30; +sleep_tick = 0x1fff0a34; +counter_tracking = 0x1fff0a38; +forever_write = 0x1fff0a3c; +g_TIM2_wakeup_delay = 0x1fff0a40; +g_rfPhyTpCal0 = 0x1fff0a44; +g_rfPhyTpCal1 = 0x1fff0a45; +g_rfPhyTpCal0_2Mbps = 0x1fff0a46; +g_rfPhyTpCal1_2Mbps = 0x1fff0a47; +g_rfPhyTxPower = 0x1fff0a48; +g_rfPhyPktFmt = 0x1fff0a49; +g_system_clk = 0x1fff0a4a; +g_rfPhyClkSel = 0x1fff0a4b; +g_rxAdcClkSel = 0x1fff0a4c; +g_dtmModeType = 0x1fff0a4d; +g_dtmLength = 0x1fff0a4e; +g_dtmExtLen = 0x1fff0a4f; +g_dtmPKT = 0x1fff0a50; +g_dtmTxPower = 0x1fff0a51; +g_dtmRssi = 0x1fff0a52; +g_dtmCarrSens = 0x1fff0a53; +g_dtmPktIntv = 0x1fff0a54; +g_dtmPktCount = 0x1fff0a56; +g_dtmRxCrcNum = 0x1fff0a58; +g_dtmRxTONum = 0x1fff0a5a; +g_dtmRsp = 0x1fff0a5c; +g_dtmFoff = 0x1fff0a5e; +g_rfPhyRxDcIQ = 0x1fff0a60; +g_dtmTick = 0x1fff0a64; +g_rfPhyFreqOffSet = 0x1fff0a68; +g_rfPhyDtmCmd = 0x1fff0a69; +g_rfPhyDtmEvt = 0x1fff0a6b; +g_dtmCmd = 0x1fff0a6d; +g_dtmFreq = 0x1fff0a6e; +g_dtmCtrl = 0x1fff0a6f; +g_dtmPara = 0x1fff0a70; +g_dtmEvt = 0x1fff0a71; +g_dtmStatus = 0x1fff0a72; +g_dtmTpCalEnable = 0x1fff0a73; +g_dtmPerAutoIntv = 0x1fff0a74; +g_dtmAccessCode = 0x1fff0a78; +g_system_reset_cause = 0x1fff0a80; +cbTimers = 0x1fff0afc; +g_llSleepContext = 0x1fff0b74; +syncInfo = 0x1fff0b84; +scanSyncInfo = 0x1fff0b96; +adv_param = 0x1fff0ba6; +scanInfo = 0x1fff0bbc; +initInfo = 0x1fff0bd4; +extScanInfo = 0x1fff0be8; +extInitInfo = 0x1fff0c10; +g_llPeriodAdvSyncInfo = 0x1fff0c50; +g_ll_conn_ctx = 0x1fff0d30; +deviceFeatureSet = 0x1fff0e48; +g_llWhitelist = 0x1fff0e51; +g_llResolvinglist = 0x1fff0e89; +g_pmCounters = 0x1fff0ffc; +g_llPduLen = 0x1fff1084; +rfCounters = 0x1fff10e0; +ext_adv_hdr = 0x1fff10ec; +dataPkt = 0x1fff1118; +cachedTRNGdata = 0x1fff1138; +whiten_seed = 0x1fff1144; +g_tx_adv_buf = 0x1fff116c; +g_tx_ext_adv_buf = 0x1fff1278; +tx_scanRsp_desc = 0x1fff1384; +g_rx_adv_buf = 0x1fff1490; diff --git a/ota_boot/source/misc/ota_upboot.ld b/ota_boot/source/misc/ota_upboot.ld new file mode 100644 index 0000000..2d3a0ee --- /dev/null +++ b/ota_boot/source/misc/ota_upboot.ld @@ -0,0 +1,133 @@ +/* SRAM + XIP linker script */ +/* https://docs.oracle.com/cd/E19120-01/open.solaris/819-0690/6n33n7fds/index.html */ +PHDRS +{ + romdata PT_LOAD FLAGS(6); + text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); + xip PT_LOAD FLAGS(5); + rodata PT_LOAD FLAGS(4); +} + +MEMORY +{ + jumptbl (rw) : ORIGIN = 0x1fff0000, LENGTH = 0x00400 + gcfgtbl (rw) : ORIGIN = 0x1fff0400, LENGTH = 0x00400 + sram (rwx) : ORIGIN = 0x1fff1838, LENGTH = 0x0E7C8 + flash (rx) : ORIGIN = 0x11010100, LENGTH = 0x1ff00 + sram2 (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000 + sram3 (rwx) : ORIGIN = 0x20010000, LENGTH = 0x02000 + sram4 (rwx) : ORIGIN = 0x20012000, LENGTH = 0x00800 +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +ENTRY(__start) + +SECTIONS +{ + .jumptbl : { + *(jump_table_mem_area) + } > jumptbl : romdata + + .gcfgtbl (NOLOAD) : { + *(global_config_area) + } > gcfgtbl + + .textentry : { + *(*.isr_vector) + } > sram : text + + _sdata = ABSOLUTE(.); + .text : { + _stextram = ABSOLUTE(.); + + *phy6222_start.o(.text) + *phy6222_cstart.o(.text) + *main.o(.text.*) + *.o(_section_standby_code_) + *.o(_section_sram_code_) + + _etextram = ABSOLUTE(.); + } > sram : text + + .data : { + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + } > sram : data + . = ALIGN(4); + _edata = ABSOLUTE(.); + + .bss : { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > sram + + .irq_stack : { + *(g_irqstack_base) + } > sram + + g_stack = ORIGIN(sram) + LENGTH(sram); + + .xip : { + _stext = ABSOLUTE(.); + *.o(_func_xip_code_) + *.o(_section_xip_code_) + *(.text .text.*) + + _etext = ABSOLUTE(.); + } > flash : xip + + .rodata : { + *(.rodata .rodata.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + } > flash : rodata + + .init_section : { + _sinit = ABSOLUTE(.); + *(.init_array .init_array.*) + _einit = ABSOLUTE(.); + } > flash : rodata + + .ARM.extab : { + *(.ARM.extab*) + } > flash : rodata + + .ARM.exidx : { + __exidx_start = ABSOLUTE(.); + *(.ARM.exidx*) + __exidx_end = ABSOLUTE(.); + } > flash : rodata + + ._sjtblsstore : { + _sjtblss = ABSOLUTE(.); + } > flash : rodata + + /* 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) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } + +} diff --git a/ota_boot/source/misc/rom_sym_def.h b/ota_boot/source/misc/rom_sym_def.h new file mode 100644 index 0000000..30d419e --- /dev/null +++ b/ota_boot/source/misc/rom_sym_def.h @@ -0,0 +1,903 @@ +/************* + rom_sym_def.h + SDK_LICENSE +***************/ +#ifndef __ROM_SYM_H__ +#define __ROM_SYM_H__ +#ifdef USE_ROMSYM_ALIAS + + #define m_in_critical_region _symrom_m_in_critical_region + #define _spif_read_status_reg _symrom__spif_read_status_reg + #define _spif_wait_nobusy _symrom__spif_wait_nobusy + #define adv_param _symrom_adv_param + #define app_sleep_process _symrom_app_sleep_process + #define app_wakeup_process _symrom_app_wakeup_process + #define ate_fun_test _symrom_ate_fun_test + #define ate_sleep_process _symrom_ate_sleep_process + #define ate_wakeup_process _symrom_ate_wakeup_process + #define baseTaskID _symrom_baseTaskID + #define bit_to_byte _symrom_bit_to_byte + #define ble_crc24_gen _symrom_ble_crc24_gen + #define bleEvtMask _symrom_bleEvtMask + #define boot_init _symrom_boot_init + #define boot_init0 _symrom_boot_init0 + #define boot_m0 _symrom_boot_m0 + #define bx_to_application _symrom_bx_to_application + #define byte_to_bit _symrom_byte_to_bit + #define cachedTRNGdata _symrom_cachedTRNGdata + #define calculate_whiten_seed _symrom_calculate_whiten_seed + #define cbTimers _symrom_cbTimers + #define chanMapUpdate _symrom_chanMapUpdate + #define clear_timer _symrom_clear_timer + #define clear_timer_int _symrom_clear_timer_int + #define clk_get_pclk _symrom_clk_get_pclk + #define clk_init _symrom_clk_init + #define clk_set_pclk_div _symrom_clk_set_pclk_div + #define clk_spif_ref_clk _symrom_clk_spif_ref_clk + #define config_RTC _symrom_config_RTC + #define conn_param _symrom_conn_param + #define connUpdateTimer _symrom_connUpdateTimer + #define counter_tracking _symrom_counter_tracking + #define rom_crc16 _symrom_crc16 + #define ctrlToHostEnable _symrom_ctrlToHostEnable + #define dataPkt _symrom_dataPkt + #define debug_print _symrom_debug_print + #define deviceFeatureSet _symrom_deviceFeatureSet + #define disableSleep _symrom_disableSleep + #define drv_disable_irq _symrom_drv_disable_irq + #define drv_enable_irq _symrom_drv_enable_irq + #define drv_irq_init _symrom_drv_irq_init + #define dwc_connect _symrom_dwc_connect + #define dwc_data_process _symrom_dwc_data_process + #define dwc_loop _symrom_dwc_loop + #define efuse_read _symrom_efuse_read + #define enableSleep _symrom_enableSleep + #define enter_sleep_off_mode _symrom_enter_sleep_off_mode + #define enterSleepProcess _symrom_enterSleepProcess + #define ext_adv_hdr _symrom_ext_adv_hdr + #define extInitInfo _symrom_extInitInfo + #define extScanInfo _symrom_extScanInfo + #define fastTxRespTime _symrom_fastTxRespTime + #define forever_write _symrom_forever_write + #define g_adv_taskEvent _symrom_g_adv_taskEvent + #define g_adv_taskID _symrom_g_adv_taskID + #define g_advPerSlotTick _symrom_g_advPerSlotTick + #define g_advSetMaximumLen _symrom_g_advSetMaximumLen + #define g_advSlotPeriodic _symrom_g_advSlotPeriodic + #define g_blePktVersion _symrom_g_blePktVersion + #define g_conn_taskEvent _symrom_g_conn_taskEvent + #define g_conn_taskID _symrom_g_conn_taskID + #define g_counter_traking_avg _symrom_g_counter_traking_avg + #define g_counter_traking_cnt _symrom_g_counter_traking_cnt + #define g_currentAdvTimer _symrom_g_currentAdvTimer + #define g_currentExtAdv _symrom_g_currentExtAdv + #define g_currentExtAdv_periodic _symrom_g_currentExtAdv_periodic + #define g_currentTimerTask _symrom_g_currentTimerTask + #define g_dle_taskEvent _symrom_g_dle_taskEvent + #define g_dle_taskID _symrom_g_dle_taskID + //#define g_dtmAccessCode _symrom_g_dtmAccessCode + //#define g_dtmCarrSens _symrom_g_dtmCarrSens + //#define g_dtmCmd _symrom_g_dtmCmd + //#define g_dtmCtrl _symrom_g_dtmCtrl + //#define g_dtmEvt _symrom_g_dtmEvt + //#define g_dtmExtLen _symrom_g_dtmExtLen + //#define g_dtmFoff _symrom_g_dtmFoff + //#define g_dtmFreq _symrom_g_dtmFreq + //#define g_dtmLength _symrom_g_dtmLength + //#define g_dtmModeType _symrom_g_dtmModeType + //#define g_dtmPara _symrom_g_dtmPara + //#define g_dtmPerAutoIntv _symrom_g_dtmPerAutoIntv + //#define g_dtmPKT _symrom_g_dtmPKT + //#define g_dtmPktCount _symrom_g_dtmPktCount + //#define g_dtmPktIntv _symrom_g_dtmPktIntv + //#define g_dtmRsp _symrom_g_dtmRsp + //#define g_dtmRssi _symrom_g_dtmRssi + //#define g_dtmRxCrcNum _symrom_g_dtmRxCrcNum + //#define g_dtmRxTONum _symrom_g_dtmRxTONum + //#define g_dtmStatus _symrom_g_dtmStatus + //#define g_dtmTick _symrom_g_dtmTick + //#define g_dtmTpCalEnable _symrom_g_dtmTpCalEnable + //#define g_dtmTxPower _symrom_g_dtmTxPower + #define g_extAdvNumber _symrom_g_extAdvNumber + #define g_getPn23_cnt _symrom_g_getPn23_cnt + #define g_getPn23_seed _symrom_g_getPn23_seed + #define g_hclk _symrom_g_hclk + #define g_interAuxPduDuration _symrom_g_interAuxPduDuration + #define g_ll_conn_ctx _symrom_g_ll_conn_ctx + #define g_llHdcDirAdvTime _symrom_g_llHdcDirAdvTime + #define g_llPduLen _symrom_g_llPduLen + #define g_llPeriodAdvSyncInfo _symrom_g_llPeriodAdvSyncInfo + #define g_llResolvinglist _symrom_g_llResolvinglist + #define g_llRlDeviceNum _symrom_g_llRlDeviceNum + #define g_llRlEnable _symrom_g_llRlEnable + #define g_llRlTimeout _symrom_g_llRlTimeout + #define g_llSleepContext _symrom_g_llSleepContext + #define g_llWhitelist _symrom_g_llWhitelist + #define g_llWlDeviceNum _symrom_g_llWlDeviceNum + #define g_maxConnNum _symrom_g_maxConnNum + #define g_maxPktPerEventRx _symrom_g_maxPktPerEventRx + #define g_maxPktPerEventTx _symrom_g_maxPktPerEventTx + #define g_new_master_delta _symrom_g_new_master_delta + #define g_osal_tick_trim _symrom_g_osal_tick_trim + #define g_osalTickTrim_mod _symrom_g_osalTickTrim_mod + #define g_pAdvSchInfo _symrom_g_pAdvSchInfo + #define g_pAdvSchInfo_periodic _symrom_g_pAdvSchInfo_periodic + #define g_perioAdvNumber _symrom_g_perioAdvNumber + #define g_pExtendedAdvInfo _symrom_g_pExtendedAdvInfo + #define g_phyChg_taskEvent _symrom_g_phyChg_taskEvent + #define g_phyChg_taskID _symrom_g_phyChg_taskID + #define g_pLLcteISample _symrom_g_pLLcteISample + #define g_pLLcteQSample _symrom_g_pLLcteQSample + #define g_pmCounters _symrom_g_pmCounters + #define g_pPeriodicAdvInfo _symrom_g_pPeriodicAdvInfo + //#define g_rfPhyClkSel _symrom_g_rfPhyClkSel + //#define g_rfPhyDtmCmd _symrom_g_rfPhyDtmCmd + //#define g_rfPhyDtmEvt _symrom_g_rfPhyDtmEvt + //#define g_rfPhyFreqOffSet _symrom_g_rfPhyFreqOffSet + //#define g_rfPhyPktFmt _symrom_g_rfPhyPktFmt + //#define g_rfPhyRxDcIQ _symrom_g_rfPhyRxDcIQ + //#define g_rfPhyTpCal0 _symrom_g_rfPhyTpCal0 + //#define g_rfPhyTpCal0_2Mbps _symrom_g_rfPhyTpCal0_2Mbps + //#define g_rfPhyTpCal1 _symrom_g_rfPhyTpCal1 + //#define g_rfPhyTpCal1_2Mbps _symrom_g_rfPhyTpCal1_2Mbps + //#define g_rfPhyTxPower _symrom_g_rfPhyTxPower + #define g_rx_adv_buf _symrom_g_rx_adv_buf + //#define g_rxAdcClkSel _symrom_g_rxAdcClkSel + #define g_same_rf_channel_flag _symrom_g_same_rf_channel_flag + #define g_schExtAdvNum _symrom_g_schExtAdvNum + #define g_schExtAdvNum_periodic _symrom_g_schExtAdvNum_periodic + #define g_smartWindowActive _symrom_g_smartWindowActive + #define g_smartWindowActiveCnt _symrom_g_smartWindowActiveCnt + #define g_smartWindowLater _symrom_g_smartWindowLater + #define g_smartWindowPreAnchPoint _symrom_g_smartWindowPreAnchPoint + #define g_smartWindowRTOCnt _symrom_g_smartWindowRTOCnt + #define g_smartWindowSize _symrom_g_smartWindowSize + #define g_smartWindowSizeNew _symrom_g_smartWindowSizeNew + #define g_system_clk _symrom_g_system_clk + #define g_TIM2_IRQ_PendingTick _symrom_g_TIM2_IRQ_PendingTick + #define g_TIM2_IRQ_TIM3_CurrCount _symrom_g_TIM2_IRQ_TIM3_CurrCount + #define g_TIM2_IRQ_to_Sleep_DeltTick _symrom_g_TIM2_IRQ_to_Sleep_DeltTick + #define g_TIM2_wakeup_delay _symrom_g_TIM2_wakeup_delay + #define g_timerExpiryTick _symrom_g_timerExpiryTick + #define g_tx_adv_buf _symrom_g_tx_adv_buf + #define g_tx_ext_adv_buf _symrom_g_tx_ext_adv_buf + #define g_wakeup_rtc_tick _symrom_g_wakeup_rtc_tick + #define get_rx_read_ptr _symrom_get_rx_read_ptr + #define get_rx_write_ptr _symrom_get_rx_write_ptr + #define get_sleep_flag _symrom_get_sleep_flag + #define get_timer_count _symrom_get_timer_count + #define get_timer_int _symrom_get_timer_int + #define get_tx_read_ptr _symrom_get_tx_read_ptr + #define get_tx_write_ptr _symrom_get_tx_write_ptr + #define getMcuPrecisionCount _symrom_getMcuPrecisionCount + #define getPN23RandNumber _symrom_getPN23RandNumber + #define getRxBufferFree _symrom_getRxBufferFree + #define getRxBufferSize _symrom_getRxBufferSize + #define getSleepMode _symrom_getSleepMode + #define getTxBufferFree _symrom_getTxBufferFree + #define getTxBufferSize _symrom_getTxBufferSize + #define gpio_cfg_analog_io _symrom_gpio_cfg_analog_io + #define gpio_dir _symrom_gpio_dir + #define gpio_fmux_control _symrom_gpio_fmux_control + #define gpio_fmux_set _symrom_gpio_fmux_set + #define gpio_in_trigger _symrom_gpio_in_trigger + #define gpio_init _symrom_gpio_init + #define gpio_interrupt_set _symrom_gpio_interrupt_set + #define GPIO_IRQHandler _symrom_GPIO_IRQHandler + #define gpio_pull_set _symrom_gpio_pull_set + #define gpio_read _symrom_gpio_read + #define gpio_wakeup_set _symrom_gpio_wakeup_set + #define gpio_write _symrom_gpio_write + #define HardFault_Handler _symrom_HardFault_Handler + #define HardFault_IRQHandler _symrom_HardFault_IRQHandler + #define HCI_bm_alloc _symrom_HCI_bm_alloc + #define HCI_CommandCompleteEvent _symrom_HCI_CommandCompleteEvent + #define HCI_CommandStatusEvent _symrom_HCI_CommandStatusEvent + #define HCI_DataBufferOverflowEvent _symrom_HCI_DataBufferOverflowEvent + #define HCI_DisconnectCmd _symrom_HCI_DisconnectCmd + #define HCI_ExtTaskRegister _symrom_HCI_ExtTaskRegister + #define HCI_GAPTaskRegister _symrom_HCI_GAPTaskRegister + #define HCI_HardwareErrorEvent _symrom_HCI_HardwareErrorEvent + #define HCI_HostBufferSizeCmd _symrom_HCI_HostBufferSizeCmd + #define HCI_HostNumCompletedPktCmd _symrom_HCI_HostNumCompletedPktCmd + #define HCI_Init _symrom_HCI_Init + #define HCI_L2CAPTaskRegister _symrom_HCI_L2CAPTaskRegister + #define HCI_LE_AddDevToResolvingListCmd _symrom_HCI_LE_AddDevToResolvingListCmd + #define HCI_LE_AddWhiteListCmd _symrom_HCI_LE_AddWhiteListCmd + #define HCI_LE_ClearAdvSetsCmd _symrom_HCI_LE_ClearAdvSetsCmd + #define HCI_LE_ClearResolvingListCmd _symrom_HCI_LE_ClearResolvingListCmd + #define HCI_LE_ClearWhiteListCmd _symrom_HCI_LE_ClearWhiteListCmd + #define HCI_LE_Connection_CTE_Request_EnableCmd _symrom_HCI_LE_Connection_CTE_Request_EnableCmd + #define HCI_LE_Connection_CTE_Response_EnableCmd _symrom_HCI_LE_Connection_CTE_Response_EnableCmd + #define HCI_LE_ConnectionlessCTE_TransmitEnableCmd _symrom_HCI_LE_ConnectionlessCTE_TransmitEnableCmd + #define HCI_LE_ConnectionlessCTE_TransmitParamCmd _symrom_HCI_LE_ConnectionlessCTE_TransmitParamCmd + #define HCI_LE_ConnectionlessIQ_SampleEnableCmd _symrom_HCI_LE_ConnectionlessIQ_SampleEnableCmd + #define HCI_LE_ConnUpdateCmd _symrom_HCI_LE_ConnUpdateCmd + #define HCI_LE_CreateConnCancelCmd _symrom_HCI_LE_CreateConnCancelCmd + #define HCI_LE_CreateConnCmd _symrom_HCI_LE_CreateConnCmd + #define HCI_LE_EncryptCmd _symrom_HCI_LE_EncryptCmd + #define HCI_LE_ExtendedCreateConnectionCmd _symrom_HCI_LE_ExtendedCreateConnectionCmd + #define HCI_LE_LtkReqNegReplyCmd _symrom_HCI_LE_LtkReqNegReplyCmd + #define HCI_LE_LtkReqReplyCmd _symrom_HCI_LE_LtkReqReplyCmd + #define HCI_LE_PeriodicAdvertisingCreateSyncCancelCmd _symrom_HCI_LE_PeriodicAdvertisingCreateSyncCancelCmd + #define HCI_LE_PeriodicAdvertisingCreateSyncCmd _symrom_HCI_LE_PeriodicAdvertisingCreateSyncCmd + #define HCI_LE_PeriodicAdvertisingTerminateSyncCmd _symrom_HCI_LE_PeriodicAdvertisingTerminateSyncCmd + #define HCI_LE_RandCmd _symrom_HCI_LE_RandCmd + #define HCI_LE_READ_Anatenna_InfoCmd _symrom_HCI_LE_READ_Anatenna_InfoCmd + #define HCI_LE_ReadAdvChanTxPowerCmd _symrom_HCI_LE_ReadAdvChanTxPowerCmd + #define HCI_LE_ReadBufSizeCmd _symrom_HCI_LE_ReadBufSizeCmd + #define HCI_LE_ReadChannelMapCmd _symrom_HCI_LE_ReadChannelMapCmd + #define HCI_LE_ReadLocalSupportedFeaturesCmd _symrom_HCI_LE_ReadLocalSupportedFeaturesCmd + #define HCI_LE_ReadMaxDataLengthCmd _symrom_HCI_LE_ReadMaxDataLengthCmd + #define HCI_LE_ReadMaximumAdvDataLengthCmd _symrom_HCI_LE_ReadMaximumAdvDataLengthCmd + #define HCI_LE_ReadNumberOfSupportAdvSetCmd _symrom_HCI_LE_ReadNumberOfSupportAdvSetCmd + #define HCI_LE_ReadPhyMode _symrom_HCI_LE_ReadPhyMode + #define HCI_LE_ReadRemoteUsedFeaturesCmd _symrom_HCI_LE_ReadRemoteUsedFeaturesCmd + #define HCI_LE_ReadResolvingListSizeCmd _symrom_HCI_LE_ReadResolvingListSizeCmd + #define HCI_LE_ReadSuggestedDefaultDataLengthCmd _symrom_HCI_LE_ReadSuggestedDefaultDataLengthCmd + #define HCI_LE_ReadSupportedStatesCmd _symrom_HCI_LE_ReadSupportedStatesCmd + #define HCI_LE_ReadWhiteListSizeCmd _symrom_HCI_LE_ReadWhiteListSizeCmd + #define HCI_LE_ReceiverTestCmd _symrom_HCI_LE_ReceiverTestCmd + #define HCI_LE_RemoveAdvSetCmd _symrom_HCI_LE_RemoveAdvSetCmd + #define HCI_LE_RemoveResolvingListCmd _symrom_HCI_LE_RemoveResolvingListCmd + #define HCI_LE_RemoveWhiteListCmd _symrom_HCI_LE_RemoveWhiteListCmd + #define HCI_LE_Set_ConnectionCTE_ReceiveParamCmd _symrom_HCI_LE_Set_ConnectionCTE_ReceiveParamCmd + #define HCI_LE_Set_ConnectionCTE_TransmitParamCmd _symrom_HCI_LE_Set_ConnectionCTE_TransmitParamCmd + #define HCI_LE_SetAddressResolutionEnableCmd _symrom_HCI_LE_SetAddressResolutionEnableCmd + #define HCI_LE_SetAdvDataCmd _symrom_HCI_LE_SetAdvDataCmd + #define HCI_LE_SetAdvEnableCmd _symrom_HCI_LE_SetAdvEnableCmd + #define HCI_LE_SetAdvParamCmd _symrom_HCI_LE_SetAdvParamCmd + #define HCI_LE_SetDataLengthCmd _symrom_HCI_LE_SetDataLengthCmd + #define HCI_LE_SetDefaultPhyMode _symrom_HCI_LE_SetDefaultPhyMode + #define HCI_LE_SetEventMaskCmd _symrom_HCI_LE_SetEventMaskCmd + #define HCI_LE_SetExtAdvDataCmd _symrom_HCI_LE_SetExtAdvDataCmd + #define HCI_LE_SetExtAdvEnableCmd _symrom_HCI_LE_SetExtAdvEnableCmd + #define HCI_LE_SetExtAdvParamCmd _symrom_HCI_LE_SetExtAdvParamCmd + #define HCI_LE_SetExtAdvSetRandomAddressCmd _symrom_HCI_LE_SetExtAdvSetRandomAddressCmd + #define HCI_LE_SetExtendedScanEnableCmd _symrom_HCI_LE_SetExtendedScanEnableCmd + #define HCI_LE_SetExtendedScanParametersCmd _symrom_HCI_LE_SetExtendedScanParametersCmd + #define HCI_LE_SetExtScanRspDataCmd _symrom_HCI_LE_SetExtScanRspDataCmd + #define HCI_LE_SetHostChanClassificationCmd _symrom_HCI_LE_SetHostChanClassificationCmd + #define HCI_LE_SetPeriodicAdvDataCmd _symrom_HCI_LE_SetPeriodicAdvDataCmd + #define HCI_LE_SetPeriodicAdvEnableCmd _symrom_HCI_LE_SetPeriodicAdvEnableCmd + #define HCI_LE_SetPeriodicAdvParameterCmd _symrom_HCI_LE_SetPeriodicAdvParameterCmd + #define HCI_LE_SetPhyMode _symrom_HCI_LE_SetPhyMode + #define HCI_LE_SetRandomAddressCmd _symrom_HCI_LE_SetRandomAddressCmd + #define HCI_LE_SetResolvablePrivateAddressTimeoutCmd _symrom_HCI_LE_SetResolvablePrivateAddressTimeoutCmd + #define HCI_LE_SetScanEnableCmd _symrom_HCI_LE_SetScanEnableCmd + #define HCI_LE_SetScanParamCmd _symrom_HCI_LE_SetScanParamCmd + #define HCI_LE_SetScanRspDataCmd _symrom_HCI_LE_SetScanRspDataCmd + #define HCI_LE_StartEncyptCmd _symrom_HCI_LE_StartEncyptCmd + #define HCI_LE_TestEndCmd _symrom_HCI_LE_TestEndCmd + #define HCI_LE_TransmitterTestCmd _symrom_HCI_LE_TransmitterTestCmd + #define HCI_LE_WriteSuggestedDefaultDataLengthCmd _symrom_HCI_LE_WriteSuggestedDefaultDataLengthCmd + #define HCI_NumOfCompletedPacketsEvent _symrom_HCI_NumOfCompletedPacketsEvent + #define HCI_ProcessEvent _symrom_HCI_ProcessEvent + #define HCI_ReadBDADDRCmd _symrom_HCI_ReadBDADDRCmd + #define HCI_ReadLocalSupportedCommandsCmd _symrom_HCI_ReadLocalSupportedCommandsCmd + #define HCI_ReadLocalSupportedFeaturesCmd _symrom_HCI_ReadLocalSupportedFeaturesCmd + #define HCI_ReadLocalVersionInfoCmd _symrom_HCI_ReadLocalVersionInfoCmd + #define HCI_ReadRemoteVersionInfoCmd _symrom_HCI_ReadRemoteVersionInfoCmd + #define HCI_ReadRssiCmd _symrom_HCI_ReadRssiCmd + #define HCI_ReadTransmitPowerLevelCmd _symrom_HCI_ReadTransmitPowerLevelCmd + #define HCI_ResetCmd _symrom_HCI_ResetCmd + #define HCI_ReverseBytes _symrom_HCI_ReverseBytes + #define HCI_SendCommandCompleteEvent _symrom_HCI_SendCommandCompleteEvent + #define HCI_SendCommandStatusEvent _symrom_HCI_SendCommandStatusEvent + #define HCI_SendControllerToHostEvent _symrom_HCI_SendControllerToHostEvent + #define HCI_SendDataPkt _symrom_HCI_SendDataPkt + #define HCI_SetControllerToHostFlowCtrlCmd _symrom_HCI_SetControllerToHostFlowCtrlCmd + #define HCI_SetEventMaskCmd _symrom_HCI_SetEventMaskCmd + #define HCI_SMPTaskRegister _symrom_HCI_SMPTaskRegister + #define HCI_TestAppTaskRegister _symrom_HCI_TestAppTaskRegister + #define HCI_ValidConnTimeParams _symrom_HCI_ValidConnTimeParams + #define HCI_VendorSpecifcCommandCompleteEvent _symrom_HCI_VendorSpecifcCommandCompleteEvent + #define hciCmdTable _symrom_hciCmdTable + #define hciCtrlCmdToken _symrom_hciCtrlCmdToken + #define hciExtTaskID _symrom_hciExtTaskID + #define hciGapTaskID _symrom_hciGapTaskID + #define hciInitEventMasks _symrom_hciInitEventMasks + #define hciL2capTaskID _symrom_hciL2capTaskID + #define hciPTMenabled _symrom_hciPTMenabled + #define hciSmpTaskID _symrom_hciSmpTaskID + #define hciTaskID _symrom_hciTaskID + #define hciTestTaskID _symrom_hciTestTaskID + #define hclk_per_us _symrom_hclk_per_us + #define hclk_per_us_shift _symrom_hclk_per_us_shift + #define initInfo _symrom_initInfo + #define ISR_entry_time _symrom_ISR_entry_time + #define isSleepAllow _symrom_isSleepAllow + #define isTimer1Running _symrom_isTimer1Running + #define isTimer4Running _symrom_isTimer4Running + #define jump_area_init _symrom_jump_area_init + #define ll_add_adv_task _symrom_ll_add_adv_task + #define ll_add_adv_task_periodic _symrom_ll_add_adv_task_periodic + #define LL_AddResolvingListLDevice _symrom_LL_AddResolvingListLDevice + #define ll_addTask _symrom_ll_addTask + #define LL_AddWhiteListDevice _symrom_LL_AddWhiteListDevice + #define ll_adptive_adj_next_time _symrom_ll_adptive_adj_next_time + #define ll_adptive_smart_window _symrom_ll_adptive_smart_window + #define ll_adv_scheduler _symrom_ll_adv_scheduler + #define ll_adv_scheduler_periodic _symrom_ll_adv_scheduler_periodic + #define LL_AdvReportCback _symrom_LL_AdvReportCback + #define ll_allocAuxAdvTimeSlot _symrom_ll_allocAuxAdvTimeSlot + #define ll_allocAuxAdvTimeSlot_prd _symrom_ll_allocAuxAdvTimeSlot_prd + #define ll_CalcRandomAddr _symrom_ll_CalcRandomAddr + #define LL_ChanMapUpdate _symrom_LL_ChanMapUpdate + #define LL_ClearAdvSets _symrom_LL_ClearAdvSets + #define LL_ClearResolvingList _symrom_LL_ClearResolvingList + #define LL_ClearWhiteList _symrom_LL_ClearWhiteList + #define LL_ConnActive _symrom_LL_ConnActive + #define LL_Connection_CTE_Request_Enable _symrom_LL_Connection_CTE_Request_Enable + #define LL_Connection_CTE_Response_Enable _symrom_LL_Connection_CTE_Response_Enable + #define LL_ConnectionCompleteCback _symrom_LL_ConnectionCompleteCback + #define LL_ConnectionIQReportCback _symrom_LL_ConnectionIQReportCback + #define LL_ConnectionlessCTE_TransmitEnable _symrom_LL_ConnectionlessCTE_TransmitEnable + #define LL_ConnectionlessCTE_TransmitParam _symrom_LL_ConnectionlessCTE_TransmitParam + #define LL_ConnectionlessIQ_SampleEnable _symrom_LL_ConnectionlessIQ_SampleEnable + #define LL_ConnectionlessIQReportCback _symrom_LL_ConnectionlessIQReportCback + #define LL_ConnParamUpdateCback _symrom_LL_ConnParamUpdateCback + #define LL_ConnUpdate _symrom_LL_ConnUpdate + #define LL_CreateConn _symrom_LL_CreateConn + #define LL_CreateConnCancel _symrom_LL_CreateConnCancel + #define LL_CTE_Report_FailedCback _symrom_LL_CTE_Report_FailedCback + #define LL_CtrlToHostFlowControl _symrom_LL_CtrlToHostFlowControl + #define LL_DataLengthChangeCback _symrom_LL_DataLengthChangeCback + #define ll_debug_output _symrom_ll_debug_output + #define ll_delete_adv_task _symrom_ll_delete_adv_task + #define ll_delete_adv_task_periodic _symrom_ll_delete_adv_task_periodic + #define ll_deleteTask _symrom_ll_deleteTask + #define LL_DirectTestEnd _symrom_LL_DirectTestEnd + #define LL_DirectTestTxTest _symrom_LL_DirectTestTxTest + #define LL_Disconnect _symrom_LL_Disconnect + #define LL_DisconnectCback _symrom_LL_DisconnectCback + #define LL_ENC_AES128_Encrypt _symrom_LL_ENC_AES128_Encrypt + #define LL_ENC_Decrypt _symrom_LL_ENC_Decrypt + #define LL_ENC_Encrypt _symrom_LL_ENC_Encrypt + #define LL_ENC_GenDeviceIV _symrom_LL_ENC_GenDeviceIV + #define LL_ENC_GenDeviceSKD _symrom_LL_ENC_GenDeviceSKD + #define LL_ENC_GenerateNonce _symrom_LL_ENC_GenerateNonce + #define LL_ENC_GeneratePseudoRandNum _symrom_LL_ENC_GeneratePseudoRandNum + #define LL_ENC_GenerateTrueRandNum _symrom_LL_ENC_GenerateTrueRandNum + #define LL_ENC_LoadKey _symrom_LL_ENC_LoadKey + #define LL_ENC_ReverseBytes _symrom_LL_ENC_ReverseBytes + #define LL_ENC_sm_ah _symrom_LL_ENC_sm_ah + #define LL_EncChangeCback _symrom_LL_EncChangeCback + #define LL_EncKeyRefreshCback _symrom_LL_EncKeyRefreshCback + #define LL_EncLtkNegReply _symrom_LL_EncLtkNegReply + #define LL_EncLtkReply _symrom_LL_EncLtkReply + #define LL_EncLtkReqCback _symrom_LL_EncLtkReqCback + #define LL_Encrypt _symrom_LL_Encrypt + #define LL_evt_schedule _symrom_LL_evt_schedule + #define ll_ext_adv_schedule_next_event _symrom_ll_ext_adv_schedule_next_event + #define LL_EXT_AdvEventNotice _symrom_LL_EXT_AdvEventNotice + #define LL_EXT_BuildRevision _symrom_LL_EXT_BuildRevision + #define LL_EXT_ClkDivOnHalt _symrom_LL_EXT_ClkDivOnHalt + #define LL_EXT_ConnEventNotice _symrom_LL_EXT_ConnEventNotice + #define LL_EXT_DeclareNvUsage _symrom_LL_EXT_DeclareNvUsage + #define LL_EXT_Decrypt _symrom_LL_EXT_Decrypt + #define LL_EXT_DelaySleep _symrom_LL_EXT_DelaySleep + #define LL_EXT_DisconnectImmed _symrom_LL_EXT_DisconnectImmed + #define LL_EXT_EndModemTest _symrom_LL_EXT_EndModemTest + #define LL_EXT_HaltDuringRf _symrom_LL_EXT_HaltDuringRf + #define LL_EXT_Init_IQ_pBuff _symrom_LL_EXT_Init_IQ_pBuff + #define ll_ext_init_schedule_next_event _symrom_ll_ext_init_schedule_next_event + #define LL_EXT_MapPmIoPort _symrom_LL_EXT_MapPmIoPort + #define LL_EXT_ModemHopTestTx _symrom_LL_EXT_ModemHopTestTx + #define LL_EXT_ModemTestRx _symrom_LL_EXT_ModemTestRx + #define LL_EXT_ModemTestTx _symrom_LL_EXT_ModemTestTx + #define LL_EXT_NumComplPktsLimit _symrom_LL_EXT_NumComplPktsLimit + #define LL_EXT_OnePacketPerEvent _symrom_LL_EXT_OnePacketPerEvent + #define LL_EXT_OverlappedProcessing _symrom_LL_EXT_OverlappedProcessing + #define LL_EXT_PacketErrorRate _symrom_LL_EXT_PacketErrorRate + #define LL_EXT_PERbyChan _symrom_LL_EXT_PERbyChan + #define LL_EXT_ResetSystem _symrom_LL_EXT_ResetSystem + #define LL_EXT_SaveFreqTune _symrom_LL_EXT_SaveFreqTune + #define ll_ext_scan_schedule_next_event _symrom_ll_ext_scan_schedule_next_event + #define LL_EXT_SetBDADDR _symrom_LL_EXT_SetBDADDR + #define LL_EXT_SetFastTxResponseTime _symrom_LL_EXT_SetFastTxResponseTime + #define LL_EXT_SetFreqTune _symrom_LL_EXT_SetFreqTune + #define LL_EXT_SetLocalSupportedFeatures _symrom_LL_EXT_SetLocalSupportedFeatures + #define LL_EXT_SetMaxDtmTxPower _symrom_LL_EXT_SetMaxDtmTxPower + #define LL_EXT_SetRxGain _symrom_LL_EXT_SetRxGain + #define LL_EXT_SetSCA _symrom_LL_EXT_SetSCA + #define LL_EXT_SetSlaveLatencyOverride _symrom_LL_EXT_SetSlaveLatencyOverride + #define LL_EXT_SetTxPower _symrom_LL_EXT_SetTxPower + #define LL_ExtAdvReportCback _symrom_LL_ExtAdvReportCback + #define LL_extAdvTimerExpProcess _symrom_LL_extAdvTimerExpProcess + #define LL_ExtendedCreateConnection _symrom_LL_ExtendedCreateConnection + #define LL_extInitTimerExpProcess _symrom_LL_extInitTimerExpProcess + #define LL_extScanTimerExpProcess _symrom_LL_extScanTimerExpProcess + #define ll_generateExtAdvDid _symrom_ll_generateExtAdvDid + #define ll_generateTxBuffer _symrom_ll_generateTxBuffer + #define ll_get_next_active_conn _symrom_ll_get_next_active_conn + #define ll_get_next_timer _symrom_ll_get_next_timer + #define ll_getFirstAdvChn _symrom_ll_getFirstAdvChn + #define ll_getRPAListEntry _symrom_ll_getRPAListEntry + #define ll_hw_clr_irq _symrom_ll_hw_clr_irq + #define ll_hw_config _symrom_ll_hw_config + #define ll_hw_get_anchor _symrom_ll_hw_get_anchor + #define ll_hw_get_fsm_status _symrom_ll_hw_get_fsm_status + #define ll_hw_get_iq_RawSample _symrom_ll_hw_get_iq_RawSample + #define ll_hw_get_irq_status _symrom_ll_hw_get_irq_status + #define ll_hw_get_last_ack _symrom_ll_hw_get_last_ack + #define ll_hw_get_loop_cycle _symrom_ll_hw_get_loop_cycle + #define ll_hw_get_loop_time _symrom_ll_hw_get_loop_time + #define ll_hw_get_nAck _symrom_ll_hw_get_nAck + #define ll_hw_get_rfifo_depth _symrom_ll_hw_get_rfifo_depth + #define ll_hw_get_rfifo_info _symrom_ll_hw_get_rfifo_info + #define ll_hw_get_rxPkt_CrcErr_num _symrom_ll_hw_get_rxPkt_CrcErr_num + #define ll_hw_get_rxPkt_CrcOk_num _symrom_ll_hw_get_rxPkt_CrcOk_num + #define ll_hw_get_rxPkt_num _symrom_ll_hw_get_rxPkt_num + #define ll_hw_get_rxPkt_stats _symrom_ll_hw_get_rxPkt_stats + #define ll_hw_get_rxPkt_Total_num _symrom_ll_hw_get_rxPkt_Total_num + #define ll_hw_get_snNesn _symrom_ll_hw_get_snNesn + #define ll_hw_get_tfifo_info _symrom_ll_hw_get_tfifo_info + #define ll_hw_get_tfifo_wrptr _symrom_ll_hw_get_tfifo_wrptr + #define ll_hw_get_tr_mode _symrom_ll_hw_get_tr_mode + #define ll_hw_get_txAck _symrom_ll_hw_get_txAck + #define ll_hw_go _symrom_ll_hw_go + #define ll_hw_ign_rfifo _symrom_ll_hw_ign_rfifo + #define ll_hw_process_RTO _symrom_ll_hw_process_RTO + #define ll_hw_read_rfifo _symrom_ll_hw_read_rfifo + #define ll_hw_read_rfifo_pplus _symrom_ll_hw_read_rfifo_pplus + #define ll_hw_read_rfifo_zb _symrom_ll_hw_read_rfifo_zb + #define ll_hw_read_tfifo_packet _symrom_ll_hw_read_tfifo_packet + #define ll_hw_read_tfifo_rtlp _symrom_ll_hw_read_tfifo_rtlp + #define ll_hw_rst_rfifo _symrom_ll_hw_rst_rfifo + #define ll_hw_rst_tfifo _symrom_ll_hw_rst_tfifo + #define ll_hw_set_ant_pattern _symrom_ll_hw_set_ant_pattern + #define ll_hw_set_ant_switch_mode _symrom_ll_hw_set_ant_switch_mode + #define ll_hw_set_ant_switch_timing _symrom_ll_hw_set_ant_switch_timing + #define ll_hw_set_crc_fmt _symrom_ll_hw_set_crc_fmt + #define ll_hw_set_cte_rxSupp _symrom_ll_hw_set_cte_rxSupp + #define ll_hw_set_cte_txSupp _symrom_ll_hw_set_cte_txSupp + #define ll_hw_set_empty_head _symrom_ll_hw_set_empty_head + #define ll_hw_set_irq _symrom_ll_hw_set_irq + #define ll_hw_set_loop_nack_num _symrom_ll_hw_set_loop_nack_num + #define ll_hw_set_loop_timeout _symrom_ll_hw_set_loop_timeout + #define ll_hw_set_pplus_pktfmt _symrom_ll_hw_set_pplus_pktfmt + #define ll_hw_set_rtlp _symrom_ll_hw_set_rtlp + #define ll_hw_set_rtlp_1st _symrom_ll_hw_set_rtlp_1st + #define ll_hw_set_rtx _symrom_ll_hw_set_rtx + #define ll_hw_set_rx_timeout _symrom_ll_hw_set_rx_timeout + #define ll_hw_set_rx_timeout_1st _symrom_ll_hw_set_rx_timeout_1st + #define ll_hw_set_rx_tx_interval _symrom_ll_hw_set_rx_tx_interval + #define ll_hw_set_srx _symrom_ll_hw_set_srx + #define ll_hw_set_stx _symrom_ll_hw_set_stx + #define ll_hw_set_tfifo_space _symrom_ll_hw_set_tfifo_space + #define ll_hw_set_timing _symrom_ll_hw_set_timing + #define ll_hw_set_trlp _symrom_ll_hw_set_trlp + #define ll_hw_set_trx _symrom_ll_hw_set_trx + #define ll_hw_set_trx_settle _symrom_ll_hw_set_trx_settle + #define ll_hw_set_tx_rx_interval _symrom_ll_hw_set_tx_rx_interval + #define ll_hw_set_tx_rx_release _symrom_ll_hw_set_tx_rx_release + #define ll_hw_trigger _symrom_ll_hw_trigger + #define ll_hw_trx_settle_config _symrom_ll_hw_trx_settle_config + #define ll_hw_tx2rx_timing_config _symrom_ll_hw_tx2rx_timing_config + #define ll_hw_update _symrom_ll_hw_update + #define ll_hw_update_rtlp_mode _symrom_ll_hw_update_rtlp_mode + #define ll_hw_update_trlp_mode _symrom_ll_hw_update_trlp_mode + #define ll_hw_write_tfifo _symrom_ll_hw_write_tfifo + #define LL_Init _symrom_LL_Init + #define LL_InitConnectContext _symrom_LL_InitConnectContext + #define LL_InitExtendedAdv _symrom_LL_InitExtendedAdv + #define LL_InitExtendedScan _symrom_LL_InitExtendedScan + #define LL_InitPeriodicAdv _symrom_LL_InitPeriodicAdv + #define LL_IRQHandler _symrom_LL_IRQHandler + #define ll_isAddrInWhiteList _symrom_ll_isAddrInWhiteList + #define ll_isFirstAdvChn _symrom_ll_isFirstAdvChn + #define LL_master_conn_event _symrom_LL_master_conn_event + #define LL_NumEmptyWlEntries _symrom_LL_NumEmptyWlEntries + #define ll_parseExtHeader _symrom_ll_parseExtHeader + #define LL_PeriodicAdvertisingCreateSync _symrom_LL_PeriodicAdvertisingCreateSync + #define LL_PeriodicAdvertisingCreateSyncCancel _symrom_LL_PeriodicAdvertisingCreateSyncCancel + #define LL_PeriodicAdvertisingTerminateSync _symrom_LL_PeriodicAdvertisingTerminateSync + #define LL_PhyUpdate _symrom_LL_PhyUpdate + #define LL_PhyUpdateCompleteCback _symrom_LL_PhyUpdateCompleteCback + #define LL_PLUS_AdvDataFilterCBack _symrom_LL_PLUS_AdvDataFilterCBack + #define LL_PLUS_DisableSlaveLatency _symrom_LL_PLUS_DisableSlaveLatency + #define LL_PLUS_EnableSlaveLatency _symrom_LL_PLUS_EnableSlaveLatency + #define LL_PLUS_GetAdvDataExtendData _symrom_LL_PLUS_GetAdvDataExtendData + #define LL_PLUS_GetScanerAddr _symrom_LL_PLUS_GetScanerAddr + #define LL_PLUS_GetScanRequestExtendData _symrom_LL_PLUS_GetScanRequestExtendData + #define LL_PLUS_PerStasReadByChn _symrom_LL_PLUS_PerStasReadByChn + #define LL_PLUS_PerStats_Init _symrom_LL_PLUS_PerStats_Init + #define LL_PLUS_PerStatsReset _symrom_LL_PLUS_PerStatsReset + #define LL_PLUS_ScanRequestFilterCBack _symrom_LL_PLUS_ScanRequestFilterCBack + #define LL_PLUS_SetAdvDataFilterCB _symrom_LL_PLUS_SetAdvDataFilterCB + #define LL_PLUS_SetScanRequestData _symrom_LL_PLUS_SetScanRequestData + #define LL_PLUS_SetScanRequestFilterCB _symrom_LL_PLUS_SetScanRequestFilterCB + #define LL_PLUS_SetScanRsqData _symrom_LL_PLUS_SetScanRsqData + #define LL_PLUS_SetScanRsqDataByIndex _symrom_LL_PLUS_SetScanRsqDataByIndex + #define ll_prd_adv_schedule_next_event _symrom_ll_prd_adv_schedule_next_event + #define ll_prd_scan_schedule_next_event _symrom_ll_prd_scan_schedule_next_event + #define LL_PrdAdvReportCback _symrom_LL_PrdAdvReportCback + #define LL_PrdAdvSyncEstablishedCback _symrom_LL_PrdAdvSyncEstablishedCback + #define LL_PrdAdvSyncLostCback _symrom_LL_PrdAdvSyncLostCback + #define LL_prdAdvTimerExpProcess _symrom_LL_prdAdvTimerExpProcess + #define LL_prdScanTimerExpProcess _symrom_LL_prdScanTimerExpProcess + #define ll_processBasicIRQ _symrom_ll_processBasicIRQ + #define LL_ProcessEvent _symrom_LL_ProcessEvent + #define ll_processExtAdvIRQ _symrom_ll_processExtAdvIRQ + #define ll_processExtInitIRQ _symrom_ll_processExtInitIRQ + #define ll_processExtScanIRQ _symrom_ll_processExtScanIRQ + #define ll_processMissMasterEvt _symrom_ll_processMissMasterEvt + #define ll_processMissSlaveEvt _symrom_ll_processMissSlaveEvt + #define ll_processPrdAdvIRQ _symrom_ll_processPrdAdvIRQ + #define ll_processPrdScanIRQ _symrom_ll_processPrdScanIRQ + #define LL_PseudoRand _symrom_LL_PseudoRand + #define LL_Rand _symrom_LL_Rand + #define LL_RandCback _symrom_LL_RandCback + #define LL_READ_Anatenna_Info _symrom_LL_READ_Anatenna_Info + #define ll_read_rxfifo _symrom_ll_read_rxfifo + #define LL_ReadAdvChanTxPower _symrom_LL_ReadAdvChanTxPower + #define LL_ReadBDADDR _symrom_LL_ReadBDADDR + #define LL_ReadCarrSens _symrom_LL_ReadCarrSens + #define LL_ReadChanMap _symrom_LL_ReadChanMap + #define LL_ReadFoff _symrom_LL_ReadFoff + #define ll_readLocalIRK _symrom_ll_readLocalIRK + #define LL_ReadLocalSupportedFeatures _symrom_LL_ReadLocalSupportedFeatures + #define LL_ReadLocalVersionInfo _symrom_LL_ReadLocalVersionInfo + #define LL_ReadMaximumAdvDataLength _symrom_LL_ReadMaximumAdvDataLength + #define LL_ReadNumberOfSupportAdvSet _symrom_LL_ReadNumberOfSupportAdvSet + #define LL_ReadRemoteUsedFeatures _symrom_LL_ReadRemoteUsedFeatures + #define LL_ReadRemoteUsedFeaturesCompleteCback _symrom_LL_ReadRemoteUsedFeaturesCompleteCback + #define LL_ReadRemoteVersionInfo _symrom_LL_ReadRemoteVersionInfo + #define LL_ReadRemoteVersionInfoCback _symrom_LL_ReadRemoteVersionInfoCback + #define LL_ReadResolvingListSize _symrom_LL_ReadResolvingListSize + #define LL_ReadRssi _symrom_LL_ReadRssi + #define LL_ReadSupportedStates _symrom_LL_ReadSupportedStates + #define LL_ReadTxPowerLevel _symrom_LL_ReadTxPowerLevel + #define LL_ReadWlSize _symrom_LL_ReadWlSize + #define ll_remain_time _symrom_ll_remain_time + #define LL_RemoveAdvSet _symrom_LL_RemoveAdvSet + #define LL_RemoveResolvingListDevice _symrom_LL_RemoveResolvingListDevice + #define LL_RemoveWhiteListDevice _symrom_LL_RemoveWhiteListDevice + #define LL_Reset _symrom_LL_Reset + #define ll_ResolveRandomAddrs _symrom_ll_ResolveRandomAddrs + #define LL_RX_bm_alloc _symrom_LL_RX_bm_alloc + #define LL_RxDataCompleteCback _symrom_LL_RxDataCompleteCback + #define ll_schedule_next_event _symrom_ll_schedule_next_event + #define ll_scheduler _symrom_ll_scheduler + #define LL_Set_ConnectionCTE_ReceiveParam _symrom_LL_Set_ConnectionCTE_ReceiveParam + #define LL_Set_ConnectionCTE_TransmitParam _symrom_LL_Set_ConnectionCTE_TransmitParam + #define LL_set_default_conn_params _symrom_LL_set_default_conn_params + #define LL_SetAddressResolutionEnable _symrom_LL_SetAddressResolutionEnable + #define LL_SetAdvControl _symrom_LL_SetAdvControl + #define LL_SetAdvData _symrom_LL_SetAdvData + #define LL_SetAdvParam _symrom_LL_SetAdvParam + #define LL_SetDataLengh _symrom_LL_SetDataLengh + #define LL_SetDefaultPhyMode _symrom_LL_SetDefaultPhyMode + #define LL_SetExtAdvData _symrom_LL_SetExtAdvData + #define LL_SetExtAdvEnable _symrom_LL_SetExtAdvEnable + #define LL_SetExtAdvParam _symrom_LL_SetExtAdvParam + #define LL_SetExtAdvSetRandomAddress _symrom_LL_SetExtAdvSetRandomAddress + #define LL_SetExtendedScanEnable _symrom_LL_SetExtendedScanEnable + #define LL_SetExtendedScanParameters _symrom_LL_SetExtendedScanParameters + #define LL_SetExtScanRspData _symrom_LL_SetExtScanRspData + #define LL_SetPeriodicAdvData _symrom_LL_SetPeriodicAdvData + #define LL_SetPeriodicAdvEnable _symrom_LL_SetPeriodicAdvEnable + #define LL_SetPeriodicAdvParameter _symrom_LL_SetPeriodicAdvParameter + #define LL_SetPhyMode _symrom_LL_SetPhyMode + #define LL_SetRandomAddress _symrom_LL_SetRandomAddress + #define LL_SetResolvablePrivateAddressTimeout _symrom_LL_SetResolvablePrivateAddressTimeout + #define LL_SetScanControl _symrom_LL_SetScanControl + #define LL_SetScanParam _symrom_LL_SetScanParam + #define LL_SetScanRspData _symrom_LL_SetScanRspData + #define LL_SetTxPowerLevel _symrom_LL_SetTxPowerLevel + #define LL_slave_conn_event _symrom_LL_slave_conn_event + #define LL_StartEncrypt _symrom_LL_StartEncrypt + #define LL_TaskID _symrom_LL_TaskID + #define LL_TX_bm_alloc _symrom_LL_TX_bm_alloc + #define LL_TxData _symrom_LL_TxData + #define ll_updateAuxAdvTimeSlot _symrom_ll_updateAuxAdvTimeSlot + #define ll_updateExtAdvRemainderTime _symrom_ll_updateExtAdvRemainderTime + #define LL_WriteSuggestedDefaultDataLength _symrom_LL_WriteSuggestedDefaultDataLength + #define ll24BitTimeCompare _symrom_ll24BitTimeCompare + #define llAdjSlaveLatencyValue _symrom_llAdjSlaveLatencyValue + #define llAllocateSyncHandle _symrom_llAllocateSyncHandle + #define llAllocConnId _symrom_llAllocConnId + #define llAtLeastTwoChans _symrom_llAtLeastTwoChans + #define llCalcMaxScanTime _symrom_llCalcMaxScanTime + #define llCalcScaFactor _symrom_llCalcScaFactor + #define llCalcTimerDrift _symrom_llCalcTimerDrift + #define llCheckForLstoDuringSL _symrom_llCheckForLstoDuringSL + #define llCheckWhiteListUsage _symrom_llCheckWhiteListUsage + #define llConnCleanup _symrom_llConnCleanup + #define llConnTerminate _symrom_llConnTerminate + #define llConvertCtrlProcTimeoutToEvent _symrom_llConvertCtrlProcTimeoutToEvent + #define llConvertLstoToEvent _symrom_llConvertLstoToEvent + #define llCurrentScanChn _symrom_llCurrentScanChn + #define llDeleteSyncHandle _symrom_llDeleteSyncHandle + #define llDequeueCtrlPkt _symrom_llDequeueCtrlPkt + #define llDequeueDataQ _symrom_llDequeueDataQ + #define llEnqueueCtrlPkt _symrom_llEnqueueCtrlPkt + #define llEnqueueDataQ _symrom_llEnqueueDataQ + #define llEqAlreadyValidAddr _symrom_llEqAlreadyValidAddr + #define llEqSynchWord _symrom_llEqSynchWord + #define llEqualBytes _symrom_llEqualBytes + #define llEventDelta _symrom_llEventDelta + #define llEventInRange _symrom_llEventInRange + #define llGenerateCRC _symrom_llGenerateCRC + #define llGenerateValidAccessAddr _symrom_llGenerateValidAccessAddr + #define llGetNextAdvChn _symrom_llGetNextAdvChn + #define llGetNextAuxAdvChn _symrom_llGetNextAuxAdvChn + #define llGetNextDataChan _symrom_llGetNextDataChan + #define llGetNextDataChanCSA2 _symrom_llGetNextDataChanCSA2 + #define llGtSixConsecZerosOrOnes _symrom_llGtSixConsecZerosOrOnes + #define llGtTwentyFourTransitions _symrom_llGtTwentyFourTransitions + #define llInitFeatureSet _symrom_llInitFeatureSet + #define llInitFeatureSet2MPHY _symrom_llInitFeatureSet2MPHY + #define llInitFeatureSetCodedPHY _symrom_llInitFeatureSetCodedPHY + #define llInitFeatureSetDLE _symrom_llInitFeatureSetDLE + #define llLtTwoChangesInLastSixBits _symrom_llLtTwoChangesInLastSixBits + #define llMasterEvt_TaskEndOk _symrom_llMasterEvt_TaskEndOk + #define llMemCopyDst _symrom_llMemCopyDst + #define llMemCopySrc _symrom_llMemCopySrc + #define llOneBitSynchWordDiffer _symrom_llOneBitSynchWordDiffer + #define llPduLengthManagmentReset _symrom_llPduLengthManagmentReset + #define llPduLengthUpdate _symrom_llPduLengthUpdate + #define llPendingUpdateParam _symrom_llPendingUpdateParam + #define llPhyModeCtrlReset _symrom_llPhyModeCtrlReset + #define llPhyModeCtrlUpdateNotify _symrom_llPhyModeCtrlUpdateNotify + #define llProcessChanMap _symrom_llProcessChanMap + #define llProcessMasterControlPacket _symrom_llProcessMasterControlPacket + #define llProcessMasterControlProcedures _symrom_llProcessMasterControlProcedures + #define llProcessRxData _symrom_llProcessRxData + #define llProcessSlaveControlPacket _symrom_llProcessSlaveControlPacket + #define llProcessSlaveControlProcedures _symrom_llProcessSlaveControlProcedures + #define llProcessTxData _symrom_llProcessTxData + #define llReleaseAllConnId _symrom_llReleaseAllConnId + #define llReleaseConnId _symrom_llReleaseConnId + #define llReplaceCtrlPkt _symrom_llReplaceCtrlPkt + #define llResetConnId _symrom_llResetConnId + #define llResetRfCounters _symrom_llResetRfCounters + #define llScanT1 _symrom_llScanT1 + #define llScanTime _symrom_llScanTime + #define llSecAdvAllow _symrom_llSecAdvAllow + #define llSecondaryState _symrom_llSecondaryState + #define llSetNextDataChan _symrom_llSetNextDataChan + #define llSetNextPhyMode _symrom_llSetNextPhyMode + #define llSetupAdv _symrom_llSetupAdv + #define llSetupAdvExtIndPDU _symrom_llSetupAdvExtIndPDU + #define llSetupAuxAdvIndPDU _symrom_llSetupAuxAdvIndPDU + #define llSetupAuxChainIndPDU _symrom_llSetupAuxChainIndPDU + #define llSetupAuxConnectReqPDU _symrom_llSetupAuxConnectReqPDU + #define llSetupAuxConnectRspPDU _symrom_llSetupAuxConnectRspPDU + #define llSetupAuxScanRspPDU _symrom_llSetupAuxScanRspPDU + #define llSetupAuxSyncIndPDU _symrom_llSetupAuxSyncIndPDU + #define llSetupConn _symrom_llSetupConn + #define llSetupCTEReq _symrom_llSetupCTEReq + #define llSetupCTERsp _symrom_llSetupCTERsp + #define llSetupDataLenghtReq _symrom_llSetupDataLenghtReq + #define llSetupDataLenghtRsp _symrom_llSetupDataLenghtRsp + #define llSetupDirectedAdvEvt _symrom_llSetupDirectedAdvEvt + #define llSetupEncReq _symrom_llSetupEncReq + #define llSetupEncRsp _symrom_llSetupEncRsp + #define llSetupExtAdvEvent _symrom_llSetupExtAdvEvent + #define llSetupExtInit _symrom_llSetupExtInit + #define llSetupExtScan _symrom_llSetupExtScan + #define llSetupFeatureSetReq _symrom_llSetupFeatureSetReq + #define llSetupFeatureSetRsp _symrom_llSetupFeatureSetRsp + #define llSetupInit _symrom_llSetupInit + #define llSetupNextMasterEvent _symrom_llSetupNextMasterEvent + #define llSetupNextSlaveEvent _symrom_llSetupNextSlaveEvent + #define llSetupNonConnectableAdvEvt _symrom_llSetupNonConnectableAdvEvt + #define llSetupPauseEncReq _symrom_llSetupPauseEncReq + #define llSetupPauseEncRsp _symrom_llSetupPauseEncRsp + #define llSetupPhyReq _symrom_llSetupPhyReq + #define llSetupPhyRsp _symrom_llSetupPhyRsp + #define llSetupPhyUpdateInd _symrom_llSetupPhyUpdateInd + #define llSetupPrdAdvEvent _symrom_llSetupPrdAdvEvent + #define llSetupPrdScan _symrom_llSetupPrdScan + #define llSetupRejectExtInd _symrom_llSetupRejectExtInd + #define llSetupRejectInd _symrom_llSetupRejectInd + #define llSetupScan _symrom_llSetupScan + #define llSetupScanInit _symrom_llSetupScanInit + #define llSetupScannableAdvEvt _symrom_llSetupScannableAdvEvt + #define llSetupSecAdvEvt _symrom_llSetupSecAdvEvt + #define llSetupSecConnectableAdvEvt _symrom_llSetupSecConnectableAdvEvt + #define llSetupSecInit _symrom_llSetupSecInit + #define llSetupSecNonConnectableAdvEvt _symrom_llSetupSecNonConnectableAdvEvt + #define llSetupSecScan _symrom_llSetupSecScan + #define llSetupSecScannableAdvEvt _symrom_llSetupSecScannableAdvEvt + #define llSetupStartEncReq _symrom_llSetupStartEncReq + #define llSetupStartEncRsp _symrom_llSetupStartEncRsp + #define llSetupSyncInfo _symrom_llSetupSyncInfo + #define llSetupTermInd _symrom_llSetupTermInd + #define llSetupUndirectedAdvEvt _symrom_llSetupUndirectedAdvEvt + #define llSetupUnknownRsp _symrom_llSetupUnknownRsp + #define llSetupUpdateChanReq _symrom_llSetupUpdateChanReq + #define llSetupUpdateParamReq _symrom_llSetupUpdateParamReq + #define llSetupVersionIndReq _symrom_llSetupVersionIndReq + #define llSlaveEvt_TaskAbort _symrom_llSlaveEvt_TaskAbort + #define llSlaveEvt_TaskEndOk _symrom_llSlaveEvt_TaskEndOk + #define llState _symrom_llState + #define llTaskState _symrom_llTaskState + #define llTrxNumAdaptiveConfig _symrom_llTrxNumAdaptiveConfig + #define llValidAccessAddr _symrom_llValidAccessAddr + #define llWaitingIrq _symrom_llWaitingIrq + #define llWaitUs _symrom_llWaitUs + #define llWriteTxData _symrom_llWriteTxData + #define log_clr_putc _symrom_log_clr_putc + #define log_debug_level _symrom_log_debug_level + #define log_get_debug_level _symrom_log_get_debug_level + #define log_printf _symrom_log_printf + #define log_set_putc _symrom_log_set_putc + #define log_vsprintf _symrom_log_vsprintf + #define move_to_master_function _symrom_move_to_master_function + #define move_to_slave_function _symrom_move_to_slave_function + #define NMI_Handler _symrom_NMI_Handler + #define numComplPkts _symrom_numComplPkts + #define numComplPktsLimit _symrom_numComplPktsLimit + #define numHostBufs _symrom_numHostBufs + #define osal_bm_adjust_header _symrom_osal_bm_adjust_header + #define osal_bm_adjust_tail _symrom_osal_bm_adjust_tail + #define osal_bm_alloc _symrom_osal_bm_alloc + #define osal_bm_free _symrom_osal_bm_free + #define osal_buffer_uint24 _symrom_osal_buffer_uint24 + #define osal_buffer_uint32 _symrom_osal_buffer_uint32 + #define osal_build_uint16 _symrom_osal_build_uint16 + #define osal_build_uint32 _symrom_osal_build_uint32 + #define osal_CbTimerInit _symrom_osal_CbTimerInit + #define osal_CbTimerProcessEvent _symrom_osal_CbTimerProcessEvent + #define osal_CbTimerStart _symrom_osal_CbTimerStart + #define osal_CbTimerStop _symrom_osal_CbTimerStop + #define osal_CbTimerUpdate _symrom_osal_CbTimerUpdate + #define osal_clear_event _symrom_osal_clear_event + #define osal_ConvertUTCSecs _symrom_osal_ConvertUTCSecs + #define osal_ConvertUTCTime _symrom_osal_ConvertUTCTime + #define osal_get_timeoutEx _symrom_osal_get_timeoutEx + #define osal_getClock _symrom_osal_getClock + #define osal_GetSystemClock _symrom_osal_GetSystemClock + #define osal_init_system _symrom_osal_init_system + #define osal_isbufset _symrom_osal_isbufset + #define osal_mem_alloc _symrom_osal_mem_alloc + #define osal_mem_free _symrom_osal_mem_free + #define osal_mem_init _symrom_osal_mem_init + #define osal_mem_kick _symrom_osal_mem_kick + #define osal_mem_set_heap _symrom_osal_mem_set_heap + #define osal_memcmp _symrom_osal_memcmp + #define osal_memcpy _symrom_osal_memcpy + #define osal_memdup _symrom_osal_memdup + #define osal_memset _symrom_osal_memset + #define osal_msg_allocate _symrom_osal_msg_allocate + #define osal_msg_deallocate _symrom_osal_msg_deallocate + #define osal_msg_dequeue _symrom_osal_msg_dequeue + #define osal_msg_enqueue _symrom_osal_msg_enqueue + #define osal_msg_enqueue_max _symrom_osal_msg_enqueue_max + #define osal_msg_extract _symrom_osal_msg_extract + #define osal_msg_find _symrom_osal_msg_find + #define osal_msg_push _symrom_osal_msg_push + #define osal_msg_push_front _symrom_osal_msg_push_front + #define osal_msg_receive _symrom_osal_msg_receive + #define osal_msg_send _symrom_osal_msg_send + #define osal_next_timeout _symrom_osal_next_timeout + #define osal_pwrmgr_device _symrom_osal_pwrmgr_device + #define osal_pwrmgr_init _symrom_osal_pwrmgr_init + #define osal_pwrmgr_powerconserve _symrom_osal_pwrmgr_powerconserve + #define osal_pwrmgr_task_state _symrom_osal_pwrmgr_task_state + #define osal_qHead _symrom_osal_qHead + #define osal_rand _symrom_osal_rand + #define osal_revmemcpy _symrom_osal_revmemcpy + #define osal_run_system _symrom_osal_run_system + #define osal_self _symrom_osal_self + #define osal_set_event _symrom_osal_set_event + #define osal_setClock _symrom_osal_setClock + #define osal_start_reload_timer _symrom_osal_start_reload_timer + #define osal_start_system _symrom_osal_start_system + #define osal_start_timerEx _symrom_osal_start_timerEx + #define osal_stop_timerEx _symrom_osal_stop_timerEx + #define osal_strlen _symrom_osal_strlen + #define osal_sys_tick _symrom_osal_sys_tick + #define osal_timer_num_active _symrom_osal_timer_num_active + #define OSAL_timeSeconds _symrom_OSAL_timeSeconds + #define osalAddTimer _symrom_osalAddTimer + #define osalDeleteTimer _symrom_osalDeleteTimer + #define osalFindTimer _symrom_osalFindTimer + #define osalTimerInit _symrom_osalTimerInit + #define osalTimerUpdate _symrom_osalTimerUpdate + #define osalTimeUpdate _symrom_osalTimeUpdate + #define osalTimeUpdate1 _symrom_osalTimeUpdate1 + #define ownPublicAddr _symrom_ownPublicAddr + #define p_perStatsByChan _symrom_p_perStatsByChan + #define peerInfo _symrom_peerInfo + #define PendSV_Handler _symrom_PendSV_Handler + #define pHciEvtMask _symrom_pHciEvtMask + #define phy_sec_app_key _symrom_phy_sec_app_key + #define phy_sec_decrypt _symrom_phy_sec_decrypt + #define phy_sec_efuse_lock _symrom_phy_sec_efuse_lock + #define phy_sec_encrypt _symrom_phy_sec_encrypt + #define phy_sec_init _symrom_phy_sec_init + #define phy_sec_key_valid _symrom_phy_sec_key_valid + #define prog_process_data _symrom_prog_process_data + #define prog_uart_command _symrom_prog_uart_command + #define prog_uart_fct_command _symrom_prog_uart_fct_command + #define prog_uart_handle _symrom_prog_uart_handle + #define pwrmgr_attribute _symrom_pwrmgr_attribute + #define read_current_fine_time _symrom_read_current_fine_time + #define read_ll_adv_remainder_time _symrom_read_ll_adv_remainder_time + #define read_LL_remainder_time _symrom_read_LL_remainder_time + #define receive_timeout_flag _symrom_receive_timeout_flag + #define reset_conn_buf _symrom_reset_conn_buf + //#define rf_calibrate _symrom_rf_calibrate + //#define rf_init _symrom_rf_init + //#define rf_phy_ana_cfg _symrom_rf_phy_ana_cfg + //#define rf_phy_bb_cfg _symrom_rf_phy_bb_cfg + //#define rf_phy_change_cfg _symrom_rf_phy_change_cfg + //#define rf_phy_direct_test_ate _symrom_rf_phy_direct_test_ate + //#define rf_phy_get_pktFoot _symrom_rf_phy_get_pktFoot + //#define rf_phy_ini _symrom_rf_phy_ini + //#define rf_phy_set_txPower _symrom_rf_phy_set_txPower + //#define rf_rxDcoc_cfg _symrom_rf_rxDcoc_cfg + //#define rf_tp_cal _symrom_rf_tp_cal + //#define rf_tpCal_cfg _symrom_rf_tpCal_cfg + //#define rf_tpCal_cfg_avg _symrom_rf_tpCal_cfg_avg + //#define rf_tpCal_gen_cap_arrary _symrom_rf_tpCal_gen_cap_arrary + #define rfCounters _symrom_rfCounters + #define rom_board_init _symrom_rom_board_init + #define rtc_clear _symrom_rtc_clear + #define rtc_config_prescale _symrom_rtc_config_prescale + #define rtc_get_counter _symrom_rtc_get_counter + #define rtc_mod_value _symrom_rtc_mod_value + #define rtc_start _symrom_rtc_start + #define rtc_stop _symrom_rtc_stop + #define rxFifoFlowCtrl _symrom_rxFifoFlowCtrl + #define s_prog_time_save _symrom_s_prog_time_save + #define s_prog_timeout _symrom_s_prog_timeout + #define s_rom_debug_level _symrom_s_rom_debug_level + #define s_spif_ctx _symrom_s_spif_ctx + #define SCA _symrom_SCA + #define scanInfo _symrom_scanInfo + #define scanSyncInfo _symrom_scanSyncInfo + #define set_access_address _symrom_set_access_address + #define set_channel _symrom_set_channel + #define set_crc_seed _symrom_set_crc_seed + #define set_gpio_pull_down_ate _symrom_set_gpio_pull_down_ate + #define set_gpio_pull_up_ate _symrom_set_gpio_pull_up_ate + #define set_int _symrom_set_int + #define set_max_length _symrom_set_max_length + #define set_sleep_flag _symrom_set_sleep_flag + #define set_timer _symrom_set_timer + #define set_whiten_seed _symrom_set_whiten_seed + #define setSleepMode _symrom_setSleepMode + #define slave_conn_event_recv_delay _symrom_slave_conn_event_recv_delay + #define sleep_flag _symrom_sleep_flag + #define spif_cmd _symrom_spif_cmd + #define spif_erase_all _symrom_spif_erase_all + #define spif_erase_block64 _symrom_spif_erase_block64 + #define spif_erase_chip _symrom_spif_erase_chip + #define spif_erase_sector _symrom_spif_erase_sector + #define spif_flash_size _symrom_spif_flash_size + #define spif_flash_status_reg_0 _symrom_spif_flash_status_reg_0 + #define spif_flash_status_reg_1 _symrom_spif_flash_status_reg_1 + #define spif_init _symrom_spif_init + #define spif_rddata _symrom_spif_rddata + #define spif_read _symrom_spif_read + #define spif_release_deep_sleep _symrom_spif_release_deep_sleep + #define spif_set_deep_sleep _symrom_spif_set_deep_sleep + #define spif_wrdata _symrom_spif_wrdata + #define spif_write _symrom_spif_write + #define spif_write_protect _symrom_spif_write_protect + #define sram_ret_patch _symrom_sram_ret_patch + #define supportedCmdsTable _symrom_supportedCmdsTable + #define syncInfo _symrom_syncInfo + #define timerHead _symrom_timerHead + #define tx_scanRsp_desc _symrom_tx_scanRsp_desc + #define update_rx_read_ptr _symrom_update_rx_read_ptr + #define update_rx_write_ptr _symrom_update_rx_write_ptr + #define update_tx_read_ptr _symrom_update_tx_read_ptr + #define update_tx_write_ptr _symrom_update_tx_write_ptr + #define verInfo _symrom_verInfo + #define WaitRTCCount _symrom_WaitRTCCount + #define wakeup_init _symrom_wakeup_init + #define wakeup_init0 _symrom_wakeup_init0 + #define wakeupProcess _symrom_wakeupProcess + #define whiten_seed _symrom_whiten_seed + #define zigbee_crc16_gen _symrom_zigbee_crc16_gen + #define WaitUs _symrom_WaitUs + +#endif +#endif + diff --git a/ota_boot/source/ota_boot.h b/ota_boot/source/ota_boot.h new file mode 100644 index 0000000..1d2792f --- /dev/null +++ b/ota_boot/source/ota_boot.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * @file ota_boot.h + * + ******************************************************************************/ + +#ifndef OTA_BOOT_H_ +#define OTA_BOOT_H_ + +/* FLASH */ +#ifndef FLASH_SIZE +#define FLASH_SIZE 0x80000 // 512k (512*1024) +#endif +#define FLASH_MAX_SIZE 0x200000 // 2M (2048*1024) +#ifndef FLASH_SECTOR_SIZE +#define FLASH_SECTOR_SIZE 0x01000 // 4k (4*1024) +#endif +#define FADDR_START_ADDR (0x11000000) +#define FADDR_BOOT_ROM_INFO (FADDR_START_ADDR + 0x02000) // 4k +#define FADDR_OTA_SEC (FADDR_START_ADDR + 0x03000) // 52k +#define FADDR_APP_SEC (FADDR_START_ADDR + 0x10000) // 176k (for 256k Flash) + +#define START_UP_FLAG 0x36594850 // "PHY6" + +#define OTA_MODE_SELECT_REG 0x4000f034 +//#define OTA_MODE_SELECT_REG (AP_AON->RTCCC2) // [0x4000f034] == 0x55 -> OTA +#define BOOT_FLG_OTA 0x55 // перезагрузка в FW Boot для OTA (ожидание соединения 80 сек) +#define BOOT_FLG_FW0 0x33 // перезагрузка в FW Boot + +typedef enum _SYSCLK_SEL +{ + SYS_CLK_RC_32M = 0, + SYS_CLK_DBL_32M = 1, + SYS_CLK_XTAL_16M = 2, + SYS_CLK_DLL_48M = 3, + SYS_CLK_DLL_64M = 4, + SYS_CLK_DLL_96M = 5, + SYS_CLK_8M = 6, + SYS_CLK_4M = 7, + SYS_CLK_NUM = 8, +} sysclk_t; + +extern sysclk_t g_system_clk; + +int _spif_wait_nobusy(uint8_t flg, uint32_t tout_ns); +int spif_write(uint32_t addr, uint8_t* data, uint32_t size); +int spif_write_dma(uint32_t addr, uint8_t* data, uint32_t size); +int spif_read(uint32_t addr, uint8_t* data, uint32_t size); +int spif_read_dma(uint32_t addr, uint8_t* data, uint32_t size); +int spif_erase_sector(unsigned int addr); +int spif_erase_block64(unsigned int addr); +int spif_erase_all(void); +uint8_t spif_flash_status_reg_0(void); +int spif_write_protect(bool en); +void spif_cmd(uint8_t op, uint8_t addrlen, uint8_t rdlen, uint8_t wrlen, uint8_t mbit, uint8_t dummy); +void spif_rddata(uint8_t* data, uint8_t len); +int spif_config(sysclk_t ref_clk, uint8_t div, uint32_t rd_instr, uint8_t mode_bit, uint8_t QE); + + +#endif /* OTA_BOOT_H_ */ diff --git a/rdwr_phy62x2.py b/rdwr_phy62x2.py index 99e2124..b7898ca 100644 --- a/rdwr_phy62x2.py +++ b/rdwr_phy62x2.py @@ -459,7 +459,7 @@ class phyflasher: def HexfHeader(self, hp, start = DEF_START_RUN_APP_ADDR, raddr = DEF_START_WR_FLASH_ADDR): if len(hp) > 1: hexf = bytearray(b'\xff')*(0x100) - hexf[0:4] = int.to_bytes(len(hp), 4, byteorder='little') + hexf[0:4] = int.to_bytes(len(hp)-1, 4, byteorder='little') hexf[8:12] = int.to_bytes(start, 4, byteorder='little') #sections = 0 faddr_min = MAX_FLASH_SIZE-1 @@ -592,8 +592,6 @@ def main(): print ('Error Flash read Unique ID!') sys.exit(3) print ('Flash Serial Number:', rb.hex()) # Unique ID - - exit(0) if args.operation == 'rc': #filename = "r%08x-%08x.bin" % (addr, length) if args.size == 0: diff --git a/update_boot/BOOT_BTH01_v14.bin b/update_boot/BOOT_BTH01_v14.bin new file mode 100644 index 0000000000000000000000000000000000000000..9db19d506620ff2b03a50a5808b448af07a93c94 GIT binary patch literal 48932 zcmWIWh%{qlU|_J2_%E-ppMimak&)pBBZPmA>ul)%VGJHHF$x;U|Ce`^_%F}o+4z~G zgW<#69}Em2F>7z;$wk{(l$cjC&tUj);D?2efRZ8uh`sBFnYU8LEGMgrsTtXFeA;F= zE+{|BkY<|YWO#{3jd`|#2cz+SV}{8LAGZErQPTC)@nHBc;RlP74w%*bL&y8Agf^qL zFXLowZ{`{D43Z2+3<3ts6Bs`9{?K4BVz6Xj_)zhKakhZzYNxjspJp_uDEXx@Fz58L)N-BXtSd)d5AHu0W}8V$OEOH>mA>%&fZHDiMnMJX|MH;pz@We& zs3QGeUPJo7Jcj~)IJ_AZr3zRSlo{B(7^X0MQ2Fuyd(eLc2C=;c(*NZ_ zdc3&)%Ud%raxiXT@@R2m+>_wWuzzYXBLgyjJ0AlIKeZ55{%9^Le`P)+11#Bs{KE`Q z-wt~i7#Iu~7<{_Hw4mbG4?;e>85kH?7#J8B{>vME-?GnVKLf)nZAkiGT)k)=%$%W0 zGbk5t)%Ml#(O^hUWKv`NQ2f(D@t=}ni3Wp)H^Vf>4|{(yXqa78tog5`!Jq;b+47S? zL-(SR_oB{OPHGn)cPe^KcH+IL;GLYP;H{Lwpv8QVL7VY{^J(WJ8VrmdI)4`LmG+wK z#CU;0`TcV#Zz(V7jLA-HHxDSYC}}V#*34#L{J{82&^tL%)cgK(24&@vSI^HVTPUtk z(qNd)s93`I;nPnBjZYW(ypt38ydO96d7pXy#qq!Vgv9^ya}xi{&rAF-9~sHO(9Fuf zpz6pV=&_SQut}7GVN2qF`F3FjhLD{Mf_EJm1Xr#4|KDaOgW&hAV&06C4ofh}GAJ-i z?of_qy(}S}5hEjYVa_H89f=#g6>>al+|u37R_HR>I=%D1-)5TQ#C(y< zlhuRcgZOU+27$eQRGu)sdHzr33DfuI2izDAunRI=U>9U~z%Iz}fnD(b|Nr$Lw$9!l z%D^&#d7^_B!_5T`*j7h2NHzTbe&|071B-^(O$H^lmH)qI{Abk=xXHF!x?{By&qW4Z z_6vdDS_~{R4@hu)SoD)YgXtopg7k(Dd)ZdYHYhN#&HVqp{y&Rc^+mSX?34e0pYy*# zIhyg9M1wLrgEaFzC&tS^)V?u+LgKRo<7DX!Mq{Q6j59bsT>W9|38HuYvX*6d8=qjTpbhKbBGrFpuYR4zDZDcxXH zGGO3X`Tx7XeOWf^T?#AH_urZ7{KxHgP(!n`&L#45e5e>#TyLjjOz*;%p3lH|Mw3R3sww< z4FA6`{l}sqaMP?~j}!NWy-u7Llw`IzG2AqgVe_7}>7axL1IGuJUk020?LFYku<7@6 zW(5bQA7Jy%x3Va)Fz_-kt`PJ5|NYE=CI%J_?u(4G7dvrWUhTwkLBNx71>@BJ-+%sN zRIuC2=cAmVz`!_};{)#x#+eEXjFyZOIX=Aq35vrf671e{oZekzQDTPbx&Mzr;mPv@ zZlR$J4B+&|z#(X`wQ~c<2f3dDN||n|9_$|^|Eqd4%$nuIcad>6(=2{%;~NZ$j4Et1 z7_B)jF=#SeV4B15OnPrA!28TQ627|p1R2hAAncqJL)lHx>zd`B8)@eS|y)Q8^C@L_>B(Q%l`mf9| z#jC?uDq*s>R7I9DgBHUDLF30sT*}I+6THopq$@ZS7AN<4D@r_06i`-9>h-o(O-?+a ze4Al$qB28|u~dSFGNaX_WQCOElvC*}R*JHx(iIu@81g14G8{1ENKj-rV#uAK$iQZL z1}w&5djd>fFyu;5Vz^=?kf6kH!$>$miGfM|fsrDEc!HDC9Yd}JMFwfxCt#H?z^1%0 zl`M7e~eNyVy9Q*&)oQ336Q(6jCI*H(tPBiU5)2FhhZz_;gc%qH9@MB;|<@_(7A;7?J zgp+~6!HJ(iK%If%55s@?gP^t*!+&{Eo&WMn_5aJ;>iw5*l>aYZsP9$r)vC{uhsl7e^cVW{6h8r@<&zv%U@LaFV8FYU;e1vfB9C~|ME=AAGR{8B>N`& zX%{4WPuw6=knGPq**Jqikwam30o#Y4zd01xK79DapghBg^}?=-P%Wkl###&)=07k_ zU{PTEko=eZ!|i|nzsLS#|M35xyb_}dgJQ6^z&fddU~id%U~fqf&Y0*dX2s+%#1j|%E`pZ1(It}wD<62WdCsGAG5L&gRLjy6o$#R9_$}f{^}^%c(Sfw z|4{#*bxmT0LIslv+lTePmO1^nXzs(P$e_UXVb5<)1x7`-4?BJ>nEcfmGfGtJJ7q|M2rK z^K6NV1Dn`Ci2P^&aOjVsCyN662e*H0ALjjG_^{#!!-oTZ89rqEWB9=Hi$Otf!-u^L zlNA{xyg;fJ|7%db%{nLP|M!%?A!v4!^g#4FJ*ufwu@`1tOfBldD|Nqbb&(Hu#Z=m*a!Bz%U zRZlf9H4oopj#JXC(!6ganw)-KWKe5RQu3a}+MUd)sOYWaBbTJ)EvRrSUD5kiMwj!g zgjpF1o?H&I64VmdKYaWnsKEXq?{9-ra?WJuB)MtdkyR2r6uLew@JmLF_L`#bmJCIsP~(D`hmO zf?~5lIVs~dldyAg!r}}aFKy?=35zqB6onlYCp0K8%9zb4>@1+PI6*mwU174ba*A>e zzm>4Fa!P}8G=p`LQnrG(l!H=oQnr*sQu3l~DThVLkFtdw9w$G}koFRGc$~oYq2ec_ zBD(_HhmK$3-hv8IIik+7DeND_|NT`I@fHP_77fbB6_T=}nT4H`lOJa^Fc>>OPT=im{23wg|uyk-MFzE1I^vq!Q<*4wi;ACQS=2BSc#CnlYQGr3SfyrCCO1Qva zucQ_O11N02ZxvO zm#0Gq+lR}4HJrFFaCkGWjPCVq;BH{^W>Au@O6cG&Wd5-9pZx}dy$9S>693C*IQ*9f zxk+Fvt0$`m+lSo0EQ%~%AePo&0jQe){}~v1b}$Hn)Cz26@?iPE29^u7VGv|f7TDTc zAYjZ~=wj_$sAb$-=wf`hkU^PAiBXZch|im;z_CE4qp`@PNV1Bl_+Zhj3a8>*6-~v= zN{5Q2Dw#^6DxFGrl$uIrRURt2UCCT3sC>9UR6$@b#7!a!>>qag5%LyMVo;PwVE-WX zn?Zs7gZyt$>5%h_NrC;t#6Qdm%pa2evna5BDF4r@!2DssPc{YS54r!?6&OFT`~sD# zOaE{xFnoCSALJi{#Q*Z_AN0T`NdIB~@bV7>1E;sZRu%?Oxyz`@a#4YS&6DlJ%Rd5p znKb`gWVB@Y;QNO`g^OGj zOj;5by)ptTL@W5bIGHq^CpxiS;Psm5#CbucflGzufrt{9r&I&`hi88j7z+0CC~ zW>9#-&T^Gqkrf+J3A<@D7VfJ794Gen^xS1sWmp4uPFVE)qUtYio)eOcD z=P=BO?nRhU2{j`w@xOe0;(vLN8$f1!-^#~eUM0i8v09M9mO-jRL0Q&8-pS^oaRrmM z^~K^0`HJWYX(nrDIse^G92Y>O$OT#7)lP~RxKuS5{_SPZ(z+<3qjf`x;X?-d2aiAE z-ZBM@Iv;QT|Gwe>yXOpA(iatUq@l8we+0c*6lDqoyd^5wKdkz7@A>0Rj4BM17^iSC z7&5Sbxc!5b;mUIk)l1JARWCf}Rz3HeSM>~1n1k{Z$o-&j0F{5n%An9^F5psP_hd9+ z|G@c&&6{6AIzx) z`<4IMZZ{ejloC1^S2BON`v;OAL2(EUcW@pH`3*|1ckLMj3$}_eu&fg4U|l6z;gu0k zAy~n{q~*oo+#tcK;eCVsgZnRLVL43`dv*mD9qt>fNC2mo--(MDM&ROety91&ei|_rFSw2)+GLy=ibR6$hMO~ zkZ~u2;GZ3!w9Tu?E@aR#xtQ%Xvr{|c9Lh2g`yA1uy?pUW`3fRBlQ#z8>k6~8(I zL-AH+KhOwY=MN=ccI7NL0|w0+h7U{-m+BZ_%yyHmsMprN!SG?*k8HOa6(5wDSfrVy z9J1YJcZhjL@0z_y%2_*ufiu`yt5ce1wuE;>wp&!i>J2z6>JssQLbUo=D%Q}&3BRCSA&7! zgYl0u%Am0y#hTfS3?IJy0EwmlDA>#4{it)6)31xHU{wk~7{H@P3?GjEc>5eQ76cj- z0{LBFD~GpK4TBcvh3HHMZMF+D+*#xpFZ}!7{SP!Q0&>LxH<0>*tp_Vv8F(0y<>oj_ zc|T!#BH_uvl5lbpLnZ5nyZ>HRW>k7IFdClR#QNddzZaF91_w5=eR%kvLHTi7qOo$q zs>*0<1}(k|N*S}9nXEyr3ohlyiR{M8Nes%$$%~U2jUOi$>;=mzgJj*5lM~sD7bm`d z&Je)h0BW1DFfeD_O*;TKnf=3_ADRpbm8>6Z{%JBKRI+}s_y=kw{n#qUz_wbpfQ2gefavX zL4nPyfk7}MIh)yu^&-SIKW;KA6zpYC_yg8kuvL};(U z=2A`+P=>JIZUUKl>R*EbJ04RZ{uJ2C;qy3yL7U@ZgA$u}5R-JqY>DIqR&VJH>9$ypP#W;*@8DCXIfG0RE*@+_(D1QBmWHHnPLn=Ub3 z;&XO(a%NEQ$&lufmK0)|Ey3r*mEoNbDzn&$=LUlY;|1>ot^_VG;RKEhE^mp1g1r%P zO;UHCb9fmr%$Cq%c=a4KE)KF&gzLXNsE-G;`@r50{|mOt`zTl1Yct-oS5_{R^;W8s zDuDDc4*if&mhzPH;%<=g6mH;d2yR$hDe2juz}>*3IJtq**xOmmS5k(7vDt~?CZmjI z!^MW=N(ODgi;Tv}h00Zo+Ke}tl$DE;DwV5vJ%XLN6eFD3J_P*d_SHxz*tc^DYJ@-Q%b*edJOptRJ5g`q@Deft^uVgW=+V2e&mCE{Hv3(PFr<@_~RVs}}2pPZhhzU)O|2h@&!n5;C~U-W6yb% z-acnlitq%9c>HHm-TPcfDGbbW{4cD!?Ky{1FqmicpHp@H^TLV`nyfbhyd^pqKV1CH zq`K_+f92$YU(bEK8MT-%6jekOBo%yq9$oR}xdOxg?|i>m8KypG(PFvj>Z_l?_QB%c ziiH2)xBg{OVxGXf5@aL)e^%9&=k~sATB0}Elpub+`(PK68Q7OE`h;gWtTc!0`aQ27h;J7|1JU@LqQO?=8KGmj0UV90)GkY71+wC$$ybU zgZCnXB1p{r7b|$wh4q4(607{g>xc67&|>DpkO%EZ`&H zsa(Km#bV9xkzBy`;mBWIWkw}lPd<;wh5x@_{LiSw=xmCzVSV@6F(DUE-{NIAU3>xBh zS647-i(GJ)(JtUr&Msh3W{_kq(5TR4U<9|$nEq&1C^0Zvp4`Ns!1_V|Pr=^*-vfXoD?6@jgS-cl731)$a&g9i6SK5wZCHZArWAZnHCA<@T1SVET~sLtrn1 z#-9u9-qIC}+DsRit(mmH-eB=&1gC_fzu!Lxg(WEMaHW9SQUQJeUV)wl1sn>jAL@QF zDsn2YerWj#B2#~XMju%})cypyD(=_6?`}WYKJffuR&w)n^Z5VW`oFFUGXsl~Oo59h zqrw00#{UhJSqhwdoqU`NnhW%-*_0F*96VpQ|NH*t7n_Fg1yI?$^cRx`=LKd(5c~L_ zUggIHdDhB>lE%q}Al0Ux|Go?SGVzwq_+uQC^8b6(e+GsB-<$s%`WSjKDjIqVRVY+2 ze%Soqz{|i}sDeQe#9Q;9QAy8RszA?sc15VR;YD3MO3f$@XQPe!ml zo!xngHc@(0Dp1ye*vm%Y*UUbFaK%k4=PC) zg4K8YJn@`+6N5I_Edy^*`BU&4)ShJfaOQV|0t3^-=S(V!PHY!cycrdwivE9}`A>o2 z`g3k}>8t<0Fa9OxE$1okGb6(*Be|*x>K~7Uf8TTd{{LR`^Z$2`p9~+K{Z`Jn&CYoB z|99aZ911(13#jlhs5yYl;&E#_;2v|s5S8TC^qnTGN^DhaC-?i{QoZUpUayCTpqst zrN96hs|LBFl81qzl!t)%h0)jL7U-r!NVnfpc3W(PZqg=3(OUZ zv>7fcJ-nbTbz!2m>qX}ZK5eIqbG(~6W;xkiobA<|AymPtWqFZVK_aYP!}P)o@JO`b zh3E_hZM_RK+;tu_RIqDk-eCK{{*y&R!rs1Q#f{_&25p{;jEX(pk_ElqQWXqZ(HDBW z4JsHvnEqwZ2))3r)aor&5cnXmfy2xm3 zT_E>>N%{Bld~d0ad~c@73|ib5q$@x()F6GVA7cMoSFmZbTx7I<`J8FCRKfS>EZUA2 z85Nmk8&pUZuzl$L5d-$`&I_RN_iY!#y#y*+o+np?`ZH*&Uu08Kl#TXa`@r-osWZwu z%2TRgQD>C5RKw#=?gmyx%Yq0`u7(IN;RdCyaBr!GaBz*rc~M@0;lts7zmz61I61Q@ z8dR`;kowP{b=`Q1w(UPzC8KU|J38>oWbk@tjGSgF(VU(uwnexHqUAV!kNrEz!aH!Q~&5 z!u)3}DvD0b7yf@Y|Es_-;~583EyKmh&qTdtDj0Q`FEHuwUf@vZdM4y8>=GD z1P)h*DgVDe`1|qs|L?tj-+{|~P#D3=6;QZ=!V6U12s=T_98g&Y3IlN7cY=%~fXW1c ztxV84DuIih8L$~D9*;&R&WlWnk_}wmksX2sw<{PFqBjK>2<&C|;Zj)W^b0J<>^-wX zupqkf!}9}fdC>W*d@a!W8Bqp8b6Bh&RQ?h(hb5DOI)|ltLB!LcgY`q<4-F@t3qs&I zECwa+1}0_i27d48j_!tp4yF%IKY2Y9I#@r%{W!qRbCnxBp8-?F<~z`*k1(|-j9Hcyrh@BTyPR9HT&{x7f>G@k;}2U6d& zlR*%qA2k2P^q~zrmn0g_AjrhsGkN|0e(OJ|gj@qQ)31WN zqH}{86Ayzp1LFiaXGX2Wn^V2#IWgQQf52!w&q?MYo0j;+Qx)A6LQGQ5+?CQS!p>fm zLTpmbJ>F4?3`$Z3Q4QT*Q3>5%vl6u*Abl2E32`MTt$UFc4 zF7?0NiQz)u0|q_YiwLt{W`KIs5Yw3_b18K@30?fJytv?TfpTGTVRk2|=l-}_sYaR! z;tEC$DvawY2uP+TQd=460k>vaah zB<4wqvOG#GlUYCP|Hr7H#=x@D!AZdE|My4#80{JL#V<0<;#Ss3Y;t0_;PaeCNybxw zf%O9yXjEfmMh5GLy}w^(Fwgq0Jkg2aqRsQ~)>h9!tKN?M6EM5~oKtzb(~=v8&lzTK zc4D~s=NY@Q_H!m>&F9R@>d)DfRiASyD?k7L4>CUqTH6Im)1dWTjQ<%J{{LqXWcts* z0O~jI0p~GhA8rOlB}E2?581y2_O6X#5ajMC*viJh%fO@}rY(3=n}J!0)05#t%r6!> zu8Zv6S{>3Ik}{K>7;Xy67%+5hV)*d>7icW}fZNR&20=H_`kt*`6)X&lR@@9s3XEFp zH@GSov{){%Dk(59c`|&k0QYympIsr>pundmP6G@g4LWuQX>skbM&Xc-i`4Lg5S5cbn-H= zF)%7J=qO!aP;Sb&9421Dpe=WcM@Q-=kIj-z!jcXh43m`^m_D@qbC#Ro$Y@Z_cAG!D zz+RcrM&4n`CXIsi1#21@bl5L!&R{fNoxq^T0h)7Fc>R1$!jI?N70dBW~3s@8i+*uTuwAn5)Cy-Z3ZYGAKNI&Z2-n&JZ?k1>4BLP_UIzQI3H{fn^S#1GkgJ#nTRVH}yJ+ z+~o4Sy@|79rW5~VWrlagvIWKr5e$M7o)uy-oJ@w!jK+#VH#hYmA!}`Cha!eNt7+60{`K7@Cs+|wGxq!#RKr^ch z8ax*m6dFO}2%y!xo~$1p{$Nzlu23${u1GE}*n7b34Y-{EDt*NnWEfgEFlkC(U{Day zWWUIy&3-{ZoB5*X0|o^F9gYj2eto8!1p{boQHvqdjr&2Sn*qcB@2CDNF@VHb9x!RY zya<|+0J(C+d+zprcSv+S;Lyc~IOldrNn8J272m@^)Z27*ya6k^}jP(c6JRBC5b0#1>a#^p zFlsPg6i{4{!So^GFGv(*VgXb%A%p3I?_W@yfXpe_$|A>lkwKIB0-F-A2kQscAH3eO z6^y!q7a4R|FES}f6|jEr{-wcCuou)y1C5dX*ZzJ1G=EX?|MPPO)sLV#W+eYHGYD*D z&|tjCpdhf9p@Q3sL4)~XWXHuO=}O@;;R+`0PZvQeO&KnN`i(5!(iQ);883kL0Wm5( zdk%6BD2y011uuY7ly@b_9}Y@EPQuR25A2nM9hfzkE-)&17Z$iXD1CX(!SL&O!B$RR zMh1-v1`X~D>^`6|QI-#j|AR*7|9`*zAJq2H`3drCLCSx5uay7t44PaQ7&SO9+ADci zPIf+^&3wTD+>@OlQ{Y~(Ros`2LA&C=w&(>e1=bJmf3nC4faCdub#sBBx1gtVg7fLf|E+&REwCLCU@ADVuE+yL?$%pEx? z|K(?-{Fk4T@?SpT6$1mK_lyis`UHgmqxbC$iHrhw5S!gwVC$_6$SyBdZ;6Wk8q60! z>t$I#RQv$d=^!;Ab3tpJm_D5N!73+nfzO*QNxp(XpWz~V#p+4{1;)v&A3A@s$nk^x z(s10mxqxx@OIesdc>XIgSTH_7^G$u;s(k2Go9~YQr1WGnKeYwMAe1Fs8 z7zqZ($^XCK{Li4leu2@JaTfE;*PDzBx}2CUK9B^J7q=yEZ@LXGX_-FE`@zg0qyQRm zQDlhdVEG{PAJon%*vjYI!jK%vpe=eqA`6t8SU-IKp&c0kWqiIHnmd3Mmxq1@+p0U6|qi^SP+^OefKc!eBYB z3m|d!3p3mqG*~V|M*d_AoJ`k zDR4?~FKBCMF4SOP`SAQ7;{yiW7Z(?FaCA$$*f{y>+GyX2x}FzwdiNY5nc<18$%^B)pY{ zA*GYK^H4`)$AJpaILNvG!h0DQ1h%sHC}c2bFkfK#aQ8ohvT}mJ-jmJ$;w?!lOK07PF~!>Fxi*^R5pUfE4eQ|>Rep8 zu!Ct5XaJ7kgRmGb z0>yB05!39Y4U3DIXCK(~xQJ)=;{=uu6@Nh`#rLhe42%;PKN$aGms7aFr@->z&p#G9 zX|THu|FFq1T(kq3*KpLDO=)q#PuT}DEFY@>FwWLuNN!|QzUv_6AnTyWpj4b%{9zNz z2fx4H_cAbm+|M*YfPt4moPlc|$kiZfOaP7U1XlkR2j{#a#cuK*qKF%L674i z_e{{dF3(H`O{R;yGZ{3cE=W1^&Q>Y})fy)sFz7K{JpX_}m*K*h2MOR3iRHthe=>@o za>4I!LK5o(CgoYqe8$(GPj*%=O!eNya3z94hvDL?2Ml@w7nHLYw3#o;D6o8p_@|H* z=e>*Jas;TnW4<7xWXQnsLG%yLYzA$i3*kPy8Dt}~!K%d+SUx!Z%ShVI@Hhfg9x`7L zQ{tJ)^5Oq)-r1m$av$G43~7;@!D>YmSUza~+mHk)EtxNfDDlo@`S9wu1!({0Usk#F z3yxqr8MKowNM)HQfa(kxi&r3Z&jPVz3>r2?XMxHWF@uIpEFY}?vB-H{ zkWgY!WchICHz;nie=|-1wIj4E7$<{L4byA|hU5Y+Wlg`u16aFB9(cL6k~Js}0OE>+&2 zQNcQ+eFKBG>V?@Atdki&Z2rxlp?HBy;s5t5zgQT!75;y}@Jq~_l|ineSZNn0eByO2)}dlNcr#Gbk{y&SLq{`WIB5{{O!9KZ6GA1vZ8M z-`D+OVPIFd@ti~9|MwNYSQt1JKy?ww-JtruU@Mm&3xjb5FT;Or-U}=WEFWV2GRkp) zOO*fMhZ3QST7l{R3-*HS`LR{apN+vfgO@>2g+ZJ3BCC?Jw{(TD6VpW@6;MxI!An3z zD1$-k#|5DZ2Cc6bZnH~X)vlN&$EYQBgGYho!|gx9Di#S08ZRy|D03+}7icoD6)+jF ze3<_0|M%$sEOJ~I{(m?8fAcxR2ch4fdicq62JJ@|E|QJ%=KtRR9OOPwyBicIpzz2;YQufs$~allTZBQXf>oJ~fuBK0LCQ(- z0;8tFMNx0r3esPE^sTqpOA`i27|Wv1?dWY zn`S5BiwvsV{!EG%6)Ycw{&IS=C|Xp=Hn4o)`OEID!64gUoDoyN^5N(&76wq5g8T() zi*}^^mk0T&U@N1B@?PnK2Aso&A=qd+z%?-!gR*gggg>i_b%g|j zf`hV?;ssF;h7a1mtSgkAgfA#4uza}sTO)x1w3Y%~wygUJ5(|JF$mR`{`(;RDyNFV7FSf#Mhxwjg&XfYv2#O^kdouOz@Wi#klL={+rR>52Zt^E4`J?bB$ z!oR(cSv&@51kXHd2-c>Nrt>%~Q81(pwezhQav3^;EZ zXMpnC=bxZ83fIAD85G{2cn9@CK;bX2Rot_=gNdQrN#TOv4N=c-C-Dm+o(u}n5;He3 zYO>#$lp$CFn)$o2>Hqhie;E}7_VRf#D9n~%SDL+PmXm|yflXhZH)nv-N5=mT&zm!5 zRzy{BGD%bjI)mDy&!2NCFfgzwFfjbM|NsB``~UwldP@|5`V+d~@MZH+C}8~H_)DRJ z<->-btcnU13?GufdwxJ}-ZPxEZ-7YY8x`I& zoE}_UoFP#WDf9n($q$PMcG@>CHdiofmt4rX!Kj^gfl2$q#R72pR|dD_6fVqgmwS-o zeL#XoQaKE%z*i~0AC^9&EynO!u`>UVlpEq=PdCzcSz5pT_E)+a>1FJj? zR(arpBE!|^qSlPsyKg2x|Nni)ukFwOf3N+u<+;7LbOnnx`$Y!jEH~i>#!80{h7U*o ztaxq)*1ZI*d*KB}1~ZQt?sLKGN4PF%g5{9gxQq(U&%4>Vu0rN+VKN~9GbxxoXHnE( z;Beq|Vz_AdT-DFGgF##I0;BcpO~wtNRX6{?-~Pd%!F55wTc$t^#bl8F|KE@O$aG`; z!1y=A?ceu*|78{aeGmR`(7>X=^_&TuE@u7u@%(@rD9wP<6`ukF1ET^11E&B3!<3Z& z^8cV|57d_BQD9);R$yQN^|N>t7#M^V7#KkL9n|Lnm4l%CA+VM4!|a~|puR!^D6N9@ zad$8%h-ow45LaeVVDtiwLLYE*1C1{z6u7f{F*68uG&-?gnApLfFw=?YBBMbAgMdVV zJA(q~?1&}c`nD<#s!WF(76rXpml8**;It|&tGI;zq%u{f?;}!+p3HO?ksZ0F0QU%nib6fGU2j> zC4&J&bOvZ21^30(6)f7@E-=qBWDuxOVgT()$^Fg3uoSFS6X*)6dEva z6?ixN`|kdG!E*!W|MGu!G6>3gn{Q=hnBl~IfkBh&A}HU3#tv|M#r_EOI|CFe*noF*hu(_^N95)7K z2?oZgiEeW@c}jL}TID1S-XoCYV%5N)Y{0;w#Bo58f%!x5KLIb{3%^m!84 zJ|3`rxqlfnj$hpMJRw7t(LvI&kf_>`um6lbr-FGtHXp#CL;1pXDOg zYzA$Ci#iOipIb9%Rxr=X$oTjD+aJ(*FN|i}HZAVh?DX)4O2)0{i!-=pMRy7}ynN1} z_W3!;pXT8C2G0&g<%v$>ml?D~FQm#US86dZDRO!I`+nt*fHG+GPq{L&L!pB~MT-H{ zb6@|TOL>74!v$pq2?o2p2i!p6CcKr4fujRtPKOis4bZv^1{L8-RwI!5=}79u_Tp37 zgrf4p*6t0=6TCV&I`|kEm7APGFEeNaUtmyXRA*VET)?1I2-@&J>Hqii|EzL$7ZfTO zG)ymQS1@TyTud*>>TG6UG^{;XTqw(!c$^|Uik~ggxGCCOz z8a6R#-@G9IfJr&IKu9^lIjd7yg2e!&M*yrx8?J{z`{_jl zox~O==37FHvm_=vFi3EA-+?>5}Z zm_MHpr{v0u=xU^HNuo|VzC>Hqise{2j)irN(t9$6XxzAyR>8cWLQ1hv^NfLwTi z(S}8G$tLF6pgy}yg8>7m7X?z!3s&Ftn?d9GMG&70%y0S)8o6Z9yLZ95W3kiiizS_m zHus?*AZrh#5he_Sx%E3lOnG@@O=@L|S}|KEN7{`+14-YdEVTzayD1oW>>i?@6Bcc8Y5-CV91csF~gmOVMPXL zT$cGm@?QoWj*Ajr%(I0Z#Jwgvv0d0)Ar11qVnzqZZjhTT|AE?d6%L?q=LfeC1YqXK z-MRqU*>L^hrV7TDpxTM2Fr(w|_iz8tJ!ew^%~ycjy9VTDP-Vd=!~hDD?^_us{80dn z;K(sBfB5v51=JGI5xTHJS%E>hfMfO-rSyW-2DL&C1JEdfBm?t@g5Qb^j5C-&`21l| z__vp1Ci92--(Nv#Q;zKdL&aYW<{Qi(^8Wo-RxSXgNiO-xn?UK7Nr73L^+uBeg94NH z#h}>|a|#6ZUP<{c4_ceRVhx%{1*zb^0ouXO@WJOVGlK|tEE^QF3?J_O2JIDO-zv<& z?8PvN3pD%wLFW(O-UDu|bqs>+TNx)YD=|!B^5$X?Qe^nx`G;?BGgv&^jd7J=1B>U4 z2963gV@3_8iy$B9|6$*|HRZoNkGH^9i2?@Y|B9g1p2Cfj8z(n#dIdKK7X%hfZk$|n zvE*`-aA{yU^M_-<89w|0uO)br@?Re0?rq?iqZf|%H3r+!S ze?cRGOCB&+OweYyF!ur5dPWAf4hsf`55m7HGgufHG#M_=d0^eas-1Vyx|3O3<|gYJ zP^w+@BdJ4NEAfV9r?BiyC&P=C8OjwbhD;N0vRhnDs9^Ze_mdqI%F4`zpqh!}g0Qyo z1yJf?xLEOk`GfPH(g#T$OfxxGFnn0{gJ}ZDzV4r#tCTA&su(9RC>b&^Ok$eF@ImM& zNG9bcXq@i;1<>xY}=5cL#&^u?roQ zoGXtGUT6eI3(>Z9qQ{_LS4$DQ5uNW^d zf4KP@l!Rd-F z@ahBSh5~o44rT_X0X0hz>JZ|JDtr%0-3*KhO-?*Fy(_rDW-2!{JF#7a*^t}-Dw~+Je(2rX{- z@EkFljhF}T?qDwL2Cd#GJl)Y;c)CNH>u@25LV-J|{@~COx#(5FQ6a>{WsvIERwP`K3qnlWc#U{qkzV!g<7$$J6 z7EusqkgZ^x$o%2)Zx%VB3yYMQ3m9j+7dSU?&SouiE96lEl@06{KshVvry>Kx4CW7Z zzrOF~oXPy5=;ycR=37BCaLygzJp`%;JA{=Ps>GETr!q_h?VkCsoZ66Fq*`DOo^Rms zWMS~?0PSqiE+x_&KD#E_A(lB88d5syvU&N1FQ#BCOK3w ze~|q1Upcu*U~hpti-Ew_hE2>LIDUa=JQO{hm_J1Q29;q2TNzXZd=_M=HY{yi+OWcj z=>qeI-d{@-7*u(Dc)SyGWgC!lDJG~oLG_Gg>rFM|1Nx#-4K-7KM>fHgF9biy)PT;C!W#DIE(qgz! z{oqswvzGYH?u@t!$qF;3I~6x7`J87~NLQ&aNi*>{Gdl-+M(^ToFqWO{BzKWThvh=D zJd-xxO-2RL2aL0Py@ePrM}c;XgW4DS{(E@|XEGWKC$cE+$k1!lX#n~7;jfGY1_jXA zud^?U4jWiM|IODKjK;4MZa-(7Wdk*X^#aI@IsdgY8I83Q&Akm6m?ncxK$B)HzPsp0?0OyO>2Jr>R@DGu~J}Q{^0h5aVFEO z-yL01EY`Cnm}YecX=gARYbPvvzB-f9cy;2u=W^a4^W_+sW`B-i(AK@cG_yx?K?Z|{ z#sx+#wTr(xW=qW8R2;OhbEcE{<=IjPBz9&ne~|vcG<#9!=cvg}3>RvjGbm{{F7D87 zSe%iaz%=_)5Vu!w2BUFsLcwzmugMvV#*-63J~IBF@tnmgIFr#hIPu%_18&b!{>y{n z?M(`3OqW$o^dh$px3>g1#w7|8azSl0Q2t3xRb>b;g~fW^PY#ncPTwyU?1jbmhppla z3zb?oOk!Z1?Bs0e&Bh>|!NV|H;->L`W7&$o-yQ$67_>UE+%;hM``!9Ki^0)Nd!5)X zTQPvzhm5m9=?xSonhX{U%pdB1Dl;706kse@z&x38wkAVzDo8Zt*Xd16lR@Kg%(EHI z9$|)a6dB7dgCy6)tBn z8edM@@H`=d`2+J$4wFyMnLqsh!JwR+dg3`~?hF)ept&b@1{TGP4CW6Te`{me51w27|NYZn zVO176$qPI)nB|x*FwRtvo#D>R^|*jlnQ7I60v3Y_jp_vqGtvr}S59tVnezX8`+v}y zAyB%m`k?`CA%o`1+Be99=7}qqC$dgvRODUF#voI{GKt~CwI3p?3>u2ywIy|b8BIa6 za)O?$v$-mm3mAhSe^$darrJ!@9SQ+>j*nHUhA!D|N3>pkG+*wTaIDNYa z+Sk&P`d@xQ>VJ7gWj3#9r{D$#W#Pi$Bo;5>gy4k936~Ru6ARoy@*s6g450OSY@Tx% zI3huFRY?H?dl`*cwZB~yR`~h+fE!2+vsZA3gp{*WgrkF#fCEG?c)oBl*J}9+(0n<= z1n~UnB<9KgzrXm;${?t~peucm&*T61hyPg^L=_lxL@ux?anD>{_&}EFgXurU*#->C zg-oFIUdS*ztwFhfd3I{j`Za)Ux4sEjw*%I?MP6WYPZAY8$qu+)j=LbOz*lec4p zlYj&0>?V-kLFRLK32bFl=3$uN#Bt&O_n!aEax52^E0rChdyW&s1rdXSy^dMTm8=R3n(P;Zl%yO4w3sfkDlq7M zy2!6^o9+G8&N?22l}??Go=%=l91hRHX%({8h~c8ZUS# zMgoRRA3pyR*!uz8uNP2Yoh;74GLh-S#{Ucx1QeJ)to_e0TUdp00=QPz;JGNQ!Z3sB z!=?YA`5dMT5)4cq&iq$k0QIUts;B)2wL6$TO!_aZ!pgv)$8d4o0|pIA@GLgdhxETj z44MqgGnhW?`o|*2chR__UOVuH0XVm={?9NQbYe^J4aS)aGyZ>H{NI3q>BGGL47yAg zG#HpZ%>2)wbMPX_jufaJ3ICZUFzD4>V9=}50Qu+Tq^1lXyswcy&|KGj-FMqDd0CK1Qe+>o&PsUmQzdQV2 z`kY^p-+^Ujm&DCY{Z1S=FUGK~kOarXw~I`(7-t@MUMc0_>Dc{WoG@TL}s=#eW=1EDVMWtTUKCtp2n5 zxv(IRcRCY0`GE895u)n~dWqW~J7L+=fCNq6F@lVi{ zMb6~H-|y~!SwU^^nF_K@AAJA6-o!llae+3^?M?bz43m=!{%_LeQ!ZFuz&QEucb&fi zN{kF_E0{i5{#RsRn#Ho3ZN>lZFaNR1@m^$}&7ovmz%ZL-<>ms$+2sYF3k+nLKB)fx z`(5_00t3^B1OGI@>EgrI{tdhgBJ-FhuuNi|%%H`5kx4~?fq%n?y$pIkFEG#e|NZG- z5fyg1FBgg`jKQn$H&=kx;D4$Bt-xo_Vw?n8EyZa3_#%TY^9AclMwQv@_pWj%F(`uE zW&4M9wy+9|G0c~t|5)YDUtpcZGLyxC>BGH$EJ}t9p!9R|pCyBUl7J!C3Z@U2|7kKX z&0<^4wc`Kx=6@`5{1-Wt*j93^VESi4XGq8iTwu@@xd_?=#&dCo42KcZhr7R-KD_?RXbPG!Q_her0G$KF zWh}wKp~Upz{BKYh{Plv60@DY}e{6ER7Y-^bW-u4H7BCqKC@~o@ec1O~Im3`4qJrte z%s&blOdsU_fo9R~JU`%eA{Dg9k%d7);qUj*-@Jay8FojqGB9ZKUI2{+-l+Jm!FiFx zQ;UHo^m8P;2eWaa1k;D*e}3%MWMKNh{g*-G!^I!ZpQQemKa=`jUUM$!tSdI?`Y_fD zH!7GuO#Js>DLL|10ciafNF8W>X3qv522oH;L@C3K=|jhFLk0mb%lMzHf+7R6QicoD z2i#oXqDh_X%j~QqcNi)gVxuJp!l!;E1)E_l7#`J_Wv&dB{r~H*$PIh3=FlY ze_5ObloVz>*(9`*>BEM<3Jl^KKI|>n%EutW(6fON96GWLOdl5iHDusWVp+lTVcuUw z1`e=GXZ{6+lgnQg1_31v29A}W{k@P-0`=8+85mT|CD%AHT>i0_>4WnhW-jZ3WSQHW z7|rK8G2dh|`4IAC)4S&~3~!$oZ)IcPVPH}Pm8uMy;un||8CU%Oe)oU2+pJ1^Whn&SY<25VQK5YL3Sz!oDUwqyT42L5MK;xs@{1@hC zFzE7J(5_IB`0(f#-%8LaUe|wd&*qxRGMQ~Q=M1LF?6aAtF-~Tf&bOLp)&K7` z|3o)@*!%bUnO|%ZK&||9zaGmjuVkMru$qm5WAd%%2i!pJGuX=G)5@R~$;{BYfl&c; zf`bG@rrZDT+5fd8r7CW8Kvtu&dS|(@D>8hz`I~iv!CsI)=_w3?no}4A4YqRnv@&Q$ zwr&9BQB^~x4>NvhMG7jicwgwqa%1>#0IUOI*HH}hriM%(8c@`)KvK^<6}11w*T0QH zK;cUyF9XwuMZZ5sDkMo{2`e#Z{jvDCcU-(inif*XT+13Tjte-3d6Mnxuteg~!6CTA;W zrBd_iaHzZkJL8q<9Q+O}3QD#686dJrwG8T0+!EZ1s+}CTz$WuMFe)b1b~#%)CzY1N z^@7X}=iql>Qb?+;XJ~R3cTO)Yt7cHDb0}kHyt0df%Yj8Lv33%}MrSVPq|&Sk&XCUP*h-G^k(>Q?3eJ~-za+bg7tb&V-T$0%F4j)y^7&V z1P23y4*!L;eC7H_9f}pq)70{rrajAJoVFy7Vang{oPR(wj=%oa?}eltfvw_-|Gz(g zt}*6f;ALR*W>REfVEEAgi;Y3E0yJZA@xK8Bs2o!!0tgBc_k7(O`tWK$N>@V>yHA$>8SR%J%5qZgUHcRVjl`7eJb^}jr*Ec&rk$G?r?b0lbFn?c**!mW-bC)M6@ z;C6!E1xAIL8B$rCwTw<|7euRBotQ7MD@7GBD*V{Xq`>IJ0v2Puz^U}*ISZICRL$hX zc!68#&2z}gfR`6QbKTFtD=T(KGAKq@2x;HH2nu)6|F@s>dB1rss0Ep=GE&uK`1G7X zmjf(o^b<6`C7{eyDeTN#sK}tf@b~+SUx%P+6z2Ydt$cp1467qq7#OsL!8`c{FLHtB z8<1Bt6i0$=WxfdNQ~m#b^IySUChs@k_5~;mKxT1*%Xa|<(CD937HDJ-v`c{Pf>4!o zoq)_NCx)96GN3vKRE8C7WoF=I5McoAA2hhYps9C3xPZHYLpHd;yJB*||L@EHJSbpP zU{chsQZCG{W_Cy}%&O*c0Ie=fF3hVIb1-%W(cd_}F@RXw)yxiy3pJ`49T*h2ofj8s zg4HfA)T+M3afw0Ld2wOEUV*J#42%qn3ZOnC=!_u{k4fSG_g()%ySu8F-BtLFd0I2<&BMU{c}$?LpCIyTG8ya)Hk%Qik!v ztbd@g3nVMB6``92s+-4%@k8f71_hAM|9`*tAEXYXitPe}HfVn*g92B9bcJ^TXiS<( z0W|-^pviV2x`IK0yMWP}L!05IgaJqn*=#nb*<419AEM!AZ}<=DX@d5Tg3fm0yTG8u zbAeq^vOusSvOutdlWS&ypah4~4H?D{j$l2^3|tIM3Iba}sRp!jWoAW01?ZG#!G;Mk zH)S}K7(eJj)gjx>0kwOQ1mg!;usjn3%uenLptQ#cva>=$BC;S*hE0j_0~c5oXv`oU z*@ar17eM{-zzWF%K?zWK%J|{yUr;!q#sU}AJ~ku94^P4JAd{?6OoGIQ1VdoO|L?)S zL1utPLBtv47_!{hlvx=#7$!DOZus~8z#m~1MmeSlJQpk&Hn@ZKCTTD*uKf2s{}+oK z(*>p(j2}Y&gGyk=Uy#)Xpjqqg4U7{(?Q#JnrWK4I_WU*WTh6c}l0n1f!r_j^PL>y$ zD;TuRE;?1PX-QlJ_47lGObvMq*jE4lzVa7?h9kzXjA=Tgmjn;s>Jw zs2|^$2WnSxcL{1~T$~HK-(rT4A*U7NhYSBeJ)+%_3Ji1e{(t8O^`RKffrenghA(nRtq~ZTzec>=rB~5K(f7m7nHq@RAd0PA^HDsD7}u9c>pq%^@0?GWY>odA*27_dH*me zG0v8(eH|(2WP3rOTENNb0=p5%gD)L_zTbwLF8GH_>2+jO0n_X`3|f)F73|h5+JZMO zbo~1s@sB~n@515ED2_`K8lFtEnP!|0(T;SKU@=zpVEnNCFYAU6d;ff&{}(iO)C^j& zpujx&b>zK{Ki_BnWuD2z0GcOz^P6$j>qx;`79~L^9&l)JUf@QI4h`@QIX4ulomh#r4+=l z0bKUKNc}HwJQvhfVe^)%V1cgbX1KuY@&CK}F9rqB7#XOpG=Z*@2Cd^}m2(EC$NFE& zeoGh@L^fqiuDQ+5ag|w-IZL{d+kp{u%1k}CGjqAK?9KXaIVNr18%&xE7Z?=}bo}`~ z;XjL_aimmzWC546R5@tZ9-}7DMJ8ndCFcSLMIHmj54wL0A_Wvp4gP=k{`u}XtLB@F zOv)D}oC^e$K(cIqSd@(-1?#z;h09+(=TMc>K3lB)sZhi$)iMtWDUfWpAqyWsG1ZU!y}Rbx{l9z&4YsXsv^(=S#f(1_#i$O8;f z1)HF{Lk$=|O#jU?+uvs{gJvYl3@!$?)uBc_hX21;{nU&UP;xb7Tfz9@*&oo}K#(cl zf3i*h?c8Eh(vFNOV4czToI{y)@~`K~6+GHi7azm(%F@3N(sqOUd-)dxlr$L_KcxKL z9mz7|P9EsI2wtTHWxFGz3i6&m$YaomyO3PLs~vq&yMsfCxoM@0kOAWd-`~3$A$>QvH^~gON&h#$((cIf z&yy?owGA#RZq)by1)d9T^Sm4S0*CgCi;a~H z9sj@I_{H%+6ns+D{fnSg#*s4rz90C56D}p{tP9Abj9mnA{f*bvDX2 zbj)yn^ZfsJ$6uhCGR6yxAB_Hh$~5u6N1ub-3tA&80bTbAYOe`wWvKZ7UFa96Jpf|; z{UxxMN7>mKH0C{9A_{cx*#%I4dV;&aUQjFU_XP&cpBF(R&j;K@(*DacDmOcDdI@Zu zk}cyrB{?8_hI2sjm23ru8O|VG3Jem?7m@|Dxt)cR1@eEe3GeI@quK$Kv#aRrR92YDZKs#udW>z|Y z#E<-Ee88an^CF`OkD0j6{fn&N^U*-&|498W&*sgj7?p9z0aTtzXB>8rVBl~laF@;n z%~OEXFeqVvrJ(0WzS9TWyznN?hz`Mn>-NK4MCh^=5$ z)|F;7UG2bVz1U%)!)<3C1|bdh8yudK7=k1OGb9}podpvN_Of~jW^g+wI}0a(*5e-E z#URM>fx!WEkI5nVf~{9Ju_<%vaNl551`s8 zUG*O%BKkk0{QmO;ZZmf=2!h=7GZk_VBcl?NMUw-oHz+nC{wZ*Wxc%32P&oeB%E!Q{ z$j{L3An3)ya5>|z^KR$M3C(h#lQ2MiSx7HN??0Cpw|8I$qaN!;OJ`}xz=XI0(5eVc zhrk3TB^k-2f?1iO4s#Q~fXxJj1;`DIN&;J(9N4`CM6*EfHJr|NDmjjLM50*gQ2DxH6=ixe{1CxiV%s zb0rk)1?4S}9VQJ74h9XN^SeQ(B>&eCzQC-?>hS;j)&Cq`i#cX9%$BfMddslNVV#3y zh62MxXG3Sn1duCw{}t?&umHsokBW=4us18i6N%&uQ2DwzLr8%^Tj~On5~DhwH-lod zWK@9$gL=XL@0tITGvwqrE-cQlV*vFAKshb)pPR$CO&Z|)+BpA#!UU4GS zD#xF00=a1_xK+&auezR*q1g#ENA&;u(!Y!*JmySh;yQ;fe&5Te$e>&p_BpKAf!zxf zMzbxaOl#XC&NMI|YB51Vp7@YL0hg$uY^GGZAAFxVOSpjX zgXE9viVO#yJ0%2f68{6li^eECZ7YkEXy4POnoAm)Lo({{F82pGA)2 zB4{2(gW>mgm;ZmhZ~FWHyU=fttwI6}3x>2rp3hgO4ffizb#I483yy?f56tljWAL%Kq_ z;Oq0x84TKD7dVu(8l*au3Zy!OxRMH@Iu;c~bqH}iDwx%wR5%MHR(PvpQQ_?lX|BhG zx1Vb_+cpbKx2RdCw zLV-#1_eG%&L2s#sZ_gzZI5fXpB~dzLAH? zi`j$WLl5{&2$kIof*^IQUd#*v;JtF7vo#qnHe?jIGh}>w{wMRlJZK#t2g58UmJ6VB zXl6MvTwqWra0jiA_@u<3%ig#tze$%d!|(EPYU#h>pL|5-f#emDLvu$L#} zzxdrGc$nJConJ|!jA=f7tH_fOThCZ7P}b)A2@^d z-131}iu0_N?_gT}O#(DZVaUKV>F@W9ACNVK{1*&5{(txW&&R45o?)G7KL&|FAt^F|ukf zWMENBkYV^R^ACfZdj2v4v>rh7Ka;X`gF*oVS3<#N zs9eZ%CZ*RI(j8XN@_hO87a0s6-u*eWiJ5_2VUrWXCFke77no+=-c%?t(~0T!BA%BD6!-T(}(LXr`IR--pIfiKratyMJatuL?aty_catvn~-}p`;6Pd* z{Z5HNvE75=!=~TdtE{UlJ1sgHCRs7?8iB@$SQr{Wr?l$WUvzuW;9b$dI=SB4k>PX{ z_d0g#+nbC!m_X|{Cs%tbGO$f%n9Mr+|M&cVCB6(A0vFk4TXliXuI9dI!N59G$bjL) zsXq)FEElvZk~(KIyq1V+5L0GbAuVClp}wnjCyG|~Z$_EUpcAeqg zY?G@y*k(mD%#LEVp6kSPn?d)(h3E%jN^C2HBtZTH`OX0BKmEU;@r#HHZk>!(6&-)R zfBeHD=W@}_yP|`AGTUrNhLcgQ-Yk|UH?gg{)WtTLX(H%$P1c$0v;Tkp^Or?V|03IL zOHZke$ubPOY8Sm5DmyH^JsD0%1xhkocRMNEWu0y45#8x1$z8ZohSBuornj3|C%Q^X zb7>c{&erv0F_w^E`0(JDjyLNp>5j`1cQ@&H&vRnE0NUp@=ecLcOs8uXK=a!QJ{k;( z9Sk3s|0onFGJyPB^k3*X>zohILFZXCKd-J3(Pp^F`CQD?y3((KyMU(%cax zgW6Qnxdv)eEZC;|46w^HHp6cT*2y3rvd&gykm&sL-QX{y9P>ri*^DZ3oyE^9 zIwpB5b+FChob1dX9X-L1(fT%M#j7&IG{(uCv;TjW{tFr_XPqtA8T%ZTUf5>|bQpCA zNlbQPx+5*cXl>k3@55wZ)WJEEK@zmzUAe=kgVA)hgmS~%O)H+G=N67X463XXSZ6b6 zvs~m-VbEo`nD-#z0qg9F4#}!N-w*$0WMGj?zL@Eg<6Y6gHidIC+iVwxCsCQ+Y&K6e zaj!G#V4uu1g>fRoWY(D=_nrR3BIk3FeRiCubcd8IgRa3vuLjoH(LPa~$&ylq*)p>? zJ(dvSk}3q{BBKsziONpa8GpVj{r#`FN=8qX*_4}sb;6`g+cvG;1e(EPTYbCh<|b*b zMG~o!f`!_JKE4LBS{Z&&5>PR=<_d1lw)+heggEY^&fE zQLpL_!H$_u%ojvF8lBiL3O5LQe^LY88+LQkN+-q3oGJ^SYjpho&iI=_LmzCv4wC)% zFHCw4Ikyj#?m_9BBlEvJD9wY~NuV?jY8x0bL^_9LFd8RFBt|i4Ub<+*z+s}u@JWf` z!?z!heEQ_C-BU)DoacNhSal{gv2pecXB zx{6Vo`(jSV>W+$zRkEPnmO;NkDU?Ckx=63%6ZphC&^|K;W$gym*`U&qbux!H>rCki zHm`1{>)`f_a07$RxeH&PGN_p_uugjqZp(n&3R+JJI+g4H_i4YF1qI+Um49sI_Ge?Tt^m!g{@3Qaz@@^l1HnA2OcD zq{+a*>@Bbr)T;sYfBu2`UD^NT*|&n$J$?Gm;>GI0peQ88@ZrFZAKw{%gXCGVA@@=< zZej9habw(*;LfoBpy_{kWd7Q93=GJ8TM1PDOCLrQ`R*W8{@j(Q>P3A~A5 zRi4oZ)xPa~sPY^AQ2DugQ2CkY=Bc2{-$e`mO0@WT>xJt7NPkp5t0k)YV#QI-ua!WR zcQr@lztligztRoW{GVv)5zR2~}R#8r8hBXzn?R z7XME@Q1u78qx$FVQdD`(Kvemoim396Xz_K^6IK0ZH2*~!qq;Xx71caPH2*9`i%(88 z^X8)E?~`cxb0V6&Xf~?*j_RViM-weQSE9+^M2nxTXyL7hmOj4vq1so9=001r{OgMD zzFbuOnlh;2brP+-2}KKkMl|=yqLo*zX!-AM8mfKHXzE$xQ0;F;OP_^k`OP#GRsBu0 z^2-n{JkjIV6)pWWqQ!q8TK;{DX1^s``ag+QUTj8lza(1vJ1UFnenEFe1_nk(W+rB4 zW)@~vCN?H^CJrV}1}E$)hO^cTf{Zo{f(#6xyWAKU z7VTgVl+@yv;9_84_!!B+@K=R_!O@M8A+m-+Fn11v;K2e0!PqJW!Q3DQ!NgSzf)D)| z1P|IW2!6DKm?0(xG3U(=2Ei}?KmWhw4^}g_yUj$28I-Y?Xo8n@~qbw z+*F(3c&F@3V0Lyy;wE34Le>C<<{fWcCi8!IvH04xp3RA;HylctedW^Swu(nw3uHd+ z-TT{Qc6TFfBGs>PzksKubgq{*zo zsKKDYC;?i+2vP~h?Tm~}j7(sHnVE%=nGpn-nVA?ttKIk*1Q-Mvgc(E_*%>()xfr<_ zWf*0dSeRJB=}3}Eib;k^mKl`3#2J_v8CY2uIM^AuxfsO77-VHYrn0gy^6@eX3NVTY zGm48bN=Y&?F*0#;G4b&-2?{WY2s4R`F|)ETbFedWb20PrGB7eRvvYEB^YIG^3We|D<~>4tX#|>n7RbwPf)z%?Sil;ZiLVvu^gzFrY(cuiX9AsOLi~_g6?;R`*f5+ z_Ym+k`Y*rM;J^IAG)B7HJ!&ECL*Onn|B+);q!egwj~t!2^$6tumv@x-FVE!J_?e@F z>4W|+1_qFrz*eRYnZMXISS|=@a9m*0;J6^Lm&J=kK{%VySUCB|b0&pv&qWlzJO}Ns z1)ZJC!=T2X$`D{?P!VVfT5rV6pivNEqFnG}uV%$51`oML$HfvB42xo-Gfr;$4<29U zy{KJri(!!jqj5ljc7bsPix;D{ae;6aqp@((jpvNY_rYezC_6i|dkSnlDZ$MU0Y1-# z^&;rZMrN_4-ogn?A8LPt?omJB z2AW3|U=RSEgUrD6LFp%xw@d=lhdl7vFCaN*IneIH1xg>bUSf=P5_S;v74vdnoGqax zAyfxio5`RheL;$W!{|yrgVM82Z0nzFn&QNFM?>OpCTJ}!<4mSif`x3WSSB&85-Vn2 zF~c3S>Qb^|X9%OwtLIX+QWb2g8P%i;o;_ca{$HNK0kmF5)tiOEf$>mG>jnlb?F&*8 zf^`g<>K7)~F=(n>5UgaPH!1? z95{TXB~m2Wec6l|ttM?+<@EM~M2DMf>Z^g)um0}pP$HpnIKu=C3k6)Q~_u$)sg2A`QuRf+;hv+I{+Bo4 z{V#9A`Cony_kVd8uK)6`T>s@|IRDElbAs+eWBOqJg8_Wg2Dn@T-?hZ_LG;H$MOLp) zhA9=SUWv{^87$sG5cFS3%08GYG*KLYg}OZ!2d%#!;@;w((it2X%}yehFIh`S zF=|O&5CNUMwU_b3v;RWgk{L`NZvD9Y9ArN~n0NWdmFK*k(GoA7p9dEu32LBBng3hJqK!n{KPDorV;QTKy!SP>S_rE;@=$>5A7$`4;hNjp>W`-rkhdQJ? zW=nBoi7_-N$uI~gUt(pPI5C5j z0kkHLK`F}nx`9*z9}fQPfolmZ>yk0LeLn<+3ZZz-vlY zfpxtG>#_sOFwQb&5_Y!n5>Bx3R$`Erp5w->X?tfg$1Db6hCruHQp{Rz7frn$NCZkX zRX9`#u`n<(IX{SDF$R@{3`+mCz3+Zd((@K#luF=N()E@~&;_3g`R4+IvXYm&r*HzN zw2>^gq;v+0l?0b^K|+B9k2K$cg2x3cCJb7i?ldR~C|YM+Vr4Y8PMDn0?L0Z*``%=? zs}(aOCRgaPNwa7>i&n5$YCDHkuo&qwX*)9~tbfj=#dT58>p@JQ)FX)?@L5V+2`t95 zH*J5;sI~PXmsgO~!x+JYug^I=BPBpGYo0SOusGN-usB#SusE17us9enusHBAusAR< zvN*6Xus8@XusDb?usD3*DhiJ)hKUn1*dcMHoa%MmKsbT%!~ef?mF*a2GyIIOW;kVL z#PG)$bbes{gNO{q4-fxZG8k3Fc%L>zj-xeh;JB#JkOjp>C^*E?;|U}a0FkNUssgS2 z>8b+js!{~UpchzIi$XrGRkhzzhGt8bXA)O(~ zC0r0#Aju=mce#K?IofGr!5kMBqX(cl0|N2N!Oy?|i`#;&Y;uwpn3STtXID;kX4DqG z80jrl@n4JoVpPR{EuM?BD*kJ6Uc6QDUyJRcRONpy=8MslpmPdmJ_zvUQIM)&)Z)0n zpycN(RiIhH&A@5RqRn_iQK4Y3w>+cvubZwui>q0*8E!T`SX9ZZ#c;Fk!7RB;n;5m2 zZX|TbYn0z)&2;_v6oia(#TTQX`MxS{LGnQ=0!lWq4^ zZBNh{x!W%?YBAnq(B6EJNtwH#K~ddT&A5|MqXJ|S*S`iujfzf2#t&P6Gb%4`Pz2Z6 zTo-;RH7Lq^Phybn;ADz&mIAMF2b~2t={e(v3BR=~mNl@0>g}829(o0gAL9QCdJFo1 z+D>d28Wb6n6e>Cyr3x57-2Th>;pE>2MFr5lt`ArK-g_>jQ26|S+cNI|^4XmK<)t_w z^`r;qe|b<@52`PvIseNmg7}>Orh@ghiF%w{LPTT7Iq z86HMGkl^HEGGzRq^;emJQR$yCqaCBERQs<2m>pUdR&4sWmpQ|hfkAuUg~kpR1BiN| zzaY0hj*w5-^jw)?qwy|=|Hd;S7|jtX82>`d*zNT0&I_e)Qg0;~l!F)+hb()}p#BlO zZ%W}egNFPC20huk#gZLr?vjj?w}ETDoZnFf4Ganr4jGK52=i`&cLRL;wK$T|cyZuf zC#DOGv*$WJyC~=l3X9bjrYg?{hsv@GeBKYE7&I4M;PqM@Gt-IbCZqAxerWkM<@o_OSi6EjgxTSNz<>EDCI*HgCI*H$CI$vx&w{O9dAvTCn7cDCaW8UW zyTR?tq_WD1L{6wNzc{aln3FQjyf+x?JK|5?dEdBlA zIfDX|_MMB2ACCWe^&He*1Eot)8U(fFKy5vcUqRkVda1qR8c zs3yh_^1ll9wg`aQl8hfLf3tcsC`4zlYO~yA_6o|l#KdrA28Y02P+s}-kl{hWR>lwe zfAV@uXZ$g~lPR0^|NE2wDUvNtESEUF8C5_ttLzt8lo(Xlyrl}*ye4Nd8c$AS{O}FD z))$lqLG5Bt7=YTw1zUN1wKM)0$7C^nnELbo_x=C1GZ<9=7|+gnEYa-5atU-6?P@26 zi>%U&pt}gb`@mslTvuZ8p2RR4bWVddXf7Ajt_7_@7TC)8;qs6F-{1dN_f+>jm8W2I#tzMIzu9h@x%3>D&8tyQVA;Fs$NnF3zSs6gBUi#-e|nydz_5gY*};qJzdWdIeV7xpPRyPG)cymF8Gz2>O7}C)=rESfX#UL6!T3S% zSBh7vr*H;?0=I*3Lb7*?mvqKtCx(m59x#3g_|2r4=p~%d?JS(||9k%bc<*>0iHZZ8 z7(aBw{TSoTsGyv{_`&NZvogq+&p>N5KN$aFWnld9;76#pL;~Z7o?ju}k{L--!Ey_o z7%mAjG$>tS2A!ren`t(eQO3orlk5yv3Lp4*%J6Vz%--bV9OVN?=Z4(PqBMXk_dFV)JDs01zLLvQlBLKF+)gVqLa!^ zhzd;)#t-{{Fen=rX?R1zHsA+?0^^6ZzZgHf{>k`Z<*%6McNk|fFqx!CMKYvFaVmN{ zHyEFGSi*ITe?Xx?D>Q2L))K|)3aT)RyD z!Km@(f{TxG1&emxMaB=hKN&QhTwwf=`6EJs;lsB7Ov=gycb(S5!PzmAtE&omej_TM0XW#^=Jl->E7(dMVQS_W$o8dzKb58FW)r=pcer7#C;0Efeg38GW&^|t>Ob68+p#J|A z?*H)ygV7CQn$2xK?8ArvExj7a4UKF3#BmIw$Vg zMP>y?J@$)?x-1tNXR9zik(4Q5wD`AIK=02*CJO=GpBI=6zCUMRXi)yXb&i{wx0*lW zWHnE9FLhrH9}RCN4XKL>ZWaj~8ESq84h?E%%m&UJ35+v2D;P96FN!57d1)mmc_}44 zP?F4;=)Ay6`ay%@NhZOBPtVib>=O7hB>n6h8r1(Y**Wt;b@5&lPXO%~7xmIg5QXbJ z0NPoU@O^KCVkeVe!n@}W6#2cFoV618y_6E9GP;~UJoo1MFaLmn+2IBQv%>@iW(QFD z9KgWr;K0D_@c;kg|4a>RwhgWvN}w{kA&o0yKkHR>v3MJQ{wZM$EHkF>%i;u6SzQe zU!laH$n3%J;o5(O4_p3&c2%3CgT@s=XRw_4%b?7o!0pAz5b4}25g5au$$Md;6URkH zWd@b(0)`J?{xW{x`k}y3u$R%8OZ)XjAr;X0D?mtL4s{afhUi=5`_z0+QliT1ZE%EL-!-wO4KR*YV^L;A|1CIiO za*G?EFXN%PH^}BuPT+ns4VR4oapMkgh499#oIwqD#67Y z!~)ZitDL0*k19=Km>03m+0eN`ZDzpy2z$?OjQkFE&hrB1MKq|JF`020IL`=ZP>_mb zVB&IMa+V5YF_DTi^Rs6$a%fPqa+V5|iZo*rViMvqa+V6@Fp-LEP=lyDtTc&Xe#92H z_0Hzb^8@BbX!`Lxu!C9Vpmfh-?%bdT5;tSBXR_x4sX3q|AGzKcVkXE$G3R4Sa)FZ= z=0vP9A3=u$Ni}VI>5AJNtDP9{fcD%$ zMspWK?^W5gRiFgWO>|CitLfx$roGTYEbPn;I<;MyP2nr3J)izxp4FSpQ@VmH zgViINoykF(TiBUFfjgnV9b^Wqjx5;9qx%2*tN&cyG8J6jPdHMY-%2p(FkS?uFVH$q zwhP%X*V^#degwM~q#xuq`K=6!OiJ7gj1w6qvMMlqDF4f(%WaimX za?Fz$w0~V>hl~>4;#SFVQ2?I+ulZM@f@Ooi-U%ld92ic3#{O9txV#xBgU+O6yeOz3 zw)g+{^Z%6@m>pQ0STBG~-|>fWHly|1=MoGbo*!`g|NlQb`&NbzrhgigI213jPR?SS z2)aLk-Ev|QlOm6oU;^Vz4>`sO44S_#G8+meuo^N>M2HB2_w9g3ACf?OpV;>@901MH z==yYS0L792#ed(={bEwq@@Jl41@#ZxWVYE+a%^D#sQQ6!E&Fo|G=s6|KcgJe1wjSS zy_3ug%u0+C7$&f;ov*;~;r$tSYGSB$; zefh6d71cR28FYVLWL8d2`v2Yf|I(!Y-xL0W&NK6I{x3iE|G)2`IAvvE{Lk``;Q<3E z4gY8O4>~=Co#Eei#a~RytPHw7O3;u6jcrBAF@VEF11V&`{sXO*7F2LKa#*!HgAc7$OP~{DMeugX0QL> z!@=jv9B>1LjiL!?j}{9<>jvgYOcVcopZ&8#DVaH%JBU@vxk33h>)fmcWp#gsNxL!_ z)EFm7GtYA3x%op`jX|14&OyeB?Lvc+qIVEeToPoTGJ`JnMTQTXe=#Y^cuOUK^hYHz zTFpvg`0(=&gEI51$xaFv8FWD<{=#1(-pop}P&IRt7(TrC)1bU717rioO$I%-3!uGf zJf2ZWQW;zhQVEPR{(VpU2{}!iVHVTOOAnx|jUOIhaDc_%hpi1Nog3H~{(Zmo;|c5HEGAXv z$xIU%KJflxR5tLpO-M~zoW$@U?2n$0GStn;HftfddC^~3Dg~7QDkv!mxy(Sgw(~EO z+_Q_)-pq<}3Cs+j@xtEiP^2BQ|+4F#o%&XNg`d{N-esMO@}?YX^%AXJs9)y)iMEw&p1N}v-WAm>HA ze$J=_vg_;fc#WqwoRk}sB%~az!EVo*=^U68n8ocJoOA;>(MW@G@Z)c^NW5p+}AhhIMrC~mU8#f(N-Um2YzXr}b7!D)CO~y_J;T5M4SyLKinf93PDW$l1QsP$Z>aB+10NV1Ky6S~PwouR-J>jCTnQ|mTnQ{*!r;5#M7aLTx5zOtfcm>2 zbqvbPUcw15T;Lw^fx*GyBZGs>M+OH5Wr3{{K3y9aCNoY3opz&sA=8aff#E~uFVKl4 z46}tiL1+21tzw=m=*_f3I)i1hfVXr8=w{aiKLwQdJlR$-d|3PoG-vl8TuX6n5ZKG8 z%<0AM$+SYbfZ;>$PeujMJ(UKaIZ#aoK@Lp@K^{#8K?O|)L6emK^1@pgRUkGR{9^WI zm;$;(ed~V(2C=;d+;($=?zR5^eg6Od-(UX+l@v_gpk6m993C!WU|`x(=;q1c$-o)r z$tu>A;Lsc)BhiZS}22}oDZdCOz#Zmd3Ca8Sf98^AIC#rcr zO;P31_gcKXf~x-MMg~FTy$6!NP~~r;xwlgU)qM258|Z6`dj(O|+oJ8wc&UzRU+ymGueDu8stp`!%8Ly-A(bt~0qNV?fXnTF; zqV2T-t)WCtU!CTt{y&Je7Xp3n(8D#T?ny+`{}yd6Kl_m0*M@NVo&2~cEER81r0V;0-m9K%C2ebb@ zRNe?G&yA-49aP=`D$j-{{}w8*2bE_;lYax1*MZ9a0r{5+1Q@_TOq79v)tf=^q!)u= z#ZCsn35>D~pe5`7|FbhPF|)9;F)^}%72+V6(c)tUn*D2>AmOtJYX2&z|6$=Pk^+&3 zg$GRi0;u{mXzF=VAZdUBlt3651wm^J13V(lV9w)aU}gBgz`(GDfk6WV4N4a7uX>t@G~$nure5wvNH%UFfug$2Z@3R)dB`V-8=@tz1a+c z|Nk>GfW#bUF$nIR&LDVo8e~m8NG$^c2LlTO1A{dKBS$3D1I7+T4X|2Jx`w48gWafU z=&my)43ePv;!Qe)4-1n!Q27L?Jm?G*ka;lq8<sQd-z|MH+Xlx3K}$i%?F%*4ci llJ8v5>{oDs*cSs`&kynk$b48FfzHZM01X#G@jvg&YygyiC&2&! literal 0 HcmV?d00001 diff --git a/update_boot/BOOT_TH05D_v14.bin b/update_boot/BOOT_TH05D_v14.bin new file mode 100644 index 0000000000000000000000000000000000000000..7cc5cbce03e304603c2b7d1b29290301578eab39 GIT binary patch literal 50052 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

|pVh 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 literal 0 HcmV?d00001 diff --git a/update_boot/BOOT_TH05_v14.bin b/update_boot/BOOT_TH05_v14.bin new file mode 100644 index 0000000000000000000000000000000000000000..a3bf8cd4be41a43b1e9ef1cd83b49a18648c733e GIT binary patch literal 49956 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 IeR&Tv0JlD=#{d8T literal 0 HcmV?d00001 diff --git a/update_boot/BOOT_THB1_v14.bin b/update_boot/BOOT_THB1_v14.bin new file mode 100644 index 0000000000000000000000000000000000000000..83969962e0d8d25b01b2b512383a356415424a24 GIT binary patch literal 49908 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 aALI{^`LH+wos*#e8ZP?(|Gxr9wmbm9?+}py literal 0 HcmV?d00001