From df5b05e9367ba2278f09fb6ab4605197150afdd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BA=AA=E7=94=B0=E9=87=8E?= Date: Fri, 1 May 2026 20:29:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E6=AF=95=E4=B8=9A?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 44 + DS1302时序.md | 89 + .../Target_1_STM32F103C8_1.0.0.dbgconf | 97 + EventRecorderStub.scvd | 9 + Hardware/Attendance.c | 703 ++ Hardware/Attendance.h | 79 + Hardware/Buzzer_LED.c | 29 + Hardware/Buzzer_LED.h | 19 + Hardware/Crypto.c | 99 + Hardware/Crypto.h | 30 + Hardware/DS1302.c | 246 + Hardware/DS1302.h | 24 + Hardware/K210_USART.c | 136 + Hardware/K210_USART.h | 18 + Hardware/LightSensor.c | 106 + Hardware/LightSensor.h | 30 + Hardware/OLED.c | 258 + Hardware/OLED.h | 21 + Hardware/OLED_Font.h | 326 + Hardware/Serial.c | 83 + Hardware/Serial.h | 17 + Hardware/aes.c | 237 + Hardware/aes.h | 65 + Hardware/aes_fixed.c | 237 + Hardware/aes_fixed.h | 63 + Hardware/base64.c | 81 + Hardware/base64.h | 34 + Hardware/esp8266.c | 624 ++ Hardware/esp8266.h | 98 + Hardware/esp8266_new.c | 243 + Hardware/esp8266_new.h | 70 + Library/misc.c | 225 + Library/misc.h | 220 + Library/stm32f10x_adc.c | 1307 +++ Library/stm32f10x_adc.h | 483 + Library/stm32f10x_bkp.c | 308 + Library/stm32f10x_bkp.h | 195 + Library/stm32f10x_can.c | 1415 +++ Library/stm32f10x_can.h | 697 ++ Library/stm32f10x_cec.c | 433 + Library/stm32f10x_cec.h | 210 + Library/stm32f10x_crc.c | 160 + Library/stm32f10x_crc.h | 94 + Library/stm32f10x_dac.c | 571 ++ Library/stm32f10x_dac.h | 317 + Library/stm32f10x_dbgmcu.c | 162 + Library/stm32f10x_dbgmcu.h | 119 + Library/stm32f10x_dma.c | 714 ++ Library/stm32f10x_dma.h | 439 + Library/stm32f10x_exti.c | 269 + Library/stm32f10x_exti.h | 184 + Library/stm32f10x_flash.c | 1684 ++++ Library/stm32f10x_flash.h | 426 + Library/stm32f10x_fsmc.c | 866 ++ Library/stm32f10x_fsmc.h | 733 ++ Library/stm32f10x_gpio.c | 650 ++ Library/stm32f10x_gpio.h | 385 + Library/stm32f10x_i2c.c | 1331 +++ Library/stm32f10x_i2c.h | 684 ++ Library/stm32f10x_iwdg.c | 190 + Library/stm32f10x_iwdg.h | 140 + Library/stm32f10x_pwr.c | 307 + Library/stm32f10x_pwr.h | 156 + Library/stm32f10x_rcc.c | 1470 +++ Library/stm32f10x_rcc.h | 727 ++ Library/stm32f10x_rtc.c | 339 + Library/stm32f10x_rtc.h | 135 + Library/stm32f10x_sdio.c | 799 ++ Library/stm32f10x_sdio.h | 531 ++ Library/stm32f10x_spi.c | 908 ++ Library/stm32f10x_spi.h | 487 + Library/stm32f10x_tim.c | 2890 ++++++ Library/stm32f10x_tim.h | 1164 +++ Library/stm32f10x_usart.c | 1058 +++ Library/stm32f10x_usart.h | 412 + Library/stm32f10x_wwdg.c | 224 + Library/stm32f10x_wwdg.h | 115 + Project.uvguix.Admin | 1828 ++++ Project.uvguix.yzfh | 3609 +++++++ Project.uvoptx | 1076 +++ Project.uvprojx | 761 ++ QT/.gitignore | 59 + QT/CMakeLists.txt | 145 + QT/LICENSE | 21 + QT/README.md | 517 + QT/android/gradle.properties | 2 + QT/android/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 9022 bytes QT/android/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 4737 bytes QT/android/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 14035 bytes QT/android/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 27543 bytes QT/android/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 44797 bytes QT/assets/favicon-128x128.png | Bin 0 -> 19939 bytes QT/assets/favicon-16x16.png | Bin 0 -> 627 bytes QT/assets/favicon-192x192.png | Bin 0 -> 40269 bytes QT/assets/favicon-256x256.png | Bin 0 -> 69006 bytes QT/assets/favicon-32x32.png | Bin 0 -> 1887 bytes QT/assets/favicon-48x48.png | Bin 0 -> 3774 bytes QT/assets/favicon-64x64.png | Bin 0 -> 6105 bytes QT/assets/favicon.ico | Bin 0 -> 101440 bytes QT/cmake/app_icon.rc.in | 1 + QT/cmake/rewrite_qt.desktop.in | 7 + QT/main.cpp | 63 + QT/qml/Main.qml | 2945 ++++++ QT/src/ApiClient.cpp | 673 ++ QT/src/ApiClient.h | 75 + QT/src/AppController.cpp | 806 ++ QT/src/AppController.h | 155 + QT/src/AttendanceTypes.h | 59 + QT/src/CryptoUtils.cpp | 48 + QT/src/CryptoUtils.h | 12 + QT/src/FaceListModel.cpp | 85 + QT/src/FaceListModel.h | 47 + QT/src/MappingListModel.cpp | 132 + QT/src/MappingListModel.h | 48 + QT/src/RecordListModel.cpp | 59 + QT/src/RecordListModel.h | 53 + QT/src/StatisticsListModel.cpp | 53 + QT/src/StatisticsListModel.h | 48 + QT/src/TimeSlotListModel.cpp | 146 + QT/src/TimeSlotListModel.h | 48 + QT/src/crypto/tiny_aes.hpp | 217 + Start/core_cm3.c | 784 ++ Start/core_cm3.h | 1818 ++++ Start/startup_stm32f10x_cl.s | 368 + Start/startup_stm32f10x_hd.s | 358 + Start/startup_stm32f10x_hd_vl.s | 346 + Start/startup_stm32f10x_ld.s | 297 + Start/startup_stm32f10x_ld_vl.s | 304 + Start/startup_stm32f10x_md.s | 307 + Start/startup_stm32f10x_md_vl.s | 315 + Start/startup_stm32f10x_xl.s | 358 + Start/stm32f10x.h | 8336 +++++++++++++++++ Start/system_stm32f10x.c | 1094 +++ Start/system_stm32f10x.h | 98 + System/Debug.c | 91 + System/Debug.h | 29 + System/Delay.c | 60 + System/Delay.h | 16 + User/main.c | 925 ++ User/stm32f10x_conf.h | 77 + User/stm32f10x_it.c | 55 + User/stm32f10x_it.h | 44 + demo_DS1302.md | 172 + docs/00_项目总文档.md | 50 + docs/01_STM32固件端文档.md | 66 + docs/02_K210识别端文档.md | 75 + docs/03_服务端文档.md | 122 + docs/04_Qt管理端文档.md | 628 ++ docs/05_项目审查问题清单.md | 142 + docs/06_后端接口Windows测试命令.md | 329 + docs/07_后续优化路线.md | 272 + image/image-20260206145924158.png | Bin 0 -> 123809 bytes k210/main.py | 1727 ++++ k210/view_attendance.py | 50 + keilkill.bat | 27 + server/server_encrypted.cpp | 2558 +++++ server/tiny_aes.hpp | 291 + 连接图.md | 22 + 158 files changed, 67957 insertions(+) create mode 100644 .gitignore create mode 100644 DS1302时序.md create mode 100644 DebugConfig/Target_1_STM32F103C8_1.0.0.dbgconf create mode 100644 EventRecorderStub.scvd create mode 100644 Hardware/Attendance.c create mode 100644 Hardware/Attendance.h create mode 100644 Hardware/Buzzer_LED.c create mode 100644 Hardware/Buzzer_LED.h create mode 100644 Hardware/Crypto.c create mode 100644 Hardware/Crypto.h create mode 100644 Hardware/DS1302.c create mode 100644 Hardware/DS1302.h create mode 100644 Hardware/K210_USART.c create mode 100644 Hardware/K210_USART.h create mode 100644 Hardware/LightSensor.c create mode 100644 Hardware/LightSensor.h create mode 100644 Hardware/OLED.c create mode 100644 Hardware/OLED.h create mode 100644 Hardware/OLED_Font.h create mode 100644 Hardware/Serial.c create mode 100644 Hardware/Serial.h create mode 100644 Hardware/aes.c create mode 100644 Hardware/aes.h create mode 100644 Hardware/aes_fixed.c create mode 100644 Hardware/aes_fixed.h create mode 100644 Hardware/base64.c create mode 100644 Hardware/base64.h create mode 100644 Hardware/esp8266.c create mode 100644 Hardware/esp8266.h create mode 100644 Hardware/esp8266_new.c create mode 100644 Hardware/esp8266_new.h create mode 100644 Library/misc.c create mode 100644 Library/misc.h create mode 100644 Library/stm32f10x_adc.c create mode 100644 Library/stm32f10x_adc.h create mode 100644 Library/stm32f10x_bkp.c create mode 100644 Library/stm32f10x_bkp.h create mode 100644 Library/stm32f10x_can.c create mode 100644 Library/stm32f10x_can.h create mode 100644 Library/stm32f10x_cec.c create mode 100644 Library/stm32f10x_cec.h create mode 100644 Library/stm32f10x_crc.c create mode 100644 Library/stm32f10x_crc.h create mode 100644 Library/stm32f10x_dac.c create mode 100644 Library/stm32f10x_dac.h create mode 100644 Library/stm32f10x_dbgmcu.c create mode 100644 Library/stm32f10x_dbgmcu.h create mode 100644 Library/stm32f10x_dma.c create mode 100644 Library/stm32f10x_dma.h create mode 100644 Library/stm32f10x_exti.c create mode 100644 Library/stm32f10x_exti.h create mode 100644 Library/stm32f10x_flash.c create mode 100644 Library/stm32f10x_flash.h create mode 100644 Library/stm32f10x_fsmc.c create mode 100644 Library/stm32f10x_fsmc.h create mode 100644 Library/stm32f10x_gpio.c create mode 100644 Library/stm32f10x_gpio.h create mode 100644 Library/stm32f10x_i2c.c create mode 100644 Library/stm32f10x_i2c.h create mode 100644 Library/stm32f10x_iwdg.c create mode 100644 Library/stm32f10x_iwdg.h create mode 100644 Library/stm32f10x_pwr.c create mode 100644 Library/stm32f10x_pwr.h create mode 100644 Library/stm32f10x_rcc.c create mode 100644 Library/stm32f10x_rcc.h create mode 100644 Library/stm32f10x_rtc.c create mode 100644 Library/stm32f10x_rtc.h create mode 100644 Library/stm32f10x_sdio.c create mode 100644 Library/stm32f10x_sdio.h create mode 100644 Library/stm32f10x_spi.c create mode 100644 Library/stm32f10x_spi.h create mode 100644 Library/stm32f10x_tim.c create mode 100644 Library/stm32f10x_tim.h create mode 100644 Library/stm32f10x_usart.c create mode 100644 Library/stm32f10x_usart.h create mode 100644 Library/stm32f10x_wwdg.c create mode 100644 Library/stm32f10x_wwdg.h create mode 100644 Project.uvguix.Admin create mode 100644 Project.uvguix.yzfh create mode 100644 Project.uvoptx create mode 100644 Project.uvprojx create mode 100644 QT/.gitignore create mode 100644 QT/CMakeLists.txt create mode 100644 QT/LICENSE create mode 100644 QT/README.md create mode 100644 QT/android/gradle.properties create mode 100644 QT/android/res/mipmap-hdpi/ic_launcher.png create mode 100644 QT/android/res/mipmap-mdpi/ic_launcher.png create mode 100644 QT/android/res/mipmap-xhdpi/ic_launcher.png create mode 100644 QT/android/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 QT/android/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 QT/assets/favicon-128x128.png create mode 100644 QT/assets/favicon-16x16.png create mode 100644 QT/assets/favicon-192x192.png create mode 100644 QT/assets/favicon-256x256.png create mode 100644 QT/assets/favicon-32x32.png create mode 100644 QT/assets/favicon-48x48.png create mode 100644 QT/assets/favicon-64x64.png create mode 100644 QT/assets/favicon.ico create mode 100644 QT/cmake/app_icon.rc.in create mode 100644 QT/cmake/rewrite_qt.desktop.in create mode 100644 QT/main.cpp create mode 100644 QT/qml/Main.qml create mode 100644 QT/src/ApiClient.cpp create mode 100644 QT/src/ApiClient.h create mode 100644 QT/src/AppController.cpp create mode 100644 QT/src/AppController.h create mode 100644 QT/src/AttendanceTypes.h create mode 100644 QT/src/CryptoUtils.cpp create mode 100644 QT/src/CryptoUtils.h create mode 100644 QT/src/FaceListModel.cpp create mode 100644 QT/src/FaceListModel.h create mode 100644 QT/src/MappingListModel.cpp create mode 100644 QT/src/MappingListModel.h create mode 100644 QT/src/RecordListModel.cpp create mode 100644 QT/src/RecordListModel.h create mode 100644 QT/src/StatisticsListModel.cpp create mode 100644 QT/src/StatisticsListModel.h create mode 100644 QT/src/TimeSlotListModel.cpp create mode 100644 QT/src/TimeSlotListModel.h create mode 100644 QT/src/crypto/tiny_aes.hpp create mode 100644 Start/core_cm3.c create mode 100644 Start/core_cm3.h create mode 100644 Start/startup_stm32f10x_cl.s create mode 100644 Start/startup_stm32f10x_hd.s create mode 100644 Start/startup_stm32f10x_hd_vl.s create mode 100644 Start/startup_stm32f10x_ld.s create mode 100644 Start/startup_stm32f10x_ld_vl.s create mode 100644 Start/startup_stm32f10x_md.s create mode 100644 Start/startup_stm32f10x_md_vl.s create mode 100644 Start/startup_stm32f10x_xl.s create mode 100644 Start/stm32f10x.h create mode 100644 Start/system_stm32f10x.c create mode 100644 Start/system_stm32f10x.h create mode 100644 System/Debug.c create mode 100644 System/Debug.h create mode 100644 System/Delay.c create mode 100644 System/Delay.h create mode 100644 User/main.c create mode 100644 User/stm32f10x_conf.h create mode 100644 User/stm32f10x_it.c create mode 100644 User/stm32f10x_it.h create mode 100644 demo_DS1302.md create mode 100644 docs/00_项目总文档.md create mode 100644 docs/01_STM32固件端文档.md create mode 100644 docs/02_K210识别端文档.md create mode 100644 docs/03_服务端文档.md create mode 100644 docs/04_Qt管理端文档.md create mode 100644 docs/05_项目审查问题清单.md create mode 100644 docs/06_后端接口Windows测试命令.md create mode 100644 docs/07_后续优化路线.md create mode 100644 image/image-20260206145924158.png create mode 100644 k210/main.py create mode 100644 k210/view_attendance.py create mode 100644 keilkill.bat create mode 100644 server/server_encrypted.cpp create mode 100644 server/tiny_aes.hpp create mode 100644 连接图.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c0e5878 --- /dev/null +++ b/.gitignore @@ -0,0 +1,44 @@ +# Local IDE and assistant state +.claude/ +.vscode/ +.qt_git_backup/ + +# Build outputs +Objects/ +Listings/ +QT/build/ +QT/dist/ +QT/.qtcreator/ + +# Generated binaries and intermediates +*.o +*.obj +*.d +*.crf +*.axf +*.elf +*.bin +*.hex +*.map +*.lnp +*.htm +*.build_log.htm +*.exe +*.dll +*.pdb + +# Runtime data +attendance.db +attendance.log +faces/ + +# OS/editor files +.DS_Store +Thumbs.db +desktop.ini +*.tmp +*.bak +*.swp +*~ +__pycache__/ +*.pyc diff --git a/DS1302时序.md b/DS1302时序.md new file mode 100644 index 0000000..b064b6f --- /dev/null +++ b/DS1302时序.md @@ -0,0 +1,89 @@ +好的,这张图片详细说明了DS1302实时时钟(RTC)模块的工作原理、读写时序和寄存器定义。下面我将分部分进行文字描述。 + +### 1. 总体概述 +这张图片是DS1302芯片的技术资料片段,主要包含两部分: +* **读/写时序图 (Timing Diagram)**:展示了微控制器如何通过三线串行接口与DS1302进行单字节的读取和写入操作。 +* **寄存器地址/定义表 (Register Map)**:列出了存储时间、日期等信息的各个寄存器的地址、位定义和取值范围。 + +--- + +### 2. 工作原理与读/写时序 + +这部分解释了DS1302的通信协议。 + +**核心通信方式:** + +* **三线串行接口**:DS1302使用三根信号线与微控制器(如单片机)通信: + 1. **RST (Reset/Enable)**:复位/使能引脚。当RST为高电平时,DS1302被使能,可以进行通信。通信结束后,RST应恢复为低电平。 + 2. **SCLK (Serial Clock)**:串行时钟引脚。由微控制器产生,用于同步数据的传输,在每个时钟脉冲的**上升沿**采样数据。 + 3. **I/O (Input/Output)**:双向数据引脚。数据的输入和输出都通过这根线完成。 + +* **数据格式**:时间、日期数据均采用**BCD码 (Binary-Cododed Decimal)** 格式存储。简单来说,一个字节(8位)的高4位表示十位上的数字,低4位表示个位上的数字。例如,数字59在BCD码中表示为 `0101 1001`。 + +**时序图详解:** + +#### a. SINGLE BYTE READ (单字节读取) + +此过程用于从DS1302的某个寄存器中读取一个字节的数据。 +1. **启动通信**:微控制器将 **RST** 引脚拉高,使能DS1302。 +2. **发送命令字节**:微控制器通过 **I/O** 线发送一个8位的命令字节。这个命令字节在8个 **SCLK** 时钟脉冲的驱动下逐位传输。 + * 命令字节的格式为 `R/W A0 A1 A2 A3 A4 R/C 1`。 + * **R/W (Bit 7)**:读写控制位。对于读取操作,该位必须为 **1**。 + * **A0-A4 (Bit 1-5)**:寄存器地址位。 + * **R/C (Bit 6)**:寄存器类型选择位。选择时钟/日历寄存器或RAM寄存器。 + * **Bit 0**:必须为 **1**。 + * 综合来看,一个读取命令的地址字节,其最高位和最低位都必须是1。例如,读取秒寄存器(地址81h)的命令字节是 `1000 0001`。 +3. **接收数据字节**:在发送完命令字节后的接下来8个 **SCLK** 时钟脉冲期间,DS1302会通过 **I/O** 线将其寻址寄存器中的数据逐位发送给微控制器。此时,I/O线的控制权从微控制器转移到DS1302。 +4. **结束通信**:数据接收完毕后,微控制器将 **RST** 引脚拉低,结束本次通信。 + +#### b. SINGLE BYTE WRITE (单字节写入) + +此过程用于向DS1302的某个寄存器写入一个字节的数据。 +1. **启动通信**:微控制器将 **RST** 引脚拉高。 +2. **发送命令字节**:微控制器通过 **I/O** 线发送一个8位的命令字节。 + * **R/W (Bit 7)**:读写控制位。对于写入操作,该位必须为 **0**。 + * 其余地址位(A0-A4, R/C)用于选择要写入的目标寄存器。 + * **Bit 0**:必须为 **0**。 + * 综合来看,一个写入命令的地址字节,其最高位和最低位都必须是0。例如,写入秒寄存器(地址80h)的命令字节是 `1000 0000`。 +3. **发送数据字节**:在发送完命令字节后的接下来8个 **SCLK** 时钟脉冲期间,微控制器继续通过 **I/O** 线将要写入的数据(D0-D7)逐位发送给DS1302。 +4. **结束通信**:数据发送完毕后,微控制器将 **RST** 引脚拉低,结束本次通信。 + +--- + +### 3. 寄存器地址/定义 + +这张表详细定义了DS1302内部各个寄存器的功能。 + +* **READ / WRITE**:分别列出了读取和写入某个功能寄存器时需要使用的十六进制地址。可以看出,同一功能的写地址通常是读地址减1(例如秒寄存器:读地址`81h`,写地址`80h`)。这实际上是因为命令字节的最低位(Bit 0)不同。 +* **BIT 7 - BIT 0**:描述了一个字节内每一位(或某几位)的含义。 +* **RANGE**:表示该寄存器存储数值的有效范围。 + +**主要寄存器解析:** + +* **秒 (Seconds, 80h/81h)**: + * `BIT 7`: **CH (Clock Halt)**。当此位为1时,时钟振荡器停止工作,时钟暂停,可以降低功耗。设为0时正常工作。 + * `BIT 6-4`: 秒的十位 (10 Seconds)。 + * `BIT 3-0`: 秒的个位 (Seconds)。 + * 范围:00-59。 + +* **分 (Minutes, 82h/83h)**: + * `BIT 6-4`: 分的十位 (10 Minutes)。 + * `BIT 3-0`: 分的个位 (Minutes)。 + * 范围:00-59。 + +* **时 (Hour, 84h/85h)**: + * `BIT 7`: **12/24** 模式选择。为1时是12小时制,为0时是24小时制。 + * **12小时制下**:`BIT 5` 为 **AM/PM** 标志(1=PM, 0=AM),`BIT 4` 是小时的十位,`BIT 3-0` 是小时的个位。 + * **24小时制下**:`BIT 5-4` 是小时的十位,`BIT 3-0` 是小时的个位。 + * 范围:1-12 (12小时制) 或 0-23 (24小时制)。 + +* **日 (Date, 86h/87h)** / **月 (Month, 88h/89h)** / **星期 (Day, 8Ah/8Bh)** / **年 (Year, 8Ch/8Dh)**:这些寄存器同样采用BCD码格式存储对应的日期信息。 + +* **写保护 (Write Protect, 8Eh/8Fh)**: + * `BIT 7`: **WP (Write Protect)**。当此位为1时,所有时间、日期寄存器被保护,无法写入,防止数据被意外修改。要更新时间,必须先将此位清零。 + +* **涓流充电 (Trickle Charge, 90h/91h)**:此寄存器用于配置对备用电池或超级电容的涓流充电功能,图中只列出了其地址,具体位定义不完整。 + +**总结**,这张图是DS1302芯片的核心使用说明,它清晰地定义了如何通过一个精确的时序协议来读写芯片内的寄存器,从而实现对实时时钟的设置和读取。 + +![image-20260206145924158](image/image-20260206145924158.png) \ No newline at end of file diff --git a/DebugConfig/Target_1_STM32F103C8_1.0.0.dbgconf b/DebugConfig/Target_1_STM32F103C8_1.0.0.dbgconf new file mode 100644 index 0000000..90dabd8 --- /dev/null +++ b/DebugConfig/Target_1_STM32F103C8_1.0.0.dbgconf @@ -0,0 +1,97 @@ +// <<< Use Configuration Wizard in Context Menu >>> +// Debug MCU Configuration +// DBG_SLEEP +// Debug Sleep Mode +// 0: (FCLK=On, HCLK=Off) FCLK is clocked by the system clock as previously configured by the software while HCLK is disabled +// 1: (FCLK=On, HCLK=On) HCLK is fed by the same clock that is provided to FCLK +// DBG_STOP +// Debug Stop Mode +// 0: (FCLK=Off, HCLK=Off) Clock controller disables all clocks +// 1: (FCLK=On, HCLK=On) FCLK and HCLK are provided by the internal RC oscillator which remains active +// DBG_STANDBY +// Debug Standby Mode +// 0: (FCLK=Off, HCLK=Off) The whole digital part is unpowered. +// 1: (FCLK=On, HCLK=On) Digital part is powered and FCLK and HCLK are provided by the internal RC oscillator which remains active +// DBG_IWDG_STOP +// Debug independent watchdog stopped when core is halted +// 0: The watchdog counter clock continues even if the core is halted +// 1: The watchdog counter clock is stopped when the core is halted +// DBG_WWDG_STOP +// Debug window watchdog stopped when core is halted +// 0: The window watchdog counter clock continues even if the core is halted +// 1: The window watchdog counter clock is stopped when the core is halted +// DBG_TIM1_STOP +// Timer 1 counter stopped when core is halted +// 0: The clock of the involved Timer Counter is fed even if the core is halted +// 1: The clock of the involved Timer counter is stopped when the core is halted +// DBG_TIM2_STOP +// Timer 2 counter stopped when core is halted +// 0: The clock of the involved Timer Counter is fed even if the core is halted +// 1: The clock of the involved Timer counter is stopped when the core is halted +// DBG_TIM3_STOP +// Timer 3 counter stopped when core is halted +// 0: The clock of the involved Timer Counter is fed even if the core is halted +// 1: The clock of the involved Timer counter is stopped when the core is halted +// DBG_TIM4_STOP +// Timer 4 counter stopped when core is halted +// 0: The clock of the involved Timer Counter is fed even if the core is halted +// 1: The clock of the involved Timer counter is stopped when the core is halted +// DBG_CAN1_STOP +// Debug CAN1 stopped when Core is halted +// 0: Same behavior as in normal mode +// 1: CAN1 receive registers are frozen +// DBG_I2C1_SMBUS_TIMEOUT +// I2C1 SMBUS timeout mode stopped when Core is halted +// 0: Same behavior as in normal mode +// 1: The SMBUS timeout is frozen +// DBG_I2C2_SMBUS_TIMEOUT +// I2C2 SMBUS timeout mode stopped when Core is halted +// 0: Same behavior as in normal mode +// 1: The SMBUS timeout is frozen +// DBG_TIM8_STOP +// Timer 8 counter stopped when core is halted +// 0: The clock of the involved timer counter is fed even if the core is halted, and the outputs behave normally. +// 1: The clock of the involved timer counter is stopped when the core is halted, and the outputs are disabled (as if there were an emergency stop in response to a break event). +// DBG_TIM5_STOP +// Timer 5 counter stopped when core is halted +// 0: The clock of the involved timer counter is fed even if the core is halted, and the outputs behave normally. +// 1: The clock of the involved timer counter is stopped when the core is halted, and the outputs are disabled (as if there were an emergency stop in response to a break event). +// DBG_TIM6_STOP +// Timer 6 counter stopped when core is halted +// 0: The clock of the involved timer counter is fed even if the core is halted, and the outputs behave normally. +// 1: The clock of the involved timer counter is stopped when the core is halted, and the outputs are disabled (as if there were an emergency stop in response to a break event). +// DBG_TIM7_STOP +// Timer 7 counter stopped when core is halted +// 0: The clock of the involved timer counter is fed even if the core is halted, and the outputs behave normally. +// 1: The clock of the involved timer counter is stopped when the core is halted, and the outputs are disabled (as if there were an emergency stop in response to a break event). +// DBG_CAN2_STOP +// Debug CAN2 stopped when Core is halted +// 0: Same behavior as in normal mode +// 1: CAN2 receive registers are frozen +// DBG_TIM12_STOP +// Timer 12 counter stopped when core is halted +// 0: The clock of the involved timer counter is fed even if the core is halted, and the outputs behave normally. +// 1: The clock of the involved timer counter is stopped when the core is halted, and the outputs are disabled (as if there were an emergency stop in response to a break event). +// DBG_TIM13_STOP +// Timer 13 counter stopped when core is halted +// 0: The clock of the involved timer counter is fed even if the core is halted, and the outputs behave normally. +// 1: The clock of the involved timer counter is stopped when the core is halted, and the outputs are disabled (as if there were an emergency stop in response to a break event). +// DBG_TIM14_STOP +// Timer 14 counter stopped when core is halted +// 0: The clock of the involved timer counter is fed even if the core is halted, and the outputs behave normally. +// 1: The clock of the involved timer counter is stopped when the core is halted, and the outputs are disabled (as if there were an emergency stop in response to a break event). +// DBG_TIM9_STOP +// Timer 9 counter stopped when core is halted +// 0: The clock of the involved timer counter is fed even if the core is halted, and the outputs behave normally. +// 1: The clock of the involved timer counter is stopped when the core is halted, and the outputs are disabled (as if there were an emergency stop in response to a break event). +// DBG_TIM10_STOP +// Timer 10 counter stopped when core is halted +// 0: The clock of the involved timer counter is fed even if the core is halted, and the outputs behave normally. +// 1: The clock of the involved timer counter is stopped when the core is halted, and the outputs are disabled (as if there were an emergency stop in response to a break event). +// DBG_TIM11_STOP +// Timer 11 counter stopped when core is halted +// 0: The clock of the involved timer counter is fed even if the core is halted, and the outputs behave normally. +// 1: The clock of the involved timer counter is stopped when the core is halted, and the outputs are disabled (as if there were an emergency stop in response to a break event). +// +DbgMCU_CR = 0x00000007; +// <<< end of configuration section >>> \ No newline at end of file diff --git a/EventRecorderStub.scvd b/EventRecorderStub.scvd new file mode 100644 index 0000000..2956b29 --- /dev/null +++ b/EventRecorderStub.scvd @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Hardware/Attendance.c b/Hardware/Attendance.c new file mode 100644 index 0000000..0dd1d4c --- /dev/null +++ b/Hardware/Attendance.c @@ -0,0 +1,703 @@ +#include "Attendance.h" +#include "Delay.h" +#include "Debug.h" +#include "esp8266.h" // ✨ 添加ESP8266头文件 +#include +#include // ← 添加atoi函数声明 + +// 配置参数 +#define MAX_ATTENDANCE_RECORDS 100 // 最大记录数量 +#define MIN_CONFIDENCE_THRESHOLD 0.75 // 最小置信度阈值 +#define MAX_TIME_SLOT_COUNT 10 // 最大时间段数量 +#define MAX_CACHED_IDS 50 // 最大缓存学号数量(从服务器下载) + +// 时间段配置(动态从服务器更新) +static TimeSlot time_slots[MAX_TIME_SLOT_COUNT]; +static uint8_t time_slot_count = 0; // 当前有效时间段数量 + +// 今日已签到学号缓存(从服务器下载) +static char cached_student_ids[MAX_CACHED_IDS][20]; +static uint8_t cached_id_count = 0; + +// 默认时间段配置(在服务器配置下载失败时使用) +static const TimeSlot default_time_slots[] = { + {1, 8, 0, 9, 30, "Morning Check-in"}, // 上午签到 08:00-09:30 + {1, 12, 0, 13, 0, "Noon Check-out"}, // 中午签退 12:00-13:00 + {1, 14, 0, 15, 0, "Afternoon Check-in"}, // 下午签到 14:00-15:00 + {1, 17, 0, 18, 30, "Evening Check-out"}, // 晚上签退 17:00-18:30 +}; +#define DEFAULT_TIME_SLOT_COUNT 4 + +// 当前时间(由外部更新,如果有RTC则从RTC读取) +static uint8_t current_hour = 8; +static uint8_t current_minute = 30; + +// 内部存储 +static AttendanceRecord attendance_records[MAX_ATTENDANCE_RECORDS]; +static uint16_t record_count = 0; +static uint32_t total_attendance_count = 0; // 总考勤人次 + +/** + * @brief 初始化考勤模块 + */ +void Attendance_Init(void) +{ + record_count = 0; + total_attendance_count = 0; + current_hour = 8; + current_minute = 0; + memset(attendance_records, 0, sizeof(attendance_records)); + + // 初始化为默认时间段配置 + memcpy(time_slots, default_time_slots, sizeof(default_time_slots)); + time_slot_count = DEFAULT_TIME_SLOT_COUNT; + + // 清空缓存 + cached_id_count = 0; + memset(cached_student_ids, 0, sizeof(cached_student_ids)); + + DEBUG_INFO("[Attendance] Initialized with time slot mode"); +} + +/** + * @brief 清空今日签到缓存 + */ +void Attendance_ClearCache(void) +{ + cached_id_count = 0; + memset(cached_student_ids, 0, sizeof(cached_student_ids)); + DEBUG_INFO("[Attendance] Cache cleared"); +} + +/** + * @brief 添加学号到缓存 + */ +void Attendance_AddToCache(const char* student_id) +{ + if (cached_id_count >= MAX_CACHED_IDS) { + DEBUG_ERROR("[Attendance] Cache full, cannot add more IDs"); + return; + } + + // 检查是否已存在 + for (uint8_t i = 0; i < cached_id_count; i++) { + if (strcmp(cached_student_ids[i], student_id) == 0) { + return; // 已存在,不重复添加 + } + } + + strncpy(cached_student_ids[cached_id_count], student_id, 19); + cached_student_ids[cached_id_count][19] = '\0'; + cached_id_count++; + + DEBUG_PRINT("[Attendance] Added to cache: %s (total: %d)\r\n", student_id, cached_id_count); +} + +/** + * @brief 在本地缓存中查重 + * @retval 1=在缓存中找到(重复), 0=未找到 + */ +uint8_t Attendance_IsDuplicateInCache(const char* student_id) +{ + for (uint8_t i = 0; i < cached_id_count; i++) { + if (strcmp(cached_student_ids[i], student_id) == 0) { + DEBUG_PRINT("[Attendance] Found in cache: %s\r\n", student_id); + return 1; + } + } + return 0; +} + +/** + * @brief 从服务器加载今日已签到记录到缓存 + * @retval 加载的记录数量 + */ +uint8_t Attendance_LoadTodayRecordsFromServer(void) +{ + char slot_start[8]; + char slot_end[8]; + char records_buffer[512]; + + // 获取当前时段时间 + Attendance_GetCurrentSlotTime(slot_start, slot_end); + + DEBUG_PRINT("[Attendance] Loading today's records for slot %s-%s\r\n", slot_start, slot_end); + + // 清空旧缓存 + Attendance_ClearCache(); + + // 从服务器下载 + uint8_t count = ESP8266_DownloadTodayRecords(slot_start, slot_end, records_buffer, sizeof(records_buffer)); + + if (count == 0) { + DEBUG_INFO("[Attendance] No records to load or download failed"); + return 0; + } + + // 解析学号列表 (格式: "1","2","3") + char* ptr = records_buffer; + char student_id[20]; + uint8_t loaded = 0; + + while (*ptr != '\0' && loaded < MAX_CACHED_IDS) { + // 跳过引号和逗号 + while (*ptr == '"' || *ptr == ',' || *ptr == ' ') ptr++; + + if (*ptr == '\0') break; + + // 提取学号 + char* id_start = ptr; + while (*ptr != '"' && *ptr != ',' && *ptr != '\0') ptr++; + + uint8_t len = ptr - id_start; + if (len > 0 && len < 20) { + strncpy(student_id, id_start, len); + student_id[len] = '\0'; + Attendance_AddToCache(student_id); + loaded++; + } + } + + DEBUG_PRINT("[Attendance] Loaded %d records from server\r\n", loaded); + return loaded; +} + +/** + * @brief 更新时间段配置(从服务器下载后调用) + * @param slots 新的时间段配置数组 + * @param count 时间段数量 + */ +void Attendance_UpdateTimeSlots(TimeSlot* slots, uint8_t count) +{ + if (count > MAX_TIME_SLOT_COUNT) { + DEBUG_PRINT("[Attendance] Too many time slots: %d (max: %d)\r\n", count, MAX_TIME_SLOT_COUNT); + return; + } + + // 更新时间段配置 + memcpy(time_slots, slots, count * sizeof(TimeSlot)); + time_slot_count = count; + + DEBUG_PRINT("[Attendance] Time slots updated: %d slots loaded\r\n", count); + + // 调试:打印所有时间段 + for (uint8_t i = 0; i < time_slot_count; i++) { + DEBUG_PRINT("[Attendance] Slot %d: %s (%02d:%02d-%02d:%02d) %s\r\n", + i, time_slots[i].name, + time_slots[i].start_hour, time_slots[i].start_minute, + time_slots[i].end_hour, time_slots[i].end_minute, + time_slots[i].enabled ? "ENABLED" : "DISABLED"); + } +} + +/** + * @brief 从JSON字符串解析时间段配置 + * @param json_str JSON字符串(格式:{"time_slots":[{"enabled":true,"start_time":"08:00",...}]}) + * @retval 成功解析的时间段数量 + */ +uint8_t Attendance_ParseTimeSlotsJSON(const char* json_str) +{ + TimeSlot temp_slots[MAX_TIME_SLOT_COUNT]; + uint8_t slot_count = 0; + + DEBUG_INFO("[Attendance] Parsing time slots JSON..."); + DEBUG_PRINT("[Attendance] JSON: %s\r\n", json_str); + + // 查找 "time_slots" 数组 + const char* ptr = strstr(json_str, "\"time_slots\""); + if (ptr == NULL) { + DEBUG_ERROR("[Attendance] Invalid JSON: no 'time_slots' field found"); + return 0; + } + + // 查找数组开始 '[' + ptr = strchr(ptr, '['); + if (ptr == NULL) { + DEBUG_ERROR("[Attendance] Invalid JSON: no '[' found"); + return 0; + } + ptr++; // 跳过 '[' + + while (*ptr == ' ' || *ptr == '\n' || *ptr == '\r' || *ptr == '\t') ptr++; + if (*ptr == ']') { + DEBUG_INFO("[Attendance] Empty time slot config, keeping current slots"); + return time_slot_count; + } + + // 解析每个时间段对象 + while (*ptr != '\0' && *ptr != ']' && slot_count < MAX_TIME_SLOT_COUNT) + { + // 跳过空格、换行、逗号 + while (*ptr == ' ' || *ptr == ',' || *ptr == '\n' || *ptr == '\r' || *ptr == '\t') ptr++; + + // 查找对象开始 + if (*ptr != '{') break; + ptr++; // 跳过 '{' + + // 初始化当前时间段 + temp_slots[slot_count].enabled = 1; + temp_slots[slot_count].start_hour = 0; + temp_slots[slot_count].start_minute = 0; + temp_slots[slot_count].end_hour = 0; + temp_slots[slot_count].end_minute = 0; + strcpy(temp_slots[slot_count].name, "Unknown"); + + // 解析对象字段 + while (*ptr != '\0' && *ptr != '}') + { + // 跳过空格、换行、逗号 + while (*ptr == ' ' || *ptr == ',' || *ptr == '\n' || *ptr == '\r' || *ptr == '\t') ptr++; + + // 跳过引号 + if (*ptr == '"') ptr++; + + // 解析字段名 + if (strncmp(ptr, "enabled", 7) == 0) { + ptr = strchr(ptr, ':'); + if (ptr) { + ptr++; + while (*ptr == ' ') ptr++; + // 处理 true/false 或 1/0 + temp_slots[slot_count].enabled = (*ptr == 't' || *ptr == '1') ? 1 : 0; + } + } + else if (strncmp(ptr, "start_time", 10) == 0) { + // 格式: "start_time": "08:30" + ptr = strchr(ptr, ':'); + if (ptr) { + ptr++; + while (*ptr == ' ' || *ptr == '"') ptr++; + // 解析 "HH:MM" + temp_slots[slot_count].start_hour = (ptr[0] - '0') * 10 + (ptr[1] - '0'); + temp_slots[slot_count].start_minute = (ptr[3] - '0') * 10 + (ptr[4] - '0'); + } + } + else if (strncmp(ptr, "end_time", 8) == 0) { + // 格式: "end_time": "09:30" + ptr = strchr(ptr, ':'); + if (ptr) { + ptr++; + while (*ptr == ' ' || *ptr == '"') ptr++; + // 解析 "HH:MM" + temp_slots[slot_count].end_hour = (ptr[0] - '0') * 10 + (ptr[1] - '0'); + temp_slots[slot_count].end_minute = (ptr[3] - '0') * 10 + (ptr[4] - '0'); + } + } + else if (strncmp(ptr, "name", 4) == 0) { + ptr = strchr(ptr, ':'); + if (ptr) { + ptr++; + while (*ptr == ' ' || *ptr == '"') ptr++; + // 提取名称(直到遇到引号) + const char* name_start = ptr; + while (*ptr != '"' && *ptr != '\0') ptr++; + int len = ptr - name_start; + if (len > 19) len = 19; + strncpy(temp_slots[slot_count].name, name_start, len); + temp_slots[slot_count].name[len] = '\0'; + } + } + + // 移动到下一个字段或对象结束 + while (*ptr != '\0' && *ptr != ',' && *ptr != '}') ptr++; + if (*ptr == ',') ptr++; + } + + if (*ptr == '}') ptr++; // 跳过 '}' + + DEBUG_PRINT("[Attendance] Parsed slot %d: %s (%02d:%02d-%02d:%02d) %s\r\n", + slot_count, temp_slots[slot_count].name, + temp_slots[slot_count].start_hour, temp_slots[slot_count].start_minute, + temp_slots[slot_count].end_hour, temp_slots[slot_count].end_minute, + temp_slots[slot_count].enabled ? "ENABLED" : "DISABLED"); + + slot_count++; + } + + DEBUG_PRINT("[Attendance] Parsed %d time slots\r\n", slot_count); + + // 应用解析结果 + if (slot_count > 0) { + Attendance_UpdateTimeSlots(temp_slots, slot_count); + return slot_count; + } + + DEBUG_ERROR("[Attendance] Failed to parse any time slots"); + return 0; +} + +/** + * @brief 设置当前时间(由外部定期调用更新) + * @param hour 小时 (0-23) + * @param minute 分钟 (0-59) + */ +void Attendance_SetCurrentTime(uint8_t hour, uint8_t minute) +{ + current_hour = hour; + current_minute = minute; +} + +/** + * @brief 获取当前所处的考勤时段 + * @retval 时段编号 (0-N),如果不在任何时段内则返回 -1 + */ +int8_t Attendance_GetCurrentTimeSlot(void) +{ + for (uint8_t i = 0; i < time_slot_count; i++) + { + // 跳过禁用的时间段 + if (!time_slots[i].enabled) { + continue; + } + + uint16_t current_minutes = current_hour * 60 + current_minute; + uint16_t start_minutes = time_slots[i].start_hour * 60 + time_slots[i].start_minute; + uint16_t end_minutes = time_slots[i].end_hour * 60 + time_slots[i].end_minute; + + if (current_minutes >= start_minutes && current_minutes <= end_minutes) + { + return i; // 返回时段编号 + } + } + + return -1; // 不在任何考勤时段内 +} + +/** + * @brief 获取当前时段的开始和结束时间 + * @param start_time 输出:开始时间(格式"HH:MM") + * @param end_time 输出:结束时间(格式"HH:MM") + */ +void Attendance_GetCurrentSlotTime(char* start_time, char* end_time) +{ + int8_t current_slot = Attendance_GetCurrentTimeSlot(); + + if (current_slot >= 0 && current_slot < time_slot_count) { + sprintf(start_time, "%02d:%02d", + time_slots[current_slot].start_hour, + time_slots[current_slot].start_minute); + sprintf(end_time, "%02d:%02d", + time_slots[current_slot].end_hour, + time_slots[current_slot].end_minute); + } else { + // 不在任何时段,返回全天 + strcpy(start_time, "00:00"); + strcpy(end_time, "23:59"); + } +} + +/** + * @brief 检查学生是否在服务器端已签到(服务器端查重) + * @param student_id 学生学号 + * @retval 1=服务器显示已签到(重复), 0=未签到或查询失败 + */ +uint8_t Attendance_IsDuplicateOnServer(const char* student_id) +{ + char slot_start[8]; + char slot_end[8]; + + // 获取当前时段时间 + Attendance_GetCurrentSlotTime(slot_start, slot_end); + + DEBUG_PRINT("[Attendance] Checking server for duplicate: %s (%s-%s)\r\n", + student_id, slot_start, slot_end); + + // 调用ESP8266查询服务器(这个过程可能耗时,蜂鸣器状态由调用者控制) + return ESP8266_CheckDuplicate(student_id, slot_start, slot_end); +} + +/** + * @brief 检查是否在当前时段重复打卡(本地+服务器) + * @param student_id 学生学号 + * @retval 1=重复, 0=不重复 + */ +uint8_t Attendance_IsDuplicate(const char* student_id) +{ + int8_t current_slot = Attendance_GetCurrentTimeSlot(); + + if (current_slot < 0) { + return 0; // 不在考勤时段,不算重复 + } + + // 遍历现有记录,检查是否在当前时段已打卡 + for (uint16_t i = 0; i < record_count; i++) + { + // 如果找到相同学号且在相同时段 + if (strcmp(attendance_records[i].student_id, student_id) == 0 && + attendance_records[i].time_slot == current_slot) + { + return 1; // 本时段已打卡,重复 + } + } + + return 0; // 不重复 +} + +/** + * @brief 处理人脸识别结果并记录考勤 + * @param result 人脸识别结果 + * @retval 考勤状态 + */ +AttendanceStatus Attendance_ProcessFaceResult(FaceRecognitionResult* result) +{ + // 1. 检查识别是否成功 + if (result->success == 0) + { + return ATTENDANCE_UNKNOWN; + } + + // 2. 检查置信度 + if (result->confidence < MIN_CONFIDENCE_THRESHOLD) + { + return ATTENDANCE_LOW_CONFIDENCE; + } + + // 3. 检查是否在考勤时段内 + int8_t current_slot = Attendance_GetCurrentTimeSlot(); + if (current_slot < 0) + { + DEBUG_PRINT("[Attendance] Not in time slot (Current: %02d:%02d)\r\n", + current_hour, current_minute); + return ATTENDANCE_OUT_OF_TIME; + } + + DEBUG_PRINT("[Attendance] Current slot: %s (%02d:%02d)\r\n", + time_slots[current_slot].name, current_hour, current_minute); + + // 4. 检查是否在当前时段重复打卡(本地记录检查) + if (Attendance_IsDuplicate(result->student_id)) + { + DEBUG_PRINT("[Attendance] Local duplicate in slot: %s\r\n", time_slots[current_slot].name); + return ATTENDANCE_DUPLICATE; + } + + // 5. 检查缓存中是否已签到(从服务器下载的今日记录) + if (Attendance_IsDuplicateInCache(result->student_id)) + { + DEBUG_PRINT("[Attendance] Cache duplicate in slot: %s\r\n", time_slots[current_slot].name); + return ATTENDANCE_DUPLICATE; + } + + // 6. 添加新记录 + if (record_count < MAX_ATTENDANCE_RECORDS) + { + // 复制学号和姓名 + strncpy(attendance_records[record_count].student_id, result->student_id, 19); + attendance_records[record_count].student_id[19] = '\0'; + + strncpy(attendance_records[record_count].student_name, result->student_name, 31); + attendance_records[record_count].student_name[31] = '\0'; + + // 记录置信度 + attendance_records[record_count].confidence = result->confidence; + + // 记录时间戳和时段 + // 简化:使用系统运行时间戳(服务器会用接收时间替换) + attendance_records[record_count].timestamp = Get_Time_ms() / 1000; + attendance_records[record_count].time_slot = current_slot; + + // 初始化同步状态 + attendance_records[record_count].sync_status = SYNC_PENDING; + attendance_records[record_count].retry_count = 0; + attendance_records[record_count].last_retry_time = 0; + + record_count++; + total_attendance_count++; + + // 添加到缓存,防止重复签到 + Attendance_AddToCache(result->student_id); + + DEBUG_PRINT("[Attendance] Success! Slot=%s, Total=%d, Status=PENDING\r\n", + time_slots[current_slot].name, total_attendance_count); + + return ATTENDANCE_SUCCESS; + } + else + { + // 记录已满,覆盖最早的记录 + memmove(&attendance_records[0], &attendance_records[1], + sizeof(AttendanceRecord) * (MAX_ATTENDANCE_RECORDS - 1)); + record_count = MAX_ATTENDANCE_RECORDS - 1; + + // 在最后位置添加新记录 + strncpy(attendance_records[record_count].student_id, result->student_id, 19); + attendance_records[record_count].student_id[19] = '\0'; + strncpy(attendance_records[record_count].student_name, result->student_name, 31); + attendance_records[record_count].student_name[31] = '\0'; + attendance_records[record_count].confidence = result->confidence; + + // 简化:使用系统运行时间戳(服务器会用接收时间替换) + attendance_records[record_count].timestamp = Get_Time_ms() / 1000; + attendance_records[record_count].time_slot = current_slot; + attendance_records[record_count].sync_status = SYNC_PENDING; + attendance_records[record_count].retry_count = 0; + attendance_records[record_count].last_retry_time = 0; + + record_count++; + total_attendance_count++; + + return ATTENDANCE_SUCCESS; + } +} + +/** + * @brief 清空所有考勤记录 + */ +void Attendance_ClearRecords(void) +{ + record_count = 0; + memset(attendance_records, 0, sizeof(attendance_records)); + // 注意:不清空 total_attendance_count,保留历史统计 +} + +/** + * @brief 获取累计考勤总数 + */ +uint16_t Attendance_GetTotalCount(void) +{ + return total_attendance_count; +} + +/** + * @brief 获取当前缓存中的记录数 + */ +uint16_t Attendance_GetActiveCount(void) +{ + return record_count; +} + +/** + * @brief 获取待同步记录的数量(PENDING或FAILED状态) + * @retval 待同步记录数 + */ +uint16_t Attendance_GetPendingCount(void) +{ + uint16_t count = 0; + for (uint16_t i = 0; i < record_count; i++) + { + if (attendance_records[i].sync_status == SYNC_PENDING || + attendance_records[i].sync_status == SYNC_FAILED) + { + count++; + } + } + return count; +} + +/** + * @brief 获取下一个待同步的记录(PENDING或FAILED状态) + * @param index 输出参数,返回记录的索引 + * @retval 记录指针,如果没有待同步记录则返回NULL + */ +AttendanceRecord* Attendance_GetNextPendingRecord(uint16_t* index) +{ + uint32_t current_time = Get_Time_ms(); + + // 优先处理PENDING状态的记录 + for (uint16_t i = 0; i < record_count; i++) + { + if (attendance_records[i].sync_status == SYNC_PENDING) + { + if (index != NULL) + { + *index = i; + } + return &attendance_records[i]; + } + } + + // 然后处理FAILED状态的记录(需要等待重试间隔) + for (uint16_t i = 0; i < record_count; i++) + { + if (attendance_records[i].sync_status == SYNC_FAILED) + { + // 指数退避算法:重试间隔 = 2^retry_count * 1000ms (最大30秒) + uint32_t retry_interval = (1 << attendance_records[i].retry_count) * 1000; + if (retry_interval > 30000) retry_interval = 30000; + + // 检查是否到达重试时间 + if (current_time - attendance_records[i].last_retry_time >= retry_interval) + { + if (index != NULL) + { + *index = i; + } + return &attendance_records[i]; + } + } + } + + return NULL; // 没有待同步记录 +} + +/** + * @brief 更新记录的同步状态 + * @param index 记录索引 + * @param status 新的同步状态 + */ +void Attendance_MarkSyncStatus(uint16_t index, SyncStatus status) +{ + if (index < record_count) + { + attendance_records[index].sync_status = status; + + if (status == SYNC_FAILED || status == SYNC_SYNCING) + { + attendance_records[index].last_retry_time = Get_Time_ms(); + } + + const char* status_str[] = {"PENDING", "SYNCING", "SYNCED", "FAILED"}; + DEBUG_PRINT("[Attendance] Record %d status: %s (ID=%s)\r\n", + index, status_str[status], attendance_records[index].student_id); + } +} + +/** + * @brief 增加记录的重试计数 + * @param index 记录索引 + */ +void Attendance_IncrementRetry(uint16_t index) +{ + if (index < record_count) + { + attendance_records[index].retry_count++; + DEBUG_PRINT("[Attendance] Record %d retry count: %d\r\n", + index, attendance_records[index].retry_count); + } +} + +/** + * @brief 将所有FAILED记录重置为PENDING(用于网络恢复后) + */ +void Attendance_ResetFailedRecords(void) +{ + uint16_t reset_count = 0; + for (uint16_t i = 0; i < record_count; i++) + { + if (attendance_records[i].sync_status == SYNC_FAILED) + { + attendance_records[i].sync_status = SYNC_PENDING; + attendance_records[i].retry_count = 0; + reset_count++; + } + } + + if (reset_count > 0) + { + DEBUG_PRINT("[Attendance] Reset %d failed records to pending\r\n", reset_count); + } +} + +/** + * @brief 按索引获取记录 + * @param index 记录索引 + * @retval 记录指针,如果索引无效则返回NULL + */ +AttendanceRecord* Attendance_GetRecordByIndex(uint16_t index) +{ + if (index < record_count) + { + return &attendance_records[index]; + } + return NULL; +} diff --git a/Hardware/Attendance.h b/Hardware/Attendance.h new file mode 100644 index 0000000..8df9563 --- /dev/null +++ b/Hardware/Attendance.h @@ -0,0 +1,79 @@ +#ifndef __ATTENDANCE_H +#define __ATTENDANCE_H + +#include "stm32f10x.h" + +// 同步状态枚举 +typedef enum { + SYNC_PENDING = 0, // 待同步(新记录) + SYNC_SYNCING, // 同步中 + SYNC_SYNCED, // 已同步成功 + SYNC_FAILED // 同步失败(等待重试) +} SyncStatus; + +// 考勤记录结构体 +typedef struct { + char student_id[20]; // 学号 + char student_name[32]; // 学生姓名 + float confidence; // 识别置信度 + uint32_t timestamp; // 打卡时间戳(秒) + uint8_t time_slot; // 打卡时段编号 + SyncStatus sync_status; // 同步状态 + uint8_t retry_count; // 重试次数 + uint32_t last_retry_time; // 上次重试时间(毫秒) +} AttendanceRecord; + +// 人脸识别结果结构体 +typedef struct { + uint8_t success; // 识别是否成功 (1=成功, 0=失败) + char student_id[20]; // 学号 + char student_name[32]; // 学生姓名 + float confidence; // 置信度 (0.0-1.0) +} FaceRecognitionResult; + +// 考勤状态 +typedef enum { + ATTENDANCE_SUCCESS = 0, // 打卡成功 + ATTENDANCE_DUPLICATE, // 重复打卡(本时段已打卡) + ATTENDANCE_UNKNOWN, // 未识别到人脸 + ATTENDANCE_LOW_CONFIDENCE, // 置信度过低 + ATTENDANCE_OUT_OF_TIME // 不在考勤时间段内 +} AttendanceStatus; + +// 时间段定义结构体 +typedef struct { + uint8_t enabled; // 是否启用该时间段(1=启用, 0=禁用) + uint8_t start_hour; // 开始小时 (0-23) + uint8_t start_minute; // 开始分钟 (0-59) + uint8_t end_hour; // 结束小时 (0-23) + uint8_t end_minute; // 结束分钟 (0-59) + char name[20]; // 时段名称(如"上午签到") +} TimeSlot; + +// 函数声明 +void Attendance_Init(void); +void Attendance_SetCurrentTime(uint8_t hour, uint8_t minute); // 设置当前时间 +void Attendance_UpdateTimeSlots(TimeSlot* slots, uint8_t count); // 更新时间段配置(从服务器下载后调用) +uint8_t Attendance_ParseTimeSlotsJSON(const char* json_str); // 从JSON字符串解析时间段配置 +AttendanceStatus Attendance_ProcessFaceResult(FaceRecognitionResult* result); +uint8_t Attendance_IsDuplicate(const char* student_id); +uint8_t Attendance_IsDuplicateOnServer(const char* student_id); // 服务器端查重 +void Attendance_GetCurrentSlotTime(char* start_time, char* end_time); // 获取当前时段时间 +uint8_t Attendance_LoadTodayRecordsFromServer(void); // 新增:从服务器加载今日签到记录 +uint8_t Attendance_IsDuplicateInCache(const char* student_id); // 新增:在本地缓存中查重 +void Attendance_AddToCache(const char* student_id); // 新增:添加学号到缓存 +void Attendance_ClearCache(void); // 新增:清空缓存 +void Attendance_ClearRecords(void); +uint16_t Attendance_GetTotalCount(void); // 获取累计考勤总数 +uint16_t Attendance_GetActiveCount(void); // 获取当前缓存记录数 +int8_t Attendance_GetCurrentTimeSlot(void); // 获取当前时段编号(-1表示不在考勤时段) + +// 数据同步相关函数 +uint16_t Attendance_GetPendingCount(void); // 获取待同步记录数量(PENDING状态) +AttendanceRecord* Attendance_GetNextPendingRecord(uint16_t* index); // 获取下一个待同步记录 +void Attendance_MarkSyncStatus(uint16_t index, SyncStatus status); // 更新记录的同步状态 +void Attendance_IncrementRetry(uint16_t index); // 增加重试计数 +AttendanceRecord* Attendance_GetRecordByIndex(uint16_t index); // 按索引获取记录 +void Attendance_ResetFailedRecords(void); // 将所有FAILED记录重置为PENDING + +#endif diff --git a/Hardware/Buzzer_LED.c b/Hardware/Buzzer_LED.c new file mode 100644 index 0000000..7504474 --- /dev/null +++ b/Hardware/Buzzer_LED.c @@ -0,0 +1,29 @@ +#include "Buzzer_LED.h" + +void Buzzer_LED_Init(void) +{ + GPIO_InitTypeDef GPIO_InitStructure; + RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE); + + // 释放PB4(默认是JTAG引脚),保留SWD调试 + GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); + + // 根据连接图.md: LED=PB4, 蜂鸣器=PB5 + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOB, &GPIO_InitStructure); + + // PC13板载状态指示LED + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOC, &GPIO_InitStructure); + + // 初始状态:LED和蜂鸣器都关闭 + LED_SUCCESS_OFF(); + BUZZER_OFF(); + + // PC13状态LED:初始化时点亮(表示系统正在初始化) + LED_STATUS_ON(); +} diff --git a/Hardware/Buzzer_LED.h b/Hardware/Buzzer_LED.h new file mode 100644 index 0000000..67ce257 --- /dev/null +++ b/Hardware/Buzzer_LED.h @@ -0,0 +1,19 @@ +#ifndef __BUZZER_LED_H +#define __BUZZER_LED_H + +#include "stm32f10x.h" + +// 定义GPIO控制宏 (根据连接图.md修改) +#define LED_SUCCESS_OFF() GPIO_ResetBits(GPIOB, GPIO_Pin_4) // PB4, 高电平点亮 +#define LED_SUCCESS_ON() GPIO_SetBits(GPIOB, GPIO_Pin_4) +#define BUZZER_OFF() GPIO_SetBits(GPIOB, GPIO_Pin_5) // PB5, 低电平触发 +#define BUZZER_ON() GPIO_ResetBits(GPIOB, GPIO_Pin_5) + +// PC13板载状态指示LED (低电平点亮) +#define LED_STATUS_ON() GPIO_ResetBits(GPIOC, GPIO_Pin_13) // 初始化中:常亮 +#define LED_STATUS_OFF() GPIO_SetBits(GPIOC, GPIO_Pin_13) // 就绪后:熄灭 + +// 声明初始化函数 +void Buzzer_LED_Init(void); + +#endif diff --git a/Hardware/Crypto.c b/Hardware/Crypto.c new file mode 100644 index 0000000..b3346f5 --- /dev/null +++ b/Hardware/Crypto.c @@ -0,0 +1,99 @@ +/* + * 加密模块实现 + * 使用AES-128-CBC + Base64编码 + */ + +#include "Crypto.h" +#include "aes.h" +#include "base64.h" +#include + +// ⚠️ 重要:密钥和IV必须与服务器端完全一致! +// AES-128密钥(16字节) +static const uint8_t AES_KEY[16] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; + +// 初始化向量(16字节) +static const uint8_t AES_IV[16] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f +}; + +static struct AES_ctx aes_ctx; + +void Crypto_Init(void) +{ + // 初始化AES上下文(使用CBC模式) + AES_init_ctx_iv(&aes_ctx, AES_KEY, AES_IV); +} + +/** + * @brief PKCS#7填充 + * 将数据填充到16字节的倍数 + */ +static uint32_t pkcs7_pad(uint8_t* data, uint32_t data_len, uint32_t buffer_size) +{ + // 计算需要填充的字节数 + uint32_t padding_len = 16 - (data_len % 16); + + // 检查缓冲区是否足够 + if (data_len + padding_len > buffer_size) { + return 0; // 缓冲区不足 + } + + // 填充(PKCS#7标准) + uint32_t i; + for (i = 0; i < padding_len; i++) { + data[data_len + i] = (uint8_t)padding_len; + } + + return data_len + padding_len; +} + +uint32_t Crypto_EncryptJSON(const char* json_data, char* encrypted_output) +{ + uint32_t json_len = strlen(json_data); + uint8_t buffer[512]; // 临时缓冲区 + + // 1. 复制JSON数据到缓冲区 + if (json_len > sizeof(buffer) - 16) { + return 0; // 数据太长 + } + memcpy(buffer, json_data, json_len); + + // 2. PKCS#7填充到16字节的倍数 + uint32_t padded_len = pkcs7_pad(buffer, json_len, sizeof(buffer)); + if (padded_len == 0) { + return 0; // 填充失败 + } + + // 3. 手动实现标准CBC加密(绕过aes.c的bug) + struct AES_ctx ctx; + uint8_t iv[16]; + uint32_t i, j; + + // 初始化密钥和IV + AES_init_ctx(&ctx, AES_KEY); + memcpy(iv, AES_IV, 16); + + // CBC加密:每个块先XOR IV,再加密,然后用密文更新IV + for (i = 0; i < padded_len; i += 16) { + // XOR with IV + for (j = 0; j < 16; j++) { + buffer[i + j] ^= iv[j]; + } + + // AES加密单个块 + AES_ECB_encrypt(&ctx, &buffer[i]); + + // 更新IV为当前密文块 + memcpy(iv, &buffer[i], 16); + } + + // 4. Base64编码 + uint32_t encoded_len = base64_encode(buffer, padded_len, encrypted_output); + + return encoded_len; +} diff --git a/Hardware/Crypto.h b/Hardware/Crypto.h new file mode 100644 index 0000000..b1d8e66 --- /dev/null +++ b/Hardware/Crypto.h @@ -0,0 +1,30 @@ +#ifndef _CRYPTO_H_ +#define _CRYPTO_H_ + +#include +#include + +/** + * @brief 加密JSON数据 + * @param json_data 原始JSON字符串 + * @param encrypted_output 输出的加密Base64字符串(需要预分配足够空间) + * @return 加密后的Base64字符串长度 + * + * 注意:encrypted_output缓冲区至少需要 (strlen(json_data) / 16 + 1) * 16 * 4/3 + 10 字节 + */ +uint32_t Crypto_EncryptJSON(const char* json_data, char* encrypted_output); + +/** + * @brief 获取加密后数据的最大长度 + * @param json_length JSON字符串长度 + * @return 加密后的最大长度 + */ +#define CRYPTO_MAX_ENCRYPTED_SIZE(json_len) (((json_len) / 16 + 1) * 16 * 4 / 3 + 10) + +/** + * @brief 初始化加密模块 + * 设置密钥和IV(初始化向量) + */ +void Crypto_Init(void); + +#endif // _CRYPTO_H_ diff --git a/Hardware/DS1302.c b/Hardware/DS1302.c new file mode 100644 index 0000000..3d8f4b5 --- /dev/null +++ b/Hardware/DS1302.c @@ -0,0 +1,246 @@ +#include "DS1302.h" +#include "Delay.h" + +// 根据连接图.md: DS1302引脚配置 +// CLK: PA4, DAT: PA5, RST: PA6 + +#define DS1302_SCLK_PIN GPIO_Pin_4 // CLK +#define DS1302_IO_PIN GPIO_Pin_5 // DAT (双向) +#define DS1302_CE_PIN GPIO_Pin_6 // RST/CE +#define DS1302_GPIO GPIOA + +// GPIO控制宏 +#define SCLK_H GPIO_SetBits(DS1302_GPIO, DS1302_SCLK_PIN) +#define SCLK_L GPIO_ResetBits(DS1302_GPIO, DS1302_SCLK_PIN) +#define DATA_H GPIO_SetBits(DS1302_GPIO, DS1302_IO_PIN) +#define DATA_L GPIO_ResetBits(DS1302_GPIO, DS1302_IO_PIN) +#define CE_H GPIO_SetBits(DS1302_GPIO, DS1302_CE_PIN) +#define CE_L GPIO_ResetBits(DS1302_GPIO, DS1302_CE_PIN) +#define DATA_READ GPIO_ReadInputDataBit(DS1302_GPIO, DS1302_IO_PIN) + +// DS1302寄存器地址(写地址) +#define DS1302_SECOND 0x80 +#define DS1302_MINUTE 0x82 +#define DS1302_HOUR 0x84 +#define DS1302_DATE 0x86 +#define DS1302_MONTH 0x88 +#define DS1302_DAY 0x8A +#define DS1302_YEAR 0x8C +#define DS1302_WP 0x8E + +// BCD码转换 +#define BCD_TO_DEC(bcd) (((bcd) >> 4) * 10 + ((bcd) & 0x0F)) +#define DEC_TO_BCD(dec) ((((dec) / 10) << 4) | ((dec) % 10)) + +// 微秒延时 +static void delay_us(uint32_t us) +{ + volatile uint32_t i; + while (us--) { + for (i = 0; i < 12; i++); // 72MHz下约1us + } +} + +/** + * @brief 配置IO口为输出 + */ +static void DS1302_DATAOUT_init(void) +{ + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = DS1302_IO_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(DS1302_GPIO, &GPIO_InitStructure); +} + +/** + * @brief 配置IO口为输入 + */ +static void DS1302_DATAINPUT_init(void) +{ + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = DS1302_IO_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_Init(DS1302_GPIO, &GPIO_InitStructure); +} + +/** + * @brief DS1302初始化 + */ +void DS1302_Init(void) +{ + GPIO_InitTypeDef GPIO_InitStructure; + + // 使能GPIOA时钟 + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); + + // 配置SCLK和CE为推挽输出 + GPIO_InitStructure.GPIO_Pin = DS1302_SCLK_PIN | DS1302_CE_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(DS1302_GPIO, &GPIO_InitStructure); + + // 配置IO为输出(初始状态) + DS1302_DATAOUT_init(); + + // 初始化引脚状态 + SCLK_L; + CE_L; +} + +/** + * @brief 向DS1302发送一字节数据(根据demo代码) + * @param data 要发送的数据 + */ +static void DS1302_write_onebyte(uint8_t data) +{ + uint8_t count = 0; + + DS1302_DATAOUT_init(); // 配置为输出 + SCLK_L; + + for (count = 0; count < 8; count++) + { + SCLK_L; + + // 先准备好数据再发送 + if (data & 0x01) + DATA_H; + else + DATA_L; + + SCLK_H; // 拉高时钟线,发送数据 + data >>= 1; + } +} + +/** + * @brief 向指定寄存器地址发送数据(根据demo代码) + * @param address 寄存器地址 + * @param data 数据 + */ +void DS1302_WriteByte(uint8_t address, uint8_t data) +{ + CE_L; + SCLK_L; + delay_us(1); + + CE_H; + delay_us(2); + + DS1302_write_onebyte(address); + DS1302_write_onebyte(data); + + CE_L; + SCLK_L; + delay_us(2); +} + +/** + * @brief 从指定地址读取一字节数据(根据demo代码) + * @param address 寄存器地址 + * @retval 读取到的数据 + */ +uint8_t DS1302_ReadByte(uint8_t address) +{ + uint8_t count = 0; + uint8_t return_data = 0x00; + + CE_L; + SCLK_L; + delay_us(3); + + CE_H; + delay_us(3); + + DS1302_write_onebyte(address); + + DS1302_DATAINPUT_init(); // 配置I/O口为输入 + delay_us(2); + + for (count = 0; count < 8; count++) + { + delay_us(2); // 使电平持续一段时间 + return_data >>= 1; + + SCLK_H; + delay_us(4); // 使高电平持续一段时间 + + SCLK_L; + delay_us(14); // ⭐ 关键延时:延时14us后再去读取电压,更加准确 + + if (DATA_READ) + return_data = return_data | 0x80; + } + + delay_us(2); + CE_L; + DATA_L; + + return return_data; +} + +/** + * @brief 设置DS1302时间 + * @param time 时间结构体指针 + */ +void DS1302_SetTime(DS1302_Time* time) +{ + // 关闭写保护 + DS1302_WriteByte(DS1302_WP, 0x00); + + // 写入时间数据(BCD码格式) + DS1302_WriteByte(DS1302_SECOND, DEC_TO_BCD(time->second)); + DS1302_WriteByte(DS1302_MINUTE, DEC_TO_BCD(time->minute)); + DS1302_WriteByte(DS1302_HOUR, DEC_TO_BCD(time->hour)); + DS1302_WriteByte(DS1302_DATE, DEC_TO_BCD(time->day)); + DS1302_WriteByte(DS1302_MONTH, DEC_TO_BCD(time->month)); + DS1302_WriteByte(DS1302_DAY, DEC_TO_BCD(time->week)); + DS1302_WriteByte(DS1302_YEAR, DEC_TO_BCD(time->year % 100)); + + // 开启写保护 + DS1302_WriteByte(DS1302_WP, 0x80); +} + +/** + * @brief 读取DS1302时间 + * @param time 时间结构体指针 + */ +void DS1302_GetTime(DS1302_Time* time) +{ + uint8_t read_time[7]; + uint8_t hour_reg; + + // 读取时间数据(BCD码) + read_time[0] = DS1302_ReadByte(0x81); // 读秒 + read_time[1] = DS1302_ReadByte(0x83); // 读分 + read_time[2] = DS1302_ReadByte(0x85); // 读时 + read_time[3] = DS1302_ReadByte(0x87); // 读日 + read_time[4] = DS1302_ReadByte(0x89); // 读月 + read_time[5] = DS1302_ReadByte(0x8B); // 读星期 + read_time[6] = DS1302_ReadByte(0x8D); // 读年 + + // BCD码转换为10进制(先屏蔽控制位,再转换) + time->second = BCD_TO_DEC(read_time[0] & 0x7F); // bit7=CH + time->minute = BCD_TO_DEC(read_time[1] & 0x7F); + + hour_reg = read_time[2]; + if (hour_reg & 0x80) { + // 12小时制:bit5=PM, bit4~0=小时(1~12) + uint8_t hour12 = BCD_TO_DEC(hour_reg & 0x1F); + uint8_t is_pm = (hour_reg & 0x20) ? 1 : 0; + if (hour12 == 12) { + time->hour = is_pm ? 12 : 0; + } else { + time->hour = is_pm ? (hour12 + 12) : hour12; + } + } else { + // 24小时制:bit5~0=小时(0~23) + time->hour = BCD_TO_DEC(hour_reg & 0x3F); + } + + time->day = BCD_TO_DEC(read_time[3] & 0x3F); + time->month = BCD_TO_DEC(read_time[4] & 0x1F); + time->week = read_time[5] & 0x07; + time->year = BCD_TO_DEC(read_time[6]) + 2000; +} diff --git a/Hardware/DS1302.h b/Hardware/DS1302.h new file mode 100644 index 0000000..f65d4eb --- /dev/null +++ b/Hardware/DS1302.h @@ -0,0 +1,24 @@ +#ifndef __DS1302_H +#define __DS1302_H + +#include "stm32f10x.h" + +// DS1302时间结构体 +typedef struct { + uint16_t year; // 年份 (2000-2099) + uint8_t month; // 月份 (1-12) + uint8_t day; // 日期 (1-31) + uint8_t hour; // 小时 (0-23) + uint8_t minute; // 分钟 (0-59) + uint8_t second; // 秒钟 (0-59) + uint8_t week; // 星期 (1-7, 1=周一) +} DS1302_Time; + +// 函数声明 +void DS1302_Init(void); +void DS1302_SetTime(DS1302_Time* time); +void DS1302_GetTime(DS1302_Time* time); +uint8_t DS1302_ReadByte(uint8_t addr); +void DS1302_WriteByte(uint8_t addr, uint8_t dat); + +#endif diff --git a/Hardware/K210_USART.c b/Hardware/K210_USART.c new file mode 100644 index 0000000..d6d01df --- /dev/null +++ b/Hardware/K210_USART.c @@ -0,0 +1,136 @@ +#include "K210_USART.h" +#include "Debug.h" // 添加调试支持 +#include +#include + +// 引用来自 main.c 的全局变量 +extern volatile char g_k210_rx_buffer[]; +extern volatile uint16_t g_k210_rx_counter; +extern volatile uint8_t g_k210_rx_flag; + +// 全局变量:存储解析后的人脸识别结果 +FaceRecognitionResult K210_FaceResult; + +void K210_USART_Init(void) +{ + // 根据连接图.md: K210使用USART3 (PB10/PB11) + GPIO_InitTypeDef GPIO_InitStructure; + USART_InitTypeDef USART_InitStructure; + NVIC_InitTypeDef NVIC_InitStructure; + + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); + RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); + + // PB10: USART3_TX + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOB, &GPIO_InitStructure); + + // PB11: USART3_RX + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_Init(GPIOB, &GPIO_InitStructure); + + USART_InitStructure.USART_BaudRate = 115200; + USART_InitStructure.USART_WordLength = USART_WordLength_8b; + USART_InitStructure.USART_StopBits = USART_StopBits_1; + USART_InitStructure.USART_Parity = USART_Parity_No; + USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; + USART_Init(USART3, &USART_InitStructure); + + USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); + + NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + + USART_Cmd(USART3, ENABLE); +} + +/** + * @brief 解析K210发送的人脸识别数据 + * @param buffer 接收到的数据缓冲区 + * @param result 解析结果存储结构体 + * @retval 1=解析成功, 0=解析失败 + * + * K210数据格式示例: "ID:2021001,NAME:Zhang_San,CONF:0.95" + * 或者: "UNKNOWN" (未识别到人脸) + */ +uint8_t K210_ParseFaceData(const char* buffer, FaceRecognitionResult* result) +{ + DEBUG_PRINT("[K210] Raw data: %s\r\n", buffer); + + // 清空结果结构体 + memset(result, 0, sizeof(FaceRecognitionResult)); + + // 检查是否为未识别 + if (strstr(buffer, "UNKNOWN") != NULL) + { + DEBUG_INFO("[K210] Unknown face detected"); + result->success = 0; + strcpy(result->student_name, "Unknown"); + return 1; + } + + // 尝试解析完整数据 + char id[20] = {0}; + char name[32] = {0}; + float conf = 0.0f; + + // 解析格式: ID:2021001,NAME:Zhang_San,CONF:0.95 + int parsed = sscanf(buffer, "ID:%19[^,],NAME:%31[^,],CONF:%f", id, name, &conf); + + if (parsed == 3) + { + DEBUG_PRINT("[K210] Parsed: ID=%s, Name=%s, Conf=%.2f\r\n", id, name, conf); + + result->success = 1; + strncpy(result->student_id, id, 19); + result->student_id[19] = '\0'; + + // 将下划线替换为空格(方便显示) + strncpy(result->student_name, name, 31); + result->student_name[31] = '\0'; + for (int i = 0; result->student_name[i] != '\0'; i++) + { + if (result->student_name[i] == '_') + result->student_name[i] = ' '; + } + + result->confidence = conf; + return 1; + } + + DEBUG_ERROR("[K210] Parse failed!"); + return 0; // 解析失败 +} + +uint8_t K210_GetRxFlag(void) +{ + if (g_k210_rx_flag) + { + DEBUG_INFO("[K210] Data received, parsing..."); + + // 解析K210发送的人脸识别数据 + K210_ParseFaceData((const char*)g_k210_rx_buffer, &K210_FaceResult); + + g_k210_rx_flag = 0; // 清除标志位 + g_k210_rx_counter = 0; // 重置计数器 + + // 清空缓冲区,防止数据粘连 + memset((void*)g_k210_rx_buffer, 0, K210_RX_BUFFER_SIZE); + + return 1; + } + return 0; +} + +void K210_ClearRxFlag(void) +{ + g_k210_rx_flag = 0; + g_k210_rx_counter = 0; +} diff --git a/Hardware/K210_USART.h b/Hardware/K210_USART.h new file mode 100644 index 0000000..1a6c0a2 --- /dev/null +++ b/Hardware/K210_USART.h @@ -0,0 +1,18 @@ +#ifndef __K210_USART_H +#define __K210_USART_H + +#include "stm32f10x.h" +#include "Attendance.h" + +#define K210_RX_BUFFER_SIZE 128 + +// 声明外部变量 +extern FaceRecognitionResult K210_FaceResult; + +// 声明公共函数 +void K210_USART_Init(void); +uint8_t K210_GetRxFlag(void); +void K210_ClearRxFlag(void); +uint8_t K210_ParseFaceData(const char* buffer, FaceRecognitionResult* result); + +#endif diff --git a/Hardware/LightSensor.c b/Hardware/LightSensor.c new file mode 100644 index 0000000..b6cda12 --- /dev/null +++ b/Hardware/LightSensor.c @@ -0,0 +1,106 @@ +#include "LightSensor.h" + +// 补光灯当前状态 +static uint8_t g_fill_light_on = 0; + +/** + * @brief 初始化光敏电阻ADC和补光灯GPIO + */ +void LightSensor_Init(void) +{ + GPIO_InitTypeDef GPIO_InitStructure; + ADC_InitTypeDef ADC_InitStructure; + + // 1. 使能时钟 + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_ADC1, ENABLE); + + // 配置ADC时钟分频(ADC时钟不能超过14MHz) + RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 72MHz / 6 = 12MHz + + // 2. 配置PB0为模拟输入(光敏电阻) + GPIO_InitStructure.GPIO_Pin = LIGHT_SENSOR_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入 + GPIO_Init(LIGHT_SENSOR_PORT, &GPIO_InitStructure); + + // 3. 配置PB1为推挽输出(补光灯) + GPIO_InitStructure.GPIO_Pin = FILL_LIGHT_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(FILL_LIGHT_PORT, &GPIO_InitStructure); + + // 4. 初始化ADC1 + ADC_DeInit(ADC1); + + ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 独立模式 + ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 单通道模式 + ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 单次转换 + ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 软件触发 + ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 右对齐 + ADC_InitStructure.ADC_NbrOfChannel = 1; // 1个通道 + ADC_Init(ADC1, &ADC_InitStructure); + + // 5. 配置ADC通道1,采样时间239.5周期(更稳定) + ADC_RegularChannelConfig(ADC1, LIGHT_SENSOR_ADC_CH, 1, ADC_SampleTime_239Cycles5); + + // 6. 使能ADC1 + ADC_Cmd(ADC1, ENABLE); + + // 7. ADC校准 + ADC_ResetCalibration(ADC1); + while (ADC_GetResetCalibrationStatus(ADC1)); + ADC_StartCalibration(ADC1); + while (ADC_GetCalibrationStatus(ADC1)); + + // 8. 初始状态:补光灯关闭 + FILL_LIGHT_OFF(); + g_fill_light_on = 0; +} + +/** + * @brief 获取光敏电阻ADC值 + * @return ADC值 (0-4095),值越大表示光线越暗(电阻越大) + */ +uint16_t LightSensor_GetValue(void) +{ + // 启动ADC转换 + ADC_SoftwareStartConvCmd(ADC1, ENABLE); + + // 等待转换完成 + while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); + + // 返回转换结果 + return ADC_GetConversionValue(ADC1); +} + +/** + * @brief 更新补光灯状态(在主循环中定期调用) + * 使用迟滞控制避免灯光频繁开关 + */ +void LightSensor_Update(void) +{ + uint16_t light_value = LightSensor_GetValue(); + + // 迟滞控制逻辑 + if (g_fill_light_on) { + // 当前灯是亮的,只有光线足够亮时才关灯 + if (light_value < LIGHT_THRESHOLD_HIGH) { + FILL_LIGHT_OFF(); + g_fill_light_on = 0; + } + } else { + // 当前灯是灭的,只有光线足够暗时才开灯 + if (light_value > LIGHT_THRESHOLD_LOW) { + FILL_LIGHT_ON(); + g_fill_light_on = 1; + } + } +} + +/** + * @brief 获取补光灯当前状态 + * @return 1=亮,0=灭 + */ +uint8_t LightSensor_IsLightOn(void) +{ + return g_fill_light_on; +} diff --git a/Hardware/LightSensor.h b/Hardware/LightSensor.h new file mode 100644 index 0000000..036f92d --- /dev/null +++ b/Hardware/LightSensor.h @@ -0,0 +1,30 @@ +#ifndef __LIGHTSENSOR_H +#define __LIGHTSENSOR_H + +#include "stm32f10x.h" + +// 光敏电阻引脚定义 +#define LIGHT_SENSOR_PIN GPIO_Pin_0 +#define LIGHT_SENSOR_PORT GPIOB +#define LIGHT_SENSOR_ADC_CH ADC_Channel_8 // PB0 对应 ADC1 通道8 + +// 补光灯引脚定义 +#define FILL_LIGHT_PIN GPIO_Pin_1 +#define FILL_LIGHT_PORT GPIOB + +// 补光灯控制宏(根据实际电路调整,假设高电平点亮) +#define FILL_LIGHT_ON() GPIO_SetBits(FILL_LIGHT_PORT, FILL_LIGHT_PIN) +#define FILL_LIGHT_OFF() GPIO_ResetBits(FILL_LIGHT_PORT, FILL_LIGHT_PIN) + +// 光线阈值配置(可根据实际环境调整) +#define LIGHT_THRESHOLD_LOW 1500 // 低于此值开灯(光线暗) +#define LIGHT_THRESHOLD_HIGH 2000 // 高于此值关灯(光线亮) +// 使用迟滞区间避免频繁开关 + +// 函数声明 +void LightSensor_Init(void); // 初始化光敏电阻ADC和补光灯GPIO +uint16_t LightSensor_GetValue(void); // 获取光敏电阻ADC值 +void LightSensor_Update(void); // 更新补光灯状态(主循环中调用) +uint8_t LightSensor_IsLightOn(void); // 获取补光灯当前状态 + +#endif diff --git a/Hardware/OLED.c b/Hardware/OLED.c new file mode 100644 index 0000000..940631c --- /dev/null +++ b/Hardware/OLED.c @@ -0,0 +1,258 @@ +// ====================================================== +// OLED.c (最终修正版, 支持中文) +// ====================================================== +#include "stm32f10x.h" +#include "OLED_Font.h" // 包含ASCII和中文的字模 + +/*引脚配置*/ +#define OLED_W_SCL(x) GPIO_WriteBit(GPIOB, GPIO_Pin_8, (BitAction)(x)) +#define OLED_W_SDA(x) GPIO_WriteBit(GPIOB, GPIO_Pin_9, (BitAction)(x)) + +/* ... 从 OLED_I2C_Init() 到 OLED_ShowBinNum() 的所有函数保持不变 ... */ +/* ... 请确保您文件里这部分内容是完整的 ... */ + +/*引脚初始化*/ +void OLED_I2C_Init(void) +{ + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; + GPIO_Init(GPIOB, &GPIO_InitStructure); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; + GPIO_Init(GPIOB, &GPIO_InitStructure); + + OLED_W_SCL(1); + OLED_W_SDA(1); +} + +void OLED_I2C_Start(void) +{ + OLED_W_SDA(1); + OLED_W_SCL(1); + OLED_W_SDA(0); + OLED_W_SCL(0); +} + +void OLED_I2C_Stop(void) +{ + OLED_W_SDA(0); + OLED_W_SCL(1); + OLED_W_SDA(1); +} + +void OLED_I2C_SendByte(uint8_t Byte) +{ + uint8_t i; + for (i = 0; i < 8; i++) + { + OLED_W_SDA(Byte & (0x80 >> i)); + OLED_W_SCL(1); + OLED_W_SCL(0); + } + OLED_W_SCL(1); + OLED_W_SCL(0); +} + +void OLED_WriteCommand(uint8_t Command) +{ + OLED_I2C_Start(); + OLED_I2C_SendByte(0x78); + OLED_I2C_SendByte(0x00); + OLED_I2C_SendByte(Command); + OLED_I2C_Stop(); +} + +void OLED_WriteData(uint8_t Data) +{ + OLED_I2C_Start(); + OLED_I2C_SendByte(0x78); + OLED_I2C_SendByte(0x40); + OLED_I2C_SendByte(Data); + OLED_I2C_Stop(); +} + +void OLED_SetCursor(uint8_t Y, uint8_t X) +{ + OLED_WriteCommand(0xB0 | Y); + OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4)); + OLED_WriteCommand(0x00 | (X & 0x0F)); +} + +void OLED_Clear(void) +{ + uint8_t i, j; + for (j = 0; j < 8; j++) + { + OLED_SetCursor(j, 0); + for(i = 0; i < 128; i++) + { + OLED_WriteData(0x00); + } + } +} + +void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char) +{ + uint8_t i; + OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8); + for (i = 0; i < 8; i++) + { + OLED_WriteData(OLED_F8x16[Char - ' '][i]); + } + OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); + for (i = 0; i < 8; i++) + { + OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]); + } +} + +void OLED_ShowString(uint8_t Line, uint8_t Column, char *String) +{ + uint8_t i; + for (i = 0; String[i] != '\0'; i++) + { + OLED_ShowChar(Line, Column + i, String[i]); + } +} + +uint32_t OLED_Pow(uint32_t X, uint32_t Y) +{ + uint32_t Result = 1; + while (Y--) + { + Result *= X; + } + return Result; +} + +void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length) +{ + uint8_t i; + for (i = 0; i < Length; i++) + { + OLED_ShowChar(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0'); + } +} + +void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length) +{ + uint8_t i; + uint32_t Number1; + if (Number >= 0) + { + OLED_ShowChar(Line, Column, '+'); + Number1 = Number; + } + else + { + OLED_ShowChar(Line, Column, '-'); + Number1 = -Number; + } + for (i = 0; i < Length; i++) + { + OLED_ShowChar(Line, Column + i + 1, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0'); + } +} + +void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length) +{ + uint8_t i, SingleNumber; + for (i = 0; i < Length; i++) + { + SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16; + if (SingleNumber < 10) + { + OLED_ShowChar(Line, Column + i, SingleNumber + '0'); + } + else + { + OLED_ShowChar(Line, Column + i, SingleNumber - 10 + 'A'); + } + } +} + +void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length) +{ + uint8_t i; + for (i = 0; i < Length; i++) + { + OLED_ShowChar(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0'); + } +} + + +/** + * @brief OLED显示一个16*16的汉字 + * @param Line 行位置,范围:1~4 (一个汉字占用2行高度) + * @param Column 列位置,范围:1~8 (一个汉字占用2个字符宽度) + * @param num 要显示的汉字在OLED_F16x16_CN字模数组中的索引 + * @retval 无 + */ +void OLED_ShowChinese(uint8_t Line, uint8_t Column, uint8_t num) +{ + uint8_t i; + // 计算X坐标:一个汉字宽度为16像素,等于2个8像素的字符宽度 + uint8_t x = (Column - 1) * 16; + // 计算Y坐标:一个汉字高度为16像素,等于2个8像素的行(页)高度 + uint8_t y = (Line - 1) * 2; + + // 检查坐标是否越界 + if (x > 127 || y > 7) return; + + // 显示上半部分 (16*8) + OLED_SetCursor(y, x); + for (i = 0; i < 16; i++) + { + OLED_WriteData(OLED_F16x16_CN[num][i]); + } + + // 显示下半部分 (16*8) + OLED_SetCursor(y + 1, x); + for (i = 0; i < 16; i++) + { + OLED_WriteData(OLED_F16x16_CN[num][i + 16]); + } +} + + +/* ... OLED_Init() 函数保持不变 ... */ +void OLED_Init(void) +{ + uint32_t i, j; + + for (i = 0; i < 1000; i++) + { + for (j = 0; j < 1000; j++); + } + + OLED_I2C_Init(); + + OLED_WriteCommand(0xAE); //关闭显示 + OLED_WriteCommand(0xD5); //设置显示时钟分频比/振荡器频率 + OLED_WriteCommand(0x80); + OLED_WriteCommand(0xA8); //设置多路复用率 + OLED_WriteCommand(0x3F); + OLED_WriteCommand(0xD3); //设置显示偏移 + OLED_WriteCommand(0x00); + OLED_WriteCommand(0x40); //设置显示开始行 + OLED_WriteCommand(0xA1); //设置左右方向,0xA1正常 0xA0左右反置 + OLED_WriteCommand(0xC8); //设置上下方向,0xC8正常 0xC0上下反置 + OLED_WriteCommand(0xDA); //设置COM引脚硬件配置 + OLED_WriteCommand(0x12); + OLED_WriteCommand(0x81); //设置对比度控制 + OLED_WriteCommand(0xCF); + OLED_WriteCommand(0xD9); //设置预充电周期 + OLED_WriteCommand(0xF1); + OLED_WriteCommand(0xDB); //设置VCOMH取消选择级别 + OLED_WriteCommand(0x30); + OLED_WriteCommand(0xA4); //设置整个显示打开/关闭 + OLED_WriteCommand(0xA6); //设置正常/倒转显示 + OLED_WriteCommand(0x8D); //设置充电泵 + OLED_WriteCommand(0x14); + OLED_WriteCommand(0xAF); //开启显示 + + OLED_Clear(); +} diff --git a/Hardware/OLED.h b/Hardware/OLED.h new file mode 100644 index 0000000..73bdc1b --- /dev/null +++ b/Hardware/OLED.h @@ -0,0 +1,21 @@ +// ====================================================== +// OLED.h (最终修正版) +// ====================================================== +#ifndef __OLED_H +#define __OLED_H + +#include "stm32f10x.h" + +void OLED_Init(void); +void OLED_Clear(void); +void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char); +void OLED_ShowString(uint8_t Line, uint8_t Column, char *String); +void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length); +void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length); +void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length); +void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length); + +// 添加显示汉字的函数声明 +void OLED_ShowChinese(uint8_t Line, uint8_t Column, uint8_t num); + +#endif diff --git a/Hardware/OLED_Font.h b/Hardware/OLED_Font.h new file mode 100644 index 0000000..05089eb --- /dev/null +++ b/Hardware/OLED_Font.h @@ -0,0 +1,326 @@ +#ifndef __OLED_FONT_H +#define __OLED_FONT_H + +/*OLED字模库,宽8像素,高16像素*/ +const uint8_t OLED_F8x16[][16]= +{ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0 + + 0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 1 + + 0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 2 + + 0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00, + 0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 3 + + 0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00, + 0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 4 + + 0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00, + 0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 5 + + 0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00, + 0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 6 + + 0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 7 + + 0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00, + 0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 8 + + 0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00, + 0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 9 + + 0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00, + 0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 10 + + 0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00, + 0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 11 + + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 12 + + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 13 + + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 14 + + 0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04, + 0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 15 + + 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00, + 0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 16 + + 0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00, + 0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 17 + + 0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00, + 0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 18 + + 0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00, + 0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 19 + + 0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00, + 0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 20 + + 0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00, + 0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 21 + + 0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00, + 0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 22 + + 0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00, + 0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 23 + + 0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00, + 0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 24 + + 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00, + 0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 25 + + 0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00, + 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 26 + + 0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00, + 0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 27 + + 0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00, + 0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 28 + + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, + 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 29 + + 0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00, + 0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 30 + + 0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00, + 0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 31 + + 0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00, + 0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 32 + + 0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00, + 0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 33 + + 0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00, + 0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 34 + + 0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00, + 0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 35 + + 0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00, + 0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 36 + + 0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00, + 0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 37 + + 0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00, + 0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 38 + + 0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00, + 0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 39 + + 0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08, + 0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 40 + + 0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00, + 0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 41 + + 0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00, + 0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 42 + + 0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00, + 0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 43 + + 0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00, + 0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 44 + + 0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00, + 0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 45 + + 0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08, + 0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 46 + + 0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00, + 0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 47 + + 0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00, + 0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 48 + + 0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00, + 0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 49 + + 0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00, + 0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 50 + + 0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00, + 0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 51 + + 0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00, + 0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 52 + + 0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08, + 0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 53 + + 0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08, + 0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 54 + + 0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00, + 0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 55 + + 0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08, + 0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 56 + + 0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00, + 0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 57 + + 0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00, + 0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 58 + + 0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00, + 0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 59 + + 0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 60 + + 0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00, + 0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 61 + + 0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 62 + + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 63 + + 0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 64 + + 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00, + 0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 65 + + 0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00, + 0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 66 + + 0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00, + 0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 67 + + 0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00, + 0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 68 + + 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00, + 0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 69 + + 0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18, + 0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 70 + + 0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00, + 0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 71 + + 0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00, + 0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 72 + + 0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00, + 0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 73 + + 0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00, + 0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 74 + + 0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00, + 0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 75 + + 0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00, + 0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 76 + + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00, + 0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 77 + + 0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00, + 0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 78 + + 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00, + 0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 79 + + 0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00, + 0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 80 + + 0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00, + 0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 81 + + 0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00, + 0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 82 + + 0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00, + 0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 83 + + 0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00, + 0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 84 + + 0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00, + 0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 85 + + 0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80, + 0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 86 + + 0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80, + 0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 87 + + 0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00, + 0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 88 + + 0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80, + 0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 89 + + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00, + 0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 90 + + 0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02, + 0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 91 + + 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 92 + + 0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00, + 0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 93 + + 0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94 +}; + +/* + * 添加16x16中文字模库 + * 每个汉字占用32个字节 + * 汉字列表: 成(0) 功(1) 识(2) 别(3) 录(4) 入(5) 失(6) 败(7) + */ +const uint8_t OLED_F16x16_CN[][32]= +{ + {0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x3F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x80,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x00,0x03,0x0C,0x10,0x20,0x40,0x80,0x00},/*"成",0*/ + + {0x00,0xFE,0x22,0x22,0xFE,0x00,0x40,0x20,0x50,0x4C,0x43,0x4C,0x50,0x20,0x40,0x00, + 0x80,0x7F,0x02,0x82,0xFF,0x00,0x40,0x44,0x58,0x41,0x4E,0x60,0x58,0x47,0x40,0x00},/*"功",1*/ + + {0x40,0x40,0x42,0xCC,0x00,0x00,0x00,0xFC,0x04,0x04,0x04,0x04,0x04,0xFC,0x00,0x00, + 0x00,0x00,0x00,0x3F,0x10,0x88,0x40,0x23,0x19,0x01,0x01,0x09,0x11,0x23,0xC0,0x00},/*"识",2*/ + + {0x00,0x3E,0x22,0xE2,0x22,0x22,0x22,0x3E,0x00,0x00,0xF8,0x00,0x00,0xFF,0x00,0x00, + 0x81,0x41,0x31,0x0F,0x41,0x81,0x41,0x3F,0x00,0x00,0x0F,0x40,0x80,0x7F,0x00,0x00},/*"别",3*/ + + {0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0x08,0x08,0xFF,0x08,0x09,0x0A,0xC8,0x08,0x00, + 0x80,0x60,0x1F,0x00,0x10,0x20,0x1F,0x80,0x40,0x21,0x16,0x18,0x26,0x41,0xF8,0x00},/*"录",4*/ + + {0x08,0x08,0x08,0xF8,0x08,0x08,0x08,0x10,0x10,0xFF,0x10,0x10,0x10,0xF0,0x00,0x00, + 0x10,0x30,0x10,0x1F,0x08,0x88,0x48,0x30,0x0E,0x01,0x40,0x80,0x40,0x3F,0x00,0x00},/*"入",5*/ + + {0x00,0x40,0x30,0x1E,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00, + 0x81,0x81,0x41,0x21,0x11,0x0D,0x03,0x01,0x03,0x0D,0x11,0x21,0x41,0x81,0x81,0x00},/*"失",6*/ + + {0x00,0xFE,0x02,0xFA,0x02,0xFE,0x40,0x20,0xD8,0x17,0x10,0x10,0xF0,0x10,0x10,0x00, + 0x80,0x47,0x30,0x0F,0x10,0x67,0x80,0x40,0x21,0x16,0x08,0x16,0x21,0x40,0x80,0x00},/*"败",7*/ +}; + + +#endif diff --git a/Hardware/Serial.c b/Hardware/Serial.c new file mode 100644 index 0000000..e385353 --- /dev/null +++ b/Hardware/Serial.c @@ -0,0 +1,83 @@ +#include "Serial.h" +#include "Delay.h" // Get_Time_ms 在这里,所以我们包含它 +#include + +#define RX_BUFFER_SIZE 1024 // ← 增大到1024字节,支持完整HTTP响应 +char RxBuffer[RX_BUFFER_SIZE]; +uint16_t RxCounter = 0; + +// 初始化ESP8266所用的串口 (根据连接图.md: USART1 PA9/PA10) +void Serial_Init(void) +{ + GPIO_InitTypeDef GPIO_InitStructure; + USART_InitTypeDef USART_InitStructure; + NVIC_InitTypeDef NVIC_InitStructure; + + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE); + + // PA9: USART1_TX + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + // PA10: USART1_RX + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + USART_InitStructure.USART_BaudRate = 115200; + USART_InitStructure.USART_WordLength = USART_WordLength_8b; + USART_InitStructure.USART_StopBits = USART_StopBits_1; + USART_InitStructure.USART_Parity = USART_Parity_No; + USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; + USART_Init(USART1, &USART_InitStructure); + + USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); + + NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 优先级低于K210 + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + + USART_Cmd(USART1, ENABLE); +} + +// 发送字符串 +void Serial_SendString(const char* String) +{ + for (uint32_t i = 0; String[i] != '\0'; i++) + { + while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); + USART_SendData(USART1, String[i]); + } +} + +// 获取接收缓冲区 +char* Serial_GetRxBuffer(void) +{ + return RxBuffer; +} + +// 清空接收缓冲区 +void Serial_ClearRxBuffer(void) +{ + memset(RxBuffer, 0, RX_BUFFER_SIZE); + RxCounter = 0; +} + +// USART1中断服务函数 (ESP8266) +void USART1_IRQHandler(void) +{ + if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET) + { + uint8_t RxData = USART_ReceiveData(USART1); + if (RxCounter < RX_BUFFER_SIZE - 1) + { + RxBuffer[RxCounter++] = RxData; + } + USART_ClearITPendingBit(USART1, USART_IT_RXNE); + } +} diff --git a/Hardware/Serial.h b/Hardware/Serial.h new file mode 100644 index 0000000..7cf41b8 --- /dev/null +++ b/Hardware/Serial.h @@ -0,0 +1,17 @@ +#ifndef __SERIAL_H +#define __SERIAL_H + +#include +#include "stm32f10x.h" + +void Serial_Init(void); // 初始化串口 +void Serial_SendByte(uint8_t Byte); // 发送一个字节 +void Serial_SendString(const char* String); // 发送字符串 +char* Serial_GetRxBuffer(void); // 获取接收缓冲区指针 +void Serial_ClearRxBuffer(void); // 清空接收缓冲区 + +// 注意:Get_Time_ms() 函数与串口无关,应该在 `Delay.h` 中声明。 +// 我们暂时将它与串口放一起,但更规范的做法是分离。 +uint32_t Get_Time_ms(void); + +#endif diff --git a/Hardware/aes.c b/Hardware/aes.c new file mode 100644 index 0000000..9b8425c --- /dev/null +++ b/Hardware/aes.c @@ -0,0 +1,237 @@ +/* + * 标准AES-128-CBC实现 - 与OpenSSL完全兼容 + * 基于FIPS-197标准 + */ + +#include "aes.h" +#include + +// S-box +static const uint8_t sbox[256] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +// Rcon +static const uint8_t Rcon[11] = { + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 +}; + +#define getSBoxValue(num) (sbox[(num)]) + +// 密钥扩展 +static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) +{ + unsigned i, j, k; + uint8_t tempa[4]; + + // 前4个轮密钥直接复制 + for (i = 0; i < 4; ++i) { + RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; + RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; + RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; + RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; + } + + // 生成其余轮密钥 + for (i = 4; i < 44; ++i) { + k = (i - 1) * 4; + tempa[0] = RoundKey[k + 0]; + tempa[1] = RoundKey[k + 1]; + tempa[2] = RoundKey[k + 2]; + tempa[3] = RoundKey[k + 3]; + + if (i % 4 == 0) { + // RotWord + const uint8_t u8tmp = tempa[0]; + tempa[0] = tempa[1]; + tempa[1] = tempa[2]; + tempa[2] = tempa[3]; + tempa[3] = u8tmp; + + // SubWord + tempa[0] = getSBoxValue(tempa[0]); + tempa[1] = getSBoxValue(tempa[1]); + tempa[2] = getSBoxValue(tempa[2]); + tempa[3] = getSBoxValue(tempa[3]); + + tempa[0] = tempa[0] ^ Rcon[i / 4]; + } + + j = i * 4; + k = (i - 4) * 4; + RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0]; + RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1]; + RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2]; + RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3]; + } +} + +// AddRoundKey +static void AddRoundKey(uint8_t round, uint8_t* state, const uint8_t* RoundKey) +{ + uint8_t i, j; + for (i = 0; i < 4; ++i) { + for (j = 0; j < 4; ++j) { + state[i * 4 + j] ^= RoundKey[(round * 16) + (i * 4 + j)]; + } + } +} + +// SubBytes +static void SubBytes(uint8_t* state) +{ + uint8_t i; + for (i = 0; i < 16; ++i) { + state[i] = getSBoxValue(state[i]); + } +} + +// ShiftRows +static void ShiftRows(uint8_t* state) +{ + uint8_t temp; + + // 第二行左移1字节 + temp = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = temp; + + // 第三行左移2字节 + temp = state[2]; + state[2] = state[10]; + state[10] = temp; + temp = state[6]; + state[6] = state[14]; + state[14] = temp; + + // 第四行左移3字节 + temp = state[15]; + state[15] = state[11]; + state[11] = state[7]; + state[7] = state[3]; + state[3] = temp; +} + +// xtime (用于MixColumns) +static uint8_t xtime(uint8_t x) +{ + return ((x << 1) ^ (((x >> 7) & 1) * 0x1b)); +} + +// MixColumns +static void MixColumns(uint8_t* state) +{ + uint8_t i; + uint8_t Tmp, Tm, t; + + for (i = 0; i < 4; ++i) { + t = state[i * 4 + 0]; + Tmp = state[i * 4 + 0] ^ state[i * 4 + 1] ^ state[i * 4 + 2] ^ state[i * 4 + 3]; + + Tm = state[i * 4 + 0] ^ state[i * 4 + 1]; + Tm = xtime(Tm); + state[i * 4 + 0] ^= Tm ^ Tmp; + + Tm = state[i * 4 + 1] ^ state[i * 4 + 2]; + Tm = xtime(Tm); + state[i * 4 + 1] ^= Tm ^ Tmp; + + Tm = state[i * 4 + 2] ^ state[i * 4 + 3]; + Tm = xtime(Tm); + state[i * 4 + 2] ^= Tm ^ Tmp; + + Tm = state[i * 4 + 3] ^ t; + Tm = xtime(Tm); + state[i * 4 + 3] ^= Tm ^ Tmp; + } +} + +// Cipher - AES加密核心 +static void Cipher(uint8_t* state, const uint8_t* RoundKey) +{ + uint8_t round = 0; + + // 初始轮密钥加 + AddRoundKey(0, state, RoundKey); + + // 9轮标准变换 + for (round = 1; round < 10; ++round) { + SubBytes(state); + ShiftRows(state); + MixColumns(state); + AddRoundKey(round, state, RoundKey); + } + + // 最后一轮(无MixColumns) + SubBytes(state); + ShiftRows(state); + AddRoundKey(10, state, RoundKey); +} + +// ========== 公开API函数 ========== + +void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key) +{ + KeyExpansion(ctx->RoundKey, key); +} + +void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv) +{ + KeyExpansion(ctx->RoundKey, key); + memcpy(ctx->Iv, iv, AES_BLOCKLEN); +} + +void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf) +{ + Cipher(buf, ctx->RoundKey); +} + +void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) +{ + size_t i; + uint8_t j; + + for (i = 0; i < length; i += AES_BLOCKLEN) { + // XOR with IV/previous ciphertext block + for (j = 0; j < AES_BLOCKLEN; ++j) { + buf[i + j] ^= ctx->Iv[j]; + } + + // Encrypt block + Cipher(buf + i, ctx->RoundKey); + + // Update IV to current ciphertext block + memcpy(ctx->Iv, buf + i, AES_BLOCKLEN); + } +} + +// STM32端不需要解密功能 +void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf) +{ + (void)ctx; + (void)buf; +} + +void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) +{ + (void)ctx; + (void)buf; + (void)length; +} diff --git a/Hardware/aes.h b/Hardware/aes.h new file mode 100644 index 0000000..84a0ef3 --- /dev/null +++ b/Hardware/aes.h @@ -0,0 +1,65 @@ +#ifndef _AES_H_ +#define _AES_H_ + +#include +#include + +// 使用AES-128(16字节密钥) +#define AES_BLOCKLEN 16 // Block length in bytes - AES is 128b block only +#define AES_KEYLEN 16 // Key length in bytes (AES-128) +#define AES_keyExpSize 176 + +struct AES_ctx +{ + uint8_t RoundKey[AES_keyExpSize]; + uint8_t Iv[AES_BLOCKLEN]; // 独立的IV存储(标准做法,与OpenSSL兼容) +}; + +/** + * @brief 初始化AES上下文 + * @param ctx AES上下文结构 + * @param key 16字节密钥 + */ +void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); + +/** + * @brief AES-ECB加密(单个块) + * @param ctx AES上下文 + * @param buf 要加密的数据(16字节块) + */ +void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf); + +/** + * @brief AES-ECB解密(单个块) + * @param ctx AES上下文 + * @param buf 要解密的数据(16字节块) + */ +void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf); + +/** + * @brief AES-CBC加密(多个块) + * @param ctx AES上下文 + * @param buf 要加密的数据 + * @param length 数据长度(必须是16的倍数) + * @param iv 初始化向量(16字节) + */ +void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); + +/** + * @brief AES-CBC解密(多个块) + * @param ctx AES上下文 + * @param buf 要解密的数据 + * @param length 数据长度(必须是16的倍数) + * @param iv 初始化向量(16字节) + */ +void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); + +/** + * @brief 初始化AES上下文(CBC模式) + * @param ctx AES上下文结构 + * @param key 16字节密钥 + * @param iv 16字节初始化向量 + */ +void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv); + +#endif // _AES_H_ diff --git a/Hardware/aes_fixed.c b/Hardware/aes_fixed.c new file mode 100644 index 0000000..9b8425c --- /dev/null +++ b/Hardware/aes_fixed.c @@ -0,0 +1,237 @@ +/* + * 标准AES-128-CBC实现 - 与OpenSSL完全兼容 + * 基于FIPS-197标准 + */ + +#include "aes.h" +#include + +// S-box +static const uint8_t sbox[256] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +// Rcon +static const uint8_t Rcon[11] = { + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 +}; + +#define getSBoxValue(num) (sbox[(num)]) + +// 密钥扩展 +static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) +{ + unsigned i, j, k; + uint8_t tempa[4]; + + // 前4个轮密钥直接复制 + for (i = 0; i < 4; ++i) { + RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; + RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; + RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; + RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; + } + + // 生成其余轮密钥 + for (i = 4; i < 44; ++i) { + k = (i - 1) * 4; + tempa[0] = RoundKey[k + 0]; + tempa[1] = RoundKey[k + 1]; + tempa[2] = RoundKey[k + 2]; + tempa[3] = RoundKey[k + 3]; + + if (i % 4 == 0) { + // RotWord + const uint8_t u8tmp = tempa[0]; + tempa[0] = tempa[1]; + tempa[1] = tempa[2]; + tempa[2] = tempa[3]; + tempa[3] = u8tmp; + + // SubWord + tempa[0] = getSBoxValue(tempa[0]); + tempa[1] = getSBoxValue(tempa[1]); + tempa[2] = getSBoxValue(tempa[2]); + tempa[3] = getSBoxValue(tempa[3]); + + tempa[0] = tempa[0] ^ Rcon[i / 4]; + } + + j = i * 4; + k = (i - 4) * 4; + RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0]; + RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1]; + RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2]; + RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3]; + } +} + +// AddRoundKey +static void AddRoundKey(uint8_t round, uint8_t* state, const uint8_t* RoundKey) +{ + uint8_t i, j; + for (i = 0; i < 4; ++i) { + for (j = 0; j < 4; ++j) { + state[i * 4 + j] ^= RoundKey[(round * 16) + (i * 4 + j)]; + } + } +} + +// SubBytes +static void SubBytes(uint8_t* state) +{ + uint8_t i; + for (i = 0; i < 16; ++i) { + state[i] = getSBoxValue(state[i]); + } +} + +// ShiftRows +static void ShiftRows(uint8_t* state) +{ + uint8_t temp; + + // 第二行左移1字节 + temp = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = temp; + + // 第三行左移2字节 + temp = state[2]; + state[2] = state[10]; + state[10] = temp; + temp = state[6]; + state[6] = state[14]; + state[14] = temp; + + // 第四行左移3字节 + temp = state[15]; + state[15] = state[11]; + state[11] = state[7]; + state[7] = state[3]; + state[3] = temp; +} + +// xtime (用于MixColumns) +static uint8_t xtime(uint8_t x) +{ + return ((x << 1) ^ (((x >> 7) & 1) * 0x1b)); +} + +// MixColumns +static void MixColumns(uint8_t* state) +{ + uint8_t i; + uint8_t Tmp, Tm, t; + + for (i = 0; i < 4; ++i) { + t = state[i * 4 + 0]; + Tmp = state[i * 4 + 0] ^ state[i * 4 + 1] ^ state[i * 4 + 2] ^ state[i * 4 + 3]; + + Tm = state[i * 4 + 0] ^ state[i * 4 + 1]; + Tm = xtime(Tm); + state[i * 4 + 0] ^= Tm ^ Tmp; + + Tm = state[i * 4 + 1] ^ state[i * 4 + 2]; + Tm = xtime(Tm); + state[i * 4 + 1] ^= Tm ^ Tmp; + + Tm = state[i * 4 + 2] ^ state[i * 4 + 3]; + Tm = xtime(Tm); + state[i * 4 + 2] ^= Tm ^ Tmp; + + Tm = state[i * 4 + 3] ^ t; + Tm = xtime(Tm); + state[i * 4 + 3] ^= Tm ^ Tmp; + } +} + +// Cipher - AES加密核心 +static void Cipher(uint8_t* state, const uint8_t* RoundKey) +{ + uint8_t round = 0; + + // 初始轮密钥加 + AddRoundKey(0, state, RoundKey); + + // 9轮标准变换 + for (round = 1; round < 10; ++round) { + SubBytes(state); + ShiftRows(state); + MixColumns(state); + AddRoundKey(round, state, RoundKey); + } + + // 最后一轮(无MixColumns) + SubBytes(state); + ShiftRows(state); + AddRoundKey(10, state, RoundKey); +} + +// ========== 公开API函数 ========== + +void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key) +{ + KeyExpansion(ctx->RoundKey, key); +} + +void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv) +{ + KeyExpansion(ctx->RoundKey, key); + memcpy(ctx->Iv, iv, AES_BLOCKLEN); +} + +void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf) +{ + Cipher(buf, ctx->RoundKey); +} + +void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) +{ + size_t i; + uint8_t j; + + for (i = 0; i < length; i += AES_BLOCKLEN) { + // XOR with IV/previous ciphertext block + for (j = 0; j < AES_BLOCKLEN; ++j) { + buf[i + j] ^= ctx->Iv[j]; + } + + // Encrypt block + Cipher(buf + i, ctx->RoundKey); + + // Update IV to current ciphertext block + memcpy(ctx->Iv, buf + i, AES_BLOCKLEN); + } +} + +// STM32端不需要解密功能 +void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf) +{ + (void)ctx; + (void)buf; +} + +void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) +{ + (void)ctx; + (void)buf; + (void)length; +} diff --git a/Hardware/aes_fixed.h b/Hardware/aes_fixed.h new file mode 100644 index 0000000..142d860 --- /dev/null +++ b/Hardware/aes_fixed.h @@ -0,0 +1,63 @@ +#ifndef _AES_H_ +#define _AES_H_ + +#include +#include + +// AES-128配置 +#define AES_BLOCKLEN 16 // Block length in bytes (AES is 128-bit block) +#define AES_KEYLEN 16 // Key length in bytes (AES-128) +#define AES_keyExpSize 176 // Expanded key size (44 * 4 bytes) + +struct AES_ctx +{ + uint8_t RoundKey[AES_keyExpSize]; // 扩展密钥 + uint8_t Iv[AES_BLOCKLEN]; // IV向量(独立存储,标准做法) +}; + +/** + * @brief 初始化AES上下文(仅密钥) + * @param ctx AES上下文结构 + * @param key 16字节密钥 + */ +void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); + +/** + * @brief 初始化AES上下文(密钥+IV) + * @param ctx AES上下文结构 + * @param key 16字节密钥 + * @param iv 16字节初始化向量 + */ +void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv); + +/** + * @brief AES-ECB加密(单个块) + * @param ctx AES上下文 + * @param buf 要加密的数据(16字节块) + */ +void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf); + +/** + * @brief AES-ECB解密(单个块) + * @param ctx AES上下文 + * @param buf 要解密的数据(16字节块) + */ +void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf); + +/** + * @brief AES-CBC加密(多个块) + * @param ctx AES上下文 + * @param buf 要加密的数据 + * @param length 数据长度(必须是16的倍数) + */ +void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); + +/** + * @brief AES-CBC解密(多个块) + * @param ctx AES上下文 + * @param buf 要解密的数据 + * @param length 数据长度(必须是16的倍数) + */ +void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); + +#endif // _AES_H_ diff --git a/Hardware/base64.c b/Hardware/base64.c new file mode 100644 index 0000000..e903745 --- /dev/null +++ b/Hardware/base64.c @@ -0,0 +1,81 @@ +/* + * Base64 编码/解码实现 + * 优化用于嵌入式系统 + */ + +#include "base64.h" +#include + +static const char base64_chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +uint32_t base64_encode(const uint8_t* input, uint32_t input_length, char* output) +{ + uint32_t i, j; + uint32_t output_length = 0; + + for (i = 0, j = 0; i < input_length;) { + uint32_t octet_a = i < input_length ? input[i++] : 0; + uint32_t octet_b = i < input_length ? input[i++] : 0; + uint32_t octet_c = i < input_length ? input[i++] : 0; + + uint32_t triple = (octet_a << 16) + (octet_b << 8) + octet_c; + + output[j++] = base64_chars[(triple >> 18) & 0x3F]; + output[j++] = base64_chars[(triple >> 12) & 0x3F]; + output[j++] = base64_chars[(triple >> 6) & 0x3F]; + output[j++] = base64_chars[triple & 0x3F]; + } + + output_length = j; + + // 处理padding + uint32_t mod = input_length % 3; + if (mod > 0) { + for (i = 0; i < 3 - mod; i++) { + output[output_length - 1 - i] = '='; + } + } + + output[output_length] = '\0'; + return output_length; +} + +static uint8_t base64_char_value(char c) +{ + if (c >= 'A' && c <= 'Z') return c - 'A'; + if (c >= 'a' && c <= 'z') return c - 'a' + 26; + if (c >= '0' && c <= '9') return c - '0' + 52; + if (c == '+') return 62; + if (c == '/') return 63; + return 0; +} + +uint32_t base64_decode(const char* input, uint32_t input_length, uint8_t* output) +{ + uint32_t i, j; + uint32_t output_length = 0; + + if (input_length % 4 != 0) return 0; + + for (i = 0, j = 0; i < input_length;) { + uint32_t sextet_a = input[i] == '=' ? 0 : base64_char_value(input[i]); i++; + uint32_t sextet_b = input[i] == '=' ? 0 : base64_char_value(input[i]); i++; + uint32_t sextet_c = input[i] == '=' ? 0 : base64_char_value(input[i]); i++; + uint32_t sextet_d = input[i] == '=' ? 0 : base64_char_value(input[i]); i++; + + uint32_t triple = (sextet_a << 18) + (sextet_b << 12) + (sextet_c << 6) + sextet_d; + + if (j < input_length) output[j++] = (triple >> 16) & 0xFF; + if (j < input_length) output[j++] = (triple >> 8) & 0xFF; + if (j < input_length) output[j++] = triple & 0xFF; + } + + output_length = j; + + // 移除padding + if (input[input_length - 1] == '=') output_length--; + if (input[input_length - 2] == '=') output_length--; + + return output_length; +} diff --git a/Hardware/base64.h b/Hardware/base64.h new file mode 100644 index 0000000..7d108c0 --- /dev/null +++ b/Hardware/base64.h @@ -0,0 +1,34 @@ +#ifndef _BASE64_H_ +#define _BASE64_H_ + +#include +#include + +/** + * @brief Base64编码 + * @param input 输入数据 + * @param input_length 输入数据长度 + * @param output 输出缓冲区(需要预分配足够空间) + * @return 编码后的字符串长度 + * + * 注意:output缓冲区大小至少需要 ((input_length + 2) / 3) * 4 + 1 字节 + */ +uint32_t base64_encode(const uint8_t* input, uint32_t input_length, char* output); + +/** + * @brief Base64解码 + * @param input 输入Base64字符串 + * @param input_length 输入字符串长度 + * @param output 输出缓冲区 + * @return 解码后的数据长度 + */ +uint32_t base64_decode(const char* input, uint32_t input_length, uint8_t* output); + +/** + * @brief 计算Base64编码后的长度 + * @param input_length 输入数据长度 + * @return 编码后的长度(不含结束符) + */ +#define BASE64_ENCODE_SIZE(len) (((len) + 2) / 3 * 4) + +#endif // _BASE64_H_ diff --git a/Hardware/esp8266.c b/Hardware/esp8266.c new file mode 100644 index 0000000..d0ab9ec --- /dev/null +++ b/Hardware/esp8266.c @@ -0,0 +1,624 @@ +/* + * ESP8266 WiFi模块驱动(支持HTTP加密传输) + * 版本:v2.0 - 加密方案C + * 修改: + * 1. 添加HTTP POST请求支持 + * 2. 添加加密数据传输 + * 3. 保留原有TCP兼容接口 + */ + +#include "esp8266.h" +#include "Serial.h" +#include "Delay.h" +#include "Debug.h" +#include +#include +#include // ← 添加atoi函数声明 + +// 外部配置(在main.c中定义) +extern const char* WIFI_SSID; +extern const char* WIFI_PASSWORD; +extern const char* HTTP_SERVER_IP; +extern const char* HTTP_SERVER_PORT; +extern const char* HTTP_API_TOKEN; +extern uint8_t g_server_connected; + +/* --- 私有辅助函数 --- */ +static void ESP8266_SendCmd(const char* cmd) { + Serial_SendString(cmd); + Serial_SendString("\r\n"); +} + +static uint8_t ESP8266_WaitForAck(const char* ack, uint32_t timeout) { + uint32_t time_start = Get_Time_ms(); + uint32_t time_elapsed; + Serial_ClearRxBuffer(); + + DEBUG_PRINT("[ESP8266] Waiting for: %s (timeout: %dms)\r\n", ack, timeout); + + while(1) { + time_elapsed = Get_Time_ms() - time_start; + if (time_elapsed > timeout) { + DEBUG_PRINT("[ESP8266] Timeout after %dms\r\n", time_elapsed); + break; + } + + char* response = Serial_GetRxBuffer(); + if (response && strstr(response, ack) != NULL) { + DEBUG_OK("[ESP8266] Received expected response"); + return ESP8266_SUCCESS; + } + + Delay_ms(10); + } + + DEBUG_PRINT("[ESP8266] Failed! Response: %s\r\n", Serial_GetRxBuffer()); + return ESP8266_FAIL; +} + +static uint8_t IsLeapYear(uint16_t year) +{ + return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 1 : 0; +} + +static uint8_t DaysInMonth(uint16_t year, uint8_t month) +{ + static const uint8_t days_table[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; + if (month == 2 && IsLeapYear(year)) return 29; + return days_table[month - 1]; +} + +static void EpochToDateTimeUTC8(uint32_t epoch_seconds, ESP8266_DateTime* datetime) +{ + // 转为北京时间(UTC+8) + uint32_t total = epoch_seconds + 8U * 3600U; + uint32_t days = total / 86400U; + uint32_t sec_of_day = total % 86400U; + + datetime->hour = sec_of_day / 3600U; + datetime->minute = (sec_of_day % 3600U) / 60U; + datetime->second = sec_of_day % 60U; + + datetime->year = 1970; + while (1) { + uint16_t ydays = IsLeapYear(datetime->year) ? 366 : 365; + if (days < ydays) break; + days -= ydays; + datetime->year++; + } + + datetime->month = 1; + while (1) { + uint8_t mdays = DaysInMonth(datetime->year, datetime->month); + if (days < mdays) break; + days -= mdays; + datetime->month++; + } + + datetime->day = (uint8_t)(days + 1U); +} + +/* --- 公共接口函数实现 --- */ + +uint8_t ESP8266_Setup(void) +{ + ESP8266_SendCmd("+++"); + Delay_ms(500); + + ESP8266_SendCmd("AT"); + if (!ESP8266_WaitForAck("OK", 1000)) return ESP8266_FAIL; + + ESP8266_SendCmd("AT+CWMODE=1"); + if (!ESP8266_WaitForAck("OK", 2000)) return ESP8266_FAIL; + + // 先关闭可能存在的连接(避免 "link is builded" 错误) + ESP8266_SendCmd("AT+CIPCLOSE"); + Delay_ms(500); // 等待连接关闭 + + // 设置单连接模式 + ESP8266_SendCmd("AT+CIPMUX=0"); + ESP8266_WaitForAck("OK", 1000); + + return ESP8266_SUCCESS; +} + +uint8_t ESP8266_ConnectWiFi(const char* ssid, const char* password) +{ + char cmd_buffer[128]; + + sprintf(cmd_buffer, "AT+CWJAP=\"%s\",\"%s\"", ssid, password); + ESP8266_SendCmd(cmd_buffer); + + return ESP8266_WaitForAck("WIFI GOT IP", 15000); +} + +/** + * @brief 连接到HTTP服务器(新增) + */ +uint8_t ESP8266_ConnectHTTPServer(const char* ip, const char* port) +{ + char cmd_buffer[100]; + uint32_t start_time; + + DEBUG_PRINT("[ESP8266] Connecting to HTTP server %s:%s\r\n", ip, port); + + // 先断开之前的连接 + ESP8266_SendCmd("AT+CIPCLOSE"); + Delay_ms(500); + + // 建立TCP连接 + sprintf(cmd_buffer, "AT+CIPSTART=\"TCP\",\"%s\",%s", ip, port); + Serial_ClearRxBuffer(); + ESP8266_SendCmd(cmd_buffer); + + // 等待连接成功 + start_time = Get_Time_ms(); + + while(Get_Time_ms() - start_time < 10000) { + char* response = Serial_GetRxBuffer(); + + if (strstr(response, "CONNECT") != NULL || strstr(response, "ALREADY") != NULL) { + DEBUG_OK("[ESP8266] HTTP server connected"); + Delay_ms(500); + return ESP8266_SUCCESS; + } + + if (strstr(response, "ERROR") != NULL || strstr(response, "CLOSED") != NULL) { + DEBUG_ERROR("[ESP8266] Connection failed"); + break; + } + + Delay_ms(100); + } + + DEBUG_ERROR("[ESP8266] Connection timeout"); + return ESP8266_FAIL; +} + +/** + * @brief 发送加密数据(HTTP POST请求) + */ +uint8_t ESP8266_SendEncryptedData(const char* encrypted_data) +{ + char http_request[1024]; + char cmd_buffer[32]; + uint32_t content_length = strlen(encrypted_data); + + if (ESP8266_CheckConnection() != ESP8266_SUCCESS) { + DEBUG_INFO("[ESP8266] HTTP connection not ready, reconnecting..."); + if (ESP8266_ConnectHTTPServer(HTTP_SERVER_IP, HTTP_SERVER_PORT) != ESP8266_SUCCESS) { + DEBUG_ERROR("[ESP8266] Reconnect failed before POST"); + return ESP8266_FAIL; + } + g_server_connected = 1; + } + + // 构建HTTP POST请求 + sprintf(http_request, + "POST /api/v1/attendance/checkins HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Content-Type: application/octet-stream\r\n" + "X-Api-Token: %s\r\n" + "X-Encrypted: AES128-CBC\r\n" + "Content-Length: %u\r\n" + "Connection: close\r\n" + "\r\n" + "%s", + HTTP_SERVER_IP, + HTTP_SERVER_PORT, + HTTP_API_TOKEN, + content_length, + encrypted_data + ); + + uint32_t request_len = strlen(http_request); + + DEBUG_PRINT("[ESP8266] Sending HTTP POST (%u bytes)\r\n", request_len); + + // 发送数据长度命令 + sprintf(cmd_buffer, "AT+CIPSEND=%u", request_len); + Serial_ClearRxBuffer(); + ESP8266_SendCmd(cmd_buffer); + + // 等待 ">" 提示符 + uint32_t start_time = Get_Time_ms(); + + while(Get_Time_ms() - start_time < 2000) { + if (strstr(Serial_GetRxBuffer(), ">") != NULL) { + DEBUG_INFO("[ESP8266] Ready to send"); + + // 发送HTTP请求 + Serial_SendString(http_request); + Delay_ms(100); + + // 不等待SEND OK,直接返回成功 + DEBUG_OK("[ESP8266] Data sent"); + return ESP8266_SUCCESS; + } + Delay_ms(10); + } + + DEBUG_ERROR("[ESP8266] No '>' prompt"); + return ESP8266_FAIL; +} + +uint8_t ESP8266_GetNetworkTime(ESP8266_DateTime* datetime) +{ + char response_buffer[256]; + char* epoch_ptr; + uint32_t epoch_seconds = 0; + uint8_t digit_count = 0; + + DEBUG_INFO("[ESP8266] Getting network time..."); + + // 优先直接请求业务服务器时间接口 + // 期望响应: {"epoch":1700000000,"server_time":"2026-02-12 12:34:56"} + if (ESP8266_HttpGet("/api/v1/system/time", response_buffer, sizeof(response_buffer)) != ESP8266_SUCCESS) { + DEBUG_ERROR("[ESP8266] /api/v1/system/time request failed, try reconnect..."); + if (ESP8266_ConnectHTTPServer(HTTP_SERVER_IP, HTTP_SERVER_PORT) != ESP8266_SUCCESS) { + DEBUG_ERROR("[ESP8266] Reconnect failed when getting time"); + return ESP8266_FAIL; + } + g_server_connected = 1; + if (ESP8266_HttpGet("/api/v1/system/time", response_buffer, sizeof(response_buffer)) != ESP8266_SUCCESS) { + DEBUG_ERROR("[ESP8266] /api/v1/system/time request failed after reconnect"); + return ESP8266_FAIL; + } + } + + epoch_ptr = strstr(response_buffer, "\"epoch\":"); + if (epoch_ptr == NULL) { + DEBUG_ERROR("[ESP8266] /api/v1/system/time response missing epoch"); + DEBUG_PRINT("[ESP8266] Response: %s\r\n", response_buffer); + return ESP8266_FAIL; + } + + epoch_ptr += 8; // 跳过 "epoch": + while (*epoch_ptr == ' ' || *epoch_ptr == '\"') epoch_ptr++; + while (*epoch_ptr >= '0' && *epoch_ptr <= '9' && digit_count < 10) { + epoch_seconds = epoch_seconds * 10U + (uint32_t)(*epoch_ptr - '0'); + epoch_ptr++; + digit_count++; + } + if (digit_count < 9) { + DEBUG_ERROR("[ESP8266] Invalid epoch value in /api/v1/system/time response"); + DEBUG_PRINT("[ESP8266] Response: %s\r\n", response_buffer); + return ESP8266_FAIL; + } + + EpochToDateTimeUTC8(epoch_seconds, datetime); + DEBUG_PRINT("[ESP8266] Time(from server): %04d-%02d-%02d %02d:%02d:%02d\r\n", + datetime->year, datetime->month, datetime->day, + datetime->hour, datetime->minute, datetime->second); + + return ESP8266_SUCCESS; +} + +uint8_t ESP8266_CheckConnection(void) +{ + char* response; + + Serial_ClearRxBuffer(); + ESP8266_SendCmd("AT+CIPSTATUS"); + Delay_ms(500); + + response = Serial_GetRxBuffer(); + + if (strstr(response, "STATUS:3") != NULL) { + DEBUG_INFO("[ESP8266] Connection OK (STATUS:3)"); + return ESP8266_SUCCESS; + } + + if (strstr(response, "STATUS:4") != NULL) { + DEBUG_ERROR("[ESP8266] Connection closed (STATUS:4)"); + return ESP8266_FAIL; + } + + if (strstr(response, "STATUS:5") != NULL) { + DEBUG_ERROR("[ESP8266] WiFi disconnected (STATUS:5)"); + return ESP8266_FAIL; + } + + if (strstr(response, "STATUS:2") != NULL) { + DEBUG_ERROR("[ESP8266] Not connected to server (STATUS:2)"); + return ESP8266_FAIL; + } + + DEBUG_ERROR("[ESP8266] Unknown connection status"); + return ESP8266_FAIL; +} + +/** + * @brief 发送HTTP GET请求并接收响应 + */ +uint8_t ESP8266_HttpGet(const char* path, char* response_buffer, uint16_t buffer_size) +{ + char http_request[256]; + char cmd_buffer[32]; + uint8_t request_sent = 0; + + DEBUG_PRINT("[ESP8266] HTTP GET: %s\r\n", path); + + if (response_buffer != NULL && buffer_size > 0) { + response_buffer[0] = '\0'; + } + + if (ESP8266_CheckConnection() != ESP8266_SUCCESS) { + DEBUG_INFO("[ESP8266] HTTP connection not ready, reconnecting..."); + if (ESP8266_ConnectHTTPServer(HTTP_SERVER_IP, HTTP_SERVER_PORT) != ESP8266_SUCCESS) { + DEBUG_ERROR("[ESP8266] Reconnect failed before GET"); + return ESP8266_FAIL; + } + g_server_connected = 1; + } + + // 构建HTTP GET请求 + sprintf(http_request, + "GET %s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "X-Api-Token: %s\r\n" + "Connection: close\r\n" + "\r\n", + path, + HTTP_SERVER_IP, + HTTP_SERVER_PORT, + HTTP_API_TOKEN + ); + + uint32_t request_len = strlen(http_request); + + // 发送数据长度命令 + sprintf(cmd_buffer, "AT+CIPSEND=%u", request_len); + Serial_ClearRxBuffer(); + ESP8266_SendCmd(cmd_buffer); + + // 等待 ">" 提示符 + uint32_t start_time = Get_Time_ms(); + + while(Get_Time_ms() - start_time < 2000) { + if (strstr(Serial_GetRxBuffer(), ">") != NULL) { + DEBUG_INFO("[ESP8266] Ready to send GET request"); + + // 发送HTTP GET请求 + Serial_SendString(http_request); + request_sent = 1; + break; + } + Delay_ms(10); + } + + if (!request_sent) { + DEBUG_ERROR("[ESP8266] No '>' prompt for GET request"); + return ESP8266_FAIL; + } + + // 等待接收完整响应(最多8秒) + start_time = Get_Time_ms(); + uint8_t found_header = 0; + uint32_t content_length = 0; + + while(Get_Time_ms() - start_time < 8000) { + char* response = Serial_GetRxBuffer(); + + // 1. 处理+IPD前缀(ESP8266格式:+IPD,长度:数据) + char* ipd_marker = strstr(response, "+IPD,"); + if (ipd_marker != NULL) { + // 跳过 "+IPD," 找到实际数据 + char* data_start = strchr(ipd_marker, ':'); + if (data_start != NULL) { + data_start++; // 跳过 ':' + response = data_start; // 从这里开始才是HTTP响应 + } + } + + // 2. 查找HTTP响应体(JSON数据在\r\n\r\n之后) + char* body_start = strstr(response, "\r\n\r\n"); + if (body_start != NULL) { + body_start += 4; // 跳过 \r\n\r\n + + // 3. 如果还没提取Content-Length,尝试提取 + if (!found_header) { + char* cl_str = strstr(response, "Content-Length:"); + if (cl_str != NULL) { + cl_str += 15; // 跳过 "Content-Length:" + while (*cl_str == ' ') cl_str++; + content_length = atoi(cl_str); + DEBUG_PRINT("[ESP8266] Content-Length: %u\r\n", content_length); + found_header = 1; + } + } + + // 4. 检查是否接收完整(比较实际长度和Content-Length) + uint16_t body_len = strlen(body_start); + + // 移除末尾的 "CLOSED" "OK" 等ESP8266附加信息 + char* closed_marker = strstr(body_start, "\r\nCLOSED"); + if (closed_marker != NULL) { + *closed_marker = '\0'; + body_len = strlen(body_start); + } + // 同时处理没有\r\n的情况 + closed_marker = strstr(body_start, "CLOSED"); + if (closed_marker != NULL) { + *closed_marker = '\0'; + body_len = strlen(body_start); + } + // 移除末尾的OK + char* ok_marker = strstr(body_start, "\r\nOK"); + if (ok_marker != NULL) { + *ok_marker = '\0'; + body_len = strlen(body_start); + } + + // 5. 如果数据完整或超时,复制到缓冲区 + if ((found_header && body_len >= content_length) || + (Get_Time_ms() - start_time > 3000 && body_len > 0)) { + if (body_len >= buffer_size) { + body_len = buffer_size - 1; + } + + strncpy(response_buffer, body_start, body_len); + response_buffer[body_len] = '\0'; + + DEBUG_PRINT("[ESP8266] Received response (%d bytes)\r\n", strlen(response_buffer)); + DEBUG_PRINT("[ESP8266] Response: %s\r\n", response_buffer); + return ESP8266_SUCCESS; + } + } + + Delay_ms(100); + } + + DEBUG_ERROR("[ESP8266] No valid HTTP response or timeout"); + return ESP8266_FAIL; +} + +// ========== 兼容旧版本的函数 ========== + +/** + * @brief 查询学生在指定时段是否已签到(服务器端查重) + * @param student_id 学号 + * @param slot_start 时段开始时间(格式"HH:MM") + * @param slot_end 时段结束时间(格式"HH:MM") + * @retval 1 表示已签到(重复), 0 表示未签到 + */ +uint8_t ESP8266_CheckDuplicate(const char* student_id, const char* slot_start, const char* slot_end) +{ + char path[128]; + char response_buffer[256]; + + // 构建查询路径 + sprintf(path, "/api/v1/attendance/duplicates?student_id=%s&slot_start=%s&slot_end=%s", + student_id, slot_start, slot_end); + + DEBUG_PRINT("[ESP8266] Checking duplicate: %s\r\n", path); + + // 先检查连接状态,如果断开则重连 + if (ESP8266_CheckConnection() != ESP8266_SUCCESS) { + DEBUG_INFO("[ESP8266] Connection lost, reconnecting..."); + extern const char* HTTP_SERVER_IP; + extern const char* HTTP_SERVER_PORT; + if (ESP8266_ConnectHTTPServer(HTTP_SERVER_IP, HTTP_SERVER_PORT) != ESP8266_SUCCESS) { + DEBUG_ERROR("[ESP8266] Reconnect failed"); + return 0; // 连接失败,默认允许签到 + } + Delay_ms(200); // 等待连接稳定 + } + + // 发送HTTP GET请求 + if (ESP8266_HttpGet(path, response_buffer, sizeof(response_buffer)) == ESP8266_SUCCESS) { + // 解析响应,查找 "duplicate":true + if (strstr(response_buffer, "\"duplicate\":true") != NULL) { + DEBUG_INFO("[ESP8266] Duplicate found on server!"); + return 1; // 已签到 + } else { + DEBUG_INFO("[ESP8266] No duplicate found"); + return 0; // 未签到 + } + } + + DEBUG_ERROR("[ESP8266] Failed to check duplicate, assuming not duplicate"); + return 0; // 查询失败时默认为未签到,允许本地签到 +} + +/** + * @brief 下载今日已签到学生列表(开机时调用) + * @param slot_start 时段开始时间(格式"HH:MM") + * @param slot_end 时段结束时间(格式"HH:MM") + * @param student_ids 输出:学号数组(逗号分隔的字符串) + * @param buffer_size 缓冲区大小 + * @retval 成功下载的学号数量 + */ +uint8_t ESP8266_DownloadTodayRecords(const char* slot_start, const char* slot_end, char* student_ids, uint16_t buffer_size) +{ + char path[128]; + char response_buffer[512]; + + // 构建查询路径 + sprintf(path, "/api/v1/attendance/today?slot_start=%s&slot_end=%s", slot_start, slot_end); + + DEBUG_PRINT("[ESP8266] Downloading today's records: %s\r\n", path); + + // 先检查连接状态,如果断开则重连 + if (ESP8266_CheckConnection() != ESP8266_SUCCESS) { + DEBUG_INFO("[ESP8266] Connection lost, reconnecting before download..."); + extern const char* HTTP_SERVER_IP; + extern const char* HTTP_SERVER_PORT; + if (ESP8266_ConnectHTTPServer(HTTP_SERVER_IP, HTTP_SERVER_PORT) != ESP8266_SUCCESS) { + DEBUG_ERROR("[ESP8266] Reconnect failed"); + return 0; + } + Delay_ms(300); // 等待连接稳定 + } + + // 发送HTTP GET请求 + if (ESP8266_HttpGet(path, response_buffer, sizeof(response_buffer)) != ESP8266_SUCCESS) { + DEBUG_ERROR("[ESP8266] Failed to download today's records"); + return 0; + } + + // 解析响应,提取学号列表 + // 格式: {"date":"2026-02-07","records":["1","2","3"]} + char* records_start = strstr(response_buffer, "\"records\":["); + if (records_start == NULL) { + DEBUG_ERROR("[ESP8266] Invalid response format"); + return 0; + } + + records_start += 11; // 跳过 "records":[ + char* records_end = strchr(records_start, ']'); + if (records_end == NULL) { + DEBUG_ERROR("[ESP8266] Invalid response format"); + return 0; + } + + // 复制学号列表到输出缓冲区 + uint16_t len = records_end - records_start; + if (len >= buffer_size) len = buffer_size - 1; + + strncpy(student_ids, records_start, len); + student_ids[len] = '\0'; + + // 统计学号数量(空列表返回0) + uint8_t count = 0; + if (len > 2) { // 至少有一个学号 "x" + count = 1; + for (uint16_t i = 0; i < len; i++) { + if (student_ids[i] == ',') count++; + } + } + + DEBUG_PRINT("[ESP8266] Downloaded %d records: %s\r\n", count, student_ids); + return count; +} + +uint8_t ESP8266_ConnectTCPServer(const char* ip, const char* port) +{ + // 重定向到HTTP版本 + return ESP8266_ConnectHTTPServer(ip, port); +} + +uint8_t ESP8266_SendData(char* Data) +{ + char cmd_buffer[32]; + uint16_t data_len = strlen(Data); + + DEBUG_PRINT("[ESP8266] Sending %d bytes (legacy mode)\r\n", data_len); + + sprintf(cmd_buffer, "AT+CIPSEND=%d", data_len); + ESP8266_SendCmd(cmd_buffer); + + uint32_t start_time = Get_Time_ms(); + Serial_ClearRxBuffer(); + + while(Get_Time_ms() - start_time < 1000) { + if (strstr(Serial_GetRxBuffer(), ">") != NULL) { + Serial_SendString(Data); + Delay_ms(50); + return ESP8266_SUCCESS; + } + Delay_ms(10); + } + + return ESP8266_FAIL; +} diff --git a/Hardware/esp8266.h b/Hardware/esp8266.h new file mode 100644 index 0000000..33a2f48 --- /dev/null +++ b/Hardware/esp8266.h @@ -0,0 +1,98 @@ +#ifndef __ESP8266_H +#define __ESP8266_H + +#include "stm32f10x.h" + +// 定义布尔类型,方便返回状态 +#define ESP8266_SUCCESS 1 +#define ESP8266_FAIL 0 + +// 时间结构体 +typedef struct { + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; +} ESP8266_DateTime; + +/* +--- 公共函数接口 --- +*/ + +/** + * @brief 对ESP8266模块进行基础设置 + * @retval 1 表示成功, 0 表示失败 + */ +uint8_t ESP8266_Setup(void); + +/** + * @brief 命令ESP8266连接到指定的WiFi网络 + * @param ssid 要连接的WiFi名称 (SSID) + * @param password WiFi的密码 + * @retval 1 表示成功, 0 表示失败 + */ +uint8_t ESP8266_ConnectWiFi(const char* ssid, const char* password); + +/** + * @brief 命令ESP8266连接到HTTP服务器(新增) + * @param ip 服务器的IP地址 + * @param port 服务器的端口号 + * @retval 1 表示成功, 0 表示失败 + */ +uint8_t ESP8266_ConnectHTTPServer(const char* ip, const char* port); + +/** + * @brief 通过ESP8266发送HTTP POST请求(新增 - 加密版本) + * @param encrypted_data 加密后的Base64数据 + * @retval 1 表示成功, 0 表示失败 + */ +uint8_t ESP8266_SendEncryptedData(const char* encrypted_data); + +/** + * @brief 检查TCP连接是否正常 + * @retval 1 表示已连接, 0 表示未连接 + */ +uint8_t ESP8266_CheckConnection(void); + +/** + * @brief 从网络获取当前时间(NTP/SNTP) + * @param datetime 时间结构体指针,用于存储获取的时间 + * @retval 1 表示成功, 0 表示失败 + */ +uint8_t ESP8266_GetNetworkTime(ESP8266_DateTime* datetime); + +/** + * @brief 发送HTTP GET请求并接收响应(新增) + * @param path 请求路径(如"/api/v1/config/time-slots") + * @param response_buffer 接收响应数据的缓冲区 + * @param buffer_size 缓冲区大小 + * @retval 1 表示成功, 0 表示失败 + */ +uint8_t ESP8266_HttpGet(const char* path, char* response_buffer, uint16_t buffer_size); + +/** + * @brief 查询学生在指定时段是否已签到(服务器端查重) + * @param student_id 学号 + * @param slot_start 时段开始时间(格式"HH:MM") + * @param slot_end 时段结束时间(格式"HH:MM") + * @retval 1 表示已签到(重复), 0 表示未签到 + */ +uint8_t ESP8266_CheckDuplicate(const char* student_id, const char* slot_start, const char* slot_end); + +/** + * @brief 下载今日已签到学生列表(开机时调用) + * @param slot_start 时段开始时间(格式"HH:MM") + * @param slot_end 时段结束时间(格式"HH:MM") + * @param student_ids 输出:学号数组(逗号分隔的字符串) + * @param buffer_size 缓冲区大小 + * @retval 成功下载的学号数量 + */ +uint8_t ESP8266_DownloadTodayRecords(const char* slot_start, const char* slot_end, char* student_ids, uint16_t buffer_size); + +// 兼容旧版本(已废弃,建议使用HTTP版本) +uint8_t ESP8266_ConnectTCPServer(const char* ip, const char* port); +uint8_t ESP8266_SendData(char* Data); + +#endif diff --git a/Hardware/esp8266_new.c b/Hardware/esp8266_new.c new file mode 100644 index 0000000..db4b952 --- /dev/null +++ b/Hardware/esp8266_new.c @@ -0,0 +1,243 @@ +/* + * ESP8266 WiFi模块驱动(支持HTTP加密传输) + * 新增功能: + * 1. HTTP POST请求支持 + * 2. 加密数据传输 + * 3. 自动重连机制 + */ + +#include "esp8266.h" +#include "Serial.h" +#include "Delay.h" +#include +#include + +// 外部配置(在main.c中定义) +extern const char* WIFI_SSID; +extern const char* WIFI_PASSWORD; +extern const char* HTTP_SERVER_IP; +extern const char* HTTP_SERVER_PORT; +extern const char* HTTP_API_TOKEN; + +// 内部函数声明 +static uint8_t ESP8266_SendCommand(const char* cmd, const char* expected, uint16_t timeout); +static void ESP8266_ClearBuffer(void); + +/** + * @brief 发送AT命令并等待响应 + */ +static uint8_t ESP8266_SendCommand(const char* cmd, const char* expected, uint16_t timeout) +{ + Serial_SendString(cmd); + Serial_SendString("\r\n"); + + Delay_ms(timeout); + + if (expected == NULL) { + return ESP8266_SUCCESS; + } + + // 检查是否收到期望的响应 + char* response = Serial_GetRxData(); + if (strstr(response, expected) != NULL) { + return ESP8266_SUCCESS; + } + + return ESP8266_FAIL; +} + +static void ESP8266_ClearBuffer(void) +{ + Serial_ClearRxBuffer(); +} + +uint8_t ESP8266_Setup(void) +{ + ESP8266_ClearBuffer(); + + // 测试AT指令 + if (ESP8266_SendCommand("AT", "OK", 1000) == ESP8266_FAIL) { + return ESP8266_FAIL; + } + + // 设置为STA模式(客户端模式) + if (ESP8266_SendCommand("AT+CWMODE=1", "OK", 1000) == ESP8266_FAIL) { + return ESP8266_FAIL; + } + + // 关闭回显 + ESP8266_SendCommand("ATE0", "OK", 500); + + // 设置单连接模式 + if (ESP8266_SendCommand("AT+CIPMUX=0", "OK", 1000) == ESP8266_FAIL) { + return ESP8266_FAIL; + } + + return ESP8266_SUCCESS; +} + +uint8_t ESP8266_ConnectWiFi(const char* ssid, const char* password) +{ + char cmd[128]; + + ESP8266_ClearBuffer(); + + // 断开之前的WiFi连接 + ESP8266_SendCommand("AT+CWQAP", "OK", 1000); + Delay_ms(1000); + + // 连接到WiFi + sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"", ssid, password); + + // WiFi连接可能需要较长时间 + if (ESP8266_SendCommand(cmd, "OK", 10000) == ESP8266_FAIL) { + return ESP8266_FAIL; + } + + Delay_ms(2000); + return ESP8266_SUCCESS; +} + +uint8_t ESP8266_ConnectHTTPServer(const char* ip, const char* port) +{ + char cmd[64]; + + ESP8266_ClearBuffer(); + + // 断开之前的TCP连接 + ESP8266_SendCommand("AT+CIPCLOSE", "OK", 1000); + Delay_ms(500); + + // 建立TCP连接到HTTP服务器 + sprintf(cmd, "AT+CIPSTART=\"TCP\",\"%s\",%s", ip, port); + + if (ESP8266_SendCommand(cmd, "OK", 5000) == ESP8266_FAIL) { + return ESP8266_FAIL; + } + + Delay_ms(1000); + return ESP8266_SUCCESS; +} + +uint8_t ESP8266_SendEncryptedData(const char* encrypted_data) +{ + char http_request[1024]; + char cmd[32]; + uint32_t content_length = strlen(encrypted_data); + + // 构建HTTP POST请求 + sprintf(http_request, + "POST /api/v1/attendance/checkins HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Content-Type: application/octet-stream\r\n" + "X-Api-Token: %s\r\n" + "X-Encrypted: AES128-CBC\r\n" + "Content-Length: %u\r\n" + "Connection: keep-alive\r\n" + "\r\n" + "%s", + HTTP_SERVER_IP, + HTTP_SERVER_PORT, + HTTP_API_TOKEN, + content_length, + encrypted_data + ); + + uint32_t request_len = strlen(http_request); + + // 发送数据长度命令 + sprintf(cmd, "AT+CIPSEND=%u", request_len); + + ESP8266_ClearBuffer(); + + if (ESP8266_SendCommand(cmd, ">", 2000) == ESP8266_FAIL) { + return ESP8266_FAIL; + } + + // 发送HTTP请求 + Serial_SendString(http_request); + + // 等待发送完成(不阻塞太久) + Delay_ms(100); + + // 可选:等待服务器响应(检查是否有"200 OK") + // 但为了不阻塞,建议不等待 + + return ESP8266_SUCCESS; +} + +uint8_t ESP8266_CheckConnection(void) +{ + ESP8266_ClearBuffer(); + + if (ESP8266_SendCommand("AT+CIPSTATUS", "OK", 1000) == ESP8266_FAIL) { + return ESP8266_FAIL; + } + + // 检查响应中是否包含"STATUS:3"(已连接) + char* response = Serial_GetRxData(); + if (strstr(response, "STATUS:3") != NULL || + strstr(response, "STATUS:4") != NULL) { + return ESP8266_SUCCESS; + } + + return ESP8266_FAIL; +} + +uint8_t ESP8266_GetNetworkTime(ESP8266_DateTime* datetime) +{ + // 启用SNTP + if (ESP8266_SendCommand("AT+CIPSNTPCFG=1,8,\"pool.ntp.org\"", "OK", 2000) == ESP8266_FAIL) { + return ESP8266_FAIL; + } + + Delay_ms(3000); // 等待时间同步 + + ESP8266_ClearBuffer(); + + // 获取时间 + if (ESP8266_SendCommand("AT+CIPSNTPTIME?", "OK", 1000) == ESP8266_FAIL) { + return ESP8266_FAIL; + } + + // 解析响应(格式:+CIPSNTPTIME:Thu Jan 01 08:00:00 2024) + char* response = Serial_GetRxData(); + char* time_str = strstr(response, "+CIPSNTPTIME:"); + + if (time_str != NULL) { + // 简单解析(这里只是示例,实际需要更完善的解析) + sscanf(time_str, "+CIPSNTPTIME:%*s %*s %d %d:%d:%d %d", + &datetime->day, &datetime->hour, + &datetime->minute, &datetime->second, &datetime->year); + + return ESP8266_SUCCESS; + } + + return ESP8266_FAIL; +} + +// ========== 兼容旧版本的函数(已废弃) ========== + +uint8_t ESP8266_ConnectTCPServer(const char* ip, const char* port) +{ + // 重定向到HTTP版本 + return ESP8266_ConnectHTTPServer(ip, port); +} + +uint8_t ESP8266_SendData(char* Data) +{ + // 警告:此函数已废弃,请使用ESP8266_SendEncryptedData + // 为了兼容,这里保留基本实现 + char cmd[32]; + + sprintf(cmd, "AT+CIPSEND=%d", strlen(Data)); + + if (ESP8266_SendCommand(cmd, ">", 2000) == ESP8266_FAIL) { + return ESP8266_FAIL; + } + + Serial_SendString(Data); + Delay_ms(50); + + return ESP8266_SUCCESS; +} diff --git a/Hardware/esp8266_new.h b/Hardware/esp8266_new.h new file mode 100644 index 0000000..0c994e7 --- /dev/null +++ b/Hardware/esp8266_new.h @@ -0,0 +1,70 @@ +#ifndef __ESP8266_H +#define __ESP8266_H + +#include "stm32f10x.h" + +// 定义布尔类型,方便返回状态 +#define ESP8266_SUCCESS 1 +#define ESP8266_FAIL 0 + +// 时间结构体 +typedef struct { + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; +} ESP8266_DateTime; + +/* +--- 公共函数接口 --- +*/ + +/** + * @brief 对ESP8266模块进行基础设置 + * @retval 1 表示成功, 0 表示失败 + */ +uint8_t ESP8266_Setup(void); + +/** + * @brief 命令ESP8266连接到指定的WiFi网络 + * @param ssid 要连接的WiFi名称 (SSID) + * @param password WiFi的密码 + * @retval 1 表示成功, 0 表示失败 + */ +uint8_t ESP8266_ConnectWiFi(const char* ssid, const char* password); + +/** + * @brief 命令ESP8266连接到HTTP服务器(新增) + * @param ip 服务器的IP地址 + * @param port 服务器的端口号 + * @retval 1 表示成功, 0 表示失败 + */ +uint8_t ESP8266_ConnectHTTPServer(const char* ip, const char* port); + +/** + * @brief 通过ESP8266发送HTTP POST请求(新增 - 加密版本) + * @param encrypted_data 加密后的Base64数据 + * @retval 1 表示成功, 0 表示失败 + */ +uint8_t ESP8266_SendEncryptedData(const char* encrypted_data); + +/** + * @brief 检查TCP连接是否正常 + * @retval 1 表示已连接, 0 表示未连接 + */ +uint8_t ESP8266_CheckConnection(void); + +/** + * @brief 从网络获取当前时间(NTP/SNTP) + * @param datetime 时间结构体指针,用于存储获取的时间 + * @retval 1 表示成功, 0 表示失败 + */ +uint8_t ESP8266_GetNetworkTime(ESP8266_DateTime* datetime); + +// 兼容旧版本(已废弃,建议使用HTTP版本) +uint8_t ESP8266_ConnectTCPServer(const char* ip, const char* port); +uint8_t ESP8266_SendData(char* Data); + +#endif diff --git a/Library/misc.c b/Library/misc.c new file mode 100644 index 0000000..c0a5e11 --- /dev/null +++ b/Library/misc.c @@ -0,0 +1,225 @@ +/** + ****************************************************************************** + * @file misc.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the miscellaneous firmware functions (add-on + * to CMSIS functions). + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "misc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup MISC + * @brief MISC driver modules + * @{ + */ + +/** @defgroup MISC_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup MISC_Private_Defines + * @{ + */ + +#define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000) +/** + * @} + */ + +/** @defgroup MISC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup MISC_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup MISC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup MISC_Private_Functions + * @{ + */ + +/** + * @brief Configures the priority grouping: pre-emption priority and subpriority. + * @param NVIC_PriorityGroup: specifies the priority grouping bits length. + * This parameter can be one of the following values: + * @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority + * 4 bits for subpriority + * @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority + * 3 bits for subpriority + * @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority + * 2 bits for subpriority + * @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority + * 1 bits for subpriority + * @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority + * 0 bits for subpriority + * @retval None + */ +void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup) +{ + /* Check the parameters */ + assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup)); + + /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */ + SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup; +} + +/** + * @brief Initializes the NVIC peripheral according to the specified + * parameters in the NVIC_InitStruct. + * @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains + * the configuration information for the specified NVIC peripheral. + * @retval None + */ +void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct) +{ + uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F; + + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd)); + assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority)); + assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority)); + + if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE) + { + /* Compute the Corresponding IRQ Priority --------------------------------*/ + tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08; + tmppre = (0x4 - tmppriority); + tmpsub = tmpsub >> tmppriority; + + tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre; + tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub; + tmppriority = tmppriority << 0x04; + + NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority; + + /* Enable the Selected IRQ Channels --------------------------------------*/ + NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = + (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); + } + else + { + /* Disable the Selected IRQ Channels -------------------------------------*/ + NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = + (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); + } +} + +/** + * @brief Sets the vector table location and Offset. + * @param NVIC_VectTab: specifies if the vector table is in RAM or FLASH memory. + * This parameter can be one of the following values: + * @arg NVIC_VectTab_RAM + * @arg NVIC_VectTab_FLASH + * @param Offset: Vector Table base offset field. This value must be a multiple + * of 0x200. + * @retval None + */ +void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset) +{ + /* Check the parameters */ + assert_param(IS_NVIC_VECTTAB(NVIC_VectTab)); + assert_param(IS_NVIC_OFFSET(Offset)); + + SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80); +} + +/** + * @brief Selects the condition for the system to enter low power mode. + * @param LowPowerMode: Specifies the new mode for the system to enter low power mode. + * This parameter can be one of the following values: + * @arg NVIC_LP_SEVONPEND + * @arg NVIC_LP_SLEEPDEEP + * @arg NVIC_LP_SLEEPONEXIT + * @param NewState: new state of LP condition. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_NVIC_LP(LowPowerMode)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + SCB->SCR |= LowPowerMode; + } + else + { + SCB->SCR &= (uint32_t)(~(uint32_t)LowPowerMode); + } +} + +/** + * @brief Configures the SysTick clock source. + * @param SysTick_CLKSource: specifies the SysTick clock source. + * This parameter can be one of the following values: + * @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source. + * @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source. + * @retval None + */ +void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource) +{ + /* Check the parameters */ + assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource)); + if (SysTick_CLKSource == SysTick_CLKSource_HCLK) + { + SysTick->CTRL |= SysTick_CLKSource_HCLK; + } + else + { + SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8; + } +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/misc.h b/Library/misc.h new file mode 100644 index 0000000..9a6bd07 --- /dev/null +++ b/Library/misc.h @@ -0,0 +1,220 @@ +/** + ****************************************************************************** + * @file misc.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the miscellaneous + * firmware library functions (add-on to CMSIS functions). + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __MISC_H +#define __MISC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup MISC + * @{ + */ + +/** @defgroup MISC_Exported_Types + * @{ + */ + +/** + * @brief NVIC Init Structure definition + */ + +typedef struct +{ + uint8_t NVIC_IRQChannel; /*!< Specifies the IRQ channel to be enabled or disabled. + This parameter can be a value of @ref IRQn_Type + (For the complete STM32 Devices IRQ Channels list, please + refer to stm32f10x.h file) */ + + uint8_t NVIC_IRQChannelPreemptionPriority; /*!< Specifies the pre-emption priority for the IRQ channel + specified in NVIC_IRQChannel. This parameter can be a value + between 0 and 15 as described in the table @ref NVIC_Priority_Table */ + + uint8_t NVIC_IRQChannelSubPriority; /*!< Specifies the subpriority level for the IRQ channel specified + in NVIC_IRQChannel. This parameter can be a value + between 0 and 15 as described in the table @ref NVIC_Priority_Table */ + + FunctionalState NVIC_IRQChannelCmd; /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel + will be enabled or disabled. + This parameter can be set either to ENABLE or DISABLE */ +} NVIC_InitTypeDef; + +/** + * @} + */ + +/** @defgroup NVIC_Priority_Table + * @{ + */ + +/** +@code + The table below gives the allowed values of the pre-emption priority and subpriority according + to the Priority Grouping configuration performed by NVIC_PriorityGroupConfig function + ============================================================================================================================ + NVIC_PriorityGroup | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority | Description + ============================================================================================================================ + NVIC_PriorityGroup_0 | 0 | 0-15 | 0 bits for pre-emption priority + | | | 4 bits for subpriority + ---------------------------------------------------------------------------------------------------------------------------- + NVIC_PriorityGroup_1 | 0-1 | 0-7 | 1 bits for pre-emption priority + | | | 3 bits for subpriority + ---------------------------------------------------------------------------------------------------------------------------- + NVIC_PriorityGroup_2 | 0-3 | 0-3 | 2 bits for pre-emption priority + | | | 2 bits for subpriority + ---------------------------------------------------------------------------------------------------------------------------- + NVIC_PriorityGroup_3 | 0-7 | 0-1 | 3 bits for pre-emption priority + | | | 1 bits for subpriority + ---------------------------------------------------------------------------------------------------------------------------- + NVIC_PriorityGroup_4 | 0-15 | 0 | 4 bits for pre-emption priority + | | | 0 bits for subpriority + ============================================================================================================================ +@endcode +*/ + +/** + * @} + */ + +/** @defgroup MISC_Exported_Constants + * @{ + */ + +/** @defgroup Vector_Table_Base + * @{ + */ + +#define NVIC_VectTab_RAM ((uint32_t)0x20000000) +#define NVIC_VectTab_FLASH ((uint32_t)0x08000000) +#define IS_NVIC_VECTTAB(VECTTAB) (((VECTTAB) == NVIC_VectTab_RAM) || \ + ((VECTTAB) == NVIC_VectTab_FLASH)) +/** + * @} + */ + +/** @defgroup System_Low_Power + * @{ + */ + +#define NVIC_LP_SEVONPEND ((uint8_t)0x10) +#define NVIC_LP_SLEEPDEEP ((uint8_t)0x04) +#define NVIC_LP_SLEEPONEXIT ((uint8_t)0x02) +#define IS_NVIC_LP(LP) (((LP) == NVIC_LP_SEVONPEND) || \ + ((LP) == NVIC_LP_SLEEPDEEP) || \ + ((LP) == NVIC_LP_SLEEPONEXIT)) +/** + * @} + */ + +/** @defgroup Preemption_Priority_Group + * @{ + */ + +#define NVIC_PriorityGroup_0 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority + 4 bits for subpriority */ +#define NVIC_PriorityGroup_1 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority + 3 bits for subpriority */ +#define NVIC_PriorityGroup_2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority + 2 bits for subpriority */ +#define NVIC_PriorityGroup_3 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority + 1 bits for subpriority */ +#define NVIC_PriorityGroup_4 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority + 0 bits for subpriority */ + +#define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PriorityGroup_0) || \ + ((GROUP) == NVIC_PriorityGroup_1) || \ + ((GROUP) == NVIC_PriorityGroup_2) || \ + ((GROUP) == NVIC_PriorityGroup_3) || \ + ((GROUP) == NVIC_PriorityGroup_4)) + +#define IS_NVIC_PREEMPTION_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) + +#define IS_NVIC_SUB_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) + +#define IS_NVIC_OFFSET(OFFSET) ((OFFSET) < 0x000FFFFF) + +/** + * @} + */ + +/** @defgroup SysTick_clock_source + * @{ + */ + +#define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB) +#define SysTick_CLKSource_HCLK ((uint32_t)0x00000004) +#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \ + ((SOURCE) == SysTick_CLKSource_HCLK_Div8)) +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup MISC_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup MISC_Exported_Functions + * @{ + */ + +void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); +void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct); +void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset); +void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState); +void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource); + +#ifdef __cplusplus +} +#endif + +#endif /* __MISC_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_adc.c b/Library/stm32f10x_adc.c new file mode 100644 index 0000000..8155dc9 --- /dev/null +++ b/Library/stm32f10x_adc.c @@ -0,0 +1,1307 @@ +/** + ****************************************************************************** + * @file stm32f10x_adc.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the ADC firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_adc.h" +#include "stm32f10x_rcc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup ADC + * @brief ADC driver modules + * @{ + */ + +/** @defgroup ADC_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup ADC_Private_Defines + * @{ + */ + +/* ADC DISCNUM mask */ +#define CR1_DISCNUM_Reset ((uint32_t)0xFFFF1FFF) + +/* ADC DISCEN mask */ +#define CR1_DISCEN_Set ((uint32_t)0x00000800) +#define CR1_DISCEN_Reset ((uint32_t)0xFFFFF7FF) + +/* ADC JAUTO mask */ +#define CR1_JAUTO_Set ((uint32_t)0x00000400) +#define CR1_JAUTO_Reset ((uint32_t)0xFFFFFBFF) + +/* ADC JDISCEN mask */ +#define CR1_JDISCEN_Set ((uint32_t)0x00001000) +#define CR1_JDISCEN_Reset ((uint32_t)0xFFFFEFFF) + +/* ADC AWDCH mask */ +#define CR1_AWDCH_Reset ((uint32_t)0xFFFFFFE0) + +/* ADC Analog watchdog enable mode mask */ +#define CR1_AWDMode_Reset ((uint32_t)0xFF3FFDFF) + +/* CR1 register Mask */ +#define CR1_CLEAR_Mask ((uint32_t)0xFFF0FEFF) + +/* ADC ADON mask */ +#define CR2_ADON_Set ((uint32_t)0x00000001) +#define CR2_ADON_Reset ((uint32_t)0xFFFFFFFE) + +/* ADC DMA mask */ +#define CR2_DMA_Set ((uint32_t)0x00000100) +#define CR2_DMA_Reset ((uint32_t)0xFFFFFEFF) + +/* ADC RSTCAL mask */ +#define CR2_RSTCAL_Set ((uint32_t)0x00000008) + +/* ADC CAL mask */ +#define CR2_CAL_Set ((uint32_t)0x00000004) + +/* ADC SWSTART mask */ +#define CR2_SWSTART_Set ((uint32_t)0x00400000) + +/* ADC EXTTRIG mask */ +#define CR2_EXTTRIG_Set ((uint32_t)0x00100000) +#define CR2_EXTTRIG_Reset ((uint32_t)0xFFEFFFFF) + +/* ADC Software start mask */ +#define CR2_EXTTRIG_SWSTART_Set ((uint32_t)0x00500000) +#define CR2_EXTTRIG_SWSTART_Reset ((uint32_t)0xFFAFFFFF) + +/* ADC JEXTSEL mask */ +#define CR2_JEXTSEL_Reset ((uint32_t)0xFFFF8FFF) + +/* ADC JEXTTRIG mask */ +#define CR2_JEXTTRIG_Set ((uint32_t)0x00008000) +#define CR2_JEXTTRIG_Reset ((uint32_t)0xFFFF7FFF) + +/* ADC JSWSTART mask */ +#define CR2_JSWSTART_Set ((uint32_t)0x00200000) + +/* ADC injected software start mask */ +#define CR2_JEXTTRIG_JSWSTART_Set ((uint32_t)0x00208000) +#define CR2_JEXTTRIG_JSWSTART_Reset ((uint32_t)0xFFDF7FFF) + +/* ADC TSPD mask */ +#define CR2_TSVREFE_Set ((uint32_t)0x00800000) +#define CR2_TSVREFE_Reset ((uint32_t)0xFF7FFFFF) + +/* CR2 register Mask */ +#define CR2_CLEAR_Mask ((uint32_t)0xFFF1F7FD) + +/* ADC SQx mask */ +#define SQR3_SQ_Set ((uint32_t)0x0000001F) +#define SQR2_SQ_Set ((uint32_t)0x0000001F) +#define SQR1_SQ_Set ((uint32_t)0x0000001F) + +/* SQR1 register Mask */ +#define SQR1_CLEAR_Mask ((uint32_t)0xFF0FFFFF) + +/* ADC JSQx mask */ +#define JSQR_JSQ_Set ((uint32_t)0x0000001F) + +/* ADC JL mask */ +#define JSQR_JL_Set ((uint32_t)0x00300000) +#define JSQR_JL_Reset ((uint32_t)0xFFCFFFFF) + +/* ADC SMPx mask */ +#define SMPR1_SMP_Set ((uint32_t)0x00000007) +#define SMPR2_SMP_Set ((uint32_t)0x00000007) + +/* ADC JDRx registers offset */ +#define JDR_Offset ((uint8_t)0x28) + +/* ADC1 DR register base address */ +#define DR_ADDRESS ((uint32_t)0x4001244C) + +/** + * @} + */ + +/** @defgroup ADC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup ADC_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup ADC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup ADC_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the ADCx peripheral registers to their default reset values. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval None + */ +void ADC_DeInit(ADC_TypeDef* ADCx) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + + if (ADCx == ADC1) + { + /* Enable ADC1 reset state */ + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, ENABLE); + /* Release ADC1 from reset state */ + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, DISABLE); + } + else if (ADCx == ADC2) + { + /* Enable ADC2 reset state */ + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC2, ENABLE); + /* Release ADC2 from reset state */ + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC2, DISABLE); + } + else + { + if (ADCx == ADC3) + { + /* Enable ADC3 reset state */ + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3, ENABLE); + /* Release ADC3 from reset state */ + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3, DISABLE); + } + } +} + +/** + * @brief Initializes the ADCx peripheral according to the specified parameters + * in the ADC_InitStruct. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_InitStruct: pointer to an ADC_InitTypeDef structure that contains + * the configuration information for the specified ADC peripheral. + * @retval None + */ +void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct) +{ + uint32_t tmpreg1 = 0; + uint8_t tmpreg2 = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_MODE(ADC_InitStruct->ADC_Mode)); + assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->ADC_ScanConvMode)); + assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->ADC_ContinuousConvMode)); + assert_param(IS_ADC_EXT_TRIG(ADC_InitStruct->ADC_ExternalTrigConv)); + assert_param(IS_ADC_DATA_ALIGN(ADC_InitStruct->ADC_DataAlign)); + assert_param(IS_ADC_REGULAR_LENGTH(ADC_InitStruct->ADC_NbrOfChannel)); + + /*---------------------------- ADCx CR1 Configuration -----------------*/ + /* Get the ADCx CR1 value */ + tmpreg1 = ADCx->CR1; + /* Clear DUALMOD and SCAN bits */ + tmpreg1 &= CR1_CLEAR_Mask; + /* Configure ADCx: Dual mode and scan conversion mode */ + /* Set DUALMOD bits according to ADC_Mode value */ + /* Set SCAN bit according to ADC_ScanConvMode value */ + tmpreg1 |= (uint32_t)(ADC_InitStruct->ADC_Mode | ((uint32_t)ADC_InitStruct->ADC_ScanConvMode << 8)); + /* Write to ADCx CR1 */ + ADCx->CR1 = tmpreg1; + + /*---------------------------- ADCx CR2 Configuration -----------------*/ + /* Get the ADCx CR2 value */ + tmpreg1 = ADCx->CR2; + /* Clear CONT, ALIGN and EXTSEL bits */ + tmpreg1 &= CR2_CLEAR_Mask; + /* Configure ADCx: external trigger event and continuous conversion mode */ + /* Set ALIGN bit according to ADC_DataAlign value */ + /* Set EXTSEL bits according to ADC_ExternalTrigConv value */ + /* Set CONT bit according to ADC_ContinuousConvMode value */ + tmpreg1 |= (uint32_t)(ADC_InitStruct->ADC_DataAlign | ADC_InitStruct->ADC_ExternalTrigConv | + ((uint32_t)ADC_InitStruct->ADC_ContinuousConvMode << 1)); + /* Write to ADCx CR2 */ + ADCx->CR2 = tmpreg1; + + /*---------------------------- ADCx SQR1 Configuration -----------------*/ + /* Get the ADCx SQR1 value */ + tmpreg1 = ADCx->SQR1; + /* Clear L bits */ + tmpreg1 &= SQR1_CLEAR_Mask; + /* Configure ADCx: regular channel sequence length */ + /* Set L bits according to ADC_NbrOfChannel value */ + tmpreg2 |= (uint8_t) (ADC_InitStruct->ADC_NbrOfChannel - (uint8_t)1); + tmpreg1 |= (uint32_t)tmpreg2 << 20; + /* Write to ADCx SQR1 */ + ADCx->SQR1 = tmpreg1; +} + +/** + * @brief Fills each ADC_InitStruct member with its default value. + * @param ADC_InitStruct : pointer to an ADC_InitTypeDef structure which will be initialized. + * @retval None + */ +void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct) +{ + /* Reset ADC init structure parameters values */ + /* Initialize the ADC_Mode member */ + ADC_InitStruct->ADC_Mode = ADC_Mode_Independent; + /* initialize the ADC_ScanConvMode member */ + ADC_InitStruct->ADC_ScanConvMode = DISABLE; + /* Initialize the ADC_ContinuousConvMode member */ + ADC_InitStruct->ADC_ContinuousConvMode = DISABLE; + /* Initialize the ADC_ExternalTrigConv member */ + ADC_InitStruct->ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; + /* Initialize the ADC_DataAlign member */ + ADC_InitStruct->ADC_DataAlign = ADC_DataAlign_Right; + /* Initialize the ADC_NbrOfChannel member */ + ADC_InitStruct->ADC_NbrOfChannel = 1; +} + +/** + * @brief Enables or disables the specified ADC peripheral. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the ADCx peripheral. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Set the ADON bit to wake up the ADC from power down mode */ + ADCx->CR2 |= CR2_ADON_Set; + } + else + { + /* Disable the selected ADC peripheral */ + ADCx->CR2 &= CR2_ADON_Reset; + } +} + +/** + * @brief Enables or disables the specified ADC DMA request. + * @param ADCx: where x can be 1 or 3 to select the ADC peripheral. + * Note: ADC2 hasn't a DMA capability. + * @param NewState: new state of the selected ADC DMA transfer. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_DMA_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC DMA request */ + ADCx->CR2 |= CR2_DMA_Set; + } + else + { + /* Disable the selected ADC DMA request */ + ADCx->CR2 &= CR2_DMA_Reset; + } +} + +/** + * @brief Enables or disables the specified ADC interrupts. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_IT: specifies the ADC interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg ADC_IT_EOC: End of conversion interrupt mask + * @arg ADC_IT_AWD: Analog watchdog interrupt mask + * @arg ADC_IT_JEOC: End of injected conversion interrupt mask + * @param NewState: new state of the specified ADC interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState) +{ + uint8_t itmask = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + assert_param(IS_ADC_IT(ADC_IT)); + /* Get the ADC IT index */ + itmask = (uint8_t)ADC_IT; + if (NewState != DISABLE) + { + /* Enable the selected ADC interrupts */ + ADCx->CR1 |= itmask; + } + else + { + /* Disable the selected ADC interrupts */ + ADCx->CR1 &= (~(uint32_t)itmask); + } +} + +/** + * @brief Resets the selected ADC calibration registers. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval None + */ +void ADC_ResetCalibration(ADC_TypeDef* ADCx) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + /* Resets the selected ADC calibration registers */ + ADCx->CR2 |= CR2_RSTCAL_Set; +} + +/** + * @brief Gets the selected ADC reset calibration registers status. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval The new state of ADC reset calibration registers (SET or RESET). + */ +FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + /* Check the status of RSTCAL bit */ + if ((ADCx->CR2 & CR2_RSTCAL_Set) != (uint32_t)RESET) + { + /* RSTCAL bit is set */ + bitstatus = SET; + } + else + { + /* RSTCAL bit is reset */ + bitstatus = RESET; + } + /* Return the RSTCAL bit status */ + return bitstatus; +} + +/** + * @brief Starts the selected ADC calibration process. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval None + */ +void ADC_StartCalibration(ADC_TypeDef* ADCx) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + /* Enable the selected ADC calibration process */ + ADCx->CR2 |= CR2_CAL_Set; +} + +/** + * @brief Gets the selected ADC calibration status. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval The new state of ADC calibration (SET or RESET). + */ +FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + /* Check the status of CAL bit */ + if ((ADCx->CR2 & CR2_CAL_Set) != (uint32_t)RESET) + { + /* CAL bit is set: calibration on going */ + bitstatus = SET; + } + else + { + /* CAL bit is reset: end of calibration */ + bitstatus = RESET; + } + /* Return the CAL bit status */ + return bitstatus; +} + +/** + * @brief Enables or disables the selected ADC software start conversion . + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC software start conversion. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC conversion on external event and start the selected + ADC conversion */ + ADCx->CR2 |= CR2_EXTTRIG_SWSTART_Set; + } + else + { + /* Disable the selected ADC conversion on external event and stop the selected + ADC conversion */ + ADCx->CR2 &= CR2_EXTTRIG_SWSTART_Reset; + } +} + +/** + * @brief Gets the selected ADC Software start conversion Status. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval The new state of ADC software start conversion (SET or RESET). + */ +FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + /* Check the status of SWSTART bit */ + if ((ADCx->CR2 & CR2_SWSTART_Set) != (uint32_t)RESET) + { + /* SWSTART bit is set */ + bitstatus = SET; + } + else + { + /* SWSTART bit is reset */ + bitstatus = RESET; + } + /* Return the SWSTART bit status */ + return bitstatus; +} + +/** + * @brief Configures the discontinuous mode for the selected ADC regular + * group channel. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param Number: specifies the discontinuous mode regular channel + * count value. This number must be between 1 and 8. + * @retval None + */ +void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number) +{ + uint32_t tmpreg1 = 0; + uint32_t tmpreg2 = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_REGULAR_DISC_NUMBER(Number)); + /* Get the old register value */ + tmpreg1 = ADCx->CR1; + /* Clear the old discontinuous mode channel count */ + tmpreg1 &= CR1_DISCNUM_Reset; + /* Set the discontinuous mode channel count */ + tmpreg2 = Number - 1; + tmpreg1 |= tmpreg2 << 13; + /* Store the new register value */ + ADCx->CR1 = tmpreg1; +} + +/** + * @brief Enables or disables the discontinuous mode on regular group + * channel for the specified ADC + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC discontinuous mode + * on regular group channel. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC regular discontinuous mode */ + ADCx->CR1 |= CR1_DISCEN_Set; + } + else + { + /* Disable the selected ADC regular discontinuous mode */ + ADCx->CR1 &= CR1_DISCEN_Reset; + } +} + +/** + * @brief Configures for the selected ADC regular channel its corresponding + * rank in the sequencer and its sample time. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_Channel: the ADC channel to configure. + * This parameter can be one of the following values: + * @arg ADC_Channel_0: ADC Channel0 selected + * @arg ADC_Channel_1: ADC Channel1 selected + * @arg ADC_Channel_2: ADC Channel2 selected + * @arg ADC_Channel_3: ADC Channel3 selected + * @arg ADC_Channel_4: ADC Channel4 selected + * @arg ADC_Channel_5: ADC Channel5 selected + * @arg ADC_Channel_6: ADC Channel6 selected + * @arg ADC_Channel_7: ADC Channel7 selected + * @arg ADC_Channel_8: ADC Channel8 selected + * @arg ADC_Channel_9: ADC Channel9 selected + * @arg ADC_Channel_10: ADC Channel10 selected + * @arg ADC_Channel_11: ADC Channel11 selected + * @arg ADC_Channel_12: ADC Channel12 selected + * @arg ADC_Channel_13: ADC Channel13 selected + * @arg ADC_Channel_14: ADC Channel14 selected + * @arg ADC_Channel_15: ADC Channel15 selected + * @arg ADC_Channel_16: ADC Channel16 selected + * @arg ADC_Channel_17: ADC Channel17 selected + * @param Rank: The rank in the regular group sequencer. This parameter must be between 1 to 16. + * @param ADC_SampleTime: The sample time value to be set for the selected channel. + * This parameter can be one of the following values: + * @arg ADC_SampleTime_1Cycles5: Sample time equal to 1.5 cycles + * @arg ADC_SampleTime_7Cycles5: Sample time equal to 7.5 cycles + * @arg ADC_SampleTime_13Cycles5: Sample time equal to 13.5 cycles + * @arg ADC_SampleTime_28Cycles5: Sample time equal to 28.5 cycles + * @arg ADC_SampleTime_41Cycles5: Sample time equal to 41.5 cycles + * @arg ADC_SampleTime_55Cycles5: Sample time equal to 55.5 cycles + * @arg ADC_SampleTime_71Cycles5: Sample time equal to 71.5 cycles + * @arg ADC_SampleTime_239Cycles5: Sample time equal to 239.5 cycles + * @retval None + */ +void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_CHANNEL(ADC_Channel)); + assert_param(IS_ADC_REGULAR_RANK(Rank)); + assert_param(IS_ADC_SAMPLE_TIME(ADC_SampleTime)); + /* if ADC_Channel_10 ... ADC_Channel_17 is selected */ + if (ADC_Channel > ADC_Channel_9) + { + /* Get the old register value */ + tmpreg1 = ADCx->SMPR1; + /* Calculate the mask to clear */ + tmpreg2 = SMPR1_SMP_Set << (3 * (ADC_Channel - 10)); + /* Clear the old channel sample time */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * (ADC_Channel - 10)); + /* Set the new channel sample time */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SMPR1 = tmpreg1; + } + else /* ADC_Channel include in ADC_Channel_[0..9] */ + { + /* Get the old register value */ + tmpreg1 = ADCx->SMPR2; + /* Calculate the mask to clear */ + tmpreg2 = SMPR2_SMP_Set << (3 * ADC_Channel); + /* Clear the old channel sample time */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel); + /* Set the new channel sample time */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SMPR2 = tmpreg1; + } + /* For Rank 1 to 6 */ + if (Rank < 7) + { + /* Get the old register value */ + tmpreg1 = ADCx->SQR3; + /* Calculate the mask to clear */ + tmpreg2 = SQR3_SQ_Set << (5 * (Rank - 1)); + /* Clear the old SQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 1)); + /* Set the SQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SQR3 = tmpreg1; + } + /* For Rank 7 to 12 */ + else if (Rank < 13) + { + /* Get the old register value */ + tmpreg1 = ADCx->SQR2; + /* Calculate the mask to clear */ + tmpreg2 = SQR2_SQ_Set << (5 * (Rank - 7)); + /* Clear the old SQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 7)); + /* Set the SQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SQR2 = tmpreg1; + } + /* For Rank 13 to 16 */ + else + { + /* Get the old register value */ + tmpreg1 = ADCx->SQR1; + /* Calculate the mask to clear */ + tmpreg2 = SQR1_SQ_Set << (5 * (Rank - 13)); + /* Clear the old SQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 13)); + /* Set the SQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SQR1 = tmpreg1; + } +} + +/** + * @brief Enables or disables the ADCx conversion through external trigger. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC external trigger start of conversion. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC conversion on external event */ + ADCx->CR2 |= CR2_EXTTRIG_Set; + } + else + { + /* Disable the selected ADC conversion on external event */ + ADCx->CR2 &= CR2_EXTTRIG_Reset; + } +} + +/** + * @brief Returns the last ADCx conversion result data for regular channel. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval The Data conversion value. + */ +uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + /* Return the selected ADC conversion value */ + return (uint16_t) ADCx->DR; +} + +/** + * @brief Returns the last ADC1 and ADC2 conversion result data in dual mode. + * @retval The Data conversion value. + */ +uint32_t ADC_GetDualModeConversionValue(void) +{ + /* Return the dual mode conversion value */ + return (*(__IO uint32_t *) DR_ADDRESS); +} + +/** + * @brief Enables or disables the selected ADC automatic injected group + * conversion after regular one. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC auto injected conversion + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC automatic injected group conversion */ + ADCx->CR1 |= CR1_JAUTO_Set; + } + else + { + /* Disable the selected ADC automatic injected group conversion */ + ADCx->CR1 &= CR1_JAUTO_Reset; + } +} + +/** + * @brief Enables or disables the discontinuous mode for injected group + * channel for the specified ADC + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC discontinuous mode + * on injected group channel. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC injected discontinuous mode */ + ADCx->CR1 |= CR1_JDISCEN_Set; + } + else + { + /* Disable the selected ADC injected discontinuous mode */ + ADCx->CR1 &= CR1_JDISCEN_Reset; + } +} + +/** + * @brief Configures the ADCx external trigger for injected channels conversion. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_ExternalTrigInjecConv: specifies the ADC trigger to start injected conversion. + * This parameter can be one of the following values: + * @arg ADC_ExternalTrigInjecConv_T1_TRGO: Timer1 TRGO event selected (for ADC1, ADC2 and ADC3) + * @arg ADC_ExternalTrigInjecConv_T1_CC4: Timer1 capture compare4 selected (for ADC1, ADC2 and ADC3) + * @arg ADC_ExternalTrigInjecConv_T2_TRGO: Timer2 TRGO event selected (for ADC1 and ADC2) + * @arg ADC_ExternalTrigInjecConv_T2_CC1: Timer2 capture compare1 selected (for ADC1 and ADC2) + * @arg ADC_ExternalTrigInjecConv_T3_CC4: Timer3 capture compare4 selected (for ADC1 and ADC2) + * @arg ADC_ExternalTrigInjecConv_T4_TRGO: Timer4 TRGO event selected (for ADC1 and ADC2) + * @arg ADC_ExternalTrigInjecConv_Ext_IT15_TIM8_CC4: External interrupt line 15 or Timer8 + * capture compare4 event selected (for ADC1 and ADC2) + * @arg ADC_ExternalTrigInjecConv_T4_CC3: Timer4 capture compare3 selected (for ADC3 only) + * @arg ADC_ExternalTrigInjecConv_T8_CC2: Timer8 capture compare2 selected (for ADC3 only) + * @arg ADC_ExternalTrigInjecConv_T8_CC4: Timer8 capture compare4 selected (for ADC3 only) + * @arg ADC_ExternalTrigInjecConv_T5_TRGO: Timer5 TRGO event selected (for ADC3 only) + * @arg ADC_ExternalTrigInjecConv_T5_CC4: Timer5 capture compare4 selected (for ADC3 only) + * @arg ADC_ExternalTrigInjecConv_None: Injected conversion started by software and not + * by external trigger (for ADC1, ADC2 and ADC3) + * @retval None + */ +void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_EXT_INJEC_TRIG(ADC_ExternalTrigInjecConv)); + /* Get the old register value */ + tmpreg = ADCx->CR2; + /* Clear the old external event selection for injected group */ + tmpreg &= CR2_JEXTSEL_Reset; + /* Set the external event selection for injected group */ + tmpreg |= ADC_ExternalTrigInjecConv; + /* Store the new register value */ + ADCx->CR2 = tmpreg; +} + +/** + * @brief Enables or disables the ADCx injected channels conversion through + * external trigger + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC external trigger start of + * injected conversion. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_ExternalTrigInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC external event selection for injected group */ + ADCx->CR2 |= CR2_JEXTTRIG_Set; + } + else + { + /* Disable the selected ADC external event selection for injected group */ + ADCx->CR2 &= CR2_JEXTTRIG_Reset; + } +} + +/** + * @brief Enables or disables the selected ADC start of the injected + * channels conversion. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC software start injected conversion. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_SoftwareStartInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC conversion for injected group on external event and start the selected + ADC injected conversion */ + ADCx->CR2 |= CR2_JEXTTRIG_JSWSTART_Set; + } + else + { + /* Disable the selected ADC conversion on external event for injected group and stop the selected + ADC injected conversion */ + ADCx->CR2 &= CR2_JEXTTRIG_JSWSTART_Reset; + } +} + +/** + * @brief Gets the selected ADC Software start injected conversion Status. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval The new state of ADC software start injected conversion (SET or RESET). + */ +FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + /* Check the status of JSWSTART bit */ + if ((ADCx->CR2 & CR2_JSWSTART_Set) != (uint32_t)RESET) + { + /* JSWSTART bit is set */ + bitstatus = SET; + } + else + { + /* JSWSTART bit is reset */ + bitstatus = RESET; + } + /* Return the JSWSTART bit status */ + return bitstatus; +} + +/** + * @brief Configures for the selected ADC injected channel its corresponding + * rank in the sequencer and its sample time. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_Channel: the ADC channel to configure. + * This parameter can be one of the following values: + * @arg ADC_Channel_0: ADC Channel0 selected + * @arg ADC_Channel_1: ADC Channel1 selected + * @arg ADC_Channel_2: ADC Channel2 selected + * @arg ADC_Channel_3: ADC Channel3 selected + * @arg ADC_Channel_4: ADC Channel4 selected + * @arg ADC_Channel_5: ADC Channel5 selected + * @arg ADC_Channel_6: ADC Channel6 selected + * @arg ADC_Channel_7: ADC Channel7 selected + * @arg ADC_Channel_8: ADC Channel8 selected + * @arg ADC_Channel_9: ADC Channel9 selected + * @arg ADC_Channel_10: ADC Channel10 selected + * @arg ADC_Channel_11: ADC Channel11 selected + * @arg ADC_Channel_12: ADC Channel12 selected + * @arg ADC_Channel_13: ADC Channel13 selected + * @arg ADC_Channel_14: ADC Channel14 selected + * @arg ADC_Channel_15: ADC Channel15 selected + * @arg ADC_Channel_16: ADC Channel16 selected + * @arg ADC_Channel_17: ADC Channel17 selected + * @param Rank: The rank in the injected group sequencer. This parameter must be between 1 and 4. + * @param ADC_SampleTime: The sample time value to be set for the selected channel. + * This parameter can be one of the following values: + * @arg ADC_SampleTime_1Cycles5: Sample time equal to 1.5 cycles + * @arg ADC_SampleTime_7Cycles5: Sample time equal to 7.5 cycles + * @arg ADC_SampleTime_13Cycles5: Sample time equal to 13.5 cycles + * @arg ADC_SampleTime_28Cycles5: Sample time equal to 28.5 cycles + * @arg ADC_SampleTime_41Cycles5: Sample time equal to 41.5 cycles + * @arg ADC_SampleTime_55Cycles5: Sample time equal to 55.5 cycles + * @arg ADC_SampleTime_71Cycles5: Sample time equal to 71.5 cycles + * @arg ADC_SampleTime_239Cycles5: Sample time equal to 239.5 cycles + * @retval None + */ +void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0, tmpreg3 = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_CHANNEL(ADC_Channel)); + assert_param(IS_ADC_INJECTED_RANK(Rank)); + assert_param(IS_ADC_SAMPLE_TIME(ADC_SampleTime)); + /* if ADC_Channel_10 ... ADC_Channel_17 is selected */ + if (ADC_Channel > ADC_Channel_9) + { + /* Get the old register value */ + tmpreg1 = ADCx->SMPR1; + /* Calculate the mask to clear */ + tmpreg2 = SMPR1_SMP_Set << (3*(ADC_Channel - 10)); + /* Clear the old channel sample time */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3*(ADC_Channel - 10)); + /* Set the new channel sample time */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SMPR1 = tmpreg1; + } + else /* ADC_Channel include in ADC_Channel_[0..9] */ + { + /* Get the old register value */ + tmpreg1 = ADCx->SMPR2; + /* Calculate the mask to clear */ + tmpreg2 = SMPR2_SMP_Set << (3 * ADC_Channel); + /* Clear the old channel sample time */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel); + /* Set the new channel sample time */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SMPR2 = tmpreg1; + } + /* Rank configuration */ + /* Get the old register value */ + tmpreg1 = ADCx->JSQR; + /* Get JL value: Number = JL+1 */ + tmpreg3 = (tmpreg1 & JSQR_JL_Set)>> 20; + /* Calculate the mask to clear: ((Rank-1)+(4-JL-1)) */ + tmpreg2 = JSQR_JSQ_Set << (5 * (uint8_t)((Rank + 3) - (tmpreg3 + 1))); + /* Clear the old JSQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set: ((Rank-1)+(4-JL-1)) */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (uint8_t)((Rank + 3) - (tmpreg3 + 1))); + /* Set the JSQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->JSQR = tmpreg1; +} + +/** + * @brief Configures the sequencer length for injected channels + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param Length: The sequencer length. + * This parameter must be a number between 1 to 4. + * @retval None + */ +void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length) +{ + uint32_t tmpreg1 = 0; + uint32_t tmpreg2 = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_INJECTED_LENGTH(Length)); + + /* Get the old register value */ + tmpreg1 = ADCx->JSQR; + /* Clear the old injected sequnence lenght JL bits */ + tmpreg1 &= JSQR_JL_Reset; + /* Set the injected sequnence lenght JL bits */ + tmpreg2 = Length - 1; + tmpreg1 |= tmpreg2 << 20; + /* Store the new register value */ + ADCx->JSQR = tmpreg1; +} + +/** + * @brief Set the injected channels conversion value offset + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_InjectedChannel: the ADC injected channel to set its offset. + * This parameter can be one of the following values: + * @arg ADC_InjectedChannel_1: Injected Channel1 selected + * @arg ADC_InjectedChannel_2: Injected Channel2 selected + * @arg ADC_InjectedChannel_3: Injected Channel3 selected + * @arg ADC_InjectedChannel_4: Injected Channel4 selected + * @param Offset: the offset value for the selected ADC injected channel + * This parameter must be a 12bit value. + * @retval None + */ +void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_INJECTED_CHANNEL(ADC_InjectedChannel)); + assert_param(IS_ADC_OFFSET(Offset)); + + tmp = (uint32_t)ADCx; + tmp += ADC_InjectedChannel; + + /* Set the selected injected channel data offset */ + *(__IO uint32_t *) tmp = (uint32_t)Offset; +} + +/** + * @brief Returns the ADC injected channel conversion result + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_InjectedChannel: the converted ADC injected channel. + * This parameter can be one of the following values: + * @arg ADC_InjectedChannel_1: Injected Channel1 selected + * @arg ADC_InjectedChannel_2: Injected Channel2 selected + * @arg ADC_InjectedChannel_3: Injected Channel3 selected + * @arg ADC_InjectedChannel_4: Injected Channel4 selected + * @retval The Data conversion value. + */ +uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_INJECTED_CHANNEL(ADC_InjectedChannel)); + + tmp = (uint32_t)ADCx; + tmp += ADC_InjectedChannel + JDR_Offset; + + /* Returns the selected injected channel conversion data value */ + return (uint16_t) (*(__IO uint32_t*) tmp); +} + +/** + * @brief Enables or disables the analog watchdog on single/all regular + * or injected channels + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_AnalogWatchdog: the ADC analog watchdog configuration. + * This parameter can be one of the following values: + * @arg ADC_AnalogWatchdog_SingleRegEnable: Analog watchdog on a single regular channel + * @arg ADC_AnalogWatchdog_SingleInjecEnable: Analog watchdog on a single injected channel + * @arg ADC_AnalogWatchdog_SingleRegOrInjecEnable: Analog watchdog on a single regular or injected channel + * @arg ADC_AnalogWatchdog_AllRegEnable: Analog watchdog on all regular channel + * @arg ADC_AnalogWatchdog_AllInjecEnable: Analog watchdog on all injected channel + * @arg ADC_AnalogWatchdog_AllRegAllInjecEnable: Analog watchdog on all regular and injected channels + * @arg ADC_AnalogWatchdog_None: No channel guarded by the analog watchdog + * @retval None + */ +void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_ANALOG_WATCHDOG(ADC_AnalogWatchdog)); + /* Get the old register value */ + tmpreg = ADCx->CR1; + /* Clear AWDEN, AWDENJ and AWDSGL bits */ + tmpreg &= CR1_AWDMode_Reset; + /* Set the analog watchdog enable mode */ + tmpreg |= ADC_AnalogWatchdog; + /* Store the new register value */ + ADCx->CR1 = tmpreg; +} + +/** + * @brief Configures the high and low thresholds of the analog watchdog. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param HighThreshold: the ADC analog watchdog High threshold value. + * This parameter must be a 12bit value. + * @param LowThreshold: the ADC analog watchdog Low threshold value. + * This parameter must be a 12bit value. + * @retval None + */ +void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, + uint16_t LowThreshold) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_THRESHOLD(HighThreshold)); + assert_param(IS_ADC_THRESHOLD(LowThreshold)); + /* Set the ADCx high threshold */ + ADCx->HTR = HighThreshold; + /* Set the ADCx low threshold */ + ADCx->LTR = LowThreshold; +} + +/** + * @brief Configures the analog watchdog guarded single channel + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_Channel: the ADC channel to configure for the analog watchdog. + * This parameter can be one of the following values: + * @arg ADC_Channel_0: ADC Channel0 selected + * @arg ADC_Channel_1: ADC Channel1 selected + * @arg ADC_Channel_2: ADC Channel2 selected + * @arg ADC_Channel_3: ADC Channel3 selected + * @arg ADC_Channel_4: ADC Channel4 selected + * @arg ADC_Channel_5: ADC Channel5 selected + * @arg ADC_Channel_6: ADC Channel6 selected + * @arg ADC_Channel_7: ADC Channel7 selected + * @arg ADC_Channel_8: ADC Channel8 selected + * @arg ADC_Channel_9: ADC Channel9 selected + * @arg ADC_Channel_10: ADC Channel10 selected + * @arg ADC_Channel_11: ADC Channel11 selected + * @arg ADC_Channel_12: ADC Channel12 selected + * @arg ADC_Channel_13: ADC Channel13 selected + * @arg ADC_Channel_14: ADC Channel14 selected + * @arg ADC_Channel_15: ADC Channel15 selected + * @arg ADC_Channel_16: ADC Channel16 selected + * @arg ADC_Channel_17: ADC Channel17 selected + * @retval None + */ +void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_CHANNEL(ADC_Channel)); + /* Get the old register value */ + tmpreg = ADCx->CR1; + /* Clear the Analog watchdog channel select bits */ + tmpreg &= CR1_AWDCH_Reset; + /* Set the Analog watchdog channel */ + tmpreg |= ADC_Channel; + /* Store the new register value */ + ADCx->CR1 = tmpreg; +} + +/** + * @brief Enables or disables the temperature sensor and Vrefint channel. + * @param NewState: new state of the temperature sensor. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_TempSensorVrefintCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the temperature sensor and Vrefint channel*/ + ADC1->CR2 |= CR2_TSVREFE_Set; + } + else + { + /* Disable the temperature sensor and Vrefint channel*/ + ADC1->CR2 &= CR2_TSVREFE_Reset; + } +} + +/** + * @brief Checks whether the specified ADC flag is set or not. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_FLAG: specifies the flag to check. + * This parameter can be one of the following values: + * @arg ADC_FLAG_AWD: Analog watchdog flag + * @arg ADC_FLAG_EOC: End of conversion flag + * @arg ADC_FLAG_JEOC: End of injected group conversion flag + * @arg ADC_FLAG_JSTRT: Start of injected group conversion flag + * @arg ADC_FLAG_STRT: Start of regular group conversion flag + * @retval The new state of ADC_FLAG (SET or RESET). + */ +FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_GET_FLAG(ADC_FLAG)); + /* Check the status of the specified ADC flag */ + if ((ADCx->SR & ADC_FLAG) != (uint8_t)RESET) + { + /* ADC_FLAG is set */ + bitstatus = SET; + } + else + { + /* ADC_FLAG is reset */ + bitstatus = RESET; + } + /* Return the ADC_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the ADCx's pending flags. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_FLAG: specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg ADC_FLAG_AWD: Analog watchdog flag + * @arg ADC_FLAG_EOC: End of conversion flag + * @arg ADC_FLAG_JEOC: End of injected group conversion flag + * @arg ADC_FLAG_JSTRT: Start of injected group conversion flag + * @arg ADC_FLAG_STRT: Start of regular group conversion flag + * @retval None + */ +void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_CLEAR_FLAG(ADC_FLAG)); + /* Clear the selected ADC flags */ + ADCx->SR = ~(uint32_t)ADC_FLAG; +} + +/** + * @brief Checks whether the specified ADC interrupt has occurred or not. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_IT: specifies the ADC interrupt source to check. + * This parameter can be one of the following values: + * @arg ADC_IT_EOC: End of conversion interrupt mask + * @arg ADC_IT_AWD: Analog watchdog interrupt mask + * @arg ADC_IT_JEOC: End of injected conversion interrupt mask + * @retval The new state of ADC_IT (SET or RESET). + */ +ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT) +{ + ITStatus bitstatus = RESET; + uint32_t itmask = 0, enablestatus = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_GET_IT(ADC_IT)); + /* Get the ADC IT index */ + itmask = ADC_IT >> 8; + /* Get the ADC_IT enable bit status */ + enablestatus = (ADCx->CR1 & (uint8_t)ADC_IT) ; + /* Check the status of the specified ADC interrupt */ + if (((ADCx->SR & itmask) != (uint32_t)RESET) && enablestatus) + { + /* ADC_IT is set */ + bitstatus = SET; + } + else + { + /* ADC_IT is reset */ + bitstatus = RESET; + } + /* Return the ADC_IT status */ + return bitstatus; +} + +/** + * @brief Clears the ADCx's interrupt pending bits. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_IT: specifies the ADC interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg ADC_IT_EOC: End of conversion interrupt mask + * @arg ADC_IT_AWD: Analog watchdog interrupt mask + * @arg ADC_IT_JEOC: End of injected conversion interrupt mask + * @retval None + */ +void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT) +{ + uint8_t itmask = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_IT(ADC_IT)); + /* Get the ADC IT index */ + itmask = (uint8_t)(ADC_IT >> 8); + /* Clear the selected ADC interrupt pending bits */ + ADCx->SR = ~(uint32_t)itmask; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_adc.h b/Library/stm32f10x_adc.h new file mode 100644 index 0000000..c465d33 --- /dev/null +++ b/Library/stm32f10x_adc.h @@ -0,0 +1,483 @@ +/** + ****************************************************************************** + * @file stm32f10x_adc.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the ADC firmware + * library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_ADC_H +#define __STM32F10x_ADC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup ADC + * @{ + */ + +/** @defgroup ADC_Exported_Types + * @{ + */ + +/** + * @brief ADC Init structure definition + */ + +typedef struct +{ + uint32_t ADC_Mode; /*!< Configures the ADC to operate in independent or + dual mode. + This parameter can be a value of @ref ADC_mode */ + + FunctionalState ADC_ScanConvMode; /*!< Specifies whether the conversion is performed in + Scan (multichannels) or Single (one channel) mode. + This parameter can be set to ENABLE or DISABLE */ + + FunctionalState ADC_ContinuousConvMode; /*!< Specifies whether the conversion is performed in + Continuous or Single mode. + This parameter can be set to ENABLE or DISABLE. */ + + uint32_t ADC_ExternalTrigConv; /*!< Defines the external trigger used to start the analog + to digital conversion of regular channels. This parameter + can be a value of @ref ADC_external_trigger_sources_for_regular_channels_conversion */ + + uint32_t ADC_DataAlign; /*!< Specifies whether the ADC data alignment is left or right. + This parameter can be a value of @ref ADC_data_align */ + + uint8_t ADC_NbrOfChannel; /*!< Specifies the number of ADC channels that will be converted + using the sequencer for regular channel group. + This parameter must range from 1 to 16. */ +}ADC_InitTypeDef; +/** + * @} + */ + +/** @defgroup ADC_Exported_Constants + * @{ + */ + +#define IS_ADC_ALL_PERIPH(PERIPH) (((PERIPH) == ADC1) || \ + ((PERIPH) == ADC2) || \ + ((PERIPH) == ADC3)) + +#define IS_ADC_DMA_PERIPH(PERIPH) (((PERIPH) == ADC1) || \ + ((PERIPH) == ADC3)) + +/** @defgroup ADC_mode + * @{ + */ + +#define ADC_Mode_Independent ((uint32_t)0x00000000) +#define ADC_Mode_RegInjecSimult ((uint32_t)0x00010000) +#define ADC_Mode_RegSimult_AlterTrig ((uint32_t)0x00020000) +#define ADC_Mode_InjecSimult_FastInterl ((uint32_t)0x00030000) +#define ADC_Mode_InjecSimult_SlowInterl ((uint32_t)0x00040000) +#define ADC_Mode_InjecSimult ((uint32_t)0x00050000) +#define ADC_Mode_RegSimult ((uint32_t)0x00060000) +#define ADC_Mode_FastInterl ((uint32_t)0x00070000) +#define ADC_Mode_SlowInterl ((uint32_t)0x00080000) +#define ADC_Mode_AlterTrig ((uint32_t)0x00090000) + +#define IS_ADC_MODE(MODE) (((MODE) == ADC_Mode_Independent) || \ + ((MODE) == ADC_Mode_RegInjecSimult) || \ + ((MODE) == ADC_Mode_RegSimult_AlterTrig) || \ + ((MODE) == ADC_Mode_InjecSimult_FastInterl) || \ + ((MODE) == ADC_Mode_InjecSimult_SlowInterl) || \ + ((MODE) == ADC_Mode_InjecSimult) || \ + ((MODE) == ADC_Mode_RegSimult) || \ + ((MODE) == ADC_Mode_FastInterl) || \ + ((MODE) == ADC_Mode_SlowInterl) || \ + ((MODE) == ADC_Mode_AlterTrig)) +/** + * @} + */ + +/** @defgroup ADC_external_trigger_sources_for_regular_channels_conversion + * @{ + */ + +#define ADC_ExternalTrigConv_T1_CC1 ((uint32_t)0x00000000) /*!< For ADC1 and ADC2 */ +#define ADC_ExternalTrigConv_T1_CC2 ((uint32_t)0x00020000) /*!< For ADC1 and ADC2 */ +#define ADC_ExternalTrigConv_T2_CC2 ((uint32_t)0x00060000) /*!< For ADC1 and ADC2 */ +#define ADC_ExternalTrigConv_T3_TRGO ((uint32_t)0x00080000) /*!< For ADC1 and ADC2 */ +#define ADC_ExternalTrigConv_T4_CC4 ((uint32_t)0x000A0000) /*!< For ADC1 and ADC2 */ +#define ADC_ExternalTrigConv_Ext_IT11_TIM8_TRGO ((uint32_t)0x000C0000) /*!< For ADC1 and ADC2 */ + +#define ADC_ExternalTrigConv_T1_CC3 ((uint32_t)0x00040000) /*!< For ADC1, ADC2 and ADC3 */ +#define ADC_ExternalTrigConv_None ((uint32_t)0x000E0000) /*!< For ADC1, ADC2 and ADC3 */ + +#define ADC_ExternalTrigConv_T3_CC1 ((uint32_t)0x00000000) /*!< For ADC3 only */ +#define ADC_ExternalTrigConv_T2_CC3 ((uint32_t)0x00020000) /*!< For ADC3 only */ +#define ADC_ExternalTrigConv_T8_CC1 ((uint32_t)0x00060000) /*!< For ADC3 only */ +#define ADC_ExternalTrigConv_T8_TRGO ((uint32_t)0x00080000) /*!< For ADC3 only */ +#define ADC_ExternalTrigConv_T5_CC1 ((uint32_t)0x000A0000) /*!< For ADC3 only */ +#define ADC_ExternalTrigConv_T5_CC3 ((uint32_t)0x000C0000) /*!< For ADC3 only */ + +#define IS_ADC_EXT_TRIG(REGTRIG) (((REGTRIG) == ADC_ExternalTrigConv_T1_CC1) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T1_CC2) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T1_CC3) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T2_CC2) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T3_TRGO) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T4_CC4) || \ + ((REGTRIG) == ADC_ExternalTrigConv_Ext_IT11_TIM8_TRGO) || \ + ((REGTRIG) == ADC_ExternalTrigConv_None) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T3_CC1) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T2_CC3) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T8_CC1) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T8_TRGO) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T5_CC1) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T5_CC3)) +/** + * @} + */ + +/** @defgroup ADC_data_align + * @{ + */ + +#define ADC_DataAlign_Right ((uint32_t)0x00000000) +#define ADC_DataAlign_Left ((uint32_t)0x00000800) +#define IS_ADC_DATA_ALIGN(ALIGN) (((ALIGN) == ADC_DataAlign_Right) || \ + ((ALIGN) == ADC_DataAlign_Left)) +/** + * @} + */ + +/** @defgroup ADC_channels + * @{ + */ + +#define ADC_Channel_0 ((uint8_t)0x00) +#define ADC_Channel_1 ((uint8_t)0x01) +#define ADC_Channel_2 ((uint8_t)0x02) +#define ADC_Channel_3 ((uint8_t)0x03) +#define ADC_Channel_4 ((uint8_t)0x04) +#define ADC_Channel_5 ((uint8_t)0x05) +#define ADC_Channel_6 ((uint8_t)0x06) +#define ADC_Channel_7 ((uint8_t)0x07) +#define ADC_Channel_8 ((uint8_t)0x08) +#define ADC_Channel_9 ((uint8_t)0x09) +#define ADC_Channel_10 ((uint8_t)0x0A) +#define ADC_Channel_11 ((uint8_t)0x0B) +#define ADC_Channel_12 ((uint8_t)0x0C) +#define ADC_Channel_13 ((uint8_t)0x0D) +#define ADC_Channel_14 ((uint8_t)0x0E) +#define ADC_Channel_15 ((uint8_t)0x0F) +#define ADC_Channel_16 ((uint8_t)0x10) +#define ADC_Channel_17 ((uint8_t)0x11) + +#define ADC_Channel_TempSensor ((uint8_t)ADC_Channel_16) +#define ADC_Channel_Vrefint ((uint8_t)ADC_Channel_17) + +#define IS_ADC_CHANNEL(CHANNEL) (((CHANNEL) == ADC_Channel_0) || ((CHANNEL) == ADC_Channel_1) || \ + ((CHANNEL) == ADC_Channel_2) || ((CHANNEL) == ADC_Channel_3) || \ + ((CHANNEL) == ADC_Channel_4) || ((CHANNEL) == ADC_Channel_5) || \ + ((CHANNEL) == ADC_Channel_6) || ((CHANNEL) == ADC_Channel_7) || \ + ((CHANNEL) == ADC_Channel_8) || ((CHANNEL) == ADC_Channel_9) || \ + ((CHANNEL) == ADC_Channel_10) || ((CHANNEL) == ADC_Channel_11) || \ + ((CHANNEL) == ADC_Channel_12) || ((CHANNEL) == ADC_Channel_13) || \ + ((CHANNEL) == ADC_Channel_14) || ((CHANNEL) == ADC_Channel_15) || \ + ((CHANNEL) == ADC_Channel_16) || ((CHANNEL) == ADC_Channel_17)) +/** + * @} + */ + +/** @defgroup ADC_sampling_time + * @{ + */ + +#define ADC_SampleTime_1Cycles5 ((uint8_t)0x00) +#define ADC_SampleTime_7Cycles5 ((uint8_t)0x01) +#define ADC_SampleTime_13Cycles5 ((uint8_t)0x02) +#define ADC_SampleTime_28Cycles5 ((uint8_t)0x03) +#define ADC_SampleTime_41Cycles5 ((uint8_t)0x04) +#define ADC_SampleTime_55Cycles5 ((uint8_t)0x05) +#define ADC_SampleTime_71Cycles5 ((uint8_t)0x06) +#define ADC_SampleTime_239Cycles5 ((uint8_t)0x07) +#define IS_ADC_SAMPLE_TIME(TIME) (((TIME) == ADC_SampleTime_1Cycles5) || \ + ((TIME) == ADC_SampleTime_7Cycles5) || \ + ((TIME) == ADC_SampleTime_13Cycles5) || \ + ((TIME) == ADC_SampleTime_28Cycles5) || \ + ((TIME) == ADC_SampleTime_41Cycles5) || \ + ((TIME) == ADC_SampleTime_55Cycles5) || \ + ((TIME) == ADC_SampleTime_71Cycles5) || \ + ((TIME) == ADC_SampleTime_239Cycles5)) +/** + * @} + */ + +/** @defgroup ADC_external_trigger_sources_for_injected_channels_conversion + * @{ + */ + +#define ADC_ExternalTrigInjecConv_T2_TRGO ((uint32_t)0x00002000) /*!< For ADC1 and ADC2 */ +#define ADC_ExternalTrigInjecConv_T2_CC1 ((uint32_t)0x00003000) /*!< For ADC1 and ADC2 */ +#define ADC_ExternalTrigInjecConv_T3_CC4 ((uint32_t)0x00004000) /*!< For ADC1 and ADC2 */ +#define ADC_ExternalTrigInjecConv_T4_TRGO ((uint32_t)0x00005000) /*!< For ADC1 and ADC2 */ +#define ADC_ExternalTrigInjecConv_Ext_IT15_TIM8_CC4 ((uint32_t)0x00006000) /*!< For ADC1 and ADC2 */ + +#define ADC_ExternalTrigInjecConv_T1_TRGO ((uint32_t)0x00000000) /*!< For ADC1, ADC2 and ADC3 */ +#define ADC_ExternalTrigInjecConv_T1_CC4 ((uint32_t)0x00001000) /*!< For ADC1, ADC2 and ADC3 */ +#define ADC_ExternalTrigInjecConv_None ((uint32_t)0x00007000) /*!< For ADC1, ADC2 and ADC3 */ + +#define ADC_ExternalTrigInjecConv_T4_CC3 ((uint32_t)0x00002000) /*!< For ADC3 only */ +#define ADC_ExternalTrigInjecConv_T8_CC2 ((uint32_t)0x00003000) /*!< For ADC3 only */ +#define ADC_ExternalTrigInjecConv_T8_CC4 ((uint32_t)0x00004000) /*!< For ADC3 only */ +#define ADC_ExternalTrigInjecConv_T5_TRGO ((uint32_t)0x00005000) /*!< For ADC3 only */ +#define ADC_ExternalTrigInjecConv_T5_CC4 ((uint32_t)0x00006000) /*!< For ADC3 only */ + +#define IS_ADC_EXT_INJEC_TRIG(INJTRIG) (((INJTRIG) == ADC_ExternalTrigInjecConv_T1_TRGO) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T1_CC4) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T2_TRGO) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T2_CC1) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T3_CC4) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_TRGO) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_Ext_IT15_TIM8_CC4) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_None) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_CC3) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T8_CC2) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T8_CC4) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T5_TRGO) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T5_CC4)) +/** + * @} + */ + +/** @defgroup ADC_injected_channel_selection + * @{ + */ + +#define ADC_InjectedChannel_1 ((uint8_t)0x14) +#define ADC_InjectedChannel_2 ((uint8_t)0x18) +#define ADC_InjectedChannel_3 ((uint8_t)0x1C) +#define ADC_InjectedChannel_4 ((uint8_t)0x20) +#define IS_ADC_INJECTED_CHANNEL(CHANNEL) (((CHANNEL) == ADC_InjectedChannel_1) || \ + ((CHANNEL) == ADC_InjectedChannel_2) || \ + ((CHANNEL) == ADC_InjectedChannel_3) || \ + ((CHANNEL) == ADC_InjectedChannel_4)) +/** + * @} + */ + +/** @defgroup ADC_analog_watchdog_selection + * @{ + */ + +#define ADC_AnalogWatchdog_SingleRegEnable ((uint32_t)0x00800200) +#define ADC_AnalogWatchdog_SingleInjecEnable ((uint32_t)0x00400200) +#define ADC_AnalogWatchdog_SingleRegOrInjecEnable ((uint32_t)0x00C00200) +#define ADC_AnalogWatchdog_AllRegEnable ((uint32_t)0x00800000) +#define ADC_AnalogWatchdog_AllInjecEnable ((uint32_t)0x00400000) +#define ADC_AnalogWatchdog_AllRegAllInjecEnable ((uint32_t)0x00C00000) +#define ADC_AnalogWatchdog_None ((uint32_t)0x00000000) + +#define IS_ADC_ANALOG_WATCHDOG(WATCHDOG) (((WATCHDOG) == ADC_AnalogWatchdog_SingleRegEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_SingleInjecEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_SingleRegOrInjecEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_AllRegEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_AllInjecEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_AllRegAllInjecEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_None)) +/** + * @} + */ + +/** @defgroup ADC_interrupts_definition + * @{ + */ + +#define ADC_IT_EOC ((uint16_t)0x0220) +#define ADC_IT_AWD ((uint16_t)0x0140) +#define ADC_IT_JEOC ((uint16_t)0x0480) + +#define IS_ADC_IT(IT) ((((IT) & (uint16_t)0xF81F) == 0x00) && ((IT) != 0x00)) + +#define IS_ADC_GET_IT(IT) (((IT) == ADC_IT_EOC) || ((IT) == ADC_IT_AWD) || \ + ((IT) == ADC_IT_JEOC)) +/** + * @} + */ + +/** @defgroup ADC_flags_definition + * @{ + */ + +#define ADC_FLAG_AWD ((uint8_t)0x01) +#define ADC_FLAG_EOC ((uint8_t)0x02) +#define ADC_FLAG_JEOC ((uint8_t)0x04) +#define ADC_FLAG_JSTRT ((uint8_t)0x08) +#define ADC_FLAG_STRT ((uint8_t)0x10) +#define IS_ADC_CLEAR_FLAG(FLAG) ((((FLAG) & (uint8_t)0xE0) == 0x00) && ((FLAG) != 0x00)) +#define IS_ADC_GET_FLAG(FLAG) (((FLAG) == ADC_FLAG_AWD) || ((FLAG) == ADC_FLAG_EOC) || \ + ((FLAG) == ADC_FLAG_JEOC) || ((FLAG)== ADC_FLAG_JSTRT) || \ + ((FLAG) == ADC_FLAG_STRT)) +/** + * @} + */ + +/** @defgroup ADC_thresholds + * @{ + */ + +#define IS_ADC_THRESHOLD(THRESHOLD) ((THRESHOLD) <= 0xFFF) + +/** + * @} + */ + +/** @defgroup ADC_injected_offset + * @{ + */ + +#define IS_ADC_OFFSET(OFFSET) ((OFFSET) <= 0xFFF) + +/** + * @} + */ + +/** @defgroup ADC_injected_length + * @{ + */ + +#define IS_ADC_INJECTED_LENGTH(LENGTH) (((LENGTH) >= 0x1) && ((LENGTH) <= 0x4)) + +/** + * @} + */ + +/** @defgroup ADC_injected_rank + * @{ + */ + +#define IS_ADC_INJECTED_RANK(RANK) (((RANK) >= 0x1) && ((RANK) <= 0x4)) + +/** + * @} + */ + + +/** @defgroup ADC_regular_length + * @{ + */ + +#define IS_ADC_REGULAR_LENGTH(LENGTH) (((LENGTH) >= 0x1) && ((LENGTH) <= 0x10)) +/** + * @} + */ + +/** @defgroup ADC_regular_rank + * @{ + */ + +#define IS_ADC_REGULAR_RANK(RANK) (((RANK) >= 0x1) && ((RANK) <= 0x10)) + +/** + * @} + */ + +/** @defgroup ADC_regular_discontinuous_mode_number + * @{ + */ + +#define IS_ADC_REGULAR_DISC_NUMBER(NUMBER) (((NUMBER) >= 0x1) && ((NUMBER) <= 0x8)) + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup ADC_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup ADC_Exported_Functions + * @{ + */ + +void ADC_DeInit(ADC_TypeDef* ADCx); +void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct); +void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct); +void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState); +void ADC_ResetCalibration(ADC_TypeDef* ADCx); +FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx); +void ADC_StartCalibration(ADC_TypeDef* ADCx); +FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx); +void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx); +void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number); +void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); +void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx); +uint32_t ADC_GetDualModeConversionValue(void); +void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv); +void ADC_ExternalTrigInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_SoftwareStartInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx); +void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); +void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length); +void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset); +uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel); +void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog); +void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, uint16_t LowThreshold); +void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel); +void ADC_TempSensorVrefintCmd(FunctionalState NewState); +FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG); +void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG); +ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT); +void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT); + +#ifdef __cplusplus +} +#endif + +#endif /*__STM32F10x_ADC_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_bkp.c b/Library/stm32f10x_bkp.c new file mode 100644 index 0000000..997eecc --- /dev/null +++ b/Library/stm32f10x_bkp.c @@ -0,0 +1,308 @@ +/** + ****************************************************************************** + * @file stm32f10x_bkp.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the BKP firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_bkp.h" +#include "stm32f10x_rcc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup BKP + * @brief BKP driver modules + * @{ + */ + +/** @defgroup BKP_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup BKP_Private_Defines + * @{ + */ + +/* ------------ BKP registers bit address in the alias region --------------- */ +#define BKP_OFFSET (BKP_BASE - PERIPH_BASE) + +/* --- CR Register ----*/ + +/* Alias word address of TPAL bit */ +#define CR_OFFSET (BKP_OFFSET + 0x30) +#define TPAL_BitNumber 0x01 +#define CR_TPAL_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (TPAL_BitNumber * 4)) + +/* Alias word address of TPE bit */ +#define TPE_BitNumber 0x00 +#define CR_TPE_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (TPE_BitNumber * 4)) + +/* --- CSR Register ---*/ + +/* Alias word address of TPIE bit */ +#define CSR_OFFSET (BKP_OFFSET + 0x34) +#define TPIE_BitNumber 0x02 +#define CSR_TPIE_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (TPIE_BitNumber * 4)) + +/* Alias word address of TIF bit */ +#define TIF_BitNumber 0x09 +#define CSR_TIF_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (TIF_BitNumber * 4)) + +/* Alias word address of TEF bit */ +#define TEF_BitNumber 0x08 +#define CSR_TEF_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (TEF_BitNumber * 4)) + +/* ---------------------- BKP registers bit mask ------------------------ */ + +/* RTCCR register bit mask */ +#define RTCCR_CAL_MASK ((uint16_t)0xFF80) +#define RTCCR_MASK ((uint16_t)0xFC7F) + +/** + * @} + */ + + +/** @defgroup BKP_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup BKP_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup BKP_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup BKP_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the BKP peripheral registers to their default reset values. + * @param None + * @retval None + */ +void BKP_DeInit(void) +{ + RCC_BackupResetCmd(ENABLE); + RCC_BackupResetCmd(DISABLE); +} + +/** + * @brief Configures the Tamper Pin active level. + * @param BKP_TamperPinLevel: specifies the Tamper Pin active level. + * This parameter can be one of the following values: + * @arg BKP_TamperPinLevel_High: Tamper pin active on high level + * @arg BKP_TamperPinLevel_Low: Tamper pin active on low level + * @retval None + */ +void BKP_TamperPinLevelConfig(uint16_t BKP_TamperPinLevel) +{ + /* Check the parameters */ + assert_param(IS_BKP_TAMPER_PIN_LEVEL(BKP_TamperPinLevel)); + *(__IO uint32_t *) CR_TPAL_BB = BKP_TamperPinLevel; +} + +/** + * @brief Enables or disables the Tamper Pin activation. + * @param NewState: new state of the Tamper Pin activation. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void BKP_TamperPinCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + *(__IO uint32_t *) CR_TPE_BB = (uint32_t)NewState; +} + +/** + * @brief Enables or disables the Tamper Pin Interrupt. + * @param NewState: new state of the Tamper Pin Interrupt. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void BKP_ITConfig(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + *(__IO uint32_t *) CSR_TPIE_BB = (uint32_t)NewState; +} + +/** + * @brief Select the RTC output source to output on the Tamper pin. + * @param BKP_RTCOutputSource: specifies the RTC output source. + * This parameter can be one of the following values: + * @arg BKP_RTCOutputSource_None: no RTC output on the Tamper pin. + * @arg BKP_RTCOutputSource_CalibClock: output the RTC clock with frequency + * divided by 64 on the Tamper pin. + * @arg BKP_RTCOutputSource_Alarm: output the RTC Alarm pulse signal on + * the Tamper pin. + * @arg BKP_RTCOutputSource_Second: output the RTC Second pulse signal on + * the Tamper pin. + * @retval None + */ +void BKP_RTCOutputConfig(uint16_t BKP_RTCOutputSource) +{ + uint16_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_BKP_RTC_OUTPUT_SOURCE(BKP_RTCOutputSource)); + tmpreg = BKP->RTCCR; + /* Clear CCO, ASOE and ASOS bits */ + tmpreg &= RTCCR_MASK; + + /* Set CCO, ASOE and ASOS bits according to BKP_RTCOutputSource value */ + tmpreg |= BKP_RTCOutputSource; + /* Store the new value */ + BKP->RTCCR = tmpreg; +} + +/** + * @brief Sets RTC Clock Calibration value. + * @param CalibrationValue: specifies the RTC Clock Calibration value. + * This parameter must be a number between 0 and 0x7F. + * @retval None + */ +void BKP_SetRTCCalibrationValue(uint8_t CalibrationValue) +{ + uint16_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_BKP_CALIBRATION_VALUE(CalibrationValue)); + tmpreg = BKP->RTCCR; + /* Clear CAL[6:0] bits */ + tmpreg &= RTCCR_CAL_MASK; + /* Set CAL[6:0] bits according to CalibrationValue value */ + tmpreg |= CalibrationValue; + /* Store the new value */ + BKP->RTCCR = tmpreg; +} + +/** + * @brief Writes user data to the specified Data Backup Register. + * @param BKP_DR: specifies the Data Backup Register. + * This parameter can be BKP_DRx where x:[1, 42] + * @param Data: data to write + * @retval None + */ +void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_BKP_DR(BKP_DR)); + + tmp = (uint32_t)BKP_BASE; + tmp += BKP_DR; + + *(__IO uint32_t *) tmp = Data; +} + +/** + * @brief Reads data from the specified Data Backup Register. + * @param BKP_DR: specifies the Data Backup Register. + * This parameter can be BKP_DRx where x:[1, 42] + * @retval The content of the specified Data Backup Register + */ +uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_BKP_DR(BKP_DR)); + + tmp = (uint32_t)BKP_BASE; + tmp += BKP_DR; + + return (*(__IO uint16_t *) tmp); +} + +/** + * @brief Checks whether the Tamper Pin Event flag is set or not. + * @param None + * @retval The new state of the Tamper Pin Event flag (SET or RESET). + */ +FlagStatus BKP_GetFlagStatus(void) +{ + return (FlagStatus)(*(__IO uint32_t *) CSR_TEF_BB); +} + +/** + * @brief Clears Tamper Pin Event pending flag. + * @param None + * @retval None + */ +void BKP_ClearFlag(void) +{ + /* Set CTE bit to clear Tamper Pin Event flag */ + BKP->CSR |= BKP_CSR_CTE; +} + +/** + * @brief Checks whether the Tamper Pin Interrupt has occurred or not. + * @param None + * @retval The new state of the Tamper Pin Interrupt (SET or RESET). + */ +ITStatus BKP_GetITStatus(void) +{ + return (ITStatus)(*(__IO uint32_t *) CSR_TIF_BB); +} + +/** + * @brief Clears Tamper Pin Interrupt pending bit. + * @param None + * @retval None + */ +void BKP_ClearITPendingBit(void) +{ + /* Set CTI bit to clear Tamper Pin Interrupt pending bit */ + BKP->CSR |= BKP_CSR_CTI; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_bkp.h b/Library/stm32f10x_bkp.h new file mode 100644 index 0000000..275c5e1 --- /dev/null +++ b/Library/stm32f10x_bkp.h @@ -0,0 +1,195 @@ +/** + ****************************************************************************** + * @file stm32f10x_bkp.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the BKP firmware + * library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_BKP_H +#define __STM32F10x_BKP_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup BKP + * @{ + */ + +/** @defgroup BKP_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @defgroup BKP_Exported_Constants + * @{ + */ + +/** @defgroup Tamper_Pin_active_level + * @{ + */ + +#define BKP_TamperPinLevel_High ((uint16_t)0x0000) +#define BKP_TamperPinLevel_Low ((uint16_t)0x0001) +#define IS_BKP_TAMPER_PIN_LEVEL(LEVEL) (((LEVEL) == BKP_TamperPinLevel_High) || \ + ((LEVEL) == BKP_TamperPinLevel_Low)) +/** + * @} + */ + +/** @defgroup RTC_output_source_to_output_on_the_Tamper_pin + * @{ + */ + +#define BKP_RTCOutputSource_None ((uint16_t)0x0000) +#define BKP_RTCOutputSource_CalibClock ((uint16_t)0x0080) +#define BKP_RTCOutputSource_Alarm ((uint16_t)0x0100) +#define BKP_RTCOutputSource_Second ((uint16_t)0x0300) +#define IS_BKP_RTC_OUTPUT_SOURCE(SOURCE) (((SOURCE) == BKP_RTCOutputSource_None) || \ + ((SOURCE) == BKP_RTCOutputSource_CalibClock) || \ + ((SOURCE) == BKP_RTCOutputSource_Alarm) || \ + ((SOURCE) == BKP_RTCOutputSource_Second)) +/** + * @} + */ + +/** @defgroup Data_Backup_Register + * @{ + */ + +#define BKP_DR1 ((uint16_t)0x0004) +#define BKP_DR2 ((uint16_t)0x0008) +#define BKP_DR3 ((uint16_t)0x000C) +#define BKP_DR4 ((uint16_t)0x0010) +#define BKP_DR5 ((uint16_t)0x0014) +#define BKP_DR6 ((uint16_t)0x0018) +#define BKP_DR7 ((uint16_t)0x001C) +#define BKP_DR8 ((uint16_t)0x0020) +#define BKP_DR9 ((uint16_t)0x0024) +#define BKP_DR10 ((uint16_t)0x0028) +#define BKP_DR11 ((uint16_t)0x0040) +#define BKP_DR12 ((uint16_t)0x0044) +#define BKP_DR13 ((uint16_t)0x0048) +#define BKP_DR14 ((uint16_t)0x004C) +#define BKP_DR15 ((uint16_t)0x0050) +#define BKP_DR16 ((uint16_t)0x0054) +#define BKP_DR17 ((uint16_t)0x0058) +#define BKP_DR18 ((uint16_t)0x005C) +#define BKP_DR19 ((uint16_t)0x0060) +#define BKP_DR20 ((uint16_t)0x0064) +#define BKP_DR21 ((uint16_t)0x0068) +#define BKP_DR22 ((uint16_t)0x006C) +#define BKP_DR23 ((uint16_t)0x0070) +#define BKP_DR24 ((uint16_t)0x0074) +#define BKP_DR25 ((uint16_t)0x0078) +#define BKP_DR26 ((uint16_t)0x007C) +#define BKP_DR27 ((uint16_t)0x0080) +#define BKP_DR28 ((uint16_t)0x0084) +#define BKP_DR29 ((uint16_t)0x0088) +#define BKP_DR30 ((uint16_t)0x008C) +#define BKP_DR31 ((uint16_t)0x0090) +#define BKP_DR32 ((uint16_t)0x0094) +#define BKP_DR33 ((uint16_t)0x0098) +#define BKP_DR34 ((uint16_t)0x009C) +#define BKP_DR35 ((uint16_t)0x00A0) +#define BKP_DR36 ((uint16_t)0x00A4) +#define BKP_DR37 ((uint16_t)0x00A8) +#define BKP_DR38 ((uint16_t)0x00AC) +#define BKP_DR39 ((uint16_t)0x00B0) +#define BKP_DR40 ((uint16_t)0x00B4) +#define BKP_DR41 ((uint16_t)0x00B8) +#define BKP_DR42 ((uint16_t)0x00BC) + +#define IS_BKP_DR(DR) (((DR) == BKP_DR1) || ((DR) == BKP_DR2) || ((DR) == BKP_DR3) || \ + ((DR) == BKP_DR4) || ((DR) == BKP_DR5) || ((DR) == BKP_DR6) || \ + ((DR) == BKP_DR7) || ((DR) == BKP_DR8) || ((DR) == BKP_DR9) || \ + ((DR) == BKP_DR10) || ((DR) == BKP_DR11) || ((DR) == BKP_DR12) || \ + ((DR) == BKP_DR13) || ((DR) == BKP_DR14) || ((DR) == BKP_DR15) || \ + ((DR) == BKP_DR16) || ((DR) == BKP_DR17) || ((DR) == BKP_DR18) || \ + ((DR) == BKP_DR19) || ((DR) == BKP_DR20) || ((DR) == BKP_DR21) || \ + ((DR) == BKP_DR22) || ((DR) == BKP_DR23) || ((DR) == BKP_DR24) || \ + ((DR) == BKP_DR25) || ((DR) == BKP_DR26) || ((DR) == BKP_DR27) || \ + ((DR) == BKP_DR28) || ((DR) == BKP_DR29) || ((DR) == BKP_DR30) || \ + ((DR) == BKP_DR31) || ((DR) == BKP_DR32) || ((DR) == BKP_DR33) || \ + ((DR) == BKP_DR34) || ((DR) == BKP_DR35) || ((DR) == BKP_DR36) || \ + ((DR) == BKP_DR37) || ((DR) == BKP_DR38) || ((DR) == BKP_DR39) || \ + ((DR) == BKP_DR40) || ((DR) == BKP_DR41) || ((DR) == BKP_DR42)) + +#define IS_BKP_CALIBRATION_VALUE(VALUE) ((VALUE) <= 0x7F) +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup BKP_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup BKP_Exported_Functions + * @{ + */ + +void BKP_DeInit(void); +void BKP_TamperPinLevelConfig(uint16_t BKP_TamperPinLevel); +void BKP_TamperPinCmd(FunctionalState NewState); +void BKP_ITConfig(FunctionalState NewState); +void BKP_RTCOutputConfig(uint16_t BKP_RTCOutputSource); +void BKP_SetRTCCalibrationValue(uint8_t CalibrationValue); +void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data); +uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR); +FlagStatus BKP_GetFlagStatus(void); +void BKP_ClearFlag(void); +ITStatus BKP_GetITStatus(void); +void BKP_ClearITPendingBit(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F10x_BKP_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_can.c b/Library/stm32f10x_can.c new file mode 100644 index 0000000..ec8e049 --- /dev/null +++ b/Library/stm32f10x_can.c @@ -0,0 +1,1415 @@ +/** + ****************************************************************************** + * @file stm32f10x_can.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the CAN firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_can.h" +#include "stm32f10x_rcc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup CAN + * @brief CAN driver modules + * @{ + */ + +/** @defgroup CAN_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup CAN_Private_Defines + * @{ + */ + +/* CAN Master Control Register bits */ + +#define MCR_DBF ((uint32_t)0x00010000) /* software master reset */ + +/* CAN Mailbox Transmit Request */ +#define TMIDxR_TXRQ ((uint32_t)0x00000001) /* Transmit mailbox request */ + +/* CAN Filter Master Register bits */ +#define FMR_FINIT ((uint32_t)0x00000001) /* Filter init mode */ + +/* Time out for INAK bit */ +#define INAK_TIMEOUT ((uint32_t)0x0000FFFF) +/* Time out for SLAK bit */ +#define SLAK_TIMEOUT ((uint32_t)0x0000FFFF) + + + +/* Flags in TSR register */ +#define CAN_FLAGS_TSR ((uint32_t)0x08000000) +/* Flags in RF1R register */ +#define CAN_FLAGS_RF1R ((uint32_t)0x04000000) +/* Flags in RF0R register */ +#define CAN_FLAGS_RF0R ((uint32_t)0x02000000) +/* Flags in MSR register */ +#define CAN_FLAGS_MSR ((uint32_t)0x01000000) +/* Flags in ESR register */ +#define CAN_FLAGS_ESR ((uint32_t)0x00F00000) + +/* Mailboxes definition */ +#define CAN_TXMAILBOX_0 ((uint8_t)0x00) +#define CAN_TXMAILBOX_1 ((uint8_t)0x01) +#define CAN_TXMAILBOX_2 ((uint8_t)0x02) + + + +#define CAN_MODE_MASK ((uint32_t) 0x00000003) +/** + * @} + */ + +/** @defgroup CAN_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup CAN_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup CAN_Private_FunctionPrototypes + * @{ + */ + +static ITStatus CheckITStatus(uint32_t CAN_Reg, uint32_t It_Bit); + +/** + * @} + */ + +/** @defgroup CAN_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the CAN peripheral registers to their default reset values. + * @param CANx: where x can be 1 or 2 to select the CAN peripheral. + * @retval None. + */ +void CAN_DeInit(CAN_TypeDef* CANx) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + if (CANx == CAN1) + { + /* Enable CAN1 reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1, ENABLE); + /* Release CAN1 from reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1, DISABLE); + } + else + { + /* Enable CAN2 reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN2, ENABLE); + /* Release CAN2 from reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN2, DISABLE); + } +} + +/** + * @brief Initializes the CAN peripheral according to the specified + * parameters in the CAN_InitStruct. + * @param CANx: where x can be 1 or 2 to to select the CAN + * peripheral. + * @param CAN_InitStruct: pointer to a CAN_InitTypeDef structure that + * contains the configuration information for the + * CAN peripheral. + * @retval Constant indicates initialization succeed which will be + * CAN_InitStatus_Failed or CAN_InitStatus_Success. + */ +uint8_t CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct) +{ + uint8_t InitStatus = CAN_InitStatus_Failed; + uint32_t wait_ack = 0x00000000; + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_TTCM)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_ABOM)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_AWUM)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_NART)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_RFLM)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_TXFP)); + assert_param(IS_CAN_MODE(CAN_InitStruct->CAN_Mode)); + assert_param(IS_CAN_SJW(CAN_InitStruct->CAN_SJW)); + assert_param(IS_CAN_BS1(CAN_InitStruct->CAN_BS1)); + assert_param(IS_CAN_BS2(CAN_InitStruct->CAN_BS2)); + assert_param(IS_CAN_PRESCALER(CAN_InitStruct->CAN_Prescaler)); + + /* Exit from sleep mode */ + CANx->MCR &= (~(uint32_t)CAN_MCR_SLEEP); + + /* Request initialisation */ + CANx->MCR |= CAN_MCR_INRQ ; + + /* Wait the acknowledge */ + while (((CANx->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) && (wait_ack != INAK_TIMEOUT)) + { + wait_ack++; + } + + /* Check acknowledge */ + if ((CANx->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) + { + InitStatus = CAN_InitStatus_Failed; + } + else + { + /* Set the time triggered communication mode */ + if (CAN_InitStruct->CAN_TTCM == ENABLE) + { + CANx->MCR |= CAN_MCR_TTCM; + } + else + { + CANx->MCR &= ~(uint32_t)CAN_MCR_TTCM; + } + + /* Set the automatic bus-off management */ + if (CAN_InitStruct->CAN_ABOM == ENABLE) + { + CANx->MCR |= CAN_MCR_ABOM; + } + else + { + CANx->MCR &= ~(uint32_t)CAN_MCR_ABOM; + } + + /* Set the automatic wake-up mode */ + if (CAN_InitStruct->CAN_AWUM == ENABLE) + { + CANx->MCR |= CAN_MCR_AWUM; + } + else + { + CANx->MCR &= ~(uint32_t)CAN_MCR_AWUM; + } + + /* Set the no automatic retransmission */ + if (CAN_InitStruct->CAN_NART == ENABLE) + { + CANx->MCR |= CAN_MCR_NART; + } + else + { + CANx->MCR &= ~(uint32_t)CAN_MCR_NART; + } + + /* Set the receive FIFO locked mode */ + if (CAN_InitStruct->CAN_RFLM == ENABLE) + { + CANx->MCR |= CAN_MCR_RFLM; + } + else + { + CANx->MCR &= ~(uint32_t)CAN_MCR_RFLM; + } + + /* Set the transmit FIFO priority */ + if (CAN_InitStruct->CAN_TXFP == ENABLE) + { + CANx->MCR |= CAN_MCR_TXFP; + } + else + { + CANx->MCR &= ~(uint32_t)CAN_MCR_TXFP; + } + + /* Set the bit timing register */ + CANx->BTR = (uint32_t)((uint32_t)CAN_InitStruct->CAN_Mode << 30) | \ + ((uint32_t)CAN_InitStruct->CAN_SJW << 24) | \ + ((uint32_t)CAN_InitStruct->CAN_BS1 << 16) | \ + ((uint32_t)CAN_InitStruct->CAN_BS2 << 20) | \ + ((uint32_t)CAN_InitStruct->CAN_Prescaler - 1); + + /* Request leave initialisation */ + CANx->MCR &= ~(uint32_t)CAN_MCR_INRQ; + + /* Wait the acknowledge */ + wait_ack = 0; + + while (((CANx->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) && (wait_ack != INAK_TIMEOUT)) + { + wait_ack++; + } + + /* ...and check acknowledged */ + if ((CANx->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) + { + InitStatus = CAN_InitStatus_Failed; + } + else + { + InitStatus = CAN_InitStatus_Success ; + } + } + + /* At this step, return the status of initialization */ + return InitStatus; +} + +/** + * @brief Initializes the CAN peripheral according to the specified + * parameters in the CAN_FilterInitStruct. + * @param CAN_FilterInitStruct: pointer to a CAN_FilterInitTypeDef + * structure that contains the configuration + * information. + * @retval None. + */ +void CAN_FilterInit(CAN_FilterInitTypeDef* CAN_FilterInitStruct) +{ + uint32_t filter_number_bit_pos = 0; + /* Check the parameters */ + assert_param(IS_CAN_FILTER_NUMBER(CAN_FilterInitStruct->CAN_FilterNumber)); + assert_param(IS_CAN_FILTER_MODE(CAN_FilterInitStruct->CAN_FilterMode)); + assert_param(IS_CAN_FILTER_SCALE(CAN_FilterInitStruct->CAN_FilterScale)); + assert_param(IS_CAN_FILTER_FIFO(CAN_FilterInitStruct->CAN_FilterFIFOAssignment)); + assert_param(IS_FUNCTIONAL_STATE(CAN_FilterInitStruct->CAN_FilterActivation)); + + filter_number_bit_pos = ((uint32_t)1) << CAN_FilterInitStruct->CAN_FilterNumber; + + /* Initialisation mode for the filter */ + CAN1->FMR |= FMR_FINIT; + + /* Filter Deactivation */ + CAN1->FA1R &= ~(uint32_t)filter_number_bit_pos; + + /* Filter Scale */ + if (CAN_FilterInitStruct->CAN_FilterScale == CAN_FilterScale_16bit) + { + /* 16-bit scale for the filter */ + CAN1->FS1R &= ~(uint32_t)filter_number_bit_pos; + + /* First 16-bit identifier and First 16-bit mask */ + /* Or First 16-bit identifier and Second 16-bit identifier */ + CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR1 = + ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdLow) << 16) | + (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdLow); + + /* Second 16-bit identifier and Second 16-bit mask */ + /* Or Third 16-bit identifier and Fourth 16-bit identifier */ + CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR2 = + ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdHigh) << 16) | + (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdHigh); + } + + if (CAN_FilterInitStruct->CAN_FilterScale == CAN_FilterScale_32bit) + { + /* 32-bit scale for the filter */ + CAN1->FS1R |= filter_number_bit_pos; + /* 32-bit identifier or First 32-bit identifier */ + CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR1 = + ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdHigh) << 16) | + (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdLow); + /* 32-bit mask or Second 32-bit identifier */ + CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR2 = + ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdHigh) << 16) | + (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdLow); + } + + /* Filter Mode */ + if (CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdMask) + { + /*Id/Mask mode for the filter*/ + CAN1->FM1R &= ~(uint32_t)filter_number_bit_pos; + } + else /* CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdList */ + { + /*Identifier list mode for the filter*/ + CAN1->FM1R |= (uint32_t)filter_number_bit_pos; + } + + /* Filter FIFO assignment */ + if (CAN_FilterInitStruct->CAN_FilterFIFOAssignment == CAN_Filter_FIFO0) + { + /* FIFO 0 assignation for the filter */ + CAN1->FFA1R &= ~(uint32_t)filter_number_bit_pos; + } + + if (CAN_FilterInitStruct->CAN_FilterFIFOAssignment == CAN_Filter_FIFO1) + { + /* FIFO 1 assignation for the filter */ + CAN1->FFA1R |= (uint32_t)filter_number_bit_pos; + } + + /* Filter activation */ + if (CAN_FilterInitStruct->CAN_FilterActivation == ENABLE) + { + CAN1->FA1R |= filter_number_bit_pos; + } + + /* Leave the initialisation mode for the filter */ + CAN1->FMR &= ~FMR_FINIT; +} + +/** + * @brief Fills each CAN_InitStruct member with its default value. + * @param CAN_InitStruct: pointer to a CAN_InitTypeDef structure which + * will be initialized. + * @retval None. + */ +void CAN_StructInit(CAN_InitTypeDef* CAN_InitStruct) +{ + /* Reset CAN init structure parameters values */ + + /* Initialize the time triggered communication mode */ + CAN_InitStruct->CAN_TTCM = DISABLE; + + /* Initialize the automatic bus-off management */ + CAN_InitStruct->CAN_ABOM = DISABLE; + + /* Initialize the automatic wake-up mode */ + CAN_InitStruct->CAN_AWUM = DISABLE; + + /* Initialize the no automatic retransmission */ + CAN_InitStruct->CAN_NART = DISABLE; + + /* Initialize the receive FIFO locked mode */ + CAN_InitStruct->CAN_RFLM = DISABLE; + + /* Initialize the transmit FIFO priority */ + CAN_InitStruct->CAN_TXFP = DISABLE; + + /* Initialize the CAN_Mode member */ + CAN_InitStruct->CAN_Mode = CAN_Mode_Normal; + + /* Initialize the CAN_SJW member */ + CAN_InitStruct->CAN_SJW = CAN_SJW_1tq; + + /* Initialize the CAN_BS1 member */ + CAN_InitStruct->CAN_BS1 = CAN_BS1_4tq; + + /* Initialize the CAN_BS2 member */ + CAN_InitStruct->CAN_BS2 = CAN_BS2_3tq; + + /* Initialize the CAN_Prescaler member */ + CAN_InitStruct->CAN_Prescaler = 1; +} + +/** + * @brief Select the start bank filter for slave CAN. + * @note This function applies only to STM32 Connectivity line devices. + * @param CAN_BankNumber: Select the start slave bank filter from 1..27. + * @retval None. + */ +void CAN_SlaveStartBank(uint8_t CAN_BankNumber) +{ + /* Check the parameters */ + assert_param(IS_CAN_BANKNUMBER(CAN_BankNumber)); + + /* Enter Initialisation mode for the filter */ + CAN1->FMR |= FMR_FINIT; + + /* Select the start slave bank */ + CAN1->FMR &= (uint32_t)0xFFFFC0F1 ; + CAN1->FMR |= (uint32_t)(CAN_BankNumber)<<8; + + /* Leave Initialisation mode for the filter */ + CAN1->FMR &= ~FMR_FINIT; +} + +/** + * @brief Enables or disables the DBG Freeze for CAN. + * @param CANx: where x can be 1 or 2 to to select the CAN peripheral. + * @param NewState: new state of the CAN peripheral. This parameter can + * be: ENABLE or DISABLE. + * @retval None. + */ +void CAN_DBGFreeze(CAN_TypeDef* CANx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable Debug Freeze */ + CANx->MCR |= MCR_DBF; + } + else + { + /* Disable Debug Freeze */ + CANx->MCR &= ~MCR_DBF; + } +} + + +/** + * @brief Enables or disabes the CAN Time TriggerOperation communication mode. + * @param CANx: where x can be 1 or 2 to to select the CAN peripheral. + * @param NewState : Mode new state , can be one of @ref FunctionalState. + * @note when enabled, Time stamp (TIME[15:0]) value is sent in the last + * two data bytes of the 8-byte message: TIME[7:0] in data byte 6 + * and TIME[15:8] in data byte 7 + * @note DLC must be programmed as 8 in order Time Stamp (2 bytes) to be + * sent over the CAN bus. + * @retval None + */ +void CAN_TTComModeCmd(CAN_TypeDef* CANx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the TTCM mode */ + CANx->MCR |= CAN_MCR_TTCM; + + /* Set TGT bits */ + CANx->sTxMailBox[0].TDTR |= ((uint32_t)CAN_TDT0R_TGT); + CANx->sTxMailBox[1].TDTR |= ((uint32_t)CAN_TDT1R_TGT); + CANx->sTxMailBox[2].TDTR |= ((uint32_t)CAN_TDT2R_TGT); + } + else + { + /* Disable the TTCM mode */ + CANx->MCR &= (uint32_t)(~(uint32_t)CAN_MCR_TTCM); + + /* Reset TGT bits */ + CANx->sTxMailBox[0].TDTR &= ((uint32_t)~CAN_TDT0R_TGT); + CANx->sTxMailBox[1].TDTR &= ((uint32_t)~CAN_TDT1R_TGT); + CANx->sTxMailBox[2].TDTR &= ((uint32_t)~CAN_TDT2R_TGT); + } +} +/** + * @brief Initiates the transmission of a message. + * @param CANx: where x can be 1 or 2 to to select the CAN peripheral. + * @param TxMessage: pointer to a structure which contains CAN Id, CAN + * DLC and CAN data. + * @retval The number of the mailbox that is used for transmission + * or CAN_TxStatus_NoMailBox if there is no empty mailbox. + */ +uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage) +{ + uint8_t transmit_mailbox = 0; + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_IDTYPE(TxMessage->IDE)); + assert_param(IS_CAN_RTR(TxMessage->RTR)); + assert_param(IS_CAN_DLC(TxMessage->DLC)); + + /* Select one empty transmit mailbox */ + if ((CANx->TSR&CAN_TSR_TME0) == CAN_TSR_TME0) + { + transmit_mailbox = 0; + } + else if ((CANx->TSR&CAN_TSR_TME1) == CAN_TSR_TME1) + { + transmit_mailbox = 1; + } + else if ((CANx->TSR&CAN_TSR_TME2) == CAN_TSR_TME2) + { + transmit_mailbox = 2; + } + else + { + transmit_mailbox = CAN_TxStatus_NoMailBox; + } + + if (transmit_mailbox != CAN_TxStatus_NoMailBox) + { + /* Set up the Id */ + CANx->sTxMailBox[transmit_mailbox].TIR &= TMIDxR_TXRQ; + if (TxMessage->IDE == CAN_Id_Standard) + { + assert_param(IS_CAN_STDID(TxMessage->StdId)); + CANx->sTxMailBox[transmit_mailbox].TIR |= ((TxMessage->StdId << 21) | \ + TxMessage->RTR); + } + else + { + assert_param(IS_CAN_EXTID(TxMessage->ExtId)); + CANx->sTxMailBox[transmit_mailbox].TIR |= ((TxMessage->ExtId << 3) | \ + TxMessage->IDE | \ + TxMessage->RTR); + } + + /* Set up the DLC */ + TxMessage->DLC &= (uint8_t)0x0000000F; + CANx->sTxMailBox[transmit_mailbox].TDTR &= (uint32_t)0xFFFFFFF0; + CANx->sTxMailBox[transmit_mailbox].TDTR |= TxMessage->DLC; + + /* Set up the data field */ + CANx->sTxMailBox[transmit_mailbox].TDLR = (((uint32_t)TxMessage->Data[3] << 24) | + ((uint32_t)TxMessage->Data[2] << 16) | + ((uint32_t)TxMessage->Data[1] << 8) | + ((uint32_t)TxMessage->Data[0])); + CANx->sTxMailBox[transmit_mailbox].TDHR = (((uint32_t)TxMessage->Data[7] << 24) | + ((uint32_t)TxMessage->Data[6] << 16) | + ((uint32_t)TxMessage->Data[5] << 8) | + ((uint32_t)TxMessage->Data[4])); + /* Request transmission */ + CANx->sTxMailBox[transmit_mailbox].TIR |= TMIDxR_TXRQ; + } + return transmit_mailbox; +} + +/** + * @brief Checks the transmission of a message. + * @param CANx: where x can be 1 or 2 to to select the + * CAN peripheral. + * @param TransmitMailbox: the number of the mailbox that is used for + * transmission. + * @retval CAN_TxStatus_Ok if the CAN driver transmits the message, CAN_TxStatus_Failed + * in an other case. + */ +uint8_t CAN_TransmitStatus(CAN_TypeDef* CANx, uint8_t TransmitMailbox) +{ + uint32_t state = 0; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_TRANSMITMAILBOX(TransmitMailbox)); + + switch (TransmitMailbox) + { + case (CAN_TXMAILBOX_0): + state = CANx->TSR & (CAN_TSR_RQCP0 | CAN_TSR_TXOK0 | CAN_TSR_TME0); + break; + case (CAN_TXMAILBOX_1): + state = CANx->TSR & (CAN_TSR_RQCP1 | CAN_TSR_TXOK1 | CAN_TSR_TME1); + break; + case (CAN_TXMAILBOX_2): + state = CANx->TSR & (CAN_TSR_RQCP2 | CAN_TSR_TXOK2 | CAN_TSR_TME2); + break; + default: + state = CAN_TxStatus_Failed; + break; + } + switch (state) + { + /* transmit pending */ + case (0x0): state = CAN_TxStatus_Pending; + break; + /* transmit failed */ + case (CAN_TSR_RQCP0 | CAN_TSR_TME0): state = CAN_TxStatus_Failed; + break; + case (CAN_TSR_RQCP1 | CAN_TSR_TME1): state = CAN_TxStatus_Failed; + break; + case (CAN_TSR_RQCP2 | CAN_TSR_TME2): state = CAN_TxStatus_Failed; + break; + /* transmit succeeded */ + case (CAN_TSR_RQCP0 | CAN_TSR_TXOK0 | CAN_TSR_TME0):state = CAN_TxStatus_Ok; + break; + case (CAN_TSR_RQCP1 | CAN_TSR_TXOK1 | CAN_TSR_TME1):state = CAN_TxStatus_Ok; + break; + case (CAN_TSR_RQCP2 | CAN_TSR_TXOK2 | CAN_TSR_TME2):state = CAN_TxStatus_Ok; + break; + default: state = CAN_TxStatus_Failed; + break; + } + return (uint8_t) state; +} + +/** + * @brief Cancels a transmit request. + * @param CANx: where x can be 1 or 2 to to select the CAN peripheral. + * @param Mailbox: Mailbox number. + * @retval None. + */ +void CAN_CancelTransmit(CAN_TypeDef* CANx, uint8_t Mailbox) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_TRANSMITMAILBOX(Mailbox)); + /* abort transmission */ + switch (Mailbox) + { + case (CAN_TXMAILBOX_0): CANx->TSR |= CAN_TSR_ABRQ0; + break; + case (CAN_TXMAILBOX_1): CANx->TSR |= CAN_TSR_ABRQ1; + break; + case (CAN_TXMAILBOX_2): CANx->TSR |= CAN_TSR_ABRQ2; + break; + default: + break; + } +} + + +/** + * @brief Receives a message. + * @param CANx: where x can be 1 or 2 to to select the CAN peripheral. + * @param FIFONumber: Receive FIFO number, CAN_FIFO0 or CAN_FIFO1. + * @param RxMessage: pointer to a structure receive message which contains + * CAN Id, CAN DLC, CAN datas and FMI number. + * @retval None. + */ +void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_FIFO(FIFONumber)); + /* Get the Id */ + RxMessage->IDE = (uint8_t)0x04 & CANx->sFIFOMailBox[FIFONumber].RIR; + if (RxMessage->IDE == CAN_Id_Standard) + { + RxMessage->StdId = (uint32_t)0x000007FF & (CANx->sFIFOMailBox[FIFONumber].RIR >> 21); + } + else + { + RxMessage->ExtId = (uint32_t)0x1FFFFFFF & (CANx->sFIFOMailBox[FIFONumber].RIR >> 3); + } + + RxMessage->RTR = (uint8_t)0x02 & CANx->sFIFOMailBox[FIFONumber].RIR; + /* Get the DLC */ + RxMessage->DLC = (uint8_t)0x0F & CANx->sFIFOMailBox[FIFONumber].RDTR; + /* Get the FMI */ + RxMessage->FMI = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDTR >> 8); + /* Get the data field */ + RxMessage->Data[0] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONumber].RDLR; + RxMessage->Data[1] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 8); + RxMessage->Data[2] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 16); + RxMessage->Data[3] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 24); + RxMessage->Data[4] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONumber].RDHR; + RxMessage->Data[5] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 8); + RxMessage->Data[6] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 16); + RxMessage->Data[7] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 24); + /* Release the FIFO */ + /* Release FIFO0 */ + if (FIFONumber == CAN_FIFO0) + { + CANx->RF0R |= CAN_RF0R_RFOM0; + } + /* Release FIFO1 */ + else /* FIFONumber == CAN_FIFO1 */ + { + CANx->RF1R |= CAN_RF1R_RFOM1; + } +} + +/** + * @brief Releases the specified FIFO. + * @param CANx: where x can be 1 or 2 to to select the CAN peripheral. + * @param FIFONumber: FIFO to release, CAN_FIFO0 or CAN_FIFO1. + * @retval None. + */ +void CAN_FIFORelease(CAN_TypeDef* CANx, uint8_t FIFONumber) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_FIFO(FIFONumber)); + /* Release FIFO0 */ + if (FIFONumber == CAN_FIFO0) + { + CANx->RF0R |= CAN_RF0R_RFOM0; + } + /* Release FIFO1 */ + else /* FIFONumber == CAN_FIFO1 */ + { + CANx->RF1R |= CAN_RF1R_RFOM1; + } +} + +/** + * @brief Returns the number of pending messages. + * @param CANx: where x can be 1 or 2 to to select the CAN peripheral. + * @param FIFONumber: Receive FIFO number, CAN_FIFO0 or CAN_FIFO1. + * @retval NbMessage : which is the number of pending message. + */ +uint8_t CAN_MessagePending(CAN_TypeDef* CANx, uint8_t FIFONumber) +{ + uint8_t message_pending=0; + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_FIFO(FIFONumber)); + if (FIFONumber == CAN_FIFO0) + { + message_pending = (uint8_t)(CANx->RF0R&(uint32_t)0x03); + } + else if (FIFONumber == CAN_FIFO1) + { + message_pending = (uint8_t)(CANx->RF1R&(uint32_t)0x03); + } + else + { + message_pending = 0; + } + return message_pending; +} + + +/** + * @brief Select the CAN Operation mode. + * @param CAN_OperatingMode : CAN Operating Mode. This parameter can be one + * of @ref CAN_OperatingMode_TypeDef enumeration. + * @retval status of the requested mode which can be + * - CAN_ModeStatus_Failed CAN failed entering the specific mode + * - CAN_ModeStatus_Success CAN Succeed entering the specific mode + + */ +uint8_t CAN_OperatingModeRequest(CAN_TypeDef* CANx, uint8_t CAN_OperatingMode) +{ + uint8_t status = CAN_ModeStatus_Failed; + + /* Timeout for INAK or also for SLAK bits*/ + uint32_t timeout = INAK_TIMEOUT; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_OPERATING_MODE(CAN_OperatingMode)); + + if (CAN_OperatingMode == CAN_OperatingMode_Initialization) + { + /* Request initialisation */ + CANx->MCR = (uint32_t)((CANx->MCR & (uint32_t)(~(uint32_t)CAN_MCR_SLEEP)) | CAN_MCR_INRQ); + + /* Wait the acknowledge */ + while (((CANx->MSR & CAN_MODE_MASK) != CAN_MSR_INAK) && (timeout != 0)) + { + timeout--; + } + if ((CANx->MSR & CAN_MODE_MASK) != CAN_MSR_INAK) + { + status = CAN_ModeStatus_Failed; + } + else + { + status = CAN_ModeStatus_Success; + } + } + else if (CAN_OperatingMode == CAN_OperatingMode_Normal) + { + /* Request leave initialisation and sleep mode and enter Normal mode */ + CANx->MCR &= (uint32_t)(~(CAN_MCR_SLEEP|CAN_MCR_INRQ)); + + /* Wait the acknowledge */ + while (((CANx->MSR & CAN_MODE_MASK) != 0) && (timeout!=0)) + { + timeout--; + } + if ((CANx->MSR & CAN_MODE_MASK) != 0) + { + status = CAN_ModeStatus_Failed; + } + else + { + status = CAN_ModeStatus_Success; + } + } + else if (CAN_OperatingMode == CAN_OperatingMode_Sleep) + { + /* Request Sleep mode */ + CANx->MCR = (uint32_t)((CANx->MCR & (uint32_t)(~(uint32_t)CAN_MCR_INRQ)) | CAN_MCR_SLEEP); + + /* Wait the acknowledge */ + while (((CANx->MSR & CAN_MODE_MASK) != CAN_MSR_SLAK) && (timeout!=0)) + { + timeout--; + } + if ((CANx->MSR & CAN_MODE_MASK) != CAN_MSR_SLAK) + { + status = CAN_ModeStatus_Failed; + } + else + { + status = CAN_ModeStatus_Success; + } + } + else + { + status = CAN_ModeStatus_Failed; + } + + return (uint8_t) status; +} + +/** + * @brief Enters the low power mode. + * @param CANx: where x can be 1 or 2 to to select the CAN peripheral. + * @retval status: CAN_Sleep_Ok if sleep entered, CAN_Sleep_Failed in an + * other case. + */ +uint8_t CAN_Sleep(CAN_TypeDef* CANx) +{ + uint8_t sleepstatus = CAN_Sleep_Failed; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + /* Request Sleep mode */ + CANx->MCR = (((CANx->MCR) & (uint32_t)(~(uint32_t)CAN_MCR_INRQ)) | CAN_MCR_SLEEP); + + /* Sleep mode status */ + if ((CANx->MSR & (CAN_MSR_SLAK|CAN_MSR_INAK)) == CAN_MSR_SLAK) + { + /* Sleep mode not entered */ + sleepstatus = CAN_Sleep_Ok; + } + /* return sleep mode status */ + return (uint8_t)sleepstatus; +} + +/** + * @brief Wakes the CAN up. + * @param CANx: where x can be 1 or 2 to to select the CAN peripheral. + * @retval status: CAN_WakeUp_Ok if sleep mode left, CAN_WakeUp_Failed in an + * other case. + */ +uint8_t CAN_WakeUp(CAN_TypeDef* CANx) +{ + uint32_t wait_slak = SLAK_TIMEOUT; + uint8_t wakeupstatus = CAN_WakeUp_Failed; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + /* Wake up request */ + CANx->MCR &= ~(uint32_t)CAN_MCR_SLEEP; + + /* Sleep mode status */ + while(((CANx->MSR & CAN_MSR_SLAK) == CAN_MSR_SLAK)&&(wait_slak!=0x00)) + { + wait_slak--; + } + if((CANx->MSR & CAN_MSR_SLAK) != CAN_MSR_SLAK) + { + /* wake up done : Sleep mode exited */ + wakeupstatus = CAN_WakeUp_Ok; + } + /* return wakeup status */ + return (uint8_t)wakeupstatus; +} + + +/** + * @brief Returns the CANx's last error code (LEC). + * @param CANx: where x can be 1 or 2 to to select the CAN peripheral. + * @retval CAN_ErrorCode: specifies the Error code : + * - CAN_ERRORCODE_NoErr No Error + * - CAN_ERRORCODE_StuffErr Stuff Error + * - CAN_ERRORCODE_FormErr Form Error + * - CAN_ERRORCODE_ACKErr Acknowledgment Error + * - CAN_ERRORCODE_BitRecessiveErr Bit Recessive Error + * - CAN_ERRORCODE_BitDominantErr Bit Dominant Error + * - CAN_ERRORCODE_CRCErr CRC Error + * - CAN_ERRORCODE_SoftwareSetErr Software Set Error + */ + +uint8_t CAN_GetLastErrorCode(CAN_TypeDef* CANx) +{ + uint8_t errorcode=0; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + /* Get the error code*/ + errorcode = (((uint8_t)CANx->ESR) & (uint8_t)CAN_ESR_LEC); + + /* Return the error code*/ + return errorcode; +} +/** + * @brief Returns the CANx Receive Error Counter (REC). + * @note In case of an error during reception, this counter is incremented + * by 1 or by 8 depending on the error condition as defined by the CAN + * standard. After every successful reception, the counter is + * decremented by 1 or reset to 120 if its value was higher than 128. + * When the counter value exceeds 127, the CAN controller enters the + * error passive state. + * @param CANx: where x can be 1 or 2 to to select the CAN peripheral. + * @retval CAN Receive Error Counter. + */ +uint8_t CAN_GetReceiveErrorCounter(CAN_TypeDef* CANx) +{ + uint8_t counter=0; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + /* Get the Receive Error Counter*/ + counter = (uint8_t)((CANx->ESR & CAN_ESR_REC)>> 24); + + /* Return the Receive Error Counter*/ + return counter; +} + + +/** + * @brief Returns the LSB of the 9-bit CANx Transmit Error Counter(TEC). + * @param CANx: where x can be 1 or 2 to to select the CAN peripheral. + * @retval LSB of the 9-bit CAN Transmit Error Counter. + */ +uint8_t CAN_GetLSBTransmitErrorCounter(CAN_TypeDef* CANx) +{ + uint8_t counter=0; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + /* Get the LSB of the 9-bit CANx Transmit Error Counter(TEC) */ + counter = (uint8_t)((CANx->ESR & CAN_ESR_TEC)>> 16); + + /* Return the LSB of the 9-bit CANx Transmit Error Counter(TEC) */ + return counter; +} + + +/** + * @brief Enables or disables the specified CANx interrupts. + * @param CANx: where x can be 1 or 2 to to select the CAN peripheral. + * @param CAN_IT: specifies the CAN interrupt sources to be enabled or disabled. + * This parameter can be: + * - CAN_IT_TME, + * - CAN_IT_FMP0, + * - CAN_IT_FF0, + * - CAN_IT_FOV0, + * - CAN_IT_FMP1, + * - CAN_IT_FF1, + * - CAN_IT_FOV1, + * - CAN_IT_EWG, + * - CAN_IT_EPV, + * - CAN_IT_LEC, + * - CAN_IT_ERR, + * - CAN_IT_WKU or + * - CAN_IT_SLK. + * @param NewState: new state of the CAN interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None. + */ +void CAN_ITConfig(CAN_TypeDef* CANx, uint32_t CAN_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_IT(CAN_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected CANx interrupt */ + CANx->IER |= CAN_IT; + } + else + { + /* Disable the selected CANx interrupt */ + CANx->IER &= ~CAN_IT; + } +} +/** + * @brief Checks whether the specified CAN flag is set or not. + * @param CANx: where x can be 1 or 2 to to select the CAN peripheral. + * @param CAN_FLAG: specifies the flag to check. + * This parameter can be one of the following flags: + * - CAN_FLAG_EWG + * - CAN_FLAG_EPV + * - CAN_FLAG_BOF + * - CAN_FLAG_RQCP0 + * - CAN_FLAG_RQCP1 + * - CAN_FLAG_RQCP2 + * - CAN_FLAG_FMP1 + * - CAN_FLAG_FF1 + * - CAN_FLAG_FOV1 + * - CAN_FLAG_FMP0 + * - CAN_FLAG_FF0 + * - CAN_FLAG_FOV0 + * - CAN_FLAG_WKU + * - CAN_FLAG_SLAK + * - CAN_FLAG_LEC + * @retval The new state of CAN_FLAG (SET or RESET). + */ +FlagStatus CAN_GetFlagStatus(CAN_TypeDef* CANx, uint32_t CAN_FLAG) +{ + FlagStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_GET_FLAG(CAN_FLAG)); + + + if((CAN_FLAG & CAN_FLAGS_ESR) != (uint32_t)RESET) + { + /* Check the status of the specified CAN flag */ + if ((CANx->ESR & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + /* CAN_FLAG is set */ + bitstatus = SET; + } + else + { + /* CAN_FLAG is reset */ + bitstatus = RESET; + } + } + else if((CAN_FLAG & CAN_FLAGS_MSR) != (uint32_t)RESET) + { + /* Check the status of the specified CAN flag */ + if ((CANx->MSR & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + /* CAN_FLAG is set */ + bitstatus = SET; + } + else + { + /* CAN_FLAG is reset */ + bitstatus = RESET; + } + } + else if((CAN_FLAG & CAN_FLAGS_TSR) != (uint32_t)RESET) + { + /* Check the status of the specified CAN flag */ + if ((CANx->TSR & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + /* CAN_FLAG is set */ + bitstatus = SET; + } + else + { + /* CAN_FLAG is reset */ + bitstatus = RESET; + } + } + else if((CAN_FLAG & CAN_FLAGS_RF0R) != (uint32_t)RESET) + { + /* Check the status of the specified CAN flag */ + if ((CANx->RF0R & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + /* CAN_FLAG is set */ + bitstatus = SET; + } + else + { + /* CAN_FLAG is reset */ + bitstatus = RESET; + } + } + else /* If(CAN_FLAG & CAN_FLAGS_RF1R != (uint32_t)RESET) */ + { + /* Check the status of the specified CAN flag */ + if ((uint32_t)(CANx->RF1R & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + /* CAN_FLAG is set */ + bitstatus = SET; + } + else + { + /* CAN_FLAG is reset */ + bitstatus = RESET; + } + } + /* Return the CAN_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the CAN's pending flags. + * @param CANx: where x can be 1 or 2 to to select the CAN peripheral. + * @param CAN_FLAG: specifies the flag to clear. + * This parameter can be one of the following flags: + * - CAN_FLAG_RQCP0 + * - CAN_FLAG_RQCP1 + * - CAN_FLAG_RQCP2 + * - CAN_FLAG_FF1 + * - CAN_FLAG_FOV1 + * - CAN_FLAG_FF0 + * - CAN_FLAG_FOV0 + * - CAN_FLAG_WKU + * - CAN_FLAG_SLAK + * - CAN_FLAG_LEC + * @retval None. + */ +void CAN_ClearFlag(CAN_TypeDef* CANx, uint32_t CAN_FLAG) +{ + uint32_t flagtmp=0; + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_CLEAR_FLAG(CAN_FLAG)); + + if (CAN_FLAG == CAN_FLAG_LEC) /* ESR register */ + { + /* Clear the selected CAN flags */ + CANx->ESR = (uint32_t)RESET; + } + else /* MSR or TSR or RF0R or RF1R */ + { + flagtmp = CAN_FLAG & 0x000FFFFF; + + if ((CAN_FLAG & CAN_FLAGS_RF0R)!=(uint32_t)RESET) + { + /* Receive Flags */ + CANx->RF0R = (uint32_t)(flagtmp); + } + else if ((CAN_FLAG & CAN_FLAGS_RF1R)!=(uint32_t)RESET) + { + /* Receive Flags */ + CANx->RF1R = (uint32_t)(flagtmp); + } + else if ((CAN_FLAG & CAN_FLAGS_TSR)!=(uint32_t)RESET) + { + /* Transmit Flags */ + CANx->TSR = (uint32_t)(flagtmp); + } + else /* If((CAN_FLAG & CAN_FLAGS_MSR)!=(uint32_t)RESET) */ + { + /* Operating mode Flags */ + CANx->MSR = (uint32_t)(flagtmp); + } + } +} + +/** + * @brief Checks whether the specified CANx interrupt has occurred or not. + * @param CANx: where x can be 1 or 2 to to select the CAN peripheral. + * @param CAN_IT: specifies the CAN interrupt source to check. + * This parameter can be one of the following flags: + * - CAN_IT_TME + * - CAN_IT_FMP0 + * - CAN_IT_FF0 + * - CAN_IT_FOV0 + * - CAN_IT_FMP1 + * - CAN_IT_FF1 + * - CAN_IT_FOV1 + * - CAN_IT_WKU + * - CAN_IT_SLK + * - CAN_IT_EWG + * - CAN_IT_EPV + * - CAN_IT_BOF + * - CAN_IT_LEC + * - CAN_IT_ERR + * @retval The current state of CAN_IT (SET or RESET). + */ +ITStatus CAN_GetITStatus(CAN_TypeDef* CANx, uint32_t CAN_IT) +{ + ITStatus itstatus = RESET; + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_IT(CAN_IT)); + + /* check the enable interrupt bit */ + if((CANx->IER & CAN_IT) != RESET) + { + /* in case the Interrupt is enabled, .... */ + switch (CAN_IT) + { + case CAN_IT_TME: + /* Check CAN_TSR_RQCPx bits */ + itstatus = CheckITStatus(CANx->TSR, CAN_TSR_RQCP0|CAN_TSR_RQCP1|CAN_TSR_RQCP2); + break; + case CAN_IT_FMP0: + /* Check CAN_RF0R_FMP0 bit */ + itstatus = CheckITStatus(CANx->RF0R, CAN_RF0R_FMP0); + break; + case CAN_IT_FF0: + /* Check CAN_RF0R_FULL0 bit */ + itstatus = CheckITStatus(CANx->RF0R, CAN_RF0R_FULL0); + break; + case CAN_IT_FOV0: + /* Check CAN_RF0R_FOVR0 bit */ + itstatus = CheckITStatus(CANx->RF0R, CAN_RF0R_FOVR0); + break; + case CAN_IT_FMP1: + /* Check CAN_RF1R_FMP1 bit */ + itstatus = CheckITStatus(CANx->RF1R, CAN_RF1R_FMP1); + break; + case CAN_IT_FF1: + /* Check CAN_RF1R_FULL1 bit */ + itstatus = CheckITStatus(CANx->RF1R, CAN_RF1R_FULL1); + break; + case CAN_IT_FOV1: + /* Check CAN_RF1R_FOVR1 bit */ + itstatus = CheckITStatus(CANx->RF1R, CAN_RF1R_FOVR1); + break; + case CAN_IT_WKU: + /* Check CAN_MSR_WKUI bit */ + itstatus = CheckITStatus(CANx->MSR, CAN_MSR_WKUI); + break; + case CAN_IT_SLK: + /* Check CAN_MSR_SLAKI bit */ + itstatus = CheckITStatus(CANx->MSR, CAN_MSR_SLAKI); + break; + case CAN_IT_EWG: + /* Check CAN_ESR_EWGF bit */ + itstatus = CheckITStatus(CANx->ESR, CAN_ESR_EWGF); + break; + case CAN_IT_EPV: + /* Check CAN_ESR_EPVF bit */ + itstatus = CheckITStatus(CANx->ESR, CAN_ESR_EPVF); + break; + case CAN_IT_BOF: + /* Check CAN_ESR_BOFF bit */ + itstatus = CheckITStatus(CANx->ESR, CAN_ESR_BOFF); + break; + case CAN_IT_LEC: + /* Check CAN_ESR_LEC bit */ + itstatus = CheckITStatus(CANx->ESR, CAN_ESR_LEC); + break; + case CAN_IT_ERR: + /* Check CAN_MSR_ERRI bit */ + itstatus = CheckITStatus(CANx->MSR, CAN_MSR_ERRI); + break; + default : + /* in case of error, return RESET */ + itstatus = RESET; + break; + } + } + else + { + /* in case the Interrupt is not enabled, return RESET */ + itstatus = RESET; + } + + /* Return the CAN_IT status */ + return itstatus; +} + +/** + * @brief Clears the CANx's interrupt pending bits. + * @param CANx: where x can be 1 or 2 to to select the CAN peripheral. + * @param CAN_IT: specifies the interrupt pending bit to clear. + * - CAN_IT_TME + * - CAN_IT_FF0 + * - CAN_IT_FOV0 + * - CAN_IT_FF1 + * - CAN_IT_FOV1 + * - CAN_IT_WKU + * - CAN_IT_SLK + * - CAN_IT_EWG + * - CAN_IT_EPV + * - CAN_IT_BOF + * - CAN_IT_LEC + * - CAN_IT_ERR + * @retval None. + */ +void CAN_ClearITPendingBit(CAN_TypeDef* CANx, uint32_t CAN_IT) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_CLEAR_IT(CAN_IT)); + + switch (CAN_IT) + { + case CAN_IT_TME: + /* Clear CAN_TSR_RQCPx (rc_w1)*/ + CANx->TSR = CAN_TSR_RQCP0|CAN_TSR_RQCP1|CAN_TSR_RQCP2; + break; + case CAN_IT_FF0: + /* Clear CAN_RF0R_FULL0 (rc_w1)*/ + CANx->RF0R = CAN_RF0R_FULL0; + break; + case CAN_IT_FOV0: + /* Clear CAN_RF0R_FOVR0 (rc_w1)*/ + CANx->RF0R = CAN_RF0R_FOVR0; + break; + case CAN_IT_FF1: + /* Clear CAN_RF1R_FULL1 (rc_w1)*/ + CANx->RF1R = CAN_RF1R_FULL1; + break; + case CAN_IT_FOV1: + /* Clear CAN_RF1R_FOVR1 (rc_w1)*/ + CANx->RF1R = CAN_RF1R_FOVR1; + break; + case CAN_IT_WKU: + /* Clear CAN_MSR_WKUI (rc_w1)*/ + CANx->MSR = CAN_MSR_WKUI; + break; + case CAN_IT_SLK: + /* Clear CAN_MSR_SLAKI (rc_w1)*/ + CANx->MSR = CAN_MSR_SLAKI; + break; + case CAN_IT_EWG: + /* Clear CAN_MSR_ERRI (rc_w1) */ + CANx->MSR = CAN_MSR_ERRI; + /* Note : the corresponding Flag is cleared by hardware depending + of the CAN Bus status*/ + break; + case CAN_IT_EPV: + /* Clear CAN_MSR_ERRI (rc_w1) */ + CANx->MSR = CAN_MSR_ERRI; + /* Note : the corresponding Flag is cleared by hardware depending + of the CAN Bus status*/ + break; + case CAN_IT_BOF: + /* Clear CAN_MSR_ERRI (rc_w1) */ + CANx->MSR = CAN_MSR_ERRI; + /* Note : the corresponding Flag is cleared by hardware depending + of the CAN Bus status*/ + break; + case CAN_IT_LEC: + /* Clear LEC bits */ + CANx->ESR = RESET; + /* Clear CAN_MSR_ERRI (rc_w1) */ + CANx->MSR = CAN_MSR_ERRI; + break; + case CAN_IT_ERR: + /*Clear LEC bits */ + CANx->ESR = RESET; + /* Clear CAN_MSR_ERRI (rc_w1) */ + CANx->MSR = CAN_MSR_ERRI; + /* Note : BOFF, EPVF and EWGF Flags are cleared by hardware depending + of the CAN Bus status*/ + break; + default : + break; + } +} + +/** + * @brief Checks whether the CAN interrupt has occurred or not. + * @param CAN_Reg: specifies the CAN interrupt register to check. + * @param It_Bit: specifies the interrupt source bit to check. + * @retval The new state of the CAN Interrupt (SET or RESET). + */ +static ITStatus CheckITStatus(uint32_t CAN_Reg, uint32_t It_Bit) +{ + ITStatus pendingbitstatus = RESET; + + if ((CAN_Reg & It_Bit) != (uint32_t)RESET) + { + /* CAN_IT is set */ + pendingbitstatus = SET; + } + else + { + /* CAN_IT is reset */ + pendingbitstatus = RESET; + } + return pendingbitstatus; +} + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_can.h b/Library/stm32f10x_can.h new file mode 100644 index 0000000..d185aa2 --- /dev/null +++ b/Library/stm32f10x_can.h @@ -0,0 +1,697 @@ +/** + ****************************************************************************** + * @file stm32f10x_can.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the CAN firmware + * library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_CAN_H +#define __STM32F10x_CAN_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup CAN + * @{ + */ + +/** @defgroup CAN_Exported_Types + * @{ + */ + +#define IS_CAN_ALL_PERIPH(PERIPH) (((PERIPH) == CAN1) || \ + ((PERIPH) == CAN2)) + +/** + * @brief CAN init structure definition + */ + +typedef struct +{ + uint16_t CAN_Prescaler; /*!< Specifies the length of a time quantum. + It ranges from 1 to 1024. */ + + uint8_t CAN_Mode; /*!< Specifies the CAN operating mode. + This parameter can be a value of + @ref CAN_operating_mode */ + + uint8_t CAN_SJW; /*!< Specifies the maximum number of time quanta + the CAN hardware is allowed to lengthen or + shorten a bit to perform resynchronization. + This parameter can be a value of + @ref CAN_synchronisation_jump_width */ + + uint8_t CAN_BS1; /*!< Specifies the number of time quanta in Bit + Segment 1. This parameter can be a value of + @ref CAN_time_quantum_in_bit_segment_1 */ + + uint8_t CAN_BS2; /*!< Specifies the number of time quanta in Bit + Segment 2. + This parameter can be a value of + @ref CAN_time_quantum_in_bit_segment_2 */ + + FunctionalState CAN_TTCM; /*!< Enable or disable the time triggered + communication mode. This parameter can be set + either to ENABLE or DISABLE. */ + + FunctionalState CAN_ABOM; /*!< Enable or disable the automatic bus-off + management. This parameter can be set either + to ENABLE or DISABLE. */ + + FunctionalState CAN_AWUM; /*!< Enable or disable the automatic wake-up mode. + This parameter can be set either to ENABLE or + DISABLE. */ + + FunctionalState CAN_NART; /*!< Enable or disable the no-automatic + retransmission mode. This parameter can be + set either to ENABLE or DISABLE. */ + + FunctionalState CAN_RFLM; /*!< Enable or disable the Receive FIFO Locked mode. + This parameter can be set either to ENABLE + or DISABLE. */ + + FunctionalState CAN_TXFP; /*!< Enable or disable the transmit FIFO priority. + This parameter can be set either to ENABLE + or DISABLE. */ +} CAN_InitTypeDef; + +/** + * @brief CAN filter init structure definition + */ + +typedef struct +{ + uint16_t CAN_FilterIdHigh; /*!< Specifies the filter identification number (MSBs for a 32-bit + configuration, first one for a 16-bit configuration). + This parameter can be a value between 0x0000 and 0xFFFF */ + + uint16_t CAN_FilterIdLow; /*!< Specifies the filter identification number (LSBs for a 32-bit + configuration, second one for a 16-bit configuration). + This parameter can be a value between 0x0000 and 0xFFFF */ + + uint16_t CAN_FilterMaskIdHigh; /*!< Specifies the filter mask number or identification number, + according to the mode (MSBs for a 32-bit configuration, + first one for a 16-bit configuration). + This parameter can be a value between 0x0000 and 0xFFFF */ + + uint16_t CAN_FilterMaskIdLow; /*!< Specifies the filter mask number or identification number, + according to the mode (LSBs for a 32-bit configuration, + second one for a 16-bit configuration). + This parameter can be a value between 0x0000 and 0xFFFF */ + + uint16_t CAN_FilterFIFOAssignment; /*!< Specifies the FIFO (0 or 1) which will be assigned to the filter. + This parameter can be a value of @ref CAN_filter_FIFO */ + + uint8_t CAN_FilterNumber; /*!< Specifies the filter which will be initialized. It ranges from 0 to 13. */ + + uint8_t CAN_FilterMode; /*!< Specifies the filter mode to be initialized. + This parameter can be a value of @ref CAN_filter_mode */ + + uint8_t CAN_FilterScale; /*!< Specifies the filter scale. + This parameter can be a value of @ref CAN_filter_scale */ + + FunctionalState CAN_FilterActivation; /*!< Enable or disable the filter. + This parameter can be set either to ENABLE or DISABLE. */ +} CAN_FilterInitTypeDef; + +/** + * @brief CAN Tx message structure definition + */ + +typedef struct +{ + uint32_t StdId; /*!< Specifies the standard identifier. + This parameter can be a value between 0 to 0x7FF. */ + + uint32_t ExtId; /*!< Specifies the extended identifier. + This parameter can be a value between 0 to 0x1FFFFFFF. */ + + uint8_t IDE; /*!< Specifies the type of identifier for the message that + will be transmitted. This parameter can be a value + of @ref CAN_identifier_type */ + + uint8_t RTR; /*!< Specifies the type of frame for the message that will + be transmitted. This parameter can be a value of + @ref CAN_remote_transmission_request */ + + uint8_t DLC; /*!< Specifies the length of the frame that will be + transmitted. This parameter can be a value between + 0 to 8 */ + + uint8_t Data[8]; /*!< Contains the data to be transmitted. It ranges from 0 + to 0xFF. */ +} CanTxMsg; + +/** + * @brief CAN Rx message structure definition + */ + +typedef struct +{ + uint32_t StdId; /*!< Specifies the standard identifier. + This parameter can be a value between 0 to 0x7FF. */ + + uint32_t ExtId; /*!< Specifies the extended identifier. + This parameter can be a value between 0 to 0x1FFFFFFF. */ + + uint8_t IDE; /*!< Specifies the type of identifier for the message that + will be received. This parameter can be a value of + @ref CAN_identifier_type */ + + uint8_t RTR; /*!< Specifies the type of frame for the received message. + This parameter can be a value of + @ref CAN_remote_transmission_request */ + + uint8_t DLC; /*!< Specifies the length of the frame that will be received. + This parameter can be a value between 0 to 8 */ + + uint8_t Data[8]; /*!< Contains the data to be received. It ranges from 0 to + 0xFF. */ + + uint8_t FMI; /*!< Specifies the index of the filter the message stored in + the mailbox passes through. This parameter can be a + value between 0 to 0xFF */ +} CanRxMsg; + +/** + * @} + */ + +/** @defgroup CAN_Exported_Constants + * @{ + */ + +/** @defgroup CAN_sleep_constants + * @{ + */ + +#define CAN_InitStatus_Failed ((uint8_t)0x00) /*!< CAN initialization failed */ +#define CAN_InitStatus_Success ((uint8_t)0x01) /*!< CAN initialization OK */ + +/** + * @} + */ + +/** @defgroup CAN_Mode + * @{ + */ + +#define CAN_Mode_Normal ((uint8_t)0x00) /*!< normal mode */ +#define CAN_Mode_LoopBack ((uint8_t)0x01) /*!< loopback mode */ +#define CAN_Mode_Silent ((uint8_t)0x02) /*!< silent mode */ +#define CAN_Mode_Silent_LoopBack ((uint8_t)0x03) /*!< loopback combined with silent mode */ + +#define IS_CAN_MODE(MODE) (((MODE) == CAN_Mode_Normal) || \ + ((MODE) == CAN_Mode_LoopBack)|| \ + ((MODE) == CAN_Mode_Silent) || \ + ((MODE) == CAN_Mode_Silent_LoopBack)) +/** + * @} + */ + + +/** + * @defgroup CAN_Operating_Mode + * @{ + */ +#define CAN_OperatingMode_Initialization ((uint8_t)0x00) /*!< Initialization mode */ +#define CAN_OperatingMode_Normal ((uint8_t)0x01) /*!< Normal mode */ +#define CAN_OperatingMode_Sleep ((uint8_t)0x02) /*!< sleep mode */ + + +#define IS_CAN_OPERATING_MODE(MODE) (((MODE) == CAN_OperatingMode_Initialization) ||\ + ((MODE) == CAN_OperatingMode_Normal)|| \ + ((MODE) == CAN_OperatingMode_Sleep)) +/** + * @} + */ + +/** + * @defgroup CAN_Mode_Status + * @{ + */ + +#define CAN_ModeStatus_Failed ((uint8_t)0x00) /*!< CAN entering the specific mode failed */ +#define CAN_ModeStatus_Success ((uint8_t)!CAN_ModeStatus_Failed) /*!< CAN entering the specific mode Succeed */ + + +/** + * @} + */ + +/** @defgroup CAN_synchronisation_jump_width + * @{ + */ + +#define CAN_SJW_1tq ((uint8_t)0x00) /*!< 1 time quantum */ +#define CAN_SJW_2tq ((uint8_t)0x01) /*!< 2 time quantum */ +#define CAN_SJW_3tq ((uint8_t)0x02) /*!< 3 time quantum */ +#define CAN_SJW_4tq ((uint8_t)0x03) /*!< 4 time quantum */ + +#define IS_CAN_SJW(SJW) (((SJW) == CAN_SJW_1tq) || ((SJW) == CAN_SJW_2tq)|| \ + ((SJW) == CAN_SJW_3tq) || ((SJW) == CAN_SJW_4tq)) +/** + * @} + */ + +/** @defgroup CAN_time_quantum_in_bit_segment_1 + * @{ + */ + +#define CAN_BS1_1tq ((uint8_t)0x00) /*!< 1 time quantum */ +#define CAN_BS1_2tq ((uint8_t)0x01) /*!< 2 time quantum */ +#define CAN_BS1_3tq ((uint8_t)0x02) /*!< 3 time quantum */ +#define CAN_BS1_4tq ((uint8_t)0x03) /*!< 4 time quantum */ +#define CAN_BS1_5tq ((uint8_t)0x04) /*!< 5 time quantum */ +#define CAN_BS1_6tq ((uint8_t)0x05) /*!< 6 time quantum */ +#define CAN_BS1_7tq ((uint8_t)0x06) /*!< 7 time quantum */ +#define CAN_BS1_8tq ((uint8_t)0x07) /*!< 8 time quantum */ +#define CAN_BS1_9tq ((uint8_t)0x08) /*!< 9 time quantum */ +#define CAN_BS1_10tq ((uint8_t)0x09) /*!< 10 time quantum */ +#define CAN_BS1_11tq ((uint8_t)0x0A) /*!< 11 time quantum */ +#define CAN_BS1_12tq ((uint8_t)0x0B) /*!< 12 time quantum */ +#define CAN_BS1_13tq ((uint8_t)0x0C) /*!< 13 time quantum */ +#define CAN_BS1_14tq ((uint8_t)0x0D) /*!< 14 time quantum */ +#define CAN_BS1_15tq ((uint8_t)0x0E) /*!< 15 time quantum */ +#define CAN_BS1_16tq ((uint8_t)0x0F) /*!< 16 time quantum */ + +#define IS_CAN_BS1(BS1) ((BS1) <= CAN_BS1_16tq) +/** + * @} + */ + +/** @defgroup CAN_time_quantum_in_bit_segment_2 + * @{ + */ + +#define CAN_BS2_1tq ((uint8_t)0x00) /*!< 1 time quantum */ +#define CAN_BS2_2tq ((uint8_t)0x01) /*!< 2 time quantum */ +#define CAN_BS2_3tq ((uint8_t)0x02) /*!< 3 time quantum */ +#define CAN_BS2_4tq ((uint8_t)0x03) /*!< 4 time quantum */ +#define CAN_BS2_5tq ((uint8_t)0x04) /*!< 5 time quantum */ +#define CAN_BS2_6tq ((uint8_t)0x05) /*!< 6 time quantum */ +#define CAN_BS2_7tq ((uint8_t)0x06) /*!< 7 time quantum */ +#define CAN_BS2_8tq ((uint8_t)0x07) /*!< 8 time quantum */ + +#define IS_CAN_BS2(BS2) ((BS2) <= CAN_BS2_8tq) + +/** + * @} + */ + +/** @defgroup CAN_clock_prescaler + * @{ + */ + +#define IS_CAN_PRESCALER(PRESCALER) (((PRESCALER) >= 1) && ((PRESCALER) <= 1024)) + +/** + * @} + */ + +/** @defgroup CAN_filter_number + * @{ + */ +#ifndef STM32F10X_CL + #define IS_CAN_FILTER_NUMBER(NUMBER) ((NUMBER) <= 13) +#else + #define IS_CAN_FILTER_NUMBER(NUMBER) ((NUMBER) <= 27) +#endif /* STM32F10X_CL */ +/** + * @} + */ + +/** @defgroup CAN_filter_mode + * @{ + */ + +#define CAN_FilterMode_IdMask ((uint8_t)0x00) /*!< identifier/mask mode */ +#define CAN_FilterMode_IdList ((uint8_t)0x01) /*!< identifier list mode */ + +#define IS_CAN_FILTER_MODE(MODE) (((MODE) == CAN_FilterMode_IdMask) || \ + ((MODE) == CAN_FilterMode_IdList)) +/** + * @} + */ + +/** @defgroup CAN_filter_scale + * @{ + */ + +#define CAN_FilterScale_16bit ((uint8_t)0x00) /*!< Two 16-bit filters */ +#define CAN_FilterScale_32bit ((uint8_t)0x01) /*!< One 32-bit filter */ + +#define IS_CAN_FILTER_SCALE(SCALE) (((SCALE) == CAN_FilterScale_16bit) || \ + ((SCALE) == CAN_FilterScale_32bit)) + +/** + * @} + */ + +/** @defgroup CAN_filter_FIFO + * @{ + */ + +#define CAN_Filter_FIFO0 ((uint8_t)0x00) /*!< Filter FIFO 0 assignment for filter x */ +#define CAN_Filter_FIFO1 ((uint8_t)0x01) /*!< Filter FIFO 1 assignment for filter x */ +#define IS_CAN_FILTER_FIFO(FIFO) (((FIFO) == CAN_FilterFIFO0) || \ + ((FIFO) == CAN_FilterFIFO1)) +/** + * @} + */ + +/** @defgroup Start_bank_filter_for_slave_CAN + * @{ + */ +#define IS_CAN_BANKNUMBER(BANKNUMBER) (((BANKNUMBER) >= 1) && ((BANKNUMBER) <= 27)) +/** + * @} + */ + +/** @defgroup CAN_Tx + * @{ + */ + +#define IS_CAN_TRANSMITMAILBOX(TRANSMITMAILBOX) ((TRANSMITMAILBOX) <= ((uint8_t)0x02)) +#define IS_CAN_STDID(STDID) ((STDID) <= ((uint32_t)0x7FF)) +#define IS_CAN_EXTID(EXTID) ((EXTID) <= ((uint32_t)0x1FFFFFFF)) +#define IS_CAN_DLC(DLC) ((DLC) <= ((uint8_t)0x08)) + +/** + * @} + */ + +/** @defgroup CAN_identifier_type + * @{ + */ + +#define CAN_Id_Standard ((uint32_t)0x00000000) /*!< Standard Id */ +#define CAN_Id_Extended ((uint32_t)0x00000004) /*!< Extended Id */ +#define IS_CAN_IDTYPE(IDTYPE) (((IDTYPE) == CAN_Id_Standard) || \ + ((IDTYPE) == CAN_Id_Extended)) +/** + * @} + */ + +/** @defgroup CAN_remote_transmission_request + * @{ + */ + +#define CAN_RTR_Data ((uint32_t)0x00000000) /*!< Data frame */ +#define CAN_RTR_Remote ((uint32_t)0x00000002) /*!< Remote frame */ +#define IS_CAN_RTR(RTR) (((RTR) == CAN_RTR_Data) || ((RTR) == CAN_RTR_Remote)) + +/** + * @} + */ + +/** @defgroup CAN_transmit_constants + * @{ + */ + +#define CAN_TxStatus_Failed ((uint8_t)0x00)/*!< CAN transmission failed */ +#define CAN_TxStatus_Ok ((uint8_t)0x01) /*!< CAN transmission succeeded */ +#define CAN_TxStatus_Pending ((uint8_t)0x02) /*!< CAN transmission pending */ +#define CAN_TxStatus_NoMailBox ((uint8_t)0x04) /*!< CAN cell did not provide an empty mailbox */ + +/** + * @} + */ + +/** @defgroup CAN_receive_FIFO_number_constants + * @{ + */ + +#define CAN_FIFO0 ((uint8_t)0x00) /*!< CAN FIFO 0 used to receive */ +#define CAN_FIFO1 ((uint8_t)0x01) /*!< CAN FIFO 1 used to receive */ + +#define IS_CAN_FIFO(FIFO) (((FIFO) == CAN_FIFO0) || ((FIFO) == CAN_FIFO1)) + +/** + * @} + */ + +/** @defgroup CAN_sleep_constants + * @{ + */ + +#define CAN_Sleep_Failed ((uint8_t)0x00) /*!< CAN did not enter the sleep mode */ +#define CAN_Sleep_Ok ((uint8_t)0x01) /*!< CAN entered the sleep mode */ + +/** + * @} + */ + +/** @defgroup CAN_wake_up_constants + * @{ + */ + +#define CAN_WakeUp_Failed ((uint8_t)0x00) /*!< CAN did not leave the sleep mode */ +#define CAN_WakeUp_Ok ((uint8_t)0x01) /*!< CAN leaved the sleep mode */ + +/** + * @} + */ + +/** + * @defgroup CAN_Error_Code_constants + * @{ + */ + +#define CAN_ErrorCode_NoErr ((uint8_t)0x00) /*!< No Error */ +#define CAN_ErrorCode_StuffErr ((uint8_t)0x10) /*!< Stuff Error */ +#define CAN_ErrorCode_FormErr ((uint8_t)0x20) /*!< Form Error */ +#define CAN_ErrorCode_ACKErr ((uint8_t)0x30) /*!< Acknowledgment Error */ +#define CAN_ErrorCode_BitRecessiveErr ((uint8_t)0x40) /*!< Bit Recessive Error */ +#define CAN_ErrorCode_BitDominantErr ((uint8_t)0x50) /*!< Bit Dominant Error */ +#define CAN_ErrorCode_CRCErr ((uint8_t)0x60) /*!< CRC Error */ +#define CAN_ErrorCode_SoftwareSetErr ((uint8_t)0x70) /*!< Software Set Error */ + + +/** + * @} + */ + +/** @defgroup CAN_flags + * @{ + */ +/* If the flag is 0x3XXXXXXX, it means that it can be used with CAN_GetFlagStatus() + and CAN_ClearFlag() functions. */ +/* If the flag is 0x1XXXXXXX, it means that it can only be used with CAN_GetFlagStatus() function. */ + +/* Transmit Flags */ +#define CAN_FLAG_RQCP0 ((uint32_t)0x38000001) /*!< Request MailBox0 Flag */ +#define CAN_FLAG_RQCP1 ((uint32_t)0x38000100) /*!< Request MailBox1 Flag */ +#define CAN_FLAG_RQCP2 ((uint32_t)0x38010000) /*!< Request MailBox2 Flag */ + +/* Receive Flags */ +#define CAN_FLAG_FMP0 ((uint32_t)0x12000003) /*!< FIFO 0 Message Pending Flag */ +#define CAN_FLAG_FF0 ((uint32_t)0x32000008) /*!< FIFO 0 Full Flag */ +#define CAN_FLAG_FOV0 ((uint32_t)0x32000010) /*!< FIFO 0 Overrun Flag */ +#define CAN_FLAG_FMP1 ((uint32_t)0x14000003) /*!< FIFO 1 Message Pending Flag */ +#define CAN_FLAG_FF1 ((uint32_t)0x34000008) /*!< FIFO 1 Full Flag */ +#define CAN_FLAG_FOV1 ((uint32_t)0x34000010) /*!< FIFO 1 Overrun Flag */ + +/* Operating Mode Flags */ +#define CAN_FLAG_WKU ((uint32_t)0x31000008) /*!< Wake up Flag */ +#define CAN_FLAG_SLAK ((uint32_t)0x31000012) /*!< Sleep acknowledge Flag */ +/* Note: When SLAK intterupt is disabled (SLKIE=0), no polling on SLAKI is possible. + In this case the SLAK bit can be polled.*/ + +/* Error Flags */ +#define CAN_FLAG_EWG ((uint32_t)0x10F00001) /*!< Error Warning Flag */ +#define CAN_FLAG_EPV ((uint32_t)0x10F00002) /*!< Error Passive Flag */ +#define CAN_FLAG_BOF ((uint32_t)0x10F00004) /*!< Bus-Off Flag */ +#define CAN_FLAG_LEC ((uint32_t)0x30F00070) /*!< Last error code Flag */ + +#define IS_CAN_GET_FLAG(FLAG) (((FLAG) == CAN_FLAG_LEC) || ((FLAG) == CAN_FLAG_BOF) || \ + ((FLAG) == CAN_FLAG_EPV) || ((FLAG) == CAN_FLAG_EWG) || \ + ((FLAG) == CAN_FLAG_WKU) || ((FLAG) == CAN_FLAG_FOV0) || \ + ((FLAG) == CAN_FLAG_FF0) || ((FLAG) == CAN_FLAG_FMP0) || \ + ((FLAG) == CAN_FLAG_FOV1) || ((FLAG) == CAN_FLAG_FF1) || \ + ((FLAG) == CAN_FLAG_FMP1) || ((FLAG) == CAN_FLAG_RQCP2) || \ + ((FLAG) == CAN_FLAG_RQCP1)|| ((FLAG) == CAN_FLAG_RQCP0) || \ + ((FLAG) == CAN_FLAG_SLAK )) + +#define IS_CAN_CLEAR_FLAG(FLAG)(((FLAG) == CAN_FLAG_LEC) || ((FLAG) == CAN_FLAG_RQCP2) || \ + ((FLAG) == CAN_FLAG_RQCP1) || ((FLAG) == CAN_FLAG_RQCP0) || \ + ((FLAG) == CAN_FLAG_FF0) || ((FLAG) == CAN_FLAG_FOV0) ||\ + ((FLAG) == CAN_FLAG_FF1) || ((FLAG) == CAN_FLAG_FOV1) || \ + ((FLAG) == CAN_FLAG_WKU) || ((FLAG) == CAN_FLAG_SLAK)) +/** + * @} + */ + + +/** @defgroup CAN_interrupts + * @{ + */ + + + +#define CAN_IT_TME ((uint32_t)0x00000001) /*!< Transmit mailbox empty Interrupt*/ + +/* Receive Interrupts */ +#define CAN_IT_FMP0 ((uint32_t)0x00000002) /*!< FIFO 0 message pending Interrupt*/ +#define CAN_IT_FF0 ((uint32_t)0x00000004) /*!< FIFO 0 full Interrupt*/ +#define CAN_IT_FOV0 ((uint32_t)0x00000008) /*!< FIFO 0 overrun Interrupt*/ +#define CAN_IT_FMP1 ((uint32_t)0x00000010) /*!< FIFO 1 message pending Interrupt*/ +#define CAN_IT_FF1 ((uint32_t)0x00000020) /*!< FIFO 1 full Interrupt*/ +#define CAN_IT_FOV1 ((uint32_t)0x00000040) /*!< FIFO 1 overrun Interrupt*/ + +/* Operating Mode Interrupts */ +#define CAN_IT_WKU ((uint32_t)0x00010000) /*!< Wake-up Interrupt*/ +#define CAN_IT_SLK ((uint32_t)0x00020000) /*!< Sleep acknowledge Interrupt*/ + +/* Error Interrupts */ +#define CAN_IT_EWG ((uint32_t)0x00000100) /*!< Error warning Interrupt*/ +#define CAN_IT_EPV ((uint32_t)0x00000200) /*!< Error passive Interrupt*/ +#define CAN_IT_BOF ((uint32_t)0x00000400) /*!< Bus-off Interrupt*/ +#define CAN_IT_LEC ((uint32_t)0x00000800) /*!< Last error code Interrupt*/ +#define CAN_IT_ERR ((uint32_t)0x00008000) /*!< Error Interrupt*/ + +/* Flags named as Interrupts : kept only for FW compatibility */ +#define CAN_IT_RQCP0 CAN_IT_TME +#define CAN_IT_RQCP1 CAN_IT_TME +#define CAN_IT_RQCP2 CAN_IT_TME + + +#define IS_CAN_IT(IT) (((IT) == CAN_IT_TME) || ((IT) == CAN_IT_FMP0) ||\ + ((IT) == CAN_IT_FF0) || ((IT) == CAN_IT_FOV0) ||\ + ((IT) == CAN_IT_FMP1) || ((IT) == CAN_IT_FF1) ||\ + ((IT) == CAN_IT_FOV1) || ((IT) == CAN_IT_EWG) ||\ + ((IT) == CAN_IT_EPV) || ((IT) == CAN_IT_BOF) ||\ + ((IT) == CAN_IT_LEC) || ((IT) == CAN_IT_ERR) ||\ + ((IT) == CAN_IT_WKU) || ((IT) == CAN_IT_SLK)) + +#define IS_CAN_CLEAR_IT(IT) (((IT) == CAN_IT_TME) || ((IT) == CAN_IT_FF0) ||\ + ((IT) == CAN_IT_FOV0)|| ((IT) == CAN_IT_FF1) ||\ + ((IT) == CAN_IT_FOV1)|| ((IT) == CAN_IT_EWG) ||\ + ((IT) == CAN_IT_EPV) || ((IT) == CAN_IT_BOF) ||\ + ((IT) == CAN_IT_LEC) || ((IT) == CAN_IT_ERR) ||\ + ((IT) == CAN_IT_WKU) || ((IT) == CAN_IT_SLK)) + +/** + * @} + */ + +/** @defgroup CAN_Legacy + * @{ + */ +#define CANINITFAILED CAN_InitStatus_Failed +#define CANINITOK CAN_InitStatus_Success +#define CAN_FilterFIFO0 CAN_Filter_FIFO0 +#define CAN_FilterFIFO1 CAN_Filter_FIFO1 +#define CAN_ID_STD CAN_Id_Standard +#define CAN_ID_EXT CAN_Id_Extended +#define CAN_RTR_DATA CAN_RTR_Data +#define CAN_RTR_REMOTE CAN_RTR_Remote +#define CANTXFAILE CAN_TxStatus_Failed +#define CANTXOK CAN_TxStatus_Ok +#define CANTXPENDING CAN_TxStatus_Pending +#define CAN_NO_MB CAN_TxStatus_NoMailBox +#define CANSLEEPFAILED CAN_Sleep_Failed +#define CANSLEEPOK CAN_Sleep_Ok +#define CANWAKEUPFAILED CAN_WakeUp_Failed +#define CANWAKEUPOK CAN_WakeUp_Ok + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup CAN_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup CAN_Exported_Functions + * @{ + */ +/* Function used to set the CAN configuration to the default reset state *****/ +void CAN_DeInit(CAN_TypeDef* CANx); + +/* Initialization and Configuration functions *********************************/ +uint8_t CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct); +void CAN_FilterInit(CAN_FilterInitTypeDef* CAN_FilterInitStruct); +void CAN_StructInit(CAN_InitTypeDef* CAN_InitStruct); +void CAN_SlaveStartBank(uint8_t CAN_BankNumber); +void CAN_DBGFreeze(CAN_TypeDef* CANx, FunctionalState NewState); +void CAN_TTComModeCmd(CAN_TypeDef* CANx, FunctionalState NewState); + +/* Transmit functions *********************************************************/ +uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage); +uint8_t CAN_TransmitStatus(CAN_TypeDef* CANx, uint8_t TransmitMailbox); +void CAN_CancelTransmit(CAN_TypeDef* CANx, uint8_t Mailbox); + +/* Receive functions **********************************************************/ +void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage); +void CAN_FIFORelease(CAN_TypeDef* CANx, uint8_t FIFONumber); +uint8_t CAN_MessagePending(CAN_TypeDef* CANx, uint8_t FIFONumber); + + +/* Operation modes functions **************************************************/ +uint8_t CAN_OperatingModeRequest(CAN_TypeDef* CANx, uint8_t CAN_OperatingMode); +uint8_t CAN_Sleep(CAN_TypeDef* CANx); +uint8_t CAN_WakeUp(CAN_TypeDef* CANx); + +/* Error management functions *************************************************/ +uint8_t CAN_GetLastErrorCode(CAN_TypeDef* CANx); +uint8_t CAN_GetReceiveErrorCounter(CAN_TypeDef* CANx); +uint8_t CAN_GetLSBTransmitErrorCounter(CAN_TypeDef* CANx); + +/* Interrupts and flags management functions **********************************/ +void CAN_ITConfig(CAN_TypeDef* CANx, uint32_t CAN_IT, FunctionalState NewState); +FlagStatus CAN_GetFlagStatus(CAN_TypeDef* CANx, uint32_t CAN_FLAG); +void CAN_ClearFlag(CAN_TypeDef* CANx, uint32_t CAN_FLAG); +ITStatus CAN_GetITStatus(CAN_TypeDef* CANx, uint32_t CAN_IT); +void CAN_ClearITPendingBit(CAN_TypeDef* CANx, uint32_t CAN_IT); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F10x_CAN_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_cec.c b/Library/stm32f10x_cec.c new file mode 100644 index 0000000..4dc615f --- /dev/null +++ b/Library/stm32f10x_cec.c @@ -0,0 +1,433 @@ +/** + ****************************************************************************** + * @file stm32f10x_cec.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the CEC firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_cec.h" +#include "stm32f10x_rcc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup CEC + * @brief CEC driver modules + * @{ + */ + +/** @defgroup CEC_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + + +/** @defgroup CEC_Private_Defines + * @{ + */ + +/* ------------ CEC registers bit address in the alias region ----------- */ +#define CEC_OFFSET (CEC_BASE - PERIPH_BASE) + +/* --- CFGR Register ---*/ + +/* Alias word address of PE bit */ +#define CFGR_OFFSET (CEC_OFFSET + 0x00) +#define PE_BitNumber 0x00 +#define CFGR_PE_BB (PERIPH_BB_BASE + (CFGR_OFFSET * 32) + (PE_BitNumber * 4)) + +/* Alias word address of IE bit */ +#define IE_BitNumber 0x01 +#define CFGR_IE_BB (PERIPH_BB_BASE + (CFGR_OFFSET * 32) + (IE_BitNumber * 4)) + +/* --- CSR Register ---*/ + +/* Alias word address of TSOM bit */ +#define CSR_OFFSET (CEC_OFFSET + 0x10) +#define TSOM_BitNumber 0x00 +#define CSR_TSOM_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (TSOM_BitNumber * 4)) + +/* Alias word address of TEOM bit */ +#define TEOM_BitNumber 0x01 +#define CSR_TEOM_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (TEOM_BitNumber * 4)) + +#define CFGR_CLEAR_Mask (uint8_t)(0xF3) /* CFGR register Mask */ +#define FLAG_Mask ((uint32_t)0x00FFFFFF) /* CEC FLAG mask */ + +/** + * @} + */ + + +/** @defgroup CEC_Private_Macros + * @{ + */ + +/** + * @} + */ + + +/** @defgroup CEC_Private_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup CEC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + + +/** @defgroup CEC_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the CEC peripheral registers to their default reset + * values. + * @param None + * @retval None + */ +void CEC_DeInit(void) +{ + /* Enable CEC reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_CEC, ENABLE); + /* Release CEC from reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_CEC, DISABLE); +} + + +/** + * @brief Initializes the CEC peripheral according to the specified + * parameters in the CEC_InitStruct. + * @param CEC_InitStruct: pointer to an CEC_InitTypeDef structure that + * contains the configuration information for the specified + * CEC peripheral. + * @retval None + */ +void CEC_Init(CEC_InitTypeDef* CEC_InitStruct) +{ + uint16_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_CEC_BIT_TIMING_ERROR_MODE(CEC_InitStruct->CEC_BitTimingMode)); + assert_param(IS_CEC_BIT_PERIOD_ERROR_MODE(CEC_InitStruct->CEC_BitPeriodMode)); + + /*---------------------------- CEC CFGR Configuration -----------------*/ + /* Get the CEC CFGR value */ + tmpreg = CEC->CFGR; + + /* Clear BTEM and BPEM bits */ + tmpreg &= CFGR_CLEAR_Mask; + + /* Configure CEC: Bit Timing Error and Bit Period Error */ + tmpreg |= (uint16_t)(CEC_InitStruct->CEC_BitTimingMode | CEC_InitStruct->CEC_BitPeriodMode); + + /* Write to CEC CFGR register*/ + CEC->CFGR = tmpreg; + +} + +/** + * @brief Enables or disables the specified CEC peripheral. + * @param NewState: new state of the CEC peripheral. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void CEC_Cmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CFGR_PE_BB = (uint32_t)NewState; + + if(NewState == DISABLE) + { + /* Wait until the PE bit is cleared by hardware (Idle Line detected) */ + while((CEC->CFGR & CEC_CFGR_PE) != (uint32_t)RESET) + { + } + } +} + +/** + * @brief Enables or disables the CEC interrupt. + * @param NewState: new state of the CEC interrupt. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void CEC_ITConfig(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CFGR_IE_BB = (uint32_t)NewState; +} + +/** + * @brief Defines the Own Address of the CEC device. + * @param CEC_OwnAddress: The CEC own address + * @retval None + */ +void CEC_OwnAddressConfig(uint8_t CEC_OwnAddress) +{ + /* Check the parameters */ + assert_param(IS_CEC_ADDRESS(CEC_OwnAddress)); + + /* Set the CEC own address */ + CEC->OAR = CEC_OwnAddress; +} + +/** + * @brief Sets the CEC prescaler value. + * @param CEC_Prescaler: CEC prescaler new value + * @retval None + */ +void CEC_SetPrescaler(uint16_t CEC_Prescaler) +{ + /* Check the parameters */ + assert_param(IS_CEC_PRESCALER(CEC_Prescaler)); + + /* Set the Prescaler value*/ + CEC->PRES = CEC_Prescaler; +} + +/** + * @brief Transmits single data through the CEC peripheral. + * @param Data: the data to transmit. + * @retval None + */ +void CEC_SendDataByte(uint8_t Data) +{ + /* Transmit Data */ + CEC->TXD = Data ; +} + + +/** + * @brief Returns the most recent received data by the CEC peripheral. + * @param None + * @retval The received data. + */ +uint8_t CEC_ReceiveDataByte(void) +{ + /* Receive Data */ + return (uint8_t)(CEC->RXD); +} + +/** + * @brief Starts a new message. + * @param None + * @retval None + */ +void CEC_StartOfMessage(void) +{ + /* Starts of new message */ + *(__IO uint32_t *) CSR_TSOM_BB = (uint32_t)0x1; +} + +/** + * @brief Transmits message with or without an EOM bit. + * @param NewState: new state of the CEC Tx End Of Message. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void CEC_EndOfMessageCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + /* The data byte will be transmitted with or without an EOM bit*/ + *(__IO uint32_t *) CSR_TEOM_BB = (uint32_t)NewState; +} + +/** + * @brief Gets the CEC flag status + * @param CEC_FLAG: specifies the CEC flag to check. + * This parameter can be one of the following values: + * @arg CEC_FLAG_BTE: Bit Timing Error + * @arg CEC_FLAG_BPE: Bit Period Error + * @arg CEC_FLAG_RBTFE: Rx Block Transfer Finished Error + * @arg CEC_FLAG_SBE: Start Bit Error + * @arg CEC_FLAG_ACKE: Block Acknowledge Error + * @arg CEC_FLAG_LINE: Line Error + * @arg CEC_FLAG_TBTFE: Tx Block Transfer Finished Error + * @arg CEC_FLAG_TEOM: Tx End Of Message + * @arg CEC_FLAG_TERR: Tx Error + * @arg CEC_FLAG_TBTRF: Tx Byte Transfer Request or Block Transfer Finished + * @arg CEC_FLAG_RSOM: Rx Start Of Message + * @arg CEC_FLAG_REOM: Rx End Of Message + * @arg CEC_FLAG_RERR: Rx Error + * @arg CEC_FLAG_RBTF: Rx Byte/Block Transfer Finished + * @retval The new state of CEC_FLAG (SET or RESET) + */ +FlagStatus CEC_GetFlagStatus(uint32_t CEC_FLAG) +{ + FlagStatus bitstatus = RESET; + uint32_t cecreg = 0, cecbase = 0; + + /* Check the parameters */ + assert_param(IS_CEC_GET_FLAG(CEC_FLAG)); + + /* Get the CEC peripheral base address */ + cecbase = (uint32_t)(CEC_BASE); + + /* Read flag register index */ + cecreg = CEC_FLAG >> 28; + + /* Get bit[23:0] of the flag */ + CEC_FLAG &= FLAG_Mask; + + if(cecreg != 0) + { + /* Flag in CEC ESR Register */ + CEC_FLAG = (uint32_t)(CEC_FLAG >> 16); + + /* Get the CEC ESR register address */ + cecbase += 0xC; + } + else + { + /* Get the CEC CSR register address */ + cecbase += 0x10; + } + + if(((*(__IO uint32_t *)cecbase) & CEC_FLAG) != (uint32_t)RESET) + { + /* CEC_FLAG is set */ + bitstatus = SET; + } + else + { + /* CEC_FLAG is reset */ + bitstatus = RESET; + } + + /* Return the CEC_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the CEC's pending flags. + * @param CEC_FLAG: specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg CEC_FLAG_TERR: Tx Error + * @arg CEC_FLAG_TBTRF: Tx Byte Transfer Request or Block Transfer Finished + * @arg CEC_FLAG_RSOM: Rx Start Of Message + * @arg CEC_FLAG_REOM: Rx End Of Message + * @arg CEC_FLAG_RERR: Rx Error + * @arg CEC_FLAG_RBTF: Rx Byte/Block Transfer Finished + * @retval None + */ +void CEC_ClearFlag(uint32_t CEC_FLAG) +{ + uint32_t tmp = 0x0; + + /* Check the parameters */ + assert_param(IS_CEC_CLEAR_FLAG(CEC_FLAG)); + + tmp = CEC->CSR & 0x2; + + /* Clear the selected CEC flags */ + CEC->CSR &= (uint32_t)(((~(uint32_t)CEC_FLAG) & 0xFFFFFFFC) | tmp); +} + +/** + * @brief Checks whether the specified CEC interrupt has occurred or not. + * @param CEC_IT: specifies the CEC interrupt source to check. + * This parameter can be one of the following values: + * @arg CEC_IT_TERR: Tx Error + * @arg CEC_IT_TBTF: Tx Block Transfer Finished + * @arg CEC_IT_RERR: Rx Error + * @arg CEC_IT_RBTF: Rx Block Transfer Finished + * @retval The new state of CEC_IT (SET or RESET). + */ +ITStatus CEC_GetITStatus(uint8_t CEC_IT) +{ + ITStatus bitstatus = RESET; + uint32_t enablestatus = 0; + + /* Check the parameters */ + assert_param(IS_CEC_GET_IT(CEC_IT)); + + /* Get the CEC IT enable bit status */ + enablestatus = (CEC->CFGR & (uint8_t)CEC_CFGR_IE) ; + + /* Check the status of the specified CEC interrupt */ + if (((CEC->CSR & CEC_IT) != (uint32_t)RESET) && enablestatus) + { + /* CEC_IT is set */ + bitstatus = SET; + } + else + { + /* CEC_IT is reset */ + bitstatus = RESET; + } + /* Return the CEC_IT status */ + return bitstatus; +} + +/** + * @brief Clears the CEC's interrupt pending bits. + * @param CEC_IT: specifies the CEC interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg CEC_IT_TERR: Tx Error + * @arg CEC_IT_TBTF: Tx Block Transfer Finished + * @arg CEC_IT_RERR: Rx Error + * @arg CEC_IT_RBTF: Rx Block Transfer Finished + * @retval None + */ +void CEC_ClearITPendingBit(uint16_t CEC_IT) +{ + uint32_t tmp = 0x0; + + /* Check the parameters */ + assert_param(IS_CEC_GET_IT(CEC_IT)); + + tmp = CEC->CSR & 0x2; + + /* Clear the selected CEC interrupt pending bits */ + CEC->CSR &= (uint32_t)(((~(uint32_t)CEC_IT) & 0xFFFFFFFC) | tmp); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_cec.h b/Library/stm32f10x_cec.h new file mode 100644 index 0000000..7ce6896 --- /dev/null +++ b/Library/stm32f10x_cec.h @@ -0,0 +1,210 @@ +/** + ****************************************************************************** + * @file stm32f10x_cec.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the CEC firmware + * library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_CEC_H +#define __STM32F10x_CEC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup CEC + * @{ + */ + + +/** @defgroup CEC_Exported_Types + * @{ + */ + +/** + * @brief CEC Init structure definition + */ +typedef struct +{ + uint16_t CEC_BitTimingMode; /*!< Configures the CEC Bit Timing Error Mode. + This parameter can be a value of @ref CEC_BitTiming_Mode */ + uint16_t CEC_BitPeriodMode; /*!< Configures the CEC Bit Period Error Mode. + This parameter can be a value of @ref CEC_BitPeriod_Mode */ +}CEC_InitTypeDef; + +/** + * @} + */ + +/** @defgroup CEC_Exported_Constants + * @{ + */ + +/** @defgroup CEC_BitTiming_Mode + * @{ + */ +#define CEC_BitTimingStdMode ((uint16_t)0x00) /*!< Bit timing error Standard Mode */ +#define CEC_BitTimingErrFreeMode CEC_CFGR_BTEM /*!< Bit timing error Free Mode */ + +#define IS_CEC_BIT_TIMING_ERROR_MODE(MODE) (((MODE) == CEC_BitTimingStdMode) || \ + ((MODE) == CEC_BitTimingErrFreeMode)) +/** + * @} + */ + +/** @defgroup CEC_BitPeriod_Mode + * @{ + */ +#define CEC_BitPeriodStdMode ((uint16_t)0x00) /*!< Bit period error Standard Mode */ +#define CEC_BitPeriodFlexibleMode CEC_CFGR_BPEM /*!< Bit period error Flexible Mode */ + +#define IS_CEC_BIT_PERIOD_ERROR_MODE(MODE) (((MODE) == CEC_BitPeriodStdMode) || \ + ((MODE) == CEC_BitPeriodFlexibleMode)) +/** + * @} + */ + + +/** @defgroup CEC_interrupts_definition + * @{ + */ +#define CEC_IT_TERR CEC_CSR_TERR +#define CEC_IT_TBTRF CEC_CSR_TBTRF +#define CEC_IT_RERR CEC_CSR_RERR +#define CEC_IT_RBTF CEC_CSR_RBTF +#define IS_CEC_GET_IT(IT) (((IT) == CEC_IT_TERR) || ((IT) == CEC_IT_TBTRF) || \ + ((IT) == CEC_IT_RERR) || ((IT) == CEC_IT_RBTF)) +/** + * @} + */ + + +/** @defgroup CEC_Own_Address + * @{ + */ +#define IS_CEC_ADDRESS(ADDRESS) ((ADDRESS) < 0x10) +/** + * @} + */ + +/** @defgroup CEC_Prescaler + * @{ + */ +#define IS_CEC_PRESCALER(PRESCALER) ((PRESCALER) <= 0x3FFF) + +/** + * @} + */ + +/** @defgroup CEC_flags_definition + * @{ + */ + +/** + * @brief ESR register flags + */ +#define CEC_FLAG_BTE ((uint32_t)0x10010000) +#define CEC_FLAG_BPE ((uint32_t)0x10020000) +#define CEC_FLAG_RBTFE ((uint32_t)0x10040000) +#define CEC_FLAG_SBE ((uint32_t)0x10080000) +#define CEC_FLAG_ACKE ((uint32_t)0x10100000) +#define CEC_FLAG_LINE ((uint32_t)0x10200000) +#define CEC_FLAG_TBTFE ((uint32_t)0x10400000) + +/** + * @brief CSR register flags + */ +#define CEC_FLAG_TEOM ((uint32_t)0x00000002) +#define CEC_FLAG_TERR ((uint32_t)0x00000004) +#define CEC_FLAG_TBTRF ((uint32_t)0x00000008) +#define CEC_FLAG_RSOM ((uint32_t)0x00000010) +#define CEC_FLAG_REOM ((uint32_t)0x00000020) +#define CEC_FLAG_RERR ((uint32_t)0x00000040) +#define CEC_FLAG_RBTF ((uint32_t)0x00000080) + +#define IS_CEC_CLEAR_FLAG(FLAG) ((((FLAG) & (uint32_t)0xFFFFFF03) == 0x00) && ((FLAG) != 0x00)) + +#define IS_CEC_GET_FLAG(FLAG) (((FLAG) == CEC_FLAG_BTE) || ((FLAG) == CEC_FLAG_BPE) || \ + ((FLAG) == CEC_FLAG_RBTFE) || ((FLAG)== CEC_FLAG_SBE) || \ + ((FLAG) == CEC_FLAG_ACKE) || ((FLAG) == CEC_FLAG_LINE) || \ + ((FLAG) == CEC_FLAG_TBTFE) || ((FLAG) == CEC_FLAG_TEOM) || \ + ((FLAG) == CEC_FLAG_TERR) || ((FLAG) == CEC_FLAG_TBTRF) || \ + ((FLAG) == CEC_FLAG_RSOM) || ((FLAG) == CEC_FLAG_REOM) || \ + ((FLAG) == CEC_FLAG_RERR) || ((FLAG) == CEC_FLAG_RBTF)) + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup CEC_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup CEC_Exported_Functions + * @{ + */ +void CEC_DeInit(void); +void CEC_Init(CEC_InitTypeDef* CEC_InitStruct); +void CEC_Cmd(FunctionalState NewState); +void CEC_ITConfig(FunctionalState NewState); +void CEC_OwnAddressConfig(uint8_t CEC_OwnAddress); +void CEC_SetPrescaler(uint16_t CEC_Prescaler); +void CEC_SendDataByte(uint8_t Data); +uint8_t CEC_ReceiveDataByte(void); +void CEC_StartOfMessage(void); +void CEC_EndOfMessageCmd(FunctionalState NewState); +FlagStatus CEC_GetFlagStatus(uint32_t CEC_FLAG); +void CEC_ClearFlag(uint32_t CEC_FLAG); +ITStatus CEC_GetITStatus(uint8_t CEC_IT); +void CEC_ClearITPendingBit(uint16_t CEC_IT); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F10x_CEC_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_crc.c b/Library/stm32f10x_crc.c new file mode 100644 index 0000000..6501728 --- /dev/null +++ b/Library/stm32f10x_crc.c @@ -0,0 +1,160 @@ +/** + ****************************************************************************** + * @file stm32f10x_crc.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the CRC firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_crc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup CRC + * @brief CRC driver modules + * @{ + */ + +/** @defgroup CRC_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup CRC_Private_Defines + * @{ + */ + +/** + * @} + */ + +/** @defgroup CRC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup CRC_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup CRC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup CRC_Private_Functions + * @{ + */ + +/** + * @brief Resets the CRC Data register (DR). + * @param None + * @retval None + */ +void CRC_ResetDR(void) +{ + /* Reset CRC generator */ + CRC->CR = CRC_CR_RESET; +} + +/** + * @brief Computes the 32-bit CRC of a given data word(32-bit). + * @param Data: data word(32-bit) to compute its CRC + * @retval 32-bit CRC + */ +uint32_t CRC_CalcCRC(uint32_t Data) +{ + CRC->DR = Data; + + return (CRC->DR); +} + +/** + * @brief Computes the 32-bit CRC of a given buffer of data word(32-bit). + * @param pBuffer: pointer to the buffer containing the data to be computed + * @param BufferLength: length of the buffer to be computed + * @retval 32-bit CRC + */ +uint32_t CRC_CalcBlockCRC(uint32_t pBuffer[], uint32_t BufferLength) +{ + uint32_t index = 0; + + for(index = 0; index < BufferLength; index++) + { + CRC->DR = pBuffer[index]; + } + return (CRC->DR); +} + +/** + * @brief Returns the current CRC value. + * @param None + * @retval 32-bit CRC + */ +uint32_t CRC_GetCRC(void) +{ + return (CRC->DR); +} + +/** + * @brief Stores a 8-bit data in the Independent Data(ID) register. + * @param IDValue: 8-bit value to be stored in the ID register + * @retval None + */ +void CRC_SetIDRegister(uint8_t IDValue) +{ + CRC->IDR = IDValue; +} + +/** + * @brief Returns the 8-bit data stored in the Independent Data(ID) register + * @param None + * @retval 8-bit value of the ID register + */ +uint8_t CRC_GetIDRegister(void) +{ + return (CRC->IDR); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_crc.h b/Library/stm32f10x_crc.h new file mode 100644 index 0000000..3362fca --- /dev/null +++ b/Library/stm32f10x_crc.h @@ -0,0 +1,94 @@ +/** + ****************************************************************************** + * @file stm32f10x_crc.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the CRC firmware + * library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_CRC_H +#define __STM32F10x_CRC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup CRC + * @{ + */ + +/** @defgroup CRC_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @defgroup CRC_Exported_Constants + * @{ + */ + +/** + * @} + */ + +/** @defgroup CRC_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup CRC_Exported_Functions + * @{ + */ + +void CRC_ResetDR(void); +uint32_t CRC_CalcCRC(uint32_t Data); +uint32_t CRC_CalcBlockCRC(uint32_t pBuffer[], uint32_t BufferLength); +uint32_t CRC_GetCRC(void); +void CRC_SetIDRegister(uint8_t IDValue); +uint8_t CRC_GetIDRegister(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F10x_CRC_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_dac.c b/Library/stm32f10x_dac.c new file mode 100644 index 0000000..1cfc71d --- /dev/null +++ b/Library/stm32f10x_dac.c @@ -0,0 +1,571 @@ +/** + ****************************************************************************** + * @file stm32f10x_dac.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the DAC firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_dac.h" +#include "stm32f10x_rcc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup DAC + * @brief DAC driver modules + * @{ + */ + +/** @defgroup DAC_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup DAC_Private_Defines + * @{ + */ + +/* CR register Mask */ +#define CR_CLEAR_MASK ((uint32_t)0x00000FFE) + +/* DAC Dual Channels SWTRIG masks */ +#define DUAL_SWTRIG_SET ((uint32_t)0x00000003) +#define DUAL_SWTRIG_RESET ((uint32_t)0xFFFFFFFC) + +/* DHR registers offsets */ +#define DHR12R1_OFFSET ((uint32_t)0x00000008) +#define DHR12R2_OFFSET ((uint32_t)0x00000014) +#define DHR12RD_OFFSET ((uint32_t)0x00000020) + +/* DOR register offset */ +#define DOR_OFFSET ((uint32_t)0x0000002C) +/** + * @} + */ + +/** @defgroup DAC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup DAC_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup DAC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup DAC_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the DAC peripheral registers to their default reset values. + * @param None + * @retval None + */ +void DAC_DeInit(void) +{ + /* Enable DAC reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_DAC, ENABLE); + /* Release DAC from reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_DAC, DISABLE); +} + +/** + * @brief Initializes the DAC peripheral according to the specified + * parameters in the DAC_InitStruct. + * @param DAC_Channel: the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_InitStruct: pointer to a DAC_InitTypeDef structure that + * contains the configuration information for the specified DAC channel. + * @retval None + */ +void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0; + /* Check the DAC parameters */ + assert_param(IS_DAC_TRIGGER(DAC_InitStruct->DAC_Trigger)); + assert_param(IS_DAC_GENERATE_WAVE(DAC_InitStruct->DAC_WaveGeneration)); + assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude)); + assert_param(IS_DAC_OUTPUT_BUFFER_STATE(DAC_InitStruct->DAC_OutputBuffer)); +/*---------------------------- DAC CR Configuration --------------------------*/ + /* Get the DAC CR value */ + tmpreg1 = DAC->CR; + /* Clear BOFFx, TENx, TSELx, WAVEx and MAMPx bits */ + tmpreg1 &= ~(CR_CLEAR_MASK << DAC_Channel); + /* Configure for the selected DAC channel: buffer output, trigger, wave generation, + mask/amplitude for wave generation */ + /* Set TSELx and TENx bits according to DAC_Trigger value */ + /* Set WAVEx bits according to DAC_WaveGeneration value */ + /* Set MAMPx bits according to DAC_LFSRUnmask_TriangleAmplitude value */ + /* Set BOFFx bit according to DAC_OutputBuffer value */ + tmpreg2 = (DAC_InitStruct->DAC_Trigger | DAC_InitStruct->DAC_WaveGeneration | + DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude | DAC_InitStruct->DAC_OutputBuffer); + /* Calculate CR register value depending on DAC_Channel */ + tmpreg1 |= tmpreg2 << DAC_Channel; + /* Write to DAC CR */ + DAC->CR = tmpreg1; +} + +/** + * @brief Fills each DAC_InitStruct member with its default value. + * @param DAC_InitStruct : pointer to a DAC_InitTypeDef structure which will + * be initialized. + * @retval None + */ +void DAC_StructInit(DAC_InitTypeDef* DAC_InitStruct) +{ +/*--------------- Reset DAC init structure parameters values -----------------*/ + /* Initialize the DAC_Trigger member */ + DAC_InitStruct->DAC_Trigger = DAC_Trigger_None; + /* Initialize the DAC_WaveGeneration member */ + DAC_InitStruct->DAC_WaveGeneration = DAC_WaveGeneration_None; + /* Initialize the DAC_LFSRUnmask_TriangleAmplitude member */ + DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; + /* Initialize the DAC_OutputBuffer member */ + DAC_InitStruct->DAC_OutputBuffer = DAC_OutputBuffer_Enable; +} + +/** + * @brief Enables or disables the specified DAC channel. + * @param DAC_Channel: the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param NewState: new state of the DAC channel. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DAC_Cmd(uint32_t DAC_Channel, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected DAC channel */ + DAC->CR |= (DAC_CR_EN1 << DAC_Channel); + } + else + { + /* Disable the selected DAC channel */ + DAC->CR &= ~(DAC_CR_EN1 << DAC_Channel); + } +} +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) +/** + * @brief Enables or disables the specified DAC interrupts. + * @param DAC_Channel: the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_IT: specifies the DAC interrupt sources to be enabled or disabled. + * This parameter can be the following values: + * @arg DAC_IT_DMAUDR: DMA underrun interrupt mask + * @param NewState: new state of the specified DAC interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DAC_ITConfig(uint32_t DAC_Channel, uint32_t DAC_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + assert_param(IS_DAC_IT(DAC_IT)); + + if (NewState != DISABLE) + { + /* Enable the selected DAC interrupts */ + DAC->CR |= (DAC_IT << DAC_Channel); + } + else + { + /* Disable the selected DAC interrupts */ + DAC->CR &= (~(uint32_t)(DAC_IT << DAC_Channel)); + } +} +#endif + +/** + * @brief Enables or disables the specified DAC channel DMA request. + * @param DAC_Channel: the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param NewState: new state of the selected DAC channel DMA request. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DAC_DMACmd(uint32_t DAC_Channel, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected DAC channel DMA request */ + DAC->CR |= (DAC_CR_DMAEN1 << DAC_Channel); + } + else + { + /* Disable the selected DAC channel DMA request */ + DAC->CR &= ~(DAC_CR_DMAEN1 << DAC_Channel); + } +} + +/** + * @brief Enables or disables the selected DAC channel software trigger. + * @param DAC_Channel: the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param NewState: new state of the selected DAC channel software trigger. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DAC_SoftwareTriggerCmd(uint32_t DAC_Channel, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable software trigger for the selected DAC channel */ + DAC->SWTRIGR |= (uint32_t)DAC_SWTRIGR_SWTRIG1 << (DAC_Channel >> 4); + } + else + { + /* Disable software trigger for the selected DAC channel */ + DAC->SWTRIGR &= ~((uint32_t)DAC_SWTRIGR_SWTRIG1 << (DAC_Channel >> 4)); + } +} + +/** + * @brief Enables or disables simultaneously the two DAC channels software + * triggers. + * @param NewState: new state of the DAC channels software triggers. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DAC_DualSoftwareTriggerCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable software trigger for both DAC channels */ + DAC->SWTRIGR |= DUAL_SWTRIG_SET ; + } + else + { + /* Disable software trigger for both DAC channels */ + DAC->SWTRIGR &= DUAL_SWTRIG_RESET; + } +} + +/** + * @brief Enables or disables the selected DAC channel wave generation. + * @param DAC_Channel: the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_Wave: Specifies the wave type to enable or disable. + * This parameter can be one of the following values: + * @arg DAC_Wave_Noise: noise wave generation + * @arg DAC_Wave_Triangle: triangle wave generation + * @param NewState: new state of the selected DAC channel wave generation. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DAC_WaveGenerationCmd(uint32_t DAC_Channel, uint32_t DAC_Wave, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_DAC_WAVE(DAC_Wave)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected wave generation for the selected DAC channel */ + DAC->CR |= DAC_Wave << DAC_Channel; + } + else + { + /* Disable the selected wave generation for the selected DAC channel */ + DAC->CR &= ~(DAC_Wave << DAC_Channel); + } +} + +/** + * @brief Set the specified data holding register value for DAC channel1. + * @param DAC_Align: Specifies the data alignment for DAC channel1. + * This parameter can be one of the following values: + * @arg DAC_Align_8b_R: 8bit right data alignment selected + * @arg DAC_Align_12b_L: 12bit left data alignment selected + * @arg DAC_Align_12b_R: 12bit right data alignment selected + * @param Data : Data to be loaded in the selected data holding register. + * @retval None + */ +void DAC_SetChannel1Data(uint32_t DAC_Align, uint16_t Data) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_ALIGN(DAC_Align)); + assert_param(IS_DAC_DATA(Data)); + + tmp = (uint32_t)DAC_BASE; + tmp += DHR12R1_OFFSET + DAC_Align; + + /* Set the DAC channel1 selected data holding register */ + *(__IO uint32_t *) tmp = Data; +} + +/** + * @brief Set the specified data holding register value for DAC channel2. + * @param DAC_Align: Specifies the data alignment for DAC channel2. + * This parameter can be one of the following values: + * @arg DAC_Align_8b_R: 8bit right data alignment selected + * @arg DAC_Align_12b_L: 12bit left data alignment selected + * @arg DAC_Align_12b_R: 12bit right data alignment selected + * @param Data : Data to be loaded in the selected data holding register. + * @retval None + */ +void DAC_SetChannel2Data(uint32_t DAC_Align, uint16_t Data) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_ALIGN(DAC_Align)); + assert_param(IS_DAC_DATA(Data)); + + tmp = (uint32_t)DAC_BASE; + tmp += DHR12R2_OFFSET + DAC_Align; + + /* Set the DAC channel2 selected data holding register */ + *(__IO uint32_t *)tmp = Data; +} + +/** + * @brief Set the specified data holding register value for dual channel + * DAC. + * @param DAC_Align: Specifies the data alignment for dual channel DAC. + * This parameter can be one of the following values: + * @arg DAC_Align_8b_R: 8bit right data alignment selected + * @arg DAC_Align_12b_L: 12bit left data alignment selected + * @arg DAC_Align_12b_R: 12bit right data alignment selected + * @param Data2: Data for DAC Channel2 to be loaded in the selected data + * holding register. + * @param Data1: Data for DAC Channel1 to be loaded in the selected data + * holding register. + * @retval None + */ +void DAC_SetDualChannelData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1) +{ + uint32_t data = 0, tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_ALIGN(DAC_Align)); + assert_param(IS_DAC_DATA(Data1)); + assert_param(IS_DAC_DATA(Data2)); + + /* Calculate and set dual DAC data holding register value */ + if (DAC_Align == DAC_Align_8b_R) + { + data = ((uint32_t)Data2 << 8) | Data1; + } + else + { + data = ((uint32_t)Data2 << 16) | Data1; + } + + tmp = (uint32_t)DAC_BASE; + tmp += DHR12RD_OFFSET + DAC_Align; + + /* Set the dual DAC selected data holding register */ + *(__IO uint32_t *)tmp = data; +} + +/** + * @brief Returns the last data output value of the selected DAC channel. + * @param DAC_Channel: the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @retval The selected DAC channel data output value. + */ +uint16_t DAC_GetDataOutputValue(uint32_t DAC_Channel) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + + tmp = (uint32_t) DAC_BASE ; + tmp += DOR_OFFSET + ((uint32_t)DAC_Channel >> 2); + + /* Returns the DAC channel data output register value */ + return (uint16_t) (*(__IO uint32_t*) tmp); +} + +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) +/** + * @brief Checks whether the specified DAC flag is set or not. + * @param DAC_Channel: thee selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_FLAG: specifies the flag to check. + * This parameter can be only of the following value: + * @arg DAC_FLAG_DMAUDR: DMA underrun flag + * @retval The new state of DAC_FLAG (SET or RESET). + */ +FlagStatus DAC_GetFlagStatus(uint32_t DAC_Channel, uint32_t DAC_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_DAC_FLAG(DAC_FLAG)); + + /* Check the status of the specified DAC flag */ + if ((DAC->SR & (DAC_FLAG << DAC_Channel)) != (uint8_t)RESET) + { + /* DAC_FLAG is set */ + bitstatus = SET; + } + else + { + /* DAC_FLAG is reset */ + bitstatus = RESET; + } + /* Return the DAC_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the DAC channelx's pending flags. + * @param DAC_Channel: the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_FLAG: specifies the flag to clear. + * This parameter can be of the following value: + * @arg DAC_FLAG_DMAUDR: DMA underrun flag + * @retval None + */ +void DAC_ClearFlag(uint32_t DAC_Channel, uint32_t DAC_FLAG) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_DAC_FLAG(DAC_FLAG)); + + /* Clear the selected DAC flags */ + DAC->SR = (DAC_FLAG << DAC_Channel); +} + +/** + * @brief Checks whether the specified DAC interrupt has occurred or not. + * @param DAC_Channel: the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_IT: specifies the DAC interrupt source to check. + * This parameter can be the following values: + * @arg DAC_IT_DMAUDR: DMA underrun interrupt mask + * @retval The new state of DAC_IT (SET or RESET). + */ +ITStatus DAC_GetITStatus(uint32_t DAC_Channel, uint32_t DAC_IT) +{ + ITStatus bitstatus = RESET; + uint32_t enablestatus = 0; + + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_DAC_IT(DAC_IT)); + + /* Get the DAC_IT enable bit status */ + enablestatus = (DAC->CR & (DAC_IT << DAC_Channel)) ; + + /* Check the status of the specified DAC interrupt */ + if (((DAC->SR & (DAC_IT << DAC_Channel)) != (uint32_t)RESET) && enablestatus) + { + /* DAC_IT is set */ + bitstatus = SET; + } + else + { + /* DAC_IT is reset */ + bitstatus = RESET; + } + /* Return the DAC_IT status */ + return bitstatus; +} + +/** + * @brief Clears the DAC channelx's interrupt pending bits. + * @param DAC_Channel: the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_IT: specifies the DAC interrupt pending bit to clear. + * This parameter can be the following values: + * @arg DAC_IT_DMAUDR: DMA underrun interrupt mask + * @retval None + */ +void DAC_ClearITPendingBit(uint32_t DAC_Channel, uint32_t DAC_IT) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_DAC_IT(DAC_IT)); + + /* Clear the selected DAC interrupt pending bits */ + DAC->SR = (DAC_IT << DAC_Channel); +} +#endif + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_dac.h b/Library/stm32f10x_dac.h new file mode 100644 index 0000000..174773c --- /dev/null +++ b/Library/stm32f10x_dac.h @@ -0,0 +1,317 @@ +/** + ****************************************************************************** + * @file stm32f10x_dac.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the DAC firmware + * library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_DAC_H +#define __STM32F10x_DAC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DAC + * @{ + */ + +/** @defgroup DAC_Exported_Types + * @{ + */ + +/** + * @brief DAC Init structure definition + */ + +typedef struct +{ + uint32_t DAC_Trigger; /*!< Specifies the external trigger for the selected DAC channel. + This parameter can be a value of @ref DAC_trigger_selection */ + + uint32_t DAC_WaveGeneration; /*!< Specifies whether DAC channel noise waves or triangle waves + are generated, or whether no wave is generated. + This parameter can be a value of @ref DAC_wave_generation */ + + uint32_t DAC_LFSRUnmask_TriangleAmplitude; /*!< Specifies the LFSR mask for noise wave generation or + the maximum amplitude triangle generation for the DAC channel. + This parameter can be a value of @ref DAC_lfsrunmask_triangleamplitude */ + + uint32_t DAC_OutputBuffer; /*!< Specifies whether the DAC channel output buffer is enabled or disabled. + This parameter can be a value of @ref DAC_output_buffer */ +}DAC_InitTypeDef; + +/** + * @} + */ + +/** @defgroup DAC_Exported_Constants + * @{ + */ + +/** @defgroup DAC_trigger_selection + * @{ + */ + +#define DAC_Trigger_None ((uint32_t)0x00000000) /*!< Conversion is automatic once the DAC1_DHRxxxx register + has been loaded, and not by external trigger */ +#define DAC_Trigger_T6_TRGO ((uint32_t)0x00000004) /*!< TIM6 TRGO selected as external conversion trigger for DAC channel */ +#define DAC_Trigger_T8_TRGO ((uint32_t)0x0000000C) /*!< TIM8 TRGO selected as external conversion trigger for DAC channel + only in High-density devices*/ +#define DAC_Trigger_T3_TRGO ((uint32_t)0x0000000C) /*!< TIM8 TRGO selected as external conversion trigger for DAC channel + only in Connectivity line, Medium-density and Low-density Value Line devices */ +#define DAC_Trigger_T7_TRGO ((uint32_t)0x00000014) /*!< TIM7 TRGO selected as external conversion trigger for DAC channel */ +#define DAC_Trigger_T5_TRGO ((uint32_t)0x0000001C) /*!< TIM5 TRGO selected as external conversion trigger for DAC channel */ +#define DAC_Trigger_T15_TRGO ((uint32_t)0x0000001C) /*!< TIM15 TRGO selected as external conversion trigger for DAC channel + only in Medium-density and Low-density Value Line devices*/ +#define DAC_Trigger_T2_TRGO ((uint32_t)0x00000024) /*!< TIM2 TRGO selected as external conversion trigger for DAC channel */ +#define DAC_Trigger_T4_TRGO ((uint32_t)0x0000002C) /*!< TIM4 TRGO selected as external conversion trigger for DAC channel */ +#define DAC_Trigger_Ext_IT9 ((uint32_t)0x00000034) /*!< EXTI Line9 event selected as external conversion trigger for DAC channel */ +#define DAC_Trigger_Software ((uint32_t)0x0000003C) /*!< Conversion started by software trigger for DAC channel */ + +#define IS_DAC_TRIGGER(TRIGGER) (((TRIGGER) == DAC_Trigger_None) || \ + ((TRIGGER) == DAC_Trigger_T6_TRGO) || \ + ((TRIGGER) == DAC_Trigger_T8_TRGO) || \ + ((TRIGGER) == DAC_Trigger_T7_TRGO) || \ + ((TRIGGER) == DAC_Trigger_T5_TRGO) || \ + ((TRIGGER) == DAC_Trigger_T2_TRGO) || \ + ((TRIGGER) == DAC_Trigger_T4_TRGO) || \ + ((TRIGGER) == DAC_Trigger_Ext_IT9) || \ + ((TRIGGER) == DAC_Trigger_Software)) + +/** + * @} + */ + +/** @defgroup DAC_wave_generation + * @{ + */ + +#define DAC_WaveGeneration_None ((uint32_t)0x00000000) +#define DAC_WaveGeneration_Noise ((uint32_t)0x00000040) +#define DAC_WaveGeneration_Triangle ((uint32_t)0x00000080) +#define IS_DAC_GENERATE_WAVE(WAVE) (((WAVE) == DAC_WaveGeneration_None) || \ + ((WAVE) == DAC_WaveGeneration_Noise) || \ + ((WAVE) == DAC_WaveGeneration_Triangle)) +/** + * @} + */ + +/** @defgroup DAC_lfsrunmask_triangleamplitude + * @{ + */ + +#define DAC_LFSRUnmask_Bit0 ((uint32_t)0x00000000) /*!< Unmask DAC channel LFSR bit0 for noise wave generation */ +#define DAC_LFSRUnmask_Bits1_0 ((uint32_t)0x00000100) /*!< Unmask DAC channel LFSR bit[1:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits2_0 ((uint32_t)0x00000200) /*!< Unmask DAC channel LFSR bit[2:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits3_0 ((uint32_t)0x00000300) /*!< Unmask DAC channel LFSR bit[3:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits4_0 ((uint32_t)0x00000400) /*!< Unmask DAC channel LFSR bit[4:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits5_0 ((uint32_t)0x00000500) /*!< Unmask DAC channel LFSR bit[5:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits6_0 ((uint32_t)0x00000600) /*!< Unmask DAC channel LFSR bit[6:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits7_0 ((uint32_t)0x00000700) /*!< Unmask DAC channel LFSR bit[7:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits8_0 ((uint32_t)0x00000800) /*!< Unmask DAC channel LFSR bit[8:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits9_0 ((uint32_t)0x00000900) /*!< Unmask DAC channel LFSR bit[9:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits10_0 ((uint32_t)0x00000A00) /*!< Unmask DAC channel LFSR bit[10:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits11_0 ((uint32_t)0x00000B00) /*!< Unmask DAC channel LFSR bit[11:0] for noise wave generation */ +#define DAC_TriangleAmplitude_1 ((uint32_t)0x00000000) /*!< Select max triangle amplitude of 1 */ +#define DAC_TriangleAmplitude_3 ((uint32_t)0x00000100) /*!< Select max triangle amplitude of 3 */ +#define DAC_TriangleAmplitude_7 ((uint32_t)0x00000200) /*!< Select max triangle amplitude of 7 */ +#define DAC_TriangleAmplitude_15 ((uint32_t)0x00000300) /*!< Select max triangle amplitude of 15 */ +#define DAC_TriangleAmplitude_31 ((uint32_t)0x00000400) /*!< Select max triangle amplitude of 31 */ +#define DAC_TriangleAmplitude_63 ((uint32_t)0x00000500) /*!< Select max triangle amplitude of 63 */ +#define DAC_TriangleAmplitude_127 ((uint32_t)0x00000600) /*!< Select max triangle amplitude of 127 */ +#define DAC_TriangleAmplitude_255 ((uint32_t)0x00000700) /*!< Select max triangle amplitude of 255 */ +#define DAC_TriangleAmplitude_511 ((uint32_t)0x00000800) /*!< Select max triangle amplitude of 511 */ +#define DAC_TriangleAmplitude_1023 ((uint32_t)0x00000900) /*!< Select max triangle amplitude of 1023 */ +#define DAC_TriangleAmplitude_2047 ((uint32_t)0x00000A00) /*!< Select max triangle amplitude of 2047 */ +#define DAC_TriangleAmplitude_4095 ((uint32_t)0x00000B00) /*!< Select max triangle amplitude of 4095 */ + +#define IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(VALUE) (((VALUE) == DAC_LFSRUnmask_Bit0) || \ + ((VALUE) == DAC_LFSRUnmask_Bits1_0) || \ + ((VALUE) == DAC_LFSRUnmask_Bits2_0) || \ + ((VALUE) == DAC_LFSRUnmask_Bits3_0) || \ + ((VALUE) == DAC_LFSRUnmask_Bits4_0) || \ + ((VALUE) == DAC_LFSRUnmask_Bits5_0) || \ + ((VALUE) == DAC_LFSRUnmask_Bits6_0) || \ + ((VALUE) == DAC_LFSRUnmask_Bits7_0) || \ + ((VALUE) == DAC_LFSRUnmask_Bits8_0) || \ + ((VALUE) == DAC_LFSRUnmask_Bits9_0) || \ + ((VALUE) == DAC_LFSRUnmask_Bits10_0) || \ + ((VALUE) == DAC_LFSRUnmask_Bits11_0) || \ + ((VALUE) == DAC_TriangleAmplitude_1) || \ + ((VALUE) == DAC_TriangleAmplitude_3) || \ + ((VALUE) == DAC_TriangleAmplitude_7) || \ + ((VALUE) == DAC_TriangleAmplitude_15) || \ + ((VALUE) == DAC_TriangleAmplitude_31) || \ + ((VALUE) == DAC_TriangleAmplitude_63) || \ + ((VALUE) == DAC_TriangleAmplitude_127) || \ + ((VALUE) == DAC_TriangleAmplitude_255) || \ + ((VALUE) == DAC_TriangleAmplitude_511) || \ + ((VALUE) == DAC_TriangleAmplitude_1023) || \ + ((VALUE) == DAC_TriangleAmplitude_2047) || \ + ((VALUE) == DAC_TriangleAmplitude_4095)) +/** + * @} + */ + +/** @defgroup DAC_output_buffer + * @{ + */ + +#define DAC_OutputBuffer_Enable ((uint32_t)0x00000000) +#define DAC_OutputBuffer_Disable ((uint32_t)0x00000002) +#define IS_DAC_OUTPUT_BUFFER_STATE(STATE) (((STATE) == DAC_OutputBuffer_Enable) || \ + ((STATE) == DAC_OutputBuffer_Disable)) +/** + * @} + */ + +/** @defgroup DAC_Channel_selection + * @{ + */ + +#define DAC_Channel_1 ((uint32_t)0x00000000) +#define DAC_Channel_2 ((uint32_t)0x00000010) +#define IS_DAC_CHANNEL(CHANNEL) (((CHANNEL) == DAC_Channel_1) || \ + ((CHANNEL) == DAC_Channel_2)) +/** + * @} + */ + +/** @defgroup DAC_data_alignment + * @{ + */ + +#define DAC_Align_12b_R ((uint32_t)0x00000000) +#define DAC_Align_12b_L ((uint32_t)0x00000004) +#define DAC_Align_8b_R ((uint32_t)0x00000008) +#define IS_DAC_ALIGN(ALIGN) (((ALIGN) == DAC_Align_12b_R) || \ + ((ALIGN) == DAC_Align_12b_L) || \ + ((ALIGN) == DAC_Align_8b_R)) +/** + * @} + */ + +/** @defgroup DAC_wave_generation + * @{ + */ + +#define DAC_Wave_Noise ((uint32_t)0x00000040) +#define DAC_Wave_Triangle ((uint32_t)0x00000080) +#define IS_DAC_WAVE(WAVE) (((WAVE) == DAC_Wave_Noise) || \ + ((WAVE) == DAC_Wave_Triangle)) +/** + * @} + */ + +/** @defgroup DAC_data + * @{ + */ + +#define IS_DAC_DATA(DATA) ((DATA) <= 0xFFF0) +/** + * @} + */ +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) +/** @defgroup DAC_interrupts_definition + * @{ + */ + +#define DAC_IT_DMAUDR ((uint32_t)0x00002000) +#define IS_DAC_IT(IT) (((IT) == DAC_IT_DMAUDR)) + +/** + * @} + */ + +/** @defgroup DAC_flags_definition + * @{ + */ + +#define DAC_FLAG_DMAUDR ((uint32_t)0x00002000) +#define IS_DAC_FLAG(FLAG) (((FLAG) == DAC_FLAG_DMAUDR)) + +/** + * @} + */ +#endif + +/** + * @} + */ + +/** @defgroup DAC_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup DAC_Exported_Functions + * @{ + */ + +void DAC_DeInit(void); +void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct); +void DAC_StructInit(DAC_InitTypeDef* DAC_InitStruct); +void DAC_Cmd(uint32_t DAC_Channel, FunctionalState NewState); +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) +void DAC_ITConfig(uint32_t DAC_Channel, uint32_t DAC_IT, FunctionalState NewState); +#endif +void DAC_DMACmd(uint32_t DAC_Channel, FunctionalState NewState); +void DAC_SoftwareTriggerCmd(uint32_t DAC_Channel, FunctionalState NewState); +void DAC_DualSoftwareTriggerCmd(FunctionalState NewState); +void DAC_WaveGenerationCmd(uint32_t DAC_Channel, uint32_t DAC_Wave, FunctionalState NewState); +void DAC_SetChannel1Data(uint32_t DAC_Align, uint16_t Data); +void DAC_SetChannel2Data(uint32_t DAC_Align, uint16_t Data); +void DAC_SetDualChannelData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1); +uint16_t DAC_GetDataOutputValue(uint32_t DAC_Channel); +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) +FlagStatus DAC_GetFlagStatus(uint32_t DAC_Channel, uint32_t DAC_FLAG); +void DAC_ClearFlag(uint32_t DAC_Channel, uint32_t DAC_FLAG); +ITStatus DAC_GetITStatus(uint32_t DAC_Channel, uint32_t DAC_IT); +void DAC_ClearITPendingBit(uint32_t DAC_Channel, uint32_t DAC_IT); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /*__STM32F10x_DAC_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_dbgmcu.c b/Library/stm32f10x_dbgmcu.c new file mode 100644 index 0000000..96a8fde --- /dev/null +++ b/Library/stm32f10x_dbgmcu.c @@ -0,0 +1,162 @@ +/** + ****************************************************************************** + * @file stm32f10x_dbgmcu.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the DBGMCU firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_dbgmcu.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup DBGMCU + * @brief DBGMCU driver modules + * @{ + */ + +/** @defgroup DBGMCU_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup DBGMCU_Private_Defines + * @{ + */ + +#define IDCODE_DEVID_MASK ((uint32_t)0x00000FFF) +/** + * @} + */ + +/** @defgroup DBGMCU_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup DBGMCU_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup DBGMCU_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup DBGMCU_Private_Functions + * @{ + */ + +/** + * @brief Returns the device revision identifier. + * @param None + * @retval Device revision identifier + */ +uint32_t DBGMCU_GetREVID(void) +{ + return(DBGMCU->IDCODE >> 16); +} + +/** + * @brief Returns the device identifier. + * @param None + * @retval Device identifier + */ +uint32_t DBGMCU_GetDEVID(void) +{ + return(DBGMCU->IDCODE & IDCODE_DEVID_MASK); +} + +/** + * @brief Configures the specified peripheral and low power mode behavior + * when the MCU under Debug mode. + * @param DBGMCU_Periph: specifies the peripheral and low power mode. + * This parameter can be any combination of the following values: + * @arg DBGMCU_SLEEP: Keep debugger connection during SLEEP mode + * @arg DBGMCU_STOP: Keep debugger connection during STOP mode + * @arg DBGMCU_STANDBY: Keep debugger connection during STANDBY mode + * @arg DBGMCU_IWDG_STOP: Debug IWDG stopped when Core is halted + * @arg DBGMCU_WWDG_STOP: Debug WWDG stopped when Core is halted + * @arg DBGMCU_TIM1_STOP: TIM1 counter stopped when Core is halted + * @arg DBGMCU_TIM2_STOP: TIM2 counter stopped when Core is halted + * @arg DBGMCU_TIM3_STOP: TIM3 counter stopped when Core is halted + * @arg DBGMCU_TIM4_STOP: TIM4 counter stopped when Core is halted + * @arg DBGMCU_CAN1_STOP: Debug CAN2 stopped when Core is halted + * @arg DBGMCU_I2C1_SMBUS_TIMEOUT: I2C1 SMBUS timeout mode stopped when Core is halted + * @arg DBGMCU_I2C2_SMBUS_TIMEOUT: I2C2 SMBUS timeout mode stopped when Core is halted + * @arg DBGMCU_TIM5_STOP: TIM5 counter stopped when Core is halted + * @arg DBGMCU_TIM6_STOP: TIM6 counter stopped when Core is halted + * @arg DBGMCU_TIM7_STOP: TIM7 counter stopped when Core is halted + * @arg DBGMCU_TIM8_STOP: TIM8 counter stopped when Core is halted + * @arg DBGMCU_CAN2_STOP: Debug CAN2 stopped when Core is halted + * @arg DBGMCU_TIM15_STOP: TIM15 counter stopped when Core is halted + * @arg DBGMCU_TIM16_STOP: TIM16 counter stopped when Core is halted + * @arg DBGMCU_TIM17_STOP: TIM17 counter stopped when Core is halted + * @arg DBGMCU_TIM9_STOP: TIM9 counter stopped when Core is halted + * @arg DBGMCU_TIM10_STOP: TIM10 counter stopped when Core is halted + * @arg DBGMCU_TIM11_STOP: TIM11 counter stopped when Core is halted + * @arg DBGMCU_TIM12_STOP: TIM12 counter stopped when Core is halted + * @arg DBGMCU_TIM13_STOP: TIM13 counter stopped when Core is halted + * @arg DBGMCU_TIM14_STOP: TIM14 counter stopped when Core is halted + * @param NewState: new state of the specified peripheral in Debug mode. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DBGMCU_Config(uint32_t DBGMCU_Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DBGMCU_PERIPH(DBGMCU_Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + DBGMCU->CR |= DBGMCU_Periph; + } + else + { + DBGMCU->CR &= ~DBGMCU_Periph; + } +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_dbgmcu.h b/Library/stm32f10x_dbgmcu.h new file mode 100644 index 0000000..89ceb9a --- /dev/null +++ b/Library/stm32f10x_dbgmcu.h @@ -0,0 +1,119 @@ +/** + ****************************************************************************** + * @file stm32f10x_dbgmcu.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the DBGMCU + * firmware library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_DBGMCU_H +#define __STM32F10x_DBGMCU_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DBGMCU + * @{ + */ + +/** @defgroup DBGMCU_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @defgroup DBGMCU_Exported_Constants + * @{ + */ + +#define DBGMCU_SLEEP ((uint32_t)0x00000001) +#define DBGMCU_STOP ((uint32_t)0x00000002) +#define DBGMCU_STANDBY ((uint32_t)0x00000004) +#define DBGMCU_IWDG_STOP ((uint32_t)0x00000100) +#define DBGMCU_WWDG_STOP ((uint32_t)0x00000200) +#define DBGMCU_TIM1_STOP ((uint32_t)0x00000400) +#define DBGMCU_TIM2_STOP ((uint32_t)0x00000800) +#define DBGMCU_TIM3_STOP ((uint32_t)0x00001000) +#define DBGMCU_TIM4_STOP ((uint32_t)0x00002000) +#define DBGMCU_CAN1_STOP ((uint32_t)0x00004000) +#define DBGMCU_I2C1_SMBUS_TIMEOUT ((uint32_t)0x00008000) +#define DBGMCU_I2C2_SMBUS_TIMEOUT ((uint32_t)0x00010000) +#define DBGMCU_TIM8_STOP ((uint32_t)0x00020000) +#define DBGMCU_TIM5_STOP ((uint32_t)0x00040000) +#define DBGMCU_TIM6_STOP ((uint32_t)0x00080000) +#define DBGMCU_TIM7_STOP ((uint32_t)0x00100000) +#define DBGMCU_CAN2_STOP ((uint32_t)0x00200000) +#define DBGMCU_TIM15_STOP ((uint32_t)0x00400000) +#define DBGMCU_TIM16_STOP ((uint32_t)0x00800000) +#define DBGMCU_TIM17_STOP ((uint32_t)0x01000000) +#define DBGMCU_TIM12_STOP ((uint32_t)0x02000000) +#define DBGMCU_TIM13_STOP ((uint32_t)0x04000000) +#define DBGMCU_TIM14_STOP ((uint32_t)0x08000000) +#define DBGMCU_TIM9_STOP ((uint32_t)0x10000000) +#define DBGMCU_TIM10_STOP ((uint32_t)0x20000000) +#define DBGMCU_TIM11_STOP ((uint32_t)0x40000000) + +#define IS_DBGMCU_PERIPH(PERIPH) ((((PERIPH) & 0x800000F8) == 0x00) && ((PERIPH) != 0x00)) +/** + * @} + */ + +/** @defgroup DBGMCU_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup DBGMCU_Exported_Functions + * @{ + */ + +uint32_t DBGMCU_GetREVID(void); +uint32_t DBGMCU_GetDEVID(void); +void DBGMCU_Config(uint32_t DBGMCU_Periph, FunctionalState NewState); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F10x_DBGMCU_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_dma.c b/Library/stm32f10x_dma.c new file mode 100644 index 0000000..bf072df --- /dev/null +++ b/Library/stm32f10x_dma.c @@ -0,0 +1,714 @@ +/** + ****************************************************************************** + * @file stm32f10x_dma.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the DMA firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_dma.h" +#include "stm32f10x_rcc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup DMA + * @brief DMA driver modules + * @{ + */ + +/** @defgroup DMA_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + +/** @defgroup DMA_Private_Defines + * @{ + */ + + +/* DMA1 Channelx interrupt pending bit masks */ +#define DMA1_Channel1_IT_Mask ((uint32_t)(DMA_ISR_GIF1 | DMA_ISR_TCIF1 | DMA_ISR_HTIF1 | DMA_ISR_TEIF1)) +#define DMA1_Channel2_IT_Mask ((uint32_t)(DMA_ISR_GIF2 | DMA_ISR_TCIF2 | DMA_ISR_HTIF2 | DMA_ISR_TEIF2)) +#define DMA1_Channel3_IT_Mask ((uint32_t)(DMA_ISR_GIF3 | DMA_ISR_TCIF3 | DMA_ISR_HTIF3 | DMA_ISR_TEIF3)) +#define DMA1_Channel4_IT_Mask ((uint32_t)(DMA_ISR_GIF4 | DMA_ISR_TCIF4 | DMA_ISR_HTIF4 | DMA_ISR_TEIF4)) +#define DMA1_Channel5_IT_Mask ((uint32_t)(DMA_ISR_GIF5 | DMA_ISR_TCIF5 | DMA_ISR_HTIF5 | DMA_ISR_TEIF5)) +#define DMA1_Channel6_IT_Mask ((uint32_t)(DMA_ISR_GIF6 | DMA_ISR_TCIF6 | DMA_ISR_HTIF6 | DMA_ISR_TEIF6)) +#define DMA1_Channel7_IT_Mask ((uint32_t)(DMA_ISR_GIF7 | DMA_ISR_TCIF7 | DMA_ISR_HTIF7 | DMA_ISR_TEIF7)) + +/* DMA2 Channelx interrupt pending bit masks */ +#define DMA2_Channel1_IT_Mask ((uint32_t)(DMA_ISR_GIF1 | DMA_ISR_TCIF1 | DMA_ISR_HTIF1 | DMA_ISR_TEIF1)) +#define DMA2_Channel2_IT_Mask ((uint32_t)(DMA_ISR_GIF2 | DMA_ISR_TCIF2 | DMA_ISR_HTIF2 | DMA_ISR_TEIF2)) +#define DMA2_Channel3_IT_Mask ((uint32_t)(DMA_ISR_GIF3 | DMA_ISR_TCIF3 | DMA_ISR_HTIF3 | DMA_ISR_TEIF3)) +#define DMA2_Channel4_IT_Mask ((uint32_t)(DMA_ISR_GIF4 | DMA_ISR_TCIF4 | DMA_ISR_HTIF4 | DMA_ISR_TEIF4)) +#define DMA2_Channel5_IT_Mask ((uint32_t)(DMA_ISR_GIF5 | DMA_ISR_TCIF5 | DMA_ISR_HTIF5 | DMA_ISR_TEIF5)) + +/* DMA2 FLAG mask */ +#define FLAG_Mask ((uint32_t)0x10000000) + +/* DMA registers Masks */ +#define CCR_CLEAR_Mask ((uint32_t)0xFFFF800F) + +/** + * @} + */ + +/** @defgroup DMA_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup DMA_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup DMA_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup DMA_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the DMAy Channelx registers to their default reset + * values. + * @param DMAy_Channelx: where y can be 1 or 2 to select the DMA and + * x can be 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel. + * @retval None + */ +void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx)); + + /* Disable the selected DMAy Channelx */ + DMAy_Channelx->CCR &= (uint16_t)(~DMA_CCR1_EN); + + /* Reset DMAy Channelx control register */ + DMAy_Channelx->CCR = 0; + + /* Reset DMAy Channelx remaining bytes register */ + DMAy_Channelx->CNDTR = 0; + + /* Reset DMAy Channelx peripheral address register */ + DMAy_Channelx->CPAR = 0; + + /* Reset DMAy Channelx memory address register */ + DMAy_Channelx->CMAR = 0; + + if (DMAy_Channelx == DMA1_Channel1) + { + /* Reset interrupt pending bits for DMA1 Channel1 */ + DMA1->IFCR |= DMA1_Channel1_IT_Mask; + } + else if (DMAy_Channelx == DMA1_Channel2) + { + /* Reset interrupt pending bits for DMA1 Channel2 */ + DMA1->IFCR |= DMA1_Channel2_IT_Mask; + } + else if (DMAy_Channelx == DMA1_Channel3) + { + /* Reset interrupt pending bits for DMA1 Channel3 */ + DMA1->IFCR |= DMA1_Channel3_IT_Mask; + } + else if (DMAy_Channelx == DMA1_Channel4) + { + /* Reset interrupt pending bits for DMA1 Channel4 */ + DMA1->IFCR |= DMA1_Channel4_IT_Mask; + } + else if (DMAy_Channelx == DMA1_Channel5) + { + /* Reset interrupt pending bits for DMA1 Channel5 */ + DMA1->IFCR |= DMA1_Channel5_IT_Mask; + } + else if (DMAy_Channelx == DMA1_Channel6) + { + /* Reset interrupt pending bits for DMA1 Channel6 */ + DMA1->IFCR |= DMA1_Channel6_IT_Mask; + } + else if (DMAy_Channelx == DMA1_Channel7) + { + /* Reset interrupt pending bits for DMA1 Channel7 */ + DMA1->IFCR |= DMA1_Channel7_IT_Mask; + } + else if (DMAy_Channelx == DMA2_Channel1) + { + /* Reset interrupt pending bits for DMA2 Channel1 */ + DMA2->IFCR |= DMA2_Channel1_IT_Mask; + } + else if (DMAy_Channelx == DMA2_Channel2) + { + /* Reset interrupt pending bits for DMA2 Channel2 */ + DMA2->IFCR |= DMA2_Channel2_IT_Mask; + } + else if (DMAy_Channelx == DMA2_Channel3) + { + /* Reset interrupt pending bits for DMA2 Channel3 */ + DMA2->IFCR |= DMA2_Channel3_IT_Mask; + } + else if (DMAy_Channelx == DMA2_Channel4) + { + /* Reset interrupt pending bits for DMA2 Channel4 */ + DMA2->IFCR |= DMA2_Channel4_IT_Mask; + } + else + { + if (DMAy_Channelx == DMA2_Channel5) + { + /* Reset interrupt pending bits for DMA2 Channel5 */ + DMA2->IFCR |= DMA2_Channel5_IT_Mask; + } + } +} + +/** + * @brief Initializes the DMAy Channelx according to the specified + * parameters in the DMA_InitStruct. + * @param DMAy_Channelx: where y can be 1 or 2 to select the DMA and + * x can be 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel. + * @param DMA_InitStruct: pointer to a DMA_InitTypeDef structure that + * contains the configuration information for the specified DMA Channel. + * @retval None + */ +void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx)); + assert_param(IS_DMA_DIR(DMA_InitStruct->DMA_DIR)); + assert_param(IS_DMA_BUFFER_SIZE(DMA_InitStruct->DMA_BufferSize)); + assert_param(IS_DMA_PERIPHERAL_INC_STATE(DMA_InitStruct->DMA_PeripheralInc)); + assert_param(IS_DMA_MEMORY_INC_STATE(DMA_InitStruct->DMA_MemoryInc)); + assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(DMA_InitStruct->DMA_PeripheralDataSize)); + assert_param(IS_DMA_MEMORY_DATA_SIZE(DMA_InitStruct->DMA_MemoryDataSize)); + assert_param(IS_DMA_MODE(DMA_InitStruct->DMA_Mode)); + assert_param(IS_DMA_PRIORITY(DMA_InitStruct->DMA_Priority)); + assert_param(IS_DMA_M2M_STATE(DMA_InitStruct->DMA_M2M)); + +/*--------------------------- DMAy Channelx CCR Configuration -----------------*/ + /* Get the DMAy_Channelx CCR value */ + tmpreg = DMAy_Channelx->CCR; + /* Clear MEM2MEM, PL, MSIZE, PSIZE, MINC, PINC, CIRC and DIR bits */ + tmpreg &= CCR_CLEAR_Mask; + /* Configure DMAy Channelx: data transfer, data size, priority level and mode */ + /* Set DIR bit according to DMA_DIR value */ + /* Set CIRC bit according to DMA_Mode value */ + /* Set PINC bit according to DMA_PeripheralInc value */ + /* Set MINC bit according to DMA_MemoryInc value */ + /* Set PSIZE bits according to DMA_PeripheralDataSize value */ + /* Set MSIZE bits according to DMA_MemoryDataSize value */ + /* Set PL bits according to DMA_Priority value */ + /* Set the MEM2MEM bit according to DMA_M2M value */ + tmpreg |= DMA_InitStruct->DMA_DIR | DMA_InitStruct->DMA_Mode | + DMA_InitStruct->DMA_PeripheralInc | DMA_InitStruct->DMA_MemoryInc | + DMA_InitStruct->DMA_PeripheralDataSize | DMA_InitStruct->DMA_MemoryDataSize | + DMA_InitStruct->DMA_Priority | DMA_InitStruct->DMA_M2M; + + /* Write to DMAy Channelx CCR */ + DMAy_Channelx->CCR = tmpreg; + +/*--------------------------- DMAy Channelx CNDTR Configuration ---------------*/ + /* Write to DMAy Channelx CNDTR */ + DMAy_Channelx->CNDTR = DMA_InitStruct->DMA_BufferSize; + +/*--------------------------- DMAy Channelx CPAR Configuration ----------------*/ + /* Write to DMAy Channelx CPAR */ + DMAy_Channelx->CPAR = DMA_InitStruct->DMA_PeripheralBaseAddr; + +/*--------------------------- DMAy Channelx CMAR Configuration ----------------*/ + /* Write to DMAy Channelx CMAR */ + DMAy_Channelx->CMAR = DMA_InitStruct->DMA_MemoryBaseAddr; +} + +/** + * @brief Fills each DMA_InitStruct member with its default value. + * @param DMA_InitStruct : pointer to a DMA_InitTypeDef structure which will + * be initialized. + * @retval None + */ +void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct) +{ +/*-------------- Reset DMA init structure parameters values ------------------*/ + /* Initialize the DMA_PeripheralBaseAddr member */ + DMA_InitStruct->DMA_PeripheralBaseAddr = 0; + /* Initialize the DMA_MemoryBaseAddr member */ + DMA_InitStruct->DMA_MemoryBaseAddr = 0; + /* Initialize the DMA_DIR member */ + DMA_InitStruct->DMA_DIR = DMA_DIR_PeripheralSRC; + /* Initialize the DMA_BufferSize member */ + DMA_InitStruct->DMA_BufferSize = 0; + /* Initialize the DMA_PeripheralInc member */ + DMA_InitStruct->DMA_PeripheralInc = DMA_PeripheralInc_Disable; + /* Initialize the DMA_MemoryInc member */ + DMA_InitStruct->DMA_MemoryInc = DMA_MemoryInc_Disable; + /* Initialize the DMA_PeripheralDataSize member */ + DMA_InitStruct->DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + /* Initialize the DMA_MemoryDataSize member */ + DMA_InitStruct->DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + /* Initialize the DMA_Mode member */ + DMA_InitStruct->DMA_Mode = DMA_Mode_Normal; + /* Initialize the DMA_Priority member */ + DMA_InitStruct->DMA_Priority = DMA_Priority_Low; + /* Initialize the DMA_M2M member */ + DMA_InitStruct->DMA_M2M = DMA_M2M_Disable; +} + +/** + * @brief Enables or disables the specified DMAy Channelx. + * @param DMAy_Channelx: where y can be 1 or 2 to select the DMA and + * x can be 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel. + * @param NewState: new state of the DMAy Channelx. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected DMAy Channelx */ + DMAy_Channelx->CCR |= DMA_CCR1_EN; + } + else + { + /* Disable the selected DMAy Channelx */ + DMAy_Channelx->CCR &= (uint16_t)(~DMA_CCR1_EN); + } +} + +/** + * @brief Enables or disables the specified DMAy Channelx interrupts. + * @param DMAy_Channelx: where y can be 1 or 2 to select the DMA and + * x can be 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel. + * @param DMA_IT: specifies the DMA interrupts sources to be enabled + * or disabled. + * This parameter can be any combination of the following values: + * @arg DMA_IT_TC: Transfer complete interrupt mask + * @arg DMA_IT_HT: Half transfer interrupt mask + * @arg DMA_IT_TE: Transfer error interrupt mask + * @param NewState: new state of the specified DMA interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx)); + assert_param(IS_DMA_CONFIG_IT(DMA_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected DMA interrupts */ + DMAy_Channelx->CCR |= DMA_IT; + } + else + { + /* Disable the selected DMA interrupts */ + DMAy_Channelx->CCR &= ~DMA_IT; + } +} + +/** + * @brief Sets the number of data units in the current DMAy Channelx transfer. + * @param DMAy_Channelx: where y can be 1 or 2 to select the DMA and + * x can be 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel. + * @param DataNumber: The number of data units in the current DMAy Channelx + * transfer. + * @note This function can only be used when the DMAy_Channelx is disabled. + * @retval None. + */ +void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx)); + +/*--------------------------- DMAy Channelx CNDTR Configuration ---------------*/ + /* Write to DMAy Channelx CNDTR */ + DMAy_Channelx->CNDTR = DataNumber; +} + +/** + * @brief Returns the number of remaining data units in the current + * DMAy Channelx transfer. + * @param DMAy_Channelx: where y can be 1 or 2 to select the DMA and + * x can be 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel. + * @retval The number of remaining data units in the current DMAy Channelx + * transfer. + */ +uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx)); + /* Return the number of remaining data units for DMAy Channelx */ + return ((uint16_t)(DMAy_Channelx->CNDTR)); +} + +/** + * @brief Checks whether the specified DMAy Channelx flag is set or not. + * @param DMAy_FLAG: specifies the flag to check. + * This parameter can be one of the following values: + * @arg DMA1_FLAG_GL1: DMA1 Channel1 global flag. + * @arg DMA1_FLAG_TC1: DMA1 Channel1 transfer complete flag. + * @arg DMA1_FLAG_HT1: DMA1 Channel1 half transfer flag. + * @arg DMA1_FLAG_TE1: DMA1 Channel1 transfer error flag. + * @arg DMA1_FLAG_GL2: DMA1 Channel2 global flag. + * @arg DMA1_FLAG_TC2: DMA1 Channel2 transfer complete flag. + * @arg DMA1_FLAG_HT2: DMA1 Channel2 half transfer flag. + * @arg DMA1_FLAG_TE2: DMA1 Channel2 transfer error flag. + * @arg DMA1_FLAG_GL3: DMA1 Channel3 global flag. + * @arg DMA1_FLAG_TC3: DMA1 Channel3 transfer complete flag. + * @arg DMA1_FLAG_HT3: DMA1 Channel3 half transfer flag. + * @arg DMA1_FLAG_TE3: DMA1 Channel3 transfer error flag. + * @arg DMA1_FLAG_GL4: DMA1 Channel4 global flag. + * @arg DMA1_FLAG_TC4: DMA1 Channel4 transfer complete flag. + * @arg DMA1_FLAG_HT4: DMA1 Channel4 half transfer flag. + * @arg DMA1_FLAG_TE4: DMA1 Channel4 transfer error flag. + * @arg DMA1_FLAG_GL5: DMA1 Channel5 global flag. + * @arg DMA1_FLAG_TC5: DMA1 Channel5 transfer complete flag. + * @arg DMA1_FLAG_HT5: DMA1 Channel5 half transfer flag. + * @arg DMA1_FLAG_TE5: DMA1 Channel5 transfer error flag. + * @arg DMA1_FLAG_GL6: DMA1 Channel6 global flag. + * @arg DMA1_FLAG_TC6: DMA1 Channel6 transfer complete flag. + * @arg DMA1_FLAG_HT6: DMA1 Channel6 half transfer flag. + * @arg DMA1_FLAG_TE6: DMA1 Channel6 transfer error flag. + * @arg DMA1_FLAG_GL7: DMA1 Channel7 global flag. + * @arg DMA1_FLAG_TC7: DMA1 Channel7 transfer complete flag. + * @arg DMA1_FLAG_HT7: DMA1 Channel7 half transfer flag. + * @arg DMA1_FLAG_TE7: DMA1 Channel7 transfer error flag. + * @arg DMA2_FLAG_GL1: DMA2 Channel1 global flag. + * @arg DMA2_FLAG_TC1: DMA2 Channel1 transfer complete flag. + * @arg DMA2_FLAG_HT1: DMA2 Channel1 half transfer flag. + * @arg DMA2_FLAG_TE1: DMA2 Channel1 transfer error flag. + * @arg DMA2_FLAG_GL2: DMA2 Channel2 global flag. + * @arg DMA2_FLAG_TC2: DMA2 Channel2 transfer complete flag. + * @arg DMA2_FLAG_HT2: DMA2 Channel2 half transfer flag. + * @arg DMA2_FLAG_TE2: DMA2 Channel2 transfer error flag. + * @arg DMA2_FLAG_GL3: DMA2 Channel3 global flag. + * @arg DMA2_FLAG_TC3: DMA2 Channel3 transfer complete flag. + * @arg DMA2_FLAG_HT3: DMA2 Channel3 half transfer flag. + * @arg DMA2_FLAG_TE3: DMA2 Channel3 transfer error flag. + * @arg DMA2_FLAG_GL4: DMA2 Channel4 global flag. + * @arg DMA2_FLAG_TC4: DMA2 Channel4 transfer complete flag. + * @arg DMA2_FLAG_HT4: DMA2 Channel4 half transfer flag. + * @arg DMA2_FLAG_TE4: DMA2 Channel4 transfer error flag. + * @arg DMA2_FLAG_GL5: DMA2 Channel5 global flag. + * @arg DMA2_FLAG_TC5: DMA2 Channel5 transfer complete flag. + * @arg DMA2_FLAG_HT5: DMA2 Channel5 half transfer flag. + * @arg DMA2_FLAG_TE5: DMA2 Channel5 transfer error flag. + * @retval The new state of DMAy_FLAG (SET or RESET). + */ +FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG) +{ + FlagStatus bitstatus = RESET; + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_DMA_GET_FLAG(DMAy_FLAG)); + + /* Calculate the used DMAy */ + if ((DMAy_FLAG & FLAG_Mask) != (uint32_t)RESET) + { + /* Get DMA2 ISR register value */ + tmpreg = DMA2->ISR ; + } + else + { + /* Get DMA1 ISR register value */ + tmpreg = DMA1->ISR ; + } + + /* Check the status of the specified DMAy flag */ + if ((tmpreg & DMAy_FLAG) != (uint32_t)RESET) + { + /* DMAy_FLAG is set */ + bitstatus = SET; + } + else + { + /* DMAy_FLAG is reset */ + bitstatus = RESET; + } + + /* Return the DMAy_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the DMAy Channelx's pending flags. + * @param DMAy_FLAG: specifies the flag to clear. + * This parameter can be any combination (for the same DMA) of the following values: + * @arg DMA1_FLAG_GL1: DMA1 Channel1 global flag. + * @arg DMA1_FLAG_TC1: DMA1 Channel1 transfer complete flag. + * @arg DMA1_FLAG_HT1: DMA1 Channel1 half transfer flag. + * @arg DMA1_FLAG_TE1: DMA1 Channel1 transfer error flag. + * @arg DMA1_FLAG_GL2: DMA1 Channel2 global flag. + * @arg DMA1_FLAG_TC2: DMA1 Channel2 transfer complete flag. + * @arg DMA1_FLAG_HT2: DMA1 Channel2 half transfer flag. + * @arg DMA1_FLAG_TE2: DMA1 Channel2 transfer error flag. + * @arg DMA1_FLAG_GL3: DMA1 Channel3 global flag. + * @arg DMA1_FLAG_TC3: DMA1 Channel3 transfer complete flag. + * @arg DMA1_FLAG_HT3: DMA1 Channel3 half transfer flag. + * @arg DMA1_FLAG_TE3: DMA1 Channel3 transfer error flag. + * @arg DMA1_FLAG_GL4: DMA1 Channel4 global flag. + * @arg DMA1_FLAG_TC4: DMA1 Channel4 transfer complete flag. + * @arg DMA1_FLAG_HT4: DMA1 Channel4 half transfer flag. + * @arg DMA1_FLAG_TE4: DMA1 Channel4 transfer error flag. + * @arg DMA1_FLAG_GL5: DMA1 Channel5 global flag. + * @arg DMA1_FLAG_TC5: DMA1 Channel5 transfer complete flag. + * @arg DMA1_FLAG_HT5: DMA1 Channel5 half transfer flag. + * @arg DMA1_FLAG_TE5: DMA1 Channel5 transfer error flag. + * @arg DMA1_FLAG_GL6: DMA1 Channel6 global flag. + * @arg DMA1_FLAG_TC6: DMA1 Channel6 transfer complete flag. + * @arg DMA1_FLAG_HT6: DMA1 Channel6 half transfer flag. + * @arg DMA1_FLAG_TE6: DMA1 Channel6 transfer error flag. + * @arg DMA1_FLAG_GL7: DMA1 Channel7 global flag. + * @arg DMA1_FLAG_TC7: DMA1 Channel7 transfer complete flag. + * @arg DMA1_FLAG_HT7: DMA1 Channel7 half transfer flag. + * @arg DMA1_FLAG_TE7: DMA1 Channel7 transfer error flag. + * @arg DMA2_FLAG_GL1: DMA2 Channel1 global flag. + * @arg DMA2_FLAG_TC1: DMA2 Channel1 transfer complete flag. + * @arg DMA2_FLAG_HT1: DMA2 Channel1 half transfer flag. + * @arg DMA2_FLAG_TE1: DMA2 Channel1 transfer error flag. + * @arg DMA2_FLAG_GL2: DMA2 Channel2 global flag. + * @arg DMA2_FLAG_TC2: DMA2 Channel2 transfer complete flag. + * @arg DMA2_FLAG_HT2: DMA2 Channel2 half transfer flag. + * @arg DMA2_FLAG_TE2: DMA2 Channel2 transfer error flag. + * @arg DMA2_FLAG_GL3: DMA2 Channel3 global flag. + * @arg DMA2_FLAG_TC3: DMA2 Channel3 transfer complete flag. + * @arg DMA2_FLAG_HT3: DMA2 Channel3 half transfer flag. + * @arg DMA2_FLAG_TE3: DMA2 Channel3 transfer error flag. + * @arg DMA2_FLAG_GL4: DMA2 Channel4 global flag. + * @arg DMA2_FLAG_TC4: DMA2 Channel4 transfer complete flag. + * @arg DMA2_FLAG_HT4: DMA2 Channel4 half transfer flag. + * @arg DMA2_FLAG_TE4: DMA2 Channel4 transfer error flag. + * @arg DMA2_FLAG_GL5: DMA2 Channel5 global flag. + * @arg DMA2_FLAG_TC5: DMA2 Channel5 transfer complete flag. + * @arg DMA2_FLAG_HT5: DMA2 Channel5 half transfer flag. + * @arg DMA2_FLAG_TE5: DMA2 Channel5 transfer error flag. + * @retval None + */ +void DMA_ClearFlag(uint32_t DMAy_FLAG) +{ + /* Check the parameters */ + assert_param(IS_DMA_CLEAR_FLAG(DMAy_FLAG)); + + /* Calculate the used DMAy */ + if ((DMAy_FLAG & FLAG_Mask) != (uint32_t)RESET) + { + /* Clear the selected DMAy flags */ + DMA2->IFCR = DMAy_FLAG; + } + else + { + /* Clear the selected DMAy flags */ + DMA1->IFCR = DMAy_FLAG; + } +} + +/** + * @brief Checks whether the specified DMAy Channelx interrupt has occurred or not. + * @param DMAy_IT: specifies the DMAy interrupt source to check. + * This parameter can be one of the following values: + * @arg DMA1_IT_GL1: DMA1 Channel1 global interrupt. + * @arg DMA1_IT_TC1: DMA1 Channel1 transfer complete interrupt. + * @arg DMA1_IT_HT1: DMA1 Channel1 half transfer interrupt. + * @arg DMA1_IT_TE1: DMA1 Channel1 transfer error interrupt. + * @arg DMA1_IT_GL2: DMA1 Channel2 global interrupt. + * @arg DMA1_IT_TC2: DMA1 Channel2 transfer complete interrupt. + * @arg DMA1_IT_HT2: DMA1 Channel2 half transfer interrupt. + * @arg DMA1_IT_TE2: DMA1 Channel2 transfer error interrupt. + * @arg DMA1_IT_GL3: DMA1 Channel3 global interrupt. + * @arg DMA1_IT_TC3: DMA1 Channel3 transfer complete interrupt. + * @arg DMA1_IT_HT3: DMA1 Channel3 half transfer interrupt. + * @arg DMA1_IT_TE3: DMA1 Channel3 transfer error interrupt. + * @arg DMA1_IT_GL4: DMA1 Channel4 global interrupt. + * @arg DMA1_IT_TC4: DMA1 Channel4 transfer complete interrupt. + * @arg DMA1_IT_HT4: DMA1 Channel4 half transfer interrupt. + * @arg DMA1_IT_TE4: DMA1 Channel4 transfer error interrupt. + * @arg DMA1_IT_GL5: DMA1 Channel5 global interrupt. + * @arg DMA1_IT_TC5: DMA1 Channel5 transfer complete interrupt. + * @arg DMA1_IT_HT5: DMA1 Channel5 half transfer interrupt. + * @arg DMA1_IT_TE5: DMA1 Channel5 transfer error interrupt. + * @arg DMA1_IT_GL6: DMA1 Channel6 global interrupt. + * @arg DMA1_IT_TC6: DMA1 Channel6 transfer complete interrupt. + * @arg DMA1_IT_HT6: DMA1 Channel6 half transfer interrupt. + * @arg DMA1_IT_TE6: DMA1 Channel6 transfer error interrupt. + * @arg DMA1_IT_GL7: DMA1 Channel7 global interrupt. + * @arg DMA1_IT_TC7: DMA1 Channel7 transfer complete interrupt. + * @arg DMA1_IT_HT7: DMA1 Channel7 half transfer interrupt. + * @arg DMA1_IT_TE7: DMA1 Channel7 transfer error interrupt. + * @arg DMA2_IT_GL1: DMA2 Channel1 global interrupt. + * @arg DMA2_IT_TC1: DMA2 Channel1 transfer complete interrupt. + * @arg DMA2_IT_HT1: DMA2 Channel1 half transfer interrupt. + * @arg DMA2_IT_TE1: DMA2 Channel1 transfer error interrupt. + * @arg DMA2_IT_GL2: DMA2 Channel2 global interrupt. + * @arg DMA2_IT_TC2: DMA2 Channel2 transfer complete interrupt. + * @arg DMA2_IT_HT2: DMA2 Channel2 half transfer interrupt. + * @arg DMA2_IT_TE2: DMA2 Channel2 transfer error interrupt. + * @arg DMA2_IT_GL3: DMA2 Channel3 global interrupt. + * @arg DMA2_IT_TC3: DMA2 Channel3 transfer complete interrupt. + * @arg DMA2_IT_HT3: DMA2 Channel3 half transfer interrupt. + * @arg DMA2_IT_TE3: DMA2 Channel3 transfer error interrupt. + * @arg DMA2_IT_GL4: DMA2 Channel4 global interrupt. + * @arg DMA2_IT_TC4: DMA2 Channel4 transfer complete interrupt. + * @arg DMA2_IT_HT4: DMA2 Channel4 half transfer interrupt. + * @arg DMA2_IT_TE4: DMA2 Channel4 transfer error interrupt. + * @arg DMA2_IT_GL5: DMA2 Channel5 global interrupt. + * @arg DMA2_IT_TC5: DMA2 Channel5 transfer complete interrupt. + * @arg DMA2_IT_HT5: DMA2 Channel5 half transfer interrupt. + * @arg DMA2_IT_TE5: DMA2 Channel5 transfer error interrupt. + * @retval The new state of DMAy_IT (SET or RESET). + */ +ITStatus DMA_GetITStatus(uint32_t DMAy_IT) +{ + ITStatus bitstatus = RESET; + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_DMA_GET_IT(DMAy_IT)); + + /* Calculate the used DMA */ + if ((DMAy_IT & FLAG_Mask) != (uint32_t)RESET) + { + /* Get DMA2 ISR register value */ + tmpreg = DMA2->ISR; + } + else + { + /* Get DMA1 ISR register value */ + tmpreg = DMA1->ISR; + } + + /* Check the status of the specified DMAy interrupt */ + if ((tmpreg & DMAy_IT) != (uint32_t)RESET) + { + /* DMAy_IT is set */ + bitstatus = SET; + } + else + { + /* DMAy_IT is reset */ + bitstatus = RESET; + } + /* Return the DMA_IT status */ + return bitstatus; +} + +/** + * @brief Clears the DMAy Channelx's interrupt pending bits. + * @param DMAy_IT: specifies the DMAy interrupt pending bit to clear. + * This parameter can be any combination (for the same DMA) of the following values: + * @arg DMA1_IT_GL1: DMA1 Channel1 global interrupt. + * @arg DMA1_IT_TC1: DMA1 Channel1 transfer complete interrupt. + * @arg DMA1_IT_HT1: DMA1 Channel1 half transfer interrupt. + * @arg DMA1_IT_TE1: DMA1 Channel1 transfer error interrupt. + * @arg DMA1_IT_GL2: DMA1 Channel2 global interrupt. + * @arg DMA1_IT_TC2: DMA1 Channel2 transfer complete interrupt. + * @arg DMA1_IT_HT2: DMA1 Channel2 half transfer interrupt. + * @arg DMA1_IT_TE2: DMA1 Channel2 transfer error interrupt. + * @arg DMA1_IT_GL3: DMA1 Channel3 global interrupt. + * @arg DMA1_IT_TC3: DMA1 Channel3 transfer complete interrupt. + * @arg DMA1_IT_HT3: DMA1 Channel3 half transfer interrupt. + * @arg DMA1_IT_TE3: DMA1 Channel3 transfer error interrupt. + * @arg DMA1_IT_GL4: DMA1 Channel4 global interrupt. + * @arg DMA1_IT_TC4: DMA1 Channel4 transfer complete interrupt. + * @arg DMA1_IT_HT4: DMA1 Channel4 half transfer interrupt. + * @arg DMA1_IT_TE4: DMA1 Channel4 transfer error interrupt. + * @arg DMA1_IT_GL5: DMA1 Channel5 global interrupt. + * @arg DMA1_IT_TC5: DMA1 Channel5 transfer complete interrupt. + * @arg DMA1_IT_HT5: DMA1 Channel5 half transfer interrupt. + * @arg DMA1_IT_TE5: DMA1 Channel5 transfer error interrupt. + * @arg DMA1_IT_GL6: DMA1 Channel6 global interrupt. + * @arg DMA1_IT_TC6: DMA1 Channel6 transfer complete interrupt. + * @arg DMA1_IT_HT6: DMA1 Channel6 half transfer interrupt. + * @arg DMA1_IT_TE6: DMA1 Channel6 transfer error interrupt. + * @arg DMA1_IT_GL7: DMA1 Channel7 global interrupt. + * @arg DMA1_IT_TC7: DMA1 Channel7 transfer complete interrupt. + * @arg DMA1_IT_HT7: DMA1 Channel7 half transfer interrupt. + * @arg DMA1_IT_TE7: DMA1 Channel7 transfer error interrupt. + * @arg DMA2_IT_GL1: DMA2 Channel1 global interrupt. + * @arg DMA2_IT_TC1: DMA2 Channel1 transfer complete interrupt. + * @arg DMA2_IT_HT1: DMA2 Channel1 half transfer interrupt. + * @arg DMA2_IT_TE1: DMA2 Channel1 transfer error interrupt. + * @arg DMA2_IT_GL2: DMA2 Channel2 global interrupt. + * @arg DMA2_IT_TC2: DMA2 Channel2 transfer complete interrupt. + * @arg DMA2_IT_HT2: DMA2 Channel2 half transfer interrupt. + * @arg DMA2_IT_TE2: DMA2 Channel2 transfer error interrupt. + * @arg DMA2_IT_GL3: DMA2 Channel3 global interrupt. + * @arg DMA2_IT_TC3: DMA2 Channel3 transfer complete interrupt. + * @arg DMA2_IT_HT3: DMA2 Channel3 half transfer interrupt. + * @arg DMA2_IT_TE3: DMA2 Channel3 transfer error interrupt. + * @arg DMA2_IT_GL4: DMA2 Channel4 global interrupt. + * @arg DMA2_IT_TC4: DMA2 Channel4 transfer complete interrupt. + * @arg DMA2_IT_HT4: DMA2 Channel4 half transfer interrupt. + * @arg DMA2_IT_TE4: DMA2 Channel4 transfer error interrupt. + * @arg DMA2_IT_GL5: DMA2 Channel5 global interrupt. + * @arg DMA2_IT_TC5: DMA2 Channel5 transfer complete interrupt. + * @arg DMA2_IT_HT5: DMA2 Channel5 half transfer interrupt. + * @arg DMA2_IT_TE5: DMA2 Channel5 transfer error interrupt. + * @retval None + */ +void DMA_ClearITPendingBit(uint32_t DMAy_IT) +{ + /* Check the parameters */ + assert_param(IS_DMA_CLEAR_IT(DMAy_IT)); + + /* Calculate the used DMAy */ + if ((DMAy_IT & FLAG_Mask) != (uint32_t)RESET) + { + /* Clear the selected DMAy interrupt pending bits */ + DMA2->IFCR = DMAy_IT; + } + else + { + /* Clear the selected DMAy interrupt pending bits */ + DMA1->IFCR = DMAy_IT; + } +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_dma.h b/Library/stm32f10x_dma.h new file mode 100644 index 0000000..14275fe --- /dev/null +++ b/Library/stm32f10x_dma.h @@ -0,0 +1,439 @@ +/** + ****************************************************************************** + * @file stm32f10x_dma.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the DMA firmware + * library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_DMA_H +#define __STM32F10x_DMA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DMA + * @{ + */ + +/** @defgroup DMA_Exported_Types + * @{ + */ + +/** + * @brief DMA Init structure definition + */ + +typedef struct +{ + uint32_t DMA_PeripheralBaseAddr; /*!< Specifies the peripheral base address for DMAy Channelx. */ + + uint32_t DMA_MemoryBaseAddr; /*!< Specifies the memory base address for DMAy Channelx. */ + + uint32_t DMA_DIR; /*!< Specifies if the peripheral is the source or destination. + This parameter can be a value of @ref DMA_data_transfer_direction */ + + uint32_t DMA_BufferSize; /*!< Specifies the buffer size, in data unit, of the specified Channel. + The data unit is equal to the configuration set in DMA_PeripheralDataSize + or DMA_MemoryDataSize members depending in the transfer direction. */ + + uint32_t DMA_PeripheralInc; /*!< Specifies whether the Peripheral address register is incremented or not. + This parameter can be a value of @ref DMA_peripheral_incremented_mode */ + + uint32_t DMA_MemoryInc; /*!< Specifies whether the memory address register is incremented or not. + This parameter can be a value of @ref DMA_memory_incremented_mode */ + + uint32_t DMA_PeripheralDataSize; /*!< Specifies the Peripheral data width. + This parameter can be a value of @ref DMA_peripheral_data_size */ + + uint32_t DMA_MemoryDataSize; /*!< Specifies the Memory data width. + This parameter can be a value of @ref DMA_memory_data_size */ + + uint32_t DMA_Mode; /*!< Specifies the operation mode of the DMAy Channelx. + This parameter can be a value of @ref DMA_circular_normal_mode. + @note: The circular buffer mode cannot be used if the memory-to-memory + data transfer is configured on the selected Channel */ + + uint32_t DMA_Priority; /*!< Specifies the software priority for the DMAy Channelx. + This parameter can be a value of @ref DMA_priority_level */ + + uint32_t DMA_M2M; /*!< Specifies if the DMAy Channelx will be used in memory-to-memory transfer. + This parameter can be a value of @ref DMA_memory_to_memory */ +}DMA_InitTypeDef; + +/** + * @} + */ + +/** @defgroup DMA_Exported_Constants + * @{ + */ + +#define IS_DMA_ALL_PERIPH(PERIPH) (((PERIPH) == DMA1_Channel1) || \ + ((PERIPH) == DMA1_Channel2) || \ + ((PERIPH) == DMA1_Channel3) || \ + ((PERIPH) == DMA1_Channel4) || \ + ((PERIPH) == DMA1_Channel5) || \ + ((PERIPH) == DMA1_Channel6) || \ + ((PERIPH) == DMA1_Channel7) || \ + ((PERIPH) == DMA2_Channel1) || \ + ((PERIPH) == DMA2_Channel2) || \ + ((PERIPH) == DMA2_Channel3) || \ + ((PERIPH) == DMA2_Channel4) || \ + ((PERIPH) == DMA2_Channel5)) + +/** @defgroup DMA_data_transfer_direction + * @{ + */ + +#define DMA_DIR_PeripheralDST ((uint32_t)0x00000010) +#define DMA_DIR_PeripheralSRC ((uint32_t)0x00000000) +#define IS_DMA_DIR(DIR) (((DIR) == DMA_DIR_PeripheralDST) || \ + ((DIR) == DMA_DIR_PeripheralSRC)) +/** + * @} + */ + +/** @defgroup DMA_peripheral_incremented_mode + * @{ + */ + +#define DMA_PeripheralInc_Enable ((uint32_t)0x00000040) +#define DMA_PeripheralInc_Disable ((uint32_t)0x00000000) +#define IS_DMA_PERIPHERAL_INC_STATE(STATE) (((STATE) == DMA_PeripheralInc_Enable) || \ + ((STATE) == DMA_PeripheralInc_Disable)) +/** + * @} + */ + +/** @defgroup DMA_memory_incremented_mode + * @{ + */ + +#define DMA_MemoryInc_Enable ((uint32_t)0x00000080) +#define DMA_MemoryInc_Disable ((uint32_t)0x00000000) +#define IS_DMA_MEMORY_INC_STATE(STATE) (((STATE) == DMA_MemoryInc_Enable) || \ + ((STATE) == DMA_MemoryInc_Disable)) +/** + * @} + */ + +/** @defgroup DMA_peripheral_data_size + * @{ + */ + +#define DMA_PeripheralDataSize_Byte ((uint32_t)0x00000000) +#define DMA_PeripheralDataSize_HalfWord ((uint32_t)0x00000100) +#define DMA_PeripheralDataSize_Word ((uint32_t)0x00000200) +#define IS_DMA_PERIPHERAL_DATA_SIZE(SIZE) (((SIZE) == DMA_PeripheralDataSize_Byte) || \ + ((SIZE) == DMA_PeripheralDataSize_HalfWord) || \ + ((SIZE) == DMA_PeripheralDataSize_Word)) +/** + * @} + */ + +/** @defgroup DMA_memory_data_size + * @{ + */ + +#define DMA_MemoryDataSize_Byte ((uint32_t)0x00000000) +#define DMA_MemoryDataSize_HalfWord ((uint32_t)0x00000400) +#define DMA_MemoryDataSize_Word ((uint32_t)0x00000800) +#define IS_DMA_MEMORY_DATA_SIZE(SIZE) (((SIZE) == DMA_MemoryDataSize_Byte) || \ + ((SIZE) == DMA_MemoryDataSize_HalfWord) || \ + ((SIZE) == DMA_MemoryDataSize_Word)) +/** + * @} + */ + +/** @defgroup DMA_circular_normal_mode + * @{ + */ + +#define DMA_Mode_Circular ((uint32_t)0x00000020) +#define DMA_Mode_Normal ((uint32_t)0x00000000) +#define IS_DMA_MODE(MODE) (((MODE) == DMA_Mode_Circular) || ((MODE) == DMA_Mode_Normal)) +/** + * @} + */ + +/** @defgroup DMA_priority_level + * @{ + */ + +#define DMA_Priority_VeryHigh ((uint32_t)0x00003000) +#define DMA_Priority_High ((uint32_t)0x00002000) +#define DMA_Priority_Medium ((uint32_t)0x00001000) +#define DMA_Priority_Low ((uint32_t)0x00000000) +#define IS_DMA_PRIORITY(PRIORITY) (((PRIORITY) == DMA_Priority_VeryHigh) || \ + ((PRIORITY) == DMA_Priority_High) || \ + ((PRIORITY) == DMA_Priority_Medium) || \ + ((PRIORITY) == DMA_Priority_Low)) +/** + * @} + */ + +/** @defgroup DMA_memory_to_memory + * @{ + */ + +#define DMA_M2M_Enable ((uint32_t)0x00004000) +#define DMA_M2M_Disable ((uint32_t)0x00000000) +#define IS_DMA_M2M_STATE(STATE) (((STATE) == DMA_M2M_Enable) || ((STATE) == DMA_M2M_Disable)) + +/** + * @} + */ + +/** @defgroup DMA_interrupts_definition + * @{ + */ + +#define DMA_IT_TC ((uint32_t)0x00000002) +#define DMA_IT_HT ((uint32_t)0x00000004) +#define DMA_IT_TE ((uint32_t)0x00000008) +#define IS_DMA_CONFIG_IT(IT) ((((IT) & 0xFFFFFFF1) == 0x00) && ((IT) != 0x00)) + +#define DMA1_IT_GL1 ((uint32_t)0x00000001) +#define DMA1_IT_TC1 ((uint32_t)0x00000002) +#define DMA1_IT_HT1 ((uint32_t)0x00000004) +#define DMA1_IT_TE1 ((uint32_t)0x00000008) +#define DMA1_IT_GL2 ((uint32_t)0x00000010) +#define DMA1_IT_TC2 ((uint32_t)0x00000020) +#define DMA1_IT_HT2 ((uint32_t)0x00000040) +#define DMA1_IT_TE2 ((uint32_t)0x00000080) +#define DMA1_IT_GL3 ((uint32_t)0x00000100) +#define DMA1_IT_TC3 ((uint32_t)0x00000200) +#define DMA1_IT_HT3 ((uint32_t)0x00000400) +#define DMA1_IT_TE3 ((uint32_t)0x00000800) +#define DMA1_IT_GL4 ((uint32_t)0x00001000) +#define DMA1_IT_TC4 ((uint32_t)0x00002000) +#define DMA1_IT_HT4 ((uint32_t)0x00004000) +#define DMA1_IT_TE4 ((uint32_t)0x00008000) +#define DMA1_IT_GL5 ((uint32_t)0x00010000) +#define DMA1_IT_TC5 ((uint32_t)0x00020000) +#define DMA1_IT_HT5 ((uint32_t)0x00040000) +#define DMA1_IT_TE5 ((uint32_t)0x00080000) +#define DMA1_IT_GL6 ((uint32_t)0x00100000) +#define DMA1_IT_TC6 ((uint32_t)0x00200000) +#define DMA1_IT_HT6 ((uint32_t)0x00400000) +#define DMA1_IT_TE6 ((uint32_t)0x00800000) +#define DMA1_IT_GL7 ((uint32_t)0x01000000) +#define DMA1_IT_TC7 ((uint32_t)0x02000000) +#define DMA1_IT_HT7 ((uint32_t)0x04000000) +#define DMA1_IT_TE7 ((uint32_t)0x08000000) + +#define DMA2_IT_GL1 ((uint32_t)0x10000001) +#define DMA2_IT_TC1 ((uint32_t)0x10000002) +#define DMA2_IT_HT1 ((uint32_t)0x10000004) +#define DMA2_IT_TE1 ((uint32_t)0x10000008) +#define DMA2_IT_GL2 ((uint32_t)0x10000010) +#define DMA2_IT_TC2 ((uint32_t)0x10000020) +#define DMA2_IT_HT2 ((uint32_t)0x10000040) +#define DMA2_IT_TE2 ((uint32_t)0x10000080) +#define DMA2_IT_GL3 ((uint32_t)0x10000100) +#define DMA2_IT_TC3 ((uint32_t)0x10000200) +#define DMA2_IT_HT3 ((uint32_t)0x10000400) +#define DMA2_IT_TE3 ((uint32_t)0x10000800) +#define DMA2_IT_GL4 ((uint32_t)0x10001000) +#define DMA2_IT_TC4 ((uint32_t)0x10002000) +#define DMA2_IT_HT4 ((uint32_t)0x10004000) +#define DMA2_IT_TE4 ((uint32_t)0x10008000) +#define DMA2_IT_GL5 ((uint32_t)0x10010000) +#define DMA2_IT_TC5 ((uint32_t)0x10020000) +#define DMA2_IT_HT5 ((uint32_t)0x10040000) +#define DMA2_IT_TE5 ((uint32_t)0x10080000) + +#define IS_DMA_CLEAR_IT(IT) (((((IT) & 0xF0000000) == 0x00) || (((IT) & 0xEFF00000) == 0x00)) && ((IT) != 0x00)) + +#define IS_DMA_GET_IT(IT) (((IT) == DMA1_IT_GL1) || ((IT) == DMA1_IT_TC1) || \ + ((IT) == DMA1_IT_HT1) || ((IT) == DMA1_IT_TE1) || \ + ((IT) == DMA1_IT_GL2) || ((IT) == DMA1_IT_TC2) || \ + ((IT) == DMA1_IT_HT2) || ((IT) == DMA1_IT_TE2) || \ + ((IT) == DMA1_IT_GL3) || ((IT) == DMA1_IT_TC3) || \ + ((IT) == DMA1_IT_HT3) || ((IT) == DMA1_IT_TE3) || \ + ((IT) == DMA1_IT_GL4) || ((IT) == DMA1_IT_TC4) || \ + ((IT) == DMA1_IT_HT4) || ((IT) == DMA1_IT_TE4) || \ + ((IT) == DMA1_IT_GL5) || ((IT) == DMA1_IT_TC5) || \ + ((IT) == DMA1_IT_HT5) || ((IT) == DMA1_IT_TE5) || \ + ((IT) == DMA1_IT_GL6) || ((IT) == DMA1_IT_TC6) || \ + ((IT) == DMA1_IT_HT6) || ((IT) == DMA1_IT_TE6) || \ + ((IT) == DMA1_IT_GL7) || ((IT) == DMA1_IT_TC7) || \ + ((IT) == DMA1_IT_HT7) || ((IT) == DMA1_IT_TE7) || \ + ((IT) == DMA2_IT_GL1) || ((IT) == DMA2_IT_TC1) || \ + ((IT) == DMA2_IT_HT1) || ((IT) == DMA2_IT_TE1) || \ + ((IT) == DMA2_IT_GL2) || ((IT) == DMA2_IT_TC2) || \ + ((IT) == DMA2_IT_HT2) || ((IT) == DMA2_IT_TE2) || \ + ((IT) == DMA2_IT_GL3) || ((IT) == DMA2_IT_TC3) || \ + ((IT) == DMA2_IT_HT3) || ((IT) == DMA2_IT_TE3) || \ + ((IT) == DMA2_IT_GL4) || ((IT) == DMA2_IT_TC4) || \ + ((IT) == DMA2_IT_HT4) || ((IT) == DMA2_IT_TE4) || \ + ((IT) == DMA2_IT_GL5) || ((IT) == DMA2_IT_TC5) || \ + ((IT) == DMA2_IT_HT5) || ((IT) == DMA2_IT_TE5)) + +/** + * @} + */ + +/** @defgroup DMA_flags_definition + * @{ + */ +#define DMA1_FLAG_GL1 ((uint32_t)0x00000001) +#define DMA1_FLAG_TC1 ((uint32_t)0x00000002) +#define DMA1_FLAG_HT1 ((uint32_t)0x00000004) +#define DMA1_FLAG_TE1 ((uint32_t)0x00000008) +#define DMA1_FLAG_GL2 ((uint32_t)0x00000010) +#define DMA1_FLAG_TC2 ((uint32_t)0x00000020) +#define DMA1_FLAG_HT2 ((uint32_t)0x00000040) +#define DMA1_FLAG_TE2 ((uint32_t)0x00000080) +#define DMA1_FLAG_GL3 ((uint32_t)0x00000100) +#define DMA1_FLAG_TC3 ((uint32_t)0x00000200) +#define DMA1_FLAG_HT3 ((uint32_t)0x00000400) +#define DMA1_FLAG_TE3 ((uint32_t)0x00000800) +#define DMA1_FLAG_GL4 ((uint32_t)0x00001000) +#define DMA1_FLAG_TC4 ((uint32_t)0x00002000) +#define DMA1_FLAG_HT4 ((uint32_t)0x00004000) +#define DMA1_FLAG_TE4 ((uint32_t)0x00008000) +#define DMA1_FLAG_GL5 ((uint32_t)0x00010000) +#define DMA1_FLAG_TC5 ((uint32_t)0x00020000) +#define DMA1_FLAG_HT5 ((uint32_t)0x00040000) +#define DMA1_FLAG_TE5 ((uint32_t)0x00080000) +#define DMA1_FLAG_GL6 ((uint32_t)0x00100000) +#define DMA1_FLAG_TC6 ((uint32_t)0x00200000) +#define DMA1_FLAG_HT6 ((uint32_t)0x00400000) +#define DMA1_FLAG_TE6 ((uint32_t)0x00800000) +#define DMA1_FLAG_GL7 ((uint32_t)0x01000000) +#define DMA1_FLAG_TC7 ((uint32_t)0x02000000) +#define DMA1_FLAG_HT7 ((uint32_t)0x04000000) +#define DMA1_FLAG_TE7 ((uint32_t)0x08000000) + +#define DMA2_FLAG_GL1 ((uint32_t)0x10000001) +#define DMA2_FLAG_TC1 ((uint32_t)0x10000002) +#define DMA2_FLAG_HT1 ((uint32_t)0x10000004) +#define DMA2_FLAG_TE1 ((uint32_t)0x10000008) +#define DMA2_FLAG_GL2 ((uint32_t)0x10000010) +#define DMA2_FLAG_TC2 ((uint32_t)0x10000020) +#define DMA2_FLAG_HT2 ((uint32_t)0x10000040) +#define DMA2_FLAG_TE2 ((uint32_t)0x10000080) +#define DMA2_FLAG_GL3 ((uint32_t)0x10000100) +#define DMA2_FLAG_TC3 ((uint32_t)0x10000200) +#define DMA2_FLAG_HT3 ((uint32_t)0x10000400) +#define DMA2_FLAG_TE3 ((uint32_t)0x10000800) +#define DMA2_FLAG_GL4 ((uint32_t)0x10001000) +#define DMA2_FLAG_TC4 ((uint32_t)0x10002000) +#define DMA2_FLAG_HT4 ((uint32_t)0x10004000) +#define DMA2_FLAG_TE4 ((uint32_t)0x10008000) +#define DMA2_FLAG_GL5 ((uint32_t)0x10010000) +#define DMA2_FLAG_TC5 ((uint32_t)0x10020000) +#define DMA2_FLAG_HT5 ((uint32_t)0x10040000) +#define DMA2_FLAG_TE5 ((uint32_t)0x10080000) + +#define IS_DMA_CLEAR_FLAG(FLAG) (((((FLAG) & 0xF0000000) == 0x00) || (((FLAG) & 0xEFF00000) == 0x00)) && ((FLAG) != 0x00)) + +#define IS_DMA_GET_FLAG(FLAG) (((FLAG) == DMA1_FLAG_GL1) || ((FLAG) == DMA1_FLAG_TC1) || \ + ((FLAG) == DMA1_FLAG_HT1) || ((FLAG) == DMA1_FLAG_TE1) || \ + ((FLAG) == DMA1_FLAG_GL2) || ((FLAG) == DMA1_FLAG_TC2) || \ + ((FLAG) == DMA1_FLAG_HT2) || ((FLAG) == DMA1_FLAG_TE2) || \ + ((FLAG) == DMA1_FLAG_GL3) || ((FLAG) == DMA1_FLAG_TC3) || \ + ((FLAG) == DMA1_FLAG_HT3) || ((FLAG) == DMA1_FLAG_TE3) || \ + ((FLAG) == DMA1_FLAG_GL4) || ((FLAG) == DMA1_FLAG_TC4) || \ + ((FLAG) == DMA1_FLAG_HT4) || ((FLAG) == DMA1_FLAG_TE4) || \ + ((FLAG) == DMA1_FLAG_GL5) || ((FLAG) == DMA1_FLAG_TC5) || \ + ((FLAG) == DMA1_FLAG_HT5) || ((FLAG) == DMA1_FLAG_TE5) || \ + ((FLAG) == DMA1_FLAG_GL6) || ((FLAG) == DMA1_FLAG_TC6) || \ + ((FLAG) == DMA1_FLAG_HT6) || ((FLAG) == DMA1_FLAG_TE6) || \ + ((FLAG) == DMA1_FLAG_GL7) || ((FLAG) == DMA1_FLAG_TC7) || \ + ((FLAG) == DMA1_FLAG_HT7) || ((FLAG) == DMA1_FLAG_TE7) || \ + ((FLAG) == DMA2_FLAG_GL1) || ((FLAG) == DMA2_FLAG_TC1) || \ + ((FLAG) == DMA2_FLAG_HT1) || ((FLAG) == DMA2_FLAG_TE1) || \ + ((FLAG) == DMA2_FLAG_GL2) || ((FLAG) == DMA2_FLAG_TC2) || \ + ((FLAG) == DMA2_FLAG_HT2) || ((FLAG) == DMA2_FLAG_TE2) || \ + ((FLAG) == DMA2_FLAG_GL3) || ((FLAG) == DMA2_FLAG_TC3) || \ + ((FLAG) == DMA2_FLAG_HT3) || ((FLAG) == DMA2_FLAG_TE3) || \ + ((FLAG) == DMA2_FLAG_GL4) || ((FLAG) == DMA2_FLAG_TC4) || \ + ((FLAG) == DMA2_FLAG_HT4) || ((FLAG) == DMA2_FLAG_TE4) || \ + ((FLAG) == DMA2_FLAG_GL5) || ((FLAG) == DMA2_FLAG_TC5) || \ + ((FLAG) == DMA2_FLAG_HT5) || ((FLAG) == DMA2_FLAG_TE5)) +/** + * @} + */ + +/** @defgroup DMA_Buffer_Size + * @{ + */ + +#define IS_DMA_BUFFER_SIZE(SIZE) (((SIZE) >= 0x1) && ((SIZE) < 0x10000)) + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup DMA_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup DMA_Exported_Functions + * @{ + */ + +void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx); +void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct); +void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct); +void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState); +void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState); +void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber); +uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx); +FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG); +void DMA_ClearFlag(uint32_t DMAy_FLAG); +ITStatus DMA_GetITStatus(uint32_t DMAy_IT); +void DMA_ClearITPendingBit(uint32_t DMAy_IT); + +#ifdef __cplusplus +} +#endif + +#endif /*__STM32F10x_DMA_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_exti.c b/Library/stm32f10x_exti.c new file mode 100644 index 0000000..b6290d5 --- /dev/null +++ b/Library/stm32f10x_exti.c @@ -0,0 +1,269 @@ +/** + ****************************************************************************** + * @file stm32f10x_exti.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the EXTI firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_exti.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup EXTI + * @brief EXTI driver modules + * @{ + */ + +/** @defgroup EXTI_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup EXTI_Private_Defines + * @{ + */ + +#define EXTI_LINENONE ((uint32_t)0x00000) /* No interrupt selected */ + +/** + * @} + */ + +/** @defgroup EXTI_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup EXTI_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup EXTI_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup EXTI_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the EXTI peripheral registers to their default reset values. + * @param None + * @retval None + */ +void EXTI_DeInit(void) +{ + EXTI->IMR = 0x00000000; + EXTI->EMR = 0x00000000; + EXTI->RTSR = 0x00000000; + EXTI->FTSR = 0x00000000; + EXTI->PR = 0x000FFFFF; +} + +/** + * @brief Initializes the EXTI peripheral according to the specified + * parameters in the EXTI_InitStruct. + * @param EXTI_InitStruct: pointer to a EXTI_InitTypeDef structure + * that contains the configuration information for the EXTI peripheral. + * @retval None + */ +void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct) +{ + uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_EXTI_MODE(EXTI_InitStruct->EXTI_Mode)); + assert_param(IS_EXTI_TRIGGER(EXTI_InitStruct->EXTI_Trigger)); + assert_param(IS_EXTI_LINE(EXTI_InitStruct->EXTI_Line)); + assert_param(IS_FUNCTIONAL_STATE(EXTI_InitStruct->EXTI_LineCmd)); + + tmp = (uint32_t)EXTI_BASE; + + if (EXTI_InitStruct->EXTI_LineCmd != DISABLE) + { + /* Clear EXTI line configuration */ + EXTI->IMR &= ~EXTI_InitStruct->EXTI_Line; + EXTI->EMR &= ~EXTI_InitStruct->EXTI_Line; + + tmp += EXTI_InitStruct->EXTI_Mode; + + *(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line; + + /* Clear Rising Falling edge configuration */ + EXTI->RTSR &= ~EXTI_InitStruct->EXTI_Line; + EXTI->FTSR &= ~EXTI_InitStruct->EXTI_Line; + + /* Select the trigger for the selected external interrupts */ + if (EXTI_InitStruct->EXTI_Trigger == EXTI_Trigger_Rising_Falling) + { + /* Rising Falling edge */ + EXTI->RTSR |= EXTI_InitStruct->EXTI_Line; + EXTI->FTSR |= EXTI_InitStruct->EXTI_Line; + } + else + { + tmp = (uint32_t)EXTI_BASE; + tmp += EXTI_InitStruct->EXTI_Trigger; + + *(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line; + } + } + else + { + tmp += EXTI_InitStruct->EXTI_Mode; + + /* Disable the selected external lines */ + *(__IO uint32_t *) tmp &= ~EXTI_InitStruct->EXTI_Line; + } +} + +/** + * @brief Fills each EXTI_InitStruct member with its reset value. + * @param EXTI_InitStruct: pointer to a EXTI_InitTypeDef structure which will + * be initialized. + * @retval None + */ +void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct) +{ + EXTI_InitStruct->EXTI_Line = EXTI_LINENONE; + EXTI_InitStruct->EXTI_Mode = EXTI_Mode_Interrupt; + EXTI_InitStruct->EXTI_Trigger = EXTI_Trigger_Falling; + EXTI_InitStruct->EXTI_LineCmd = DISABLE; +} + +/** + * @brief Generates a Software interrupt. + * @param EXTI_Line: specifies the EXTI lines to be enabled or disabled. + * This parameter can be any combination of EXTI_Linex where x can be (0..19). + * @retval None + */ +void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line) +{ + /* Check the parameters */ + assert_param(IS_EXTI_LINE(EXTI_Line)); + + EXTI->SWIER |= EXTI_Line; +} + +/** + * @brief Checks whether the specified EXTI line flag is set or not. + * @param EXTI_Line: specifies the EXTI line flag to check. + * This parameter can be: + * @arg EXTI_Linex: External interrupt line x where x(0..19) + * @retval The new state of EXTI_Line (SET or RESET). + */ +FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_GET_EXTI_LINE(EXTI_Line)); + + if ((EXTI->PR & EXTI_Line) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the EXTI's line pending flags. + * @param EXTI_Line: specifies the EXTI lines flags to clear. + * This parameter can be any combination of EXTI_Linex where x can be (0..19). + * @retval None + */ +void EXTI_ClearFlag(uint32_t EXTI_Line) +{ + /* Check the parameters */ + assert_param(IS_EXTI_LINE(EXTI_Line)); + + EXTI->PR = EXTI_Line; +} + +/** + * @brief Checks whether the specified EXTI line is asserted or not. + * @param EXTI_Line: specifies the EXTI line to check. + * This parameter can be: + * @arg EXTI_Linex: External interrupt line x where x(0..19) + * @retval The new state of EXTI_Line (SET or RESET). + */ +ITStatus EXTI_GetITStatus(uint32_t EXTI_Line) +{ + ITStatus bitstatus = RESET; + uint32_t enablestatus = 0; + /* Check the parameters */ + assert_param(IS_GET_EXTI_LINE(EXTI_Line)); + + enablestatus = EXTI->IMR & EXTI_Line; + if (((EXTI->PR & EXTI_Line) != (uint32_t)RESET) && (enablestatus != (uint32_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the EXTI's line pending bits. + * @param EXTI_Line: specifies the EXTI lines to clear. + * This parameter can be any combination of EXTI_Linex where x can be (0..19). + * @retval None + */ +void EXTI_ClearITPendingBit(uint32_t EXTI_Line) +{ + /* Check the parameters */ + assert_param(IS_EXTI_LINE(EXTI_Line)); + + EXTI->PR = EXTI_Line; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_exti.h b/Library/stm32f10x_exti.h new file mode 100644 index 0000000..bb9d7f6 --- /dev/null +++ b/Library/stm32f10x_exti.h @@ -0,0 +1,184 @@ +/** + ****************************************************************************** + * @file stm32f10x_exti.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the EXTI firmware + * library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_EXTI_H +#define __STM32F10x_EXTI_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup EXTI + * @{ + */ + +/** @defgroup EXTI_Exported_Types + * @{ + */ + +/** + * @brief EXTI mode enumeration + */ + +typedef enum +{ + EXTI_Mode_Interrupt = 0x00, + EXTI_Mode_Event = 0x04 +}EXTIMode_TypeDef; + +#define IS_EXTI_MODE(MODE) (((MODE) == EXTI_Mode_Interrupt) || ((MODE) == EXTI_Mode_Event)) + +/** + * @brief EXTI Trigger enumeration + */ + +typedef enum +{ + EXTI_Trigger_Rising = 0x08, + EXTI_Trigger_Falling = 0x0C, + EXTI_Trigger_Rising_Falling = 0x10 +}EXTITrigger_TypeDef; + +#define IS_EXTI_TRIGGER(TRIGGER) (((TRIGGER) == EXTI_Trigger_Rising) || \ + ((TRIGGER) == EXTI_Trigger_Falling) || \ + ((TRIGGER) == EXTI_Trigger_Rising_Falling)) +/** + * @brief EXTI Init Structure definition + */ + +typedef struct +{ + uint32_t EXTI_Line; /*!< Specifies the EXTI lines to be enabled or disabled. + This parameter can be any combination of @ref EXTI_Lines */ + + EXTIMode_TypeDef EXTI_Mode; /*!< Specifies the mode for the EXTI lines. + This parameter can be a value of @ref EXTIMode_TypeDef */ + + EXTITrigger_TypeDef EXTI_Trigger; /*!< Specifies the trigger signal active edge for the EXTI lines. + This parameter can be a value of @ref EXTIMode_TypeDef */ + + FunctionalState EXTI_LineCmd; /*!< Specifies the new state of the selected EXTI lines. + This parameter can be set either to ENABLE or DISABLE */ +}EXTI_InitTypeDef; + +/** + * @} + */ + +/** @defgroup EXTI_Exported_Constants + * @{ + */ + +/** @defgroup EXTI_Lines + * @{ + */ + +#define EXTI_Line0 ((uint32_t)0x00001) /*!< External interrupt line 0 */ +#define EXTI_Line1 ((uint32_t)0x00002) /*!< External interrupt line 1 */ +#define EXTI_Line2 ((uint32_t)0x00004) /*!< External interrupt line 2 */ +#define EXTI_Line3 ((uint32_t)0x00008) /*!< External interrupt line 3 */ +#define EXTI_Line4 ((uint32_t)0x00010) /*!< External interrupt line 4 */ +#define EXTI_Line5 ((uint32_t)0x00020) /*!< External interrupt line 5 */ +#define EXTI_Line6 ((uint32_t)0x00040) /*!< External interrupt line 6 */ +#define EXTI_Line7 ((uint32_t)0x00080) /*!< External interrupt line 7 */ +#define EXTI_Line8 ((uint32_t)0x00100) /*!< External interrupt line 8 */ +#define EXTI_Line9 ((uint32_t)0x00200) /*!< External interrupt line 9 */ +#define EXTI_Line10 ((uint32_t)0x00400) /*!< External interrupt line 10 */ +#define EXTI_Line11 ((uint32_t)0x00800) /*!< External interrupt line 11 */ +#define EXTI_Line12 ((uint32_t)0x01000) /*!< External interrupt line 12 */ +#define EXTI_Line13 ((uint32_t)0x02000) /*!< External interrupt line 13 */ +#define EXTI_Line14 ((uint32_t)0x04000) /*!< External interrupt line 14 */ +#define EXTI_Line15 ((uint32_t)0x08000) /*!< External interrupt line 15 */ +#define EXTI_Line16 ((uint32_t)0x10000) /*!< External interrupt line 16 Connected to the PVD Output */ +#define EXTI_Line17 ((uint32_t)0x20000) /*!< External interrupt line 17 Connected to the RTC Alarm event */ +#define EXTI_Line18 ((uint32_t)0x40000) /*!< External interrupt line 18 Connected to the USB Device/USB OTG FS + Wakeup from suspend event */ +#define EXTI_Line19 ((uint32_t)0x80000) /*!< External interrupt line 19 Connected to the Ethernet Wakeup event */ + +#define IS_EXTI_LINE(LINE) ((((LINE) & (uint32_t)0xFFF00000) == 0x00) && ((LINE) != (uint16_t)0x00)) +#define IS_GET_EXTI_LINE(LINE) (((LINE) == EXTI_Line0) || ((LINE) == EXTI_Line1) || \ + ((LINE) == EXTI_Line2) || ((LINE) == EXTI_Line3) || \ + ((LINE) == EXTI_Line4) || ((LINE) == EXTI_Line5) || \ + ((LINE) == EXTI_Line6) || ((LINE) == EXTI_Line7) || \ + ((LINE) == EXTI_Line8) || ((LINE) == EXTI_Line9) || \ + ((LINE) == EXTI_Line10) || ((LINE) == EXTI_Line11) || \ + ((LINE) == EXTI_Line12) || ((LINE) == EXTI_Line13) || \ + ((LINE) == EXTI_Line14) || ((LINE) == EXTI_Line15) || \ + ((LINE) == EXTI_Line16) || ((LINE) == EXTI_Line17) || \ + ((LINE) == EXTI_Line18) || ((LINE) == EXTI_Line19)) + + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup EXTI_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup EXTI_Exported_Functions + * @{ + */ + +void EXTI_DeInit(void); +void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct); +void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct); +void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line); +FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line); +void EXTI_ClearFlag(uint32_t EXTI_Line); +ITStatus EXTI_GetITStatus(uint32_t EXTI_Line); +void EXTI_ClearITPendingBit(uint32_t EXTI_Line); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F10x_EXTI_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_flash.c b/Library/stm32f10x_flash.c new file mode 100644 index 0000000..cdff9e9 --- /dev/null +++ b/Library/stm32f10x_flash.c @@ -0,0 +1,1684 @@ +/** + ****************************************************************************** + * @file stm32f10x_flash.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the FLASH firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_flash.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup FLASH + * @brief FLASH driver modules + * @{ + */ + +/** @defgroup FLASH_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup FLASH_Private_Defines + * @{ + */ + +/* Flash Access Control Register bits */ +#define ACR_LATENCY_Mask ((uint32_t)0x00000038) +#define ACR_HLFCYA_Mask ((uint32_t)0xFFFFFFF7) +#define ACR_PRFTBE_Mask ((uint32_t)0xFFFFFFEF) + +/* Flash Access Control Register bits */ +#define ACR_PRFTBS_Mask ((uint32_t)0x00000020) + +/* Flash Control Register bits */ +#define CR_PG_Set ((uint32_t)0x00000001) +#define CR_PG_Reset ((uint32_t)0x00001FFE) +#define CR_PER_Set ((uint32_t)0x00000002) +#define CR_PER_Reset ((uint32_t)0x00001FFD) +#define CR_MER_Set ((uint32_t)0x00000004) +#define CR_MER_Reset ((uint32_t)0x00001FFB) +#define CR_OPTPG_Set ((uint32_t)0x00000010) +#define CR_OPTPG_Reset ((uint32_t)0x00001FEF) +#define CR_OPTER_Set ((uint32_t)0x00000020) +#define CR_OPTER_Reset ((uint32_t)0x00001FDF) +#define CR_STRT_Set ((uint32_t)0x00000040) +#define CR_LOCK_Set ((uint32_t)0x00000080) + +/* FLASH Mask */ +#define RDPRT_Mask ((uint32_t)0x00000002) +#define WRP0_Mask ((uint32_t)0x000000FF) +#define WRP1_Mask ((uint32_t)0x0000FF00) +#define WRP2_Mask ((uint32_t)0x00FF0000) +#define WRP3_Mask ((uint32_t)0xFF000000) +#define OB_USER_BFB2 ((uint16_t)0x0008) + +/* FLASH Keys */ +#define RDP_Key ((uint16_t)0x00A5) +#define FLASH_KEY1 ((uint32_t)0x45670123) +#define FLASH_KEY2 ((uint32_t)0xCDEF89AB) + +/* FLASH BANK address */ +#define FLASH_BANK1_END_ADDRESS ((uint32_t)0x807FFFF) + +/* Delay definition */ +#define EraseTimeout ((uint32_t)0x000B0000) +#define ProgramTimeout ((uint32_t)0x00002000) +/** + * @} + */ + +/** @defgroup FLASH_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup FLASH_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup FLASH_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup FLASH_Private_Functions + * @{ + */ + +/** +@code + + This driver provides functions to configure and program the Flash memory of all STM32F10x devices, + including the latest STM32F10x_XL density devices. + + STM32F10x_XL devices feature up to 1 Mbyte with dual bank architecture for read-while-write (RWW) capability: + - bank1: fixed size of 512 Kbytes (256 pages of 2Kbytes each) + - bank2: up to 512 Kbytes (up to 256 pages of 2Kbytes each) + While other STM32F10x devices features only one bank with memory up to 512 Kbytes. + + In version V3.3.0, some functions were updated and new ones were added to support + STM32F10x_XL devices. Thus some functions manages all devices, while other are + dedicated for XL devices only. + + The table below presents the list of available functions depending on the used STM32F10x devices. + + *************************************************** + * Legacy functions used for all STM32F10x devices * + *************************************************** + +----------------------------------------------------------------------------------------------------------------------------------+ + | Functions prototypes |STM32F10x_XL|Other STM32F10x| Comments | + | | devices | devices | | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_SetLatency | Yes | Yes | No change | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_HalfCycleAccessCmd | Yes | Yes | No change | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_PrefetchBufferCmd | Yes | Yes | No change | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_Unlock | Yes | Yes | - For STM32F10X_XL devices: unlock Bank1 and Bank2. | + | | | | - For other devices: unlock Bank1 and it is equivalent | + | | | | to FLASH_UnlockBank1 function. | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_Lock | Yes | Yes | - For STM32F10X_XL devices: lock Bank1 and Bank2. | + | | | | - For other devices: lock Bank1 and it is equivalent | + | | | | to FLASH_LockBank1 function. | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_ErasePage | Yes | Yes | - For STM32F10x_XL devices: erase a page in Bank1 and Bank2 | + | | | | - For other devices: erase a page in Bank1 | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_EraseAllPages | Yes | Yes | - For STM32F10x_XL devices: erase all pages in Bank1 and Bank2 | + | | | | - For other devices: erase all pages in Bank1 | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_EraseOptionBytes | Yes | Yes | No change | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_ProgramWord | Yes | Yes | Updated to program up to 1MByte (depending on the used device) | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_ProgramHalfWord | Yes | Yes | Updated to program up to 1MByte (depending on the used device) | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_ProgramOptionByteData | Yes | Yes | No change | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_EnableWriteProtection | Yes | Yes | No change | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_ReadOutProtection | Yes | Yes | No change | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_UserOptionByteConfig | Yes | Yes | No change | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_GetUserOptionByte | Yes | Yes | No change | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_GetWriteProtectionOptionByte | Yes | Yes | No change | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_GetReadOutProtectionStatus | Yes | Yes | No change | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_GetPrefetchBufferStatus | Yes | Yes | No change | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_ITConfig | Yes | Yes | - For STM32F10x_XL devices: enable Bank1 and Bank2's interrupts| + | | | | - For other devices: enable Bank1's interrupts | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_GetFlagStatus | Yes | Yes | - For STM32F10x_XL devices: return Bank1 and Bank2's flag status| + | | | | - For other devices: return Bank1's flag status | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_ClearFlag | Yes | Yes | - For STM32F10x_XL devices: clear Bank1 and Bank2's flag | + | | | | - For other devices: clear Bank1's flag | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_GetStatus | Yes | Yes | - Return the status of Bank1 (for all devices) | + | | | | equivalent to FLASH_GetBank1Status function | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_WaitForLastOperation | Yes | Yes | - Wait for Bank1 last operation (for all devices) | + | | | | equivalent to: FLASH_WaitForLastBank1Operation function | + +----------------------------------------------------------------------------------------------------------------------------------+ + + ************************************************************************************************************************ + * New functions used for all STM32F10x devices to manage Bank1: * + * - These functions are mainly useful for STM32F10x_XL density devices, to have separate control for Bank1 and bank2 * + * - For other devices, these functions are optional (covered by functions listed above) * + ************************************************************************************************************************ + +----------------------------------------------------------------------------------------------------------------------------------+ + | Functions prototypes |STM32F10x_XL|Other STM32F10x| Comments | + | | devices | devices | | + |----------------------------------------------------------------------------------------------------------------------------------| + | FLASH_UnlockBank1 | Yes | Yes | - Unlock Bank1 | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_LockBank1 | Yes | Yes | - Lock Bank1 | + |----------------------------------------------------------------------------------------------------------------------------------| + | FLASH_EraseAllBank1Pages | Yes | Yes | - Erase all pages in Bank1 | + |----------------------------------------------------------------------------------------------------------------------------------| + | FLASH_GetBank1Status | Yes | Yes | - Return the status of Bank1 | + |----------------------------------------------------------------------------------------------------------------------------------| + | FLASH_WaitForLastBank1Operation | Yes | Yes | - Wait for Bank1 last operation | + +----------------------------------------------------------------------------------------------------------------------------------+ + + ***************************************************************************** + * New Functions used only with STM32F10x_XL density devices to manage Bank2 * + ***************************************************************************** + +----------------------------------------------------------------------------------------------------------------------------------+ + | Functions prototypes |STM32F10x_XL|Other STM32F10x| Comments | + | | devices | devices | | + |----------------------------------------------------------------------------------------------------------------------------------| + | FLASH_UnlockBank2 | Yes | No | - Unlock Bank2 | + |----------------------------------------------------------------------------------------------------------------------------------| + |FLASH_LockBank2 | Yes | No | - Lock Bank2 | + |----------------------------------------------------------------------------------------------------------------------------------| + | FLASH_EraseAllBank2Pages | Yes | No | - Erase all pages in Bank2 | + |----------------------------------------------------------------------------------------------------------------------------------| + | FLASH_GetBank2Status | Yes | No | - Return the status of Bank2 | + |----------------------------------------------------------------------------------------------------------------------------------| + | FLASH_WaitForLastBank2Operation | Yes | No | - Wait for Bank2 last operation | + |----------------------------------------------------------------------------------------------------------------------------------| + | FLASH_BootConfig | Yes | No | - Configure to boot from Bank1 or Bank2 | + +----------------------------------------------------------------------------------------------------------------------------------+ +@endcode +*/ + + +/** + * @brief Sets the code latency value. + * @note This function can be used for all STM32F10x devices. + * @param FLASH_Latency: specifies the FLASH Latency value. + * This parameter can be one of the following values: + * @arg FLASH_Latency_0: FLASH Zero Latency cycle + * @arg FLASH_Latency_1: FLASH One Latency cycle + * @arg FLASH_Latency_2: FLASH Two Latency cycles + * @retval None + */ +void FLASH_SetLatency(uint32_t FLASH_Latency) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_FLASH_LATENCY(FLASH_Latency)); + + /* Read the ACR register */ + tmpreg = FLASH->ACR; + + /* Sets the Latency value */ + tmpreg &= ACR_LATENCY_Mask; + tmpreg |= FLASH_Latency; + + /* Write the ACR register */ + FLASH->ACR = tmpreg; +} + +/** + * @brief Enables or disables the Half cycle flash access. + * @note This function can be used for all STM32F10x devices. + * @param FLASH_HalfCycleAccess: specifies the FLASH Half cycle Access mode. + * This parameter can be one of the following values: + * @arg FLASH_HalfCycleAccess_Enable: FLASH Half Cycle Enable + * @arg FLASH_HalfCycleAccess_Disable: FLASH Half Cycle Disable + * @retval None + */ +void FLASH_HalfCycleAccessCmd(uint32_t FLASH_HalfCycleAccess) +{ + /* Check the parameters */ + assert_param(IS_FLASH_HALFCYCLEACCESS_STATE(FLASH_HalfCycleAccess)); + + /* Enable or disable the Half cycle access */ + FLASH->ACR &= ACR_HLFCYA_Mask; + FLASH->ACR |= FLASH_HalfCycleAccess; +} + +/** + * @brief Enables or disables the Prefetch Buffer. + * @note This function can be used for all STM32F10x devices. + * @param FLASH_PrefetchBuffer: specifies the Prefetch buffer status. + * This parameter can be one of the following values: + * @arg FLASH_PrefetchBuffer_Enable: FLASH Prefetch Buffer Enable + * @arg FLASH_PrefetchBuffer_Disable: FLASH Prefetch Buffer Disable + * @retval None + */ +void FLASH_PrefetchBufferCmd(uint32_t FLASH_PrefetchBuffer) +{ + /* Check the parameters */ + assert_param(IS_FLASH_PREFETCHBUFFER_STATE(FLASH_PrefetchBuffer)); + + /* Enable or disable the Prefetch Buffer */ + FLASH->ACR &= ACR_PRFTBE_Mask; + FLASH->ACR |= FLASH_PrefetchBuffer; +} + +/** + * @brief Unlocks the FLASH Program Erase Controller. + * @note This function can be used for all STM32F10x devices. + * - For STM32F10X_XL devices this function unlocks Bank1 and Bank2. + * - For all other devices it unlocks Bank1 and it is equivalent + * to FLASH_UnlockBank1 function.. + * @param None + * @retval None + */ +void FLASH_Unlock(void) +{ + /* Authorize the FPEC of Bank1 Access */ + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; + +#ifdef STM32F10X_XL + /* Authorize the FPEC of Bank2 Access */ + FLASH->KEYR2 = FLASH_KEY1; + FLASH->KEYR2 = FLASH_KEY2; +#endif /* STM32F10X_XL */ +} +/** + * @brief Unlocks the FLASH Bank1 Program Erase Controller. + * @note This function can be used for all STM32F10x devices. + * - For STM32F10X_XL devices this function unlocks Bank1. + * - For all other devices it unlocks Bank1 and it is + * equivalent to FLASH_Unlock function. + * @param None + * @retval None + */ +void FLASH_UnlockBank1(void) +{ + /* Authorize the FPEC of Bank1 Access */ + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; +} + +#ifdef STM32F10X_XL +/** + * @brief Unlocks the FLASH Bank2 Program Erase Controller. + * @note This function can be used only for STM32F10X_XL density devices. + * @param None + * @retval None + */ +void FLASH_UnlockBank2(void) +{ + /* Authorize the FPEC of Bank2 Access */ + FLASH->KEYR2 = FLASH_KEY1; + FLASH->KEYR2 = FLASH_KEY2; + +} +#endif /* STM32F10X_XL */ + +/** + * @brief Locks the FLASH Program Erase Controller. + * @note This function can be used for all STM32F10x devices. + * - For STM32F10X_XL devices this function Locks Bank1 and Bank2. + * - For all other devices it Locks Bank1 and it is equivalent + * to FLASH_LockBank1 function. + * @param None + * @retval None + */ +void FLASH_Lock(void) +{ + /* Set the Lock Bit to lock the FPEC and the CR of Bank1 */ + FLASH->CR |= CR_LOCK_Set; + +#ifdef STM32F10X_XL + /* Set the Lock Bit to lock the FPEC and the CR of Bank2 */ + FLASH->CR2 |= CR_LOCK_Set; +#endif /* STM32F10X_XL */ +} + +/** + * @brief Locks the FLASH Bank1 Program Erase Controller. + * @note this function can be used for all STM32F10x devices. + * - For STM32F10X_XL devices this function Locks Bank1. + * - For all other devices it Locks Bank1 and it is equivalent + * to FLASH_Lock function. + * @param None + * @retval None + */ +void FLASH_LockBank1(void) +{ + /* Set the Lock Bit to lock the FPEC and the CR of Bank1 */ + FLASH->CR |= CR_LOCK_Set; +} + +#ifdef STM32F10X_XL +/** + * @brief Locks the FLASH Bank2 Program Erase Controller. + * @note This function can be used only for STM32F10X_XL density devices. + * @param None + * @retval None + */ +void FLASH_LockBank2(void) +{ + /* Set the Lock Bit to lock the FPEC and the CR of Bank2 */ + FLASH->CR2 |= CR_LOCK_Set; +} +#endif /* STM32F10X_XL */ + +/** + * @brief Erases a specified FLASH page. + * @note This function can be used for all STM32F10x devices. + * @param Page_Address: The page address to be erased. + * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_ErasePage(uint32_t Page_Address) +{ + FLASH_Status status = FLASH_COMPLETE; + /* Check the parameters */ + assert_param(IS_FLASH_ADDRESS(Page_Address)); + +#ifdef STM32F10X_XL + if(Page_Address < FLASH_BANK1_END_ADDRESS) + { + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank1Operation(EraseTimeout); + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to erase the page */ + FLASH->CR|= CR_PER_Set; + FLASH->AR = Page_Address; + FLASH->CR|= CR_STRT_Set; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank1Operation(EraseTimeout); + + /* Disable the PER Bit */ + FLASH->CR &= CR_PER_Reset; + } + } + else + { + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank2Operation(EraseTimeout); + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to erase the page */ + FLASH->CR2|= CR_PER_Set; + FLASH->AR2 = Page_Address; + FLASH->CR2|= CR_STRT_Set; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank2Operation(EraseTimeout); + + /* Disable the PER Bit */ + FLASH->CR2 &= CR_PER_Reset; + } + } +#else + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(EraseTimeout); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to erase the page */ + FLASH->CR|= CR_PER_Set; + FLASH->AR = Page_Address; + FLASH->CR|= CR_STRT_Set; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(EraseTimeout); + + /* Disable the PER Bit */ + FLASH->CR &= CR_PER_Reset; + } +#endif /* STM32F10X_XL */ + + /* Return the Erase Status */ + return status; +} + +/** + * @brief Erases all FLASH pages. + * @note This function can be used for all STM32F10x devices. + * @param None + * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_EraseAllPages(void) +{ + FLASH_Status status = FLASH_COMPLETE; + +#ifdef STM32F10X_XL + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank1Operation(EraseTimeout); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to erase all pages */ + FLASH->CR |= CR_MER_Set; + FLASH->CR |= CR_STRT_Set; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank1Operation(EraseTimeout); + + /* Disable the MER Bit */ + FLASH->CR &= CR_MER_Reset; + } + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to erase all pages */ + FLASH->CR2 |= CR_MER_Set; + FLASH->CR2 |= CR_STRT_Set; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank2Operation(EraseTimeout); + + /* Disable the MER Bit */ + FLASH->CR2 &= CR_MER_Reset; + } +#else + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(EraseTimeout); + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to erase all pages */ + FLASH->CR |= CR_MER_Set; + FLASH->CR |= CR_STRT_Set; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(EraseTimeout); + + /* Disable the MER Bit */ + FLASH->CR &= CR_MER_Reset; + } +#endif /* STM32F10X_XL */ + + /* Return the Erase Status */ + return status; +} + +/** + * @brief Erases all Bank1 FLASH pages. + * @note This function can be used for all STM32F10x devices. + * - For STM32F10X_XL devices this function erases all Bank1 pages. + * - For all other devices it erases all Bank1 pages and it is equivalent + * to FLASH_EraseAllPages function. + * @param None + * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_EraseAllBank1Pages(void) +{ + FLASH_Status status = FLASH_COMPLETE; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank1Operation(EraseTimeout); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to erase all pages */ + FLASH->CR |= CR_MER_Set; + FLASH->CR |= CR_STRT_Set; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank1Operation(EraseTimeout); + + /* Disable the MER Bit */ + FLASH->CR &= CR_MER_Reset; + } + /* Return the Erase Status */ + return status; +} + +#ifdef STM32F10X_XL +/** + * @brief Erases all Bank2 FLASH pages. + * @note This function can be used only for STM32F10x_XL density devices. + * @param None + * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_EraseAllBank2Pages(void) +{ + FLASH_Status status = FLASH_COMPLETE; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank2Operation(EraseTimeout); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to erase all pages */ + FLASH->CR2 |= CR_MER_Set; + FLASH->CR2 |= CR_STRT_Set; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank2Operation(EraseTimeout); + + /* Disable the MER Bit */ + FLASH->CR2 &= CR_MER_Reset; + } + /* Return the Erase Status */ + return status; +} +#endif /* STM32F10X_XL */ + +/** + * @brief Erases the FLASH option bytes. + * @note This functions erases all option bytes except the Read protection (RDP). + * @note This function can be used for all STM32F10x devices. + * @param None + * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_EraseOptionBytes(void) +{ + uint16_t rdptmp = RDP_Key; + + FLASH_Status status = FLASH_COMPLETE; + + /* Get the actual read protection Option Byte value */ + if(FLASH_GetReadOutProtectionStatus() != RESET) + { + rdptmp = 0x00; + } + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(EraseTimeout); + if(status == FLASH_COMPLETE) + { + /* Authorize the small information block programming */ + FLASH->OPTKEYR = FLASH_KEY1; + FLASH->OPTKEYR = FLASH_KEY2; + + /* if the previous operation is completed, proceed to erase the option bytes */ + FLASH->CR |= CR_OPTER_Set; + FLASH->CR |= CR_STRT_Set; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(EraseTimeout); + + if(status == FLASH_COMPLETE) + { + /* if the erase operation is completed, disable the OPTER Bit */ + FLASH->CR &= CR_OPTER_Reset; + + /* Enable the Option Bytes Programming operation */ + FLASH->CR |= CR_OPTPG_Set; + /* Restore the last read protection Option Byte value */ + OB->RDP = (uint16_t)rdptmp; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + + if(status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CR &= CR_OPTPG_Reset; + } + } + else + { + if (status != FLASH_TIMEOUT) + { + /* Disable the OPTPG Bit */ + FLASH->CR &= CR_OPTPG_Reset; + } + } + } + /* Return the erase status */ + return status; +} + +/** + * @brief Programs a word at a specified address. + * @note This function can be used for all STM32F10x devices. + * @param Address: specifies the address to be programmed. + * @param Data: specifies the data to be programmed. + * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data) +{ + FLASH_Status status = FLASH_COMPLETE; + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_FLASH_ADDRESS(Address)); + +#ifdef STM32F10X_XL + if(Address < FLASH_BANK1_END_ADDRESS - 2) + { + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank1Operation(ProgramTimeout); + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to program the new first + half word */ + FLASH->CR |= CR_PG_Set; + + *(__IO uint16_t*)Address = (uint16_t)Data; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to program the new second + half word */ + tmp = Address + 2; + + *(__IO uint16_t*) tmp = Data >> 16; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + + /* Disable the PG Bit */ + FLASH->CR &= CR_PG_Reset; + } + else + { + /* Disable the PG Bit */ + FLASH->CR &= CR_PG_Reset; + } + } + } + else if(Address == (FLASH_BANK1_END_ADDRESS - 1)) + { + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank1Operation(ProgramTimeout); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to program the new first + half word */ + FLASH->CR |= CR_PG_Set; + + *(__IO uint16_t*)Address = (uint16_t)Data; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank1Operation(ProgramTimeout); + + /* Disable the PG Bit */ + FLASH->CR &= CR_PG_Reset; + } + else + { + /* Disable the PG Bit */ + FLASH->CR &= CR_PG_Reset; + } + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank2Operation(ProgramTimeout); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to program the new second + half word */ + FLASH->CR2 |= CR_PG_Set; + tmp = Address + 2; + + *(__IO uint16_t*) tmp = Data >> 16; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank2Operation(ProgramTimeout); + + /* Disable the PG Bit */ + FLASH->CR2 &= CR_PG_Reset; + } + else + { + /* Disable the PG Bit */ + FLASH->CR2 &= CR_PG_Reset; + } + } + else + { + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank2Operation(ProgramTimeout); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to program the new first + half word */ + FLASH->CR2 |= CR_PG_Set; + + *(__IO uint16_t*)Address = (uint16_t)Data; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank2Operation(ProgramTimeout); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to program the new second + half word */ + tmp = Address + 2; + + *(__IO uint16_t*) tmp = Data >> 16; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank2Operation(ProgramTimeout); + + /* Disable the PG Bit */ + FLASH->CR2 &= CR_PG_Reset; + } + else + { + /* Disable the PG Bit */ + FLASH->CR2 &= CR_PG_Reset; + } + } + } +#else + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to program the new first + half word */ + FLASH->CR |= CR_PG_Set; + + *(__IO uint16_t*)Address = (uint16_t)Data; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to program the new second + half word */ + tmp = Address + 2; + + *(__IO uint16_t*) tmp = Data >> 16; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + + /* Disable the PG Bit */ + FLASH->CR &= CR_PG_Reset; + } + else + { + /* Disable the PG Bit */ + FLASH->CR &= CR_PG_Reset; + } + } +#endif /* STM32F10X_XL */ + + /* Return the Program Status */ + return status; +} + +/** + * @brief Programs a half word at a specified address. + * @note This function can be used for all STM32F10x devices. + * @param Address: specifies the address to be programmed. + * @param Data: specifies the data to be programmed. + * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) +{ + FLASH_Status status = FLASH_COMPLETE; + /* Check the parameters */ + assert_param(IS_FLASH_ADDRESS(Address)); + +#ifdef STM32F10X_XL + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + + if(Address < FLASH_BANK1_END_ADDRESS) + { + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to program the new data */ + FLASH->CR |= CR_PG_Set; + + *(__IO uint16_t*)Address = Data; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank1Operation(ProgramTimeout); + + /* Disable the PG Bit */ + FLASH->CR &= CR_PG_Reset; + } + } + else + { + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to program the new data */ + FLASH->CR2 |= CR_PG_Set; + + *(__IO uint16_t*)Address = Data; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastBank2Operation(ProgramTimeout); + + /* Disable the PG Bit */ + FLASH->CR2 &= CR_PG_Reset; + } + } +#else + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to program the new data */ + FLASH->CR |= CR_PG_Set; + + *(__IO uint16_t*)Address = Data; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + + /* Disable the PG Bit */ + FLASH->CR &= CR_PG_Reset; + } +#endif /* STM32F10X_XL */ + + /* Return the Program Status */ + return status; +} + +/** + * @brief Programs a half word at a specified Option Byte Data address. + * @note This function can be used for all STM32F10x devices. + * @param Address: specifies the address to be programmed. + * This parameter can be 0x1FFFF804 or 0x1FFFF806. + * @param Data: specifies the data to be programmed. + * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data) +{ + FLASH_Status status = FLASH_COMPLETE; + /* Check the parameters */ + assert_param(IS_OB_DATA_ADDRESS(Address)); + status = FLASH_WaitForLastOperation(ProgramTimeout); + + if(status == FLASH_COMPLETE) + { + /* Authorize the small information block programming */ + FLASH->OPTKEYR = FLASH_KEY1; + FLASH->OPTKEYR = FLASH_KEY2; + /* Enables the Option Bytes Programming operation */ + FLASH->CR |= CR_OPTPG_Set; + *(__IO uint16_t*)Address = Data; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + if(status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CR &= CR_OPTPG_Reset; + } + } + /* Return the Option Byte Data Program Status */ + return status; +} + +/** + * @brief Write protects the desired pages + * @note This function can be used for all STM32F10x devices. + * @param FLASH_Pages: specifies the address of the pages to be write protected. + * This parameter can be: + * @arg For @b STM32_Low-density_devices: value between FLASH_WRProt_Pages0to3 and FLASH_WRProt_Pages28to31 + * @arg For @b STM32_Medium-density_devices: value between FLASH_WRProt_Pages0to3 + * and FLASH_WRProt_Pages124to127 + * @arg For @b STM32_High-density_devices: value between FLASH_WRProt_Pages0to1 and + * FLASH_WRProt_Pages60to61 or FLASH_WRProt_Pages62to255 + * @arg For @b STM32_Connectivity_line_devices: value between FLASH_WRProt_Pages0to1 and + * FLASH_WRProt_Pages60to61 or FLASH_WRProt_Pages62to127 + * @arg For @b STM32_XL-density_devices: value between FLASH_WRProt_Pages0to1 and + * FLASH_WRProt_Pages60to61 or FLASH_WRProt_Pages62to511 + * @arg FLASH_WRProt_AllPages + * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages) +{ + uint16_t WRP0_Data = 0xFFFF, WRP1_Data = 0xFFFF, WRP2_Data = 0xFFFF, WRP3_Data = 0xFFFF; + + FLASH_Status status = FLASH_COMPLETE; + + /* Check the parameters */ + assert_param(IS_FLASH_WRPROT_PAGE(FLASH_Pages)); + + FLASH_Pages = (uint32_t)(~FLASH_Pages); + WRP0_Data = (uint16_t)(FLASH_Pages & WRP0_Mask); + WRP1_Data = (uint16_t)((FLASH_Pages & WRP1_Mask) >> 8); + WRP2_Data = (uint16_t)((FLASH_Pages & WRP2_Mask) >> 16); + WRP3_Data = (uint16_t)((FLASH_Pages & WRP3_Mask) >> 24); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + + if(status == FLASH_COMPLETE) + { + /* Authorizes the small information block programming */ + FLASH->OPTKEYR = FLASH_KEY1; + FLASH->OPTKEYR = FLASH_KEY2; + FLASH->CR |= CR_OPTPG_Set; + if(WRP0_Data != 0xFF) + { + OB->WRP0 = WRP0_Data; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + } + if((status == FLASH_COMPLETE) && (WRP1_Data != 0xFF)) + { + OB->WRP1 = WRP1_Data; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + } + if((status == FLASH_COMPLETE) && (WRP2_Data != 0xFF)) + { + OB->WRP2 = WRP2_Data; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + } + + if((status == FLASH_COMPLETE)&& (WRP3_Data != 0xFF)) + { + OB->WRP3 = WRP3_Data; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + } + + if(status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CR &= CR_OPTPG_Reset; + } + } + /* Return the write protection operation Status */ + return status; +} + +/** + * @brief Enables or disables the read out protection. + * @note If the user has already programmed the other option bytes before calling + * this function, he must re-program them since this function erases all option bytes. + * @note This function can be used for all STM32F10x devices. + * @param Newstate: new state of the ReadOut Protection. + * This parameter can be: ENABLE or DISABLE. + * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState) +{ + FLASH_Status status = FLASH_COMPLETE; + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + status = FLASH_WaitForLastOperation(EraseTimeout); + if(status == FLASH_COMPLETE) + { + /* Authorizes the small information block programming */ + FLASH->OPTKEYR = FLASH_KEY1; + FLASH->OPTKEYR = FLASH_KEY2; + FLASH->CR |= CR_OPTER_Set; + FLASH->CR |= CR_STRT_Set; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(EraseTimeout); + if(status == FLASH_COMPLETE) + { + /* if the erase operation is completed, disable the OPTER Bit */ + FLASH->CR &= CR_OPTER_Reset; + /* Enable the Option Bytes Programming operation */ + FLASH->CR |= CR_OPTPG_Set; + if(NewState != DISABLE) + { + OB->RDP = 0x00; + } + else + { + OB->RDP = RDP_Key; + } + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(EraseTimeout); + + if(status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CR &= CR_OPTPG_Reset; + } + } + else + { + if(status != FLASH_TIMEOUT) + { + /* Disable the OPTER Bit */ + FLASH->CR &= CR_OPTER_Reset; + } + } + } + /* Return the protection operation Status */ + return status; +} + +/** + * @brief Programs the FLASH User Option Byte: IWDG_SW / RST_STOP / RST_STDBY. + * @note This function can be used for all STM32F10x devices. + * @param OB_IWDG: Selects the IWDG mode + * This parameter can be one of the following values: + * @arg OB_IWDG_SW: Software IWDG selected + * @arg OB_IWDG_HW: Hardware IWDG selected + * @param OB_STOP: Reset event when entering STOP mode. + * This parameter can be one of the following values: + * @arg OB_STOP_NoRST: No reset generated when entering in STOP + * @arg OB_STOP_RST: Reset generated when entering in STOP + * @param OB_STDBY: Reset event when entering Standby mode. + * This parameter can be one of the following values: + * @arg OB_STDBY_NoRST: No reset generated when entering in STANDBY + * @arg OB_STDBY_RST: Reset generated when entering in STANDBY + * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_UserOptionByteConfig(uint16_t OB_IWDG, uint16_t OB_STOP, uint16_t OB_STDBY) +{ + FLASH_Status status = FLASH_COMPLETE; + + /* Check the parameters */ + assert_param(IS_OB_IWDG_SOURCE(OB_IWDG)); + assert_param(IS_OB_STOP_SOURCE(OB_STOP)); + assert_param(IS_OB_STDBY_SOURCE(OB_STDBY)); + + /* Authorize the small information block programming */ + FLASH->OPTKEYR = FLASH_KEY1; + FLASH->OPTKEYR = FLASH_KEY2; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + + if(status == FLASH_COMPLETE) + { + /* Enable the Option Bytes Programming operation */ + FLASH->CR |= CR_OPTPG_Set; + + OB->USER = OB_IWDG | (uint16_t)(OB_STOP | (uint16_t)(OB_STDBY | ((uint16_t)0xF8))); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + if(status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CR &= CR_OPTPG_Reset; + } + } + /* Return the Option Byte program Status */ + return status; +} + +#ifdef STM32F10X_XL +/** + * @brief Configures to boot from Bank1 or Bank2. + * @note This function can be used only for STM32F10x_XL density devices. + * @param FLASH_BOOT: select the FLASH Bank to boot from. + * This parameter can be one of the following values: + * @arg FLASH_BOOT_Bank1: At startup, if boot pins are set in boot from user Flash + * position and this parameter is selected the device will boot from Bank1(Default). + * @arg FLASH_BOOT_Bank2: At startup, if boot pins are set in boot from user Flash + * position and this parameter is selected the device will boot from Bank2 or Bank1, + * depending on the activation of the bank. The active banks are checked in + * the following order: Bank2, followed by Bank1. + * The active bank is recognized by the value programmed at the base address + * of the respective bank (corresponding to the initial stack pointer value + * in the interrupt vector table). + * For more information, please refer to AN2606 from www.st.com. + * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_BootConfig(uint16_t FLASH_BOOT) +{ + FLASH_Status status = FLASH_COMPLETE; + assert_param(IS_FLASH_BOOT(FLASH_BOOT)); + /* Authorize the small information block programming */ + FLASH->OPTKEYR = FLASH_KEY1; + FLASH->OPTKEYR = FLASH_KEY2; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + + if(status == FLASH_COMPLETE) + { + /* Enable the Option Bytes Programming operation */ + FLASH->CR |= CR_OPTPG_Set; + + if(FLASH_BOOT == FLASH_BOOT_Bank1) + { + OB->USER |= OB_USER_BFB2; + } + else + { + OB->USER &= (uint16_t)(~(uint16_t)(OB_USER_BFB2)); + } + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + if(status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CR &= CR_OPTPG_Reset; + } + } + /* Return the Option Byte program Status */ + return status; +} +#endif /* STM32F10X_XL */ + +/** + * @brief Returns the FLASH User Option Bytes values. + * @note This function can be used for all STM32F10x devices. + * @param None + * @retval The FLASH User Option Bytes values:IWDG_SW(Bit0), RST_STOP(Bit1) + * and RST_STDBY(Bit2). + */ +uint32_t FLASH_GetUserOptionByte(void) +{ + /* Return the User Option Byte */ + return (uint32_t)(FLASH->OBR >> 2); +} + +/** + * @brief Returns the FLASH Write Protection Option Bytes Register value. + * @note This function can be used for all STM32F10x devices. + * @param None + * @retval The FLASH Write Protection Option Bytes Register value + */ +uint32_t FLASH_GetWriteProtectionOptionByte(void) +{ + /* Return the Flash write protection Register value */ + return (uint32_t)(FLASH->WRPR); +} + +/** + * @brief Checks whether the FLASH Read Out Protection Status is set or not. + * @note This function can be used for all STM32F10x devices. + * @param None + * @retval FLASH ReadOut Protection Status(SET or RESET) + */ +FlagStatus FLASH_GetReadOutProtectionStatus(void) +{ + FlagStatus readoutstatus = RESET; + if ((FLASH->OBR & RDPRT_Mask) != (uint32_t)RESET) + { + readoutstatus = SET; + } + else + { + readoutstatus = RESET; + } + return readoutstatus; +} + +/** + * @brief Checks whether the FLASH Prefetch Buffer status is set or not. + * @note This function can be used for all STM32F10x devices. + * @param None + * @retval FLASH Prefetch Buffer Status (SET or RESET). + */ +FlagStatus FLASH_GetPrefetchBufferStatus(void) +{ + FlagStatus bitstatus = RESET; + + if ((FLASH->ACR & ACR_PRFTBS_Mask) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + /* Return the new state of FLASH Prefetch Buffer Status (SET or RESET) */ + return bitstatus; +} + +/** + * @brief Enables or disables the specified FLASH interrupts. + * @note This function can be used for all STM32F10x devices. + * - For STM32F10X_XL devices, enables or disables the specified FLASH interrupts + for Bank1 and Bank2. + * - For other devices it enables or disables the specified FLASH interrupts for Bank1. + * @param FLASH_IT: specifies the FLASH interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg FLASH_IT_ERROR: FLASH Error Interrupt + * @arg FLASH_IT_EOP: FLASH end of operation Interrupt + * @param NewState: new state of the specified Flash interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FLASH_ITConfig(uint32_t FLASH_IT, FunctionalState NewState) +{ +#ifdef STM32F10X_XL + /* Check the parameters */ + assert_param(IS_FLASH_IT(FLASH_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if((FLASH_IT & 0x80000000) != 0x0) + { + if(NewState != DISABLE) + { + /* Enable the interrupt sources */ + FLASH->CR2 |= (FLASH_IT & 0x7FFFFFFF); + } + else + { + /* Disable the interrupt sources */ + FLASH->CR2 &= ~(uint32_t)(FLASH_IT & 0x7FFFFFFF); + } + } + else + { + if(NewState != DISABLE) + { + /* Enable the interrupt sources */ + FLASH->CR |= FLASH_IT; + } + else + { + /* Disable the interrupt sources */ + FLASH->CR &= ~(uint32_t)FLASH_IT; + } + } +#else + /* Check the parameters */ + assert_param(IS_FLASH_IT(FLASH_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if(NewState != DISABLE) + { + /* Enable the interrupt sources */ + FLASH->CR |= FLASH_IT; + } + else + { + /* Disable the interrupt sources */ + FLASH->CR &= ~(uint32_t)FLASH_IT; + } +#endif /* STM32F10X_XL */ +} + +/** + * @brief Checks whether the specified FLASH flag is set or not. + * @note This function can be used for all STM32F10x devices. + * - For STM32F10X_XL devices, this function checks whether the specified + * Bank1 or Bank2 flag is set or not. + * - For other devices, it checks whether the specified Bank1 flag is + * set or not. + * @param FLASH_FLAG: specifies the FLASH flag to check. + * This parameter can be one of the following values: + * @arg FLASH_FLAG_BSY: FLASH Busy flag + * @arg FLASH_FLAG_PGERR: FLASH Program error flag + * @arg FLASH_FLAG_WRPRTERR: FLASH Write protected error flag + * @arg FLASH_FLAG_EOP: FLASH End of Operation flag + * @arg FLASH_FLAG_OPTERR: FLASH Option Byte error flag + * @retval The new state of FLASH_FLAG (SET or RESET). + */ +FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_FLAG) +{ + FlagStatus bitstatus = RESET; + +#ifdef STM32F10X_XL + /* Check the parameters */ + assert_param(IS_FLASH_GET_FLAG(FLASH_FLAG)) ; + if(FLASH_FLAG == FLASH_FLAG_OPTERR) + { + if((FLASH->OBR & FLASH_FLAG_OPTERR) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + else + { + if((FLASH_FLAG & 0x80000000) != 0x0) + { + if((FLASH->SR2 & FLASH_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + else + { + if((FLASH->SR & FLASH_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + } +#else + /* Check the parameters */ + assert_param(IS_FLASH_GET_FLAG(FLASH_FLAG)) ; + if(FLASH_FLAG == FLASH_FLAG_OPTERR) + { + if((FLASH->OBR & FLASH_FLAG_OPTERR) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + else + { + if((FLASH->SR & FLASH_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } +#endif /* STM32F10X_XL */ + + /* Return the new state of FLASH_FLAG (SET or RESET) */ + return bitstatus; +} + +/** + * @brief Clears the FLASH's pending flags. + * @note This function can be used for all STM32F10x devices. + * - For STM32F10X_XL devices, this function clears Bank1 or Bank2’s pending flags + * - For other devices, it clears Bank1’s pending flags. + * @param FLASH_FLAG: specifies the FLASH flags to clear. + * This parameter can be any combination of the following values: + * @arg FLASH_FLAG_PGERR: FLASH Program error flag + * @arg FLASH_FLAG_WRPRTERR: FLASH Write protected error flag + * @arg FLASH_FLAG_EOP: FLASH End of Operation flag + * @retval None + */ +void FLASH_ClearFlag(uint32_t FLASH_FLAG) +{ +#ifdef STM32F10X_XL + /* Check the parameters */ + assert_param(IS_FLASH_CLEAR_FLAG(FLASH_FLAG)) ; + + if((FLASH_FLAG & 0x80000000) != 0x0) + { + /* Clear the flags */ + FLASH->SR2 = FLASH_FLAG; + } + else + { + /* Clear the flags */ + FLASH->SR = FLASH_FLAG; + } + +#else + /* Check the parameters */ + assert_param(IS_FLASH_CLEAR_FLAG(FLASH_FLAG)) ; + + /* Clear the flags */ + FLASH->SR = FLASH_FLAG; +#endif /* STM32F10X_XL */ +} + +/** + * @brief Returns the FLASH Status. + * @note This function can be used for all STM32F10x devices, it is equivalent + * to FLASH_GetBank1Status function. + * @param None + * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, + * FLASH_ERROR_WRP or FLASH_COMPLETE + */ +FLASH_Status FLASH_GetStatus(void) +{ + FLASH_Status flashstatus = FLASH_COMPLETE; + + if((FLASH->SR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY) + { + flashstatus = FLASH_BUSY; + } + else + { + if((FLASH->SR & FLASH_FLAG_PGERR) != 0) + { + flashstatus = FLASH_ERROR_PG; + } + else + { + if((FLASH->SR & FLASH_FLAG_WRPRTERR) != 0 ) + { + flashstatus = FLASH_ERROR_WRP; + } + else + { + flashstatus = FLASH_COMPLETE; + } + } + } + /* Return the Flash Status */ + return flashstatus; +} + +/** + * @brief Returns the FLASH Bank1 Status. + * @note This function can be used for all STM32F10x devices, it is equivalent + * to FLASH_GetStatus function. + * @param None + * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, + * FLASH_ERROR_WRP or FLASH_COMPLETE + */ +FLASH_Status FLASH_GetBank1Status(void) +{ + FLASH_Status flashstatus = FLASH_COMPLETE; + + if((FLASH->SR & FLASH_FLAG_BANK1_BSY) == FLASH_FLAG_BSY) + { + flashstatus = FLASH_BUSY; + } + else + { + if((FLASH->SR & FLASH_FLAG_BANK1_PGERR) != 0) + { + flashstatus = FLASH_ERROR_PG; + } + else + { + if((FLASH->SR & FLASH_FLAG_BANK1_WRPRTERR) != 0 ) + { + flashstatus = FLASH_ERROR_WRP; + } + else + { + flashstatus = FLASH_COMPLETE; + } + } + } + /* Return the Flash Status */ + return flashstatus; +} + +#ifdef STM32F10X_XL +/** + * @brief Returns the FLASH Bank2 Status. + * @note This function can be used for STM32F10x_XL density devices. + * @param None + * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, + * FLASH_ERROR_WRP or FLASH_COMPLETE + */ +FLASH_Status FLASH_GetBank2Status(void) +{ + FLASH_Status flashstatus = FLASH_COMPLETE; + + if((FLASH->SR2 & (FLASH_FLAG_BANK2_BSY & 0x7FFFFFFF)) == (FLASH_FLAG_BANK2_BSY & 0x7FFFFFFF)) + { + flashstatus = FLASH_BUSY; + } + else + { + if((FLASH->SR2 & (FLASH_FLAG_BANK2_PGERR & 0x7FFFFFFF)) != 0) + { + flashstatus = FLASH_ERROR_PG; + } + else + { + if((FLASH->SR2 & (FLASH_FLAG_BANK2_WRPRTERR & 0x7FFFFFFF)) != 0 ) + { + flashstatus = FLASH_ERROR_WRP; + } + else + { + flashstatus = FLASH_COMPLETE; + } + } + } + /* Return the Flash Status */ + return flashstatus; +} +#endif /* STM32F10X_XL */ +/** + * @brief Waits for a Flash operation to complete or a TIMEOUT to occur. + * @note This function can be used for all STM32F10x devices, + * it is equivalent to FLASH_WaitForLastBank1Operation. + * - For STM32F10X_XL devices this function waits for a Bank1 Flash operation + * to complete or a TIMEOUT to occur. + * - For all other devices it waits for a Flash operation to complete + * or a TIMEOUT to occur. + * @param Timeout: FLASH programming Timeout + * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout) +{ + FLASH_Status status = FLASH_COMPLETE; + + /* Check for the Flash Status */ + status = FLASH_GetBank1Status(); + /* Wait for a Flash operation to complete or a TIMEOUT to occur */ + while((status == FLASH_BUSY) && (Timeout != 0x00)) + { + status = FLASH_GetBank1Status(); + Timeout--; + } + if(Timeout == 0x00 ) + { + status = FLASH_TIMEOUT; + } + /* Return the operation status */ + return status; +} + +/** + * @brief Waits for a Flash operation on Bank1 to complete or a TIMEOUT to occur. + * @note This function can be used for all STM32F10x devices, + * it is equivalent to FLASH_WaitForLastOperation. + * @param Timeout: FLASH programming Timeout + * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_WaitForLastBank1Operation(uint32_t Timeout) +{ + FLASH_Status status = FLASH_COMPLETE; + + /* Check for the Flash Status */ + status = FLASH_GetBank1Status(); + /* Wait for a Flash operation to complete or a TIMEOUT to occur */ + while((status == FLASH_FLAG_BANK1_BSY) && (Timeout != 0x00)) + { + status = FLASH_GetBank1Status(); + Timeout--; + } + if(Timeout == 0x00 ) + { + status = FLASH_TIMEOUT; + } + /* Return the operation status */ + return status; +} + +#ifdef STM32F10X_XL +/** + * @brief Waits for a Flash operation on Bank2 to complete or a TIMEOUT to occur. + * @note This function can be used only for STM32F10x_XL density devices. + * @param Timeout: FLASH programming Timeout + * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_WaitForLastBank2Operation(uint32_t Timeout) +{ + FLASH_Status status = FLASH_COMPLETE; + + /* Check for the Flash Status */ + status = FLASH_GetBank2Status(); + /* Wait for a Flash operation to complete or a TIMEOUT to occur */ + while((status == (FLASH_FLAG_BANK2_BSY & 0x7FFFFFFF)) && (Timeout != 0x00)) + { + status = FLASH_GetBank2Status(); + Timeout--; + } + if(Timeout == 0x00 ) + { + status = FLASH_TIMEOUT; + } + /* Return the operation status */ + return status; +} +#endif /* STM32F10X_XL */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_flash.h b/Library/stm32f10x_flash.h new file mode 100644 index 0000000..63720de --- /dev/null +++ b/Library/stm32f10x_flash.h @@ -0,0 +1,426 @@ +/** + ****************************************************************************** + * @file stm32f10x_flash.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the FLASH + * firmware library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_FLASH_H +#define __STM32F10x_FLASH_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup FLASH + * @{ + */ + +/** @defgroup FLASH_Exported_Types + * @{ + */ + +/** + * @brief FLASH Status + */ + +typedef enum +{ + FLASH_BUSY = 1, + FLASH_ERROR_PG, + FLASH_ERROR_WRP, + FLASH_COMPLETE, + FLASH_TIMEOUT +}FLASH_Status; + +/** + * @} + */ + +/** @defgroup FLASH_Exported_Constants + * @{ + */ + +/** @defgroup Flash_Latency + * @{ + */ + +#define FLASH_Latency_0 ((uint32_t)0x00000000) /*!< FLASH Zero Latency cycle */ +#define FLASH_Latency_1 ((uint32_t)0x00000001) /*!< FLASH One Latency cycle */ +#define FLASH_Latency_2 ((uint32_t)0x00000002) /*!< FLASH Two Latency cycles */ +#define IS_FLASH_LATENCY(LATENCY) (((LATENCY) == FLASH_Latency_0) || \ + ((LATENCY) == FLASH_Latency_1) || \ + ((LATENCY) == FLASH_Latency_2)) +/** + * @} + */ + +/** @defgroup Half_Cycle_Enable_Disable + * @{ + */ + +#define FLASH_HalfCycleAccess_Enable ((uint32_t)0x00000008) /*!< FLASH Half Cycle Enable */ +#define FLASH_HalfCycleAccess_Disable ((uint32_t)0x00000000) /*!< FLASH Half Cycle Disable */ +#define IS_FLASH_HALFCYCLEACCESS_STATE(STATE) (((STATE) == FLASH_HalfCycleAccess_Enable) || \ + ((STATE) == FLASH_HalfCycleAccess_Disable)) +/** + * @} + */ + +/** @defgroup Prefetch_Buffer_Enable_Disable + * @{ + */ + +#define FLASH_PrefetchBuffer_Enable ((uint32_t)0x00000010) /*!< FLASH Prefetch Buffer Enable */ +#define FLASH_PrefetchBuffer_Disable ((uint32_t)0x00000000) /*!< FLASH Prefetch Buffer Disable */ +#define IS_FLASH_PREFETCHBUFFER_STATE(STATE) (((STATE) == FLASH_PrefetchBuffer_Enable) || \ + ((STATE) == FLASH_PrefetchBuffer_Disable)) +/** + * @} + */ + +/** @defgroup Option_Bytes_Write_Protection + * @{ + */ + +/* Values to be used with STM32 Low and Medium density devices */ +#define FLASH_WRProt_Pages0to3 ((uint32_t)0x00000001) /*!< STM32 Low and Medium density devices: Write protection of page 0 to 3 */ +#define FLASH_WRProt_Pages4to7 ((uint32_t)0x00000002) /*!< STM32 Low and Medium density devices: Write protection of page 4 to 7 */ +#define FLASH_WRProt_Pages8to11 ((uint32_t)0x00000004) /*!< STM32 Low and Medium density devices: Write protection of page 8 to 11 */ +#define FLASH_WRProt_Pages12to15 ((uint32_t)0x00000008) /*!< STM32 Low and Medium density devices: Write protection of page 12 to 15 */ +#define FLASH_WRProt_Pages16to19 ((uint32_t)0x00000010) /*!< STM32 Low and Medium density devices: Write protection of page 16 to 19 */ +#define FLASH_WRProt_Pages20to23 ((uint32_t)0x00000020) /*!< STM32 Low and Medium density devices: Write protection of page 20 to 23 */ +#define FLASH_WRProt_Pages24to27 ((uint32_t)0x00000040) /*!< STM32 Low and Medium density devices: Write protection of page 24 to 27 */ +#define FLASH_WRProt_Pages28to31 ((uint32_t)0x00000080) /*!< STM32 Low and Medium density devices: Write protection of page 28 to 31 */ + +/* Values to be used with STM32 Medium-density devices */ +#define FLASH_WRProt_Pages32to35 ((uint32_t)0x00000100) /*!< STM32 Medium-density devices: Write protection of page 32 to 35 */ +#define FLASH_WRProt_Pages36to39 ((uint32_t)0x00000200) /*!< STM32 Medium-density devices: Write protection of page 36 to 39 */ +#define FLASH_WRProt_Pages40to43 ((uint32_t)0x00000400) /*!< STM32 Medium-density devices: Write protection of page 40 to 43 */ +#define FLASH_WRProt_Pages44to47 ((uint32_t)0x00000800) /*!< STM32 Medium-density devices: Write protection of page 44 to 47 */ +#define FLASH_WRProt_Pages48to51 ((uint32_t)0x00001000) /*!< STM32 Medium-density devices: Write protection of page 48 to 51 */ +#define FLASH_WRProt_Pages52to55 ((uint32_t)0x00002000) /*!< STM32 Medium-density devices: Write protection of page 52 to 55 */ +#define FLASH_WRProt_Pages56to59 ((uint32_t)0x00004000) /*!< STM32 Medium-density devices: Write protection of page 56 to 59 */ +#define FLASH_WRProt_Pages60to63 ((uint32_t)0x00008000) /*!< STM32 Medium-density devices: Write protection of page 60 to 63 */ +#define FLASH_WRProt_Pages64to67 ((uint32_t)0x00010000) /*!< STM32 Medium-density devices: Write protection of page 64 to 67 */ +#define FLASH_WRProt_Pages68to71 ((uint32_t)0x00020000) /*!< STM32 Medium-density devices: Write protection of page 68 to 71 */ +#define FLASH_WRProt_Pages72to75 ((uint32_t)0x00040000) /*!< STM32 Medium-density devices: Write protection of page 72 to 75 */ +#define FLASH_WRProt_Pages76to79 ((uint32_t)0x00080000) /*!< STM32 Medium-density devices: Write protection of page 76 to 79 */ +#define FLASH_WRProt_Pages80to83 ((uint32_t)0x00100000) /*!< STM32 Medium-density devices: Write protection of page 80 to 83 */ +#define FLASH_WRProt_Pages84to87 ((uint32_t)0x00200000) /*!< STM32 Medium-density devices: Write protection of page 84 to 87 */ +#define FLASH_WRProt_Pages88to91 ((uint32_t)0x00400000) /*!< STM32 Medium-density devices: Write protection of page 88 to 91 */ +#define FLASH_WRProt_Pages92to95 ((uint32_t)0x00800000) /*!< STM32 Medium-density devices: Write protection of page 92 to 95 */ +#define FLASH_WRProt_Pages96to99 ((uint32_t)0x01000000) /*!< STM32 Medium-density devices: Write protection of page 96 to 99 */ +#define FLASH_WRProt_Pages100to103 ((uint32_t)0x02000000) /*!< STM32 Medium-density devices: Write protection of page 100 to 103 */ +#define FLASH_WRProt_Pages104to107 ((uint32_t)0x04000000) /*!< STM32 Medium-density devices: Write protection of page 104 to 107 */ +#define FLASH_WRProt_Pages108to111 ((uint32_t)0x08000000) /*!< STM32 Medium-density devices: Write protection of page 108 to 111 */ +#define FLASH_WRProt_Pages112to115 ((uint32_t)0x10000000) /*!< STM32 Medium-density devices: Write protection of page 112 to 115 */ +#define FLASH_WRProt_Pages116to119 ((uint32_t)0x20000000) /*!< STM32 Medium-density devices: Write protection of page 115 to 119 */ +#define FLASH_WRProt_Pages120to123 ((uint32_t)0x40000000) /*!< STM32 Medium-density devices: Write protection of page 120 to 123 */ +#define FLASH_WRProt_Pages124to127 ((uint32_t)0x80000000) /*!< STM32 Medium-density devices: Write protection of page 124 to 127 */ + +/* Values to be used with STM32 High-density and STM32F10X Connectivity line devices */ +#define FLASH_WRProt_Pages0to1 ((uint32_t)0x00000001) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 0 to 1 */ +#define FLASH_WRProt_Pages2to3 ((uint32_t)0x00000002) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 2 to 3 */ +#define FLASH_WRProt_Pages4to5 ((uint32_t)0x00000004) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 4 to 5 */ +#define FLASH_WRProt_Pages6to7 ((uint32_t)0x00000008) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 6 to 7 */ +#define FLASH_WRProt_Pages8to9 ((uint32_t)0x00000010) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 8 to 9 */ +#define FLASH_WRProt_Pages10to11 ((uint32_t)0x00000020) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 10 to 11 */ +#define FLASH_WRProt_Pages12to13 ((uint32_t)0x00000040) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 12 to 13 */ +#define FLASH_WRProt_Pages14to15 ((uint32_t)0x00000080) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 14 to 15 */ +#define FLASH_WRProt_Pages16to17 ((uint32_t)0x00000100) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 16 to 17 */ +#define FLASH_WRProt_Pages18to19 ((uint32_t)0x00000200) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 18 to 19 */ +#define FLASH_WRProt_Pages20to21 ((uint32_t)0x00000400) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 20 to 21 */ +#define FLASH_WRProt_Pages22to23 ((uint32_t)0x00000800) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 22 to 23 */ +#define FLASH_WRProt_Pages24to25 ((uint32_t)0x00001000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 24 to 25 */ +#define FLASH_WRProt_Pages26to27 ((uint32_t)0x00002000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 26 to 27 */ +#define FLASH_WRProt_Pages28to29 ((uint32_t)0x00004000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 28 to 29 */ +#define FLASH_WRProt_Pages30to31 ((uint32_t)0x00008000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 30 to 31 */ +#define FLASH_WRProt_Pages32to33 ((uint32_t)0x00010000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 32 to 33 */ +#define FLASH_WRProt_Pages34to35 ((uint32_t)0x00020000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 34 to 35 */ +#define FLASH_WRProt_Pages36to37 ((uint32_t)0x00040000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 36 to 37 */ +#define FLASH_WRProt_Pages38to39 ((uint32_t)0x00080000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 38 to 39 */ +#define FLASH_WRProt_Pages40to41 ((uint32_t)0x00100000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 40 to 41 */ +#define FLASH_WRProt_Pages42to43 ((uint32_t)0x00200000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 42 to 43 */ +#define FLASH_WRProt_Pages44to45 ((uint32_t)0x00400000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 44 to 45 */ +#define FLASH_WRProt_Pages46to47 ((uint32_t)0x00800000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 46 to 47 */ +#define FLASH_WRProt_Pages48to49 ((uint32_t)0x01000000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 48 to 49 */ +#define FLASH_WRProt_Pages50to51 ((uint32_t)0x02000000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 50 to 51 */ +#define FLASH_WRProt_Pages52to53 ((uint32_t)0x04000000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 52 to 53 */ +#define FLASH_WRProt_Pages54to55 ((uint32_t)0x08000000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 54 to 55 */ +#define FLASH_WRProt_Pages56to57 ((uint32_t)0x10000000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 56 to 57 */ +#define FLASH_WRProt_Pages58to59 ((uint32_t)0x20000000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 58 to 59 */ +#define FLASH_WRProt_Pages60to61 ((uint32_t)0x40000000) /*!< STM32 High-density, XL-density and Connectivity line devices: + Write protection of page 60 to 61 */ +#define FLASH_WRProt_Pages62to127 ((uint32_t)0x80000000) /*!< STM32 Connectivity line devices: Write protection of page 62 to 127 */ +#define FLASH_WRProt_Pages62to255 ((uint32_t)0x80000000) /*!< STM32 Medium-density devices: Write protection of page 62 to 255 */ +#define FLASH_WRProt_Pages62to511 ((uint32_t)0x80000000) /*!< STM32 XL-density devices: Write protection of page 62 to 511 */ + +#define FLASH_WRProt_AllPages ((uint32_t)0xFFFFFFFF) /*!< Write protection of all Pages */ + +#define IS_FLASH_WRPROT_PAGE(PAGE) (((PAGE) != 0x00000000)) + +#define IS_FLASH_ADDRESS(ADDRESS) (((ADDRESS) >= 0x08000000) && ((ADDRESS) < 0x080FFFFF)) + +#define IS_OB_DATA_ADDRESS(ADDRESS) (((ADDRESS) == 0x1FFFF804) || ((ADDRESS) == 0x1FFFF806)) + +/** + * @} + */ + +/** @defgroup Option_Bytes_IWatchdog + * @{ + */ + +#define OB_IWDG_SW ((uint16_t)0x0001) /*!< Software IWDG selected */ +#define OB_IWDG_HW ((uint16_t)0x0000) /*!< Hardware IWDG selected */ +#define IS_OB_IWDG_SOURCE(SOURCE) (((SOURCE) == OB_IWDG_SW) || ((SOURCE) == OB_IWDG_HW)) + +/** + * @} + */ + +/** @defgroup Option_Bytes_nRST_STOP + * @{ + */ + +#define OB_STOP_NoRST ((uint16_t)0x0002) /*!< No reset generated when entering in STOP */ +#define OB_STOP_RST ((uint16_t)0x0000) /*!< Reset generated when entering in STOP */ +#define IS_OB_STOP_SOURCE(SOURCE) (((SOURCE) == OB_STOP_NoRST) || ((SOURCE) == OB_STOP_RST)) + +/** + * @} + */ + +/** @defgroup Option_Bytes_nRST_STDBY + * @{ + */ + +#define OB_STDBY_NoRST ((uint16_t)0x0004) /*!< No reset generated when entering in STANDBY */ +#define OB_STDBY_RST ((uint16_t)0x0000) /*!< Reset generated when entering in STANDBY */ +#define IS_OB_STDBY_SOURCE(SOURCE) (((SOURCE) == OB_STDBY_NoRST) || ((SOURCE) == OB_STDBY_RST)) + +#ifdef STM32F10X_XL +/** + * @} + */ +/** @defgroup FLASH_Boot + * @{ + */ +#define FLASH_BOOT_Bank1 ((uint16_t)0x0000) /*!< At startup, if boot pins are set in boot from user Flash position + and this parameter is selected the device will boot from Bank1(Default) */ +#define FLASH_BOOT_Bank2 ((uint16_t)0x0001) /*!< At startup, if boot pins are set in boot from user Flash position + and this parameter is selected the device will boot from Bank 2 or Bank 1, + depending on the activation of the bank */ +#define IS_FLASH_BOOT(BOOT) (((BOOT) == FLASH_BOOT_Bank1) || ((BOOT) == FLASH_BOOT_Bank2)) +#endif +/** + * @} + */ +/** @defgroup FLASH_Interrupts + * @{ + */ +#ifdef STM32F10X_XL +#define FLASH_IT_BANK2_ERROR ((uint32_t)0x80000400) /*!< FPEC BANK2 error interrupt source */ +#define FLASH_IT_BANK2_EOP ((uint32_t)0x80001000) /*!< End of FLASH BANK2 Operation Interrupt source */ + +#define FLASH_IT_BANK1_ERROR FLASH_IT_ERROR /*!< FPEC BANK1 error interrupt source */ +#define FLASH_IT_BANK1_EOP FLASH_IT_EOP /*!< End of FLASH BANK1 Operation Interrupt source */ + +#define FLASH_IT_ERROR ((uint32_t)0x00000400) /*!< FPEC BANK1 error interrupt source */ +#define FLASH_IT_EOP ((uint32_t)0x00001000) /*!< End of FLASH BANK1 Operation Interrupt source */ +#define IS_FLASH_IT(IT) ((((IT) & (uint32_t)0x7FFFEBFF) == 0x00000000) && (((IT) != 0x00000000))) +#else +#define FLASH_IT_ERROR ((uint32_t)0x00000400) /*!< FPEC error interrupt source */ +#define FLASH_IT_EOP ((uint32_t)0x00001000) /*!< End of FLASH Operation Interrupt source */ +#define FLASH_IT_BANK1_ERROR FLASH_IT_ERROR /*!< FPEC BANK1 error interrupt source */ +#define FLASH_IT_BANK1_EOP FLASH_IT_EOP /*!< End of FLASH BANK1 Operation Interrupt source */ + +#define IS_FLASH_IT(IT) ((((IT) & (uint32_t)0xFFFFEBFF) == 0x00000000) && (((IT) != 0x00000000))) +#endif + +/** + * @} + */ + +/** @defgroup FLASH_Flags + * @{ + */ +#ifdef STM32F10X_XL +#define FLASH_FLAG_BANK2_BSY ((uint32_t)0x80000001) /*!< FLASH BANK2 Busy flag */ +#define FLASH_FLAG_BANK2_EOP ((uint32_t)0x80000020) /*!< FLASH BANK2 End of Operation flag */ +#define FLASH_FLAG_BANK2_PGERR ((uint32_t)0x80000004) /*!< FLASH BANK2 Program error flag */ +#define FLASH_FLAG_BANK2_WRPRTERR ((uint32_t)0x80000010) /*!< FLASH BANK2 Write protected error flag */ + +#define FLASH_FLAG_BANK1_BSY FLASH_FLAG_BSY /*!< FLASH BANK1 Busy flag*/ +#define FLASH_FLAG_BANK1_EOP FLASH_FLAG_EOP /*!< FLASH BANK1 End of Operation flag */ +#define FLASH_FLAG_BANK1_PGERR FLASH_FLAG_PGERR /*!< FLASH BANK1 Program error flag */ +#define FLASH_FLAG_BANK1_WRPRTERR FLASH_FLAG_WRPRTERR /*!< FLASH BANK1 Write protected error flag */ + +#define FLASH_FLAG_BSY ((uint32_t)0x00000001) /*!< FLASH Busy flag */ +#define FLASH_FLAG_EOP ((uint32_t)0x00000020) /*!< FLASH End of Operation flag */ +#define FLASH_FLAG_PGERR ((uint32_t)0x00000004) /*!< FLASH Program error flag */ +#define FLASH_FLAG_WRPRTERR ((uint32_t)0x00000010) /*!< FLASH Write protected error flag */ +#define FLASH_FLAG_OPTERR ((uint32_t)0x00000001) /*!< FLASH Option Byte error flag */ + +#define IS_FLASH_CLEAR_FLAG(FLAG) ((((FLAG) & (uint32_t)0x7FFFFFCA) == 0x00000000) && ((FLAG) != 0x00000000)) +#define IS_FLASH_GET_FLAG(FLAG) (((FLAG) == FLASH_FLAG_BSY) || ((FLAG) == FLASH_FLAG_EOP) || \ + ((FLAG) == FLASH_FLAG_PGERR) || ((FLAG) == FLASH_FLAG_WRPRTERR) || \ + ((FLAG) == FLASH_FLAG_OPTERR)|| \ + ((FLAG) == FLASH_FLAG_BANK1_BSY) || ((FLAG) == FLASH_FLAG_BANK1_EOP) || \ + ((FLAG) == FLASH_FLAG_BANK1_PGERR) || ((FLAG) == FLASH_FLAG_BANK1_WRPRTERR) || \ + ((FLAG) == FLASH_FLAG_BANK2_BSY) || ((FLAG) == FLASH_FLAG_BANK2_EOP) || \ + ((FLAG) == FLASH_FLAG_BANK2_PGERR) || ((FLAG) == FLASH_FLAG_BANK2_WRPRTERR)) +#else +#define FLASH_FLAG_BSY ((uint32_t)0x00000001) /*!< FLASH Busy flag */ +#define FLASH_FLAG_EOP ((uint32_t)0x00000020) /*!< FLASH End of Operation flag */ +#define FLASH_FLAG_PGERR ((uint32_t)0x00000004) /*!< FLASH Program error flag */ +#define FLASH_FLAG_WRPRTERR ((uint32_t)0x00000010) /*!< FLASH Write protected error flag */ +#define FLASH_FLAG_OPTERR ((uint32_t)0x00000001) /*!< FLASH Option Byte error flag */ + +#define FLASH_FLAG_BANK1_BSY FLASH_FLAG_BSY /*!< FLASH BANK1 Busy flag*/ +#define FLASH_FLAG_BANK1_EOP FLASH_FLAG_EOP /*!< FLASH BANK1 End of Operation flag */ +#define FLASH_FLAG_BANK1_PGERR FLASH_FLAG_PGERR /*!< FLASH BANK1 Program error flag */ +#define FLASH_FLAG_BANK1_WRPRTERR FLASH_FLAG_WRPRTERR /*!< FLASH BANK1 Write protected error flag */ + +#define IS_FLASH_CLEAR_FLAG(FLAG) ((((FLAG) & (uint32_t)0xFFFFFFCA) == 0x00000000) && ((FLAG) != 0x00000000)) +#define IS_FLASH_GET_FLAG(FLAG) (((FLAG) == FLASH_FLAG_BSY) || ((FLAG) == FLASH_FLAG_EOP) || \ + ((FLAG) == FLASH_FLAG_PGERR) || ((FLAG) == FLASH_FLAG_WRPRTERR) || \ + ((FLAG) == FLASH_FLAG_BANK1_BSY) || ((FLAG) == FLASH_FLAG_BANK1_EOP) || \ + ((FLAG) == FLASH_FLAG_BANK1_PGERR) || ((FLAG) == FLASH_FLAG_BANK1_WRPRTERR) || \ + ((FLAG) == FLASH_FLAG_OPTERR)) +#endif + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup FLASH_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup FLASH_Exported_Functions + * @{ + */ + +/*------------ Functions used for all STM32F10x devices -----*/ +void FLASH_SetLatency(uint32_t FLASH_Latency); +void FLASH_HalfCycleAccessCmd(uint32_t FLASH_HalfCycleAccess); +void FLASH_PrefetchBufferCmd(uint32_t FLASH_PrefetchBuffer); +void FLASH_Unlock(void); +void FLASH_Lock(void); +FLASH_Status FLASH_ErasePage(uint32_t Page_Address); +FLASH_Status FLASH_EraseAllPages(void); +FLASH_Status FLASH_EraseOptionBytes(void); +FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data); +FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data); +FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data); +FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages); +FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState); +FLASH_Status FLASH_UserOptionByteConfig(uint16_t OB_IWDG, uint16_t OB_STOP, uint16_t OB_STDBY); +uint32_t FLASH_GetUserOptionByte(void); +uint32_t FLASH_GetWriteProtectionOptionByte(void); +FlagStatus FLASH_GetReadOutProtectionStatus(void); +FlagStatus FLASH_GetPrefetchBufferStatus(void); +void FLASH_ITConfig(uint32_t FLASH_IT, FunctionalState NewState); +FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_FLAG); +void FLASH_ClearFlag(uint32_t FLASH_FLAG); +FLASH_Status FLASH_GetStatus(void); +FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout); + +/*------------ New function used for all STM32F10x devices -----*/ +void FLASH_UnlockBank1(void); +void FLASH_LockBank1(void); +FLASH_Status FLASH_EraseAllBank1Pages(void); +FLASH_Status FLASH_GetBank1Status(void); +FLASH_Status FLASH_WaitForLastBank1Operation(uint32_t Timeout); + +#ifdef STM32F10X_XL +/*---- New Functions used only with STM32F10x_XL density devices -----*/ +void FLASH_UnlockBank2(void); +void FLASH_LockBank2(void); +FLASH_Status FLASH_EraseAllBank2Pages(void); +FLASH_Status FLASH_GetBank2Status(void); +FLASH_Status FLASH_WaitForLastBank2Operation(uint32_t Timeout); +FLASH_Status FLASH_BootConfig(uint16_t FLASH_BOOT); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F10x_FLASH_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_fsmc.c b/Library/stm32f10x_fsmc.c new file mode 100644 index 0000000..51669ee --- /dev/null +++ b/Library/stm32f10x_fsmc.c @@ -0,0 +1,866 @@ +/** + ****************************************************************************** + * @file stm32f10x_fsmc.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the FSMC firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_fsmc.h" +#include "stm32f10x_rcc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup FSMC + * @brief FSMC driver modules + * @{ + */ + +/** @defgroup FSMC_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + +/** @defgroup FSMC_Private_Defines + * @{ + */ + +/* --------------------- FSMC registers bit mask ---------------------------- */ + +/* FSMC BCRx Mask */ +#define BCR_MBKEN_Set ((uint32_t)0x00000001) +#define BCR_MBKEN_Reset ((uint32_t)0x000FFFFE) +#define BCR_FACCEN_Set ((uint32_t)0x00000040) + +/* FSMC PCRx Mask */ +#define PCR_PBKEN_Set ((uint32_t)0x00000004) +#define PCR_PBKEN_Reset ((uint32_t)0x000FFFFB) +#define PCR_ECCEN_Set ((uint32_t)0x00000040) +#define PCR_ECCEN_Reset ((uint32_t)0x000FFFBF) +#define PCR_MemoryType_NAND ((uint32_t)0x00000008) +/** + * @} + */ + +/** @defgroup FSMC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup FSMC_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup FSMC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup FSMC_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the FSMC NOR/SRAM Banks registers to their default + * reset values. + * @param FSMC_Bank: specifies the FSMC Bank to be used + * This parameter can be one of the following values: + * @arg FSMC_Bank1_NORSRAM1: FSMC Bank1 NOR/SRAM1 + * @arg FSMC_Bank1_NORSRAM2: FSMC Bank1 NOR/SRAM2 + * @arg FSMC_Bank1_NORSRAM3: FSMC Bank1 NOR/SRAM3 + * @arg FSMC_Bank1_NORSRAM4: FSMC Bank1 NOR/SRAM4 + * @retval None + */ +void FSMC_NORSRAMDeInit(uint32_t FSMC_Bank) +{ + /* Check the parameter */ + assert_param(IS_FSMC_NORSRAM_BANK(FSMC_Bank)); + + /* FSMC_Bank1_NORSRAM1 */ + if(FSMC_Bank == FSMC_Bank1_NORSRAM1) + { + FSMC_Bank1->BTCR[FSMC_Bank] = 0x000030DB; + } + /* FSMC_Bank1_NORSRAM2, FSMC_Bank1_NORSRAM3 or FSMC_Bank1_NORSRAM4 */ + else + { + FSMC_Bank1->BTCR[FSMC_Bank] = 0x000030D2; + } + FSMC_Bank1->BTCR[FSMC_Bank + 1] = 0x0FFFFFFF; + FSMC_Bank1E->BWTR[FSMC_Bank] = 0x0FFFFFFF; +} + +/** + * @brief Deinitializes the FSMC NAND Banks registers to their default reset values. + * @param FSMC_Bank: specifies the FSMC Bank to be used + * This parameter can be one of the following values: + * @arg FSMC_Bank2_NAND: FSMC Bank2 NAND + * @arg FSMC_Bank3_NAND: FSMC Bank3 NAND + * @retval None + */ +void FSMC_NANDDeInit(uint32_t FSMC_Bank) +{ + /* Check the parameter */ + assert_param(IS_FSMC_NAND_BANK(FSMC_Bank)); + + if(FSMC_Bank == FSMC_Bank2_NAND) + { + /* Set the FSMC_Bank2 registers to their reset values */ + FSMC_Bank2->PCR2 = 0x00000018; + FSMC_Bank2->SR2 = 0x00000040; + FSMC_Bank2->PMEM2 = 0xFCFCFCFC; + FSMC_Bank2->PATT2 = 0xFCFCFCFC; + } + /* FSMC_Bank3_NAND */ + else + { + /* Set the FSMC_Bank3 registers to their reset values */ + FSMC_Bank3->PCR3 = 0x00000018; + FSMC_Bank3->SR3 = 0x00000040; + FSMC_Bank3->PMEM3 = 0xFCFCFCFC; + FSMC_Bank3->PATT3 = 0xFCFCFCFC; + } +} + +/** + * @brief Deinitializes the FSMC PCCARD Bank registers to their default reset values. + * @param None + * @retval None + */ +void FSMC_PCCARDDeInit(void) +{ + /* Set the FSMC_Bank4 registers to their reset values */ + FSMC_Bank4->PCR4 = 0x00000018; + FSMC_Bank4->SR4 = 0x00000000; + FSMC_Bank4->PMEM4 = 0xFCFCFCFC; + FSMC_Bank4->PATT4 = 0xFCFCFCFC; + FSMC_Bank4->PIO4 = 0xFCFCFCFC; +} + +/** + * @brief Initializes the FSMC NOR/SRAM Banks according to the specified + * parameters in the FSMC_NORSRAMInitStruct. + * @param FSMC_NORSRAMInitStruct : pointer to a FSMC_NORSRAMInitTypeDef + * structure that contains the configuration information for + * the FSMC NOR/SRAM specified Banks. + * @retval None + */ +void FSMC_NORSRAMInit(FSMC_NORSRAMInitTypeDef* FSMC_NORSRAMInitStruct) +{ + /* Check the parameters */ + assert_param(IS_FSMC_NORSRAM_BANK(FSMC_NORSRAMInitStruct->FSMC_Bank)); + assert_param(IS_FSMC_MUX(FSMC_NORSRAMInitStruct->FSMC_DataAddressMux)); + assert_param(IS_FSMC_MEMORY(FSMC_NORSRAMInitStruct->FSMC_MemoryType)); + assert_param(IS_FSMC_MEMORY_WIDTH(FSMC_NORSRAMInitStruct->FSMC_MemoryDataWidth)); + assert_param(IS_FSMC_BURSTMODE(FSMC_NORSRAMInitStruct->FSMC_BurstAccessMode)); + assert_param(IS_FSMC_ASYNWAIT(FSMC_NORSRAMInitStruct->FSMC_AsynchronousWait)); + assert_param(IS_FSMC_WAIT_POLARITY(FSMC_NORSRAMInitStruct->FSMC_WaitSignalPolarity)); + assert_param(IS_FSMC_WRAP_MODE(FSMC_NORSRAMInitStruct->FSMC_WrapMode)); + assert_param(IS_FSMC_WAIT_SIGNAL_ACTIVE(FSMC_NORSRAMInitStruct->FSMC_WaitSignalActive)); + assert_param(IS_FSMC_WRITE_OPERATION(FSMC_NORSRAMInitStruct->FSMC_WriteOperation)); + assert_param(IS_FSMC_WAITE_SIGNAL(FSMC_NORSRAMInitStruct->FSMC_WaitSignal)); + assert_param(IS_FSMC_EXTENDED_MODE(FSMC_NORSRAMInitStruct->FSMC_ExtendedMode)); + assert_param(IS_FSMC_WRITE_BURST(FSMC_NORSRAMInitStruct->FSMC_WriteBurst)); + assert_param(IS_FSMC_ADDRESS_SETUP_TIME(FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AddressSetupTime)); + assert_param(IS_FSMC_ADDRESS_HOLD_TIME(FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AddressHoldTime)); + assert_param(IS_FSMC_DATASETUP_TIME(FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_DataSetupTime)); + assert_param(IS_FSMC_TURNAROUND_TIME(FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_BusTurnAroundDuration)); + assert_param(IS_FSMC_CLK_DIV(FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_CLKDivision)); + assert_param(IS_FSMC_DATA_LATENCY(FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_DataLatency)); + assert_param(IS_FSMC_ACCESS_MODE(FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AccessMode)); + + /* Bank1 NOR/SRAM control register configuration */ + FSMC_Bank1->BTCR[FSMC_NORSRAMInitStruct->FSMC_Bank] = + (uint32_t)FSMC_NORSRAMInitStruct->FSMC_DataAddressMux | + FSMC_NORSRAMInitStruct->FSMC_MemoryType | + FSMC_NORSRAMInitStruct->FSMC_MemoryDataWidth | + FSMC_NORSRAMInitStruct->FSMC_BurstAccessMode | + FSMC_NORSRAMInitStruct->FSMC_AsynchronousWait | + FSMC_NORSRAMInitStruct->FSMC_WaitSignalPolarity | + FSMC_NORSRAMInitStruct->FSMC_WrapMode | + FSMC_NORSRAMInitStruct->FSMC_WaitSignalActive | + FSMC_NORSRAMInitStruct->FSMC_WriteOperation | + FSMC_NORSRAMInitStruct->FSMC_WaitSignal | + FSMC_NORSRAMInitStruct->FSMC_ExtendedMode | + FSMC_NORSRAMInitStruct->FSMC_WriteBurst; + + if(FSMC_NORSRAMInitStruct->FSMC_MemoryType == FSMC_MemoryType_NOR) + { + FSMC_Bank1->BTCR[FSMC_NORSRAMInitStruct->FSMC_Bank] |= (uint32_t)BCR_FACCEN_Set; + } + + /* Bank1 NOR/SRAM timing register configuration */ + FSMC_Bank1->BTCR[FSMC_NORSRAMInitStruct->FSMC_Bank+1] = + (uint32_t)FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AddressSetupTime | + (FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AddressHoldTime << 4) | + (FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_DataSetupTime << 8) | + (FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_BusTurnAroundDuration << 16) | + (FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_CLKDivision << 20) | + (FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_DataLatency << 24) | + FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AccessMode; + + + /* Bank1 NOR/SRAM timing register for write configuration, if extended mode is used */ + if(FSMC_NORSRAMInitStruct->FSMC_ExtendedMode == FSMC_ExtendedMode_Enable) + { + assert_param(IS_FSMC_ADDRESS_SETUP_TIME(FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AddressSetupTime)); + assert_param(IS_FSMC_ADDRESS_HOLD_TIME(FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AddressHoldTime)); + assert_param(IS_FSMC_DATASETUP_TIME(FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_DataSetupTime)); + assert_param(IS_FSMC_CLK_DIV(FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_CLKDivision)); + assert_param(IS_FSMC_DATA_LATENCY(FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_DataLatency)); + assert_param(IS_FSMC_ACCESS_MODE(FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AccessMode)); + FSMC_Bank1E->BWTR[FSMC_NORSRAMInitStruct->FSMC_Bank] = + (uint32_t)FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AddressSetupTime | + (FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AddressHoldTime << 4 )| + (FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_DataSetupTime << 8) | + (FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_CLKDivision << 20) | + (FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_DataLatency << 24) | + FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AccessMode; + } + else + { + FSMC_Bank1E->BWTR[FSMC_NORSRAMInitStruct->FSMC_Bank] = 0x0FFFFFFF; + } +} + +/** + * @brief Initializes the FSMC NAND Banks according to the specified + * parameters in the FSMC_NANDInitStruct. + * @param FSMC_NANDInitStruct : pointer to a FSMC_NANDInitTypeDef + * structure that contains the configuration information for the FSMC + * NAND specified Banks. + * @retval None + */ +void FSMC_NANDInit(FSMC_NANDInitTypeDef* FSMC_NANDInitStruct) +{ + uint32_t tmppcr = 0x00000000, tmppmem = 0x00000000, tmppatt = 0x00000000; + + /* Check the parameters */ + assert_param( IS_FSMC_NAND_BANK(FSMC_NANDInitStruct->FSMC_Bank)); + assert_param( IS_FSMC_WAIT_FEATURE(FSMC_NANDInitStruct->FSMC_Waitfeature)); + assert_param( IS_FSMC_MEMORY_WIDTH(FSMC_NANDInitStruct->FSMC_MemoryDataWidth)); + assert_param( IS_FSMC_ECC_STATE(FSMC_NANDInitStruct->FSMC_ECC)); + assert_param( IS_FSMC_ECCPAGE_SIZE(FSMC_NANDInitStruct->FSMC_ECCPageSize)); + assert_param( IS_FSMC_TCLR_TIME(FSMC_NANDInitStruct->FSMC_TCLRSetupTime)); + assert_param( IS_FSMC_TAR_TIME(FSMC_NANDInitStruct->FSMC_TARSetupTime)); + assert_param(IS_FSMC_SETUP_TIME(FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_SetupTime)); + assert_param(IS_FSMC_WAIT_TIME(FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_WaitSetupTime)); + assert_param(IS_FSMC_HOLD_TIME(FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HoldSetupTime)); + assert_param(IS_FSMC_HIZ_TIME(FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HiZSetupTime)); + assert_param(IS_FSMC_SETUP_TIME(FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_SetupTime)); + assert_param(IS_FSMC_WAIT_TIME(FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_WaitSetupTime)); + assert_param(IS_FSMC_HOLD_TIME(FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HoldSetupTime)); + assert_param(IS_FSMC_HIZ_TIME(FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HiZSetupTime)); + + /* Set the tmppcr value according to FSMC_NANDInitStruct parameters */ + tmppcr = (uint32_t)FSMC_NANDInitStruct->FSMC_Waitfeature | + PCR_MemoryType_NAND | + FSMC_NANDInitStruct->FSMC_MemoryDataWidth | + FSMC_NANDInitStruct->FSMC_ECC | + FSMC_NANDInitStruct->FSMC_ECCPageSize | + (FSMC_NANDInitStruct->FSMC_TCLRSetupTime << 9 )| + (FSMC_NANDInitStruct->FSMC_TARSetupTime << 13); + + /* Set tmppmem value according to FSMC_CommonSpaceTimingStructure parameters */ + tmppmem = (uint32_t)FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_SetupTime | + (FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_WaitSetupTime << 8) | + (FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HoldSetupTime << 16)| + (FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HiZSetupTime << 24); + + /* Set tmppatt value according to FSMC_AttributeSpaceTimingStructure parameters */ + tmppatt = (uint32_t)FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_SetupTime | + (FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_WaitSetupTime << 8) | + (FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HoldSetupTime << 16)| + (FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HiZSetupTime << 24); + + if(FSMC_NANDInitStruct->FSMC_Bank == FSMC_Bank2_NAND) + { + /* FSMC_Bank2_NAND registers configuration */ + FSMC_Bank2->PCR2 = tmppcr; + FSMC_Bank2->PMEM2 = tmppmem; + FSMC_Bank2->PATT2 = tmppatt; + } + else + { + /* FSMC_Bank3_NAND registers configuration */ + FSMC_Bank3->PCR3 = tmppcr; + FSMC_Bank3->PMEM3 = tmppmem; + FSMC_Bank3->PATT3 = tmppatt; + } +} + +/** + * @brief Initializes the FSMC PCCARD Bank according to the specified + * parameters in the FSMC_PCCARDInitStruct. + * @param FSMC_PCCARDInitStruct : pointer to a FSMC_PCCARDInitTypeDef + * structure that contains the configuration information for the FSMC + * PCCARD Bank. + * @retval None + */ +void FSMC_PCCARDInit(FSMC_PCCARDInitTypeDef* FSMC_PCCARDInitStruct) +{ + /* Check the parameters */ + assert_param(IS_FSMC_WAIT_FEATURE(FSMC_PCCARDInitStruct->FSMC_Waitfeature)); + assert_param(IS_FSMC_TCLR_TIME(FSMC_PCCARDInitStruct->FSMC_TCLRSetupTime)); + assert_param(IS_FSMC_TAR_TIME(FSMC_PCCARDInitStruct->FSMC_TARSetupTime)); + + assert_param(IS_FSMC_SETUP_TIME(FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_SetupTime)); + assert_param(IS_FSMC_WAIT_TIME(FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_WaitSetupTime)); + assert_param(IS_FSMC_HOLD_TIME(FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HoldSetupTime)); + assert_param(IS_FSMC_HIZ_TIME(FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HiZSetupTime)); + + assert_param(IS_FSMC_SETUP_TIME(FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_SetupTime)); + assert_param(IS_FSMC_WAIT_TIME(FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_WaitSetupTime)); + assert_param(IS_FSMC_HOLD_TIME(FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HoldSetupTime)); + assert_param(IS_FSMC_HIZ_TIME(FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HiZSetupTime)); + assert_param(IS_FSMC_SETUP_TIME(FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_SetupTime)); + assert_param(IS_FSMC_WAIT_TIME(FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_WaitSetupTime)); + assert_param(IS_FSMC_HOLD_TIME(FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_HoldSetupTime)); + assert_param(IS_FSMC_HIZ_TIME(FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_HiZSetupTime)); + + /* Set the PCR4 register value according to FSMC_PCCARDInitStruct parameters */ + FSMC_Bank4->PCR4 = (uint32_t)FSMC_PCCARDInitStruct->FSMC_Waitfeature | + FSMC_MemoryDataWidth_16b | + (FSMC_PCCARDInitStruct->FSMC_TCLRSetupTime << 9) | + (FSMC_PCCARDInitStruct->FSMC_TARSetupTime << 13); + + /* Set PMEM4 register value according to FSMC_CommonSpaceTimingStructure parameters */ + FSMC_Bank4->PMEM4 = (uint32_t)FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_SetupTime | + (FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_WaitSetupTime << 8) | + (FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HoldSetupTime << 16)| + (FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HiZSetupTime << 24); + + /* Set PATT4 register value according to FSMC_AttributeSpaceTimingStructure parameters */ + FSMC_Bank4->PATT4 = (uint32_t)FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_SetupTime | + (FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_WaitSetupTime << 8) | + (FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HoldSetupTime << 16)| + (FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HiZSetupTime << 24); + + /* Set PIO4 register value according to FSMC_IOSpaceTimingStructure parameters */ + FSMC_Bank4->PIO4 = (uint32_t)FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_SetupTime | + (FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_WaitSetupTime << 8) | + (FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_HoldSetupTime << 16)| + (FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_HiZSetupTime << 24); +} + +/** + * @brief Fills each FSMC_NORSRAMInitStruct member with its default value. + * @param FSMC_NORSRAMInitStruct: pointer to a FSMC_NORSRAMInitTypeDef + * structure which will be initialized. + * @retval None + */ +void FSMC_NORSRAMStructInit(FSMC_NORSRAMInitTypeDef* FSMC_NORSRAMInitStruct) +{ + /* Reset NOR/SRAM Init structure parameters values */ + FSMC_NORSRAMInitStruct->FSMC_Bank = FSMC_Bank1_NORSRAM1; + FSMC_NORSRAMInitStruct->FSMC_DataAddressMux = FSMC_DataAddressMux_Enable; + FSMC_NORSRAMInitStruct->FSMC_MemoryType = FSMC_MemoryType_SRAM; + FSMC_NORSRAMInitStruct->FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b; + FSMC_NORSRAMInitStruct->FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; + FSMC_NORSRAMInitStruct->FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; + FSMC_NORSRAMInitStruct->FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; + FSMC_NORSRAMInitStruct->FSMC_WrapMode = FSMC_WrapMode_Disable; + FSMC_NORSRAMInitStruct->FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; + FSMC_NORSRAMInitStruct->FSMC_WriteOperation = FSMC_WriteOperation_Enable; + FSMC_NORSRAMInitStruct->FSMC_WaitSignal = FSMC_WaitSignal_Enable; + FSMC_NORSRAMInitStruct->FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; + FSMC_NORSRAMInitStruct->FSMC_WriteBurst = FSMC_WriteBurst_Disable; + FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AddressSetupTime = 0xF; + FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AddressHoldTime = 0xF; + FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_DataSetupTime = 0xFF; + FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_BusTurnAroundDuration = 0xF; + FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_CLKDivision = 0xF; + FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_DataLatency = 0xF; + FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AccessMode = FSMC_AccessMode_A; + FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AddressSetupTime = 0xF; + FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AddressHoldTime = 0xF; + FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_DataSetupTime = 0xFF; + FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_BusTurnAroundDuration = 0xF; + FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_CLKDivision = 0xF; + FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_DataLatency = 0xF; + FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AccessMode = FSMC_AccessMode_A; +} + +/** + * @brief Fills each FSMC_NANDInitStruct member with its default value. + * @param FSMC_NANDInitStruct: pointer to a FSMC_NANDInitTypeDef + * structure which will be initialized. + * @retval None + */ +void FSMC_NANDStructInit(FSMC_NANDInitTypeDef* FSMC_NANDInitStruct) +{ + /* Reset NAND Init structure parameters values */ + FSMC_NANDInitStruct->FSMC_Bank = FSMC_Bank2_NAND; + FSMC_NANDInitStruct->FSMC_Waitfeature = FSMC_Waitfeature_Disable; + FSMC_NANDInitStruct->FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b; + FSMC_NANDInitStruct->FSMC_ECC = FSMC_ECC_Disable; + FSMC_NANDInitStruct->FSMC_ECCPageSize = FSMC_ECCPageSize_256Bytes; + FSMC_NANDInitStruct->FSMC_TCLRSetupTime = 0x0; + FSMC_NANDInitStruct->FSMC_TARSetupTime = 0x0; + FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_SetupTime = 0xFC; + FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_WaitSetupTime = 0xFC; + FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HoldSetupTime = 0xFC; + FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HiZSetupTime = 0xFC; + FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_SetupTime = 0xFC; + FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_WaitSetupTime = 0xFC; + FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HoldSetupTime = 0xFC; + FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HiZSetupTime = 0xFC; +} + +/** + * @brief Fills each FSMC_PCCARDInitStruct member with its default value. + * @param FSMC_PCCARDInitStruct: pointer to a FSMC_PCCARDInitTypeDef + * structure which will be initialized. + * @retval None + */ +void FSMC_PCCARDStructInit(FSMC_PCCARDInitTypeDef* FSMC_PCCARDInitStruct) +{ + /* Reset PCCARD Init structure parameters values */ + FSMC_PCCARDInitStruct->FSMC_Waitfeature = FSMC_Waitfeature_Disable; + FSMC_PCCARDInitStruct->FSMC_TCLRSetupTime = 0x0; + FSMC_PCCARDInitStruct->FSMC_TARSetupTime = 0x0; + FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_SetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_WaitSetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HoldSetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HiZSetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_SetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_WaitSetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HoldSetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HiZSetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_SetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_WaitSetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_HoldSetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_HiZSetupTime = 0xFC; +} + +/** + * @brief Enables or disables the specified NOR/SRAM Memory Bank. + * @param FSMC_Bank: specifies the FSMC Bank to be used + * This parameter can be one of the following values: + * @arg FSMC_Bank1_NORSRAM1: FSMC Bank1 NOR/SRAM1 + * @arg FSMC_Bank1_NORSRAM2: FSMC Bank1 NOR/SRAM2 + * @arg FSMC_Bank1_NORSRAM3: FSMC Bank1 NOR/SRAM3 + * @arg FSMC_Bank1_NORSRAM4: FSMC Bank1 NOR/SRAM4 + * @param NewState: new state of the FSMC_Bank. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FSMC_NORSRAMCmd(uint32_t FSMC_Bank, FunctionalState NewState) +{ + assert_param(IS_FSMC_NORSRAM_BANK(FSMC_Bank)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected NOR/SRAM Bank by setting the PBKEN bit in the BCRx register */ + FSMC_Bank1->BTCR[FSMC_Bank] |= BCR_MBKEN_Set; + } + else + { + /* Disable the selected NOR/SRAM Bank by clearing the PBKEN bit in the BCRx register */ + FSMC_Bank1->BTCR[FSMC_Bank] &= BCR_MBKEN_Reset; + } +} + +/** + * @brief Enables or disables the specified NAND Memory Bank. + * @param FSMC_Bank: specifies the FSMC Bank to be used + * This parameter can be one of the following values: + * @arg FSMC_Bank2_NAND: FSMC Bank2 NAND + * @arg FSMC_Bank3_NAND: FSMC Bank3 NAND + * @param NewState: new state of the FSMC_Bank. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FSMC_NANDCmd(uint32_t FSMC_Bank, FunctionalState NewState) +{ + assert_param(IS_FSMC_NAND_BANK(FSMC_Bank)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected NAND Bank by setting the PBKEN bit in the PCRx register */ + if(FSMC_Bank == FSMC_Bank2_NAND) + { + FSMC_Bank2->PCR2 |= PCR_PBKEN_Set; + } + else + { + FSMC_Bank3->PCR3 |= PCR_PBKEN_Set; + } + } + else + { + /* Disable the selected NAND Bank by clearing the PBKEN bit in the PCRx register */ + if(FSMC_Bank == FSMC_Bank2_NAND) + { + FSMC_Bank2->PCR2 &= PCR_PBKEN_Reset; + } + else + { + FSMC_Bank3->PCR3 &= PCR_PBKEN_Reset; + } + } +} + +/** + * @brief Enables or disables the PCCARD Memory Bank. + * @param NewState: new state of the PCCARD Memory Bank. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FSMC_PCCARDCmd(FunctionalState NewState) +{ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the PCCARD Bank by setting the PBKEN bit in the PCR4 register */ + FSMC_Bank4->PCR4 |= PCR_PBKEN_Set; + } + else + { + /* Disable the PCCARD Bank by clearing the PBKEN bit in the PCR4 register */ + FSMC_Bank4->PCR4 &= PCR_PBKEN_Reset; + } +} + +/** + * @brief Enables or disables the FSMC NAND ECC feature. + * @param FSMC_Bank: specifies the FSMC Bank to be used + * This parameter can be one of the following values: + * @arg FSMC_Bank2_NAND: FSMC Bank2 NAND + * @arg FSMC_Bank3_NAND: FSMC Bank3 NAND + * @param NewState: new state of the FSMC NAND ECC feature. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FSMC_NANDECCCmd(uint32_t FSMC_Bank, FunctionalState NewState) +{ + assert_param(IS_FSMC_NAND_BANK(FSMC_Bank)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected NAND Bank ECC function by setting the ECCEN bit in the PCRx register */ + if(FSMC_Bank == FSMC_Bank2_NAND) + { + FSMC_Bank2->PCR2 |= PCR_ECCEN_Set; + } + else + { + FSMC_Bank3->PCR3 |= PCR_ECCEN_Set; + } + } + else + { + /* Disable the selected NAND Bank ECC function by clearing the ECCEN bit in the PCRx register */ + if(FSMC_Bank == FSMC_Bank2_NAND) + { + FSMC_Bank2->PCR2 &= PCR_ECCEN_Reset; + } + else + { + FSMC_Bank3->PCR3 &= PCR_ECCEN_Reset; + } + } +} + +/** + * @brief Returns the error correction code register value. + * @param FSMC_Bank: specifies the FSMC Bank to be used + * This parameter can be one of the following values: + * @arg FSMC_Bank2_NAND: FSMC Bank2 NAND + * @arg FSMC_Bank3_NAND: FSMC Bank3 NAND + * @retval The Error Correction Code (ECC) value. + */ +uint32_t FSMC_GetECC(uint32_t FSMC_Bank) +{ + uint32_t eccval = 0x00000000; + + if(FSMC_Bank == FSMC_Bank2_NAND) + { + /* Get the ECCR2 register value */ + eccval = FSMC_Bank2->ECCR2; + } + else + { + /* Get the ECCR3 register value */ + eccval = FSMC_Bank3->ECCR3; + } + /* Return the error correction code value */ + return(eccval); +} + +/** + * @brief Enables or disables the specified FSMC interrupts. + * @param FSMC_Bank: specifies the FSMC Bank to be used + * This parameter can be one of the following values: + * @arg FSMC_Bank2_NAND: FSMC Bank2 NAND + * @arg FSMC_Bank3_NAND: FSMC Bank3 NAND + * @arg FSMC_Bank4_PCCARD: FSMC Bank4 PCCARD + * @param FSMC_IT: specifies the FSMC interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg FSMC_IT_RisingEdge: Rising edge detection interrupt. + * @arg FSMC_IT_Level: Level edge detection interrupt. + * @arg FSMC_IT_FallingEdge: Falling edge detection interrupt. + * @param NewState: new state of the specified FSMC interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FSMC_ITConfig(uint32_t FSMC_Bank, uint32_t FSMC_IT, FunctionalState NewState) +{ + assert_param(IS_FSMC_IT_BANK(FSMC_Bank)); + assert_param(IS_FSMC_IT(FSMC_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected FSMC_Bank2 interrupts */ + if(FSMC_Bank == FSMC_Bank2_NAND) + { + FSMC_Bank2->SR2 |= FSMC_IT; + } + /* Enable the selected FSMC_Bank3 interrupts */ + else if (FSMC_Bank == FSMC_Bank3_NAND) + { + FSMC_Bank3->SR3 |= FSMC_IT; + } + /* Enable the selected FSMC_Bank4 interrupts */ + else + { + FSMC_Bank4->SR4 |= FSMC_IT; + } + } + else + { + /* Disable the selected FSMC_Bank2 interrupts */ + if(FSMC_Bank == FSMC_Bank2_NAND) + { + + FSMC_Bank2->SR2 &= (uint32_t)~FSMC_IT; + } + /* Disable the selected FSMC_Bank3 interrupts */ + else if (FSMC_Bank == FSMC_Bank3_NAND) + { + FSMC_Bank3->SR3 &= (uint32_t)~FSMC_IT; + } + /* Disable the selected FSMC_Bank4 interrupts */ + else + { + FSMC_Bank4->SR4 &= (uint32_t)~FSMC_IT; + } + } +} + +/** + * @brief Checks whether the specified FSMC flag is set or not. + * @param FSMC_Bank: specifies the FSMC Bank to be used + * This parameter can be one of the following values: + * @arg FSMC_Bank2_NAND: FSMC Bank2 NAND + * @arg FSMC_Bank3_NAND: FSMC Bank3 NAND + * @arg FSMC_Bank4_PCCARD: FSMC Bank4 PCCARD + * @param FSMC_FLAG: specifies the flag to check. + * This parameter can be one of the following values: + * @arg FSMC_FLAG_RisingEdge: Rising egde detection Flag. + * @arg FSMC_FLAG_Level: Level detection Flag. + * @arg FSMC_FLAG_FallingEdge: Falling egde detection Flag. + * @arg FSMC_FLAG_FEMPT: Fifo empty Flag. + * @retval The new state of FSMC_FLAG (SET or RESET). + */ +FlagStatus FSMC_GetFlagStatus(uint32_t FSMC_Bank, uint32_t FSMC_FLAG) +{ + FlagStatus bitstatus = RESET; + uint32_t tmpsr = 0x00000000; + + /* Check the parameters */ + assert_param(IS_FSMC_GETFLAG_BANK(FSMC_Bank)); + assert_param(IS_FSMC_GET_FLAG(FSMC_FLAG)); + + if(FSMC_Bank == FSMC_Bank2_NAND) + { + tmpsr = FSMC_Bank2->SR2; + } + else if(FSMC_Bank == FSMC_Bank3_NAND) + { + tmpsr = FSMC_Bank3->SR3; + } + /* FSMC_Bank4_PCCARD*/ + else + { + tmpsr = FSMC_Bank4->SR4; + } + + /* Get the flag status */ + if ((tmpsr & FSMC_FLAG) != (uint16_t)RESET ) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + /* Return the flag status */ + return bitstatus; +} + +/** + * @brief Clears the FSMC's pending flags. + * @param FSMC_Bank: specifies the FSMC Bank to be used + * This parameter can be one of the following values: + * @arg FSMC_Bank2_NAND: FSMC Bank2 NAND + * @arg FSMC_Bank3_NAND: FSMC Bank3 NAND + * @arg FSMC_Bank4_PCCARD: FSMC Bank4 PCCARD + * @param FSMC_FLAG: specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg FSMC_FLAG_RisingEdge: Rising egde detection Flag. + * @arg FSMC_FLAG_Level: Level detection Flag. + * @arg FSMC_FLAG_FallingEdge: Falling egde detection Flag. + * @retval None + */ +void FSMC_ClearFlag(uint32_t FSMC_Bank, uint32_t FSMC_FLAG) +{ + /* Check the parameters */ + assert_param(IS_FSMC_GETFLAG_BANK(FSMC_Bank)); + assert_param(IS_FSMC_CLEAR_FLAG(FSMC_FLAG)) ; + + if(FSMC_Bank == FSMC_Bank2_NAND) + { + FSMC_Bank2->SR2 &= ~FSMC_FLAG; + } + else if(FSMC_Bank == FSMC_Bank3_NAND) + { + FSMC_Bank3->SR3 &= ~FSMC_FLAG; + } + /* FSMC_Bank4_PCCARD*/ + else + { + FSMC_Bank4->SR4 &= ~FSMC_FLAG; + } +} + +/** + * @brief Checks whether the specified FSMC interrupt has occurred or not. + * @param FSMC_Bank: specifies the FSMC Bank to be used + * This parameter can be one of the following values: + * @arg FSMC_Bank2_NAND: FSMC Bank2 NAND + * @arg FSMC_Bank3_NAND: FSMC Bank3 NAND + * @arg FSMC_Bank4_PCCARD: FSMC Bank4 PCCARD + * @param FSMC_IT: specifies the FSMC interrupt source to check. + * This parameter can be one of the following values: + * @arg FSMC_IT_RisingEdge: Rising edge detection interrupt. + * @arg FSMC_IT_Level: Level edge detection interrupt. + * @arg FSMC_IT_FallingEdge: Falling edge detection interrupt. + * @retval The new state of FSMC_IT (SET or RESET). + */ +ITStatus FSMC_GetITStatus(uint32_t FSMC_Bank, uint32_t FSMC_IT) +{ + ITStatus bitstatus = RESET; + uint32_t tmpsr = 0x0, itstatus = 0x0, itenable = 0x0; + + /* Check the parameters */ + assert_param(IS_FSMC_IT_BANK(FSMC_Bank)); + assert_param(IS_FSMC_GET_IT(FSMC_IT)); + + if(FSMC_Bank == FSMC_Bank2_NAND) + { + tmpsr = FSMC_Bank2->SR2; + } + else if(FSMC_Bank == FSMC_Bank3_NAND) + { + tmpsr = FSMC_Bank3->SR3; + } + /* FSMC_Bank4_PCCARD*/ + else + { + tmpsr = FSMC_Bank4->SR4; + } + + itstatus = tmpsr & FSMC_IT; + + itenable = tmpsr & (FSMC_IT >> 3); + if ((itstatus != (uint32_t)RESET) && (itenable != (uint32_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the FSMC's interrupt pending bits. + * @param FSMC_Bank: specifies the FSMC Bank to be used + * This parameter can be one of the following values: + * @arg FSMC_Bank2_NAND: FSMC Bank2 NAND + * @arg FSMC_Bank3_NAND: FSMC Bank3 NAND + * @arg FSMC_Bank4_PCCARD: FSMC Bank4 PCCARD + * @param FSMC_IT: specifies the interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg FSMC_IT_RisingEdge: Rising edge detection interrupt. + * @arg FSMC_IT_Level: Level edge detection interrupt. + * @arg FSMC_IT_FallingEdge: Falling edge detection interrupt. + * @retval None + */ +void FSMC_ClearITPendingBit(uint32_t FSMC_Bank, uint32_t FSMC_IT) +{ + /* Check the parameters */ + assert_param(IS_FSMC_IT_BANK(FSMC_Bank)); + assert_param(IS_FSMC_IT(FSMC_IT)); + + if(FSMC_Bank == FSMC_Bank2_NAND) + { + FSMC_Bank2->SR2 &= ~(FSMC_IT >> 3); + } + else if(FSMC_Bank == FSMC_Bank3_NAND) + { + FSMC_Bank3->SR3 &= ~(FSMC_IT >> 3); + } + /* FSMC_Bank4_PCCARD*/ + else + { + FSMC_Bank4->SR4 &= ~(FSMC_IT >> 3); + } +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_fsmc.h b/Library/stm32f10x_fsmc.h new file mode 100644 index 0000000..6e1769d --- /dev/null +++ b/Library/stm32f10x_fsmc.h @@ -0,0 +1,733 @@ +/** + ****************************************************************************** + * @file stm32f10x_fsmc.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the FSMC firmware + * library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_FSMC_H +#define __STM32F10x_FSMC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup FSMC + * @{ + */ + +/** @defgroup FSMC_Exported_Types + * @{ + */ + +/** + * @brief Timing parameters For NOR/SRAM Banks + */ + +typedef struct +{ + uint32_t FSMC_AddressSetupTime; /*!< Defines the number of HCLK cycles to configure + the duration of the address setup time. + This parameter can be a value between 0 and 0xF. + @note: It is not used with synchronous NOR Flash memories. */ + + uint32_t FSMC_AddressHoldTime; /*!< Defines the number of HCLK cycles to configure + the duration of the address hold time. + This parameter can be a value between 0 and 0xF. + @note: It is not used with synchronous NOR Flash memories.*/ + + uint32_t FSMC_DataSetupTime; /*!< Defines the number of HCLK cycles to configure + the duration of the data setup time. + This parameter can be a value between 0 and 0xFF. + @note: It is used for SRAMs, ROMs and asynchronous multiplexed NOR Flash memories. */ + + uint32_t FSMC_BusTurnAroundDuration; /*!< Defines the number of HCLK cycles to configure + the duration of the bus turnaround. + This parameter can be a value between 0 and 0xF. + @note: It is only used for multiplexed NOR Flash memories. */ + + uint32_t FSMC_CLKDivision; /*!< Defines the period of CLK clock output signal, expressed in number of HCLK cycles. + This parameter can be a value between 1 and 0xF. + @note: This parameter is not used for asynchronous NOR Flash, SRAM or ROM accesses. */ + + uint32_t FSMC_DataLatency; /*!< Defines the number of memory clock cycles to issue + to the memory before getting the first data. + The value of this parameter depends on the memory type as shown below: + - It must be set to 0 in case of a CRAM + - It is don't care in asynchronous NOR, SRAM or ROM accesses + - It may assume a value between 0 and 0xF in NOR Flash memories + with synchronous burst mode enable */ + + uint32_t FSMC_AccessMode; /*!< Specifies the asynchronous access mode. + This parameter can be a value of @ref FSMC_Access_Mode */ +}FSMC_NORSRAMTimingInitTypeDef; + +/** + * @brief FSMC NOR/SRAM Init structure definition + */ + +typedef struct +{ + uint32_t FSMC_Bank; /*!< Specifies the NOR/SRAM memory bank that will be used. + This parameter can be a value of @ref FSMC_NORSRAM_Bank */ + + uint32_t FSMC_DataAddressMux; /*!< Specifies whether the address and data values are + multiplexed on the databus or not. + This parameter can be a value of @ref FSMC_Data_Address_Bus_Multiplexing */ + + uint32_t FSMC_MemoryType; /*!< Specifies the type of external memory attached to + the corresponding memory bank. + This parameter can be a value of @ref FSMC_Memory_Type */ + + uint32_t FSMC_MemoryDataWidth; /*!< Specifies the external memory device width. + This parameter can be a value of @ref FSMC_Data_Width */ + + uint32_t FSMC_BurstAccessMode; /*!< Enables or disables the burst access mode for Flash memory, + valid only with synchronous burst Flash memories. + This parameter can be a value of @ref FSMC_Burst_Access_Mode */ + + uint32_t FSMC_AsynchronousWait; /*!< Enables or disables wait signal during asynchronous transfers, + valid only with asynchronous Flash memories. + This parameter can be a value of @ref FSMC_AsynchronousWait */ + + uint32_t FSMC_WaitSignalPolarity; /*!< Specifies the wait signal polarity, valid only when accessing + the Flash memory in burst mode. + This parameter can be a value of @ref FSMC_Wait_Signal_Polarity */ + + uint32_t FSMC_WrapMode; /*!< Enables or disables the Wrapped burst access mode for Flash + memory, valid only when accessing Flash memories in burst mode. + This parameter can be a value of @ref FSMC_Wrap_Mode */ + + uint32_t FSMC_WaitSignalActive; /*!< Specifies if the wait signal is asserted by the memory one + clock cycle before the wait state or during the wait state, + valid only when accessing memories in burst mode. + This parameter can be a value of @ref FSMC_Wait_Timing */ + + uint32_t FSMC_WriteOperation; /*!< Enables or disables the write operation in the selected bank by the FSMC. + This parameter can be a value of @ref FSMC_Write_Operation */ + + uint32_t FSMC_WaitSignal; /*!< Enables or disables the wait-state insertion via wait + signal, valid for Flash memory access in burst mode. + This parameter can be a value of @ref FSMC_Wait_Signal */ + + uint32_t FSMC_ExtendedMode; /*!< Enables or disables the extended mode. + This parameter can be a value of @ref FSMC_Extended_Mode */ + + uint32_t FSMC_WriteBurst; /*!< Enables or disables the write burst operation. + This parameter can be a value of @ref FSMC_Write_Burst */ + + FSMC_NORSRAMTimingInitTypeDef* FSMC_ReadWriteTimingStruct; /*!< Timing Parameters for write and read access if the ExtendedMode is not used*/ + + FSMC_NORSRAMTimingInitTypeDef* FSMC_WriteTimingStruct; /*!< Timing Parameters for write access if the ExtendedMode is used*/ +}FSMC_NORSRAMInitTypeDef; + +/** + * @brief Timing parameters For FSMC NAND and PCCARD Banks + */ + +typedef struct +{ + uint32_t FSMC_SetupTime; /*!< Defines the number of HCLK cycles to setup address before + the command assertion for NAND-Flash read or write access + to common/Attribute or I/O memory space (depending on + the memory space timing to be configured). + This parameter can be a value between 0 and 0xFF.*/ + + uint32_t FSMC_WaitSetupTime; /*!< Defines the minimum number of HCLK cycles to assert the + command for NAND-Flash read or write access to + common/Attribute or I/O memory space (depending on the + memory space timing to be configured). + This parameter can be a number between 0x00 and 0xFF */ + + uint32_t FSMC_HoldSetupTime; /*!< Defines the number of HCLK clock cycles to hold address + (and data for write access) after the command deassertion + for NAND-Flash read or write access to common/Attribute + or I/O memory space (depending on the memory space timing + to be configured). + This parameter can be a number between 0x00 and 0xFF */ + + uint32_t FSMC_HiZSetupTime; /*!< Defines the number of HCLK clock cycles during which the + databus is kept in HiZ after the start of a NAND-Flash + write access to common/Attribute or I/O memory space (depending + on the memory space timing to be configured). + This parameter can be a number between 0x00 and 0xFF */ +}FSMC_NAND_PCCARDTimingInitTypeDef; + +/** + * @brief FSMC NAND Init structure definition + */ + +typedef struct +{ + uint32_t FSMC_Bank; /*!< Specifies the NAND memory bank that will be used. + This parameter can be a value of @ref FSMC_NAND_Bank */ + + uint32_t FSMC_Waitfeature; /*!< Enables or disables the Wait feature for the NAND Memory Bank. + This parameter can be any value of @ref FSMC_Wait_feature */ + + uint32_t FSMC_MemoryDataWidth; /*!< Specifies the external memory device width. + This parameter can be any value of @ref FSMC_Data_Width */ + + uint32_t FSMC_ECC; /*!< Enables or disables the ECC computation. + This parameter can be any value of @ref FSMC_ECC */ + + uint32_t FSMC_ECCPageSize; /*!< Defines the page size for the extended ECC. + This parameter can be any value of @ref FSMC_ECC_Page_Size */ + + uint32_t FSMC_TCLRSetupTime; /*!< Defines the number of HCLK cycles to configure the + delay between CLE low and RE low. + This parameter can be a value between 0 and 0xFF. */ + + uint32_t FSMC_TARSetupTime; /*!< Defines the number of HCLK cycles to configure the + delay between ALE low and RE low. + This parameter can be a number between 0x0 and 0xFF */ + + FSMC_NAND_PCCARDTimingInitTypeDef* FSMC_CommonSpaceTimingStruct; /*!< FSMC Common Space Timing */ + + FSMC_NAND_PCCARDTimingInitTypeDef* FSMC_AttributeSpaceTimingStruct; /*!< FSMC Attribute Space Timing */ +}FSMC_NANDInitTypeDef; + +/** + * @brief FSMC PCCARD Init structure definition + */ + +typedef struct +{ + uint32_t FSMC_Waitfeature; /*!< Enables or disables the Wait feature for the Memory Bank. + This parameter can be any value of @ref FSMC_Wait_feature */ + + uint32_t FSMC_TCLRSetupTime; /*!< Defines the number of HCLK cycles to configure the + delay between CLE low and RE low. + This parameter can be a value between 0 and 0xFF. */ + + uint32_t FSMC_TARSetupTime; /*!< Defines the number of HCLK cycles to configure the + delay between ALE low and RE low. + This parameter can be a number between 0x0 and 0xFF */ + + + FSMC_NAND_PCCARDTimingInitTypeDef* FSMC_CommonSpaceTimingStruct; /*!< FSMC Common Space Timing */ + + FSMC_NAND_PCCARDTimingInitTypeDef* FSMC_AttributeSpaceTimingStruct; /*!< FSMC Attribute Space Timing */ + + FSMC_NAND_PCCARDTimingInitTypeDef* FSMC_IOSpaceTimingStruct; /*!< FSMC IO Space Timing */ +}FSMC_PCCARDInitTypeDef; + +/** + * @} + */ + +/** @defgroup FSMC_Exported_Constants + * @{ + */ + +/** @defgroup FSMC_NORSRAM_Bank + * @{ + */ +#define FSMC_Bank1_NORSRAM1 ((uint32_t)0x00000000) +#define FSMC_Bank1_NORSRAM2 ((uint32_t)0x00000002) +#define FSMC_Bank1_NORSRAM3 ((uint32_t)0x00000004) +#define FSMC_Bank1_NORSRAM4 ((uint32_t)0x00000006) +/** + * @} + */ + +/** @defgroup FSMC_NAND_Bank + * @{ + */ +#define FSMC_Bank2_NAND ((uint32_t)0x00000010) +#define FSMC_Bank3_NAND ((uint32_t)0x00000100) +/** + * @} + */ + +/** @defgroup FSMC_PCCARD_Bank + * @{ + */ +#define FSMC_Bank4_PCCARD ((uint32_t)0x00001000) +/** + * @} + */ + +#define IS_FSMC_NORSRAM_BANK(BANK) (((BANK) == FSMC_Bank1_NORSRAM1) || \ + ((BANK) == FSMC_Bank1_NORSRAM2) || \ + ((BANK) == FSMC_Bank1_NORSRAM3) || \ + ((BANK) == FSMC_Bank1_NORSRAM4)) + +#define IS_FSMC_NAND_BANK(BANK) (((BANK) == FSMC_Bank2_NAND) || \ + ((BANK) == FSMC_Bank3_NAND)) + +#define IS_FSMC_GETFLAG_BANK(BANK) (((BANK) == FSMC_Bank2_NAND) || \ + ((BANK) == FSMC_Bank3_NAND) || \ + ((BANK) == FSMC_Bank4_PCCARD)) + +#define IS_FSMC_IT_BANK(BANK) (((BANK) == FSMC_Bank2_NAND) || \ + ((BANK) == FSMC_Bank3_NAND) || \ + ((BANK) == FSMC_Bank4_PCCARD)) + +/** @defgroup NOR_SRAM_Controller + * @{ + */ + +/** @defgroup FSMC_Data_Address_Bus_Multiplexing + * @{ + */ + +#define FSMC_DataAddressMux_Disable ((uint32_t)0x00000000) +#define FSMC_DataAddressMux_Enable ((uint32_t)0x00000002) +#define IS_FSMC_MUX(MUX) (((MUX) == FSMC_DataAddressMux_Disable) || \ + ((MUX) == FSMC_DataAddressMux_Enable)) + +/** + * @} + */ + +/** @defgroup FSMC_Memory_Type + * @{ + */ + +#define FSMC_MemoryType_SRAM ((uint32_t)0x00000000) +#define FSMC_MemoryType_PSRAM ((uint32_t)0x00000004) +#define FSMC_MemoryType_NOR ((uint32_t)0x00000008) +#define IS_FSMC_MEMORY(MEMORY) (((MEMORY) == FSMC_MemoryType_SRAM) || \ + ((MEMORY) == FSMC_MemoryType_PSRAM)|| \ + ((MEMORY) == FSMC_MemoryType_NOR)) + +/** + * @} + */ + +/** @defgroup FSMC_Data_Width + * @{ + */ + +#define FSMC_MemoryDataWidth_8b ((uint32_t)0x00000000) +#define FSMC_MemoryDataWidth_16b ((uint32_t)0x00000010) +#define IS_FSMC_MEMORY_WIDTH(WIDTH) (((WIDTH) == FSMC_MemoryDataWidth_8b) || \ + ((WIDTH) == FSMC_MemoryDataWidth_16b)) + +/** + * @} + */ + +/** @defgroup FSMC_Burst_Access_Mode + * @{ + */ + +#define FSMC_BurstAccessMode_Disable ((uint32_t)0x00000000) +#define FSMC_BurstAccessMode_Enable ((uint32_t)0x00000100) +#define IS_FSMC_BURSTMODE(STATE) (((STATE) == FSMC_BurstAccessMode_Disable) || \ + ((STATE) == FSMC_BurstAccessMode_Enable)) +/** + * @} + */ + +/** @defgroup FSMC_AsynchronousWait + * @{ + */ +#define FSMC_AsynchronousWait_Disable ((uint32_t)0x00000000) +#define FSMC_AsynchronousWait_Enable ((uint32_t)0x00008000) +#define IS_FSMC_ASYNWAIT(STATE) (((STATE) == FSMC_AsynchronousWait_Disable) || \ + ((STATE) == FSMC_AsynchronousWait_Enable)) + +/** + * @} + */ + +/** @defgroup FSMC_Wait_Signal_Polarity + * @{ + */ + +#define FSMC_WaitSignalPolarity_Low ((uint32_t)0x00000000) +#define FSMC_WaitSignalPolarity_High ((uint32_t)0x00000200) +#define IS_FSMC_WAIT_POLARITY(POLARITY) (((POLARITY) == FSMC_WaitSignalPolarity_Low) || \ + ((POLARITY) == FSMC_WaitSignalPolarity_High)) + +/** + * @} + */ + +/** @defgroup FSMC_Wrap_Mode + * @{ + */ + +#define FSMC_WrapMode_Disable ((uint32_t)0x00000000) +#define FSMC_WrapMode_Enable ((uint32_t)0x00000400) +#define IS_FSMC_WRAP_MODE(MODE) (((MODE) == FSMC_WrapMode_Disable) || \ + ((MODE) == FSMC_WrapMode_Enable)) + +/** + * @} + */ + +/** @defgroup FSMC_Wait_Timing + * @{ + */ + +#define FSMC_WaitSignalActive_BeforeWaitState ((uint32_t)0x00000000) +#define FSMC_WaitSignalActive_DuringWaitState ((uint32_t)0x00000800) +#define IS_FSMC_WAIT_SIGNAL_ACTIVE(ACTIVE) (((ACTIVE) == FSMC_WaitSignalActive_BeforeWaitState) || \ + ((ACTIVE) == FSMC_WaitSignalActive_DuringWaitState)) + +/** + * @} + */ + +/** @defgroup FSMC_Write_Operation + * @{ + */ + +#define FSMC_WriteOperation_Disable ((uint32_t)0x00000000) +#define FSMC_WriteOperation_Enable ((uint32_t)0x00001000) +#define IS_FSMC_WRITE_OPERATION(OPERATION) (((OPERATION) == FSMC_WriteOperation_Disable) || \ + ((OPERATION) == FSMC_WriteOperation_Enable)) + +/** + * @} + */ + +/** @defgroup FSMC_Wait_Signal + * @{ + */ + +#define FSMC_WaitSignal_Disable ((uint32_t)0x00000000) +#define FSMC_WaitSignal_Enable ((uint32_t)0x00002000) +#define IS_FSMC_WAITE_SIGNAL(SIGNAL) (((SIGNAL) == FSMC_WaitSignal_Disable) || \ + ((SIGNAL) == FSMC_WaitSignal_Enable)) +/** + * @} + */ + +/** @defgroup FSMC_Extended_Mode + * @{ + */ + +#define FSMC_ExtendedMode_Disable ((uint32_t)0x00000000) +#define FSMC_ExtendedMode_Enable ((uint32_t)0x00004000) + +#define IS_FSMC_EXTENDED_MODE(MODE) (((MODE) == FSMC_ExtendedMode_Disable) || \ + ((MODE) == FSMC_ExtendedMode_Enable)) + +/** + * @} + */ + +/** @defgroup FSMC_Write_Burst + * @{ + */ + +#define FSMC_WriteBurst_Disable ((uint32_t)0x00000000) +#define FSMC_WriteBurst_Enable ((uint32_t)0x00080000) +#define IS_FSMC_WRITE_BURST(BURST) (((BURST) == FSMC_WriteBurst_Disable) || \ + ((BURST) == FSMC_WriteBurst_Enable)) +/** + * @} + */ + +/** @defgroup FSMC_Address_Setup_Time + * @{ + */ + +#define IS_FSMC_ADDRESS_SETUP_TIME(TIME) ((TIME) <= 0xF) + +/** + * @} + */ + +/** @defgroup FSMC_Address_Hold_Time + * @{ + */ + +#define IS_FSMC_ADDRESS_HOLD_TIME(TIME) ((TIME) <= 0xF) + +/** + * @} + */ + +/** @defgroup FSMC_Data_Setup_Time + * @{ + */ + +#define IS_FSMC_DATASETUP_TIME(TIME) (((TIME) > 0) && ((TIME) <= 0xFF)) + +/** + * @} + */ + +/** @defgroup FSMC_Bus_Turn_around_Duration + * @{ + */ + +#define IS_FSMC_TURNAROUND_TIME(TIME) ((TIME) <= 0xF) + +/** + * @} + */ + +/** @defgroup FSMC_CLK_Division + * @{ + */ + +#define IS_FSMC_CLK_DIV(DIV) ((DIV) <= 0xF) + +/** + * @} + */ + +/** @defgroup FSMC_Data_Latency + * @{ + */ + +#define IS_FSMC_DATA_LATENCY(LATENCY) ((LATENCY) <= 0xF) + +/** + * @} + */ + +/** @defgroup FSMC_Access_Mode + * @{ + */ + +#define FSMC_AccessMode_A ((uint32_t)0x00000000) +#define FSMC_AccessMode_B ((uint32_t)0x10000000) +#define FSMC_AccessMode_C ((uint32_t)0x20000000) +#define FSMC_AccessMode_D ((uint32_t)0x30000000) +#define IS_FSMC_ACCESS_MODE(MODE) (((MODE) == FSMC_AccessMode_A) || \ + ((MODE) == FSMC_AccessMode_B) || \ + ((MODE) == FSMC_AccessMode_C) || \ + ((MODE) == FSMC_AccessMode_D)) + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup NAND_PCCARD_Controller + * @{ + */ + +/** @defgroup FSMC_Wait_feature + * @{ + */ + +#define FSMC_Waitfeature_Disable ((uint32_t)0x00000000) +#define FSMC_Waitfeature_Enable ((uint32_t)0x00000002) +#define IS_FSMC_WAIT_FEATURE(FEATURE) (((FEATURE) == FSMC_Waitfeature_Disable) || \ + ((FEATURE) == FSMC_Waitfeature_Enable)) + +/** + * @} + */ + + +/** @defgroup FSMC_ECC + * @{ + */ + +#define FSMC_ECC_Disable ((uint32_t)0x00000000) +#define FSMC_ECC_Enable ((uint32_t)0x00000040) +#define IS_FSMC_ECC_STATE(STATE) (((STATE) == FSMC_ECC_Disable) || \ + ((STATE) == FSMC_ECC_Enable)) + +/** + * @} + */ + +/** @defgroup FSMC_ECC_Page_Size + * @{ + */ + +#define FSMC_ECCPageSize_256Bytes ((uint32_t)0x00000000) +#define FSMC_ECCPageSize_512Bytes ((uint32_t)0x00020000) +#define FSMC_ECCPageSize_1024Bytes ((uint32_t)0x00040000) +#define FSMC_ECCPageSize_2048Bytes ((uint32_t)0x00060000) +#define FSMC_ECCPageSize_4096Bytes ((uint32_t)0x00080000) +#define FSMC_ECCPageSize_8192Bytes ((uint32_t)0x000A0000) +#define IS_FSMC_ECCPAGE_SIZE(SIZE) (((SIZE) == FSMC_ECCPageSize_256Bytes) || \ + ((SIZE) == FSMC_ECCPageSize_512Bytes) || \ + ((SIZE) == FSMC_ECCPageSize_1024Bytes) || \ + ((SIZE) == FSMC_ECCPageSize_2048Bytes) || \ + ((SIZE) == FSMC_ECCPageSize_4096Bytes) || \ + ((SIZE) == FSMC_ECCPageSize_8192Bytes)) + +/** + * @} + */ + +/** @defgroup FSMC_TCLR_Setup_Time + * @{ + */ + +#define IS_FSMC_TCLR_TIME(TIME) ((TIME) <= 0xFF) + +/** + * @} + */ + +/** @defgroup FSMC_TAR_Setup_Time + * @{ + */ + +#define IS_FSMC_TAR_TIME(TIME) ((TIME) <= 0xFF) + +/** + * @} + */ + +/** @defgroup FSMC_Setup_Time + * @{ + */ + +#define IS_FSMC_SETUP_TIME(TIME) ((TIME) <= 0xFF) + +/** + * @} + */ + +/** @defgroup FSMC_Wait_Setup_Time + * @{ + */ + +#define IS_FSMC_WAIT_TIME(TIME) ((TIME) <= 0xFF) + +/** + * @} + */ + +/** @defgroup FSMC_Hold_Setup_Time + * @{ + */ + +#define IS_FSMC_HOLD_TIME(TIME) ((TIME) <= 0xFF) + +/** + * @} + */ + +/** @defgroup FSMC_HiZ_Setup_Time + * @{ + */ + +#define IS_FSMC_HIZ_TIME(TIME) ((TIME) <= 0xFF) + +/** + * @} + */ + +/** @defgroup FSMC_Interrupt_sources + * @{ + */ + +#define FSMC_IT_RisingEdge ((uint32_t)0x00000008) +#define FSMC_IT_Level ((uint32_t)0x00000010) +#define FSMC_IT_FallingEdge ((uint32_t)0x00000020) +#define IS_FSMC_IT(IT) ((((IT) & (uint32_t)0xFFFFFFC7) == 0x00000000) && ((IT) != 0x00000000)) +#define IS_FSMC_GET_IT(IT) (((IT) == FSMC_IT_RisingEdge) || \ + ((IT) == FSMC_IT_Level) || \ + ((IT) == FSMC_IT_FallingEdge)) +/** + * @} + */ + +/** @defgroup FSMC_Flags + * @{ + */ + +#define FSMC_FLAG_RisingEdge ((uint32_t)0x00000001) +#define FSMC_FLAG_Level ((uint32_t)0x00000002) +#define FSMC_FLAG_FallingEdge ((uint32_t)0x00000004) +#define FSMC_FLAG_FEMPT ((uint32_t)0x00000040) +#define IS_FSMC_GET_FLAG(FLAG) (((FLAG) == FSMC_FLAG_RisingEdge) || \ + ((FLAG) == FSMC_FLAG_Level) || \ + ((FLAG) == FSMC_FLAG_FallingEdge) || \ + ((FLAG) == FSMC_FLAG_FEMPT)) + +#define IS_FSMC_CLEAR_FLAG(FLAG) ((((FLAG) & (uint32_t)0xFFFFFFF8) == 0x00000000) && ((FLAG) != 0x00000000)) + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup FSMC_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup FSMC_Exported_Functions + * @{ + */ + +void FSMC_NORSRAMDeInit(uint32_t FSMC_Bank); +void FSMC_NANDDeInit(uint32_t FSMC_Bank); +void FSMC_PCCARDDeInit(void); +void FSMC_NORSRAMInit(FSMC_NORSRAMInitTypeDef* FSMC_NORSRAMInitStruct); +void FSMC_NANDInit(FSMC_NANDInitTypeDef* FSMC_NANDInitStruct); +void FSMC_PCCARDInit(FSMC_PCCARDInitTypeDef* FSMC_PCCARDInitStruct); +void FSMC_NORSRAMStructInit(FSMC_NORSRAMInitTypeDef* FSMC_NORSRAMInitStruct); +void FSMC_NANDStructInit(FSMC_NANDInitTypeDef* FSMC_NANDInitStruct); +void FSMC_PCCARDStructInit(FSMC_PCCARDInitTypeDef* FSMC_PCCARDInitStruct); +void FSMC_NORSRAMCmd(uint32_t FSMC_Bank, FunctionalState NewState); +void FSMC_NANDCmd(uint32_t FSMC_Bank, FunctionalState NewState); +void FSMC_PCCARDCmd(FunctionalState NewState); +void FSMC_NANDECCCmd(uint32_t FSMC_Bank, FunctionalState NewState); +uint32_t FSMC_GetECC(uint32_t FSMC_Bank); +void FSMC_ITConfig(uint32_t FSMC_Bank, uint32_t FSMC_IT, FunctionalState NewState); +FlagStatus FSMC_GetFlagStatus(uint32_t FSMC_Bank, uint32_t FSMC_FLAG); +void FSMC_ClearFlag(uint32_t FSMC_Bank, uint32_t FSMC_FLAG); +ITStatus FSMC_GetITStatus(uint32_t FSMC_Bank, uint32_t FSMC_IT); +void FSMC_ClearITPendingBit(uint32_t FSMC_Bank, uint32_t FSMC_IT); + +#ifdef __cplusplus +} +#endif + +#endif /*__STM32F10x_FSMC_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_gpio.c b/Library/stm32f10x_gpio.c new file mode 100644 index 0000000..457ff11 --- /dev/null +++ b/Library/stm32f10x_gpio.c @@ -0,0 +1,650 @@ +/** + ****************************************************************************** + * @file stm32f10x_gpio.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the GPIO firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_gpio.h" +#include "stm32f10x_rcc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup GPIO + * @brief GPIO driver modules + * @{ + */ + +/** @defgroup GPIO_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup GPIO_Private_Defines + * @{ + */ + +/* ------------ RCC registers bit address in the alias region ----------------*/ +#define AFIO_OFFSET (AFIO_BASE - PERIPH_BASE) + +/* --- EVENTCR Register -----*/ + +/* Alias word address of EVOE bit */ +#define EVCR_OFFSET (AFIO_OFFSET + 0x00) +#define EVOE_BitNumber ((uint8_t)0x07) +#define EVCR_EVOE_BB (PERIPH_BB_BASE + (EVCR_OFFSET * 32) + (EVOE_BitNumber * 4)) + + +/* --- MAPR Register ---*/ +/* Alias word address of MII_RMII_SEL bit */ +#define MAPR_OFFSET (AFIO_OFFSET + 0x04) +#define MII_RMII_SEL_BitNumber ((u8)0x17) +#define MAPR_MII_RMII_SEL_BB (PERIPH_BB_BASE + (MAPR_OFFSET * 32) + (MII_RMII_SEL_BitNumber * 4)) + + +#define EVCR_PORTPINCONFIG_MASK ((uint16_t)0xFF80) +#define LSB_MASK ((uint16_t)0xFFFF) +#define DBGAFR_POSITION_MASK ((uint32_t)0x000F0000) +#define DBGAFR_SWJCFG_MASK ((uint32_t)0xF0FFFFFF) +#define DBGAFR_LOCATION_MASK ((uint32_t)0x00200000) +#define DBGAFR_NUMBITS_MASK ((uint32_t)0x00100000) +/** + * @} + */ + +/** @defgroup GPIO_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup GPIO_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup GPIO_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup GPIO_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the GPIOx peripheral registers to their default reset values. + * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. + * @retval None + */ +void GPIO_DeInit(GPIO_TypeDef* GPIOx) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + if (GPIOx == GPIOA) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, DISABLE); + } + else if (GPIOx == GPIOB) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, DISABLE); + } + else if (GPIOx == GPIOC) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, DISABLE); + } + else if (GPIOx == GPIOD) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOD, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOD, DISABLE); + } + else if (GPIOx == GPIOE) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOE, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOE, DISABLE); + } + else if (GPIOx == GPIOF) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOF, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOF, DISABLE); + } + else + { + if (GPIOx == GPIOG) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOG, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOG, DISABLE); + } + } +} + +/** + * @brief Deinitializes the Alternate Functions (remap, event control + * and EXTI configuration) registers to their default reset values. + * @param None + * @retval None + */ +void GPIO_AFIODeInit(void) +{ + RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, DISABLE); +} + +/** + * @brief Initializes the GPIOx peripheral according to the specified + * parameters in the GPIO_InitStruct. + * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. + * @param GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that + * contains the configuration information for the specified GPIO peripheral. + * @retval None + */ +void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) +{ + uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00; + uint32_t tmpreg = 0x00, pinmask = 0x00; + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode)); + assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin)); + +/*---------------------------- GPIO Mode Configuration -----------------------*/ + currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F); + if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00) + { + /* Check the parameters */ + assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed)); + /* Output mode */ + currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed; + } +/*---------------------------- GPIO CRL Configuration ------------------------*/ + /* Configure the eight low port pins */ + if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00) + { + tmpreg = GPIOx->CRL; + for (pinpos = 0x00; pinpos < 0x08; pinpos++) + { + pos = ((uint32_t)0x01) << pinpos; + /* Get the port pins position */ + currentpin = (GPIO_InitStruct->GPIO_Pin) & pos; + if (currentpin == pos) + { + pos = pinpos << 2; + /* Clear the corresponding low control register bits */ + pinmask = ((uint32_t)0x0F) << pos; + tmpreg &= ~pinmask; + /* Write the mode configuration in the corresponding bits */ + tmpreg |= (currentmode << pos); + /* Reset the corresponding ODR bit */ + if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) + { + GPIOx->BRR = (((uint32_t)0x01) << pinpos); + } + else + { + /* Set the corresponding ODR bit */ + if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU) + { + GPIOx->BSRR = (((uint32_t)0x01) << pinpos); + } + } + } + } + GPIOx->CRL = tmpreg; + } +/*---------------------------- GPIO CRH Configuration ------------------------*/ + /* Configure the eight high port pins */ + if (GPIO_InitStruct->GPIO_Pin > 0x00FF) + { + tmpreg = GPIOx->CRH; + for (pinpos = 0x00; pinpos < 0x08; pinpos++) + { + pos = (((uint32_t)0x01) << (pinpos + 0x08)); + /* Get the port pins position */ + currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos); + if (currentpin == pos) + { + pos = pinpos << 2; + /* Clear the corresponding high control register bits */ + pinmask = ((uint32_t)0x0F) << pos; + tmpreg &= ~pinmask; + /* Write the mode configuration in the corresponding bits */ + tmpreg |= (currentmode << pos); + /* Reset the corresponding ODR bit */ + if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) + { + GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08)); + } + /* Set the corresponding ODR bit */ + if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU) + { + GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08)); + } + } + } + GPIOx->CRH = tmpreg; + } +} + +/** + * @brief Fills each GPIO_InitStruct member with its default value. + * @param GPIO_InitStruct : pointer to a GPIO_InitTypeDef structure which will + * be initialized. + * @retval None + */ +void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct) +{ + /* Reset GPIO init structure parameters values */ + GPIO_InitStruct->GPIO_Pin = GPIO_Pin_All; + GPIO_InitStruct->GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStruct->GPIO_Mode = GPIO_Mode_IN_FLOATING; +} + +/** + * @brief Reads the specified input port pin. + * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. + * @param GPIO_Pin: specifies the port bit to read. + * This parameter can be GPIO_Pin_x where x can be (0..15). + * @retval The input port pin value. + */ +uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + uint8_t bitstatus = 0x00; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GET_GPIO_PIN(GPIO_Pin)); + + if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET) + { + bitstatus = (uint8_t)Bit_SET; + } + else + { + bitstatus = (uint8_t)Bit_RESET; + } + return bitstatus; +} + +/** + * @brief Reads the specified GPIO input data port. + * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. + * @retval GPIO input data port value. + */ +uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + return ((uint16_t)GPIOx->IDR); +} + +/** + * @brief Reads the specified output data port bit. + * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. + * @param GPIO_Pin: specifies the port bit to read. + * This parameter can be GPIO_Pin_x where x can be (0..15). + * @retval The output port pin value. + */ +uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + uint8_t bitstatus = 0x00; + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GET_GPIO_PIN(GPIO_Pin)); + + if ((GPIOx->ODR & GPIO_Pin) != (uint32_t)Bit_RESET) + { + bitstatus = (uint8_t)Bit_SET; + } + else + { + bitstatus = (uint8_t)Bit_RESET; + } + return bitstatus; +} + +/** + * @brief Reads the specified GPIO output data port. + * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. + * @retval GPIO output data port value. + */ +uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + return ((uint16_t)GPIOx->ODR); +} + +/** + * @brief Sets the selected data port bits. + * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. + * @param GPIO_Pin: specifies the port bits to be written. + * This parameter can be any combination of GPIO_Pin_x where x can be (0..15). + * @retval None + */ +void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GPIO_PIN(GPIO_Pin)); + + GPIOx->BSRR = GPIO_Pin; +} + +/** + * @brief Clears the selected data port bits. + * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. + * @param GPIO_Pin: specifies the port bits to be written. + * This parameter can be any combination of GPIO_Pin_x where x can be (0..15). + * @retval None + */ +void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GPIO_PIN(GPIO_Pin)); + + GPIOx->BRR = GPIO_Pin; +} + +/** + * @brief Sets or clears the selected data port bit. + * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. + * @param GPIO_Pin: specifies the port bit to be written. + * This parameter can be one of GPIO_Pin_x where x can be (0..15). + * @param BitVal: specifies the value to be written to the selected bit. + * This parameter can be one of the BitAction enum values: + * @arg Bit_RESET: to clear the port pin + * @arg Bit_SET: to set the port pin + * @retval None + */ +void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GET_GPIO_PIN(GPIO_Pin)); + assert_param(IS_GPIO_BIT_ACTION(BitVal)); + + if (BitVal != Bit_RESET) + { + GPIOx->BSRR = GPIO_Pin; + } + else + { + GPIOx->BRR = GPIO_Pin; + } +} + +/** + * @brief Writes data to the specified GPIO data port. + * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. + * @param PortVal: specifies the value to be written to the port output data register. + * @retval None + */ +void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + GPIOx->ODR = PortVal; +} + +/** + * @brief Locks GPIO Pins configuration registers. + * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. + * @param GPIO_Pin: specifies the port bit to be written. + * This parameter can be any combination of GPIO_Pin_x where x can be (0..15). + * @retval None + */ +void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + uint32_t tmp = 0x00010000; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GPIO_PIN(GPIO_Pin)); + + tmp |= GPIO_Pin; + /* Set LCKK bit */ + GPIOx->LCKR = tmp; + /* Reset LCKK bit */ + GPIOx->LCKR = GPIO_Pin; + /* Set LCKK bit */ + GPIOx->LCKR = tmp; + /* Read LCKK bit*/ + tmp = GPIOx->LCKR; + /* Read LCKK bit*/ + tmp = GPIOx->LCKR; +} + +/** + * @brief Selects the GPIO pin used as Event output. + * @param GPIO_PortSource: selects the GPIO port to be used as source + * for Event output. + * This parameter can be GPIO_PortSourceGPIOx where x can be (A..E). + * @param GPIO_PinSource: specifies the pin for the Event output. + * This parameter can be GPIO_PinSourcex where x can be (0..15). + * @retval None + */ +void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) +{ + uint32_t tmpreg = 0x00; + /* Check the parameters */ + assert_param(IS_GPIO_EVENTOUT_PORT_SOURCE(GPIO_PortSource)); + assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource)); + + tmpreg = AFIO->EVCR; + /* Clear the PORT[6:4] and PIN[3:0] bits */ + tmpreg &= EVCR_PORTPINCONFIG_MASK; + tmpreg |= (uint32_t)GPIO_PortSource << 0x04; + tmpreg |= GPIO_PinSource; + AFIO->EVCR = tmpreg; +} + +/** + * @brief Enables or disables the Event Output. + * @param NewState: new state of the Event output. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void GPIO_EventOutputCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) EVCR_EVOE_BB = (uint32_t)NewState; +} + +/** + * @brief Changes the mapping of the specified pin. + * @param GPIO_Remap: selects the pin to remap. + * This parameter can be one of the following values: + * @arg GPIO_Remap_SPI1 : SPI1 Alternate Function mapping + * @arg GPIO_Remap_I2C1 : I2C1 Alternate Function mapping + * @arg GPIO_Remap_USART1 : USART1 Alternate Function mapping + * @arg GPIO_Remap_USART2 : USART2 Alternate Function mapping + * @arg GPIO_PartialRemap_USART3 : USART3 Partial Alternate Function mapping + * @arg GPIO_FullRemap_USART3 : USART3 Full Alternate Function mapping + * @arg GPIO_PartialRemap_TIM1 : TIM1 Partial Alternate Function mapping + * @arg GPIO_FullRemap_TIM1 : TIM1 Full Alternate Function mapping + * @arg GPIO_PartialRemap1_TIM2 : TIM2 Partial1 Alternate Function mapping + * @arg GPIO_PartialRemap2_TIM2 : TIM2 Partial2 Alternate Function mapping + * @arg GPIO_FullRemap_TIM2 : TIM2 Full Alternate Function mapping + * @arg GPIO_PartialRemap_TIM3 : TIM3 Partial Alternate Function mapping + * @arg GPIO_FullRemap_TIM3 : TIM3 Full Alternate Function mapping + * @arg GPIO_Remap_TIM4 : TIM4 Alternate Function mapping + * @arg GPIO_Remap1_CAN1 : CAN1 Alternate Function mapping + * @arg GPIO_Remap2_CAN1 : CAN1 Alternate Function mapping + * @arg GPIO_Remap_PD01 : PD01 Alternate Function mapping + * @arg GPIO_Remap_TIM5CH4_LSI : LSI connected to TIM5 Channel4 input capture for calibration + * @arg GPIO_Remap_ADC1_ETRGINJ : ADC1 External Trigger Injected Conversion remapping + * @arg GPIO_Remap_ADC1_ETRGREG : ADC1 External Trigger Regular Conversion remapping + * @arg GPIO_Remap_ADC2_ETRGINJ : ADC2 External Trigger Injected Conversion remapping + * @arg GPIO_Remap_ADC2_ETRGREG : ADC2 External Trigger Regular Conversion remapping + * @arg GPIO_Remap_ETH : Ethernet remapping (only for Connectivity line devices) + * @arg GPIO_Remap_CAN2 : CAN2 remapping (only for Connectivity line devices) + * @arg GPIO_Remap_SWJ_NoJTRST : Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST + * @arg GPIO_Remap_SWJ_JTAGDisable : JTAG-DP Disabled and SW-DP Enabled + * @arg GPIO_Remap_SWJ_Disable : Full SWJ Disabled (JTAG-DP + SW-DP) + * @arg GPIO_Remap_SPI3 : SPI3/I2S3 Alternate Function mapping (only for Connectivity line devices) + * When the SPI3/I2S3 is remapped using this function, the SWJ is configured + * to Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST. + * @arg GPIO_Remap_TIM2ITR1_PTP_SOF : Ethernet PTP output or USB OTG SOF (Start of Frame) connected + * to TIM2 Internal Trigger 1 for calibration (only for Connectivity line devices) + * If the GPIO_Remap_TIM2ITR1_PTP_SOF is enabled the TIM2 ITR1 is connected to + * Ethernet PTP output. When Reset TIM2 ITR1 is connected to USB OTG SOF output. + * @arg GPIO_Remap_PTP_PPS : Ethernet MAC PPS_PTS output on PB05 (only for Connectivity line devices) + * @arg GPIO_Remap_TIM15 : TIM15 Alternate Function mapping (only for Value line devices) + * @arg GPIO_Remap_TIM16 : TIM16 Alternate Function mapping (only for Value line devices) + * @arg GPIO_Remap_TIM17 : TIM17 Alternate Function mapping (only for Value line devices) + * @arg GPIO_Remap_CEC : CEC Alternate Function mapping (only for Value line devices) + * @arg GPIO_Remap_TIM1_DMA : TIM1 DMA requests mapping (only for Value line devices) + * @arg GPIO_Remap_TIM9 : TIM9 Alternate Function mapping (only for XL-density devices) + * @arg GPIO_Remap_TIM10 : TIM10 Alternate Function mapping (only for XL-density devices) + * @arg GPIO_Remap_TIM11 : TIM11 Alternate Function mapping (only for XL-density devices) + * @arg GPIO_Remap_TIM13 : TIM13 Alternate Function mapping (only for High density Value line and XL-density devices) + * @arg GPIO_Remap_TIM14 : TIM14 Alternate Function mapping (only for High density Value line and XL-density devices) + * @arg GPIO_Remap_FSMC_NADV : FSMC_NADV Alternate Function mapping (only for High density Value line and XL-density devices) + * @arg GPIO_Remap_TIM67_DAC_DMA : TIM6/TIM7 and DAC DMA requests remapping (only for High density Value line devices) + * @arg GPIO_Remap_TIM12 : TIM12 Alternate Function mapping (only for High density Value line devices) + * @arg GPIO_Remap_MISC : Miscellaneous Remap (DMA2 Channel5 Position and DAC Trigger remapping, + * only for High density Value line devices) + * @param NewState: new state of the port pin remapping. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState) +{ + uint32_t tmp = 0x00, tmp1 = 0x00, tmpreg = 0x00, tmpmask = 0x00; + + /* Check the parameters */ + assert_param(IS_GPIO_REMAP(GPIO_Remap)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if((GPIO_Remap & 0x80000000) == 0x80000000) + { + tmpreg = AFIO->MAPR2; + } + else + { + tmpreg = AFIO->MAPR; + } + + tmpmask = (GPIO_Remap & DBGAFR_POSITION_MASK) >> 0x10; + tmp = GPIO_Remap & LSB_MASK; + + if ((GPIO_Remap & (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) == (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) + { + tmpreg &= DBGAFR_SWJCFG_MASK; + AFIO->MAPR &= DBGAFR_SWJCFG_MASK; + } + else if ((GPIO_Remap & DBGAFR_NUMBITS_MASK) == DBGAFR_NUMBITS_MASK) + { + tmp1 = ((uint32_t)0x03) << tmpmask; + tmpreg &= ~tmp1; + tmpreg |= ~DBGAFR_SWJCFG_MASK; + } + else + { + tmpreg &= ~(tmp << ((GPIO_Remap >> 0x15)*0x10)); + tmpreg |= ~DBGAFR_SWJCFG_MASK; + } + + if (NewState != DISABLE) + { + tmpreg |= (tmp << ((GPIO_Remap >> 0x15)*0x10)); + } + + if((GPIO_Remap & 0x80000000) == 0x80000000) + { + AFIO->MAPR2 = tmpreg; + } + else + { + AFIO->MAPR = tmpreg; + } +} + +/** + * @brief Selects the GPIO pin used as EXTI Line. + * @param GPIO_PortSource: selects the GPIO port to be used as source for EXTI lines. + * This parameter can be GPIO_PortSourceGPIOx where x can be (A..G). + * @param GPIO_PinSource: specifies the EXTI line to be configured. + * This parameter can be GPIO_PinSourcex where x can be (0..15). + * @retval None + */ +void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) +{ + uint32_t tmp = 0x00; + /* Check the parameters */ + assert_param(IS_GPIO_EXTI_PORT_SOURCE(GPIO_PortSource)); + assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource)); + + tmp = ((uint32_t)0x0F) << (0x04 * (GPIO_PinSource & (uint8_t)0x03)); + AFIO->EXTICR[GPIO_PinSource >> 0x02] &= ~tmp; + AFIO->EXTICR[GPIO_PinSource >> 0x02] |= (((uint32_t)GPIO_PortSource) << (0x04 * (GPIO_PinSource & (uint8_t)0x03))); +} + +/** + * @brief Selects the Ethernet media interface. + * @note This function applies only to STM32 Connectivity line devices. + * @param GPIO_ETH_MediaInterface: specifies the Media Interface mode. + * This parameter can be one of the following values: + * @arg GPIO_ETH_MediaInterface_MII: MII mode + * @arg GPIO_ETH_MediaInterface_RMII: RMII mode + * @retval None + */ +void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface) +{ + assert_param(IS_GPIO_ETH_MEDIA_INTERFACE(GPIO_ETH_MediaInterface)); + + /* Configure MII_RMII selection bit */ + *(__IO uint32_t *) MAPR_MII_RMII_SEL_BB = GPIO_ETH_MediaInterface; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_gpio.h b/Library/stm32f10x_gpio.h new file mode 100644 index 0000000..dd28da8 --- /dev/null +++ b/Library/stm32f10x_gpio.h @@ -0,0 +1,385 @@ +/** + ****************************************************************************** + * @file stm32f10x_gpio.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the GPIO + * firmware library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_GPIO_H +#define __STM32F10x_GPIO_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup GPIO + * @{ + */ + +/** @defgroup GPIO_Exported_Types + * @{ + */ + +#define IS_GPIO_ALL_PERIPH(PERIPH) (((PERIPH) == GPIOA) || \ + ((PERIPH) == GPIOB) || \ + ((PERIPH) == GPIOC) || \ + ((PERIPH) == GPIOD) || \ + ((PERIPH) == GPIOE) || \ + ((PERIPH) == GPIOF) || \ + ((PERIPH) == GPIOG)) + +/** + * @brief Output Maximum frequency selection + */ + +typedef enum +{ + GPIO_Speed_10MHz = 1, + GPIO_Speed_2MHz, + GPIO_Speed_50MHz +}GPIOSpeed_TypeDef; +#define IS_GPIO_SPEED(SPEED) (((SPEED) == GPIO_Speed_10MHz) || ((SPEED) == GPIO_Speed_2MHz) || \ + ((SPEED) == GPIO_Speed_50MHz)) + +/** + * @brief Configuration Mode enumeration + */ + +typedef enum +{ GPIO_Mode_AIN = 0x0, + GPIO_Mode_IN_FLOATING = 0x04, + GPIO_Mode_IPD = 0x28, + GPIO_Mode_IPU = 0x48, + GPIO_Mode_Out_OD = 0x14, + GPIO_Mode_Out_PP = 0x10, + GPIO_Mode_AF_OD = 0x1C, + GPIO_Mode_AF_PP = 0x18 +}GPIOMode_TypeDef; + +#define IS_GPIO_MODE(MODE) (((MODE) == GPIO_Mode_AIN) || ((MODE) == GPIO_Mode_IN_FLOATING) || \ + ((MODE) == GPIO_Mode_IPD) || ((MODE) == GPIO_Mode_IPU) || \ + ((MODE) == GPIO_Mode_Out_OD) || ((MODE) == GPIO_Mode_Out_PP) || \ + ((MODE) == GPIO_Mode_AF_OD) || ((MODE) == GPIO_Mode_AF_PP)) + +/** + * @brief GPIO Init structure definition + */ + +typedef struct +{ + uint16_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured. + This parameter can be any value of @ref GPIO_pins_define */ + + GPIOSpeed_TypeDef GPIO_Speed; /*!< Specifies the speed for the selected pins. + This parameter can be a value of @ref GPIOSpeed_TypeDef */ + + GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins. + This parameter can be a value of @ref GPIOMode_TypeDef */ +}GPIO_InitTypeDef; + + +/** + * @brief Bit_SET and Bit_RESET enumeration + */ + +typedef enum +{ Bit_RESET = 0, + Bit_SET +}BitAction; + +#define IS_GPIO_BIT_ACTION(ACTION) (((ACTION) == Bit_RESET) || ((ACTION) == Bit_SET)) + +/** + * @} + */ + +/** @defgroup GPIO_Exported_Constants + * @{ + */ + +/** @defgroup GPIO_pins_define + * @{ + */ + +#define GPIO_Pin_0 ((uint16_t)0x0001) /*!< Pin 0 selected */ +#define GPIO_Pin_1 ((uint16_t)0x0002) /*!< Pin 1 selected */ +#define GPIO_Pin_2 ((uint16_t)0x0004) /*!< Pin 2 selected */ +#define GPIO_Pin_3 ((uint16_t)0x0008) /*!< Pin 3 selected */ +#define GPIO_Pin_4 ((uint16_t)0x0010) /*!< Pin 4 selected */ +#define GPIO_Pin_5 ((uint16_t)0x0020) /*!< Pin 5 selected */ +#define GPIO_Pin_6 ((uint16_t)0x0040) /*!< Pin 6 selected */ +#define GPIO_Pin_7 ((uint16_t)0x0080) /*!< Pin 7 selected */ +#define GPIO_Pin_8 ((uint16_t)0x0100) /*!< Pin 8 selected */ +#define GPIO_Pin_9 ((uint16_t)0x0200) /*!< Pin 9 selected */ +#define GPIO_Pin_10 ((uint16_t)0x0400) /*!< Pin 10 selected */ +#define GPIO_Pin_11 ((uint16_t)0x0800) /*!< Pin 11 selected */ +#define GPIO_Pin_12 ((uint16_t)0x1000) /*!< Pin 12 selected */ +#define GPIO_Pin_13 ((uint16_t)0x2000) /*!< Pin 13 selected */ +#define GPIO_Pin_14 ((uint16_t)0x4000) /*!< Pin 14 selected */ +#define GPIO_Pin_15 ((uint16_t)0x8000) /*!< Pin 15 selected */ +#define GPIO_Pin_All ((uint16_t)0xFFFF) /*!< All pins selected */ + +#define IS_GPIO_PIN(PIN) ((((PIN) & (uint16_t)0x00) == 0x00) && ((PIN) != (uint16_t)0x00)) + +#define IS_GET_GPIO_PIN(PIN) (((PIN) == GPIO_Pin_0) || \ + ((PIN) == GPIO_Pin_1) || \ + ((PIN) == GPIO_Pin_2) || \ + ((PIN) == GPIO_Pin_3) || \ + ((PIN) == GPIO_Pin_4) || \ + ((PIN) == GPIO_Pin_5) || \ + ((PIN) == GPIO_Pin_6) || \ + ((PIN) == GPIO_Pin_7) || \ + ((PIN) == GPIO_Pin_8) || \ + ((PIN) == GPIO_Pin_9) || \ + ((PIN) == GPIO_Pin_10) || \ + ((PIN) == GPIO_Pin_11) || \ + ((PIN) == GPIO_Pin_12) || \ + ((PIN) == GPIO_Pin_13) || \ + ((PIN) == GPIO_Pin_14) || \ + ((PIN) == GPIO_Pin_15)) + +/** + * @} + */ + +/** @defgroup GPIO_Remap_define + * @{ + */ + +#define GPIO_Remap_SPI1 ((uint32_t)0x00000001) /*!< SPI1 Alternate Function mapping */ +#define GPIO_Remap_I2C1 ((uint32_t)0x00000002) /*!< I2C1 Alternate Function mapping */ +#define GPIO_Remap_USART1 ((uint32_t)0x00000004) /*!< USART1 Alternate Function mapping */ +#define GPIO_Remap_USART2 ((uint32_t)0x00000008) /*!< USART2 Alternate Function mapping */ +#define GPIO_PartialRemap_USART3 ((uint32_t)0x00140010) /*!< USART3 Partial Alternate Function mapping */ +#define GPIO_FullRemap_USART3 ((uint32_t)0x00140030) /*!< USART3 Full Alternate Function mapping */ +#define GPIO_PartialRemap_TIM1 ((uint32_t)0x00160040) /*!< TIM1 Partial Alternate Function mapping */ +#define GPIO_FullRemap_TIM1 ((uint32_t)0x001600C0) /*!< TIM1 Full Alternate Function mapping */ +#define GPIO_PartialRemap1_TIM2 ((uint32_t)0x00180100) /*!< TIM2 Partial1 Alternate Function mapping */ +#define GPIO_PartialRemap2_TIM2 ((uint32_t)0x00180200) /*!< TIM2 Partial2 Alternate Function mapping */ +#define GPIO_FullRemap_TIM2 ((uint32_t)0x00180300) /*!< TIM2 Full Alternate Function mapping */ +#define GPIO_PartialRemap_TIM3 ((uint32_t)0x001A0800) /*!< TIM3 Partial Alternate Function mapping */ +#define GPIO_FullRemap_TIM3 ((uint32_t)0x001A0C00) /*!< TIM3 Full Alternate Function mapping */ +#define GPIO_Remap_TIM4 ((uint32_t)0x00001000) /*!< TIM4 Alternate Function mapping */ +#define GPIO_Remap1_CAN1 ((uint32_t)0x001D4000) /*!< CAN1 Alternate Function mapping */ +#define GPIO_Remap2_CAN1 ((uint32_t)0x001D6000) /*!< CAN1 Alternate Function mapping */ +#define GPIO_Remap_PD01 ((uint32_t)0x00008000) /*!< PD01 Alternate Function mapping */ +#define GPIO_Remap_TIM5CH4_LSI ((uint32_t)0x00200001) /*!< LSI connected to TIM5 Channel4 input capture for calibration */ +#define GPIO_Remap_ADC1_ETRGINJ ((uint32_t)0x00200002) /*!< ADC1 External Trigger Injected Conversion remapping */ +#define GPIO_Remap_ADC1_ETRGREG ((uint32_t)0x00200004) /*!< ADC1 External Trigger Regular Conversion remapping */ +#define GPIO_Remap_ADC2_ETRGINJ ((uint32_t)0x00200008) /*!< ADC2 External Trigger Injected Conversion remapping */ +#define GPIO_Remap_ADC2_ETRGREG ((uint32_t)0x00200010) /*!< ADC2 External Trigger Regular Conversion remapping */ +#define GPIO_Remap_ETH ((uint32_t)0x00200020) /*!< Ethernet remapping (only for Connectivity line devices) */ +#define GPIO_Remap_CAN2 ((uint32_t)0x00200040) /*!< CAN2 remapping (only for Connectivity line devices) */ +#define GPIO_Remap_SWJ_NoJTRST ((uint32_t)0x00300100) /*!< Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST */ +#define GPIO_Remap_SWJ_JTAGDisable ((uint32_t)0x00300200) /*!< JTAG-DP Disabled and SW-DP Enabled */ +#define GPIO_Remap_SWJ_Disable ((uint32_t)0x00300400) /*!< Full SWJ Disabled (JTAG-DP + SW-DP) */ +#define GPIO_Remap_SPI3 ((uint32_t)0x00201100) /*!< SPI3/I2S3 Alternate Function mapping (only for Connectivity line devices) */ +#define GPIO_Remap_TIM2ITR1_PTP_SOF ((uint32_t)0x00202000) /*!< Ethernet PTP output or USB OTG SOF (Start of Frame) connected + to TIM2 Internal Trigger 1 for calibration + (only for Connectivity line devices) */ +#define GPIO_Remap_PTP_PPS ((uint32_t)0x00204000) /*!< Ethernet MAC PPS_PTS output on PB05 (only for Connectivity line devices) */ + +#define GPIO_Remap_TIM15 ((uint32_t)0x80000001) /*!< TIM15 Alternate Function mapping (only for Value line devices) */ +#define GPIO_Remap_TIM16 ((uint32_t)0x80000002) /*!< TIM16 Alternate Function mapping (only for Value line devices) */ +#define GPIO_Remap_TIM17 ((uint32_t)0x80000004) /*!< TIM17 Alternate Function mapping (only for Value line devices) */ +#define GPIO_Remap_CEC ((uint32_t)0x80000008) /*!< CEC Alternate Function mapping (only for Value line devices) */ +#define GPIO_Remap_TIM1_DMA ((uint32_t)0x80000010) /*!< TIM1 DMA requests mapping (only for Value line devices) */ + +#define GPIO_Remap_TIM9 ((uint32_t)0x80000020) /*!< TIM9 Alternate Function mapping (only for XL-density devices) */ +#define GPIO_Remap_TIM10 ((uint32_t)0x80000040) /*!< TIM10 Alternate Function mapping (only for XL-density devices) */ +#define GPIO_Remap_TIM11 ((uint32_t)0x80000080) /*!< TIM11 Alternate Function mapping (only for XL-density devices) */ +#define GPIO_Remap_TIM13 ((uint32_t)0x80000100) /*!< TIM13 Alternate Function mapping (only for High density Value line and XL-density devices) */ +#define GPIO_Remap_TIM14 ((uint32_t)0x80000200) /*!< TIM14 Alternate Function mapping (only for High density Value line and XL-density devices) */ +#define GPIO_Remap_FSMC_NADV ((uint32_t)0x80000400) /*!< FSMC_NADV Alternate Function mapping (only for High density Value line and XL-density devices) */ + +#define GPIO_Remap_TIM67_DAC_DMA ((uint32_t)0x80000800) /*!< TIM6/TIM7 and DAC DMA requests remapping (only for High density Value line devices) */ +#define GPIO_Remap_TIM12 ((uint32_t)0x80001000) /*!< TIM12 Alternate Function mapping (only for High density Value line devices) */ +#define GPIO_Remap_MISC ((uint32_t)0x80002000) /*!< Miscellaneous Remap (DMA2 Channel5 Position and DAC Trigger remapping, + only for High density Value line devices) */ + +#define IS_GPIO_REMAP(REMAP) (((REMAP) == GPIO_Remap_SPI1) || ((REMAP) == GPIO_Remap_I2C1) || \ + ((REMAP) == GPIO_Remap_USART1) || ((REMAP) == GPIO_Remap_USART2) || \ + ((REMAP) == GPIO_PartialRemap_USART3) || ((REMAP) == GPIO_FullRemap_USART3) || \ + ((REMAP) == GPIO_PartialRemap_TIM1) || ((REMAP) == GPIO_FullRemap_TIM1) || \ + ((REMAP) == GPIO_PartialRemap1_TIM2) || ((REMAP) == GPIO_PartialRemap2_TIM2) || \ + ((REMAP) == GPIO_FullRemap_TIM2) || ((REMAP) == GPIO_PartialRemap_TIM3) || \ + ((REMAP) == GPIO_FullRemap_TIM3) || ((REMAP) == GPIO_Remap_TIM4) || \ + ((REMAP) == GPIO_Remap1_CAN1) || ((REMAP) == GPIO_Remap2_CAN1) || \ + ((REMAP) == GPIO_Remap_PD01) || ((REMAP) == GPIO_Remap_TIM5CH4_LSI) || \ + ((REMAP) == GPIO_Remap_ADC1_ETRGINJ) ||((REMAP) == GPIO_Remap_ADC1_ETRGREG) || \ + ((REMAP) == GPIO_Remap_ADC2_ETRGINJ) ||((REMAP) == GPIO_Remap_ADC2_ETRGREG) || \ + ((REMAP) == GPIO_Remap_ETH) ||((REMAP) == GPIO_Remap_CAN2) || \ + ((REMAP) == GPIO_Remap_SWJ_NoJTRST) || ((REMAP) == GPIO_Remap_SWJ_JTAGDisable) || \ + ((REMAP) == GPIO_Remap_SWJ_Disable)|| ((REMAP) == GPIO_Remap_SPI3) || \ + ((REMAP) == GPIO_Remap_TIM2ITR1_PTP_SOF) || ((REMAP) == GPIO_Remap_PTP_PPS) || \ + ((REMAP) == GPIO_Remap_TIM15) || ((REMAP) == GPIO_Remap_TIM16) || \ + ((REMAP) == GPIO_Remap_TIM17) || ((REMAP) == GPIO_Remap_CEC) || \ + ((REMAP) == GPIO_Remap_TIM1_DMA) || ((REMAP) == GPIO_Remap_TIM9) || \ + ((REMAP) == GPIO_Remap_TIM10) || ((REMAP) == GPIO_Remap_TIM11) || \ + ((REMAP) == GPIO_Remap_TIM13) || ((REMAP) == GPIO_Remap_TIM14) || \ + ((REMAP) == GPIO_Remap_FSMC_NADV) || ((REMAP) == GPIO_Remap_TIM67_DAC_DMA) || \ + ((REMAP) == GPIO_Remap_TIM12) || ((REMAP) == GPIO_Remap_MISC)) + +/** + * @} + */ + +/** @defgroup GPIO_Port_Sources + * @{ + */ + +#define GPIO_PortSourceGPIOA ((uint8_t)0x00) +#define GPIO_PortSourceGPIOB ((uint8_t)0x01) +#define GPIO_PortSourceGPIOC ((uint8_t)0x02) +#define GPIO_PortSourceGPIOD ((uint8_t)0x03) +#define GPIO_PortSourceGPIOE ((uint8_t)0x04) +#define GPIO_PortSourceGPIOF ((uint8_t)0x05) +#define GPIO_PortSourceGPIOG ((uint8_t)0x06) +#define IS_GPIO_EVENTOUT_PORT_SOURCE(PORTSOURCE) (((PORTSOURCE) == GPIO_PortSourceGPIOA) || \ + ((PORTSOURCE) == GPIO_PortSourceGPIOB) || \ + ((PORTSOURCE) == GPIO_PortSourceGPIOC) || \ + ((PORTSOURCE) == GPIO_PortSourceGPIOD) || \ + ((PORTSOURCE) == GPIO_PortSourceGPIOE)) + +#define IS_GPIO_EXTI_PORT_SOURCE(PORTSOURCE) (((PORTSOURCE) == GPIO_PortSourceGPIOA) || \ + ((PORTSOURCE) == GPIO_PortSourceGPIOB) || \ + ((PORTSOURCE) == GPIO_PortSourceGPIOC) || \ + ((PORTSOURCE) == GPIO_PortSourceGPIOD) || \ + ((PORTSOURCE) == GPIO_PortSourceGPIOE) || \ + ((PORTSOURCE) == GPIO_PortSourceGPIOF) || \ + ((PORTSOURCE) == GPIO_PortSourceGPIOG)) + +/** + * @} + */ + +/** @defgroup GPIO_Pin_sources + * @{ + */ + +#define GPIO_PinSource0 ((uint8_t)0x00) +#define GPIO_PinSource1 ((uint8_t)0x01) +#define GPIO_PinSource2 ((uint8_t)0x02) +#define GPIO_PinSource3 ((uint8_t)0x03) +#define GPIO_PinSource4 ((uint8_t)0x04) +#define GPIO_PinSource5 ((uint8_t)0x05) +#define GPIO_PinSource6 ((uint8_t)0x06) +#define GPIO_PinSource7 ((uint8_t)0x07) +#define GPIO_PinSource8 ((uint8_t)0x08) +#define GPIO_PinSource9 ((uint8_t)0x09) +#define GPIO_PinSource10 ((uint8_t)0x0A) +#define GPIO_PinSource11 ((uint8_t)0x0B) +#define GPIO_PinSource12 ((uint8_t)0x0C) +#define GPIO_PinSource13 ((uint8_t)0x0D) +#define GPIO_PinSource14 ((uint8_t)0x0E) +#define GPIO_PinSource15 ((uint8_t)0x0F) + +#define IS_GPIO_PIN_SOURCE(PINSOURCE) (((PINSOURCE) == GPIO_PinSource0) || \ + ((PINSOURCE) == GPIO_PinSource1) || \ + ((PINSOURCE) == GPIO_PinSource2) || \ + ((PINSOURCE) == GPIO_PinSource3) || \ + ((PINSOURCE) == GPIO_PinSource4) || \ + ((PINSOURCE) == GPIO_PinSource5) || \ + ((PINSOURCE) == GPIO_PinSource6) || \ + ((PINSOURCE) == GPIO_PinSource7) || \ + ((PINSOURCE) == GPIO_PinSource8) || \ + ((PINSOURCE) == GPIO_PinSource9) || \ + ((PINSOURCE) == GPIO_PinSource10) || \ + ((PINSOURCE) == GPIO_PinSource11) || \ + ((PINSOURCE) == GPIO_PinSource12) || \ + ((PINSOURCE) == GPIO_PinSource13) || \ + ((PINSOURCE) == GPIO_PinSource14) || \ + ((PINSOURCE) == GPIO_PinSource15)) + +/** + * @} + */ + +/** @defgroup Ethernet_Media_Interface + * @{ + */ +#define GPIO_ETH_MediaInterface_MII ((u32)0x00000000) +#define GPIO_ETH_MediaInterface_RMII ((u32)0x00000001) + +#define IS_GPIO_ETH_MEDIA_INTERFACE(INTERFACE) (((INTERFACE) == GPIO_ETH_MediaInterface_MII) || \ + ((INTERFACE) == GPIO_ETH_MediaInterface_RMII)) + +/** + * @} + */ +/** + * @} + */ + +/** @defgroup GPIO_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup GPIO_Exported_Functions + * @{ + */ + +void GPIO_DeInit(GPIO_TypeDef* GPIOx); +void GPIO_AFIODeInit(void); +void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct); +void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct); +uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx); +uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx); +void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal); +void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal); +void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource); +void GPIO_EventOutputCmd(FunctionalState NewState); +void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState); +void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource); +void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F10x_GPIO_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_i2c.c b/Library/stm32f10x_i2c.c new file mode 100644 index 0000000..4ea321c --- /dev/null +++ b/Library/stm32f10x_i2c.c @@ -0,0 +1,1331 @@ +/** + ****************************************************************************** + * @file stm32f10x_i2c.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the I2C firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_i2c.h" +#include "stm32f10x_rcc.h" + + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup I2C + * @brief I2C driver modules + * @{ + */ + +/** @defgroup I2C_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup I2C_Private_Defines + * @{ + */ + +/* I2C SPE mask */ +#define CR1_PE_Set ((uint16_t)0x0001) +#define CR1_PE_Reset ((uint16_t)0xFFFE) + +/* I2C START mask */ +#define CR1_START_Set ((uint16_t)0x0100) +#define CR1_START_Reset ((uint16_t)0xFEFF) + +/* I2C STOP mask */ +#define CR1_STOP_Set ((uint16_t)0x0200) +#define CR1_STOP_Reset ((uint16_t)0xFDFF) + +/* I2C ACK mask */ +#define CR1_ACK_Set ((uint16_t)0x0400) +#define CR1_ACK_Reset ((uint16_t)0xFBFF) + +/* I2C ENGC mask */ +#define CR1_ENGC_Set ((uint16_t)0x0040) +#define CR1_ENGC_Reset ((uint16_t)0xFFBF) + +/* I2C SWRST mask */ +#define CR1_SWRST_Set ((uint16_t)0x8000) +#define CR1_SWRST_Reset ((uint16_t)0x7FFF) + +/* I2C PEC mask */ +#define CR1_PEC_Set ((uint16_t)0x1000) +#define CR1_PEC_Reset ((uint16_t)0xEFFF) + +/* I2C ENPEC mask */ +#define CR1_ENPEC_Set ((uint16_t)0x0020) +#define CR1_ENPEC_Reset ((uint16_t)0xFFDF) + +/* I2C ENARP mask */ +#define CR1_ENARP_Set ((uint16_t)0x0010) +#define CR1_ENARP_Reset ((uint16_t)0xFFEF) + +/* I2C NOSTRETCH mask */ +#define CR1_NOSTRETCH_Set ((uint16_t)0x0080) +#define CR1_NOSTRETCH_Reset ((uint16_t)0xFF7F) + +/* I2C registers Masks */ +#define CR1_CLEAR_Mask ((uint16_t)0xFBF5) + +/* I2C DMAEN mask */ +#define CR2_DMAEN_Set ((uint16_t)0x0800) +#define CR2_DMAEN_Reset ((uint16_t)0xF7FF) + +/* I2C LAST mask */ +#define CR2_LAST_Set ((uint16_t)0x1000) +#define CR2_LAST_Reset ((uint16_t)0xEFFF) + +/* I2C FREQ mask */ +#define CR2_FREQ_Reset ((uint16_t)0xFFC0) + +/* I2C ADD0 mask */ +#define OAR1_ADD0_Set ((uint16_t)0x0001) +#define OAR1_ADD0_Reset ((uint16_t)0xFFFE) + +/* I2C ENDUAL mask */ +#define OAR2_ENDUAL_Set ((uint16_t)0x0001) +#define OAR2_ENDUAL_Reset ((uint16_t)0xFFFE) + +/* I2C ADD2 mask */ +#define OAR2_ADD2_Reset ((uint16_t)0xFF01) + +/* I2C F/S mask */ +#define CCR_FS_Set ((uint16_t)0x8000) + +/* I2C CCR mask */ +#define CCR_CCR_Set ((uint16_t)0x0FFF) + +/* I2C FLAG mask */ +#define FLAG_Mask ((uint32_t)0x00FFFFFF) + +/* I2C Interrupt Enable mask */ +#define ITEN_Mask ((uint32_t)0x07000000) + +/** + * @} + */ + +/** @defgroup I2C_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup I2C_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup I2C_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup I2C_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the I2Cx peripheral registers to their default reset values. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @retval None + */ +void I2C_DeInit(I2C_TypeDef* I2Cx) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + + if (I2Cx == I2C1) + { + /* Enable I2C1 reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE); + /* Release I2C1 from reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE); + } + else + { + /* Enable I2C2 reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, ENABLE); + /* Release I2C2 from reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, DISABLE); + } +} + +/** + * @brief Initializes the I2Cx peripheral according to the specified + * parameters in the I2C_InitStruct. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_InitStruct: pointer to a I2C_InitTypeDef structure that + * contains the configuration information for the specified I2C peripheral. + * @retval None + */ +void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct) +{ + uint16_t tmpreg = 0, freqrange = 0; + uint16_t result = 0x04; + uint32_t pclk1 = 8000000; + RCC_ClocksTypeDef rcc_clocks; + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_I2C_CLOCK_SPEED(I2C_InitStruct->I2C_ClockSpeed)); + assert_param(IS_I2C_MODE(I2C_InitStruct->I2C_Mode)); + assert_param(IS_I2C_DUTY_CYCLE(I2C_InitStruct->I2C_DutyCycle)); + assert_param(IS_I2C_OWN_ADDRESS1(I2C_InitStruct->I2C_OwnAddress1)); + assert_param(IS_I2C_ACK_STATE(I2C_InitStruct->I2C_Ack)); + assert_param(IS_I2C_ACKNOWLEDGE_ADDRESS(I2C_InitStruct->I2C_AcknowledgedAddress)); + +/*---------------------------- I2Cx CR2 Configuration ------------------------*/ + /* Get the I2Cx CR2 value */ + tmpreg = I2Cx->CR2; + /* Clear frequency FREQ[5:0] bits */ + tmpreg &= CR2_FREQ_Reset; + /* Get pclk1 frequency value */ + RCC_GetClocksFreq(&rcc_clocks); + pclk1 = rcc_clocks.PCLK1_Frequency; + /* Set frequency bits depending on pclk1 value */ + freqrange = (uint16_t)(pclk1 / 1000000); + tmpreg |= freqrange; + /* Write to I2Cx CR2 */ + I2Cx->CR2 = tmpreg; + +/*---------------------------- I2Cx CCR Configuration ------------------------*/ + /* Disable the selected I2C peripheral to configure TRISE */ + I2Cx->CR1 &= CR1_PE_Reset; + /* Reset tmpreg value */ + /* Clear F/S, DUTY and CCR[11:0] bits */ + tmpreg = 0; + + /* Configure speed in standard mode */ + if (I2C_InitStruct->I2C_ClockSpeed <= 100000) + { + /* Standard mode speed calculate */ + result = (uint16_t)(pclk1 / (I2C_InitStruct->I2C_ClockSpeed << 1)); + /* Test if CCR value is under 0x4*/ + if (result < 0x04) + { + /* Set minimum allowed value */ + result = 0x04; + } + /* Set speed value for standard mode */ + tmpreg |= result; + /* Set Maximum Rise Time for standard mode */ + I2Cx->TRISE = freqrange + 1; + } + /* Configure speed in fast mode */ + else /*(I2C_InitStruct->I2C_ClockSpeed <= 400000)*/ + { + if (I2C_InitStruct->I2C_DutyCycle == I2C_DutyCycle_2) + { + /* Fast mode speed calculate: Tlow/Thigh = 2 */ + result = (uint16_t)(pclk1 / (I2C_InitStruct->I2C_ClockSpeed * 3)); + } + else /*I2C_InitStruct->I2C_DutyCycle == I2C_DutyCycle_16_9*/ + { + /* Fast mode speed calculate: Tlow/Thigh = 16/9 */ + result = (uint16_t)(pclk1 / (I2C_InitStruct->I2C_ClockSpeed * 25)); + /* Set DUTY bit */ + result |= I2C_DutyCycle_16_9; + } + + /* Test if CCR value is under 0x1*/ + if ((result & CCR_CCR_Set) == 0) + { + /* Set minimum allowed value */ + result |= (uint16_t)0x0001; + } + /* Set speed value and set F/S bit for fast mode */ + tmpreg |= (uint16_t)(result | CCR_FS_Set); + /* Set Maximum Rise Time for fast mode */ + I2Cx->TRISE = (uint16_t)(((freqrange * (uint16_t)300) / (uint16_t)1000) + (uint16_t)1); + } + + /* Write to I2Cx CCR */ + I2Cx->CCR = tmpreg; + /* Enable the selected I2C peripheral */ + I2Cx->CR1 |= CR1_PE_Set; + +/*---------------------------- I2Cx CR1 Configuration ------------------------*/ + /* Get the I2Cx CR1 value */ + tmpreg = I2Cx->CR1; + /* Clear ACK, SMBTYPE and SMBUS bits */ + tmpreg &= CR1_CLEAR_Mask; + /* Configure I2Cx: mode and acknowledgement */ + /* Set SMBTYPE and SMBUS bits according to I2C_Mode value */ + /* Set ACK bit according to I2C_Ack value */ + tmpreg |= (uint16_t)((uint32_t)I2C_InitStruct->I2C_Mode | I2C_InitStruct->I2C_Ack); + /* Write to I2Cx CR1 */ + I2Cx->CR1 = tmpreg; + +/*---------------------------- I2Cx OAR1 Configuration -----------------------*/ + /* Set I2Cx Own Address1 and acknowledged address */ + I2Cx->OAR1 = (I2C_InitStruct->I2C_AcknowledgedAddress | I2C_InitStruct->I2C_OwnAddress1); +} + +/** + * @brief Fills each I2C_InitStruct member with its default value. + * @param I2C_InitStruct: pointer to an I2C_InitTypeDef structure which will be initialized. + * @retval None + */ +void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct) +{ +/*---------------- Reset I2C init structure parameters values ----------------*/ + /* initialize the I2C_ClockSpeed member */ + I2C_InitStruct->I2C_ClockSpeed = 5000; + /* Initialize the I2C_Mode member */ + I2C_InitStruct->I2C_Mode = I2C_Mode_I2C; + /* Initialize the I2C_DutyCycle member */ + I2C_InitStruct->I2C_DutyCycle = I2C_DutyCycle_2; + /* Initialize the I2C_OwnAddress1 member */ + I2C_InitStruct->I2C_OwnAddress1 = 0; + /* Initialize the I2C_Ack member */ + I2C_InitStruct->I2C_Ack = I2C_Ack_Disable; + /* Initialize the I2C_AcknowledgedAddress member */ + I2C_InitStruct->I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; +} + +/** + * @brief Enables or disables the specified I2C peripheral. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param NewState: new state of the I2Cx peripheral. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected I2C peripheral */ + I2Cx->CR1 |= CR1_PE_Set; + } + else + { + /* Disable the selected I2C peripheral */ + I2Cx->CR1 &= CR1_PE_Reset; + } +} + +/** + * @brief Enables or disables the specified I2C DMA requests. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param NewState: new state of the I2C DMA transfer. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected I2C DMA requests */ + I2Cx->CR2 |= CR2_DMAEN_Set; + } + else + { + /* Disable the selected I2C DMA requests */ + I2Cx->CR2 &= CR2_DMAEN_Reset; + } +} + +/** + * @brief Specifies if the next DMA transfer will be the last one. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param NewState: new state of the I2C DMA last transfer. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void I2C_DMALastTransferCmd(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Next DMA transfer is the last transfer */ + I2Cx->CR2 |= CR2_LAST_Set; + } + else + { + /* Next DMA transfer is not the last transfer */ + I2Cx->CR2 &= CR2_LAST_Reset; + } +} + +/** + * @brief Generates I2Cx communication START condition. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param NewState: new state of the I2C START condition generation. + * This parameter can be: ENABLE or DISABLE. + * @retval None. + */ +void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Generate a START condition */ + I2Cx->CR1 |= CR1_START_Set; + } + else + { + /* Disable the START condition generation */ + I2Cx->CR1 &= CR1_START_Reset; + } +} + +/** + * @brief Generates I2Cx communication STOP condition. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param NewState: new state of the I2C STOP condition generation. + * This parameter can be: ENABLE or DISABLE. + * @retval None. + */ +void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Generate a STOP condition */ + I2Cx->CR1 |= CR1_STOP_Set; + } + else + { + /* Disable the STOP condition generation */ + I2Cx->CR1 &= CR1_STOP_Reset; + } +} + +/** + * @brief Enables or disables the specified I2C acknowledge feature. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param NewState: new state of the I2C Acknowledgement. + * This parameter can be: ENABLE or DISABLE. + * @retval None. + */ +void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the acknowledgement */ + I2Cx->CR1 |= CR1_ACK_Set; + } + else + { + /* Disable the acknowledgement */ + I2Cx->CR1 &= CR1_ACK_Reset; + } +} + +/** + * @brief Configures the specified I2C own address2. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param Address: specifies the 7bit I2C own address2. + * @retval None. + */ +void I2C_OwnAddress2Config(I2C_TypeDef* I2Cx, uint8_t Address) +{ + uint16_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + + /* Get the old register value */ + tmpreg = I2Cx->OAR2; + + /* Reset I2Cx Own address2 bit [7:1] */ + tmpreg &= OAR2_ADD2_Reset; + + /* Set I2Cx Own address2 */ + tmpreg |= (uint16_t)((uint16_t)Address & (uint16_t)0x00FE); + + /* Store the new register value */ + I2Cx->OAR2 = tmpreg; +} + +/** + * @brief Enables or disables the specified I2C dual addressing mode. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param NewState: new state of the I2C dual addressing mode. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void I2C_DualAddressCmd(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable dual addressing mode */ + I2Cx->OAR2 |= OAR2_ENDUAL_Set; + } + else + { + /* Disable dual addressing mode */ + I2Cx->OAR2 &= OAR2_ENDUAL_Reset; + } +} + +/** + * @brief Enables or disables the specified I2C general call feature. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param NewState: new state of the I2C General call. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void I2C_GeneralCallCmd(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable generall call */ + I2Cx->CR1 |= CR1_ENGC_Set; + } + else + { + /* Disable generall call */ + I2Cx->CR1 &= CR1_ENGC_Reset; + } +} + +/** + * @brief Enables or disables the specified I2C interrupts. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_IT: specifies the I2C interrupts sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg I2C_IT_BUF: Buffer interrupt mask + * @arg I2C_IT_EVT: Event interrupt mask + * @arg I2C_IT_ERR: Error interrupt mask + * @param NewState: new state of the specified I2C interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void I2C_ITConfig(I2C_TypeDef* I2Cx, uint16_t I2C_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + assert_param(IS_I2C_CONFIG_IT(I2C_IT)); + + if (NewState != DISABLE) + { + /* Enable the selected I2C interrupts */ + I2Cx->CR2 |= I2C_IT; + } + else + { + /* Disable the selected I2C interrupts */ + I2Cx->CR2 &= (uint16_t)~I2C_IT; + } +} + +/** + * @brief Sends a data byte through the I2Cx peripheral. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param Data: Byte to be transmitted.. + * @retval None + */ +void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + /* Write in the DR register the data to be sent */ + I2Cx->DR = Data; +} + +/** + * @brief Returns the most recent received data by the I2Cx peripheral. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @retval The value of the received data. + */ +uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + /* Return the data in the DR register */ + return (uint8_t)I2Cx->DR; +} + +/** + * @brief Transmits the address byte to select the slave device. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param Address: specifies the slave address which will be transmitted + * @param I2C_Direction: specifies whether the I2C device will be a + * Transmitter or a Receiver. This parameter can be one of the following values + * @arg I2C_Direction_Transmitter: Transmitter mode + * @arg I2C_Direction_Receiver: Receiver mode + * @retval None. + */ +void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_I2C_DIRECTION(I2C_Direction)); + /* Test on the direction to set/reset the read/write bit */ + if (I2C_Direction != I2C_Direction_Transmitter) + { + /* Set the address bit0 for read */ + Address |= OAR1_ADD0_Set; + } + else + { + /* Reset the address bit0 for write */ + Address &= OAR1_ADD0_Reset; + } + /* Send the address */ + I2Cx->DR = Address; +} + +/** + * @brief Reads the specified I2C register and returns its value. + * @param I2C_Register: specifies the register to read. + * This parameter can be one of the following values: + * @arg I2C_Register_CR1: CR1 register. + * @arg I2C_Register_CR2: CR2 register. + * @arg I2C_Register_OAR1: OAR1 register. + * @arg I2C_Register_OAR2: OAR2 register. + * @arg I2C_Register_DR: DR register. + * @arg I2C_Register_SR1: SR1 register. + * @arg I2C_Register_SR2: SR2 register. + * @arg I2C_Register_CCR: CCR register. + * @arg I2C_Register_TRISE: TRISE register. + * @retval The value of the read register. + */ +uint16_t I2C_ReadRegister(I2C_TypeDef* I2Cx, uint8_t I2C_Register) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_I2C_REGISTER(I2C_Register)); + + tmp = (uint32_t) I2Cx; + tmp += I2C_Register; + + /* Return the selected register value */ + return (*(__IO uint16_t *) tmp); +} + +/** + * @brief Enables or disables the specified I2C software reset. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param NewState: new state of the I2C software reset. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void I2C_SoftwareResetCmd(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Peripheral under reset */ + I2Cx->CR1 |= CR1_SWRST_Set; + } + else + { + /* Peripheral not under reset */ + I2Cx->CR1 &= CR1_SWRST_Reset; + } +} + +/** + * @brief Selects the specified I2C NACK position in master receiver mode. + * This function is useful in I2C Master Receiver mode when the number + * of data to be received is equal to 2. In this case, this function + * should be called (with parameter I2C_NACKPosition_Next) before data + * reception starts,as described in the 2-byte reception procedure + * recommended in Reference Manual in Section: Master receiver. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_NACKPosition: specifies the NACK position. + * This parameter can be one of the following values: + * @arg I2C_NACKPosition_Next: indicates that the next byte will be the last + * received byte. + * @arg I2C_NACKPosition_Current: indicates that current byte is the last + * received byte. + * + * @note This function configures the same bit (POS) as I2C_PECPositionConfig() + * but is intended to be used in I2C mode while I2C_PECPositionConfig() + * is intended to used in SMBUS mode. + * + * @retval None + */ +void I2C_NACKPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_NACKPosition) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_I2C_NACK_POSITION(I2C_NACKPosition)); + + /* Check the input parameter */ + if (I2C_NACKPosition == I2C_NACKPosition_Next) + { + /* Next byte in shift register is the last received byte */ + I2Cx->CR1 |= I2C_NACKPosition_Next; + } + else + { + /* Current byte in shift register is the last received byte */ + I2Cx->CR1 &= I2C_NACKPosition_Current; + } +} + +/** + * @brief Drives the SMBusAlert pin high or low for the specified I2C. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_SMBusAlert: specifies SMBAlert pin level. + * This parameter can be one of the following values: + * @arg I2C_SMBusAlert_Low: SMBAlert pin driven low + * @arg I2C_SMBusAlert_High: SMBAlert pin driven high + * @retval None + */ +void I2C_SMBusAlertConfig(I2C_TypeDef* I2Cx, uint16_t I2C_SMBusAlert) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_I2C_SMBUS_ALERT(I2C_SMBusAlert)); + if (I2C_SMBusAlert == I2C_SMBusAlert_Low) + { + /* Drive the SMBusAlert pin Low */ + I2Cx->CR1 |= I2C_SMBusAlert_Low; + } + else + { + /* Drive the SMBusAlert pin High */ + I2Cx->CR1 &= I2C_SMBusAlert_High; + } +} + +/** + * @brief Enables or disables the specified I2C PEC transfer. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param NewState: new state of the I2C PEC transmission. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void I2C_TransmitPEC(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected I2C PEC transmission */ + I2Cx->CR1 |= CR1_PEC_Set; + } + else + { + /* Disable the selected I2C PEC transmission */ + I2Cx->CR1 &= CR1_PEC_Reset; + } +} + +/** + * @brief Selects the specified I2C PEC position. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_PECPosition: specifies the PEC position. + * This parameter can be one of the following values: + * @arg I2C_PECPosition_Next: indicates that the next byte is PEC + * @arg I2C_PECPosition_Current: indicates that current byte is PEC + * + * @note This function configures the same bit (POS) as I2C_NACKPositionConfig() + * but is intended to be used in SMBUS mode while I2C_NACKPositionConfig() + * is intended to used in I2C mode. + * + * @retval None + */ +void I2C_PECPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_PECPosition) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_I2C_PEC_POSITION(I2C_PECPosition)); + if (I2C_PECPosition == I2C_PECPosition_Next) + { + /* Next byte in shift register is PEC */ + I2Cx->CR1 |= I2C_PECPosition_Next; + } + else + { + /* Current byte in shift register is PEC */ + I2Cx->CR1 &= I2C_PECPosition_Current; + } +} + +/** + * @brief Enables or disables the PEC value calculation of the transferred bytes. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param NewState: new state of the I2Cx PEC value calculation. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void I2C_CalculatePEC(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected I2C PEC calculation */ + I2Cx->CR1 |= CR1_ENPEC_Set; + } + else + { + /* Disable the selected I2C PEC calculation */ + I2Cx->CR1 &= CR1_ENPEC_Reset; + } +} + +/** + * @brief Returns the PEC value for the specified I2C. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @retval The PEC value. + */ +uint8_t I2C_GetPEC(I2C_TypeDef* I2Cx) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + /* Return the selected I2C PEC value */ + return ((I2Cx->SR2) >> 8); +} + +/** + * @brief Enables or disables the specified I2C ARP. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param NewState: new state of the I2Cx ARP. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void I2C_ARPCmd(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected I2C ARP */ + I2Cx->CR1 |= CR1_ENARP_Set; + } + else + { + /* Disable the selected I2C ARP */ + I2Cx->CR1 &= CR1_ENARP_Reset; + } +} + +/** + * @brief Enables or disables the specified I2C Clock stretching. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param NewState: new state of the I2Cx Clock stretching. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void I2C_StretchClockCmd(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState == DISABLE) + { + /* Enable the selected I2C Clock stretching */ + I2Cx->CR1 |= CR1_NOSTRETCH_Set; + } + else + { + /* Disable the selected I2C Clock stretching */ + I2Cx->CR1 &= CR1_NOSTRETCH_Reset; + } +} + +/** + * @brief Selects the specified I2C fast mode duty cycle. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_DutyCycle: specifies the fast mode duty cycle. + * This parameter can be one of the following values: + * @arg I2C_DutyCycle_2: I2C fast mode Tlow/Thigh = 2 + * @arg I2C_DutyCycle_16_9: I2C fast mode Tlow/Thigh = 16/9 + * @retval None + */ +void I2C_FastModeDutyCycleConfig(I2C_TypeDef* I2Cx, uint16_t I2C_DutyCycle) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_I2C_DUTY_CYCLE(I2C_DutyCycle)); + if (I2C_DutyCycle != I2C_DutyCycle_16_9) + { + /* I2C fast mode Tlow/Thigh=2 */ + I2Cx->CCR &= I2C_DutyCycle_2; + } + else + { + /* I2C fast mode Tlow/Thigh=16/9 */ + I2Cx->CCR |= I2C_DutyCycle_16_9; + } +} + + + +/** + * @brief + **************************************************************************************** + * + * I2C State Monitoring Functions + * + **************************************************************************************** + * This I2C driver provides three different ways for I2C state monitoring + * depending on the application requirements and constraints: + * + * + * 1) Basic state monitoring: + * Using I2C_CheckEvent() function: + * It compares the status registers (SR1 and SR2) content to a given event + * (can be the combination of one or more flags). + * It returns SUCCESS if the current status includes the given flags + * and returns ERROR if one or more flags are missing in the current status. + * - When to use: + * - This function is suitable for most applications as well as for startup + * activity since the events are fully described in the product reference manual + * (RM0008). + * - It is also suitable for users who need to define their own events. + * - Limitations: + * - If an error occurs (ie. error flags are set besides to the monitored flags), + * the I2C_CheckEvent() function may return SUCCESS despite the communication + * hold or corrupted real state. + * In this case, it is advised to use error interrupts to monitor the error + * events and handle them in the interrupt IRQ handler. + * + * @note + * For error management, it is advised to use the following functions: + * - I2C_ITConfig() to configure and enable the error interrupts (I2C_IT_ERR). + * - I2Cx_ER_IRQHandler() which is called when the error interrupt occurs. + * Where x is the peripheral instance (I2C1, I2C2 ...) + * - I2C_GetFlagStatus() or I2C_GetITStatus() to be called into I2Cx_ER_IRQHandler() + * in order to determine which error occured. + * - I2C_ClearFlag() or I2C_ClearITPendingBit() and/or I2C_SoftwareResetCmd() + * and/or I2C_GenerateStop() in order to clear the error flag and source, + * and return to correct communication status. + * + * + * 2) Advanced state monitoring: + * Using the function I2C_GetLastEvent() which returns the image of both status + * registers in a single word (uint32_t) (Status Register 2 value is shifted left + * by 16 bits and concatenated to Status Register 1). + * - When to use: + * - This function is suitable for the same applications above but it allows to + * overcome the mentioned limitation of I2C_GetFlagStatus() function. + * The returned value could be compared to events already defined in the + * library (stm32f10x_i2c.h) or to custom values defined by user. + * - This function is suitable when multiple flags are monitored at the same time. + * - At the opposite of I2C_CheckEvent() function, this function allows user to + * choose when an event is accepted (when all events flags are set and no + * other flags are set or just when the needed flags are set like + * I2C_CheckEvent() function). + * - Limitations: + * - User may need to define his own events. + * - Same remark concerning the error management is applicable for this + * function if user decides to check only regular communication flags (and + * ignores error flags). + * + * + * 3) Flag-based state monitoring: + * Using the function I2C_GetFlagStatus() which simply returns the status of + * one single flag (ie. I2C_FLAG_RXNE ...). + * - When to use: + * - This function could be used for specific applications or in debug phase. + * - It is suitable when only one flag checking is needed (most I2C events + * are monitored through multiple flags). + * - Limitations: + * - When calling this function, the Status register is accessed. Some flags are + * cleared when the status register is accessed. So checking the status + * of one Flag, may clear other ones. + * - Function may need to be called twice or more in order to monitor one + * single event. + * + * For detailed description of Events, please refer to section I2C_Events in + * stm32f10x_i2c.h file. + * + */ + +/** + * + * 1) Basic state monitoring + ******************************************************************************* + */ + +/** + * @brief Checks whether the last I2Cx Event is equal to the one passed + * as parameter. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_EVENT: specifies the event to be checked. + * This parameter can be one of the following values: + * @arg I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED : EV1 + * @arg I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED : EV1 + * @arg I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED : EV1 + * @arg I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED : EV1 + * @arg I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED : EV1 + * @arg I2C_EVENT_SLAVE_BYTE_RECEIVED : EV2 + * @arg (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_DUALF) : EV2 + * @arg (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_GENCALL) : EV2 + * @arg I2C_EVENT_SLAVE_BYTE_TRANSMITTED : EV3 + * @arg (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_DUALF) : EV3 + * @arg (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_GENCALL) : EV3 + * @arg I2C_EVENT_SLAVE_ACK_FAILURE : EV3_2 + * @arg I2C_EVENT_SLAVE_STOP_DETECTED : EV4 + * @arg I2C_EVENT_MASTER_MODE_SELECT : EV5 + * @arg I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED : EV6 + * @arg I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED : EV6 + * @arg I2C_EVENT_MASTER_BYTE_RECEIVED : EV7 + * @arg I2C_EVENT_MASTER_BYTE_TRANSMITTING : EV8 + * @arg I2C_EVENT_MASTER_BYTE_TRANSMITTED : EV8_2 + * @arg I2C_EVENT_MASTER_MODE_ADDRESS10 : EV9 + * + * @note: For detailed description of Events, please refer to section + * I2C_Events in stm32f10x_i2c.h file. + * + * @retval An ErrorStatus enumeration value: + * - SUCCESS: Last event is equal to the I2C_EVENT + * - ERROR: Last event is different from the I2C_EVENT + */ +ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT) +{ + uint32_t lastevent = 0; + uint32_t flag1 = 0, flag2 = 0; + ErrorStatus status = ERROR; + + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_I2C_EVENT(I2C_EVENT)); + + /* Read the I2Cx status register */ + flag1 = I2Cx->SR1; + flag2 = I2Cx->SR2; + flag2 = flag2 << 16; + + /* Get the last event value from I2C status register */ + lastevent = (flag1 | flag2) & FLAG_Mask; + + /* Check whether the last event contains the I2C_EVENT */ + if ((lastevent & I2C_EVENT) == I2C_EVENT) + { + /* SUCCESS: last event is equal to I2C_EVENT */ + status = SUCCESS; + } + else + { + /* ERROR: last event is different from I2C_EVENT */ + status = ERROR; + } + /* Return status */ + return status; +} + +/** + * + * 2) Advanced state monitoring + ******************************************************************************* + */ + +/** + * @brief Returns the last I2Cx Event. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * + * @note: For detailed description of Events, please refer to section + * I2C_Events in stm32f10x_i2c.h file. + * + * @retval The last event + */ +uint32_t I2C_GetLastEvent(I2C_TypeDef* I2Cx) +{ + uint32_t lastevent = 0; + uint32_t flag1 = 0, flag2 = 0; + + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + + /* Read the I2Cx status register */ + flag1 = I2Cx->SR1; + flag2 = I2Cx->SR2; + flag2 = flag2 << 16; + + /* Get the last event value from I2C status register */ + lastevent = (flag1 | flag2) & FLAG_Mask; + + /* Return status */ + return lastevent; +} + +/** + * + * 3) Flag-based state monitoring + ******************************************************************************* + */ + +/** + * @brief Checks whether the specified I2C flag is set or not. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_FLAG: specifies the flag to check. + * This parameter can be one of the following values: + * @arg I2C_FLAG_DUALF: Dual flag (Slave mode) + * @arg I2C_FLAG_SMBHOST: SMBus host header (Slave mode) + * @arg I2C_FLAG_SMBDEFAULT: SMBus default header (Slave mode) + * @arg I2C_FLAG_GENCALL: General call header flag (Slave mode) + * @arg I2C_FLAG_TRA: Transmitter/Receiver flag + * @arg I2C_FLAG_BUSY: Bus busy flag + * @arg I2C_FLAG_MSL: Master/Slave flag + * @arg I2C_FLAG_SMBALERT: SMBus Alert flag + * @arg I2C_FLAG_TIMEOUT: Timeout or Tlow error flag + * @arg I2C_FLAG_PECERR: PEC error in reception flag + * @arg I2C_FLAG_OVR: Overrun/Underrun flag (Slave mode) + * @arg I2C_FLAG_AF: Acknowledge failure flag + * @arg I2C_FLAG_ARLO: Arbitration lost flag (Master mode) + * @arg I2C_FLAG_BERR: Bus error flag + * @arg I2C_FLAG_TXE: Data register empty flag (Transmitter) + * @arg I2C_FLAG_RXNE: Data register not empty (Receiver) flag + * @arg I2C_FLAG_STOPF: Stop detection flag (Slave mode) + * @arg I2C_FLAG_ADD10: 10-bit header sent flag (Master mode) + * @arg I2C_FLAG_BTF: Byte transfer finished flag + * @arg I2C_FLAG_ADDR: Address sent flag (Master mode) "ADSL" + * Address matched flag (Slave mode)"ENDA" + * @arg I2C_FLAG_SB: Start bit flag (Master mode) + * @retval The new state of I2C_FLAG (SET or RESET). + */ +FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG) +{ + FlagStatus bitstatus = RESET; + __IO uint32_t i2creg = 0, i2cxbase = 0; + + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_I2C_GET_FLAG(I2C_FLAG)); + + /* Get the I2Cx peripheral base address */ + i2cxbase = (uint32_t)I2Cx; + + /* Read flag register index */ + i2creg = I2C_FLAG >> 28; + + /* Get bit[23:0] of the flag */ + I2C_FLAG &= FLAG_Mask; + + if(i2creg != 0) + { + /* Get the I2Cx SR1 register address */ + i2cxbase += 0x14; + } + else + { + /* Flag in I2Cx SR2 Register */ + I2C_FLAG = (uint32_t)(I2C_FLAG >> 16); + /* Get the I2Cx SR2 register address */ + i2cxbase += 0x18; + } + + if(((*(__IO uint32_t *)i2cxbase) & I2C_FLAG) != (uint32_t)RESET) + { + /* I2C_FLAG is set */ + bitstatus = SET; + } + else + { + /* I2C_FLAG is reset */ + bitstatus = RESET; + } + + /* Return the I2C_FLAG status */ + return bitstatus; +} + + + +/** + * @brief Clears the I2Cx's pending flags. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_FLAG: specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg I2C_FLAG_SMBALERT: SMBus Alert flag + * @arg I2C_FLAG_TIMEOUT: Timeout or Tlow error flag + * @arg I2C_FLAG_PECERR: PEC error in reception flag + * @arg I2C_FLAG_OVR: Overrun/Underrun flag (Slave mode) + * @arg I2C_FLAG_AF: Acknowledge failure flag + * @arg I2C_FLAG_ARLO: Arbitration lost flag (Master mode) + * @arg I2C_FLAG_BERR: Bus error flag + * + * @note + * - STOPF (STOP detection) is cleared by software sequence: a read operation + * to I2C_SR1 register (I2C_GetFlagStatus()) followed by a write operation + * to I2C_CR1 register (I2C_Cmd() to re-enable the I2C peripheral). + * - ADD10 (10-bit header sent) is cleared by software sequence: a read + * operation to I2C_SR1 (I2C_GetFlagStatus()) followed by writing the + * second byte of the address in DR register. + * - BTF (Byte Transfer Finished) is cleared by software sequence: a read + * operation to I2C_SR1 register (I2C_GetFlagStatus()) followed by a + * read/write to I2C_DR register (I2C_SendData()). + * - ADDR (Address sent) is cleared by software sequence: a read operation to + * I2C_SR1 register (I2C_GetFlagStatus()) followed by a read operation to + * I2C_SR2 register ((void)(I2Cx->SR2)). + * - SB (Start Bit) is cleared software sequence: a read operation to I2C_SR1 + * register (I2C_GetFlagStatus()) followed by a write operation to I2C_DR + * register (I2C_SendData()). + * @retval None + */ +void I2C_ClearFlag(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG) +{ + uint32_t flagpos = 0; + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_I2C_CLEAR_FLAG(I2C_FLAG)); + /* Get the I2C flag position */ + flagpos = I2C_FLAG & FLAG_Mask; + /* Clear the selected I2C flag */ + I2Cx->SR1 = (uint16_t)~flagpos; +} + +/** + * @brief Checks whether the specified I2C interrupt has occurred or not. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_IT: specifies the interrupt source to check. + * This parameter can be one of the following values: + * @arg I2C_IT_SMBALERT: SMBus Alert flag + * @arg I2C_IT_TIMEOUT: Timeout or Tlow error flag + * @arg I2C_IT_PECERR: PEC error in reception flag + * @arg I2C_IT_OVR: Overrun/Underrun flag (Slave mode) + * @arg I2C_IT_AF: Acknowledge failure flag + * @arg I2C_IT_ARLO: Arbitration lost flag (Master mode) + * @arg I2C_IT_BERR: Bus error flag + * @arg I2C_IT_TXE: Data register empty flag (Transmitter) + * @arg I2C_IT_RXNE: Data register not empty (Receiver) flag + * @arg I2C_IT_STOPF: Stop detection flag (Slave mode) + * @arg I2C_IT_ADD10: 10-bit header sent flag (Master mode) + * @arg I2C_IT_BTF: Byte transfer finished flag + * @arg I2C_IT_ADDR: Address sent flag (Master mode) "ADSL" + * Address matched flag (Slave mode)"ENDAD" + * @arg I2C_IT_SB: Start bit flag (Master mode) + * @retval The new state of I2C_IT (SET or RESET). + */ +ITStatus I2C_GetITStatus(I2C_TypeDef* I2Cx, uint32_t I2C_IT) +{ + ITStatus bitstatus = RESET; + uint32_t enablestatus = 0; + + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_I2C_GET_IT(I2C_IT)); + + /* Check if the interrupt source is enabled or not */ + enablestatus = (uint32_t)(((I2C_IT & ITEN_Mask) >> 16) & (I2Cx->CR2)) ; + + /* Get bit[23:0] of the flag */ + I2C_IT &= FLAG_Mask; + + /* Check the status of the specified I2C flag */ + if (((I2Cx->SR1 & I2C_IT) != (uint32_t)RESET) && enablestatus) + { + /* I2C_IT is set */ + bitstatus = SET; + } + else + { + /* I2C_IT is reset */ + bitstatus = RESET; + } + /* Return the I2C_IT status */ + return bitstatus; +} + +/** + * @brief Clears the I2Cx’s interrupt pending bits. + * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_IT: specifies the interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg I2C_IT_SMBALERT: SMBus Alert interrupt + * @arg I2C_IT_TIMEOUT: Timeout or Tlow error interrupt + * @arg I2C_IT_PECERR: PEC error in reception interrupt + * @arg I2C_IT_OVR: Overrun/Underrun interrupt (Slave mode) + * @arg I2C_IT_AF: Acknowledge failure interrupt + * @arg I2C_IT_ARLO: Arbitration lost interrupt (Master mode) + * @arg I2C_IT_BERR: Bus error interrupt + * + * @note + * - STOPF (STOP detection) is cleared by software sequence: a read operation + * to I2C_SR1 register (I2C_GetITStatus()) followed by a write operation to + * I2C_CR1 register (I2C_Cmd() to re-enable the I2C peripheral). + * - ADD10 (10-bit header sent) is cleared by software sequence: a read + * operation to I2C_SR1 (I2C_GetITStatus()) followed by writing the second + * byte of the address in I2C_DR register. + * - BTF (Byte Transfer Finished) is cleared by software sequence: a read + * operation to I2C_SR1 register (I2C_GetITStatus()) followed by a + * read/write to I2C_DR register (I2C_SendData()). + * - ADDR (Address sent) is cleared by software sequence: a read operation to + * I2C_SR1 register (I2C_GetITStatus()) followed by a read operation to + * I2C_SR2 register ((void)(I2Cx->SR2)). + * - SB (Start Bit) is cleared by software sequence: a read operation to + * I2C_SR1 register (I2C_GetITStatus()) followed by a write operation to + * I2C_DR register (I2C_SendData()). + * @retval None + */ +void I2C_ClearITPendingBit(I2C_TypeDef* I2Cx, uint32_t I2C_IT) +{ + uint32_t flagpos = 0; + /* Check the parameters */ + assert_param(IS_I2C_ALL_PERIPH(I2Cx)); + assert_param(IS_I2C_CLEAR_IT(I2C_IT)); + /* Get the I2C flag position */ + flagpos = I2C_IT & FLAG_Mask; + /* Clear the selected I2C flag */ + I2Cx->SR1 = (uint16_t)~flagpos; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_i2c.h b/Library/stm32f10x_i2c.h new file mode 100644 index 0000000..60e4b14 --- /dev/null +++ b/Library/stm32f10x_i2c.h @@ -0,0 +1,684 @@ +/** + ****************************************************************************** + * @file stm32f10x_i2c.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the I2C firmware + * library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_I2C_H +#define __STM32F10x_I2C_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup I2C + * @{ + */ + +/** @defgroup I2C_Exported_Types + * @{ + */ + +/** + * @brief I2C Init structure definition + */ + +typedef struct +{ + uint32_t I2C_ClockSpeed; /*!< Specifies the clock frequency. + This parameter must be set to a value lower than 400kHz */ + + uint16_t I2C_Mode; /*!< Specifies the I2C mode. + This parameter can be a value of @ref I2C_mode */ + + uint16_t I2C_DutyCycle; /*!< Specifies the I2C fast mode duty cycle. + This parameter can be a value of @ref I2C_duty_cycle_in_fast_mode */ + + uint16_t I2C_OwnAddress1; /*!< Specifies the first device own address. + This parameter can be a 7-bit or 10-bit address. */ + + uint16_t I2C_Ack; /*!< Enables or disables the acknowledgement. + This parameter can be a value of @ref I2C_acknowledgement */ + + uint16_t I2C_AcknowledgedAddress; /*!< Specifies if 7-bit or 10-bit address is acknowledged. + This parameter can be a value of @ref I2C_acknowledged_address */ +}I2C_InitTypeDef; + +/** + * @} + */ + + +/** @defgroup I2C_Exported_Constants + * @{ + */ + +#define IS_I2C_ALL_PERIPH(PERIPH) (((PERIPH) == I2C1) || \ + ((PERIPH) == I2C2)) +/** @defgroup I2C_mode + * @{ + */ + +#define I2C_Mode_I2C ((uint16_t)0x0000) +#define I2C_Mode_SMBusDevice ((uint16_t)0x0002) +#define I2C_Mode_SMBusHost ((uint16_t)0x000A) +#define IS_I2C_MODE(MODE) (((MODE) == I2C_Mode_I2C) || \ + ((MODE) == I2C_Mode_SMBusDevice) || \ + ((MODE) == I2C_Mode_SMBusHost)) +/** + * @} + */ + +/** @defgroup I2C_duty_cycle_in_fast_mode + * @{ + */ + +#define I2C_DutyCycle_16_9 ((uint16_t)0x4000) /*!< I2C fast mode Tlow/Thigh = 16/9 */ +#define I2C_DutyCycle_2 ((uint16_t)0xBFFF) /*!< I2C fast mode Tlow/Thigh = 2 */ +#define IS_I2C_DUTY_CYCLE(CYCLE) (((CYCLE) == I2C_DutyCycle_16_9) || \ + ((CYCLE) == I2C_DutyCycle_2)) +/** + * @} + */ + +/** @defgroup I2C_acknowledgement + * @{ + */ + +#define I2C_Ack_Enable ((uint16_t)0x0400) +#define I2C_Ack_Disable ((uint16_t)0x0000) +#define IS_I2C_ACK_STATE(STATE) (((STATE) == I2C_Ack_Enable) || \ + ((STATE) == I2C_Ack_Disable)) +/** + * @} + */ + +/** @defgroup I2C_transfer_direction + * @{ + */ + +#define I2C_Direction_Transmitter ((uint8_t)0x00) +#define I2C_Direction_Receiver ((uint8_t)0x01) +#define IS_I2C_DIRECTION(DIRECTION) (((DIRECTION) == I2C_Direction_Transmitter) || \ + ((DIRECTION) == I2C_Direction_Receiver)) +/** + * @} + */ + +/** @defgroup I2C_acknowledged_address + * @{ + */ + +#define I2C_AcknowledgedAddress_7bit ((uint16_t)0x4000) +#define I2C_AcknowledgedAddress_10bit ((uint16_t)0xC000) +#define IS_I2C_ACKNOWLEDGE_ADDRESS(ADDRESS) (((ADDRESS) == I2C_AcknowledgedAddress_7bit) || \ + ((ADDRESS) == I2C_AcknowledgedAddress_10bit)) +/** + * @} + */ + +/** @defgroup I2C_registers + * @{ + */ + +#define I2C_Register_CR1 ((uint8_t)0x00) +#define I2C_Register_CR2 ((uint8_t)0x04) +#define I2C_Register_OAR1 ((uint8_t)0x08) +#define I2C_Register_OAR2 ((uint8_t)0x0C) +#define I2C_Register_DR ((uint8_t)0x10) +#define I2C_Register_SR1 ((uint8_t)0x14) +#define I2C_Register_SR2 ((uint8_t)0x18) +#define I2C_Register_CCR ((uint8_t)0x1C) +#define I2C_Register_TRISE ((uint8_t)0x20) +#define IS_I2C_REGISTER(REGISTER) (((REGISTER) == I2C_Register_CR1) || \ + ((REGISTER) == I2C_Register_CR2) || \ + ((REGISTER) == I2C_Register_OAR1) || \ + ((REGISTER) == I2C_Register_OAR2) || \ + ((REGISTER) == I2C_Register_DR) || \ + ((REGISTER) == I2C_Register_SR1) || \ + ((REGISTER) == I2C_Register_SR2) || \ + ((REGISTER) == I2C_Register_CCR) || \ + ((REGISTER) == I2C_Register_TRISE)) +/** + * @} + */ + +/** @defgroup I2C_SMBus_alert_pin_level + * @{ + */ + +#define I2C_SMBusAlert_Low ((uint16_t)0x2000) +#define I2C_SMBusAlert_High ((uint16_t)0xDFFF) +#define IS_I2C_SMBUS_ALERT(ALERT) (((ALERT) == I2C_SMBusAlert_Low) || \ + ((ALERT) == I2C_SMBusAlert_High)) +/** + * @} + */ + +/** @defgroup I2C_PEC_position + * @{ + */ + +#define I2C_PECPosition_Next ((uint16_t)0x0800) +#define I2C_PECPosition_Current ((uint16_t)0xF7FF) +#define IS_I2C_PEC_POSITION(POSITION) (((POSITION) == I2C_PECPosition_Next) || \ + ((POSITION) == I2C_PECPosition_Current)) +/** + * @} + */ + +/** @defgroup I2C_NCAK_position + * @{ + */ + +#define I2C_NACKPosition_Next ((uint16_t)0x0800) +#define I2C_NACKPosition_Current ((uint16_t)0xF7FF) +#define IS_I2C_NACK_POSITION(POSITION) (((POSITION) == I2C_NACKPosition_Next) || \ + ((POSITION) == I2C_NACKPosition_Current)) +/** + * @} + */ + +/** @defgroup I2C_interrupts_definition + * @{ + */ + +#define I2C_IT_BUF ((uint16_t)0x0400) +#define I2C_IT_EVT ((uint16_t)0x0200) +#define I2C_IT_ERR ((uint16_t)0x0100) +#define IS_I2C_CONFIG_IT(IT) ((((IT) & (uint16_t)0xF8FF) == 0x00) && ((IT) != 0x00)) +/** + * @} + */ + +/** @defgroup I2C_interrupts_definition + * @{ + */ + +#define I2C_IT_SMBALERT ((uint32_t)0x01008000) +#define I2C_IT_TIMEOUT ((uint32_t)0x01004000) +#define I2C_IT_PECERR ((uint32_t)0x01001000) +#define I2C_IT_OVR ((uint32_t)0x01000800) +#define I2C_IT_AF ((uint32_t)0x01000400) +#define I2C_IT_ARLO ((uint32_t)0x01000200) +#define I2C_IT_BERR ((uint32_t)0x01000100) +#define I2C_IT_TXE ((uint32_t)0x06000080) +#define I2C_IT_RXNE ((uint32_t)0x06000040) +#define I2C_IT_STOPF ((uint32_t)0x02000010) +#define I2C_IT_ADD10 ((uint32_t)0x02000008) +#define I2C_IT_BTF ((uint32_t)0x02000004) +#define I2C_IT_ADDR ((uint32_t)0x02000002) +#define I2C_IT_SB ((uint32_t)0x02000001) + +#define IS_I2C_CLEAR_IT(IT) ((((IT) & (uint16_t)0x20FF) == 0x00) && ((IT) != (uint16_t)0x00)) + +#define IS_I2C_GET_IT(IT) (((IT) == I2C_IT_SMBALERT) || ((IT) == I2C_IT_TIMEOUT) || \ + ((IT) == I2C_IT_PECERR) || ((IT) == I2C_IT_OVR) || \ + ((IT) == I2C_IT_AF) || ((IT) == I2C_IT_ARLO) || \ + ((IT) == I2C_IT_BERR) || ((IT) == I2C_IT_TXE) || \ + ((IT) == I2C_IT_RXNE) || ((IT) == I2C_IT_STOPF) || \ + ((IT) == I2C_IT_ADD10) || ((IT) == I2C_IT_BTF) || \ + ((IT) == I2C_IT_ADDR) || ((IT) == I2C_IT_SB)) +/** + * @} + */ + +/** @defgroup I2C_flags_definition + * @{ + */ + +/** + * @brief SR2 register flags + */ + +#define I2C_FLAG_DUALF ((uint32_t)0x00800000) +#define I2C_FLAG_SMBHOST ((uint32_t)0x00400000) +#define I2C_FLAG_SMBDEFAULT ((uint32_t)0x00200000) +#define I2C_FLAG_GENCALL ((uint32_t)0x00100000) +#define I2C_FLAG_TRA ((uint32_t)0x00040000) +#define I2C_FLAG_BUSY ((uint32_t)0x00020000) +#define I2C_FLAG_MSL ((uint32_t)0x00010000) + +/** + * @brief SR1 register flags + */ + +#define I2C_FLAG_SMBALERT ((uint32_t)0x10008000) +#define I2C_FLAG_TIMEOUT ((uint32_t)0x10004000) +#define I2C_FLAG_PECERR ((uint32_t)0x10001000) +#define I2C_FLAG_OVR ((uint32_t)0x10000800) +#define I2C_FLAG_AF ((uint32_t)0x10000400) +#define I2C_FLAG_ARLO ((uint32_t)0x10000200) +#define I2C_FLAG_BERR ((uint32_t)0x10000100) +#define I2C_FLAG_TXE ((uint32_t)0x10000080) +#define I2C_FLAG_RXNE ((uint32_t)0x10000040) +#define I2C_FLAG_STOPF ((uint32_t)0x10000010) +#define I2C_FLAG_ADD10 ((uint32_t)0x10000008) +#define I2C_FLAG_BTF ((uint32_t)0x10000004) +#define I2C_FLAG_ADDR ((uint32_t)0x10000002) +#define I2C_FLAG_SB ((uint32_t)0x10000001) + +#define IS_I2C_CLEAR_FLAG(FLAG) ((((FLAG) & (uint16_t)0x20FF) == 0x00) && ((FLAG) != (uint16_t)0x00)) + +#define IS_I2C_GET_FLAG(FLAG) (((FLAG) == I2C_FLAG_DUALF) || ((FLAG) == I2C_FLAG_SMBHOST) || \ + ((FLAG) == I2C_FLAG_SMBDEFAULT) || ((FLAG) == I2C_FLAG_GENCALL) || \ + ((FLAG) == I2C_FLAG_TRA) || ((FLAG) == I2C_FLAG_BUSY) || \ + ((FLAG) == I2C_FLAG_MSL) || ((FLAG) == I2C_FLAG_SMBALERT) || \ + ((FLAG) == I2C_FLAG_TIMEOUT) || ((FLAG) == I2C_FLAG_PECERR) || \ + ((FLAG) == I2C_FLAG_OVR) || ((FLAG) == I2C_FLAG_AF) || \ + ((FLAG) == I2C_FLAG_ARLO) || ((FLAG) == I2C_FLAG_BERR) || \ + ((FLAG) == I2C_FLAG_TXE) || ((FLAG) == I2C_FLAG_RXNE) || \ + ((FLAG) == I2C_FLAG_STOPF) || ((FLAG) == I2C_FLAG_ADD10) || \ + ((FLAG) == I2C_FLAG_BTF) || ((FLAG) == I2C_FLAG_ADDR) || \ + ((FLAG) == I2C_FLAG_SB)) +/** + * @} + */ + +/** @defgroup I2C_Events + * @{ + */ + +/*======================================== + + I2C Master Events (Events grouped in order of communication) + ==========================================*/ +/** + * @brief Communication start + * + * After sending the START condition (I2C_GenerateSTART() function) the master + * has to wait for this event. It means that the Start condition has been correctly + * released on the I2C bus (the bus is free, no other devices is communicating). + * + */ +/* --EV5 */ +#define I2C_EVENT_MASTER_MODE_SELECT ((uint32_t)0x00030001) /* BUSY, MSL and SB flag */ + +/** + * @brief Address Acknowledge + * + * After checking on EV5 (start condition correctly released on the bus), the + * master sends the address of the slave(s) with which it will communicate + * (I2C_Send7bitAddress() function, it also determines the direction of the communication: + * Master transmitter or Receiver). Then the master has to wait that a slave acknowledges + * his address. If an acknowledge is sent on the bus, one of the following events will + * be set: + * + * 1) In case of Master Receiver (7-bit addressing): the I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED + * event is set. + * + * 2) In case of Master Transmitter (7-bit addressing): the I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED + * is set + * + * 3) In case of 10-Bit addressing mode, the master (just after generating the START + * and checking on EV5) has to send the header of 10-bit addressing mode (I2C_SendData() + * function). Then master should wait on EV9. It means that the 10-bit addressing + * header has been correctly sent on the bus. Then master should send the second part of + * the 10-bit address (LSB) using the function I2C_Send7bitAddress(). Then master + * should wait for event EV6. + * + */ + +/* --EV6 */ +#define I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ((uint32_t)0x00070082) /* BUSY, MSL, ADDR, TXE and TRA flags */ +#define I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ((uint32_t)0x00030002) /* BUSY, MSL and ADDR flags */ +/* --EV9 */ +#define I2C_EVENT_MASTER_MODE_ADDRESS10 ((uint32_t)0x00030008) /* BUSY, MSL and ADD10 flags */ + +/** + * @brief Communication events + * + * If a communication is established (START condition generated and slave address + * acknowledged) then the master has to check on one of the following events for + * communication procedures: + * + * 1) Master Receiver mode: The master has to wait on the event EV7 then to read + * the data received from the slave (I2C_ReceiveData() function). + * + * 2) Master Transmitter mode: The master has to send data (I2C_SendData() + * function) then to wait on event EV8 or EV8_2. + * These two events are similar: + * - EV8 means that the data has been written in the data register and is + * being shifted out. + * - EV8_2 means that the data has been physically shifted out and output + * on the bus. + * In most cases, using EV8 is sufficient for the application. + * Using EV8_2 leads to a slower communication but ensure more reliable test. + * EV8_2 is also more suitable than EV8 for testing on the last data transmission + * (before Stop condition generation). + * + * @note In case the user software does not guarantee that this event EV7 is + * managed before the current byte end of transfer, then user may check on EV7 + * and BTF flag at the same time (ie. (I2C_EVENT_MASTER_BYTE_RECEIVED | I2C_FLAG_BTF)). + * In this case the communication may be slower. + * + */ + +/* Master RECEIVER mode -----------------------------*/ +/* --EV7 */ +#define I2C_EVENT_MASTER_BYTE_RECEIVED ((uint32_t)0x00030040) /* BUSY, MSL and RXNE flags */ + +/* Master TRANSMITTER mode --------------------------*/ +/* --EV8 */ +#define I2C_EVENT_MASTER_BYTE_TRANSMITTING ((uint32_t)0x00070080) /* TRA, BUSY, MSL, TXE flags */ +/* --EV8_2 */ +#define I2C_EVENT_MASTER_BYTE_TRANSMITTED ((uint32_t)0x00070084) /* TRA, BUSY, MSL, TXE and BTF flags */ + + +/*======================================== + + I2C Slave Events (Events grouped in order of communication) + ==========================================*/ + +/** + * @brief Communication start events + * + * Wait on one of these events at the start of the communication. It means that + * the I2C peripheral detected a Start condition on the bus (generated by master + * device) followed by the peripheral address. The peripheral generates an ACK + * condition on the bus (if the acknowledge feature is enabled through function + * I2C_AcknowledgeConfig()) and the events listed above are set : + * + * 1) In normal case (only one address managed by the slave), when the address + * sent by the master matches the own address of the peripheral (configured by + * I2C_OwnAddress1 field) the I2C_EVENT_SLAVE_XXX_ADDRESS_MATCHED event is set + * (where XXX could be TRANSMITTER or RECEIVER). + * + * 2) In case the address sent by the master matches the second address of the + * peripheral (configured by the function I2C_OwnAddress2Config() and enabled + * by the function I2C_DualAddressCmd()) the events I2C_EVENT_SLAVE_XXX_SECONDADDRESS_MATCHED + * (where XXX could be TRANSMITTER or RECEIVER) are set. + * + * 3) In case the address sent by the master is General Call (address 0x00) and + * if the General Call is enabled for the peripheral (using function I2C_GeneralCallCmd()) + * the following event is set I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED. + * + */ + +/* --EV1 (all the events below are variants of EV1) */ +/* 1) Case of One Single Address managed by the slave */ +#define I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED ((uint32_t)0x00020002) /* BUSY and ADDR flags */ +#define I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED ((uint32_t)0x00060082) /* TRA, BUSY, TXE and ADDR flags */ + +/* 2) Case of Dual address managed by the slave */ +#define I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED ((uint32_t)0x00820000) /* DUALF and BUSY flags */ +#define I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED ((uint32_t)0x00860080) /* DUALF, TRA, BUSY and TXE flags */ + +/* 3) Case of General Call enabled for the slave */ +#define I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED ((uint32_t)0x00120000) /* GENCALL and BUSY flags */ + +/** + * @brief Communication events + * + * Wait on one of these events when EV1 has already been checked and: + * + * - Slave RECEIVER mode: + * - EV2: When the application is expecting a data byte to be received. + * - EV4: When the application is expecting the end of the communication: master + * sends a stop condition and data transmission is stopped. + * + * - Slave Transmitter mode: + * - EV3: When a byte has been transmitted by the slave and the application is expecting + * the end of the byte transmission. The two events I2C_EVENT_SLAVE_BYTE_TRANSMITTED and + * I2C_EVENT_SLAVE_BYTE_TRANSMITTING are similar. The second one can optionally be + * used when the user software doesn't guarantee the EV3 is managed before the + * current byte end of transfer. + * - EV3_2: When the master sends a NACK in order to tell slave that data transmission + * shall end (before sending the STOP condition). In this case slave has to stop sending + * data bytes and expect a Stop condition on the bus. + * + * @note In case the user software does not guarantee that the event EV2 is + * managed before the current byte end of transfer, then user may check on EV2 + * and BTF flag at the same time (ie. (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_BTF)). + * In this case the communication may be slower. + * + */ + +/* Slave RECEIVER mode --------------------------*/ +/* --EV2 */ +#define I2C_EVENT_SLAVE_BYTE_RECEIVED ((uint32_t)0x00020040) /* BUSY and RXNE flags */ +/* --EV4 */ +#define I2C_EVENT_SLAVE_STOP_DETECTED ((uint32_t)0x00000010) /* STOPF flag */ + +/* Slave TRANSMITTER mode -----------------------*/ +/* --EV3 */ +#define I2C_EVENT_SLAVE_BYTE_TRANSMITTED ((uint32_t)0x00060084) /* TRA, BUSY, TXE and BTF flags */ +#define I2C_EVENT_SLAVE_BYTE_TRANSMITTING ((uint32_t)0x00060080) /* TRA, BUSY and TXE flags */ +/* --EV3_2 */ +#define I2C_EVENT_SLAVE_ACK_FAILURE ((uint32_t)0x00000400) /* AF flag */ + +/*=========================== End of Events Description ==========================================*/ + +#define IS_I2C_EVENT(EVENT) (((EVENT) == I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED) || \ + ((EVENT) == I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED) || \ + ((EVENT) == I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED) || \ + ((EVENT) == I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED) || \ + ((EVENT) == I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED) || \ + ((EVENT) == I2C_EVENT_SLAVE_BYTE_RECEIVED) || \ + ((EVENT) == (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_DUALF)) || \ + ((EVENT) == (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_GENCALL)) || \ + ((EVENT) == I2C_EVENT_SLAVE_BYTE_TRANSMITTED) || \ + ((EVENT) == (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_DUALF)) || \ + ((EVENT) == (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_GENCALL)) || \ + ((EVENT) == I2C_EVENT_SLAVE_STOP_DETECTED) || \ + ((EVENT) == I2C_EVENT_MASTER_MODE_SELECT) || \ + ((EVENT) == I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) || \ + ((EVENT) == I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) || \ + ((EVENT) == I2C_EVENT_MASTER_BYTE_RECEIVED) || \ + ((EVENT) == I2C_EVENT_MASTER_BYTE_TRANSMITTED) || \ + ((EVENT) == I2C_EVENT_MASTER_BYTE_TRANSMITTING) || \ + ((EVENT) == I2C_EVENT_MASTER_MODE_ADDRESS10) || \ + ((EVENT) == I2C_EVENT_SLAVE_ACK_FAILURE)) +/** + * @} + */ + +/** @defgroup I2C_own_address1 + * @{ + */ + +#define IS_I2C_OWN_ADDRESS1(ADDRESS1) ((ADDRESS1) <= 0x3FF) +/** + * @} + */ + +/** @defgroup I2C_clock_speed + * @{ + */ + +#define IS_I2C_CLOCK_SPEED(SPEED) (((SPEED) >= 0x1) && ((SPEED) <= 400000)) +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup I2C_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup I2C_Exported_Functions + * @{ + */ + +void I2C_DeInit(I2C_TypeDef* I2Cx); +void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct); +void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct); +void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_DMALastTransferCmd(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_OwnAddress2Config(I2C_TypeDef* I2Cx, uint8_t Address); +void I2C_DualAddressCmd(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_GeneralCallCmd(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_ITConfig(I2C_TypeDef* I2Cx, uint16_t I2C_IT, FunctionalState NewState); +void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data); +uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx); +void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction); +uint16_t I2C_ReadRegister(I2C_TypeDef* I2Cx, uint8_t I2C_Register); +void I2C_SoftwareResetCmd(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_NACKPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_NACKPosition); +void I2C_SMBusAlertConfig(I2C_TypeDef* I2Cx, uint16_t I2C_SMBusAlert); +void I2C_TransmitPEC(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_PECPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_PECPosition); +void I2C_CalculatePEC(I2C_TypeDef* I2Cx, FunctionalState NewState); +uint8_t I2C_GetPEC(I2C_TypeDef* I2Cx); +void I2C_ARPCmd(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_StretchClockCmd(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_FastModeDutyCycleConfig(I2C_TypeDef* I2Cx, uint16_t I2C_DutyCycle); + +/** + * @brief + **************************************************************************************** + * + * I2C State Monitoring Functions + * + **************************************************************************************** + * This I2C driver provides three different ways for I2C state monitoring + * depending on the application requirements and constraints: + * + * + * 1) Basic state monitoring: + * Using I2C_CheckEvent() function: + * It compares the status registers (SR1 and SR2) content to a given event + * (can be the combination of one or more flags). + * It returns SUCCESS if the current status includes the given flags + * and returns ERROR if one or more flags are missing in the current status. + * - When to use: + * - This function is suitable for most applications as well as for startup + * activity since the events are fully described in the product reference manual + * (RM0008). + * - It is also suitable for users who need to define their own events. + * - Limitations: + * - If an error occurs (ie. error flags are set besides to the monitored flags), + * the I2C_CheckEvent() function may return SUCCESS despite the communication + * hold or corrupted real state. + * In this case, it is advised to use error interrupts to monitor the error + * events and handle them in the interrupt IRQ handler. + * + * @note + * For error management, it is advised to use the following functions: + * - I2C_ITConfig() to configure and enable the error interrupts (I2C_IT_ERR). + * - I2Cx_ER_IRQHandler() which is called when the error interrupt occurs. + * Where x is the peripheral instance (I2C1, I2C2 ...) + * - I2C_GetFlagStatus() or I2C_GetITStatus() to be called into I2Cx_ER_IRQHandler() + * in order to determine which error occurred. + * - I2C_ClearFlag() or I2C_ClearITPendingBit() and/or I2C_SoftwareResetCmd() + * and/or I2C_GenerateStop() in order to clear the error flag and source, + * and return to correct communication status. + * + * + * 2) Advanced state monitoring: + * Using the function I2C_GetLastEvent() which returns the image of both status + * registers in a single word (uint32_t) (Status Register 2 value is shifted left + * by 16 bits and concatenated to Status Register 1). + * - When to use: + * - This function is suitable for the same applications above but it allows to + * overcome the limitations of I2C_GetFlagStatus() function (see below). + * The returned value could be compared to events already defined in the + * library (stm32f10x_i2c.h) or to custom values defined by user. + * - This function is suitable when multiple flags are monitored at the same time. + * - At the opposite of I2C_CheckEvent() function, this function allows user to + * choose when an event is accepted (when all events flags are set and no + * other flags are set or just when the needed flags are set like + * I2C_CheckEvent() function). + * - Limitations: + * - User may need to define his own events. + * - Same remark concerning the error management is applicable for this + * function if user decides to check only regular communication flags (and + * ignores error flags). + * + * + * 3) Flag-based state monitoring: + * Using the function I2C_GetFlagStatus() which simply returns the status of + * one single flag (ie. I2C_FLAG_RXNE ...). + * - When to use: + * - This function could be used for specific applications or in debug phase. + * - It is suitable when only one flag checking is needed (most I2C events + * are monitored through multiple flags). + * - Limitations: + * - When calling this function, the Status register is accessed. Some flags are + * cleared when the status register is accessed. So checking the status + * of one Flag, may clear other ones. + * - Function may need to be called twice or more in order to monitor one + * single event. + * + */ + +/** + * + * 1) Basic state monitoring + ******************************************************************************* + */ +ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT); +/** + * + * 2) Advanced state monitoring + ******************************************************************************* + */ +uint32_t I2C_GetLastEvent(I2C_TypeDef* I2Cx); +/** + * + * 3) Flag-based state monitoring + ******************************************************************************* + */ +FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG); +/** + * + ******************************************************************************* + */ + +void I2C_ClearFlag(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG); +ITStatus I2C_GetITStatus(I2C_TypeDef* I2Cx, uint32_t I2C_IT); +void I2C_ClearITPendingBit(I2C_TypeDef* I2Cx, uint32_t I2C_IT); + +#ifdef __cplusplus +} +#endif + +#endif /*__STM32F10x_I2C_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_iwdg.c b/Library/stm32f10x_iwdg.c new file mode 100644 index 0000000..c7cbf7e --- /dev/null +++ b/Library/stm32f10x_iwdg.c @@ -0,0 +1,190 @@ +/** + ****************************************************************************** + * @file stm32f10x_iwdg.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the IWDG firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_iwdg.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup IWDG + * @brief IWDG driver modules + * @{ + */ + +/** @defgroup IWDG_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup IWDG_Private_Defines + * @{ + */ + +/* ---------------------- IWDG registers bit mask ----------------------------*/ + +/* KR register bit mask */ +#define KR_KEY_Reload ((uint16_t)0xAAAA) +#define KR_KEY_Enable ((uint16_t)0xCCCC) + +/** + * @} + */ + +/** @defgroup IWDG_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup IWDG_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup IWDG_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup IWDG_Private_Functions + * @{ + */ + +/** + * @brief Enables or disables write access to IWDG_PR and IWDG_RLR registers. + * @param IWDG_WriteAccess: new state of write access to IWDG_PR and IWDG_RLR registers. + * This parameter can be one of the following values: + * @arg IWDG_WriteAccess_Enable: Enable write access to IWDG_PR and IWDG_RLR registers + * @arg IWDG_WriteAccess_Disable: Disable write access to IWDG_PR and IWDG_RLR registers + * @retval None + */ +void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess) +{ + /* Check the parameters */ + assert_param(IS_IWDG_WRITE_ACCESS(IWDG_WriteAccess)); + IWDG->KR = IWDG_WriteAccess; +} + +/** + * @brief Sets IWDG Prescaler value. + * @param IWDG_Prescaler: specifies the IWDG Prescaler value. + * This parameter can be one of the following values: + * @arg IWDG_Prescaler_4: IWDG prescaler set to 4 + * @arg IWDG_Prescaler_8: IWDG prescaler set to 8 + * @arg IWDG_Prescaler_16: IWDG prescaler set to 16 + * @arg IWDG_Prescaler_32: IWDG prescaler set to 32 + * @arg IWDG_Prescaler_64: IWDG prescaler set to 64 + * @arg IWDG_Prescaler_128: IWDG prescaler set to 128 + * @arg IWDG_Prescaler_256: IWDG prescaler set to 256 + * @retval None + */ +void IWDG_SetPrescaler(uint8_t IWDG_Prescaler) +{ + /* Check the parameters */ + assert_param(IS_IWDG_PRESCALER(IWDG_Prescaler)); + IWDG->PR = IWDG_Prescaler; +} + +/** + * @brief Sets IWDG Reload value. + * @param Reload: specifies the IWDG Reload value. + * This parameter must be a number between 0 and 0x0FFF. + * @retval None + */ +void IWDG_SetReload(uint16_t Reload) +{ + /* Check the parameters */ + assert_param(IS_IWDG_RELOAD(Reload)); + IWDG->RLR = Reload; +} + +/** + * @brief Reloads IWDG counter with value defined in the reload register + * (write access to IWDG_PR and IWDG_RLR registers disabled). + * @param None + * @retval None + */ +void IWDG_ReloadCounter(void) +{ + IWDG->KR = KR_KEY_Reload; +} + +/** + * @brief Enables IWDG (write access to IWDG_PR and IWDG_RLR registers disabled). + * @param None + * @retval None + */ +void IWDG_Enable(void) +{ + IWDG->KR = KR_KEY_Enable; +} + +/** + * @brief Checks whether the specified IWDG flag is set or not. + * @param IWDG_FLAG: specifies the flag to check. + * This parameter can be one of the following values: + * @arg IWDG_FLAG_PVU: Prescaler Value Update on going + * @arg IWDG_FLAG_RVU: Reload Value Update on going + * @retval The new state of IWDG_FLAG (SET or RESET). + */ +FlagStatus IWDG_GetFlagStatus(uint16_t IWDG_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_IWDG_FLAG(IWDG_FLAG)); + if ((IWDG->SR & IWDG_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + /* Return the flag status */ + return bitstatus; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_iwdg.h b/Library/stm32f10x_iwdg.h new file mode 100644 index 0000000..25b0bb5 --- /dev/null +++ b/Library/stm32f10x_iwdg.h @@ -0,0 +1,140 @@ +/** + ****************************************************************************** + * @file stm32f10x_iwdg.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the IWDG + * firmware library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_IWDG_H +#define __STM32F10x_IWDG_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup IWDG + * @{ + */ + +/** @defgroup IWDG_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @defgroup IWDG_Exported_Constants + * @{ + */ + +/** @defgroup IWDG_WriteAccess + * @{ + */ + +#define IWDG_WriteAccess_Enable ((uint16_t)0x5555) +#define IWDG_WriteAccess_Disable ((uint16_t)0x0000) +#define IS_IWDG_WRITE_ACCESS(ACCESS) (((ACCESS) == IWDG_WriteAccess_Enable) || \ + ((ACCESS) == IWDG_WriteAccess_Disable)) +/** + * @} + */ + +/** @defgroup IWDG_prescaler + * @{ + */ + +#define IWDG_Prescaler_4 ((uint8_t)0x00) +#define IWDG_Prescaler_8 ((uint8_t)0x01) +#define IWDG_Prescaler_16 ((uint8_t)0x02) +#define IWDG_Prescaler_32 ((uint8_t)0x03) +#define IWDG_Prescaler_64 ((uint8_t)0x04) +#define IWDG_Prescaler_128 ((uint8_t)0x05) +#define IWDG_Prescaler_256 ((uint8_t)0x06) +#define IS_IWDG_PRESCALER(PRESCALER) (((PRESCALER) == IWDG_Prescaler_4) || \ + ((PRESCALER) == IWDG_Prescaler_8) || \ + ((PRESCALER) == IWDG_Prescaler_16) || \ + ((PRESCALER) == IWDG_Prescaler_32) || \ + ((PRESCALER) == IWDG_Prescaler_64) || \ + ((PRESCALER) == IWDG_Prescaler_128)|| \ + ((PRESCALER) == IWDG_Prescaler_256)) +/** + * @} + */ + +/** @defgroup IWDG_Flag + * @{ + */ + +#define IWDG_FLAG_PVU ((uint16_t)0x0001) +#define IWDG_FLAG_RVU ((uint16_t)0x0002) +#define IS_IWDG_FLAG(FLAG) (((FLAG) == IWDG_FLAG_PVU) || ((FLAG) == IWDG_FLAG_RVU)) +#define IS_IWDG_RELOAD(RELOAD) ((RELOAD) <= 0xFFF) +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup IWDG_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup IWDG_Exported_Functions + * @{ + */ + +void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess); +void IWDG_SetPrescaler(uint8_t IWDG_Prescaler); +void IWDG_SetReload(uint16_t Reload); +void IWDG_ReloadCounter(void); +void IWDG_Enable(void); +FlagStatus IWDG_GetFlagStatus(uint16_t IWDG_FLAG); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F10x_IWDG_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_pwr.c b/Library/stm32f10x_pwr.c new file mode 100644 index 0000000..a5a5c57 --- /dev/null +++ b/Library/stm32f10x_pwr.c @@ -0,0 +1,307 @@ +/** + ****************************************************************************** + * @file stm32f10x_pwr.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the PWR firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_pwr.h" +#include "stm32f10x_rcc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup PWR + * @brief PWR driver modules + * @{ + */ + +/** @defgroup PWR_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup PWR_Private_Defines + * @{ + */ + +/* --------- PWR registers bit address in the alias region ---------- */ +#define PWR_OFFSET (PWR_BASE - PERIPH_BASE) + +/* --- CR Register ---*/ + +/* Alias word address of DBP bit */ +#define CR_OFFSET (PWR_OFFSET + 0x00) +#define DBP_BitNumber 0x08 +#define CR_DBP_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (DBP_BitNumber * 4)) + +/* Alias word address of PVDE bit */ +#define PVDE_BitNumber 0x04 +#define CR_PVDE_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PVDE_BitNumber * 4)) + +/* --- CSR Register ---*/ + +/* Alias word address of EWUP bit */ +#define CSR_OFFSET (PWR_OFFSET + 0x04) +#define EWUP_BitNumber 0x08 +#define CSR_EWUP_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (EWUP_BitNumber * 4)) + +/* ------------------ PWR registers bit mask ------------------------ */ + +/* CR register bit mask */ +#define CR_DS_MASK ((uint32_t)0xFFFFFFFC) +#define CR_PLS_MASK ((uint32_t)0xFFFFFF1F) + + +/** + * @} + */ + +/** @defgroup PWR_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup PWR_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup PWR_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup PWR_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the PWR peripheral registers to their default reset values. + * @param None + * @retval None + */ +void PWR_DeInit(void) +{ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_PWR, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_PWR, DISABLE); +} + +/** + * @brief Enables or disables access to the RTC and backup registers. + * @param NewState: new state of the access to the RTC and backup registers. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void PWR_BackupAccessCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + *(__IO uint32_t *) CR_DBP_BB = (uint32_t)NewState; +} + +/** + * @brief Enables or disables the Power Voltage Detector(PVD). + * @param NewState: new state of the PVD. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void PWR_PVDCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + *(__IO uint32_t *) CR_PVDE_BB = (uint32_t)NewState; +} + +/** + * @brief Configures the voltage threshold detected by the Power Voltage Detector(PVD). + * @param PWR_PVDLevel: specifies the PVD detection level + * This parameter can be one of the following values: + * @arg PWR_PVDLevel_2V2: PVD detection level set to 2.2V + * @arg PWR_PVDLevel_2V3: PVD detection level set to 2.3V + * @arg PWR_PVDLevel_2V4: PVD detection level set to 2.4V + * @arg PWR_PVDLevel_2V5: PVD detection level set to 2.5V + * @arg PWR_PVDLevel_2V6: PVD detection level set to 2.6V + * @arg PWR_PVDLevel_2V7: PVD detection level set to 2.7V + * @arg PWR_PVDLevel_2V8: PVD detection level set to 2.8V + * @arg PWR_PVDLevel_2V9: PVD detection level set to 2.9V + * @retval None + */ +void PWR_PVDLevelConfig(uint32_t PWR_PVDLevel) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_PWR_PVD_LEVEL(PWR_PVDLevel)); + tmpreg = PWR->CR; + /* Clear PLS[7:5] bits */ + tmpreg &= CR_PLS_MASK; + /* Set PLS[7:5] bits according to PWR_PVDLevel value */ + tmpreg |= PWR_PVDLevel; + /* Store the new value */ + PWR->CR = tmpreg; +} + +/** + * @brief Enables or disables the WakeUp Pin functionality. + * @param NewState: new state of the WakeUp Pin functionality. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void PWR_WakeUpPinCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + *(__IO uint32_t *) CSR_EWUP_BB = (uint32_t)NewState; +} + +/** + * @brief Enters STOP mode. + * @param PWR_Regulator: specifies the regulator state in STOP mode. + * This parameter can be one of the following values: + * @arg PWR_Regulator_ON: STOP mode with regulator ON + * @arg PWR_Regulator_LowPower: STOP mode with regulator in low power mode + * @param PWR_STOPEntry: specifies if STOP mode in entered with WFI or WFE instruction. + * This parameter can be one of the following values: + * @arg PWR_STOPEntry_WFI: enter STOP mode with WFI instruction + * @arg PWR_STOPEntry_WFE: enter STOP mode with WFE instruction + * @retval None + */ +void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_PWR_REGULATOR(PWR_Regulator)); + assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry)); + + /* Select the regulator state in STOP mode ---------------------------------*/ + tmpreg = PWR->CR; + /* Clear PDDS and LPDS bits */ + tmpreg &= CR_DS_MASK; + /* Set LPDS bit according to PWR_Regulator value */ + tmpreg |= PWR_Regulator; + /* Store the new value */ + PWR->CR = tmpreg; + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP; + + /* Select STOP mode entry --------------------------------------------------*/ + if(PWR_STOPEntry == PWR_STOPEntry_WFI) + { + /* Request Wait For Interrupt */ + __WFI(); + } + else + { + /* Request Wait For Event */ + __WFE(); + } + + /* Reset SLEEPDEEP bit of Cortex System Control Register */ + SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP); +} + +/** + * @brief Enters STANDBY mode. + * @param None + * @retval None + */ +void PWR_EnterSTANDBYMode(void) +{ + /* Clear Wake-up flag */ + PWR->CR |= PWR_CR_CWUF; + /* Select STANDBY mode */ + PWR->CR |= PWR_CR_PDDS; + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP; +/* This option is used to ensure that store operations are completed */ +#if defined ( __CC_ARM ) + __force_stores(); +#endif + /* Request Wait For Interrupt */ + __WFI(); +} + +/** + * @brief Checks whether the specified PWR flag is set or not. + * @param PWR_FLAG: specifies the flag to check. + * This parameter can be one of the following values: + * @arg PWR_FLAG_WU: Wake Up flag + * @arg PWR_FLAG_SB: StandBy flag + * @arg PWR_FLAG_PVDO: PVD Output + * @retval The new state of PWR_FLAG (SET or RESET). + */ +FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_PWR_GET_FLAG(PWR_FLAG)); + + if ((PWR->CSR & PWR_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + /* Return the flag status */ + return bitstatus; +} + +/** + * @brief Clears the PWR's pending flags. + * @param PWR_FLAG: specifies the flag to clear. + * This parameter can be one of the following values: + * @arg PWR_FLAG_WU: Wake Up flag + * @arg PWR_FLAG_SB: StandBy flag + * @retval None + */ +void PWR_ClearFlag(uint32_t PWR_FLAG) +{ + /* Check the parameters */ + assert_param(IS_PWR_CLEAR_FLAG(PWR_FLAG)); + + PWR->CR |= PWR_FLAG << 2; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_pwr.h b/Library/stm32f10x_pwr.h new file mode 100644 index 0000000..1c025e2 --- /dev/null +++ b/Library/stm32f10x_pwr.h @@ -0,0 +1,156 @@ +/** + ****************************************************************************** + * @file stm32f10x_pwr.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the PWR firmware + * library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_PWR_H +#define __STM32F10x_PWR_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup PWR + * @{ + */ + +/** @defgroup PWR_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @defgroup PWR_Exported_Constants + * @{ + */ + +/** @defgroup PVD_detection_level + * @{ + */ + +#define PWR_PVDLevel_2V2 ((uint32_t)0x00000000) +#define PWR_PVDLevel_2V3 ((uint32_t)0x00000020) +#define PWR_PVDLevel_2V4 ((uint32_t)0x00000040) +#define PWR_PVDLevel_2V5 ((uint32_t)0x00000060) +#define PWR_PVDLevel_2V6 ((uint32_t)0x00000080) +#define PWR_PVDLevel_2V7 ((uint32_t)0x000000A0) +#define PWR_PVDLevel_2V8 ((uint32_t)0x000000C0) +#define PWR_PVDLevel_2V9 ((uint32_t)0x000000E0) +#define IS_PWR_PVD_LEVEL(LEVEL) (((LEVEL) == PWR_PVDLevel_2V2) || ((LEVEL) == PWR_PVDLevel_2V3)|| \ + ((LEVEL) == PWR_PVDLevel_2V4) || ((LEVEL) == PWR_PVDLevel_2V5)|| \ + ((LEVEL) == PWR_PVDLevel_2V6) || ((LEVEL) == PWR_PVDLevel_2V7)|| \ + ((LEVEL) == PWR_PVDLevel_2V8) || ((LEVEL) == PWR_PVDLevel_2V9)) +/** + * @} + */ + +/** @defgroup Regulator_state_is_STOP_mode + * @{ + */ + +#define PWR_Regulator_ON ((uint32_t)0x00000000) +#define PWR_Regulator_LowPower ((uint32_t)0x00000001) +#define IS_PWR_REGULATOR(REGULATOR) (((REGULATOR) == PWR_Regulator_ON) || \ + ((REGULATOR) == PWR_Regulator_LowPower)) +/** + * @} + */ + +/** @defgroup STOP_mode_entry + * @{ + */ + +#define PWR_STOPEntry_WFI ((uint8_t)0x01) +#define PWR_STOPEntry_WFE ((uint8_t)0x02) +#define IS_PWR_STOP_ENTRY(ENTRY) (((ENTRY) == PWR_STOPEntry_WFI) || ((ENTRY) == PWR_STOPEntry_WFE)) + +/** + * @} + */ + +/** @defgroup PWR_Flag + * @{ + */ + +#define PWR_FLAG_WU ((uint32_t)0x00000001) +#define PWR_FLAG_SB ((uint32_t)0x00000002) +#define PWR_FLAG_PVDO ((uint32_t)0x00000004) +#define IS_PWR_GET_FLAG(FLAG) (((FLAG) == PWR_FLAG_WU) || ((FLAG) == PWR_FLAG_SB) || \ + ((FLAG) == PWR_FLAG_PVDO)) + +#define IS_PWR_CLEAR_FLAG(FLAG) (((FLAG) == PWR_FLAG_WU) || ((FLAG) == PWR_FLAG_SB)) +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup PWR_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup PWR_Exported_Functions + * @{ + */ + +void PWR_DeInit(void); +void PWR_BackupAccessCmd(FunctionalState NewState); +void PWR_PVDCmd(FunctionalState NewState); +void PWR_PVDLevelConfig(uint32_t PWR_PVDLevel); +void PWR_WakeUpPinCmd(FunctionalState NewState); +void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry); +void PWR_EnterSTANDBYMode(void); +FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG); +void PWR_ClearFlag(uint32_t PWR_FLAG); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F10x_PWR_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_rcc.c b/Library/stm32f10x_rcc.c new file mode 100644 index 0000000..a29034b --- /dev/null +++ b/Library/stm32f10x_rcc.c @@ -0,0 +1,1470 @@ +/** + ****************************************************************************** + * @file stm32f10x_rcc.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the RCC firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_rcc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup RCC + * @brief RCC driver modules + * @{ + */ + +/** @defgroup RCC_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup RCC_Private_Defines + * @{ + */ + +/* ------------ RCC registers bit address in the alias region ----------- */ +#define RCC_OFFSET (RCC_BASE - PERIPH_BASE) + +/* --- CR Register ---*/ + +/* Alias word address of HSION bit */ +#define CR_OFFSET (RCC_OFFSET + 0x00) +#define HSION_BitNumber 0x00 +#define CR_HSION_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (HSION_BitNumber * 4)) + +/* Alias word address of PLLON bit */ +#define PLLON_BitNumber 0x18 +#define CR_PLLON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PLLON_BitNumber * 4)) + +#ifdef STM32F10X_CL + /* Alias word address of PLL2ON bit */ + #define PLL2ON_BitNumber 0x1A + #define CR_PLL2ON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PLL2ON_BitNumber * 4)) + + /* Alias word address of PLL3ON bit */ + #define PLL3ON_BitNumber 0x1C + #define CR_PLL3ON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PLL3ON_BitNumber * 4)) +#endif /* STM32F10X_CL */ + +/* Alias word address of CSSON bit */ +#define CSSON_BitNumber 0x13 +#define CR_CSSON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (CSSON_BitNumber * 4)) + +/* --- CFGR Register ---*/ + +/* Alias word address of USBPRE bit */ +#define CFGR_OFFSET (RCC_OFFSET + 0x04) + +#ifndef STM32F10X_CL + #define USBPRE_BitNumber 0x16 + #define CFGR_USBPRE_BB (PERIPH_BB_BASE + (CFGR_OFFSET * 32) + (USBPRE_BitNumber * 4)) +#else + #define OTGFSPRE_BitNumber 0x16 + #define CFGR_OTGFSPRE_BB (PERIPH_BB_BASE + (CFGR_OFFSET * 32) + (OTGFSPRE_BitNumber * 4)) +#endif /* STM32F10X_CL */ + +/* --- BDCR Register ---*/ + +/* Alias word address of RTCEN bit */ +#define BDCR_OFFSET (RCC_OFFSET + 0x20) +#define RTCEN_BitNumber 0x0F +#define BDCR_RTCEN_BB (PERIPH_BB_BASE + (BDCR_OFFSET * 32) + (RTCEN_BitNumber * 4)) + +/* Alias word address of BDRST bit */ +#define BDRST_BitNumber 0x10 +#define BDCR_BDRST_BB (PERIPH_BB_BASE + (BDCR_OFFSET * 32) + (BDRST_BitNumber * 4)) + +/* --- CSR Register ---*/ + +/* Alias word address of LSION bit */ +#define CSR_OFFSET (RCC_OFFSET + 0x24) +#define LSION_BitNumber 0x00 +#define CSR_LSION_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (LSION_BitNumber * 4)) + +#ifdef STM32F10X_CL +/* --- CFGR2 Register ---*/ + + /* Alias word address of I2S2SRC bit */ + #define CFGR2_OFFSET (RCC_OFFSET + 0x2C) + #define I2S2SRC_BitNumber 0x11 + #define CFGR2_I2S2SRC_BB (PERIPH_BB_BASE + (CFGR2_OFFSET * 32) + (I2S2SRC_BitNumber * 4)) + + /* Alias word address of I2S3SRC bit */ + #define I2S3SRC_BitNumber 0x12 + #define CFGR2_I2S3SRC_BB (PERIPH_BB_BASE + (CFGR2_OFFSET * 32) + (I2S3SRC_BitNumber * 4)) +#endif /* STM32F10X_CL */ + +/* ---------------------- RCC registers bit mask ------------------------ */ + +/* CR register bit mask */ +#define CR_HSEBYP_Reset ((uint32_t)0xFFFBFFFF) +#define CR_HSEBYP_Set ((uint32_t)0x00040000) +#define CR_HSEON_Reset ((uint32_t)0xFFFEFFFF) +#define CR_HSEON_Set ((uint32_t)0x00010000) +#define CR_HSITRIM_Mask ((uint32_t)0xFFFFFF07) + +/* CFGR register bit mask */ +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL) + #define CFGR_PLL_Mask ((uint32_t)0xFFC2FFFF) +#else + #define CFGR_PLL_Mask ((uint32_t)0xFFC0FFFF) +#endif /* STM32F10X_CL */ + +#define CFGR_PLLMull_Mask ((uint32_t)0x003C0000) +#define CFGR_PLLSRC_Mask ((uint32_t)0x00010000) +#define CFGR_PLLXTPRE_Mask ((uint32_t)0x00020000) +#define CFGR_SWS_Mask ((uint32_t)0x0000000C) +#define CFGR_SW_Mask ((uint32_t)0xFFFFFFFC) +#define CFGR_HPRE_Reset_Mask ((uint32_t)0xFFFFFF0F) +#define CFGR_HPRE_Set_Mask ((uint32_t)0x000000F0) +#define CFGR_PPRE1_Reset_Mask ((uint32_t)0xFFFFF8FF) +#define CFGR_PPRE1_Set_Mask ((uint32_t)0x00000700) +#define CFGR_PPRE2_Reset_Mask ((uint32_t)0xFFFFC7FF) +#define CFGR_PPRE2_Set_Mask ((uint32_t)0x00003800) +#define CFGR_ADCPRE_Reset_Mask ((uint32_t)0xFFFF3FFF) +#define CFGR_ADCPRE_Set_Mask ((uint32_t)0x0000C000) + +/* CSR register bit mask */ +#define CSR_RMVF_Set ((uint32_t)0x01000000) + +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL) +/* CFGR2 register bit mask */ + #define CFGR2_PREDIV1SRC ((uint32_t)0x00010000) + #define CFGR2_PREDIV1 ((uint32_t)0x0000000F) +#endif +#ifdef STM32F10X_CL + #define CFGR2_PREDIV2 ((uint32_t)0x000000F0) + #define CFGR2_PLL2MUL ((uint32_t)0x00000F00) + #define CFGR2_PLL3MUL ((uint32_t)0x0000F000) +#endif /* STM32F10X_CL */ + +/* RCC Flag Mask */ +#define FLAG_Mask ((uint8_t)0x1F) + +/* CIR register byte 2 (Bits[15:8]) base address */ +#define CIR_BYTE2_ADDRESS ((uint32_t)0x40021009) + +/* CIR register byte 3 (Bits[23:16]) base address */ +#define CIR_BYTE3_ADDRESS ((uint32_t)0x4002100A) + +/* CFGR register byte 4 (Bits[31:24]) base address */ +#define CFGR_BYTE4_ADDRESS ((uint32_t)0x40021007) + +/* BDCR register base address */ +#define BDCR_ADDRESS (PERIPH_BASE + BDCR_OFFSET) + +/** + * @} + */ + +/** @defgroup RCC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup RCC_Private_Variables + * @{ + */ + +static __I uint8_t APBAHBPrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9}; +static __I uint8_t ADCPrescTable[4] = {2, 4, 6, 8}; + +/** + * @} + */ + +/** @defgroup RCC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup RCC_Private_Functions + * @{ + */ + +/** + * @brief Resets the RCC clock configuration to the default reset state. + * @param None + * @retval None + */ +void RCC_DeInit(void) +{ + /* Set HSION bit */ + RCC->CR |= (uint32_t)0x00000001; + + /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */ +#ifndef STM32F10X_CL + RCC->CFGR &= (uint32_t)0xF8FF0000; +#else + RCC->CFGR &= (uint32_t)0xF0FF0000; +#endif /* STM32F10X_CL */ + + /* Reset HSEON, CSSON and PLLON bits */ + RCC->CR &= (uint32_t)0xFEF6FFFF; + + /* Reset HSEBYP bit */ + RCC->CR &= (uint32_t)0xFFFBFFFF; + + /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */ + RCC->CFGR &= (uint32_t)0xFF80FFFF; + +#ifdef STM32F10X_CL + /* Reset PLL2ON and PLL3ON bits */ + RCC->CR &= (uint32_t)0xEBFFFFFF; + + /* Disable all interrupts and clear pending bits */ + RCC->CIR = 0x00FF0000; + + /* Reset CFGR2 register */ + RCC->CFGR2 = 0x00000000; +#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) + /* Disable all interrupts and clear pending bits */ + RCC->CIR = 0x009F0000; + + /* Reset CFGR2 register */ + RCC->CFGR2 = 0x00000000; +#else + /* Disable all interrupts and clear pending bits */ + RCC->CIR = 0x009F0000; +#endif /* STM32F10X_CL */ + +} + +/** + * @brief Configures the External High Speed oscillator (HSE). + * @note HSE can not be stopped if it is used directly or through the PLL as system clock. + * @param RCC_HSE: specifies the new state of the HSE. + * This parameter can be one of the following values: + * @arg RCC_HSE_OFF: HSE oscillator OFF + * @arg RCC_HSE_ON: HSE oscillator ON + * @arg RCC_HSE_Bypass: HSE oscillator bypassed with external clock + * @retval None + */ +void RCC_HSEConfig(uint32_t RCC_HSE) +{ + /* Check the parameters */ + assert_param(IS_RCC_HSE(RCC_HSE)); + /* Reset HSEON and HSEBYP bits before configuring the HSE ------------------*/ + /* Reset HSEON bit */ + RCC->CR &= CR_HSEON_Reset; + /* Reset HSEBYP bit */ + RCC->CR &= CR_HSEBYP_Reset; + /* Configure HSE (RCC_HSE_OFF is already covered by the code section above) */ + switch(RCC_HSE) + { + case RCC_HSE_ON: + /* Set HSEON bit */ + RCC->CR |= CR_HSEON_Set; + break; + + case RCC_HSE_Bypass: + /* Set HSEBYP and HSEON bits */ + RCC->CR |= CR_HSEBYP_Set | CR_HSEON_Set; + break; + + default: + break; + } +} + +/** + * @brief Waits for HSE start-up. + * @param None + * @retval An ErrorStatus enumuration value: + * - SUCCESS: HSE oscillator is stable and ready to use + * - ERROR: HSE oscillator not yet ready + */ +ErrorStatus RCC_WaitForHSEStartUp(void) +{ + __IO uint32_t StartUpCounter = 0; + ErrorStatus status = ERROR; + FlagStatus HSEStatus = RESET; + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC_GetFlagStatus(RCC_FLAG_HSERDY); + StartUpCounter++; + } while((StartUpCounter != HSE_STARTUP_TIMEOUT) && (HSEStatus == RESET)); + + if (RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET) + { + status = SUCCESS; + } + else + { + status = ERROR; + } + return (status); +} + +/** + * @brief Adjusts the Internal High Speed oscillator (HSI) calibration value. + * @param HSICalibrationValue: specifies the calibration trimming value. + * This parameter must be a number between 0 and 0x1F. + * @retval None + */ +void RCC_AdjustHSICalibrationValue(uint8_t HSICalibrationValue) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_RCC_CALIBRATION_VALUE(HSICalibrationValue)); + tmpreg = RCC->CR; + /* Clear HSITRIM[4:0] bits */ + tmpreg &= CR_HSITRIM_Mask; + /* Set the HSITRIM[4:0] bits according to HSICalibrationValue value */ + tmpreg |= (uint32_t)HSICalibrationValue << 3; + /* Store the new value */ + RCC->CR = tmpreg; +} + +/** + * @brief Enables or disables the Internal High Speed oscillator (HSI). + * @note HSI can not be stopped if it is used directly or through the PLL as system clock. + * @param NewState: new state of the HSI. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_HSICmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + *(__IO uint32_t *) CR_HSION_BB = (uint32_t)NewState; +} + +/** + * @brief Configures the PLL clock source and multiplication factor. + * @note This function must be used only when the PLL is disabled. + * @param RCC_PLLSource: specifies the PLL entry clock source. + * For @b STM32_Connectivity_line_devices or @b STM32_Value_line_devices, + * this parameter can be one of the following values: + * @arg RCC_PLLSource_HSI_Div2: HSI oscillator clock divided by 2 selected as PLL clock entry + * @arg RCC_PLLSource_PREDIV1: PREDIV1 clock selected as PLL clock entry + * For @b other_STM32_devices, this parameter can be one of the following values: + * @arg RCC_PLLSource_HSI_Div2: HSI oscillator clock divided by 2 selected as PLL clock entry + * @arg RCC_PLLSource_HSE_Div1: HSE oscillator clock selected as PLL clock entry + * @arg RCC_PLLSource_HSE_Div2: HSE oscillator clock divided by 2 selected as PLL clock entry + * @param RCC_PLLMul: specifies the PLL multiplication factor. + * For @b STM32_Connectivity_line_devices, this parameter can be RCC_PLLMul_x where x:{[4,9], 6_5} + * For @b other_STM32_devices, this parameter can be RCC_PLLMul_x where x:[2,16] + * @retval None + */ +void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_PLL_SOURCE(RCC_PLLSource)); + assert_param(IS_RCC_PLL_MUL(RCC_PLLMul)); + + tmpreg = RCC->CFGR; + /* Clear PLLSRC, PLLXTPRE and PLLMUL[3:0] bits */ + tmpreg &= CFGR_PLL_Mask; + /* Set the PLL configuration bits */ + tmpreg |= RCC_PLLSource | RCC_PLLMul; + /* Store the new value */ + RCC->CFGR = tmpreg; +} + +/** + * @brief Enables or disables the PLL. + * @note The PLL can not be disabled if it is used as system clock. + * @param NewState: new state of the PLL. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_PLLCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CR_PLLON_BB = (uint32_t)NewState; +} + +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL) +/** + * @brief Configures the PREDIV1 division factor. + * @note + * - This function must be used only when the PLL is disabled. + * - This function applies only to STM32 Connectivity line and Value line + * devices. + * @param RCC_PREDIV1_Source: specifies the PREDIV1 clock source. + * This parameter can be one of the following values: + * @arg RCC_PREDIV1_Source_HSE: HSE selected as PREDIV1 clock + * @arg RCC_PREDIV1_Source_PLL2: PLL2 selected as PREDIV1 clock + * @note + * For @b STM32_Value_line_devices this parameter is always RCC_PREDIV1_Source_HSE + * @param RCC_PREDIV1_Div: specifies the PREDIV1 clock division factor. + * This parameter can be RCC_PREDIV1_Divx where x:[1,16] + * @retval None + */ +void RCC_PREDIV1Config(uint32_t RCC_PREDIV1_Source, uint32_t RCC_PREDIV1_Div) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_PREDIV1_SOURCE(RCC_PREDIV1_Source)); + assert_param(IS_RCC_PREDIV1(RCC_PREDIV1_Div)); + + tmpreg = RCC->CFGR2; + /* Clear PREDIV1[3:0] and PREDIV1SRC bits */ + tmpreg &= ~(CFGR2_PREDIV1 | CFGR2_PREDIV1SRC); + /* Set the PREDIV1 clock source and division factor */ + tmpreg |= RCC_PREDIV1_Source | RCC_PREDIV1_Div ; + /* Store the new value */ + RCC->CFGR2 = tmpreg; +} +#endif + +#ifdef STM32F10X_CL +/** + * @brief Configures the PREDIV2 division factor. + * @note + * - This function must be used only when both PLL2 and PLL3 are disabled. + * - This function applies only to STM32 Connectivity line devices. + * @param RCC_PREDIV2_Div: specifies the PREDIV2 clock division factor. + * This parameter can be RCC_PREDIV2_Divx where x:[1,16] + * @retval None + */ +void RCC_PREDIV2Config(uint32_t RCC_PREDIV2_Div) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_PREDIV2(RCC_PREDIV2_Div)); + + tmpreg = RCC->CFGR2; + /* Clear PREDIV2[3:0] bits */ + tmpreg &= ~CFGR2_PREDIV2; + /* Set the PREDIV2 division factor */ + tmpreg |= RCC_PREDIV2_Div; + /* Store the new value */ + RCC->CFGR2 = tmpreg; +} + +/** + * @brief Configures the PLL2 multiplication factor. + * @note + * - This function must be used only when the PLL2 is disabled. + * - This function applies only to STM32 Connectivity line devices. + * @param RCC_PLL2Mul: specifies the PLL2 multiplication factor. + * This parameter can be RCC_PLL2Mul_x where x:{[8,14], 16, 20} + * @retval None + */ +void RCC_PLL2Config(uint32_t RCC_PLL2Mul) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_PLL2_MUL(RCC_PLL2Mul)); + + tmpreg = RCC->CFGR2; + /* Clear PLL2Mul[3:0] bits */ + tmpreg &= ~CFGR2_PLL2MUL; + /* Set the PLL2 configuration bits */ + tmpreg |= RCC_PLL2Mul; + /* Store the new value */ + RCC->CFGR2 = tmpreg; +} + + +/** + * @brief Enables or disables the PLL2. + * @note + * - The PLL2 can not be disabled if it is used indirectly as system clock + * (i.e. it is used as PLL clock entry that is used as System clock). + * - This function applies only to STM32 Connectivity line devices. + * @param NewState: new state of the PLL2. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_PLL2Cmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CR_PLL2ON_BB = (uint32_t)NewState; +} + + +/** + * @brief Configures the PLL3 multiplication factor. + * @note + * - This function must be used only when the PLL3 is disabled. + * - This function applies only to STM32 Connectivity line devices. + * @param RCC_PLL3Mul: specifies the PLL3 multiplication factor. + * This parameter can be RCC_PLL3Mul_x where x:{[8,14], 16, 20} + * @retval None + */ +void RCC_PLL3Config(uint32_t RCC_PLL3Mul) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_PLL3_MUL(RCC_PLL3Mul)); + + tmpreg = RCC->CFGR2; + /* Clear PLL3Mul[3:0] bits */ + tmpreg &= ~CFGR2_PLL3MUL; + /* Set the PLL3 configuration bits */ + tmpreg |= RCC_PLL3Mul; + /* Store the new value */ + RCC->CFGR2 = tmpreg; +} + + +/** + * @brief Enables or disables the PLL3. + * @note This function applies only to STM32 Connectivity line devices. + * @param NewState: new state of the PLL3. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_PLL3Cmd(FunctionalState NewState) +{ + /* Check the parameters */ + + assert_param(IS_FUNCTIONAL_STATE(NewState)); + *(__IO uint32_t *) CR_PLL3ON_BB = (uint32_t)NewState; +} +#endif /* STM32F10X_CL */ + +/** + * @brief Configures the system clock (SYSCLK). + * @param RCC_SYSCLKSource: specifies the clock source used as system clock. + * This parameter can be one of the following values: + * @arg RCC_SYSCLKSource_HSI: HSI selected as system clock + * @arg RCC_SYSCLKSource_HSE: HSE selected as system clock + * @arg RCC_SYSCLKSource_PLLCLK: PLL selected as system clock + * @retval None + */ +void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_RCC_SYSCLK_SOURCE(RCC_SYSCLKSource)); + tmpreg = RCC->CFGR; + /* Clear SW[1:0] bits */ + tmpreg &= CFGR_SW_Mask; + /* Set SW[1:0] bits according to RCC_SYSCLKSource value */ + tmpreg |= RCC_SYSCLKSource; + /* Store the new value */ + RCC->CFGR = tmpreg; +} + +/** + * @brief Returns the clock source used as system clock. + * @param None + * @retval The clock source used as system clock. The returned value can + * be one of the following: + * - 0x00: HSI used as system clock + * - 0x04: HSE used as system clock + * - 0x08: PLL used as system clock + */ +uint8_t RCC_GetSYSCLKSource(void) +{ + return ((uint8_t)(RCC->CFGR & CFGR_SWS_Mask)); +} + +/** + * @brief Configures the AHB clock (HCLK). + * @param RCC_SYSCLK: defines the AHB clock divider. This clock is derived from + * the system clock (SYSCLK). + * This parameter can be one of the following values: + * @arg RCC_SYSCLK_Div1: AHB clock = SYSCLK + * @arg RCC_SYSCLK_Div2: AHB clock = SYSCLK/2 + * @arg RCC_SYSCLK_Div4: AHB clock = SYSCLK/4 + * @arg RCC_SYSCLK_Div8: AHB clock = SYSCLK/8 + * @arg RCC_SYSCLK_Div16: AHB clock = SYSCLK/16 + * @arg RCC_SYSCLK_Div64: AHB clock = SYSCLK/64 + * @arg RCC_SYSCLK_Div128: AHB clock = SYSCLK/128 + * @arg RCC_SYSCLK_Div256: AHB clock = SYSCLK/256 + * @arg RCC_SYSCLK_Div512: AHB clock = SYSCLK/512 + * @retval None + */ +void RCC_HCLKConfig(uint32_t RCC_SYSCLK) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_RCC_HCLK(RCC_SYSCLK)); + tmpreg = RCC->CFGR; + /* Clear HPRE[3:0] bits */ + tmpreg &= CFGR_HPRE_Reset_Mask; + /* Set HPRE[3:0] bits according to RCC_SYSCLK value */ + tmpreg |= RCC_SYSCLK; + /* Store the new value */ + RCC->CFGR = tmpreg; +} + +/** + * @brief Configures the Low Speed APB clock (PCLK1). + * @param RCC_HCLK: defines the APB1 clock divider. This clock is derived from + * the AHB clock (HCLK). + * This parameter can be one of the following values: + * @arg RCC_HCLK_Div1: APB1 clock = HCLK + * @arg RCC_HCLK_Div2: APB1 clock = HCLK/2 + * @arg RCC_HCLK_Div4: APB1 clock = HCLK/4 + * @arg RCC_HCLK_Div8: APB1 clock = HCLK/8 + * @arg RCC_HCLK_Div16: APB1 clock = HCLK/16 + * @retval None + */ +void RCC_PCLK1Config(uint32_t RCC_HCLK) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_RCC_PCLK(RCC_HCLK)); + tmpreg = RCC->CFGR; + /* Clear PPRE1[2:0] bits */ + tmpreg &= CFGR_PPRE1_Reset_Mask; + /* Set PPRE1[2:0] bits according to RCC_HCLK value */ + tmpreg |= RCC_HCLK; + /* Store the new value */ + RCC->CFGR = tmpreg; +} + +/** + * @brief Configures the High Speed APB clock (PCLK2). + * @param RCC_HCLK: defines the APB2 clock divider. This clock is derived from + * the AHB clock (HCLK). + * This parameter can be one of the following values: + * @arg RCC_HCLK_Div1: APB2 clock = HCLK + * @arg RCC_HCLK_Div2: APB2 clock = HCLK/2 + * @arg RCC_HCLK_Div4: APB2 clock = HCLK/4 + * @arg RCC_HCLK_Div8: APB2 clock = HCLK/8 + * @arg RCC_HCLK_Div16: APB2 clock = HCLK/16 + * @retval None + */ +void RCC_PCLK2Config(uint32_t RCC_HCLK) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_RCC_PCLK(RCC_HCLK)); + tmpreg = RCC->CFGR; + /* Clear PPRE2[2:0] bits */ + tmpreg &= CFGR_PPRE2_Reset_Mask; + /* Set PPRE2[2:0] bits according to RCC_HCLK value */ + tmpreg |= RCC_HCLK << 3; + /* Store the new value */ + RCC->CFGR = tmpreg; +} + +/** + * @brief Enables or disables the specified RCC interrupts. + * @param RCC_IT: specifies the RCC interrupt sources to be enabled or disabled. + * + * For @b STM32_Connectivity_line_devices, this parameter can be any combination + * of the following values + * @arg RCC_IT_LSIRDY: LSI ready interrupt + * @arg RCC_IT_LSERDY: LSE ready interrupt + * @arg RCC_IT_HSIRDY: HSI ready interrupt + * @arg RCC_IT_HSERDY: HSE ready interrupt + * @arg RCC_IT_PLLRDY: PLL ready interrupt + * @arg RCC_IT_PLL2RDY: PLL2 ready interrupt + * @arg RCC_IT_PLL3RDY: PLL3 ready interrupt + * + * For @b other_STM32_devices, this parameter can be any combination of the + * following values + * @arg RCC_IT_LSIRDY: LSI ready interrupt + * @arg RCC_IT_LSERDY: LSE ready interrupt + * @arg RCC_IT_HSIRDY: HSI ready interrupt + * @arg RCC_IT_HSERDY: HSE ready interrupt + * @arg RCC_IT_PLLRDY: PLL ready interrupt + * + * @param NewState: new state of the specified RCC interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_ITConfig(uint8_t RCC_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_IT(RCC_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Perform Byte access to RCC_CIR bits to enable the selected interrupts */ + *(__IO uint8_t *) CIR_BYTE2_ADDRESS |= RCC_IT; + } + else + { + /* Perform Byte access to RCC_CIR bits to disable the selected interrupts */ + *(__IO uint8_t *) CIR_BYTE2_ADDRESS &= (uint8_t)~RCC_IT; + } +} + +#ifndef STM32F10X_CL +/** + * @brief Configures the USB clock (USBCLK). + * @param RCC_USBCLKSource: specifies the USB clock source. This clock is + * derived from the PLL output. + * This parameter can be one of the following values: + * @arg RCC_USBCLKSource_PLLCLK_1Div5: PLL clock divided by 1,5 selected as USB + * clock source + * @arg RCC_USBCLKSource_PLLCLK_Div1: PLL clock selected as USB clock source + * @retval None + */ +void RCC_USBCLKConfig(uint32_t RCC_USBCLKSource) +{ + /* Check the parameters */ + assert_param(IS_RCC_USBCLK_SOURCE(RCC_USBCLKSource)); + + *(__IO uint32_t *) CFGR_USBPRE_BB = RCC_USBCLKSource; +} +#else +/** + * @brief Configures the USB OTG FS clock (OTGFSCLK). + * This function applies only to STM32 Connectivity line devices. + * @param RCC_OTGFSCLKSource: specifies the USB OTG FS clock source. + * This clock is derived from the PLL output. + * This parameter can be one of the following values: + * @arg RCC_OTGFSCLKSource_PLLVCO_Div3: PLL VCO clock divided by 2 selected as USB OTG FS clock source + * @arg RCC_OTGFSCLKSource_PLLVCO_Div2: PLL VCO clock divided by 2 selected as USB OTG FS clock source + * @retval None + */ +void RCC_OTGFSCLKConfig(uint32_t RCC_OTGFSCLKSource) +{ + /* Check the parameters */ + assert_param(IS_RCC_OTGFSCLK_SOURCE(RCC_OTGFSCLKSource)); + + *(__IO uint32_t *) CFGR_OTGFSPRE_BB = RCC_OTGFSCLKSource; +} +#endif /* STM32F10X_CL */ + +/** + * @brief Configures the ADC clock (ADCCLK). + * @param RCC_PCLK2: defines the ADC clock divider. This clock is derived from + * the APB2 clock (PCLK2). + * This parameter can be one of the following values: + * @arg RCC_PCLK2_Div2: ADC clock = PCLK2/2 + * @arg RCC_PCLK2_Div4: ADC clock = PCLK2/4 + * @arg RCC_PCLK2_Div6: ADC clock = PCLK2/6 + * @arg RCC_PCLK2_Div8: ADC clock = PCLK2/8 + * @retval None + */ +void RCC_ADCCLKConfig(uint32_t RCC_PCLK2) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_RCC_ADCCLK(RCC_PCLK2)); + tmpreg = RCC->CFGR; + /* Clear ADCPRE[1:0] bits */ + tmpreg &= CFGR_ADCPRE_Reset_Mask; + /* Set ADCPRE[1:0] bits according to RCC_PCLK2 value */ + tmpreg |= RCC_PCLK2; + /* Store the new value */ + RCC->CFGR = tmpreg; +} + +#ifdef STM32F10X_CL +/** + * @brief Configures the I2S2 clock source(I2S2CLK). + * @note + * - This function must be called before enabling I2S2 APB clock. + * - This function applies only to STM32 Connectivity line devices. + * @param RCC_I2S2CLKSource: specifies the I2S2 clock source. + * This parameter can be one of the following values: + * @arg RCC_I2S2CLKSource_SYSCLK: system clock selected as I2S2 clock entry + * @arg RCC_I2S2CLKSource_PLL3_VCO: PLL3 VCO clock selected as I2S2 clock entry + * @retval None + */ +void RCC_I2S2CLKConfig(uint32_t RCC_I2S2CLKSource) +{ + /* Check the parameters */ + assert_param(IS_RCC_I2S2CLK_SOURCE(RCC_I2S2CLKSource)); + + *(__IO uint32_t *) CFGR2_I2S2SRC_BB = RCC_I2S2CLKSource; +} + +/** + * @brief Configures the I2S3 clock source(I2S2CLK). + * @note + * - This function must be called before enabling I2S3 APB clock. + * - This function applies only to STM32 Connectivity line devices. + * @param RCC_I2S3CLKSource: specifies the I2S3 clock source. + * This parameter can be one of the following values: + * @arg RCC_I2S3CLKSource_SYSCLK: system clock selected as I2S3 clock entry + * @arg RCC_I2S3CLKSource_PLL3_VCO: PLL3 VCO clock selected as I2S3 clock entry + * @retval None + */ +void RCC_I2S3CLKConfig(uint32_t RCC_I2S3CLKSource) +{ + /* Check the parameters */ + assert_param(IS_RCC_I2S3CLK_SOURCE(RCC_I2S3CLKSource)); + + *(__IO uint32_t *) CFGR2_I2S3SRC_BB = RCC_I2S3CLKSource; +} +#endif /* STM32F10X_CL */ + +/** + * @brief Configures the External Low Speed oscillator (LSE). + * @param RCC_LSE: specifies the new state of the LSE. + * This parameter can be one of the following values: + * @arg RCC_LSE_OFF: LSE oscillator OFF + * @arg RCC_LSE_ON: LSE oscillator ON + * @arg RCC_LSE_Bypass: LSE oscillator bypassed with external clock + * @retval None + */ +void RCC_LSEConfig(uint8_t RCC_LSE) +{ + /* Check the parameters */ + assert_param(IS_RCC_LSE(RCC_LSE)); + /* Reset LSEON and LSEBYP bits before configuring the LSE ------------------*/ + /* Reset LSEON bit */ + *(__IO uint8_t *) BDCR_ADDRESS = RCC_LSE_OFF; + /* Reset LSEBYP bit */ + *(__IO uint8_t *) BDCR_ADDRESS = RCC_LSE_OFF; + /* Configure LSE (RCC_LSE_OFF is already covered by the code section above) */ + switch(RCC_LSE) + { + case RCC_LSE_ON: + /* Set LSEON bit */ + *(__IO uint8_t *) BDCR_ADDRESS = RCC_LSE_ON; + break; + + case RCC_LSE_Bypass: + /* Set LSEBYP and LSEON bits */ + *(__IO uint8_t *) BDCR_ADDRESS = RCC_LSE_Bypass | RCC_LSE_ON; + break; + + default: + break; + } +} + +/** + * @brief Enables or disables the Internal Low Speed oscillator (LSI). + * @note LSI can not be disabled if the IWDG is running. + * @param NewState: new state of the LSI. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_LSICmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + *(__IO uint32_t *) CSR_LSION_BB = (uint32_t)NewState; +} + +/** + * @brief Configures the RTC clock (RTCCLK). + * @note Once the RTC clock is selected it can't be changed unless the Backup domain is reset. + * @param RCC_RTCCLKSource: specifies the RTC clock source. + * This parameter can be one of the following values: + * @arg RCC_RTCCLKSource_LSE: LSE selected as RTC clock + * @arg RCC_RTCCLKSource_LSI: LSI selected as RTC clock + * @arg RCC_RTCCLKSource_HSE_Div128: HSE clock divided by 128 selected as RTC clock + * @retval None + */ +void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource) +{ + /* Check the parameters */ + assert_param(IS_RCC_RTCCLK_SOURCE(RCC_RTCCLKSource)); + /* Select the RTC clock source */ + RCC->BDCR |= RCC_RTCCLKSource; +} + +/** + * @brief Enables or disables the RTC clock. + * @note This function must be used only after the RTC clock was selected using the RCC_RTCCLKConfig function. + * @param NewState: new state of the RTC clock. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_RTCCLKCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + *(__IO uint32_t *) BDCR_RTCEN_BB = (uint32_t)NewState; +} + +/** + * @brief Returns the frequencies of different on chip clocks. + * @param RCC_Clocks: pointer to a RCC_ClocksTypeDef structure which will hold + * the clocks frequencies. + * @note The result of this function could be not correct when using + * fractional value for HSE crystal. + * @retval None + */ +void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks) +{ + uint32_t tmp = 0, pllmull = 0, pllsource = 0, presc = 0; + +#ifdef STM32F10X_CL + uint32_t prediv1source = 0, prediv1factor = 0, prediv2factor = 0, pll2mull = 0; +#endif /* STM32F10X_CL */ + +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) + uint32_t prediv1factor = 0; +#endif + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & CFGR_SWS_Mask; + + switch (tmp) + { + case 0x00: /* HSI used as system clock */ + RCC_Clocks->SYSCLK_Frequency = HSI_VALUE; + break; + case 0x04: /* HSE used as system clock */ + RCC_Clocks->SYSCLK_Frequency = HSE_VALUE; + break; + case 0x08: /* PLL used as system clock */ + + /* Get PLL clock source and multiplication factor ----------------------*/ + pllmull = RCC->CFGR & CFGR_PLLMull_Mask; + pllsource = RCC->CFGR & CFGR_PLLSRC_Mask; + +#ifndef STM32F10X_CL + pllmull = ( pllmull >> 18) + 2; + + if (pllsource == 0x00) + {/* HSI oscillator clock divided by 2 selected as PLL clock entry */ + RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE >> 1) * pllmull; + } + else + { + #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) + prediv1factor = (RCC->CFGR2 & CFGR2_PREDIV1) + 1; + /* HSE oscillator clock selected as PREDIV1 clock entry */ + RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE / prediv1factor) * pllmull; + #else + /* HSE selected as PLL clock entry */ + if ((RCC->CFGR & CFGR_PLLXTPRE_Mask) != (uint32_t)RESET) + {/* HSE oscillator clock divided by 2 */ + RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE >> 1) * pllmull; + } + else + { + RCC_Clocks->SYSCLK_Frequency = HSE_VALUE * pllmull; + } + #endif + } +#else + pllmull = pllmull >> 18; + + if (pllmull != 0x0D) + { + pllmull += 2; + } + else + { /* PLL multiplication factor = PLL input clock * 6.5 */ + pllmull = 13 / 2; + } + + if (pllsource == 0x00) + {/* HSI oscillator clock divided by 2 selected as PLL clock entry */ + RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE >> 1) * pllmull; + } + else + {/* PREDIV1 selected as PLL clock entry */ + + /* Get PREDIV1 clock source and division factor */ + prediv1source = RCC->CFGR2 & CFGR2_PREDIV1SRC; + prediv1factor = (RCC->CFGR2 & CFGR2_PREDIV1) + 1; + + if (prediv1source == 0) + { /* HSE oscillator clock selected as PREDIV1 clock entry */ + RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE / prediv1factor) * pllmull; + } + else + {/* PLL2 clock selected as PREDIV1 clock entry */ + + /* Get PREDIV2 division factor and PLL2 multiplication factor */ + prediv2factor = ((RCC->CFGR2 & CFGR2_PREDIV2) >> 4) + 1; + pll2mull = ((RCC->CFGR2 & CFGR2_PLL2MUL) >> 8 ) + 2; + RCC_Clocks->SYSCLK_Frequency = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull; + } + } +#endif /* STM32F10X_CL */ + break; + + default: + RCC_Clocks->SYSCLK_Frequency = HSI_VALUE; + break; + } + + /* Compute HCLK, PCLK1, PCLK2 and ADCCLK clocks frequencies ----------------*/ + /* Get HCLK prescaler */ + tmp = RCC->CFGR & CFGR_HPRE_Set_Mask; + tmp = tmp >> 4; + presc = APBAHBPrescTable[tmp]; + /* HCLK clock frequency */ + RCC_Clocks->HCLK_Frequency = RCC_Clocks->SYSCLK_Frequency >> presc; + /* Get PCLK1 prescaler */ + tmp = RCC->CFGR & CFGR_PPRE1_Set_Mask; + tmp = tmp >> 8; + presc = APBAHBPrescTable[tmp]; + /* PCLK1 clock frequency */ + RCC_Clocks->PCLK1_Frequency = RCC_Clocks->HCLK_Frequency >> presc; + /* Get PCLK2 prescaler */ + tmp = RCC->CFGR & CFGR_PPRE2_Set_Mask; + tmp = tmp >> 11; + presc = APBAHBPrescTable[tmp]; + /* PCLK2 clock frequency */ + RCC_Clocks->PCLK2_Frequency = RCC_Clocks->HCLK_Frequency >> presc; + /* Get ADCCLK prescaler */ + tmp = RCC->CFGR & CFGR_ADCPRE_Set_Mask; + tmp = tmp >> 14; + presc = ADCPrescTable[tmp]; + /* ADCCLK clock frequency */ + RCC_Clocks->ADCCLK_Frequency = RCC_Clocks->PCLK2_Frequency / presc; +} + +/** + * @brief Enables or disables the AHB peripheral clock. + * @param RCC_AHBPeriph: specifies the AHB peripheral to gates its clock. + * + * For @b STM32_Connectivity_line_devices, this parameter can be any combination + * of the following values: + * @arg RCC_AHBPeriph_DMA1 + * @arg RCC_AHBPeriph_DMA2 + * @arg RCC_AHBPeriph_SRAM + * @arg RCC_AHBPeriph_FLITF + * @arg RCC_AHBPeriph_CRC + * @arg RCC_AHBPeriph_OTG_FS + * @arg RCC_AHBPeriph_ETH_MAC + * @arg RCC_AHBPeriph_ETH_MAC_Tx + * @arg RCC_AHBPeriph_ETH_MAC_Rx + * + * For @b other_STM32_devices, this parameter can be any combination of the + * following values: + * @arg RCC_AHBPeriph_DMA1 + * @arg RCC_AHBPeriph_DMA2 + * @arg RCC_AHBPeriph_SRAM + * @arg RCC_AHBPeriph_FLITF + * @arg RCC_AHBPeriph_CRC + * @arg RCC_AHBPeriph_FSMC + * @arg RCC_AHBPeriph_SDIO + * + * @note SRAM and FLITF clock can be disabled only during sleep mode. + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB_PERIPH(RCC_AHBPeriph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->AHBENR |= RCC_AHBPeriph; + } + else + { + RCC->AHBENR &= ~RCC_AHBPeriph; + } +} + +/** + * @brief Enables or disables the High Speed APB (APB2) peripheral clock. + * @param RCC_APB2Periph: specifies the APB2 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB, + * RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE, + * RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG, RCC_APB2Periph_ADC1, + * RCC_APB2Periph_ADC2, RCC_APB2Periph_TIM1, RCC_APB2Periph_SPI1, + * RCC_APB2Periph_TIM8, RCC_APB2Periph_USART1, RCC_APB2Periph_ADC3, + * RCC_APB2Periph_TIM15, RCC_APB2Periph_TIM16, RCC_APB2Periph_TIM17, + * RCC_APB2Periph_TIM9, RCC_APB2Periph_TIM10, RCC_APB2Periph_TIM11 + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + RCC->APB2ENR |= RCC_APB2Periph; + } + else + { + RCC->APB2ENR &= ~RCC_APB2Periph; + } +} + +/** + * @brief Enables or disables the Low Speed APB (APB1) peripheral clock. + * @param RCC_APB1Periph: specifies the APB1 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_APB1Periph_TIM2, RCC_APB1Periph_TIM3, RCC_APB1Periph_TIM4, + * RCC_APB1Periph_TIM5, RCC_APB1Periph_TIM6, RCC_APB1Periph_TIM7, + * RCC_APB1Periph_WWDG, RCC_APB1Periph_SPI2, RCC_APB1Periph_SPI3, + * RCC_APB1Periph_USART2, RCC_APB1Periph_USART3, RCC_APB1Periph_USART4, + * RCC_APB1Periph_USART5, RCC_APB1Periph_I2C1, RCC_APB1Periph_I2C2, + * RCC_APB1Periph_USB, RCC_APB1Periph_CAN1, RCC_APB1Periph_BKP, + * RCC_APB1Periph_PWR, RCC_APB1Periph_DAC, RCC_APB1Periph_CEC, + * RCC_APB1Periph_TIM12, RCC_APB1Periph_TIM13, RCC_APB1Periph_TIM14 + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + RCC->APB1ENR |= RCC_APB1Periph; + } + else + { + RCC->APB1ENR &= ~RCC_APB1Periph; + } +} + +#ifdef STM32F10X_CL +/** + * @brief Forces or releases AHB peripheral reset. + * @note This function applies only to STM32 Connectivity line devices. + * @param RCC_AHBPeriph: specifies the AHB peripheral to reset. + * This parameter can be any combination of the following values: + * @arg RCC_AHBPeriph_OTG_FS + * @arg RCC_AHBPeriph_ETH_MAC + * @param NewState: new state of the specified peripheral reset. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_AHBPeriphResetCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB_PERIPH_RESET(RCC_AHBPeriph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->AHBRSTR |= RCC_AHBPeriph; + } + else + { + RCC->AHBRSTR &= ~RCC_AHBPeriph; + } +} +#endif /* STM32F10X_CL */ + +/** + * @brief Forces or releases High Speed APB (APB2) peripheral reset. + * @param RCC_APB2Periph: specifies the APB2 peripheral to reset. + * This parameter can be any combination of the following values: + * @arg RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB, + * RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE, + * RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG, RCC_APB2Periph_ADC1, + * RCC_APB2Periph_ADC2, RCC_APB2Periph_TIM1, RCC_APB2Periph_SPI1, + * RCC_APB2Periph_TIM8, RCC_APB2Periph_USART1, RCC_APB2Periph_ADC3, + * RCC_APB2Periph_TIM15, RCC_APB2Periph_TIM16, RCC_APB2Periph_TIM17, + * RCC_APB2Periph_TIM9, RCC_APB2Periph_TIM10, RCC_APB2Periph_TIM11 + * @param NewState: new state of the specified peripheral reset. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + RCC->APB2RSTR |= RCC_APB2Periph; + } + else + { + RCC->APB2RSTR &= ~RCC_APB2Periph; + } +} + +/** + * @brief Forces or releases Low Speed APB (APB1) peripheral reset. + * @param RCC_APB1Periph: specifies the APB1 peripheral to reset. + * This parameter can be any combination of the following values: + * @arg RCC_APB1Periph_TIM2, RCC_APB1Periph_TIM3, RCC_APB1Periph_TIM4, + * RCC_APB1Periph_TIM5, RCC_APB1Periph_TIM6, RCC_APB1Periph_TIM7, + * RCC_APB1Periph_WWDG, RCC_APB1Periph_SPI2, RCC_APB1Periph_SPI3, + * RCC_APB1Periph_USART2, RCC_APB1Periph_USART3, RCC_APB1Periph_USART4, + * RCC_APB1Periph_USART5, RCC_APB1Periph_I2C1, RCC_APB1Periph_I2C2, + * RCC_APB1Periph_USB, RCC_APB1Periph_CAN1, RCC_APB1Periph_BKP, + * RCC_APB1Periph_PWR, RCC_APB1Periph_DAC, RCC_APB1Periph_CEC, + * RCC_APB1Periph_TIM12, RCC_APB1Periph_TIM13, RCC_APB1Periph_TIM14 + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + RCC->APB1RSTR |= RCC_APB1Periph; + } + else + { + RCC->APB1RSTR &= ~RCC_APB1Periph; + } +} + +/** + * @brief Forces or releases the Backup domain reset. + * @param NewState: new state of the Backup domain reset. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_BackupResetCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + *(__IO uint32_t *) BDCR_BDRST_BB = (uint32_t)NewState; +} + +/** + * @brief Enables or disables the Clock Security System. + * @param NewState: new state of the Clock Security System.. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_ClockSecuritySystemCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + *(__IO uint32_t *) CR_CSSON_BB = (uint32_t)NewState; +} + +/** + * @brief Selects the clock source to output on MCO pin. + * @param RCC_MCO: specifies the clock source to output. + * + * For @b STM32_Connectivity_line_devices, this parameter can be one of the + * following values: + * @arg RCC_MCO_NoClock: No clock selected + * @arg RCC_MCO_SYSCLK: System clock selected + * @arg RCC_MCO_HSI: HSI oscillator clock selected + * @arg RCC_MCO_HSE: HSE oscillator clock selected + * @arg RCC_MCO_PLLCLK_Div2: PLL clock divided by 2 selected + * @arg RCC_MCO_PLL2CLK: PLL2 clock selected + * @arg RCC_MCO_PLL3CLK_Div2: PLL3 clock divided by 2 selected + * @arg RCC_MCO_XT1: External 3-25 MHz oscillator clock selected + * @arg RCC_MCO_PLL3CLK: PLL3 clock selected + * + * For @b other_STM32_devices, this parameter can be one of the following values: + * @arg RCC_MCO_NoClock: No clock selected + * @arg RCC_MCO_SYSCLK: System clock selected + * @arg RCC_MCO_HSI: HSI oscillator clock selected + * @arg RCC_MCO_HSE: HSE oscillator clock selected + * @arg RCC_MCO_PLLCLK_Div2: PLL clock divided by 2 selected + * + * @retval None + */ +void RCC_MCOConfig(uint8_t RCC_MCO) +{ + /* Check the parameters */ + assert_param(IS_RCC_MCO(RCC_MCO)); + + /* Perform Byte access to MCO bits to select the MCO source */ + *(__IO uint8_t *) CFGR_BYTE4_ADDRESS = RCC_MCO; +} + +/** + * @brief Checks whether the specified RCC flag is set or not. + * @param RCC_FLAG: specifies the flag to check. + * + * For @b STM32_Connectivity_line_devices, this parameter can be one of the + * following values: + * @arg RCC_FLAG_HSIRDY: HSI oscillator clock ready + * @arg RCC_FLAG_HSERDY: HSE oscillator clock ready + * @arg RCC_FLAG_PLLRDY: PLL clock ready + * @arg RCC_FLAG_PLL2RDY: PLL2 clock ready + * @arg RCC_FLAG_PLL3RDY: PLL3 clock ready + * @arg RCC_FLAG_LSERDY: LSE oscillator clock ready + * @arg RCC_FLAG_LSIRDY: LSI oscillator clock ready + * @arg RCC_FLAG_PINRST: Pin reset + * @arg RCC_FLAG_PORRST: POR/PDR reset + * @arg RCC_FLAG_SFTRST: Software reset + * @arg RCC_FLAG_IWDGRST: Independent Watchdog reset + * @arg RCC_FLAG_WWDGRST: Window Watchdog reset + * @arg RCC_FLAG_LPWRRST: Low Power reset + * + * For @b other_STM32_devices, this parameter can be one of the following values: + * @arg RCC_FLAG_HSIRDY: HSI oscillator clock ready + * @arg RCC_FLAG_HSERDY: HSE oscillator clock ready + * @arg RCC_FLAG_PLLRDY: PLL clock ready + * @arg RCC_FLAG_LSERDY: LSE oscillator clock ready + * @arg RCC_FLAG_LSIRDY: LSI oscillator clock ready + * @arg RCC_FLAG_PINRST: Pin reset + * @arg RCC_FLAG_PORRST: POR/PDR reset + * @arg RCC_FLAG_SFTRST: Software reset + * @arg RCC_FLAG_IWDGRST: Independent Watchdog reset + * @arg RCC_FLAG_WWDGRST: Window Watchdog reset + * @arg RCC_FLAG_LPWRRST: Low Power reset + * + * @retval The new state of RCC_FLAG (SET or RESET). + */ +FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG) +{ + uint32_t tmp = 0; + uint32_t statusreg = 0; + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_RCC_FLAG(RCC_FLAG)); + + /* Get the RCC register index */ + tmp = RCC_FLAG >> 5; + if (tmp == 1) /* The flag to check is in CR register */ + { + statusreg = RCC->CR; + } + else if (tmp == 2) /* The flag to check is in BDCR register */ + { + statusreg = RCC->BDCR; + } + else /* The flag to check is in CSR register */ + { + statusreg = RCC->CSR; + } + + /* Get the flag position */ + tmp = RCC_FLAG & FLAG_Mask; + if ((statusreg & ((uint32_t)1 << tmp)) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + /* Return the flag status */ + return bitstatus; +} + +/** + * @brief Clears the RCC reset flags. + * @note The reset flags are: RCC_FLAG_PINRST, RCC_FLAG_PORRST, RCC_FLAG_SFTRST, + * RCC_FLAG_IWDGRST, RCC_FLAG_WWDGRST, RCC_FLAG_LPWRRST + * @param None + * @retval None + */ +void RCC_ClearFlag(void) +{ + /* Set RMVF bit to clear the reset flags */ + RCC->CSR |= CSR_RMVF_Set; +} + +/** + * @brief Checks whether the specified RCC interrupt has occurred or not. + * @param RCC_IT: specifies the RCC interrupt source to check. + * + * For @b STM32_Connectivity_line_devices, this parameter can be one of the + * following values: + * @arg RCC_IT_LSIRDY: LSI ready interrupt + * @arg RCC_IT_LSERDY: LSE ready interrupt + * @arg RCC_IT_HSIRDY: HSI ready interrupt + * @arg RCC_IT_HSERDY: HSE ready interrupt + * @arg RCC_IT_PLLRDY: PLL ready interrupt + * @arg RCC_IT_PLL2RDY: PLL2 ready interrupt + * @arg RCC_IT_PLL3RDY: PLL3 ready interrupt + * @arg RCC_IT_CSS: Clock Security System interrupt + * + * For @b other_STM32_devices, this parameter can be one of the following values: + * @arg RCC_IT_LSIRDY: LSI ready interrupt + * @arg RCC_IT_LSERDY: LSE ready interrupt + * @arg RCC_IT_HSIRDY: HSI ready interrupt + * @arg RCC_IT_HSERDY: HSE ready interrupt + * @arg RCC_IT_PLLRDY: PLL ready interrupt + * @arg RCC_IT_CSS: Clock Security System interrupt + * + * @retval The new state of RCC_IT (SET or RESET). + */ +ITStatus RCC_GetITStatus(uint8_t RCC_IT) +{ + ITStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_RCC_GET_IT(RCC_IT)); + + /* Check the status of the specified RCC interrupt */ + if ((RCC->CIR & RCC_IT) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + /* Return the RCC_IT status */ + return bitstatus; +} + +/** + * @brief Clears the RCC's interrupt pending bits. + * @param RCC_IT: specifies the interrupt pending bit to clear. + * + * For @b STM32_Connectivity_line_devices, this parameter can be any combination + * of the following values: + * @arg RCC_IT_LSIRDY: LSI ready interrupt + * @arg RCC_IT_LSERDY: LSE ready interrupt + * @arg RCC_IT_HSIRDY: HSI ready interrupt + * @arg RCC_IT_HSERDY: HSE ready interrupt + * @arg RCC_IT_PLLRDY: PLL ready interrupt + * @arg RCC_IT_PLL2RDY: PLL2 ready interrupt + * @arg RCC_IT_PLL3RDY: PLL3 ready interrupt + * @arg RCC_IT_CSS: Clock Security System interrupt + * + * For @b other_STM32_devices, this parameter can be any combination of the + * following values: + * @arg RCC_IT_LSIRDY: LSI ready interrupt + * @arg RCC_IT_LSERDY: LSE ready interrupt + * @arg RCC_IT_HSIRDY: HSI ready interrupt + * @arg RCC_IT_HSERDY: HSE ready interrupt + * @arg RCC_IT_PLLRDY: PLL ready interrupt + * + * @arg RCC_IT_CSS: Clock Security System interrupt + * @retval None + */ +void RCC_ClearITPendingBit(uint8_t RCC_IT) +{ + /* Check the parameters */ + assert_param(IS_RCC_CLEAR_IT(RCC_IT)); + + /* Perform Byte access to RCC_CIR[23:16] bits to clear the selected interrupt + pending bits */ + *(__IO uint8_t *) CIR_BYTE3_ADDRESS = RCC_IT; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_rcc.h b/Library/stm32f10x_rcc.h new file mode 100644 index 0000000..1149c34 --- /dev/null +++ b/Library/stm32f10x_rcc.h @@ -0,0 +1,727 @@ +/** + ****************************************************************************** + * @file stm32f10x_rcc.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the RCC firmware + * library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_RCC_H +#define __STM32F10x_RCC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup RCC + * @{ + */ + +/** @defgroup RCC_Exported_Types + * @{ + */ + +typedef struct +{ + uint32_t SYSCLK_Frequency; /*!< returns SYSCLK clock frequency expressed in Hz */ + uint32_t HCLK_Frequency; /*!< returns HCLK clock frequency expressed in Hz */ + uint32_t PCLK1_Frequency; /*!< returns PCLK1 clock frequency expressed in Hz */ + uint32_t PCLK2_Frequency; /*!< returns PCLK2 clock frequency expressed in Hz */ + uint32_t ADCCLK_Frequency; /*!< returns ADCCLK clock frequency expressed in Hz */ +}RCC_ClocksTypeDef; + +/** + * @} + */ + +/** @defgroup RCC_Exported_Constants + * @{ + */ + +/** @defgroup HSE_configuration + * @{ + */ + +#define RCC_HSE_OFF ((uint32_t)0x00000000) +#define RCC_HSE_ON ((uint32_t)0x00010000) +#define RCC_HSE_Bypass ((uint32_t)0x00040000) +#define IS_RCC_HSE(HSE) (((HSE) == RCC_HSE_OFF) || ((HSE) == RCC_HSE_ON) || \ + ((HSE) == RCC_HSE_Bypass)) + +/** + * @} + */ + +/** @defgroup PLL_entry_clock_source + * @{ + */ + +#define RCC_PLLSource_HSI_Div2 ((uint32_t)0x00000000) + +#if !defined (STM32F10X_LD_VL) && !defined (STM32F10X_MD_VL) && !defined (STM32F10X_HD_VL) && !defined (STM32F10X_CL) + #define RCC_PLLSource_HSE_Div1 ((uint32_t)0x00010000) + #define RCC_PLLSource_HSE_Div2 ((uint32_t)0x00030000) + #define IS_RCC_PLL_SOURCE(SOURCE) (((SOURCE) == RCC_PLLSource_HSI_Div2) || \ + ((SOURCE) == RCC_PLLSource_HSE_Div1) || \ + ((SOURCE) == RCC_PLLSource_HSE_Div2)) +#else + #define RCC_PLLSource_PREDIV1 ((uint32_t)0x00010000) + #define IS_RCC_PLL_SOURCE(SOURCE) (((SOURCE) == RCC_PLLSource_HSI_Div2) || \ + ((SOURCE) == RCC_PLLSource_PREDIV1)) +#endif /* STM32F10X_CL */ + +/** + * @} + */ + +/** @defgroup PLL_multiplication_factor + * @{ + */ +#ifndef STM32F10X_CL + #define RCC_PLLMul_2 ((uint32_t)0x00000000) + #define RCC_PLLMul_3 ((uint32_t)0x00040000) + #define RCC_PLLMul_4 ((uint32_t)0x00080000) + #define RCC_PLLMul_5 ((uint32_t)0x000C0000) + #define RCC_PLLMul_6 ((uint32_t)0x00100000) + #define RCC_PLLMul_7 ((uint32_t)0x00140000) + #define RCC_PLLMul_8 ((uint32_t)0x00180000) + #define RCC_PLLMul_9 ((uint32_t)0x001C0000) + #define RCC_PLLMul_10 ((uint32_t)0x00200000) + #define RCC_PLLMul_11 ((uint32_t)0x00240000) + #define RCC_PLLMul_12 ((uint32_t)0x00280000) + #define RCC_PLLMul_13 ((uint32_t)0x002C0000) + #define RCC_PLLMul_14 ((uint32_t)0x00300000) + #define RCC_PLLMul_15 ((uint32_t)0x00340000) + #define RCC_PLLMul_16 ((uint32_t)0x00380000) + #define IS_RCC_PLL_MUL(MUL) (((MUL) == RCC_PLLMul_2) || ((MUL) == RCC_PLLMul_3) || \ + ((MUL) == RCC_PLLMul_4) || ((MUL) == RCC_PLLMul_5) || \ + ((MUL) == RCC_PLLMul_6) || ((MUL) == RCC_PLLMul_7) || \ + ((MUL) == RCC_PLLMul_8) || ((MUL) == RCC_PLLMul_9) || \ + ((MUL) == RCC_PLLMul_10) || ((MUL) == RCC_PLLMul_11) || \ + ((MUL) == RCC_PLLMul_12) || ((MUL) == RCC_PLLMul_13) || \ + ((MUL) == RCC_PLLMul_14) || ((MUL) == RCC_PLLMul_15) || \ + ((MUL) == RCC_PLLMul_16)) + +#else + #define RCC_PLLMul_4 ((uint32_t)0x00080000) + #define RCC_PLLMul_5 ((uint32_t)0x000C0000) + #define RCC_PLLMul_6 ((uint32_t)0x00100000) + #define RCC_PLLMul_7 ((uint32_t)0x00140000) + #define RCC_PLLMul_8 ((uint32_t)0x00180000) + #define RCC_PLLMul_9 ((uint32_t)0x001C0000) + #define RCC_PLLMul_6_5 ((uint32_t)0x00340000) + + #define IS_RCC_PLL_MUL(MUL) (((MUL) == RCC_PLLMul_4) || ((MUL) == RCC_PLLMul_5) || \ + ((MUL) == RCC_PLLMul_6) || ((MUL) == RCC_PLLMul_7) || \ + ((MUL) == RCC_PLLMul_8) || ((MUL) == RCC_PLLMul_9) || \ + ((MUL) == RCC_PLLMul_6_5)) +#endif /* STM32F10X_CL */ +/** + * @} + */ + +/** @defgroup PREDIV1_division_factor + * @{ + */ +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL) + #define RCC_PREDIV1_Div1 ((uint32_t)0x00000000) + #define RCC_PREDIV1_Div2 ((uint32_t)0x00000001) + #define RCC_PREDIV1_Div3 ((uint32_t)0x00000002) + #define RCC_PREDIV1_Div4 ((uint32_t)0x00000003) + #define RCC_PREDIV1_Div5 ((uint32_t)0x00000004) + #define RCC_PREDIV1_Div6 ((uint32_t)0x00000005) + #define RCC_PREDIV1_Div7 ((uint32_t)0x00000006) + #define RCC_PREDIV1_Div8 ((uint32_t)0x00000007) + #define RCC_PREDIV1_Div9 ((uint32_t)0x00000008) + #define RCC_PREDIV1_Div10 ((uint32_t)0x00000009) + #define RCC_PREDIV1_Div11 ((uint32_t)0x0000000A) + #define RCC_PREDIV1_Div12 ((uint32_t)0x0000000B) + #define RCC_PREDIV1_Div13 ((uint32_t)0x0000000C) + #define RCC_PREDIV1_Div14 ((uint32_t)0x0000000D) + #define RCC_PREDIV1_Div15 ((uint32_t)0x0000000E) + #define RCC_PREDIV1_Div16 ((uint32_t)0x0000000F) + + #define IS_RCC_PREDIV1(PREDIV1) (((PREDIV1) == RCC_PREDIV1_Div1) || ((PREDIV1) == RCC_PREDIV1_Div2) || \ + ((PREDIV1) == RCC_PREDIV1_Div3) || ((PREDIV1) == RCC_PREDIV1_Div4) || \ + ((PREDIV1) == RCC_PREDIV1_Div5) || ((PREDIV1) == RCC_PREDIV1_Div6) || \ + ((PREDIV1) == RCC_PREDIV1_Div7) || ((PREDIV1) == RCC_PREDIV1_Div8) || \ + ((PREDIV1) == RCC_PREDIV1_Div9) || ((PREDIV1) == RCC_PREDIV1_Div10) || \ + ((PREDIV1) == RCC_PREDIV1_Div11) || ((PREDIV1) == RCC_PREDIV1_Div12) || \ + ((PREDIV1) == RCC_PREDIV1_Div13) || ((PREDIV1) == RCC_PREDIV1_Div14) || \ + ((PREDIV1) == RCC_PREDIV1_Div15) || ((PREDIV1) == RCC_PREDIV1_Div16)) +#endif +/** + * @} + */ + + +/** @defgroup PREDIV1_clock_source + * @{ + */ +#ifdef STM32F10X_CL +/* PREDIV1 clock source (for STM32 connectivity line devices) */ + #define RCC_PREDIV1_Source_HSE ((uint32_t)0x00000000) + #define RCC_PREDIV1_Source_PLL2 ((uint32_t)0x00010000) + + #define IS_RCC_PREDIV1_SOURCE(SOURCE) (((SOURCE) == RCC_PREDIV1_Source_HSE) || \ + ((SOURCE) == RCC_PREDIV1_Source_PLL2)) +#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) +/* PREDIV1 clock source (for STM32 Value line devices) */ + #define RCC_PREDIV1_Source_HSE ((uint32_t)0x00000000) + + #define IS_RCC_PREDIV1_SOURCE(SOURCE) (((SOURCE) == RCC_PREDIV1_Source_HSE)) +#endif +/** + * @} + */ + +#ifdef STM32F10X_CL +/** @defgroup PREDIV2_division_factor + * @{ + */ + + #define RCC_PREDIV2_Div1 ((uint32_t)0x00000000) + #define RCC_PREDIV2_Div2 ((uint32_t)0x00000010) + #define RCC_PREDIV2_Div3 ((uint32_t)0x00000020) + #define RCC_PREDIV2_Div4 ((uint32_t)0x00000030) + #define RCC_PREDIV2_Div5 ((uint32_t)0x00000040) + #define RCC_PREDIV2_Div6 ((uint32_t)0x00000050) + #define RCC_PREDIV2_Div7 ((uint32_t)0x00000060) + #define RCC_PREDIV2_Div8 ((uint32_t)0x00000070) + #define RCC_PREDIV2_Div9 ((uint32_t)0x00000080) + #define RCC_PREDIV2_Div10 ((uint32_t)0x00000090) + #define RCC_PREDIV2_Div11 ((uint32_t)0x000000A0) + #define RCC_PREDIV2_Div12 ((uint32_t)0x000000B0) + #define RCC_PREDIV2_Div13 ((uint32_t)0x000000C0) + #define RCC_PREDIV2_Div14 ((uint32_t)0x000000D0) + #define RCC_PREDIV2_Div15 ((uint32_t)0x000000E0) + #define RCC_PREDIV2_Div16 ((uint32_t)0x000000F0) + + #define IS_RCC_PREDIV2(PREDIV2) (((PREDIV2) == RCC_PREDIV2_Div1) || ((PREDIV2) == RCC_PREDIV2_Div2) || \ + ((PREDIV2) == RCC_PREDIV2_Div3) || ((PREDIV2) == RCC_PREDIV2_Div4) || \ + ((PREDIV2) == RCC_PREDIV2_Div5) || ((PREDIV2) == RCC_PREDIV2_Div6) || \ + ((PREDIV2) == RCC_PREDIV2_Div7) || ((PREDIV2) == RCC_PREDIV2_Div8) || \ + ((PREDIV2) == RCC_PREDIV2_Div9) || ((PREDIV2) == RCC_PREDIV2_Div10) || \ + ((PREDIV2) == RCC_PREDIV2_Div11) || ((PREDIV2) == RCC_PREDIV2_Div12) || \ + ((PREDIV2) == RCC_PREDIV2_Div13) || ((PREDIV2) == RCC_PREDIV2_Div14) || \ + ((PREDIV2) == RCC_PREDIV2_Div15) || ((PREDIV2) == RCC_PREDIV2_Div16)) +/** + * @} + */ + + +/** @defgroup PLL2_multiplication_factor + * @{ + */ + + #define RCC_PLL2Mul_8 ((uint32_t)0x00000600) + #define RCC_PLL2Mul_9 ((uint32_t)0x00000700) + #define RCC_PLL2Mul_10 ((uint32_t)0x00000800) + #define RCC_PLL2Mul_11 ((uint32_t)0x00000900) + #define RCC_PLL2Mul_12 ((uint32_t)0x00000A00) + #define RCC_PLL2Mul_13 ((uint32_t)0x00000B00) + #define RCC_PLL2Mul_14 ((uint32_t)0x00000C00) + #define RCC_PLL2Mul_16 ((uint32_t)0x00000E00) + #define RCC_PLL2Mul_20 ((uint32_t)0x00000F00) + + #define IS_RCC_PLL2_MUL(MUL) (((MUL) == RCC_PLL2Mul_8) || ((MUL) == RCC_PLL2Mul_9) || \ + ((MUL) == RCC_PLL2Mul_10) || ((MUL) == RCC_PLL2Mul_11) || \ + ((MUL) == RCC_PLL2Mul_12) || ((MUL) == RCC_PLL2Mul_13) || \ + ((MUL) == RCC_PLL2Mul_14) || ((MUL) == RCC_PLL2Mul_16) || \ + ((MUL) == RCC_PLL2Mul_20)) +/** + * @} + */ + + +/** @defgroup PLL3_multiplication_factor + * @{ + */ + + #define RCC_PLL3Mul_8 ((uint32_t)0x00006000) + #define RCC_PLL3Mul_9 ((uint32_t)0x00007000) + #define RCC_PLL3Mul_10 ((uint32_t)0x00008000) + #define RCC_PLL3Mul_11 ((uint32_t)0x00009000) + #define RCC_PLL3Mul_12 ((uint32_t)0x0000A000) + #define RCC_PLL3Mul_13 ((uint32_t)0x0000B000) + #define RCC_PLL3Mul_14 ((uint32_t)0x0000C000) + #define RCC_PLL3Mul_16 ((uint32_t)0x0000E000) + #define RCC_PLL3Mul_20 ((uint32_t)0x0000F000) + + #define IS_RCC_PLL3_MUL(MUL) (((MUL) == RCC_PLL3Mul_8) || ((MUL) == RCC_PLL3Mul_9) || \ + ((MUL) == RCC_PLL3Mul_10) || ((MUL) == RCC_PLL3Mul_11) || \ + ((MUL) == RCC_PLL3Mul_12) || ((MUL) == RCC_PLL3Mul_13) || \ + ((MUL) == RCC_PLL3Mul_14) || ((MUL) == RCC_PLL3Mul_16) || \ + ((MUL) == RCC_PLL3Mul_20)) +/** + * @} + */ + +#endif /* STM32F10X_CL */ + + +/** @defgroup System_clock_source + * @{ + */ + +#define RCC_SYSCLKSource_HSI ((uint32_t)0x00000000) +#define RCC_SYSCLKSource_HSE ((uint32_t)0x00000001) +#define RCC_SYSCLKSource_PLLCLK ((uint32_t)0x00000002) +#define IS_RCC_SYSCLK_SOURCE(SOURCE) (((SOURCE) == RCC_SYSCLKSource_HSI) || \ + ((SOURCE) == RCC_SYSCLKSource_HSE) || \ + ((SOURCE) == RCC_SYSCLKSource_PLLCLK)) +/** + * @} + */ + +/** @defgroup AHB_clock_source + * @{ + */ + +#define RCC_SYSCLK_Div1 ((uint32_t)0x00000000) +#define RCC_SYSCLK_Div2 ((uint32_t)0x00000080) +#define RCC_SYSCLK_Div4 ((uint32_t)0x00000090) +#define RCC_SYSCLK_Div8 ((uint32_t)0x000000A0) +#define RCC_SYSCLK_Div16 ((uint32_t)0x000000B0) +#define RCC_SYSCLK_Div64 ((uint32_t)0x000000C0) +#define RCC_SYSCLK_Div128 ((uint32_t)0x000000D0) +#define RCC_SYSCLK_Div256 ((uint32_t)0x000000E0) +#define RCC_SYSCLK_Div512 ((uint32_t)0x000000F0) +#define IS_RCC_HCLK(HCLK) (((HCLK) == RCC_SYSCLK_Div1) || ((HCLK) == RCC_SYSCLK_Div2) || \ + ((HCLK) == RCC_SYSCLK_Div4) || ((HCLK) == RCC_SYSCLK_Div8) || \ + ((HCLK) == RCC_SYSCLK_Div16) || ((HCLK) == RCC_SYSCLK_Div64) || \ + ((HCLK) == RCC_SYSCLK_Div128) || ((HCLK) == RCC_SYSCLK_Div256) || \ + ((HCLK) == RCC_SYSCLK_Div512)) +/** + * @} + */ + +/** @defgroup APB1_APB2_clock_source + * @{ + */ + +#define RCC_HCLK_Div1 ((uint32_t)0x00000000) +#define RCC_HCLK_Div2 ((uint32_t)0x00000400) +#define RCC_HCLK_Div4 ((uint32_t)0x00000500) +#define RCC_HCLK_Div8 ((uint32_t)0x00000600) +#define RCC_HCLK_Div16 ((uint32_t)0x00000700) +#define IS_RCC_PCLK(PCLK) (((PCLK) == RCC_HCLK_Div1) || ((PCLK) == RCC_HCLK_Div2) || \ + ((PCLK) == RCC_HCLK_Div4) || ((PCLK) == RCC_HCLK_Div8) || \ + ((PCLK) == RCC_HCLK_Div16)) +/** + * @} + */ + +/** @defgroup RCC_Interrupt_source + * @{ + */ + +#define RCC_IT_LSIRDY ((uint8_t)0x01) +#define RCC_IT_LSERDY ((uint8_t)0x02) +#define RCC_IT_HSIRDY ((uint8_t)0x04) +#define RCC_IT_HSERDY ((uint8_t)0x08) +#define RCC_IT_PLLRDY ((uint8_t)0x10) +#define RCC_IT_CSS ((uint8_t)0x80) + +#ifndef STM32F10X_CL + #define IS_RCC_IT(IT) ((((IT) & (uint8_t)0xE0) == 0x00) && ((IT) != 0x00)) + #define IS_RCC_GET_IT(IT) (((IT) == RCC_IT_LSIRDY) || ((IT) == RCC_IT_LSERDY) || \ + ((IT) == RCC_IT_HSIRDY) || ((IT) == RCC_IT_HSERDY) || \ + ((IT) == RCC_IT_PLLRDY) || ((IT) == RCC_IT_CSS)) + #define IS_RCC_CLEAR_IT(IT) ((((IT) & (uint8_t)0x60) == 0x00) && ((IT) != 0x00)) +#else + #define RCC_IT_PLL2RDY ((uint8_t)0x20) + #define RCC_IT_PLL3RDY ((uint8_t)0x40) + #define IS_RCC_IT(IT) ((((IT) & (uint8_t)0x80) == 0x00) && ((IT) != 0x00)) + #define IS_RCC_GET_IT(IT) (((IT) == RCC_IT_LSIRDY) || ((IT) == RCC_IT_LSERDY) || \ + ((IT) == RCC_IT_HSIRDY) || ((IT) == RCC_IT_HSERDY) || \ + ((IT) == RCC_IT_PLLRDY) || ((IT) == RCC_IT_CSS) || \ + ((IT) == RCC_IT_PLL2RDY) || ((IT) == RCC_IT_PLL3RDY)) + #define IS_RCC_CLEAR_IT(IT) ((IT) != 0x00) +#endif /* STM32F10X_CL */ + + +/** + * @} + */ + +#ifndef STM32F10X_CL +/** @defgroup USB_Device_clock_source + * @{ + */ + + #define RCC_USBCLKSource_PLLCLK_1Div5 ((uint8_t)0x00) + #define RCC_USBCLKSource_PLLCLK_Div1 ((uint8_t)0x01) + + #define IS_RCC_USBCLK_SOURCE(SOURCE) (((SOURCE) == RCC_USBCLKSource_PLLCLK_1Div5) || \ + ((SOURCE) == RCC_USBCLKSource_PLLCLK_Div1)) +/** + * @} + */ +#else +/** @defgroup USB_OTG_FS_clock_source + * @{ + */ + #define RCC_OTGFSCLKSource_PLLVCO_Div3 ((uint8_t)0x00) + #define RCC_OTGFSCLKSource_PLLVCO_Div2 ((uint8_t)0x01) + + #define IS_RCC_OTGFSCLK_SOURCE(SOURCE) (((SOURCE) == RCC_OTGFSCLKSource_PLLVCO_Div3) || \ + ((SOURCE) == RCC_OTGFSCLKSource_PLLVCO_Div2)) +/** + * @} + */ +#endif /* STM32F10X_CL */ + + +#ifdef STM32F10X_CL +/** @defgroup I2S2_clock_source + * @{ + */ + #define RCC_I2S2CLKSource_SYSCLK ((uint8_t)0x00) + #define RCC_I2S2CLKSource_PLL3_VCO ((uint8_t)0x01) + + #define IS_RCC_I2S2CLK_SOURCE(SOURCE) (((SOURCE) == RCC_I2S2CLKSource_SYSCLK) || \ + ((SOURCE) == RCC_I2S2CLKSource_PLL3_VCO)) +/** + * @} + */ + +/** @defgroup I2S3_clock_source + * @{ + */ + #define RCC_I2S3CLKSource_SYSCLK ((uint8_t)0x00) + #define RCC_I2S3CLKSource_PLL3_VCO ((uint8_t)0x01) + + #define IS_RCC_I2S3CLK_SOURCE(SOURCE) (((SOURCE) == RCC_I2S3CLKSource_SYSCLK) || \ + ((SOURCE) == RCC_I2S3CLKSource_PLL3_VCO)) +/** + * @} + */ +#endif /* STM32F10X_CL */ + + +/** @defgroup ADC_clock_source + * @{ + */ + +#define RCC_PCLK2_Div2 ((uint32_t)0x00000000) +#define RCC_PCLK2_Div4 ((uint32_t)0x00004000) +#define RCC_PCLK2_Div6 ((uint32_t)0x00008000) +#define RCC_PCLK2_Div8 ((uint32_t)0x0000C000) +#define IS_RCC_ADCCLK(ADCCLK) (((ADCCLK) == RCC_PCLK2_Div2) || ((ADCCLK) == RCC_PCLK2_Div4) || \ + ((ADCCLK) == RCC_PCLK2_Div6) || ((ADCCLK) == RCC_PCLK2_Div8)) +/** + * @} + */ + +/** @defgroup LSE_configuration + * @{ + */ + +#define RCC_LSE_OFF ((uint8_t)0x00) +#define RCC_LSE_ON ((uint8_t)0x01) +#define RCC_LSE_Bypass ((uint8_t)0x04) +#define IS_RCC_LSE(LSE) (((LSE) == RCC_LSE_OFF) || ((LSE) == RCC_LSE_ON) || \ + ((LSE) == RCC_LSE_Bypass)) +/** + * @} + */ + +/** @defgroup RTC_clock_source + * @{ + */ + +#define RCC_RTCCLKSource_LSE ((uint32_t)0x00000100) +#define RCC_RTCCLKSource_LSI ((uint32_t)0x00000200) +#define RCC_RTCCLKSource_HSE_Div128 ((uint32_t)0x00000300) +#define IS_RCC_RTCCLK_SOURCE(SOURCE) (((SOURCE) == RCC_RTCCLKSource_LSE) || \ + ((SOURCE) == RCC_RTCCLKSource_LSI) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div128)) +/** + * @} + */ + +/** @defgroup AHB_peripheral + * @{ + */ + +#define RCC_AHBPeriph_DMA1 ((uint32_t)0x00000001) +#define RCC_AHBPeriph_DMA2 ((uint32_t)0x00000002) +#define RCC_AHBPeriph_SRAM ((uint32_t)0x00000004) +#define RCC_AHBPeriph_FLITF ((uint32_t)0x00000010) +#define RCC_AHBPeriph_CRC ((uint32_t)0x00000040) + +#ifndef STM32F10X_CL + #define RCC_AHBPeriph_FSMC ((uint32_t)0x00000100) + #define RCC_AHBPeriph_SDIO ((uint32_t)0x00000400) + #define IS_RCC_AHB_PERIPH(PERIPH) ((((PERIPH) & 0xFFFFFAA8) == 0x00) && ((PERIPH) != 0x00)) +#else + #define RCC_AHBPeriph_OTG_FS ((uint32_t)0x00001000) + #define RCC_AHBPeriph_ETH_MAC ((uint32_t)0x00004000) + #define RCC_AHBPeriph_ETH_MAC_Tx ((uint32_t)0x00008000) + #define RCC_AHBPeriph_ETH_MAC_Rx ((uint32_t)0x00010000) + + #define IS_RCC_AHB_PERIPH(PERIPH) ((((PERIPH) & 0xFFFE2FA8) == 0x00) && ((PERIPH) != 0x00)) + #define IS_RCC_AHB_PERIPH_RESET(PERIPH) ((((PERIPH) & 0xFFFFAFFF) == 0x00) && ((PERIPH) != 0x00)) +#endif /* STM32F10X_CL */ +/** + * @} + */ + +/** @defgroup APB2_peripheral + * @{ + */ + +#define RCC_APB2Periph_AFIO ((uint32_t)0x00000001) +#define RCC_APB2Periph_GPIOA ((uint32_t)0x00000004) +#define RCC_APB2Periph_GPIOB ((uint32_t)0x00000008) +#define RCC_APB2Periph_GPIOC ((uint32_t)0x00000010) +#define RCC_APB2Periph_GPIOD ((uint32_t)0x00000020) +#define RCC_APB2Periph_GPIOE ((uint32_t)0x00000040) +#define RCC_APB2Periph_GPIOF ((uint32_t)0x00000080) +#define RCC_APB2Periph_GPIOG ((uint32_t)0x00000100) +#define RCC_APB2Periph_ADC1 ((uint32_t)0x00000200) +#define RCC_APB2Periph_ADC2 ((uint32_t)0x00000400) +#define RCC_APB2Periph_TIM1 ((uint32_t)0x00000800) +#define RCC_APB2Periph_SPI1 ((uint32_t)0x00001000) +#define RCC_APB2Periph_TIM8 ((uint32_t)0x00002000) +#define RCC_APB2Periph_USART1 ((uint32_t)0x00004000) +#define RCC_APB2Periph_ADC3 ((uint32_t)0x00008000) +#define RCC_APB2Periph_TIM15 ((uint32_t)0x00010000) +#define RCC_APB2Periph_TIM16 ((uint32_t)0x00020000) +#define RCC_APB2Periph_TIM17 ((uint32_t)0x00040000) +#define RCC_APB2Periph_TIM9 ((uint32_t)0x00080000) +#define RCC_APB2Periph_TIM10 ((uint32_t)0x00100000) +#define RCC_APB2Periph_TIM11 ((uint32_t)0x00200000) + +#define IS_RCC_APB2_PERIPH(PERIPH) ((((PERIPH) & 0xFFC00002) == 0x00) && ((PERIPH) != 0x00)) +/** + * @} + */ + +/** @defgroup APB1_peripheral + * @{ + */ + +#define RCC_APB1Periph_TIM2 ((uint32_t)0x00000001) +#define RCC_APB1Periph_TIM3 ((uint32_t)0x00000002) +#define RCC_APB1Periph_TIM4 ((uint32_t)0x00000004) +#define RCC_APB1Periph_TIM5 ((uint32_t)0x00000008) +#define RCC_APB1Periph_TIM6 ((uint32_t)0x00000010) +#define RCC_APB1Periph_TIM7 ((uint32_t)0x00000020) +#define RCC_APB1Periph_TIM12 ((uint32_t)0x00000040) +#define RCC_APB1Periph_TIM13 ((uint32_t)0x00000080) +#define RCC_APB1Periph_TIM14 ((uint32_t)0x00000100) +#define RCC_APB1Periph_WWDG ((uint32_t)0x00000800) +#define RCC_APB1Periph_SPI2 ((uint32_t)0x00004000) +#define RCC_APB1Periph_SPI3 ((uint32_t)0x00008000) +#define RCC_APB1Periph_USART2 ((uint32_t)0x00020000) +#define RCC_APB1Periph_USART3 ((uint32_t)0x00040000) +#define RCC_APB1Periph_UART4 ((uint32_t)0x00080000) +#define RCC_APB1Periph_UART5 ((uint32_t)0x00100000) +#define RCC_APB1Periph_I2C1 ((uint32_t)0x00200000) +#define RCC_APB1Periph_I2C2 ((uint32_t)0x00400000) +#define RCC_APB1Periph_USB ((uint32_t)0x00800000) +#define RCC_APB1Periph_CAN1 ((uint32_t)0x02000000) +#define RCC_APB1Periph_CAN2 ((uint32_t)0x04000000) +#define RCC_APB1Periph_BKP ((uint32_t)0x08000000) +#define RCC_APB1Periph_PWR ((uint32_t)0x10000000) +#define RCC_APB1Periph_DAC ((uint32_t)0x20000000) +#define RCC_APB1Periph_CEC ((uint32_t)0x40000000) + +#define IS_RCC_APB1_PERIPH(PERIPH) ((((PERIPH) & 0x81013600) == 0x00) && ((PERIPH) != 0x00)) + +/** + * @} + */ + +/** @defgroup Clock_source_to_output_on_MCO_pin + * @{ + */ + +#define RCC_MCO_NoClock ((uint8_t)0x00) +#define RCC_MCO_SYSCLK ((uint8_t)0x04) +#define RCC_MCO_HSI ((uint8_t)0x05) +#define RCC_MCO_HSE ((uint8_t)0x06) +#define RCC_MCO_PLLCLK_Div2 ((uint8_t)0x07) + +#ifndef STM32F10X_CL + #define IS_RCC_MCO(MCO) (((MCO) == RCC_MCO_NoClock) || ((MCO) == RCC_MCO_HSI) || \ + ((MCO) == RCC_MCO_SYSCLK) || ((MCO) == RCC_MCO_HSE) || \ + ((MCO) == RCC_MCO_PLLCLK_Div2)) +#else + #define RCC_MCO_PLL2CLK ((uint8_t)0x08) + #define RCC_MCO_PLL3CLK_Div2 ((uint8_t)0x09) + #define RCC_MCO_XT1 ((uint8_t)0x0A) + #define RCC_MCO_PLL3CLK ((uint8_t)0x0B) + + #define IS_RCC_MCO(MCO) (((MCO) == RCC_MCO_NoClock) || ((MCO) == RCC_MCO_HSI) || \ + ((MCO) == RCC_MCO_SYSCLK) || ((MCO) == RCC_MCO_HSE) || \ + ((MCO) == RCC_MCO_PLLCLK_Div2) || ((MCO) == RCC_MCO_PLL2CLK) || \ + ((MCO) == RCC_MCO_PLL3CLK_Div2) || ((MCO) == RCC_MCO_XT1) || \ + ((MCO) == RCC_MCO_PLL3CLK)) +#endif /* STM32F10X_CL */ + +/** + * @} + */ + +/** @defgroup RCC_Flag + * @{ + */ + +#define RCC_FLAG_HSIRDY ((uint8_t)0x21) +#define RCC_FLAG_HSERDY ((uint8_t)0x31) +#define RCC_FLAG_PLLRDY ((uint8_t)0x39) +#define RCC_FLAG_LSERDY ((uint8_t)0x41) +#define RCC_FLAG_LSIRDY ((uint8_t)0x61) +#define RCC_FLAG_PINRST ((uint8_t)0x7A) +#define RCC_FLAG_PORRST ((uint8_t)0x7B) +#define RCC_FLAG_SFTRST ((uint8_t)0x7C) +#define RCC_FLAG_IWDGRST ((uint8_t)0x7D) +#define RCC_FLAG_WWDGRST ((uint8_t)0x7E) +#define RCC_FLAG_LPWRRST ((uint8_t)0x7F) + +#ifndef STM32F10X_CL + #define IS_RCC_FLAG(FLAG) (((FLAG) == RCC_FLAG_HSIRDY) || ((FLAG) == RCC_FLAG_HSERDY) || \ + ((FLAG) == RCC_FLAG_PLLRDY) || ((FLAG) == RCC_FLAG_LSERDY) || \ + ((FLAG) == RCC_FLAG_LSIRDY) || ((FLAG) == RCC_FLAG_PINRST) || \ + ((FLAG) == RCC_FLAG_PORRST) || ((FLAG) == RCC_FLAG_SFTRST) || \ + ((FLAG) == RCC_FLAG_IWDGRST)|| ((FLAG) == RCC_FLAG_WWDGRST)|| \ + ((FLAG) == RCC_FLAG_LPWRRST)) +#else + #define RCC_FLAG_PLL2RDY ((uint8_t)0x3B) + #define RCC_FLAG_PLL3RDY ((uint8_t)0x3D) + #define IS_RCC_FLAG(FLAG) (((FLAG) == RCC_FLAG_HSIRDY) || ((FLAG) == RCC_FLAG_HSERDY) || \ + ((FLAG) == RCC_FLAG_PLLRDY) || ((FLAG) == RCC_FLAG_LSERDY) || \ + ((FLAG) == RCC_FLAG_PLL2RDY) || ((FLAG) == RCC_FLAG_PLL3RDY) || \ + ((FLAG) == RCC_FLAG_LSIRDY) || ((FLAG) == RCC_FLAG_PINRST) || \ + ((FLAG) == RCC_FLAG_PORRST) || ((FLAG) == RCC_FLAG_SFTRST) || \ + ((FLAG) == RCC_FLAG_IWDGRST)|| ((FLAG) == RCC_FLAG_WWDGRST)|| \ + ((FLAG) == RCC_FLAG_LPWRRST)) +#endif /* STM32F10X_CL */ + +#define IS_RCC_CALIBRATION_VALUE(VALUE) ((VALUE) <= 0x1F) +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup RCC_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup RCC_Exported_Functions + * @{ + */ + +void RCC_DeInit(void); +void RCC_HSEConfig(uint32_t RCC_HSE); +ErrorStatus RCC_WaitForHSEStartUp(void); +void RCC_AdjustHSICalibrationValue(uint8_t HSICalibrationValue); +void RCC_HSICmd(FunctionalState NewState); +void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul); +void RCC_PLLCmd(FunctionalState NewState); + +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL) + void RCC_PREDIV1Config(uint32_t RCC_PREDIV1_Source, uint32_t RCC_PREDIV1_Div); +#endif + +#ifdef STM32F10X_CL + void RCC_PREDIV2Config(uint32_t RCC_PREDIV2_Div); + void RCC_PLL2Config(uint32_t RCC_PLL2Mul); + void RCC_PLL2Cmd(FunctionalState NewState); + void RCC_PLL3Config(uint32_t RCC_PLL3Mul); + void RCC_PLL3Cmd(FunctionalState NewState); +#endif /* STM32F10X_CL */ + +void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource); +uint8_t RCC_GetSYSCLKSource(void); +void RCC_HCLKConfig(uint32_t RCC_SYSCLK); +void RCC_PCLK1Config(uint32_t RCC_HCLK); +void RCC_PCLK2Config(uint32_t RCC_HCLK); +void RCC_ITConfig(uint8_t RCC_IT, FunctionalState NewState); + +#ifndef STM32F10X_CL + void RCC_USBCLKConfig(uint32_t RCC_USBCLKSource); +#else + void RCC_OTGFSCLKConfig(uint32_t RCC_OTGFSCLKSource); +#endif /* STM32F10X_CL */ + +void RCC_ADCCLKConfig(uint32_t RCC_PCLK2); + +#ifdef STM32F10X_CL + void RCC_I2S2CLKConfig(uint32_t RCC_I2S2CLKSource); + void RCC_I2S3CLKConfig(uint32_t RCC_I2S3CLKSource); +#endif /* STM32F10X_CL */ + +void RCC_LSEConfig(uint8_t RCC_LSE); +void RCC_LSICmd(FunctionalState NewState); +void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource); +void RCC_RTCCLKCmd(FunctionalState NewState); +void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks); +void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState); +void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState); +void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState); + +#ifdef STM32F10X_CL +void RCC_AHBPeriphResetCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState); +#endif /* STM32F10X_CL */ + +void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState); +void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState); +void RCC_BackupResetCmd(FunctionalState NewState); +void RCC_ClockSecuritySystemCmd(FunctionalState NewState); +void RCC_MCOConfig(uint8_t RCC_MCO); +FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG); +void RCC_ClearFlag(void); +ITStatus RCC_GetITStatus(uint8_t RCC_IT); +void RCC_ClearITPendingBit(uint8_t RCC_IT); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F10x_RCC_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_rtc.c b/Library/stm32f10x_rtc.c new file mode 100644 index 0000000..f05aef5 --- /dev/null +++ b/Library/stm32f10x_rtc.c @@ -0,0 +1,339 @@ +/** + ****************************************************************************** + * @file stm32f10x_rtc.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the RTC firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_rtc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup RTC + * @brief RTC driver modules + * @{ + */ + +/** @defgroup RTC_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + +/** @defgroup RTC_Private_Defines + * @{ + */ +#define RTC_LSB_MASK ((uint32_t)0x0000FFFF) /*!< RTC LSB Mask */ +#define PRLH_MSB_MASK ((uint32_t)0x000F0000) /*!< RTC Prescaler MSB Mask */ + +/** + * @} + */ + +/** @defgroup RTC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup RTC_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup RTC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup RTC_Private_Functions + * @{ + */ + +/** + * @brief Enables or disables the specified RTC interrupts. + * @param RTC_IT: specifies the RTC interrupts sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg RTC_IT_OW: Overflow interrupt + * @arg RTC_IT_ALR: Alarm interrupt + * @arg RTC_IT_SEC: Second interrupt + * @param NewState: new state of the specified RTC interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RTC_IT(RTC_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RTC->CRH |= RTC_IT; + } + else + { + RTC->CRH &= (uint16_t)~RTC_IT; + } +} + +/** + * @brief Enters the RTC configuration mode. + * @param None + * @retval None + */ +void RTC_EnterConfigMode(void) +{ + /* Set the CNF flag to enter in the Configuration Mode */ + RTC->CRL |= RTC_CRL_CNF; +} + +/** + * @brief Exits from the RTC configuration mode. + * @param None + * @retval None + */ +void RTC_ExitConfigMode(void) +{ + /* Reset the CNF flag to exit from the Configuration Mode */ + RTC->CRL &= (uint16_t)~((uint16_t)RTC_CRL_CNF); +} + +/** + * @brief Gets the RTC counter value. + * @param None + * @retval RTC counter value. + */ +uint32_t RTC_GetCounter(void) +{ + uint16_t tmp = 0; + tmp = RTC->CNTL; + return (((uint32_t)RTC->CNTH << 16 ) | tmp) ; +} + +/** + * @brief Sets the RTC counter value. + * @param CounterValue: RTC counter new value. + * @retval None + */ +void RTC_SetCounter(uint32_t CounterValue) +{ + RTC_EnterConfigMode(); + /* Set RTC COUNTER MSB word */ + RTC->CNTH = CounterValue >> 16; + /* Set RTC COUNTER LSB word */ + RTC->CNTL = (CounterValue & RTC_LSB_MASK); + RTC_ExitConfigMode(); +} + +/** + * @brief Sets the RTC prescaler value. + * @param PrescalerValue: RTC prescaler new value. + * @retval None + */ +void RTC_SetPrescaler(uint32_t PrescalerValue) +{ + /* Check the parameters */ + assert_param(IS_RTC_PRESCALER(PrescalerValue)); + + RTC_EnterConfigMode(); + /* Set RTC PRESCALER MSB word */ + RTC->PRLH = (PrescalerValue & PRLH_MSB_MASK) >> 16; + /* Set RTC PRESCALER LSB word */ + RTC->PRLL = (PrescalerValue & RTC_LSB_MASK); + RTC_ExitConfigMode(); +} + +/** + * @brief Sets the RTC alarm value. + * @param AlarmValue: RTC alarm new value. + * @retval None + */ +void RTC_SetAlarm(uint32_t AlarmValue) +{ + RTC_EnterConfigMode(); + /* Set the ALARM MSB word */ + RTC->ALRH = AlarmValue >> 16; + /* Set the ALARM LSB word */ + RTC->ALRL = (AlarmValue & RTC_LSB_MASK); + RTC_ExitConfigMode(); +} + +/** + * @brief Gets the RTC divider value. + * @param None + * @retval RTC Divider value. + */ +uint32_t RTC_GetDivider(void) +{ + uint32_t tmp = 0x00; + tmp = ((uint32_t)RTC->DIVH & (uint32_t)0x000F) << 16; + tmp |= RTC->DIVL; + return tmp; +} + +/** + * @brief Waits until last write operation on RTC registers has finished. + * @note This function must be called before any write to RTC registers. + * @param None + * @retval None + */ +void RTC_WaitForLastTask(void) +{ + /* Loop until RTOFF flag is set */ + while ((RTC->CRL & RTC_FLAG_RTOFF) == (uint16_t)RESET) + { + } +} + +/** + * @brief Waits until the RTC registers (RTC_CNT, RTC_ALR and RTC_PRL) + * are synchronized with RTC APB clock. + * @note This function must be called before any read operation after an APB reset + * or an APB clock stop. + * @param None + * @retval None + */ +void RTC_WaitForSynchro(void) +{ + /* Clear RSF flag */ + RTC->CRL &= (uint16_t)~RTC_FLAG_RSF; + /* Loop until RSF flag is set */ + while ((RTC->CRL & RTC_FLAG_RSF) == (uint16_t)RESET) + { + } +} + +/** + * @brief Checks whether the specified RTC flag is set or not. + * @param RTC_FLAG: specifies the flag to check. + * This parameter can be one the following values: + * @arg RTC_FLAG_RTOFF: RTC Operation OFF flag + * @arg RTC_FLAG_RSF: Registers Synchronized flag + * @arg RTC_FLAG_OW: Overflow flag + * @arg RTC_FLAG_ALR: Alarm flag + * @arg RTC_FLAG_SEC: Second flag + * @retval The new state of RTC_FLAG (SET or RESET). + */ +FlagStatus RTC_GetFlagStatus(uint16_t RTC_FLAG) +{ + FlagStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_RTC_GET_FLAG(RTC_FLAG)); + + if ((RTC->CRL & RTC_FLAG) != (uint16_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the RTC's pending flags. + * @param RTC_FLAG: specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg RTC_FLAG_RSF: Registers Synchronized flag. This flag is cleared only after + * an APB reset or an APB Clock stop. + * @arg RTC_FLAG_OW: Overflow flag + * @arg RTC_FLAG_ALR: Alarm flag + * @arg RTC_FLAG_SEC: Second flag + * @retval None + */ +void RTC_ClearFlag(uint16_t RTC_FLAG) +{ + /* Check the parameters */ + assert_param(IS_RTC_CLEAR_FLAG(RTC_FLAG)); + + /* Clear the corresponding RTC flag */ + RTC->CRL &= (uint16_t)~RTC_FLAG; +} + +/** + * @brief Checks whether the specified RTC interrupt has occurred or not. + * @param RTC_IT: specifies the RTC interrupts sources to check. + * This parameter can be one of the following values: + * @arg RTC_IT_OW: Overflow interrupt + * @arg RTC_IT_ALR: Alarm interrupt + * @arg RTC_IT_SEC: Second interrupt + * @retval The new state of the RTC_IT (SET or RESET). + */ +ITStatus RTC_GetITStatus(uint16_t RTC_IT) +{ + ITStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_RTC_GET_IT(RTC_IT)); + + bitstatus = (ITStatus)(RTC->CRL & RTC_IT); + if (((RTC->CRH & RTC_IT) != (uint16_t)RESET) && (bitstatus != (uint16_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the RTC's interrupt pending bits. + * @param RTC_IT: specifies the interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg RTC_IT_OW: Overflow interrupt + * @arg RTC_IT_ALR: Alarm interrupt + * @arg RTC_IT_SEC: Second interrupt + * @retval None + */ +void RTC_ClearITPendingBit(uint16_t RTC_IT) +{ + /* Check the parameters */ + assert_param(IS_RTC_IT(RTC_IT)); + + /* Clear the corresponding RTC pending bit */ + RTC->CRL &= (uint16_t)~RTC_IT; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_rtc.h b/Library/stm32f10x_rtc.h new file mode 100644 index 0000000..fd8beb5 --- /dev/null +++ b/Library/stm32f10x_rtc.h @@ -0,0 +1,135 @@ +/** + ****************************************************************************** + * @file stm32f10x_rtc.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the RTC firmware + * library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_RTC_H +#define __STM32F10x_RTC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup RTC + * @{ + */ + +/** @defgroup RTC_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @defgroup RTC_Exported_Constants + * @{ + */ + +/** @defgroup RTC_interrupts_define + * @{ + */ + +#define RTC_IT_OW ((uint16_t)0x0004) /*!< Overflow interrupt */ +#define RTC_IT_ALR ((uint16_t)0x0002) /*!< Alarm interrupt */ +#define RTC_IT_SEC ((uint16_t)0x0001) /*!< Second interrupt */ +#define IS_RTC_IT(IT) ((((IT) & (uint16_t)0xFFF8) == 0x00) && ((IT) != 0x00)) +#define IS_RTC_GET_IT(IT) (((IT) == RTC_IT_OW) || ((IT) == RTC_IT_ALR) || \ + ((IT) == RTC_IT_SEC)) +/** + * @} + */ + +/** @defgroup RTC_interrupts_flags + * @{ + */ + +#define RTC_FLAG_RTOFF ((uint16_t)0x0020) /*!< RTC Operation OFF flag */ +#define RTC_FLAG_RSF ((uint16_t)0x0008) /*!< Registers Synchronized flag */ +#define RTC_FLAG_OW ((uint16_t)0x0004) /*!< Overflow flag */ +#define RTC_FLAG_ALR ((uint16_t)0x0002) /*!< Alarm flag */ +#define RTC_FLAG_SEC ((uint16_t)0x0001) /*!< Second flag */ +#define IS_RTC_CLEAR_FLAG(FLAG) ((((FLAG) & (uint16_t)0xFFF0) == 0x00) && ((FLAG) != 0x00)) +#define IS_RTC_GET_FLAG(FLAG) (((FLAG) == RTC_FLAG_RTOFF) || ((FLAG) == RTC_FLAG_RSF) || \ + ((FLAG) == RTC_FLAG_OW) || ((FLAG) == RTC_FLAG_ALR) || \ + ((FLAG) == RTC_FLAG_SEC)) +#define IS_RTC_PRESCALER(PRESCALER) ((PRESCALER) <= 0xFFFFF) + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup RTC_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup RTC_Exported_Functions + * @{ + */ + +void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState); +void RTC_EnterConfigMode(void); +void RTC_ExitConfigMode(void); +uint32_t RTC_GetCounter(void); +void RTC_SetCounter(uint32_t CounterValue); +void RTC_SetPrescaler(uint32_t PrescalerValue); +void RTC_SetAlarm(uint32_t AlarmValue); +uint32_t RTC_GetDivider(void); +void RTC_WaitForLastTask(void); +void RTC_WaitForSynchro(void); +FlagStatus RTC_GetFlagStatus(uint16_t RTC_FLAG); +void RTC_ClearFlag(uint16_t RTC_FLAG); +ITStatus RTC_GetITStatus(uint16_t RTC_IT); +void RTC_ClearITPendingBit(uint16_t RTC_IT); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F10x_RTC_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_sdio.c b/Library/stm32f10x_sdio.c new file mode 100644 index 0000000..bc1719d --- /dev/null +++ b/Library/stm32f10x_sdio.c @@ -0,0 +1,799 @@ +/** + ****************************************************************************** + * @file stm32f10x_sdio.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the SDIO firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_sdio.h" +#include "stm32f10x_rcc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup SDIO + * @brief SDIO driver modules + * @{ + */ + +/** @defgroup SDIO_Private_TypesDefinitions + * @{ + */ + +/* ------------ SDIO registers bit address in the alias region ----------- */ +#define SDIO_OFFSET (SDIO_BASE - PERIPH_BASE) + +/* --- CLKCR Register ---*/ + +/* Alias word address of CLKEN bit */ +#define CLKCR_OFFSET (SDIO_OFFSET + 0x04) +#define CLKEN_BitNumber 0x08 +#define CLKCR_CLKEN_BB (PERIPH_BB_BASE + (CLKCR_OFFSET * 32) + (CLKEN_BitNumber * 4)) + +/* --- CMD Register ---*/ + +/* Alias word address of SDIOSUSPEND bit */ +#define CMD_OFFSET (SDIO_OFFSET + 0x0C) +#define SDIOSUSPEND_BitNumber 0x0B +#define CMD_SDIOSUSPEND_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (SDIOSUSPEND_BitNumber * 4)) + +/* Alias word address of ENCMDCOMPL bit */ +#define ENCMDCOMPL_BitNumber 0x0C +#define CMD_ENCMDCOMPL_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (ENCMDCOMPL_BitNumber * 4)) + +/* Alias word address of NIEN bit */ +#define NIEN_BitNumber 0x0D +#define CMD_NIEN_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (NIEN_BitNumber * 4)) + +/* Alias word address of ATACMD bit */ +#define ATACMD_BitNumber 0x0E +#define CMD_ATACMD_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (ATACMD_BitNumber * 4)) + +/* --- DCTRL Register ---*/ + +/* Alias word address of DMAEN bit */ +#define DCTRL_OFFSET (SDIO_OFFSET + 0x2C) +#define DMAEN_BitNumber 0x03 +#define DCTRL_DMAEN_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (DMAEN_BitNumber * 4)) + +/* Alias word address of RWSTART bit */ +#define RWSTART_BitNumber 0x08 +#define DCTRL_RWSTART_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWSTART_BitNumber * 4)) + +/* Alias word address of RWSTOP bit */ +#define RWSTOP_BitNumber 0x09 +#define DCTRL_RWSTOP_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWSTOP_BitNumber * 4)) + +/* Alias word address of RWMOD bit */ +#define RWMOD_BitNumber 0x0A +#define DCTRL_RWMOD_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWMOD_BitNumber * 4)) + +/* Alias word address of SDIOEN bit */ +#define SDIOEN_BitNumber 0x0B +#define DCTRL_SDIOEN_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (SDIOEN_BitNumber * 4)) + +/* ---------------------- SDIO registers bit mask ------------------------ */ + +/* --- CLKCR Register ---*/ + +/* CLKCR register clear mask */ +#define CLKCR_CLEAR_MASK ((uint32_t)0xFFFF8100) + +/* --- PWRCTRL Register ---*/ + +/* SDIO PWRCTRL Mask */ +#define PWR_PWRCTRL_MASK ((uint32_t)0xFFFFFFFC) + +/* --- DCTRL Register ---*/ + +/* SDIO DCTRL Clear Mask */ +#define DCTRL_CLEAR_MASK ((uint32_t)0xFFFFFF08) + +/* --- CMD Register ---*/ + +/* CMD Register clear mask */ +#define CMD_CLEAR_MASK ((uint32_t)0xFFFFF800) + +/* SDIO RESP Registers Address */ +#define SDIO_RESP_ADDR ((uint32_t)(SDIO_BASE + 0x14)) + +/** + * @} + */ + +/** @defgroup SDIO_Private_Defines + * @{ + */ + +/** + * @} + */ + +/** @defgroup SDIO_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup SDIO_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup SDIO_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup SDIO_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the SDIO peripheral registers to their default reset values. + * @param None + * @retval None + */ +void SDIO_DeInit(void) +{ + SDIO->POWER = 0x00000000; + SDIO->CLKCR = 0x00000000; + SDIO->ARG = 0x00000000; + SDIO->CMD = 0x00000000; + SDIO->DTIMER = 0x00000000; + SDIO->DLEN = 0x00000000; + SDIO->DCTRL = 0x00000000; + SDIO->ICR = 0x00C007FF; + SDIO->MASK = 0x00000000; +} + +/** + * @brief Initializes the SDIO peripheral according to the specified + * parameters in the SDIO_InitStruct. + * @param SDIO_InitStruct : pointer to a SDIO_InitTypeDef structure + * that contains the configuration information for the SDIO peripheral. + * @retval None + */ +void SDIO_Init(SDIO_InitTypeDef* SDIO_InitStruct) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_CLOCK_EDGE(SDIO_InitStruct->SDIO_ClockEdge)); + assert_param(IS_SDIO_CLOCK_BYPASS(SDIO_InitStruct->SDIO_ClockBypass)); + assert_param(IS_SDIO_CLOCK_POWER_SAVE(SDIO_InitStruct->SDIO_ClockPowerSave)); + assert_param(IS_SDIO_BUS_WIDE(SDIO_InitStruct->SDIO_BusWide)); + assert_param(IS_SDIO_HARDWARE_FLOW_CONTROL(SDIO_InitStruct->SDIO_HardwareFlowControl)); + +/*---------------------------- SDIO CLKCR Configuration ------------------------*/ + /* Get the SDIO CLKCR value */ + tmpreg = SDIO->CLKCR; + + /* Clear CLKDIV, PWRSAV, BYPASS, WIDBUS, NEGEDGE, HWFC_EN bits */ + tmpreg &= CLKCR_CLEAR_MASK; + + /* Set CLKDIV bits according to SDIO_ClockDiv value */ + /* Set PWRSAV bit according to SDIO_ClockPowerSave value */ + /* Set BYPASS bit according to SDIO_ClockBypass value */ + /* Set WIDBUS bits according to SDIO_BusWide value */ + /* Set NEGEDGE bits according to SDIO_ClockEdge value */ + /* Set HWFC_EN bits according to SDIO_HardwareFlowControl value */ + tmpreg |= (SDIO_InitStruct->SDIO_ClockDiv | SDIO_InitStruct->SDIO_ClockPowerSave | + SDIO_InitStruct->SDIO_ClockBypass | SDIO_InitStruct->SDIO_BusWide | + SDIO_InitStruct->SDIO_ClockEdge | SDIO_InitStruct->SDIO_HardwareFlowControl); + + /* Write to SDIO CLKCR */ + SDIO->CLKCR = tmpreg; +} + +/** + * @brief Fills each SDIO_InitStruct member with its default value. + * @param SDIO_InitStruct: pointer to an SDIO_InitTypeDef structure which + * will be initialized. + * @retval None + */ +void SDIO_StructInit(SDIO_InitTypeDef* SDIO_InitStruct) +{ + /* SDIO_InitStruct members default value */ + SDIO_InitStruct->SDIO_ClockDiv = 0x00; + SDIO_InitStruct->SDIO_ClockEdge = SDIO_ClockEdge_Rising; + SDIO_InitStruct->SDIO_ClockBypass = SDIO_ClockBypass_Disable; + SDIO_InitStruct->SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable; + SDIO_InitStruct->SDIO_BusWide = SDIO_BusWide_1b; + SDIO_InitStruct->SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable; +} + +/** + * @brief Enables or disables the SDIO Clock. + * @param NewState: new state of the SDIO Clock. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_ClockCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CLKCR_CLKEN_BB = (uint32_t)NewState; +} + +/** + * @brief Sets the power status of the controller. + * @param SDIO_PowerState: new state of the Power state. + * This parameter can be one of the following values: + * @arg SDIO_PowerState_OFF + * @arg SDIO_PowerState_ON + * @retval None + */ +void SDIO_SetPowerState(uint32_t SDIO_PowerState) +{ + /* Check the parameters */ + assert_param(IS_SDIO_POWER_STATE(SDIO_PowerState)); + + SDIO->POWER &= PWR_PWRCTRL_MASK; + SDIO->POWER |= SDIO_PowerState; +} + +/** + * @brief Gets the power status of the controller. + * @param None + * @retval Power status of the controller. The returned value can + * be one of the following: + * - 0x00: Power OFF + * - 0x02: Power UP + * - 0x03: Power ON + */ +uint32_t SDIO_GetPowerState(void) +{ + return (SDIO->POWER & (~PWR_PWRCTRL_MASK)); +} + +/** + * @brief Enables or disables the SDIO interrupts. + * @param SDIO_IT: specifies the SDIO interrupt sources to be enabled or disabled. + * This parameter can be one or a combination of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_IT_DATAEND: Data end (data counter, SDIDCOUNT, is zero) interrupt + * @arg SDIO_IT_STBITERR: Start bit not detected on all data signals in wide + * bus mode interrupt + * @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt + * @arg SDIO_IT_CMDACT: Command transfer in progress interrupt + * @arg SDIO_IT_TXACT: Data transmit in progress interrupt + * @arg SDIO_IT_RXACT: Data receive in progress interrupt + * @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt + * @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt + * @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt + * @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt + * @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt + * @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt + * @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt + * @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt + * @arg SDIO_IT_SDIOIT: SD I/O interrupt received interrupt + * @arg SDIO_IT_CEATAEND: CE-ATA command completion signal received for CMD61 interrupt + * @param NewState: new state of the specified SDIO interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_ITConfig(uint32_t SDIO_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_SDIO_IT(SDIO_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the SDIO interrupts */ + SDIO->MASK |= SDIO_IT; + } + else + { + /* Disable the SDIO interrupts */ + SDIO->MASK &= ~SDIO_IT; + } +} + +/** + * @brief Enables or disables the SDIO DMA request. + * @param NewState: new state of the selected SDIO DMA request. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_DMACmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) DCTRL_DMAEN_BB = (uint32_t)NewState; +} + +/** + * @brief Initializes the SDIO Command according to the specified + * parameters in the SDIO_CmdInitStruct and send the command. + * @param SDIO_CmdInitStruct : pointer to a SDIO_CmdInitTypeDef + * structure that contains the configuration information for the SDIO command. + * @retval None + */ +void SDIO_SendCommand(SDIO_CmdInitTypeDef *SDIO_CmdInitStruct) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_CMD_INDEX(SDIO_CmdInitStruct->SDIO_CmdIndex)); + assert_param(IS_SDIO_RESPONSE(SDIO_CmdInitStruct->SDIO_Response)); + assert_param(IS_SDIO_WAIT(SDIO_CmdInitStruct->SDIO_Wait)); + assert_param(IS_SDIO_CPSM(SDIO_CmdInitStruct->SDIO_CPSM)); + +/*---------------------------- SDIO ARG Configuration ------------------------*/ + /* Set the SDIO Argument value */ + SDIO->ARG = SDIO_CmdInitStruct->SDIO_Argument; + +/*---------------------------- SDIO CMD Configuration ------------------------*/ + /* Get the SDIO CMD value */ + tmpreg = SDIO->CMD; + /* Clear CMDINDEX, WAITRESP, WAITINT, WAITPEND, CPSMEN bits */ + tmpreg &= CMD_CLEAR_MASK; + /* Set CMDINDEX bits according to SDIO_CmdIndex value */ + /* Set WAITRESP bits according to SDIO_Response value */ + /* Set WAITINT and WAITPEND bits according to SDIO_Wait value */ + /* Set CPSMEN bits according to SDIO_CPSM value */ + tmpreg |= (uint32_t)SDIO_CmdInitStruct->SDIO_CmdIndex | SDIO_CmdInitStruct->SDIO_Response + | SDIO_CmdInitStruct->SDIO_Wait | SDIO_CmdInitStruct->SDIO_CPSM; + + /* Write to SDIO CMD */ + SDIO->CMD = tmpreg; +} + +/** + * @brief Fills each SDIO_CmdInitStruct member with its default value. + * @param SDIO_CmdInitStruct: pointer to an SDIO_CmdInitTypeDef + * structure which will be initialized. + * @retval None + */ +void SDIO_CmdStructInit(SDIO_CmdInitTypeDef* SDIO_CmdInitStruct) +{ + /* SDIO_CmdInitStruct members default value */ + SDIO_CmdInitStruct->SDIO_Argument = 0x00; + SDIO_CmdInitStruct->SDIO_CmdIndex = 0x00; + SDIO_CmdInitStruct->SDIO_Response = SDIO_Response_No; + SDIO_CmdInitStruct->SDIO_Wait = SDIO_Wait_No; + SDIO_CmdInitStruct->SDIO_CPSM = SDIO_CPSM_Disable; +} + +/** + * @brief Returns command index of last command for which response received. + * @param None + * @retval Returns the command index of the last command response received. + */ +uint8_t SDIO_GetCommandResponse(void) +{ + return (uint8_t)(SDIO->RESPCMD); +} + +/** + * @brief Returns response received from the card for the last command. + * @param SDIO_RESP: Specifies the SDIO response register. + * This parameter can be one of the following values: + * @arg SDIO_RESP1: Response Register 1 + * @arg SDIO_RESP2: Response Register 2 + * @arg SDIO_RESP3: Response Register 3 + * @arg SDIO_RESP4: Response Register 4 + * @retval The Corresponding response register value. + */ +uint32_t SDIO_GetResponse(uint32_t SDIO_RESP) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_RESP(SDIO_RESP)); + + tmp = SDIO_RESP_ADDR + SDIO_RESP; + + return (*(__IO uint32_t *) tmp); +} + +/** + * @brief Initializes the SDIO data path according to the specified + * parameters in the SDIO_DataInitStruct. + * @param SDIO_DataInitStruct : pointer to a SDIO_DataInitTypeDef structure that + * contains the configuration information for the SDIO command. + * @retval None + */ +void SDIO_DataConfig(SDIO_DataInitTypeDef* SDIO_DataInitStruct) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_DATA_LENGTH(SDIO_DataInitStruct->SDIO_DataLength)); + assert_param(IS_SDIO_BLOCK_SIZE(SDIO_DataInitStruct->SDIO_DataBlockSize)); + assert_param(IS_SDIO_TRANSFER_DIR(SDIO_DataInitStruct->SDIO_TransferDir)); + assert_param(IS_SDIO_TRANSFER_MODE(SDIO_DataInitStruct->SDIO_TransferMode)); + assert_param(IS_SDIO_DPSM(SDIO_DataInitStruct->SDIO_DPSM)); + +/*---------------------------- SDIO DTIMER Configuration ---------------------*/ + /* Set the SDIO Data TimeOut value */ + SDIO->DTIMER = SDIO_DataInitStruct->SDIO_DataTimeOut; + +/*---------------------------- SDIO DLEN Configuration -----------------------*/ + /* Set the SDIO DataLength value */ + SDIO->DLEN = SDIO_DataInitStruct->SDIO_DataLength; + +/*---------------------------- SDIO DCTRL Configuration ----------------------*/ + /* Get the SDIO DCTRL value */ + tmpreg = SDIO->DCTRL; + /* Clear DEN, DTMODE, DTDIR and DBCKSIZE bits */ + tmpreg &= DCTRL_CLEAR_MASK; + /* Set DEN bit according to SDIO_DPSM value */ + /* Set DTMODE bit according to SDIO_TransferMode value */ + /* Set DTDIR bit according to SDIO_TransferDir value */ + /* Set DBCKSIZE bits according to SDIO_DataBlockSize value */ + tmpreg |= (uint32_t)SDIO_DataInitStruct->SDIO_DataBlockSize | SDIO_DataInitStruct->SDIO_TransferDir + | SDIO_DataInitStruct->SDIO_TransferMode | SDIO_DataInitStruct->SDIO_DPSM; + + /* Write to SDIO DCTRL */ + SDIO->DCTRL = tmpreg; +} + +/** + * @brief Fills each SDIO_DataInitStruct member with its default value. + * @param SDIO_DataInitStruct: pointer to an SDIO_DataInitTypeDef structure which + * will be initialized. + * @retval None + */ +void SDIO_DataStructInit(SDIO_DataInitTypeDef* SDIO_DataInitStruct) +{ + /* SDIO_DataInitStruct members default value */ + SDIO_DataInitStruct->SDIO_DataTimeOut = 0xFFFFFFFF; + SDIO_DataInitStruct->SDIO_DataLength = 0x00; + SDIO_DataInitStruct->SDIO_DataBlockSize = SDIO_DataBlockSize_1b; + SDIO_DataInitStruct->SDIO_TransferDir = SDIO_TransferDir_ToCard; + SDIO_DataInitStruct->SDIO_TransferMode = SDIO_TransferMode_Block; + SDIO_DataInitStruct->SDIO_DPSM = SDIO_DPSM_Disable; +} + +/** + * @brief Returns number of remaining data bytes to be transferred. + * @param None + * @retval Number of remaining data bytes to be transferred + */ +uint32_t SDIO_GetDataCounter(void) +{ + return SDIO->DCOUNT; +} + +/** + * @brief Read one data word from Rx FIFO. + * @param None + * @retval Data received + */ +uint32_t SDIO_ReadData(void) +{ + return SDIO->FIFO; +} + +/** + * @brief Write one data word to Tx FIFO. + * @param Data: 32-bit data word to write. + * @retval None + */ +void SDIO_WriteData(uint32_t Data) +{ + SDIO->FIFO = Data; +} + +/** + * @brief Returns the number of words left to be written to or read from FIFO. + * @param None + * @retval Remaining number of words. + */ +uint32_t SDIO_GetFIFOCount(void) +{ + return SDIO->FIFOCNT; +} + +/** + * @brief Starts the SD I/O Read Wait operation. + * @param NewState: new state of the Start SDIO Read Wait operation. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_StartSDIOReadWait(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) DCTRL_RWSTART_BB = (uint32_t) NewState; +} + +/** + * @brief Stops the SD I/O Read Wait operation. + * @param NewState: new state of the Stop SDIO Read Wait operation. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_StopSDIOReadWait(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) DCTRL_RWSTOP_BB = (uint32_t) NewState; +} + +/** + * @brief Sets one of the two options of inserting read wait interval. + * @param SDIO_ReadWaitMode: SD I/O Read Wait operation mode. + * This parameter can be: + * @arg SDIO_ReadWaitMode_CLK: Read Wait control by stopping SDIOCLK + * @arg SDIO_ReadWaitMode_DATA2: Read Wait control using SDIO_DATA2 + * @retval None + */ +void SDIO_SetSDIOReadWaitMode(uint32_t SDIO_ReadWaitMode) +{ + /* Check the parameters */ + assert_param(IS_SDIO_READWAIT_MODE(SDIO_ReadWaitMode)); + + *(__IO uint32_t *) DCTRL_RWMOD_BB = SDIO_ReadWaitMode; +} + +/** + * @brief Enables or disables the SD I/O Mode Operation. + * @param NewState: new state of SDIO specific operation. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_SetSDIOOperation(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) DCTRL_SDIOEN_BB = (uint32_t)NewState; +} + +/** + * @brief Enables or disables the SD I/O Mode suspend command sending. + * @param NewState: new state of the SD I/O Mode suspend command. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_SendSDIOSuspendCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CMD_SDIOSUSPEND_BB = (uint32_t)NewState; +} + +/** + * @brief Enables or disables the command completion signal. + * @param NewState: new state of command completion signal. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_CommandCompletionCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CMD_ENCMDCOMPL_BB = (uint32_t)NewState; +} + +/** + * @brief Enables or disables the CE-ATA interrupt. + * @param NewState: new state of CE-ATA interrupt. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_CEATAITCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CMD_NIEN_BB = (uint32_t)((~((uint32_t)NewState)) & ((uint32_t)0x1)); +} + +/** + * @brief Sends CE-ATA command (CMD61). + * @param NewState: new state of CE-ATA command. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_SendCEATACmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CMD_ATACMD_BB = (uint32_t)NewState; +} + +/** + * @brief Checks whether the specified SDIO flag is set or not. + * @param SDIO_FLAG: specifies the flag to check. + * This parameter can be one of the following values: + * @arg SDIO_FLAG_CCRCFAIL: Command response received (CRC check failed) + * @arg SDIO_FLAG_DCRCFAIL: Data block sent/received (CRC check failed) + * @arg SDIO_FLAG_CTIMEOUT: Command response timeout + * @arg SDIO_FLAG_DTIMEOUT: Data timeout + * @arg SDIO_FLAG_TXUNDERR: Transmit FIFO underrun error + * @arg SDIO_FLAG_RXOVERR: Received FIFO overrun error + * @arg SDIO_FLAG_CMDREND: Command response received (CRC check passed) + * @arg SDIO_FLAG_CMDSENT: Command sent (no response required) + * @arg SDIO_FLAG_DATAEND: Data end (data counter, SDIDCOUNT, is zero) + * @arg SDIO_FLAG_STBITERR: Start bit not detected on all data signals in wide + * bus mode. + * @arg SDIO_FLAG_DBCKEND: Data block sent/received (CRC check passed) + * @arg SDIO_FLAG_CMDACT: Command transfer in progress + * @arg SDIO_FLAG_TXACT: Data transmit in progress + * @arg SDIO_FLAG_RXACT: Data receive in progress + * @arg SDIO_FLAG_TXFIFOHE: Transmit FIFO Half Empty + * @arg SDIO_FLAG_RXFIFOHF: Receive FIFO Half Full + * @arg SDIO_FLAG_TXFIFOF: Transmit FIFO full + * @arg SDIO_FLAG_RXFIFOF: Receive FIFO full + * @arg SDIO_FLAG_TXFIFOE: Transmit FIFO empty + * @arg SDIO_FLAG_RXFIFOE: Receive FIFO empty + * @arg SDIO_FLAG_TXDAVL: Data available in transmit FIFO + * @arg SDIO_FLAG_RXDAVL: Data available in receive FIFO + * @arg SDIO_FLAG_SDIOIT: SD I/O interrupt received + * @arg SDIO_FLAG_CEATAEND: CE-ATA command completion signal received for CMD61 + * @retval The new state of SDIO_FLAG (SET or RESET). + */ +FlagStatus SDIO_GetFlagStatus(uint32_t SDIO_FLAG) +{ + FlagStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_SDIO_FLAG(SDIO_FLAG)); + + if ((SDIO->STA & SDIO_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the SDIO's pending flags. + * @param SDIO_FLAG: specifies the flag to clear. + * This parameter can be one or a combination of the following values: + * @arg SDIO_FLAG_CCRCFAIL: Command response received (CRC check failed) + * @arg SDIO_FLAG_DCRCFAIL: Data block sent/received (CRC check failed) + * @arg SDIO_FLAG_CTIMEOUT: Command response timeout + * @arg SDIO_FLAG_DTIMEOUT: Data timeout + * @arg SDIO_FLAG_TXUNDERR: Transmit FIFO underrun error + * @arg SDIO_FLAG_RXOVERR: Received FIFO overrun error + * @arg SDIO_FLAG_CMDREND: Command response received (CRC check passed) + * @arg SDIO_FLAG_CMDSENT: Command sent (no response required) + * @arg SDIO_FLAG_DATAEND: Data end (data counter, SDIDCOUNT, is zero) + * @arg SDIO_FLAG_STBITERR: Start bit not detected on all data signals in wide + * bus mode + * @arg SDIO_FLAG_DBCKEND: Data block sent/received (CRC check passed) + * @arg SDIO_FLAG_SDIOIT: SD I/O interrupt received + * @arg SDIO_FLAG_CEATAEND: CE-ATA command completion signal received for CMD61 + * @retval None + */ +void SDIO_ClearFlag(uint32_t SDIO_FLAG) +{ + /* Check the parameters */ + assert_param(IS_SDIO_CLEAR_FLAG(SDIO_FLAG)); + + SDIO->ICR = SDIO_FLAG; +} + +/** + * @brief Checks whether the specified SDIO interrupt has occurred or not. + * @param SDIO_IT: specifies the SDIO interrupt source to check. + * This parameter can be one of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_IT_DATAEND: Data end (data counter, SDIDCOUNT, is zero) interrupt + * @arg SDIO_IT_STBITERR: Start bit not detected on all data signals in wide + * bus mode interrupt + * @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt + * @arg SDIO_IT_CMDACT: Command transfer in progress interrupt + * @arg SDIO_IT_TXACT: Data transmit in progress interrupt + * @arg SDIO_IT_RXACT: Data receive in progress interrupt + * @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt + * @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt + * @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt + * @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt + * @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt + * @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt + * @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt + * @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt + * @arg SDIO_IT_SDIOIT: SD I/O interrupt received interrupt + * @arg SDIO_IT_CEATAEND: CE-ATA command completion signal received for CMD61 interrupt + * @retval The new state of SDIO_IT (SET or RESET). + */ +ITStatus SDIO_GetITStatus(uint32_t SDIO_IT) +{ + ITStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_SDIO_GET_IT(SDIO_IT)); + if ((SDIO->STA & SDIO_IT) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the SDIO's interrupt pending bits. + * @param SDIO_IT: specifies the interrupt pending bit to clear. + * This parameter can be one or a combination of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_IT_DATAEND: Data end (data counter, SDIDCOUNT, is zero) interrupt + * @arg SDIO_IT_STBITERR: Start bit not detected on all data signals in wide + * bus mode interrupt + * @arg SDIO_IT_SDIOIT: SD I/O interrupt received interrupt + * @arg SDIO_IT_CEATAEND: CE-ATA command completion signal received for CMD61 + * @retval None + */ +void SDIO_ClearITPendingBit(uint32_t SDIO_IT) +{ + /* Check the parameters */ + assert_param(IS_SDIO_CLEAR_IT(SDIO_IT)); + + SDIO->ICR = SDIO_IT; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_sdio.h b/Library/stm32f10x_sdio.h new file mode 100644 index 0000000..81c058a --- /dev/null +++ b/Library/stm32f10x_sdio.h @@ -0,0 +1,531 @@ +/** + ****************************************************************************** + * @file stm32f10x_sdio.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the SDIO firmware + * library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_SDIO_H +#define __STM32F10x_SDIO_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup SDIO + * @{ + */ + +/** @defgroup SDIO_Exported_Types + * @{ + */ + +typedef struct +{ + uint32_t SDIO_ClockEdge; /*!< Specifies the clock transition on which the bit capture is made. + This parameter can be a value of @ref SDIO_Clock_Edge */ + + uint32_t SDIO_ClockBypass; /*!< Specifies whether the SDIO Clock divider bypass is + enabled or disabled. + This parameter can be a value of @ref SDIO_Clock_Bypass */ + + uint32_t SDIO_ClockPowerSave; /*!< Specifies whether SDIO Clock output is enabled or + disabled when the bus is idle. + This parameter can be a value of @ref SDIO_Clock_Power_Save */ + + uint32_t SDIO_BusWide; /*!< Specifies the SDIO bus width. + This parameter can be a value of @ref SDIO_Bus_Wide */ + + uint32_t SDIO_HardwareFlowControl; /*!< Specifies whether the SDIO hardware flow control is enabled or disabled. + This parameter can be a value of @ref SDIO_Hardware_Flow_Control */ + + uint8_t SDIO_ClockDiv; /*!< Specifies the clock frequency of the SDIO controller. + This parameter can be a value between 0x00 and 0xFF. */ + +} SDIO_InitTypeDef; + +typedef struct +{ + uint32_t SDIO_Argument; /*!< Specifies the SDIO command argument which is sent + to a card as part of a command message. If a command + contains an argument, it must be loaded into this register + before writing the command to the command register */ + + uint32_t SDIO_CmdIndex; /*!< Specifies the SDIO command index. It must be lower than 0x40. */ + + uint32_t SDIO_Response; /*!< Specifies the SDIO response type. + This parameter can be a value of @ref SDIO_Response_Type */ + + uint32_t SDIO_Wait; /*!< Specifies whether SDIO wait-for-interrupt request is enabled or disabled. + This parameter can be a value of @ref SDIO_Wait_Interrupt_State */ + + uint32_t SDIO_CPSM; /*!< Specifies whether SDIO Command path state machine (CPSM) + is enabled or disabled. + This parameter can be a value of @ref SDIO_CPSM_State */ +} SDIO_CmdInitTypeDef; + +typedef struct +{ + uint32_t SDIO_DataTimeOut; /*!< Specifies the data timeout period in card bus clock periods. */ + + uint32_t SDIO_DataLength; /*!< Specifies the number of data bytes to be transferred. */ + + uint32_t SDIO_DataBlockSize; /*!< Specifies the data block size for block transfer. + This parameter can be a value of @ref SDIO_Data_Block_Size */ + + uint32_t SDIO_TransferDir; /*!< Specifies the data transfer direction, whether the transfer + is a read or write. + This parameter can be a value of @ref SDIO_Transfer_Direction */ + + uint32_t SDIO_TransferMode; /*!< Specifies whether data transfer is in stream or block mode. + This parameter can be a value of @ref SDIO_Transfer_Type */ + + uint32_t SDIO_DPSM; /*!< Specifies whether SDIO Data path state machine (DPSM) + is enabled or disabled. + This parameter can be a value of @ref SDIO_DPSM_State */ +} SDIO_DataInitTypeDef; + +/** + * @} + */ + +/** @defgroup SDIO_Exported_Constants + * @{ + */ + +/** @defgroup SDIO_Clock_Edge + * @{ + */ + +#define SDIO_ClockEdge_Rising ((uint32_t)0x00000000) +#define SDIO_ClockEdge_Falling ((uint32_t)0x00002000) +#define IS_SDIO_CLOCK_EDGE(EDGE) (((EDGE) == SDIO_ClockEdge_Rising) || \ + ((EDGE) == SDIO_ClockEdge_Falling)) +/** + * @} + */ + +/** @defgroup SDIO_Clock_Bypass + * @{ + */ + +#define SDIO_ClockBypass_Disable ((uint32_t)0x00000000) +#define SDIO_ClockBypass_Enable ((uint32_t)0x00000400) +#define IS_SDIO_CLOCK_BYPASS(BYPASS) (((BYPASS) == SDIO_ClockBypass_Disable) || \ + ((BYPASS) == SDIO_ClockBypass_Enable)) +/** + * @} + */ + +/** @defgroup SDIO_Clock_Power_Save + * @{ + */ + +#define SDIO_ClockPowerSave_Disable ((uint32_t)0x00000000) +#define SDIO_ClockPowerSave_Enable ((uint32_t)0x00000200) +#define IS_SDIO_CLOCK_POWER_SAVE(SAVE) (((SAVE) == SDIO_ClockPowerSave_Disable) || \ + ((SAVE) == SDIO_ClockPowerSave_Enable)) +/** + * @} + */ + +/** @defgroup SDIO_Bus_Wide + * @{ + */ + +#define SDIO_BusWide_1b ((uint32_t)0x00000000) +#define SDIO_BusWide_4b ((uint32_t)0x00000800) +#define SDIO_BusWide_8b ((uint32_t)0x00001000) +#define IS_SDIO_BUS_WIDE(WIDE) (((WIDE) == SDIO_BusWide_1b) || ((WIDE) == SDIO_BusWide_4b) || \ + ((WIDE) == SDIO_BusWide_8b)) + +/** + * @} + */ + +/** @defgroup SDIO_Hardware_Flow_Control + * @{ + */ + +#define SDIO_HardwareFlowControl_Disable ((uint32_t)0x00000000) +#define SDIO_HardwareFlowControl_Enable ((uint32_t)0x00004000) +#define IS_SDIO_HARDWARE_FLOW_CONTROL(CONTROL) (((CONTROL) == SDIO_HardwareFlowControl_Disable) || \ + ((CONTROL) == SDIO_HardwareFlowControl_Enable)) +/** + * @} + */ + +/** @defgroup SDIO_Power_State + * @{ + */ + +#define SDIO_PowerState_OFF ((uint32_t)0x00000000) +#define SDIO_PowerState_ON ((uint32_t)0x00000003) +#define IS_SDIO_POWER_STATE(STATE) (((STATE) == SDIO_PowerState_OFF) || ((STATE) == SDIO_PowerState_ON)) +/** + * @} + */ + + +/** @defgroup SDIO_Interrupt_sources + * @{ + */ + +#define SDIO_IT_CCRCFAIL ((uint32_t)0x00000001) +#define SDIO_IT_DCRCFAIL ((uint32_t)0x00000002) +#define SDIO_IT_CTIMEOUT ((uint32_t)0x00000004) +#define SDIO_IT_DTIMEOUT ((uint32_t)0x00000008) +#define SDIO_IT_TXUNDERR ((uint32_t)0x00000010) +#define SDIO_IT_RXOVERR ((uint32_t)0x00000020) +#define SDIO_IT_CMDREND ((uint32_t)0x00000040) +#define SDIO_IT_CMDSENT ((uint32_t)0x00000080) +#define SDIO_IT_DATAEND ((uint32_t)0x00000100) +#define SDIO_IT_STBITERR ((uint32_t)0x00000200) +#define SDIO_IT_DBCKEND ((uint32_t)0x00000400) +#define SDIO_IT_CMDACT ((uint32_t)0x00000800) +#define SDIO_IT_TXACT ((uint32_t)0x00001000) +#define SDIO_IT_RXACT ((uint32_t)0x00002000) +#define SDIO_IT_TXFIFOHE ((uint32_t)0x00004000) +#define SDIO_IT_RXFIFOHF ((uint32_t)0x00008000) +#define SDIO_IT_TXFIFOF ((uint32_t)0x00010000) +#define SDIO_IT_RXFIFOF ((uint32_t)0x00020000) +#define SDIO_IT_TXFIFOE ((uint32_t)0x00040000) +#define SDIO_IT_RXFIFOE ((uint32_t)0x00080000) +#define SDIO_IT_TXDAVL ((uint32_t)0x00100000) +#define SDIO_IT_RXDAVL ((uint32_t)0x00200000) +#define SDIO_IT_SDIOIT ((uint32_t)0x00400000) +#define SDIO_IT_CEATAEND ((uint32_t)0x00800000) +#define IS_SDIO_IT(IT) ((((IT) & (uint32_t)0xFF000000) == 0x00) && ((IT) != (uint32_t)0x00)) +/** + * @} + */ + +/** @defgroup SDIO_Command_Index + * @{ + */ + +#define IS_SDIO_CMD_INDEX(INDEX) ((INDEX) < 0x40) +/** + * @} + */ + +/** @defgroup SDIO_Response_Type + * @{ + */ + +#define SDIO_Response_No ((uint32_t)0x00000000) +#define SDIO_Response_Short ((uint32_t)0x00000040) +#define SDIO_Response_Long ((uint32_t)0x000000C0) +#define IS_SDIO_RESPONSE(RESPONSE) (((RESPONSE) == SDIO_Response_No) || \ + ((RESPONSE) == SDIO_Response_Short) || \ + ((RESPONSE) == SDIO_Response_Long)) +/** + * @} + */ + +/** @defgroup SDIO_Wait_Interrupt_State + * @{ + */ + +#define SDIO_Wait_No ((uint32_t)0x00000000) /*!< SDIO No Wait, TimeOut is enabled */ +#define SDIO_Wait_IT ((uint32_t)0x00000100) /*!< SDIO Wait Interrupt Request */ +#define SDIO_Wait_Pend ((uint32_t)0x00000200) /*!< SDIO Wait End of transfer */ +#define IS_SDIO_WAIT(WAIT) (((WAIT) == SDIO_Wait_No) || ((WAIT) == SDIO_Wait_IT) || \ + ((WAIT) == SDIO_Wait_Pend)) +/** + * @} + */ + +/** @defgroup SDIO_CPSM_State + * @{ + */ + +#define SDIO_CPSM_Disable ((uint32_t)0x00000000) +#define SDIO_CPSM_Enable ((uint32_t)0x00000400) +#define IS_SDIO_CPSM(CPSM) (((CPSM) == SDIO_CPSM_Enable) || ((CPSM) == SDIO_CPSM_Disable)) +/** + * @} + */ + +/** @defgroup SDIO_Response_Registers + * @{ + */ + +#define SDIO_RESP1 ((uint32_t)0x00000000) +#define SDIO_RESP2 ((uint32_t)0x00000004) +#define SDIO_RESP3 ((uint32_t)0x00000008) +#define SDIO_RESP4 ((uint32_t)0x0000000C) +#define IS_SDIO_RESP(RESP) (((RESP) == SDIO_RESP1) || ((RESP) == SDIO_RESP2) || \ + ((RESP) == SDIO_RESP3) || ((RESP) == SDIO_RESP4)) +/** + * @} + */ + +/** @defgroup SDIO_Data_Length + * @{ + */ + +#define IS_SDIO_DATA_LENGTH(LENGTH) ((LENGTH) <= 0x01FFFFFF) +/** + * @} + */ + +/** @defgroup SDIO_Data_Block_Size + * @{ + */ + +#define SDIO_DataBlockSize_1b ((uint32_t)0x00000000) +#define SDIO_DataBlockSize_2b ((uint32_t)0x00000010) +#define SDIO_DataBlockSize_4b ((uint32_t)0x00000020) +#define SDIO_DataBlockSize_8b ((uint32_t)0x00000030) +#define SDIO_DataBlockSize_16b ((uint32_t)0x00000040) +#define SDIO_DataBlockSize_32b ((uint32_t)0x00000050) +#define SDIO_DataBlockSize_64b ((uint32_t)0x00000060) +#define SDIO_DataBlockSize_128b ((uint32_t)0x00000070) +#define SDIO_DataBlockSize_256b ((uint32_t)0x00000080) +#define SDIO_DataBlockSize_512b ((uint32_t)0x00000090) +#define SDIO_DataBlockSize_1024b ((uint32_t)0x000000A0) +#define SDIO_DataBlockSize_2048b ((uint32_t)0x000000B0) +#define SDIO_DataBlockSize_4096b ((uint32_t)0x000000C0) +#define SDIO_DataBlockSize_8192b ((uint32_t)0x000000D0) +#define SDIO_DataBlockSize_16384b ((uint32_t)0x000000E0) +#define IS_SDIO_BLOCK_SIZE(SIZE) (((SIZE) == SDIO_DataBlockSize_1b) || \ + ((SIZE) == SDIO_DataBlockSize_2b) || \ + ((SIZE) == SDIO_DataBlockSize_4b) || \ + ((SIZE) == SDIO_DataBlockSize_8b) || \ + ((SIZE) == SDIO_DataBlockSize_16b) || \ + ((SIZE) == SDIO_DataBlockSize_32b) || \ + ((SIZE) == SDIO_DataBlockSize_64b) || \ + ((SIZE) == SDIO_DataBlockSize_128b) || \ + ((SIZE) == SDIO_DataBlockSize_256b) || \ + ((SIZE) == SDIO_DataBlockSize_512b) || \ + ((SIZE) == SDIO_DataBlockSize_1024b) || \ + ((SIZE) == SDIO_DataBlockSize_2048b) || \ + ((SIZE) == SDIO_DataBlockSize_4096b) || \ + ((SIZE) == SDIO_DataBlockSize_8192b) || \ + ((SIZE) == SDIO_DataBlockSize_16384b)) +/** + * @} + */ + +/** @defgroup SDIO_Transfer_Direction + * @{ + */ + +#define SDIO_TransferDir_ToCard ((uint32_t)0x00000000) +#define SDIO_TransferDir_ToSDIO ((uint32_t)0x00000002) +#define IS_SDIO_TRANSFER_DIR(DIR) (((DIR) == SDIO_TransferDir_ToCard) || \ + ((DIR) == SDIO_TransferDir_ToSDIO)) +/** + * @} + */ + +/** @defgroup SDIO_Transfer_Type + * @{ + */ + +#define SDIO_TransferMode_Block ((uint32_t)0x00000000) +#define SDIO_TransferMode_Stream ((uint32_t)0x00000004) +#define IS_SDIO_TRANSFER_MODE(MODE) (((MODE) == SDIO_TransferMode_Stream) || \ + ((MODE) == SDIO_TransferMode_Block)) +/** + * @} + */ + +/** @defgroup SDIO_DPSM_State + * @{ + */ + +#define SDIO_DPSM_Disable ((uint32_t)0x00000000) +#define SDIO_DPSM_Enable ((uint32_t)0x00000001) +#define IS_SDIO_DPSM(DPSM) (((DPSM) == SDIO_DPSM_Enable) || ((DPSM) == SDIO_DPSM_Disable)) +/** + * @} + */ + +/** @defgroup SDIO_Flags + * @{ + */ + +#define SDIO_FLAG_CCRCFAIL ((uint32_t)0x00000001) +#define SDIO_FLAG_DCRCFAIL ((uint32_t)0x00000002) +#define SDIO_FLAG_CTIMEOUT ((uint32_t)0x00000004) +#define SDIO_FLAG_DTIMEOUT ((uint32_t)0x00000008) +#define SDIO_FLAG_TXUNDERR ((uint32_t)0x00000010) +#define SDIO_FLAG_RXOVERR ((uint32_t)0x00000020) +#define SDIO_FLAG_CMDREND ((uint32_t)0x00000040) +#define SDIO_FLAG_CMDSENT ((uint32_t)0x00000080) +#define SDIO_FLAG_DATAEND ((uint32_t)0x00000100) +#define SDIO_FLAG_STBITERR ((uint32_t)0x00000200) +#define SDIO_FLAG_DBCKEND ((uint32_t)0x00000400) +#define SDIO_FLAG_CMDACT ((uint32_t)0x00000800) +#define SDIO_FLAG_TXACT ((uint32_t)0x00001000) +#define SDIO_FLAG_RXACT ((uint32_t)0x00002000) +#define SDIO_FLAG_TXFIFOHE ((uint32_t)0x00004000) +#define SDIO_FLAG_RXFIFOHF ((uint32_t)0x00008000) +#define SDIO_FLAG_TXFIFOF ((uint32_t)0x00010000) +#define SDIO_FLAG_RXFIFOF ((uint32_t)0x00020000) +#define SDIO_FLAG_TXFIFOE ((uint32_t)0x00040000) +#define SDIO_FLAG_RXFIFOE ((uint32_t)0x00080000) +#define SDIO_FLAG_TXDAVL ((uint32_t)0x00100000) +#define SDIO_FLAG_RXDAVL ((uint32_t)0x00200000) +#define SDIO_FLAG_SDIOIT ((uint32_t)0x00400000) +#define SDIO_FLAG_CEATAEND ((uint32_t)0x00800000) +#define IS_SDIO_FLAG(FLAG) (((FLAG) == SDIO_FLAG_CCRCFAIL) || \ + ((FLAG) == SDIO_FLAG_DCRCFAIL) || \ + ((FLAG) == SDIO_FLAG_CTIMEOUT) || \ + ((FLAG) == SDIO_FLAG_DTIMEOUT) || \ + ((FLAG) == SDIO_FLAG_TXUNDERR) || \ + ((FLAG) == SDIO_FLAG_RXOVERR) || \ + ((FLAG) == SDIO_FLAG_CMDREND) || \ + ((FLAG) == SDIO_FLAG_CMDSENT) || \ + ((FLAG) == SDIO_FLAG_DATAEND) || \ + ((FLAG) == SDIO_FLAG_STBITERR) || \ + ((FLAG) == SDIO_FLAG_DBCKEND) || \ + ((FLAG) == SDIO_FLAG_CMDACT) || \ + ((FLAG) == SDIO_FLAG_TXACT) || \ + ((FLAG) == SDIO_FLAG_RXACT) || \ + ((FLAG) == SDIO_FLAG_TXFIFOHE) || \ + ((FLAG) == SDIO_FLAG_RXFIFOHF) || \ + ((FLAG) == SDIO_FLAG_TXFIFOF) || \ + ((FLAG) == SDIO_FLAG_RXFIFOF) || \ + ((FLAG) == SDIO_FLAG_TXFIFOE) || \ + ((FLAG) == SDIO_FLAG_RXFIFOE) || \ + ((FLAG) == SDIO_FLAG_TXDAVL) || \ + ((FLAG) == SDIO_FLAG_RXDAVL) || \ + ((FLAG) == SDIO_FLAG_SDIOIT) || \ + ((FLAG) == SDIO_FLAG_CEATAEND)) + +#define IS_SDIO_CLEAR_FLAG(FLAG) ((((FLAG) & (uint32_t)0xFF3FF800) == 0x00) && ((FLAG) != (uint32_t)0x00)) + +#define IS_SDIO_GET_IT(IT) (((IT) == SDIO_IT_CCRCFAIL) || \ + ((IT) == SDIO_IT_DCRCFAIL) || \ + ((IT) == SDIO_IT_CTIMEOUT) || \ + ((IT) == SDIO_IT_DTIMEOUT) || \ + ((IT) == SDIO_IT_TXUNDERR) || \ + ((IT) == SDIO_IT_RXOVERR) || \ + ((IT) == SDIO_IT_CMDREND) || \ + ((IT) == SDIO_IT_CMDSENT) || \ + ((IT) == SDIO_IT_DATAEND) || \ + ((IT) == SDIO_IT_STBITERR) || \ + ((IT) == SDIO_IT_DBCKEND) || \ + ((IT) == SDIO_IT_CMDACT) || \ + ((IT) == SDIO_IT_TXACT) || \ + ((IT) == SDIO_IT_RXACT) || \ + ((IT) == SDIO_IT_TXFIFOHE) || \ + ((IT) == SDIO_IT_RXFIFOHF) || \ + ((IT) == SDIO_IT_TXFIFOF) || \ + ((IT) == SDIO_IT_RXFIFOF) || \ + ((IT) == SDIO_IT_TXFIFOE) || \ + ((IT) == SDIO_IT_RXFIFOE) || \ + ((IT) == SDIO_IT_TXDAVL) || \ + ((IT) == SDIO_IT_RXDAVL) || \ + ((IT) == SDIO_IT_SDIOIT) || \ + ((IT) == SDIO_IT_CEATAEND)) + +#define IS_SDIO_CLEAR_IT(IT) ((((IT) & (uint32_t)0xFF3FF800) == 0x00) && ((IT) != (uint32_t)0x00)) + +/** + * @} + */ + +/** @defgroup SDIO_Read_Wait_Mode + * @{ + */ + +#define SDIO_ReadWaitMode_CLK ((uint32_t)0x00000001) +#define SDIO_ReadWaitMode_DATA2 ((uint32_t)0x00000000) +#define IS_SDIO_READWAIT_MODE(MODE) (((MODE) == SDIO_ReadWaitMode_CLK) || \ + ((MODE) == SDIO_ReadWaitMode_DATA2)) +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup SDIO_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup SDIO_Exported_Functions + * @{ + */ + +void SDIO_DeInit(void); +void SDIO_Init(SDIO_InitTypeDef* SDIO_InitStruct); +void SDIO_StructInit(SDIO_InitTypeDef* SDIO_InitStruct); +void SDIO_ClockCmd(FunctionalState NewState); +void SDIO_SetPowerState(uint32_t SDIO_PowerState); +uint32_t SDIO_GetPowerState(void); +void SDIO_ITConfig(uint32_t SDIO_IT, FunctionalState NewState); +void SDIO_DMACmd(FunctionalState NewState); +void SDIO_SendCommand(SDIO_CmdInitTypeDef *SDIO_CmdInitStruct); +void SDIO_CmdStructInit(SDIO_CmdInitTypeDef* SDIO_CmdInitStruct); +uint8_t SDIO_GetCommandResponse(void); +uint32_t SDIO_GetResponse(uint32_t SDIO_RESP); +void SDIO_DataConfig(SDIO_DataInitTypeDef* SDIO_DataInitStruct); +void SDIO_DataStructInit(SDIO_DataInitTypeDef* SDIO_DataInitStruct); +uint32_t SDIO_GetDataCounter(void); +uint32_t SDIO_ReadData(void); +void SDIO_WriteData(uint32_t Data); +uint32_t SDIO_GetFIFOCount(void); +void SDIO_StartSDIOReadWait(FunctionalState NewState); +void SDIO_StopSDIOReadWait(FunctionalState NewState); +void SDIO_SetSDIOReadWaitMode(uint32_t SDIO_ReadWaitMode); +void SDIO_SetSDIOOperation(FunctionalState NewState); +void SDIO_SendSDIOSuspendCmd(FunctionalState NewState); +void SDIO_CommandCompletionCmd(FunctionalState NewState); +void SDIO_CEATAITCmd(FunctionalState NewState); +void SDIO_SendCEATACmd(FunctionalState NewState); +FlagStatus SDIO_GetFlagStatus(uint32_t SDIO_FLAG); +void SDIO_ClearFlag(uint32_t SDIO_FLAG); +ITStatus SDIO_GetITStatus(uint32_t SDIO_IT); +void SDIO_ClearITPendingBit(uint32_t SDIO_IT); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F10x_SDIO_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_spi.c b/Library/stm32f10x_spi.c new file mode 100644 index 0000000..4ec65b2 --- /dev/null +++ b/Library/stm32f10x_spi.c @@ -0,0 +1,908 @@ +/** + ****************************************************************************** + * @file stm32f10x_spi.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the SPI firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_spi.h" +#include "stm32f10x_rcc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup SPI + * @brief SPI driver modules + * @{ + */ + +/** @defgroup SPI_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + + +/** @defgroup SPI_Private_Defines + * @{ + */ + +/* SPI SPE mask */ +#define CR1_SPE_Set ((uint16_t)0x0040) +#define CR1_SPE_Reset ((uint16_t)0xFFBF) + +/* I2S I2SE mask */ +#define I2SCFGR_I2SE_Set ((uint16_t)0x0400) +#define I2SCFGR_I2SE_Reset ((uint16_t)0xFBFF) + +/* SPI CRCNext mask */ +#define CR1_CRCNext_Set ((uint16_t)0x1000) + +/* SPI CRCEN mask */ +#define CR1_CRCEN_Set ((uint16_t)0x2000) +#define CR1_CRCEN_Reset ((uint16_t)0xDFFF) + +/* SPI SSOE mask */ +#define CR2_SSOE_Set ((uint16_t)0x0004) +#define CR2_SSOE_Reset ((uint16_t)0xFFFB) + +/* SPI registers Masks */ +#define CR1_CLEAR_Mask ((uint16_t)0x3040) +#define I2SCFGR_CLEAR_Mask ((uint16_t)0xF040) + +/* SPI or I2S mode selection masks */ +#define SPI_Mode_Select ((uint16_t)0xF7FF) +#define I2S_Mode_Select ((uint16_t)0x0800) + +/* I2S clock source selection masks */ +#define I2S2_CLOCK_SRC ((uint32_t)(0x00020000)) +#define I2S3_CLOCK_SRC ((uint32_t)(0x00040000)) +#define I2S_MUL_MASK ((uint32_t)(0x0000F000)) +#define I2S_DIV_MASK ((uint32_t)(0x000000F0)) + +/** + * @} + */ + +/** @defgroup SPI_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup SPI_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup SPI_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup SPI_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the SPIx peripheral registers to their default + * reset values (Affects also the I2Ss). + * @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. + * @retval None + */ +void SPI_I2S_DeInit(SPI_TypeDef* SPIx) +{ + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + + if (SPIx == SPI1) + { + /* Enable SPI1 reset state */ + RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE); + /* Release SPI1 from reset state */ + RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE); + } + else if (SPIx == SPI2) + { + /* Enable SPI2 reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, ENABLE); + /* Release SPI2 from reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, DISABLE); + } + else + { + if (SPIx == SPI3) + { + /* Enable SPI3 reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, ENABLE); + /* Release SPI3 from reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, DISABLE); + } + } +} + +/** + * @brief Initializes the SPIx peripheral according to the specified + * parameters in the SPI_InitStruct. + * @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. + * @param SPI_InitStruct: pointer to a SPI_InitTypeDef structure that + * contains the configuration information for the specified SPI peripheral. + * @retval None + */ +void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct) +{ + uint16_t tmpreg = 0; + + /* check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + + /* Check the SPI parameters */ + assert_param(IS_SPI_DIRECTION_MODE(SPI_InitStruct->SPI_Direction)); + assert_param(IS_SPI_MODE(SPI_InitStruct->SPI_Mode)); + assert_param(IS_SPI_DATASIZE(SPI_InitStruct->SPI_DataSize)); + assert_param(IS_SPI_CPOL(SPI_InitStruct->SPI_CPOL)); + assert_param(IS_SPI_CPHA(SPI_InitStruct->SPI_CPHA)); + assert_param(IS_SPI_NSS(SPI_InitStruct->SPI_NSS)); + assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_InitStruct->SPI_BaudRatePrescaler)); + assert_param(IS_SPI_FIRST_BIT(SPI_InitStruct->SPI_FirstBit)); + assert_param(IS_SPI_CRC_POLYNOMIAL(SPI_InitStruct->SPI_CRCPolynomial)); + +/*---------------------------- SPIx CR1 Configuration ------------------------*/ + /* Get the SPIx CR1 value */ + tmpreg = SPIx->CR1; + /* Clear BIDIMode, BIDIOE, RxONLY, SSM, SSI, LSBFirst, BR, MSTR, CPOL and CPHA bits */ + tmpreg &= CR1_CLEAR_Mask; + /* Configure SPIx: direction, NSS management, first transmitted bit, BaudRate prescaler + master/salve mode, CPOL and CPHA */ + /* Set BIDImode, BIDIOE and RxONLY bits according to SPI_Direction value */ + /* Set SSM, SSI and MSTR bits according to SPI_Mode and SPI_NSS values */ + /* Set LSBFirst bit according to SPI_FirstBit value */ + /* Set BR bits according to SPI_BaudRatePrescaler value */ + /* Set CPOL bit according to SPI_CPOL value */ + /* Set CPHA bit according to SPI_CPHA value */ + tmpreg |= (uint16_t)((uint32_t)SPI_InitStruct->SPI_Direction | SPI_InitStruct->SPI_Mode | + SPI_InitStruct->SPI_DataSize | SPI_InitStruct->SPI_CPOL | + SPI_InitStruct->SPI_CPHA | SPI_InitStruct->SPI_NSS | + SPI_InitStruct->SPI_BaudRatePrescaler | SPI_InitStruct->SPI_FirstBit); + /* Write to SPIx CR1 */ + SPIx->CR1 = tmpreg; + + /* Activate the SPI mode (Reset I2SMOD bit in I2SCFGR register) */ + SPIx->I2SCFGR &= SPI_Mode_Select; + +/*---------------------------- SPIx CRCPOLY Configuration --------------------*/ + /* Write to SPIx CRCPOLY */ + SPIx->CRCPR = SPI_InitStruct->SPI_CRCPolynomial; +} + +/** + * @brief Initializes the SPIx peripheral according to the specified + * parameters in the I2S_InitStruct. + * @param SPIx: where x can be 2 or 3 to select the SPI peripheral + * (configured in I2S mode). + * @param I2S_InitStruct: pointer to an I2S_InitTypeDef structure that + * contains the configuration information for the specified SPI peripheral + * configured in I2S mode. + * @note + * The function calculates the optimal prescaler needed to obtain the most + * accurate audio frequency (depending on the I2S clock source, the PLL values + * and the product configuration). But in case the prescaler value is greater + * than 511, the default value (0x02) will be configured instead. * + * @retval None + */ +void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct) +{ + uint16_t tmpreg = 0, i2sdiv = 2, i2sodd = 0, packetlength = 1; + uint32_t tmp = 0; + RCC_ClocksTypeDef RCC_Clocks; + uint32_t sourceclock = 0; + + /* Check the I2S parameters */ + assert_param(IS_SPI_23_PERIPH(SPIx)); + assert_param(IS_I2S_MODE(I2S_InitStruct->I2S_Mode)); + assert_param(IS_I2S_STANDARD(I2S_InitStruct->I2S_Standard)); + assert_param(IS_I2S_DATA_FORMAT(I2S_InitStruct->I2S_DataFormat)); + assert_param(IS_I2S_MCLK_OUTPUT(I2S_InitStruct->I2S_MCLKOutput)); + assert_param(IS_I2S_AUDIO_FREQ(I2S_InitStruct->I2S_AudioFreq)); + assert_param(IS_I2S_CPOL(I2S_InitStruct->I2S_CPOL)); + +/*----------------------- SPIx I2SCFGR & I2SPR Configuration -----------------*/ + /* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */ + SPIx->I2SCFGR &= I2SCFGR_CLEAR_Mask; + SPIx->I2SPR = 0x0002; + + /* Get the I2SCFGR register value */ + tmpreg = SPIx->I2SCFGR; + + /* If the default value has to be written, reinitialize i2sdiv and i2sodd*/ + if(I2S_InitStruct->I2S_AudioFreq == I2S_AudioFreq_Default) + { + i2sodd = (uint16_t)0; + i2sdiv = (uint16_t)2; + } + /* If the requested audio frequency is not the default, compute the prescaler */ + else + { + /* Check the frame length (For the Prescaler computing) */ + if(I2S_InitStruct->I2S_DataFormat == I2S_DataFormat_16b) + { + /* Packet length is 16 bits */ + packetlength = 1; + } + else + { + /* Packet length is 32 bits */ + packetlength = 2; + } + + /* Get the I2S clock source mask depending on the peripheral number */ + if(((uint32_t)SPIx) == SPI2_BASE) + { + /* The mask is relative to I2S2 */ + tmp = I2S2_CLOCK_SRC; + } + else + { + /* The mask is relative to I2S3 */ + tmp = I2S3_CLOCK_SRC; + } + + /* Check the I2S clock source configuration depending on the Device: + Only Connectivity line devices have the PLL3 VCO clock */ +#ifdef STM32F10X_CL + if((RCC->CFGR2 & tmp) != 0) + { + /* Get the configuration bits of RCC PLL3 multiplier */ + tmp = (uint32_t)((RCC->CFGR2 & I2S_MUL_MASK) >> 12); + + /* Get the value of the PLL3 multiplier */ + if((tmp > 5) && (tmp < 15)) + { + /* Multiplier is between 8 and 14 (value 15 is forbidden) */ + tmp += 2; + } + else + { + if (tmp == 15) + { + /* Multiplier is 20 */ + tmp = 20; + } + } + /* Get the PREDIV2 value */ + sourceclock = (uint32_t)(((RCC->CFGR2 & I2S_DIV_MASK) >> 4) + 1); + + /* Calculate the Source Clock frequency based on PLL3 and PREDIV2 values */ + sourceclock = (uint32_t) ((HSE_Value / sourceclock) * tmp * 2); + } + else + { + /* I2S Clock source is System clock: Get System Clock frequency */ + RCC_GetClocksFreq(&RCC_Clocks); + + /* Get the source clock value: based on System Clock value */ + sourceclock = RCC_Clocks.SYSCLK_Frequency; + } +#else /* STM32F10X_HD */ + /* I2S Clock source is System clock: Get System Clock frequency */ + RCC_GetClocksFreq(&RCC_Clocks); + + /* Get the source clock value: based on System Clock value */ + sourceclock = RCC_Clocks.SYSCLK_Frequency; +#endif /* STM32F10X_CL */ + + /* Compute the Real divider depending on the MCLK output state with a floating point */ + if(I2S_InitStruct->I2S_MCLKOutput == I2S_MCLKOutput_Enable) + { + /* MCLK output is enabled */ + tmp = (uint16_t)(((((sourceclock / 256) * 10) / I2S_InitStruct->I2S_AudioFreq)) + 5); + } + else + { + /* MCLK output is disabled */ + tmp = (uint16_t)(((((sourceclock / (32 * packetlength)) *10 ) / I2S_InitStruct->I2S_AudioFreq)) + 5); + } + + /* Remove the floating point */ + tmp = tmp / 10; + + /* Check the parity of the divider */ + i2sodd = (uint16_t)(tmp & (uint16_t)0x0001); + + /* Compute the i2sdiv prescaler */ + i2sdiv = (uint16_t)((tmp - i2sodd) / 2); + + /* Get the Mask for the Odd bit (SPI_I2SPR[8]) register */ + i2sodd = (uint16_t) (i2sodd << 8); + } + + /* Test if the divider is 1 or 0 or greater than 0xFF */ + if ((i2sdiv < 2) || (i2sdiv > 0xFF)) + { + /* Set the default values */ + i2sdiv = 2; + i2sodd = 0; + } + + /* Write to SPIx I2SPR register the computed value */ + SPIx->I2SPR = (uint16_t)(i2sdiv | (uint16_t)(i2sodd | (uint16_t)I2S_InitStruct->I2S_MCLKOutput)); + + /* Configure the I2S with the SPI_InitStruct values */ + tmpreg |= (uint16_t)(I2S_Mode_Select | (uint16_t)(I2S_InitStruct->I2S_Mode | \ + (uint16_t)(I2S_InitStruct->I2S_Standard | (uint16_t)(I2S_InitStruct->I2S_DataFormat | \ + (uint16_t)I2S_InitStruct->I2S_CPOL)))); + + /* Write to SPIx I2SCFGR */ + SPIx->I2SCFGR = tmpreg; +} + +/** + * @brief Fills each SPI_InitStruct member with its default value. + * @param SPI_InitStruct : pointer to a SPI_InitTypeDef structure which will be initialized. + * @retval None + */ +void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct) +{ +/*--------------- Reset SPI init structure parameters values -----------------*/ + /* Initialize the SPI_Direction member */ + SPI_InitStruct->SPI_Direction = SPI_Direction_2Lines_FullDuplex; + /* initialize the SPI_Mode member */ + SPI_InitStruct->SPI_Mode = SPI_Mode_Slave; + /* initialize the SPI_DataSize member */ + SPI_InitStruct->SPI_DataSize = SPI_DataSize_8b; + /* Initialize the SPI_CPOL member */ + SPI_InitStruct->SPI_CPOL = SPI_CPOL_Low; + /* Initialize the SPI_CPHA member */ + SPI_InitStruct->SPI_CPHA = SPI_CPHA_1Edge; + /* Initialize the SPI_NSS member */ + SPI_InitStruct->SPI_NSS = SPI_NSS_Hard; + /* Initialize the SPI_BaudRatePrescaler member */ + SPI_InitStruct->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; + /* Initialize the SPI_FirstBit member */ + SPI_InitStruct->SPI_FirstBit = SPI_FirstBit_MSB; + /* Initialize the SPI_CRCPolynomial member */ + SPI_InitStruct->SPI_CRCPolynomial = 7; +} + +/** + * @brief Fills each I2S_InitStruct member with its default value. + * @param I2S_InitStruct : pointer to a I2S_InitTypeDef structure which will be initialized. + * @retval None + */ +void I2S_StructInit(I2S_InitTypeDef* I2S_InitStruct) +{ +/*--------------- Reset I2S init structure parameters values -----------------*/ + /* Initialize the I2S_Mode member */ + I2S_InitStruct->I2S_Mode = I2S_Mode_SlaveTx; + + /* Initialize the I2S_Standard member */ + I2S_InitStruct->I2S_Standard = I2S_Standard_Phillips; + + /* Initialize the I2S_DataFormat member */ + I2S_InitStruct->I2S_DataFormat = I2S_DataFormat_16b; + + /* Initialize the I2S_MCLKOutput member */ + I2S_InitStruct->I2S_MCLKOutput = I2S_MCLKOutput_Disable; + + /* Initialize the I2S_AudioFreq member */ + I2S_InitStruct->I2S_AudioFreq = I2S_AudioFreq_Default; + + /* Initialize the I2S_CPOL member */ + I2S_InitStruct->I2S_CPOL = I2S_CPOL_Low; +} + +/** + * @brief Enables or disables the specified SPI peripheral. + * @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. + * @param NewState: new state of the SPIx peripheral. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected SPI peripheral */ + SPIx->CR1 |= CR1_SPE_Set; + } + else + { + /* Disable the selected SPI peripheral */ + SPIx->CR1 &= CR1_SPE_Reset; + } +} + +/** + * @brief Enables or disables the specified SPI peripheral (in I2S mode). + * @param SPIx: where x can be 2 or 3 to select the SPI peripheral. + * @param NewState: new state of the SPIx peripheral. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void I2S_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_SPI_23_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected SPI peripheral (in I2S mode) */ + SPIx->I2SCFGR |= I2SCFGR_I2SE_Set; + } + else + { + /* Disable the selected SPI peripheral (in I2S mode) */ + SPIx->I2SCFGR &= I2SCFGR_I2SE_Reset; + } +} + +/** + * @brief Enables or disables the specified SPI/I2S interrupts. + * @param SPIx: where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @param SPI_I2S_IT: specifies the SPI/I2S interrupt source to be enabled or disabled. + * This parameter can be one of the following values: + * @arg SPI_I2S_IT_TXE: Tx buffer empty interrupt mask + * @arg SPI_I2S_IT_RXNE: Rx buffer not empty interrupt mask + * @arg SPI_I2S_IT_ERR: Error interrupt mask + * @param NewState: new state of the specified SPI/I2S interrupt. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState) +{ + uint16_t itpos = 0, itmask = 0 ; + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + assert_param(IS_SPI_I2S_CONFIG_IT(SPI_I2S_IT)); + + /* Get the SPI/I2S IT index */ + itpos = SPI_I2S_IT >> 4; + + /* Set the IT mask */ + itmask = (uint16_t)1 << (uint16_t)itpos; + + if (NewState != DISABLE) + { + /* Enable the selected SPI/I2S interrupt */ + SPIx->CR2 |= itmask; + } + else + { + /* Disable the selected SPI/I2S interrupt */ + SPIx->CR2 &= (uint16_t)~itmask; + } +} + +/** + * @brief Enables or disables the SPIx/I2Sx DMA interface. + * @param SPIx: where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @param SPI_I2S_DMAReq: specifies the SPI/I2S DMA transfer request to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg SPI_I2S_DMAReq_Tx: Tx buffer DMA transfer request + * @arg SPI_I2S_DMAReq_Rx: Rx buffer DMA transfer request + * @param NewState: new state of the selected SPI/I2S DMA transfer request. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + assert_param(IS_SPI_I2S_DMAREQ(SPI_I2S_DMAReq)); + if (NewState != DISABLE) + { + /* Enable the selected SPI/I2S DMA requests */ + SPIx->CR2 |= SPI_I2S_DMAReq; + } + else + { + /* Disable the selected SPI/I2S DMA requests */ + SPIx->CR2 &= (uint16_t)~SPI_I2S_DMAReq; + } +} + +/** + * @brief Transmits a Data through the SPIx/I2Sx peripheral. + * @param SPIx: where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @param Data : Data to be transmitted. + * @retval None + */ +void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data) +{ + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + + /* Write in the DR register the data to be sent */ + SPIx->DR = Data; +} + +/** + * @brief Returns the most recent received data by the SPIx/I2Sx peripheral. + * @param SPIx: where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @retval The value of the received data. + */ +uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx) +{ + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + + /* Return the data in the DR register */ + return SPIx->DR; +} + +/** + * @brief Configures internally by software the NSS pin for the selected SPI. + * @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. + * @param SPI_NSSInternalSoft: specifies the SPI NSS internal state. + * This parameter can be one of the following values: + * @arg SPI_NSSInternalSoft_Set: Set NSS pin internally + * @arg SPI_NSSInternalSoft_Reset: Reset NSS pin internally + * @retval None + */ +void SPI_NSSInternalSoftwareConfig(SPI_TypeDef* SPIx, uint16_t SPI_NSSInternalSoft) +{ + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + assert_param(IS_SPI_NSS_INTERNAL(SPI_NSSInternalSoft)); + if (SPI_NSSInternalSoft != SPI_NSSInternalSoft_Reset) + { + /* Set NSS pin internally by software */ + SPIx->CR1 |= SPI_NSSInternalSoft_Set; + } + else + { + /* Reset NSS pin internally by software */ + SPIx->CR1 &= SPI_NSSInternalSoft_Reset; + } +} + +/** + * @brief Enables or disables the SS output for the selected SPI. + * @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. + * @param NewState: new state of the SPIx SS output. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SPI_SSOutputCmd(SPI_TypeDef* SPIx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected SPI SS output */ + SPIx->CR2 |= CR2_SSOE_Set; + } + else + { + /* Disable the selected SPI SS output */ + SPIx->CR2 &= CR2_SSOE_Reset; + } +} + +/** + * @brief Configures the data size for the selected SPI. + * @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. + * @param SPI_DataSize: specifies the SPI data size. + * This parameter can be one of the following values: + * @arg SPI_DataSize_16b: Set data frame format to 16bit + * @arg SPI_DataSize_8b: Set data frame format to 8bit + * @retval None + */ +void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize) +{ + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + assert_param(IS_SPI_DATASIZE(SPI_DataSize)); + /* Clear DFF bit */ + SPIx->CR1 &= (uint16_t)~SPI_DataSize_16b; + /* Set new DFF bit value */ + SPIx->CR1 |= SPI_DataSize; +} + +/** + * @brief Transmit the SPIx CRC value. + * @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. + * @retval None + */ +void SPI_TransmitCRC(SPI_TypeDef* SPIx) +{ + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + + /* Enable the selected SPI CRC transmission */ + SPIx->CR1 |= CR1_CRCNext_Set; +} + +/** + * @brief Enables or disables the CRC value calculation of the transferred bytes. + * @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. + * @param NewState: new state of the SPIx CRC value calculation. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SPI_CalculateCRC(SPI_TypeDef* SPIx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected SPI CRC calculation */ + SPIx->CR1 |= CR1_CRCEN_Set; + } + else + { + /* Disable the selected SPI CRC calculation */ + SPIx->CR1 &= CR1_CRCEN_Reset; + } +} + +/** + * @brief Returns the transmit or the receive CRC register value for the specified SPI. + * @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. + * @param SPI_CRC: specifies the CRC register to be read. + * This parameter can be one of the following values: + * @arg SPI_CRC_Tx: Selects Tx CRC register + * @arg SPI_CRC_Rx: Selects Rx CRC register + * @retval The selected CRC register value.. + */ +uint16_t SPI_GetCRC(SPI_TypeDef* SPIx, uint8_t SPI_CRC) +{ + uint16_t crcreg = 0; + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + assert_param(IS_SPI_CRC(SPI_CRC)); + if (SPI_CRC != SPI_CRC_Rx) + { + /* Get the Tx CRC register */ + crcreg = SPIx->TXCRCR; + } + else + { + /* Get the Rx CRC register */ + crcreg = SPIx->RXCRCR; + } + /* Return the selected CRC register */ + return crcreg; +} + +/** + * @brief Returns the CRC Polynomial register value for the specified SPI. + * @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. + * @retval The CRC Polynomial register value. + */ +uint16_t SPI_GetCRCPolynomial(SPI_TypeDef* SPIx) +{ + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + + /* Return the CRC polynomial register */ + return SPIx->CRCPR; +} + +/** + * @brief Selects the data transfer direction in bi-directional mode for the specified SPI. + * @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. + * @param SPI_Direction: specifies the data transfer direction in bi-directional mode. + * This parameter can be one of the following values: + * @arg SPI_Direction_Tx: Selects Tx transmission direction + * @arg SPI_Direction_Rx: Selects Rx receive direction + * @retval None + */ +void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, uint16_t SPI_Direction) +{ + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + assert_param(IS_SPI_DIRECTION(SPI_Direction)); + if (SPI_Direction == SPI_Direction_Tx) + { + /* Set the Tx only mode */ + SPIx->CR1 |= SPI_Direction_Tx; + } + else + { + /* Set the Rx only mode */ + SPIx->CR1 &= SPI_Direction_Rx; + } +} + +/** + * @brief Checks whether the specified SPI/I2S flag is set or not. + * @param SPIx: where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @param SPI_I2S_FLAG: specifies the SPI/I2S flag to check. + * This parameter can be one of the following values: + * @arg SPI_I2S_FLAG_TXE: Transmit buffer empty flag. + * @arg SPI_I2S_FLAG_RXNE: Receive buffer not empty flag. + * @arg SPI_I2S_FLAG_BSY: Busy flag. + * @arg SPI_I2S_FLAG_OVR: Overrun flag. + * @arg SPI_FLAG_MODF: Mode Fault flag. + * @arg SPI_FLAG_CRCERR: CRC Error flag. + * @arg I2S_FLAG_UDR: Underrun Error flag. + * @arg I2S_FLAG_CHSIDE: Channel Side flag. + * @retval The new state of SPI_I2S_FLAG (SET or RESET). + */ +FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + assert_param(IS_SPI_I2S_GET_FLAG(SPI_I2S_FLAG)); + /* Check the status of the specified SPI/I2S flag */ + if ((SPIx->SR & SPI_I2S_FLAG) != (uint16_t)RESET) + { + /* SPI_I2S_FLAG is set */ + bitstatus = SET; + } + else + { + /* SPI_I2S_FLAG is reset */ + bitstatus = RESET; + } + /* Return the SPI_I2S_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the SPIx CRC Error (CRCERR) flag. + * @param SPIx: where x can be + * - 1, 2 or 3 in SPI mode + * @param SPI_I2S_FLAG: specifies the SPI flag to clear. + * This function clears only CRCERR flag. + * @note + * - OVR (OverRun error) flag is cleared by software sequence: a read + * operation to SPI_DR register (SPI_I2S_ReceiveData()) followed by a read + * operation to SPI_SR register (SPI_I2S_GetFlagStatus()). + * - UDR (UnderRun error) flag is cleared by a read operation to + * SPI_SR register (SPI_I2S_GetFlagStatus()). + * - MODF (Mode Fault) flag is cleared by software sequence: a read/write + * operation to SPI_SR register (SPI_I2S_GetFlagStatus()) followed by a + * write operation to SPI_CR1 register (SPI_Cmd() to enable the SPI). + * @retval None + */ +void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG) +{ + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + assert_param(IS_SPI_I2S_CLEAR_FLAG(SPI_I2S_FLAG)); + + /* Clear the selected SPI CRC Error (CRCERR) flag */ + SPIx->SR = (uint16_t)~SPI_I2S_FLAG; +} + +/** + * @brief Checks whether the specified SPI/I2S interrupt has occurred or not. + * @param SPIx: where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @param SPI_I2S_IT: specifies the SPI/I2S interrupt source to check. + * This parameter can be one of the following values: + * @arg SPI_I2S_IT_TXE: Transmit buffer empty interrupt. + * @arg SPI_I2S_IT_RXNE: Receive buffer not empty interrupt. + * @arg SPI_I2S_IT_OVR: Overrun interrupt. + * @arg SPI_IT_MODF: Mode Fault interrupt. + * @arg SPI_IT_CRCERR: CRC Error interrupt. + * @arg I2S_IT_UDR: Underrun Error interrupt. + * @retval The new state of SPI_I2S_IT (SET or RESET). + */ +ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT) +{ + ITStatus bitstatus = RESET; + uint16_t itpos = 0, itmask = 0, enablestatus = 0; + + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + assert_param(IS_SPI_I2S_GET_IT(SPI_I2S_IT)); + + /* Get the SPI/I2S IT index */ + itpos = 0x01 << (SPI_I2S_IT & 0x0F); + + /* Get the SPI/I2S IT mask */ + itmask = SPI_I2S_IT >> 4; + + /* Set the IT mask */ + itmask = 0x01 << itmask; + + /* Get the SPI_I2S_IT enable bit status */ + enablestatus = (SPIx->CR2 & itmask) ; + + /* Check the status of the specified SPI/I2S interrupt */ + if (((SPIx->SR & itpos) != (uint16_t)RESET) && enablestatus) + { + /* SPI_I2S_IT is set */ + bitstatus = SET; + } + else + { + /* SPI_I2S_IT is reset */ + bitstatus = RESET; + } + /* Return the SPI_I2S_IT status */ + return bitstatus; +} + +/** + * @brief Clears the SPIx CRC Error (CRCERR) interrupt pending bit. + * @param SPIx: where x can be + * - 1, 2 or 3 in SPI mode + * @param SPI_I2S_IT: specifies the SPI interrupt pending bit to clear. + * This function clears only CRCERR interrupt pending bit. + * @note + * - OVR (OverRun Error) interrupt pending bit is cleared by software + * sequence: a read operation to SPI_DR register (SPI_I2S_ReceiveData()) + * followed by a read operation to SPI_SR register (SPI_I2S_GetITStatus()). + * - UDR (UnderRun Error) interrupt pending bit is cleared by a read + * operation to SPI_SR register (SPI_I2S_GetITStatus()). + * - MODF (Mode Fault) interrupt pending bit is cleared by software sequence: + * a read/write operation to SPI_SR register (SPI_I2S_GetITStatus()) + * followed by a write operation to SPI_CR1 register (SPI_Cmd() to enable + * the SPI). + * @retval None + */ +void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT) +{ + uint16_t itpos = 0; + /* Check the parameters */ + assert_param(IS_SPI_ALL_PERIPH(SPIx)); + assert_param(IS_SPI_I2S_CLEAR_IT(SPI_I2S_IT)); + + /* Get the SPI IT index */ + itpos = 0x01 << (SPI_I2S_IT & 0x0F); + + /* Clear the selected SPI CRC Error (CRCERR) interrupt pending bit */ + SPIx->SR = (uint16_t)~itpos; +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_spi.h b/Library/stm32f10x_spi.h new file mode 100644 index 0000000..23cc26d --- /dev/null +++ b/Library/stm32f10x_spi.h @@ -0,0 +1,487 @@ +/** + ****************************************************************************** + * @file stm32f10x_spi.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the SPI firmware + * library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_SPI_H +#define __STM32F10x_SPI_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup SPI + * @{ + */ + +/** @defgroup SPI_Exported_Types + * @{ + */ + +/** + * @brief SPI Init structure definition + */ + +typedef struct +{ + uint16_t SPI_Direction; /*!< Specifies the SPI unidirectional or bidirectional data mode. + This parameter can be a value of @ref SPI_data_direction */ + + uint16_t SPI_Mode; /*!< Specifies the SPI operating mode. + This parameter can be a value of @ref SPI_mode */ + + uint16_t SPI_DataSize; /*!< Specifies the SPI data size. + This parameter can be a value of @ref SPI_data_size */ + + uint16_t SPI_CPOL; /*!< Specifies the serial clock steady state. + This parameter can be a value of @ref SPI_Clock_Polarity */ + + uint16_t SPI_CPHA; /*!< Specifies the clock active edge for the bit capture. + This parameter can be a value of @ref SPI_Clock_Phase */ + + uint16_t SPI_NSS; /*!< Specifies whether the NSS signal is managed by + hardware (NSS pin) or by software using the SSI bit. + This parameter can be a value of @ref SPI_Slave_Select_management */ + + uint16_t SPI_BaudRatePrescaler; /*!< Specifies the Baud Rate prescaler value which will be + used to configure the transmit and receive SCK clock. + This parameter can be a value of @ref SPI_BaudRate_Prescaler. + @note The communication clock is derived from the master + clock. The slave clock does not need to be set. */ + + uint16_t SPI_FirstBit; /*!< Specifies whether data transfers start from MSB or LSB bit. + This parameter can be a value of @ref SPI_MSB_LSB_transmission */ + + uint16_t SPI_CRCPolynomial; /*!< Specifies the polynomial used for the CRC calculation. */ +}SPI_InitTypeDef; + +/** + * @brief I2S Init structure definition + */ + +typedef struct +{ + + uint16_t I2S_Mode; /*!< Specifies the I2S operating mode. + This parameter can be a value of @ref I2S_Mode */ + + uint16_t I2S_Standard; /*!< Specifies the standard used for the I2S communication. + This parameter can be a value of @ref I2S_Standard */ + + uint16_t I2S_DataFormat; /*!< Specifies the data format for the I2S communication. + This parameter can be a value of @ref I2S_Data_Format */ + + uint16_t I2S_MCLKOutput; /*!< Specifies whether the I2S MCLK output is enabled or not. + This parameter can be a value of @ref I2S_MCLK_Output */ + + uint32_t I2S_AudioFreq; /*!< Specifies the frequency selected for the I2S communication. + This parameter can be a value of @ref I2S_Audio_Frequency */ + + uint16_t I2S_CPOL; /*!< Specifies the idle state of the I2S clock. + This parameter can be a value of @ref I2S_Clock_Polarity */ +}I2S_InitTypeDef; + +/** + * @} + */ + +/** @defgroup SPI_Exported_Constants + * @{ + */ + +#define IS_SPI_ALL_PERIPH(PERIPH) (((PERIPH) == SPI1) || \ + ((PERIPH) == SPI2) || \ + ((PERIPH) == SPI3)) + +#define IS_SPI_23_PERIPH(PERIPH) (((PERIPH) == SPI2) || \ + ((PERIPH) == SPI3)) + +/** @defgroup SPI_data_direction + * @{ + */ + +#define SPI_Direction_2Lines_FullDuplex ((uint16_t)0x0000) +#define SPI_Direction_2Lines_RxOnly ((uint16_t)0x0400) +#define SPI_Direction_1Line_Rx ((uint16_t)0x8000) +#define SPI_Direction_1Line_Tx ((uint16_t)0xC000) +#define IS_SPI_DIRECTION_MODE(MODE) (((MODE) == SPI_Direction_2Lines_FullDuplex) || \ + ((MODE) == SPI_Direction_2Lines_RxOnly) || \ + ((MODE) == SPI_Direction_1Line_Rx) || \ + ((MODE) == SPI_Direction_1Line_Tx)) +/** + * @} + */ + +/** @defgroup SPI_mode + * @{ + */ + +#define SPI_Mode_Master ((uint16_t)0x0104) +#define SPI_Mode_Slave ((uint16_t)0x0000) +#define IS_SPI_MODE(MODE) (((MODE) == SPI_Mode_Master) || \ + ((MODE) == SPI_Mode_Slave)) +/** + * @} + */ + +/** @defgroup SPI_data_size + * @{ + */ + +#define SPI_DataSize_16b ((uint16_t)0x0800) +#define SPI_DataSize_8b ((uint16_t)0x0000) +#define IS_SPI_DATASIZE(DATASIZE) (((DATASIZE) == SPI_DataSize_16b) || \ + ((DATASIZE) == SPI_DataSize_8b)) +/** + * @} + */ + +/** @defgroup SPI_Clock_Polarity + * @{ + */ + +#define SPI_CPOL_Low ((uint16_t)0x0000) +#define SPI_CPOL_High ((uint16_t)0x0002) +#define IS_SPI_CPOL(CPOL) (((CPOL) == SPI_CPOL_Low) || \ + ((CPOL) == SPI_CPOL_High)) +/** + * @} + */ + +/** @defgroup SPI_Clock_Phase + * @{ + */ + +#define SPI_CPHA_1Edge ((uint16_t)0x0000) +#define SPI_CPHA_2Edge ((uint16_t)0x0001) +#define IS_SPI_CPHA(CPHA) (((CPHA) == SPI_CPHA_1Edge) || \ + ((CPHA) == SPI_CPHA_2Edge)) +/** + * @} + */ + +/** @defgroup SPI_Slave_Select_management + * @{ + */ + +#define SPI_NSS_Soft ((uint16_t)0x0200) +#define SPI_NSS_Hard ((uint16_t)0x0000) +#define IS_SPI_NSS(NSS) (((NSS) == SPI_NSS_Soft) || \ + ((NSS) == SPI_NSS_Hard)) +/** + * @} + */ + +/** @defgroup SPI_BaudRate_Prescaler + * @{ + */ + +#define SPI_BaudRatePrescaler_2 ((uint16_t)0x0000) +#define SPI_BaudRatePrescaler_4 ((uint16_t)0x0008) +#define SPI_BaudRatePrescaler_8 ((uint16_t)0x0010) +#define SPI_BaudRatePrescaler_16 ((uint16_t)0x0018) +#define SPI_BaudRatePrescaler_32 ((uint16_t)0x0020) +#define SPI_BaudRatePrescaler_64 ((uint16_t)0x0028) +#define SPI_BaudRatePrescaler_128 ((uint16_t)0x0030) +#define SPI_BaudRatePrescaler_256 ((uint16_t)0x0038) +#define IS_SPI_BAUDRATE_PRESCALER(PRESCALER) (((PRESCALER) == SPI_BaudRatePrescaler_2) || \ + ((PRESCALER) == SPI_BaudRatePrescaler_4) || \ + ((PRESCALER) == SPI_BaudRatePrescaler_8) || \ + ((PRESCALER) == SPI_BaudRatePrescaler_16) || \ + ((PRESCALER) == SPI_BaudRatePrescaler_32) || \ + ((PRESCALER) == SPI_BaudRatePrescaler_64) || \ + ((PRESCALER) == SPI_BaudRatePrescaler_128) || \ + ((PRESCALER) == SPI_BaudRatePrescaler_256)) +/** + * @} + */ + +/** @defgroup SPI_MSB_LSB_transmission + * @{ + */ + +#define SPI_FirstBit_MSB ((uint16_t)0x0000) +#define SPI_FirstBit_LSB ((uint16_t)0x0080) +#define IS_SPI_FIRST_BIT(BIT) (((BIT) == SPI_FirstBit_MSB) || \ + ((BIT) == SPI_FirstBit_LSB)) +/** + * @} + */ + +/** @defgroup I2S_Mode + * @{ + */ + +#define I2S_Mode_SlaveTx ((uint16_t)0x0000) +#define I2S_Mode_SlaveRx ((uint16_t)0x0100) +#define I2S_Mode_MasterTx ((uint16_t)0x0200) +#define I2S_Mode_MasterRx ((uint16_t)0x0300) +#define IS_I2S_MODE(MODE) (((MODE) == I2S_Mode_SlaveTx) || \ + ((MODE) == I2S_Mode_SlaveRx) || \ + ((MODE) == I2S_Mode_MasterTx) || \ + ((MODE) == I2S_Mode_MasterRx) ) +/** + * @} + */ + +/** @defgroup I2S_Standard + * @{ + */ + +#define I2S_Standard_Phillips ((uint16_t)0x0000) +#define I2S_Standard_MSB ((uint16_t)0x0010) +#define I2S_Standard_LSB ((uint16_t)0x0020) +#define I2S_Standard_PCMShort ((uint16_t)0x0030) +#define I2S_Standard_PCMLong ((uint16_t)0x00B0) +#define IS_I2S_STANDARD(STANDARD) (((STANDARD) == I2S_Standard_Phillips) || \ + ((STANDARD) == I2S_Standard_MSB) || \ + ((STANDARD) == I2S_Standard_LSB) || \ + ((STANDARD) == I2S_Standard_PCMShort) || \ + ((STANDARD) == I2S_Standard_PCMLong)) +/** + * @} + */ + +/** @defgroup I2S_Data_Format + * @{ + */ + +#define I2S_DataFormat_16b ((uint16_t)0x0000) +#define I2S_DataFormat_16bextended ((uint16_t)0x0001) +#define I2S_DataFormat_24b ((uint16_t)0x0003) +#define I2S_DataFormat_32b ((uint16_t)0x0005) +#define IS_I2S_DATA_FORMAT(FORMAT) (((FORMAT) == I2S_DataFormat_16b) || \ + ((FORMAT) == I2S_DataFormat_16bextended) || \ + ((FORMAT) == I2S_DataFormat_24b) || \ + ((FORMAT) == I2S_DataFormat_32b)) +/** + * @} + */ + +/** @defgroup I2S_MCLK_Output + * @{ + */ + +#define I2S_MCLKOutput_Enable ((uint16_t)0x0200) +#define I2S_MCLKOutput_Disable ((uint16_t)0x0000) +#define IS_I2S_MCLK_OUTPUT(OUTPUT) (((OUTPUT) == I2S_MCLKOutput_Enable) || \ + ((OUTPUT) == I2S_MCLKOutput_Disable)) +/** + * @} + */ + +/** @defgroup I2S_Audio_Frequency + * @{ + */ + +#define I2S_AudioFreq_192k ((uint32_t)192000) +#define I2S_AudioFreq_96k ((uint32_t)96000) +#define I2S_AudioFreq_48k ((uint32_t)48000) +#define I2S_AudioFreq_44k ((uint32_t)44100) +#define I2S_AudioFreq_32k ((uint32_t)32000) +#define I2S_AudioFreq_22k ((uint32_t)22050) +#define I2S_AudioFreq_16k ((uint32_t)16000) +#define I2S_AudioFreq_11k ((uint32_t)11025) +#define I2S_AudioFreq_8k ((uint32_t)8000) +#define I2S_AudioFreq_Default ((uint32_t)2) + +#define IS_I2S_AUDIO_FREQ(FREQ) ((((FREQ) >= I2S_AudioFreq_8k) && \ + ((FREQ) <= I2S_AudioFreq_192k)) || \ + ((FREQ) == I2S_AudioFreq_Default)) +/** + * @} + */ + +/** @defgroup I2S_Clock_Polarity + * @{ + */ + +#define I2S_CPOL_Low ((uint16_t)0x0000) +#define I2S_CPOL_High ((uint16_t)0x0008) +#define IS_I2S_CPOL(CPOL) (((CPOL) == I2S_CPOL_Low) || \ + ((CPOL) == I2S_CPOL_High)) +/** + * @} + */ + +/** @defgroup SPI_I2S_DMA_transfer_requests + * @{ + */ + +#define SPI_I2S_DMAReq_Tx ((uint16_t)0x0002) +#define SPI_I2S_DMAReq_Rx ((uint16_t)0x0001) +#define IS_SPI_I2S_DMAREQ(DMAREQ) ((((DMAREQ) & (uint16_t)0xFFFC) == 0x00) && ((DMAREQ) != 0x00)) +/** + * @} + */ + +/** @defgroup SPI_NSS_internal_software_management + * @{ + */ + +#define SPI_NSSInternalSoft_Set ((uint16_t)0x0100) +#define SPI_NSSInternalSoft_Reset ((uint16_t)0xFEFF) +#define IS_SPI_NSS_INTERNAL(INTERNAL) (((INTERNAL) == SPI_NSSInternalSoft_Set) || \ + ((INTERNAL) == SPI_NSSInternalSoft_Reset)) +/** + * @} + */ + +/** @defgroup SPI_CRC_Transmit_Receive + * @{ + */ + +#define SPI_CRC_Tx ((uint8_t)0x00) +#define SPI_CRC_Rx ((uint8_t)0x01) +#define IS_SPI_CRC(CRC) (((CRC) == SPI_CRC_Tx) || ((CRC) == SPI_CRC_Rx)) +/** + * @} + */ + +/** @defgroup SPI_direction_transmit_receive + * @{ + */ + +#define SPI_Direction_Rx ((uint16_t)0xBFFF) +#define SPI_Direction_Tx ((uint16_t)0x4000) +#define IS_SPI_DIRECTION(DIRECTION) (((DIRECTION) == SPI_Direction_Rx) || \ + ((DIRECTION) == SPI_Direction_Tx)) +/** + * @} + */ + +/** @defgroup SPI_I2S_interrupts_definition + * @{ + */ + +#define SPI_I2S_IT_TXE ((uint8_t)0x71) +#define SPI_I2S_IT_RXNE ((uint8_t)0x60) +#define SPI_I2S_IT_ERR ((uint8_t)0x50) +#define IS_SPI_I2S_CONFIG_IT(IT) (((IT) == SPI_I2S_IT_TXE) || \ + ((IT) == SPI_I2S_IT_RXNE) || \ + ((IT) == SPI_I2S_IT_ERR)) +#define SPI_I2S_IT_OVR ((uint8_t)0x56) +#define SPI_IT_MODF ((uint8_t)0x55) +#define SPI_IT_CRCERR ((uint8_t)0x54) +#define I2S_IT_UDR ((uint8_t)0x53) +#define IS_SPI_I2S_CLEAR_IT(IT) (((IT) == SPI_IT_CRCERR)) +#define IS_SPI_I2S_GET_IT(IT) (((IT) == SPI_I2S_IT_RXNE) || ((IT) == SPI_I2S_IT_TXE) || \ + ((IT) == I2S_IT_UDR) || ((IT) == SPI_IT_CRCERR) || \ + ((IT) == SPI_IT_MODF) || ((IT) == SPI_I2S_IT_OVR)) +/** + * @} + */ + +/** @defgroup SPI_I2S_flags_definition + * @{ + */ + +#define SPI_I2S_FLAG_RXNE ((uint16_t)0x0001) +#define SPI_I2S_FLAG_TXE ((uint16_t)0x0002) +#define I2S_FLAG_CHSIDE ((uint16_t)0x0004) +#define I2S_FLAG_UDR ((uint16_t)0x0008) +#define SPI_FLAG_CRCERR ((uint16_t)0x0010) +#define SPI_FLAG_MODF ((uint16_t)0x0020) +#define SPI_I2S_FLAG_OVR ((uint16_t)0x0040) +#define SPI_I2S_FLAG_BSY ((uint16_t)0x0080) +#define IS_SPI_I2S_CLEAR_FLAG(FLAG) (((FLAG) == SPI_FLAG_CRCERR)) +#define IS_SPI_I2S_GET_FLAG(FLAG) (((FLAG) == SPI_I2S_FLAG_BSY) || ((FLAG) == SPI_I2S_FLAG_OVR) || \ + ((FLAG) == SPI_FLAG_MODF) || ((FLAG) == SPI_FLAG_CRCERR) || \ + ((FLAG) == I2S_FLAG_UDR) || ((FLAG) == I2S_FLAG_CHSIDE) || \ + ((FLAG) == SPI_I2S_FLAG_TXE) || ((FLAG) == SPI_I2S_FLAG_RXNE)) +/** + * @} + */ + +/** @defgroup SPI_CRC_polynomial + * @{ + */ + +#define IS_SPI_CRC_POLYNOMIAL(POLYNOMIAL) ((POLYNOMIAL) >= 0x1) +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup SPI_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup SPI_Exported_Functions + * @{ + */ + +void SPI_I2S_DeInit(SPI_TypeDef* SPIx); +void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct); +void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct); +void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct); +void I2S_StructInit(I2S_InitTypeDef* I2S_InitStruct); +void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState); +void I2S_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState); +void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState); +void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState); +void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data); +uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx); +void SPI_NSSInternalSoftwareConfig(SPI_TypeDef* SPIx, uint16_t SPI_NSSInternalSoft); +void SPI_SSOutputCmd(SPI_TypeDef* SPIx, FunctionalState NewState); +void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize); +void SPI_TransmitCRC(SPI_TypeDef* SPIx); +void SPI_CalculateCRC(SPI_TypeDef* SPIx, FunctionalState NewState); +uint16_t SPI_GetCRC(SPI_TypeDef* SPIx, uint8_t SPI_CRC); +uint16_t SPI_GetCRCPolynomial(SPI_TypeDef* SPIx); +void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, uint16_t SPI_Direction); +FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG); +void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG); +ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT); +void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT); + +#ifdef __cplusplus +} +#endif + +#endif /*__STM32F10x_SPI_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_tim.c b/Library/stm32f10x_tim.c new file mode 100644 index 0000000..bfb4dd1 --- /dev/null +++ b/Library/stm32f10x_tim.c @@ -0,0 +1,2890 @@ +/** + ****************************************************************************** + * @file stm32f10x_tim.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the TIM firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_tim.h" +#include "stm32f10x_rcc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup TIM + * @brief TIM driver modules + * @{ + */ + +/** @defgroup TIM_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup TIM_Private_Defines + * @{ + */ + +/* ---------------------- TIM registers bit mask ------------------------ */ +#define SMCR_ETR_Mask ((uint16_t)0x00FF) +#define CCMR_Offset ((uint16_t)0x0018) +#define CCER_CCE_Set ((uint16_t)0x0001) +#define CCER_CCNE_Set ((uint16_t)0x0004) + +/** + * @} + */ + +/** @defgroup TIM_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup TIM_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup TIM_Private_FunctionPrototypes + * @{ + */ + +static void TI1_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter); +static void TI2_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter); +static void TI3_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter); +static void TI4_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter); +/** + * @} + */ + +/** @defgroup TIM_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup TIM_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup TIM_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup TIM_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the TIMx peripheral registers to their default reset values. + * @param TIMx: where x can be 1 to 17 to select the TIM peripheral. + * @retval None + */ +void TIM_DeInit(TIM_TypeDef* TIMx) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + + if (TIMx == TIM1) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, DISABLE); + } + else if (TIMx == TIM2) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, DISABLE); + } + else if (TIMx == TIM3) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, DISABLE); + } + else if (TIMx == TIM4) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, DISABLE); + } + else if (TIMx == TIM5) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, DISABLE); + } + else if (TIMx == TIM6) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM6, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM6, DISABLE); + } + else if (TIMx == TIM7) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM7, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM7, DISABLE); + } + else if (TIMx == TIM8) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM8, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM8, DISABLE); + } + else if (TIMx == TIM9) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM9, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM9, DISABLE); + } + else if (TIMx == TIM10) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM10, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM10, DISABLE); + } + else if (TIMx == TIM11) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM11, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM11, DISABLE); + } + else if (TIMx == TIM12) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM12, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM12, DISABLE); + } + else if (TIMx == TIM13) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM13, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM13, DISABLE); + } + else if (TIMx == TIM14) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM14, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM14, DISABLE); + } + else if (TIMx == TIM15) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM15, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM15, DISABLE); + } + else if (TIMx == TIM16) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM16, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM16, DISABLE); + } + else + { + if (TIMx == TIM17) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM17, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM17, DISABLE); + } + } +} + +/** + * @brief Initializes the TIMx Time Base Unit peripheral according to + * the specified parameters in the TIM_TimeBaseInitStruct. + * @param TIMx: where x can be 1 to 17 to select the TIM peripheral. + * @param TIM_TimeBaseInitStruct: pointer to a TIM_TimeBaseInitTypeDef + * structure that contains the configuration information for the + * specified TIM peripheral. + * @retval None + */ +void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct) +{ + uint16_t tmpcr1 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_COUNTER_MODE(TIM_TimeBaseInitStruct->TIM_CounterMode)); + assert_param(IS_TIM_CKD_DIV(TIM_TimeBaseInitStruct->TIM_ClockDivision)); + + tmpcr1 = TIMx->CR1; + + if((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM2) || (TIMx == TIM3)|| + (TIMx == TIM4) || (TIMx == TIM5)) + { + /* Select the Counter Mode */ + tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS))); + tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_CounterMode; + } + + if((TIMx != TIM6) && (TIMx != TIM7)) + { + /* Set the clock division */ + tmpcr1 &= (uint16_t)(~((uint16_t)TIM_CR1_CKD)); + tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_ClockDivision; + } + + TIMx->CR1 = tmpcr1; + + /* Set the Autoreload value */ + TIMx->ARR = TIM_TimeBaseInitStruct->TIM_Period ; + + /* Set the Prescaler value */ + TIMx->PSC = TIM_TimeBaseInitStruct->TIM_Prescaler; + + if ((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM15)|| (TIMx == TIM16) || (TIMx == TIM17)) + { + /* Set the Repetition Counter value */ + TIMx->RCR = TIM_TimeBaseInitStruct->TIM_RepetitionCounter; + } + + /* Generate an update event to reload the Prescaler and the Repetition counter + values immediately */ + TIMx->EGR = TIM_PSCReloadMode_Immediate; +} + +/** + * @brief Initializes the TIMx Channel1 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral. + * @param TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure + * that contains the configuration information for the specified TIM peripheral. + * @retval None + */ +void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST8_PERIPH(TIMx)); + assert_param(IS_TIM_OC_MODE(TIM_OCInitStruct->TIM_OCMode)); + assert_param(IS_TIM_OUTPUT_STATE(TIM_OCInitStruct->TIM_OutputState)); + assert_param(IS_TIM_OC_POLARITY(TIM_OCInitStruct->TIM_OCPolarity)); + /* Disable the Channel 1: Reset the CC1E Bit */ + TIMx->CCER &= (uint16_t)(~(uint16_t)TIM_CCER_CC1E); + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + /* Get the TIMx CR2 register value */ + tmpcr2 = TIMx->CR2; + + /* Get the TIMx CCMR1 register value */ + tmpccmrx = TIMx->CCMR1; + + /* Reset the Output Compare Mode Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_OC1M)); + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_CC1S)); + + /* Select the Output Compare Mode */ + tmpccmrx |= TIM_OCInitStruct->TIM_OCMode; + + /* Reset the Output Polarity level */ + tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC1P)); + /* Set the Output Compare Polarity */ + tmpccer |= TIM_OCInitStruct->TIM_OCPolarity; + + /* Set the Output State */ + tmpccer |= TIM_OCInitStruct->TIM_OutputState; + + if((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM15)|| + (TIMx == TIM16)|| (TIMx == TIM17)) + { + assert_param(IS_TIM_OUTPUTN_STATE(TIM_OCInitStruct->TIM_OutputNState)); + assert_param(IS_TIM_OCN_POLARITY(TIM_OCInitStruct->TIM_OCNPolarity)); + assert_param(IS_TIM_OCNIDLE_STATE(TIM_OCInitStruct->TIM_OCNIdleState)); + assert_param(IS_TIM_OCIDLE_STATE(TIM_OCInitStruct->TIM_OCIdleState)); + + /* Reset the Output N Polarity level */ + tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC1NP)); + /* Set the Output N Polarity */ + tmpccer |= TIM_OCInitStruct->TIM_OCNPolarity; + + /* Reset the Output N State */ + tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC1NE)); + /* Set the Output N State */ + tmpccer |= TIM_OCInitStruct->TIM_OutputNState; + + /* Reset the Output Compare and Output Compare N IDLE State */ + tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS1)); + tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS1N)); + + /* Set the Output Idle state */ + tmpcr2 |= TIM_OCInitStruct->TIM_OCIdleState; + /* Set the Output N Idle state */ + tmpcr2 |= TIM_OCInitStruct->TIM_OCNIdleState; + } + /* Write to TIMx CR2 */ + TIMx->CR2 = tmpcr2; + + /* Write to TIMx CCMR1 */ + TIMx->CCMR1 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCR1 = TIM_OCInitStruct->TIM_Pulse; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Initializes the TIMx Channel2 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select + * the TIM peripheral. + * @param TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure + * that contains the configuration information for the specified TIM peripheral. + * @retval None + */ +void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + assert_param(IS_TIM_OC_MODE(TIM_OCInitStruct->TIM_OCMode)); + assert_param(IS_TIM_OUTPUT_STATE(TIM_OCInitStruct->TIM_OutputState)); + assert_param(IS_TIM_OC_POLARITY(TIM_OCInitStruct->TIM_OCPolarity)); + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCER &= (uint16_t)(~((uint16_t)TIM_CCER_CC2E)); + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + /* Get the TIMx CR2 register value */ + tmpcr2 = TIMx->CR2; + + /* Get the TIMx CCMR1 register value */ + tmpccmrx = TIMx->CCMR1; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_OC2M)); + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_CC2S)); + + /* Select the Output Compare Mode */ + tmpccmrx |= (uint16_t)(TIM_OCInitStruct->TIM_OCMode << 8); + + /* Reset the Output Polarity level */ + tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC2P)); + /* Set the Output Compare Polarity */ + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCPolarity << 4); + + /* Set the Output State */ + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputState << 4); + + if((TIMx == TIM1) || (TIMx == TIM8)) + { + assert_param(IS_TIM_OUTPUTN_STATE(TIM_OCInitStruct->TIM_OutputNState)); + assert_param(IS_TIM_OCN_POLARITY(TIM_OCInitStruct->TIM_OCNPolarity)); + assert_param(IS_TIM_OCNIDLE_STATE(TIM_OCInitStruct->TIM_OCNIdleState)); + assert_param(IS_TIM_OCIDLE_STATE(TIM_OCInitStruct->TIM_OCIdleState)); + + /* Reset the Output N Polarity level */ + tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC2NP)); + /* Set the Output N Polarity */ + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCNPolarity << 4); + + /* Reset the Output N State */ + tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC2NE)); + /* Set the Output N State */ + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputNState << 4); + + /* Reset the Output Compare and Output Compare N IDLE State */ + tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS2)); + tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS2N)); + + /* Set the Output Idle state */ + tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCIdleState << 2); + /* Set the Output N Idle state */ + tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCNIdleState << 2); + } + /* Write to TIMx CR2 */ + TIMx->CR2 = tmpcr2; + + /* Write to TIMx CCMR1 */ + TIMx->CCMR1 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCR2 = TIM_OCInitStruct->TIM_Pulse; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Initializes the TIMx Channel3 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure + * that contains the configuration information for the specified TIM peripheral. + * @retval None + */ +void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OC_MODE(TIM_OCInitStruct->TIM_OCMode)); + assert_param(IS_TIM_OUTPUT_STATE(TIM_OCInitStruct->TIM_OutputState)); + assert_param(IS_TIM_OC_POLARITY(TIM_OCInitStruct->TIM_OCPolarity)); + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCER &= (uint16_t)(~((uint16_t)TIM_CCER_CC3E)); + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + /* Get the TIMx CR2 register value */ + tmpcr2 = TIMx->CR2; + + /* Get the TIMx CCMR2 register value */ + tmpccmrx = TIMx->CCMR2; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_OC3M)); + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_CC3S)); + /* Select the Output Compare Mode */ + tmpccmrx |= TIM_OCInitStruct->TIM_OCMode; + + /* Reset the Output Polarity level */ + tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC3P)); + /* Set the Output Compare Polarity */ + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCPolarity << 8); + + /* Set the Output State */ + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputState << 8); + + if((TIMx == TIM1) || (TIMx == TIM8)) + { + assert_param(IS_TIM_OUTPUTN_STATE(TIM_OCInitStruct->TIM_OutputNState)); + assert_param(IS_TIM_OCN_POLARITY(TIM_OCInitStruct->TIM_OCNPolarity)); + assert_param(IS_TIM_OCNIDLE_STATE(TIM_OCInitStruct->TIM_OCNIdleState)); + assert_param(IS_TIM_OCIDLE_STATE(TIM_OCInitStruct->TIM_OCIdleState)); + + /* Reset the Output N Polarity level */ + tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC3NP)); + /* Set the Output N Polarity */ + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCNPolarity << 8); + /* Reset the Output N State */ + tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC3NE)); + + /* Set the Output N State */ + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputNState << 8); + /* Reset the Output Compare and Output Compare N IDLE State */ + tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS3)); + tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS3N)); + /* Set the Output Idle state */ + tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCIdleState << 4); + /* Set the Output N Idle state */ + tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCNIdleState << 4); + } + /* Write to TIMx CR2 */ + TIMx->CR2 = tmpcr2; + + /* Write to TIMx CCMR2 */ + TIMx->CCMR2 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCR3 = TIM_OCInitStruct->TIM_Pulse; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Initializes the TIMx Channel4 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure + * that contains the configuration information for the specified TIM peripheral. + * @retval None + */ +void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OC_MODE(TIM_OCInitStruct->TIM_OCMode)); + assert_param(IS_TIM_OUTPUT_STATE(TIM_OCInitStruct->TIM_OutputState)); + assert_param(IS_TIM_OC_POLARITY(TIM_OCInitStruct->TIM_OCPolarity)); + /* Disable the Channel 2: Reset the CC4E Bit */ + TIMx->CCER &= (uint16_t)(~((uint16_t)TIM_CCER_CC4E)); + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + /* Get the TIMx CR2 register value */ + tmpcr2 = TIMx->CR2; + + /* Get the TIMx CCMR2 register value */ + tmpccmrx = TIMx->CCMR2; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_OC4M)); + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_CC4S)); + + /* Select the Output Compare Mode */ + tmpccmrx |= (uint16_t)(TIM_OCInitStruct->TIM_OCMode << 8); + + /* Reset the Output Polarity level */ + tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC4P)); + /* Set the Output Compare Polarity */ + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCPolarity << 12); + + /* Set the Output State */ + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputState << 12); + + if((TIMx == TIM1) || (TIMx == TIM8)) + { + assert_param(IS_TIM_OCIDLE_STATE(TIM_OCInitStruct->TIM_OCIdleState)); + /* Reset the Output Compare IDLE State */ + tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS4)); + /* Set the Output Idle state */ + tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCIdleState << 6); + } + /* Write to TIMx CR2 */ + TIMx->CR2 = tmpcr2; + + /* Write to TIMx CCMR2 */ + TIMx->CCMR2 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCR4 = TIM_OCInitStruct->TIM_Pulse; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Initializes the TIM peripheral according to the specified + * parameters in the TIM_ICInitStruct. + * @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral. + * @param TIM_ICInitStruct: pointer to a TIM_ICInitTypeDef structure + * that contains the configuration information for the specified TIM peripheral. + * @retval None + */ +void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct) +{ + /* Check the parameters */ + assert_param(IS_TIM_CHANNEL(TIM_ICInitStruct->TIM_Channel)); + assert_param(IS_TIM_IC_SELECTION(TIM_ICInitStruct->TIM_ICSelection)); + assert_param(IS_TIM_IC_PRESCALER(TIM_ICInitStruct->TIM_ICPrescaler)); + assert_param(IS_TIM_IC_FILTER(TIM_ICInitStruct->TIM_ICFilter)); + + if((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || + (TIMx == TIM4) ||(TIMx == TIM5)) + { + assert_param(IS_TIM_IC_POLARITY(TIM_ICInitStruct->TIM_ICPolarity)); + } + else + { + assert_param(IS_TIM_IC_POLARITY_LITE(TIM_ICInitStruct->TIM_ICPolarity)); + } + if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_1) + { + assert_param(IS_TIM_LIST8_PERIPH(TIMx)); + /* TI1 Configuration */ + TI1_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, + TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } + else if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_2) + { + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + /* TI2 Configuration */ + TI2_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, + TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } + else if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_3) + { + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + /* TI3 Configuration */ + TI3_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, + TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetIC3Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } + else + { + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + /* TI4 Configuration */ + TI4_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, + TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetIC4Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } +} + +/** + * @brief Configures the TIM peripheral according to the specified + * parameters in the TIM_ICInitStruct to measure an external PWM signal. + * @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral. + * @param TIM_ICInitStruct: pointer to a TIM_ICInitTypeDef structure + * that contains the configuration information for the specified TIM peripheral. + * @retval None + */ +void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct) +{ + uint16_t icoppositepolarity = TIM_ICPolarity_Rising; + uint16_t icoppositeselection = TIM_ICSelection_DirectTI; + /* Check the parameters */ + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + /* Select the Opposite Input Polarity */ + if (TIM_ICInitStruct->TIM_ICPolarity == TIM_ICPolarity_Rising) + { + icoppositepolarity = TIM_ICPolarity_Falling; + } + else + { + icoppositepolarity = TIM_ICPolarity_Rising; + } + /* Select the Opposite Input */ + if (TIM_ICInitStruct->TIM_ICSelection == TIM_ICSelection_DirectTI) + { + icoppositeselection = TIM_ICSelection_IndirectTI; + } + else + { + icoppositeselection = TIM_ICSelection_DirectTI; + } + if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_1) + { + /* TI1 Configuration */ + TI1_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + /* TI2 Configuration */ + TI2_Config(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->TIM_ICFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } + else + { + /* TI2 Configuration */ + TI2_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + /* TI1 Configuration */ + TI1_Config(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->TIM_ICFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } +} + +/** + * @brief Configures the: Break feature, dead time, Lock level, the OSSI, + * the OSSR State and the AOE(automatic output enable). + * @param TIMx: where x can be 1 or 8 to select the TIM + * @param TIM_BDTRInitStruct: pointer to a TIM_BDTRInitTypeDef structure that + * contains the BDTR Register configuration information for the TIM peripheral. + * @retval None + */ +void TIM_BDTRConfig(TIM_TypeDef* TIMx, TIM_BDTRInitTypeDef *TIM_BDTRInitStruct) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + assert_param(IS_TIM_OSSR_STATE(TIM_BDTRInitStruct->TIM_OSSRState)); + assert_param(IS_TIM_OSSI_STATE(TIM_BDTRInitStruct->TIM_OSSIState)); + assert_param(IS_TIM_LOCK_LEVEL(TIM_BDTRInitStruct->TIM_LOCKLevel)); + assert_param(IS_TIM_BREAK_STATE(TIM_BDTRInitStruct->TIM_Break)); + assert_param(IS_TIM_BREAK_POLARITY(TIM_BDTRInitStruct->TIM_BreakPolarity)); + assert_param(IS_TIM_AUTOMATIC_OUTPUT_STATE(TIM_BDTRInitStruct->TIM_AutomaticOutput)); + /* Set the Lock level, the Break enable Bit and the Ploarity, the OSSR State, + the OSSI State, the dead time value and the Automatic Output Enable Bit */ + TIMx->BDTR = (uint32_t)TIM_BDTRInitStruct->TIM_OSSRState | TIM_BDTRInitStruct->TIM_OSSIState | + TIM_BDTRInitStruct->TIM_LOCKLevel | TIM_BDTRInitStruct->TIM_DeadTime | + TIM_BDTRInitStruct->TIM_Break | TIM_BDTRInitStruct->TIM_BreakPolarity | + TIM_BDTRInitStruct->TIM_AutomaticOutput; +} + +/** + * @brief Fills each TIM_TimeBaseInitStruct member with its default value. + * @param TIM_TimeBaseInitStruct : pointer to a TIM_TimeBaseInitTypeDef + * structure which will be initialized. + * @retval None + */ +void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct) +{ + /* Set the default configuration */ + TIM_TimeBaseInitStruct->TIM_Period = 0xFFFF; + TIM_TimeBaseInitStruct->TIM_Prescaler = 0x0000; + TIM_TimeBaseInitStruct->TIM_ClockDivision = TIM_CKD_DIV1; + TIM_TimeBaseInitStruct->TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseInitStruct->TIM_RepetitionCounter = 0x0000; +} + +/** + * @brief Fills each TIM_OCInitStruct member with its default value. + * @param TIM_OCInitStruct : pointer to a TIM_OCInitTypeDef structure which will + * be initialized. + * @retval None + */ +void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct) +{ + /* Set the default configuration */ + TIM_OCInitStruct->TIM_OCMode = TIM_OCMode_Timing; + TIM_OCInitStruct->TIM_OutputState = TIM_OutputState_Disable; + TIM_OCInitStruct->TIM_OutputNState = TIM_OutputNState_Disable; + TIM_OCInitStruct->TIM_Pulse = 0x0000; + TIM_OCInitStruct->TIM_OCPolarity = TIM_OCPolarity_High; + TIM_OCInitStruct->TIM_OCNPolarity = TIM_OCPolarity_High; + TIM_OCInitStruct->TIM_OCIdleState = TIM_OCIdleState_Reset; + TIM_OCInitStruct->TIM_OCNIdleState = TIM_OCNIdleState_Reset; +} + +/** + * @brief Fills each TIM_ICInitStruct member with its default value. + * @param TIM_ICInitStruct: pointer to a TIM_ICInitTypeDef structure which will + * be initialized. + * @retval None + */ +void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct) +{ + /* Set the default configuration */ + TIM_ICInitStruct->TIM_Channel = TIM_Channel_1; + TIM_ICInitStruct->TIM_ICPolarity = TIM_ICPolarity_Rising; + TIM_ICInitStruct->TIM_ICSelection = TIM_ICSelection_DirectTI; + TIM_ICInitStruct->TIM_ICPrescaler = TIM_ICPSC_DIV1; + TIM_ICInitStruct->TIM_ICFilter = 0x00; +} + +/** + * @brief Fills each TIM_BDTRInitStruct member with its default value. + * @param TIM_BDTRInitStruct: pointer to a TIM_BDTRInitTypeDef structure which + * will be initialized. + * @retval None + */ +void TIM_BDTRStructInit(TIM_BDTRInitTypeDef* TIM_BDTRInitStruct) +{ + /* Set the default configuration */ + TIM_BDTRInitStruct->TIM_OSSRState = TIM_OSSRState_Disable; + TIM_BDTRInitStruct->TIM_OSSIState = TIM_OSSIState_Disable; + TIM_BDTRInitStruct->TIM_LOCKLevel = TIM_LOCKLevel_OFF; + TIM_BDTRInitStruct->TIM_DeadTime = 0x00; + TIM_BDTRInitStruct->TIM_Break = TIM_Break_Disable; + TIM_BDTRInitStruct->TIM_BreakPolarity = TIM_BreakPolarity_Low; + TIM_BDTRInitStruct->TIM_AutomaticOutput = TIM_AutomaticOutput_Disable; +} + +/** + * @brief Enables or disables the specified TIM peripheral. + * @param TIMx: where x can be 1 to 17 to select the TIMx peripheral. + * @param NewState: new state of the TIMx peripheral. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the TIM Counter */ + TIMx->CR1 |= TIM_CR1_CEN; + } + else + { + /* Disable the TIM Counter */ + TIMx->CR1 &= (uint16_t)(~((uint16_t)TIM_CR1_CEN)); + } +} + +/** + * @brief Enables or disables the TIM peripheral Main Outputs. + * @param TIMx: where x can be 1, 8, 15, 16 or 17 to select the TIMx peripheral. + * @param NewState: new state of the TIM peripheral Main Outputs. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the TIM Main Output */ + TIMx->BDTR |= TIM_BDTR_MOE; + } + else + { + /* Disable the TIM Main Output */ + TIMx->BDTR &= (uint16_t)(~((uint16_t)TIM_BDTR_MOE)); + } +} + +/** + * @brief Enables or disables the specified TIM interrupts. + * @param TIMx: where x can be 1 to 17 to select the TIMx peripheral. + * @param TIM_IT: specifies the TIM interrupts sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg TIM_IT_Update: TIM update Interrupt source + * @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source + * @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source + * @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source + * @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source + * @arg TIM_IT_COM: TIM Commutation Interrupt source + * @arg TIM_IT_Trigger: TIM Trigger Interrupt source + * @arg TIM_IT_Break: TIM Break Interrupt source + * @note + * - TIM6 and TIM7 can only generate an update interrupt. + * - TIM9, TIM12 and TIM15 can have only TIM_IT_Update, TIM_IT_CC1, + * TIM_IT_CC2 or TIM_IT_Trigger. + * - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_IT_Update or TIM_IT_CC1. + * - TIM_IT_Break is used only with TIM1, TIM8 and TIM15. + * - TIM_IT_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17. + * @param NewState: new state of the TIM interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_IT(TIM_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the Interrupt sources */ + TIMx->DIER |= TIM_IT; + } + else + { + /* Disable the Interrupt sources */ + TIMx->DIER &= (uint16_t)~TIM_IT; + } +} + +/** + * @brief Configures the TIMx event to be generate by software. + * @param TIMx: where x can be 1 to 17 to select the TIM peripheral. + * @param TIM_EventSource: specifies the event source. + * This parameter can be one or more of the following values: + * @arg TIM_EventSource_Update: Timer update Event source + * @arg TIM_EventSource_CC1: Timer Capture Compare 1 Event source + * @arg TIM_EventSource_CC2: Timer Capture Compare 2 Event source + * @arg TIM_EventSource_CC3: Timer Capture Compare 3 Event source + * @arg TIM_EventSource_CC4: Timer Capture Compare 4 Event source + * @arg TIM_EventSource_COM: Timer COM event source + * @arg TIM_EventSource_Trigger: Timer Trigger Event source + * @arg TIM_EventSource_Break: Timer Break event source + * @note + * - TIM6 and TIM7 can only generate an update event. + * - TIM_EventSource_COM and TIM_EventSource_Break are used only with TIM1 and TIM8. + * @retval None + */ +void TIM_GenerateEvent(TIM_TypeDef* TIMx, uint16_t TIM_EventSource) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_EVENT_SOURCE(TIM_EventSource)); + + /* Set the event sources */ + TIMx->EGR = TIM_EventSource; +} + +/** + * @brief Configures the TIMx's DMA interface. + * @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 15, 16 or 17 to select + * the TIM peripheral. + * @param TIM_DMABase: DMA Base address. + * This parameter can be one of the following values: + * @arg TIM_DMABase_CR, TIM_DMABase_CR2, TIM_DMABase_SMCR, + * TIM_DMABase_DIER, TIM1_DMABase_SR, TIM_DMABase_EGR, + * TIM_DMABase_CCMR1, TIM_DMABase_CCMR2, TIM_DMABase_CCER, + * TIM_DMABase_CNT, TIM_DMABase_PSC, TIM_DMABase_ARR, + * TIM_DMABase_RCR, TIM_DMABase_CCR1, TIM_DMABase_CCR2, + * TIM_DMABase_CCR3, TIM_DMABase_CCR4, TIM_DMABase_BDTR, + * TIM_DMABase_DCR. + * @param TIM_DMABurstLength: DMA Burst length. + * This parameter can be one value between: + * TIM_DMABurstLength_1Transfer and TIM_DMABurstLength_18Transfers. + * @retval None + */ +void TIM_DMAConfig(TIM_TypeDef* TIMx, uint16_t TIM_DMABase, uint16_t TIM_DMABurstLength) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST4_PERIPH(TIMx)); + assert_param(IS_TIM_DMA_BASE(TIM_DMABase)); + assert_param(IS_TIM_DMA_LENGTH(TIM_DMABurstLength)); + /* Set the DMA Base and the DMA Burst Length */ + TIMx->DCR = TIM_DMABase | TIM_DMABurstLength; +} + +/** + * @brief Enables or disables the TIMx's DMA Requests. + * @param TIMx: where x can be 1, 2, 3, 4, 5, 6, 7, 8, 15, 16 or 17 + * to select the TIM peripheral. + * @param TIM_DMASource: specifies the DMA Request sources. + * This parameter can be any combination of the following values: + * @arg TIM_DMA_Update: TIM update Interrupt source + * @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source + * @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source + * @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source + * @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source + * @arg TIM_DMA_COM: TIM Commutation DMA source + * @arg TIM_DMA_Trigger: TIM Trigger DMA source + * @param NewState: new state of the DMA Request sources. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void TIM_DMACmd(TIM_TypeDef* TIMx, uint16_t TIM_DMASource, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST9_PERIPH(TIMx)); + assert_param(IS_TIM_DMA_SOURCE(TIM_DMASource)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the DMA sources */ + TIMx->DIER |= TIM_DMASource; + } + else + { + /* Disable the DMA sources */ + TIMx->DIER &= (uint16_t)~TIM_DMASource; + } +} + +/** + * @brief Configures the TIMx internal Clock + * @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 + * to select the TIM peripheral. + * @retval None + */ +void TIM_InternalClockConfig(TIM_TypeDef* TIMx) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + /* Disable slave mode to clock the prescaler directly with the internal clock */ + TIMx->SMCR &= (uint16_t)(~((uint16_t)TIM_SMCR_SMS)); +} + +/** + * @brief Configures the TIMx Internal Trigger as External Clock + * @param TIMx: where x can be 1, 2, 3, 4, 5, 9, 12 or 15 to select the TIM peripheral. + * @param TIM_ITRSource: Trigger source. + * This parameter can be one of the following values: + * @param TIM_TS_ITR0: Internal Trigger 0 + * @param TIM_TS_ITR1: Internal Trigger 1 + * @param TIM_TS_ITR2: Internal Trigger 2 + * @param TIM_TS_ITR3: Internal Trigger 3 + * @retval None + */ +void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + assert_param(IS_TIM_INTERNAL_TRIGGER_SELECTION(TIM_InputTriggerSource)); + /* Select the Internal Trigger */ + TIM_SelectInputTrigger(TIMx, TIM_InputTriggerSource); + /* Select the External clock mode1 */ + TIMx->SMCR |= TIM_SlaveMode_External1; +} + +/** + * @brief Configures the TIMx Trigger as External Clock + * @param TIMx: where x can be 1, 2, 3, 4, 5, 9, 12 or 15 to select the TIM peripheral. + * @param TIM_TIxExternalCLKSource: Trigger source. + * This parameter can be one of the following values: + * @arg TIM_TIxExternalCLK1Source_TI1ED: TI1 Edge Detector + * @arg TIM_TIxExternalCLK1Source_TI1: Filtered Timer Input 1 + * @arg TIM_TIxExternalCLK1Source_TI2: Filtered Timer Input 2 + * @param TIM_ICPolarity: specifies the TIx Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising + * @arg TIM_ICPolarity_Falling + * @param ICFilter : specifies the filter value. + * This parameter must be a value between 0x0 and 0xF. + * @retval None + */ +void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource, + uint16_t TIM_ICPolarity, uint16_t ICFilter) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + assert_param(IS_TIM_TIXCLK_SOURCE(TIM_TIxExternalCLKSource)); + assert_param(IS_TIM_IC_POLARITY(TIM_ICPolarity)); + assert_param(IS_TIM_IC_FILTER(ICFilter)); + /* Configure the Timer Input Clock Source */ + if (TIM_TIxExternalCLKSource == TIM_TIxExternalCLK1Source_TI2) + { + TI2_Config(TIMx, TIM_ICPolarity, TIM_ICSelection_DirectTI, ICFilter); + } + else + { + TI1_Config(TIMx, TIM_ICPolarity, TIM_ICSelection_DirectTI, ICFilter); + } + /* Select the Trigger source */ + TIM_SelectInputTrigger(TIMx, TIM_TIxExternalCLKSource); + /* Select the External clock mode1 */ + TIMx->SMCR |= TIM_SlaveMode_External1; +} + +/** + * @brief Configures the External clock Mode1 + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ExtTRGPrescaler: The external Trigger Prescaler. + * This parameter can be one of the following values: + * @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF. + * @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2. + * @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4. + * @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8. + * @param TIM_ExtTRGPolarity: The external Trigger Polarity. + * This parameter can be one of the following values: + * @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active. + * @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active. + * @param ExtTRGFilter: External Trigger Filter. + * This parameter must be a value between 0x00 and 0x0F + * @retval None + */ +void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter) +{ + uint16_t tmpsmcr = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_EXT_PRESCALER(TIM_ExtTRGPrescaler)); + assert_param(IS_TIM_EXT_POLARITY(TIM_ExtTRGPolarity)); + assert_param(IS_TIM_EXT_FILTER(ExtTRGFilter)); + /* Configure the ETR Clock source */ + TIM_ETRConfig(TIMx, TIM_ExtTRGPrescaler, TIM_ExtTRGPolarity, ExtTRGFilter); + + /* Get the TIMx SMCR register value */ + tmpsmcr = TIMx->SMCR; + /* Reset the SMS Bits */ + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_SMS)); + /* Select the External clock mode1 */ + tmpsmcr |= TIM_SlaveMode_External1; + /* Select the Trigger selection : ETRF */ + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_TS)); + tmpsmcr |= TIM_TS_ETRF; + /* Write to TIMx SMCR */ + TIMx->SMCR = tmpsmcr; +} + +/** + * @brief Configures the External clock Mode2 + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ExtTRGPrescaler: The external Trigger Prescaler. + * This parameter can be one of the following values: + * @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF. + * @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2. + * @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4. + * @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8. + * @param TIM_ExtTRGPolarity: The external Trigger Polarity. + * This parameter can be one of the following values: + * @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active. + * @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active. + * @param ExtTRGFilter: External Trigger Filter. + * This parameter must be a value between 0x00 and 0x0F + * @retval None + */ +void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_EXT_PRESCALER(TIM_ExtTRGPrescaler)); + assert_param(IS_TIM_EXT_POLARITY(TIM_ExtTRGPolarity)); + assert_param(IS_TIM_EXT_FILTER(ExtTRGFilter)); + /* Configure the ETR Clock source */ + TIM_ETRConfig(TIMx, TIM_ExtTRGPrescaler, TIM_ExtTRGPolarity, ExtTRGFilter); + /* Enable the External clock mode2 */ + TIMx->SMCR |= TIM_SMCR_ECE; +} + +/** + * @brief Configures the TIMx External Trigger (ETR). + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ExtTRGPrescaler: The external Trigger Prescaler. + * This parameter can be one of the following values: + * @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF. + * @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2. + * @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4. + * @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8. + * @param TIM_ExtTRGPolarity: The external Trigger Polarity. + * This parameter can be one of the following values: + * @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active. + * @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active. + * @param ExtTRGFilter: External Trigger Filter. + * This parameter must be a value between 0x00 and 0x0F + * @retval None + */ +void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter) +{ + uint16_t tmpsmcr = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_EXT_PRESCALER(TIM_ExtTRGPrescaler)); + assert_param(IS_TIM_EXT_POLARITY(TIM_ExtTRGPolarity)); + assert_param(IS_TIM_EXT_FILTER(ExtTRGFilter)); + tmpsmcr = TIMx->SMCR; + /* Reset the ETR Bits */ + tmpsmcr &= SMCR_ETR_Mask; + /* Set the Prescaler, the Filter value and the Polarity */ + tmpsmcr |= (uint16_t)(TIM_ExtTRGPrescaler | (uint16_t)(TIM_ExtTRGPolarity | (uint16_t)(ExtTRGFilter << (uint16_t)8))); + /* Write to TIMx SMCR */ + TIMx->SMCR = tmpsmcr; +} + +/** + * @brief Configures the TIMx Prescaler. + * @param TIMx: where x can be 1 to 17 to select the TIM peripheral. + * @param Prescaler: specifies the Prescaler Register value + * @param TIM_PSCReloadMode: specifies the TIM Prescaler Reload mode + * This parameter can be one of the following values: + * @arg TIM_PSCReloadMode_Update: The Prescaler is loaded at the update event. + * @arg TIM_PSCReloadMode_Immediate: The Prescaler is loaded immediately. + * @retval None + */ +void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_PRESCALER_RELOAD(TIM_PSCReloadMode)); + /* Set the Prescaler value */ + TIMx->PSC = Prescaler; + /* Set or reset the UG Bit */ + TIMx->EGR = TIM_PSCReloadMode; +} + +/** + * @brief Specifies the TIMx Counter Mode to be used. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_CounterMode: specifies the Counter Mode to be used + * This parameter can be one of the following values: + * @arg TIM_CounterMode_Up: TIM Up Counting Mode + * @arg TIM_CounterMode_Down: TIM Down Counting Mode + * @arg TIM_CounterMode_CenterAligned1: TIM Center Aligned Mode1 + * @arg TIM_CounterMode_CenterAligned2: TIM Center Aligned Mode2 + * @arg TIM_CounterMode_CenterAligned3: TIM Center Aligned Mode3 + * @retval None + */ +void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode) +{ + uint16_t tmpcr1 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_COUNTER_MODE(TIM_CounterMode)); + tmpcr1 = TIMx->CR1; + /* Reset the CMS and DIR Bits */ + tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS))); + /* Set the Counter Mode */ + tmpcr1 |= TIM_CounterMode; + /* Write to TIMx CR1 register */ + TIMx->CR1 = tmpcr1; +} + +/** + * @brief Selects the Input Trigger source + * @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral. + * @param TIM_InputTriggerSource: The Input Trigger source. + * This parameter can be one of the following values: + * @arg TIM_TS_ITR0: Internal Trigger 0 + * @arg TIM_TS_ITR1: Internal Trigger 1 + * @arg TIM_TS_ITR2: Internal Trigger 2 + * @arg TIM_TS_ITR3: Internal Trigger 3 + * @arg TIM_TS_TI1F_ED: TI1 Edge Detector + * @arg TIM_TS_TI1FP1: Filtered Timer Input 1 + * @arg TIM_TS_TI2FP2: Filtered Timer Input 2 + * @arg TIM_TS_ETRF: External Trigger input + * @retval None + */ +void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource) +{ + uint16_t tmpsmcr = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + assert_param(IS_TIM_TRIGGER_SELECTION(TIM_InputTriggerSource)); + /* Get the TIMx SMCR register value */ + tmpsmcr = TIMx->SMCR; + /* Reset the TS Bits */ + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_TS)); + /* Set the Input Trigger source */ + tmpsmcr |= TIM_InputTriggerSource; + /* Write to TIMx SMCR */ + TIMx->SMCR = tmpsmcr; +} + +/** + * @brief Configures the TIMx Encoder Interface. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_EncoderMode: specifies the TIMx Encoder Mode. + * This parameter can be one of the following values: + * @arg TIM_EncoderMode_TI1: Counter counts on TI1FP1 edge depending on TI2FP2 level. + * @arg TIM_EncoderMode_TI2: Counter counts on TI2FP2 edge depending on TI1FP1 level. + * @arg TIM_EncoderMode_TI12: Counter counts on both TI1FP1 and TI2FP2 edges depending + * on the level of the other input. + * @param TIM_IC1Polarity: specifies the IC1 Polarity + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Falling: IC Falling edge. + * @arg TIM_ICPolarity_Rising: IC Rising edge. + * @param TIM_IC2Polarity: specifies the IC2 Polarity + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Falling: IC Falling edge. + * @arg TIM_ICPolarity_Rising: IC Rising edge. + * @retval None + */ +void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode, + uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity) +{ + uint16_t tmpsmcr = 0; + uint16_t tmpccmr1 = 0; + uint16_t tmpccer = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST5_PERIPH(TIMx)); + assert_param(IS_TIM_ENCODER_MODE(TIM_EncoderMode)); + assert_param(IS_TIM_IC_POLARITY(TIM_IC1Polarity)); + assert_param(IS_TIM_IC_POLARITY(TIM_IC2Polarity)); + + /* Get the TIMx SMCR register value */ + tmpsmcr = TIMx->SMCR; + + /* Get the TIMx CCMR1 register value */ + tmpccmr1 = TIMx->CCMR1; + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + + /* Set the encoder Mode */ + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_SMS)); + tmpsmcr |= TIM_EncoderMode; + + /* Select the Capture Compare 1 and the Capture Compare 2 as input */ + tmpccmr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR1_CC1S)) & (uint16_t)(~((uint16_t)TIM_CCMR1_CC2S))); + tmpccmr1 |= TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0; + + /* Set the TI1 and the TI2 Polarities */ + tmpccer &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCER_CC1P)) & ((uint16_t)~((uint16_t)TIM_CCER_CC2P))); + tmpccer |= (uint16_t)(TIM_IC1Polarity | (uint16_t)(TIM_IC2Polarity << (uint16_t)4)); + + /* Write to TIMx SMCR */ + TIMx->SMCR = tmpsmcr; + /* Write to TIMx CCMR1 */ + TIMx->CCMR1 = tmpccmr1; + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Forces the TIMx output 1 waveform to active or inactive level. + * @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral. + * @param TIM_ForcedAction: specifies the forced Action to be set to the output waveform. + * This parameter can be one of the following values: + * @arg TIM_ForcedAction_Active: Force active level on OC1REF + * @arg TIM_ForcedAction_InActive: Force inactive level on OC1REF. + * @retval None + */ +void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST8_PERIPH(TIMx)); + assert_param(IS_TIM_FORCED_ACTION(TIM_ForcedAction)); + tmpccmr1 = TIMx->CCMR1; + /* Reset the OC1M Bits */ + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1M); + /* Configure The Forced output Mode */ + tmpccmr1 |= TIM_ForcedAction; + /* Write to TIMx CCMR1 register */ + TIMx->CCMR1 = tmpccmr1; +} + +/** + * @brief Forces the TIMx output 2 waveform to active or inactive level. + * @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral. + * @param TIM_ForcedAction: specifies the forced Action to be set to the output waveform. + * This parameter can be one of the following values: + * @arg TIM_ForcedAction_Active: Force active level on OC2REF + * @arg TIM_ForcedAction_InActive: Force inactive level on OC2REF. + * @retval None + */ +void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + assert_param(IS_TIM_FORCED_ACTION(TIM_ForcedAction)); + tmpccmr1 = TIMx->CCMR1; + /* Reset the OC2M Bits */ + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2M); + /* Configure The Forced output Mode */ + tmpccmr1 |= (uint16_t)(TIM_ForcedAction << 8); + /* Write to TIMx CCMR1 register */ + TIMx->CCMR1 = tmpccmr1; +} + +/** + * @brief Forces the TIMx output 3 waveform to active or inactive level. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ForcedAction: specifies the forced Action to be set to the output waveform. + * This parameter can be one of the following values: + * @arg TIM_ForcedAction_Active: Force active level on OC3REF + * @arg TIM_ForcedAction_InActive: Force inactive level on OC3REF. + * @retval None + */ +void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_FORCED_ACTION(TIM_ForcedAction)); + tmpccmr2 = TIMx->CCMR2; + /* Reset the OC1M Bits */ + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3M); + /* Configure The Forced output Mode */ + tmpccmr2 |= TIM_ForcedAction; + /* Write to TIMx CCMR2 register */ + TIMx->CCMR2 = tmpccmr2; +} + +/** + * @brief Forces the TIMx output 4 waveform to active or inactive level. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ForcedAction: specifies the forced Action to be set to the output waveform. + * This parameter can be one of the following values: + * @arg TIM_ForcedAction_Active: Force active level on OC4REF + * @arg TIM_ForcedAction_InActive: Force inactive level on OC4REF. + * @retval None + */ +void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_FORCED_ACTION(TIM_ForcedAction)); + tmpccmr2 = TIMx->CCMR2; + /* Reset the OC2M Bits */ + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4M); + /* Configure The Forced output Mode */ + tmpccmr2 |= (uint16_t)(TIM_ForcedAction << 8); + /* Write to TIMx CCMR2 register */ + TIMx->CCMR2 = tmpccmr2; +} + +/** + * @brief Enables or disables TIMx peripheral Preload register on ARR. + * @param TIMx: where x can be 1 to 17 to select the TIM peripheral. + * @param NewState: new state of the TIMx peripheral Preload register + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Set the ARR Preload Bit */ + TIMx->CR1 |= TIM_CR1_ARPE; + } + else + { + /* Reset the ARR Preload Bit */ + TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_ARPE); + } +} + +/** + * @brief Selects the TIM peripheral Commutation event. + * @param TIMx: where x can be 1, 8, 15, 16 or 17 to select the TIMx peripheral + * @param NewState: new state of the Commutation event. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void TIM_SelectCOM(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Set the COM Bit */ + TIMx->CR2 |= TIM_CR2_CCUS; + } + else + { + /* Reset the COM Bit */ + TIMx->CR2 &= (uint16_t)~((uint16_t)TIM_CR2_CCUS); + } +} + +/** + * @brief Selects the TIMx peripheral Capture Compare DMA source. + * @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 15, 16 or 17 to select + * the TIM peripheral. + * @param NewState: new state of the Capture Compare DMA source + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void TIM_SelectCCDMA(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST4_PERIPH(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Set the CCDS Bit */ + TIMx->CR2 |= TIM_CR2_CCDS; + } + else + { + /* Reset the CCDS Bit */ + TIMx->CR2 &= (uint16_t)~((uint16_t)TIM_CR2_CCDS); + } +} + +/** + * @brief Sets or Resets the TIM peripheral Capture Compare Preload Control bit. + * @param TIMx: where x can be 1, 2, 3, 4, 5, 8 or 15 + * to select the TIMx peripheral + * @param NewState: new state of the Capture Compare Preload Control bit + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void TIM_CCPreloadControl(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST5_PERIPH(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Set the CCPC Bit */ + TIMx->CR2 |= TIM_CR2_CCPC; + } + else + { + /* Reset the CCPC Bit */ + TIMx->CR2 &= (uint16_t)~((uint16_t)TIM_CR2_CCPC); + } +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCR1. + * @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral. + * @param TIM_OCPreload: new state of the TIMx peripheral Preload register + * This parameter can be one of the following values: + * @arg TIM_OCPreload_Enable + * @arg TIM_OCPreload_Disable + * @retval None + */ +void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST8_PERIPH(TIMx)); + assert_param(IS_TIM_OCPRELOAD_STATE(TIM_OCPreload)); + tmpccmr1 = TIMx->CCMR1; + /* Reset the OC1PE Bit */ + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1PE); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr1 |= TIM_OCPreload; + /* Write to TIMx CCMR1 register */ + TIMx->CCMR1 = tmpccmr1; +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCR2. + * @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select + * the TIM peripheral. + * @param TIM_OCPreload: new state of the TIMx peripheral Preload register + * This parameter can be one of the following values: + * @arg TIM_OCPreload_Enable + * @arg TIM_OCPreload_Disable + * @retval None + */ +void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + assert_param(IS_TIM_OCPRELOAD_STATE(TIM_OCPreload)); + tmpccmr1 = TIMx->CCMR1; + /* Reset the OC2PE Bit */ + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2PE); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr1 |= (uint16_t)(TIM_OCPreload << 8); + /* Write to TIMx CCMR1 register */ + TIMx->CCMR1 = tmpccmr1; +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCR3. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCPreload: new state of the TIMx peripheral Preload register + * This parameter can be one of the following values: + * @arg TIM_OCPreload_Enable + * @arg TIM_OCPreload_Disable + * @retval None + */ +void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OCPRELOAD_STATE(TIM_OCPreload)); + tmpccmr2 = TIMx->CCMR2; + /* Reset the OC3PE Bit */ + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3PE); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr2 |= TIM_OCPreload; + /* Write to TIMx CCMR2 register */ + TIMx->CCMR2 = tmpccmr2; +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCR4. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCPreload: new state of the TIMx peripheral Preload register + * This parameter can be one of the following values: + * @arg TIM_OCPreload_Enable + * @arg TIM_OCPreload_Disable + * @retval None + */ +void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OCPRELOAD_STATE(TIM_OCPreload)); + tmpccmr2 = TIMx->CCMR2; + /* Reset the OC4PE Bit */ + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4PE); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr2 |= (uint16_t)(TIM_OCPreload << 8); + /* Write to TIMx CCMR2 register */ + TIMx->CCMR2 = tmpccmr2; +} + +/** + * @brief Configures the TIMx Output Compare 1 Fast feature. + * @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral. + * @param TIM_OCFast: new state of the Output Compare Fast Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OCFast_Enable: TIM output compare fast enable + * @arg TIM_OCFast_Disable: TIM output compare fast disable + * @retval None + */ +void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST8_PERIPH(TIMx)); + assert_param(IS_TIM_OCFAST_STATE(TIM_OCFast)); + /* Get the TIMx CCMR1 register value */ + tmpccmr1 = TIMx->CCMR1; + /* Reset the OC1FE Bit */ + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1FE); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr1 |= TIM_OCFast; + /* Write to TIMx CCMR1 */ + TIMx->CCMR1 = tmpccmr1; +} + +/** + * @brief Configures the TIMx Output Compare 2 Fast feature. + * @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select + * the TIM peripheral. + * @param TIM_OCFast: new state of the Output Compare Fast Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OCFast_Enable: TIM output compare fast enable + * @arg TIM_OCFast_Disable: TIM output compare fast disable + * @retval None + */ +void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + assert_param(IS_TIM_OCFAST_STATE(TIM_OCFast)); + /* Get the TIMx CCMR1 register value */ + tmpccmr1 = TIMx->CCMR1; + /* Reset the OC2FE Bit */ + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2FE); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr1 |= (uint16_t)(TIM_OCFast << 8); + /* Write to TIMx CCMR1 */ + TIMx->CCMR1 = tmpccmr1; +} + +/** + * @brief Configures the TIMx Output Compare 3 Fast feature. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCFast: new state of the Output Compare Fast Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OCFast_Enable: TIM output compare fast enable + * @arg TIM_OCFast_Disable: TIM output compare fast disable + * @retval None + */ +void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OCFAST_STATE(TIM_OCFast)); + /* Get the TIMx CCMR2 register value */ + tmpccmr2 = TIMx->CCMR2; + /* Reset the OC3FE Bit */ + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3FE); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr2 |= TIM_OCFast; + /* Write to TIMx CCMR2 */ + TIMx->CCMR2 = tmpccmr2; +} + +/** + * @brief Configures the TIMx Output Compare 4 Fast feature. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCFast: new state of the Output Compare Fast Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OCFast_Enable: TIM output compare fast enable + * @arg TIM_OCFast_Disable: TIM output compare fast disable + * @retval None + */ +void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OCFAST_STATE(TIM_OCFast)); + /* Get the TIMx CCMR2 register value */ + tmpccmr2 = TIMx->CCMR2; + /* Reset the OC4FE Bit */ + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4FE); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr2 |= (uint16_t)(TIM_OCFast << 8); + /* Write to TIMx CCMR2 */ + TIMx->CCMR2 = tmpccmr2; +} + +/** + * @brief Clears or safeguards the OCREF1 signal on an external event + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCClear: new state of the Output Compare Clear Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OCClear_Enable: TIM Output clear enable + * @arg TIM_OCClear_Disable: TIM Output clear disable + * @retval None + */ +void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OCCLEAR_STATE(TIM_OCClear)); + + tmpccmr1 = TIMx->CCMR1; + + /* Reset the OC1CE Bit */ + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1CE); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr1 |= TIM_OCClear; + /* Write to TIMx CCMR1 register */ + TIMx->CCMR1 = tmpccmr1; +} + +/** + * @brief Clears or safeguards the OCREF2 signal on an external event + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCClear: new state of the Output Compare Clear Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OCClear_Enable: TIM Output clear enable + * @arg TIM_OCClear_Disable: TIM Output clear disable + * @retval None + */ +void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OCCLEAR_STATE(TIM_OCClear)); + tmpccmr1 = TIMx->CCMR1; + /* Reset the OC2CE Bit */ + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2CE); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr1 |= (uint16_t)(TIM_OCClear << 8); + /* Write to TIMx CCMR1 register */ + TIMx->CCMR1 = tmpccmr1; +} + +/** + * @brief Clears or safeguards the OCREF3 signal on an external event + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCClear: new state of the Output Compare Clear Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OCClear_Enable: TIM Output clear enable + * @arg TIM_OCClear_Disable: TIM Output clear disable + * @retval None + */ +void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OCCLEAR_STATE(TIM_OCClear)); + tmpccmr2 = TIMx->CCMR2; + /* Reset the OC3CE Bit */ + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3CE); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr2 |= TIM_OCClear; + /* Write to TIMx CCMR2 register */ + TIMx->CCMR2 = tmpccmr2; +} + +/** + * @brief Clears or safeguards the OCREF4 signal on an external event + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCClear: new state of the Output Compare Clear Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OCClear_Enable: TIM Output clear enable + * @arg TIM_OCClear_Disable: TIM Output clear disable + * @retval None + */ +void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OCCLEAR_STATE(TIM_OCClear)); + tmpccmr2 = TIMx->CCMR2; + /* Reset the OC4CE Bit */ + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4CE); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr2 |= (uint16_t)(TIM_OCClear << 8); + /* Write to TIMx CCMR2 register */ + TIMx->CCMR2 = tmpccmr2; +} + +/** + * @brief Configures the TIMx channel 1 polarity. + * @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral. + * @param TIM_OCPolarity: specifies the OC1 Polarity + * This parameter can be one of the following values: + * @arg TIM_OCPolarity_High: Output Compare active high + * @arg TIM_OCPolarity_Low: Output Compare active low + * @retval None + */ +void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity) +{ + uint16_t tmpccer = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST8_PERIPH(TIMx)); + assert_param(IS_TIM_OC_POLARITY(TIM_OCPolarity)); + tmpccer = TIMx->CCER; + /* Set or Reset the CC1P Bit */ + tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC1P); + tmpccer |= TIM_OCPolarity; + /* Write to TIMx CCER register */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Configures the TIMx Channel 1N polarity. + * @param TIMx: where x can be 1, 8, 15, 16 or 17 to select the TIM peripheral. + * @param TIM_OCNPolarity: specifies the OC1N Polarity + * This parameter can be one of the following values: + * @arg TIM_OCNPolarity_High: Output Compare active high + * @arg TIM_OCNPolarity_Low: Output Compare active low + * @retval None + */ +void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity) +{ + uint16_t tmpccer = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + assert_param(IS_TIM_OCN_POLARITY(TIM_OCNPolarity)); + + tmpccer = TIMx->CCER; + /* Set or Reset the CC1NP Bit */ + tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC1NP); + tmpccer |= TIM_OCNPolarity; + /* Write to TIMx CCER register */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Configures the TIMx channel 2 polarity. + * @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral. + * @param TIM_OCPolarity: specifies the OC2 Polarity + * This parameter can be one of the following values: + * @arg TIM_OCPolarity_High: Output Compare active high + * @arg TIM_OCPolarity_Low: Output Compare active low + * @retval None + */ +void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity) +{ + uint16_t tmpccer = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + assert_param(IS_TIM_OC_POLARITY(TIM_OCPolarity)); + tmpccer = TIMx->CCER; + /* Set or Reset the CC2P Bit */ + tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC2P); + tmpccer |= (uint16_t)(TIM_OCPolarity << 4); + /* Write to TIMx CCER register */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Configures the TIMx Channel 2N polarity. + * @param TIMx: where x can be 1 or 8 to select the TIM peripheral. + * @param TIM_OCNPolarity: specifies the OC2N Polarity + * This parameter can be one of the following values: + * @arg TIM_OCNPolarity_High: Output Compare active high + * @arg TIM_OCNPolarity_Low: Output Compare active low + * @retval None + */ +void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity) +{ + uint16_t tmpccer = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + assert_param(IS_TIM_OCN_POLARITY(TIM_OCNPolarity)); + + tmpccer = TIMx->CCER; + /* Set or Reset the CC2NP Bit */ + tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC2NP); + tmpccer |= (uint16_t)(TIM_OCNPolarity << 4); + /* Write to TIMx CCER register */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Configures the TIMx channel 3 polarity. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCPolarity: specifies the OC3 Polarity + * This parameter can be one of the following values: + * @arg TIM_OCPolarity_High: Output Compare active high + * @arg TIM_OCPolarity_Low: Output Compare active low + * @retval None + */ +void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity) +{ + uint16_t tmpccer = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OC_POLARITY(TIM_OCPolarity)); + tmpccer = TIMx->CCER; + /* Set or Reset the CC3P Bit */ + tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC3P); + tmpccer |= (uint16_t)(TIM_OCPolarity << 8); + /* Write to TIMx CCER register */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Configures the TIMx Channel 3N polarity. + * @param TIMx: where x can be 1 or 8 to select the TIM peripheral. + * @param TIM_OCNPolarity: specifies the OC3N Polarity + * This parameter can be one of the following values: + * @arg TIM_OCNPolarity_High: Output Compare active high + * @arg TIM_OCNPolarity_Low: Output Compare active low + * @retval None + */ +void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity) +{ + uint16_t tmpccer = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + assert_param(IS_TIM_OCN_POLARITY(TIM_OCNPolarity)); + + tmpccer = TIMx->CCER; + /* Set or Reset the CC3NP Bit */ + tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC3NP); + tmpccer |= (uint16_t)(TIM_OCNPolarity << 8); + /* Write to TIMx CCER register */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Configures the TIMx channel 4 polarity. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCPolarity: specifies the OC4 Polarity + * This parameter can be one of the following values: + * @arg TIM_OCPolarity_High: Output Compare active high + * @arg TIM_OCPolarity_Low: Output Compare active low + * @retval None + */ +void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity) +{ + uint16_t tmpccer = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OC_POLARITY(TIM_OCPolarity)); + tmpccer = TIMx->CCER; + /* Set or Reset the CC4P Bit */ + tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC4P); + tmpccer |= (uint16_t)(TIM_OCPolarity << 12); + /* Write to TIMx CCER register */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Enables or disables the TIM Capture Compare Channel x. + * @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral. + * @param TIM_Channel: specifies the TIM Channel + * This parameter can be one of the following values: + * @arg TIM_Channel_1: TIM Channel 1 + * @arg TIM_Channel_2: TIM Channel 2 + * @arg TIM_Channel_3: TIM Channel 3 + * @arg TIM_Channel_4: TIM Channel 4 + * @param TIM_CCx: specifies the TIM Channel CCxE bit new state. + * This parameter can be: TIM_CCx_Enable or TIM_CCx_Disable. + * @retval None + */ +void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx) +{ + uint16_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST8_PERIPH(TIMx)); + assert_param(IS_TIM_CHANNEL(TIM_Channel)); + assert_param(IS_TIM_CCX(TIM_CCx)); + + tmp = CCER_CCE_Set << TIM_Channel; + + /* Reset the CCxE Bit */ + TIMx->CCER &= (uint16_t)~ tmp; + + /* Set or reset the CCxE Bit */ + TIMx->CCER |= (uint16_t)(TIM_CCx << TIM_Channel); +} + +/** + * @brief Enables or disables the TIM Capture Compare Channel xN. + * @param TIMx: where x can be 1, 8, 15, 16 or 17 to select the TIM peripheral. + * @param TIM_Channel: specifies the TIM Channel + * This parameter can be one of the following values: + * @arg TIM_Channel_1: TIM Channel 1 + * @arg TIM_Channel_2: TIM Channel 2 + * @arg TIM_Channel_3: TIM Channel 3 + * @param TIM_CCxN: specifies the TIM Channel CCxNE bit new state. + * This parameter can be: TIM_CCxN_Enable or TIM_CCxN_Disable. + * @retval None + */ +void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN) +{ + uint16_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + assert_param(IS_TIM_COMPLEMENTARY_CHANNEL(TIM_Channel)); + assert_param(IS_TIM_CCXN(TIM_CCxN)); + + tmp = CCER_CCNE_Set << TIM_Channel; + + /* Reset the CCxNE Bit */ + TIMx->CCER &= (uint16_t) ~tmp; + + /* Set or reset the CCxNE Bit */ + TIMx->CCER |= (uint16_t)(TIM_CCxN << TIM_Channel); +} + +/** + * @brief Selects the TIM Output Compare Mode. + * @note This function disables the selected channel before changing the Output + * Compare Mode. + * User has to enable this channel using TIM_CCxCmd and TIM_CCxNCmd functions. + * @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral. + * @param TIM_Channel: specifies the TIM Channel + * This parameter can be one of the following values: + * @arg TIM_Channel_1: TIM Channel 1 + * @arg TIM_Channel_2: TIM Channel 2 + * @arg TIM_Channel_3: TIM Channel 3 + * @arg TIM_Channel_4: TIM Channel 4 + * @param TIM_OCMode: specifies the TIM Output Compare Mode. + * This parameter can be one of the following values: + * @arg TIM_OCMode_Timing + * @arg TIM_OCMode_Active + * @arg TIM_OCMode_Toggle + * @arg TIM_OCMode_PWM1 + * @arg TIM_OCMode_PWM2 + * @arg TIM_ForcedAction_Active + * @arg TIM_ForcedAction_InActive + * @retval None + */ +void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode) +{ + uint32_t tmp = 0; + uint16_t tmp1 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST8_PERIPH(TIMx)); + assert_param(IS_TIM_CHANNEL(TIM_Channel)); + assert_param(IS_TIM_OCM(TIM_OCMode)); + + tmp = (uint32_t) TIMx; + tmp += CCMR_Offset; + + tmp1 = CCER_CCE_Set << (uint16_t)TIM_Channel; + + /* Disable the Channel: Reset the CCxE Bit */ + TIMx->CCER &= (uint16_t) ~tmp1; + + if((TIM_Channel == TIM_Channel_1) ||(TIM_Channel == TIM_Channel_3)) + { + tmp += (TIM_Channel>>1); + + /* Reset the OCxM bits in the CCMRx register */ + *(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIM_CCMR1_OC1M); + + /* Configure the OCxM bits in the CCMRx register */ + *(__IO uint32_t *) tmp |= TIM_OCMode; + } + else + { + tmp += (uint16_t)(TIM_Channel - (uint16_t)4)>> (uint16_t)1; + + /* Reset the OCxM bits in the CCMRx register */ + *(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIM_CCMR1_OC2M); + + /* Configure the OCxM bits in the CCMRx register */ + *(__IO uint32_t *) tmp |= (uint16_t)(TIM_OCMode << 8); + } +} + +/** + * @brief Enables or Disables the TIMx Update event. + * @param TIMx: where x can be 1 to 17 to select the TIM peripheral. + * @param NewState: new state of the TIMx UDIS bit + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void TIM_UpdateDisableConfig(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Set the Update Disable Bit */ + TIMx->CR1 |= TIM_CR1_UDIS; + } + else + { + /* Reset the Update Disable Bit */ + TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_UDIS); + } +} + +/** + * @brief Configures the TIMx Update Request Interrupt source. + * @param TIMx: where x can be 1 to 17 to select the TIM peripheral. + * @param TIM_UpdateSource: specifies the Update source. + * This parameter can be one of the following values: + * @arg TIM_UpdateSource_Regular: Source of update is the counter overflow/underflow + or the setting of UG bit, or an update generation + through the slave mode controller. + * @arg TIM_UpdateSource_Global: Source of update is counter overflow/underflow. + * @retval None + */ +void TIM_UpdateRequestConfig(TIM_TypeDef* TIMx, uint16_t TIM_UpdateSource) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_UPDATE_SOURCE(TIM_UpdateSource)); + if (TIM_UpdateSource != TIM_UpdateSource_Global) + { + /* Set the URS Bit */ + TIMx->CR1 |= TIM_CR1_URS; + } + else + { + /* Reset the URS Bit */ + TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_URS); + } +} + +/** + * @brief Enables or disables the TIMx's Hall sensor interface. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param NewState: new state of the TIMx Hall sensor interface. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void TIM_SelectHallSensor(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Set the TI1S Bit */ + TIMx->CR2 |= TIM_CR2_TI1S; + } + else + { + /* Reset the TI1S Bit */ + TIMx->CR2 &= (uint16_t)~((uint16_t)TIM_CR2_TI1S); + } +} + +/** + * @brief Selects the TIMx's One Pulse Mode. + * @param TIMx: where x can be 1 to 17 to select the TIM peripheral. + * @param TIM_OPMode: specifies the OPM Mode to be used. + * This parameter can be one of the following values: + * @arg TIM_OPMode_Single + * @arg TIM_OPMode_Repetitive + * @retval None + */ +void TIM_SelectOnePulseMode(TIM_TypeDef* TIMx, uint16_t TIM_OPMode) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_OPM_MODE(TIM_OPMode)); + /* Reset the OPM Bit */ + TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_OPM); + /* Configure the OPM Mode */ + TIMx->CR1 |= TIM_OPMode; +} + +/** + * @brief Selects the TIMx Trigger Output Mode. + * @param TIMx: where x can be 1, 2, 3, 4, 5, 6, 7, 8, 9, 12 or 15 to select the TIM peripheral. + * @param TIM_TRGOSource: specifies the Trigger Output source. + * This paramter can be one of the following values: + * + * - For all TIMx + * @arg TIM_TRGOSource_Reset: The UG bit in the TIM_EGR register is used as the trigger output (TRGO). + * @arg TIM_TRGOSource_Enable: The Counter Enable CEN is used as the trigger output (TRGO). + * @arg TIM_TRGOSource_Update: The update event is selected as the trigger output (TRGO). + * + * - For all TIMx except TIM6 and TIM7 + * @arg TIM_TRGOSource_OC1: The trigger output sends a positive pulse when the CC1IF flag + * is to be set, as soon as a capture or compare match occurs (TRGO). + * @arg TIM_TRGOSource_OC1Ref: OC1REF signal is used as the trigger output (TRGO). + * @arg TIM_TRGOSource_OC2Ref: OC2REF signal is used as the trigger output (TRGO). + * @arg TIM_TRGOSource_OC3Ref: OC3REF signal is used as the trigger output (TRGO). + * @arg TIM_TRGOSource_OC4Ref: OC4REF signal is used as the trigger output (TRGO). + * + * @retval None + */ +void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST7_PERIPH(TIMx)); + assert_param(IS_TIM_TRGO_SOURCE(TIM_TRGOSource)); + /* Reset the MMS Bits */ + TIMx->CR2 &= (uint16_t)~((uint16_t)TIM_CR2_MMS); + /* Select the TRGO source */ + TIMx->CR2 |= TIM_TRGOSource; +} + +/** + * @brief Selects the TIMx Slave Mode. + * @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral. + * @param TIM_SlaveMode: specifies the Timer Slave Mode. + * This parameter can be one of the following values: + * @arg TIM_SlaveMode_Reset: Rising edge of the selected trigger signal (TRGI) re-initializes + * the counter and triggers an update of the registers. + * @arg TIM_SlaveMode_Gated: The counter clock is enabled when the trigger signal (TRGI) is high. + * @arg TIM_SlaveMode_Trigger: The counter starts at a rising edge of the trigger TRGI. + * @arg TIM_SlaveMode_External1: Rising edges of the selected trigger (TRGI) clock the counter. + * @retval None + */ +void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + assert_param(IS_TIM_SLAVE_MODE(TIM_SlaveMode)); + /* Reset the SMS Bits */ + TIMx->SMCR &= (uint16_t)~((uint16_t)TIM_SMCR_SMS); + /* Select the Slave Mode */ + TIMx->SMCR |= TIM_SlaveMode; +} + +/** + * @brief Sets or Resets the TIMx Master/Slave Mode. + * @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral. + * @param TIM_MasterSlaveMode: specifies the Timer Master Slave Mode. + * This parameter can be one of the following values: + * @arg TIM_MasterSlaveMode_Enable: synchronization between the current timer + * and its slaves (through TRGO). + * @arg TIM_MasterSlaveMode_Disable: No action + * @retval None + */ +void TIM_SelectMasterSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_MasterSlaveMode) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + assert_param(IS_TIM_MSM_STATE(TIM_MasterSlaveMode)); + /* Reset the MSM Bit */ + TIMx->SMCR &= (uint16_t)~((uint16_t)TIM_SMCR_MSM); + + /* Set or Reset the MSM Bit */ + TIMx->SMCR |= TIM_MasterSlaveMode; +} + +/** + * @brief Sets the TIMx Counter Register value + * @param TIMx: where x can be 1 to 17 to select the TIM peripheral. + * @param Counter: specifies the Counter register new value. + * @retval None + */ +void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + /* Set the Counter Register value */ + TIMx->CNT = Counter; +} + +/** + * @brief Sets the TIMx Autoreload Register value + * @param TIMx: where x can be 1 to 17 to select the TIM peripheral. + * @param Autoreload: specifies the Autoreload register new value. + * @retval None + */ +void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + /* Set the Autoreload Register value */ + TIMx->ARR = Autoreload; +} + +/** + * @brief Sets the TIMx Capture Compare1 Register value + * @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral. + * @param Compare1: specifies the Capture Compare1 register new value. + * @retval None + */ +void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST8_PERIPH(TIMx)); + /* Set the Capture Compare1 Register value */ + TIMx->CCR1 = Compare1; +} + +/** + * @brief Sets the TIMx Capture Compare2 Register value + * @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral. + * @param Compare2: specifies the Capture Compare2 register new value. + * @retval None + */ +void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + /* Set the Capture Compare2 Register value */ + TIMx->CCR2 = Compare2; +} + +/** + * @brief Sets the TIMx Capture Compare3 Register value + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param Compare3: specifies the Capture Compare3 register new value. + * @retval None + */ +void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + /* Set the Capture Compare3 Register value */ + TIMx->CCR3 = Compare3; +} + +/** + * @brief Sets the TIMx Capture Compare4 Register value + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param Compare4: specifies the Capture Compare4 register new value. + * @retval None + */ +void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + /* Set the Capture Compare4 Register value */ + TIMx->CCR4 = Compare4; +} + +/** + * @brief Sets the TIMx Input Capture 1 prescaler. + * @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral. + * @param TIM_ICPSC: specifies the Input Capture1 prescaler new value. + * This parameter can be one of the following values: + * @arg TIM_ICPSC_DIV1: no prescaler + * @arg TIM_ICPSC_DIV2: capture is done once every 2 events + * @arg TIM_ICPSC_DIV4: capture is done once every 4 events + * @arg TIM_ICPSC_DIV8: capture is done once every 8 events + * @retval None + */ +void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST8_PERIPH(TIMx)); + assert_param(IS_TIM_IC_PRESCALER(TIM_ICPSC)); + /* Reset the IC1PSC Bits */ + TIMx->CCMR1 &= (uint16_t)~((uint16_t)TIM_CCMR1_IC1PSC); + /* Set the IC1PSC value */ + TIMx->CCMR1 |= TIM_ICPSC; +} + +/** + * @brief Sets the TIMx Input Capture 2 prescaler. + * @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral. + * @param TIM_ICPSC: specifies the Input Capture2 prescaler new value. + * This parameter can be one of the following values: + * @arg TIM_ICPSC_DIV1: no prescaler + * @arg TIM_ICPSC_DIV2: capture is done once every 2 events + * @arg TIM_ICPSC_DIV4: capture is done once every 4 events + * @arg TIM_ICPSC_DIV8: capture is done once every 8 events + * @retval None + */ +void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + assert_param(IS_TIM_IC_PRESCALER(TIM_ICPSC)); + /* Reset the IC2PSC Bits */ + TIMx->CCMR1 &= (uint16_t)~((uint16_t)TIM_CCMR1_IC2PSC); + /* Set the IC2PSC value */ + TIMx->CCMR1 |= (uint16_t)(TIM_ICPSC << 8); +} + +/** + * @brief Sets the TIMx Input Capture 3 prescaler. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ICPSC: specifies the Input Capture3 prescaler new value. + * This parameter can be one of the following values: + * @arg TIM_ICPSC_DIV1: no prescaler + * @arg TIM_ICPSC_DIV2: capture is done once every 2 events + * @arg TIM_ICPSC_DIV4: capture is done once every 4 events + * @arg TIM_ICPSC_DIV8: capture is done once every 8 events + * @retval None + */ +void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_IC_PRESCALER(TIM_ICPSC)); + /* Reset the IC3PSC Bits */ + TIMx->CCMR2 &= (uint16_t)~((uint16_t)TIM_CCMR2_IC3PSC); + /* Set the IC3PSC value */ + TIMx->CCMR2 |= TIM_ICPSC; +} + +/** + * @brief Sets the TIMx Input Capture 4 prescaler. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ICPSC: specifies the Input Capture4 prescaler new value. + * This parameter can be one of the following values: + * @arg TIM_ICPSC_DIV1: no prescaler + * @arg TIM_ICPSC_DIV2: capture is done once every 2 events + * @arg TIM_ICPSC_DIV4: capture is done once every 4 events + * @arg TIM_ICPSC_DIV8: capture is done once every 8 events + * @retval None + */ +void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_IC_PRESCALER(TIM_ICPSC)); + /* Reset the IC4PSC Bits */ + TIMx->CCMR2 &= (uint16_t)~((uint16_t)TIM_CCMR2_IC4PSC); + /* Set the IC4PSC value */ + TIMx->CCMR2 |= (uint16_t)(TIM_ICPSC << 8); +} + +/** + * @brief Sets the TIMx Clock Division value. + * @param TIMx: where x can be 1 to 17 except 6 and 7 to select + * the TIM peripheral. + * @param TIM_CKD: specifies the clock division value. + * This parameter can be one of the following value: + * @arg TIM_CKD_DIV1: TDTS = Tck_tim + * @arg TIM_CKD_DIV2: TDTS = 2*Tck_tim + * @arg TIM_CKD_DIV4: TDTS = 4*Tck_tim + * @retval None + */ +void TIM_SetClockDivision(TIM_TypeDef* TIMx, uint16_t TIM_CKD) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST8_PERIPH(TIMx)); + assert_param(IS_TIM_CKD_DIV(TIM_CKD)); + /* Reset the CKD Bits */ + TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_CKD); + /* Set the CKD value */ + TIMx->CR1 |= TIM_CKD; +} + +/** + * @brief Gets the TIMx Input Capture 1 value. + * @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral. + * @retval Capture Compare 1 Register value. + */ +uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST8_PERIPH(TIMx)); + /* Get the Capture 1 Register value */ + return TIMx->CCR1; +} + +/** + * @brief Gets the TIMx Input Capture 2 value. + * @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral. + * @retval Capture Compare 2 Register value. + */ +uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + /* Get the Capture 2 Register value */ + return TIMx->CCR2; +} + +/** + * @brief Gets the TIMx Input Capture 3 value. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @retval Capture Compare 3 Register value. + */ +uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + /* Get the Capture 3 Register value */ + return TIMx->CCR3; +} + +/** + * @brief Gets the TIMx Input Capture 4 value. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @retval Capture Compare 4 Register value. + */ +uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + /* Get the Capture 4 Register value */ + return TIMx->CCR4; +} + +/** + * @brief Gets the TIMx Counter value. + * @param TIMx: where x can be 1 to 17 to select the TIM peripheral. + * @retval Counter Register value. + */ +uint16_t TIM_GetCounter(TIM_TypeDef* TIMx) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + /* Get the Counter Register value */ + return TIMx->CNT; +} + +/** + * @brief Gets the TIMx Prescaler value. + * @param TIMx: where x can be 1 to 17 to select the TIM peripheral. + * @retval Prescaler Register value. + */ +uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + /* Get the Prescaler Register value */ + return TIMx->PSC; +} + +/** + * @brief Checks whether the specified TIM flag is set or not. + * @param TIMx: where x can be 1 to 17 to select the TIM peripheral. + * @param TIM_FLAG: specifies the flag to check. + * This parameter can be one of the following values: + * @arg TIM_FLAG_Update: TIM update Flag + * @arg TIM_FLAG_CC1: TIM Capture Compare 1 Flag + * @arg TIM_FLAG_CC2: TIM Capture Compare 2 Flag + * @arg TIM_FLAG_CC3: TIM Capture Compare 3 Flag + * @arg TIM_FLAG_CC4: TIM Capture Compare 4 Flag + * @arg TIM_FLAG_COM: TIM Commutation Flag + * @arg TIM_FLAG_Trigger: TIM Trigger Flag + * @arg TIM_FLAG_Break: TIM Break Flag + * @arg TIM_FLAG_CC1OF: TIM Capture Compare 1 overcapture Flag + * @arg TIM_FLAG_CC2OF: TIM Capture Compare 2 overcapture Flag + * @arg TIM_FLAG_CC3OF: TIM Capture Compare 3 overcapture Flag + * @arg TIM_FLAG_CC4OF: TIM Capture Compare 4 overcapture Flag + * @note + * - TIM6 and TIM7 can have only one update flag. + * - TIM9, TIM12 and TIM15 can have only TIM_FLAG_Update, TIM_FLAG_CC1, + * TIM_FLAG_CC2 or TIM_FLAG_Trigger. + * - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_FLAG_Update or TIM_FLAG_CC1. + * - TIM_FLAG_Break is used only with TIM1, TIM8 and TIM15. + * - TIM_FLAG_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17. + * @retval The new state of TIM_FLAG (SET or RESET). + */ +FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG) +{ + ITStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_GET_FLAG(TIM_FLAG)); + + if ((TIMx->SR & TIM_FLAG) != (uint16_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the TIMx's pending flags. + * @param TIMx: where x can be 1 to 17 to select the TIM peripheral. + * @param TIM_FLAG: specifies the flag bit to clear. + * This parameter can be any combination of the following values: + * @arg TIM_FLAG_Update: TIM update Flag + * @arg TIM_FLAG_CC1: TIM Capture Compare 1 Flag + * @arg TIM_FLAG_CC2: TIM Capture Compare 2 Flag + * @arg TIM_FLAG_CC3: TIM Capture Compare 3 Flag + * @arg TIM_FLAG_CC4: TIM Capture Compare 4 Flag + * @arg TIM_FLAG_COM: TIM Commutation Flag + * @arg TIM_FLAG_Trigger: TIM Trigger Flag + * @arg TIM_FLAG_Break: TIM Break Flag + * @arg TIM_FLAG_CC1OF: TIM Capture Compare 1 overcapture Flag + * @arg TIM_FLAG_CC2OF: TIM Capture Compare 2 overcapture Flag + * @arg TIM_FLAG_CC3OF: TIM Capture Compare 3 overcapture Flag + * @arg TIM_FLAG_CC4OF: TIM Capture Compare 4 overcapture Flag + * @note + * - TIM6 and TIM7 can have only one update flag. + * - TIM9, TIM12 and TIM15 can have only TIM_FLAG_Update, TIM_FLAG_CC1, + * TIM_FLAG_CC2 or TIM_FLAG_Trigger. + * - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_FLAG_Update or TIM_FLAG_CC1. + * - TIM_FLAG_Break is used only with TIM1, TIM8 and TIM15. + * - TIM_FLAG_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17. + * @retval None + */ +void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_CLEAR_FLAG(TIM_FLAG)); + + /* Clear the flags */ + TIMx->SR = (uint16_t)~TIM_FLAG; +} + +/** + * @brief Checks whether the TIM interrupt has occurred or not. + * @param TIMx: where x can be 1 to 17 to select the TIM peripheral. + * @param TIM_IT: specifies the TIM interrupt source to check. + * This parameter can be one of the following values: + * @arg TIM_IT_Update: TIM update Interrupt source + * @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source + * @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source + * @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source + * @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source + * @arg TIM_IT_COM: TIM Commutation Interrupt source + * @arg TIM_IT_Trigger: TIM Trigger Interrupt source + * @arg TIM_IT_Break: TIM Break Interrupt source + * @note + * - TIM6 and TIM7 can generate only an update interrupt. + * - TIM9, TIM12 and TIM15 can have only TIM_IT_Update, TIM_IT_CC1, + * TIM_IT_CC2 or TIM_IT_Trigger. + * - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_IT_Update or TIM_IT_CC1. + * - TIM_IT_Break is used only with TIM1, TIM8 and TIM15. + * - TIM_IT_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17. + * @retval The new state of the TIM_IT(SET or RESET). + */ +ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT) +{ + ITStatus bitstatus = RESET; + uint16_t itstatus = 0x0, itenable = 0x0; + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_GET_IT(TIM_IT)); + + itstatus = TIMx->SR & TIM_IT; + + itenable = TIMx->DIER & TIM_IT; + if ((itstatus != (uint16_t)RESET) && (itenable != (uint16_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the TIMx's interrupt pending bits. + * @param TIMx: where x can be 1 to 17 to select the TIM peripheral. + * @param TIM_IT: specifies the pending bit to clear. + * This parameter can be any combination of the following values: + * @arg TIM_IT_Update: TIM1 update Interrupt source + * @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source + * @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source + * @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source + * @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source + * @arg TIM_IT_COM: TIM Commutation Interrupt source + * @arg TIM_IT_Trigger: TIM Trigger Interrupt source + * @arg TIM_IT_Break: TIM Break Interrupt source + * @note + * - TIM6 and TIM7 can generate only an update interrupt. + * - TIM9, TIM12 and TIM15 can have only TIM_IT_Update, TIM_IT_CC1, + * TIM_IT_CC2 or TIM_IT_Trigger. + * - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_IT_Update or TIM_IT_CC1. + * - TIM_IT_Break is used only with TIM1, TIM8 and TIM15. + * - TIM_IT_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17. + * @retval None + */ +void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_IT(TIM_IT)); + /* Clear the IT pending Bit */ + TIMx->SR = (uint16_t)~TIM_IT; +} + +/** + * @brief Configure the TI1 as Input. + * @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral. + * @param TIM_ICPolarity : The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising + * @arg TIM_ICPolarity_Falling + * @param TIM_ICSelection: specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_ICSelection_DirectTI: TIM Input 1 is selected to be connected to IC1. + * @arg TIM_ICSelection_IndirectTI: TIM Input 1 is selected to be connected to IC2. + * @arg TIM_ICSelection_TRC: TIM Input 1 is selected to be connected to TRC. + * @param TIM_ICFilter: Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + */ +static void TI1_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter) +{ + uint16_t tmpccmr1 = 0, tmpccer = 0; + /* Disable the Channel 1: Reset the CC1E Bit */ + TIMx->CCER &= (uint16_t)~((uint16_t)TIM_CCER_CC1E); + tmpccmr1 = TIMx->CCMR1; + tmpccer = TIMx->CCER; + /* Select the Input and set the filter */ + tmpccmr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR1_CC1S)) & ((uint16_t)~((uint16_t)TIM_CCMR1_IC1F))); + tmpccmr1 |= (uint16_t)(TIM_ICSelection | (uint16_t)(TIM_ICFilter << (uint16_t)4)); + + if((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || + (TIMx == TIM4) ||(TIMx == TIM5)) + { + /* Select the Polarity and set the CC1E Bit */ + tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC1P)); + tmpccer |= (uint16_t)(TIM_ICPolarity | (uint16_t)TIM_CCER_CC1E); + } + else + { + /* Select the Polarity and set the CC1E Bit */ + tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC1P | TIM_CCER_CC1NP)); + tmpccer |= (uint16_t)(TIM_ICPolarity | (uint16_t)TIM_CCER_CC1E); + } + + /* Write to TIMx CCMR1 and CCER registers */ + TIMx->CCMR1 = tmpccmr1; + TIMx->CCER = tmpccer; +} + +/** + * @brief Configure the TI2 as Input. + * @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral. + * @param TIM_ICPolarity : The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising + * @arg TIM_ICPolarity_Falling + * @param TIM_ICSelection: specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_ICSelection_DirectTI: TIM Input 2 is selected to be connected to IC2. + * @arg TIM_ICSelection_IndirectTI: TIM Input 2 is selected to be connected to IC1. + * @arg TIM_ICSelection_TRC: TIM Input 2 is selected to be connected to TRC. + * @param TIM_ICFilter: Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + */ +static void TI2_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter) +{ + uint16_t tmpccmr1 = 0, tmpccer = 0, tmp = 0; + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCER &= (uint16_t)~((uint16_t)TIM_CCER_CC2E); + tmpccmr1 = TIMx->CCMR1; + tmpccer = TIMx->CCER; + tmp = (uint16_t)(TIM_ICPolarity << 4); + /* Select the Input and set the filter */ + tmpccmr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR1_CC2S)) & ((uint16_t)~((uint16_t)TIM_CCMR1_IC2F))); + tmpccmr1 |= (uint16_t)(TIM_ICFilter << 12); + tmpccmr1 |= (uint16_t)(TIM_ICSelection << 8); + + if((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || + (TIMx == TIM4) ||(TIMx == TIM5)) + { + /* Select the Polarity and set the CC2E Bit */ + tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC2P)); + tmpccer |= (uint16_t)(tmp | (uint16_t)TIM_CCER_CC2E); + } + else + { + /* Select the Polarity and set the CC2E Bit */ + tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC2P | TIM_CCER_CC2NP)); + tmpccer |= (uint16_t)(TIM_ICPolarity | (uint16_t)TIM_CCER_CC2E); + } + + /* Write to TIMx CCMR1 and CCER registers */ + TIMx->CCMR1 = tmpccmr1 ; + TIMx->CCER = tmpccer; +} + +/** + * @brief Configure the TI3 as Input. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ICPolarity : The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising + * @arg TIM_ICPolarity_Falling + * @param TIM_ICSelection: specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_ICSelection_DirectTI: TIM Input 3 is selected to be connected to IC3. + * @arg TIM_ICSelection_IndirectTI: TIM Input 3 is selected to be connected to IC4. + * @arg TIM_ICSelection_TRC: TIM Input 3 is selected to be connected to TRC. + * @param TIM_ICFilter: Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + */ +static void TI3_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter) +{ + uint16_t tmpccmr2 = 0, tmpccer = 0, tmp = 0; + /* Disable the Channel 3: Reset the CC3E Bit */ + TIMx->CCER &= (uint16_t)~((uint16_t)TIM_CCER_CC3E); + tmpccmr2 = TIMx->CCMR2; + tmpccer = TIMx->CCER; + tmp = (uint16_t)(TIM_ICPolarity << 8); + /* Select the Input and set the filter */ + tmpccmr2 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR2_CC3S)) & ((uint16_t)~((uint16_t)TIM_CCMR2_IC3F))); + tmpccmr2 |= (uint16_t)(TIM_ICSelection | (uint16_t)(TIM_ICFilter << (uint16_t)4)); + + if((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || + (TIMx == TIM4) ||(TIMx == TIM5)) + { + /* Select the Polarity and set the CC3E Bit */ + tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC3P)); + tmpccer |= (uint16_t)(tmp | (uint16_t)TIM_CCER_CC3E); + } + else + { + /* Select the Polarity and set the CC3E Bit */ + tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC3P | TIM_CCER_CC3NP)); + tmpccer |= (uint16_t)(TIM_ICPolarity | (uint16_t)TIM_CCER_CC3E); + } + + /* Write to TIMx CCMR2 and CCER registers */ + TIMx->CCMR2 = tmpccmr2; + TIMx->CCER = tmpccer; +} + +/** + * @brief Configure the TI4 as Input. + * @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ICPolarity : The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising + * @arg TIM_ICPolarity_Falling + * @param TIM_ICSelection: specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_ICSelection_DirectTI: TIM Input 4 is selected to be connected to IC4. + * @arg TIM_ICSelection_IndirectTI: TIM Input 4 is selected to be connected to IC3. + * @arg TIM_ICSelection_TRC: TIM Input 4 is selected to be connected to TRC. + * @param TIM_ICFilter: Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + */ +static void TI4_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter) +{ + uint16_t tmpccmr2 = 0, tmpccer = 0, tmp = 0; + + /* Disable the Channel 4: Reset the CC4E Bit */ + TIMx->CCER &= (uint16_t)~((uint16_t)TIM_CCER_CC4E); + tmpccmr2 = TIMx->CCMR2; + tmpccer = TIMx->CCER; + tmp = (uint16_t)(TIM_ICPolarity << 12); + /* Select the Input and set the filter */ + tmpccmr2 &= (uint16_t)((uint16_t)(~(uint16_t)TIM_CCMR2_CC4S) & ((uint16_t)~((uint16_t)TIM_CCMR2_IC4F))); + tmpccmr2 |= (uint16_t)(TIM_ICSelection << 8); + tmpccmr2 |= (uint16_t)(TIM_ICFilter << 12); + + if((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || + (TIMx == TIM4) ||(TIMx == TIM5)) + { + /* Select the Polarity and set the CC4E Bit */ + tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC4P)); + tmpccer |= (uint16_t)(tmp | (uint16_t)TIM_CCER_CC4E); + } + else + { + /* Select the Polarity and set the CC4E Bit */ + tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC3P | TIM_CCER_CC4NP)); + tmpccer |= (uint16_t)(TIM_ICPolarity | (uint16_t)TIM_CCER_CC4E); + } + /* Write to TIMx CCMR2 and CCER registers */ + TIMx->CCMR2 = tmpccmr2; + TIMx->CCER = tmpccer; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_tim.h b/Library/stm32f10x_tim.h new file mode 100644 index 0000000..65bf76a --- /dev/null +++ b/Library/stm32f10x_tim.h @@ -0,0 +1,1164 @@ +/** + ****************************************************************************** + * @file stm32f10x_tim.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the TIM firmware + * library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_TIM_H +#define __STM32F10x_TIM_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup TIM + * @{ + */ + +/** @defgroup TIM_Exported_Types + * @{ + */ + +/** + * @brief TIM Time Base Init structure definition + * @note This structure is used with all TIMx except for TIM6 and TIM7. + */ + +typedef struct +{ + uint16_t TIM_Prescaler; /*!< Specifies the prescaler value used to divide the TIM clock. + This parameter can be a number between 0x0000 and 0xFFFF */ + + uint16_t TIM_CounterMode; /*!< Specifies the counter mode. + This parameter can be a value of @ref TIM_Counter_Mode */ + + uint16_t TIM_Period; /*!< Specifies the period value to be loaded into the active + Auto-Reload Register at the next update event. + This parameter must be a number between 0x0000 and 0xFFFF. */ + + uint16_t TIM_ClockDivision; /*!< Specifies the clock division. + This parameter can be a value of @ref TIM_Clock_Division_CKD */ + + uint8_t TIM_RepetitionCounter; /*!< Specifies the repetition counter value. Each time the RCR downcounter + reaches zero, an update event is generated and counting restarts + from the RCR value (N). + This means in PWM mode that (N+1) corresponds to: + - the number of PWM periods in edge-aligned mode + - the number of half PWM period in center-aligned mode + This parameter must be a number between 0x00 and 0xFF. + @note This parameter is valid only for TIM1 and TIM8. */ +} TIM_TimeBaseInitTypeDef; + +/** + * @brief TIM Output Compare Init structure definition + */ + +typedef struct +{ + uint16_t TIM_OCMode; /*!< Specifies the TIM mode. + This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */ + + uint16_t TIM_OutputState; /*!< Specifies the TIM Output Compare state. + This parameter can be a value of @ref TIM_Output_Compare_state */ + + uint16_t TIM_OutputNState; /*!< Specifies the TIM complementary Output Compare state. + This parameter can be a value of @ref TIM_Output_Compare_N_state + @note This parameter is valid only for TIM1 and TIM8. */ + + uint16_t TIM_Pulse; /*!< Specifies the pulse value to be loaded into the Capture Compare Register. + This parameter can be a number between 0x0000 and 0xFFFF */ + + uint16_t TIM_OCPolarity; /*!< Specifies the output polarity. + This parameter can be a value of @ref TIM_Output_Compare_Polarity */ + + uint16_t TIM_OCNPolarity; /*!< Specifies the complementary output polarity. + This parameter can be a value of @ref TIM_Output_Compare_N_Polarity + @note This parameter is valid only for TIM1 and TIM8. */ + + uint16_t TIM_OCIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_Idle_State + @note This parameter is valid only for TIM1 and TIM8. */ + + uint16_t TIM_OCNIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State + @note This parameter is valid only for TIM1 and TIM8. */ +} TIM_OCInitTypeDef; + +/** + * @brief TIM Input Capture Init structure definition + */ + +typedef struct +{ + + uint16_t TIM_Channel; /*!< Specifies the TIM channel. + This parameter can be a value of @ref TIM_Channel */ + + uint16_t TIM_ICPolarity; /*!< Specifies the active edge of the input signal. + This parameter can be a value of @ref TIM_Input_Capture_Polarity */ + + uint16_t TIM_ICSelection; /*!< Specifies the input. + This parameter can be a value of @ref TIM_Input_Capture_Selection */ + + uint16_t TIM_ICPrescaler; /*!< Specifies the Input Capture Prescaler. + This parameter can be a value of @ref TIM_Input_Capture_Prescaler */ + + uint16_t TIM_ICFilter; /*!< Specifies the input capture filter. + This parameter can be a number between 0x0 and 0xF */ +} TIM_ICInitTypeDef; + +/** + * @brief BDTR structure definition + * @note This structure is used only with TIM1 and TIM8. + */ + +typedef struct +{ + + uint16_t TIM_OSSRState; /*!< Specifies the Off-State selection used in Run mode. + This parameter can be a value of @ref OSSR_Off_State_Selection_for_Run_mode_state */ + + uint16_t TIM_OSSIState; /*!< Specifies the Off-State used in Idle state. + This parameter can be a value of @ref OSSI_Off_State_Selection_for_Idle_mode_state */ + + uint16_t TIM_LOCKLevel; /*!< Specifies the LOCK level parameters. + This parameter can be a value of @ref Lock_level */ + + uint16_t TIM_DeadTime; /*!< Specifies the delay time between the switching-off and the + switching-on of the outputs. + This parameter can be a number between 0x00 and 0xFF */ + + uint16_t TIM_Break; /*!< Specifies whether the TIM Break input is enabled or not. + This parameter can be a value of @ref Break_Input_enable_disable */ + + uint16_t TIM_BreakPolarity; /*!< Specifies the TIM Break Input pin polarity. + This parameter can be a value of @ref Break_Polarity */ + + uint16_t TIM_AutomaticOutput; /*!< Specifies whether the TIM Automatic Output feature is enabled or not. + This parameter can be a value of @ref TIM_AOE_Bit_Set_Reset */ +} TIM_BDTRInitTypeDef; + +/** @defgroup TIM_Exported_constants + * @{ + */ + +#define IS_TIM_ALL_PERIPH(PERIPH) (((PERIPH) == TIM1) || \ + ((PERIPH) == TIM2) || \ + ((PERIPH) == TIM3) || \ + ((PERIPH) == TIM4) || \ + ((PERIPH) == TIM5) || \ + ((PERIPH) == TIM6) || \ + ((PERIPH) == TIM7) || \ + ((PERIPH) == TIM8) || \ + ((PERIPH) == TIM9) || \ + ((PERIPH) == TIM10)|| \ + ((PERIPH) == TIM11)|| \ + ((PERIPH) == TIM12)|| \ + ((PERIPH) == TIM13)|| \ + ((PERIPH) == TIM14)|| \ + ((PERIPH) == TIM15)|| \ + ((PERIPH) == TIM16)|| \ + ((PERIPH) == TIM17)) + +/* LIST1: TIM 1 and 8 */ +#define IS_TIM_LIST1_PERIPH(PERIPH) (((PERIPH) == TIM1) || \ + ((PERIPH) == TIM8)) + +/* LIST2: TIM 1, 8, 15 16 and 17 */ +#define IS_TIM_LIST2_PERIPH(PERIPH) (((PERIPH) == TIM1) || \ + ((PERIPH) == TIM8) || \ + ((PERIPH) == TIM15)|| \ + ((PERIPH) == TIM16)|| \ + ((PERIPH) == TIM17)) + +/* LIST3: TIM 1, 2, 3, 4, 5 and 8 */ +#define IS_TIM_LIST3_PERIPH(PERIPH) (((PERIPH) == TIM1) || \ + ((PERIPH) == TIM2) || \ + ((PERIPH) == TIM3) || \ + ((PERIPH) == TIM4) || \ + ((PERIPH) == TIM5) || \ + ((PERIPH) == TIM8)) + +/* LIST4: TIM 1, 2, 3, 4, 5, 8, 15, 16 and 17 */ +#define IS_TIM_LIST4_PERIPH(PERIPH) (((PERIPH) == TIM1) || \ + ((PERIPH) == TIM2) || \ + ((PERIPH) == TIM3) || \ + ((PERIPH) == TIM4) || \ + ((PERIPH) == TIM5) || \ + ((PERIPH) == TIM8) || \ + ((PERIPH) == TIM15)|| \ + ((PERIPH) == TIM16)|| \ + ((PERIPH) == TIM17)) + +/* LIST5: TIM 1, 2, 3, 4, 5, 8 and 15 */ +#define IS_TIM_LIST5_PERIPH(PERIPH) (((PERIPH) == TIM1) || \ + ((PERIPH) == TIM2) || \ + ((PERIPH) == TIM3) || \ + ((PERIPH) == TIM4) || \ + ((PERIPH) == TIM5) || \ + ((PERIPH) == TIM8) || \ + ((PERIPH) == TIM15)) + +/* LIST6: TIM 1, 2, 3, 4, 5, 8, 9, 12 and 15 */ +#define IS_TIM_LIST6_PERIPH(PERIPH) (((PERIPH) == TIM1) || \ + ((PERIPH) == TIM2) || \ + ((PERIPH) == TIM3) || \ + ((PERIPH) == TIM4) || \ + ((PERIPH) == TIM5) || \ + ((PERIPH) == TIM8) || \ + ((PERIPH) == TIM9) || \ + ((PERIPH) == TIM12)|| \ + ((PERIPH) == TIM15)) + +/* LIST7: TIM 1, 2, 3, 4, 5, 6, 7, 8, 9, 12 and 15 */ +#define IS_TIM_LIST7_PERIPH(PERIPH) (((PERIPH) == TIM1) || \ + ((PERIPH) == TIM2) || \ + ((PERIPH) == TIM3) || \ + ((PERIPH) == TIM4) || \ + ((PERIPH) == TIM5) || \ + ((PERIPH) == TIM6) || \ + ((PERIPH) == TIM7) || \ + ((PERIPH) == TIM8) || \ + ((PERIPH) == TIM9) || \ + ((PERIPH) == TIM12)|| \ + ((PERIPH) == TIM15)) + +/* LIST8: TIM 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16 and 17 */ +#define IS_TIM_LIST8_PERIPH(PERIPH) (((PERIPH) == TIM1) || \ + ((PERIPH) == TIM2) || \ + ((PERIPH) == TIM3) || \ + ((PERIPH) == TIM4) || \ + ((PERIPH) == TIM5) || \ + ((PERIPH) == TIM8) || \ + ((PERIPH) == TIM9) || \ + ((PERIPH) == TIM10)|| \ + ((PERIPH) == TIM11)|| \ + ((PERIPH) == TIM12)|| \ + ((PERIPH) == TIM13)|| \ + ((PERIPH) == TIM14)|| \ + ((PERIPH) == TIM15)|| \ + ((PERIPH) == TIM16)|| \ + ((PERIPH) == TIM17)) + +/* LIST9: TIM 1, 2, 3, 4, 5, 6, 7, 8, 15, 16, and 17 */ +#define IS_TIM_LIST9_PERIPH(PERIPH) (((PERIPH) == TIM1) || \ + ((PERIPH) == TIM2) || \ + ((PERIPH) == TIM3) || \ + ((PERIPH) == TIM4) || \ + ((PERIPH) == TIM5) || \ + ((PERIPH) == TIM6) || \ + ((PERIPH) == TIM7) || \ + ((PERIPH) == TIM8) || \ + ((PERIPH) == TIM15)|| \ + ((PERIPH) == TIM16)|| \ + ((PERIPH) == TIM17)) + +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_and_PWM_modes + * @{ + */ + +#define TIM_OCMode_Timing ((uint16_t)0x0000) +#define TIM_OCMode_Active ((uint16_t)0x0010) +#define TIM_OCMode_Inactive ((uint16_t)0x0020) +#define TIM_OCMode_Toggle ((uint16_t)0x0030) +#define TIM_OCMode_PWM1 ((uint16_t)0x0060) +#define TIM_OCMode_PWM2 ((uint16_t)0x0070) +#define IS_TIM_OC_MODE(MODE) (((MODE) == TIM_OCMode_Timing) || \ + ((MODE) == TIM_OCMode_Active) || \ + ((MODE) == TIM_OCMode_Inactive) || \ + ((MODE) == TIM_OCMode_Toggle)|| \ + ((MODE) == TIM_OCMode_PWM1) || \ + ((MODE) == TIM_OCMode_PWM2)) +#define IS_TIM_OCM(MODE) (((MODE) == TIM_OCMode_Timing) || \ + ((MODE) == TIM_OCMode_Active) || \ + ((MODE) == TIM_OCMode_Inactive) || \ + ((MODE) == TIM_OCMode_Toggle)|| \ + ((MODE) == TIM_OCMode_PWM1) || \ + ((MODE) == TIM_OCMode_PWM2) || \ + ((MODE) == TIM_ForcedAction_Active) || \ + ((MODE) == TIM_ForcedAction_InActive)) +/** + * @} + */ + +/** @defgroup TIM_One_Pulse_Mode + * @{ + */ + +#define TIM_OPMode_Single ((uint16_t)0x0008) +#define TIM_OPMode_Repetitive ((uint16_t)0x0000) +#define IS_TIM_OPM_MODE(MODE) (((MODE) == TIM_OPMode_Single) || \ + ((MODE) == TIM_OPMode_Repetitive)) +/** + * @} + */ + +/** @defgroup TIM_Channel + * @{ + */ + +#define TIM_Channel_1 ((uint16_t)0x0000) +#define TIM_Channel_2 ((uint16_t)0x0004) +#define TIM_Channel_3 ((uint16_t)0x0008) +#define TIM_Channel_4 ((uint16_t)0x000C) +#define IS_TIM_CHANNEL(CHANNEL) (((CHANNEL) == TIM_Channel_1) || \ + ((CHANNEL) == TIM_Channel_2) || \ + ((CHANNEL) == TIM_Channel_3) || \ + ((CHANNEL) == TIM_Channel_4)) +#define IS_TIM_PWMI_CHANNEL(CHANNEL) (((CHANNEL) == TIM_Channel_1) || \ + ((CHANNEL) == TIM_Channel_2)) +#define IS_TIM_COMPLEMENTARY_CHANNEL(CHANNEL) (((CHANNEL) == TIM_Channel_1) || \ + ((CHANNEL) == TIM_Channel_2) || \ + ((CHANNEL) == TIM_Channel_3)) +/** + * @} + */ + +/** @defgroup TIM_Clock_Division_CKD + * @{ + */ + +#define TIM_CKD_DIV1 ((uint16_t)0x0000) +#define TIM_CKD_DIV2 ((uint16_t)0x0100) +#define TIM_CKD_DIV4 ((uint16_t)0x0200) +#define IS_TIM_CKD_DIV(DIV) (((DIV) == TIM_CKD_DIV1) || \ + ((DIV) == TIM_CKD_DIV2) || \ + ((DIV) == TIM_CKD_DIV4)) +/** + * @} + */ + +/** @defgroup TIM_Counter_Mode + * @{ + */ + +#define TIM_CounterMode_Up ((uint16_t)0x0000) +#define TIM_CounterMode_Down ((uint16_t)0x0010) +#define TIM_CounterMode_CenterAligned1 ((uint16_t)0x0020) +#define TIM_CounterMode_CenterAligned2 ((uint16_t)0x0040) +#define TIM_CounterMode_CenterAligned3 ((uint16_t)0x0060) +#define IS_TIM_COUNTER_MODE(MODE) (((MODE) == TIM_CounterMode_Up) || \ + ((MODE) == TIM_CounterMode_Down) || \ + ((MODE) == TIM_CounterMode_CenterAligned1) || \ + ((MODE) == TIM_CounterMode_CenterAligned2) || \ + ((MODE) == TIM_CounterMode_CenterAligned3)) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_Polarity + * @{ + */ + +#define TIM_OCPolarity_High ((uint16_t)0x0000) +#define TIM_OCPolarity_Low ((uint16_t)0x0002) +#define IS_TIM_OC_POLARITY(POLARITY) (((POLARITY) == TIM_OCPolarity_High) || \ + ((POLARITY) == TIM_OCPolarity_Low)) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_N_Polarity + * @{ + */ + +#define TIM_OCNPolarity_High ((uint16_t)0x0000) +#define TIM_OCNPolarity_Low ((uint16_t)0x0008) +#define IS_TIM_OCN_POLARITY(POLARITY) (((POLARITY) == TIM_OCNPolarity_High) || \ + ((POLARITY) == TIM_OCNPolarity_Low)) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_state + * @{ + */ + +#define TIM_OutputState_Disable ((uint16_t)0x0000) +#define TIM_OutputState_Enable ((uint16_t)0x0001) +#define IS_TIM_OUTPUT_STATE(STATE) (((STATE) == TIM_OutputState_Disable) || \ + ((STATE) == TIM_OutputState_Enable)) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_N_state + * @{ + */ + +#define TIM_OutputNState_Disable ((uint16_t)0x0000) +#define TIM_OutputNState_Enable ((uint16_t)0x0004) +#define IS_TIM_OUTPUTN_STATE(STATE) (((STATE) == TIM_OutputNState_Disable) || \ + ((STATE) == TIM_OutputNState_Enable)) +/** + * @} + */ + +/** @defgroup TIM_Capture_Compare_state + * @{ + */ + +#define TIM_CCx_Enable ((uint16_t)0x0001) +#define TIM_CCx_Disable ((uint16_t)0x0000) +#define IS_TIM_CCX(CCX) (((CCX) == TIM_CCx_Enable) || \ + ((CCX) == TIM_CCx_Disable)) +/** + * @} + */ + +/** @defgroup TIM_Capture_Compare_N_state + * @{ + */ + +#define TIM_CCxN_Enable ((uint16_t)0x0004) +#define TIM_CCxN_Disable ((uint16_t)0x0000) +#define IS_TIM_CCXN(CCXN) (((CCXN) == TIM_CCxN_Enable) || \ + ((CCXN) == TIM_CCxN_Disable)) +/** + * @} + */ + +/** @defgroup Break_Input_enable_disable + * @{ + */ + +#define TIM_Break_Enable ((uint16_t)0x1000) +#define TIM_Break_Disable ((uint16_t)0x0000) +#define IS_TIM_BREAK_STATE(STATE) (((STATE) == TIM_Break_Enable) || \ + ((STATE) == TIM_Break_Disable)) +/** + * @} + */ + +/** @defgroup Break_Polarity + * @{ + */ + +#define TIM_BreakPolarity_Low ((uint16_t)0x0000) +#define TIM_BreakPolarity_High ((uint16_t)0x2000) +#define IS_TIM_BREAK_POLARITY(POLARITY) (((POLARITY) == TIM_BreakPolarity_Low) || \ + ((POLARITY) == TIM_BreakPolarity_High)) +/** + * @} + */ + +/** @defgroup TIM_AOE_Bit_Set_Reset + * @{ + */ + +#define TIM_AutomaticOutput_Enable ((uint16_t)0x4000) +#define TIM_AutomaticOutput_Disable ((uint16_t)0x0000) +#define IS_TIM_AUTOMATIC_OUTPUT_STATE(STATE) (((STATE) == TIM_AutomaticOutput_Enable) || \ + ((STATE) == TIM_AutomaticOutput_Disable)) +/** + * @} + */ + +/** @defgroup Lock_level + * @{ + */ + +#define TIM_LOCKLevel_OFF ((uint16_t)0x0000) +#define TIM_LOCKLevel_1 ((uint16_t)0x0100) +#define TIM_LOCKLevel_2 ((uint16_t)0x0200) +#define TIM_LOCKLevel_3 ((uint16_t)0x0300) +#define IS_TIM_LOCK_LEVEL(LEVEL) (((LEVEL) == TIM_LOCKLevel_OFF) || \ + ((LEVEL) == TIM_LOCKLevel_1) || \ + ((LEVEL) == TIM_LOCKLevel_2) || \ + ((LEVEL) == TIM_LOCKLevel_3)) +/** + * @} + */ + +/** @defgroup OSSI_Off_State_Selection_for_Idle_mode_state + * @{ + */ + +#define TIM_OSSIState_Enable ((uint16_t)0x0400) +#define TIM_OSSIState_Disable ((uint16_t)0x0000) +#define IS_TIM_OSSI_STATE(STATE) (((STATE) == TIM_OSSIState_Enable) || \ + ((STATE) == TIM_OSSIState_Disable)) +/** + * @} + */ + +/** @defgroup OSSR_Off_State_Selection_for_Run_mode_state + * @{ + */ + +#define TIM_OSSRState_Enable ((uint16_t)0x0800) +#define TIM_OSSRState_Disable ((uint16_t)0x0000) +#define IS_TIM_OSSR_STATE(STATE) (((STATE) == TIM_OSSRState_Enable) || \ + ((STATE) == TIM_OSSRState_Disable)) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_Idle_State + * @{ + */ + +#define TIM_OCIdleState_Set ((uint16_t)0x0100) +#define TIM_OCIdleState_Reset ((uint16_t)0x0000) +#define IS_TIM_OCIDLE_STATE(STATE) (((STATE) == TIM_OCIdleState_Set) || \ + ((STATE) == TIM_OCIdleState_Reset)) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_N_Idle_State + * @{ + */ + +#define TIM_OCNIdleState_Set ((uint16_t)0x0200) +#define TIM_OCNIdleState_Reset ((uint16_t)0x0000) +#define IS_TIM_OCNIDLE_STATE(STATE) (((STATE) == TIM_OCNIdleState_Set) || \ + ((STATE) == TIM_OCNIdleState_Reset)) +/** + * @} + */ + +/** @defgroup TIM_Input_Capture_Polarity + * @{ + */ + +#define TIM_ICPolarity_Rising ((uint16_t)0x0000) +#define TIM_ICPolarity_Falling ((uint16_t)0x0002) +#define TIM_ICPolarity_BothEdge ((uint16_t)0x000A) +#define IS_TIM_IC_POLARITY(POLARITY) (((POLARITY) == TIM_ICPolarity_Rising) || \ + ((POLARITY) == TIM_ICPolarity_Falling)) +#define IS_TIM_IC_POLARITY_LITE(POLARITY) (((POLARITY) == TIM_ICPolarity_Rising) || \ + ((POLARITY) == TIM_ICPolarity_Falling)|| \ + ((POLARITY) == TIM_ICPolarity_BothEdge)) +/** + * @} + */ + +/** @defgroup TIM_Input_Capture_Selection + * @{ + */ + +#define TIM_ICSelection_DirectTI ((uint16_t)0x0001) /*!< TIM Input 1, 2, 3 or 4 is selected to be + connected to IC1, IC2, IC3 or IC4, respectively */ +#define TIM_ICSelection_IndirectTI ((uint16_t)0x0002) /*!< TIM Input 1, 2, 3 or 4 is selected to be + connected to IC2, IC1, IC4 or IC3, respectively. */ +#define TIM_ICSelection_TRC ((uint16_t)0x0003) /*!< TIM Input 1, 2, 3 or 4 is selected to be connected to TRC. */ +#define IS_TIM_IC_SELECTION(SELECTION) (((SELECTION) == TIM_ICSelection_DirectTI) || \ + ((SELECTION) == TIM_ICSelection_IndirectTI) || \ + ((SELECTION) == TIM_ICSelection_TRC)) +/** + * @} + */ + +/** @defgroup TIM_Input_Capture_Prescaler + * @{ + */ + +#define TIM_ICPSC_DIV1 ((uint16_t)0x0000) /*!< Capture performed each time an edge is detected on the capture input. */ +#define TIM_ICPSC_DIV2 ((uint16_t)0x0004) /*!< Capture performed once every 2 events. */ +#define TIM_ICPSC_DIV4 ((uint16_t)0x0008) /*!< Capture performed once every 4 events. */ +#define TIM_ICPSC_DIV8 ((uint16_t)0x000C) /*!< Capture performed once every 8 events. */ +#define IS_TIM_IC_PRESCALER(PRESCALER) (((PRESCALER) == TIM_ICPSC_DIV1) || \ + ((PRESCALER) == TIM_ICPSC_DIV2) || \ + ((PRESCALER) == TIM_ICPSC_DIV4) || \ + ((PRESCALER) == TIM_ICPSC_DIV8)) +/** + * @} + */ + +/** @defgroup TIM_interrupt_sources + * @{ + */ + +#define TIM_IT_Update ((uint16_t)0x0001) +#define TIM_IT_CC1 ((uint16_t)0x0002) +#define TIM_IT_CC2 ((uint16_t)0x0004) +#define TIM_IT_CC3 ((uint16_t)0x0008) +#define TIM_IT_CC4 ((uint16_t)0x0010) +#define TIM_IT_COM ((uint16_t)0x0020) +#define TIM_IT_Trigger ((uint16_t)0x0040) +#define TIM_IT_Break ((uint16_t)0x0080) +#define IS_TIM_IT(IT) ((((IT) & (uint16_t)0xFF00) == 0x0000) && ((IT) != 0x0000)) + +#define IS_TIM_GET_IT(IT) (((IT) == TIM_IT_Update) || \ + ((IT) == TIM_IT_CC1) || \ + ((IT) == TIM_IT_CC2) || \ + ((IT) == TIM_IT_CC3) || \ + ((IT) == TIM_IT_CC4) || \ + ((IT) == TIM_IT_COM) || \ + ((IT) == TIM_IT_Trigger) || \ + ((IT) == TIM_IT_Break)) +/** + * @} + */ + +/** @defgroup TIM_DMA_Base_address + * @{ + */ + +#define TIM_DMABase_CR1 ((uint16_t)0x0000) +#define TIM_DMABase_CR2 ((uint16_t)0x0001) +#define TIM_DMABase_SMCR ((uint16_t)0x0002) +#define TIM_DMABase_DIER ((uint16_t)0x0003) +#define TIM_DMABase_SR ((uint16_t)0x0004) +#define TIM_DMABase_EGR ((uint16_t)0x0005) +#define TIM_DMABase_CCMR1 ((uint16_t)0x0006) +#define TIM_DMABase_CCMR2 ((uint16_t)0x0007) +#define TIM_DMABase_CCER ((uint16_t)0x0008) +#define TIM_DMABase_CNT ((uint16_t)0x0009) +#define TIM_DMABase_PSC ((uint16_t)0x000A) +#define TIM_DMABase_ARR ((uint16_t)0x000B) +#define TIM_DMABase_RCR ((uint16_t)0x000C) +#define TIM_DMABase_CCR1 ((uint16_t)0x000D) +#define TIM_DMABase_CCR2 ((uint16_t)0x000E) +#define TIM_DMABase_CCR3 ((uint16_t)0x000F) +#define TIM_DMABase_CCR4 ((uint16_t)0x0010) +#define TIM_DMABase_BDTR ((uint16_t)0x0011) +#define TIM_DMABase_DCR ((uint16_t)0x0012) +#define IS_TIM_DMA_BASE(BASE) (((BASE) == TIM_DMABase_CR1) || \ + ((BASE) == TIM_DMABase_CR2) || \ + ((BASE) == TIM_DMABase_SMCR) || \ + ((BASE) == TIM_DMABase_DIER) || \ + ((BASE) == TIM_DMABase_SR) || \ + ((BASE) == TIM_DMABase_EGR) || \ + ((BASE) == TIM_DMABase_CCMR1) || \ + ((BASE) == TIM_DMABase_CCMR2) || \ + ((BASE) == TIM_DMABase_CCER) || \ + ((BASE) == TIM_DMABase_CNT) || \ + ((BASE) == TIM_DMABase_PSC) || \ + ((BASE) == TIM_DMABase_ARR) || \ + ((BASE) == TIM_DMABase_RCR) || \ + ((BASE) == TIM_DMABase_CCR1) || \ + ((BASE) == TIM_DMABase_CCR2) || \ + ((BASE) == TIM_DMABase_CCR3) || \ + ((BASE) == TIM_DMABase_CCR4) || \ + ((BASE) == TIM_DMABase_BDTR) || \ + ((BASE) == TIM_DMABase_DCR)) +/** + * @} + */ + +/** @defgroup TIM_DMA_Burst_Length + * @{ + */ + +#define TIM_DMABurstLength_1Transfer ((uint16_t)0x0000) +#define TIM_DMABurstLength_2Transfers ((uint16_t)0x0100) +#define TIM_DMABurstLength_3Transfers ((uint16_t)0x0200) +#define TIM_DMABurstLength_4Transfers ((uint16_t)0x0300) +#define TIM_DMABurstLength_5Transfers ((uint16_t)0x0400) +#define TIM_DMABurstLength_6Transfers ((uint16_t)0x0500) +#define TIM_DMABurstLength_7Transfers ((uint16_t)0x0600) +#define TIM_DMABurstLength_8Transfers ((uint16_t)0x0700) +#define TIM_DMABurstLength_9Transfers ((uint16_t)0x0800) +#define TIM_DMABurstLength_10Transfers ((uint16_t)0x0900) +#define TIM_DMABurstLength_11Transfers ((uint16_t)0x0A00) +#define TIM_DMABurstLength_12Transfers ((uint16_t)0x0B00) +#define TIM_DMABurstLength_13Transfers ((uint16_t)0x0C00) +#define TIM_DMABurstLength_14Transfers ((uint16_t)0x0D00) +#define TIM_DMABurstLength_15Transfers ((uint16_t)0x0E00) +#define TIM_DMABurstLength_16Transfers ((uint16_t)0x0F00) +#define TIM_DMABurstLength_17Transfers ((uint16_t)0x1000) +#define TIM_DMABurstLength_18Transfers ((uint16_t)0x1100) +#define IS_TIM_DMA_LENGTH(LENGTH) (((LENGTH) == TIM_DMABurstLength_1Transfer) || \ + ((LENGTH) == TIM_DMABurstLength_2Transfers) || \ + ((LENGTH) == TIM_DMABurstLength_3Transfers) || \ + ((LENGTH) == TIM_DMABurstLength_4Transfers) || \ + ((LENGTH) == TIM_DMABurstLength_5Transfers) || \ + ((LENGTH) == TIM_DMABurstLength_6Transfers) || \ + ((LENGTH) == TIM_DMABurstLength_7Transfers) || \ + ((LENGTH) == TIM_DMABurstLength_8Transfers) || \ + ((LENGTH) == TIM_DMABurstLength_9Transfers) || \ + ((LENGTH) == TIM_DMABurstLength_10Transfers) || \ + ((LENGTH) == TIM_DMABurstLength_11Transfers) || \ + ((LENGTH) == TIM_DMABurstLength_12Transfers) || \ + ((LENGTH) == TIM_DMABurstLength_13Transfers) || \ + ((LENGTH) == TIM_DMABurstLength_14Transfers) || \ + ((LENGTH) == TIM_DMABurstLength_15Transfers) || \ + ((LENGTH) == TIM_DMABurstLength_16Transfers) || \ + ((LENGTH) == TIM_DMABurstLength_17Transfers) || \ + ((LENGTH) == TIM_DMABurstLength_18Transfers)) +/** + * @} + */ + +/** @defgroup TIM_DMA_sources + * @{ + */ + +#define TIM_DMA_Update ((uint16_t)0x0100) +#define TIM_DMA_CC1 ((uint16_t)0x0200) +#define TIM_DMA_CC2 ((uint16_t)0x0400) +#define TIM_DMA_CC3 ((uint16_t)0x0800) +#define TIM_DMA_CC4 ((uint16_t)0x1000) +#define TIM_DMA_COM ((uint16_t)0x2000) +#define TIM_DMA_Trigger ((uint16_t)0x4000) +#define IS_TIM_DMA_SOURCE(SOURCE) ((((SOURCE) & (uint16_t)0x80FF) == 0x0000) && ((SOURCE) != 0x0000)) + +/** + * @} + */ + +/** @defgroup TIM_External_Trigger_Prescaler + * @{ + */ + +#define TIM_ExtTRGPSC_OFF ((uint16_t)0x0000) +#define TIM_ExtTRGPSC_DIV2 ((uint16_t)0x1000) +#define TIM_ExtTRGPSC_DIV4 ((uint16_t)0x2000) +#define TIM_ExtTRGPSC_DIV8 ((uint16_t)0x3000) +#define IS_TIM_EXT_PRESCALER(PRESCALER) (((PRESCALER) == TIM_ExtTRGPSC_OFF) || \ + ((PRESCALER) == TIM_ExtTRGPSC_DIV2) || \ + ((PRESCALER) == TIM_ExtTRGPSC_DIV4) || \ + ((PRESCALER) == TIM_ExtTRGPSC_DIV8)) +/** + * @} + */ + +/** @defgroup TIM_Internal_Trigger_Selection + * @{ + */ + +#define TIM_TS_ITR0 ((uint16_t)0x0000) +#define TIM_TS_ITR1 ((uint16_t)0x0010) +#define TIM_TS_ITR2 ((uint16_t)0x0020) +#define TIM_TS_ITR3 ((uint16_t)0x0030) +#define TIM_TS_TI1F_ED ((uint16_t)0x0040) +#define TIM_TS_TI1FP1 ((uint16_t)0x0050) +#define TIM_TS_TI2FP2 ((uint16_t)0x0060) +#define TIM_TS_ETRF ((uint16_t)0x0070) +#define IS_TIM_TRIGGER_SELECTION(SELECTION) (((SELECTION) == TIM_TS_ITR0) || \ + ((SELECTION) == TIM_TS_ITR1) || \ + ((SELECTION) == TIM_TS_ITR2) || \ + ((SELECTION) == TIM_TS_ITR3) || \ + ((SELECTION) == TIM_TS_TI1F_ED) || \ + ((SELECTION) == TIM_TS_TI1FP1) || \ + ((SELECTION) == TIM_TS_TI2FP2) || \ + ((SELECTION) == TIM_TS_ETRF)) +#define IS_TIM_INTERNAL_TRIGGER_SELECTION(SELECTION) (((SELECTION) == TIM_TS_ITR0) || \ + ((SELECTION) == TIM_TS_ITR1) || \ + ((SELECTION) == TIM_TS_ITR2) || \ + ((SELECTION) == TIM_TS_ITR3)) +/** + * @} + */ + +/** @defgroup TIM_TIx_External_Clock_Source + * @{ + */ + +#define TIM_TIxExternalCLK1Source_TI1 ((uint16_t)0x0050) +#define TIM_TIxExternalCLK1Source_TI2 ((uint16_t)0x0060) +#define TIM_TIxExternalCLK1Source_TI1ED ((uint16_t)0x0040) +#define IS_TIM_TIXCLK_SOURCE(SOURCE) (((SOURCE) == TIM_TIxExternalCLK1Source_TI1) || \ + ((SOURCE) == TIM_TIxExternalCLK1Source_TI2) || \ + ((SOURCE) == TIM_TIxExternalCLK1Source_TI1ED)) +/** + * @} + */ + +/** @defgroup TIM_External_Trigger_Polarity + * @{ + */ +#define TIM_ExtTRGPolarity_Inverted ((uint16_t)0x8000) +#define TIM_ExtTRGPolarity_NonInverted ((uint16_t)0x0000) +#define IS_TIM_EXT_POLARITY(POLARITY) (((POLARITY) == TIM_ExtTRGPolarity_Inverted) || \ + ((POLARITY) == TIM_ExtTRGPolarity_NonInverted)) +/** + * @} + */ + +/** @defgroup TIM_Prescaler_Reload_Mode + * @{ + */ + +#define TIM_PSCReloadMode_Update ((uint16_t)0x0000) +#define TIM_PSCReloadMode_Immediate ((uint16_t)0x0001) +#define IS_TIM_PRESCALER_RELOAD(RELOAD) (((RELOAD) == TIM_PSCReloadMode_Update) || \ + ((RELOAD) == TIM_PSCReloadMode_Immediate)) +/** + * @} + */ + +/** @defgroup TIM_Forced_Action + * @{ + */ + +#define TIM_ForcedAction_Active ((uint16_t)0x0050) +#define TIM_ForcedAction_InActive ((uint16_t)0x0040) +#define IS_TIM_FORCED_ACTION(ACTION) (((ACTION) == TIM_ForcedAction_Active) || \ + ((ACTION) == TIM_ForcedAction_InActive)) +/** + * @} + */ + +/** @defgroup TIM_Encoder_Mode + * @{ + */ + +#define TIM_EncoderMode_TI1 ((uint16_t)0x0001) +#define TIM_EncoderMode_TI2 ((uint16_t)0x0002) +#define TIM_EncoderMode_TI12 ((uint16_t)0x0003) +#define IS_TIM_ENCODER_MODE(MODE) (((MODE) == TIM_EncoderMode_TI1) || \ + ((MODE) == TIM_EncoderMode_TI2) || \ + ((MODE) == TIM_EncoderMode_TI12)) +/** + * @} + */ + + +/** @defgroup TIM_Event_Source + * @{ + */ + +#define TIM_EventSource_Update ((uint16_t)0x0001) +#define TIM_EventSource_CC1 ((uint16_t)0x0002) +#define TIM_EventSource_CC2 ((uint16_t)0x0004) +#define TIM_EventSource_CC3 ((uint16_t)0x0008) +#define TIM_EventSource_CC4 ((uint16_t)0x0010) +#define TIM_EventSource_COM ((uint16_t)0x0020) +#define TIM_EventSource_Trigger ((uint16_t)0x0040) +#define TIM_EventSource_Break ((uint16_t)0x0080) +#define IS_TIM_EVENT_SOURCE(SOURCE) ((((SOURCE) & (uint16_t)0xFF00) == 0x0000) && ((SOURCE) != 0x0000)) + +/** + * @} + */ + +/** @defgroup TIM_Update_Source + * @{ + */ + +#define TIM_UpdateSource_Global ((uint16_t)0x0000) /*!< Source of update is the counter overflow/underflow + or the setting of UG bit, or an update generation + through the slave mode controller. */ +#define TIM_UpdateSource_Regular ((uint16_t)0x0001) /*!< Source of update is counter overflow/underflow. */ +#define IS_TIM_UPDATE_SOURCE(SOURCE) (((SOURCE) == TIM_UpdateSource_Global) || \ + ((SOURCE) == TIM_UpdateSource_Regular)) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_Preload_State + * @{ + */ + +#define TIM_OCPreload_Enable ((uint16_t)0x0008) +#define TIM_OCPreload_Disable ((uint16_t)0x0000) +#define IS_TIM_OCPRELOAD_STATE(STATE) (((STATE) == TIM_OCPreload_Enable) || \ + ((STATE) == TIM_OCPreload_Disable)) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_Fast_State + * @{ + */ + +#define TIM_OCFast_Enable ((uint16_t)0x0004) +#define TIM_OCFast_Disable ((uint16_t)0x0000) +#define IS_TIM_OCFAST_STATE(STATE) (((STATE) == TIM_OCFast_Enable) || \ + ((STATE) == TIM_OCFast_Disable)) + +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_Clear_State + * @{ + */ + +#define TIM_OCClear_Enable ((uint16_t)0x0080) +#define TIM_OCClear_Disable ((uint16_t)0x0000) +#define IS_TIM_OCCLEAR_STATE(STATE) (((STATE) == TIM_OCClear_Enable) || \ + ((STATE) == TIM_OCClear_Disable)) +/** + * @} + */ + +/** @defgroup TIM_Trigger_Output_Source + * @{ + */ + +#define TIM_TRGOSource_Reset ((uint16_t)0x0000) +#define TIM_TRGOSource_Enable ((uint16_t)0x0010) +#define TIM_TRGOSource_Update ((uint16_t)0x0020) +#define TIM_TRGOSource_OC1 ((uint16_t)0x0030) +#define TIM_TRGOSource_OC1Ref ((uint16_t)0x0040) +#define TIM_TRGOSource_OC2Ref ((uint16_t)0x0050) +#define TIM_TRGOSource_OC3Ref ((uint16_t)0x0060) +#define TIM_TRGOSource_OC4Ref ((uint16_t)0x0070) +#define IS_TIM_TRGO_SOURCE(SOURCE) (((SOURCE) == TIM_TRGOSource_Reset) || \ + ((SOURCE) == TIM_TRGOSource_Enable) || \ + ((SOURCE) == TIM_TRGOSource_Update) || \ + ((SOURCE) == TIM_TRGOSource_OC1) || \ + ((SOURCE) == TIM_TRGOSource_OC1Ref) || \ + ((SOURCE) == TIM_TRGOSource_OC2Ref) || \ + ((SOURCE) == TIM_TRGOSource_OC3Ref) || \ + ((SOURCE) == TIM_TRGOSource_OC4Ref)) +/** + * @} + */ + +/** @defgroup TIM_Slave_Mode + * @{ + */ + +#define TIM_SlaveMode_Reset ((uint16_t)0x0004) +#define TIM_SlaveMode_Gated ((uint16_t)0x0005) +#define TIM_SlaveMode_Trigger ((uint16_t)0x0006) +#define TIM_SlaveMode_External1 ((uint16_t)0x0007) +#define IS_TIM_SLAVE_MODE(MODE) (((MODE) == TIM_SlaveMode_Reset) || \ + ((MODE) == TIM_SlaveMode_Gated) || \ + ((MODE) == TIM_SlaveMode_Trigger) || \ + ((MODE) == TIM_SlaveMode_External1)) +/** + * @} + */ + +/** @defgroup TIM_Master_Slave_Mode + * @{ + */ + +#define TIM_MasterSlaveMode_Enable ((uint16_t)0x0080) +#define TIM_MasterSlaveMode_Disable ((uint16_t)0x0000) +#define IS_TIM_MSM_STATE(STATE) (((STATE) == TIM_MasterSlaveMode_Enable) || \ + ((STATE) == TIM_MasterSlaveMode_Disable)) +/** + * @} + */ + +/** @defgroup TIM_Flags + * @{ + */ + +#define TIM_FLAG_Update ((uint16_t)0x0001) +#define TIM_FLAG_CC1 ((uint16_t)0x0002) +#define TIM_FLAG_CC2 ((uint16_t)0x0004) +#define TIM_FLAG_CC3 ((uint16_t)0x0008) +#define TIM_FLAG_CC4 ((uint16_t)0x0010) +#define TIM_FLAG_COM ((uint16_t)0x0020) +#define TIM_FLAG_Trigger ((uint16_t)0x0040) +#define TIM_FLAG_Break ((uint16_t)0x0080) +#define TIM_FLAG_CC1OF ((uint16_t)0x0200) +#define TIM_FLAG_CC2OF ((uint16_t)0x0400) +#define TIM_FLAG_CC3OF ((uint16_t)0x0800) +#define TIM_FLAG_CC4OF ((uint16_t)0x1000) +#define IS_TIM_GET_FLAG(FLAG) (((FLAG) == TIM_FLAG_Update) || \ + ((FLAG) == TIM_FLAG_CC1) || \ + ((FLAG) == TIM_FLAG_CC2) || \ + ((FLAG) == TIM_FLAG_CC3) || \ + ((FLAG) == TIM_FLAG_CC4) || \ + ((FLAG) == TIM_FLAG_COM) || \ + ((FLAG) == TIM_FLAG_Trigger) || \ + ((FLAG) == TIM_FLAG_Break) || \ + ((FLAG) == TIM_FLAG_CC1OF) || \ + ((FLAG) == TIM_FLAG_CC2OF) || \ + ((FLAG) == TIM_FLAG_CC3OF) || \ + ((FLAG) == TIM_FLAG_CC4OF)) + + +#define IS_TIM_CLEAR_FLAG(TIM_FLAG) ((((TIM_FLAG) & (uint16_t)0xE100) == 0x0000) && ((TIM_FLAG) != 0x0000)) +/** + * @} + */ + +/** @defgroup TIM_Input_Capture_Filer_Value + * @{ + */ + +#define IS_TIM_IC_FILTER(ICFILTER) ((ICFILTER) <= 0xF) +/** + * @} + */ + +/** @defgroup TIM_External_Trigger_Filter + * @{ + */ + +#define IS_TIM_EXT_FILTER(EXTFILTER) ((EXTFILTER) <= 0xF) +/** + * @} + */ + +/** @defgroup TIM_Legacy + * @{ + */ + +#define TIM_DMABurstLength_1Byte TIM_DMABurstLength_1Transfer +#define TIM_DMABurstLength_2Bytes TIM_DMABurstLength_2Transfers +#define TIM_DMABurstLength_3Bytes TIM_DMABurstLength_3Transfers +#define TIM_DMABurstLength_4Bytes TIM_DMABurstLength_4Transfers +#define TIM_DMABurstLength_5Bytes TIM_DMABurstLength_5Transfers +#define TIM_DMABurstLength_6Bytes TIM_DMABurstLength_6Transfers +#define TIM_DMABurstLength_7Bytes TIM_DMABurstLength_7Transfers +#define TIM_DMABurstLength_8Bytes TIM_DMABurstLength_8Transfers +#define TIM_DMABurstLength_9Bytes TIM_DMABurstLength_9Transfers +#define TIM_DMABurstLength_10Bytes TIM_DMABurstLength_10Transfers +#define TIM_DMABurstLength_11Bytes TIM_DMABurstLength_11Transfers +#define TIM_DMABurstLength_12Bytes TIM_DMABurstLength_12Transfers +#define TIM_DMABurstLength_13Bytes TIM_DMABurstLength_13Transfers +#define TIM_DMABurstLength_14Bytes TIM_DMABurstLength_14Transfers +#define TIM_DMABurstLength_15Bytes TIM_DMABurstLength_15Transfers +#define TIM_DMABurstLength_16Bytes TIM_DMABurstLength_16Transfers +#define TIM_DMABurstLength_17Bytes TIM_DMABurstLength_17Transfers +#define TIM_DMABurstLength_18Bytes TIM_DMABurstLength_18Transfers +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup TIM_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions + * @{ + */ + +void TIM_DeInit(TIM_TypeDef* TIMx); +void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); +void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); +void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); +void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); +void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); +void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct); +void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct); +void TIM_BDTRConfig(TIM_TypeDef* TIMx, TIM_BDTRInitTypeDef *TIM_BDTRInitStruct); +void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); +void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct); +void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct); +void TIM_BDTRStructInit(TIM_BDTRInitTypeDef* TIM_BDTRInitStruct); +void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState); +void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState); +void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState); +void TIM_GenerateEvent(TIM_TypeDef* TIMx, uint16_t TIM_EventSource); +void TIM_DMAConfig(TIM_TypeDef* TIMx, uint16_t TIM_DMABase, uint16_t TIM_DMABurstLength); +void TIM_DMACmd(TIM_TypeDef* TIMx, uint16_t TIM_DMASource, FunctionalState NewState); +void TIM_InternalClockConfig(TIM_TypeDef* TIMx); +void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource); +void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource, + uint16_t TIM_ICPolarity, uint16_t ICFilter); +void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter); +void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter); +void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter); +void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode); +void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode); +void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource); +void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode, + uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity); +void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction); +void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction); +void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction); +void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction); +void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState); +void TIM_SelectCOM(TIM_TypeDef* TIMx, FunctionalState NewState); +void TIM_SelectCCDMA(TIM_TypeDef* TIMx, FunctionalState NewState); +void TIM_CCPreloadControl(TIM_TypeDef* TIMx, FunctionalState NewState); +void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); +void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); +void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); +void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); +void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast); +void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast); +void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast); +void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast); +void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear); +void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear); +void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear); +void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear); +void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity); +void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity); +void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity); +void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity); +void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity); +void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity); +void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity); +void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx); +void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN); +void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode); +void TIM_UpdateDisableConfig(TIM_TypeDef* TIMx, FunctionalState NewState); +void TIM_UpdateRequestConfig(TIM_TypeDef* TIMx, uint16_t TIM_UpdateSource); +void TIM_SelectHallSensor(TIM_TypeDef* TIMx, FunctionalState NewState); +void TIM_SelectOnePulseMode(TIM_TypeDef* TIMx, uint16_t TIM_OPMode); +void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource); +void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode); +void TIM_SelectMasterSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_MasterSlaveMode); +void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter); +void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload); +void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1); +void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2); +void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3); +void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4); +void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC); +void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC); +void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC); +void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC); +void TIM_SetClockDivision(TIM_TypeDef* TIMx, uint16_t TIM_CKD); +uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx); +uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx); +uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx); +uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx); +uint16_t TIM_GetCounter(TIM_TypeDef* TIMx); +uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx); +FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG); +void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG); +ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT); +void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT); + +#ifdef __cplusplus +} +#endif + +#endif /*__STM32F10x_TIM_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_usart.c b/Library/stm32f10x_usart.c new file mode 100644 index 0000000..e794eae --- /dev/null +++ b/Library/stm32f10x_usart.c @@ -0,0 +1,1058 @@ +/** + ****************************************************************************** + * @file stm32f10x_usart.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the USART firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_usart.h" +#include "stm32f10x_rcc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup USART + * @brief USART driver modules + * @{ + */ + +/** @defgroup USART_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup USART_Private_Defines + * @{ + */ + +#define CR1_UE_Set ((uint16_t)0x2000) /*!< USART Enable Mask */ +#define CR1_UE_Reset ((uint16_t)0xDFFF) /*!< USART Disable Mask */ + +#define CR1_WAKE_Mask ((uint16_t)0xF7FF) /*!< USART WakeUp Method Mask */ + +#define CR1_RWU_Set ((uint16_t)0x0002) /*!< USART mute mode Enable Mask */ +#define CR1_RWU_Reset ((uint16_t)0xFFFD) /*!< USART mute mode Enable Mask */ +#define CR1_SBK_Set ((uint16_t)0x0001) /*!< USART Break Character send Mask */ +#define CR1_CLEAR_Mask ((uint16_t)0xE9F3) /*!< USART CR1 Mask */ +#define CR2_Address_Mask ((uint16_t)0xFFF0) /*!< USART address Mask */ + +#define CR2_LINEN_Set ((uint16_t)0x4000) /*!< USART LIN Enable Mask */ +#define CR2_LINEN_Reset ((uint16_t)0xBFFF) /*!< USART LIN Disable Mask */ + +#define CR2_LBDL_Mask ((uint16_t)0xFFDF) /*!< USART LIN Break detection Mask */ +#define CR2_STOP_CLEAR_Mask ((uint16_t)0xCFFF) /*!< USART CR2 STOP Bits Mask */ +#define CR2_CLOCK_CLEAR_Mask ((uint16_t)0xF0FF) /*!< USART CR2 Clock Mask */ + +#define CR3_SCEN_Set ((uint16_t)0x0020) /*!< USART SC Enable Mask */ +#define CR3_SCEN_Reset ((uint16_t)0xFFDF) /*!< USART SC Disable Mask */ + +#define CR3_NACK_Set ((uint16_t)0x0010) /*!< USART SC NACK Enable Mask */ +#define CR3_NACK_Reset ((uint16_t)0xFFEF) /*!< USART SC NACK Disable Mask */ + +#define CR3_HDSEL_Set ((uint16_t)0x0008) /*!< USART Half-Duplex Enable Mask */ +#define CR3_HDSEL_Reset ((uint16_t)0xFFF7) /*!< USART Half-Duplex Disable Mask */ + +#define CR3_IRLP_Mask ((uint16_t)0xFFFB) /*!< USART IrDA LowPower mode Mask */ +#define CR3_CLEAR_Mask ((uint16_t)0xFCFF) /*!< USART CR3 Mask */ + +#define CR3_IREN_Set ((uint16_t)0x0002) /*!< USART IrDA Enable Mask */ +#define CR3_IREN_Reset ((uint16_t)0xFFFD) /*!< USART IrDA Disable Mask */ +#define GTPR_LSB_Mask ((uint16_t)0x00FF) /*!< Guard Time Register LSB Mask */ +#define GTPR_MSB_Mask ((uint16_t)0xFF00) /*!< Guard Time Register MSB Mask */ +#define IT_Mask ((uint16_t)0x001F) /*!< USART Interrupt Mask */ + +/* USART OverSampling-8 Mask */ +#define CR1_OVER8_Set ((u16)0x8000) /* USART OVER8 mode Enable Mask */ +#define CR1_OVER8_Reset ((u16)0x7FFF) /* USART OVER8 mode Disable Mask */ + +/* USART One Bit Sampling Mask */ +#define CR3_ONEBITE_Set ((u16)0x0800) /* USART ONEBITE mode Enable Mask */ +#define CR3_ONEBITE_Reset ((u16)0xF7FF) /* USART ONEBITE mode Disable Mask */ + +/** + * @} + */ + +/** @defgroup USART_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USART_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USART_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup USART_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the USARTx peripheral registers to their default reset values. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @retval None + */ +void USART_DeInit(USART_TypeDef* USARTx) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + + if (USARTx == USART1) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, DISABLE); + } + else if (USARTx == USART2) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, DISABLE); + } + else if (USARTx == USART3) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART3, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART3, DISABLE); + } + else if (USARTx == UART4) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART4, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART4, DISABLE); + } + else + { + if (USARTx == UART5) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART5, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART5, DISABLE); + } + } +} + +/** + * @brief Initializes the USARTx peripheral according to the specified + * parameters in the USART_InitStruct . + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param USART_InitStruct: pointer to a USART_InitTypeDef structure + * that contains the configuration information for the specified USART + * peripheral. + * @retval None + */ +void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct) +{ + uint32_t tmpreg = 0x00, apbclock = 0x00; + uint32_t integerdivider = 0x00; + uint32_t fractionaldivider = 0x00; + uint32_t usartxbase = 0; + RCC_ClocksTypeDef RCC_ClocksStatus; + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_BAUDRATE(USART_InitStruct->USART_BaudRate)); + assert_param(IS_USART_WORD_LENGTH(USART_InitStruct->USART_WordLength)); + assert_param(IS_USART_STOPBITS(USART_InitStruct->USART_StopBits)); + assert_param(IS_USART_PARITY(USART_InitStruct->USART_Parity)); + assert_param(IS_USART_MODE(USART_InitStruct->USART_Mode)); + assert_param(IS_USART_HARDWARE_FLOW_CONTROL(USART_InitStruct->USART_HardwareFlowControl)); + /* The hardware flow control is available only for USART1, USART2 and USART3 */ + if (USART_InitStruct->USART_HardwareFlowControl != USART_HardwareFlowControl_None) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + + usartxbase = (uint32_t)USARTx; + +/*---------------------------- USART CR2 Configuration -----------------------*/ + tmpreg = USARTx->CR2; + /* Clear STOP[13:12] bits */ + tmpreg &= CR2_STOP_CLEAR_Mask; + /* Configure the USART Stop Bits, Clock, CPOL, CPHA and LastBit ------------*/ + /* Set STOP[13:12] bits according to USART_StopBits value */ + tmpreg |= (uint32_t)USART_InitStruct->USART_StopBits; + + /* Write to USART CR2 */ + USARTx->CR2 = (uint16_t)tmpreg; + +/*---------------------------- USART CR1 Configuration -----------------------*/ + tmpreg = USARTx->CR1; + /* Clear M, PCE, PS, TE and RE bits */ + tmpreg &= CR1_CLEAR_Mask; + /* Configure the USART Word Length, Parity and mode ----------------------- */ + /* Set the M bits according to USART_WordLength value */ + /* Set PCE and PS bits according to USART_Parity value */ + /* Set TE and RE bits according to USART_Mode value */ + tmpreg |= (uint32_t)USART_InitStruct->USART_WordLength | USART_InitStruct->USART_Parity | + USART_InitStruct->USART_Mode; + /* Write to USART CR1 */ + USARTx->CR1 = (uint16_t)tmpreg; + +/*---------------------------- USART CR3 Configuration -----------------------*/ + tmpreg = USARTx->CR3; + /* Clear CTSE and RTSE bits */ + tmpreg &= CR3_CLEAR_Mask; + /* Configure the USART HFC -------------------------------------------------*/ + /* Set CTSE and RTSE bits according to USART_HardwareFlowControl value */ + tmpreg |= USART_InitStruct->USART_HardwareFlowControl; + /* Write to USART CR3 */ + USARTx->CR3 = (uint16_t)tmpreg; + +/*---------------------------- USART BRR Configuration -----------------------*/ + /* Configure the USART Baud Rate -------------------------------------------*/ + RCC_GetClocksFreq(&RCC_ClocksStatus); + if (usartxbase == USART1_BASE) + { + apbclock = RCC_ClocksStatus.PCLK2_Frequency; + } + else + { + apbclock = RCC_ClocksStatus.PCLK1_Frequency; + } + + /* Determine the integer part */ + if ((USARTx->CR1 & CR1_OVER8_Set) != 0) + { + /* Integer part computing in case Oversampling mode is 8 Samples */ + integerdivider = ((25 * apbclock) / (2 * (USART_InitStruct->USART_BaudRate))); + } + else /* if ((USARTx->CR1 & CR1_OVER8_Set) == 0) */ + { + /* Integer part computing in case Oversampling mode is 16 Samples */ + integerdivider = ((25 * apbclock) / (4 * (USART_InitStruct->USART_BaudRate))); + } + tmpreg = (integerdivider / 100) << 4; + + /* Determine the fractional part */ + fractionaldivider = integerdivider - (100 * (tmpreg >> 4)); + + /* Implement the fractional part in the register */ + if ((USARTx->CR1 & CR1_OVER8_Set) != 0) + { + tmpreg |= ((((fractionaldivider * 8) + 50) / 100)) & ((uint8_t)0x07); + } + else /* if ((USARTx->CR1 & CR1_OVER8_Set) == 0) */ + { + tmpreg |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F); + } + + /* Write to USART BRR */ + USARTx->BRR = (uint16_t)tmpreg; +} + +/** + * @brief Fills each USART_InitStruct member with its default value. + * @param USART_InitStruct: pointer to a USART_InitTypeDef structure + * which will be initialized. + * @retval None + */ +void USART_StructInit(USART_InitTypeDef* USART_InitStruct) +{ + /* USART_InitStruct members default value */ + USART_InitStruct->USART_BaudRate = 9600; + USART_InitStruct->USART_WordLength = USART_WordLength_8b; + USART_InitStruct->USART_StopBits = USART_StopBits_1; + USART_InitStruct->USART_Parity = USART_Parity_No ; + USART_InitStruct->USART_Mode = USART_Mode_Rx | USART_Mode_Tx; + USART_InitStruct->USART_HardwareFlowControl = USART_HardwareFlowControl_None; +} + +/** + * @brief Initializes the USARTx peripheral Clock according to the + * specified parameters in the USART_ClockInitStruct . + * @param USARTx: where x can be 1, 2, 3 to select the USART peripheral. + * @param USART_ClockInitStruct: pointer to a USART_ClockInitTypeDef + * structure that contains the configuration information for the specified + * USART peripheral. + * @note The Smart Card and Synchronous modes are not available for UART4 and UART5. + * @retval None + */ +void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockInitStruct) +{ + uint32_t tmpreg = 0x00; + /* Check the parameters */ + assert_param(IS_USART_123_PERIPH(USARTx)); + assert_param(IS_USART_CLOCK(USART_ClockInitStruct->USART_Clock)); + assert_param(IS_USART_CPOL(USART_ClockInitStruct->USART_CPOL)); + assert_param(IS_USART_CPHA(USART_ClockInitStruct->USART_CPHA)); + assert_param(IS_USART_LASTBIT(USART_ClockInitStruct->USART_LastBit)); + +/*---------------------------- USART CR2 Configuration -----------------------*/ + tmpreg = USARTx->CR2; + /* Clear CLKEN, CPOL, CPHA and LBCL bits */ + tmpreg &= CR2_CLOCK_CLEAR_Mask; + /* Configure the USART Clock, CPOL, CPHA and LastBit ------------*/ + /* Set CLKEN bit according to USART_Clock value */ + /* Set CPOL bit according to USART_CPOL value */ + /* Set CPHA bit according to USART_CPHA value */ + /* Set LBCL bit according to USART_LastBit value */ + tmpreg |= (uint32_t)USART_ClockInitStruct->USART_Clock | USART_ClockInitStruct->USART_CPOL | + USART_ClockInitStruct->USART_CPHA | USART_ClockInitStruct->USART_LastBit; + /* Write to USART CR2 */ + USARTx->CR2 = (uint16_t)tmpreg; +} + +/** + * @brief Fills each USART_ClockInitStruct member with its default value. + * @param USART_ClockInitStruct: pointer to a USART_ClockInitTypeDef + * structure which will be initialized. + * @retval None + */ +void USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct) +{ + /* USART_ClockInitStruct members default value */ + USART_ClockInitStruct->USART_Clock = USART_Clock_Disable; + USART_ClockInitStruct->USART_CPOL = USART_CPOL_Low; + USART_ClockInitStruct->USART_CPHA = USART_CPHA_1Edge; + USART_ClockInitStruct->USART_LastBit = USART_LastBit_Disable; +} + +/** + * @brief Enables or disables the specified USART peripheral. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param NewState: new state of the USARTx peripheral. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected USART by setting the UE bit in the CR1 register */ + USARTx->CR1 |= CR1_UE_Set; + } + else + { + /* Disable the selected USART by clearing the UE bit in the CR1 register */ + USARTx->CR1 &= CR1_UE_Reset; + } +} + +/** + * @brief Enables or disables the specified USART interrupts. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param USART_IT: specifies the USART interrupt sources to be enabled or disabled. + * This parameter can be one of the following values: + * @arg USART_IT_CTS: CTS change interrupt (not available for UART4 and UART5) + * @arg USART_IT_LBD: LIN Break detection interrupt + * @arg USART_IT_TXE: Transmit Data Register empty interrupt + * @arg USART_IT_TC: Transmission complete interrupt + * @arg USART_IT_RXNE: Receive Data register not empty interrupt + * @arg USART_IT_IDLE: Idle line detection interrupt + * @arg USART_IT_PE: Parity Error interrupt + * @arg USART_IT_ERR: Error interrupt(Frame error, noise error, overrun error) + * @param NewState: new state of the specified USARTx interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState) +{ + uint32_t usartreg = 0x00, itpos = 0x00, itmask = 0x00; + uint32_t usartxbase = 0x00; + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_CONFIG_IT(USART_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + /* The CTS interrupt is not available for UART4 and UART5 */ + if (USART_IT == USART_IT_CTS) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + + usartxbase = (uint32_t)USARTx; + + /* Get the USART register index */ + usartreg = (((uint8_t)USART_IT) >> 0x05); + + /* Get the interrupt position */ + itpos = USART_IT & IT_Mask; + itmask = (((uint32_t)0x01) << itpos); + + if (usartreg == 0x01) /* The IT is in CR1 register */ + { + usartxbase += 0x0C; + } + else if (usartreg == 0x02) /* The IT is in CR2 register */ + { + usartxbase += 0x10; + } + else /* The IT is in CR3 register */ + { + usartxbase += 0x14; + } + if (NewState != DISABLE) + { + *(__IO uint32_t*)usartxbase |= itmask; + } + else + { + *(__IO uint32_t*)usartxbase &= ~itmask; + } +} + +/** + * @brief Enables or disables the USART’s DMA interface. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param USART_DMAReq: specifies the DMA request. + * This parameter can be any combination of the following values: + * @arg USART_DMAReq_Tx: USART DMA transmit request + * @arg USART_DMAReq_Rx: USART DMA receive request + * @param NewState: new state of the DMA Request sources. + * This parameter can be: ENABLE or DISABLE. + * @note The DMA mode is not available for UART5 except in the STM32 + * High density value line devices(STM32F10X_HD_VL). + * @retval None + */ +void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_DMAREQ(USART_DMAReq)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the DMA transfer for selected requests by setting the DMAT and/or + DMAR bits in the USART CR3 register */ + USARTx->CR3 |= USART_DMAReq; + } + else + { + /* Disable the DMA transfer for selected requests by clearing the DMAT and/or + DMAR bits in the USART CR3 register */ + USARTx->CR3 &= (uint16_t)~USART_DMAReq; + } +} + +/** + * @brief Sets the address of the USART node. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param USART_Address: Indicates the address of the USART node. + * @retval None + */ +void USART_SetAddress(USART_TypeDef* USARTx, uint8_t USART_Address) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_ADDRESS(USART_Address)); + + /* Clear the USART address */ + USARTx->CR2 &= CR2_Address_Mask; + /* Set the USART address node */ + USARTx->CR2 |= USART_Address; +} + +/** + * @brief Selects the USART WakeUp method. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param USART_WakeUp: specifies the USART wakeup method. + * This parameter can be one of the following values: + * @arg USART_WakeUp_IdleLine: WakeUp by an idle line detection + * @arg USART_WakeUp_AddressMark: WakeUp by an address mark + * @retval None + */ +void USART_WakeUpConfig(USART_TypeDef* USARTx, uint16_t USART_WakeUp) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_WAKEUP(USART_WakeUp)); + + USARTx->CR1 &= CR1_WAKE_Mask; + USARTx->CR1 |= USART_WakeUp; +} + +/** + * @brief Determines if the USART is in mute mode or not. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param NewState: new state of the USART mute mode. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void USART_ReceiverWakeUpCmd(USART_TypeDef* USARTx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the USART mute mode by setting the RWU bit in the CR1 register */ + USARTx->CR1 |= CR1_RWU_Set; + } + else + { + /* Disable the USART mute mode by clearing the RWU bit in the CR1 register */ + USARTx->CR1 &= CR1_RWU_Reset; + } +} + +/** + * @brief Sets the USART LIN Break detection length. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param USART_LINBreakDetectLength: specifies the LIN break detection length. + * This parameter can be one of the following values: + * @arg USART_LINBreakDetectLength_10b: 10-bit break detection + * @arg USART_LINBreakDetectLength_11b: 11-bit break detection + * @retval None + */ +void USART_LINBreakDetectLengthConfig(USART_TypeDef* USARTx, uint16_t USART_LINBreakDetectLength) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_LIN_BREAK_DETECT_LENGTH(USART_LINBreakDetectLength)); + + USARTx->CR2 &= CR2_LBDL_Mask; + USARTx->CR2 |= USART_LINBreakDetectLength; +} + +/** + * @brief Enables or disables the USART’s LIN mode. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param NewState: new state of the USART LIN mode. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void USART_LINCmd(USART_TypeDef* USARTx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the LIN mode by setting the LINEN bit in the CR2 register */ + USARTx->CR2 |= CR2_LINEN_Set; + } + else + { + /* Disable the LIN mode by clearing the LINEN bit in the CR2 register */ + USARTx->CR2 &= CR2_LINEN_Reset; + } +} + +/** + * @brief Transmits single data through the USARTx peripheral. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param Data: the data to transmit. + * @retval None + */ +void USART_SendData(USART_TypeDef* USARTx, uint16_t Data) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_DATA(Data)); + + /* Transmit Data */ + USARTx->DR = (Data & (uint16_t)0x01FF); +} + +/** + * @brief Returns the most recent received data by the USARTx peripheral. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @retval The received data. + */ +uint16_t USART_ReceiveData(USART_TypeDef* USARTx) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + + /* Receive Data */ + return (uint16_t)(USARTx->DR & (uint16_t)0x01FF); +} + +/** + * @brief Transmits break characters. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @retval None + */ +void USART_SendBreak(USART_TypeDef* USARTx) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + + /* Send break characters */ + USARTx->CR1 |= CR1_SBK_Set; +} + +/** + * @brief Sets the specified USART guard time. + * @param USARTx: where x can be 1, 2 or 3 to select the USART peripheral. + * @param USART_GuardTime: specifies the guard time. + * @note The guard time bits are not available for UART4 and UART5. + * @retval None + */ +void USART_SetGuardTime(USART_TypeDef* USARTx, uint8_t USART_GuardTime) +{ + /* Check the parameters */ + assert_param(IS_USART_123_PERIPH(USARTx)); + + /* Clear the USART Guard time */ + USARTx->GTPR &= GTPR_LSB_Mask; + /* Set the USART guard time */ + USARTx->GTPR |= (uint16_t)((uint16_t)USART_GuardTime << 0x08); +} + +/** + * @brief Sets the system clock prescaler. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param USART_Prescaler: specifies the prescaler clock. + * @note The function is used for IrDA mode with UART4 and UART5. + * @retval None + */ +void USART_SetPrescaler(USART_TypeDef* USARTx, uint8_t USART_Prescaler) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + + /* Clear the USART prescaler */ + USARTx->GTPR &= GTPR_MSB_Mask; + /* Set the USART prescaler */ + USARTx->GTPR |= USART_Prescaler; +} + +/** + * @brief Enables or disables the USART’s Smart Card mode. + * @param USARTx: where x can be 1, 2 or 3 to select the USART peripheral. + * @param NewState: new state of the Smart Card mode. + * This parameter can be: ENABLE or DISABLE. + * @note The Smart Card mode is not available for UART4 and UART5. + * @retval None + */ +void USART_SmartCardCmd(USART_TypeDef* USARTx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_USART_123_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the SC mode by setting the SCEN bit in the CR3 register */ + USARTx->CR3 |= CR3_SCEN_Set; + } + else + { + /* Disable the SC mode by clearing the SCEN bit in the CR3 register */ + USARTx->CR3 &= CR3_SCEN_Reset; + } +} + +/** + * @brief Enables or disables NACK transmission. + * @param USARTx: where x can be 1, 2 or 3 to select the USART peripheral. + * @param NewState: new state of the NACK transmission. + * This parameter can be: ENABLE or DISABLE. + * @note The Smart Card mode is not available for UART4 and UART5. + * @retval None + */ +void USART_SmartCardNACKCmd(USART_TypeDef* USARTx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_USART_123_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the NACK transmission by setting the NACK bit in the CR3 register */ + USARTx->CR3 |= CR3_NACK_Set; + } + else + { + /* Disable the NACK transmission by clearing the NACK bit in the CR3 register */ + USARTx->CR3 &= CR3_NACK_Reset; + } +} + +/** + * @brief Enables or disables the USART’s Half Duplex communication. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param NewState: new state of the USART Communication. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void USART_HalfDuplexCmd(USART_TypeDef* USARTx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the Half-Duplex mode by setting the HDSEL bit in the CR3 register */ + USARTx->CR3 |= CR3_HDSEL_Set; + } + else + { + /* Disable the Half-Duplex mode by clearing the HDSEL bit in the CR3 register */ + USARTx->CR3 &= CR3_HDSEL_Reset; + } +} + + +/** + * @brief Enables or disables the USART's 8x oversampling mode. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param NewState: new state of the USART one bit sampling method. + * This parameter can be: ENABLE or DISABLE. + * @note + * This function has to be called before calling USART_Init() + * function in order to have correct baudrate Divider value. + * @retval None + */ +void USART_OverSampling8Cmd(USART_TypeDef* USARTx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the 8x Oversampling mode by setting the OVER8 bit in the CR1 register */ + USARTx->CR1 |= CR1_OVER8_Set; + } + else + { + /* Disable the 8x Oversampling mode by clearing the OVER8 bit in the CR1 register */ + USARTx->CR1 &= CR1_OVER8_Reset; + } +} + +/** + * @brief Enables or disables the USART's one bit sampling method. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param NewState: new state of the USART one bit sampling method. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void USART_OneBitMethodCmd(USART_TypeDef* USARTx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the one bit method by setting the ONEBITE bit in the CR3 register */ + USARTx->CR3 |= CR3_ONEBITE_Set; + } + else + { + /* Disable tthe one bit method by clearing the ONEBITE bit in the CR3 register */ + USARTx->CR3 &= CR3_ONEBITE_Reset; + } +} + +/** + * @brief Configures the USART's IrDA interface. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param USART_IrDAMode: specifies the IrDA mode. + * This parameter can be one of the following values: + * @arg USART_IrDAMode_LowPower + * @arg USART_IrDAMode_Normal + * @retval None + */ +void USART_IrDAConfig(USART_TypeDef* USARTx, uint16_t USART_IrDAMode) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_IRDA_MODE(USART_IrDAMode)); + + USARTx->CR3 &= CR3_IRLP_Mask; + USARTx->CR3 |= USART_IrDAMode; +} + +/** + * @brief Enables or disables the USART's IrDA interface. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param NewState: new state of the IrDA mode. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void USART_IrDACmd(USART_TypeDef* USARTx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the IrDA mode by setting the IREN bit in the CR3 register */ + USARTx->CR3 |= CR3_IREN_Set; + } + else + { + /* Disable the IrDA mode by clearing the IREN bit in the CR3 register */ + USARTx->CR3 &= CR3_IREN_Reset; + } +} + +/** + * @brief Checks whether the specified USART flag is set or not. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param USART_FLAG: specifies the flag to check. + * This parameter can be one of the following values: + * @arg USART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5) + * @arg USART_FLAG_LBD: LIN Break detection flag + * @arg USART_FLAG_TXE: Transmit data register empty flag + * @arg USART_FLAG_TC: Transmission Complete flag + * @arg USART_FLAG_RXNE: Receive data register not empty flag + * @arg USART_FLAG_IDLE: Idle Line detection flag + * @arg USART_FLAG_ORE: OverRun Error flag + * @arg USART_FLAG_NE: Noise Error flag + * @arg USART_FLAG_FE: Framing Error flag + * @arg USART_FLAG_PE: Parity Error flag + * @retval The new state of USART_FLAG (SET or RESET). + */ +FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_FLAG(USART_FLAG)); + /* The CTS flag is not available for UART4 and UART5 */ + if (USART_FLAG == USART_FLAG_CTS) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + + if ((USARTx->SR & USART_FLAG) != (uint16_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the USARTx's pending flags. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param USART_FLAG: specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg USART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5). + * @arg USART_FLAG_LBD: LIN Break detection flag. + * @arg USART_FLAG_TC: Transmission Complete flag. + * @arg USART_FLAG_RXNE: Receive data register not empty flag. + * + * @note + * - PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun + * error) and IDLE (Idle line detected) flags are cleared by software + * sequence: a read operation to USART_SR register (USART_GetFlagStatus()) + * followed by a read operation to USART_DR register (USART_ReceiveData()). + * - RXNE flag can be also cleared by a read to the USART_DR register + * (USART_ReceiveData()). + * - TC flag can be also cleared by software sequence: a read operation to + * USART_SR register (USART_GetFlagStatus()) followed by a write operation + * to USART_DR register (USART_SendData()). + * - TXE flag is cleared only by a write to the USART_DR register + * (USART_SendData()). + * @retval None + */ +void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_CLEAR_FLAG(USART_FLAG)); + /* The CTS flag is not available for UART4 and UART5 */ + if ((USART_FLAG & USART_FLAG_CTS) == USART_FLAG_CTS) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + + USARTx->SR = (uint16_t)~USART_FLAG; +} + +/** + * @brief Checks whether the specified USART interrupt has occurred or not. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param USART_IT: specifies the USART interrupt source to check. + * This parameter can be one of the following values: + * @arg USART_IT_CTS: CTS change interrupt (not available for UART4 and UART5) + * @arg USART_IT_LBD: LIN Break detection interrupt + * @arg USART_IT_TXE: Tansmit Data Register empty interrupt + * @arg USART_IT_TC: Transmission complete interrupt + * @arg USART_IT_RXNE: Receive Data register not empty interrupt + * @arg USART_IT_IDLE: Idle line detection interrupt + * @arg USART_IT_ORE: OverRun Error interrupt + * @arg USART_IT_NE: Noise Error interrupt + * @arg USART_IT_FE: Framing Error interrupt + * @arg USART_IT_PE: Parity Error interrupt + * @retval The new state of USART_IT (SET or RESET). + */ +ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT) +{ + uint32_t bitpos = 0x00, itmask = 0x00, usartreg = 0x00; + ITStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_GET_IT(USART_IT)); + /* The CTS interrupt is not available for UART4 and UART5 */ + if (USART_IT == USART_IT_CTS) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + + /* Get the USART register index */ + usartreg = (((uint8_t)USART_IT) >> 0x05); + /* Get the interrupt position */ + itmask = USART_IT & IT_Mask; + itmask = (uint32_t)0x01 << itmask; + + if (usartreg == 0x01) /* The IT is in CR1 register */ + { + itmask &= USARTx->CR1; + } + else if (usartreg == 0x02) /* The IT is in CR2 register */ + { + itmask &= USARTx->CR2; + } + else /* The IT is in CR3 register */ + { + itmask &= USARTx->CR3; + } + + bitpos = USART_IT >> 0x08; + bitpos = (uint32_t)0x01 << bitpos; + bitpos &= USARTx->SR; + if ((itmask != (uint16_t)RESET)&&(bitpos != (uint16_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/** + * @brief Clears the USARTx's interrupt pending bits. + * @param USARTx: Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param USART_IT: specifies the interrupt pending bit to clear. + * This parameter can be one of the following values: + * @arg USART_IT_CTS: CTS change interrupt (not available for UART4 and UART5) + * @arg USART_IT_LBD: LIN Break detection interrupt + * @arg USART_IT_TC: Transmission complete interrupt. + * @arg USART_IT_RXNE: Receive Data register not empty interrupt. + * + * @note + * - PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun + * error) and IDLE (Idle line detected) pending bits are cleared by + * software sequence: a read operation to USART_SR register + * (USART_GetITStatus()) followed by a read operation to USART_DR register + * (USART_ReceiveData()). + * - RXNE pending bit can be also cleared by a read to the USART_DR register + * (USART_ReceiveData()). + * - TC pending bit can be also cleared by software sequence: a read + * operation to USART_SR register (USART_GetITStatus()) followed by a write + * operation to USART_DR register (USART_SendData()). + * - TXE pending bit is cleared only by a write to the USART_DR register + * (USART_SendData()). + * @retval None + */ +void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT) +{ + uint16_t bitpos = 0x00, itmask = 0x00; + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_CLEAR_IT(USART_IT)); + /* The CTS interrupt is not available for UART4 and UART5 */ + if (USART_IT == USART_IT_CTS) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + + bitpos = USART_IT >> 0x08; + itmask = ((uint16_t)0x01 << (uint16_t)bitpos); + USARTx->SR = (uint16_t)~itmask; +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_usart.h b/Library/stm32f10x_usart.h new file mode 100644 index 0000000..162fa87 --- /dev/null +++ b/Library/stm32f10x_usart.h @@ -0,0 +1,412 @@ +/** + ****************************************************************************** + * @file stm32f10x_usart.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the USART + * firmware library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_USART_H +#define __STM32F10x_USART_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup USART + * @{ + */ + +/** @defgroup USART_Exported_Types + * @{ + */ + +/** + * @brief USART Init Structure definition + */ + +typedef struct +{ + uint32_t USART_BaudRate; /*!< This member configures the USART communication baud rate. + The baud rate is computed using the following formula: + - IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate))) + - FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */ + + uint16_t USART_WordLength; /*!< Specifies the number of data bits transmitted or received in a frame. + This parameter can be a value of @ref USART_Word_Length */ + + uint16_t USART_StopBits; /*!< Specifies the number of stop bits transmitted. + This parameter can be a value of @ref USART_Stop_Bits */ + + uint16_t USART_Parity; /*!< Specifies the parity mode. + This parameter can be a value of @ref USART_Parity + @note When parity is enabled, the computed parity is inserted + at the MSB position of the transmitted data (9th bit when + the word length is set to 9 data bits; 8th bit when the + word length is set to 8 data bits). */ + + uint16_t USART_Mode; /*!< Specifies wether the Receive or Transmit mode is enabled or disabled. + This parameter can be a value of @ref USART_Mode */ + + uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled + or disabled. + This parameter can be a value of @ref USART_Hardware_Flow_Control */ +} USART_InitTypeDef; + +/** + * @brief USART Clock Init Structure definition + */ + +typedef struct +{ + + uint16_t USART_Clock; /*!< Specifies whether the USART clock is enabled or disabled. + This parameter can be a value of @ref USART_Clock */ + + uint16_t USART_CPOL; /*!< Specifies the steady state value of the serial clock. + This parameter can be a value of @ref USART_Clock_Polarity */ + + uint16_t USART_CPHA; /*!< Specifies the clock transition on which the bit capture is made. + This parameter can be a value of @ref USART_Clock_Phase */ + + uint16_t USART_LastBit; /*!< Specifies whether the clock pulse corresponding to the last transmitted + data bit (MSB) has to be output on the SCLK pin in synchronous mode. + This parameter can be a value of @ref USART_Last_Bit */ +} USART_ClockInitTypeDef; + +/** + * @} + */ + +/** @defgroup USART_Exported_Constants + * @{ + */ + +#define IS_USART_ALL_PERIPH(PERIPH) (((PERIPH) == USART1) || \ + ((PERIPH) == USART2) || \ + ((PERIPH) == USART3) || \ + ((PERIPH) == UART4) || \ + ((PERIPH) == UART5)) + +#define IS_USART_123_PERIPH(PERIPH) (((PERIPH) == USART1) || \ + ((PERIPH) == USART2) || \ + ((PERIPH) == USART3)) + +#define IS_USART_1234_PERIPH(PERIPH) (((PERIPH) == USART1) || \ + ((PERIPH) == USART2) || \ + ((PERIPH) == USART3) || \ + ((PERIPH) == UART4)) +/** @defgroup USART_Word_Length + * @{ + */ + +#define USART_WordLength_8b ((uint16_t)0x0000) +#define USART_WordLength_9b ((uint16_t)0x1000) + +#define IS_USART_WORD_LENGTH(LENGTH) (((LENGTH) == USART_WordLength_8b) || \ + ((LENGTH) == USART_WordLength_9b)) +/** + * @} + */ + +/** @defgroup USART_Stop_Bits + * @{ + */ + +#define USART_StopBits_1 ((uint16_t)0x0000) +#define USART_StopBits_0_5 ((uint16_t)0x1000) +#define USART_StopBits_2 ((uint16_t)0x2000) +#define USART_StopBits_1_5 ((uint16_t)0x3000) +#define IS_USART_STOPBITS(STOPBITS) (((STOPBITS) == USART_StopBits_1) || \ + ((STOPBITS) == USART_StopBits_0_5) || \ + ((STOPBITS) == USART_StopBits_2) || \ + ((STOPBITS) == USART_StopBits_1_5)) +/** + * @} + */ + +/** @defgroup USART_Parity + * @{ + */ + +#define USART_Parity_No ((uint16_t)0x0000) +#define USART_Parity_Even ((uint16_t)0x0400) +#define USART_Parity_Odd ((uint16_t)0x0600) +#define IS_USART_PARITY(PARITY) (((PARITY) == USART_Parity_No) || \ + ((PARITY) == USART_Parity_Even) || \ + ((PARITY) == USART_Parity_Odd)) +/** + * @} + */ + +/** @defgroup USART_Mode + * @{ + */ + +#define USART_Mode_Rx ((uint16_t)0x0004) +#define USART_Mode_Tx ((uint16_t)0x0008) +#define IS_USART_MODE(MODE) ((((MODE) & (uint16_t)0xFFF3) == 0x00) && ((MODE) != (uint16_t)0x00)) +/** + * @} + */ + +/** @defgroup USART_Hardware_Flow_Control + * @{ + */ +#define USART_HardwareFlowControl_None ((uint16_t)0x0000) +#define USART_HardwareFlowControl_RTS ((uint16_t)0x0100) +#define USART_HardwareFlowControl_CTS ((uint16_t)0x0200) +#define USART_HardwareFlowControl_RTS_CTS ((uint16_t)0x0300) +#define IS_USART_HARDWARE_FLOW_CONTROL(CONTROL)\ + (((CONTROL) == USART_HardwareFlowControl_None) || \ + ((CONTROL) == USART_HardwareFlowControl_RTS) || \ + ((CONTROL) == USART_HardwareFlowControl_CTS) || \ + ((CONTROL) == USART_HardwareFlowControl_RTS_CTS)) +/** + * @} + */ + +/** @defgroup USART_Clock + * @{ + */ +#define USART_Clock_Disable ((uint16_t)0x0000) +#define USART_Clock_Enable ((uint16_t)0x0800) +#define IS_USART_CLOCK(CLOCK) (((CLOCK) == USART_Clock_Disable) || \ + ((CLOCK) == USART_Clock_Enable)) +/** + * @} + */ + +/** @defgroup USART_Clock_Polarity + * @{ + */ + +#define USART_CPOL_Low ((uint16_t)0x0000) +#define USART_CPOL_High ((uint16_t)0x0400) +#define IS_USART_CPOL(CPOL) (((CPOL) == USART_CPOL_Low) || ((CPOL) == USART_CPOL_High)) + +/** + * @} + */ + +/** @defgroup USART_Clock_Phase + * @{ + */ + +#define USART_CPHA_1Edge ((uint16_t)0x0000) +#define USART_CPHA_2Edge ((uint16_t)0x0200) +#define IS_USART_CPHA(CPHA) (((CPHA) == USART_CPHA_1Edge) || ((CPHA) == USART_CPHA_2Edge)) + +/** + * @} + */ + +/** @defgroup USART_Last_Bit + * @{ + */ + +#define USART_LastBit_Disable ((uint16_t)0x0000) +#define USART_LastBit_Enable ((uint16_t)0x0100) +#define IS_USART_LASTBIT(LASTBIT) (((LASTBIT) == USART_LastBit_Disable) || \ + ((LASTBIT) == USART_LastBit_Enable)) +/** + * @} + */ + +/** @defgroup USART_Interrupt_definition + * @{ + */ + +#define USART_IT_PE ((uint16_t)0x0028) +#define USART_IT_TXE ((uint16_t)0x0727) +#define USART_IT_TC ((uint16_t)0x0626) +#define USART_IT_RXNE ((uint16_t)0x0525) +#define USART_IT_IDLE ((uint16_t)0x0424) +#define USART_IT_LBD ((uint16_t)0x0846) +#define USART_IT_CTS ((uint16_t)0x096A) +#define USART_IT_ERR ((uint16_t)0x0060) +#define USART_IT_ORE ((uint16_t)0x0360) +#define USART_IT_NE ((uint16_t)0x0260) +#define USART_IT_FE ((uint16_t)0x0160) +#define IS_USART_CONFIG_IT(IT) (((IT) == USART_IT_PE) || ((IT) == USART_IT_TXE) || \ + ((IT) == USART_IT_TC) || ((IT) == USART_IT_RXNE) || \ + ((IT) == USART_IT_IDLE) || ((IT) == USART_IT_LBD) || \ + ((IT) == USART_IT_CTS) || ((IT) == USART_IT_ERR)) +#define IS_USART_GET_IT(IT) (((IT) == USART_IT_PE) || ((IT) == USART_IT_TXE) || \ + ((IT) == USART_IT_TC) || ((IT) == USART_IT_RXNE) || \ + ((IT) == USART_IT_IDLE) || ((IT) == USART_IT_LBD) || \ + ((IT) == USART_IT_CTS) || ((IT) == USART_IT_ORE) || \ + ((IT) == USART_IT_NE) || ((IT) == USART_IT_FE)) +#define IS_USART_CLEAR_IT(IT) (((IT) == USART_IT_TC) || ((IT) == USART_IT_RXNE) || \ + ((IT) == USART_IT_LBD) || ((IT) == USART_IT_CTS)) +/** + * @} + */ + +/** @defgroup USART_DMA_Requests + * @{ + */ + +#define USART_DMAReq_Tx ((uint16_t)0x0080) +#define USART_DMAReq_Rx ((uint16_t)0x0040) +#define IS_USART_DMAREQ(DMAREQ) ((((DMAREQ) & (uint16_t)0xFF3F) == 0x00) && ((DMAREQ) != (uint16_t)0x00)) + +/** + * @} + */ + +/** @defgroup USART_WakeUp_methods + * @{ + */ + +#define USART_WakeUp_IdleLine ((uint16_t)0x0000) +#define USART_WakeUp_AddressMark ((uint16_t)0x0800) +#define IS_USART_WAKEUP(WAKEUP) (((WAKEUP) == USART_WakeUp_IdleLine) || \ + ((WAKEUP) == USART_WakeUp_AddressMark)) +/** + * @} + */ + +/** @defgroup USART_LIN_Break_Detection_Length + * @{ + */ + +#define USART_LINBreakDetectLength_10b ((uint16_t)0x0000) +#define USART_LINBreakDetectLength_11b ((uint16_t)0x0020) +#define IS_USART_LIN_BREAK_DETECT_LENGTH(LENGTH) \ + (((LENGTH) == USART_LINBreakDetectLength_10b) || \ + ((LENGTH) == USART_LINBreakDetectLength_11b)) +/** + * @} + */ + +/** @defgroup USART_IrDA_Low_Power + * @{ + */ + +#define USART_IrDAMode_LowPower ((uint16_t)0x0004) +#define USART_IrDAMode_Normal ((uint16_t)0x0000) +#define IS_USART_IRDA_MODE(MODE) (((MODE) == USART_IrDAMode_LowPower) || \ + ((MODE) == USART_IrDAMode_Normal)) +/** + * @} + */ + +/** @defgroup USART_Flags + * @{ + */ + +#define USART_FLAG_CTS ((uint16_t)0x0200) +#define USART_FLAG_LBD ((uint16_t)0x0100) +#define USART_FLAG_TXE ((uint16_t)0x0080) +#define USART_FLAG_TC ((uint16_t)0x0040) +#define USART_FLAG_RXNE ((uint16_t)0x0020) +#define USART_FLAG_IDLE ((uint16_t)0x0010) +#define USART_FLAG_ORE ((uint16_t)0x0008) +#define USART_FLAG_NE ((uint16_t)0x0004) +#define USART_FLAG_FE ((uint16_t)0x0002) +#define USART_FLAG_PE ((uint16_t)0x0001) +#define IS_USART_FLAG(FLAG) (((FLAG) == USART_FLAG_PE) || ((FLAG) == USART_FLAG_TXE) || \ + ((FLAG) == USART_FLAG_TC) || ((FLAG) == USART_FLAG_RXNE) || \ + ((FLAG) == USART_FLAG_IDLE) || ((FLAG) == USART_FLAG_LBD) || \ + ((FLAG) == USART_FLAG_CTS) || ((FLAG) == USART_FLAG_ORE) || \ + ((FLAG) == USART_FLAG_NE) || ((FLAG) == USART_FLAG_FE)) + +#define IS_USART_CLEAR_FLAG(FLAG) ((((FLAG) & (uint16_t)0xFC9F) == 0x00) && ((FLAG) != (uint16_t)0x00)) +#define IS_USART_PERIPH_FLAG(PERIPH, USART_FLAG) ((((*(uint32_t*)&(PERIPH)) != UART4_BASE) &&\ + ((*(uint32_t*)&(PERIPH)) != UART5_BASE)) \ + || ((USART_FLAG) != USART_FLAG_CTS)) +#define IS_USART_BAUDRATE(BAUDRATE) (((BAUDRATE) > 0) && ((BAUDRATE) < 0x0044AA21)) +#define IS_USART_ADDRESS(ADDRESS) ((ADDRESS) <= 0xF) +#define IS_USART_DATA(DATA) ((DATA) <= 0x1FF) + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup USART_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USART_Exported_Functions + * @{ + */ + +void USART_DeInit(USART_TypeDef* USARTx); +void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct); +void USART_StructInit(USART_InitTypeDef* USART_InitStruct); +void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockInitStruct); +void USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct); +void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState); +void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState); +void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState); +void USART_SetAddress(USART_TypeDef* USARTx, uint8_t USART_Address); +void USART_WakeUpConfig(USART_TypeDef* USARTx, uint16_t USART_WakeUp); +void USART_ReceiverWakeUpCmd(USART_TypeDef* USARTx, FunctionalState NewState); +void USART_LINBreakDetectLengthConfig(USART_TypeDef* USARTx, uint16_t USART_LINBreakDetectLength); +void USART_LINCmd(USART_TypeDef* USARTx, FunctionalState NewState); +void USART_SendData(USART_TypeDef* USARTx, uint16_t Data); +uint16_t USART_ReceiveData(USART_TypeDef* USARTx); +void USART_SendBreak(USART_TypeDef* USARTx); +void USART_SetGuardTime(USART_TypeDef* USARTx, uint8_t USART_GuardTime); +void USART_SetPrescaler(USART_TypeDef* USARTx, uint8_t USART_Prescaler); +void USART_SmartCardCmd(USART_TypeDef* USARTx, FunctionalState NewState); +void USART_SmartCardNACKCmd(USART_TypeDef* USARTx, FunctionalState NewState); +void USART_HalfDuplexCmd(USART_TypeDef* USARTx, FunctionalState NewState); +void USART_OverSampling8Cmd(USART_TypeDef* USARTx, FunctionalState NewState); +void USART_OneBitMethodCmd(USART_TypeDef* USARTx, FunctionalState NewState); +void USART_IrDAConfig(USART_TypeDef* USARTx, uint16_t USART_IrDAMode); +void USART_IrDACmd(USART_TypeDef* USARTx, FunctionalState NewState); +FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG); +void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG); +ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT); +void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F10x_USART_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_wwdg.c b/Library/stm32f10x_wwdg.c new file mode 100644 index 0000000..4a901e4 --- /dev/null +++ b/Library/stm32f10x_wwdg.c @@ -0,0 +1,224 @@ +/** + ****************************************************************************** + * @file stm32f10x_wwdg.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file provides all the WWDG firmware functions. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x_wwdg.h" +#include "stm32f10x_rcc.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @defgroup WWDG + * @brief WWDG driver modules + * @{ + */ + +/** @defgroup WWDG_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup WWDG_Private_Defines + * @{ + */ + +/* ----------- WWDG registers bit address in the alias region ----------- */ +#define WWDG_OFFSET (WWDG_BASE - PERIPH_BASE) + +/* Alias word address of EWI bit */ +#define CFR_OFFSET (WWDG_OFFSET + 0x04) +#define EWI_BitNumber 0x09 +#define CFR_EWI_BB (PERIPH_BB_BASE + (CFR_OFFSET * 32) + (EWI_BitNumber * 4)) + +/* --------------------- WWDG registers bit mask ------------------------ */ + +/* CR register bit mask */ +#define CR_WDGA_Set ((uint32_t)0x00000080) + +/* CFR register bit mask */ +#define CFR_WDGTB_Mask ((uint32_t)0xFFFFFE7F) +#define CFR_W_Mask ((uint32_t)0xFFFFFF80) +#define BIT_Mask ((uint8_t)0x7F) + +/** + * @} + */ + +/** @defgroup WWDG_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup WWDG_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup WWDG_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup WWDG_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the WWDG peripheral registers to their default reset values. + * @param None + * @retval None + */ +void WWDG_DeInit(void) +{ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_WWDG, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_WWDG, DISABLE); +} + +/** + * @brief Sets the WWDG Prescaler. + * @param WWDG_Prescaler: specifies the WWDG Prescaler. + * This parameter can be one of the following values: + * @arg WWDG_Prescaler_1: WWDG counter clock = (PCLK1/4096)/1 + * @arg WWDG_Prescaler_2: WWDG counter clock = (PCLK1/4096)/2 + * @arg WWDG_Prescaler_4: WWDG counter clock = (PCLK1/4096)/4 + * @arg WWDG_Prescaler_8: WWDG counter clock = (PCLK1/4096)/8 + * @retval None + */ +void WWDG_SetPrescaler(uint32_t WWDG_Prescaler) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_WWDG_PRESCALER(WWDG_Prescaler)); + /* Clear WDGTB[1:0] bits */ + tmpreg = WWDG->CFR & CFR_WDGTB_Mask; + /* Set WDGTB[1:0] bits according to WWDG_Prescaler value */ + tmpreg |= WWDG_Prescaler; + /* Store the new value */ + WWDG->CFR = tmpreg; +} + +/** + * @brief Sets the WWDG window value. + * @param WindowValue: specifies the window value to be compared to the downcounter. + * This parameter value must be lower than 0x80. + * @retval None + */ +void WWDG_SetWindowValue(uint8_t WindowValue) +{ + __IO uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_WWDG_WINDOW_VALUE(WindowValue)); + /* Clear W[6:0] bits */ + + tmpreg = WWDG->CFR & CFR_W_Mask; + + /* Set W[6:0] bits according to WindowValue value */ + tmpreg |= WindowValue & (uint32_t) BIT_Mask; + + /* Store the new value */ + WWDG->CFR = tmpreg; +} + +/** + * @brief Enables the WWDG Early Wakeup interrupt(EWI). + * @param None + * @retval None + */ +void WWDG_EnableIT(void) +{ + *(__IO uint32_t *) CFR_EWI_BB = (uint32_t)ENABLE; +} + +/** + * @brief Sets the WWDG counter value. + * @param Counter: specifies the watchdog counter value. + * This parameter must be a number between 0x40 and 0x7F. + * @retval None + */ +void WWDG_SetCounter(uint8_t Counter) +{ + /* Check the parameters */ + assert_param(IS_WWDG_COUNTER(Counter)); + /* Write to T[6:0] bits to configure the counter value, no need to do + a read-modify-write; writing a 0 to WDGA bit does nothing */ + WWDG->CR = Counter & BIT_Mask; +} + +/** + * @brief Enables WWDG and load the counter value. + * @param Counter: specifies the watchdog counter value. + * This parameter must be a number between 0x40 and 0x7F. + * @retval None + */ +void WWDG_Enable(uint8_t Counter) +{ + /* Check the parameters */ + assert_param(IS_WWDG_COUNTER(Counter)); + WWDG->CR = CR_WDGA_Set | Counter; +} + +/** + * @brief Checks whether the Early Wakeup interrupt flag is set or not. + * @param None + * @retval The new state of the Early Wakeup interrupt flag (SET or RESET) + */ +FlagStatus WWDG_GetFlagStatus(void) +{ + return (FlagStatus)(WWDG->SR); +} + +/** + * @brief Clears Early Wakeup interrupt flag. + * @param None + * @retval None + */ +void WWDG_ClearFlag(void) +{ + WWDG->SR = (uint32_t)RESET; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Library/stm32f10x_wwdg.h b/Library/stm32f10x_wwdg.h new file mode 100644 index 0000000..bdfa177 --- /dev/null +++ b/Library/stm32f10x_wwdg.h @@ -0,0 +1,115 @@ +/** + ****************************************************************************** + * @file stm32f10x_wwdg.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief This file contains all the functions prototypes for the WWDG firmware + * library. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_WWDG_H +#define __STM32F10x_WWDG_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/** @addtogroup STM32F10x_StdPeriph_Driver + * @{ + */ + +/** @addtogroup WWDG + * @{ + */ + +/** @defgroup WWDG_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @defgroup WWDG_Exported_Constants + * @{ + */ + +/** @defgroup WWDG_Prescaler + * @{ + */ + +#define WWDG_Prescaler_1 ((uint32_t)0x00000000) +#define WWDG_Prescaler_2 ((uint32_t)0x00000080) +#define WWDG_Prescaler_4 ((uint32_t)0x00000100) +#define WWDG_Prescaler_8 ((uint32_t)0x00000180) +#define IS_WWDG_PRESCALER(PRESCALER) (((PRESCALER) == WWDG_Prescaler_1) || \ + ((PRESCALER) == WWDG_Prescaler_2) || \ + ((PRESCALER) == WWDG_Prescaler_4) || \ + ((PRESCALER) == WWDG_Prescaler_8)) +#define IS_WWDG_WINDOW_VALUE(VALUE) ((VALUE) <= 0x7F) +#define IS_WWDG_COUNTER(COUNTER) (((COUNTER) >= 0x40) && ((COUNTER) <= 0x7F)) + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup WWDG_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup WWDG_Exported_Functions + * @{ + */ + +void WWDG_DeInit(void); +void WWDG_SetPrescaler(uint32_t WWDG_Prescaler); +void WWDG_SetWindowValue(uint8_t WindowValue); +void WWDG_EnableIT(void); +void WWDG_SetCounter(uint8_t Counter); +void WWDG_Enable(uint8_t Counter); +FlagStatus WWDG_GetFlagStatus(void); +void WWDG_ClearFlag(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F10x_WWDG_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Project.uvguix.Admin b/Project.uvguix.Admin new file mode 100644 index 0000000..a4374a5 --- /dev/null +++ b/Project.uvguix.Admin @@ -0,0 +1,1828 @@ + + + + -6.1 + +
### uVision Project, (C) Keil Software
+ + + + + + 38003 + Registers + 115 123 + + + 346 + Code Coverage + 665 160 + + + 204 + Performance Analyzer + 825 + + + + + + 1506 + Symbols + + 64 64 64 + + + 1936 + Watch 1 + + 64 64 64 + + + 1937 + Watch 2 + + 64 64 64 + + + 1935 + Call Stack + Locals + + 64 64 64 + + + 2506 + Trace Data + + 75 135 130 95 70 230 200 150 + + + 466 + Source Browser + 500 + 300 + + + + + + + + 1 + 1 + 0 + 0 + -1 + + + + + + + 44 + 2 + 3 + + -1 + -1 + + + -1 + -1 + + + 91 + 0 + 1170 + 816 + + + + 0 + + 274 + 0100000004000000010000000100000001000000010000000000000002000000000000000100000001000000000000002800000028000000010000000100000000000000010000004E453A5CBDCCB3CC5C53544D3332C8EBC3C5BDCCB3CC5CD7CAC1CF5CB3CCD0F2D4B4C2EB5C53544D333250726F6A6563745C392D3220B4AEBFDAB7A2CBCD2BBDD3CAD55C557365725C6D61696E2E6300000000066D61696E2E6300000000FFDC7800FFFFFFFF0100000010000000C5D4F200FFDC7800BECEA100F0A0A100BCA8E1009CC1B600F7B88600D9ADC200A5C2D700B3A6BE00EAD6A300F6FA7D00B5E99D005FC3CF00C1838300CACAD500010000000000000002000000FC000000660000000006000089020000 + + + + 0 + Build + + -1 + -1 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + AE0000004F000000F1030000B3000000 + + + 16 + AE00000066000000F1030000CA000000 + + + + 1005 + 1005 + 1 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 0300000066000000F500000059020000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 109 + 109 + 1 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 0300000066000000F500000059020000 + + + 16 + 2200000039000000EB000000C5010000 + + + + 1465 + 1465 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007C010000EE030000C2010000 + + + 16 + 22000000390000001A0200009B000000 + + + + 1466 + 1466 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007C010000EE030000C2010000 + + + 16 + 22000000390000001A0200009B000000 + + + + 1467 + 1467 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007C010000EE030000C2010000 + + + 16 + 22000000390000001A0200009B000000 + + + + 1468 + 1468 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007C010000EE030000C2010000 + + + 16 + 22000000390000001A0200009B000000 + + + + 1506 + 1506 + 0 + 0 + 0 + 0 + 32767 + 0 + 16384 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 1913 + 1913 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B100000066000000EE0300009A000000 + + + 16 + 22000000390000001A0200009B000000 + + + + 1935 + 1935 + 0 + 0 + 0 + 0 + 32767 + 0 + 32768 + 0 + + 16 + 030000007C010000EE030000C2010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 1936 + 1936 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007C010000EE030000C2010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 1937 + 1937 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007C010000EE030000C2010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 1939 + 1939 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007C010000EE030000C2010000 + + + 16 + 22000000390000001A0200009B000000 + + + + 1940 + 1940 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007C010000EE030000C2010000 + + + 16 + 22000000390000001A0200009B000000 + + + + 1941 + 1941 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007C010000EE030000C2010000 + + + 16 + 22000000390000001A0200009B000000 + + + + 1942 + 1942 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007C010000EE030000C2010000 + + + 16 + 22000000390000001A0200009B000000 + + + + 195 + 195 + 1 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 0300000066000000F500000059020000 + + + 16 + 2200000039000000EB000000C5010000 + + + + 196 + 196 + 1 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 0300000066000000F500000059020000 + + + 16 + 2200000039000000EB000000C5010000 + + + + 197 + 197 + 1 + 0 + 0 + 0 + 32767 + 0 + 32768 + 0 + + 16 + 000000008A0200000006000006030000 + + + 16 + 22000000390000001A0200009B000000 + + + + 198 + 198 + 0 + 0 + 0 + 0 + 32767 + 0 + 32768 + 0 + + 16 + 0000000065010000F1030000DB010000 + + + 16 + 22000000390000001A0200009B000000 + + + + 199 + 199 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000008D020000FD050000ED020000 + + + 16 + 22000000390000001A0200009B000000 + + + + 203 + 203 + 0 + 0 + 0 + 0 + 32767 + 0 + 8192 + 0 + + 16 + B100000066000000EE0300009A000000 + + + 16 + 22000000390000001A0200009B000000 + + + + 204 + 204 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B100000066000000EE0300009A000000 + + + 16 + 22000000390000001A0200009B000000 + + + + 221 + 221 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 00000000000000000000000000000000 + + + 16 + 0A0000000A0000006E0000006E000000 + + + + 2506 + 2506 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 2507 + 2507 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007C010000EE030000C2010000 + + + 16 + 22000000390000001A0200009B000000 + + + + 343 + 343 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B100000066000000EE0300009A000000 + + + 16 + 22000000390000001A0200009B000000 + + + + 346 + 346 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B100000066000000EE0300009A000000 + + + 16 + 22000000390000001A0200009B000000 + + + + 35824 + 35824 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B100000066000000EE0300009A000000 + + + 16 + 22000000390000001A0200009B000000 + + + + 35885 + 35885 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35886 + 35886 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35887 + 35887 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35888 + 35888 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35889 + 35889 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35890 + 35890 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35891 + 35891 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35892 + 35892 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35893 + 35893 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35894 + 35894 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35895 + 35895 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35896 + 35896 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35897 + 35897 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35898 + 35898 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35899 + 35899 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35900 + 35900 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35901 + 35901 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35902 + 35902 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35903 + 35903 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35904 + 35904 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 35905 + 35905 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 38003 + 38003 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 0300000066000000F500000059020000 + + + 16 + 2200000039000000EB000000C5010000 + + + + 38007 + 38007 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000008D020000FD050000ED020000 + + + 16 + 22000000390000001A0200009B000000 + + + + 436 + 436 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000008D020000FD050000ED020000 + + + 16 + 2200000039000000EB000000C5010000 + + + + 437 + 437 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007C010000EE030000C2010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 440 + 440 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007C010000EE030000C2010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 463 + 463 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000008D020000FD050000ED020000 + + + 16 + 2200000039000000EB000000C5010000 + + + + 466 + 466 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000008D020000FD050000ED020000 + + + 16 + 2200000039000000EB000000C5010000 + + + + 50000 + 50000 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50001 + 50001 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50002 + 50002 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50003 + 50003 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50004 + 50004 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50005 + 50005 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50006 + 50006 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50007 + 50007 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50008 + 50008 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50009 + 50009 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50010 + 50010 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50011 + 50011 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50012 + 50012 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50013 + 50013 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50014 + 50014 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50015 + 50015 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50016 + 50016 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50017 + 50017 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50018 + 50018 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 50019 + 50019 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 4A03000066000000EE0300005A010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 59392 + 59392 + 1 + 0 + 0 + 0 + 940 + 0 + 8192 + 0 + + 16 + 0000000000000000B70300001C000000 + + + 16 + 0A0000000A0000006E0000006E000000 + + + + 59393 + 0 + 1 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 00000000060300000006000019030000 + + + 16 + 0A0000000A0000006E0000006E000000 + + + + 59399 + 59399 + 1 + 0 + 0 + 0 + 463 + 0 + 8192 + 1 + + 16 + 000000001C000000DA01000038000000 + + + 16 + 0A0000000A0000006E0000006E000000 + + + + 59400 + 59400 + 0 + 0 + 0 + 0 + 612 + 0 + 8192 + 2 + + 16 + 00000000380000006F02000054000000 + + + 16 + 0A0000000A0000006E0000006E000000 + + + + 824 + 824 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007C010000EE030000C2010000 + + + 16 + 2200000039000000CC000000C8000000 + + + + 3236 + 000000000B000000000000000020000000000000FFFFFFFFFFFFFFFFAE000000B3000000F1030000B7000000000000000100000004000000010000000000000000000000FFFFFFFF06000000CB00000057010000CC000000F08B00005A01000079070000FFFF02000B004354616262656450616E650020000000000000AE00000066000000F1030000CA000000AE0000004F000000F1030000B30000000000000040280046060000000B446973617373656D626C7900000000CB00000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A6572000000005701000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A657200000000CC00000001000000FFFFFFFFFFFFFFFF0E4C6F67696320416E616C797A657200000000F08B000001000000FFFFFFFFFFFFFFFF0D436F646520436F766572616765000000005A01000001000000FFFFFFFFFFFFFFFF11496E737472756374696F6E205472616365000000007907000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFCB00000001000000FFFFFFFFCB000000000000000040000000000000FFFFFFFFFFFFFFFF430300004F0000004703000073010000000000000200000004000000010000000000000000000000FFFFFFFF2B000000E2050000CA0900002D8C00002E8C00002F8C0000308C0000318C0000328C0000338C0000348C0000358C0000368C0000378C0000388C0000398C00003A8C00003B8C00003C8C00003D8C00003E8C00003F8C0000408C0000418C000050C3000051C3000052C3000053C3000054C3000055C3000056C3000057C3000058C3000059C300005AC300005BC300005CC300005DC300005EC300005FC3000060C3000061C3000062C3000063C30000018000400000000000004703000066000000F10300008A010000470300004F000000F10300007301000000000000404100462B0000000753796D626F6C7300000000E205000001000000FFFFFFFFFFFFFFFF0A5472616365204461746100000000CA09000001000000FFFFFFFFFFFFFFFF00000000002D8C000001000000FFFFFFFFFFFFFFFF00000000002E8C000001000000FFFFFFFFFFFFFFFF00000000002F8C000001000000FFFFFFFFFFFFFFFF0000000000308C000001000000FFFFFFFFFFFFFFFF0000000000318C000001000000FFFFFFFFFFFFFFFF0000000000328C000001000000FFFFFFFFFFFFFFFF0000000000338C000001000000FFFFFFFFFFFFFFFF0000000000348C000001000000FFFFFFFFFFFFFFFF0000000000358C000001000000FFFFFFFFFFFFFFFF0000000000368C000001000000FFFFFFFFFFFFFFFF0000000000378C000001000000FFFFFFFFFFFFFFFF0000000000388C000001000000FFFFFFFFFFFFFFFF0000000000398C000001000000FFFFFFFFFFFFFFFF00000000003A8C000001000000FFFFFFFFFFFFFFFF00000000003B8C000001000000FFFFFFFFFFFFFFFF00000000003C8C000001000000FFFFFFFFFFFFFFFF00000000003D8C000001000000FFFFFFFFFFFFFFFF00000000003E8C000001000000FFFFFFFFFFFFFFFF00000000003F8C000001000000FFFFFFFFFFFFFFFF0000000000408C000001000000FFFFFFFFFFFFFFFF0000000000418C000001000000FFFFFFFFFFFFFFFF000000000050C3000001000000FFFFFFFFFFFFFFFF000000000051C3000001000000FFFFFFFFFFFFFFFF000000000052C3000001000000FFFFFFFFFFFFFFFF000000000053C3000001000000FFFFFFFFFFFFFFFF000000000054C3000001000000FFFFFFFFFFFFFFFF000000000055C3000001000000FFFFFFFFFFFFFFFF000000000056C3000001000000FFFFFFFFFFFFFFFF000000000057C3000001000000FFFFFFFFFFFFFFFF000000000058C3000001000000FFFFFFFFFFFFFFFF000000000059C3000001000000FFFFFFFFFFFFFFFF00000000005AC3000001000000FFFFFFFFFFFFFFFF00000000005BC3000001000000FFFFFFFFFFFFFFFF00000000005CC3000001000000FFFFFFFFFFFFFFFF00000000005DC3000001000000FFFFFFFFFFFFFFFF00000000005EC3000001000000FFFFFFFFFFFFFFFF00000000005FC3000001000000FFFFFFFFFFFFFFFF000000000060C3000001000000FFFFFFFFFFFFFFFF000000000061C3000001000000FFFFFFFFFFFFFFFF000000000062C3000001000000FFFFFFFFFFFFFFFF000000000063C3000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFE205000001000000FFFFFFFFE2050000000000000010000001000000FFFFFFFFFFFFFFFFF80000004F000000FC000000720200000100000002000010040000000100000038FFFFFF83040000FFFFFFFF05000000ED0300006D000000C3000000C400000073940000018000100000010000000000000066000000F800000089020000000000004F000000F8000000720200000000000040410056050000000750726F6A65637401000000ED03000001000000FFFFFFFFFFFFFFFF05426F6F6B73010000006D00000001000000FFFFFFFFFFFFFFFF0946756E6374696F6E7301000000C300000001000000FFFFFFFFFFFFFFFF0954656D706C6174657301000000C400000001000000FFFFFFFFFFFFFFFF09526567697374657273000000007394000001000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000001000000FFFFFFFFED03000001000000FFFFFFFFED030000000000000080000000000000FFFFFFFFFFFFFFFF0000000061010000F10300006501000000000000010000000400000001000000000000000000000000000000000000000000000001000000C6000000FFFFFFFF0F0000008F070000930700009407000095070000960700009007000091070000B5010000B801000038030000B9050000BA050000BB050000BC050000CB09000001800080000000000000000000007C010000F1030000F20100000000000065010000F1030000DB01000000000000404100460F0000001343616C6C20537461636B202B204C6F63616C73000000008F07000001000000FFFFFFFFFFFFFFFF0755415254202331000000009307000001000000FFFFFFFFFFFFFFFF0755415254202332000000009407000001000000FFFFFFFFFFFFFFFF0755415254202333000000009507000001000000FFFFFFFFFFFFFFFF15446562756720287072696E74662920566965776572000000009607000001000000FFFFFFFFFFFFFFFF0757617463682031000000009007000001000000FFFFFFFFFFFFFFFF0757617463682032000000009107000001000000FFFFFFFFFFFFFFFF10547261636520457863657074696F6E7300000000B501000001000000FFFFFFFFFFFFFFFF0E4576656E7420436F756E7465727300000000B801000001000000FFFFFFFFFFFFFFFF09554C494E4B706C7573000000003803000001000000FFFFFFFFFFFFFFFF084D656D6F7279203100000000B905000001000000FFFFFFFFFFFFFFFF084D656D6F7279203200000000BA05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203300000000BB05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203400000000BC05000001000000FFFFFFFFFFFFFFFF105472616365204E617669676174696F6E00000000CB09000001000000FFFFFFFFFFFFFFFFFFFFFFFF0000000001000000000000000000000001000000FFFFFFFFF901000065010000FD010000DB01000000000000020000000400000000000000000000000000000000000000000000000000000002000000C6000000FFFFFFFF8F07000001000000FFFFFFFF8F07000001000000C6000000000000000080000001000000FFFFFFFFFFFFFFFF000000007202000000060000760200000100000001000010040000000100000004FEFFFF62000000FFFFFFFF06000000C5000000C7000000B4010000D2010000CF0100007794000001800080000001000000000000008D020000000600001D030000000000007602000000060000060300000000000040820056060000000C4275696C64204F757470757401000000C500000001000000FFFFFFFFFFFFFFFF0D46696E6420496E2046696C657300000000C700000001000000FFFFFFFFFFFFFFFF0A4572726F72204C69737400000000B401000001000000FFFFFFFFFFFFFFFF0E536F757263652042726F7773657200000000D201000001000000FFFFFFFFFFFFFFFF1346696E6420416C6C205265666572656E63657300000000CF01000001000000FFFFFFFFFFFFFFFF0742726F77736572000000007794000001000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000001000000FFFFFFFFC500000001000000FFFFFFFFC5000000000000000000000000000000 + + + 59392 + File + + 2002 + 00200000010000002800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000000020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000040004000000000000000000000000000000000100000001000000018022E100000000040005000000000000000000000000000000000100000001000000018025E10000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000004000700000000000000000000000000000000010000000100000001802CE10000000004000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000004000900000000000000000000000000000000010000000100000001807B8A0000000004000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000000000B000000000000000000000000000000000100000001000000018015B10000000004000C0000000000000000000000000000000001000000010000000180F4B00000000004000D000000000000000000000000000000000100000001000000018036B10000000004000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF88000000000400460000000000000000000000000000000001000000010000000180FE880000000004004500000000000000000000000000000000010000000100000001800B810000000004001300000000000000000000000000000000010000000100000001800C810000000004001400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F0880000020000000F000000000000000000000000000000000100000001000000FFFF0100120043555646696E64436F6D626F427574746F6EE803000000000000000000000000000000000000000000000001000000010000009600000002002050000000000096000000000000000000018024E10000000000001100000000000000000000000000000000010000000100000001800A810000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018022800000020000001500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000000160000000000000000000000000000000001000000010000000180C988000000000400180000000000000000000000000000000001000000010000000180C788000000000000190000000000000000000000000000000001000000010000000180C8880000000000001700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E4C010000020001001A0000000F2650726F6A6563742057696E646F77000000000000000000000000010000000100000000000000000000000100000008002880DD880000000000001A0000000750726F6A656374000000000000000000000000010000000100000000000000000000000100000000002880DC8B0000000000003A00000005426F6F6B73000000000000000000000000010000000100000000000000000000000100000000002880E18B0000000000003B0000000946756E6374696F6E73000000000000000000000000010000000100000000000000000000000100000000002880E28B000000000000400000000954656D706C6174657300000000000000000000000001000000010000000000000000000000010000000000288018890000000000003D0000000E536F757263652042726F777365720000000000000000000000000100000001000000000000000000000001000000000028800000000000000400FFFFFFFF00000000000000000001000000000000000100000000000000000000000100000000002880D988000000000000390000000C4275696C64204F7574707574000000000000000000000000010000000100000000000000000000000100000000002880E38B000000000000410000000B46696E64204F75747075740000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001B000000000000000000000000000000000100000001000000000000000446696C65AC030000 + + + 1423 + 2800FFFF01001100434D4643546F6F6C426172427574746F6E00E1000000000000FFFFFFFF000100000000000000010000000000000001000000018001E1000000000000FFFFFFFF000100000000000000010000000000000001000000018003E1000000000000FFFFFFFF0001000000000000000100000000000000010000000180CD7F000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF000000000000000000010000000000000001000000018023E1000000000000FFFFFFFF000100000000000000010000000000000001000000018022E1000000000000FFFFFFFF000100000000000000010000000000000001000000018025E1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001802BE1000000000000FFFFFFFF00010000000000000001000000000000000100000001802CE1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001807A8A000000000000FFFFFFFF00010000000000000001000000000000000100000001807B8A000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180D3B0000000000000FFFFFFFF000100000000000000010000000000000001000000018015B1000000000000FFFFFFFF0001000000000000000100000000000000010000000180F4B0000000000000FFFFFFFF000100000000000000010000000000000001000000018036B1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180FF88000000000000FFFFFFFF0001000000000000000100000000000000010000000180FE88000000000000FFFFFFFF00010000000000000001000000000000000100000001800B81000000000000FFFFFFFF00010000000000000001000000000000000100000001800C81000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180F088000000000000FFFFFFFF0001000000000000000100000000000000010000000180EE7F000000000000FFFFFFFF000100000000000000010000000000000001000000018024E1000000000000FFFFFFFF00010000000000000001000000000000000100000001800A81000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001802280000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180C488000000000000FFFFFFFF0001000000000000000100000000000000010000000180C988000000000000FFFFFFFF0001000000000000000100000000000000010000000180C788000000000000FFFFFFFF0001000000000000000100000000000000010000000180C888000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180DD88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180FB7F000000000000FFFFFFFF000100000000000000010000000000000001000000 + + + 1423 + 2800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000000020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000000004000000000000000000000000000000000100000001000000018022E100000000000005000000000000000000000000000000000100000001000000018025E10000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000000000700000000000000000000000000000000010000000100000001802CE10000000000000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000000000900000000000000000000000000000000010000000100000001807B8A0000000000000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000000000B000000000000000000000000000000000100000001000000018015B10000000000000C0000000000000000000000000000000001000000010000000180F4B00000000000000D000000000000000000000000000000000100000001000000018036B10000000000000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF880000000000000F0000000000000000000000000000000001000000010000000180FE880000000000001000000000000000000000000000000000010000000100000001800B810000000000001100000000000000000000000000000000010000000100000001800C810000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F088000000000000130000000000000000000000000000000001000000010000000180EE7F00000000000014000000000000000000000000000000000100000001000000018024E10000000000001500000000000000000000000000000000010000000100000001800A810000000000001600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018022800000000000001700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000000180000000000000000000000000000000001000000010000000180C988000000000000190000000000000000000000000000000001000000010000000180C7880000000000001A0000000000000000000000000000000001000000010000000180C8880000000000001B00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180DD880000000000001C00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001D000000000000000000000000000000000100000001000000 + + + + 59399 + Build + + 678 + 00200000010000001000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F0000000000001C0000000000000000000000000000000001000000010000000180D07F0000000000001D000000000000000000000000000000000100000001000000018030800000000000001E00000000000000000000000000000000010000000100000001809E8A0000000000001F0000000000000000000000000000000001000000010000000180D17F0000000004002000000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001804C8A0000000000002100000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001900434D4643546F6F6C426172436F6D626F426F78427574746F6EBA000000000000000000000000000000000000000000000000010000000100000096000000030020500000000008546172676574203196000000000000000100085461726765742031000000000180EB880000000000002200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C07F000000000000230000000000000000000000000000000001000000010000000180B08A000000000400240000000000000000000000000000000001000000010000000180A8010000000000004E00000000000000000000000000000000010000000100000001807202000000000000530000000000000000000000000000000001000000010000000180BE010000000000005000000000000000000000000000000000010000000100000000000000054275696C64CF010000 + + + 583 + 1000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F000000000000FFFFFFFF0001000000000000000100000000000000010000000180D07F000000000000FFFFFFFF00010000000000000001000000000000000100000001803080000000000000FFFFFFFF00010000000000000001000000000000000100000001809E8A000000000000FFFFFFFF0001000000000000000100000000000000010000000180D17F000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001804C8A000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001806680000000000000FFFFFFFF0001000000000000000100000000000000010000000180EB88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180C07F000000000000FFFFFFFF0001000000000000000100000000000000010000000180B08A000000000000FFFFFFFF0001000000000000000100000000000000010000000180A801000000000000FFFFFFFF00010000000000000001000000000000000100000001807202000000000000FFFFFFFF0001000000000000000100000000000000010000000180BE01000000000000FFFFFFFF000100000000000000010000000000000001000000 + + + 583 + 1000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F000000000000000000000000000000000000000000000001000000010000000180D07F00000000000001000000000000000000000000000000000100000001000000018030800000000000000200000000000000000000000000000000010000000100000001809E8A000000000000030000000000000000000000000000000001000000010000000180D17F0000000000000400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001804C8A0000000000000500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001806680000000000000060000000000000000000000000000000001000000010000000180EB880000000000000700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C07F000000000000080000000000000000000000000000000001000000010000000180B08A000000000000090000000000000000000000000000000001000000010000000180A8010000000000000A000000000000000000000000000000000100000001000000018072020000000000000B0000000000000000000000000000000001000000010000000180BE010000000000000C000000000000000000000000000000000100000001000000 + + + + 59400 + Debug + + 2373 + 00200000000000001900FFFF01001100434D4643546F6F6C426172427574746F6ECC880000000000002500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018017800000000000002600000000000000000000000000000000010000000100000001801D800000000000002700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001801A800000000000002800000000000000000000000000000000010000000100000001801B80000000000000290000000000000000000000000000000001000000010000000180E57F0000000000002A00000000000000000000000000000000010000000100000001801C800000000000002B00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018000890000000000002C00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180E48B0000000000002D0000000000000000000000000000000001000000010000000180F07F0000000000002E0000000000000000000000000000000001000000010000000180E8880000000000003700000000000000000000000000000000010000000100000001803B010000000000002F0000000000000000000000000000000001000000010000000180BB8A00000000000030000000000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E0E01000000000000310000000D57617463682057696E646F7773000000000000000000000000010000000100000000000000000000000100000003001380D88B00000000000031000000085761746368202631000000000000000000000000010000000100000000000000000000000100000000001380D98B00000000000031000000085761746368202632000000000000000000000000010000000100000000000000000000000100000000001380CE01000000000000FFFFFFFF0C576174636820416E63686F720100000000000000010000000000000001000000000000000000000001000000000013800F01000000000000320000000E4D656D6F72792057696E646F7773000000000000000000000000010000000100000000000000000000000100000004001380D28B00000000000032000000094D656D6F7279202631000000000000000000000000010000000100000000000000000000000100000000001380D38B00000000000032000000094D656D6F7279202632000000000000000000000000010000000100000000000000000000000100000000001380D48B00000000000032000000094D656D6F7279202633000000000000000000000000010000000100000000000000000000000100000000001380D58B00000000000032000000094D656D6F72792026340000000000000000000000000100000001000000000000000000000001000000000013801001000000000000330000000E53657269616C2057696E646F77730000000000000000000000000100000001000000000000000000000001000000040013809307000000000000330000000855415254202326310000000000000000000000000100000001000000000000000000000001000000000013809407000000000000330000000855415254202326320000000000000000000000000100000001000000000000000000000001000000000013809507000000000000330000000855415254202326330000000000000000000000000100000001000000000000000000000001000000000013809607000000000000330000001626446562756720287072696E746629205669657765720000000000000000000000000100000001000000000000000000000001000000000013803C010000000000003400000010416E616C797369732057696E646F7773000000000000000000000000010000000100000000000000000000000100000004001380658A000000000000340000000F264C6F67696320416E616C797A6572000000000000000000000000010000000100000000000000000000000100000000001380DC7F0000000000003E0000001526506572666F726D616E636520416E616C797A6572000000000000000000000000010000000100000000000000000000000100000000001380E788000000000000380000000E26436F646520436F766572616765000000000000000000000000010000000100000000000000000000000100000000001380CD01000000000000FFFFFFFF0F416E616C7973697320416E63686F7201000000000000000100000000000000010000000000000000000000010000000000138053010000000000003F0000000D54726163652057696E646F77730000000000000000000000000100000001000000000000000000000001000000010013805401000000000000FFFFFFFF115472616365204D656E7520416E63686F720100000000000000010000000000000001000000000000000000000001000000000013802901000000000000350000001553797374656D205669657765722057696E646F77730000000000000000000000000100000001000000000000000000000001000000010013804B01000000000000FFFFFFFF1453797374656D2056696577657220416E63686F720100000000000000010000000000000001000000000000000000000001000000000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000013800189000000000000360000000F26546F6F6C626F782057696E646F7700000000000000000000000001000000010000000000000000000000010000000300138044C5000000000000FFFFFFFF0E5570646174652057696E646F77730100000000000000010000000000000001000000000000000000000001000000000013800000000000000400FFFFFFFF000000000000000000010000000000000001000000000000000000000001000000000013805B01000000000000FFFFFFFF12546F6F6C626F78204D656E75416E63686F72010000000000000001000000000000000100000000000000000000000100000000000000000005446562756764020000 + + + 898 + 1900FFFF01001100434D4643546F6F6C426172427574746F6ECC88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001801780000000000000FFFFFFFF00010000000000000001000000000000000100000001801D80000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001801A80000000000000FFFFFFFF00010000000000000001000000000000000100000001801B80000000000000FFFFFFFF0001000000000000000100000000000000010000000180E57F000000000000FFFFFFFF00010000000000000001000000000000000100000001801C80000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001800089000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180E48B000000000000FFFFFFFF0001000000000000000100000000000000010000000180F07F000000000000FFFFFFFF0001000000000000000100000000000000010000000180E888000000000000FFFFFFFF00010000000000000001000000000000000100000001803B01000000000000FFFFFFFF0001000000000000000100000000000000010000000180BB8A000000000000FFFFFFFF0001000000000000000100000000000000010000000180D88B000000000000FFFFFFFF0001000000000000000100000000000000010000000180D28B000000000000FFFFFFFF00010000000000000001000000000000000100000001809307000000000000FFFFFFFF0001000000000000000100000000000000010000000180658A000000000000FFFFFFFF0001000000000000000100000000000000010000000180C18A000000000000FFFFFFFF0001000000000000000100000000000000010000000180EE8B000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001800189000000000000FFFFFFFF000100000000000000010000000000000001000000 + + + 898 + 1900FFFF01001100434D4643546F6F6C426172427574746F6ECC880000000000000000000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018017800000000000000100000000000000000000000000000000010000000100000001801D800000000000000200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001801A800000000000000300000000000000000000000000000000010000000100000001801B80000000000000040000000000000000000000000000000001000000010000000180E57F0000000000000500000000000000000000000000000000010000000100000001801C800000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018000890000000000000700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180E48B000000000000080000000000000000000000000000000001000000010000000180F07F000000000000090000000000000000000000000000000001000000010000000180E8880000000000000A00000000000000000000000000000000010000000100000001803B010000000000000B0000000000000000000000000000000001000000010000000180BB8A0000000000000C0000000000000000000000000000000001000000010000000180D88B0000000000000D0000000000000000000000000000000001000000010000000180D28B0000000000000E000000000000000000000000000000000100000001000000018093070000000000000F0000000000000000000000000000000001000000010000000180658A000000000000100000000000000000000000000000000001000000010000000180C18A000000000000110000000000000000000000000000000001000000010000000180EE8B0000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180018900000000000013000000000000000000000000000000000100000001000000 + + + + 0 + 1536 + 864 + + + + + + 1 + 0 + + 100 + 0 + + .\User\main.c + 0 + 4 + 17 + 1 + + 0 + + + + +
diff --git a/Project.uvguix.yzfh b/Project.uvguix.yzfh new file mode 100644 index 0000000..f3e0159 --- /dev/null +++ b/Project.uvguix.yzfh @@ -0,0 +1,3609 @@ + + + + -6.1 + +
### uVision Project, (C) Keil Software
+ + + + + + 38003 + Registers + 115 67 + + + 346 + Code Coverage + 770 160 + + + 204 + Performance Analyzer + 930 + + + + + + 1506 + Symbols + + 64 64 64 + + + 1936 + Watch 1 + + 200 133 133 + + + 1937 + Watch 2 + + 200 133 133 + + + 1935 + Call Stack + Locals + + 200 133 133 + + + 2506 + Trace Data + + 75 135 130 95 70 230 200 150 + + + 466 + Source Browser + 500 + 300 + + + + + + + + 0 + 0 + 0 + 50 + 16 + + + + + + + 44 + 2 + 3 + + -32000 + -32000 + + + -1 + -1 + + + 156 + 156 + 1308 + 743 + + + + 0 + + 252 + 01000000040000000100000001000000010000000100000000000000020000000000000001000000010000000000000028000000280000000100000001000000000000000100000038443A5C556E69766572736974795C67726164756174696F6E5C636F64655C5265636F6E7374727563745F51745C557365725C6D61696E2E6300000000066D61696E2E6300000000C5D4F200FFFFFFFF0100000010000000C5D4F200FFDC7800BECEA100F0A0A100BCA8E1009CC1B600F7B88600D9ADC200A5C2D700B3A6BE00EAD6A300F6FA7D00B5E99D005FC3CF00C1838300CACAD500010000000000000002000000C4000000660000000006000076020000 + + + + 0 + Build + + -1 + -1 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + C40000004F00000070040000BC000000 + + + 16 + C40000006600000070040000D3000000 + + + + 1005 + 1005 + 1 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 0300000066000000BD00000046020000 + + + 16 + BE000000D50000007E01000073010000 + + + + 109 + 109 + 1 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 0300000066000000BD00000046020000 + + + 16 + BE000000D5000000A10100008C020000 + + + + 1465 + 1465 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000A70100006D040000F8010000 + + + 16 + BE000000D5000000F602000042010000 + + + + 1466 + 1466 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000A70100006D040000F8010000 + + + 16 + BE000000D5000000F602000042010000 + + + + 1467 + 1467 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000A70100006D040000F8010000 + + + 16 + BE000000D5000000F602000042010000 + + + + 1468 + 1468 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000A70100006D040000F8010000 + + + 16 + BE000000D5000000F602000042010000 + + + + 1506 + 1506 + 0 + 0 + 0 + 0 + 32767 + 0 + 16384 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 1913 + 1913 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + C7000000660000006D040000A3000000 + + + 16 + BE000000D5000000F602000042010000 + + + + 1935 + 1935 + 0 + 0 + 0 + 0 + 32767 + 0 + 32768 + 0 + + 16 + 03000000A70100006D040000F8010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 1936 + 1936 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000A70100006D040000F8010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 1937 + 1937 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000A70100006D040000F8010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 1939 + 1939 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000A70100006D040000F8010000 + + + 16 + BE000000D5000000F602000042010000 + + + + 1940 + 1940 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000A70100006D040000F8010000 + + + 16 + BE000000D5000000F602000042010000 + + + + 1941 + 1941 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000A70100006D040000F8010000 + + + 16 + BE000000D5000000F602000042010000 + + + + 1942 + 1942 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000A70100006D040000F8010000 + + + 16 + BE000000D5000000F602000042010000 + + + + 195 + 195 + 1 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 0300000066000000BD00000046020000 + + + 16 + BE000000D5000000A10100008C020000 + + + + 196 + 196 + 1 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 0300000066000000BD00000046020000 + + + 16 + BE000000D5000000A10100008C020000 + + + + 197 + 197 + 1 + 0 + 0 + 0 + 32767 + 0 + 32768 + 0 + + 16 + 00000000770200000006000006030000 + + + 16 + BE000000D5000000F602000042010000 + + + + 198 + 198 + 0 + 0 + 0 + 0 + 32767 + 0 + 32768 + 0 + + 16 + 00000000900100007004000011020000 + + + 16 + BE000000D5000000F602000042010000 + + + + 199 + 199 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007A020000FD050000B7020000 + + + 16 + BE000000D5000000F602000042010000 + + + + 203 + 203 + 0 + 0 + 0 + 0 + 32767 + 0 + 8192 + 0 + + 16 + C7000000660000006D040000A3000000 + + + 16 + BE000000D5000000F602000042010000 + + + + 204 + 204 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + C7000000660000006D040000A3000000 + + + 16 + BE000000D5000000F602000042010000 + + + + 221 + 221 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 00000000000000000000000000000000 + + + 16 + 0A0000000A0000006E0000006E000000 + + + + 2506 + 2506 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 2507 + 2507 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000A70100006D040000F8010000 + + + 16 + BE000000D5000000F602000042010000 + + + + 343 + 343 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + C7000000660000006D040000A3000000 + + + 16 + BE000000D5000000F602000042010000 + + + + 346 + 346 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + C7000000660000006D040000A3000000 + + + 16 + BE000000D5000000F602000042010000 + + + + 35141 + 35141 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + C7000000660000006D040000A3000000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35824 + 35824 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + C7000000660000006D040000A3000000 + + + 16 + BE000000D5000000F602000042010000 + + + + 35885 + 35885 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35886 + 35886 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35887 + 35887 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35888 + 35888 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35889 + 35889 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35890 + 35890 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35891 + 35891 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35892 + 35892 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35893 + 35893 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35894 + 35894 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35895 + 35895 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35896 + 35896 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35897 + 35897 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35898 + 35898 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35899 + 35899 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35900 + 35900 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35901 + 35901 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35902 + 35902 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35903 + 35903 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35904 + 35904 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 35905 + 35905 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 38003 + 38003 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 0300000066000000BD0000007C020000 + + + 16 + BE000000D5000000A10100008C020000 + + + + 38007 + 38007 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007A020000FD050000B7020000 + + + 16 + BE000000D5000000F602000042010000 + + + + 436 + 436 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007A020000FD050000B7020000 + + + 16 + BE000000D5000000A10100008C020000 + + + + 437 + 437 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000A70100006D040000F8010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 440 + 440 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000A70100006D040000F8010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 463 + 463 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007A020000FD050000B7020000 + + + 16 + BE000000D5000000A10100008C020000 + + + + 466 + 466 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 030000007A020000FD050000B7020000 + + + 16 + BE000000D5000000A10100008C020000 + + + + 470 + 470 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + C7000000660000006D040000A3000000 + + + 16 + BE000000D5000000F602000042010000 + + + + 50000 + 50000 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50001 + 50001 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50002 + 50002 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50003 + 50003 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50004 + 50004 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50005 + 50005 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50006 + 50006 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50007 + 50007 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50008 + 50008 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50009 + 50009 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50010 + 50010 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50011 + 50011 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50012 + 50012 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50013 + 50013 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50014 + 50014 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50015 + 50015 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50016 + 50016 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50017 + 50017 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50018 + 50018 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 50019 + 50019 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 59392 + 59392 + 1 + 0 + 0 + 0 + 953 + 0 + 8192 + 0 + + 16 + 0000000000000000C40300001C000000 + + + 16 + 0A0000000A0000006E0000006E000000 + + + + 59393 + 0 + 1 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 00000000060300000006000019030000 + + + 16 + 0A0000000A0000006E0000006E000000 + + + + 59399 + 59399 + 1 + 0 + 0 + 0 + 476 + 0 + 8192 + 1 + + 16 + 000000001C000000E701000038000000 + + + 16 + 0A0000000A0000006E0000006E000000 + + + + 59400 + 59400 + 0 + 0 + 0 + 0 + 612 + 0 + 8192 + 2 + + 16 + 00000000380000006F02000054000000 + + + 16 + 0A0000000A0000006E0000006E000000 + + + + 824 + 824 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000A70100006D040000F8010000 + + + 16 + BE000000D50000007E01000073010000 + + + + 3317 + 000000000B000000000000000020000000000000FFFFFFFFFFFFFFFFC4000000BC00000070040000C0000000000000000100000004000000010000000000000000000000FFFFFFFF08000000CB00000057010000CC000000F08B00005A01000079070000D601000045890000FFFF02000B004354616262656450616E650020000000000000C40000006600000070040000D3000000C40000004F00000070040000BC0000000000000040280046080000000B446973617373656D626C7900000000CB00000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A6572000000005701000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A657200000000CC00000001000000FFFFFFFFFFFFFFFF0E4C6F67696320416E616C797A657200000000F08B000001000000FFFFFFFFFFFFFFFF0D436F646520436F766572616765000000005A01000001000000FFFFFFFFFFFFFFFF11496E737472756374696F6E205472616365000000007907000001000000FFFFFFFFFFFFFFFF0F53797374656D20416E616C797A657200000000D601000001000000FFFFFFFFFFFFFFFF104576656E742053746174697374696373000000004589000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFCB00000001000000FFFFFFFFCB000000000000000040000000000000FFFFFFFFFFFFFFFFAC0300004F000000B0030000A0010000000000000200000004000000010000000000000000000000FFFFFFFF2B000000E2050000CA0900002D8C00002E8C00002F8C0000308C0000318C0000328C0000338C0000348C0000358C0000368C0000378C0000388C0000398C00003A8C00003B8C00003C8C00003D8C00003E8C00003F8C0000408C0000418C000050C3000051C3000052C3000053C3000054C3000055C3000056C3000057C3000058C3000059C300005AC300005BC300005CC300005DC300005EC300005FC3000060C3000061C3000062C3000063C3000001800040000000000000B00300006600000070040000B7010000B00300004F00000070040000A001000000000000404100462B0000000753796D626F6C7300000000E205000001000000FFFFFFFFFFFFFFFF0A5472616365204461746100000000CA09000001000000FFFFFFFFFFFFFFFF00000000002D8C000001000000FFFFFFFFFFFFFFFF00000000002E8C000001000000FFFFFFFFFFFFFFFF00000000002F8C000001000000FFFFFFFFFFFFFFFF0000000000308C000001000000FFFFFFFFFFFFFFFF0000000000318C000001000000FFFFFFFFFFFFFFFF0000000000328C000001000000FFFFFFFFFFFFFFFF0000000000338C000001000000FFFFFFFFFFFFFFFF0000000000348C000001000000FFFFFFFFFFFFFFFF0000000000358C000001000000FFFFFFFFFFFFFFFF0000000000368C000001000000FFFFFFFFFFFFFFFF0000000000378C000001000000FFFFFFFFFFFFFFFF0000000000388C000001000000FFFFFFFFFFFFFFFF0000000000398C000001000000FFFFFFFFFFFFFFFF00000000003A8C000001000000FFFFFFFFFFFFFFFF00000000003B8C000001000000FFFFFFFFFFFFFFFF00000000003C8C000001000000FFFFFFFFFFFFFFFF00000000003D8C000001000000FFFFFFFFFFFFFFFF00000000003E8C000001000000FFFFFFFFFFFFFFFF00000000003F8C000001000000FFFFFFFFFFFFFFFF0000000000408C000001000000FFFFFFFFFFFFFFFF0000000000418C000001000000FFFFFFFFFFFFFFFF000000000050C3000001000000FFFFFFFFFFFFFFFF000000000051C3000001000000FFFFFFFFFFFFFFFF000000000052C3000001000000FFFFFFFFFFFFFFFF000000000053C3000001000000FFFFFFFFFFFFFFFF000000000054C3000001000000FFFFFFFFFFFFFFFF000000000055C3000001000000FFFFFFFFFFFFFFFF000000000056C3000001000000FFFFFFFFFFFFFFFF000000000057C3000001000000FFFFFFFFFFFFFFFF000000000058C3000001000000FFFFFFFFFFFFFFFF000000000059C3000001000000FFFFFFFFFFFFFFFF00000000005AC3000001000000FFFFFFFFFFFFFFFF00000000005BC3000001000000FFFFFFFFFFFFFFFF00000000005CC3000001000000FFFFFFFFFFFFFFFF00000000005DC3000001000000FFFFFFFFFFFFFFFF00000000005EC3000001000000FFFFFFFFFFFFFFFF00000000005FC3000001000000FFFFFFFFFFFFFFFF000000000060C3000001000000FFFFFFFFFFFFFFFF000000000061C3000001000000FFFFFFFFFFFFFFFF000000000062C3000001000000FFFFFFFFFFFFFFFF000000000063C3000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFE205000001000000FFFFFFFFE2050000000000000010000001000000FFFFFFFFFFFFFFFFC00000004F000000C40000005F020000010000000200001004000000010000000000000000000000FFFFFFFF05000000ED0300006D000000C3000000C400000073940000018000100000010000000000000066000000C0000000AC020000000000004F000000C00000005F0200000000000040410056050000000750726F6A65637401000000ED03000001000000FFFFFFFFFFFFFFFF05426F6F6B73010000006D00000001000000FFFFFFFFFFFFFFFF0946756E6374696F6E7301000000C300000001000000FFFFFFFFFFFFFFFF0954656D706C6174657301000000C400000001000000FFFFFFFFFFFFFFFF09526567697374657273000000007394000001000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000001000000FFFFFFFFED03000001000000FFFFFFFFED030000000000000080000000000000FFFFFFFFFFFFFFFF000000008C010000700400009001000000000000010000000400000001000000000000000000000000000000000000000000000001000000C6000000FFFFFFFF0F0000008F070000930700009407000095070000960700009007000091070000B5010000B801000038030000B9050000BA050000BB050000BC050000CB0900000180008000000000000000000000A701000070040000280200000000000090010000700400001102000000000000404100460F0000001343616C6C20537461636B202B204C6F63616C73000000008F07000001000000FFFFFFFFFFFFFFFF0755415254202331000000009307000001000000FFFFFFFFFFFFFFFF0755415254202332000000009407000001000000FFFFFFFFFFFFFFFF0755415254202333000000009507000001000000FFFFFFFFFFFFFFFF15446562756720287072696E74662920566965776572000000009607000001000000FFFFFFFFFFFFFFFF0757617463682031000000009007000001000000FFFFFFFFFFFFFFFF0757617463682032000000009107000001000000FFFFFFFFFFFFFFFF10547261636520457863657074696F6E7300000000B501000001000000FFFFFFFFFFFFFFFF0E4576656E7420436F756E7465727300000000B801000001000000FFFFFFFFFFFFFFFF09554C494E4B706C7573000000003803000001000000FFFFFFFFFFFFFFFF084D656D6F7279203100000000B905000001000000FFFFFFFFFFFFFFFF084D656D6F7279203200000000BA05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203300000000BB05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203400000000BC05000001000000FFFFFFFFFFFFFFFF105472616365204E617669676174696F6E00000000CB09000001000000FFFFFFFFFFFFFFFFFFFFFFFF0000000001000000000000000000000001000000FFFFFFFF38020000900100003C0200001102000000000000020000000400000000000000000000000000000000000000000000000000000002000000C6000000FFFFFFFF8F07000001000000FFFFFFFF8F07000001000000C6000000000000000080000001000000FFFFFFFFFFFFFFFF000000005F020000000600006302000001000000010000100400000001000000BFFDFFFF6B000000FFFFFFFF06000000C5000000C7000000B4010000D2010000CF010000779400000180008000000100000000000000B0020000000600001D030000000000006302000000060000060300000000000040820056060000000C4275696C64204F757470757401000000C500000001000000FFFFFFFFFFFFFFFF0D46696E6420496E2046696C657300000000C700000001000000FFFFFFFFFFFFFFFF0A4572726F72204C69737400000000B401000001000000FFFFFFFFFFFFFFFF0E536F757263652042726F7773657200000000D201000001000000FFFFFFFFFFFFFFFF1346696E6420416C6C205265666572656E63657300000000CF01000001000000FFFFFFFFFFFFFFFF0742726F77736572000000007794000001000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000001000000FFFFFFFFC500000001000000FFFFFFFFC5000000000000000000000000000000 + + + 59392 + File + + 2445 + 00200000010000002800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000000020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000040004000000000000000000000000000000000100000001000000018022E100000000040005000000000000000000000000000000000100000001000000018025E10000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000000000700000000000000000000000000000000010000000100000001802CE10000000004000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000000000900000000000000000000000000000000010000000100000001807B8A0000000004000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000000000B000000000000000000000000000000000100000001000000018015B10000000004000C0000000000000000000000000000000001000000010000000180F4B00000000004000D000000000000000000000000000000000100000001000000018036B10000000004000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF88000000000400460000000000000000000000000000000001000000010000000180FE880000000004004500000000000000000000000000000000010000000100000001800B810000000004001300000000000000000000000000000000010000000100000001800C810000000004001400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F0880000020000000F000000000000000000000000000000000100000001000000FFFF0100120043555646696E64436F6D626F427574746F6EE803000000000000000000000000000000000000000000000001000000010000009600000002002050000000000E2F6170692F74696D65736C6F747396000000000000000B000E2F6170692F74696D65736C6F7473132F6170692F636865636B696E732F746F6461790F5379735469636B5F48616E646C657207737461746963200E55534152545F53656E6444617461205553415254315F496E69745F466F725F4553503832363628313135323030293B104F4C45445F53686F774368696E657365195553415254325F496E69745F46696E616C5F417474656D7074297768696C652028285553415254322D3E535220262055534152545F53525F54584529203D3D2030293B10537461636B5F53697A652020202020200252300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018024E10000000000001100000000000000000000000000000000010000000100000001800A810000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E22800000020000001500000019C6F4B6AF2FCDA3D6B9B5F7CAD4BBE1BBB0094374726C2B463500000000000000000000000001000000010000000000000000000000010000000200218022800000000000001500000019C6F4B6AF2FCDA3D6B9B5F7CAD4BBE1BBB0094374726C2B4635000000000000000000000000010000000100000000000000000000000100000000002180E0010000000000007500000012C4DCC1BFB2E2C1BFBACDCEDED0E8B5F7CAD40000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000000160000000000000000000000000000000001000000010000000180C988000000000400180000000000000000000000000000000001000000010000000180C788000000000000190000000000000000000000000000000001000000010000000180C8880000000000001700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000021804C010000020001001A00000008CFEEC4BFB4B0BFDA000000000000000000000000010000000100000000000000000000000100000008002180DD880000000000001A0000000750726F6A656374000000000000000000000000010000000100000000000000000000000100000000002180DC8B0000000000003A00000005426F6F6B73000000000000000000000000010000000100000000000000000000000100000000002180E18B0000000000003B0000000946756E6374696F6E73000000000000000000000000010000000100000000000000000000000100000000002180E28B000000000000400000000954656D706C6174657300000000000000000000000001000000010000000000000000000000010000000000218018890000000000003D0000000E536F757263652042726F777365720000000000000000000000000100000001000000000000000000000001000000000021800000000000000400FFFFFFFF00000000000000000001000000000000000100000000000000000000000100000000002180D988000000000000390000000C4275696C64204F7574707574000000000000000000000000010000000100000000000000000000000100000000002180E38B000000000000410000000B46696E64204F75747075740000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001B000000000000000000000000000000000100000001000000000000000446696C65B9030000 + + + 1423 + 2800FFFF01001100434D4643546F6F6C426172427574746F6E00E1000000000000FFFFFFFF000100000000000000010000000000000001000000018001E1000000000000FFFFFFFF000100000000000000010000000000000001000000018003E1000000000000FFFFFFFF0001000000000000000100000000000000010000000180CD7F000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF000000000000000000010000000000000001000000018023E1000000000000FFFFFFFF000100000000000000010000000000000001000000018022E1000000000000FFFFFFFF000100000000000000010000000000000001000000018025E1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001802BE1000000000000FFFFFFFF00010000000000000001000000000000000100000001802CE1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001807A8A000000000000FFFFFFFF00010000000000000001000000000000000100000001807B8A000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180D3B0000000000000FFFFFFFF000100000000000000010000000000000001000000018015B1000000000000FFFFFFFF0001000000000000000100000000000000010000000180F4B0000000000000FFFFFFFF000100000000000000010000000000000001000000018036B1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180FF88000000000000FFFFFFFF0001000000000000000100000000000000010000000180FE88000000000000FFFFFFFF00010000000000000001000000000000000100000001800B81000000000000FFFFFFFF00010000000000000001000000000000000100000001800C81000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180F088000000000000FFFFFFFF0001000000000000000100000000000000010000000180EE7F000000000000FFFFFFFF000100000000000000010000000000000001000000018024E1000000000000FFFFFFFF00010000000000000001000000000000000100000001800A81000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001802280000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180C488000000000000FFFFFFFF0001000000000000000100000000000000010000000180C988000000000000FFFFFFFF0001000000000000000100000000000000010000000180C788000000000000FFFFFFFF0001000000000000000100000000000000010000000180C888000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180DD88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180FB7F000000000000FFFFFFFF000100000000000000010000000000000001000000 + + + 1423 + 2800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000000020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000000004000000000000000000000000000000000100000001000000018022E100000000000005000000000000000000000000000000000100000001000000018025E10000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000000000700000000000000000000000000000000010000000100000001802CE10000000000000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000000000900000000000000000000000000000000010000000100000001807B8A0000000000000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000000000B000000000000000000000000000000000100000001000000018015B10000000000000C0000000000000000000000000000000001000000010000000180F4B00000000000000D000000000000000000000000000000000100000001000000018036B10000000000000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF880000000000000F0000000000000000000000000000000001000000010000000180FE880000000000001000000000000000000000000000000000010000000100000001800B810000000000001100000000000000000000000000000000010000000100000001800C810000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F088000000000000130000000000000000000000000000000001000000010000000180EE7F00000000000014000000000000000000000000000000000100000001000000018024E10000000000001500000000000000000000000000000000010000000100000001800A810000000000001600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018022800000000000001700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000000180000000000000000000000000000000001000000010000000180C988000000000000190000000000000000000000000000000001000000010000000180C7880000000000001A0000000000000000000000000000000001000000010000000180C8880000000000001B00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180DD880000000000001C00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001D000000000000000000000000000000000100000001000000 + + + + 59399 + Build + + 960 + 00200000010000001000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F0000000000001C0000000000000000000000000000000001000000010000000180D07F0000000000001D000000000000000000000000000000000100000001000000018030800000000000001E000000000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6EC7040000000000006A00000008C5FAC1BFB9B9BDA8000000000000000000000000010000000100000000000000000000000100000004000580C7040000000000006A00000008C5FAC1BFB9B9BDA800000000000000000000000001000000010000000000000000000000010000000000058046070000000000006B0000000CC5FAC1BFD6D8D0C2B9B9BDA80000000000000000000000000100000001000000000000000000000001000000000005804707000000000000FFFFFFFF08C5FAC1BFC7E5B3FD0100000000000000000000000100000001000000000000000000000001000000000005809E8A0000000000001F0000000BC5FAC1BFC9E8D6C32E2E2E000000000000000000000000010000000100000000000000000000000100000000000180D17F0000000004002000000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001804C8A0000000000002100000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001900434D4643546F6F6C426172436F6D626F426F78427574746F6EBA000000000000000000000000000000000000000000000000010000000100000096000000030020500000000008546172676574203196000000000000000100085461726765742031000000000180EB880000000000002200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C07F000000000000230000000000000000000000000000000001000000010000000180B08A000000000400240000000000000000000000000000000001000000010000000180A8010000000000004E00000000000000000000000000000000010000000100000001807202000000000000530000000000000000000000000000000001000000010000000180BE010000000000005000000000000000000000000000000000010000000100000000000000054275696C64DC010000 + + + 583 + 1000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F000000000000FFFFFFFF0001000000000000000100000000000000010000000180D07F000000000000FFFFFFFF00010000000000000001000000000000000100000001803080000000000000FFFFFFFF00010000000000000001000000000000000100000001809E8A000000000000FFFFFFFF0001000000000000000100000000000000010000000180D17F000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001804C8A000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001806680000000000000FFFFFFFF0001000000000000000100000000000000010000000180EB88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180C07F000000000000FFFFFFFF0001000000000000000100000000000000010000000180B08A000000000000FFFFFFFF0001000000000000000100000000000000010000000180A801000000000000FFFFFFFF00010000000000000001000000000000000100000001807202000000000000FFFFFFFF0001000000000000000100000000000000010000000180BE01000000000000FFFFFFFF000100000000000000010000000000000001000000 + + + 583 + 1000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F000000000000000000000000000000000000000000000001000000010000000180D07F00000000000001000000000000000000000000000000000100000001000000018030800000000000000200000000000000000000000000000000010000000100000001809E8A000000000000030000000000000000000000000000000001000000010000000180D17F0000000000000400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001804C8A0000000000000500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001806680000000000000060000000000000000000000000000000001000000010000000180EB880000000000000700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C07F000000000000080000000000000000000000000000000001000000010000000180B08A000000000000090000000000000000000000000000000001000000010000000180A8010000000000000A000000000000000000000000000000000100000001000000018072020000000000000B0000000000000000000000000000000001000000010000000180BE010000000000000C000000000000000000000000000000000100000001000000 + + + + 59400 + Debug + + 2337 + 00200000000000001900FFFF01001100434D4643546F6F6C426172427574746F6ECC880000000000002500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018017800000000000002600000000000000000000000000000000010000000100000001801D800000000000002700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001801A800000000000002800000000000000000000000000000000010000000100000001801B80000000000000290000000000000000000000000000000001000000010000000180E57F0000000000002A00000000000000000000000000000000010000000100000001801C800000000000002B00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018000890000000000002C00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180E48B0000000000002D0000000000000000000000000000000001000000010000000180F07F0000000000002E0000000000000000000000000000000001000000010000000180E8880000000000003700000000000000000000000000000000010000000100000001803B010000000000002F0000000000000000000000000000000001000000010000000180BB8A00000000000030000000000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E0E01000000000000310000000D57617463682057696E646F7773000000000000000000000000010000000100000000000000000000000100000003001380D88B0000000000003100000007B9DBB2E2202631000000000000000000000000010000000100000000000000000000000100000000001380D98B0000000000003100000007B9DBB2E2202632000000000000000000000000010000000100000000000000000000000100000000001380CE01000000000000FFFFFFFF0C576174636820416E63686F720100000000000000010000000000000001000000000000000000000001000000000013800F01000000000000320000000E4D656D6F72792057696E646F7773000000000000000000000000010000000100000000000000000000000100000004001380D28B0000000000003200000007C4DAB4E6202631000000000000000000000000010000000100000000000000000000000100000000001380D38B0000000000003200000007C4DAB4E6202632000000000000000000000000010000000100000000000000000000000100000000001380D48B0000000000003200000007C4DAB4E6202633000000000000000000000000010000000100000000000000000000000100000000001380D58B0000000000003200000007C4DAB4E62026340000000000000000000000000100000001000000000000000000000001000000000013801001000000000000330000000E53657269616C2057696E646F777300000000000000000000000001000000010000000000000000000000010000000400138093070000000000003300000008B4AEBFDA2023263100000000000000000000000001000000010000000000000000000000010000000000138094070000000000003300000008B4AEBFDA2023263200000000000000000000000001000000010000000000000000000000010000000000138095070000000000003300000008B4AEBFDA2023263300000000000000000000000001000000010000000000000000000000010000000000138096070000000000003300000014B5F7CAD4A3A87072696E7466A3A9B2E9BFB4C6F70000000000000000000000000100000001000000000000000000000001000000000013803C010000000000003400000010416E616C797369732057696E646F7773000000000000000000000000010000000100000000000000000000000100000004001380658A000000000000340000000AC2DFBCADB7D6CEF6D2C7000000000000000000000000010000000100000000000000000000000100000000001380DC7F0000000000003E0000000AD0D4C4DCB7D6CEF6C6F7000000000000000000000000010000000100000000000000000000000100000000001380E788000000000000380000000B26B4FAC2EBB8B2B8C7C2CA000000000000000000000000010000000100000000000000000000000100000000001380CD01000000000000FFFFFFFF0F416E616C7973697320416E63686F7201000000000000000100000000000000010000000000000000000000010000000000138053010000000000003F0000000D54726163652057696E646F77730000000000000000000000000100000001000000000000000000000001000000010013805401000000000000FFFFFFFF115472616365204D656E7520416E63686F720100000000000000010000000000000001000000000000000000000001000000000013802901000000000000350000001553797374656D205669657765722057696E646F77730000000000000000000000000100000001000000000000000000000001000000010013804B01000000000000FFFFFFFF1453797374656D2056696577657220416E63686F720100000000000000010000000000000001000000000000000000000001000000000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000013800189000000000000360000000AB9A4BEDFCFE4B4B0BFDA00000000000000000000000001000000010000000000000000000000010000000300138044C5000000000000FFFFFFFF0E5570646174652057696E646F77730100000000000000010000000000000001000000000000000000000001000000000013800000000000000400FFFFFFFF000000000000000000010000000000000001000000000000000000000001000000000013805B01000000000000FFFFFFFF12546F6F6C626F78204D656E75416E63686F72010000000000000001000000000000000100000000000000000000000100000000000000000005446562756764020000 + + + 898 + 1900FFFF01001100434D4643546F6F6C426172427574746F6ECC88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001801780000000000000FFFFFFFF00010000000000000001000000000000000100000001801D80000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001801A80000000000000FFFFFFFF00010000000000000001000000000000000100000001801B80000000000000FFFFFFFF0001000000000000000100000000000000010000000180E57F000000000000FFFFFFFF00010000000000000001000000000000000100000001801C80000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001800089000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180E48B000000000000FFFFFFFF0001000000000000000100000000000000010000000180F07F000000000000FFFFFFFF0001000000000000000100000000000000010000000180E888000000000000FFFFFFFF00010000000000000001000000000000000100000001803B01000000000000FFFFFFFF0001000000000000000100000000000000010000000180BB8A000000000000FFFFFFFF0001000000000000000100000000000000010000000180D88B000000000000FFFFFFFF0001000000000000000100000000000000010000000180D28B000000000000FFFFFFFF00010000000000000001000000000000000100000001809307000000000000FFFFFFFF0001000000000000000100000000000000010000000180658A000000000000FFFFFFFF0001000000000000000100000000000000010000000180C18A000000000000FFFFFFFF0001000000000000000100000000000000010000000180EE8B000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001800189000000000000FFFFFFFF000100000000000000010000000000000001000000 + + + 898 + 1900FFFF01001100434D4643546F6F6C426172427574746F6ECC880000000000000000000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018017800000000000000100000000000000000000000000000000010000000100000001801D800000000000000200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001801A800000000000000300000000000000000000000000000000010000000100000001801B80000000000000040000000000000000000000000000000001000000010000000180E57F0000000000000500000000000000000000000000000000010000000100000001801C800000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018000890000000000000700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180E48B000000000000080000000000000000000000000000000001000000010000000180F07F000000000000090000000000000000000000000000000001000000010000000180E8880000000000000A00000000000000000000000000000000010000000100000001803B010000000000000B0000000000000000000000000000000001000000010000000180BB8A0000000000000C0000000000000000000000000000000001000000010000000180D88B0000000000000D0000000000000000000000000000000001000000010000000180D28B0000000000000E000000000000000000000000000000000100000001000000018093070000000000000F0000000000000000000000000000000001000000010000000180658A000000000000100000000000000000000000000000000001000000010000000180C18A000000000000110000000000000000000000000000000001000000010000000180EE8B0000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180018900000000000013000000000000000000000000000000000100000001000000 + + + + 0 + 1536 + 864 + + + + 1 + Debug + + -1 + -1 + 1 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + FF0000004F00000000060000BC000000 + + + 16 + C40000006600000000060000D3000000 + + + + 1005 + 1005 + 1 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 0300000066000000F8000000B2010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 109 + 109 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 0300000066000000BD0000002A020000 + + + 16 + 8A000000A10000006D01000058020000 + + + + 1465 + 1465 + 1 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 07030000E6010000FD050000ED020000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 1466 + 1466 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 07030000E6010000FD05000075020000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 1467 + 1467 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 07030000E6010000FD05000075020000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 1468 + 1468 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 07030000E6010000FD05000075020000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 1506 + 1506 + 0 + 0 + 0 + 0 + 32767 + 0 + 16384 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 1913 + 1913 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 020100006600000038060000A3000000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 1935 + 1935 + 1 + 0 + 0 + 0 + 32767 + 0 + 32768 + 0 + + 16 + 07030000E6010000FD050000ED020000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 1936 + 1936 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 07030000E6010000FD05000075020000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 1937 + 1937 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 07030000E6010000FD05000075020000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 1939 + 1939 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 07030000E6010000FD05000075020000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 1940 + 1940 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 07030000E6010000FD05000075020000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 1941 + 1941 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 07030000E6010000FD05000075020000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 1942 + 1942 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 07030000E6010000FD05000075020000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 195 + 195 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 0300000066000000BD0000002A020000 + + + 16 + 8A000000A10000006D01000058020000 + + + + 196 + 196 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 0300000066000000BD0000002A020000 + + + 16 + 8A000000A10000006D01000058020000 + + + + 197 + 197 + 0 + 0 + 0 + 0 + 32767 + 0 + 32768 + 0 + + 16 + 03000000BB0100006D040000F8010000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 198 + 198 + 1 + 0 + 0 + 0 + 32767 + 0 + 32768 + 0 + + 16 + 00000000CF0100000003000006030000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 199 + 199 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000BB0100006D040000F8010000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 203 + 203 + 1 + 0 + 0 + 0 + 32767 + 0 + 8192 + 0 + + 16 + FF0000006300000000060000BC000000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 204 + 204 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 020100006600000038060000A3000000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 221 + 221 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 00000000000000000000000000000000 + + + 16 + 0A0000000A0000006E0000006E000000 + + + + 2506 + 2506 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 2507 + 2507 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 07030000E6010000FD05000075020000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 343 + 343 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 020100006600000038060000A3000000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 346 + 346 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 020100006600000038060000A3000000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 35141 + 35141 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 020100006600000038060000A3000000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35824 + 35824 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 020100006600000038060000A3000000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 35885 + 35885 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35886 + 35886 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35887 + 35887 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35888 + 35888 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35889 + 35889 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35890 + 35890 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35891 + 35891 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35892 + 35892 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35893 + 35893 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35894 + 35894 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35895 + 35895 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35896 + 35896 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35897 + 35897 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35898 + 35898 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35899 + 35899 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35900 + 35900 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35901 + 35901 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35902 + 35902 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35903 + 35903 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35904 + 35904 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 35905 + 35905 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 38003 + 38003 + 1 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 0300000066000000F8000000B2010000 + + + 16 + 8A000000A10000006D01000058020000 + + + + 38007 + 38007 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000BB0100006D040000F8010000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 436 + 436 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000BB0100006D040000F8010000 + + + 16 + 8A000000A10000006D01000058020000 + + + + 437 + 437 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 07030000E6010000FD05000075020000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 440 + 440 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 07030000E6010000FD05000075020000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 463 + 463 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000BB0100006D040000F8010000 + + + 16 + 8A000000A10000006D01000058020000 + + + + 466 + 466 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 03000000BB0100006D040000F8010000 + + + 16 + 8A000000A10000006D01000058020000 + + + + 470 + 470 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 020100006600000038060000A3000000 + + + 16 + 8A000000A1000000C20200000E010000 + + + + 50000 + 50000 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50001 + 50001 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50002 + 50002 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50003 + 50003 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50004 + 50004 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50005 + 50005 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50006 + 50006 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50007 + 50007 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50008 + 50008 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50009 + 50009 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50010 + 50010 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50011 + 50011 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50012 + 50012 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50013 + 50013 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50014 + 50014 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50015 + 50015 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50016 + 50016 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50017 + 50017 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50018 + 50018 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 50019 + 50019 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + B3030000660000006D04000087010000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 59392 + 59392 + 1 + 0 + 0 + 0 + 953 + 0 + 8192 + 0 + + 16 + 0000000000000000C40300001C000000 + + + 16 + 0A0000000A0000006E0000006E000000 + + + + 59393 + 0 + 1 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 00000000060300000006000019030000 + + + 16 + 0A0000000A0000006E0000006E000000 + + + + 59399 + 59399 + 0 + 0 + 0 + 0 + 476 + 0 + 8192 + 1 + + 16 + 000000001C000000E701000038000000 + + + 16 + 0A0000000A0000006E0000006E000000 + + + + 59400 + 59400 + 1 + 0 + 0 + 0 + 612 + 0 + 8192 + 2 + + 16 + 000000001C0000006F02000038000000 + + + 16 + 0A0000000A0000006E0000006E000000 + + + + 824 + 824 + 0 + 0 + 0 + 0 + 32767 + 0 + 4096 + 0 + + 16 + 07030000E6010000FD05000075020000 + + + 16 + 8A000000A10000004A0100003F010000 + + + + 3316 + 000000000B000000000000000020000001000000FFFFFFFFFFFFFFFFFF000000BC00000000060000C0000000010000000100001004000000010000000000000000000000FFFFFFFF08000000CB00000057010000CC000000F08B00005A01000079070000D601000045890000FFFF02000B004354616262656450616E650020000001000000C40000006600000000060000D3000000FF0000004F00000000060000BC0000000000000040280056080000000B446973617373656D626C7901000000CB00000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A6572000000005701000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A657200000000CC00000001000000FFFFFFFFFFFFFFFF0E4C6F67696320416E616C797A657200000000F08B000001000000FFFFFFFFFFFFFFFF0D436F646520436F766572616765000000005A01000001000000FFFFFFFFFFFFFFFF11496E737472756374696F6E205472616365000000007907000001000000FFFFFFFFFFFFFFFF0F53797374656D20416E616C797A657200000000D601000001000000FFFFFFFFFFFFFFFF104576656E742053746174697374696373000000004589000001000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000001000000FFFFFFFFCB00000001000000FFFFFFFFCB000000000000000040000000000000FFFFFFFFFFFFFFFFAC0300004F000000B0030000A0010000000000000200000004000000010000000000000000000000FFFFFFFF2B000000E2050000CA0900002D8C00002E8C00002F8C0000308C0000318C0000328C0000338C0000348C0000358C0000368C0000378C0000388C0000398C00003A8C00003B8C00003C8C00003D8C00003E8C00003F8C0000408C0000418C000050C3000051C3000052C3000053C3000054C3000055C3000056C3000057C3000058C3000059C300005AC300005BC300005CC300005DC300005EC300005FC3000060C3000061C3000062C3000063C3000001800040000000000000B00300006600000070040000B7010000B00300004F00000070040000A001000000000000404100462B0000000753796D626F6C7300000000E205000001000000FFFFFFFFFFFFFFFF0A5472616365204461746100000000CA09000001000000FFFFFFFFFFFFFFFF00000000002D8C000001000000FFFFFFFFFFFFFFFF00000000002E8C000001000000FFFFFFFFFFFFFFFF00000000002F8C000001000000FFFFFFFFFFFFFFFF0000000000308C000001000000FFFFFFFFFFFFFFFF0000000000318C000001000000FFFFFFFFFFFFFFFF0000000000328C000001000000FFFFFFFFFFFFFFFF0000000000338C000001000000FFFFFFFFFFFFFFFF0000000000348C000001000000FFFFFFFFFFFFFFFF0000000000358C000001000000FFFFFFFFFFFFFFFF0000000000368C000001000000FFFFFFFFFFFFFFFF0000000000378C000001000000FFFFFFFFFFFFFFFF0000000000388C000001000000FFFFFFFFFFFFFFFF0000000000398C000001000000FFFFFFFFFFFFFFFF00000000003A8C000001000000FFFFFFFFFFFFFFFF00000000003B8C000001000000FFFFFFFFFFFFFFFF00000000003C8C000001000000FFFFFFFFFFFFFFFF00000000003D8C000001000000FFFFFFFFFFFFFFFF00000000003E8C000001000000FFFFFFFFFFFFFFFF00000000003F8C000001000000FFFFFFFFFFFFFFFF0000000000408C000001000000FFFFFFFFFFFFFFFF0000000000418C000001000000FFFFFFFFFFFFFFFF000000000050C3000001000000FFFFFFFFFFFFFFFF000000000051C3000001000000FFFFFFFFFFFFFFFF000000000052C3000001000000FFFFFFFFFFFFFFFF000000000053C3000001000000FFFFFFFFFFFFFFFF000000000054C3000001000000FFFFFFFFFFFFFFFF000000000055C3000001000000FFFFFFFFFFFFFFFF000000000056C3000001000000FFFFFFFFFFFFFFFF000000000057C3000001000000FFFFFFFFFFFFFFFF000000000058C3000001000000FFFFFFFFFFFFFFFF000000000059C3000001000000FFFFFFFFFFFFFFFF00000000005AC3000001000000FFFFFFFFFFFFFFFF00000000005BC3000001000000FFFFFFFFFFFFFFFF00000000005CC3000001000000FFFFFFFFFFFFFFFF00000000005DC3000001000000FFFFFFFFFFFFFFFF00000000005EC3000001000000FFFFFFFFFFFFFFFF00000000005FC3000001000000FFFFFFFFFFFFFFFF000000000060C3000001000000FFFFFFFFFFFFFFFF000000000061C3000001000000FFFFFFFFFFFFFFFF000000000062C3000001000000FFFFFFFFFFFFFFFF000000000063C3000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFE205000001000000FFFFFFFFE2050000000000000010000001000000FFFFFFFFFFFFFFFFFB0000004F000000FF000000CB0100000100000002000010040000000100000042FFFFFF37050000FFFFFFFF05000000ED0300006D000000C3000000C400000073940000018000100000010000000000000066000000C00000005A020000000000004F000000FB000000CB0100000000000040410056050000000750726F6A65637401000000ED03000001000000FFFFFFFFFFFFFFFF05426F6F6B73000000006D00000001000000FFFFFFFFFFFFFFFF0946756E6374696F6E7300000000C300000001000000FFFFFFFFFFFFFFFF0954656D706C6174657300000000C400000001000000FFFFFFFFFFFFFFFF09526567697374657273010000007394000001000000FFFFFFFFFFFFFFFF04000000000000000000000000000000000000000000000001000000FFFFFFFFED03000001000000FFFFFFFFED030000000000000080000001000000FFFFFFFFFFFFFFFF00000000CB01000000060000CF0100000100000001000010040000000100000082FEFFFF5A00000000000000000000000000000001000000C6000000FFFFFFFF0F0000008F070000930700009407000095070000960700009007000091070000B5010000B801000038030000B9050000BA050000BB050000BC050000CB09000001800080000001000000040300005E020000000600001D03000004030000CF010000000600000603000000000000404100560F0000001343616C6C20537461636B202B204C6F63616C73010000008F07000001000000FFFFFFFFFFFFFFFF0755415254202331000000009307000001000000FFFFFFFFFFFFFFFF0755415254202332000000009407000001000000FFFFFFFFFFFFFFFF0755415254202333000000009507000001000000FFFFFFFFFFFFFFFF15446562756720287072696E74662920566965776572000000009607000001000000FFFFFFFFFFFFFFFF0757617463682031000000009007000001000000FFFFFFFFFFFFFFFF0757617463682032000000009107000001000000FFFFFFFFFFFFFFFF10547261636520457863657074696F6E7300000000B501000001000000FFFFFFFFFFFFFFFF0E4576656E7420436F756E7465727300000000B801000001000000FFFFFFFFFFFFFFFF09554C494E4B706C7573000000003803000001000000FFFFFFFFFFFFFFFF084D656D6F7279203101000000B905000001000000FFFFFFFFFFFFFFFF084D656D6F7279203200000000BA05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203300000000BB05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203400000000BC05000001000000FFFFFFFFFFFFFFFF105472616365204E617669676174696F6E00000000CB09000001000000FFFFFFFFFFFFFFFF000000000000000001000000000000000100000001000000FFFFFFFF00030000CF010000040300000603000001000000020000100400000000000000000000000000000000000000000000000000000002000000C6000000FFFFFFFF8F07000001000000FFFFFFFF8F07000001000000C6000000000000000080000000000000FFFFFFFFFFFFFFFF00000000A001000070040000A4010000000000000100000004000000010000000000000000000000FFFFFFFF06000000C5000000C7000000B4010000D2010000CF010000779400000180008000000000000000000000BB010000700400002802000000000000A401000070040000110200000000000040820046060000000C4275696C64204F757470757400000000C500000001000000FFFFFFFFFFFFFFFF0D46696E6420496E2046696C657300000000C700000001000000FFFFFFFFFFFFFFFF0A4572726F72204C69737400000000B401000001000000FFFFFFFFFFFFFFFF0E536F757263652042726F7773657200000000D201000001000000FFFFFFFFFFFFFFFF1346696E6420416C6C205265666572656E63657300000000CF01000001000000FFFFFFFFFFFFFFFF0642726F777365000000007794000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFC500000001000000FFFFFFFFC5000000000000000000000000000000 + + + 59392 + File + + 2369 + 00200000010000002800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000000020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000000004000000000000000000000000000000000100000001000000018022E100000000000005000000000000000000000000000000000100000001000000018025E10000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000000000700000000000000000000000000000000010000000100000001802CE10000000004000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000000000900000000000000000000000000000000010000000100000001807B8A0000000004000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000000000B000000000000000000000000000000000100000001000000018015B10000000004000C0000000000000000000000000000000001000000010000000180F4B00000000004000D000000000000000000000000000000000100000001000000018036B10000000004000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF88000000000000460000000000000000000000000000000001000000010000000180FE880000000000004500000000000000000000000000000000010000000100000001800B810000000000001300000000000000000000000000000000010000000100000001800C810000000000001400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F0880000020000000F000000000000000000000000000000000100000001000000FFFF0100120043555646696E64436F6D626F427574746F6EE80300000000000000000000000000000000000000000000000100000001000000960000000200205000000000205553415254315F496E69745F466F725F4553503832363628313135323030293B96000000000000000600205553415254315F496E69745F466F725F4553503832363628313135323030293B104F4C45445F53686F774368696E657365195553415254325F496E69745F46696E616C5F417474656D7074297768696C652028285553415254322D3E535220262055534152545F53525F54584529203D3D2030293B10537461636B5F53697A65202020202020025230000000000000000000000000000000000000000000000000018024E10000000000001100000000000000000000000000000000010000000100000001800A810000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E22800000000000001500000019C6F4B6AF2FCDA3D6B9B5F7CAD4BBE1BBB0094374726C2B463500000000000000000000000001000000010000000000000000000000010000000200218022800000000000001500000019C6F4B6AF2FCDA3D6B9B5F7CAD4BBE1BBB0094374726C2B4635000000000000000000000000010000000100000000000000000000000100000000002180E0010000000000007500000012C4DCC1BFB2E2C1BFBACDCEDED0E8B5F7CAD40000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000000160000000000000000000000000000000001000000010000000180C988000000000400180000000000000000000000000000000001000000010000000180C788000000000000190000000000000000000000000000000001000000010000000180C8880000000000001700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000021804C010000020001001A00000008CFEEC4BFB4B0BFDA000000000000000000000000010000000100000000000000000000000100000008002180DD880000000000001A0000000750726F6A656374000000000000000000000000010000000100000000000000000000000100000000002180DC8B0000000000003A00000005426F6F6B73000000000000000000000000010000000100000000000000000000000100000000002180E18B0000000000003B0000000946756E6374696F6E73000000000000000000000000010000000100000000000000000000000100000000002180E28B000000000000400000000954656D706C6174657300000000000000000000000001000000010000000000000000000000010000000000218018890000000000003D0000000E536F757263652042726F777365720000000000000000000000000100000001000000000000000000000001000000000021800000000000000400FFFFFFFF00000000000000000001000000000000000100000000000000000000000100000000002180D988000000000000390000000C4275696C64204F7574707574000000000000000000000000010000000100000000000000000000000100000000002180E38B000000000000410000000B46696E64204F75747075740000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001B000000000000000000000000000000000100000001000000000000000446696C65B9030000 + + + 1423 + 2800FFFF01001100434D4643546F6F6C426172427574746F6E00E1000000000000FFFFFFFF000100000000000000010000000000000001000000018001E1000000000000FFFFFFFF000100000000000000010000000000000001000000018003E1000000000000FFFFFFFF0001000000000000000100000000000000010000000180CD7F000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF000000000000000000010000000000000001000000018023E1000000000000FFFFFFFF000100000000000000010000000000000001000000018022E1000000000000FFFFFFFF000100000000000000010000000000000001000000018025E1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001802BE1000000000000FFFFFFFF00010000000000000001000000000000000100000001802CE1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001807A8A000000000000FFFFFFFF00010000000000000001000000000000000100000001807B8A000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180D3B0000000000000FFFFFFFF000100000000000000010000000000000001000000018015B1000000000000FFFFFFFF0001000000000000000100000000000000010000000180F4B0000000000000FFFFFFFF000100000000000000010000000000000001000000018036B1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180FF88000000000000FFFFFFFF0001000000000000000100000000000000010000000180FE88000000000000FFFFFFFF00010000000000000001000000000000000100000001800B81000000000000FFFFFFFF00010000000000000001000000000000000100000001800C81000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180F088000000000000FFFFFFFF0001000000000000000100000000000000010000000180EE7F000000000000FFFFFFFF000100000000000000010000000000000001000000018024E1000000000000FFFFFFFF00010000000000000001000000000000000100000001800A81000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001802280000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180C488000000000000FFFFFFFF0001000000000000000100000000000000010000000180C988000000000000FFFFFFFF0001000000000000000100000000000000010000000180C788000000000000FFFFFFFF0001000000000000000100000000000000010000000180C888000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180DD88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180FB7F000000000000FFFFFFFF000100000000000000010000000000000001000000 + + + 1423 + 2800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000000020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000000004000000000000000000000000000000000100000001000000018022E100000000000005000000000000000000000000000000000100000001000000018025E10000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000000000700000000000000000000000000000000010000000100000001802CE10000000000000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000000000900000000000000000000000000000000010000000100000001807B8A0000000000000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000000000B000000000000000000000000000000000100000001000000018015B10000000000000C0000000000000000000000000000000001000000010000000180F4B00000000000000D000000000000000000000000000000000100000001000000018036B10000000000000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF880000000000000F0000000000000000000000000000000001000000010000000180FE880000000000001000000000000000000000000000000000010000000100000001800B810000000000001100000000000000000000000000000000010000000100000001800C810000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F088000000000000130000000000000000000000000000000001000000010000000180EE7F00000000000014000000000000000000000000000000000100000001000000018024E10000000000001500000000000000000000000000000000010000000100000001800A810000000000001600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018022800000000000001700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000000180000000000000000000000000000000001000000010000000180C988000000000000190000000000000000000000000000000001000000010000000180C7880000000000001A0000000000000000000000000000000001000000010000000180C8880000000000001B00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180DD880000000000001C00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001D000000000000000000000000000000000100000001000000 + + + + 59399 + Build + + 939 + 00200000000000001000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F0000000000001C0000000000000000000000000000000001000000010000000180D07F0000000000001D000000000000000000000000000000000100000001000000018030800000000000001E000000000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6EC7040000000000006A00000008C5FAC1BFB9B9BDA8000000000000000000000000010000000100000000000000000000000100000004000580C7040000000000006A00000008C5FAC1BFB9B9BDA800000000000000000000000001000000010000000000000000000000010000000000058046070000000000006B0000000CC5FAC1BFD6D8D0C2B9B9BDA80000000000000000000000000100000001000000000000000000000001000000000005804707000000000000FFFFFFFF08C5FAC1BFC7E5B3FD0100000000000000010000000000000001000000000000000000000001000000000005809E8A0000000000001F0000000BC5FAC1BFC9E8D6C32E2E2E000000000000000000000000010000000100000000000000000000000100000000000180D17F0000000000002000000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001804C8A0000000000002100000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001900434D4643546F6F6C426172436F6D626F426F78427574746F6EBA00000000000000000000000000000000000000000000000001000000010000009600000003002050FFFFFFFF00960000000000000000000180EB880000000000002200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C07F000000000000230000000000000000000000000000000001000000010000000180B08A000000000000240000000000000000000000000000000001000000010000000180A8010000000000004E00000000000000000000000000000000010000000100000001807202000000000000530000000000000000000000000000000001000000010000000180BE010000000000005000000000000000000000000000000000010000000100000000000000054275696C64DC010000 + + + 583 + 1000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F000000000000FFFFFFFF0001000000000000000100000000000000010000000180D07F000000000000FFFFFFFF00010000000000000001000000000000000100000001803080000000000000FFFFFFFF00010000000000000001000000000000000100000001809E8A000000000000FFFFFFFF0001000000000000000100000000000000010000000180D17F000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001804C8A000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001806680000000000000FFFFFFFF0001000000000000000100000000000000010000000180EB88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180C07F000000000000FFFFFFFF0001000000000000000100000000000000010000000180B08A000000000000FFFFFFFF0001000000000000000100000000000000010000000180A801000000000000FFFFFFFF00010000000000000001000000000000000100000001807202000000000000FFFFFFFF0001000000000000000100000000000000010000000180BE01000000000000FFFFFFFF000100000000000000010000000000000001000000 + + + 583 + 1000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F000000000000000000000000000000000000000000000001000000010000000180D07F00000000000001000000000000000000000000000000000100000001000000018030800000000000000200000000000000000000000000000000010000000100000001809E8A000000000000030000000000000000000000000000000001000000010000000180D17F0000000000000400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001804C8A0000000000000500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001806680000000000000060000000000000000000000000000000001000000010000000180EB880000000000000700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C07F000000000000080000000000000000000000000000000001000000010000000180B08A000000000000090000000000000000000000000000000001000000010000000180A8010000000000000A000000000000000000000000000000000100000001000000018072020000000000000B0000000000000000000000000000000001000000010000000180BE010000000000000C000000000000000000000000000000000100000001000000 + + + + 59400 + Debug + + 2324 + 00200000010000001900FFFF01001100434D4643546F6F6C426172427574746F6ECC880000000000002500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018017800000000000002600000000000000000000000000000000010000000100000001801D800000000004002700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001801A800000000000002800000000000000000000000000000000010000000100000001801B80000000000000290000000000000000000000000000000001000000010000000180E57F0000000000002A00000000000000000000000000000000010000000100000001801C800000000000002B00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018000890000000000002C00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180E48B0000020001002D0000000000000000000000000000000001000000010000000180F07F0000020001002E0000000000000000000000000000000001000000010000000180E8880000020000003700000000000000000000000000000000010000000100000001803B010000020001002F0000000000000000000000000000000001000000010000000180BB8A00000200010030000000000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E0E01000002000000310000000D57617463682057696E646F7773000000000000000000000000010000000100000000000000000000000100000003001380D88B0000000000003100000007B9DBB2E2202631000000000000000000000000010000000100000000000000000000000100000000001380D98B0000000000003100000007B9DBB2E2202632000000000000000000000000010000000100000000000000000000000100000000001380CE01000000000000FFFFFFFF0C576174636820416E63686F720100000000000000010000000000000001000000000000000000000001000000000013800F010000020001003200000007C4DAB4E6202631000000000000000000000000010000000100000000000000000000000100000004001380D28B0000000000003200000007C4DAB4E6202631000000000000000000000000010000000100000000000000000000000100000000001380D38B0000000000003200000007C4DAB4E6202632000000000000000000000000010000000100000000000000000000000100000000001380D48B0000000000003200000007C4DAB4E6202633000000000000000000000000010000000100000000000000000000000100000000001380D58B0000000000003200000007C4DAB4E620263400000000000000000000000001000000010000000000000000000000010000000000138010010000020000003300000008B4AEBFDA2023263100000000000000000000000001000000010000000000000000000000010000000400138093070000000000003300000008B4AEBFDA2023263100000000000000000000000001000000010000000000000000000000010000000000138094070000000000003300000008B4AEBFDA2023263200000000000000000000000001000000010000000000000000000000010000000000138095070000000000003300000008B4AEBFDA2023263300000000000000000000000001000000010000000000000000000000010000000000138096070000000000003300000014B5F7CAD4A3A87072696E7466A3A9B2E9BFB4C6F70000000000000000000000000100000001000000000000000000000001000000000013803C010000020000003400000010416E616C797369732057696E646F7773000000000000000000000000010000000100000000000000000000000100000004001380658A000000000000340000000AC2DFBCADB7D6CEF6D2C7000000000000000000000000010000000100000000000000000000000100000000001380DC7F0000000000003E0000000AD0D4C4DCB7D6CEF6C6F7000000000000000000000000010000000100000000000000000000000100000000001380E788000000000000380000000B26B4FAC2EBB8B2B8C7C2CA000000000000000000000000010000000100000000000000000000000100000000001380CD01000000000000FFFFFFFF0F416E616C7973697320416E63686F7201000000000000000100000000000000010000000000000000000000010000000000138053010000000000003F0000000D54726163652057696E646F77730000000000000000000000000100000001000000000000000000000001000000010013805401000000000000FFFFFFFF115472616365204D656E7520416E63686F720100000000000000010000000000000001000000000000000000000001000000000013802901000000000000350000001553797374656D205669657765722057696E646F77730000000000000000000000000100000001000000000000000000000001000000010013804B01000000000000FFFFFFFF1453797374656D2056696577657220416E63686F720100000000000000010000000000000001000000000000000000000001000000000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000013800189000002000000360000000AB9A4BEDFCFE4B4B0BFDA00000000000000000000000001000000010000000000000000000000010000000300138044C5000000000000FFFFFFFF0E5570646174652057696E646F77730100000000000000010000000000000001000000000000000000000001000000000013800000000000000400FFFFFFFF000000000000000000010000000000000001000000000000000000000001000000000013805B01000000000000FFFFFFFF12546F6F6C626F78204D656E75416E63686F72010000000000000001000000000000000100000000000000000000000100000000000000000005446562756764020000 + + + 898 + 1900FFFF01001100434D4643546F6F6C426172427574746F6ECC88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001801780000000000000FFFFFFFF00010000000000000001000000000000000100000001801D80000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001801A80000000000000FFFFFFFF00010000000000000001000000000000000100000001801B80000000000000FFFFFFFF0001000000000000000100000000000000010000000180E57F000000000000FFFFFFFF00010000000000000001000000000000000100000001801C80000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001800089000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180E48B000000000000FFFFFFFF0001000000000000000100000000000000010000000180F07F000000000000FFFFFFFF0001000000000000000100000000000000010000000180E888000000000000FFFFFFFF00010000000000000001000000000000000100000001803B01000000000000FFFFFFFF0001000000000000000100000000000000010000000180BB8A000000000000FFFFFFFF0001000000000000000100000000000000010000000180D88B000000000000FFFFFFFF0001000000000000000100000000000000010000000180D28B000000000000FFFFFFFF00010000000000000001000000000000000100000001809307000000000000FFFFFFFF0001000000000000000100000000000000010000000180658A000000000000FFFFFFFF0001000000000000000100000000000000010000000180C18A000000000000FFFFFFFF0001000000000000000100000000000000010000000180EE8B000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001800189000000000000FFFFFFFF000100000000000000010000000000000001000000 + + + 898 + 1900FFFF01001100434D4643546F6F6C426172427574746F6ECC880000000000000000000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018017800000000000000100000000000000000000000000000000010000000100000001801D800000000000000200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001801A800000000000000300000000000000000000000000000000010000000100000001801B80000000000000040000000000000000000000000000000001000000010000000180E57F0000000000000500000000000000000000000000000000010000000100000001801C800000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018000890000000000000700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180E48B000000000000080000000000000000000000000000000001000000010000000180F07F000000000000090000000000000000000000000000000001000000010000000180E8880000000000000A00000000000000000000000000000000010000000100000001803B010000000000000B0000000000000000000000000000000001000000010000000180BB8A0000000000000C0000000000000000000000000000000001000000010000000180D88B0000000000000D0000000000000000000000000000000001000000010000000180D28B0000000000000E000000000000000000000000000000000100000001000000018093070000000000000F0000000000000000000000000000000001000000010000000180658A000000000000100000000000000000000000000000000001000000010000000180C18A000000000000110000000000000000000000000000000001000000010000000180EE8B0000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180018900000000000013000000000000000000000000000000000100000001000000 + + + + 0 + 1536 + 864 + + + + + + 1 + 0 + + 100 + 0 + + .\User\main.c + 39 + 1 + 22 + 1 + + 0 + + + + +
diff --git a/Project.uvoptx b/Project.uvoptx new file mode 100644 index 0000000..a6ede77 --- /dev/null +++ b/Project.uvoptx @@ -0,0 +1,1076 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + Target 1 + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\Listings\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 18 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 5 + + + + + + + + + + + STLink\ST-LINKIII-KEIL_SWO.dll + + + + 0 + ARMRTXEVENTFLAGS + -L70 -Z18 -C0 -M0 -T1 + + + 0 + DLGTARM + (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0) + + + 0 + ARMDBGFLAGS + + + + 0 + DLGUARM + (105=-1,-1,-1,-1,0) + + + 0 + PWSTATINFO + 200,50,700 + + + 0 + ST-LINKIII-KEIL_SWO + -U2 -O206 -S1 -C0 -A0 -N00("ARM CoreSight SW-DP") -D00(1BA01477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO15 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_128.FLM -FS08000000 -FL020000 -FP0($$Device:STM32F103C8$Flash\STM32F10x_128.FLM) + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_128 -FS08000000 -FL020000 -FP0($$Device:STM32F103C8$Flash\STM32F10x_128.FLM)) + + + + + 0 + + + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + 1 + 0 + 2 + 10000000 + + + + + + Start + 0 + 0 + 0 + 0 + + 1 + 1 + 2 + 0 + 0 + 0 + .\Start\startup_stm32f10x_md.s + startup_stm32f10x_md.s + 0 + 0 + + + 1 + 2 + 1 + 0 + 0 + 0 + .\Start\core_cm3.c + core_cm3.c + 0 + 0 + + + 1 + 3 + 5 + 0 + 0 + 0 + .\Start\core_cm3.h + core_cm3.h + 0 + 0 + + + 1 + 4 + 5 + 0 + 0 + 0 + .\Start\stm32f10x.h + stm32f10x.h + 0 + 0 + + + 1 + 5 + 1 + 0 + 0 + 0 + .\Start\system_stm32f10x.c + system_stm32f10x.c + 0 + 0 + + + 1 + 6 + 5 + 0 + 0 + 0 + .\Start\system_stm32f10x.h + system_stm32f10x.h + 0 + 0 + + + + + Library + 0 + 0 + 0 + 0 + + 2 + 7 + 1 + 0 + 0 + 0 + .\Library\misc.c + misc.c + 0 + 0 + + + 2 + 8 + 5 + 0 + 0 + 0 + .\Library\misc.h + misc.h + 0 + 0 + + + 2 + 9 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_adc.c + stm32f10x_adc.c + 0 + 0 + + + 2 + 10 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_adc.h + stm32f10x_adc.h + 0 + 0 + + + 2 + 11 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_bkp.c + stm32f10x_bkp.c + 0 + 0 + + + 2 + 12 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_bkp.h + stm32f10x_bkp.h + 0 + 0 + + + 2 + 13 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_can.c + stm32f10x_can.c + 0 + 0 + + + 2 + 14 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_can.h + stm32f10x_can.h + 0 + 0 + + + 2 + 15 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_cec.c + stm32f10x_cec.c + 0 + 0 + + + 2 + 16 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_cec.h + stm32f10x_cec.h + 0 + 0 + + + 2 + 17 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_crc.c + stm32f10x_crc.c + 0 + 0 + + + 2 + 18 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_crc.h + stm32f10x_crc.h + 0 + 0 + + + 2 + 19 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_dac.c + stm32f10x_dac.c + 0 + 0 + + + 2 + 20 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_dac.h + stm32f10x_dac.h + 0 + 0 + + + 2 + 21 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_dbgmcu.c + stm32f10x_dbgmcu.c + 0 + 0 + + + 2 + 22 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_dbgmcu.h + stm32f10x_dbgmcu.h + 0 + 0 + + + 2 + 23 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_dma.c + stm32f10x_dma.c + 0 + 0 + + + 2 + 24 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_dma.h + stm32f10x_dma.h + 0 + 0 + + + 2 + 25 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_exti.c + stm32f10x_exti.c + 0 + 0 + + + 2 + 26 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_exti.h + stm32f10x_exti.h + 0 + 0 + + + 2 + 27 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_flash.c + stm32f10x_flash.c + 0 + 0 + + + 2 + 28 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_flash.h + stm32f10x_flash.h + 0 + 0 + + + 2 + 29 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_fsmc.c + stm32f10x_fsmc.c + 0 + 0 + + + 2 + 30 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_fsmc.h + stm32f10x_fsmc.h + 0 + 0 + + + 2 + 31 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_gpio.c + stm32f10x_gpio.c + 0 + 0 + + + 2 + 32 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_gpio.h + stm32f10x_gpio.h + 0 + 0 + + + 2 + 33 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_i2c.c + stm32f10x_i2c.c + 0 + 0 + + + 2 + 34 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_i2c.h + stm32f10x_i2c.h + 0 + 0 + + + 2 + 35 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_iwdg.c + stm32f10x_iwdg.c + 0 + 0 + + + 2 + 36 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_iwdg.h + stm32f10x_iwdg.h + 0 + 0 + + + 2 + 37 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_pwr.c + stm32f10x_pwr.c + 0 + 0 + + + 2 + 38 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_pwr.h + stm32f10x_pwr.h + 0 + 0 + + + 2 + 39 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_rcc.c + stm32f10x_rcc.c + 0 + 0 + + + 2 + 40 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_rcc.h + stm32f10x_rcc.h + 0 + 0 + + + 2 + 41 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_rtc.c + stm32f10x_rtc.c + 0 + 0 + + + 2 + 42 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_rtc.h + stm32f10x_rtc.h + 0 + 0 + + + 2 + 43 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_sdio.c + stm32f10x_sdio.c + 0 + 0 + + + 2 + 44 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_sdio.h + stm32f10x_sdio.h + 0 + 0 + + + 2 + 45 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_spi.c + stm32f10x_spi.c + 0 + 0 + + + 2 + 46 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_spi.h + stm32f10x_spi.h + 0 + 0 + + + 2 + 47 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_tim.c + stm32f10x_tim.c + 0 + 0 + + + 2 + 48 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_tim.h + stm32f10x_tim.h + 0 + 0 + + + 2 + 49 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_usart.c + stm32f10x_usart.c + 0 + 0 + + + 2 + 50 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_usart.h + stm32f10x_usart.h + 0 + 0 + + + 2 + 51 + 1 + 0 + 0 + 0 + .\Library\stm32f10x_wwdg.c + stm32f10x_wwdg.c + 0 + 0 + + + 2 + 52 + 5 + 0 + 0 + 0 + .\Library\stm32f10x_wwdg.h + stm32f10x_wwdg.h + 0 + 0 + + + + + System + 1 + 0 + 0 + 0 + + 3 + 53 + 1 + 0 + 0 + 0 + .\System\Delay.c + Delay.c + 0 + 0 + + + 3 + 54 + 1 + 0 + 0 + 0 + .\System\Debug.c + Debug.c + 0 + 0 + + + + + Hardware + 1 + 0 + 0 + 0 + + 4 + 55 + 1 + 0 + 0 + 0 + .\Hardware\OLED.c + OLED.c + 0 + 0 + + + 4 + 56 + 1 + 0 + 0 + 0 + .\Hardware\Serial.c + Serial.c + 0 + 0 + + + 4 + 57 + 1 + 0 + 0 + 0 + .\Hardware\esp8266.c + esp8266.c + 0 + 0 + + + 4 + 58 + 1 + 0 + 0 + 0 + .\Hardware\Buzzer_LED.c + Buzzer_LED.c + 0 + 0 + + + 4 + 59 + 1 + 0 + 0 + 0 + .\Hardware\K210_USART.c + K210_USART.c + 0 + 0 + + + 4 + 60 + 1 + 0 + 0 + 0 + .\Hardware\Attendance.c + Attendance.c + 0 + 0 + + + 4 + 61 + 1 + 0 + 0 + 0 + .\Hardware\aes.c + aes.c + 0 + 0 + + + 4 + 62 + 1 + 0 + 0 + 0 + .\Hardware\base64.c + base64.c + 0 + 0 + + + 4 + 63 + 1 + 0 + 0 + 0 + .\Hardware\Crypto.c + Crypto.c + 0 + 0 + + + 4 + 64 + 1 + 0 + 0 + 0 + .\Hardware\DS1302.c + DS1302.c + 0 + 0 + + + 4 + 65 + 1 + 0 + 0 + 0 + .\Hardware\LightSensor.c + LightSensor.c + 0 + 0 + + + + + User + 1 + 0 + 0 + 0 + + 5 + 66 + 1 + 0 + 0 + 0 + .\User\main.c + main.c + 0 + 0 + + + 5 + 67 + 5 + 0 + 0 + 0 + .\User\stm32f10x_conf.h + stm32f10x_conf.h + 0 + 0 + + + 5 + 68 + 1 + 0 + 0 + 0 + .\User\stm32f10x_it.c + stm32f10x_it.c + 0 + 0 + + + 5 + 69 + 5 + 0 + 0 + 0 + .\User\stm32f10x_it.h + stm32f10x_it.h + 0 + 0 + + + +
diff --git a/Project.uvprojx b/Project.uvprojx new file mode 100644 index 0000000..e247b71 --- /dev/null +++ b/Project.uvprojx @@ -0,0 +1,761 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + Target 1 + 0x4 + ARM-ADS + 5060183::V5.06 update 2 (build 183)::ARMCC + 0 + + + STM32F103C8 + STMicroelectronics + Keil.STM32F1xx_DFP.1.1.0 + http://www.keil.com/pack/ + IRAM(0x20000000,0x5000) IROM(0x08000000,0x10000) CPUTYPE("Cortex-M3") CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_128 -FS08000000 -FL020000 -FP0($$Device:STM32F103C8$Flash\STM32F10x_128.FLM)) + 0 + $$Device:STM32F103C8$Device\Include\stm32f10x.h + + + + + + + + + + $$Device:STM32F103C8$SVD\STM32F103xx.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\Objects\ + Project + 1 + 0 + 0 + 1 + 1 + .\Listings\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 0 + -1 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x5000 + + + 1 + 0x8000000 + 0x10000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x10000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x5000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + --no-multibyte-chars + STM32F10X_MD,USE_STDPERIPH_DRIVER + + .\Start;.\Library;.\User;.\System;.\Hardware + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Start + + + startup_stm32f10x_md.s + 2 + .\Start\startup_stm32f10x_md.s + + + core_cm3.c + 1 + .\Start\core_cm3.c + + + core_cm3.h + 5 + .\Start\core_cm3.h + + + stm32f10x.h + 5 + .\Start\stm32f10x.h + + + system_stm32f10x.c + 1 + .\Start\system_stm32f10x.c + + + system_stm32f10x.h + 5 + .\Start\system_stm32f10x.h + + + + + Library + + + misc.c + 1 + .\Library\misc.c + + + misc.h + 5 + .\Library\misc.h + + + stm32f10x_adc.c + 1 + .\Library\stm32f10x_adc.c + + + stm32f10x_adc.h + 5 + .\Library\stm32f10x_adc.h + + + stm32f10x_bkp.c + 1 + .\Library\stm32f10x_bkp.c + + + stm32f10x_bkp.h + 5 + .\Library\stm32f10x_bkp.h + + + stm32f10x_can.c + 1 + .\Library\stm32f10x_can.c + + + stm32f10x_can.h + 5 + .\Library\stm32f10x_can.h + + + stm32f10x_cec.c + 1 + .\Library\stm32f10x_cec.c + + + stm32f10x_cec.h + 5 + .\Library\stm32f10x_cec.h + + + stm32f10x_crc.c + 1 + .\Library\stm32f10x_crc.c + + + stm32f10x_crc.h + 5 + .\Library\stm32f10x_crc.h + + + stm32f10x_dac.c + 1 + .\Library\stm32f10x_dac.c + + + stm32f10x_dac.h + 5 + .\Library\stm32f10x_dac.h + + + stm32f10x_dbgmcu.c + 1 + .\Library\stm32f10x_dbgmcu.c + + + stm32f10x_dbgmcu.h + 5 + .\Library\stm32f10x_dbgmcu.h + + + stm32f10x_dma.c + 1 + .\Library\stm32f10x_dma.c + + + stm32f10x_dma.h + 5 + .\Library\stm32f10x_dma.h + + + stm32f10x_exti.c + 1 + .\Library\stm32f10x_exti.c + + + stm32f10x_exti.h + 5 + .\Library\stm32f10x_exti.h + + + stm32f10x_flash.c + 1 + .\Library\stm32f10x_flash.c + + + stm32f10x_flash.h + 5 + .\Library\stm32f10x_flash.h + + + stm32f10x_fsmc.c + 1 + .\Library\stm32f10x_fsmc.c + + + stm32f10x_fsmc.h + 5 + .\Library\stm32f10x_fsmc.h + + + stm32f10x_gpio.c + 1 + .\Library\stm32f10x_gpio.c + + + stm32f10x_gpio.h + 5 + .\Library\stm32f10x_gpio.h + + + stm32f10x_i2c.c + 1 + .\Library\stm32f10x_i2c.c + + + stm32f10x_i2c.h + 5 + .\Library\stm32f10x_i2c.h + + + stm32f10x_iwdg.c + 1 + .\Library\stm32f10x_iwdg.c + + + stm32f10x_iwdg.h + 5 + .\Library\stm32f10x_iwdg.h + + + stm32f10x_pwr.c + 1 + .\Library\stm32f10x_pwr.c + + + stm32f10x_pwr.h + 5 + .\Library\stm32f10x_pwr.h + + + stm32f10x_rcc.c + 1 + .\Library\stm32f10x_rcc.c + + + stm32f10x_rcc.h + 5 + .\Library\stm32f10x_rcc.h + + + stm32f10x_rtc.c + 1 + .\Library\stm32f10x_rtc.c + + + stm32f10x_rtc.h + 5 + .\Library\stm32f10x_rtc.h + + + stm32f10x_sdio.c + 1 + .\Library\stm32f10x_sdio.c + + + stm32f10x_sdio.h + 5 + .\Library\stm32f10x_sdio.h + + + stm32f10x_spi.c + 1 + .\Library\stm32f10x_spi.c + + + stm32f10x_spi.h + 5 + .\Library\stm32f10x_spi.h + + + stm32f10x_tim.c + 1 + .\Library\stm32f10x_tim.c + + + stm32f10x_tim.h + 5 + .\Library\stm32f10x_tim.h + + + stm32f10x_usart.c + 1 + .\Library\stm32f10x_usart.c + + + stm32f10x_usart.h + 5 + .\Library\stm32f10x_usart.h + + + stm32f10x_wwdg.c + 1 + .\Library\stm32f10x_wwdg.c + + + stm32f10x_wwdg.h + 5 + .\Library\stm32f10x_wwdg.h + + + + + System + + + Delay.c + 1 + .\System\Delay.c + + + Debug.c + 1 + .\System\Debug.c + + + + + Hardware + + + OLED.c + 1 + .\Hardware\OLED.c + + + Serial.c + 1 + .\Hardware\Serial.c + + + esp8266.c + 1 + .\Hardware\esp8266.c + + + Buzzer_LED.c + 1 + .\Hardware\Buzzer_LED.c + + + K210_USART.c + 1 + .\Hardware\K210_USART.c + + + Attendance.c + 1 + .\Hardware\Attendance.c + + + aes.c + 1 + .\Hardware\aes.c + + + base64.c + 1 + .\Hardware\base64.c + + + Crypto.c + 1 + .\Hardware\Crypto.c + + + DS1302.c + 1 + .\Hardware\DS1302.c + + + LightSensor.c + 1 + .\Hardware\LightSensor.c + + + + + User + + + main.c + 1 + .\User\main.c + + + stm32f10x_conf.h + 5 + .\User\stm32f10x_conf.h + + + stm32f10x_it.c + 1 + .\User\stm32f10x_it.c + + + stm32f10x_it.h + 5 + .\User\stm32f10x_it.h + + + + + + + + + + + + + +
diff --git a/QT/.gitignore b/QT/.gitignore new file mode 100644 index 0000000..bcc1bca --- /dev/null +++ b/QT/.gitignore @@ -0,0 +1,59 @@ +# Build directories +build/ +build-*/ +cmake-build-*/ +out/ +dist/ + +# CMake generated files +CMakeCache.txt +CMakeFiles/ +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +DartConfiguration.tcl + +# Qt Creator local settings +.qtcreator/ +*.user +*.user.* + +# Qt generated artifacts +*_autogen/ +*.qmlc +*.jsc +qrc_*.cpp +moc_*.cpp +moc_*.h +ui_*.h + +# Compiled binaries and libraries +*.exe +*.dll +*.so +*.dylib +*.a +*.lib +*.o +*.obj +*.pdb +*.ilk + +# Android build outputs +android-build/ +*.apk +*.aab + +# Logs and temporary files +*.log +*.tmp +*.temp +*.bak +*.swp +*~ + +# OS files +.DS_Store +Thumbs.db +desktop.ini diff --git a/QT/CMakeLists.txt b/QT/CMakeLists.txt new file mode 100644 index 0000000..3b7a7ed --- /dev/null +++ b/QT/CMakeLists.txt @@ -0,0 +1,145 @@ +cmake_minimum_required(VERSION 3.16) + +project(rewrite_qt VERSION 1.0.0 LANGUAGES CXX) + +set(REWRITE_QT_DISPLAY_NAME "人脸识别考勤系统") +set(QT_QML_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/qml") +set(REWRITE_QT_OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dist") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${REWRITE_QT_OUTPUT_DIR}") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${REWRITE_QT_OUTPUT_DIR}") +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${REWRITE_QT_OUTPUT_DIR}") +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOMOC_COMPILER_PREDEFINES OFF) +set(CMAKE_AUTORCC ON) + +file(TO_CMAKE_PATH "$ENV{LOCALAPPDATA}" REWRITE_QT_LOCALAPPDATA) +if(REWRITE_QT_LOCALAPPDATA) + set(REWRITE_QT_AUTOGEN_DIR "${REWRITE_QT_LOCALAPPDATA}/rewrite_qt_autogen") +else() + set(REWRITE_QT_AUTOGEN_DIR "${CMAKE_BINARY_DIR}/autogen_ascii") +endif() +file(MAKE_DIRECTORY "${REWRITE_QT_AUTOGEN_DIR}") + +find_package(Qt6 6.2 REQUIRED COMPONENTS Core Gui Qml Quick QuickControls2 Network) + +get_target_property(REWRITE_QT_QMAKE_EXECUTABLE Qt6::qmake IMPORTED_LOCATION) +if(REWRITE_QT_QMAKE_EXECUTABLE) + execute_process( + COMMAND "${REWRITE_QT_QMAKE_EXECUTABLE}" -query QT_INSTALL_QML + OUTPUT_VARIABLE REWRITE_QT_INSTALL_QML + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +endif() + +qt_standard_project_setup() + +set(REWRITE_QT_APP_ICON "${CMAKE_CURRENT_SOURCE_DIR}/assets/favicon.ico") +set(REWRITE_QT_ICON_RESOURCES + assets/favicon.ico + assets/favicon-256x256.png + assets/favicon-192x192.png + assets/favicon-128x128.png + assets/favicon-64x64.png + assets/favicon-48x48.png + assets/favicon-32x32.png + assets/favicon-16x16.png +) + +qt_add_executable(apprewrite_qt + main.cpp + src/AppController.cpp + src/ApiClient.cpp + src/CryptoUtils.cpp + src/RecordListModel.cpp + src/StatisticsListModel.cpp + src/TimeSlotListModel.cpp + src/MappingListModel.cpp + src/FaceListModel.cpp +) + +if(REWRITE_QT_INSTALL_QML) + target_compile_definitions(apprewrite_qt PRIVATE + REWRITE_QT_INSTALL_QML="${REWRITE_QT_INSTALL_QML}" + ) +endif() + +if(WIN32 AND EXISTS "${REWRITE_QT_APP_ICON}") + set(REWRITE_QT_WIN32_ICON_RC "${CMAKE_CURRENT_BINARY_DIR}/app_icon.rc") + configure_file(cmake/app_icon.rc.in "${REWRITE_QT_WIN32_ICON_RC}" @ONLY) + target_sources(apprewrite_qt PRIVATE "${REWRITE_QT_WIN32_ICON_RC}") +endif() + +if(ANDROID) + set_target_properties(apprewrite_qt PROPERTIES + QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android" + QT_ANDROID_APP_NAME "${REWRITE_QT_DISPLAY_NAME}" + QT_ANDROID_APP_ICON "@mipmap/ic_launcher" + ) +endif() + +target_include_directories(apprewrite_qt PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src +) + +set(REWRITE_QT_RESOURCE_FILES + qml/Main.qml +) + +foreach(REWRITE_QT_ICON_RESOURCE IN LISTS REWRITE_QT_ICON_RESOURCES) + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${REWRITE_QT_ICON_RESOURCE}") + list(APPEND REWRITE_QT_RESOURCE_FILES "${REWRITE_QT_ICON_RESOURCE}") + endif() +endforeach() + +qt_add_resources(apprewrite_qt "qml_resources" + PREFIX "/" + FILES + ${REWRITE_QT_RESOURCE_FILES} +) + +target_link_libraries(apprewrite_qt + PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Qml + Qt6::Quick + Qt6::QuickControls2 + Qt6::Network +) + +set_target_properties(apprewrite_qt PROPERTIES + AUTOGEN_BUILD_DIR "${REWRITE_QT_AUTOGEN_DIR}" + QT_QML_MODULE_NO_IMPORT_SCAN TRUE + MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} + MACOSX_BUNDLE TRUE + WIN32_EXECUTABLE TRUE +) + +include(GNUInstallDirs) + +if(UNIX AND NOT APPLE AND NOT ANDROID) + set(REWRITE_QT_DESKTOP_FILE "${CMAKE_CURRENT_BINARY_DIR}/rewrite_qt.desktop") + configure_file(cmake/rewrite_qt.desktop.in "${REWRITE_QT_DESKTOP_FILE}" @ONLY) + install(FILES "${REWRITE_QT_DESKTOP_FILE}" + DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications" + ) + + foreach(REWRITE_QT_ICON_SIZE IN ITEMS 16 32 48 64 128 192 256) + set(REWRITE_QT_LINUX_ICON "${CMAKE_CURRENT_SOURCE_DIR}/assets/favicon-${REWRITE_QT_ICON_SIZE}x${REWRITE_QT_ICON_SIZE}.png") + if(EXISTS "${REWRITE_QT_LINUX_ICON}") + install(FILES "${REWRITE_QT_LINUX_ICON}" + DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${REWRITE_QT_ICON_SIZE}x${REWRITE_QT_ICON_SIZE}/apps" + RENAME rewrite_qt.png + ) + endif() + endforeach() +endif() + +install(TARGETS apprewrite_qt + BUNDLE DESTINATION . + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +) diff --git a/QT/LICENSE b/QT/LICENSE new file mode 100644 index 0000000..c46d1f4 --- /dev/null +++ b/QT/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Jitianye + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/QT/README.md b/QT/README.md new file mode 100644 index 0000000..92d1a45 --- /dev/null +++ b/QT/README.md @@ -0,0 +1,517 @@ +# 人脸识别考勤系统 + +基于 Qt 6 Quick/QML 开发的跨平台人脸识别考勤管理客户端,用于连接考勤服务端,完成签到记录查看、筛选导出、统计分析、签到时段配置、学生与班级名称映射、人脸照片与学号绑定等管理工作。 + +本项目是纪田野的个人毕业设计作品,主要用于人脸识别考勤场景的功能展示、系统联调和学习研究。 + +## 项目特点 + +- 跨平台客户端:支持 Windows 桌面端和 Android 端构建。 +- 单窗口管理:考勤记录、统计分析、配置中心、人脸管理和系统说明集中在一个界面中。 +- 响应式界面:针对手机窄屏做了独立布局适配,避免控件重叠和文字遮挡。 +- 数据导出:支持将考勤记录和统计报表导出为 CSV 文件。 +- 本地配置缓存:服务端地址、签到时段、映射配置会保存到本地。 +- 自动重连:服务端不可达时自动重连,并使用简短状态提示。 +- Android 字体优化:Android 端使用原生文字渲染,并降低粗体权重,减少中文粗体重影。 +- Android 路径兼容:Gradle 配置已允许中文路径构建,并启用 AndroidX。 + +## 技术栈 + +| 分类 | 内容 | +| --- | --- | +| 开发语言 | C++17、QML | +| UI 框架 | Qt Quick / Qt Quick Controls 2 | +| Qt 模块 | Core、Gui、Qml、Quick、QuickControls2、Network | +| 构建系统 | CMake 3.16+ | +| 桌面编译器 | MinGW / MSVC / Clang / GCC | +| Android 构建 | Qt for Android、Android SDK、Android NDK、JDK | +| 加密处理 | AES-128-CBC,代码位于 `src/CryptoUtils.cpp` | + +## 目录结构 + +```text +rewrite_qt/ +├── android/ # Android 打包补充资源和 Gradle 配置 +│ ├── gradle.properties +│ └── res/mipmap-*/ # Android 启动图标 +├── assets/ # 桌面端图标资源 +├── cmake/ # 平台相关模板文件 +├── qml/ +│ └── Main.qml # 主界面 +├── src/ +│ ├── ApiClient.* # 服务端 API 客户端 +│ ├── AppController.* # QML 与业务逻辑中枢 +│ ├── AttendanceTypes.h # 考勤数据结构 +│ ├── CryptoUtils.* # AES 解密工具 +│ ├── *ListModel.* # 暴露给 QML 的列表模型 +│ └── crypto/tiny_aes.hpp # AES 底层实现 +├── CMakeLists.txt +├── LICENSE +├── README.md +└── main.cpp +``` + +## 功能说明 + +### 考勤记录 + +考勤记录页用于查看和管理服务端同步下来的签到记录。 + +- 查看总记录数、今日签到数、当前筛选结果数。 +- 按班级、学号、姓名关键字筛选记录。 +- 按全部时间、今天、最近 7 天、最近 30 天、指定日期筛选。 +- 刷新最新记录。 +- 导出当前筛选结果为 CSV。 +- 清空服务端全部考勤记录。 + +导出字段: + +```text +签到时间,班级编号,班级名称,学号,姓名,置信度,状态 +``` + +### 统计分析 + +统计分析页基于当前加载的考勤记录在本地计算统计结果。 + +- 支持今天、最近 7 天、最近 30 天、本月等快捷范围。 +- 支持手动指定开始日期和结束日期。 +- 展示统计学生数、统计记录数、统计范围。 +- 按学生汇总总签到次数、今日签到次数、最后签到时间和平均置信度。 +- 导出统计报表为 CSV。 + +导出字段: + +```text +学号,姓名,总签到次数,今日签到,最后签到时间,平均置信度 +``` + +### 配置中心 + +配置中心用于维护客户端与服务端交互所需的配置。 + +- 设置服务端地址。 +- 测试服务端连接状态。 +- 管理签到时段。 +- 从服务端同步签到时段。 +- 管理学号到姓名的映射。 +- 管理班级编号到班级名称的映射。 +- 保存配置并同步到服务端。 + +默认签到时段: + +| 名称 | 开始时间 | 结束时间 | 默认状态 | +| --- | --- | --- | --- | +| 上午签到 | 08:00 | 09:30 | 启用 | +| 中午签退 | 12:00 | 13:00 | 启用 | +| 下午签到 | 14:00 | 15:00 | 启用 | +| 晚上签退 | 17:00 | 18:30 | 启用 | + +### 人脸管理 + +人脸管理页用于维护 K210 上传的人脸照片记录与真实学号之间的映射关系。 + +- 同步人脸照片 ID。 +- 同步服务端学生 ID。 +- 展示人脸照片或无照片状态。 +- 为人脸 ID 绑定真实学号。 +- 保存人脸 ID 与学号映射。 +- 删除指定人脸信息。 +- 可选择同时删除该学生相关考勤记录。 + +照片访问地址格式: + +```text +{serverUrl}/api/face_photo/{id}?ts={timestamp} +``` + +其中 `ts` 用于避免缓存导致照片不刷新。 + +## 服务端配置 + +默认服务端地址: + +```text +http://127.0.0.1:8082 +``` + +应用启动后会从本地配置读取已保存的服务端地址。用户可在“配置中心”中修改并保存。 + +本地保存键名: + +```text +server/url +``` + +## 服务端 API + +客户端会基于服务端地址拼接 `/api` 前缀访问接口。 + +| 方法 | 路径 | 用途 | +| --- | --- | --- | +| `GET` | `/api/records?limit={limit}&offset={offset}` | 获取考勤记录 | +| `GET` | `/api/statistics` | 获取总数、今日数和服务端时间 | +| `POST` | `/api/clear` | 清空全部记录 | +| `DELETE` | `/api/record?timestamp={timestamp}&student_id={studentId}` | 删除单条记录 | +| `GET` | `/api/timeslots` | 获取签到时段 | +| `POST` | `/api/timeslots` | 保存签到时段 | +| `GET` | `/api/mapping_config` | 获取学生和班级映射 | +| `POST` | `/api/mapping_config` | 保存学生和班级映射 | +| `GET` | `/api/face_id_mapping` | 获取人脸 ID 到学号映射 | +| `POST` | `/api/face_id_mapping` | 保存人脸 ID 到学号映射 | +| `GET` | `/api/face_photos` | 获取照片 ID 列表 | +| `GET` | `/api/all_student_ids` | 获取所有学生 ID | +| `GET` | `/api/face_photo/{id}` | 获取人脸照片 | +| `DELETE` | `/api/face/{studentId}` | 删除人脸信息 | +| `DELETE` | `/api/face/{studentId}?delete_records=true` | 删除人脸信息并删除相关考勤记录 | +| `GET` | `/api/health` | 健康检查 | + +### 考勤记录格式 + +`/api/records` 解密后应返回 JSON 数组。单条记录示例: + +```json +{ + "timestamp": "2026-04-24 08:10:23", + "student_id": "20240001", + "name": "张三", + "confidence": 0.9821, + "status": "success", + "class_id": "1" +} +``` + +### 统计数据格式 + +```json +{ + "total": 120, + "today": 8, + "server_time": "2026-04-24 10:30:00" +} +``` + +### 签到时段格式 + +```json +{ + "time_slots": [ + { + "name": "上午签到", + "start_time": "08:00", + "end_time": "09:30", + "enabled": true + } + ] +} +``` + +### 映射配置格式 + +```json +{ + "student_name_map": { + "20240001": "张三" + }, + "class_name_map": { + "1": "软件工程一班" + } +} +``` + +### 人脸映射格式 + +```json +{ + "mappings": { + "face_001": "20240001" + } +} +``` + +## 加密响应 + +客户端对 `/api/records` 和 `/api/statistics` 请求添加请求头: + +```text +X-Encrypted-Response: true +``` + +客户端期望服务端返回 Base64 编码的 AES-128-CBC 密文。 + +解密参数位于 `src/CryptoUtils.cpp`: + +| 参数 | 值 | +| --- | --- | +| 算法 | AES-128-CBC | +| Padding | PKCS#7 | +| Key | `2b 7e 15 16 28 ae d2 a6 ab f7 15 88 09 cf 4f 3c` | +| IV | `00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f` | + +## 本地配置文件 + +应用使用 `QSettings` 和 `QStandardPaths::AppDataLocation` 保存本地状态。 + +| 配置 | 保存位置 | +| --- | --- | +| 服务端地址 | `QSettings`,键名 `server/url` | +| 学生和班级映射 | `mapping_config.json` | +| 签到时段配置 | `timeslot_config.json` | + +应用信息: + +```text +ApplicationName: 人脸识别考勤系统 +ApplicationVersion: 3.0.0 +OrganizationName: STM32 Face Recognition +``` + +## 构建环境 + +### 基础要求 + +- Qt 6.2 或更高版本 +- CMake 3.16 或更高版本 +- 支持 C++17 的编译器 + +Windows 桌面端推荐使用 Qt 6.x MinGW 64-bit Kit。 + +Android 端需要额外配置: + +- Qt for Android +- Android SDK +- Android NDK +- JDK +- Android 平台版本,例如 `android-35` + +## 使用 Qt Creator 构建 + +1. 打开 Qt Creator。 +2. 选择项目根目录下的 `CMakeLists.txt`。 +3. 选择对应 Kit,例如 Desktop Qt 6.x 或 Qt for Android。 +4. 等待 CMake 配置完成。 +5. 构建目标 `apprewrite_qt`。 +6. 桌面端可直接运行;Android 端可部署到设备或模拟器。 + +## 命令行构建 + +Windows 示例: + +```powershell +cmake -S . -B build -DCMAKE_PREFIX_PATH=D:/Qt/6.10.0/mingw_64 +cmake --build build --target apprewrite_qt +``` + +Linux 示例: + +```bash +cmake -S . -B build -DCMAKE_PREFIX_PATH=/path/to/Qt/6.x/gcc_64 +cmake --build build --target apprewrite_qt +``` + +安装到系统路径: + +```bash +cmake --install build +``` + +## Windows 独立运行 + +直接双击构建出来的 `apprewrite_qt.exe` 时,如果提示找不到 `Qt6Gui.dll`、`Qt6Core.dll` 等动态库,需要使用 `windeployqt` 收集运行时依赖。 + +示例: + +```powershell +D:\Qt\6.10.0\mingw_64\bin\windeployqt.exe "D:\path\to\build\Desktop_Qt_6_10_0_MinGW_64_bit-Debug\apprewrite_qt.exe" +``` + +如果项目路径包含中文导致部署工具输出异常,建议复制 exe 到纯英文路径后部署: + +```powershell +mkdir C:\tmp\rewrite_qt_release +copy "D:\path\to\apprewrite_qt.exe" C:\tmp\rewrite_qt_release\ +D:\Qt\6.10.0\mingw_64\bin\windeployqt.exe C:\tmp\rewrite_qt_release\apprewrite_qt.exe +``` + +部署完成后,将整个发布目录一起复制到目标电脑运行。 + +## Android 构建说明 + +Android 相关配置位于 `CMakeLists.txt`: + +```cmake +QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android" +QT_ANDROID_APP_NAME "${REWRITE_QT_DISPLAY_NAME}" +QT_ANDROID_APP_ICON "@mipmap/ic_launcher" +``` + +Android 补充配置位于 `android/gradle.properties`: + +```properties +android.overridePathCheck=true +android.useAndroidX=true +``` + +说明: + +- `android.overridePathCheck=true` 用于绕过 Windows 下 Android Gradle 对中文路径的检查。 +- `android.useAndroidX=true` 用于启用 AndroidX,避免依赖检查失败。 +- Android 桌面显示名由 `QT_ANDROID_APP_NAME` 设置为“人脸识别考勤系统”。 +- Android 启动图标位于 `android/res/mipmap-*`。 + +如果 Android 构建目录已经生成过旧的 Gradle 工程,修改配置后建议清理对应构建目录或重新运行 CMake 配置。 + +## 图标资源 + +桌面端图标位于 `assets/`: + +```text +assets/favicon.ico +assets/favicon-16x16.png +assets/favicon-32x32.png +assets/favicon-48x48.png +assets/favicon-64x64.png +assets/favicon-128x128.png +assets/favicon-192x192.png +assets/favicon-256x256.png +``` + +Android 启动图标位于: + +```text +android/res/mipmap-mdpi/ic_launcher.png +android/res/mipmap-hdpi/ic_launcher.png +android/res/mipmap-xhdpi/ic_launcher.png +android/res/mipmap-xxhdpi/ic_launcher.png +android/res/mipmap-xxxhdpi/ic_launcher.png +``` + +图标尺寸: + +| 目录 | 尺寸 | +| --- | --- | +| `mipmap-mdpi` | 48x48 | +| `mipmap-hdpi` | 72x72 | +| `mipmap-xhdpi` | 96x96 | +| `mipmap-xxhdpi` | 144x144 | +| `mipmap-xxxhdpi` | 192x192 | + +## 界面与移动端适配 + +主界面位于 `qml/Main.qml`,采用 `ApplicationWindow`、`StackLayout`、`GridLayout`、`ColumnLayout` 等组件组织页面。 + +当前界面包含五个页面: + +- 考勤记录 +- 统计分析 +- 配置中心 +- 人脸管理 +- 关于 + +移动端适配要点: + +- `phoneLayout` 用于 560px 以下窄屏布局。 +- 顶部页签使用统一的 `MobileNavTabButton` 样式。 +- 考勤筛选区使用两列布局,按钮等宽排布。 +- 统计页前两张统计卡左右排布,统计范围独占一整行。 +- 表格在窄屏隐藏部分非关键列,避免横向溢出。 +- 空状态卡片会根据可用高度自动缩小。 +- Android 端使用 `sans-serif` 字体和 `Font.Medium` 加粗权重,减少粗体重影。 + +## 运行状态提示 + +客户端通过底部 Toast 展示状态信息。服务端不可达时,提示会被压缩为简短文案: + +```text +服务器未连接,稍后重试 +``` + +重连过程中显示: + +```text +正在重连服务器 +``` + +这样可以避免将底层网络错误、URL 和长异常文本直接展示给用户。 + +## 常见问题 + +### Android 构建提示项目路径包含中文 + +项目已经在 `android/gradle.properties` 中配置: + +```properties +android.overridePathCheck=true +``` + +如果仍然失败,清理 Android 构建目录后重新构建。 + +### Android 构建提示 AndroidX 未启用 + +项目已经在 `android/gradle.properties` 中配置: + +```properties +android.useAndroidX=true +``` + +如果旧构建目录仍然报错,删除生成的 `android-build-*` 目录后重新部署。 + +### Android 端粗体文字重影 + +项目在 Android 端启用了原生文字渲染: + +```cpp +QQuickWindow::setTextRenderType(QQuickWindow::NativeTextRendering); +``` + +同时 QML 中将 Android 端粗体权重降为 `Font.Medium`,避免合成粗体产生重影。 + +### Windows 双击 exe 提示缺少 Qt DLL + +使用 `windeployqt` 部署依赖后再运行。部署时建议使用和构建 Kit 一致的 Qt 目录。 + +### 修改图标后没有变化 + +重新运行 CMake 配置并重新构建。Windows 资源管理器可能缓存 exe 图标,可尝试换构建目录、改输出文件名或重启资源管理器。 + +### 启动后没有数据 + +检查服务端地址是否正确,并在配置中心点击“测试连接”。如果服务端不可达,底部会显示简短连接失败提示。 + +### 姓名或班级显示不正确 + +在配置中心维护学生姓名映射和班级名称映射,保存后记录列表和统计结果会重新计算。 + +### 人脸照片不显示 + +检查 `/api/face_photos` 是否返回照片 ID,并确认 `/api/face_photo/{id}` 可以访问。 + +## 仓库与作者 + +仓库地址: + +```text +ssh://git@git.yzfh.eu.cc:2084/yzfh/qt.git +``` + +作者: + +```text +纪田野 +``` + +关于页中也展示了仓库地址和查看账号信息。若项目公开发布,请避免在仓库中提交真实密码。 + +## 维护建议 + +- 不要提交 `build/`、`build-codex/` 等构建目录。 +- 修改 QML 后建议运行 `qmlformat` 保持格式一致。 +- 服务端记录量超过 1000 条时,需要扩展分页加载逻辑。 +- 服务端加密参数变化时,需要同步修改 `src/CryptoUtils.cpp`。 +- 发布桌面版本时,使用 Qt 部署工具收集运行时依赖。 +- 发布 Android 版本时,建议补充签名配置和 release 构建流程。 +- 如果需要修改历史提交作者,请在推送前完成,避免远程协作历史冲突。 + +## 开源协议 + +本项目采用 MIT License 开源,详见 `LICENSE` 文件。 diff --git a/QT/android/gradle.properties b/QT/android/gradle.properties new file mode 100644 index 0000000..b383ead --- /dev/null +++ b/QT/android/gradle.properties @@ -0,0 +1,2 @@ +android.overridePathCheck=true +android.useAndroidX=true diff --git a/QT/android/res/mipmap-hdpi/ic_launcher.png b/QT/android/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..cb9bd6ef2559cc3c431c75ac2b226807870b7e09 GIT binary patch literal 9022 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 FV1ldqlrI1P literal 0 HcmV?d00001 diff --git a/QT/android/res/mipmap-xxhdpi/ic_launcher.png b/QT/android/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..b3651fb3f242bde79eda867731fb9dd60db25f01 GIT binary patch literal 27543 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%0D7|V<@pQ+S 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 literal 0 HcmV?d00001 diff --git a/QT/assets/favicon-128x128.png b/QT/assets/favicon-128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..808a71a636cbd3293aa57d212e25b39c71690085 GIT binary patch literal 19939 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%0AaB+V^ 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
  • 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 literal 0 HcmV?d00001 diff --git a/QT/assets/favicon-32x32.png b/QT/assets/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..59d5a42323dc81f74ba69bad202dc5c033c50e96 GIT binary patch literal 1887 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 literal 0 HcmV?d00001 diff --git a/QT/assets/favicon-64x64.png b/QT/assets/favicon-64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..e979620f6a4b0008399b95e7de73634cd1b8aadb GIT binary patch literal 6105 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

    P6KsAd%k|K zKbL?1>Y)vO`122N)5%TNR%bbPNs&$hTZ@4w99-r9dHNAvdN>>0ji^0Zea`C2EU%6gA%#4#BHnAr#i=_t2Y&VDWBmGU$N8?y z5Af4ZxR4iIxXxd_j-7E9i6)j@vk85eVK)^W$VB|rVuqx|kY zXV_RK2*Nz%!>JXi>KZ;lhi?Lm1U~)HCZ9dN$qO#r!}Bj(3xt*x9(K z^A^dyyx!IoHy@y-}5f#byw_TYZ%!c27d6d2l?IST*kp! z$8X(rl4t+rZT!YkLn+vO5=E{Cxf>iq>R|JQYSfpHWloa{EeP>9(t1sS5v*Ops zS-Vb&hOulzPm_I=puaJYX90C>Kyu&f{jKi&=X}l6P!@!!^@`MgW;kw@N>wQCpArH= z#vCHb$UuJ(!Zv~G-(n=$nAFhoB8ec0WrC-izs^$*u5stt1)n^z1+!4LY+>;Y&1fh8 z#0)93us-iNwH$cUXYb)1w;X2{g!eq>a<1J!<5idJ^=FTfXh) z(AFj!YQ5s8`Z6a4l2rorqO`EDj5>(6yu>UwTT3hiW}yK__fv&>zh_?S+(CeG zbPQfp5N&y?q`= z{^U&$^41$4WNo!4A;oxV5z97M`1&=;3QwxANZzY()9Ed4I=RUc59WmQV@Efc&+^E| zts|=MN~zjpujt_PAO(4HewJ{m!9GZKX;GS+JfnQC?;#(TmE1-STePT4l}OgPLBCrH zB?1ysS+OQ%nC0LJB}&EP*3$vHNhB16S;ol9Jn)^D?n8k0-+v}=#uv#af!n&n8q55g zowsym+ZzDJy?Wd3jkagi%AI^QxL0Q{lMq zx7xvCNc`S?ry)gNb9fmQWE}D()0d*Np|our z5kqu4tXg$e`s(#U(!buM{EAj*wPycHOi2QD!Bb;-+O|WO`uln{7eMkaV=YqTSr_i* z@%vY~`SdoQIq`0=kk!1d3*l6yB7{KyUW)6YWV znfY%tfh8N!NbTFnOlj#Padt=`11A^xr*GeK^~GFw{zV+$9{9x3hxz0CPjJt(&$VyploR?yiodHq@Sj7a~vMQe^Wx@AdU}JmWn-0!-$1@(!^AB~zb2oE% z^A27UmazXk-hA0pIUXM~sAixJ7 zI1QaY`$w8>=yo2CSH5{e<|w&IB*UT@nUx1R$^Z1>YP8kZEoX9G2Cb614mK7GzWd5U z{I_RZ$=b%3S>EtY(y=cR<2GX)5$OnfuHew6-^tHD;VnG<;2Pii*}I4_mESh<8q7|k zg~|r(RBjDkIn;G#>m*Uj7buFPvNcT4ocDqd+M`}dtg&N9lva(2W}T%jpgkFJ^Gm@YL`pY<&7H#D_jjqDQ*D^s@tW{T^iNDBEBA_iWzq zuX+8Yd-+dKy@bUupueV~yM{AgHQ!L@s*^m#XPfr_xDjK|_Ihi$Cn4;Hr6afCZ6#YaQQy@qS3z0O+W( zUai=TQPVUtr!t#+$ma;?vv!`Z)NNh$H;^X(OeV1yLCwIaT@X6h9tK`|(LSEJZ^rh` zzd{%`A*?mZM0!}Bpu6Z5^iO{ma`4&2yZ$R_;~V_*$6Y}UbeRtuQYUBR6#ktv82{Ff zQ@$EWsG}^8eGmyUVOZhE!@8MAO0H9hisf=(CT(9b>2tb|v1zkx$@RNq>+^9(TMg3LR(7zM>Y>@m zC6>i0*X-SkY}|pwO-LjCMc+z)_$A1228QGGM_x{N{LdkwC*Jalj1T@fvU&mIxtlp4 z@Tm0_Qi}C>8vjq_FPU~bQBPr7~u(TgD_{j z?VSv_|2p&sA)X^HHvm}I-#HADtD;4&b+19v5RaDbP3SmUi!8EkQVkg{l;k>1_S9Sl za1(qxly9C~zV;QR+%igSwu#)SyOQ4(W^_S<7CnN%xEy)Wk^Nk>I^#3P&+(Ph8?3lZ z6u}`u%{fA&G_57*1=~ymjPLC0~Jnfvu4dN}o zNO;^&AlLm2jN3?9WxV~@7;gDbq}joe%8Ya?7Z8Et!vIn;0Yf5BcOgoWLQre4`ka=7 z6IE8t`g3JCf7jb@>rS9_dar($8*(Oz)2(} z=AE!TMurihNQS+bnrHNV5TO^bWrDiZtgcvc9s~xVRrylOZQf|~AP32dK6TVFkaq@I zg1T7p=l9*u%OCdyWbGn|=NRvLcSf3PejNIB#ykHr!!5rAvx8{OG^K%X{xi9E3Ab); z(}iFKp{fh1vTQ`EtF?kDotP#@s+?4qmWkYZ0?6o+pwfeW4%9~USxcIr4hu``la+t9 zO{tiW3C{?!9U~X6&v?a!`&h)t?>u;tA`_j|?V7jePLj87ap&E+%U4cA@5llQIh*uAS=jjLbaLt}oE?Mc>KkIkU(p~j~Y(M;QIQwzs){VFA;nV4r4!z8(E$?hl>K}7>u-5{BhZ)<4{a|wz8p9) zjBJg0ygU=(z^v!|S;yg(8Bad2&XW(U^Ttcg2jFXGHu<9mPx797j&ake4d{gRzH8SH z7_XJK1e{wAgs$TyhxhY+mz~F}FFe4Jm03gA<~VZa#umqxBWK3QI7U(&dD5Z%9De4n zv-zd}6FL5Iq~8OwhQuux2ZSZEb}{{9e}-`Wi}`0?xRqPZEm@uE*#lzvMXP*;d@Ouw zq)mkfA9-=Q%!^5+ZLZ`PeUl=|v_qe8B&ShlAohP3KlBEtbX~%hTaS6&UrZcXo$=fQ z>j<#k2flLZET1{G!ROCx@{O}w+`F~p*m7WF7}-wcnAb8%v(g3jguuZ*aQWJt$FHyQ z&FAmu`G@v$-M%%h+qcHQe)L8B&V9%E`CISjrZXF?&3h|iReBS%E^u}jAtt`#lJoc% zk2=f?&f8~d_{y0L{`%M%K7H~Ww`^{6-}b=C<-lglE07s8cwcvDAMbh6qj}mhe*=#G zG2_vX5I63EG$Q>zIP@&~%ihS={6hZuS8nIO-u*DEvsqr{6DWytHPEEX>`b0wdNSpk z%qvUzdI@K4WG9vvlr~oW^ouF4O)G6n(?SIwXI}b$LkQEdBSQSzcW*42n2=y|9C+fs z6~6rZCvnf_f){=68{B?&6NZt=`7(}iXI!Z?923MbzYiUIdf~-~5Ap+-ALexz9-s@t z*`L@Fc0JwW|!EZls zoZq|qAwGY4quqGoQBiphp==Nt_!p16f*-izQXabsYjJ@H3}H?O+`BpQZJ+xpUplkR zS_t{)>WoEkG8HFwaogW3lIn@#Rjul<;!t23v;k+#!^?H zx^U$VW^RryCDHYL*<>2IVx{9T>j&uF&$8-FVLdjsCCA7u{iI>!^XIns;L%fj@WB&2 z?Z7%e@z~4w?u!obbJtwP^AGOfO<%o(Q(If5jmToLv=HHKPYZ1#x*<8}m$-{UgmMN1G&)M#0Tk zo>rL}i(DY8_i5sxD3cQNuH&waZSFd^$<=$;_~^5r!2gQZ$4{K$MW6gCt9{^$XE%An zmu}&^FFM38U3Vp~JbZ{ho%g)$<~sp6H;#P&C5QOUr#=RN-@E@9KlY7#xpQ-yl|Im? z$jdI=&!0T&y8k7#0etQ3>821>fuwHZRu9iFm*^Fbx7;d6FvJ;(NL84g{O-48c!Zag zKmAQdN~Me4Fk_UxQ8FR`ce+{!7RIdwGVnv zF+rugVs{n-?|bkBzkJ7otmw{N5*y2bYY*<__n-V|p160N6T`q>37n0Qy~Fi>Un@PF1->gSY}#RyWkK?m;q;pfh*Qm_>*TmjwkGG zx0(Ia&G+!{zHv9}D|1o_Ii$SOcRMBGFy>VswZk0-u!CMtlio8XLKofA)#|6Y_j@o23%`wVkOOfzB=S|iZ( zLqfCGw;?{Sx&_mSh#l`%nXZgW$fYYytTcm8P!60JId3-ORp;;Lar@TUijluQewvRR zKg)U-Z1Jd_zhC$d_UquvzB7c<(+*`g{;MmLoYg9JI}t$K^Wqwl!!nd0`o4|Vp9EOP_v)1@7_zy zR!&iksfu5W?+i$~CP8Q`j?m157;<_iE9qRQt=HGYDayVIJqy_6-BR8dL5-L>jPy;c zk`ica7AYHnSVyIKX}hSofeRO~)A+=Bb~7Ao1?ermiIXZ&m#pqOeNAOU^qfKu&n3nu z?N`~w%&K~mwO`%Z4#u4DPjM7Aq{_5YLZV$AMNymbm8OHX{K=3xdH(e~?*yv!8W}~h z<$D>_VW3bKSQ=v$w|opz__I>A5mD$0dRu$wfhervJiGZ*$NMS}@rqZ+wyEH9SNWUN z^R3N#Un-wfKstkGzLaWvc65qR&+(!5VZYI9Xp>BF6-B*06rOcKtD%=uOeNdoZhlBB zyR0kULDp4Z>ihcMp}GyvT}%=+03)eN#HNW|yt9-drMf@Oj35EQpvZ!|dV`f4+ES0ML!UD;XLvG^5kRktCM`d440*wHC}I&;^-8$ zi@JWP6@=dCjiPpuiXxNITKKU%%qd+t664tHOKFsp^oSU8f(5l=L^6-B)w`+?&vi{+ zRQ{y{m&n+!X4%up1gcqe6{xR#=}~lg-5I9|y*5{&nVMYrxLGJweb!(gCR|4vx>{Gg zKNSUulY`j*l$JuBhE^vo%aa-tE{5RFYI6E2iWl=b{MwbATkh_*1@+i9Iv?)t{+ zyqoWmQP$Nm#aleoH3~|0PeZgoa#o27*Wl9QgOoM=I@1-cnQByD6=yAp)jh`4a z*N-kQQ4$Q9vf#9KZ*Jm3MXNmhE?HX@A+-1t9be@EO(>gRAOl;}+Jr3XpbZ+OE57N0 zokpe}Gh2{G4YSt_Q5tF+wN-g(oRRAJKr_7X5cSBf+`S@4RiMVPx|3DIOS3mos1-3~ zrMR#`T;n#CmYTrF`k0}N5~9darL3onHnG~2QaVd^7FZJ^+FYQ@ddH3`$B~7mCR`+% zVW!lsjUKf&%@34sLxZXt5$L7V%>A}-Y40nWFjK>DJxIDGy6#MIWz9zV9`ce~k?g$M z8;|qid{1;==pWanzSS)+DOp^sXX=}aSAMEY>$Z2bDF3+$4^&#E@>#=>)V94bnWbX7 zN+lF&JBHTwiz=nV;QCO7JMm0JX+~lBi$knj2vWrg7XM1|-3h1+#oSQA)ir1=6X%uq zXj}}dYrw6l=@~}C8K40JNK;&|JpH$J#(yiep z9P9$=W)Kc~{BvPaM%L`klFMqr#Z9VpmW8Ly&#pOxa(;pZ#O9S+vdk0pLglx4vhZ%6 zq=xD4&4A>GiLHF9_p36+#^y%3X7XMROMvFIk5cBV=aaDel{+!#i9$Y=8UhzQa(kf#-=nWfDRy^JHL8c}B~pKW1#^Q#dh{v{nRrwS|{F;c1 z2Njlge3vS+ifd^?qRnPP89vt=yo_x0n4CkVim+l2IJ7G_|9=l~jd{Ca=Dq*`002ov zPDHLkV1kKIPDc$28VUda01Zhh|nMQ>3{oW1&Z{d zy^dFLZ+Zg-z@+W@$}|{1;C*V(OS^B^H1n6)W_%R@S{v`6orbB`w@N%$HOoS+PXesk zE?bi#5Dj^$^)EW-zni$CP7!hXnjUC=tjj{Awcq5dBxgWfPC_k>?RPns)~0IaXZxj1 zu0Yc*<5l8m?}tijL(sl!dp=}AGT@IAT`oIxy`+XrW~z;DuQT^cNR9kUu_EI2irZH_ zuWGv9`ypGREgI*@WuWWaouvT^{T|{AwhMKn({^4%|Mw4{ZVozdj``5V3Zjc1VO>C zR+R1=ha8wB@L7nThTk>rIh&>P0O$@!SW<-dY#_lYFRPkl!>u4 zrQWhmHP(qcH~b@?TaE(!F)D^K-qc&|Fw?1JHNOYhjZff^pO{k4Y zB3#UvXLL|Ks^JN!F3|u^K(W8xC;QRNJYfmZGirS?MtLLwpel&RO<1PHiiWBckX78^ zj2-|z;%Lh0j)r-`(MA07GHw`Ve2M@?7e&az$P(fmD%_KVEk>VRX67}i`-Z2QZ#l8n zCxLWc=;-XoVMIM4nkk0jo)G6`Qd;;c^uOxA4ZO3+~n&%AKtmj z0%#;RB3-DRc&6Jv$^58{8ll#?BG5uSbk~u+Eq69W8eOn0vewWI2~ZK%JdHk>z(uHk z)?g8{xy)x0rb&hHKQqEDx|Q)h4xq?_`k3vV@mwlLbvX}efSnn<0bO`wqhG=>B-3OK z1;h}&iANGNn~soo^pV3^-pY`6(4*EaM>d%$0`2l8jZ>=DfNrd|45G63&8eAwBbQMd zy1Mq3ea zN29lE0|B9X0}n=f_vc9$#jg1vA0CZ(EvyGUf;7GJD8#Dnec~Zjq%Asc%-Ksz%OnXZ zp@d!J(8iNz_LyWPNZuu|CyaUkKxcqmbH(q9X^b)^bqi&nGDas*q59&YQV1FSId*B` zH{de>Oz3C;L%p5vT`<IUWMrqb$Q`DcR=;$v?^azVp% z!uH;O@d!mqAt7bkH{dfsQ)n_y5p?gW!4Dl|V!CC+%nmj|b=N#*W+7htMKk!CD>uXP zRy9DBjD|ldk;`K6bhV~O3=qAlF6d|tneS$KMTxe-RF(PCud{=efqvHkVv_kA=Z#%p zkZA?x-a_ZukW_G$0JKB{35B{eM&+=QTKezaGw}|Ql}KiVhqA^DN7#fe?HQjnK%c5h zMV#@Cxn#8v4k$Vufg)N$kkJF_IglK}bHTB`$XItn(2u#92|15~CP z=Tjpml7~{dmGo(9o32d2k@!VSmQ;%L2QgD%MUAHwkt=e3lKphqCB>0&Q_?*LxxZj+ zafXr71g{JzBY7Ag7WoVYdv$)ykWReSiRe@`(1!tij=jm1yo|&z1#%YI+#lfuAZ?6U zGXB|gpCcF53pHjT1nNne7zc)6LKyK~2RZ_HEZ^bNj@8gMP>QEK4a5wfY}n%AvvB{S zZ`OFEF~T$*SWOW~GrfNdwg!^gjLtoUCw@4BqKb+Q>lhl60>IRX5Gr`92r9+kO&};u z`N(L++IG5)Z){}J(j!JwpVKz5R0m%K?=(dVr`Vk17M?B`%?(7mQ+)$?S+t)P;e=tgT-s zKTQL)oIcd(Fl97D(c^FCty=pcLet#L z64M5PFjD+9yMcXxV&ikbQW6pagUbSmR$KFAIS2+MZ&e6*48)0a=?PfvWy849jdqM8 zh*#MX9Kc3UZObEj!ssg~xmduG#gfPREBn-RJ-%*ho1;Xq2 zxZ65U@aJJsHy#$W_glFO;w!gIk*S8x^N#Ei0N~!;SM6oCMAxGkOD1w=)D*{AojgIm zSKuDi@{v9R;zH}RYShz0QBXM6`8N)S%&QTzwevTDn~;(_aCZgu=&WZ*BtHX*%zzEa zBCevcij-qWKy7^=>p#mVNfX_v5Rf`w{O{;P02pZ$drux3B_V4c3g*Q*;bh<|5{24# zqTJ!B4=v1q?V9r<(A=MAtaZa>XKKdk;N9xrA+q(ucr*@FZ0N)hJM+Ws$jvTvFtW<6 zz8MA0a12!(yd;L)q$VarGk&ca;kXkK&sx1^MD79uAR)#OLU;E7)ie@Bo8i-tLMdjn z>X$rbkw8~Y2>Q@M1KFi?1F6woVkXEy%2BC9F>@sICyg<&9r1KeV9><$eSV ziUBRk{7GT1HO+LGLfNpX)gc1R#)yPgmLMXfH{#q#op@*8o<79$%qb=1pxfkSysR5a zNQE&nc~p$g_wkbnUI8i2($H0^F~--iV2SJ`cgUAts(T1yxRiL-2y|~jL#nakf}tPA zFU!$%@JhqNJjThah5U-%^p*_6U;n8iyoHuG=31`VQ!eHV? z^Ed`P1U5hlx6Df2SUK)Njzofv5V$8Qy>1giusJcr^w(HnWCUz?8}2AgKt}mouhwzP z7Mmoo+jvZ(PUAlbD=8k;#oodG4kbeezY)YWaFsTkSRYzn-4%GhtQ;e!be&*Kpw4+G zLiX(KjYk6*1}e8tk1`@*r|G*FrOj(00~&XG-%OvovAT>RaYoGT&vGt|3P}7m@N>Pk zc1t8O{Ym42-6KaAeTf+-V=kq@!wv;$xCyfdbV5uv1Np4$C7uo;m~pqZ&6tP)V=qfz zx+fG9G>zAd3Zvi0&Y&9MV3Wm>8OR@knJ{uogJ>hwNEb5290?_Xwb;O8_vp)n1X@ zQf-FaU!i8S%#p6RK4anFlW$SwHtVzlbBrljY0a>#Q--5NaB*#ish}f}n%In?A;g%5U_b!1IpUvNe5y;WtoM|a zrj?5!f<0zHm)kT2wc!MMS!;K|_n^nw6G>E|TAh^~!Z8;1X59NB#*{2Df=4v)489}) z5zz32h8Xm;dra;B`0x*XE}o)4U&KWu8yInxoxqr|nr#=+C<5eqU-xts!d6kCBZJsekQSs;Q{+Bzb>}j3sp2h!s1t!DfPzt}|oU*fs1&;;ul` zo(4vDAIcb?TrV?ktyu<)VikD^VTkJE>0W8+;ch{UX`K_J#*m4GN?1u0NBG-rBv5lvpT^S1XPrp}o7GnC;B z^bU1Y>I;qGdoIKxw8WxLpOkLcB94_Pl9%m@8EF6_pL%HYDfv+*+ttX=1;+0Ssl z|86rk1Bgn{WMG$cDA5D@(&-{JPHIPGW>3OV!%;?P-LgH69=<2ob&tv6UQFw0a)>S> z$(^+?hJsd$XTi0hs%NbY;8(b74c#$Tq;F2ksc_lpNA$8=8e zK7_~}t77VqJyxQO)Y@$%^Dzz0I<0o!>7~_mDOXcE=RG{PF>9BaM+SMmrzO@T`rkcF zoZ%3CZpxZx1I$aiIt_jI=|*x$CRgq4vj=B=VBL#Pn5{5pC7w@{%RY^{?+_>-o%F~? z0wO?7t5h|0FXso<>-4DA`fBYeQ@?M_X*g#*BRoxH_RlQb@c~(~vE&NPs8V)vpeH92 za}`EV9={+ME7b9hxXuM@(Z5pHG=RYw&j`s%#Mky104QoUNJ3-o>xhMs97O`e))5U5 z!B`hpL_;omoEh5e*Sw+R0{-W~$PNN~q6WZWVk0#xy_h!}GTTug+K)jEsC_av0zCus z_El-Ijq$P9-`8cZIL=}a18w4mH=HTA*&<^X^@zMk|C4D3aaD$XfIv2}DpK4$L+M=O z;fT`)A9@%)G8*gn9MfR4HQH>_oq+U}fN5Pncihg9b7?V-7|Ke1$ex2W7}bd))_jv8 zkI>|c6$VRF05UZu1{X0rOm%REn3mWkBz7-Z_IMEI-C5{JUe3GQg=V%wU2=ODg-CI> zwM{;`wTxxzbN!XYx|UVtkR`XP~I-tQZD>q`Y6wgPBY6AWNJ(6&da z^Uiu_QA%%@^eRAIovw!A63;R{oe0m@QMb9XLj1~nJL7K#qfvip_QiVSWzXQTkJtB* zIe6dxZ0j>JQ5n>-oW$2H#3HBAKj20b+2qXh_pnd8*ri8m; zP?=yA=?`s*PKDfFazCXLFMV9%U|c8(IC|jR+1@aMxg0s4rF2C3__cpOLt(wSY~ERr z`}Og|>iRZ+keZ#567|3Bfi%7{z+j29f>KVznd|%-ke}+!USniJ`#WY=sN;Kl zCgtODki8m{Zn2Q%WBe}k{VZ95d_?M#dRUwr%>b`nu2sa|n)_*&(cQSsym-1|G*g4r-VBl@p^9eYGK%pv@jsgvJ=KGAXPkj86$b*oqK|N*D{RuL%B{ z4y8pc5=WI2Lj>aMA0lv5_vC>yq#Hi8+?!{jVIW8cGbpJe1T-(_XX&B>tu||EY*S zA%*XzdZ?8gjW`Gr2TIIIdoljI%ft;mfiaOi@Np1sFlt03kTc--0aVR2k=(p5>`kfa zCf6ox#|}5X5r{}G?syu=cy56ctAk2-wBXK{fi?IkiFagBo^T0gHAd4cLxl|ij8L(@ zkhPB=7G^)eR{`I65L6P?$>94v8NXAR)Rdm_U4}xvEj#ww3Ex-f{f^*_ArBSlyx}pW z&%;~j$+c5XMEH(<6e717gb?tS{8}|D9A}CwJ+uM>F{YcNGs?Nw0 zC7P6sI;Pl+ztKO5H3Zxr*9Y!{dRU;jvE0WqbSIamej!5#fMN5NL|LACG+Fg~%5|o; zjaC=9|Ci{);3G%<8#9FrkV-#EP{d~$o>c`bkLF2jng&cEUT8DjqcE3XD|lv%vRPA0 ze-u;$2k*rh0z6Y-{D*`4`wh9jU!Eo&u?{L}ufuEI; zD26`kVvCj(ZG(*S(z>bfTvD#!4G$aeG22F0lRVA3H&Z3Z-r7kwKOJq5 z_kngHB%R8UlB-doJ1v!FKgIed!-lntQU*ZGJ8kE!+B8o`L*O%U<@hBOH z;VN&O38d-XfYFNUNP}r6qW=uwGP*-I#xuMCm$Gj3UgtjBk53!gRq0bML%SwH#~~A% z#&Duomw8?~fPsyGu`hdyRv`HfIpepILm-ldiihWfR@RA+Dq5nS_Zcuc+&C_o=~+`J;`Y84c=R+a={RV#U~EC?_r=A6=rNHA0VAr)}}t+ zYEx4_Ek-TX5M11%dRg1{!a(YWHY4R7ZpI`=I({~N9L-r+&MhLvtdiRCA{w{PfN~xx z_#M&MR5Q})N)cq+QQN){$a$)Xq+Ycvmgf`t)KccvpTZY_Mr=8a<--|;PqnE0W1{?%{iUejDzRiIY#%aZ<)JgGt{HO_dJlw^|bidiX zUuHtUcC@WSXF17dr{HEZrH)x2yg#7dguf;pu&J6n5`u%f}P?Tf@jpyy+6n6 zwm2g%PZnYaBfGV0Y}0(YlF7rO1p+Eb&$6dr3FsNO@&=NBwnxecSk?1K@8y3lsdW&_Lmn+(Le$gZh5{$NgCh&Kx7afkp%9*dCH0RVX6K;;4fLF*r=1^pwyKqn)!1e~odkts>>2DUB@x@-pyR@kI%TvMvlNxch&wBVyAn4TFBRBq z6q5j_3$X(GqS{Mhr~xj9>$y!gKZz?*=h!#9W}Q${ZZN9lhnz=B?O3Vku;nAXSw~G0 zRQFKrR)zRjF%ulqksWjtXk#)V-iO}i;~I=BGB^Y~75FUFHb$Eg)4A=Hz3t$Q0nNDJ z)z_pr9;#DEvj?GSduL@(vN#_;s>(aA)cNghT#5OdZ-@%^mCTV?v)pt*d;o*L@v0mf zIt`2!%tzl;Vs!{min<~(NvaC1ktE!QV~PGUlRj2?rTz`whluTC>a4Ixu+dt?fFb&8 zb*MC5y>O_wbgmi3$pYMWwRHK=+JKKuU1p>yva1l8UK(%H9)WQv#HehuB&GvKkjc0k zbCe(I;vt$ykP73Gl3;Ft`3Z%RS(KYW&8pxWqzmA!v zL!+?w$qalLk9OuJ!u;{R*oO@;rX&1&I`zej-j=wT@MkFiVLg`n!8o5n!6MZF#oKs;DaQc3wbsAcYJ6&xQ3j(3Wyr>*X^0nCSjl4wlUY28Sh z%YwJI?KmyrcD*G9ma%STYr7V!3N`V$JK$dmUKg9O|&BOiKA~#0Tu{=^e3gpdW zQ)h||t$k02AzM5=J6d`YfegSh%0r`jfYlY4FDhSiMC?l?HO7_fC6ZgT-!=1^!;7S@ z9SQw2CdoYGN;LVyBcn}_MoZ^|4zy8oZhDScA?(PRw4Gemg!JjH;!AeL4ZK#x$v#LzVMWq~-=?CcvH_o&2skojh;UdKt-^s;NjEa zt8%Yx1t$wI6-BXa=Yf=&cwXSb;C)6HQh=!lJ#k$VpDEi1l_(R}%r110frRcTt##R} z_YCGK0>B88_}>TuYE(%&9ZMnz(uf&30WRI|amQPPG&5Y)FYU=pLP zTal#enIS&g-NH66ON{Z3k8`PLFY!#nfw74|={?{gW`!dPkQ+1i8L%3C@e+#Wl`ITS zVijPT+E~8ywrT~|rJKnfYXXc@hB(oqq3!HEYmI6+tRDK1EhX~_9jF>RXv&i|(zqlN zPprNEEEHzFX7s1agd)Ih6@QbH4SfKht_?7fF~z3-y-zgTXiwmrGq3KMvrNNKd=nAO zSctJn#}WPP1P~U6?=<=n=>tO1w=wv&@?m}^?>4PwXBv*(w7%?lz0m*)0f6#-Hf$#J zPw^N-CJv!Yk)#`mOkY%eeR-fMyRgBX8MB;oN?fGI{#2R)TjHD?&lxzU(O9ZGHOETY z7on6%Jrb*0up@^uwv(-SM0L$wl>M>(ephuQH>RGfU2D>YJT`9ZH)Pa-Xm0q(@O7}X zz8GwUV5N?mgOwGKA}t!|-l;tiDXzgTsAFT#b;v;(kU1B~+N?}Y9`6~?2nJ~}6uIV+ zL@Sh>VeccP?NqFJ?}USd6}Mqx7JG?bLQV(-Icyef%$O->XE z#mh<&d`Ha4q^xyUYzG4E)JYo}*vdk!jFu#$=w9Oy+LCm&zBi&8sdmW6$21x;!o8!^ zf)~ECPdF;GPSAIHCIB}W?%+|Vy)zxw=q*AwbADsrLHQTqKdVP|^WX;P`7@AzWEho| zE(tgGUN0x}ohc*M?WgYMb&||qlVJ8K*}L>20_?BPAa^nHGUW|SgEcDievbX7^29?Y(b^H_ zOWqISWjY<+W7Y>AZh92hAMR%d6ezT`1gds$;G`^bC>g=1Lp)l_zS_hPyF9&odfc6|-ZHn0`nYcM+{(!IFa z(W^n7_7!6LeWWtpi2+eMKGq&B&H}SN-tFuLh-!n&=z@W;eoEzZ{sM(O=vQaK-lt`BPuZeg_6nY`z?}laYw?aXe?{|svRJUXqz^jdX(j1ch*Ip zbxQrD`#{%q`#u^|JhzwnVW!&9M>`Nw7yRH5jX_Ud3?Gh@mt_Z7cDn2|=Dm*w?k3}u zI0VJI3G^eu0)MFSUxO*;a5Tz9zd~5CoHH66*XKI}yfiD& zpp}%ZZAK%WJd7n6ECA|sXp3K)i=s${La;32htKSJW6x`7P;TSVlu@=ONMY^qf%(ce zeF<}4o6oZXrAInRB;(fNUYMtM5njy|(Ur@duA%JAH>ElajVM3T?g;FFWG*kzI7>pK zU#x?weVL55WMPpuMP_Rzn%dH)C^HZ`-CC3*m~qI;{ANCV?0fv8*gXJ|Ab#)63XmRR zkSps3r};UAHa5FnqtvvRI?=rn6z3T%d&tr^Lfx^j<6_T-lM8W3U8Uf8GUT5F}( z)2D`-;$(y9ZYh{xK;m?y=HpAG;hWIYTU#XqgbZGd451WYE^SHkQcLV|7B0%n89)^Q z>?s^}!wjUEDH^WK&8zlKzl?mwXt?3eeky<^?mcEH@>lH1bpt3Q``G-mT^1pC1g5) ze;NX$;SKy*9UgO<_*x+IK&L`&KS1Iz*Vp>70xjEg z1MOAlSQjfgLA!ZKM>b+G@oNO6Gtrtd-Jbon$88@1F(@w-X^NBz_0@WtxjnnCZBYw* z);pzW<#8CDX5{*h{DK#~9mnW}e$Pf31S0(h}OeJ`PGD z(qhx3AlwCU#~C^|q6!0G_DstC=Ub#$+G!F0Bc@yZZ|(vmzC8L+ka4nZNtRWT2ateJ zdVei}=CY!VRA(q!Tv9TE!KL(rNL2+=Td+43^`rKKe>}xWdP8jyqk5gKLSIub8j;gO zhRnd`hmn$id}9vLG0aXxzio&b3Gd7xL4cY)m+gv>Bq}CewY08cOQ^Q5xzTo!e&hSDf`S5hVkbW7-Js(17}&12}QC=;+bXt%eEEn%hh zI2`lp&JYk8s{p=qH=ACEtGxu>s9;otjMbk>AwOJ>F4GjbP+yYmDiXr6LMkAl`~Bn> zURr7TvyJO}n-pcHvARDRbh-N(`(z*1n=Z;#1qE##hN4Am@vu4{Y)ouM6Ek3)8aiMj z$;!qhBlsooGF!-OLg^0V3=b(iXOnP{R%7mWKH9bjKJ48b1L+e13|q9X1T<#uozw2W zjmg?QMJSH#U`lu@dAf*e67a>LV{NSA)i|iyR2YwW99We4qzFhgM5S%WKwqeGhRf-E z*lgOA)4B?lRR}j20QnP&oogM&hfE`TbTVk z7QLuXo8(=Z{8g-vt_XchYBV5>Q~}Fv7{5FLxAz$gZv14WO4p@pW34R`n5Oo3p5W<8 zOb4cDCyFufgyA@d?3ceNYsM|L!N!9AJ2x|ZOGp2~NfYk87fWSb= z07{xssW$#?rWINR+nrl|Bn(~FBXb>tvkC~e*Sl}yes?bdNR98t2=l^}2?zR#KYJdN zK!f<0rtpC91RR1oh{F4u!ex>}1ST3c`xsjpP~F=QD2*SlLWXCEuJI$Z!;y7sthPtA z>k3F|K%gQ$H$Z*j9ENd~4Aw`&qf>PDvn)DMPR|JBXLLx1-wd3cH`?3b`6^?rfrdZp zvuMpOcu$2I_;4OX`!t|?3MY(-k1E+9LT}g@nnHME0KL_egllEhmTt!Lo={Ba%WcFw zW+}qFO1$Ucv@tO}Y*$#ScAgY-Q7o%qSqm)rH;A6NO_H#?P6Qie9>H;Lud#Y~12MPf zkxDe*CJY1uTX7T&;A5@19yd+SkL&@lGFJygZs3PuNIfTJBY z;&JNoj7@YzC@tRUYY$X`6>W?Bq%D_YVCClGbnWYMwgW0=a!f#qp&rut@#sAV2EIme zA&_Y^IMmNVK$a27FRIl^Iv@16T%Afk6m(x{25a*B;VGD&{OKX#=$#T{?4B(&@r#48 zW3cS-v3A*ZL^+tAf!c}Gw85zTKA74f@ix}yZOjt=7=cJK9RrM~KC#zfVfnZ-VWJ%f zLDf0hHlA_Hh5y(S$Ec_>6v|mLu&?olT#lphQ=bfYJd)^6f)$yG9-r&_mJ^{y)mgwB z^tys~-UM4BQdP8tT16VruN6Lfz~z0Fd0y(S(WW~lbudv_4!}c;2(R0s5VAf(?dWhf zax+dBunFG~k>>d=ni#;u#^Mga?0MLI?Rkk%EM`XXVt%~?RIQk&HpREBf>mi+(CKUR zn^MMzAq!>PPoqP>_CeFMQjvH+KFjFUc`buD#zc=P`jC9_l34~sG#8Dook4$iByY>5 zEn(a+Ac%gLjzB9VVFy}LUpQONePRS9Cqd)gy(+z5imJe_wjsf0qgd9#H~5e)^vyUp zs#BtWOzw>ZnUAAGvV0HU-zVO`?=6Gxw*&=gpA7n|2J>b}8Lo6H2NrNd-9UKXW|` zp{}Vsdphs76?XoOfJLC{e052Mfd!|cT$)4P(@vL*SIzdr30;AQ?PKmRM*?JMBu`EM zB&(+;2^99aL+D1;=M7A{|C|?&d#*=9sk7cMbVsvP#aw{R1T2u0P6>ck=Rb$dIZA5( zcsmA0Kx%t02Sy+u=-TasjvWM87YD|{JdwX=5^*^xF3HU(jG0P1bdpMkBQc@I!3Adx z)uWYOR}!?+4>Lmit`HM^Y)r_{PC%U7PJwTXNh|L3&`G9COU{z)UWVIg3qX{`O~P7k@OoTnq8(*X> zx%SoK1k&x*O2Kpmpp}fD+K0x_)d{M77+jsFi6$4OB(7wHGg&grG#BGxl-8!tHe4O- z<1C{sQHgpzS$#no98)Fk<%Xj9Iii8r-bX_ovLxDE0Y|HeLc@?gAziS9fC!3%d4(#l zU4%k$j3p7%Mu>rG=8EdzEJT1?@nJ2pOw&-x5t?ujO+j0LK23C5a5zEGiLp zI39atztB4uyEV9iz+z0`y^F?z#$s}}m z#>mNlD5THTa|i4&&TtZ9&^AWoyqlMGOe_gFRvM({Bca$zb^oj1wv&Zq@Jv=Hz$RdY z(U*&}_o2rb7RTu&SappdE!kJwa^4l)b4jX)6NwH^+)N551=A#07DYX+Kmp2u&Cpw- zQepcf8ay;5F9Pfq1*$-1Tm3~HW5reD{|JQYy5=h*3xLXqYnAkb5Ak+P{_kbl#XOZT zM+cnG_dwBxU-bC0Gk0_p(z5Y5Rm_KW*^I!zs?QW@EQ(!Ku%511R{$HqJQu7UrFFW) zXJybsTr=;g3hb(2Qz~XCmfBvKskL^=aAJ)sZgl!Iy4C9jO8^B#B0ODfyzq$D_-a#k zeu;I!Ya|8T|CykG=Up(9R zpgbQ7lu}}){WD3$W>zeVv}K`bLy%>ov)MTQQ+<9-8UvRT#iMTqzWAvVUi`R%C*Bx2 z)FhL^dIW-pP8I*~H5I@4e#Nv=RNuQTQ2{`JGPEvm@ITIG7Y0sqN5GgbfstcHpXmN3hN#%`uF1>$QT! z2jX?x03`W&5AQ~!2QR$dqrp($IjkPnX z>BwMUrW}I4W;*jR8Ps08e6tI!C=MpYZfQquN6ygAIa_K%c`DXfQVLL)HjVW6UNqxx zKX1lu#|%Ov@SR0lqwk&ft$5DAJ;n8PIs?_C97#GGB{Rn#AC-{mOJVB3#Lx#fl*I2b zW4)Kb<`08Ku)tS8wo^Yb39y`0eBBFX{K!jZjIs;*M?(3Y;?9SF|JVQ6;ottAq8yfp zW=31&j&il7=Zv&Ey$2l-b~R>)8b2iUDGcrmy#d;MJVBX)$}+gJ%-sz;_7_-Uc$VqQif<}q%bA^r-ljNy@1GN}&uaj2fJm=#Z`8I&n^k8gNQDx* z^GXMQw0^`A?55zC4q8KNpPCyDG^tR(QMNB5TE#nExzeh3+96f>*#<| z1R0+<%Z)? z7i81zc1Xl#s@N_CtBQ}u6Z6y-3k9>RUb6#!PopSsSQJ0~WgEQo2?eK1+i`X{w-Q%& zz{!@!^HF7tz#3Do?-bwm-&R~cnJ^vn^;hFGQHoC5edme;`TkPb#J}h&B&5DyH-odL z^y}~$L6`^*i#`!i;oEbXM)gIVzV9|gYmw@&ff9|Eqb_=`V`_Z-|v>pm`@R6KM= zA%_#uGXO{L-$+wKW^N_nYNLEhMjTcGh?(n-G&<3oD1(Nh7Mb^Q! z)IR~RnQ9vj^p&D#Oh1hliF|?imSqu=)Ld4(vXE^A&)OH&*!9Qo68m}xrF_UuZMbcJ z_w^vf6weo5G-J-3A_kRMdDN6Z=owNduXi8(c-iFMTV2t`mKK9heJLl=7;&&sEK9+n zvbldm!xH=s~456X+6u8P~v0dM>IL)>}isjeC;b&T)SR@1GLxwSS2YV zPfDT+6kwX9zXb<5*{JYitULqW2=T6a(uqGs5-)StSrF>ZDgclS0Q*(A;ZS)m$6#tk z7H%-qiE-TUR%4HhuF0jQ{rLW=wd+;|>LEVy(G!05iv&--1e~tG;ill{-c|9%KefYj zNC$>8c!>s{; zJTDaO@N3A6k7XRejR|&Lq5@NvevRiYWA&9LMz-e*LoD`J7b1+ZxfDmOyb8_Q>)!=w zQOm(bvDR+u(CGuJ4)}Ze0nUrkR+6PHV`*`W3v&y_R%E1B<*+ zZwp*y@YwpxD-eQsVVxy!(Bh;c~{` zvR^LoIb`bZ>f{F4Hq8|MeTo?JJcAwadAcYzhdaFSeW&>4_chSit%{2Wf=_t_fTh|hH)DPZaopaW z9x@c=XPRKQRj}!Ad}`oreX%9L8qZR{!hX1!3fh&GY%Z!#PH z4{7VJFTxlUvlF0Qu%OET`WAgA&S2dbWvH47G)3_MT$IYx%s8vhwLa#059Zo8dGLY? zix6_ZQlCZ!?=e-eLV-=e<8N$+zbU|ORlM$l3OOuTdp(g&j=Id~q8&0^H9A8WPB#a1 zMyl7#3gfT~{@4(5nz}bF9lR>AE*0yxVmVPPr;6niShm2rDAu+5O2w%Fv!F+G#(PkE zgE9&b%a70CrBk{8+^EOi;SL(&o>4-6J;x*>_^rFzOoWa3pLiq5Ac#x+&qpGVvBLUc ziMM8ysx1=O%oU|H-iK+JgCY=dk7hs7hWCYgoY*qxJ=-Km_M9hxru+7trvUe`9KdX0 zhrdDxa(CL~z zQ9LZUEBP#lt&5r^yv4@0<*UODQ_nxRMb)@euL6 zhCqC{)i-_kN=7f(gkGkWNLv?0UD3wP6R_C`ZaH6Z>(PQshroq-!e(lWIaw<1-zx6E z4t(_bgsZ25YU%YEnC1zB4u*SLWIdEYgrs;n>O1k86^TS=?-=A_!Izc*0|Y7)9@-*( z4tfL_qGtY6QhQih%PBQJzrYOEoXp{*IPEYID;1dn)+JyZ1I7CrI>`CKHUUC=*?#9K z)ulu?>yQlO^x{QW&s#mSS6l#tf7h$pzX%|uWRGb^tBWU9T?f;h(9CdCLmh#8F*M)x-YNe3i80>Jo?44V5x z1bxiJQ1m+`0^OhW-_q_`8f004x>cZ5+mjs09th^iUc}M0%(wUU-=k;ieGo?hgG}Rr z!jqRiXiNOpbK+L%B;M;W*P_|ycaxQi{cNC?W8kqADdNU9#Src9{8AS<_ z9PCACuEjRi4qG6TkwK)Rt_9x$^Jfxg>M~syxRQ{U=_B zUUy$dIzD>4P~t&pN4p@x(zfd^tcW1OeG(Kp>K6f)Qw3Jw_M3pud-4V^e~RFRcTBkB z{24w(+sV0A)hBog+Hm29gMu3lfG1rNe9jYrzx&A>+<&5Y&7Umz(YG%6mG`f>cD(?H z1#mbo|Ng})7bt;w;Qyqdcju4lQz67SOHkyBrfOCco0vhiI zR98Ilw$#qGC*_ZC_Aet#HYI0fqD2Ckx-#sYs>G=0^PP+(g2PS4TAMN_aOj|aCL)hs z-)>mhVJa<(a|ava)jShxlGU?kcR3sg&=BHTvWlQC+}W@_dwD7R9bAN)gOOFm<_304B=_dVB4&R>f{@CbB8O%}2l&KW)YrKW)Z4?ydNd zx2*WLZ(VWa3NRgZh#I0DKWuXV<-8&EECr3f+nEe!ID`(aO*Yz$%lctzGmN zRl9X&ei#V(^Cof;Y%6d$H3Q01&Sy9it5M>2z!k3;Oj_=z{6=-P*O6DpxN~9*Esmwo(%!=9r!-8C9E6EM$q_fCen=k(uT!2bH!$@Nib>is3bJR>+n~lRc73 zwyy(IEc&s+_S$qWHJ+Oy` zylk#yM9xX$P;^!W*p&8m*y~H zrO5Pj3klsK&`He7;9;5h-ATpG7Ye@ZGdK8~&z^BKHJ+a?ib;UOO~~V2_bYz)!;074 zwc;HgUGRa+!2PF!YugpOb#*>Wli=K3aOntm{6)cY9y#OF?kITvqXbX5)W-dQV7oTj zKmHcMPrl+1U-I-7-}q}geB?5)IRci-ph}kFAL8o}o_ivT*zX(@z^Bdj@--}v;bW0N zx~*Pms20^}d?(<@j0sv_aol8MfO$f zd;&^Bxo6GJ%qyoV1d6%Y*tl2|{*Z_GLloeZQ;iIkb|q|BoYCp+v&1WRoaqw<1Z`E; z>1z83h=#QK3Q%dsP`AD@bC^GI8jyHh=E6u=BTbI>rpS`y5SJg8rDx1|#giwT-w5hjvE8*pJih$t zGoJUTg1`Jlddyai{HoFUKX7jeElq1_{rgNyCZrax3?*{{RJ=rkbY$nuf6 zF7zF4s8+AVBIo6+-L5y;U^9cW7iNG#i=J^1HO(_niilxSw%fdia zjopLdE~|nEzfDAw%yu7Uo-sIesIP2ziGjLeea6v*IOHy1@lqobDdn8-Ul@~^?C1EAan8e z?LE8zuX@jlSG`y9^qY71+s~WvSD!iIVAFP3?ke!48w-BrD-Q7&UwMjOct?Oh>l(dX z$iI>I?|0JKgw@9X0MEwch?BmF488J>^{;&$0pYs#x|=>nSs_DV`WVQ@H5U-UX%!qz ziba9d>r}7PhcJVQaUK3!Ij=Spwkm9)hdYshCROCE{H$9Ncp!F;lu{u=;8ZbXq5!Hu zRln_TKCQ;HyHH=VZN|r?+LVwz!C2aRIG~wyx+bY8qCM-XXqnZvSV(LeDbeHeKjyD9nJE27w2cKJ>dur9!j2NQnbOAhfZ z&zZ5TElD>Q;9wTK<)ex(`q}IF^#61nKmCps*H>UZ0;WydU%6JrQV}o9WQFfPt)ER5 zR&C|i+7=Ma8^OG(_@nz)e8VrD;Ke_+!|#5$y+ox*%MqNP1^@XKM|j02OxT^&{+8ae zJx?&QXW^hqwke3cP^>32)W?5k&39^FK`5~0q(Jj@I}81_Ly2vg5rIhQn`pXEOE_j8 zPjgcxD~2nixe967ev4APj>K!B{Rm@yRxUt79f|qFtLNIMl(s_eQ5Pos%2#ag=bs?h z)y9v_)Uwdu{<Z(7@|0)X9GF+uU8UvPv^ef*5&L{X-0Pc6~?U!31D08jg;rw`FzeKqtvf#-|bB z;5ubA8@;xImh4Bm*JnNL{3-sRpzp{i31zLYm{F9>oIF)yV=CJ6+y8Mw%*YBYleLm& z_||SWz=KUYy>-Xa%|@34R&^oTylzAlaA~(}sxh7R05D<`U51H%$b|7-fPTsd92D(2 z^6rkE?9@2mLC|8yPy_%&OcLa{lX zpek6_>QhSYd=cAVeFd7)IP{%~mUt3CJG*aL1@lI6S}VTkR~G!uS1*{RR?Sis=V!%_ zzx)u7xS{QIbUfs-Z0BA3<+~&D6d?mEh+jo$d3o@zl5G6}^Nb|RcJL@~6caMH@capQ ztUl?wL!6>y0)Vy}bu+ajb^4fNO1ua9u7}`-(lTMz5qJz0{V|!@Y2Iv0{@orP_-let zUg51&88O4RU)u9ZAmmr`5z4$vP`dKl4!1O}x;s;-Uf^YcME#|3hz*;Ks_!|Y^_tHb?TCwT-5RwdNuY-0yQ_=&+ zPccc6i4H?8paUy~svz>;2!pWdE^_XIgP?e-u^M;gP{3M{qaVCuu) zt{<&W#(NE0h>o->%-c9nIEKUZ*X;C+=l#14U3o7~9d)w(l*|bFE@%97V;DDQuqTrq z!bj-b*=+()^dW$DMCMMA(e-PGb344f1anlztG~oiz+r!ynwSppo^P9HV>HSw4 z4`Lr-?>>P_Bz27davE+#rYk_&d}st(wq|{Y(jz)kWQmSB+4gsM<6w||2>}~(oXK9#pkx9_QGD}nu25Cnbg1~> zetX3O*A?@oy>fcb0-b?Tr=_YAB=x1wHj^+{^4)!@WoFm z__aG%{HJ#=D2M2$44*Me({(NCYpvTG;=}+?<2k04BY)>RMOfRl<*cslNXL6UOpj2% z4UDNtpQ=lagq|~rhdD>ZYU83Fb=qv9+n(3;PcN%`as)x<1=8Uk3!&(m`){H+t zlW3K=C;eHj`@*K;8XfJ$LP>(Pv71O{h724{Rxo%#pbvo%Ty};kbd{J-*9ql7(t?%9 zY9n74Vn;96Y$ywCD!_80`23Hb@yahe!m>65-%NsEd0)jB{LBd!Y15syLR)haoh#W} zJGThb6K&S}KK|6R1l1MDM-}b?+9ILdsp7eh6ukB;j@scJXh*X_nlb#+dw2LJzqP~f z-BmFimk8k83rE7w{tEpImC8LbT<;R!3Cgsht^#bPB*=WzUDr#ClK-DxPp<5 z?rBm?2ZFMhF&~7H)4_~ zCh?Pm(%d)kU%AoV4+{r{+)_mc~dig^Vbmh+z4_?3EjUR0waJVTrn%i5DPIna>0lxb)4)6n?dx&-E zN%}4eNKCgT<8-UxAIabQA8R+B7R1r4jMc+i%!Rrt3QjKiERgZEm|d`=5pdEtIPaE& zwYD7pW@h&=7(Cg9e@gsF|E;O-Hd9yPSppu`D-4d&v4ujP8C?+)Xr%Br0Mdf>z1>#q zuJRco-pHUKXK!)xGDntlh>c%x9(i9Ii9et zmPCzVhFC#CcyA@rjTgvs>S{eE-WoWh&+vCFAYtI^?>n3Xe|-On7yYN}c-AcipLz%I z2~LXzz?eJ zHXEx>Deuwy(;f*;kAC*&3G}_W{w{^kK6V~$t;W$@v8(;?T+_4QD1iVo+J1%Wb{($N zj^qb?p3Kp0)CENFYr0bY#pUMS+Fw0f$eVQ-HPj5o6Ic{+cqX3bR0FYFd4m$6eyB%k zMSu%)#kE!1R$l`Kl&l!$4T*C(N6_d|5M3#g9joySEYzo1;Oik0lCbbQSh3?(7f@F+ zdp=r)D_0Nw1r_UQ#Vfz;JU;)4Gq$VZU=qCHLkm9b$FE_X3)J5Gj>w$*^rih$>l4uu zMJREb4aTVQZuzqs4|M}*qoWo9RYgC^rqj^rs}<<$wSmJ4U;Af{@Vzgdap_RnE=E-x z%mrWh%P07Wx2~9v+o{XE5QiihI;PZ_#Bhm-CUq#rxo!kx6sjT5z>#nat?MR31ekoR zkA`D0zN@r-0<|hm`?2EE(P%$UlWE^Ka_fYqKUpWjOs0c@IKHe=~G{?*O45 zXs+339Bk+#3KWHEe+R7)V+o--&(X5Jc_EXpZtOV(?fjr9wdEL$uYIVq?gTG*`~g1i z2{YCjhfaRmZ=PVgT2#~yV0Hc$8pAse$vab6`WkhnVtGk$j#q*reAuIHvV;mDHicrHak2VC!35_FzG!w2Ir z$%OROJC-t^S=MPGlz{9aBDr?0cHOaQL9^%RcO0CGV2s+k%}Kd@=1t(&Orh*v%;_6~ z*+Z;qhQhHFQUrL!am5|ySKM;krrM@L3nvDpWyZO3tK}1#F-AD&yn!deY(b78*IAz) zk_fE7y_qgVH=Hp=?FvVRNqllIqPA+U;BP(a0F$&e{*wrP<^4On`p!1jzt(14?#0@q zIwFF|&Bs`p=yBlc)2s&IXC;6oBxIErQLNhq&%LAI+dlmmpY?QQu zjK5+iX0s#)LKzg2p+oyiLLEtZV>Qb5^#=m&xqx=Kibv6$gf@Fh`%<{?c9eJ1JE0tv zuh;B36gM|3(G4efA;g%*oZ^ceY8>&Mvi>Fze<=fNTTY-5$GRbiKX1>9c^Yk=rlReq zzHnfxxqx#Az;S;gOJss68%kqp2P)a4AUrNO^DJo{5G3w7n6UR$?!UFUZ+LA5U5%Gl zbOsV;!sA(KvkmKR#S?F?_<|=-P;HAxR2BdHjayQ3rR=gWL!1XGpCKeS_G})lMdDQv zK$6TvV9W6_6~%hG;)Rc$@tc3)0>0x#NBH$GJBKfLvOrIEnAw|2tdlnxZ5QC+7Pf@T-WNCK(R-Q^F>6wydHDEHkqpir^ckzH z(@qgT2a>NlNQt~mcUs$}ZJx3xgM7)3#^mQ-UISY+B6B-!+G^w(4X4bE-+`@Pr}t<; zECL{30=I~c2a=%(EG-T9o^ZwXYeBl!(T$tOm(L5Er;lnFlbLXzT zHe89(mxU6(!w zK)g#FX-K=Gpd8Qm-Zxj=eWhYEwP@!N=L){?$uqERM{RrCq+1@XbUCD#%6Ol`=seOI zWyd@#0-Gg>4PnX>_wrVK)EAL!7$4lwJf@%s&1P@rQV~Ox#^0D?BpW2B)nr-yx>y9) zodb0<>$cG+aGv=_ByuJt{^(pT#1uj`HB|Nr1EHl**lEaz_&a+DAjUy$C)a5O9@<4> z@u4kny_UA4EIX7eB7uk0Y1uJ2sl-o_f!MAoieTbxD`GZBd>Kuz|7&3#Zy^pUU`mw0 zQYuyeav=D^CvUh%`0+p7V%fFReL|s$9uUyFm%#us)(u7Eb~5)k9OS{7c^QRbE`sG0 z_}@PL5HEb>gxy+kJU1nJ;TyZHcXEy*a=7QMJWG`*RM;-33Y@E`whaidiLU-0A^ zDE2;rFmT~IoTJfCLG?ZbaD*{Ocpiyb1Can213Ar8XADGx42>>j8Q7j$${&Q|Yvp!p zds{W@g7G@ds2RW*kaeE8areY{mS)fxN7bX`n>oNsn^+*$ExwyHxgb;ajDeS`n?Ih(f0rh`dU;F0GieD33C zVAo!U*53G(hloPP*JdbI{K6lfV6B49)a3I?w@tWoq3t$oJ5wSVDK_RUWNMFzaq-1?J2dG4&6P`ea9fdZ(=2TNS)QpdozeujkhokX@gw&0z*!b1L5i%@7%DJ@l zI@gwh?P^g1CqF_ly%UV!DQgp6K1U0t92QCed?@E$NY|qQLD0{U%vc|^dRVC#m96g} zGbJnlmWoe(^o(<};B;-meba{*yywA+vMK&zOBYyQJY++ahK~j?rXc2lB--`%O{VNO zYA>^fj7xj>;r7Z7FMI;I{Mul~HUyC#~m7f2a+8*`;Li5b0& zilj_x+_c_Rq;avMv3gPmmYA~@eTZtfj~=b5Iyl5T2P>X`JM*I8H}6`Yi}vlTWVnv8 zg_Omn25D-Cet0P2|2pq^U851+jv6lo*j}sn?57^$m9Mw~-8TCRO{KjWUD_7pmppdH zpZmBO>#nxp8qpzrsGgD(xhtzFT%rUPMR8 zMhWnPF8?Y4K4F7lo=@iJ5?-5-7>hv;47^ybJZLOsOGj7ajx6UY?RXbSc0j z4FLFg^KgS7rwx@S*x0kPKA1dQOX z0>DAR$KTx0W$GaFh7X+rx+2~+XANd0RX_(d0S%VELJ&k_T^?p0UuLvJ}nDW#o#CxZX|MaS4|+AM|#9>yIWmZ1+J zmKE=Rh$0RMo^TNj04Twh=G{%f$uJexx8S@*LEL8CB=zvAW#gNq`>8ywaj>4L*8W0V z`-x|K8$8>0|GsE@z1n6nXCfpoO-)kYT$F045 z;!RRcs?aLu1raXP_FM~b;{K+z@gJ|RH^guJF{QP;!@(b*Q-KEbHUl0r$KDBP!W27S z5EW94sSIQUWdl(AFra&d5GtH*v7tn#dsW5palsRAYydO?*sh9qK2U+l)w`i1(ON_? zi~6#CBde5lwD(*Zm`FdbPXH9>1AG=iq)j>6K_2U_Vs}#U%-bgXmsecCKY!5?HqsXJ zO{E<~@^^pZD*pX%KZGB8%L%S7ZI|Lw70EapTujhk&tQ`j{M8FV^>#W5zW;lLAwGTPY$N_=s9K0?h-%GbB_YuRc z*5+<)N858d@ifuywNW#ISZKy~yHawtKO7GOj5%(bs`fVn^~MawC9Rex1{zVO`Fwq( zS)H*dG2~A)(pva0uooa$AzI8x9$C=VfrlsLU@59iaNmDtdbQuO(}ex8W@%hmr%e#- z%wtcW=N-gox4x(^A+=$L06@Z zTId9Os%^iju{l4r6N;R{oo_bx zF2Lm_WB>pg+JR}jGvIH@u`X}bsI%9_uT%^5iR2mii7qLP?Xh&*j77VivG`K}ExmRD zd^x#vd0R#FtX~m95y4Is2hzkB2W^o)`JkMZHwofCnr<|pppx3HApsNOtx3#rJ3(84 znV~{EN3xMBp@<-@zmJ0bQ|VqJIhrTqp1MccX<-)oqY+5B=mtoN?7Od2)VL!|t9tGI zYap+%;DQR+CZ>G#V+=}o%;U-&z+&NU=}%wS0EhmPPQks`S6trJ_Bx-A(jozE1- z4+|c71U&Vof=_+qAwKVMGd}r|8#lbur9};!so0K1)HGXX#OvJ3c}pS^;&-=o+ZwjGTTWraE?@9B(H+guRF?)nB_!){Um zkP>H96r)u)O=#CVFXC8Enmwp?AOu^VdC^`4_hrw~z{`e?ShU-ByRL%bL+4I!&rMiA zT&IQW)@UCFLWv(<@cLE~(1XEtf~)Ulq~?6&uW;|4|+$%r7% z2r#f!oSOaP!9SA6(d#e>&ZTw4@JbHT0WCOqnV!K2OzE**sSuC*oPir9Mw3V!~*JACtRT*Lbw ztk|5Nu`aEv(*)diWrx51s}-;M;v+!X5#oyCS{B&2qyf}EBVszjJTO@a{59}o;K6r_2wZGE($&x-3oh9D_SBy-hLpNB zY0ILmXegOEz+Dv_lAcxMHQS;V|{%!{k}Xa+wr zFh&tTljn`HgnkS~ow0(Z2qz1b6)S2GLHqnM) z!osfoce7bt1LB+L#A=WG6L?i$i|ln>AX9-9U_IU8+@|3BKj#Ae>L(lmsHkh(T%u5) ztx|1k?wd?o9^lsF3AY{t&$t<9fBIN-)$Z*JFm+&g%e@P}`}cPEi9b96&`um))|fR| zSHXOsc=daB_(!iV_|6v{wYsX}aTg1I^-C_|i+d0 z(*ng&QOr}@E6`rVvJdQ@Z=#5RjXyonK|mobwNC}TE5;WwJ_=@g3yU`bN?<^IS6gr( zgra)}5DcdW+U>+0Z3!r}xBQHt9&}cNr2uai$Y8`SfGqeux`-@8RvBoN{*sKexV$$W zNu;6bGd~jO%*;ni1S%v>3m1Xtic;E(KQA2$e(sBI!b=|0&InjmU^4*+g$e2)c}7&Q zD*7?u!Q3K(Qh-_7X+xV%<91cN_5(Zo+jpGcXWzZU>8@ZpC=hM$7Z78GDx_A_Qn0yL z@Lg{_#p7?<;IDte+}>GG6^}V5c=eaufUo_vtN7V>ZZRK~wp>^NGxA#w)4&w>Zvjj~ z;VQfF@Xo62jk^h-5tT70sK!m#B{J?k2WKBP?#MOv29yjb%10#JWGy96o7=FaPa_%F_rU=K`C&#f8xwmY?>LxRTmcwrK`7kw^k+a4kY=jqusi^u2<;_q17P;Y}L? z4ww387R6F4)W-kbS&3g78F|Z31PX|E0zI*%$P6^%Y$>GyR|uaxIhFTCAxgk9^uv|3 z_c=ud(R(D&kk02)@xZp?`ciRm1|S7D9tw`m9bu~z4mX0Ie)&bblcw;<74=U2PHY>5BC6nta$e&_}W`V|S;Vn1sDg zL^r1Qm1hA=siT1~s7RFL47d*#2&I@}Lp4D>*$jG~6x)S+CHr*{lXKJ^pkR?pIua|} zbNo5XG_=8=*o}cz1~4RCM$feMOc2LL3k+HkuNW))(c%xCR$S}@;#QdlxsM*0UmLF#-q;{Jo3EY z#slEEFEn^?TXD~I;Qf~??z+6-%2t|Fo`C6Kf*iC1J=Pk-LKbDpwP*vhBEZ-G+BMvF zUGevydkEDQ)fFiI*{7e!`OSj={k139oS(6)z`1h;Prk8bKc@n07sa1k)>!TiuPXO3GQWf{Q8j*_uK@nhq;HXd6 zR*-%tV509l^MO_;+d?bO83!3Odc>jjWj4viI9|Ndkr<qf*XbJ25j`FUbL&?>IoU!9ub;ussLpI z9$W->UjrUCg2kmeWw8JER`Tbjb`OiOqD?7z}{;;pgn|fag zY%RP3xV9?Z_fWJoaL#f<-2-+!B4t_~K(6O~7si7OnX97us&R#zQRe&^uz~B;T2+-7wC9FB(GaXIFIKWI=j*gG16Y(ytHo%=HU|YrY z*@40-i^Xd3qEWP|%v!@_`_mRVn;DOM@O>rlY82@_0B2^bM)T#Xka+)|4g{MO*Ev}4E&Q*wZ7MMV#-0Q=R-&hK)59;=E-B}DT=#`CGSqR#$Gl5)rnlDV?hA!riAmM& z?fDTI)()J}h=Wjj)2~+GeV1G2dso}Fr(ay~4If`HOB=(_6Yz)kt@z4czJe<H$2ESNV1o1+<<;|ZHX!R8Ry92Lw*1@or($wNyYyF2?C zEX1y9;0PyWyG~STb^rUfT*v4B{KL5WTASt)1(p@~&KDlzrH=>n!E1Qtjlj8CaoX1c zyz{{o5AP;VLIzWrb%R$oy;RbzE-U|Z=V1oIx|Oe4aduJ&d3zDs@WT#~B9hn(l68Qg z%oYVzZEq8vrwaDl$ssXz54I=*ptPNs;cHng+~?jGF*?ny^}y>)q#7CL8%Me*NEs~r zjch8f``5hHQrl@iOOF(kJ8S^tOJRksBd^;Q&5=oHt3SgpH2u?loPpGTfjFbo3_ule zraGShV@ow1in9usU}#!wT35XB!!ZCKLvy!02Y z;_hp0_+s4r{+C?9bhzL%9z6l*o1LKet-E)a&=$!wn%uh6G27WG7%c(H$x(DY3H=ay zj`w;H_{SCRU&yBS!ktt0{=RI!Urh-&21^Ne6=?uq=Pc&7ZFzU}$ET+IH9IEG`rw|Q zA~pZc@>8Nk+I~Gppp^UI2aSogja0($q_A{itivzMG-Xpo-_N30seUykCt;|!8^;~d z+GlBXg#a~>5sj{Nl1@k@VP4Em1UfebVxWt%o-zb-RP;N-|)* zBcQQJ)bz&xj_V{1ipZl*DFR*R4sEP;?WPv&)#P1HFR+meP`i z+tZ4#de$+1=p{#}8bcO4ZMXK|;+NjPV7n9)2|n(vLrefi?YZCudH+P*4-^dDghgO< zv>7i*iA`hFHJ7`zmt!6YUh^kg{L4SM-aNau$m6pgy}_f70j=6!8Y=kbpK%^9dBTkC z)g2~JW?9w2PZ_|}^v;cdBQXGWU`Rwq?Y_OEFukk6^=bGJ3i7h^=(y>iT_PT<{Vfz3 zW+$f_(}A#a1_eMr4Z@Z_+kaszgR{)DsxDi$4kIe5iu4nKSb=@)>m7=RgXyFY=%F|| z+Gr0??09SglO7_K9zyT$D9nJ8qYrMsOU7|1FR;l+&Cqzg2k+LZdlKh`QT65D{Yt`+65;Gey1iw|F29o&}{ zSZdo-TD!4-$|E-T^)I;@f9rYYuVFy_BHsgsM!uNrHENaiW71+QS;_To2FUz41Y(_aW8U zX`#0v*)=s?*$JB{$$(pLK-oQrn9(MKBj>yY5O$ z;@PHWJQ^Rk){Ja^y&x9 zh_r}`wmnASE+hB+K7=&cq*Q0f$@I*D5#jI(wIM_KLC09P8Vjk6;ZVOSY2p1bW0 z(@$H3Bhf|&8BH`Gei;2IHzCeM?<`1L;mVspj}&|WrY2Kbdmz}OBfNt47k@7J!lxbJ zTR-VMc59<^GXa-(ihubBC-~A|zJeco`w0Y!X)5?vzkh+Wwl>Pf$a6&TS6lBe)Jz^|pTCW0T!qPX!85L7Iyv)1LEazdrOy?Bxp-}}bP_??ez zaWDxUIIZ{_|Kl>g^jELor`~f40637g)3GY>eV=gwPrM0Ow`tgJ~ZHyqC#KdtO1rcgJ}*ilA*d+=R8*13sbs-;HghL{)=-j z%{lkkFE;WXt)xf}8uml?91tvOmmj#-7Xij;HMFwG!dVYV;EYh4H>T)<@$>N z=jV#6ONqq~42SU~VmojbE3ZT>g?O&MctYY*0yMj4US6z>k7aGG!Py_)VU@0n3{ela znZ4q?uK2yLxCNhh%LYqr$DqCS-W|T`RS)8A4^99oFi&{F?FEyrc-;rCLFO4U&ABgb zd8^YV3Vi3Mp2uH&>Ji>{--5sT>dUz6T1A;`?;($2ts0x?HsR%S6Fl=>fOT8(cb|I> zf9ILU_`t&p{>pD$!MpBXJ2(lXOfF3AfNDIb+Z~RNCVcuGM|j^u3;y`N752isFMMLb z|Mh2Y#QC|I+@=Wr%{#8+|Ng5FV?MUs5~T1fV~}1#0L{n9yLo5%5?P^l(q!QWNd|`FX|3Dp=~UWH(S2yvitTl}|$z`;>SL3R~0^rPS*a z`N4bD5zvfH=}!WHy@NHB803N{l+-Aw(q4{mSXNxw6-Q(@JntV>s3tsOHpy%NBUS9UHvPrb899yG zhbB_`v4a(xQd18C(dtHELCt)3)*q862q~f(x^wM zFGSNBHp<3tpk~f_$RBp5_&Il7i0<{NR<$(%3Of)}dPwDAm)S=jr%eLbuBQm`nh-dW zib&n2*OU@&X0*LyK13OnB|;}SL)$Y>r{xa>u&I-rH?Tw+8G9P%<+TwpjbjMge%G^)MaW?}VjzQqz_N9Y1uYP@L z^Zk!VyY0e5cz!_Orvrr}3kCPXLVJ5RAGZci*JdL(ZjAQ@S#ZS9E?Y%GK|AJPnglBf zmMU156`P9_{y*+Fz zLXozKi^3@SP199Id;eamMw8M#pa6BJ`04kYA|x+(?rnBX4e`PFZjnXr3@=f3uOr^k zUN(}Y4Wy{QG()wg$DM}2IF^;^SM)dA&VGIFKO7*Nom6daV6t-notGNF_cyLZov~bd zkOv+8B?x}%!V0quqNpVCNZ?Za@H3s?Rlx84bbg@m3TGC917P1*~ zpOp9>y@(6|0X(ha@DF)rzL(y!V1~Tsnbi3adW0@V^_`%a%Bpzi&0Q>w*@RR>6fs!BG)tKl}db zPO)rHfpSE%8RB4?x}czF$e}R^sPL6T!ZL6JwdbtwfXyp}LF^lGfN*D*ceuB2bUPnO z4kP{j=~9H8jA^;x!EFOV!@i3LolbH%)|Q9K>j-Wr-^t5lj z$*}LUJ|2%axOLs2e2{hn^676|ZZ{^3`$jIC7B8hIZ6zF+Co~Q<_S^6QATo+R3mA=~a2w4D~nWo)?Y33aOpmeWOJ7J;A%B^IEQ&0Dsv?La&oc8;z zvy!sg6h<*^M!rv32LHT4D=I)_T_upsO%EX?2?IN+Z79$?hI1QWGtW4Ysqw2?+oX^V z?E!3tQ|(jzk9FxY0-Z^#v4c;e0bu9NC75$i6dUHzv;B-VFR zB;t+a@@DTb?y>T%SH4lnRSup>|H!okcV1arM!W)#ySTyAZa>$DfE9wak`KDJAM1n0 zTKnKTqqPEdicr_d_7V>TmMwf!RqvyF{6e85^*@qO0uMXuimC4mwfXv~G$_})!nPrM zLfE0jc%;E!0v2yuS3Kv|emZJb*mvH43M>nX@J=@b!5ZWFJ-u|N5;_<|0I=Ka{LY($ z*bdB0_w+8=3AJl$2uw!|7^;oK*>-|%yIOoO7?wB>zn}&@rsSvPt zge{S1iLqKRv?7#GX$4)S4z~nL%Fg#6UUEAXeyLI~*H>2g`^~L>OJ3NEG$hFPRdJNm zv6+C_lwnLl1SsAf@rgjfg+VK&cqTzSF=k1jPztX@q|qwW?@6#+-{Q^p?4S@V0Olh2 ziYFgIx7)VP-_*dfy`*$xz)j$h6*its)CmXNqn&-E=3``y38L&Zpa^)i)mjy3>d`pnb{kZNo-Lt@!AS)Si0^~h?%OK;R zL;&P3NFgts$JUvCrTPLGhQE`eVErS&*3i?IYm1$HWb&a?w5ru+0yuG(9a^^uiww*W z8Bc80DC?F{sEXo=mSO56{}@3MOGHOh_s+tZ%PbZlkM3GSN@ULuOcl)vJba0=hT464 z#*LH&X~`H{PMScgzl5WW7rR$T(}aYo#$-fS+K0AF8~spV-r!XqS|Dg|$Em9L+NT}i zi8m>>Clv>?B*T<~_JWdP%4tfRryMH;)8UNY{m6-H-&erVLcscbQ1G_SW@78oA>3IX1_O|%^4r(Q6v91ds z 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 literal 0 HcmV?d00001 diff --git a/QT/cmake/app_icon.rc.in b/QT/cmake/app_icon.rc.in new file mode 100644 index 0000000..b754112 --- /dev/null +++ b/QT/cmake/app_icon.rc.in @@ -0,0 +1 @@ +IDI_ICON1 ICON "@REWRITE_QT_APP_ICON@" diff --git a/QT/cmake/rewrite_qt.desktop.in b/QT/cmake/rewrite_qt.desktop.in new file mode 100644 index 0000000..35224cd --- /dev/null +++ b/QT/cmake/rewrite_qt.desktop.in @@ -0,0 +1,7 @@ +[Desktop Entry] +Type=Application +Name=人脸识别考勤系统 +Exec=apprewrite_qt +Icon=rewrite_qt +Terminal=false +Categories=Utility; diff --git a/QT/main.cpp b/QT/main.cpp new file mode 100644 index 0000000..101ba11 --- /dev/null +++ b/QT/main.cpp @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/AppController.h" + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + QIcon appIcon(QStringLiteral(":/assets/favicon.ico")); + appIcon.addFile(QStringLiteral(":/assets/favicon-256x256.png")); + appIcon.addFile(QStringLiteral(":/assets/favicon-192x192.png")); + appIcon.addFile(QStringLiteral(":/assets/favicon-128x128.png")); + appIcon.addFile(QStringLiteral(":/assets/favicon-64x64.png")); + appIcon.addFile(QStringLiteral(":/assets/favicon-48x48.png")); + appIcon.addFile(QStringLiteral(":/assets/favicon-32x32.png")); + appIcon.addFile(QStringLiteral(":/assets/favicon-16x16.png")); + app.setWindowIcon(appIcon); + + QCoreApplication::setApplicationName("人脸识别考勤系统"); + QCoreApplication::setApplicationVersion("3.0.0"); + QCoreApplication::setOrganizationName("STM32 Face Recognition"); + QQuickStyle::setStyle("Basic"); + +#if defined(Q_OS_ANDROID) + QQuickWindow::setTextRenderType(QQuickWindow::NativeTextRendering); +#endif + + AppController controller; + + QQmlApplicationEngine engine; + const QString qmlImportPath = QLibraryInfo::path(QLibraryInfo::QmlImportsPath); + if (!qmlImportPath.isEmpty()) { + engine.addImportPath(qmlImportPath); + } +#if defined(REWRITE_QT_INSTALL_QML) + const QString qtInstallQmlPath = QStringLiteral(REWRITE_QT_INSTALL_QML); + if (QDir(qtInstallQmlPath).exists()) { + engine.addImportPath(qtInstallQmlPath); + } +#endif + engine.rootContext()->setContextProperty("appController", &controller); + + const QUrl url(QStringLiteral("qrc:/qml/Main.qml")); + QObject::connect( + &engine, + &QQmlApplicationEngine::objectCreated, + &app, + [url](QObject *obj, const QUrl &objUrl) { + if (!obj && url == objUrl) { + QCoreApplication::exit(-1); + } + }, + Qt::QueuedConnection); + + engine.load(url); + return app.exec(); +} diff --git a/QT/qml/Main.qml b/QT/qml/Main.qml new file mode 100644 index 0000000..da0f5a2 --- /dev/null +++ b/QT/qml/Main.qml @@ -0,0 +1,2945 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Dialogs + +ApplicationWindow { + id: window + width: 1560 + height: 920 + minimumWidth: 900 + minimumHeight: 620 + visible: true + title: "人脸识别考勤系统" + color: "#f6f7f9" + + readonly property color ink900: "#182230" + readonly property color ink700: "#475467" + readonly property color ink500: "#667085" + readonly property color lineColor: "#d8dde5" + readonly property color shellColor: "#f6f7f9" + readonly property color panelColor: "#f9fafb" + readonly property color panelStrong: "#ffffff" + readonly property color accentColor: "#b6543a" + readonly property color accentDeep: "#8e3f29" + readonly property color accentSoft: "#f4d6c8" + readonly property color tealColor: "#1f6f78" + readonly property color tealSoft: "#d7ecec" + readonly property color goldColor: "#aa7a1f" + readonly property color goldSoft: "#f5e8c6" + readonly property color successColor: "#1f7a4d" + readonly property color dangerColor: "#b9382f" + readonly property string appFontFamily: Qt.platform.os === "android" ? "sans-serif" : "Microsoft YaHei UI" + readonly property int appBoldWeight: Qt.platform.os === "android" ? Font.Medium : Font.Bold + + property string statisticsPreset: "最近30天" + property int editingTimeSlotIndex: -1 + property string pendingDeleteFaceId: "" + property string toastMessage: "" + property bool toastVisible: false + property bool resizingWindow: false + property int currentPageIndex: 0 + property bool timeSlotsExpanded: false + property bool mappingsExpanded: false + readonly property bool compactLayout: width < 1460 + readonly property bool denseLayout: width < 1380 + readonly property bool narrowLayout: width < 1280 + readonly property bool slimLayout: width < 1040 + readonly property bool phoneLayout: width < 560 + readonly property int sidebarWidth: slimLayout ? 0 : (compactLayout ? 212 : 240) + + font.family: appFontFamily + + onWidthChanged: { + resizingWindow = true; + resizeSettledTimer.restart(); + } + + onHeightChanged: { + resizingWindow = true; + resizeSettledTimer.restart(); + } + + function switchPage(index) { + currentPageIndex = Math.max(0, Math.min(4, index)); + } + + Timer { + id: resizeSettledTimer + interval: 160 + repeat: false + onTriggered: resizingWindow = false + } + + component AppCard: Rectangle { + radius: 8 + color: panelStrong + border.color: lineColor + } + + component AppTextField: TextField { + id: control + implicitHeight: 42 + leftPadding: 14 + rightPadding: 14 + topPadding: 10 + bottomPadding: 10 + color: ink900 + selectedTextColor: "#ffffff" + selectionColor: accentColor + placeholderTextColor: "#98a2b3" + + background: Rectangle { + radius: 8 + color: "#ffffff" + border.width: control.activeFocus ? 2 : 1 + border.color: control.activeFocus ? accentColor : "#d6cec4" + } + } + + component AppComboBox: ComboBox { + id: control + implicitHeight: 42 + leftPadding: 14 + rightPadding: 32 + font.pixelSize: 13 + + delegate: ItemDelegate { + width: ListView.view.width + text: modelData + highlighted: control.highlightedIndex === index + } + + contentItem: Text { + leftPadding: 0 + rightPadding: 0 + text: control.displayText + font: control.font + color: ink900 + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + + indicator: Label { + x: control.width - width - 12 + y: (control.height - height) / 2 + text: "⌄" + color: ink500 + font.pixelSize: 16 + } + + background: Rectangle { + radius: 8 + color: "#ffffff" + border.width: control.activeFocus ? 2 : 1 + border.color: control.activeFocus ? accentColor : "#d6cec4" + } + + popup: Popup { + y: control.height + 6 + width: control.width + padding: 6 + + background: Rectangle { + radius: 8 + color: "#ffffff" + border.color: lineColor + } + + contentItem: ListView { + implicitHeight: contentHeight + model: control.popup.visible ? control.delegateModel : null + currentIndex: control.highlightedIndex + clip: true + } + } + } + + component PrimaryButton: Button { + id: control + property color fillColor: accentColor + property color labelColor: "#fff7f2" + hoverEnabled: true + implicitHeight: 42 + implicitWidth: 112 + + background: Rectangle { + radius: 8 + color: control.down ? Qt.darker(control.fillColor, 1.12) : control.hovered ? Qt.lighter(control.fillColor, 1.06) : control.fillColor + } + + contentItem: Label { + text: control.text + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: control.labelColor + font.pixelSize: 13 + font.weight: appBoldWeight + } + } + + component SecondaryButton: Button { + id: control + property color fillColor: "#ffffff" + property color strokeColor: "#d6cec4" + property color labelColor: ink900 + hoverEnabled: true + implicitHeight: 42 + implicitWidth: 96 + + background: Rectangle { + radius: 8 + color: control.down ? "#efe6db" : control.hovered ? "#f7f1ea" : control.fillColor + border.color: control.hovered ? accentSoft : control.strokeColor + } + + contentItem: Label { + text: control.text + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: control.labelColor + font.pixelSize: 13 + font.weight: appBoldWeight + } + } + + component DangerButton: PrimaryButton { + fillColor: dangerColor + labelColor: "#fff5f4" + } + + component AppCheckBox: CheckBox { + id: control + spacing: 10 + indicator: Rectangle { + implicitWidth: 20 + implicitHeight: 20 + radius: 6 + color: control.checked ? accentColor : "#ffffff" + border.width: 1 + border.color: control.checked ? accentColor : "#cfc6bc" + + Rectangle { + anchors.centerIn: parent + width: 8 + height: 8 + radius: 4 + color: "#fff7f2" + visible: control.checked + } + } + + contentItem: Text { + text: control.text + color: ink700 + font: control.font + verticalAlignment: Text.AlignVCenter + leftPadding: control.indicator.width + control.spacing + } + } + + component AppScrollBar: ScrollBar { + id: control + implicitWidth: 12 + policy: ScrollBar.AsNeeded + + contentItem: Rectangle { + implicitWidth: 8 + radius: 4 + color: control.pressed ? accentColor : "#cfbeb1" + opacity: control.active ? 0.9 : 0.55 + } + + background: Item {} + } + + component EmptyState: Item { + id: emptyState + property string title: "" + property string description: "" + property string badgeText: "" + property color accent: accentColor + readonly property bool tightState: phoneLayout || height < 190 + + implicitWidth: phoneLayout ? 280 : 320 + implicitHeight: phoneLayout ? 154 : 220 + width: Math.min(implicitWidth, parent ? Math.max(180, parent.width - 28) : implicitWidth) + height: Math.min(implicitHeight, parent ? Math.max(126, parent.height - 20) : implicitHeight) + z: 20 + + Rectangle { + anchors.fill: parent + radius: 8 + color: "#fffaf4" + border.color: "#e7ddd2" + + Column { + anchors.centerIn: parent + spacing: emptyState.tightState ? 8 : 12 + width: parent.width - 32 + + Rectangle { + width: emptyState.tightState ? 52 : 64 + height: width + radius: 8 + color: Qt.tint("#ffffff", Qt.rgba(accent.r, accent.g, accent.b, 0.16)) + anchors.horizontalCenter: parent.horizontalCenter + + Label { + anchors.centerIn: parent + text: badgeText + color: accent + font.pixelSize: emptyState.tightState ? 18 : 22 + font.weight: appBoldWeight + } + } + + Label { + width: parent.width + text: title + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + color: ink900 + font.pixelSize: emptyState.tightState ? 18 : 20 + font.weight: appBoldWeight + } + + Label { + width: parent.width + visible: !emptyState.tightState || parent.width > 260 + text: description + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + color: ink500 + font.pixelSize: emptyState.tightState ? 12 : 13 + } + } + } + } + + component InfoChip: Rectangle { + property string textValue: "" + property color tintColor: accentColor + + implicitHeight: 30 + implicitWidth: chipLabel.implicitWidth + 18 + radius: 15 + color: Qt.tint("#ffffff", Qt.rgba(tintColor.r, tintColor.g, tintColor.b, 0.16)) + border.color: Qt.tint("#ffffff", Qt.rgba(tintColor.r, tintColor.g, tintColor.b, 0.34)) + + Label { + id: chipLabel + anchors.centerIn: parent + text: parent.textValue + color: parent.tintColor + font.pixelSize: 11 + font.weight: appBoldWeight + } + } + + component SectionHeader: Item { + id: sectionHeader + property string title: "" + property string description: "" + property color accent: accentColor + + implicitHeight: descriptionLabel.visible ? (phoneLayout ? 64 : 52) : 32 + implicitWidth: 300 + + RowLayout { + anchors.fill: parent + spacing: 12 + + Rectangle { + Layout.preferredWidth: 6 + Layout.fillHeight: true + radius: 3 + color: sectionHeader.accent + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 2 + + Label { + Layout.fillWidth: true + text: sectionHeader.title + font.pixelSize: phoneLayout ? 20 : 22 + font.weight: appBoldWeight + color: ink900 + wrapMode: Text.WordWrap + } + + Label { + id: descriptionLabel + Layout.fillWidth: true + visible: text.length > 0 + text: sectionHeader.description + color: ink500 + font.pixelSize: 12 + wrapMode: Text.WordWrap + } + } + } + } + + component SegmentTabButton: TabButton { + id: control + implicitHeight: 40 + padding: 0 + + background: Rectangle { + radius: 8 + color: control.checked ? tealColor : "#ffffff" + border.width: 1 + border.color: control.checked ? tealColor : "#d6cec4" + } + + contentItem: Label { + text: control.text + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: control.checked ? "#f6fbfb" : ink700 + font.pixelSize: 13 + font.weight: appBoldWeight + elide: Text.ElideRight + } + } + + component MobileNavTabButton: TabButton { + id: control + implicitHeight: 42 + padding: 0 + + background: Rectangle { + radius: 8 + color: control.checked ? tealColor : panelStrong + border.width: 1 + border.color: control.checked ? tealColor : lineColor + } + + contentItem: Label { + text: control.text + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: control.checked ? "#f6fbfb" : ink700 + font.pixelSize: phoneLayout ? 12 : 13 + font.weight: appBoldWeight + elide: Text.ElideRight + } + } + + function applyRecordFilters() { + appController.applyFilters(classFilter.currentText, studentFilter.currentText, nameFilter.text, dateFilter.currentIndex, specificDateField.text); + } + + function applyStatisticsPreset() { + const today = new Date(); + let start = new Date(today); + let end = new Date(today); + + if (statisticsPreset === "今天") { + start = new Date(today); + } else if (statisticsPreset === "最近7天") { + start.setDate(start.getDate() - 7); + } else if (statisticsPreset === "最近30天") { + start.setDate(start.getDate() - 30); + } else if (statisticsPreset === "本月") { + start = new Date(today.getFullYear(), today.getMonth(), 1); + } + + statsStartField.text = Qt.formatDate(start, "yyyy-MM-dd"); + statsEndField.text = Qt.formatDate(end, "yyyy-MM-dd"); + appController.updateStatisticsRange(statsStartField.text, statsEndField.text); + } + + function openTimeSlotDialog(index) { + editingTimeSlotIndex = index; + if (index >= 0) { + const item = appController.timeSlotModel.get(index); + timeSlotNameField.text = item.name; + timeSlotStartField.text = item.startTime; + timeSlotEndField.text = item.endTime; + timeSlotEnabledBox.checked = item.enabled; + timeSlotDialog.title = "编辑时间段"; + } else { + timeSlotNameField.text = ""; + timeSlotStartField.text = "08:00"; + timeSlotEndField.text = "09:30"; + timeSlotEnabledBox.checked = true; + timeSlotDialog.title = "新增时间段"; + } + timeSlotDialog.open(); + } + + function saveTimeSlotDialog() { + if (editingTimeSlotIndex >= 0) { + appController.timeSlotModel.updateTimeSlot(editingTimeSlotIndex, timeSlotNameField.text, timeSlotStartField.text, timeSlotEndField.text, timeSlotEnabledBox.checked); + } else { + appController.timeSlotModel.addTimeSlot(timeSlotNameField.text, timeSlotStartField.text, timeSlotEndField.text, timeSlotEnabledBox.checked); + } + appController.saveTimeSlots(); + } + + Component.onCompleted: { + applyRecordFilters(); + applyStatisticsPreset(); + } + + Connections { + target: appController + + function onStatusMessageChanged() { + if (!appController.statusMessage || appController.statusMessage.length === 0) { + return; + } + toastMessage = appController.statusMessage; + toastVisible = true; + toastTimer.restart(); + } + } + + Timer { + id: toastTimer + interval: 2600 + repeat: false + onTriggered: toastVisible = false + } + + background: Rectangle { + color: shellColor + } + + FileDialog { + id: recordExportDialog + fileMode: FileDialog.SaveFile + nameFilters: ["CSV 文件 (*.csv)"] + currentFile: "attendance_export.csv" + onAccepted: appController.exportFilteredRecords(selectedFile) + } + + FileDialog { + id: statisticsExportDialog + fileMode: FileDialog.SaveFile + nameFilters: ["CSV 文件 (*.csv)"] + currentFile: "attendance_statistics.csv" + onAccepted: appController.exportStatistics(selectedFile) + } + + Dialog { + id: clearDialog + title: "确认清空" + modal: true + anchors.centerIn: Overlay.overlay + width: 440 + standardButtons: Dialog.Yes | Dialog.No + + background: Rectangle { + radius: 20 + color: panelStrong + border.color: lineColor + } + + enter: Transition { + ParallelAnimation { + NumberAnimation { + property: "opacity" + from: 0 + to: 1 + duration: 150 + } + NumberAnimation { + property: "scale" + from: 0.96 + to: 1.0 + duration: 180 + easing.type: Easing.OutCubic + } + } + } + + exit: Transition { + ParallelAnimation { + NumberAnimation { + property: "opacity" + from: 1 + to: 0 + duration: 120 + } + NumberAnimation { + property: "scale" + from: 1.0 + to: 0.98 + duration: 120 + } + } + } + + contentItem: ColumnLayout { + spacing: 14 + + Label { + text: "确定要清空服务器上的所有签到记录吗?" + font.pixelSize: 20 + font.weight: appBoldWeight + color: ink900 + } + + Label { + text: "该操作不可恢复,建议先导出数据备份。" + wrapMode: Text.WordWrap + color: ink700 + } + } + + onAccepted: appController.clearAllRecords() + } + + Dialog { + id: timeSlotDialog + modal: true + anchors.centerIn: Overlay.overlay + width: 420 + standardButtons: Dialog.Save | Dialog.Cancel + + background: Rectangle { + radius: 20 + color: panelStrong + border.color: lineColor + } + + enter: Transition { + ParallelAnimation { + NumberAnimation { + property: "opacity" + from: 0 + to: 1 + duration: 150 + } + NumberAnimation { + property: "scale" + from: 0.96 + to: 1.0 + duration: 180 + easing.type: Easing.OutCubic + } + } + } + + exit: Transition { + ParallelAnimation { + NumberAnimation { + property: "opacity" + from: 1 + to: 0 + duration: 120 + } + NumberAnimation { + property: "scale" + from: 1.0 + to: 0.98 + duration: 120 + } + } + } + + contentItem: ColumnLayout { + spacing: 12 + + AppTextField { + id: timeSlotNameField + Layout.fillWidth: true + placeholderText: "时段名称" + } + + AppTextField { + id: timeSlotStartField + Layout.fillWidth: true + placeholderText: "开始时间,例如 08:00" + } + + AppTextField { + id: timeSlotEndField + Layout.fillWidth: true + placeholderText: "结束时间,例如 09:30" + } + + AppCheckBox { + id: timeSlotEnabledBox + text: "启用此时段" + } + } + + onAccepted: saveTimeSlotDialog() + } + + Dialog { + id: deleteFaceDialog + modal: true + anchors.centerIn: Overlay.overlay + width: 430 + title: "删除人脸信息" + standardButtons: Dialog.Yes | Dialog.No + + background: Rectangle { + radius: 20 + color: panelStrong + border.color: lineColor + } + + enter: Transition { + ParallelAnimation { + NumberAnimation { + property: "opacity" + from: 0 + to: 1 + duration: 150 + } + NumberAnimation { + property: "scale" + from: 0.96 + to: 1.0 + duration: 180 + easing.type: Easing.OutCubic + } + } + } + + exit: Transition { + ParallelAnimation { + NumberAnimation { + property: "opacity" + from: 1 + to: 0 + duration: 120 + } + NumberAnimation { + property: "scale" + from: 1.0 + to: 0.98 + duration: 120 + } + } + } + + contentItem: ColumnLayout { + spacing: 12 + + Label { + text: "确定删除 ID 为 " + pendingDeleteFaceId + " 的人脸信息吗?" + wrapMode: Text.WordWrap + font.pixelSize: 18 + font.weight: appBoldWeight + color: ink900 + } + + AppCheckBox { + id: deleteFaceRecordsCheck + text: "同时删除该学生的所有考勤记录" + checked: false + } + } + + onAccepted: appController.deleteFace(pendingDeleteFaceId, deleteFaceRecordsCheck.checked) + } + + Rectangle { + anchors.fill: parent + anchors.margins: slimLayout ? 8 : 16 + radius: 12 + color: "#ffffff" + border.color: "#dbd6ce" + + RowLayout { + anchors.fill: parent + anchors.margins: slimLayout ? 10 : 16 + spacing: slimLayout ? 0 : 16 + + Rectangle { + visible: !slimLayout + Layout.preferredWidth: visible ? sidebarWidth : 0 + Layout.maximumWidth: visible ? sidebarWidth : 0 + Layout.fillHeight: true + radius: 12 + color: "#15323d" + + ColumnLayout { + anchors.fill: parent + anchors.margins: 18 + spacing: 16 + + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: compactLayout ? 74 : 86 + radius: 8 + color: "#214654" + + Label { + anchors.centerIn: parent + width: parent.width - 18 + text: "人脸识别考勤系统" + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + font.pixelSize: compactLayout ? 17 : 19 + font.weight: appBoldWeight + color: "#ffffff" + } + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 8 + + Repeater { + model: [ + { + title: "考勤记录", + hint: "查看筛选与导出", + icon: "01" + }, + { + title: "统计分析", + hint: "按时间统计趋势", + icon: "02" + }, + { + title: "配置中心", + hint: "时间段与映射设置", + icon: "03" + }, + { + title: "人脸管理", + hint: "照片与学号绑定", + icon: "04" + }, + { + title: "关于", + hint: "系统说明", + icon: "05" + } + ] + + delegate: Rectangle { + id: navButton + required property var modelData + required property int index + readonly property bool selected: window.currentPageIndex === navButton.index + Layout.fillWidth: true + Layout.preferredHeight: 74 + radius: 8 + color: selected ? "#eef7f7" : navMouse.containsMouse ? "#214957" : "#173743" + border.width: 1 + border.color: selected ? "#9fd4d7" : navMouse.containsMouse ? "#3b6470" : "#254a55" + + Behavior on color { + enabled: !resizingWindow + ColorAnimation { + duration: 120 + } + } + Behavior on border.color { + enabled: !resizingWindow + ColorAnimation { + duration: 120 + } + } + + Rectangle { + anchors.right: parent.right + anchors.rightMargin: 6 + anchors.verticalCenter: parent.verticalCenter + width: 4 + height: navButton.selected ? 42 : 0 + radius: 2 + color: tealColor + opacity: navButton.selected ? 1 : 0 + + Behavior on height { + enabled: !resizingWindow + NumberAnimation { + duration: 150 + } + } + Behavior on opacity { + enabled: !resizingWindow + NumberAnimation { + duration: 120 + } + } + } + + RowLayout { + anchors.fill: parent + anchors.leftMargin: 16 + anchors.rightMargin: 24 + spacing: compactLayout ? 10 : 12 + + Rectangle { + Layout.preferredWidth: 38 + Layout.preferredHeight: 38 + radius: 8 + color: navButton.selected ? tealSoft : "#2a515d" + + Label { + anchors.centerIn: parent + text: modelData.icon + color: navButton.selected ? tealColor : "#d6e4e9" + font.weight: appBoldWeight + } + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 2 + + Label { + Layout.fillWidth: true + text: modelData.title + color: navButton.selected ? ink900 : "#f4fbff" + font.pixelSize: compactLayout ? 14 : 15 + font.weight: appBoldWeight + horizontalAlignment: Text.AlignLeft + } + + Label { + Layout.fillWidth: true + text: modelData.hint + visible: !denseLayout + color: navButton.selected ? ink500 : "#adc4cc" + font.pixelSize: compactLayout ? 10 : 11 + horizontalAlignment: Text.AlignLeft + } + } + } + + MouseArea { + id: navMouse + anchors.fill: parent + z: 20 + cursorShape: Qt.PointingHandCursor + hoverEnabled: true + preventStealing: true + onPressed: window.switchPage(navButton.index) + onClicked: window.switchPage(navButton.index) + } + } + } + } + + Item { + Layout.fillHeight: true + } + + PrimaryButton { + Layout.fillWidth: true + text: "刷新全部数据" + onClicked: appController.refreshAll() + } + } + } + + Rectangle { + Layout.fillWidth: true + Layout.fillHeight: true + radius: 26 + color: "transparent" + + ColumnLayout { + anchors.fill: parent + spacing: 16 + + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: phoneLayout ? 108 : (slimLayout ? 96 : 142) + radius: 8 + color: panelStrong + border.color: lineColor + clip: true + + RowLayout { + anchors.fill: parent + anchors.margins: slimLayout ? 14 : 20 + spacing: 18 + + ColumnLayout { + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + spacing: 6 + + Label { + Layout.fillWidth: true + text: ["考勤记录总览", "统计分析面板", "配置与同步中心", "人脸资料管理", "关于"][window.currentPageIndex] + font.pixelSize: slimLayout ? 20 : (compactLayout ? 24 : 28) + font.weight: appBoldWeight + color: ink900 + elide: Text.ElideRight + } + + Label { + visible: !slimLayout + text: ["筛选记录、导出数据并快速查看考勤状态。", "按时间区间查看签到情况,导出统计报表。", "集中管理时间段、映射配置和连接信息。", "同步照片、调整学号映射并执行删除操作。", "了解系统用途、功能范围和运行信息。"][window.currentPageIndex] + color: ink500 + font.pixelSize: compactLayout ? 12 : 13 + } + + Flow { + visible: !slimLayout + Layout.fillWidth: true + spacing: 8 + + InfoChip { + textValue: ["实时筛选", "区间统计", "配置同步", "人脸映射", "系统说明"][window.currentPageIndex] + tintColor: [accentColor, goldColor, tealColor, accentColor, tealColor][window.currentPageIndex] + } + + InfoChip { + textValue: compactLayout ? "紧凑布局" : "桌面布局" + tintColor: tealColor + } + } + } + + Flow { + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + Layout.preferredWidth: implicitWidth + spacing: compactLayout ? 8 : 10 + + PrimaryButton { + visible: window.currentPageIndex === 0 + text: "导出当前结果" + onClicked: recordExportDialog.open() + } + + SecondaryButton { + visible: window.currentPageIndex === 1 + text: "导出统计报表" + onClicked: statisticsExportDialog.open() + } + + SecondaryButton { + visible: window.currentPageIndex === 2 + text: "测试连接" + onClicked: appController.testConnection() + } + + SecondaryButton { + visible: window.currentPageIndex === 3 + text: "刷新人脸库" + onClicked: appController.refreshFaces() + } + } + } + } + + TabBar { + id: navigationBar + visible: slimLayout + Layout.fillWidth: true + Layout.preferredHeight: visible ? 42 : 0 + spacing: 6 + padding: 0 + property real tabWidth: (width - spacing * 4) / 5 + currentIndex: window.currentPageIndex + onCurrentIndexChanged: window.switchPage(currentIndex) + background: Item {} + + MobileNavTabButton { + width: navigationBar.tabWidth + text: "考勤记录" + } + MobileNavTabButton { + width: navigationBar.tabWidth + text: "统计分析" + } + MobileNavTabButton { + width: navigationBar.tabWidth + text: "配置中心" + } + MobileNavTabButton { + width: navigationBar.tabWidth + text: "人脸管理" + } + MobileNavTabButton { + width: navigationBar.tabWidth + text: "关于" + } + } + + StackLayout { + id: pageLayout + Layout.fillWidth: true + Layout.fillHeight: true + currentIndex: window.currentPageIndex + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + visible: StackLayout.isCurrentItem + opacity: StackLayout.isCurrentItem ? 1 : 0 + scale: resizingWindow || StackLayout.isCurrentItem ? 1 : 0.985 + Behavior on opacity { + enabled: !resizingWindow + NumberAnimation { + duration: 140 + } + } + Behavior on scale { + enabled: !resizingWindow + NumberAnimation { + duration: 180 + easing.type: Easing.OutCubic + } + } + + ColumnLayout { + anchors.fill: parent + spacing: 14 + + GridLayout { + Layout.fillWidth: true + columns: slimLayout ? 3 : (compactLayout ? 1 : 3) + rowSpacing: 10 + columnSpacing: compactLayout ? 10 : 14 + + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 82 + radius: 8 + color: panelStrong + border.color: lineColor + clip: true + + Column { + anchors.fill: parent + anchors.topMargin: slimLayout ? 12 : 18 + anchors.bottomMargin: slimLayout ? 12 : 18 + anchors.leftMargin: slimLayout ? 34 : 44 + anchors.rightMargin: slimLayout ? 12 : 18 + spacing: 6 + Label { + text: "总记录数" + color: ink500 + } + Label { + text: appController.totalRecords + font.pixelSize: slimLayout ? 22 : (compactLayout ? 30 : 34) + font.weight: appBoldWeight + color: ink900 + } + } + + Rectangle { + anchors.left: parent.left + anchors.leftMargin: slimLayout ? 12 : 18 + anchors.verticalCenter: parent.verticalCenter + width: 6 + height: Math.min(parent.height - 18, 64) + radius: 3 + color: accentColor + } + } + + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 82 + radius: 8 + color: panelStrong + border.color: lineColor + clip: true + + Column { + anchors.fill: parent + anchors.topMargin: slimLayout ? 12 : 18 + anchors.bottomMargin: slimLayout ? 12 : 18 + anchors.leftMargin: slimLayout ? 34 : 44 + anchors.rightMargin: slimLayout ? 12 : 18 + spacing: 6 + Label { + text: "今日签到" + color: ink500 + } + Label { + text: appController.todayRecords + font.pixelSize: slimLayout ? 22 : (compactLayout ? 30 : 34) + font.weight: appBoldWeight + color: tealColor + } + } + + Rectangle { + anchors.left: parent.left + anchors.leftMargin: slimLayout ? 12 : 18 + anchors.verticalCenter: parent.verticalCenter + width: 6 + height: Math.min(parent.height - 18, 64) + radius: 3 + color: tealColor + } + } + + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 82 + radius: 8 + color: panelStrong + border.color: lineColor + clip: true + + Column { + anchors.fill: parent + anchors.topMargin: slimLayout ? 12 : 18 + anchors.bottomMargin: slimLayout ? 12 : 18 + anchors.leftMargin: slimLayout ? 34 : 44 + anchors.rightMargin: slimLayout ? 12 : 18 + spacing: 6 + Label { + text: "筛选结果" + color: ink500 + } + Label { + text: appController.filteredCount + " / " + appController.loadedRecords + font.pixelSize: slimLayout ? 20 : (compactLayout ? 26 : 30) + font.weight: appBoldWeight + color: goldColor + } + } + + Rectangle { + anchors.left: parent.left + anchors.leftMargin: slimLayout ? 12 : 18 + anchors.verticalCenter: parent.verticalCenter + width: 6 + height: Math.min(parent.height - 18, 64) + radius: 3 + color: goldColor + } + } + } + + Rectangle { + Layout.fillWidth: true + radius: 8 + color: panelStrong + border.color: lineColor + Layout.preferredHeight: phoneLayout ? (dateFilter.currentIndex === 4 ? 300 : 236) : (slimLayout ? (dateFilter.currentIndex === 4 ? 300 : 220) : 98) + clip: true + + GridLayout { + anchors.fill: parent + anchors.margins: slimLayout ? 12 : 14 + columns: slimLayout ? 2 : (dateFilter.currentIndex === 4 ? 6 : 5) + columnSpacing: 12 + rowSpacing: 12 + + Column { + Layout.fillWidth: true + Layout.columnSpan: 1 + Layout.preferredWidth: slimLayout ? 1 : 170 + Layout.minimumWidth: slimLayout ? 0 : 140 + spacing: 6 + Label { + text: "班级" + color: ink700 + font.weight: appBoldWeight + font.pixelSize: 12 + } + AppComboBox { + id: classFilter + width: parent.width + model: appController.classOptions + onCurrentTextChanged: applyRecordFilters() + } + } + + Column { + Layout.fillWidth: true + Layout.columnSpan: 1 + Layout.preferredWidth: slimLayout ? 1 : 170 + Layout.minimumWidth: slimLayout ? 0 : 140 + spacing: 6 + Label { + text: "学号" + color: ink700 + font.weight: appBoldWeight + font.pixelSize: 12 + } + AppComboBox { + id: studentFilter + width: parent.width + model: appController.studentOptions + onCurrentTextChanged: applyRecordFilters() + } + } + + Column { + Layout.fillWidth: true + Layout.columnSpan: 1 + Layout.preferredWidth: slimLayout ? 1 : 230 + Layout.minimumWidth: slimLayout ? 0 : 180 + spacing: 6 + Label { + text: "姓名" + color: ink700 + font.weight: appBoldWeight + font.pixelSize: 12 + } + AppTextField { + id: nameFilter + width: parent.width + placeholderText: "输入姓名关键字" + onTextChanged: applyRecordFilters() + } + } + + Column { + Layout.fillWidth: true + Layout.columnSpan: 1 + Layout.preferredWidth: slimLayout ? 1 : 170 + Layout.minimumWidth: slimLayout ? 0 : 140 + spacing: 6 + Label { + text: "日期" + color: ink700 + font.weight: appBoldWeight + font.pixelSize: 12 + } + AppComboBox { + id: dateFilter + width: parent.width + model: ["全部时间", "今天", "最近7天", "最近30天", "指定日期"] + currentIndex: 0 + onCurrentIndexChanged: applyRecordFilters() + } + } + + Column { + Layout.fillWidth: true + Layout.columnSpan: 1 + Layout.preferredWidth: slimLayout ? 1 : 170 + Layout.minimumWidth: slimLayout ? 0 : 140 + width: dateFilter.currentIndex === 4 ? implicitWidth : 0 + height: dateFilter.currentIndex === 4 ? implicitHeight : 0 + visible: dateFilter.currentIndex === 4 + spacing: 6 + Label { + text: "指定日期" + color: ink700 + font.weight: appBoldWeight + font.pixelSize: 12 + } + AppTextField { + id: specificDateField + width: parent.width + text: Qt.formatDate(new Date(), "yyyy-MM-dd") + placeholderText: "yyyy-MM-dd" + onTextChanged: if (visible) + applyRecordFilters() + } + } + + Item { + Layout.columnSpan: slimLayout ? 2 : 1 + Layout.fillWidth: slimLayout + Layout.preferredWidth: slimLayout ? 1 : (dateFilter.currentIndex === 4 ? 300 : 330) + Layout.minimumWidth: slimLayout ? 0 : 280 + Layout.preferredHeight: slimLayout ? 42 : 64 + Layout.alignment: Qt.AlignBottom + + GridLayout { + anchors.bottom: parent.bottom + anchors.right: parent.right + width: parent.width + columns: 2 + columnSpacing: 8 + rowSpacing: 10 + + SecondaryButton { + Layout.fillWidth: true + Layout.preferredWidth: 1 + text: "刷新" + onClicked: appController.refreshRecords() + } + + DangerButton { + Layout.fillWidth: true + Layout.preferredWidth: 1 + text: "清空记录" + onClicked: clearDialog.open() + } + } + } + } + } + + Rectangle { + id: recordTableCard + Layout.fillWidth: true + Layout.fillHeight: true + Layout.minimumHeight: slimLayout ? 220 : 0 + radius: 8 + color: panelStrong + border.color: lineColor + property real timeColWidth: phoneLayout ? 112 : Math.max(168, Math.min(220, width * 0.21)) + property real classColWidth: phoneLayout ? 0 : Math.max(88, Math.min(124, width * 0.11)) + property real studentColWidth: phoneLayout ? 64 : Math.max(86, Math.min(116, width * 0.10)) + property real nameColWidth: phoneLayout ? 88 : Math.max(118, Math.min(158, width * 0.14)) + property real confidenceColWidth: phoneLayout ? 0 : Math.max(96, Math.min(126, width * 0.11)) + property real statusColWidth: phoneLayout ? 64 : Math.max(84, Math.min(102, width * 0.09)) + property bool showClassColumn: !denseLayout + property bool showConfidenceColumn: !narrowLayout + + ColumnLayout { + anchors.fill: parent + anchors.margins: 16 + spacing: 8 + + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 40 + radius: 8 + color: "#eef2f6" + + RowLayout { + anchors.fill: parent + anchors.leftMargin: 16 + anchors.rightMargin: 16 + spacing: 12 + + Label { + text: "签到时间" + Layout.preferredWidth: recordTableCard.timeColWidth + font.weight: appBoldWeight + color: ink900 + } + Label { + text: "班级" + visible: recordTableCard.showClassColumn + Layout.preferredWidth: recordTableCard.classColWidth + font.weight: appBoldWeight + color: ink900 + } + Label { + text: "学号" + Layout.preferredWidth: recordTableCard.studentColWidth + font.weight: appBoldWeight + color: ink900 + } + Label { + text: "姓名" + Layout.preferredWidth: recordTableCard.nameColWidth + font.weight: appBoldWeight + color: ink900 + } + Label { + text: "置信度" + visible: recordTableCard.showConfidenceColumn + Layout.preferredWidth: recordTableCard.confidenceColWidth + font.weight: appBoldWeight + color: ink900 + } + Label { + text: "状态" + Layout.preferredWidth: recordTableCard.statusColWidth + font.weight: appBoldWeight + color: ink900 + } + Item { + Layout.fillWidth: true + } + } + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + + ListView { + id: recordListView + anchors.fill: parent + clip: true + spacing: 4 + model: appController.recordModel + + delegate: Rectangle { + width: ListView.view.width + height: 44 + property bool hovered: recordHoverHandler.hovered + radius: 8 + color: hovered ? "#f6f9fc" : (index % 2 === 0 ? "#ffffff" : "#fafbfc") + border.color: hovered ? "#cbd5e1" : "#edf0f3" + + Behavior on color { + enabled: !resizingWindow + ColorAnimation { + duration: 120 + } + } + Behavior on border.color { + enabled: !resizingWindow + ColorAnimation { + duration: 120 + } + } + + HoverHandler { + id: recordHoverHandler + } + + RowLayout { + anchors.fill: parent + anchors.leftMargin: 16 + anchors.rightMargin: 16 + spacing: 12 + + Label { + text: model.timestamp + Layout.preferredWidth: recordTableCard.timeColWidth + color: ink900 + elide: Text.ElideRight + } + Label { + text: model.className + visible: recordTableCard.showClassColumn + Layout.preferredWidth: recordTableCard.classColWidth + color: ink700 + } + Label { + text: model.studentId + Layout.preferredWidth: recordTableCard.studentColWidth + color: ink700 + elide: Text.ElideRight + } + Label { + text: model.name + Layout.preferredWidth: recordTableCard.nameColWidth + color: ink900 + font.weight: appBoldWeight + elide: Text.ElideRight + } + Label { + text: model.confidenceText + visible: recordTableCard.showConfidenceColumn + Layout.preferredWidth: recordTableCard.confidenceColWidth + color: ink700 + } + Rectangle { + Layout.preferredWidth: recordTableCard.statusColWidth + Layout.preferredHeight: 26 + radius: 8 + color: model.success ? "#dbeedb" : "#f6d9d4" + + Label { + anchors.centerIn: parent + text: model.statusText + color: model.success ? successColor : dangerColor + font.weight: appBoldWeight + } + } + Item { + Layout.fillWidth: true + } + } + } + + ScrollBar.vertical: AppScrollBar {} + } + + EmptyState { + anchors.centerIn: parent + visible: recordListView.count === 0 + title: "没有匹配记录" + description: "试着放宽筛选条件,或者先点击顶部按钮刷新最新数据。" + badgeText: "00" + accent: accentColor + } + } + } + } + } + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + visible: StackLayout.isCurrentItem + opacity: StackLayout.isCurrentItem ? 1 : 0 + scale: resizingWindow || StackLayout.isCurrentItem ? 1 : 0.985 + Behavior on opacity { + enabled: !resizingWindow + NumberAnimation { + duration: 140 + } + } + Behavior on scale { + enabled: !resizingWindow + NumberAnimation { + duration: 180 + easing.type: Easing.OutCubic + } + } + + ColumnLayout { + anchors.fill: parent + spacing: 14 + + Rectangle { + Layout.fillWidth: true + radius: 8 + color: panelStrong + border.color: lineColor + Layout.preferredHeight: phoneLayout ? 150 : (slimLayout ? 150 : 78) + clip: true + + GridLayout { + id: statisticsFilterGrid + anchors.fill: parent + anchors.margins: slimLayout ? 12 : 18 + columns: slimLayout ? 2 : 4 + rowSpacing: 10 + columnSpacing: 12 + + AppComboBox { + id: quickStatisticsFilter + Layout.fillWidth: true + Layout.preferredWidth: 1 + model: ["今天", "最近7天", "最近30天", "本月"] + currentIndex: 2 + onCurrentTextChanged: { + statisticsPreset = currentText; + applyStatisticsPreset(); + } + } + + AppTextField { + id: statsStartField + Layout.fillWidth: true + Layout.preferredWidth: 1 + placeholderText: "开始日期" + onEditingFinished: appController.updateStatisticsRange(text, statsEndField.text) + } + + AppTextField { + id: statsEndField + Layout.fillWidth: true + Layout.preferredWidth: 1 + placeholderText: "结束日期" + onEditingFinished: appController.updateStatisticsRange(statsStartField.text, text) + } + + SecondaryButton { + Layout.fillWidth: true + Layout.preferredWidth: 1 + text: "刷新统计" + onClicked: appController.updateStatisticsRange(statsStartField.text, statsEndField.text) + } + } + } + + GridLayout { + Layout.fillWidth: true + columns: phoneLayout ? 2 : (slimLayout ? 3 : (compactLayout ? 1 : 3)) + rowSpacing: 10 + columnSpacing: 14 + + Rectangle { + Layout.fillWidth: true + Layout.preferredWidth: 1 + Layout.preferredHeight: phoneLayout ? 68 : (slimLayout ? 74 : 100) + radius: 8 + color: panelStrong + border.color: lineColor + clip: true + + Column { + anchors.fill: parent + anchors.topMargin: slimLayout ? 12 : 18 + anchors.bottomMargin: slimLayout ? 12 : 18 + anchors.leftMargin: slimLayout ? 34 : 44 + anchors.rightMargin: slimLayout ? 12 : 18 + spacing: 6 + Label { + text: "统计学生数" + color: ink500 + } + Label { + text: appController.statisticsStudentCount + font.pixelSize: slimLayout ? 22 : (compactLayout ? 28 : 32) + font.weight: appBoldWeight + color: ink900 + } + } + + Rectangle { + anchors.left: parent.left + anchors.leftMargin: slimLayout ? 12 : 18 + anchors.verticalCenter: parent.verticalCenter + width: 6 + height: Math.min(parent.height - 28, 64) + radius: 3 + color: accentColor + } + } + + Rectangle { + Layout.fillWidth: true + Layout.preferredWidth: 1 + Layout.preferredHeight: phoneLayout ? 68 : (slimLayout ? 74 : 100) + radius: 8 + color: panelStrong + border.color: lineColor + clip: true + + Column { + anchors.fill: parent + anchors.topMargin: slimLayout ? 12 : 18 + anchors.bottomMargin: slimLayout ? 12 : 18 + anchors.leftMargin: slimLayout ? 34 : 44 + anchors.rightMargin: slimLayout ? 12 : 18 + spacing: 6 + Label { + text: "统计记录数" + color: ink500 + } + Label { + text: appController.statisticsRecordCount + font.pixelSize: slimLayout ? 22 : (compactLayout ? 28 : 32) + font.weight: appBoldWeight + color: tealColor + } + } + + Rectangle { + anchors.left: parent.left + anchors.leftMargin: slimLayout ? 12 : 18 + anchors.verticalCenter: parent.verticalCenter + width: 6 + height: Math.min(parent.height - 28, 64) + radius: 3 + color: tealColor + } + } + + Rectangle { + Layout.columnSpan: phoneLayout ? 2 : 1 + Layout.fillWidth: true + Layout.preferredWidth: 1 + Layout.preferredHeight: phoneLayout ? 68 : (slimLayout ? 74 : 100) + radius: 8 + color: panelStrong + border.color: lineColor + clip: true + + Column { + anchors.fill: parent + anchors.topMargin: slimLayout ? 12 : 18 + anchors.bottomMargin: slimLayout ? 12 : 18 + anchors.leftMargin: slimLayout ? 34 : 44 + anchors.rightMargin: slimLayout ? 12 : 18 + spacing: 6 + Label { + text: "统计范围" + color: ink500 + } + Label { + text: appController.statisticsRangeText + font.pixelSize: slimLayout ? 14 : (compactLayout ? 18 : 20) + font.weight: appBoldWeight + color: goldColor + elide: Text.ElideRight + } + } + + Rectangle { + anchors.left: parent.left + anchors.leftMargin: slimLayout ? 12 : 18 + anchors.verticalCenter: parent.verticalCenter + width: 6 + height: Math.min(parent.height - 28, 64) + radius: 3 + color: goldColor + } + } + } + + Rectangle { + id: statisticsTableCard + Layout.fillWidth: true + Layout.fillHeight: true + Layout.minimumHeight: slimLayout ? 220 : 0 + radius: 8 + color: panelStrong + border.color: lineColor + property real studentColWidth: phoneLayout ? 68 : Math.max(90, Math.min(128, width * 0.12)) + property real nameColWidth: phoneLayout ? 96 : Math.max(128, Math.min(188, width * 0.17)) + property real totalColWidth: phoneLayout ? 92 : Math.max(96, Math.min(124, width * 0.12)) + property real todayColWidth: Math.max(92, Math.min(110, width * 0.10)) + property real lastColWidth: Math.max(180, Math.min(240, width * 0.20)) + property real avgColWidth: Math.max(98, Math.min(126, width * 0.11)) + property bool showTodayColumn: !denseLayout + property bool showLastColumn: !narrowLayout + property bool showAverageColumn: !phoneLayout + + ColumnLayout { + anchors.fill: parent + anchors.margins: 16 + spacing: 8 + + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 40 + radius: 8 + color: "#eef2f6" + + RowLayout { + anchors.fill: parent + anchors.leftMargin: 16 + anchors.rightMargin: 16 + spacing: 12 + + Label { + text: "学号" + Layout.preferredWidth: statisticsTableCard.studentColWidth + font.weight: appBoldWeight + } + Label { + text: "姓名" + Layout.preferredWidth: statisticsTableCard.nameColWidth + font.weight: appBoldWeight + } + Label { + text: "总签到次数" + Layout.preferredWidth: statisticsTableCard.totalColWidth + font.weight: appBoldWeight + } + Label { + text: "今日签到" + visible: statisticsTableCard.showTodayColumn + Layout.preferredWidth: statisticsTableCard.todayColWidth + font.weight: appBoldWeight + } + Label { + text: "最后签到时间" + visible: statisticsTableCard.showLastColumn + Layout.preferredWidth: statisticsTableCard.lastColWidth + font.weight: appBoldWeight + } + Label { + text: "平均置信度" + visible: statisticsTableCard.showAverageColumn + Layout.preferredWidth: statisticsTableCard.avgColWidth + font.weight: appBoldWeight + } + Item { + Layout.fillWidth: true + } + } + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + + ListView { + id: statisticsListView + anchors.fill: parent + clip: true + spacing: 8 + model: appController.statisticsModel + + delegate: Rectangle { + width: ListView.view.width + height: 52 + property bool hovered: statisticsHoverHandler.hovered + radius: 16 + color: hovered ? "#f7f5e8" : (index % 2 === 0 ? "#ffffff" : "#f8f3ec") + border.color: hovered ? "#e4d6aa" : (index % 2 === 0 ? "#ece4da" : "#e7ded3") + + Behavior on color { + enabled: !resizingWindow + ColorAnimation { + duration: 120 + } + } + Behavior on border.color { + enabled: !resizingWindow + ColorAnimation { + duration: 120 + } + } + + HoverHandler { + id: statisticsHoverHandler + } + + RowLayout { + anchors.fill: parent + anchors.leftMargin: 16 + anchors.rightMargin: 16 + spacing: 12 + + Label { + text: model.studentId + Layout.preferredWidth: statisticsTableCard.studentColWidth + color: ink700 + } + Label { + text: model.name + Layout.preferredWidth: statisticsTableCard.nameColWidth + color: ink900 + font.weight: appBoldWeight + } + Label { + text: model.totalCount + Layout.preferredWidth: statisticsTableCard.totalColWidth + color: ink700 + } + Label { + text: model.todayCount + visible: statisticsTableCard.showTodayColumn + Layout.preferredWidth: statisticsTableCard.todayColWidth + color: ink700 + } + Label { + text: model.lastCheckIn + visible: statisticsTableCard.showLastColumn + Layout.preferredWidth: statisticsTableCard.lastColWidth + color: ink700 + } + Label { + text: model.averageConfidenceText + visible: statisticsTableCard.showAverageColumn + Layout.preferredWidth: statisticsTableCard.avgColWidth + color: tealColor + font.weight: appBoldWeight + } + Item { + Layout.fillWidth: true + } + } + } + + ScrollBar.vertical: AppScrollBar {} + } + + EmptyState { + anchors.centerIn: parent + visible: statisticsListView.count === 0 + title: "统计范围内没有数据" + description: "可以切换时间范围,或者先返回记录页检查同步是否正常。" + badgeText: "Σ" + accent: goldColor + } + } + } + } + } + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + visible: StackLayout.isCurrentItem + opacity: StackLayout.isCurrentItem ? 1 : 0 + scale: resizingWindow || StackLayout.isCurrentItem ? 1 : 0.985 + Behavior on opacity { + enabled: !resizingWindow + NumberAnimation { + duration: 140 + } + } + Behavior on scale { + enabled: !resizingWindow + NumberAnimation { + duration: 180 + easing.type: Easing.OutCubic + } + } + + ScrollView { + id: configScrollView + anchors.fill: parent + clip: true + contentWidth: availableWidth + contentHeight: configContentLayout.implicitHeight + + ColumnLayout { + id: configContentLayout + width: configScrollView.availableWidth + spacing: 14 + + Rectangle { + Layout.fillWidth: true + radius: 8 + color: panelStrong + border.color: lineColor + Layout.preferredHeight: phoneLayout ? 218 : (slimLayout ? 174 : 88) + clip: true + + GridLayout { + id: serverConfigGrid + anchors.fill: parent + anchors.margins: slimLayout ? 12 : 18 + columns: slimLayout ? 1 : 4 + rowSpacing: 12 + columnSpacing: 12 + + Label { + Layout.alignment: Qt.AlignVCenter + text: "服务器地址" + font.weight: appBoldWeight + color: ink700 + } + AppTextField { + id: serverUrlField + Layout.fillWidth: true + Layout.preferredWidth: slimLayout ? 0 : 520 + text: appController.serverUrl + placeholderText: "http://IP:端口" + } + + SecondaryButton { + Layout.fillWidth: phoneLayout + text: "保存地址" + onClicked: appController.serverUrl = serverUrlField.text + } + + PrimaryButton { + Layout.fillWidth: phoneLayout + text: "测试连接" + fillColor: tealColor + onClicked: appController.testConnection() + } + } + } + + Rectangle { + Layout.fillWidth: true + radius: 8 + color: panelStrong + border.color: lineColor + Layout.preferredHeight: timeSlotsExpanded + ? 18 + (phoneLayout ? 132 : 64) + 12 + (phoneLayout ? 0 : 42) + (phoneLayout ? 0 : 12) + Math.max(phoneLayout ? 96 : 52, timeSlotListView.contentHeight) + 18 + : (phoneLayout ? 124 : 100) + clip: true + + ColumnLayout { + anchors.fill: parent + anchors.margins: 18 + spacing: 12 + + ColumnLayout { + Layout.fillWidth: true + Layout.preferredHeight: phoneLayout ? 132 : 64 + spacing: 12 + + SectionHeader { + Layout.fillWidth: true + title: "时间段配置" + description: "维护签到与签退时段,并同步到服务端。" + accent: accentColor + } + GridLayout { + Layout.fillWidth: true + columns: phoneLayout ? 3 : 5 + columnSpacing: 8 + rowSpacing: 8 + + SecondaryButton { + Layout.fillWidth: true + text: timeSlotsExpanded ? "收起" : "展开" + onClicked: timeSlotsExpanded = !timeSlotsExpanded + } + SecondaryButton { + Layout.fillWidth: true + visible: timeSlotsExpanded + text: "新增时段" + onClicked: openTimeSlotDialog(-1) + } + SecondaryButton { + Layout.fillWidth: true + visible: timeSlotsExpanded + text: "恢复默认" + onClicked: { + appController.timeSlotModel.resetToDefault(); + appController.saveTimeSlots(); + } + } + SecondaryButton { + Layout.fillWidth: true + visible: timeSlotsExpanded + text: phoneLayout ? "同步" : "从服务器同步" + onClicked: appController.reloadTimeSlotsFromServer() + } + PrimaryButton { + Layout.fillWidth: true + visible: timeSlotsExpanded + text: phoneLayout ? "保存" : "保存时间段" + onClicked: appController.saveTimeSlots() + } + } + } + + Rectangle { + visible: timeSlotsExpanded && !phoneLayout + Layout.fillWidth: true + Layout.preferredHeight: visible ? 42 : 0 + radius: 8 + color: "#efe7dd" + + RowLayout { + anchors.fill: parent + anchors.leftMargin: 16 + anchors.rightMargin: 16 + Label { + text: "名称" + Layout.preferredWidth: 220 + font.weight: appBoldWeight + } + Label { + text: "开始" + Layout.preferredWidth: 120 + font.weight: appBoldWeight + } + Label { + text: "结束" + Layout.preferredWidth: 120 + font.weight: appBoldWeight + } + Label { + text: "状态" + Layout.preferredWidth: 100 + font.weight: appBoldWeight + } + Item { + Layout.fillWidth: true + } + } + } + + ListView { + id: timeSlotListView + visible: timeSlotsExpanded + Layout.fillWidth: true + Layout.preferredHeight: visible ? contentHeight : 0 + clip: false + interactive: false + spacing: 8 + model: appController.timeSlotModel + + delegate: Rectangle { + width: ListView.view.width + height: phoneLayout ? 96 : 52 + property bool hovered: timeSlotHoverHandler.hovered + radius: 16 + color: hovered ? "#f9f1ea" : (index % 2 === 0 ? "#ffffff" : "#f8f3ec") + border.color: hovered ? "#e5cfc1" : (index % 2 === 0 ? "#ece4da" : "#e7ded3") + + Behavior on color { + enabled: !resizingWindow + ColorAnimation { + duration: 120 + } + } + Behavior on border.color { + enabled: !resizingWindow + ColorAnimation { + duration: 120 + } + } + + HoverHandler { + id: timeSlotHoverHandler + } + + RowLayout { + anchors.fill: parent + anchors.leftMargin: 16 + anchors.rightMargin: 16 + visible: !phoneLayout + spacing: 12 + + Label { + text: model.name + Layout.preferredWidth: 220 + } + Label { + text: model.startTime + Layout.preferredWidth: 120 + } + Label { + text: model.endTime + Layout.preferredWidth: 120 + } + Label { + text: model.enabled ? "启用" : "禁用" + Layout.preferredWidth: 100 + color: model.enabled ? successColor : goldColor + font.weight: appBoldWeight + } + Item { + Layout.fillWidth: true + } + SecondaryButton { + text: "编辑" + onClicked: openTimeSlotDialog(index) + } + SecondaryButton { + text: "删除" + onClicked: { + appController.timeSlotModel.removeTimeSlot(index); + appController.saveTimeSlots(); + } + } + } + + ColumnLayout { + anchors.fill: parent + anchors.margins: 12 + visible: phoneLayout + spacing: 8 + + RowLayout { + Layout.fillWidth: true + spacing: 8 + + Label { + text: model.name + Layout.fillWidth: true + color: ink900 + font.pixelSize: 15 + font.weight: appBoldWeight + elide: Text.ElideRight + } + Label { + text: model.enabled ? "启用" : "禁用" + color: model.enabled ? successColor : goldColor + font.pixelSize: 12 + font.weight: appBoldWeight + } + } + + RowLayout { + Layout.fillWidth: true + spacing: 8 + + Label { + text: model.startTime + " - " + model.endTime + Layout.fillWidth: true + color: ink700 + font.pixelSize: 13 + } + SecondaryButton { + Layout.preferredWidth: 76 + text: "编辑" + onClicked: openTimeSlotDialog(index) + } + SecondaryButton { + Layout.preferredWidth: 76 + text: "删除" + onClicked: { + appController.timeSlotModel.removeTimeSlot(index); + appController.saveTimeSlots(); + } + } + } + } + } + } + } + } + + Rectangle { + Layout.fillWidth: true + radius: 8 + color: panelStrong + border.color: lineColor + Layout.preferredHeight: mappingsExpanded + ? 18 + (phoneLayout ? 120 : 64) + 12 + mappingTabs.implicitHeight + 12 + Math.max(phoneLayout ? 112 : 64, mappingTabs.currentIndex === 0 ? studentMappingListView.contentHeight : classMappingListView.contentHeight) + 18 + : (phoneLayout ? 124 : 100) + clip: true + + ColumnLayout { + anchors.fill: parent + anchors.margins: 18 + spacing: 12 + + ColumnLayout { + Layout.fillWidth: true + Layout.preferredHeight: phoneLayout ? 120 : 64 + spacing: 12 + SectionHeader { + Layout.fillWidth: true + title: "名称映射配置" + description: "让学号和班级编号显示为更清晰的真实名称。" + accent: tealColor + } + GridLayout { + Layout.fillWidth: true + columns: phoneLayout ? 3 : 3 + columnSpacing: 8 + rowSpacing: 8 + + SecondaryButton { + Layout.fillWidth: true + text: mappingsExpanded ? "收起" : "展开" + onClicked: mappingsExpanded = !mappingsExpanded + } + SecondaryButton { + Layout.fillWidth: true + visible: mappingsExpanded + text: phoneLayout ? "加载" : "从服务器加载" + onClicked: appController.loadMappingsFromServer() + } + PrimaryButton { + Layout.fillWidth: true + visible: mappingsExpanded + text: "保存映射" + fillColor: tealColor + onClicked: appController.saveMappings() + } + } + } + + TabBar { + id: mappingTabs + visible: mappingsExpanded + Layout.fillWidth: true + Layout.preferredHeight: visible ? 42 : 0 + spacing: 8 + padding: 0 + background: Rectangle { + color: "transparent" + } + + SegmentTabButton { + width: (mappingTabs.width - mappingTabs.spacing) / 2 + text: "学号 → 姓名" + } + SegmentTabButton { + width: (mappingTabs.width - mappingTabs.spacing) / 2 + text: "班级编号 → 名称" + } + } + + StackLayout { + visible: mappingsExpanded + Layout.fillWidth: true + Layout.preferredHeight: visible ? (mappingTabs.currentIndex === 0 ? studentMappingListView.contentHeight : classMappingListView.contentHeight) : 0 + currentIndex: mappingTabs.currentIndex + + Rectangle { + color: "transparent" + + ListView { + id: studentMappingListView + anchors.fill: parent + clip: false + interactive: false + spacing: 8 + model: appController.studentMappingModel + + header: RowLayout { + width: ListView.view.width + spacing: 12 + + SecondaryButton { + text: "新增映射" + onClicked: appController.studentMappingModel.addEntry("", "") + } + + Item { + Layout.fillWidth: true + } + } + + delegate: Rectangle { + width: ListView.view.width + height: phoneLayout ? 112 : 56 + property bool hovered: studentMappingHoverHandler.hovered + radius: 16 + color: hovered ? "#f9f0ea" : (index % 2 === 0 ? "#ffffff" : "#f8f3ec") + border.color: hovered ? "#e5cfc1" : (index % 2 === 0 ? "#ece4da" : "#e7ded3") + + Behavior on color { + enabled: !resizingWindow + ColorAnimation { + duration: 120 + } + } + Behavior on border.color { + enabled: !resizingWindow + ColorAnimation { + duration: 120 + } + } + + HoverHandler { + id: studentMappingHoverHandler + } + + RowLayout { + anchors.fill: parent + anchors.leftMargin: 12 + anchors.rightMargin: 12 + visible: !phoneLayout + spacing: 12 + + AppTextField { + id: studentKeyField + Layout.preferredWidth: 220 + text: model.entryKey + placeholderText: "学号" + onEditingFinished: appController.studentMappingModel.updateEntry(index, text, studentValueField.text) + } + + AppTextField { + id: studentValueField + Layout.preferredWidth: 240 + text: model.entryValue + placeholderText: "真实姓名" + onEditingFinished: appController.studentMappingModel.updateEntry(index, studentKeyField.text, text) + } + + Item { + Layout.fillWidth: true + } + SecondaryButton { + text: "删除" + onClicked: appController.studentMappingModel.removeEntry(index) + } + } + + ColumnLayout { + anchors.fill: parent + anchors.margins: 12 + visible: phoneLayout + spacing: 8 + + AppTextField { + id: studentKeyFieldPhone + Layout.fillWidth: true + text: model.entryKey + placeholderText: "学号" + onEditingFinished: appController.studentMappingModel.updateEntry(index, text, studentValueFieldPhone.text) + } + + RowLayout { + Layout.fillWidth: true + spacing: 8 + + AppTextField { + id: studentValueFieldPhone + Layout.fillWidth: true + text: model.entryValue + placeholderText: "真实姓名" + onEditingFinished: appController.studentMappingModel.updateEntry(index, studentKeyFieldPhone.text, text) + } + + SecondaryButton { + Layout.preferredWidth: 76 + text: "删除" + onClicked: appController.studentMappingModel.removeEntry(index) + } + } + } + } + } + } + + Rectangle { + color: "transparent" + + ListView { + id: classMappingListView + anchors.fill: parent + clip: false + interactive: false + spacing: 8 + model: appController.classMappingModel + + header: RowLayout { + width: ListView.view.width + spacing: 12 + + SecondaryButton { + text: "新增映射" + onClicked: appController.classMappingModel.addEntry("", "") + } + + Item { + Layout.fillWidth: true + } + } + + delegate: Rectangle { + width: ListView.view.width + height: phoneLayout ? 112 : 56 + property bool hovered: classMappingHoverHandler.hovered + radius: 16 + color: hovered ? "#eef5f4" : (index % 2 === 0 ? "#ffffff" : "#f8f3ec") + border.color: hovered ? "#c7dddd" : (index % 2 === 0 ? "#ece4da" : "#e7ded3") + + Behavior on color { + enabled: !resizingWindow + ColorAnimation { + duration: 120 + } + } + Behavior on border.color { + enabled: !resizingWindow + ColorAnimation { + duration: 120 + } + } + + HoverHandler { + id: classMappingHoverHandler + } + + RowLayout { + anchors.fill: parent + anchors.leftMargin: 12 + anchors.rightMargin: 12 + visible: !phoneLayout + spacing: 12 + + AppTextField { + id: classKeyField + Layout.preferredWidth: 220 + text: model.entryKey + placeholderText: "班级编号" + onEditingFinished: appController.classMappingModel.updateEntry(index, text, classValueField.text) + } + + AppTextField { + id: classValueField + Layout.preferredWidth: 260 + text: model.entryValue + placeholderText: "班级名称" + onEditingFinished: appController.classMappingModel.updateEntry(index, classKeyField.text, text) + } + + Item { + Layout.fillWidth: true + } + SecondaryButton { + text: "删除" + onClicked: appController.classMappingModel.removeEntry(index) + } + } + + ColumnLayout { + anchors.fill: parent + anchors.margins: 12 + visible: phoneLayout + spacing: 8 + + AppTextField { + id: classKeyFieldPhone + Layout.fillWidth: true + text: model.entryKey + placeholderText: "班级编号" + onEditingFinished: appController.classMappingModel.updateEntry(index, text, classValueFieldPhone.text) + } + + RowLayout { + Layout.fillWidth: true + spacing: 8 + + AppTextField { + id: classValueFieldPhone + Layout.fillWidth: true + text: model.entryValue + placeholderText: "班级名称" + onEditingFinished: appController.classMappingModel.updateEntry(index, classKeyFieldPhone.text, text) + } + + SecondaryButton { + Layout.preferredWidth: 76 + text: "删除" + onClicked: appController.classMappingModel.removeEntry(index) + } + } + } + } + } + } + } + } + } + + Item { + Layout.fillWidth: true + Layout.preferredHeight: 14 + } + } + } + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + visible: StackLayout.isCurrentItem + opacity: StackLayout.isCurrentItem ? 1 : 0 + scale: resizingWindow || StackLayout.isCurrentItem ? 1 : 0.985 + Behavior on opacity { + enabled: !resizingWindow + NumberAnimation { + duration: 140 + } + } + Behavior on scale { + enabled: !resizingWindow + NumberAnimation { + duration: 180 + easing.type: Easing.OutCubic + } + } + + ColumnLayout { + anchors.fill: parent + spacing: 14 + + Rectangle { + Layout.fillWidth: true + radius: 8 + color: panelStrong + border.color: lineColor + Layout.preferredHeight: phoneLayout ? 170 : (slimLayout ? 132 : 88) + clip: true + + GridLayout { + anchors.fill: parent + anchors.margins: slimLayout ? 12 : 18 + columns: phoneLayout ? 1 : 2 + rowSpacing: 12 + columnSpacing: 12 + + SectionHeader { + Layout.fillWidth: true + title: "K210 人脸照片与学号映射" + description: "同步照片状态,维护人脸与真实学号的对应关系。" + accent: goldColor + } + + Flow { + Layout.fillWidth: phoneLayout + Layout.alignment: phoneLayout ? Qt.AlignLeft : (Qt.AlignRight | Qt.AlignVCenter) + spacing: 8 + + SecondaryButton { + text: "刷新" + onClicked: appController.refreshFaces() + } + PrimaryButton { + text: "保存映射" + onClicked: appController.saveFaceMappings() + } + } + } + } + + Rectangle { + Layout.fillWidth: true + Layout.fillHeight: true + radius: 8 + color: panelStrong + border.color: lineColor + + GridView { + id: faceGridView + anchors.fill: parent + anchors.margins: 16 + clip: true + property int cardColumns: phoneLayout ? 1 : Math.max(1, Math.floor(width / (compactLayout ? 236 : 260))) + cellWidth: Math.max(phoneLayout ? 280 : 240, Math.floor(width / cardColumns)) + cellHeight: phoneLayout ? 392 : 352 + model: appController.faceModel + + delegate: Rectangle { + width: Math.min(phoneLayout ? 300 : 244, GridView.view.cellWidth - 18) + height: phoneLayout ? 368 : 328 + property bool hovered: faceHoverHandler.hovered + radius: 8 + color: hovered ? "#fff6ef" : "#ffffff" + border.color: hovered ? "#e6c8b8" : "#e8ddd0" + + Behavior on color { + enabled: !resizingWindow + ColorAnimation { + duration: 140 + } + } + Behavior on border.color { + enabled: !resizingWindow + ColorAnimation { + duration: 140 + } + } + + HoverHandler { + id: faceHoverHandler + } + + ColumnLayout { + anchors.fill: parent + anchors.margins: 14 + spacing: 10 + + Rectangle { + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + Layout.preferredHeight: phoneLayout ? 140 : (compactLayout ? 152 : 168) + radius: 16 + color: model.hasPhoto ? "#eef3f5" : goldSoft + border.color: model.hasPhoto ? "#dbe4ea" : "#eadbb0" + + Image { + anchors.fill: parent + anchors.margins: 8 + fillMode: Image.PreserveAspectFit + source: model.photoUrl + visible: model.hasPhoto + } + + Label { + anchors.centerIn: parent + visible: !model.hasPhoto + text: "无照片" + color: goldColor + font.weight: appBoldWeight + } + } + + Label { + text: "ID: " + model.faceId + color: ink900 + font.pixelSize: compactLayout ? 15 : 16 + font.weight: appBoldWeight + } + + AppTextField { + Layout.fillWidth: true + text: model.studentId + placeholderText: narrowLayout ? "学号" : "输入真实学号" + onEditingFinished: appController.faceModel.updateStudentId(index, text) + } + + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 34 + radius: 12 + color: model.hasPhoto ? "#e6f4ec" : "#f9ebcf" + + Label { + anchors.centerIn: parent + text: model.hasPhoto ? "照片已同步" : "仅检测到记录,无照片" + color: model.hasPhoto ? successColor : goldColor + font.pixelSize: narrowLayout ? 11 : 12 + font.weight: appBoldWeight + } + } + + Item { + Layout.fillHeight: true + } + + DangerButton { + Layout.fillWidth: true + text: "删除该人脸" + onClicked: { + pendingDeleteFaceId = model.faceId; + deleteFaceRecordsCheck.checked = false; + deleteFaceDialog.open(); + } + } + } + } + + ScrollBar.vertical: AppScrollBar {} + } + + EmptyState { + anchors.centerIn: parent + visible: faceGridView.count === 0 + title: "还没有可管理的人脸数据" + description: "等 K210 上传照片或服务端同步学号后,这里会自动显示对应卡片。" + badgeText: "人" + accent: tealColor + } + } + } + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + visible: StackLayout.isCurrentItem + opacity: StackLayout.isCurrentItem ? 1 : 0 + scale: resizingWindow || StackLayout.isCurrentItem ? 1 : 0.985 + Behavior on opacity { + enabled: !resizingWindow + NumberAnimation { + duration: 140 + } + } + Behavior on scale { + enabled: !resizingWindow + NumberAnimation { + duration: 180 + easing.type: Easing.OutCubic + } + } + + Rectangle { + anchors.fill: parent + radius: 8 + color: panelStrong + border.color: lineColor + clip: true + + ColumnLayout { + anchors.fill: parent + anchors.margins: phoneLayout ? 16 : 24 + spacing: phoneLayout ? 12 : 18 + + SectionHeader { + Layout.fillWidth: true + title: "人脸识别考勤系统" + description: "用于连接考勤服务端,集中查看签到记录、统计考勤情况、维护签到时段、管理名称映射与人脸照片绑定。" + accent: tealColor + } + + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 + color: lineColor + } + + Label { + Layout.fillWidth: true + text: "本客户端基于 Qt Quick/QML 构建,面向人脸识别考勤场景。它把记录查询、统计导出、服务连接配置、时间段配置、学生与班级名称映射、人脸资料管理整合在一个窗口中,减少多窗口切换。" + wrapMode: Text.WordWrap + color: ink700 + font.pixelSize: 14 + lineHeight: 1.25 + } + + Label { + Layout.fillWidth: true + text: "数据通过服务端 API 同步;记录和统计结果可导出为 CSV,配置项可保存后同步到服务端。" + wrapMode: Text.WordWrap + color: ink700 + font.pixelSize: 14 + lineHeight: 1.25 + } + + Item { + Layout.fillHeight: true + } + + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: phoneLayout ? 188 : 164 + radius: 8 + color: "#f8fafb" + border.color: lineColor + + ColumnLayout { + anchors.fill: parent + anchors.margins: 16 + spacing: 8 + + Label { + Layout.fillWidth: true + text: "毕业设计说明" + color: ink900 + font.pixelSize: 16 + font.weight: appBoldWeight + } + + TextArea { + Layout.fillWidth: true + Layout.fillHeight: true + text: "本系统为纪田野的个人毕业设计作品,仅用于毕业设计展示、学习研究与系统功能验证。\nCopyright © 2026 纪田野。保留所有权利。\n仓库地址:https://git.yzfh.eu.cc/yzfh/qt.git\n查看账号:jtybishe 查看密码:jtybishe" + readOnly: true + selectByMouse: true + selectByKeyboard: true + wrapMode: TextEdit.WrapAnywhere + color: ink700 + font.pixelSize: 12 + leftPadding: 0 + rightPadding: 0 + topPadding: 0 + bottomPadding: 0 + background: Rectangle { + color: "transparent" + } + } + } + } + } + } + } + } + + Item { + Layout.fillWidth: true + Layout.preferredHeight: 0 + } + } + } + } + } + + Rectangle { + width: Math.min(420, Math.max(220, toastLabel.implicitWidth + 44)) + height: 52 + radius: 16 + color: "#16323d" + border.color: "#264754" + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.rightMargin: 30 + anchors.bottomMargin: 28 + opacity: toastVisible ? 0.98 : 0 + visible: opacity > 0 + y: toastVisible ? parent.height - height - 28 : parent.height - height - 10 + + Behavior on opacity { + enabled: !resizingWindow + NumberAnimation { + duration: 180 + } + } + Behavior on y { + enabled: !resizingWindow + NumberAnimation { + duration: 180 + easing.type: Easing.OutCubic + } + } + + RowLayout { + anchors.fill: parent + anchors.leftMargin: 16 + anchors.rightMargin: 16 + spacing: 10 + + Rectangle { + Layout.preferredWidth: 10 + Layout.preferredHeight: 10 + radius: 5 + color: accentColor + } + + Label { + id: toastLabel + text: toastMessage + color: "#f8fafc" + elide: Label.ElideRight + Layout.fillWidth: true + } + } + } +} diff --git a/QT/src/ApiClient.cpp b/QT/src/ApiClient.cpp new file mode 100644 index 0000000..21e55ac --- /dev/null +++ b/QT/src/ApiClient.cpp @@ -0,0 +1,673 @@ +#include "ApiClient.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CryptoUtils.h" + +namespace { +constexpr int NetworkTimeoutMs = 5000; +constexpr auto DefaultApiToken = "change-me-token"; +} + +ApiClient::ApiClient(QObject *parent) + : QObject(parent) + , m_serverUrl("http://127.0.0.1:8082") +{ +} + +void ApiClient::setServerUrl(const QString &url) +{ + const QString trimmed = url.trimmed(); + if (!trimmed.isEmpty()) { + m_serverUrl = trimmed; + } +} + +QString ApiClient::serverUrl() const +{ + return m_serverUrl; +} + +QString ApiClient::buildUrl(const QString &endpoint, const QMap ¶ms) const +{ + QString baseUrl = m_serverUrl.trimmed(); + while (baseUrl.endsWith('/')) { + baseUrl.chop(1); + } + QString url = baseUrl + "/api" + endpoint; + if (!params.isEmpty()) { + QUrlQuery query; + for (auto it = params.begin(); it != params.end(); ++it) { + query.addQueryItem(it.key(), it.value()); + } + url += "?" + query.toString(QUrl::FullyEncoded); + } + return url; +} + +QNetworkRequest ApiClient::createRequest(const QString &url, bool encryptedResponse, bool jsonBody) const +{ + QNetworkRequest request{QUrl(url)}; + if (encryptedResponse) { + request.setRawHeader("X-Encrypted-Response", "true"); + } + const QString apiToken = QProcessEnvironment::systemEnvironment() + .value(QStringLiteral("ATTENDANCE_API_TOKEN"), + QString::fromLatin1(DefaultApiToken)); + request.setRawHeader("X-Api-Token", apiToken.toUtf8()); + request.setRawHeader("Accept", "application/json"); + if (jsonBody) { + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + } + request.setTransferTimeout(NetworkTimeoutMs); + return request; +} + +void ApiClient::fetchSyncState(qulonglong lastVersion) +{ + const QString url = buildUrl("/v1/sync/state", { + {"client", "qt"}, + {"last_version", QString::number(lastVersion)} + }); + qInfo() << "[ApiClient] GET sync state" << url; + + QNetworkReply *reply = m_networkManager.get(createRequest(url)); + connect(reply, &QNetworkReply::finished, this, [this, reply]() { + const QByteArray data = reply->readAll(); + if (reply->error() != QNetworkReply::NoError) { + emitNetworkError(QStringLiteral("同步状态加载失败"), reply); + reply->deleteLater(); + return; + } + + const QJsonObject root = QJsonDocument::fromJson(data).object(); + const qulonglong version = static_cast(root.value("version").toDouble(0)); + const bool changed = root.value("changed").toBool(false); + if (!changed) { + emit syncStateFetched(version, false); + reply->deleteLater(); + return; + } + + const QJsonObject state = root.value("state").toObject(); + + if (state.contains("records")) { + emit recordsFetched(parseRecords(QJsonDocument(state.value("records").toArray()).toJson(QJsonDocument::Compact))); + } + + if (state.contains("statistics")) { + const QJsonObject object = state.value("statistics").toObject(); + emit statisticsFetched(object.value("total").toInt(), + object.value("today").toInt(), + object.value("server_time").toString()); + } + + if (state.contains("time_slots")) { + QVector timeSlots; + const QJsonArray array = state.value("time_slots").toArray(); + for (const QJsonValue &value : array) { + const QJsonObject object = value.toObject(); + timeSlots.push_back({ + object.value("name").toString(), + QTime::fromString(object.value("start_time").toString(), "HH:mm"), + QTime::fromString(object.value("end_time").toString(), "HH:mm"), + object.value("enabled").toBool(true) + }); + } + emit timeSlotsFetched(timeSlots); + } + + if (state.contains("mapping_config")) { + const QJsonObject mappingConfig = state.value("mapping_config").toObject(); + QMap studentMap; + QMap classMap; + + const QJsonObject studentObject = mappingConfig.value("student_name_map").toObject(); + for (auto it = studentObject.begin(); it != studentObject.end(); ++it) { + studentMap[it.key()] = it.value().toString(); + } + + const QJsonObject classObject = mappingConfig.value("class_name_map").toObject(); + for (auto it = classObject.begin(); it != classObject.end(); ++it) { + classMap[it.key()] = it.value().toString(); + } + emit mappingConfigFetched(studentMap, classMap); + } + + if (state.contains("face_mappings")) { + const QJsonObject mappings = state.value("face_mappings").toObject(); + QMap mapping; + for (auto it = mappings.begin(); it != mappings.end(); ++it) { + mapping[it.key()] = it.value().toString(); + } + emit faceIdMappingFetched(mapping); + } + + if (state.contains("face_photos")) { + QStringList ids; + const QJsonArray photos = state.value("face_photos").toArray(); + for (const QJsonValue &value : photos) { + ids.push_back(value.toObject().value("id").toString()); + } + emit facePhotosFetched(ids); + } + + if (state.contains("all_student_ids")) { + QStringList ids; + const QJsonArray array = state.value("all_student_ids").toArray(); + for (const QJsonValue &value : array) { + ids.push_back(value.toString()); + } + emit allStudentIdsFetched(ids); + } + + emit syncStateFetched(version, true); + reply->deleteLater(); + }); +} + +QByteArray ApiClient::maybeDecrypt(const QByteArray &data, bool encrypted) const +{ + if (!encrypted) { + return data; + } + const QByteArray trimmed = data.trimmed(); + if (trimmed.startsWith('{') || trimmed.startsWith('[')) { + return trimmed; + } + return CryptoUtils::decryptAes128CbcBase64(trimmed); +} + +bool ApiClient::isConnectionError(QNetworkReply::NetworkError error) const +{ + switch (error) { + case QNetworkReply::ConnectionRefusedError: + case QNetworkReply::RemoteHostClosedError: + case QNetworkReply::HostNotFoundError: + case QNetworkReply::TimeoutError: + case QNetworkReply::OperationCanceledError: + case QNetworkReply::SslHandshakeFailedError: + case QNetworkReply::TemporaryNetworkFailureError: + case QNetworkReply::NetworkSessionFailedError: + case QNetworkReply::BackgroundRequestNotAllowedError: + case QNetworkReply::TooManyRedirectsError: + case QNetworkReply::InsecureRedirectError: + case QNetworkReply::UnknownNetworkError: + case QNetworkReply::UnknownProxyError: + case QNetworkReply::UnknownContentError: + case QNetworkReply::ProtocolFailure: + case QNetworkReply::UnknownServerError: + return true; + default: + return false; + } +} + +void ApiClient::emitNetworkError(const QString &prefix, QNetworkReply *reply) +{ + emit networkError(prefix); + if (isConnectionError(reply->error())) { + emit connectionUnavailable(prefix); + } +} + +QVector ApiClient::parseRecords(const QByteArray &data) const +{ + QVector records; + const QJsonDocument doc = QJsonDocument::fromJson(data); + if (!doc.isArray()) { + return records; + } + + const QJsonArray array = doc.array(); + records.reserve(array.size()); + for (const QJsonValue &value : array) { + const QJsonObject object = value.toObject(); + AttendanceRecord record; + record.timestamp = object.value("timestamp").toString().trimmed(); + record.studentId = object.value("student_id").toString().trimmed(); + record.originalName = object.value("name").toString().trimmed(); + record.confidence = object.value("confidence").toDouble(); + const QJsonValue statusValue = object.value("status"); + if (statusValue.isBool()) { + record.status = statusValue.toBool() ? QStringLiteral("success") : QStringLiteral("failed"); + } else if (statusValue.isDouble()) { + record.status = QString::number(statusValue.toInt()); + } else { + record.status = statusValue.toString().trimmed(); + } + record.classId = object.value("class_id").toString().trimmed(); + if (record.classId.isEmpty()) { + record.classId = "0"; + } + if (!record.timestamp.startsWith("0000-") && !record.timestamp.isEmpty() && !record.studentId.isEmpty()) { + records.push_back(record); + } + } + return records; +} + +void ApiClient::fetchRecords(int limit, int offset) +{ + const QString url = buildUrl("/v1/attendance/records", { + {"limit", QString::number(limit)}, + {"offset", QString::number(offset)} + }); + qInfo() << "[ApiClient] GET" << url; + QNetworkReply *reply = m_networkManager.get(createRequest(url)); + connect(reply, &QNetworkReply::finished, this, [this, reply]() { + const QByteArray rawData = reply->readAll(); + const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + qInfo() << "[ApiClient] records status=" << statusCode + << "error=" << reply->error() + << "bytes=" << rawData.size() + << "body=" << rawData.left(200); + if (reply->error() != QNetworkReply::NoError) { + emitNetworkError(QStringLiteral("加载记录失败"), reply); + reply->deleteLater(); + return; + } + + const QByteArray data = maybeDecrypt(rawData, false); + if (data.isEmpty()) { + emit networkError("记录数据为空"); + reply->deleteLater(); + return; + } + + QJsonParseError jsonError{}; + const QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); + if (jsonError.error != QJsonParseError::NoError || !doc.isArray()) { + emit networkError(QStringLiteral("记录数据解析失败: %1").arg(jsonError.errorString())); + reply->deleteLater(); + return; + } + + const QVector records = parseRecords(data); + qInfo() << "[ApiClient] parsed records=" << records.size(); + emit recordsFetched(records); + reply->deleteLater(); + }); +} + +void ApiClient::fetchStatistics() +{ + const QString url = buildUrl("/v1/attendance/statistics"); + qInfo() << "[ApiClient] GET" << url; + QNetworkReply *reply = m_networkManager.get(createRequest(url)); + connect(reply, &QNetworkReply::finished, this, [this, reply]() { + const QByteArray rawData = reply->readAll(); + const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + qInfo() << "[ApiClient] statistics status=" << statusCode + << "error=" << reply->error() + << "bytes=" << rawData.size() + << "body=" << rawData.left(200); + if (reply->error() != QNetworkReply::NoError) { + emitNetworkError(QStringLiteral("加载统计失败"), reply); + reply->deleteLater(); + return; + } + + const QByteArray data = maybeDecrypt(rawData, false); + if (data.isEmpty()) { + emit networkError("统计数据为空"); + reply->deleteLater(); + return; + } + + const QJsonDocument doc = QJsonDocument::fromJson(data); + const QJsonObject object = doc.object(); + emit statisticsFetched(object.value("total").toInt(), + object.value("today").toInt(), + object.value("server_time").toString()); + reply->deleteLater(); + }); +} + +void ApiClient::clearAllRecords() +{ + QNetworkReply *reply = m_networkManager.post(createRequest(buildUrl("/v1/attendance/records/clear"), false, true), QByteArray()); + connect(reply, &QNetworkReply::finished, this, [this, reply]() { + const QByteArray data = reply->readAll(); + if (reply->error() != QNetworkReply::NoError) { + if (isConnectionError(reply->error())) { + emit connectionUnavailable(QStringLiteral("清空失败: %1").arg(reply->errorString())); + } + emit recordsCleared(false, reply->errorString()); + reply->deleteLater(); + return; + } + + const QJsonObject object = QJsonDocument::fromJson(data).object(); + emit recordsCleared(object.value("success").toBool(), object.value("message").toString()); + reply->deleteLater(); + }); +} + +void ApiClient::deleteRecord(const QString ×tamp, const QString &studentId) +{ + QNetworkReply *reply = m_networkManager.deleteResource(createRequest(buildUrl("/v1/attendance/records", { + {"timestamp", timestamp}, + {"student_id", studentId} + }))); + connect(reply, &QNetworkReply::finished, this, [this, reply]() { + const QByteArray data = reply->readAll(); + if (reply->error() != QNetworkReply::NoError) { + if (isConnectionError(reply->error())) { + emit connectionUnavailable(QStringLiteral("记录删除失败: %1").arg(reply->errorString())); + } + emit recordDeleted(false, reply->errorString()); + reply->deleteLater(); + return; + } + + const QJsonObject object = QJsonDocument::fromJson(data).object(); + emit recordDeleted(object.value("success").toBool(), object.value("message").toString()); + reply->deleteLater(); + }); +} + +void ApiClient::fetchTimeSlots() +{ + QNetworkReply *reply = m_networkManager.get(createRequest(buildUrl("/v1/config/time-slots"))); + connect(reply, &QNetworkReply::finished, this, [this, reply]() { + const QByteArray data = reply->readAll(); + if (reply->error() != QNetworkReply::NoError) { + emitNetworkError(QStringLiteral("加载时间段失败"), reply); + reply->deleteLater(); + return; + } + + QVector timeSlots; + const QJsonObject root = QJsonDocument::fromJson(data).object(); + const QJsonArray array = root.value("time_slots").toArray(); + for (const QJsonValue &value : array) { + const QJsonObject object = value.toObject(); + timeSlots.push_back({ + object.value("name").toString(), + QTime::fromString(object.value("start_time").toString(), "HH:mm"), + QTime::fromString(object.value("end_time").toString(), "HH:mm"), + object.value("enabled").toBool(true) + }); + } + emit timeSlotsFetched(timeSlots); + reply->deleteLater(); + }); +} + +void ApiClient::uploadTimeSlots(const QVector &timeSlots) +{ + QJsonArray array; + for (const TimeSlot &slot : timeSlots) { + QJsonObject object; + object["name"] = slot.name; + object["start_time"] = slot.startTime.toString("HH:mm"); + object["end_time"] = slot.endTime.toString("HH:mm"); + object["enabled"] = slot.enabled; + array.append(object); + } + + QJsonObject payload; + payload["time_slots"] = array; + const QByteArray body = QJsonDocument(payload).toJson(QJsonDocument::Compact); + qInfo() << "[ApiClient] POST" << buildUrl("/v1/config/time-slots") + << "bytes=" << body.size() + << "body=" << body.left(300); + QNetworkReply *reply = m_networkManager.post(createRequest(buildUrl("/v1/config/time-slots"), false, true), body); + connect(reply, &QNetworkReply::finished, this, [this, reply]() { + const QByteArray data = reply->readAll(); + if (reply->error() != QNetworkReply::NoError) { + if (isConnectionError(reply->error())) { + emit connectionUnavailable(QStringLiteral("时间段同步失败: %1").arg(reply->errorString())); + } + emit timeSlotsUploaded(false, reply->errorString()); + reply->deleteLater(); + return; + } + const QJsonObject object = QJsonDocument::fromJson(data).object(); + emit timeSlotsUploaded(object.value("success").toBool(), object.value("message").toString()); + reply->deleteLater(); + }); +} + +void ApiClient::fetchMappingConfig() +{ + QNetworkReply *reply = m_networkManager.get(createRequest(buildUrl("/v1/config/mappings"))); + connect(reply, &QNetworkReply::finished, this, [this, reply]() { + const QByteArray data = reply->readAll(); + if (reply->error() != QNetworkReply::NoError) { + emitNetworkError(QStringLiteral("加载映射配置失败"), reply); + reply->deleteLater(); + return; + } + + const QJsonObject root = QJsonDocument::fromJson(data).object(); + QMap studentMap; + QMap classMap; + + const QJsonObject studentObject = root.value("student_name_map").toObject(); + for (auto it = studentObject.begin(); it != studentObject.end(); ++it) { + studentMap[it.key()] = it.value().toString(); + } + + const QJsonObject classObject = root.value("class_name_map").toObject(); + for (auto it = classObject.begin(); it != classObject.end(); ++it) { + classMap[it.key()] = it.value().toString(); + } + + emit mappingConfigFetched(studentMap, classMap); + reply->deleteLater(); + }); +} + +void ApiClient::uploadMappingConfig(const QMap &studentNameMap, + const QMap &classNameMap) +{ + QJsonObject studentObject; + for (auto it = studentNameMap.begin(); it != studentNameMap.end(); ++it) { + studentObject[it.key()] = it.value(); + } + + QJsonObject classObject; + for (auto it = classNameMap.begin(); it != classNameMap.end(); ++it) { + classObject[it.key()] = it.value(); + } + + QJsonObject payload; + payload["student_name_map"] = studentObject; + payload["class_name_map"] = classObject; + + QNetworkReply *reply = m_networkManager.post(createRequest(buildUrl("/v1/config/mappings"), false, true), + QJsonDocument(payload).toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply]() { + const QByteArray data = reply->readAll(); + if (reply->error() != QNetworkReply::NoError) { + if (isConnectionError(reply->error())) { + emit connectionUnavailable(QStringLiteral("映射保存失败: %1").arg(reply->errorString())); + } + emit mappingConfigUploaded(false, reply->errorString()); + reply->deleteLater(); + return; + } + const QJsonObject object = QJsonDocument::fromJson(data).object(); + emit mappingConfigUploaded(object.value("success").toBool(), object.value("message").toString()); + reply->deleteLater(); + }); +} + +void ApiClient::fetchFaceIdMapping() +{ + QNetworkReply *reply = m_networkManager.get(createRequest(buildUrl("/v1/faces/mappings"))); + connect(reply, &QNetworkReply::finished, this, [this, reply]() { + const QByteArray data = reply->readAll(); + if (reply->error() != QNetworkReply::NoError) { + emitNetworkError(QStringLiteral("加载人脸映射失败"), reply); + reply->deleteLater(); + return; + } + + const QJsonObject mappings = QJsonDocument::fromJson(data).object().value("mappings").toObject(); + QMap mapping; + for (auto it = mappings.begin(); it != mappings.end(); ++it) { + mapping[it.key()] = it.value().toString(); + } + emit faceIdMappingFetched(mapping); + reply->deleteLater(); + }); +} + +void ApiClient::uploadFaceIdMapping(const QMap &mapping) +{ + QJsonObject mappings; + for (auto it = mapping.begin(); it != mapping.end(); ++it) { + if (!it.value().trimmed().isEmpty()) { + mappings[it.key()] = it.value(); + } + } + + QJsonObject payload; + payload["mappings"] = mappings; + QNetworkReply *reply = m_networkManager.post(createRequest(buildUrl("/v1/faces/mappings"), false, true), + QJsonDocument(payload).toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply]() { + const QByteArray data = reply->readAll(); + if (reply->error() != QNetworkReply::NoError) { + if (isConnectionError(reply->error())) { + emit connectionUnavailable(QStringLiteral("人脸映射保存失败: %1").arg(reply->errorString())); + } + emit faceIdMappingUploaded(false, reply->errorString()); + reply->deleteLater(); + return; + } + const QJsonObject object = QJsonDocument::fromJson(data).object(); + emit faceIdMappingUploaded(object.value("success").toBool(), object.value("message").toString()); + reply->deleteLater(); + }); +} + +void ApiClient::fetchFacePhotos() +{ + QNetworkReply *reply = m_networkManager.get(createRequest(buildUrl("/v1/faces/photos"))); + connect(reply, &QNetworkReply::finished, this, [this, reply]() { + const QByteArray data = reply->readAll(); + if (reply->error() != QNetworkReply::NoError) { + emitNetworkError(QStringLiteral("加载照片列表失败"), reply); + reply->deleteLater(); + return; + } + + QStringList ids; + const QJsonArray photos = QJsonDocument::fromJson(data).object().value("photos").toArray(); + for (const QJsonValue &value : photos) { + ids.push_back(value.toObject().value("id").toString()); + } + emit facePhotosFetched(ids); + reply->deleteLater(); + }); +} + +void ApiClient::fetchFacePhoto(const QString &faceId) +{ + if (faceId.trimmed().isEmpty()) { + emit facePhotoFetched(faceId, {}, false, QStringLiteral("人脸ID为空")); + return; + } + + const QString encodedId = QString::fromUtf8(QUrl::toPercentEncoding(faceId.trimmed())); + QNetworkRequest request = createRequest(buildUrl(QStringLiteral("/v1/faces/photos/%1").arg(encodedId))); + request.setRawHeader("Accept", "image/jpeg,*/*"); + + QNetworkReply *reply = m_networkManager.get(request); + connect(reply, &QNetworkReply::finished, this, [this, reply, faceId]() { + const QByteArray data = reply->readAll(); + const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + if (reply->error() != QNetworkReply::NoError || statusCode >= 400 || data.isEmpty()) { + const QString message = reply->error() != QNetworkReply::NoError + ? reply->errorString() + : QStringLiteral("HTTP %1").arg(statusCode); + emit facePhotoFetched(faceId, {}, false, message); + reply->deleteLater(); + return; + } + + emit facePhotoFetched(faceId, data, true, QString()); + reply->deleteLater(); + }); +} + +void ApiClient::fetchAllStudentIds() +{ + QNetworkReply *reply = m_networkManager.get(createRequest(buildUrl("/v1/faces/student-ids"))); + connect(reply, &QNetworkReply::finished, this, [this, reply]() { + const QByteArray data = reply->readAll(); + if (reply->error() != QNetworkReply::NoError) { + emitNetworkError(QStringLiteral("加载学生ID失败"), reply); + reply->deleteLater(); + return; + } + + QStringList ids; + const QJsonArray array = QJsonDocument::fromJson(data).object().value("student_ids").toArray(); + for (const QJsonValue &value : array) { + ids.push_back(value.toString()); + } + emit allStudentIdsFetched(ids); + reply->deleteLater(); + }); +} + +void ApiClient::deleteFace(const QString &studentId, bool deleteRecords) +{ + QString baseUrl = m_serverUrl.trimmed(); + while (baseUrl.endsWith('/')) { + baseUrl.chop(1); + } + QString url = baseUrl + "/api/v1/faces/" + QString::fromLatin1(QUrl::toPercentEncoding(studentId)); + if (deleteRecords) { + url += "?delete_records=true"; + } + QNetworkReply *reply = m_networkManager.deleteResource(createRequest(url)); + connect(reply, &QNetworkReply::finished, this, [this, reply, studentId]() { + const QByteArray data = reply->readAll(); + if (reply->error() != QNetworkReply::NoError) { + if (isConnectionError(reply->error())) { + emit connectionUnavailable(QStringLiteral("删除失败: %1").arg(reply->errorString())); + } + emit faceDeleted(false, studentId, 0, reply->errorString()); + reply->deleteLater(); + return; + } + + const QJsonObject object = QJsonDocument::fromJson(data).object(); + emit faceDeleted(object.value("success").toBool(), + studentId, + object.value("records_deleted").toInt(), + object.value("message").toString()); + reply->deleteLater(); + }); +} + +void ApiClient::checkHealth() +{ + QNetworkReply *reply = m_networkManager.get(createRequest(buildUrl("/v1/system/health"))); + connect(reply, &QNetworkReply::finished, this, [this, reply]() { + const QByteArray data = reply->readAll(); + if (reply->error() != QNetworkReply::NoError) { + emit healthChecked(false, reply->errorString()); + reply->deleteLater(); + return; + } + const QJsonObject object = QJsonDocument::fromJson(data).object(); + const bool healthy = object.value("status").toString() == "healthy"; + emit healthChecked(healthy, healthy ? QStringLiteral("连接成功") : QStringLiteral("服务器无响应")); + reply->deleteLater(); + }); +} diff --git a/QT/src/ApiClient.h b/QT/src/ApiClient.h new file mode 100644 index 0000000..926865e --- /dev/null +++ b/QT/src/ApiClient.h @@ -0,0 +1,75 @@ +#ifndef API_CLIENT_H +#define API_CLIENT_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "AttendanceTypes.h" + +class ApiClient : public QObject +{ + Q_OBJECT + +public: + explicit ApiClient(QObject *parent = nullptr); + + void setServerUrl(const QString &url); + QString serverUrl() const; + + void fetchSyncState(qulonglong lastVersion); + void fetchRecords(int limit = 1000, int offset = 0); + void fetchStatistics(); + void clearAllRecords(); + void deleteRecord(const QString ×tamp, const QString &studentId); + void fetchTimeSlots(); + void uploadTimeSlots(const QVector &timeSlots); + void fetchMappingConfig(); + void uploadMappingConfig(const QMap &studentNameMap, + const QMap &classNameMap); + void fetchFaceIdMapping(); + void uploadFaceIdMapping(const QMap &mapping); + void fetchFacePhotos(); + void fetchFacePhoto(const QString &faceId); + void fetchAllStudentIds(); + void deleteFace(const QString &studentId, bool deleteRecords); + void checkHealth(); + +signals: + void recordsFetched(const QVector &records); + void statisticsFetched(int total, int today, const QString &serverTime); + void recordsCleared(bool success, const QString &message); + void recordDeleted(bool success, const QString &message); + void timeSlotsFetched(const QVector &timeSlots); + void timeSlotsUploaded(bool success, const QString &message); + void mappingConfigFetched(const QMap &studentNameMap, + const QMap &classNameMap); + void mappingConfigUploaded(bool success, const QString &message); + void faceIdMappingFetched(const QMap &mapping); + void faceIdMappingUploaded(bool success, const QString &message); + void facePhotosFetched(const QStringList &photoIds); + void facePhotoFetched(const QString &faceId, const QByteArray &data, bool success, const QString &message); + void allStudentIdsFetched(const QStringList &studentIds); + void faceDeleted(bool success, const QString &studentId, int recordsDeleted, const QString &message); + void healthChecked(bool healthy, const QString &message); + void connectionUnavailable(const QString &message); + void networkError(const QString &message); + void syncStateFetched(qulonglong version, bool changed); + +private: + QString buildUrl(const QString &endpoint, const QMap ¶ms = {}) const; + QNetworkRequest createRequest(const QString &url, bool encryptedResponse = false, bool jsonBody = false) const; + QVector parseRecords(const QByteArray &data) const; + QByteArray maybeDecrypt(const QByteArray &data, bool encrypted) const; + void emitNetworkError(const QString &prefix, QNetworkReply *reply); + bool isConnectionError(QNetworkReply::NetworkError error) const; + + QNetworkAccessManager m_networkManager; + QString m_serverUrl; +}; + +#endif diff --git a/QT/src/AppController.cpp b/QT/src/AppController.cpp new file mode 100644 index 0000000..a075f7d --- /dev/null +++ b/QT/src/AppController.cpp @@ -0,0 +1,806 @@ +#include "AppController.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { +constexpr int ReconnectIntervalMs = 5000; + +QDate parseDate(const QString &value, const QDate &fallback) +{ + const QDate date = QDate::fromString(value, Qt::ISODate); + return date.isValid() ? date : fallback; +} + +bool isSuccessStatus(const QString &status) +{ + const QString normalized = status.trimmed().toLower(); + return normalized == "success" + || normalized == "succeeded" + || normalized == "ok" + || normalized == "pass" + || normalized == "passed" + || normalized == "present" + || normalized == "recognized" + || normalized == "verified" + || normalized == "valid" + || normalized == "200" + || normalized == "true" + || normalized == "1" + || normalized == QStringLiteral("成功") + || normalized == QStringLiteral("签到成功") + || normalized == QStringLiteral("正常"); +} + +QString csvCell(const QString &value) +{ + QString escaped = value; + const bool needsQuotes = escaped.contains(',') + || escaped.contains('"') + || escaped.contains('\n') + || escaped.contains('\r'); + escaped.replace("\"", "\"\""); + return needsQuotes ? QStringLiteral("\"%1\"").arg(escaped) : escaped; +} + +QString conciseStatusMessage(const QString &message) +{ + if (message.contains(QStringLiteral("Error transferring"), Qt::CaseInsensitive) + || message.contains(QStringLiteral("Connection refused"), Qt::CaseInsensitive) + || message.contains(QStringLiteral("Host not found"), Qt::CaseInsensitive) + || message.contains(QStringLiteral("Network unreachable"), Qt::CaseInsensitive) + || message.contains(QStringLiteral("timed out"), Qt::CaseInsensitive)) { + return QStringLiteral("服务器未连接,稍后重试"); + } + return message; +} + +QString safeFileName(QString value) +{ + value = value.trimmed(); + for (int i = 0; i < value.size(); ++i) { + QChar ch = value.at(i); + if (!ch.isLetterOrNumber() && ch != '_' && ch != '-' && ch != '.') { + value[i] = '_'; + } + } + return value.isEmpty() ? QStringLiteral("unknown") : value; +} + +} + +AppController::AppController(QObject *parent) + : QObject(parent) +{ + loadLocalState(); + m_apiClient.setServerUrl(m_serverUrl); + m_reconnectTimer.setSingleShot(true); + + connect(&m_reconnectTimer, &QTimer::timeout, this, [this]() { + runReconnectCheck(); + }); + + connect(&m_apiClient, &ApiClient::recordsFetched, this, [this](const QVector &records) { + m_allRecords = records; + updateFilterOptions(); + rebuildFilteredRecords(); + rebuildStatistics(); + setStatusMessage(QStringLiteral("已加载 %1 条记录").arg(records.size())); + emit summaryChanged(); + }); + + connect(&m_apiClient, &ApiClient::statisticsFetched, this, [this](int total, int today, const QString &) { + m_totalRecords = total; + m_todayRecords = today; + emit summaryChanged(); + }); + + connect(&m_apiClient, &ApiClient::syncStateFetched, this, [this](qulonglong version, bool changed) { + if (version > 0) { + m_qtSyncVersion = version; + } + setStatusMessage(changed + ? QStringLiteral("同步完成,版本 %1").arg(version) + : QStringLiteral("数据已是最新,版本 %1").arg(version)); + }); + + connect(&m_apiClient, &ApiClient::recordsCleared, this, [this](bool success, const QString &message) { + setStatusMessage(success ? QStringLiteral("已清空全部记录") : QStringLiteral("清空失败: %1").arg(message)); + if (success) { + refreshAll(); + } + }); + + connect(&m_apiClient, &ApiClient::recordDeleted, this, [this](bool success, const QString &message) { + setStatusMessage(success ? QStringLiteral("记录删除成功") : QStringLiteral("记录删除失败: %1").arg(message)); + if (success) { + refreshRecords(); + } + }); + + connect(&m_apiClient, &ApiClient::timeSlotsFetched, this, [this](const QVector &timeSlots) { + if (!timeSlots.isEmpty()) { + m_timeSlotModel.setTimeSlots(timeSlots); + saveTimeSlotsToLocal(); + setStatusMessage(QStringLiteral("已从服务器同步时间段")); + } + }); + + connect(&m_apiClient, &ApiClient::timeSlotsUploaded, this, [this](bool success, const QString &message) { + setStatusMessage(success ? QStringLiteral("时间段已保存并同步") : QStringLiteral("时间段同步失败: %1").arg(message)); + }); + + connect(&m_apiClient, &ApiClient::mappingConfigFetched, this, + [this](const QMap &studentNameMap, const QMap &classNameMap) { + m_studentMappingModel.setMap(studentNameMap); + m_classMappingModel.setMap(classNameMap); + saveMappingsToLocal(); + rebuildFilteredRecords(); + rebuildStatistics(); + setStatusMessage("映射配置已同步"); + }); + + connect(&m_apiClient, &ApiClient::mappingConfigUploaded, this, [this](bool success, const QString &message) { + setStatusMessage(success ? QStringLiteral("映射配置已保存") : QStringLiteral("映射保存失败: %1").arg(message)); + }); + + connect(&m_apiClient, &ApiClient::faceIdMappingFetched, this, [this](const QMap &mapping) { + m_faceIdMapping = mapping; + mergeFaceItems(); + }); + + connect(&m_apiClient, &ApiClient::faceIdMappingUploaded, this, [this](bool success, const QString &message) { + setStatusMessage(success ? QStringLiteral("人脸映射已保存") : QStringLiteral("人脸映射保存失败: %1").arg(message)); + }); + + connect(&m_apiClient, &ApiClient::facePhotosFetched, this, [this](const QStringList &photoIds) { + m_facePhotoIds = photoIds; + m_facePhotoLocalUrls.clear(); + mergeFaceItems(); + for (const QString &id : m_facePhotoIds) { + m_apiClient.fetchFacePhoto(id); + } + }); + + connect(&m_apiClient, &ApiClient::facePhotoFetched, this, + [this](const QString &faceId, const QByteArray &data, bool success, const QString &message) { + if (!success) { + qWarning() << "[FacePhoto] load failed:" << faceId << message; + return; + } + + const QString path = localFacePhotoPath(faceId); + QFile file(path); + if (!file.open(QIODevice::WriteOnly)) { + qWarning() << "[FacePhoto] cache open failed:" << path; + return; + } + + file.write(data); + file.close(); + m_facePhotoLocalUrls.insert(faceId, QUrl::fromLocalFile(path).toString()); + mergeFaceItems(); + }); + + connect(&m_apiClient, &ApiClient::allStudentIdsFetched, this, [this](const QStringList &studentIds) { + m_allStudentIds = studentIds; + mergeFaceItems(); + }); + + connect(&m_apiClient, &ApiClient::faceDeleted, this, [this](bool success, const QString &studentId, int recordsDeleted, const QString &message) { + if (success) { + setStatusMessage(recordsDeleted > 0 + ? QStringLiteral("已删除 %1,并清除 %2 条记录").arg(studentId).arg(recordsDeleted) + : QStringLiteral("已删除 %1").arg(studentId)); + refreshFaces(); + refreshRecords(); + } else { + setStatusMessage(QStringLiteral("删除失败: %1").arg(message)); + } + }); + + connect(&m_apiClient, &ApiClient::healthChecked, this, [this](bool healthy, const QString &message) { + const bool wasReconnecting = m_reconnecting; + m_reconnectCheckInFlight = false; + if (healthy) { + stopReconnect(); + setStatusMessage(wasReconnecting ? QStringLiteral("服务器已恢复连接,正在同步数据") : QStringLiteral("服务器连接正常")); + if (wasReconnecting) { + refreshAll(); + refreshFaces(); + } + } else { + startReconnect(message); + } + }); + + connect(&m_apiClient, &ApiClient::networkError, this, [this](const QString &message) { + setStatusMessage(message); + }); + + connect(&m_apiClient, &ApiClient::connectionUnavailable, this, [this](const QString &message) { + startReconnect(message); + }); + + m_reconnecting = true; + emit reconnectStateChanged(); + runReconnectCheck(); +} + +RecordListModel *AppController::recordModel() { return &m_recordModel; } +StatisticsListModel *AppController::statisticsModel() { return &m_statisticsModel; } +TimeSlotListModel *AppController::timeSlotModel() { return &m_timeSlotModel; } +MappingListModel *AppController::studentMappingModel() { return &m_studentMappingModel; } +MappingListModel *AppController::classMappingModel() { return &m_classMappingModel; } +FaceListModel *AppController::faceModel() { return &m_faceModel; } + +QStringList AppController::classOptions() const { return m_classOptions; } +QStringList AppController::studentOptions() const { return m_studentOptions; } +QString AppController::serverUrl() const { return m_serverUrl; } +QString AppController::statusMessage() const { return m_statusMessage; } +bool AppController::reconnecting() const { return m_reconnecting; } +int AppController::reconnectAttempt() const { return m_reconnectAttempt; } +int AppController::totalRecords() const { return m_totalRecords; } +int AppController::todayRecords() const { return m_todayRecords; } +int AppController::filteredCount() const { return m_filteredRecords.size(); } +int AppController::loadedRecords() const { return m_allRecords.size(); } +int AppController::statisticsStudentCount() const { return m_statisticsStudentCount; } +int AppController::statisticsRecordCount() const { return m_statisticsRecordCount; } + +QString AppController::statisticsRangeText() const +{ + return QString("%1 至 %2") + .arg(m_statisticsStartDate.toString("yyyy-MM-dd")) + .arg(m_statisticsEndDate.toString("yyyy-MM-dd")); +} + +void AppController::setServerUrl(const QString &url) +{ + const QString trimmed = url.trimmed(); + if (trimmed.isEmpty() || trimmed == m_serverUrl) { + return; + } + + m_serverUrl = trimmed; + m_qtSyncVersion = 0; + m_apiClient.setServerUrl(trimmed); + saveServerUrl(); + emit serverUrlChanged(); + stopReconnect(); + setStatusMessage("服务器地址已更新,正在检查连接"); + m_reconnecting = true; + emit reconnectStateChanged(); + runReconnectCheck(); +} + +void AppController::refreshAll() +{ + m_apiClient.fetchSyncState(m_qtSyncVersion); +} + +void AppController::refreshRecords() +{ + m_apiClient.fetchRecords(1000, 0); +} + +void AppController::applyFilters(const QString &classId, + const QString &studentId, + const QString &nameFilter, + int dateFilterIndex, + const QString &specificDate) +{ + m_selectedClassId = classId.isEmpty() ? QStringLiteral("全部") : classId; + m_selectedStudentId = studentId.isEmpty() ? QStringLiteral("全部") : studentId; + m_nameFilter = nameFilter.trimmed(); + m_dateFilterIndex = dateFilterIndex; + m_specificDate = parseDate(specificDate, QDate::currentDate()); + rebuildFilteredRecords(); +} + +void AppController::updateStatisticsRange(const QString &startDate, const QString &endDate) +{ + m_statisticsStartDate = parseDate(startDate, QDate::currentDate().addDays(-30)); + m_statisticsEndDate = parseDate(endDate, QDate::currentDate()); + rebuildStatistics(); +} + +bool AppController::exportFilteredRecords(const QString &fileUrl) +{ + const QString filePath = QUrl(fileUrl).toLocalFile(); + if (filePath.isEmpty()) { + setStatusMessage("导出路径无效"); + return false; + } + + QFile file(filePath); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + setStatusMessage("无法创建导出文件"); + return false; + } + + QTextStream out(&file); + out.setEncoding(QStringConverter::Utf8); + out << "# 考勤记录导出\n"; + out << "# 导出时间: " << QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss") << "\n"; + out << "# 记录总数: " << m_filteredRecords.size() << "\n"; + out << "签到时间,班级编号,班级名称,学号,姓名,置信度,状态\n"; + + for (const AttendanceRecord &record : m_filteredRecords) { + out << csvCell(record.timestamp) << "," + << csvCell(record.classId) << "," + << csvCell(mappedClassName(record)) << "," + << csvCell(record.studentId) << "," + << csvCell(mappedStudentName(record).isEmpty() ? record.originalName : mappedStudentName(record)) << "," + << QString::number(record.confidence, 'f', 4) << "," + << csvCell(record.status) << "\n"; + } + + setStatusMessage(QStringLiteral("已导出 %1 条记录").arg(m_filteredRecords.size())); + return true; +} + +bool AppController::exportStatistics(const QString &fileUrl) +{ + const QString filePath = QUrl(fileUrl).toLocalFile(); + if (filePath.isEmpty()) { + setStatusMessage("统计导出路径无效"); + return false; + } + + QFile file(filePath); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + setStatusMessage("无法创建统计文件"); + return false; + } + + QTextStream out(&file); + out.setEncoding(QStringConverter::Utf8); + out << "考勤统计报表," << statisticsRangeText() << "\n"; + out << "学号,姓名,总签到次数,今日签到,最后签到时间,平均置信度\n"; + + for (int row = 0; row < m_statisticsModel.rowCount(); ++row) { + const QModelIndex index = m_statisticsModel.index(row); + out << csvCell(m_statisticsModel.data(index, StatisticsListModel::StudentIdRole).toString()) << "," + << csvCell(m_statisticsModel.data(index, StatisticsListModel::NameRole).toString()) << "," + << m_statisticsModel.data(index, StatisticsListModel::TotalCountRole).toInt() << "," + << m_statisticsModel.data(index, StatisticsListModel::TodayCountRole).toInt() << "," + << csvCell(m_statisticsModel.data(index, StatisticsListModel::LastCheckInRole).toString()) << "," + << QString::number(m_statisticsModel.data(index, StatisticsListModel::AverageConfidenceRole).toDouble(), 'f', 4) << "\n"; + } + + setStatusMessage("统计报表已导出"); + return true; +} + +void AppController::clearAllRecords() +{ + m_apiClient.clearAllRecords(); +} + +void AppController::saveTimeSlots() +{ + saveTimeSlotsToLocal(); + m_apiClient.uploadTimeSlots(m_timeSlotModel.timeSlots()); +} + +void AppController::reloadTimeSlotsFromServer() +{ + m_apiClient.fetchTimeSlots(); +} + +void AppController::loadMappingsFromServer() +{ + m_apiClient.fetchMappingConfig(); +} + +void AppController::saveMappings() +{ + saveMappingsToLocal(); + m_apiClient.uploadMappingConfig(m_studentMappingModel.toMap(), m_classMappingModel.toMap()); + rebuildFilteredRecords(); + rebuildStatistics(); +} + +void AppController::refreshFaces() +{ + m_apiClient.fetchFaceIdMapping(); + m_apiClient.fetchFacePhotos(); + m_apiClient.fetchAllStudentIds(); +} + +void AppController::saveFaceMappings() +{ + QMap mapping; + const QVector items = m_faceModel.items(); + for (const FaceListModel::Item &item : items) { + if (!item.studentId.trimmed().isEmpty()) { + mapping[item.faceId] = item.studentId.trimmed(); + } + } + m_faceIdMapping = mapping; + m_apiClient.uploadFaceIdMapping(mapping); +} + +void AppController::deleteFace(const QString &studentId, bool deleteRecords) +{ + m_apiClient.deleteFace(studentId, deleteRecords); +} + +void AppController::testConnection() +{ + setStatusMessage("正在检查服务器连接"); + m_apiClient.checkHealth(); +} + +void AppController::loadLocalState() +{ + QSettings settings; + m_serverUrl = settings.value("server/url", "http://127.0.0.1:8082").toString(); + m_qtSyncVersion = 0; + loadMappingsFromLocal(); + loadTimeSlotsFromLocal(); +} + +void AppController::saveServerUrl() +{ + QSettings settings; + settings.setValue("server/url", m_serverUrl); +} + +void AppController::saveMappingsToLocal() +{ + const QString path = localSettingsPath("mapping_config.json"); + QFile file(path); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + return; + } + + QJsonObject root; + QJsonObject studentObject; + const QMap studentMap = m_studentMappingModel.toMap(); + for (auto it = studentMap.begin(); it != studentMap.end(); ++it) { + studentObject[it.key()] = it.value(); + } + + QJsonObject classObject; + const QMap classMap = m_classMappingModel.toMap(); + for (auto it = classMap.begin(); it != classMap.end(); ++it) { + classObject[it.key()] = it.value(); + } + + root["student_name_map"] = studentObject; + root["class_name_map"] = classObject; + file.write(QJsonDocument(root).toJson(QJsonDocument::Indented)); +} + +void AppController::loadMappingsFromLocal() +{ + QFile file(localSettingsPath("mapping_config.json")); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + m_studentMappingModel.clear(); + m_classMappingModel.clear(); + return; + } + + const QJsonObject root = QJsonDocument::fromJson(file.readAll()).object(); + QMap studentMap; + const QJsonObject studentObject = root.value("student_name_map").toObject(); + for (auto it = studentObject.begin(); it != studentObject.end(); ++it) { + studentMap[it.key()] = it.value().toString(); + } + + QMap classMap; + const QJsonObject classObject = root.value("class_name_map").toObject(); + for (auto it = classObject.begin(); it != classObject.end(); ++it) { + classMap[it.key()] = it.value().toString(); + } + + m_studentMappingModel.setMap(studentMap); + m_classMappingModel.setMap(classMap); +} + +void AppController::saveTimeSlotsToLocal() +{ + QFile file(localSettingsPath("timeslot_config.json")); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + return; + } + + QJsonArray array; + for (const TimeSlot &slot : m_timeSlotModel.timeSlots()) { + QJsonObject object; + object["name"] = slot.name; + object["start_time"] = slot.startTime.toString("HH:mm"); + object["end_time"] = slot.endTime.toString("HH:mm"); + object["enabled"] = slot.enabled; + array.append(object); + } + + QJsonObject root; + root["time_slots"] = array; + file.write(QJsonDocument(root).toJson(QJsonDocument::Indented)); +} + +void AppController::loadTimeSlotsFromLocal() +{ + QFile file(localSettingsPath("timeslot_config.json")); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + m_timeSlotModel.setTimeSlots(defaultTimeSlots()); + return; + } + + QVector timeSlots; + const QJsonArray array = QJsonDocument::fromJson(file.readAll()).object().value("time_slots").toArray(); + for (const QJsonValue &value : array) { + const QJsonObject object = value.toObject(); + timeSlots.push_back({ + object.value("name").toString(), + QTime::fromString(object.value("start_time").toString(), "HH:mm"), + QTime::fromString(object.value("end_time").toString(), "HH:mm"), + object.value("enabled").toBool(true) + }); + } + + m_timeSlotModel.setTimeSlots(timeSlots.isEmpty() ? defaultTimeSlots() : timeSlots); +} + +QString AppController::localSettingsPath(const QString &fileName) const +{ + const QString dirPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QDir().mkpath(dirPath); + return dirPath + "/" + fileName; +} + +QString AppController::localFacePhotoPath(const QString &faceId) const +{ + const QString dirPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/face_photos"; + QDir().mkpath(dirPath); + return dirPath + "/" + safeFileName(faceId) + ".jpg"; +} + +void AppController::updateFilterOptions() +{ + QSet classIds; + QSet studentIds; + + for (const AttendanceRecord &record : m_allRecords) { + classIds.insert(record.classId); + studentIds.insert(record.studentId); + } + + m_classOptions = {"全部"}; + QStringList classValues = classIds.values(); + std::sort(classValues.begin(), classValues.end()); + m_classOptions.append(classValues); + + m_studentOptions = {"全部"}; + QStringList studentValues = studentIds.values(); + std::sort(studentValues.begin(), studentValues.end()); + m_studentOptions.append(studentValues); + + emit filtersChanged(); +} + +void AppController::rebuildFilteredRecords() +{ + QVector items; + m_filteredRecords.clear(); + const QDate today = QDate::currentDate(); + + for (const AttendanceRecord &record : m_allRecords) { + if (m_selectedClassId != "全部" && record.classId != m_selectedClassId) { + continue; + } + + if (m_selectedStudentId != "全部" && record.studentId != m_selectedStudentId) { + continue; + } + + const QString displayName = mappedStudentName(record); + const QString candidateName = displayName.isEmpty() ? record.originalName : displayName; + if (!m_nameFilter.isEmpty() && !candidateName.contains(m_nameFilter, Qt::CaseInsensitive)) { + continue; + } + + const QDate recordDate = record.dateTime().date(); + if (m_dateFilterIndex == 1 && recordDate != today) { + continue; + } + if (m_dateFilterIndex == 2 && recordDate.daysTo(today) > 7) { + continue; + } + if (m_dateFilterIndex == 3 && recordDate.daysTo(today) > 30) { + continue; + } + if (m_dateFilterIndex == 4 && recordDate != m_specificDate) { + continue; + } + + m_filteredRecords.push_back(record); + } + + std::sort(m_filteredRecords.begin(), m_filteredRecords.end(), [](const AttendanceRecord &left, const AttendanceRecord &right) { + return left.timestamp > right.timestamp; + }); + + items.reserve(m_filteredRecords.size()); + for (const AttendanceRecord &record : m_filteredRecords) { + items.push_back({ + record.timestamp, + record.classId, + mappedClassName(record), + record.studentId, + mappedStudentName(record).isEmpty() ? record.originalName : mappedStudentName(record), + record.confidence, + record.status, + isSuccessStatus(record.status) + }); + } + + m_recordModel.setItems(items); + emit summaryChanged(); +} + +void AppController::rebuildStatistics() +{ + QMap statisticsMap; + const QDate today = QDate::currentDate(); + + for (const AttendanceRecord &record : m_allRecords) { + const QDate date = record.dateTime().date(); + if (date < m_statisticsStartDate || date > m_statisticsEndDate) { + continue; + } + + StudentStatistics &stats = statisticsMap[record.studentId]; + stats.studentId = record.studentId; + stats.name = mappedStudentName(record).isEmpty() ? record.originalName : mappedStudentName(record); + stats.totalCount += 1; + stats.averageConfidence += record.confidence; + if (date == today) { + stats.todayCount += 1; + } + if (!stats.lastCheckIn.isValid() || record.dateTime() > stats.lastCheckIn) { + stats.lastCheckIn = record.dateTime(); + } + } + + QVector items; + items.reserve(statisticsMap.size()); + m_statisticsStudentCount = statisticsMap.size(); + m_statisticsRecordCount = 0; + + for (auto it = statisticsMap.begin(); it != statisticsMap.end(); ++it) { + StudentStatistics stats = it.value(); + m_statisticsRecordCount += stats.totalCount; + if (stats.totalCount > 0) { + stats.averageConfidence /= static_cast(stats.totalCount); + } + items.push_back({ + stats.studentId, + stats.name, + stats.totalCount, + stats.todayCount, + stats.lastCheckIn.isValid() ? stats.lastCheckIn.toString("yyyy-MM-dd HH:mm:ss") : QStringLiteral("无"), + stats.averageConfidence + }); + } + + std::sort(items.begin(), items.end(), [](const StatisticsListModel::Item &left, const StatisticsListModel::Item &right) { + return left.studentId < right.studentId; + }); + + m_statisticsModel.setItems(items); + emit statisticsChanged(); +} + +QString AppController::mappedStudentName(const AttendanceRecord &record) const +{ + return m_studentMappingModel.toMap().value(record.studentId); +} + +QString AppController::mappedClassName(const AttendanceRecord &record) const +{ + return m_classMappingModel.toMap().value(record.classId, record.classId); +} + +void AppController::mergeFaceItems() +{ + QSet allIds; + for (const QString &id : m_facePhotoIds) { + allIds.insert(id); + } + for (const QString &id : m_allStudentIds) { + allIds.insert(id); + } + + QStringList sortedIds = allIds.values(); + std::sort(sortedIds.begin(), sortedIds.end()); + + QVector items; + items.reserve(sortedIds.size()); + for (const QString &id : sortedIds) { + const QString photoUrl = m_facePhotoLocalUrls.value(id); + const bool hasPhoto = !photoUrl.isEmpty(); + items.push_back({ + id, + m_faceIdMapping.value(id, id), + hasPhoto, + photoUrl + }); + } + + m_faceModel.setItems(items); +} + +void AppController::setStatusMessage(const QString &message) +{ + const QString displayMessage = conciseStatusMessage(message); + if (displayMessage == m_statusMessage) { + return; + } + m_statusMessage = displayMessage; + emit statusMessageChanged(); +} + +void AppController::startReconnect(const QString &reason) +{ + Q_UNUSED(reason) + + if (!m_reconnecting) { + m_reconnecting = true; + m_reconnectAttempt = 0; + emit reconnectStateChanged(); + } + + if (m_reconnectCheckInFlight || m_reconnectTimer.isActive()) { + setStatusMessage(QStringLiteral("服务器未连接,稍后重试")); + return; + } + + setStatusMessage(QStringLiteral("服务器未连接,稍后重试")); + scheduleReconnect(); +} + +void AppController::stopReconnect() +{ + m_reconnectTimer.stop(); + m_reconnectCheckInFlight = false; + if (!m_reconnecting && m_reconnectAttempt == 0) { + return; + } + + m_reconnecting = false; + m_reconnectAttempt = 0; + emit reconnectStateChanged(); +} + +void AppController::scheduleReconnect() +{ + m_reconnectTimer.start(ReconnectIntervalMs); +} + +void AppController::runReconnectCheck() +{ + if (!m_reconnecting || m_reconnectCheckInFlight) { + return; + } + + m_reconnectCheckInFlight = true; + ++m_reconnectAttempt; + emit reconnectStateChanged(); + setStatusMessage(QStringLiteral("正在重连服务器")); + m_apiClient.checkHealth(); +} diff --git a/QT/src/AppController.h b/QT/src/AppController.h new file mode 100644 index 0000000..c1d9796 --- /dev/null +++ b/QT/src/AppController.h @@ -0,0 +1,155 @@ +#ifndef APP_CONTROLLER_H +#define APP_CONTROLLER_H + +#include +#include +#include +#include +#include +#include +#include +#include "ApiClient.h" +#include "FaceListModel.h" +#include "MappingListModel.h" +#include "RecordListModel.h" +#include "StatisticsListModel.h" +#include "TimeSlotListModel.h" + +class AppController : public QObject +{ + Q_OBJECT + Q_PROPERTY(RecordListModel* recordModel READ recordModel CONSTANT) + Q_PROPERTY(StatisticsListModel* statisticsModel READ statisticsModel CONSTANT) + Q_PROPERTY(TimeSlotListModel* timeSlotModel READ timeSlotModel CONSTANT) + Q_PROPERTY(MappingListModel* studentMappingModel READ studentMappingModel CONSTANT) + Q_PROPERTY(MappingListModel* classMappingModel READ classMappingModel CONSTANT) + Q_PROPERTY(FaceListModel* faceModel READ faceModel CONSTANT) + Q_PROPERTY(QStringList classOptions READ classOptions NOTIFY filtersChanged) + Q_PROPERTY(QStringList studentOptions READ studentOptions NOTIFY filtersChanged) + Q_PROPERTY(QString serverUrl READ serverUrl WRITE setServerUrl NOTIFY serverUrlChanged) + Q_PROPERTY(QString statusMessage READ statusMessage NOTIFY statusMessageChanged) + Q_PROPERTY(bool reconnecting READ reconnecting NOTIFY reconnectStateChanged) + Q_PROPERTY(int reconnectAttempt READ reconnectAttempt NOTIFY reconnectStateChanged) + Q_PROPERTY(int totalRecords READ totalRecords NOTIFY summaryChanged) + Q_PROPERTY(int todayRecords READ todayRecords NOTIFY summaryChanged) + Q_PROPERTY(int filteredCount READ filteredCount NOTIFY summaryChanged) + Q_PROPERTY(int loadedRecords READ loadedRecords NOTIFY summaryChanged) + Q_PROPERTY(int statisticsStudentCount READ statisticsStudentCount NOTIFY statisticsChanged) + Q_PROPERTY(int statisticsRecordCount READ statisticsRecordCount NOTIFY statisticsChanged) + Q_PROPERTY(QString statisticsRangeText READ statisticsRangeText NOTIFY statisticsChanged) + +public: + explicit AppController(QObject *parent = nullptr); + + RecordListModel *recordModel(); + StatisticsListModel *statisticsModel(); + TimeSlotListModel *timeSlotModel(); + MappingListModel *studentMappingModel(); + MappingListModel *classMappingModel(); + FaceListModel *faceModel(); + + QStringList classOptions() const; + QStringList studentOptions() const; + QString serverUrl() const; + QString statusMessage() const; + bool reconnecting() const; + int reconnectAttempt() const; + int totalRecords() const; + int todayRecords() const; + int filteredCount() const; + int loadedRecords() const; + int statisticsStudentCount() const; + int statisticsRecordCount() const; + QString statisticsRangeText() const; + + void setServerUrl(const QString &url); + + Q_INVOKABLE void refreshAll(); + Q_INVOKABLE void refreshRecords(); + Q_INVOKABLE void applyFilters(const QString &classId, + const QString &studentId, + const QString &nameFilter, + int dateFilterIndex, + const QString &specificDate); + Q_INVOKABLE void updateStatisticsRange(const QString &startDate, const QString &endDate); + Q_INVOKABLE bool exportFilteredRecords(const QString &fileUrl); + Q_INVOKABLE bool exportStatistics(const QString &fileUrl); + Q_INVOKABLE void clearAllRecords(); + Q_INVOKABLE void saveTimeSlots(); + Q_INVOKABLE void reloadTimeSlotsFromServer(); + Q_INVOKABLE void loadMappingsFromServer(); + Q_INVOKABLE void saveMappings(); + Q_INVOKABLE void refreshFaces(); + Q_INVOKABLE void saveFaceMappings(); + Q_INVOKABLE void deleteFace(const QString &studentId, bool deleteRecords); + Q_INVOKABLE void testConnection(); + +signals: + void filtersChanged(); + void serverUrlChanged(); + void statusMessageChanged(); + void reconnectStateChanged(); + void summaryChanged(); + void statisticsChanged(); + +private: + void loadLocalState(); + void saveServerUrl(); + void saveMappingsToLocal(); + void loadMappingsFromLocal(); + void saveTimeSlotsToLocal(); + void loadTimeSlotsFromLocal(); + QString localSettingsPath(const QString &fileName) const; + void updateFilterOptions(); + void rebuildFilteredRecords(); + void rebuildStatistics(); + QString mappedStudentName(const AttendanceRecord &record) const; + QString mappedClassName(const AttendanceRecord &record) const; + QString localFacePhotoPath(const QString &faceId) const; + void mergeFaceItems(); + void setStatusMessage(const QString &message); + void startReconnect(const QString &reason); + void stopReconnect(); + void scheduleReconnect(); + void runReconnectCheck(); + + ApiClient m_apiClient; + QTimer m_reconnectTimer; + RecordListModel m_recordModel; + StatisticsListModel m_statisticsModel; + TimeSlotListModel m_timeSlotModel; + MappingListModel m_studentMappingModel; + MappingListModel m_classMappingModel; + FaceListModel m_faceModel; + + QVector m_allRecords; + QVector m_filteredRecords; + QStringList m_classOptions; + QStringList m_studentOptions; + QString m_serverUrl; + QString m_statusMessage; + bool m_reconnecting = false; + bool m_reconnectCheckInFlight = false; + int m_reconnectAttempt = 0; + int m_totalRecords = 0; + int m_todayRecords = 0; + + QString m_selectedClassId = "全部"; + QString m_selectedStudentId = "全部"; + QString m_nameFilter; + int m_dateFilterIndex = 0; + QDate m_specificDate = QDate::currentDate(); + + QDate m_statisticsStartDate = QDate::currentDate().addDays(-30); + QDate m_statisticsEndDate = QDate::currentDate(); + int m_statisticsStudentCount = 0; + int m_statisticsRecordCount = 0; + qulonglong m_qtSyncVersion = 0; + + QMap m_faceIdMapping; + QHash m_facePhotoLocalUrls; + QStringList m_facePhotoIds; + QStringList m_allStudentIds; +}; + +#endif diff --git a/QT/src/AttendanceTypes.h b/QT/src/AttendanceTypes.h new file mode 100644 index 0000000..b58ffae --- /dev/null +++ b/QT/src/AttendanceTypes.h @@ -0,0 +1,59 @@ +#ifndef ATTENDANCE_TYPES_H +#define ATTENDANCE_TYPES_H + +#include +#include +#include +#include +#include + +struct AttendanceRecord +{ + QString timestamp; + QString studentId; + QString originalName; + double confidence = 0.0; + QString status; + QString classId = "0"; + + QDateTime dateTime() const + { + return QDateTime::fromString(timestamp, "yyyy-MM-dd HH:mm:ss"); + } +}; + +struct StudentStatistics +{ + QString studentId; + QString name; + int totalCount = 0; + int todayCount = 0; + QDateTime lastCheckIn; + double averageConfidence = 0.0; +}; + +struct TimeSlot +{ + QString name; + QTime startTime; + QTime endTime; + bool enabled = true; +}; + +inline QVector defaultTimeSlots() +{ + return { + {"上午签到", QTime(8, 0), QTime(9, 30), true}, + {"中午签退", QTime(12, 0), QTime(13, 0), true}, + {"下午签到", QTime(14, 0), QTime(15, 0), true}, + {"晚上签退", QTime(17, 0), QTime(18, 30), true} + }; +} + +Q_DECLARE_METATYPE(AttendanceRecord) +Q_DECLARE_METATYPE(StudentStatistics) +Q_DECLARE_METATYPE(TimeSlot) +Q_DECLARE_METATYPE(QVector) +Q_DECLARE_METATYPE(QVector) + +#endif diff --git a/QT/src/CryptoUtils.cpp b/QT/src/CryptoUtils.cpp new file mode 100644 index 0000000..fcad252 --- /dev/null +++ b/QT/src/CryptoUtils.cpp @@ -0,0 +1,48 @@ +#include "CryptoUtils.h" +#include "crypto/tiny_aes.hpp" + +namespace { +QByteArray removePkcs7Padding(const QByteArray &data) +{ + if (data.isEmpty()) { + return {}; + } + + const int padding = static_cast(data.back()); + if (padding < 1 || padding > AES_BLOCKLEN || padding > data.size()) { + return data; + } + + for (int i = data.size() - padding; i < data.size(); ++i) { + if (static_cast(data.at(i)) != padding) { + return data; + } + } + + return data.left(data.size() - padding); +} +} + +QByteArray CryptoUtils::decryptAes128CbcBase64(const QByteArray &encryptedBase64) +{ + static const uint8_t key[AES_KEYLEN] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c + }; + + static const uint8_t iv[AES_BLOCKLEN] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + + const QByteArray encrypted = QByteArray::fromBase64(encryptedBase64); + if (encrypted.isEmpty() || (encrypted.size() % AES_BLOCKLEN) != 0) { + return {}; + } + + QByteArray buffer = encrypted; + AES_ctx ctx; + AES_init_ctx_iv(&ctx, key, iv); + AES_CBC_decrypt_buffer(&ctx, reinterpret_cast(buffer.data()), static_cast(buffer.size())); + return removePkcs7Padding(buffer); +} diff --git a/QT/src/CryptoUtils.h b/QT/src/CryptoUtils.h new file mode 100644 index 0000000..3763751 --- /dev/null +++ b/QT/src/CryptoUtils.h @@ -0,0 +1,12 @@ +#ifndef CRYPTO_UTILS_H +#define CRYPTO_UTILS_H + +#include + +class CryptoUtils +{ +public: + static QByteArray decryptAes128CbcBase64(const QByteArray &encryptedBase64); +}; + +#endif diff --git a/QT/src/FaceListModel.cpp b/QT/src/FaceListModel.cpp new file mode 100644 index 0000000..91d7ab1 --- /dev/null +++ b/QT/src/FaceListModel.cpp @@ -0,0 +1,85 @@ +#include "FaceListModel.h" + +FaceListModel::FaceListModel(QObject *parent) + : QAbstractListModel(parent) +{ +} + +int FaceListModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } + return m_items.size(); +} + +QVariant FaceListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() < 0 || index.row() >= m_items.size()) { + return {}; + } + + const Item &item = m_items.at(index.row()); + switch (role) { + case FaceIdRole: return item.faceId; + case StudentIdRole: return item.studentId; + case HasPhotoRole: return item.hasPhoto; + case PhotoUrlRole: return item.photoUrl; + default: return {}; + } +} + +bool FaceListModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid() || index.row() < 0 || index.row() >= m_items.size()) { + return false; + } + + if (role == StudentIdRole) { + m_items[index.row()].studentId = value.toString().trimmed(); + emit dataChanged(index, index, {role}); + return true; + } + + return false; +} + +Qt::ItemFlags FaceListModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) { + return Qt::NoItemFlags; + } + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; +} + +QHash FaceListModel::roleNames() const +{ + return { + {FaceIdRole, "faceId"}, + {StudentIdRole, "studentId"}, + {HasPhotoRole, "hasPhoto"}, + {PhotoUrlRole, "photoUrl"} + }; +} + +void FaceListModel::setItems(const QVector &items) +{ + beginResetModel(); + m_items = items; + endResetModel(); +} + +QVector FaceListModel::items() const +{ + return m_items; +} + +void FaceListModel::updateStudentId(int index, const QString &studentId) +{ + if (index < 0 || index >= m_items.size()) { + return; + } + + m_items[index].studentId = studentId.trimmed(); + emit dataChanged(this->index(index), this->index(index), {StudentIdRole}); +} diff --git a/QT/src/FaceListModel.h b/QT/src/FaceListModel.h new file mode 100644 index 0000000..f6d3b7e --- /dev/null +++ b/QT/src/FaceListModel.h @@ -0,0 +1,47 @@ +#ifndef FACE_LIST_MODEL_H +#define FACE_LIST_MODEL_H + +#include +#include +#include +#include +#include +#include +#include + +class FaceListModel : public QAbstractListModel +{ + Q_OBJECT + +public: + enum Roles { + FaceIdRole = Qt::UserRole + 1, + StudentIdRole, + HasPhotoRole, + PhotoUrlRole + }; + + explicit FaceListModel(QObject *parent = nullptr); + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role) override; + Qt::ItemFlags flags(const QModelIndex &index) const override; + QHash roleNames() const override; + + struct Item { + QString faceId; + QString studentId; + bool hasPhoto = false; + QString photoUrl; + }; + + void setItems(const QVector &items); + QVector items() const; + Q_INVOKABLE void updateStudentId(int index, const QString &studentId); + +private: + QVector m_items; +}; + +#endif diff --git a/QT/src/MappingListModel.cpp b/QT/src/MappingListModel.cpp new file mode 100644 index 0000000..1ff47f6 --- /dev/null +++ b/QT/src/MappingListModel.cpp @@ -0,0 +1,132 @@ +#include "MappingListModel.h" +#include + +MappingListModel::MappingListModel(QObject *parent) + : QAbstractListModel(parent) +{ +} + +int MappingListModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } + return m_items.size(); +} + +QVariant MappingListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() < 0 || index.row() >= m_items.size()) { + return {}; + } + + const Item &item = m_items.at(index.row()); + switch (role) { + case KeyRole: return item.key; + case ValueRole: return item.value; + default: return {}; + } +} + +bool MappingListModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid() || index.row() < 0 || index.row() >= m_items.size()) { + return false; + } + + Item &item = m_items[index.row()]; + switch (role) { + case KeyRole: item.key = value.toString().trimmed(); break; + case ValueRole: item.value = value.toString().trimmed(); break; + default: return false; + } + + emit dataChanged(index, index, {role}); + return true; +} + +Qt::ItemFlags MappingListModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) { + return Qt::NoItemFlags; + } + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; +} + +QHash MappingListModel::roleNames() const +{ + return { + {KeyRole, "entryKey"}, + {ValueRole, "entryValue"} + }; +} + +void MappingListModel::setMap(const QMap &map) +{ + QVector items; + items.reserve(map.size()); + for (auto it = map.begin(); it != map.end(); ++it) { + items.push_back({it.key(), it.value()}); + } + + std::sort(items.begin(), items.end(), [](const Item &left, const Item &right) { + bool leftNumeric = false; + bool rightNumeric = false; + int leftValue = left.key.toInt(&leftNumeric); + int rightValue = right.key.toInt(&rightNumeric); + if (leftNumeric && rightNumeric) { + return leftValue < rightValue; + } + return left.key < right.key; + }); + + beginResetModel(); + m_items = items; + endResetModel(); +} + +QMap MappingListModel::toMap() const +{ + QMap map; + for (const Item &item : m_items) { + if (!item.key.trimmed().isEmpty()) { + map[item.key.trimmed()] = item.value.trimmed(); + } + } + return map; +} + +void MappingListModel::addEntry(const QString &key, const QString &value) +{ + beginInsertRows(QModelIndex(), m_items.size(), m_items.size()); + m_items.push_back({key.trimmed(), value.trimmed()}); + endInsertRows(); +} + +void MappingListModel::updateEntry(int index, const QString &key, const QString &value) +{ + if (index < 0 || index >= m_items.size()) { + return; + } + + m_items[index] = {key.trimmed(), value.trimmed()}; + emit dataChanged(this->index(index), this->index(index)); +} + +void MappingListModel::removeEntry(int index) +{ + if (index < 0 || index >= m_items.size()) { + return; + } + + beginRemoveRows(QModelIndex(), index, index); + m_items.removeAt(index); + endRemoveRows(); +} + +void MappingListModel::clear() +{ + beginResetModel(); + m_items.clear(); + endResetModel(); +} diff --git a/QT/src/MappingListModel.h b/QT/src/MappingListModel.h new file mode 100644 index 0000000..2a4a5c7 --- /dev/null +++ b/QT/src/MappingListModel.h @@ -0,0 +1,48 @@ +#ifndef MAPPING_LIST_MODEL_H +#define MAPPING_LIST_MODEL_H + +#include +#include +#include +#include +#include +#include +#include +#include + +class MappingListModel : public QAbstractListModel +{ + Q_OBJECT + +public: + enum Roles { + KeyRole = Qt::UserRole + 1, + ValueRole + }; + + explicit MappingListModel(QObject *parent = nullptr); + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role) override; + Qt::ItemFlags flags(const QModelIndex &index) const override; + QHash roleNames() const override; + + void setMap(const QMap &map); + QMap toMap() const; + + Q_INVOKABLE void addEntry(const QString &key, const QString &value); + Q_INVOKABLE void updateEntry(int index, const QString &key, const QString &value); + Q_INVOKABLE void removeEntry(int index); + Q_INVOKABLE void clear(); + +private: + struct Item { + QString key; + QString value; + }; + + QVector m_items; +}; + +#endif diff --git a/QT/src/RecordListModel.cpp b/QT/src/RecordListModel.cpp new file mode 100644 index 0000000..3850932 --- /dev/null +++ b/QT/src/RecordListModel.cpp @@ -0,0 +1,59 @@ +#include "RecordListModel.h" + +RecordListModel::RecordListModel(QObject *parent) + : QAbstractListModel(parent) +{ +} + +int RecordListModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } + return m_items.size(); +} + +QVariant RecordListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() < 0 || index.row() >= m_items.size()) { + return {}; + } + + const Item &item = m_items.at(index.row()); + switch (role) { + case TimestampRole: return item.timestamp; + case ClassIdRole: return item.classId; + case ClassNameRole: return item.className; + case StudentIdRole: return item.studentId; + case NameRole: return item.name; + case ConfidenceRole: return item.confidence; + case ConfidenceTextRole: return QString::number(item.confidence * 100.0, 'f', 2) + "%"; + case StatusRole: return item.status; + case StatusTextRole: return item.success ? QStringLiteral("成功") : QStringLiteral("失败"); + case SuccessRole: return item.success; + default: return {}; + } +} + +QHash RecordListModel::roleNames() const +{ + return { + {TimestampRole, "timestamp"}, + {ClassIdRole, "classId"}, + {ClassNameRole, "className"}, + {StudentIdRole, "studentId"}, + {NameRole, "name"}, + {ConfidenceRole, "confidence"}, + {ConfidenceTextRole, "confidenceText"}, + {StatusRole, "status"}, + {StatusTextRole, "statusText"}, + {SuccessRole, "success"} + }; +} + +void RecordListModel::setItems(const QVector &items) +{ + beginResetModel(); + m_items = items; + endResetModel(); +} diff --git a/QT/src/RecordListModel.h b/QT/src/RecordListModel.h new file mode 100644 index 0000000..d367d5b --- /dev/null +++ b/QT/src/RecordListModel.h @@ -0,0 +1,53 @@ +#ifndef RECORD_LIST_MODEL_H +#define RECORD_LIST_MODEL_H + +#include +#include +#include +#include +#include +#include +#include + +class RecordListModel : public QAbstractListModel +{ + Q_OBJECT + +public: + enum Roles { + TimestampRole = Qt::UserRole + 1, + ClassIdRole, + ClassNameRole, + StudentIdRole, + NameRole, + ConfidenceRole, + ConfidenceTextRole, + StatusRole, + StatusTextRole, + SuccessRole + }; + + explicit RecordListModel(QObject *parent = nullptr); + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QHash roleNames() const override; + + struct Item { + QString timestamp; + QString classId; + QString className; + QString studentId; + QString name; + double confidence = 0.0; + QString status; + bool success = false; + }; + + void setItems(const QVector &items); + +private: + QVector m_items; +}; + +#endif diff --git a/QT/src/StatisticsListModel.cpp b/QT/src/StatisticsListModel.cpp new file mode 100644 index 0000000..bd10986 --- /dev/null +++ b/QT/src/StatisticsListModel.cpp @@ -0,0 +1,53 @@ +#include "StatisticsListModel.h" + +StatisticsListModel::StatisticsListModel(QObject *parent) + : QAbstractListModel(parent) +{ +} + +int StatisticsListModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } + return m_items.size(); +} + +QVariant StatisticsListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() < 0 || index.row() >= m_items.size()) { + return {}; + } + + const Item &item = m_items.at(index.row()); + switch (role) { + case StudentIdRole: return item.studentId; + case NameRole: return item.name; + case TotalCountRole: return item.totalCount; + case TodayCountRole: return item.todayCount; + case LastCheckInRole: return item.lastCheckIn; + case AverageConfidenceRole: return item.averageConfidence; + case AverageConfidenceTextRole: return QString::number(item.averageConfidence * 100.0, 'f', 2) + "%"; + default: return {}; + } +} + +QHash StatisticsListModel::roleNames() const +{ + return { + {StudentIdRole, "studentId"}, + {NameRole, "name"}, + {TotalCountRole, "totalCount"}, + {TodayCountRole, "todayCount"}, + {LastCheckInRole, "lastCheckIn"}, + {AverageConfidenceRole, "averageConfidence"}, + {AverageConfidenceTextRole, "averageConfidenceText"} + }; +} + +void StatisticsListModel::setItems(const QVector &items) +{ + beginResetModel(); + m_items = items; + endResetModel(); +} diff --git a/QT/src/StatisticsListModel.h b/QT/src/StatisticsListModel.h new file mode 100644 index 0000000..0fff392 --- /dev/null +++ b/QT/src/StatisticsListModel.h @@ -0,0 +1,48 @@ +#ifndef STATISTICS_LIST_MODEL_H +#define STATISTICS_LIST_MODEL_H + +#include +#include +#include +#include +#include +#include +#include + +class StatisticsListModel : public QAbstractListModel +{ + Q_OBJECT + +public: + enum Roles { + StudentIdRole = Qt::UserRole + 1, + NameRole, + TotalCountRole, + TodayCountRole, + LastCheckInRole, + AverageConfidenceRole, + AverageConfidenceTextRole + }; + + explicit StatisticsListModel(QObject *parent = nullptr); + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QHash roleNames() const override; + + struct Item { + QString studentId; + QString name; + int totalCount = 0; + int todayCount = 0; + QString lastCheckIn; + double averageConfidence = 0.0; + }; + + void setItems(const QVector &items); + +private: + QVector m_items; +}; + +#endif diff --git a/QT/src/TimeSlotListModel.cpp b/QT/src/TimeSlotListModel.cpp new file mode 100644 index 0000000..98e7919 --- /dev/null +++ b/QT/src/TimeSlotListModel.cpp @@ -0,0 +1,146 @@ +#include "TimeSlotListModel.h" +#include + +TimeSlotListModel::TimeSlotListModel(QObject *parent) + : QAbstractListModel(parent) +{ +} + +int TimeSlotListModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } + return m_timeSlots.size(); +} + +QVariant TimeSlotListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() < 0 || index.row() >= m_timeSlots.size()) { + return {}; + } + + const TimeSlot &slot = m_timeSlots.at(index.row()); + switch (role) { + case NameRole: return slot.name; + case StartTimeRole: return slot.startTime.toString("HH:mm"); + case EndTimeRole: return slot.endTime.toString("HH:mm"); + case EnabledRole: return slot.enabled; + default: return {}; + } +} + +bool TimeSlotListModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid() || index.row() < 0 || index.row() >= m_timeSlots.size()) { + return false; + } + + TimeSlot &slot = m_timeSlots[index.row()]; + switch (role) { + case NameRole: slot.name = value.toString(); break; + case StartTimeRole: slot.startTime = QTime::fromString(value.toString(), "HH:mm"); break; + case EndTimeRole: slot.endTime = QTime::fromString(value.toString(), "HH:mm"); break; + case EnabledRole: slot.enabled = value.toBool(); break; + default: return false; + } + + emit dataChanged(index, index, {role}); + return true; +} + +Qt::ItemFlags TimeSlotListModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) { + return Qt::NoItemFlags; + } + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; +} + +QHash TimeSlotListModel::roleNames() const +{ + return { + {NameRole, "name"}, + {StartTimeRole, "startTime"}, + {EndTimeRole, "endTime"}, + {EnabledRole, "enabled"} + }; +} + +void TimeSlotListModel::setTimeSlots(const QVector &timeSlots) +{ + beginResetModel(); + m_timeSlots = timeSlots; + endResetModel(); +} + +QVector TimeSlotListModel::timeSlots() const +{ + return m_timeSlots; +} + +QJsonArray TimeSlotListModel::toJsonArray() const +{ + QJsonArray array; + for (const TimeSlot &slot : m_timeSlots) { + QJsonObject object; + object["name"] = slot.name; + object["start_time"] = slot.startTime.toString("HH:mm"); + object["end_time"] = slot.endTime.toString("HH:mm"); + object["enabled"] = slot.enabled; + array.append(object); + } + return array; +} + +QVariantMap TimeSlotListModel::get(int index) const +{ + if (index < 0 || index >= m_timeSlots.size()) { + return {}; + } + + const TimeSlot &slot = m_timeSlots.at(index); + return { + {"name", slot.name}, + {"startTime", slot.startTime.toString("HH:mm")}, + {"endTime", slot.endTime.toString("HH:mm")}, + {"enabled", slot.enabled} + }; +} + +void TimeSlotListModel::addTimeSlot(const QString &name, const QString &startTime, const QString &endTime, bool enabled) +{ + beginInsertRows(QModelIndex(), m_timeSlots.size(), m_timeSlots.size()); + m_timeSlots.push_back({name.trimmed(), QTime::fromString(startTime, "HH:mm"), QTime::fromString(endTime, "HH:mm"), enabled}); + endInsertRows(); +} + +void TimeSlotListModel::updateTimeSlot(int index, const QString &name, const QString &startTime, const QString &endTime, bool enabled) +{ + if (index < 0 || index >= m_timeSlots.size()) { + return; + } + + TimeSlot &slot = m_timeSlots[index]; + slot.name = name.trimmed(); + slot.startTime = QTime::fromString(startTime, "HH:mm"); + slot.endTime = QTime::fromString(endTime, "HH:mm"); + slot.enabled = enabled; + emit dataChanged(this->index(index), this->index(index)); +} + +void TimeSlotListModel::removeTimeSlot(int index) +{ + if (index < 0 || index >= m_timeSlots.size()) { + return; + } + + beginRemoveRows(QModelIndex(), index, index); + m_timeSlots.removeAt(index); + endRemoveRows(); +} + +void TimeSlotListModel::resetToDefault() +{ + setTimeSlots(defaultTimeSlots()); +} diff --git a/QT/src/TimeSlotListModel.h b/QT/src/TimeSlotListModel.h new file mode 100644 index 0000000..1c5e07e --- /dev/null +++ b/QT/src/TimeSlotListModel.h @@ -0,0 +1,48 @@ +#ifndef TIMESLOT_LIST_MODEL_H +#define TIMESLOT_LIST_MODEL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "AttendanceTypes.h" + +class TimeSlotListModel : public QAbstractListModel +{ + Q_OBJECT + +public: + enum Roles { + NameRole = Qt::UserRole + 1, + StartTimeRole, + EndTimeRole, + EnabledRole + }; + + explicit TimeSlotListModel(QObject *parent = nullptr); + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role) override; + Qt::ItemFlags flags(const QModelIndex &index) const override; + QHash roleNames() const override; + + void setTimeSlots(const QVector &timeSlots); + QVector timeSlots() const; + QJsonArray toJsonArray() const; + + Q_INVOKABLE QVariantMap get(int index) const; + Q_INVOKABLE void addTimeSlot(const QString &name, const QString &startTime, const QString &endTime, bool enabled); + Q_INVOKABLE void updateTimeSlot(int index, const QString &name, const QString &startTime, const QString &endTime, bool enabled); + Q_INVOKABLE void removeTimeSlot(int index); + Q_INVOKABLE void resetToDefault(); + +private: + QVector m_timeSlots; +}; + +#endif diff --git a/QT/src/crypto/tiny_aes.hpp b/QT/src/crypto/tiny_aes.hpp new file mode 100644 index 0000000..dfb2da5 --- /dev/null +++ b/QT/src/crypto/tiny_aes.hpp @@ -0,0 +1,217 @@ +/* + * Tiny AES128 C++ 移植版本 + * 与STM32端使用相同的AES实现,保证兼容性 + */ + +#ifndef _TINY_AES_HPP_ +#define _TINY_AES_HPP_ + +#include +#include + +#define AES_BLOCKLEN 16 +#define AES_KEYLEN 16 +#define AES_keyExpSize 176 + +struct AES_ctx +{ + uint8_t RoundKey[AES_keyExpSize]; + uint8_t Iv[AES_BLOCKLEN]; +}; + +static const uint8_t sbox[256] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +static const uint8_t rsbox[256] = { + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d +}; + +static const uint8_t Rcon[11] = { + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 +}; + +#define getSBoxValue(num) (sbox[(num)]) +#define getSBoxInvert(num) (rsbox[(num)]) + +inline void KeyExpansion(uint8_t *RoundKey, const uint8_t *Key) +{ + unsigned i, j, k; + uint8_t tempa[4]; + for (i = 0; i < 4; ++i) { + RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; + RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; + RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; + RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; + } + + for (i = 4; i < 44; ++i) { + k = (i - 1) * 4; + tempa[0] = RoundKey[k + 0]; + tempa[1] = RoundKey[k + 1]; + tempa[2] = RoundKey[k + 2]; + tempa[3] = RoundKey[k + 3]; + + if (i % 4 == 0) { + const uint8_t u8tmp = tempa[0]; + tempa[0] = tempa[1]; + tempa[1] = tempa[2]; + tempa[2] = tempa[3]; + tempa[3] = u8tmp; + + tempa[0] = getSBoxValue(tempa[0]); + tempa[1] = getSBoxValue(tempa[1]); + tempa[2] = getSBoxValue(tempa[2]); + tempa[3] = getSBoxValue(tempa[3]); + tempa[0] ^= Rcon[i / 4]; + } + + j = i * 4; + k = (i - 4) * 4; + RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0]; + RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1]; + RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2]; + RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3]; + } +} + +static void AddRoundKey(uint8_t round, uint8_t *state, const uint8_t *RoundKey) +{ + uint8_t i, j; + for (i = 0; i < 4; ++i) { + for (j = 0; j < 4; ++j) { + state[i * 4 + j] ^= RoundKey[(round * 16) + (i * 4 + j)]; + } + } +} + +static void InvSubBytes(uint8_t *state) +{ + for (uint8_t i = 0; i < 16; ++i) { + state[i] = getSBoxInvert(state[i]); + } +} + +static void InvShiftRows(uint8_t *state) +{ + uint8_t temp; + temp = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = temp; + + temp = state[2]; + state[2] = state[10]; + state[10] = temp; + temp = state[6]; + state[6] = state[14]; + state[14] = temp; + + temp = state[3]; + state[3] = state[7]; + state[7] = state[11]; + state[11] = state[15]; + state[15] = temp; +} + +static uint8_t xtime(uint8_t x) +{ + return ((x << 1) ^ (((x >> 7) & 1U) * 0x1bU)); +} + +static uint8_t Multiply(uint8_t x, uint8_t y) +{ + return (((y & 1U) * x) ^ + (((y >> 1U) & 1U) * xtime(x)) ^ + (((y >> 2U) & 1U) * xtime(xtime(x))) ^ + (((y >> 3U) & 1U) * xtime(xtime(xtime(x)))) ^ + (((y >> 4U) & 1U) * xtime(xtime(xtime(xtime(x)))))); +} + +static void InvMixColumns(uint8_t *state) +{ + int i; + uint8_t a, b, c, d; + for (i = 0; i < 4; ++i) { + a = state[i * 4 + 0]; + b = state[i * 4 + 1]; + c = state[i * 4 + 2]; + d = state[i * 4 + 3]; + + state[i * 4 + 0] = Multiply(a, 0x0eU) ^ Multiply(b, 0x0bU) ^ Multiply(c, 0x0dU) ^ Multiply(d, 0x09U); + state[i * 4 + 1] = Multiply(a, 0x09U) ^ Multiply(b, 0x0eU) ^ Multiply(c, 0x0bU) ^ Multiply(d, 0x0dU); + state[i * 4 + 2] = Multiply(a, 0x0dU) ^ Multiply(b, 0x09U) ^ Multiply(c, 0x0eU) ^ Multiply(d, 0x0bU); + state[i * 4 + 3] = Multiply(a, 0x0bU) ^ Multiply(b, 0x0dU) ^ Multiply(c, 0x09U) ^ Multiply(d, 0x0eU); + } +} + +inline void InvCipher(uint8_t *state, const uint8_t *RoundKey) +{ + uint8_t round = 0; + AddRoundKey(10, state, RoundKey); + + for (round = 9; ; --round) { + InvShiftRows(state); + InvSubBytes(state); + AddRoundKey(round, state, RoundKey); + if (round == 0) { + break; + } + InvMixColumns(state); + } +} + +inline void AES_init_ctx_iv(struct AES_ctx *ctx, const uint8_t *key, const uint8_t *iv) +{ + KeyExpansion(ctx->RoundKey, key); + memcpy(ctx->Iv, iv, AES_BLOCKLEN); +} + +inline void AES_CBC_decrypt_buffer(struct AES_ctx *ctx, uint8_t *buf, size_t length) +{ + size_t i; + uint8_t storeNextIv[AES_BLOCKLEN]; + + for (i = 0; i < length; i += AES_BLOCKLEN) { + memcpy(storeNextIv, buf + i, AES_BLOCKLEN); + InvCipher(buf + i, ctx->RoundKey); + + for (uint8_t j = 0; j < AES_BLOCKLEN; ++j) { + buf[i + j] ^= ctx->Iv[j]; + } + memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN); + } +} + +#endif diff --git a/Start/core_cm3.c b/Start/core_cm3.c new file mode 100644 index 0000000..fcff0d1 --- /dev/null +++ b/Start/core_cm3.c @@ -0,0 +1,784 @@ +/**************************************************************************//** + * @file core_cm3.c + * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Source File + * @version V1.30 + * @date 30. October 2009 + * + * @note + * Copyright (C) 2009 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#include + +/* define compiler specific symbols */ +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */ + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + +#endif + + +/* ################### Compiler specific Intrinsics ########################### */ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +/** + * @brief Return the Process Stack Pointer + * + * @return ProcessStackPointer + * + * Return the actual process stack pointer + */ +__ASM uint32_t __get_PSP(void) +{ + mrs r0, psp + bx lr +} + +/** + * @brief Set the Process Stack Pointer + * + * @param topOfProcStack Process Stack Pointer + * + * Assign the value ProcessStackPointer to the MSP + * (process stack pointer) Cortex processor register + */ +__ASM void __set_PSP(uint32_t topOfProcStack) +{ + msr psp, r0 + bx lr +} + +/** + * @brief Return the Main Stack Pointer + * + * @return Main Stack Pointer + * + * Return the current value of the MSP (main stack pointer) + * Cortex processor register + */ +__ASM uint32_t __get_MSP(void) +{ + mrs r0, msp + bx lr +} + +/** + * @brief Set the Main Stack Pointer + * + * @param topOfMainStack Main Stack Pointer + * + * Assign the value mainStackPointer to the MSP + * (main stack pointer) Cortex processor register + */ +__ASM void __set_MSP(uint32_t mainStackPointer) +{ + msr msp, r0 + bx lr +} + +/** + * @brief Reverse byte order in unsigned short value + * + * @param value value to reverse + * @return reversed value + * + * Reverse byte order in unsigned short value + */ +__ASM uint32_t __REV16(uint16_t value) +{ + rev16 r0, r0 + bx lr +} + +/** + * @brief Reverse byte order in signed short value with sign extension to integer + * + * @param value value to reverse + * @return reversed value + * + * Reverse byte order in signed short value with sign extension to integer + */ +__ASM int32_t __REVSH(int16_t value) +{ + revsh r0, r0 + bx lr +} + + +#if (__ARMCC_VERSION < 400000) + +/** + * @brief Remove the exclusive lock created by ldrex + * + * Removes the exclusive lock which is created by ldrex. + */ +__ASM void __CLREX(void) +{ + clrex +} + +/** + * @brief Return the Base Priority value + * + * @return BasePriority + * + * Return the content of the base priority register + */ +__ASM uint32_t __get_BASEPRI(void) +{ + mrs r0, basepri + bx lr +} + +/** + * @brief Set the Base Priority value + * + * @param basePri BasePriority + * + * Set the base priority register + */ +__ASM void __set_BASEPRI(uint32_t basePri) +{ + msr basepri, r0 + bx lr +} + +/** + * @brief Return the Priority Mask value + * + * @return PriMask + * + * Return state of the priority mask bit from the priority mask register + */ +__ASM uint32_t __get_PRIMASK(void) +{ + mrs r0, primask + bx lr +} + +/** + * @brief Set the Priority Mask value + * + * @param priMask PriMask + * + * Set the priority mask bit in the priority mask register + */ +__ASM void __set_PRIMASK(uint32_t priMask) +{ + msr primask, r0 + bx lr +} + +/** + * @brief Return the Fault Mask value + * + * @return FaultMask + * + * Return the content of the fault mask register + */ +__ASM uint32_t __get_FAULTMASK(void) +{ + mrs r0, faultmask + bx lr +} + +/** + * @brief Set the Fault Mask value + * + * @param faultMask faultMask value + * + * Set the fault mask register + */ +__ASM void __set_FAULTMASK(uint32_t faultMask) +{ + msr faultmask, r0 + bx lr +} + +/** + * @brief Return the Control Register value + * + * @return Control value + * + * Return the content of the control register + */ +__ASM uint32_t __get_CONTROL(void) +{ + mrs r0, control + bx lr +} + +/** + * @brief Set the Control Register value + * + * @param control Control value + * + * Set the control register + */ +__ASM void __set_CONTROL(uint32_t control) +{ + msr control, r0 + bx lr +} + +#endif /* __ARMCC_VERSION */ + + + +#elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ +#pragma diag_suppress=Pe940 + +/** + * @brief Return the Process Stack Pointer + * + * @return ProcessStackPointer + * + * Return the actual process stack pointer + */ +uint32_t __get_PSP(void) +{ + __ASM("mrs r0, psp"); + __ASM("bx lr"); +} + +/** + * @brief Set the Process Stack Pointer + * + * @param topOfProcStack Process Stack Pointer + * + * Assign the value ProcessStackPointer to the MSP + * (process stack pointer) Cortex processor register + */ +void __set_PSP(uint32_t topOfProcStack) +{ + __ASM("msr psp, r0"); + __ASM("bx lr"); +} + +/** + * @brief Return the Main Stack Pointer + * + * @return Main Stack Pointer + * + * Return the current value of the MSP (main stack pointer) + * Cortex processor register + */ +uint32_t __get_MSP(void) +{ + __ASM("mrs r0, msp"); + __ASM("bx lr"); +} + +/** + * @brief Set the Main Stack Pointer + * + * @param topOfMainStack Main Stack Pointer + * + * Assign the value mainStackPointer to the MSP + * (main stack pointer) Cortex processor register + */ +void __set_MSP(uint32_t topOfMainStack) +{ + __ASM("msr msp, r0"); + __ASM("bx lr"); +} + +/** + * @brief Reverse byte order in unsigned short value + * + * @param value value to reverse + * @return reversed value + * + * Reverse byte order in unsigned short value + */ +uint32_t __REV16(uint16_t value) +{ + __ASM("rev16 r0, r0"); + __ASM("bx lr"); +} + +/** + * @brief Reverse bit order of value + * + * @param value value to reverse + * @return reversed value + * + * Reverse bit order of value + */ +uint32_t __RBIT(uint32_t value) +{ + __ASM("rbit r0, r0"); + __ASM("bx lr"); +} + +/** + * @brief LDR Exclusive (8 bit) + * + * @param *addr address pointer + * @return value of (*address) + * + * Exclusive LDR command for 8 bit values) + */ +uint8_t __LDREXB(uint8_t *addr) +{ + __ASM("ldrexb r0, [r0]"); + __ASM("bx lr"); +} + +/** + * @brief LDR Exclusive (16 bit) + * + * @param *addr address pointer + * @return value of (*address) + * + * Exclusive LDR command for 16 bit values + */ +uint16_t __LDREXH(uint16_t *addr) +{ + __ASM("ldrexh r0, [r0]"); + __ASM("bx lr"); +} + +/** + * @brief LDR Exclusive (32 bit) + * + * @param *addr address pointer + * @return value of (*address) + * + * Exclusive LDR command for 32 bit values + */ +uint32_t __LDREXW(uint32_t *addr) +{ + __ASM("ldrex r0, [r0]"); + __ASM("bx lr"); +} + +/** + * @brief STR Exclusive (8 bit) + * + * @param value value to store + * @param *addr address pointer + * @return successful / failed + * + * Exclusive STR command for 8 bit values + */ +uint32_t __STREXB(uint8_t value, uint8_t *addr) +{ + __ASM("strexb r0, r0, [r1]"); + __ASM("bx lr"); +} + +/** + * @brief STR Exclusive (16 bit) + * + * @param value value to store + * @param *addr address pointer + * @return successful / failed + * + * Exclusive STR command for 16 bit values + */ +uint32_t __STREXH(uint16_t value, uint16_t *addr) +{ + __ASM("strexh r0, r0, [r1]"); + __ASM("bx lr"); +} + +/** + * @brief STR Exclusive (32 bit) + * + * @param value value to store + * @param *addr address pointer + * @return successful / failed + * + * Exclusive STR command for 32 bit values + */ +uint32_t __STREXW(uint32_t value, uint32_t *addr) +{ + __ASM("strex r0, r0, [r1]"); + __ASM("bx lr"); +} + +#pragma diag_default=Pe940 + + +#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** + * @brief Return the Process Stack Pointer + * + * @return ProcessStackPointer + * + * Return the actual process stack pointer + */ +uint32_t __get_PSP(void) __attribute__( ( naked ) ); +uint32_t __get_PSP(void) +{ + uint32_t result=0; + + __ASM volatile ("MRS %0, psp\n\t" + "MOV r0, %0 \n\t" + "BX lr \n\t" : "=r" (result) ); + return(result); +} + +/** + * @brief Set the Process Stack Pointer + * + * @param topOfProcStack Process Stack Pointer + * + * Assign the value ProcessStackPointer to the MSP + * (process stack pointer) Cortex processor register + */ +void __set_PSP(uint32_t topOfProcStack) __attribute__( ( naked ) ); +void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n\t" + "BX lr \n\t" : : "r" (topOfProcStack) ); +} + +/** + * @brief Return the Main Stack Pointer + * + * @return Main Stack Pointer + * + * Return the current value of the MSP (main stack pointer) + * Cortex processor register + */ +uint32_t __get_MSP(void) __attribute__( ( naked ) ); +uint32_t __get_MSP(void) +{ + uint32_t result=0; + + __ASM volatile ("MRS %0, msp\n\t" + "MOV r0, %0 \n\t" + "BX lr \n\t" : "=r" (result) ); + return(result); +} + +/** + * @brief Set the Main Stack Pointer + * + * @param topOfMainStack Main Stack Pointer + * + * Assign the value mainStackPointer to the MSP + * (main stack pointer) Cortex processor register + */ +void __set_MSP(uint32_t topOfMainStack) __attribute__( ( naked ) ); +void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n\t" + "BX lr \n\t" : : "r" (topOfMainStack) ); +} + +/** + * @brief Return the Base Priority value + * + * @return BasePriority + * + * Return the content of the base priority register + */ +uint32_t __get_BASEPRI(void) +{ + uint32_t result=0; + + __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); + return(result); +} + +/** + * @brief Set the Base Priority value + * + * @param basePri BasePriority + * + * Set the base priority register + */ +void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) ); +} + +/** + * @brief Return the Priority Mask value + * + * @return PriMask + * + * Return state of the priority mask bit from the priority mask register + */ +uint32_t __get_PRIMASK(void) +{ + uint32_t result=0; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + +/** + * @brief Set the Priority Mask value + * + * @param priMask PriMask + * + * Set the priority mask bit in the priority mask register + */ +void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) ); +} + +/** + * @brief Return the Fault Mask value + * + * @return FaultMask + * + * Return the content of the fault mask register + */ +uint32_t __get_FAULTMASK(void) +{ + uint32_t result=0; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + +/** + * @brief Set the Fault Mask value + * + * @param faultMask faultMask value + * + * Set the fault mask register + */ +void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) ); +} + +/** + * @brief Return the Control Register value +* +* @return Control value + * + * Return the content of the control register + */ +uint32_t __get_CONTROL(void) +{ + uint32_t result=0; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + +/** + * @brief Set the Control Register value + * + * @param control Control value + * + * Set the control register + */ +void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) ); +} + + +/** + * @brief Reverse byte order in integer value + * + * @param value value to reverse + * @return reversed value + * + * Reverse byte order in integer value + */ +uint32_t __REV(uint32_t value) +{ + uint32_t result=0; + + __ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + +/** + * @brief Reverse byte order in unsigned short value + * + * @param value value to reverse + * @return reversed value + * + * Reverse byte order in unsigned short value + */ +uint32_t __REV16(uint16_t value) +{ + uint32_t result=0; + + __ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + +/** + * @brief Reverse byte order in signed short value with sign extension to integer + * + * @param value value to reverse + * @return reversed value + * + * Reverse byte order in signed short value with sign extension to integer + */ +int32_t __REVSH(int16_t value) +{ + uint32_t result=0; + + __ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + +/** + * @brief Reverse bit order of value + * + * @param value value to reverse + * @return reversed value + * + * Reverse bit order of value + */ +uint32_t __RBIT(uint32_t value) +{ + uint32_t result=0; + + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + +/** + * @brief LDR Exclusive (8 bit) + * + * @param *addr address pointer + * @return value of (*address) + * + * Exclusive LDR command for 8 bit value + */ +uint8_t __LDREXB(uint8_t *addr) +{ + uint8_t result=0; + + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + +/** + * @brief LDR Exclusive (16 bit) + * + * @param *addr address pointer + * @return value of (*address) + * + * Exclusive LDR command for 16 bit values + */ +uint16_t __LDREXH(uint16_t *addr) +{ + uint16_t result=0; + + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + +/** + * @brief LDR Exclusive (32 bit) + * + * @param *addr address pointer + * @return value of (*address) + * + * Exclusive LDR command for 32 bit values + */ +uint32_t __LDREXW(uint32_t *addr) +{ + uint32_t result=0; + + __ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + +/** + * @brief STR Exclusive (8 bit) + * + * @param value value to store + * @param *addr address pointer + * @return successful / failed + * + * Exclusive STR command for 8 bit values + */ +uint32_t __STREXB(uint8_t value, uint8_t *addr) +{ + uint32_t result=0; + + __ASM volatile ("strexb %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) ); + return(result); +} + +/** + * @brief STR Exclusive (16 bit) + * + * @param value value to store + * @param *addr address pointer + * @return successful / failed + * + * Exclusive STR command for 16 bit values + */ +uint32_t __STREXH(uint16_t value, uint16_t *addr) +{ + uint32_t result=0; + + __ASM volatile ("strexh %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) ); + return(result); +} + +/** + * @brief STR Exclusive (32 bit) + * + * @param value value to store + * @param *addr address pointer + * @return successful / failed + * + * Exclusive STR command for 32 bit values + */ +uint32_t __STREXW(uint32_t value, uint32_t *addr) +{ + uint32_t result=0; + + __ASM volatile ("strex %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +#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 diff --git a/Start/core_cm3.h b/Start/core_cm3.h new file mode 100644 index 0000000..7ab7b4b --- /dev/null +++ b/Start/core_cm3.h @@ -0,0 +1,1818 @@ +/**************************************************************************//** + * @file core_cm3.h + * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File + * @version V1.30 + * @date 30. October 2009 + * + * @note + * Copyright (C) 2009 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#ifndef __CM3_CORE_H__ +#define __CM3_CORE_H__ + +/** @addtogroup CMSIS_CM3_core_LintCinfiguration CMSIS CM3 Core Lint Configuration + * + * List of Lint messages which will be suppressed and not shown: + * - Error 10: \n + * register uint32_t __regBasePri __asm("basepri"); \n + * Error 10: Expecting ';' + * . + * - Error 530: \n + * return(__regBasePri); \n + * Warning 530: Symbol '__regBasePri' (line 264) not initialized + * . + * - Error 550: \n + * __regBasePri = (basePri & 0x1ff); \n + * Warning 550: Symbol '__regBasePri' (line 271) not accessed + * . + * - Error 754: \n + * uint32_t RESERVED0[24]; \n + * Info 754: local structure member '' (line 109, file ./cm3_core.h) not referenced + * . + * - Error 750: \n + * #define __CM3_CORE_H__ \n + * Info 750: local macro '__CM3_CORE_H__' (line 43, file./cm3_core.h) not referenced + * . + * - Error 528: \n + * static __INLINE void NVIC_DisableIRQ(uint32_t IRQn) \n + * Warning 528: Symbol 'NVIC_DisableIRQ(unsigned int)' (line 419, file ./cm3_core.h) not referenced + * . + * - Error 751: \n + * } InterruptType_Type; \n + * Info 751: local typedef 'InterruptType_Type' (line 170, file ./cm3_core.h) not referenced + * . + * Note: To re-enable a Message, insert a space before 'lint' * + * + */ + +/*lint -save */ +/*lint -e10 */ +/*lint -e530 */ +/*lint -e550 */ +/*lint -e754 */ +/*lint -e750 */ +/*lint -e528 */ +/*lint -e751 */ + + +/** @addtogroup CMSIS_CM3_core_definitions CM3 Core Definitions + This file defines all structures and symbols for CMSIS core: + - CMSIS version number + - Cortex-M core registers and bitfields + - Cortex-M core peripheral base address + @{ + */ + +#ifdef __cplusplus + extern "C" { +#endif + +#define __CM3_CMSIS_VERSION_MAIN (0x01) /*!< [31:16] CMSIS HAL main version */ +#define __CM3_CMSIS_VERSION_SUB (0x30) /*!< [15:0] CMSIS HAL sub version */ +#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16) | __CM3_CMSIS_VERSION_SUB) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x03) /*!< Cortex core */ + +#include /* Include standard types */ + +#if defined (__ICCARM__) + #include /* IAR Intrinsics */ +#endif + + +#ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4 /*!< standard definition for NVIC Priority Bits */ +#endif + + + + +/** + * IO definitions + * + * define access restrictions to peripheral registers + */ + +#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 */ + + + +/******************************************************************************* + * Register Abstraction + ******************************************************************************/ +/** @addtogroup CMSIS_CM3_core_register CMSIS CM3 Core Register + @{ +*/ + + +/** @addtogroup CMSIS_CM3_NVIC CMSIS CM3 NVIC + memory mapped structure for Nested Vectored Interrupt Controller (NVIC) + @{ + */ +typedef struct +{ + __IO uint32_t ISER[8]; /*!< Offset: 0x000 Interrupt Set Enable Register */ + uint32_t RESERVED0[24]; + __IO uint32_t ICER[8]; /*!< Offset: 0x080 Interrupt Clear Enable Register */ + uint32_t RSERVED1[24]; + __IO uint32_t ISPR[8]; /*!< Offset: 0x100 Interrupt Set Pending Register */ + uint32_t RESERVED2[24]; + __IO uint32_t ICPR[8]; /*!< Offset: 0x180 Interrupt Clear Pending Register */ + uint32_t RESERVED3[24]; + __IO uint32_t IABR[8]; /*!< Offset: 0x200 Interrupt Active bit Register */ + uint32_t RESERVED4[56]; + __IO uint8_t IP[240]; /*!< Offset: 0x300 Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644]; + __O uint32_t STIR; /*!< Offset: 0xE00 Software Trigger Interrupt Register */ +} NVIC_Type; +/*@}*/ /* end of group CMSIS_CM3_NVIC */ + + +/** @addtogroup CMSIS_CM3_SCB CMSIS CM3 SCB + memory mapped structure for System Control Block (SCB) + @{ + */ +typedef struct +{ + __I uint32_t CPUID; /*!< Offset: 0x00 CPU ID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x04 Interrupt Control State Register */ + __IO uint32_t VTOR; /*!< Offset: 0x08 Vector Table Offset Register */ + __IO uint32_t AIRCR; /*!< Offset: 0x0C Application Interrupt / Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x10 System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x14 Configuration Control Register */ + __IO uint8_t SHP[12]; /*!< Offset: 0x18 System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IO uint32_t SHCSR; /*!< Offset: 0x24 System Handler Control and State Register */ + __IO uint32_t CFSR; /*!< Offset: 0x28 Configurable Fault Status Register */ + __IO uint32_t HFSR; /*!< Offset: 0x2C Hard Fault Status Register */ + __IO uint32_t DFSR; /*!< Offset: 0x30 Debug Fault Status Register */ + __IO uint32_t MMFAR; /*!< Offset: 0x34 Mem Manage Address Register */ + __IO uint32_t BFAR; /*!< Offset: 0x38 Bus Fault Address Register */ + __IO uint32_t AFSR; /*!< Offset: 0x3C Auxiliary Fault Status Register */ + __I uint32_t PFR[2]; /*!< Offset: 0x40 Processor Feature Register */ + __I uint32_t DFR; /*!< Offset: 0x48 Debug Feature Register */ + __I uint32_t ADR; /*!< Offset: 0x4C Auxiliary Feature Register */ + __I uint32_t MMFR[4]; /*!< Offset: 0x50 Memory Model Feature Register */ + __I uint32_t ISAR[5]; /*!< Offset: 0x60 ISA Feature 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_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_RETTOBASE_Pos 11 /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1ul << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE 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 Interrupt Control State Register Definitions */ +#define SCB_VTOR_TBLBASE_Pos 29 /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (0x1FFul << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFul << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 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_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7ul << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP 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 */ + +#define SCB_AIRCR_VECTRESET_Pos 0 /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1ul << SCB_AIRCR_VECTRESET_Pos) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 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_BFHFNMIGN_Pos 8 /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1ul << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4 /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1ul << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1ul << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1 /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1ul << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0 /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1ul << SCB_CCR_NONBASETHRDENA_Pos) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18 /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1ul << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17 /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1ul << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16 /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1ul << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1ul << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14 /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1ul << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13 /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1ul << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12 /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1ul << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11 /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1ul << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10 /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1ul << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8 /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1ul << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7 /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1ul << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3 /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1ul << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1 /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1ul << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0 /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1ul << SCB_SHCSR_MEMFAULTACT_Pos) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Registers Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16 /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFul << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8 /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFul << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0 /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFul << SCB_CFSR_MEMFAULTSR_Pos) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Registers Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31 /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1ul << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30 /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1ul << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1 /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1ul << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4 /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1ul << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3 /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1ul << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2 /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1ul << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1 /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1ul << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0 /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1ul << SCB_DFSR_HALTED_Pos) /*!< SCB DFSR: HALTED Mask */ +/*@}*/ /* end of group CMSIS_CM3_SCB */ + + +/** @addtogroup CMSIS_CM3_SysTick CMSIS CM3 SysTick + memory mapped structure for SysTick + @{ + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x00 SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< Offset: 0x04 SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< Offset: 0x08 SysTick Current Value Register */ + __I uint32_t CALIB; /*!< Offset: 0x0C 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_CM3_SysTick */ + + +/** @addtogroup CMSIS_CM3_ITM CMSIS CM3 ITM + memory mapped structure for Instrumentation Trace Macrocell (ITM) + @{ + */ +typedef struct +{ + __O union + { + __O uint8_t u8; /*!< Offset: ITM Stimulus Port 8-bit */ + __O uint16_t u16; /*!< Offset: ITM Stimulus Port 16-bit */ + __O uint32_t u32; /*!< Offset: ITM Stimulus Port 32-bit */ + } PORT [32]; /*!< Offset: 0x00 ITM Stimulus Port Registers */ + uint32_t RESERVED0[864]; + __IO uint32_t TER; /*!< Offset: ITM Trace Enable Register */ + uint32_t RESERVED1[15]; + __IO uint32_t TPR; /*!< Offset: ITM Trace Privilege Register */ + uint32_t RESERVED2[15]; + __IO uint32_t TCR; /*!< Offset: ITM Trace Control Register */ + uint32_t RESERVED3[29]; + __IO uint32_t IWR; /*!< Offset: ITM Integration Write Register */ + __IO uint32_t IRR; /*!< Offset: ITM Integration Read Register */ + __IO uint32_t IMCR; /*!< Offset: ITM Integration Mode Control Register */ + uint32_t RESERVED4[43]; + __IO uint32_t LAR; /*!< Offset: ITM Lock Access Register */ + __IO uint32_t LSR; /*!< Offset: ITM Lock Status Register */ + uint32_t RESERVED5[6]; + __I uint32_t PID4; /*!< Offset: ITM Peripheral Identification Register #4 */ + __I uint32_t PID5; /*!< Offset: ITM Peripheral Identification Register #5 */ + __I uint32_t PID6; /*!< Offset: ITM Peripheral Identification Register #6 */ + __I uint32_t PID7; /*!< Offset: ITM Peripheral Identification Register #7 */ + __I uint32_t PID0; /*!< Offset: ITM Peripheral Identification Register #0 */ + __I uint32_t PID1; /*!< Offset: ITM Peripheral Identification Register #1 */ + __I uint32_t PID2; /*!< Offset: ITM Peripheral Identification Register #2 */ + __I uint32_t PID3; /*!< Offset: ITM Peripheral Identification Register #3 */ + __I uint32_t CID0; /*!< Offset: ITM Component Identification Register #0 */ + __I uint32_t CID1; /*!< Offset: ITM Component Identification Register #1 */ + __I uint32_t CID2; /*!< Offset: ITM Component Identification Register #2 */ + __I uint32_t CID3; /*!< Offset: ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0 /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFul << ITM_TPR_PRIVMASK_Pos) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23 /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1ul << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_ATBID_Pos 16 /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_ATBID_Msk (0x7Ful << ITM_TCR_ATBID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_TSPrescale_Pos 8 /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3ul << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4 /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1ul << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3 /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1ul << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2 /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1ul << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1 /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1ul << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0 /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1ul << ITM_TCR_ITMENA_Pos) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0 /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1ul << ITM_IWR_ATVALIDM_Pos) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0 /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1ul << ITM_IRR_ATREADYM_Pos) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0 /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1ul << ITM_IMCR_INTEGRATION_Pos) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2 /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1ul << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1 /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1ul << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0 /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1ul << ITM_LSR_Present_Pos) /*!< ITM LSR: Present Mask */ +/*@}*/ /* end of group CMSIS_CM3_ITM */ + + +/** @addtogroup CMSIS_CM3_InterruptType CMSIS CM3 Interrupt Type + memory mapped structure for Interrupt Type + @{ + */ +typedef struct +{ + uint32_t RESERVED0; + __I uint32_t ICTR; /*!< Offset: 0x04 Interrupt Control Type Register */ +#if ((defined __CM3_REV) && (__CM3_REV >= 0x200)) + __IO uint32_t ACTLR; /*!< Offset: 0x08 Auxiliary Control Register */ +#else + uint32_t RESERVED1; +#endif +} InterruptType_Type; + +/* Interrupt Controller Type Register Definitions */ +#define InterruptType_ICTR_INTLINESNUM_Pos 0 /*!< InterruptType ICTR: INTLINESNUM Position */ +#define InterruptType_ICTR_INTLINESNUM_Msk (0x1Ful << InterruptType_ICTR_INTLINESNUM_Pos) /*!< InterruptType ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define InterruptType_ACTLR_DISFOLD_Pos 2 /*!< InterruptType ACTLR: DISFOLD Position */ +#define InterruptType_ACTLR_DISFOLD_Msk (1ul << InterruptType_ACTLR_DISFOLD_Pos) /*!< InterruptType ACTLR: DISFOLD Mask */ + +#define InterruptType_ACTLR_DISDEFWBUF_Pos 1 /*!< InterruptType ACTLR: DISDEFWBUF Position */ +#define InterruptType_ACTLR_DISDEFWBUF_Msk (1ul << InterruptType_ACTLR_DISDEFWBUF_Pos) /*!< InterruptType ACTLR: DISDEFWBUF Mask */ + +#define InterruptType_ACTLR_DISMCYCINT_Pos 0 /*!< InterruptType ACTLR: DISMCYCINT Position */ +#define InterruptType_ACTLR_DISMCYCINT_Msk (1ul << InterruptType_ACTLR_DISMCYCINT_Pos) /*!< InterruptType ACTLR: DISMCYCINT Mask */ +/*@}*/ /* end of group CMSIS_CM3_InterruptType */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1) +/** @addtogroup CMSIS_CM3_MPU CMSIS CM3 MPU + memory mapped structure for Memory Protection Unit (MPU) + @{ + */ +typedef struct +{ + __I uint32_t TYPE; /*!< Offset: 0x00 MPU Type Register */ + __IO uint32_t CTRL; /*!< Offset: 0x04 MPU Control Register */ + __IO uint32_t RNR; /*!< Offset: 0x08 MPU Region RNRber Register */ + __IO uint32_t RBAR; /*!< Offset: 0x0C MPU Region Base Address Register */ + __IO uint32_t RASR; /*!< Offset: 0x10 MPU Region Attribute and Size Register */ + __IO uint32_t RBAR_A1; /*!< Offset: 0x14 MPU Alias 1 Region Base Address Register */ + __IO uint32_t RASR_A1; /*!< Offset: 0x18 MPU Alias 1 Region Attribute and Size Register */ + __IO uint32_t RBAR_A2; /*!< Offset: 0x1C MPU Alias 2 Region Base Address Register */ + __IO uint32_t RASR_A2; /*!< Offset: 0x20 MPU Alias 2 Region Attribute and Size Register */ + __IO uint32_t RBAR_A3; /*!< Offset: 0x24 MPU Alias 3 Region Base Address Register */ + __IO uint32_t RASR_A3; /*!< Offset: 0x28 MPU Alias 3 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 5 /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFul << 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_XN_Pos 28 /*!< MPU RASR: XN Position */ +#define MPU_RASR_XN_Msk (1ul << MPU_RASR_XN_Pos) /*!< MPU RASR: XN Mask */ + +#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: AP Position */ +#define MPU_RASR_AP_Msk (7ul << MPU_RASR_AP_Pos) /*!< MPU RASR: AP Mask */ + +#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: TEX Position */ +#define MPU_RASR_TEX_Msk (7ul << MPU_RASR_TEX_Pos) /*!< MPU RASR: TEX Mask */ + +#define MPU_RASR_S_Pos 18 /*!< MPU RASR: Shareable bit Position */ +#define MPU_RASR_S_Msk (1ul << MPU_RASR_S_Pos) /*!< MPU RASR: Shareable bit Mask */ + +#define MPU_RASR_C_Pos 17 /*!< MPU RASR: Cacheable bit Position */ +#define MPU_RASR_C_Msk (1ul << MPU_RASR_C_Pos) /*!< MPU RASR: Cacheable bit Mask */ + +#define MPU_RASR_B_Pos 16 /*!< MPU RASR: Bufferable bit Position */ +#define MPU_RASR_B_Msk (1ul << MPU_RASR_B_Pos) /*!< MPU RASR: Bufferable bit 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_ENA_Pos 0 /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENA_Msk (0x1Ful << MPU_RASR_ENA_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@}*/ /* end of group CMSIS_CM3_MPU */ +#endif + + +/** @addtogroup CMSIS_CM3_CoreDebug CMSIS CM3 Core Debug + memory mapped structure for Core Debug Register + @{ + */ +typedef struct +{ + __IO uint32_t DHCSR; /*!< Offset: 0x00 Debug Halting Control and Status Register */ + __O uint32_t DCRSR; /*!< Offset: 0x04 Debug Core Register Selector Register */ + __IO uint32_t DCRDR; /*!< Offset: 0x08 Debug Core Register Data Register */ + __IO uint32_t DEMCR; /*!< Offset: 0x0C Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16 /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFul << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25 /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1ul << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24 /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1ul << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19 /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1ul << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18 /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1ul << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17 /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1ul << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16 /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1ul << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5 /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1ul << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3 /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1ul << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2 /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1ul << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1 /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1ul << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0 /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1ul << CoreDebug_DHCSR_C_DEBUGEN_Pos) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register */ +#define CoreDebug_DCRSR_REGWnR_Pos 16 /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1ul << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0 /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1Ful << CoreDebug_DCRSR_REGSEL_Pos) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register */ +#define CoreDebug_DEMCR_TRCENA_Pos 24 /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1ul << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19 /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1ul << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18 /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1ul << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17 /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1ul << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16 /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1ul << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10 /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1ul << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9 /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1ul << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8 /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1ul << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7 /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1ul << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6 /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1ul << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5 /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1ul << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4 /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1ul << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0 /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1ul << CoreDebug_DEMCR_VC_CORERESET_Pos) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ +/*@}*/ /* end of group CMSIS_CM3_CoreDebug */ + + +/* Memory mapping of Cortex-M3 Hardware */ +#define SCS_BASE (0xE000E000) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000) /*!< ITM Base Address */ +#define CoreDebug_BASE (0xE000EDF0) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00) /*!< System Control Block Base Address */ + +#define InterruptType ((InterruptType_Type *) SCS_BASE) /*!< Interrupt Type Register */ +#define SCB ((SCB_Type *) SCB_BASE) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE) /*!< ITM configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1) + #define MPU_BASE (SCS_BASE + 0x0D90) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type*) MPU_BASE) /*!< Memory Protection Unit */ +#endif + +/*@}*/ /* end of group CMSIS_CM3_core_register */ + + +/******************************************************************************* + * Hardware Abstraction Layer + ******************************************************************************/ + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */ + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + +#endif + + +/* ################### Compiler specific Intrinsics ########################### */ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#define __enable_fault_irq __enable_fiq +#define __disable_fault_irq __disable_fiq + +#define __NOP __nop +#define __WFI __wfi +#define __WFE __wfe +#define __SEV __sev +#define __ISB() __isb(0) +#define __DSB() __dsb(0) +#define __DMB() __dmb(0) +#define __REV __rev +#define __RBIT __rbit +#define __LDREXB(ptr) ((unsigned char ) __ldrex(ptr)) +#define __LDREXH(ptr) ((unsigned short) __ldrex(ptr)) +#define __LDREXW(ptr) ((unsigned int ) __ldrex(ptr)) +#define __STREXB(value, ptr) __strex(value, ptr) +#define __STREXH(value, ptr) __strex(value, ptr) +#define __STREXW(value, ptr) __strex(value, ptr) + + +/* intrinsic unsigned long long __ldrexd(volatile void *ptr) */ +/* intrinsic int __strexd(unsigned long long val, volatile void *ptr) */ +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + + +/** + * @brief Return the Process Stack Pointer + * + * @return ProcessStackPointer + * + * Return the actual process stack pointer + */ +extern uint32_t __get_PSP(void); + +/** + * @brief Set the Process Stack Pointer + * + * @param topOfProcStack Process Stack Pointer + * + * Assign the value ProcessStackPointer to the MSP + * (process stack pointer) Cortex processor register + */ +extern void __set_PSP(uint32_t topOfProcStack); + +/** + * @brief Return the Main Stack Pointer + * + * @return Main Stack Pointer + * + * Return the current value of the MSP (main stack pointer) + * Cortex processor register + */ +extern uint32_t __get_MSP(void); + +/** + * @brief Set the Main Stack Pointer + * + * @param topOfMainStack Main Stack Pointer + * + * Assign the value mainStackPointer to the MSP + * (main stack pointer) Cortex processor register + */ +extern void __set_MSP(uint32_t topOfMainStack); + +/** + * @brief Reverse byte order in unsigned short value + * + * @param value value to reverse + * @return reversed value + * + * Reverse byte order in unsigned short value + */ +extern uint32_t __REV16(uint16_t value); + +/** + * @brief Reverse byte order in signed short value with sign extension to integer + * + * @param value value to reverse + * @return reversed value + * + * Reverse byte order in signed short value with sign extension to integer + */ +extern int32_t __REVSH(int16_t value); + + +#if (__ARMCC_VERSION < 400000) + +/** + * @brief Remove the exclusive lock created by ldrex + * + * Removes the exclusive lock which is created by ldrex. + */ +extern void __CLREX(void); + +/** + * @brief Return the Base Priority value + * + * @return BasePriority + * + * Return the content of the base priority register + */ +extern uint32_t __get_BASEPRI(void); + +/** + * @brief Set the Base Priority value + * + * @param basePri BasePriority + * + * Set the base priority register + */ +extern void __set_BASEPRI(uint32_t basePri); + +/** + * @brief Return the Priority Mask value + * + * @return PriMask + * + * Return state of the priority mask bit from the priority mask register + */ +extern uint32_t __get_PRIMASK(void); + +/** + * @brief Set the Priority Mask value + * + * @param priMask PriMask + * + * Set the priority mask bit in the priority mask register + */ +extern void __set_PRIMASK(uint32_t priMask); + +/** + * @brief Return the Fault Mask value + * + * @return FaultMask + * + * Return the content of the fault mask register + */ +extern uint32_t __get_FAULTMASK(void); + +/** + * @brief Set the Fault Mask value + * + * @param faultMask faultMask value + * + * Set the fault mask register + */ +extern void __set_FAULTMASK(uint32_t faultMask); + +/** + * @brief Return the Control Register value + * + * @return Control value + * + * Return the content of the control register + */ +extern uint32_t __get_CONTROL(void); + +/** + * @brief Set the Control Register value + * + * @param control Control value + * + * Set the control register + */ +extern void __set_CONTROL(uint32_t control); + +#else /* (__ARMCC_VERSION >= 400000) */ + +/** + * @brief Remove the exclusive lock created by ldrex + * + * Removes the exclusive lock which is created by ldrex. + */ +#define __CLREX __clrex + +/** + * @brief Return the Base Priority value + * + * @return BasePriority + * + * Return the content of the base priority register + */ +static __INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + +/** + * @brief Set the Base Priority value + * + * @param basePri BasePriority + * + * Set the base priority register + */ +static __INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xff); +} + +/** + * @brief Return the Priority Mask value + * + * @return PriMask + * + * Return state of the priority mask bit from the priority mask register + */ +static __INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + +/** + * @brief Set the Priority Mask value + * + * @param priMask PriMask + * + * Set the priority mask bit in the priority mask register + */ +static __INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + +/** + * @brief Return the Fault Mask value + * + * @return FaultMask + * + * Return the content of the fault mask register + */ +static __INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + +/** + * @brief Set the Fault Mask value + * + * @param faultMask faultMask value + * + * Set the fault mask register + */ +static __INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & 1); +} + +/** + * @brief Return the Control Register value + * + * @return Control value + * + * Return the content of the control register + */ +static __INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + +/** + * @brief Set the Control Register value + * + * @param control Control value + * + * Set the control register + */ +static __INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + +#endif /* __ARMCC_VERSION */ + + + +#elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#define __enable_irq __enable_interrupt /*!< global Interrupt enable */ +#define __disable_irq __disable_interrupt /*!< global Interrupt disable */ + +static __INLINE void __enable_fault_irq() { __ASM ("cpsie f"); } +static __INLINE void __disable_fault_irq() { __ASM ("cpsid f"); } + +#define __NOP __no_operation /*!< no operation intrinsic in IAR Compiler */ +static __INLINE void __WFI() { __ASM ("wfi"); } +static __INLINE void __WFE() { __ASM ("wfe"); } +static __INLINE void __SEV() { __ASM ("sev"); } +static __INLINE void __CLREX() { __ASM ("clrex"); } + +/* intrinsic void __ISB(void) */ +/* intrinsic void __DSB(void) */ +/* intrinsic void __DMB(void) */ +/* intrinsic void __set_PRIMASK(); */ +/* intrinsic void __get_PRIMASK(); */ +/* intrinsic void __set_FAULTMASK(); */ +/* intrinsic void __get_FAULTMASK(); */ +/* intrinsic uint32_t __REV(uint32_t value); */ +/* intrinsic uint32_t __REVSH(uint32_t value); */ +/* intrinsic unsigned long __STREX(unsigned long, unsigned long); */ +/* intrinsic unsigned long __LDREX(unsigned long *); */ + + +/** + * @brief Return the Process Stack Pointer + * + * @return ProcessStackPointer + * + * Return the actual process stack pointer + */ +extern uint32_t __get_PSP(void); + +/** + * @brief Set the Process Stack Pointer + * + * @param topOfProcStack Process Stack Pointer + * + * Assign the value ProcessStackPointer to the MSP + * (process stack pointer) Cortex processor register + */ +extern void __set_PSP(uint32_t topOfProcStack); + +/** + * @brief Return the Main Stack Pointer + * + * @return Main Stack Pointer + * + * Return the current value of the MSP (main stack pointer) + * Cortex processor register + */ +extern uint32_t __get_MSP(void); + +/** + * @brief Set the Main Stack Pointer + * + * @param topOfMainStack Main Stack Pointer + * + * Assign the value mainStackPointer to the MSP + * (main stack pointer) Cortex processor register + */ +extern void __set_MSP(uint32_t topOfMainStack); + +/** + * @brief Reverse byte order in unsigned short value + * + * @param value value to reverse + * @return reversed value + * + * Reverse byte order in unsigned short value + */ +extern uint32_t __REV16(uint16_t value); + +/** + * @brief Reverse bit order of value + * + * @param value value to reverse + * @return reversed value + * + * Reverse bit order of value + */ +extern uint32_t __RBIT(uint32_t value); + +/** + * @brief LDR Exclusive (8 bit) + * + * @param *addr address pointer + * @return value of (*address) + * + * Exclusive LDR command for 8 bit values) + */ +extern uint8_t __LDREXB(uint8_t *addr); + +/** + * @brief LDR Exclusive (16 bit) + * + * @param *addr address pointer + * @return value of (*address) + * + * Exclusive LDR command for 16 bit values + */ +extern uint16_t __LDREXH(uint16_t *addr); + +/** + * @brief LDR Exclusive (32 bit) + * + * @param *addr address pointer + * @return value of (*address) + * + * Exclusive LDR command for 32 bit values + */ +extern uint32_t __LDREXW(uint32_t *addr); + +/** + * @brief STR Exclusive (8 bit) + * + * @param value value to store + * @param *addr address pointer + * @return successful / failed + * + * Exclusive STR command for 8 bit values + */ +extern uint32_t __STREXB(uint8_t value, uint8_t *addr); + +/** + * @brief STR Exclusive (16 bit) + * + * @param value value to store + * @param *addr address pointer + * @return successful / failed + * + * Exclusive STR command for 16 bit values + */ +extern uint32_t __STREXH(uint16_t value, uint16_t *addr); + +/** + * @brief STR Exclusive (32 bit) + * + * @param value value to store + * @param *addr address pointer + * @return successful / failed + * + * Exclusive STR command for 32 bit values + */ +extern uint32_t __STREXW(uint32_t value, uint32_t *addr); + + + +#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +static __INLINE void __enable_irq() { __ASM volatile ("cpsie i"); } +static __INLINE void __disable_irq() { __ASM volatile ("cpsid i"); } + +static __INLINE void __enable_fault_irq() { __ASM volatile ("cpsie f"); } +static __INLINE void __disable_fault_irq() { __ASM volatile ("cpsid f"); } + +static __INLINE void __NOP() { __ASM volatile ("nop"); } +static __INLINE void __WFI() { __ASM volatile ("wfi"); } +static __INLINE void __WFE() { __ASM volatile ("wfe"); } +static __INLINE void __SEV() { __ASM volatile ("sev"); } +static __INLINE void __ISB() { __ASM volatile ("isb"); } +static __INLINE void __DSB() { __ASM volatile ("dsb"); } +static __INLINE void __DMB() { __ASM volatile ("dmb"); } +static __INLINE void __CLREX() { __ASM volatile ("clrex"); } + + +/** + * @brief Return the Process Stack Pointer + * + * @return ProcessStackPointer + * + * Return the actual process stack pointer + */ +extern uint32_t __get_PSP(void); + +/** + * @brief Set the Process Stack Pointer + * + * @param topOfProcStack Process Stack Pointer + * + * Assign the value ProcessStackPointer to the MSP + * (process stack pointer) Cortex processor register + */ +extern void __set_PSP(uint32_t topOfProcStack); + +/** + * @brief Return the Main Stack Pointer + * + * @return Main Stack Pointer + * + * Return the current value of the MSP (main stack pointer) + * Cortex processor register + */ +extern uint32_t __get_MSP(void); + +/** + * @brief Set the Main Stack Pointer + * + * @param topOfMainStack Main Stack Pointer + * + * Assign the value mainStackPointer to the MSP + * (main stack pointer) Cortex processor register + */ +extern void __set_MSP(uint32_t topOfMainStack); + +/** + * @brief Return the Base Priority value + * + * @return BasePriority + * + * Return the content of the base priority register + */ +extern uint32_t __get_BASEPRI(void); + +/** + * @brief Set the Base Priority value + * + * @param basePri BasePriority + * + * Set the base priority register + */ +extern void __set_BASEPRI(uint32_t basePri); + +/** + * @brief Return the Priority Mask value + * + * @return PriMask + * + * Return state of the priority mask bit from the priority mask register + */ +extern uint32_t __get_PRIMASK(void); + +/** + * @brief Set the Priority Mask value + * + * @param priMask PriMask + * + * Set the priority mask bit in the priority mask register + */ +extern void __set_PRIMASK(uint32_t priMask); + +/** + * @brief Return the Fault Mask value + * + * @return FaultMask + * + * Return the content of the fault mask register + */ +extern uint32_t __get_FAULTMASK(void); + +/** + * @brief Set the Fault Mask value + * + * @param faultMask faultMask value + * + * Set the fault mask register + */ +extern void __set_FAULTMASK(uint32_t faultMask); + +/** + * @brief Return the Control Register value +* +* @return Control value + * + * Return the content of the control register + */ +extern uint32_t __get_CONTROL(void); + +/** + * @brief Set the Control Register value + * + * @param control Control value + * + * Set the control register + */ +extern void __set_CONTROL(uint32_t control); + +/** + * @brief Reverse byte order in integer value + * + * @param value value to reverse + * @return reversed value + * + * Reverse byte order in integer value + */ +extern uint32_t __REV(uint32_t value); + +/** + * @brief Reverse byte order in unsigned short value + * + * @param value value to reverse + * @return reversed value + * + * Reverse byte order in unsigned short value + */ +extern uint32_t __REV16(uint16_t value); + +/** + * @brief Reverse byte order in signed short value with sign extension to integer + * + * @param value value to reverse + * @return reversed value + * + * Reverse byte order in signed short value with sign extension to integer + */ +extern int32_t __REVSH(int16_t value); + +/** + * @brief Reverse bit order of value + * + * @param value value to reverse + * @return reversed value + * + * Reverse bit order of value + */ +extern uint32_t __RBIT(uint32_t value); + +/** + * @brief LDR Exclusive (8 bit) + * + * @param *addr address pointer + * @return value of (*address) + * + * Exclusive LDR command for 8 bit value + */ +extern uint8_t __LDREXB(uint8_t *addr); + +/** + * @brief LDR Exclusive (16 bit) + * + * @param *addr address pointer + * @return value of (*address) + * + * Exclusive LDR command for 16 bit values + */ +extern uint16_t __LDREXH(uint16_t *addr); + +/** + * @brief LDR Exclusive (32 bit) + * + * @param *addr address pointer + * @return value of (*address) + * + * Exclusive LDR command for 32 bit values + */ +extern uint32_t __LDREXW(uint32_t *addr); + +/** + * @brief STR Exclusive (8 bit) + * + * @param value value to store + * @param *addr address pointer + * @return successful / failed + * + * Exclusive STR command for 8 bit values + */ +extern uint32_t __STREXB(uint8_t value, uint8_t *addr); + +/** + * @brief STR Exclusive (16 bit) + * + * @param value value to store + * @param *addr address pointer + * @return successful / failed + * + * Exclusive STR command for 16 bit values + */ +extern uint32_t __STREXH(uint16_t value, uint16_t *addr); + +/** + * @brief STR Exclusive (32 bit) + * + * @param value value to store + * @param *addr address pointer + * @return successful / failed + * + * Exclusive STR command for 32 bit values + */ +extern uint32_t __STREXW(uint32_t value, uint32_t *addr); + + +#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 + + +/** @addtogroup CMSIS_CM3_Core_FunctionInterface CMSIS CM3 Core Function Interface + Core Function Interface containing: + - Core NVIC Functions + - Core SysTick Functions + - Core Reset Functions +*/ +/*@{*/ + +/* ########################## NVIC functions #################################### */ + +/** + * @brief Set the Priority Grouping in NVIC Interrupt Controller + * + * @param PriorityGroup is priority grouping field + * + * Set the priority grouping field using the required unlock sequence. + * The parameter priority_grouping is assigned to the field + * SCB->AIRCR [10:8] PRIGROUP field. Only values from 0..7 are used. + * In case of a conflict between priority grouping and available + * priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + */ +static __INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */ + reg_value = (reg_value | + (0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8)); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + +/** + * @brief Get the Priority Grouping from NVIC Interrupt Controller + * + * @return priority grouping field + * + * Get the priority grouping from NVIC Interrupt Controller. + * priority grouping is SCB->AIRCR [10:8] PRIGROUP field. + */ +static __INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos); /* read priority grouping field */ +} + +/** + * @brief Enable Interrupt in NVIC Interrupt Controller + * + * @param IRQn The positive number of the external interrupt to enable + * + * Enable a device specific interupt in the NVIC interrupt controller. + * The interrupt number cannot be a negative value. + */ +static __INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */ +} + +/** + * @brief Disable the interrupt line for external interrupt specified + * + * @param IRQn The positive number of the external interrupt to disable + * + * Disable a device specific interupt in the NVIC interrupt controller. + * The interrupt number cannot be a negative value. + */ +static __INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */ +} + +/** + * @brief Read the interrupt pending bit for a device specific interrupt source + * + * @param IRQn The number of the device specifc interrupt + * @return 1 = interrupt pending, 0 = interrupt not pending + * + * Read the pending register in NVIC and return 1 if its status is pending, + * otherwise it returns 0 + */ +static __INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */ +} + +/** + * @brief Set the pending bit for an external interrupt + * + * @param IRQn The number of the interrupt for set pending + * + * Set the pending bit for the specified interrupt. + * The interrupt number cannot be a negative value. + */ +static __INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */ +} + +/** + * @brief Clear the pending bit for an external interrupt + * + * @param IRQn The number of the interrupt for clear pending + * + * Clear the pending bit for the specified interrupt. + * The interrupt number cannot be a negative value. + */ +static __INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} + +/** + * @brief Read the active bit for an external interrupt + * + * @param IRQn The number of the interrupt for read active bit + * @return 1 = interrupt active, 0 = interrupt not active + * + * Read the active register in NVIC and returns 1 if its status is active, + * otherwise it returns 0. + */ +static __INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */ +} + +/** + * @brief Set the priority for an interrupt + * + * @param IRQn The number of the interrupt for set priority + * @param priority The priority to set + * + * Set the priority for the specified interrupt. The interrupt + * number can be positive to specify an external (device specific) + * interrupt, or negative to specify an internal (core) interrupt. + * + * Note: The priority cannot be set for every core interrupt. + */ +static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) { + SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M3 System Interrupts */ + else { + NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */ +} + +/** + * @brief Read the priority for an interrupt + * + * @param IRQn The number of the interrupt for get priority + * @return The priority for the interrupt + * + * Read the priority for the specified interrupt. The interrupt + * number can be positive to specify an external (device specific) + * interrupt, or negative to specify an internal (core) interrupt. + * + * The returned priority value is automatically aligned to the implemented + * priority bits of the microcontroller. + * + * Note: The priority cannot be set for every core interrupt. + */ +static __INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if(IRQn < 0) { + return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M3 system interrupts */ + else { + return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ +} + + +/** + * @brief Encode the priority for an interrupt + * + * @param PriorityGroup The used priority group + * @param PreemptPriority The preemptive priority value (starting from 0) + * @param SubPriority The sub priority value (starting from 0) + * @return The encoded priority for the interrupt + * + * Encode the priority for an interrupt with the given priority group, + * preemptive priority value and sub priority value. + * In case of a conflict between priority grouping and available + * priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. + * + * The returned priority value can be used for NVIC_SetPriority(...) function + */ +static __INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + return ( + ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) | + ((SubPriority & ((1 << (SubPriorityBits )) - 1))) + ); +} + + +/** + * @brief Decode the priority of an interrupt + * + * @param Priority The priority for the interrupt + * @param PriorityGroup The used priority group + * @param pPreemptPriority The preemptive priority value (starting from 0) + * @param pSubPriority The sub priority value (starting from 0) + * + * Decode an interrupt priority value with the given priority group to + * preemptive priority value and sub priority value. + * In case of a conflict between priority grouping and available + * priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. + * + * The priority value can be retrieved with NVIC_GetPriority(...) function + */ +static __INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1); + *pSubPriority = (Priority ) & ((1 << (SubPriorityBits )) - 1); +} + + + +/* ################################## SysTick function ############################################ */ + +#if (!defined (__Vendor_SysTickConfig)) || (__Vendor_SysTickConfig == 0) + +/** + * @brief Initialize and start the SysTick counter and its interrupt. + * + * @param ticks number of ticks between two interrupts + * @return 1 = failed, 0 = successful + * + * Initialise the system tick timer and its interrupt and start the + * system tick timer / counter in free running mode to generate + * periodical interrupts. + */ +static __INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ + + SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */ + 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 + + + + +/* ################################## Reset function ############################################ */ + +/** + * @brief Initiate a system reset request. + * + * Initiate a system reset request to reset the MCU + */ +static __INLINE void NVIC_SystemReset(void) +{ + SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + while(1); /* wait until reset */ +} + +/*@}*/ /* end of group CMSIS_CM3_Core_FunctionInterface */ + + + +/* ##################################### Debug In/Output function ########################################### */ + +/** @addtogroup CMSIS_CM3_CoreDebugInterface CMSIS CM3 Core Debug Interface + Core Debug Interface containing: + - Core Debug Receive / Transmit Functions + - Core Debug Defines + - Core Debug Variables +*/ +/*@{*/ + +extern volatile int ITM_RxBuffer; /*!< variable to receive characters */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5 /*!< value identifying ITM_RxBuffer is ready for next character */ + + +/** + * @brief Outputs a character via the ITM channel 0 + * + * @param ch character to output + * @return character to output + * + * The function outputs a character via the ITM channel 0. + * The function returns when no debugger is connected that has booked the output. + * It is blocking when a debugger is connected, but the previous character send is not transmitted. + */ +static __INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if ((CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk) && /* Trace enabled */ + (ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */ + (ITM->TER & (1ul << 0) ) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0].u32 == 0); + ITM->PORT[0].u8 = (uint8_t) ch; + } + return (ch); +} + + +/** + * @brief Inputs a character via variable ITM_RxBuffer + * + * @return received character, -1 = no character received + * + * The function inputs a character via variable ITM_RxBuffer. + * The function returns when no debugger is connected that has booked the output. + * It is blocking when a debugger is connected, but the previous character send is not transmitted. + */ +static __INLINE int ITM_ReceiveChar (void) { + int ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + * @brief Check if a character via variable ITM_RxBuffer is available + * + * @return 1 = character available, 0 = no character available + * + * The function checks variable ITM_RxBuffer whether a character is available or not. + * The function returns '1' if a character is available and '0' if no character is available. + */ +static __INLINE int ITM_CheckChar (void) { + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { + return (0); /* no character available */ + } else { + return (1); /* character available */ + } +} + +/*@}*/ /* end of group CMSIS_CM3_core_DebugInterface */ + + +#ifdef __cplusplus +} +#endif + +/*@}*/ /* end of group CMSIS_CM3_core_definitions */ + +#endif /* __CM3_CORE_H__ */ + +/*lint -restore */ diff --git a/Start/startup_stm32f10x_cl.s b/Start/startup_stm32f10x_cl.s new file mode 100644 index 0000000..833ece4 --- /dev/null +++ b/Start/startup_stm32f10x_cl.s @@ -0,0 +1,368 @@ +;******************** (C) COPYRIGHT 2011 STMicroelectronics ******************** +;* File Name : startup_stm32f10x_cl.s +;* Author : MCD Application Team +;* Version : V3.5.0 +;* Date : 11-March-2011 +;* Description : STM32F10x Connectivity line devices vector table for MDK-ARM +;* toolchain. +;* This module performs: +;* - Set the initial SP +;* - Set the initial PC == Reset_Handler +;* - Set the vector table entries with the exceptions ISR address +;* - Configure the clock system +;* - Branches to __main in the C library (which eventually +;* calls main()). +;* After Reset the CortexM3 processor is in Thread mode, +;* priority is Privileged, and the Stack is set to Main. +;* <<< Use Configuration Wizard in Context Menu >>> +;******************************************************************************* +; THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +; WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +; AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +; INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +; CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +; INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +;******************************************************************************* + +; Amount of memory (in bytes) allocated for Stack +; Tailor this value to your application needs +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00000200 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + PRESERVE8 + THUMB + + +; Vector Table Mapped to Address 0 at Reset + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDG_IRQHandler ; Window Watchdog + DCD PVD_IRQHandler ; PVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Tamper + DCD RTC_IRQHandler ; RTC + DCD FLASH_IRQHandler ; Flash + DCD RCC_IRQHandler ; RCC + DCD EXTI0_IRQHandler ; EXTI Line 0 + DCD EXTI1_IRQHandler ; EXTI Line 1 + DCD EXTI2_IRQHandler ; EXTI Line 2 + DCD EXTI3_IRQHandler ; EXTI Line 3 + DCD EXTI4_IRQHandler ; EXTI Line 4 + DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2 + DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3 + DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4 + DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5 + DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6 + DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7 + DCD ADC1_2_IRQHandler ; ADC1 and ADC2 + DCD CAN1_TX_IRQHandler ; CAN1 TX + DCD CAN1_RX0_IRQHandler ; CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; CAN1 RX1 + DCD CAN1_SCE_IRQHandler ; CAN1 SCE + DCD EXTI9_5_IRQHandler ; EXTI Line 9..5 + DCD TIM1_BRK_IRQHandler ; TIM1 Break + DCD TIM1_UP_IRQHandler ; TIM1 Update + DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation + DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare + DCD TIM2_IRQHandler ; TIM2 + DCD TIM3_IRQHandler ; TIM3 + DCD TIM4_IRQHandler ; TIM4 + DCD I2C1_EV_IRQHandler ; I2C1 Event + DCD I2C1_ER_IRQHandler ; I2C1 Error + DCD I2C2_EV_IRQHandler ; I2C2 Event + DCD I2C2_ER_IRQHandler ; I2C1 Error + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_IRQHandler ; USART3 + DCD EXTI15_10_IRQHandler ; EXTI Line 15..10 + DCD RTCAlarm_IRQHandler ; RTC alarm through EXTI line + DCD OTG_FS_WKUP_IRQHandler ; USB OTG FS Wakeup through EXTI line + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD TIM5_IRQHandler ; TIM5 + DCD SPI3_IRQHandler ; SPI3 + DCD UART4_IRQHandler ; UART4 + DCD UART5_IRQHandler ; UART5 + DCD TIM6_IRQHandler ; TIM6 + DCD TIM7_IRQHandler ; TIM7 + DCD DMA2_Channel1_IRQHandler ; DMA2 Channel1 + DCD DMA2_Channel2_IRQHandler ; DMA2 Channel2 + DCD DMA2_Channel3_IRQHandler ; DMA2 Channel3 + DCD DMA2_Channel4_IRQHandler ; DMA2 Channel4 + DCD DMA2_Channel5_IRQHandler ; DMA2 Channel5 + DCD ETH_IRQHandler ; Ethernet + DCD ETH_WKUP_IRQHandler ; Ethernet Wakeup through EXTI line + DCD CAN2_TX_IRQHandler ; CAN2 TX + DCD CAN2_RX0_IRQHandler ; CAN2 RX0 + DCD CAN2_RX1_IRQHandler ; CAN2 RX1 + DCD CAN2_SCE_IRQHandler ; CAN2 SCE + DCD OTG_FS_IRQHandler ; USB OTG FS +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT SystemInit + IMPORT __main + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +; Dummy Exception Handlers (infinite loops which can be modified) + +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC + + EXPORT WWDG_IRQHandler [WEAK] + EXPORT PVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_IRQHandler [WEAK] + EXPORT DMA1_Channel4_IRQHandler [WEAK] + EXPORT DMA1_Channel5_IRQHandler [WEAK] + EXPORT DMA1_Channel6_IRQHandler [WEAK] + EXPORT DMA1_Channel7_IRQHandler [WEAK] + EXPORT ADC1_2_IRQHandler [WEAK] + EXPORT CAN1_TX_IRQHandler [WEAK] + EXPORT CAN1_RX0_IRQHandler [WEAK] + EXPORT CAN1_RX1_IRQHandler [WEAK] + EXPORT CAN1_SCE_IRQHandler [WEAK] + EXPORT EXTI9_5_IRQHandler [WEAK] + EXPORT TIM1_BRK_IRQHandler [WEAK] + EXPORT TIM1_UP_IRQHandler [WEAK] + EXPORT TIM1_TRG_COM_IRQHandler [WEAK] + EXPORT TIM1_CC_IRQHandler [WEAK] + EXPORT TIM2_IRQHandler [WEAK] + EXPORT TIM3_IRQHandler [WEAK] + EXPORT TIM4_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT I2C2_EV_IRQHandler [WEAK] + EXPORT I2C2_ER_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT USART3_IRQHandler [WEAK] + EXPORT EXTI15_10_IRQHandler [WEAK] + EXPORT RTCAlarm_IRQHandler [WEAK] + EXPORT OTG_FS_WKUP_IRQHandler [WEAK] + EXPORT TIM5_IRQHandler [WEAK] + EXPORT SPI3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT UART5_IRQHandler [WEAK] + EXPORT TIM6_IRQHandler [WEAK] + EXPORT TIM7_IRQHandler [WEAK] + EXPORT DMA2_Channel1_IRQHandler [WEAK] + EXPORT DMA2_Channel2_IRQHandler [WEAK] + EXPORT DMA2_Channel3_IRQHandler [WEAK] + EXPORT DMA2_Channel4_IRQHandler [WEAK] + EXPORT DMA2_Channel5_IRQHandler [WEAK] + EXPORT ETH_IRQHandler [WEAK] + EXPORT ETH_WKUP_IRQHandler [WEAK] + EXPORT CAN2_TX_IRQHandler [WEAK] + EXPORT CAN2_RX0_IRQHandler [WEAK] + EXPORT CAN2_RX1_IRQHandler [WEAK] + EXPORT CAN2_SCE_IRQHandler [WEAK] + EXPORT OTG_FS_IRQHandler [WEAK] + +WWDG_IRQHandler +PVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FLASH_IRQHandler +RCC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_IRQHandler +DMA1_Channel4_IRQHandler +DMA1_Channel5_IRQHandler +DMA1_Channel6_IRQHandler +DMA1_Channel7_IRQHandler +ADC1_2_IRQHandler +CAN1_TX_IRQHandler +CAN1_RX0_IRQHandler +CAN1_RX1_IRQHandler +CAN1_SCE_IRQHandler +EXTI9_5_IRQHandler +TIM1_BRK_IRQHandler +TIM1_UP_IRQHandler +TIM1_TRG_COM_IRQHandler +TIM1_CC_IRQHandler +TIM2_IRQHandler +TIM3_IRQHandler +TIM4_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +I2C2_EV_IRQHandler +I2C2_ER_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +USART3_IRQHandler +EXTI15_10_IRQHandler +RTCAlarm_IRQHandler +OTG_FS_WKUP_IRQHandler +TIM5_IRQHandler +SPI3_IRQHandler +UART4_IRQHandler +UART5_IRQHandler +TIM6_IRQHandler +TIM7_IRQHandler +DMA2_Channel1_IRQHandler +DMA2_Channel2_IRQHandler +DMA2_Channel3_IRQHandler +DMA2_Channel4_IRQHandler +DMA2_Channel5_IRQHandler +ETH_IRQHandler +ETH_WKUP_IRQHandler +CAN2_TX_IRQHandler +CAN2_RX0_IRQHandler +CAN2_RX1_IRQHandler +CAN2_SCE_IRQHandler +OTG_FS_IRQHandler + + B . + + ENDP + + ALIGN + +;******************************************************************************* +; User Stack and Heap initialization +;******************************************************************************* + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap + + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + + ALIGN + + ENDIF + + END + +;******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE***** diff --git a/Start/startup_stm32f10x_hd.s b/Start/startup_stm32f10x_hd.s new file mode 100644 index 0000000..8a19827 --- /dev/null +++ b/Start/startup_stm32f10x_hd.s @@ -0,0 +1,358 @@ +;******************** (C) COPYRIGHT 2011 STMicroelectronics ******************** +;* File Name : startup_stm32f10x_hd.s +;* Author : MCD Application Team +;* Version : V3.5.0 +;* Date : 11-March-2011 +;* Description : STM32F10x High Density Devices vector table for MDK-ARM +;* toolchain. +;* This module performs: +;* - Set the initial SP +;* - Set the initial PC == Reset_Handler +;* - Set the vector table entries with the exceptions ISR address +;* - Configure the clock system and also configure the external +;* SRAM mounted on STM3210E-EVAL board to be used as data +;* memory (optional, to be enabled by user) +;* - Branches to __main in the C library (which eventually +;* calls main()). +;* After Reset the CortexM3 processor is in Thread mode, +;* priority is Privileged, and the Stack is set to Main. +;* <<< Use Configuration Wizard in Context Menu >>> +;******************************************************************************* +; THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +; WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +; AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +; INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +; CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +; INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +;******************************************************************************* + +; Amount of memory (in bytes) allocated for Stack +; Tailor this value to your application needs +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00000200 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + PRESERVE8 + THUMB + + +; Vector Table Mapped to Address 0 at Reset + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDG_IRQHandler ; Window Watchdog + DCD PVD_IRQHandler ; PVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Tamper + DCD RTC_IRQHandler ; RTC + DCD FLASH_IRQHandler ; Flash + DCD RCC_IRQHandler ; RCC + DCD EXTI0_IRQHandler ; EXTI Line 0 + DCD EXTI1_IRQHandler ; EXTI Line 1 + DCD EXTI2_IRQHandler ; EXTI Line 2 + DCD EXTI3_IRQHandler ; EXTI Line 3 + DCD EXTI4_IRQHandler ; EXTI Line 4 + DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2 + DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3 + DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4 + DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5 + DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6 + DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7 + DCD ADC1_2_IRQHandler ; ADC1 & ADC2 + DCD USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TX + DCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; CAN1 RX1 + DCD CAN1_SCE_IRQHandler ; CAN1 SCE + DCD EXTI9_5_IRQHandler ; EXTI Line 9..5 + DCD TIM1_BRK_IRQHandler ; TIM1 Break + DCD TIM1_UP_IRQHandler ; TIM1 Update + DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation + DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare + DCD TIM2_IRQHandler ; TIM2 + DCD TIM3_IRQHandler ; TIM3 + DCD TIM4_IRQHandler ; TIM4 + DCD I2C1_EV_IRQHandler ; I2C1 Event + DCD I2C1_ER_IRQHandler ; I2C1 Error + DCD I2C2_EV_IRQHandler ; I2C2 Event + DCD I2C2_ER_IRQHandler ; I2C2 Error + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_IRQHandler ; USART3 + DCD EXTI15_10_IRQHandler ; EXTI Line 15..10 + DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line + DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend + DCD TIM8_BRK_IRQHandler ; TIM8 Break + DCD TIM8_UP_IRQHandler ; TIM8 Update + DCD TIM8_TRG_COM_IRQHandler ; TIM8 Trigger and Commutation + DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare + DCD ADC3_IRQHandler ; ADC3 + DCD FSMC_IRQHandler ; FSMC + DCD SDIO_IRQHandler ; SDIO + DCD TIM5_IRQHandler ; TIM5 + DCD SPI3_IRQHandler ; SPI3 + DCD UART4_IRQHandler ; UART4 + DCD UART5_IRQHandler ; UART5 + DCD TIM6_IRQHandler ; TIM6 + DCD TIM7_IRQHandler ; TIM7 + DCD DMA2_Channel1_IRQHandler ; DMA2 Channel1 + DCD DMA2_Channel2_IRQHandler ; DMA2 Channel2 + DCD DMA2_Channel3_IRQHandler ; DMA2 Channel3 + DCD DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5 +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +; Dummy Exception Handlers (infinite loops which can be modified) + +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC + + EXPORT WWDG_IRQHandler [WEAK] + EXPORT PVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_IRQHandler [WEAK] + EXPORT DMA1_Channel4_IRQHandler [WEAK] + EXPORT DMA1_Channel5_IRQHandler [WEAK] + EXPORT DMA1_Channel6_IRQHandler [WEAK] + EXPORT DMA1_Channel7_IRQHandler [WEAK] + EXPORT ADC1_2_IRQHandler [WEAK] + EXPORT USB_HP_CAN1_TX_IRQHandler [WEAK] + EXPORT USB_LP_CAN1_RX0_IRQHandler [WEAK] + EXPORT CAN1_RX1_IRQHandler [WEAK] + EXPORT CAN1_SCE_IRQHandler [WEAK] + EXPORT EXTI9_5_IRQHandler [WEAK] + EXPORT TIM1_BRK_IRQHandler [WEAK] + EXPORT TIM1_UP_IRQHandler [WEAK] + EXPORT TIM1_TRG_COM_IRQHandler [WEAK] + EXPORT TIM1_CC_IRQHandler [WEAK] + EXPORT TIM2_IRQHandler [WEAK] + EXPORT TIM3_IRQHandler [WEAK] + EXPORT TIM4_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT I2C2_EV_IRQHandler [WEAK] + EXPORT I2C2_ER_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT USART3_IRQHandler [WEAK] + EXPORT EXTI15_10_IRQHandler [WEAK] + EXPORT RTCAlarm_IRQHandler [WEAK] + EXPORT USBWakeUp_IRQHandler [WEAK] + EXPORT TIM8_BRK_IRQHandler [WEAK] + EXPORT TIM8_UP_IRQHandler [WEAK] + EXPORT TIM8_TRG_COM_IRQHandler [WEAK] + EXPORT TIM8_CC_IRQHandler [WEAK] + EXPORT ADC3_IRQHandler [WEAK] + EXPORT FSMC_IRQHandler [WEAK] + EXPORT SDIO_IRQHandler [WEAK] + EXPORT TIM5_IRQHandler [WEAK] + EXPORT SPI3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT UART5_IRQHandler [WEAK] + EXPORT TIM6_IRQHandler [WEAK] + EXPORT TIM7_IRQHandler [WEAK] + EXPORT DMA2_Channel1_IRQHandler [WEAK] + EXPORT DMA2_Channel2_IRQHandler [WEAK] + EXPORT DMA2_Channel3_IRQHandler [WEAK] + EXPORT DMA2_Channel4_5_IRQHandler [WEAK] + +WWDG_IRQHandler +PVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FLASH_IRQHandler +RCC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_IRQHandler +DMA1_Channel4_IRQHandler +DMA1_Channel5_IRQHandler +DMA1_Channel6_IRQHandler +DMA1_Channel7_IRQHandler +ADC1_2_IRQHandler +USB_HP_CAN1_TX_IRQHandler +USB_LP_CAN1_RX0_IRQHandler +CAN1_RX1_IRQHandler +CAN1_SCE_IRQHandler +EXTI9_5_IRQHandler +TIM1_BRK_IRQHandler +TIM1_UP_IRQHandler +TIM1_TRG_COM_IRQHandler +TIM1_CC_IRQHandler +TIM2_IRQHandler +TIM3_IRQHandler +TIM4_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +I2C2_EV_IRQHandler +I2C2_ER_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +USART3_IRQHandler +EXTI15_10_IRQHandler +RTCAlarm_IRQHandler +USBWakeUp_IRQHandler +TIM8_BRK_IRQHandler +TIM8_UP_IRQHandler +TIM8_TRG_COM_IRQHandler +TIM8_CC_IRQHandler +ADC3_IRQHandler +FSMC_IRQHandler +SDIO_IRQHandler +TIM5_IRQHandler +SPI3_IRQHandler +UART4_IRQHandler +UART5_IRQHandler +TIM6_IRQHandler +TIM7_IRQHandler +DMA2_Channel1_IRQHandler +DMA2_Channel2_IRQHandler +DMA2_Channel3_IRQHandler +DMA2_Channel4_5_IRQHandler + B . + + ENDP + + ALIGN + +;******************************************************************************* +; User Stack and Heap initialization +;******************************************************************************* + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap + + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + + ALIGN + + ENDIF + + END + +;******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE***** diff --git a/Start/startup_stm32f10x_hd_vl.s b/Start/startup_stm32f10x_hd_vl.s new file mode 100644 index 0000000..2768298 --- /dev/null +++ b/Start/startup_stm32f10x_hd_vl.s @@ -0,0 +1,346 @@ +;******************** (C) COPYRIGHT 2011 STMicroelectronics ******************** +;* File Name : startup_stm32f10x_hd_vl.s +;* Author : MCD Application Team +;* Version : V3.5.0 +;* Date : 11-March-2011 +;* Description : STM32F10x High Density Value Line Devices vector table +;* for MDK-ARM toolchain. +;* This module performs: +;* - Set the initial SP +;* - Set the initial PC == Reset_Handler +;* - Set the vector table entries with the exceptions ISR address +;* - Configure the clock system and also configure the external +;* SRAM mounted on STM32100E-EVAL board to be used as data +;* memory (optional, to be enabled by user) +;* - Branches to __main in the C library (which eventually +;* calls main()). +;* After Reset the CortexM3 processor is in Thread mode, +;* priority is Privileged, and the Stack is set to Main. +;* <<< Use Configuration Wizard in Context Menu >>> +;******************************************************************************* +; THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +; WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +; AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +; INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +; CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +; INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +;******************************************************************************* + +; Amount of memory (in bytes) allocated for Stack +; Tailor this value to your application needs +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00000200 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + PRESERVE8 + THUMB + + +; Vector Table Mapped to Address 0 at Reset + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDG_IRQHandler ; Window Watchdog + DCD PVD_IRQHandler ; PVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Tamper + DCD RTC_IRQHandler ; RTC + DCD FLASH_IRQHandler ; Flash + DCD RCC_IRQHandler ; RCC + DCD EXTI0_IRQHandler ; EXTI Line 0 + DCD EXTI1_IRQHandler ; EXTI Line 1 + DCD EXTI2_IRQHandler ; EXTI Line 2 + DCD EXTI3_IRQHandler ; EXTI Line 3 + DCD EXTI4_IRQHandler ; EXTI Line 4 + DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2 + DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3 + DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4 + DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5 + DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6 + DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7 + DCD ADC1_IRQHandler ; ADC1 + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD EXTI9_5_IRQHandler ; EXTI Line 9..5 + DCD TIM1_BRK_TIM15_IRQHandler ; TIM1 Break and TIM15 + DCD TIM1_UP_TIM16_IRQHandler ; TIM1 Update and TIM16 + DCD TIM1_TRG_COM_TIM17_IRQHandler ; TIM1 Trigger and Commutation and TIM17 + DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare + DCD TIM2_IRQHandler ; TIM2 + DCD TIM3_IRQHandler ; TIM3 + DCD TIM4_IRQHandler ; TIM4 + DCD I2C1_EV_IRQHandler ; I2C1 Event + DCD I2C1_ER_IRQHandler ; I2C1 Error + DCD I2C2_EV_IRQHandler ; I2C2 Event + DCD I2C2_ER_IRQHandler ; I2C2 Error + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_IRQHandler ; USART3 + DCD EXTI15_10_IRQHandler ; EXTI Line 15..10 + DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line + DCD CEC_IRQHandler ; HDMI-CEC + DCD TIM12_IRQHandler ; TIM12 + DCD TIM13_IRQHandler ; TIM13 + DCD TIM14_IRQHandler ; TIM14 + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD TIM5_IRQHandler ; TIM5 + DCD SPI3_IRQHandler ; SPI3 + DCD UART4_IRQHandler ; UART4 + DCD UART5_IRQHandler ; UART5 + DCD TIM6_DAC_IRQHandler ; TIM6 and DAC underrun + DCD TIM7_IRQHandler ; TIM7 + DCD DMA2_Channel1_IRQHandler ; DMA2 Channel1 + DCD DMA2_Channel2_IRQHandler ; DMA2 Channel2 + DCD DMA2_Channel3_IRQHandler ; DMA2 Channel3 + DCD DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5 + DCD DMA2_Channel5_IRQHandler ; DMA2 Channel5 +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +; Dummy Exception Handlers (infinite loops which can be modified) + +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC + + EXPORT WWDG_IRQHandler [WEAK] + EXPORT PVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_IRQHandler [WEAK] + EXPORT DMA1_Channel4_IRQHandler [WEAK] + EXPORT DMA1_Channel5_IRQHandler [WEAK] + EXPORT DMA1_Channel6_IRQHandler [WEAK] + EXPORT DMA1_Channel7_IRQHandler [WEAK] + EXPORT ADC1_IRQHandler [WEAK] + EXPORT EXTI9_5_IRQHandler [WEAK] + EXPORT TIM1_BRK_TIM15_IRQHandler [WEAK] + EXPORT TIM1_UP_TIM16_IRQHandler [WEAK] + EXPORT TIM1_TRG_COM_TIM17_IRQHandler [WEAK] + EXPORT TIM1_CC_IRQHandler [WEAK] + EXPORT TIM2_IRQHandler [WEAK] + EXPORT TIM3_IRQHandler [WEAK] + EXPORT TIM4_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT I2C2_EV_IRQHandler [WEAK] + EXPORT I2C2_ER_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT USART3_IRQHandler [WEAK] + EXPORT EXTI15_10_IRQHandler [WEAK] + EXPORT RTCAlarm_IRQHandler [WEAK] + EXPORT CEC_IRQHandler [WEAK] + EXPORT TIM12_IRQHandler [WEAK] + EXPORT TIM13_IRQHandler [WEAK] + EXPORT TIM14_IRQHandler [WEAK] + EXPORT TIM5_IRQHandler [WEAK] + EXPORT SPI3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT UART5_IRQHandler [WEAK] + EXPORT TIM6_DAC_IRQHandler [WEAK] + EXPORT TIM7_IRQHandler [WEAK] + EXPORT DMA2_Channel1_IRQHandler [WEAK] + EXPORT DMA2_Channel2_IRQHandler [WEAK] + EXPORT DMA2_Channel3_IRQHandler [WEAK] + EXPORT DMA2_Channel4_5_IRQHandler [WEAK] + EXPORT DMA2_Channel5_IRQHandler [WEAK] + +WWDG_IRQHandler +PVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FLASH_IRQHandler +RCC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_IRQHandler +DMA1_Channel4_IRQHandler +DMA1_Channel5_IRQHandler +DMA1_Channel6_IRQHandler +DMA1_Channel7_IRQHandler +ADC1_IRQHandler +EXTI9_5_IRQHandler +TIM1_BRK_TIM15_IRQHandler +TIM1_UP_TIM16_IRQHandler +TIM1_TRG_COM_TIM17_IRQHandler +TIM1_CC_IRQHandler +TIM2_IRQHandler +TIM3_IRQHandler +TIM4_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +I2C2_EV_IRQHandler +I2C2_ER_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +USART3_IRQHandler +EXTI15_10_IRQHandler +RTCAlarm_IRQHandler +CEC_IRQHandler +TIM12_IRQHandler +TIM13_IRQHandler +TIM14_IRQHandler +TIM5_IRQHandler +SPI3_IRQHandler +UART4_IRQHandler +UART5_IRQHandler +TIM6_DAC_IRQHandler +TIM7_IRQHandler +DMA2_Channel1_IRQHandler +DMA2_Channel2_IRQHandler +DMA2_Channel3_IRQHandler +DMA2_Channel4_5_IRQHandler +DMA2_Channel5_IRQHandler + B . + + ENDP + + ALIGN + +;******************************************************************************* +; User Stack and Heap initialization +;******************************************************************************* + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap + + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + + ALIGN + + ENDIF + + END + +;******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE***** diff --git a/Start/startup_stm32f10x_ld.s b/Start/startup_stm32f10x_ld.s new file mode 100644 index 0000000..f18be4b --- /dev/null +++ b/Start/startup_stm32f10x_ld.s @@ -0,0 +1,297 @@ +;******************** (C) COPYRIGHT 2011 STMicroelectronics ******************** +;* File Name : startup_stm32f10x_ld.s +;* Author : MCD Application Team +;* Version : V3.5.0 +;* Date : 11-March-2011 +;* Description : STM32F10x Low Density Devices vector table for MDK-ARM +;* toolchain. +;* This module performs: +;* - Set the initial SP +;* - Set the initial PC == Reset_Handler +;* - Set the vector table entries with the exceptions ISR address +;* - Configure the clock system +;* - Branches to __main in the C library (which eventually +;* calls main()). +;* After Reset the CortexM3 processor is in Thread mode, +;* priority is Privileged, and the Stack is set to Main. +;* <<< Use Configuration Wizard in Context Menu >>> +;******************************************************************************* +; THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +; WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +; AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +; INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +; CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +; INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +;******************************************************************************* + +; Amount of memory (in bytes) allocated for Stack +; Tailor this value to your application needs +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00000200 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + PRESERVE8 + THUMB + + +; Vector Table Mapped to Address 0 at Reset + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDG_IRQHandler ; Window Watchdog + DCD PVD_IRQHandler ; PVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Tamper + DCD RTC_IRQHandler ; RTC + DCD FLASH_IRQHandler ; Flash + DCD RCC_IRQHandler ; RCC + DCD EXTI0_IRQHandler ; EXTI Line 0 + DCD EXTI1_IRQHandler ; EXTI Line 1 + DCD EXTI2_IRQHandler ; EXTI Line 2 + DCD EXTI3_IRQHandler ; EXTI Line 3 + DCD EXTI4_IRQHandler ; EXTI Line 4 + DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2 + DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3 + DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4 + DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5 + DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6 + DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7 + DCD ADC1_2_IRQHandler ; ADC1_2 + DCD USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TX + DCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; CAN1 RX1 + DCD CAN1_SCE_IRQHandler ; CAN1 SCE + DCD EXTI9_5_IRQHandler ; EXTI Line 9..5 + DCD TIM1_BRK_IRQHandler ; TIM1 Break + DCD TIM1_UP_IRQHandler ; TIM1 Update + DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation + DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare + DCD TIM2_IRQHandler ; TIM2 + DCD TIM3_IRQHandler ; TIM3 + DCD 0 ; Reserved + DCD I2C1_EV_IRQHandler ; I2C1 Event + DCD I2C1_ER_IRQHandler ; I2C1 Error + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SPI1_IRQHandler ; SPI1 + DCD 0 ; Reserved + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD 0 ; Reserved + DCD EXTI15_10_IRQHandler ; EXTI Line 15..10 + DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line + DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler routine +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +; Dummy Exception Handlers (infinite loops which can be modified) + +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC + + EXPORT WWDG_IRQHandler [WEAK] + EXPORT PVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_IRQHandler [WEAK] + EXPORT DMA1_Channel4_IRQHandler [WEAK] + EXPORT DMA1_Channel5_IRQHandler [WEAK] + EXPORT DMA1_Channel6_IRQHandler [WEAK] + EXPORT DMA1_Channel7_IRQHandler [WEAK] + EXPORT ADC1_2_IRQHandler [WEAK] + EXPORT USB_HP_CAN1_TX_IRQHandler [WEAK] + EXPORT USB_LP_CAN1_RX0_IRQHandler [WEAK] + EXPORT CAN1_RX1_IRQHandler [WEAK] + EXPORT CAN1_SCE_IRQHandler [WEAK] + EXPORT EXTI9_5_IRQHandler [WEAK] + EXPORT TIM1_BRK_IRQHandler [WEAK] + EXPORT TIM1_UP_IRQHandler [WEAK] + EXPORT TIM1_TRG_COM_IRQHandler [WEAK] + EXPORT TIM1_CC_IRQHandler [WEAK] + EXPORT TIM2_IRQHandler [WEAK] + EXPORT TIM3_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI15_10_IRQHandler [WEAK] + EXPORT RTCAlarm_IRQHandler [WEAK] + EXPORT USBWakeUp_IRQHandler [WEAK] + +WWDG_IRQHandler +PVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FLASH_IRQHandler +RCC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_IRQHandler +DMA1_Channel4_IRQHandler +DMA1_Channel5_IRQHandler +DMA1_Channel6_IRQHandler +DMA1_Channel7_IRQHandler +ADC1_2_IRQHandler +USB_HP_CAN1_TX_IRQHandler +USB_LP_CAN1_RX0_IRQHandler +CAN1_RX1_IRQHandler +CAN1_SCE_IRQHandler +EXTI9_5_IRQHandler +TIM1_BRK_IRQHandler +TIM1_UP_IRQHandler +TIM1_TRG_COM_IRQHandler +TIM1_CC_IRQHandler +TIM2_IRQHandler +TIM3_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI1_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI15_10_IRQHandler +RTCAlarm_IRQHandler +USBWakeUp_IRQHandler + + B . + + ENDP + + ALIGN + +;******************************************************************************* +; User Stack and Heap initialization +;******************************************************************************* + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap + + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + + ALIGN + + ENDIF + + END + +;******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE***** diff --git a/Start/startup_stm32f10x_ld_vl.s b/Start/startup_stm32f10x_ld_vl.s new file mode 100644 index 0000000..f7240dc --- /dev/null +++ b/Start/startup_stm32f10x_ld_vl.s @@ -0,0 +1,304 @@ +;******************** (C) COPYRIGHT 2011 STMicroelectronics ******************** +;* File Name : startup_stm32f10x_ld_vl.s +;* Author : MCD Application Team +;* Version : V3.5.0 +;* Date : 11-March-2011 +;* Description : STM32F10x Low Density Value Line Devices vector table +;* for MDK-ARM toolchain. +;* This module performs: +;* - Set the initial SP +;* - Set the initial PC == Reset_Handler +;* - Set the vector table entries with the exceptions ISR address +;* - Configure the clock system +;* - Branches to __main in the C library (which eventually +;* calls main()). +;* After Reset the CortexM3 processor is in Thread mode, +;* priority is Privileged, and the Stack is set to Main. +;* <<< Use Configuration Wizard in Context Menu >>> +;******************************************************************************* +; THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +; WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +; AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +; INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +; CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +; INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +;******************************************************************************* + +; Amount of memory (in bytes) allocated for Stack +; Tailor this value to your application needs +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00000200 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + PRESERVE8 + THUMB + + +; Vector Table Mapped to Address 0 at Reset + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDG_IRQHandler ; Window Watchdog + DCD PVD_IRQHandler ; PVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Tamper + DCD RTC_IRQHandler ; RTC + DCD FLASH_IRQHandler ; Flash + DCD RCC_IRQHandler ; RCC + DCD EXTI0_IRQHandler ; EXTI Line 0 + DCD EXTI1_IRQHandler ; EXTI Line 1 + DCD EXTI2_IRQHandler ; EXTI Line 2 + DCD EXTI3_IRQHandler ; EXTI Line 3 + DCD EXTI4_IRQHandler ; EXTI Line 4 + DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2 + DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3 + DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4 + DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5 + DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6 + DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7 + DCD ADC1_IRQHandler ; ADC1 + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD EXTI9_5_IRQHandler ; EXTI Line 9..5 + DCD TIM1_BRK_TIM15_IRQHandler ; TIM1 Break and TIM15 + DCD TIM1_UP_TIM16_IRQHandler ; TIM1 Update and TIM16 + DCD TIM1_TRG_COM_TIM17_IRQHandler ; TIM1 Trigger and Commutation and TIM17 + DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare + DCD TIM2_IRQHandler ; TIM2 + DCD TIM3_IRQHandler ; TIM3 + DCD 0 ; Reserved + DCD I2C1_EV_IRQHandler ; I2C1 Event + DCD I2C1_ER_IRQHandler ; I2C1 Error + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SPI1_IRQHandler ; SPI1 + DCD 0 ; Reserved + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD 0 ; Reserved + DCD EXTI15_10_IRQHandler ; EXTI Line 15..10 + DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line + DCD CEC_IRQHandler ; HDMI-CEC + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD TIM6_DAC_IRQHandler ; TIM6 and DAC underrun + DCD TIM7_IRQHandler ; TIM7 +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +; Dummy Exception Handlers (infinite loops which can be modified) + +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC + + EXPORT WWDG_IRQHandler [WEAK] + EXPORT PVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_IRQHandler [WEAK] + EXPORT DMA1_Channel4_IRQHandler [WEAK] + EXPORT DMA1_Channel5_IRQHandler [WEAK] + EXPORT DMA1_Channel6_IRQHandler [WEAK] + EXPORT DMA1_Channel7_IRQHandler [WEAK] + EXPORT ADC1_IRQHandler [WEAK] + EXPORT EXTI9_5_IRQHandler [WEAK] + EXPORT TIM1_BRK_TIM15_IRQHandler [WEAK] + EXPORT TIM1_UP_TIM16_IRQHandler [WEAK] + EXPORT TIM1_TRG_COM_TIM17_IRQHandler [WEAK] + EXPORT TIM1_CC_IRQHandler [WEAK] + EXPORT TIM2_IRQHandler [WEAK] + EXPORT TIM3_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI15_10_IRQHandler [WEAK] + EXPORT RTCAlarm_IRQHandler [WEAK] + EXPORT CEC_IRQHandler [WEAK] + EXPORT TIM6_DAC_IRQHandler [WEAK] + EXPORT TIM7_IRQHandler [WEAK] +WWDG_IRQHandler +PVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FLASH_IRQHandler +RCC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_IRQHandler +DMA1_Channel4_IRQHandler +DMA1_Channel5_IRQHandler +DMA1_Channel6_IRQHandler +DMA1_Channel7_IRQHandler +ADC1_IRQHandler +EXTI9_5_IRQHandler +TIM1_BRK_TIM15_IRQHandler +TIM1_UP_TIM16_IRQHandler +TIM1_TRG_COM_TIM17_IRQHandler +TIM1_CC_IRQHandler +TIM2_IRQHandler +TIM3_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI1_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI15_10_IRQHandler +RTCAlarm_IRQHandler +CEC_IRQHandler +TIM6_DAC_IRQHandler +TIM7_IRQHandler + B . + + ENDP + + ALIGN + +;******************************************************************************* +; User Stack and Heap initialization +;******************************************************************************* + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap + + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + + ALIGN + + ENDIF + + END + +;******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE***** diff --git a/Start/startup_stm32f10x_md.s b/Start/startup_stm32f10x_md.s new file mode 100644 index 0000000..74da96c --- /dev/null +++ b/Start/startup_stm32f10x_md.s @@ -0,0 +1,307 @@ +;******************** (C) COPYRIGHT 2011 STMicroelectronics ******************** +;* File Name : startup_stm32f10x_md.s +;* Author : MCD Application Team +;* Version : V3.5.0 +;* Date : 11-March-2011 +;* Description : STM32F10x Medium Density Devices vector table for MDK-ARM +;* toolchain. +;* This module performs: +;* - Set the initial SP +;* - Set the initial PC == Reset_Handler +;* - Set the vector table entries with the exceptions ISR address +;* - Configure the clock system +;* - Branches to __main in the C library (which eventually +;* calls main()). +;* After Reset the CortexM3 processor is in Thread mode, +;* priority is Privileged, and the Stack is set to Main. +;* <<< Use Configuration Wizard in Context Menu >>> +;******************************************************************************* +; THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +; WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +; AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +; INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +; CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +; INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +;******************************************************************************* + +; Amount of memory (in bytes) allocated for Stack +; Tailor this value to your application needs +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00000200 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + PRESERVE8 + THUMB + + +; Vector Table Mapped to Address 0 at Reset + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDG_IRQHandler ; Window Watchdog + DCD PVD_IRQHandler ; PVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Tamper + DCD RTC_IRQHandler ; RTC + DCD FLASH_IRQHandler ; Flash + DCD RCC_IRQHandler ; RCC + DCD EXTI0_IRQHandler ; EXTI Line 0 + DCD EXTI1_IRQHandler ; EXTI Line 1 + DCD EXTI2_IRQHandler ; EXTI Line 2 + DCD EXTI3_IRQHandler ; EXTI Line 3 + DCD EXTI4_IRQHandler ; EXTI Line 4 + DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2 + DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3 + DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4 + DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5 + DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6 + DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7 + DCD ADC1_2_IRQHandler ; ADC1_2 + DCD USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TX + DCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; CAN1 RX1 + DCD CAN1_SCE_IRQHandler ; CAN1 SCE + DCD EXTI9_5_IRQHandler ; EXTI Line 9..5 + DCD TIM1_BRK_IRQHandler ; TIM1 Break + DCD TIM1_UP_IRQHandler ; TIM1 Update + DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation + DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare + DCD TIM2_IRQHandler ; TIM2 + DCD TIM3_IRQHandler ; TIM3 + DCD TIM4_IRQHandler ; TIM4 + DCD I2C1_EV_IRQHandler ; I2C1 Event + DCD I2C1_ER_IRQHandler ; I2C1 Error + DCD I2C2_EV_IRQHandler ; I2C2 Event + DCD I2C2_ER_IRQHandler ; I2C2 Error + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_IRQHandler ; USART3 + DCD EXTI15_10_IRQHandler ; EXTI Line 15..10 + DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line + DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +; Dummy Exception Handlers (infinite loops which can be modified) + +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC + + EXPORT WWDG_IRQHandler [WEAK] + EXPORT PVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_IRQHandler [WEAK] + EXPORT DMA1_Channel4_IRQHandler [WEAK] + EXPORT DMA1_Channel5_IRQHandler [WEAK] + EXPORT DMA1_Channel6_IRQHandler [WEAK] + EXPORT DMA1_Channel7_IRQHandler [WEAK] + EXPORT ADC1_2_IRQHandler [WEAK] + EXPORT USB_HP_CAN1_TX_IRQHandler [WEAK] + EXPORT USB_LP_CAN1_RX0_IRQHandler [WEAK] + EXPORT CAN1_RX1_IRQHandler [WEAK] + EXPORT CAN1_SCE_IRQHandler [WEAK] + EXPORT EXTI9_5_IRQHandler [WEAK] + EXPORT TIM1_BRK_IRQHandler [WEAK] + EXPORT TIM1_UP_IRQHandler [WEAK] + EXPORT TIM1_TRG_COM_IRQHandler [WEAK] + EXPORT TIM1_CC_IRQHandler [WEAK] + EXPORT TIM2_IRQHandler [WEAK] + EXPORT TIM3_IRQHandler [WEAK] + EXPORT TIM4_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT I2C2_EV_IRQHandler [WEAK] + EXPORT I2C2_ER_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT USART3_IRQHandler [WEAK] + EXPORT EXTI15_10_IRQHandler [WEAK] + EXPORT RTCAlarm_IRQHandler [WEAK] + EXPORT USBWakeUp_IRQHandler [WEAK] + +WWDG_IRQHandler +PVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FLASH_IRQHandler +RCC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_IRQHandler +DMA1_Channel4_IRQHandler +DMA1_Channel5_IRQHandler +DMA1_Channel6_IRQHandler +DMA1_Channel7_IRQHandler +ADC1_2_IRQHandler +USB_HP_CAN1_TX_IRQHandler +USB_LP_CAN1_RX0_IRQHandler +CAN1_RX1_IRQHandler +CAN1_SCE_IRQHandler +EXTI9_5_IRQHandler +TIM1_BRK_IRQHandler +TIM1_UP_IRQHandler +TIM1_TRG_COM_IRQHandler +TIM1_CC_IRQHandler +TIM2_IRQHandler +TIM3_IRQHandler +TIM4_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +I2C2_EV_IRQHandler +I2C2_ER_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +USART3_IRQHandler +EXTI15_10_IRQHandler +RTCAlarm_IRQHandler +USBWakeUp_IRQHandler + + B . + + ENDP + + ALIGN + +;******************************************************************************* +; User Stack and Heap initialization +;******************************************************************************* + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap + + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + + ALIGN + + ENDIF + + END + +;******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE***** diff --git a/Start/startup_stm32f10x_md_vl.s b/Start/startup_stm32f10x_md_vl.s new file mode 100644 index 0000000..076aa7f --- /dev/null +++ b/Start/startup_stm32f10x_md_vl.s @@ -0,0 +1,315 @@ +;******************** (C) COPYRIGHT 2011 STMicroelectronics ******************** +;* File Name : startup_stm32f10x_md_vl.s +;* Author : MCD Application Team +;* Version : V3.5.0 +;* Date : 11-March-2011 +;* Description : STM32F10x Medium Density Value Line Devices vector table +;* for MDK-ARM toolchain. +;* This module performs: +;* - Set the initial SP +;* - Set the initial PC == Reset_Handler +;* - Set the vector table entries with the exceptions ISR address +;* - Configure the clock system +;* - Branches to __main in the C library (which eventually +;* calls main()). +;* After Reset the CortexM3 processor is in Thread mode, +;* priority is Privileged, and the Stack is set to Main. +;* <<< Use Configuration Wizard in Context Menu >>> +;******************************************************************************* +; THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +; WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +; AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +; INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +; CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +; INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +;******************************************************************************* + +; Amount of memory (in bytes) allocated for Stack +; Tailor this value to your application needs +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00000200 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + PRESERVE8 + THUMB + + +; Vector Table Mapped to Address 0 at Reset + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDG_IRQHandler ; Window Watchdog + DCD PVD_IRQHandler ; PVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Tamper + DCD RTC_IRQHandler ; RTC + DCD FLASH_IRQHandler ; Flash + DCD RCC_IRQHandler ; RCC + DCD EXTI0_IRQHandler ; EXTI Line 0 + DCD EXTI1_IRQHandler ; EXTI Line 1 + DCD EXTI2_IRQHandler ; EXTI Line 2 + DCD EXTI3_IRQHandler ; EXTI Line 3 + DCD EXTI4_IRQHandler ; EXTI Line 4 + DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2 + DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3 + DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4 + DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5 + DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6 + DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7 + DCD ADC1_IRQHandler ; ADC1 + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD EXTI9_5_IRQHandler ; EXTI Line 9..5 + DCD TIM1_BRK_TIM15_IRQHandler ; TIM1 Break and TIM15 + DCD TIM1_UP_TIM16_IRQHandler ; TIM1 Update and TIM16 + DCD TIM1_TRG_COM_TIM17_IRQHandler ; TIM1 Trigger and Commutation and TIM17 + DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare + DCD TIM2_IRQHandler ; TIM2 + DCD TIM3_IRQHandler ; TIM3 + DCD TIM4_IRQHandler ; TIM4 + DCD I2C1_EV_IRQHandler ; I2C1 Event + DCD I2C1_ER_IRQHandler ; I2C1 Error + DCD I2C2_EV_IRQHandler ; I2C2 Event + DCD I2C2_ER_IRQHandler ; I2C2 Error + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_IRQHandler ; USART3 + DCD EXTI15_10_IRQHandler ; EXTI Line 15..10 + DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line + DCD CEC_IRQHandler ; HDMI-CEC + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD TIM6_DAC_IRQHandler ; TIM6 and DAC underrun + DCD TIM7_IRQHandler ; TIM7 +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +; Dummy Exception Handlers (infinite loops which can be modified) + +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC + + EXPORT WWDG_IRQHandler [WEAK] + EXPORT PVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_IRQHandler [WEAK] + EXPORT DMA1_Channel4_IRQHandler [WEAK] + EXPORT DMA1_Channel5_IRQHandler [WEAK] + EXPORT DMA1_Channel6_IRQHandler [WEAK] + EXPORT DMA1_Channel7_IRQHandler [WEAK] + EXPORT ADC1_IRQHandler [WEAK] + EXPORT EXTI9_5_IRQHandler [WEAK] + EXPORT TIM1_BRK_TIM15_IRQHandler [WEAK] + EXPORT TIM1_UP_TIM16_IRQHandler [WEAK] + EXPORT TIM1_TRG_COM_TIM17_IRQHandler [WEAK] + EXPORT TIM1_CC_IRQHandler [WEAK] + EXPORT TIM2_IRQHandler [WEAK] + EXPORT TIM3_IRQHandler [WEAK] + EXPORT TIM4_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT I2C2_EV_IRQHandler [WEAK] + EXPORT I2C2_ER_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT USART3_IRQHandler [WEAK] + EXPORT EXTI15_10_IRQHandler [WEAK] + EXPORT RTCAlarm_IRQHandler [WEAK] + EXPORT CEC_IRQHandler [WEAK] + EXPORT TIM6_DAC_IRQHandler [WEAK] + EXPORT TIM7_IRQHandler [WEAK] + +WWDG_IRQHandler +PVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FLASH_IRQHandler +RCC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_IRQHandler +DMA1_Channel4_IRQHandler +DMA1_Channel5_IRQHandler +DMA1_Channel6_IRQHandler +DMA1_Channel7_IRQHandler +ADC1_IRQHandler +EXTI9_5_IRQHandler +TIM1_BRK_TIM15_IRQHandler +TIM1_UP_TIM16_IRQHandler +TIM1_TRG_COM_TIM17_IRQHandler +TIM1_CC_IRQHandler +TIM2_IRQHandler +TIM3_IRQHandler +TIM4_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +I2C2_EV_IRQHandler +I2C2_ER_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +USART3_IRQHandler +EXTI15_10_IRQHandler +RTCAlarm_IRQHandler +CEC_IRQHandler +TIM6_DAC_IRQHandler +TIM7_IRQHandler + B . + + ENDP + + ALIGN + +;******************************************************************************* +; User Stack and Heap initialization +;******************************************************************************* + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap + + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + + ALIGN + + ENDIF + + END + +;******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE***** diff --git a/Start/startup_stm32f10x_xl.s b/Start/startup_stm32f10x_xl.s new file mode 100644 index 0000000..9fbc640 --- /dev/null +++ b/Start/startup_stm32f10x_xl.s @@ -0,0 +1,358 @@ +;******************** (C) COPYRIGHT 2011 STMicroelectronics ******************** +;* File Name : startup_stm32f10x_xl.s +;* Author : MCD Application Team +;* Version : V3.5.0 +;* Date : 11-March-2011 +;* Description : STM32F10x XL-Density Devices vector table for MDK-ARM +;* toolchain. +;* This module performs: +;* - Set the initial SP +;* - Set the initial PC == Reset_Handler +;* - Set the vector table entries with the exceptions ISR address +;* - Configure the clock system and also configure the external +;* SRAM mounted on STM3210E-EVAL board to be used as data +;* memory (optional, to be enabled by user) +;* - Branches to __main in the C library (which eventually +;* calls main()). +;* After Reset the CortexM3 processor is in Thread mode, +;* priority is Privileged, and the Stack is set to Main. +;* <<< Use Configuration Wizard in Context Menu >>> +;******************************************************************************* +; THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +; WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +; AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +; INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +; CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +; INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +;******************************************************************************* + +; Amount of memory (in bytes) allocated for Stack +; Tailor this value to your application needs +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00000200 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + PRESERVE8 + THUMB + + +; Vector Table Mapped to Address 0 at Reset + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDG_IRQHandler ; Window Watchdog + DCD PVD_IRQHandler ; PVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Tamper + DCD RTC_IRQHandler ; RTC + DCD FLASH_IRQHandler ; Flash + DCD RCC_IRQHandler ; RCC + DCD EXTI0_IRQHandler ; EXTI Line 0 + DCD EXTI1_IRQHandler ; EXTI Line 1 + DCD EXTI2_IRQHandler ; EXTI Line 2 + DCD EXTI3_IRQHandler ; EXTI Line 3 + DCD EXTI4_IRQHandler ; EXTI Line 4 + DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2 + DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3 + DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4 + DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5 + DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6 + DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7 + DCD ADC1_2_IRQHandler ; ADC1 & ADC2 + DCD USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TX + DCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; CAN1 RX1 + DCD CAN1_SCE_IRQHandler ; CAN1 SCE + DCD EXTI9_5_IRQHandler ; EXTI Line 9..5 + DCD TIM1_BRK_TIM9_IRQHandler ; TIM1 Break and TIM9 + DCD TIM1_UP_TIM10_IRQHandler ; TIM1 Update and TIM10 + DCD TIM1_TRG_COM_TIM11_IRQHandler ; TIM1 Trigger and Commutation and TIM11 + DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare + DCD TIM2_IRQHandler ; TIM2 + DCD TIM3_IRQHandler ; TIM3 + DCD TIM4_IRQHandler ; TIM4 + DCD I2C1_EV_IRQHandler ; I2C1 Event + DCD I2C1_ER_IRQHandler ; I2C1 Error + DCD I2C2_EV_IRQHandler ; I2C2 Event + DCD I2C2_ER_IRQHandler ; I2C2 Error + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_IRQHandler ; USART3 + DCD EXTI15_10_IRQHandler ; EXTI Line 15..10 + DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line + DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend + DCD TIM8_BRK_TIM12_IRQHandler ; TIM8 Break and TIM12 + DCD TIM8_UP_TIM13_IRQHandler ; TIM8 Update and TIM13 + DCD TIM8_TRG_COM_TIM14_IRQHandler ; TIM8 Trigger and Commutation and TIM14 + DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare + DCD ADC3_IRQHandler ; ADC3 + DCD FSMC_IRQHandler ; FSMC + DCD SDIO_IRQHandler ; SDIO + DCD TIM5_IRQHandler ; TIM5 + DCD SPI3_IRQHandler ; SPI3 + DCD UART4_IRQHandler ; UART4 + DCD UART5_IRQHandler ; UART5 + DCD TIM6_IRQHandler ; TIM6 + DCD TIM7_IRQHandler ; TIM7 + DCD DMA2_Channel1_IRQHandler ; DMA2 Channel1 + DCD DMA2_Channel2_IRQHandler ; DMA2 Channel2 + DCD DMA2_Channel3_IRQHandler ; DMA2 Channel3 + DCD DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5 +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +; Dummy Exception Handlers (infinite loops which can be modified) + +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC + + EXPORT WWDG_IRQHandler [WEAK] + EXPORT PVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_IRQHandler [WEAK] + EXPORT DMA1_Channel4_IRQHandler [WEAK] + EXPORT DMA1_Channel5_IRQHandler [WEAK] + EXPORT DMA1_Channel6_IRQHandler [WEAK] + EXPORT DMA1_Channel7_IRQHandler [WEAK] + EXPORT ADC1_2_IRQHandler [WEAK] + EXPORT USB_HP_CAN1_TX_IRQHandler [WEAK] + EXPORT USB_LP_CAN1_RX0_IRQHandler [WEAK] + EXPORT CAN1_RX1_IRQHandler [WEAK] + EXPORT CAN1_SCE_IRQHandler [WEAK] + EXPORT EXTI9_5_IRQHandler [WEAK] + EXPORT TIM1_BRK_TIM9_IRQHandler [WEAK] + EXPORT TIM1_UP_TIM10_IRQHandler [WEAK] + EXPORT TIM1_TRG_COM_TIM11_IRQHandler [WEAK] + EXPORT TIM1_CC_IRQHandler [WEAK] + EXPORT TIM2_IRQHandler [WEAK] + EXPORT TIM3_IRQHandler [WEAK] + EXPORT TIM4_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT I2C2_EV_IRQHandler [WEAK] + EXPORT I2C2_ER_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT USART3_IRQHandler [WEAK] + EXPORT EXTI15_10_IRQHandler [WEAK] + EXPORT RTCAlarm_IRQHandler [WEAK] + EXPORT USBWakeUp_IRQHandler [WEAK] + EXPORT TIM8_BRK_TIM12_IRQHandler [WEAK] + EXPORT TIM8_UP_TIM13_IRQHandler [WEAK] + EXPORT TIM8_TRG_COM_TIM14_IRQHandler [WEAK] + EXPORT TIM8_CC_IRQHandler [WEAK] + EXPORT ADC3_IRQHandler [WEAK] + EXPORT FSMC_IRQHandler [WEAK] + EXPORT SDIO_IRQHandler [WEAK] + EXPORT TIM5_IRQHandler [WEAK] + EXPORT SPI3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT UART5_IRQHandler [WEAK] + EXPORT TIM6_IRQHandler [WEAK] + EXPORT TIM7_IRQHandler [WEAK] + EXPORT DMA2_Channel1_IRQHandler [WEAK] + EXPORT DMA2_Channel2_IRQHandler [WEAK] + EXPORT DMA2_Channel3_IRQHandler [WEAK] + EXPORT DMA2_Channel4_5_IRQHandler [WEAK] + +WWDG_IRQHandler +PVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FLASH_IRQHandler +RCC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_IRQHandler +DMA1_Channel4_IRQHandler +DMA1_Channel5_IRQHandler +DMA1_Channel6_IRQHandler +DMA1_Channel7_IRQHandler +ADC1_2_IRQHandler +USB_HP_CAN1_TX_IRQHandler +USB_LP_CAN1_RX0_IRQHandler +CAN1_RX1_IRQHandler +CAN1_SCE_IRQHandler +EXTI9_5_IRQHandler +TIM1_BRK_TIM9_IRQHandler +TIM1_UP_TIM10_IRQHandler +TIM1_TRG_COM_TIM11_IRQHandler +TIM1_CC_IRQHandler +TIM2_IRQHandler +TIM3_IRQHandler +TIM4_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +I2C2_EV_IRQHandler +I2C2_ER_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +USART3_IRQHandler +EXTI15_10_IRQHandler +RTCAlarm_IRQHandler +USBWakeUp_IRQHandler +TIM8_BRK_TIM12_IRQHandler +TIM8_UP_TIM13_IRQHandler +TIM8_TRG_COM_TIM14_IRQHandler +TIM8_CC_IRQHandler +ADC3_IRQHandler +FSMC_IRQHandler +SDIO_IRQHandler +TIM5_IRQHandler +SPI3_IRQHandler +UART4_IRQHandler +UART5_IRQHandler +TIM6_IRQHandler +TIM7_IRQHandler +DMA2_Channel1_IRQHandler +DMA2_Channel2_IRQHandler +DMA2_Channel3_IRQHandler +DMA2_Channel4_5_IRQHandler + B . + + ENDP + + ALIGN + +;******************************************************************************* +; User Stack and Heap initialization +;******************************************************************************* + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap + + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + + ALIGN + + ENDIF + + END + +;******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE***** diff --git a/Start/stm32f10x.h b/Start/stm32f10x.h new file mode 100644 index 0000000..8bf7624 --- /dev/null +++ b/Start/stm32f10x.h @@ -0,0 +1,8336 @@ +/** + ****************************************************************************** + * @file stm32f10x.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief CMSIS Cortex-M3 Device Peripheral Access Layer Header File. + * This file contains all the peripheral register's definitions, bits + * definitions and memory mapping for STM32F10x Connectivity line, + * High density, High density value line, Medium density, + * Medium density Value line, Low density, Low density Value line + * and XL-density devices. + * + * The file is the unique include file that the application programmer + * is using in the C source code, usually in main.c. This file contains: + * - Configuration section that allows to select: + * - The device used in the target application + * - To use or not the peripheral’s drivers in application code(i.e. + * code will be based on direct access to peripheral’s registers + * rather than drivers API), this option is controlled by + * "#define USE_STDPERIPH_DRIVER" + * - To change few application-specific parameters such as the HSE + * crystal frequency + * - Data structures and the address mapping for all peripherals + * - Peripheral's registers declarations and bits definition + * - Macros to access peripheral’s registers hardware + * + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

    © COPYRIGHT 2011 STMicroelectronics

    + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f10x + * @{ + */ + +#ifndef __STM32F10x_H +#define __STM32F10x_H + +#ifdef __cplusplus + extern "C" { +#endif + +/** @addtogroup Library_configuration_section + * @{ + */ + +/* Uncomment the line below according to the target STM32 device used in your + application + */ + +#if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) && !defined (STM32F10X_MD) && !defined (STM32F10X_MD_VL) && !defined (STM32F10X_HD) && !defined (STM32F10X_HD_VL) && !defined (STM32F10X_XL) && !defined (STM32F10X_CL) + /* #define STM32F10X_LD */ /*!< STM32F10X_LD: STM32 Low density devices */ + /* #define STM32F10X_LD_VL */ /*!< STM32F10X_LD_VL: STM32 Low density Value Line devices */ + /* #define STM32F10X_MD */ /*!< STM32F10X_MD: STM32 Medium density devices */ + /* #define STM32F10X_MD_VL */ /*!< STM32F10X_MD_VL: STM32 Medium density Value Line devices */ + /* #define STM32F10X_HD */ /*!< STM32F10X_HD: STM32 High density devices */ + /* #define STM32F10X_HD_VL */ /*!< STM32F10X_HD_VL: STM32 High density value line devices */ + /* #define STM32F10X_XL */ /*!< STM32F10X_XL: STM32 XL-density devices */ + /* #define STM32F10X_CL */ /*!< STM32F10X_CL: STM32 Connectivity line devices */ +#endif +/* Tip: To avoid modifying this file each time you need to switch between these + devices, you can define the device in your toolchain compiler preprocessor. + + - Low-density devices are STM32F101xx, STM32F102xx and STM32F103xx microcontrollers + where the Flash memory density ranges between 16 and 32 Kbytes. + - Low-density value line devices are STM32F100xx microcontrollers where the Flash + memory density ranges between 16 and 32 Kbytes. + - Medium-density devices are STM32F101xx, STM32F102xx and STM32F103xx microcontrollers + where the Flash memory density ranges between 64 and 128 Kbytes. + - Medium-density value line devices are STM32F100xx microcontrollers where the + Flash memory density ranges between 64 and 128 Kbytes. + - High-density devices are STM32F101xx and STM32F103xx microcontrollers where + the Flash memory density ranges between 256 and 512 Kbytes. + - High-density value line devices are STM32F100xx microcontrollers where the + Flash memory density ranges between 256 and 512 Kbytes. + - XL-density devices are STM32F101xx and STM32F103xx microcontrollers where + the Flash memory density ranges between 512 and 1024 Kbytes. + - Connectivity line devices are STM32F105xx and STM32F107xx microcontrollers. + */ + +#if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) && !defined (STM32F10X_MD) && !defined (STM32F10X_MD_VL) && !defined (STM32F10X_HD) && !defined (STM32F10X_HD_VL) && !defined (STM32F10X_XL) && !defined (STM32F10X_CL) + #error "Please select first the target STM32F10x device used in your application (in stm32f10x.h file)" +#endif + +#if !defined USE_STDPERIPH_DRIVER +/** + * @brief Comment the line below if you will not use the peripherals drivers. + In this case, these drivers will not be included and the application code will + be based on direct access to peripherals registers + */ + /*#define USE_STDPERIPH_DRIVER*/ +#endif + +/** + * @brief In the following line adjust the value of External High Speed oscillator (HSE) + used in your application + + Tip: To avoid modifying this file each time you need to use different HSE, you + can define the HSE value in your toolchain compiler preprocessor. + */ +#if !defined HSE_VALUE + #ifdef STM32F10X_CL + #define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */ + #else + #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ + #endif /* STM32F10X_CL */ +#endif /* HSE_VALUE */ + + +/** + * @brief In the following line adjust the External High Speed oscillator (HSE) Startup + Timeout value + */ +#define HSE_STARTUP_TIMEOUT ((uint16_t)0x0500) /*!< Time out for HSE start up */ + +#define HSI_VALUE ((uint32_t)8000000) /*!< Value of the Internal oscillator in Hz*/ + +/** + * @brief STM32F10x Standard Peripheral Library version number + */ +#define __STM32F10X_STDPERIPH_VERSION_MAIN (0x03) /*!< [31:24] main version */ +#define __STM32F10X_STDPERIPH_VERSION_SUB1 (0x05) /*!< [23:16] sub1 version */ +#define __STM32F10X_STDPERIPH_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */ +#define __STM32F10X_STDPERIPH_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __STM32F10X_STDPERIPH_VERSION ( (__STM32F10X_STDPERIPH_VERSION_MAIN << 24)\ + |(__STM32F10X_STDPERIPH_VERSION_SUB1 << 16)\ + |(__STM32F10X_STDPERIPH_VERSION_SUB2 << 8)\ + |(__STM32F10X_STDPERIPH_VERSION_RC)) + +/** + * @} + */ + +/** @addtogroup Configuration_section_for_CMSIS + * @{ + */ + +/** + * @brief Configuration of the Cortex-M3 Processor and Core Peripherals + */ +#ifdef STM32F10X_XL + #define __MPU_PRESENT 1 /*!< STM32 XL-density devices provide an MPU */ +#else + #define __MPU_PRESENT 0 /*!< Other STM32 devices does not provide an MPU */ +#endif /* STM32F10X_XL */ +#define __NVIC_PRIO_BITS 4 /*!< STM32 uses 4 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ + +/** + * @brief STM32F10x Interrupt Number Definition, according to the selected device + * in @ref Library_configuration_section + */ +typedef enum IRQn +{ +/****** Cortex-M3 Processor Exceptions Numbers ***************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M3 Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */ + +/****** STM32 specific Interrupt Numbers *********************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ + PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */ + TAMPER_IRQn = 2, /*!< Tamper Interrupt */ + RTC_IRQn = 3, /*!< RTC global Interrupt */ + FLASH_IRQn = 4, /*!< FLASH global Interrupt */ + RCC_IRQn = 5, /*!< RCC global Interrupt */ + EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */ + EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */ + EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ + EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */ + EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */ + DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */ + DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */ + DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */ + DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */ + DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */ + DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */ + DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */ + +#ifdef STM32F10X_LD + ADC1_2_IRQn = 18, /*!< ADC1 and ADC2 global Interrupt */ + USB_HP_CAN1_TX_IRQn = 19, /*!< USB Device High Priority or CAN1 TX Interrupts */ + USB_LP_CAN1_RX0_IRQn = 20, /*!< USB Device Low Priority or CAN1 RX0 Interrupts */ + CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ + CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_IRQn = 24, /*!< TIM1 Break Interrupt */ + TIM1_UP_IRQn = 25, /*!< TIM1 Update Interrupt */ + TIM1_TRG_COM_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTCAlarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */ + USBWakeUp_IRQn = 42 /*!< USB Device WakeUp from suspend through EXTI Line Interrupt */ +#endif /* STM32F10X_LD */ + +#ifdef STM32F10X_LD_VL + ADC1_IRQn = 18, /*!< ADC1 global Interrupt */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_TIM15_IRQn = 24, /*!< TIM1 Break and TIM15 Interrupts */ + TIM1_UP_TIM16_IRQn = 25, /*!< TIM1 Update and TIM16 Interrupts */ + TIM1_TRG_COM_TIM17_IRQn = 26, /*!< TIM1 Trigger and Commutation and TIM17 Interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTCAlarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */ + CEC_IRQn = 42, /*!< HDMI-CEC Interrupt */ + TIM6_DAC_IRQn = 54, /*!< TIM6 and DAC underrun Interrupt */ + TIM7_IRQn = 55 /*!< TIM7 Interrupt */ +#endif /* STM32F10X_LD_VL */ + +#ifdef STM32F10X_MD + ADC1_2_IRQn = 18, /*!< ADC1 and ADC2 global Interrupt */ + USB_HP_CAN1_TX_IRQn = 19, /*!< USB Device High Priority or CAN1 TX Interrupts */ + USB_LP_CAN1_RX0_IRQn = 20, /*!< USB Device Low Priority or CAN1 RX0 Interrupts */ + CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ + CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_IRQn = 24, /*!< TIM1 Break Interrupt */ + TIM1_UP_IRQn = 25, /*!< TIM1 Update Interrupt */ + TIM1_TRG_COM_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ + I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + USART3_IRQn = 39, /*!< USART3 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTCAlarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */ + USBWakeUp_IRQn = 42 /*!< USB Device WakeUp from suspend through EXTI Line Interrupt */ +#endif /* STM32F10X_MD */ + +#ifdef STM32F10X_MD_VL + ADC1_IRQn = 18, /*!< ADC1 global Interrupt */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_TIM15_IRQn = 24, /*!< TIM1 Break and TIM15 Interrupts */ + TIM1_UP_TIM16_IRQn = 25, /*!< TIM1 Update and TIM16 Interrupts */ + TIM1_TRG_COM_TIM17_IRQn = 26, /*!< TIM1 Trigger and Commutation and TIM17 Interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ + I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + USART3_IRQn = 39, /*!< USART3 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTCAlarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */ + CEC_IRQn = 42, /*!< HDMI-CEC Interrupt */ + TIM6_DAC_IRQn = 54, /*!< TIM6 and DAC underrun Interrupt */ + TIM7_IRQn = 55 /*!< TIM7 Interrupt */ +#endif /* STM32F10X_MD_VL */ + +#ifdef STM32F10X_HD + ADC1_2_IRQn = 18, /*!< ADC1 and ADC2 global Interrupt */ + USB_HP_CAN1_TX_IRQn = 19, /*!< USB Device High Priority or CAN1 TX Interrupts */ + USB_LP_CAN1_RX0_IRQn = 20, /*!< USB Device Low Priority or CAN1 RX0 Interrupts */ + CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ + CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_IRQn = 24, /*!< TIM1 Break Interrupt */ + TIM1_UP_IRQn = 25, /*!< TIM1 Update Interrupt */ + TIM1_TRG_COM_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ + I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + USART3_IRQn = 39, /*!< USART3 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTCAlarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */ + USBWakeUp_IRQn = 42, /*!< USB Device WakeUp from suspend through EXTI Line Interrupt */ + TIM8_BRK_IRQn = 43, /*!< TIM8 Break Interrupt */ + TIM8_UP_IRQn = 44, /*!< TIM8 Update Interrupt */ + TIM8_TRG_COM_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt */ + TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */ + ADC3_IRQn = 47, /*!< ADC3 global Interrupt */ + FSMC_IRQn = 48, /*!< FSMC global Interrupt */ + SDIO_IRQn = 49, /*!< SDIO global Interrupt */ + TIM5_IRQn = 50, /*!< TIM5 global Interrupt */ + SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ + UART4_IRQn = 52, /*!< UART4 global Interrupt */ + UART5_IRQn = 53, /*!< UART5 global Interrupt */ + TIM6_IRQn = 54, /*!< TIM6 global Interrupt */ + TIM7_IRQn = 55, /*!< TIM7 global Interrupt */ + DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 global Interrupt */ + DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 global Interrupt */ + DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 global Interrupt */ + DMA2_Channel4_5_IRQn = 59 /*!< DMA2 Channel 4 and Channel 5 global Interrupt */ +#endif /* STM32F10X_HD */ + +#ifdef STM32F10X_HD_VL + ADC1_IRQn = 18, /*!< ADC1 global Interrupt */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_TIM15_IRQn = 24, /*!< TIM1 Break and TIM15 Interrupts */ + TIM1_UP_TIM16_IRQn = 25, /*!< TIM1 Update and TIM16 Interrupts */ + TIM1_TRG_COM_TIM17_IRQn = 26, /*!< TIM1 Trigger and Commutation and TIM17 Interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ + I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + USART3_IRQn = 39, /*!< USART3 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTCAlarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */ + CEC_IRQn = 42, /*!< HDMI-CEC Interrupt */ + TIM12_IRQn = 43, /*!< TIM12 global Interrupt */ + TIM13_IRQn = 44, /*!< TIM13 global Interrupt */ + TIM14_IRQn = 45, /*!< TIM14 global Interrupt */ + TIM5_IRQn = 50, /*!< TIM5 global Interrupt */ + SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ + UART4_IRQn = 52, /*!< UART4 global Interrupt */ + UART5_IRQn = 53, /*!< UART5 global Interrupt */ + TIM6_DAC_IRQn = 54, /*!< TIM6 and DAC underrun Interrupt */ + TIM7_IRQn = 55, /*!< TIM7 Interrupt */ + DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 global Interrupt */ + DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 global Interrupt */ + DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 global Interrupt */ + DMA2_Channel4_5_IRQn = 59, /*!< DMA2 Channel 4 and Channel 5 global Interrupt */ + DMA2_Channel5_IRQn = 60 /*!< DMA2 Channel 5 global Interrupt (DMA2 Channel 5 is + mapped at position 60 only if the MISC_REMAP bit in + the AFIO_MAPR2 register is set) */ +#endif /* STM32F10X_HD_VL */ + +#ifdef STM32F10X_XL + ADC1_2_IRQn = 18, /*!< ADC1 and ADC2 global Interrupt */ + USB_HP_CAN1_TX_IRQn = 19, /*!< USB Device High Priority or CAN1 TX Interrupts */ + USB_LP_CAN1_RX0_IRQn = 20, /*!< USB Device Low Priority or CAN1 RX0 Interrupts */ + CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ + CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_TIM9_IRQn = 24, /*!< TIM1 Break Interrupt and TIM9 global Interrupt */ + TIM1_UP_TIM10_IRQn = 25, /*!< TIM1 Update Interrupt and TIM10 global Interrupt */ + TIM1_TRG_COM_TIM11_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt and TIM11 global interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ + I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + USART3_IRQn = 39, /*!< USART3 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTCAlarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */ + USBWakeUp_IRQn = 42, /*!< USB Device WakeUp from suspend through EXTI Line Interrupt */ + TIM8_BRK_TIM12_IRQn = 43, /*!< TIM8 Break Interrupt and TIM12 global Interrupt */ + TIM8_UP_TIM13_IRQn = 44, /*!< TIM8 Update Interrupt and TIM13 global Interrupt */ + TIM8_TRG_COM_TIM14_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */ + TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */ + ADC3_IRQn = 47, /*!< ADC3 global Interrupt */ + FSMC_IRQn = 48, /*!< FSMC global Interrupt */ + SDIO_IRQn = 49, /*!< SDIO global Interrupt */ + TIM5_IRQn = 50, /*!< TIM5 global Interrupt */ + SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ + UART4_IRQn = 52, /*!< UART4 global Interrupt */ + UART5_IRQn = 53, /*!< UART5 global Interrupt */ + TIM6_IRQn = 54, /*!< TIM6 global Interrupt */ + TIM7_IRQn = 55, /*!< TIM7 global Interrupt */ + DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 global Interrupt */ + DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 global Interrupt */ + DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 global Interrupt */ + DMA2_Channel4_5_IRQn = 59 /*!< DMA2 Channel 4 and Channel 5 global Interrupt */ +#endif /* STM32F10X_XL */ + +#ifdef STM32F10X_CL + ADC1_2_IRQn = 18, /*!< ADC1 and ADC2 global Interrupt */ + CAN1_TX_IRQn = 19, /*!< USB Device High Priority or CAN1 TX Interrupts */ + CAN1_RX0_IRQn = 20, /*!< USB Device Low Priority or CAN1 RX0 Interrupts */ + CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ + CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_IRQn = 24, /*!< TIM1 Break Interrupt */ + TIM1_UP_IRQn = 25, /*!< TIM1 Update Interrupt */ + TIM1_TRG_COM_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ + I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + USART3_IRQn = 39, /*!< USART3 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTCAlarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */ + OTG_FS_WKUP_IRQn = 42, /*!< USB OTG FS WakeUp from suspend through EXTI Line Interrupt */ + TIM5_IRQn = 50, /*!< TIM5 global Interrupt */ + SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ + UART4_IRQn = 52, /*!< UART4 global Interrupt */ + UART5_IRQn = 53, /*!< UART5 global Interrupt */ + TIM6_IRQn = 54, /*!< TIM6 global Interrupt */ + TIM7_IRQn = 55, /*!< TIM7 global Interrupt */ + DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 global Interrupt */ + DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 global Interrupt */ + DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 global Interrupt */ + DMA2_Channel4_IRQn = 59, /*!< DMA2 Channel 4 global Interrupt */ + DMA2_Channel5_IRQn = 60, /*!< DMA2 Channel 5 global Interrupt */ + ETH_IRQn = 61, /*!< Ethernet global Interrupt */ + ETH_WKUP_IRQn = 62, /*!< Ethernet Wakeup through EXTI line Interrupt */ + CAN2_TX_IRQn = 63, /*!< CAN2 TX Interrupt */ + CAN2_RX0_IRQn = 64, /*!< CAN2 RX0 Interrupt */ + CAN2_RX1_IRQn = 65, /*!< CAN2 RX1 Interrupt */ + CAN2_SCE_IRQn = 66, /*!< CAN2 SCE Interrupt */ + OTG_FS_IRQn = 67 /*!< USB OTG FS global Interrupt */ +#endif /* STM32F10X_CL */ +} IRQn_Type; + +/** + * @} + */ + +#include "core_cm3.h" +#include "system_stm32f10x.h" +#include + +/** @addtogroup Exported_types + * @{ + */ + +/*!< STM32F10x Standard Peripheral Library old types (maintained for legacy purpose) */ +typedef int32_t s32; +typedef int16_t s16; +typedef int8_t s8; + +typedef const int32_t sc32; /*!< Read Only */ +typedef const int16_t sc16; /*!< Read Only */ +typedef const int8_t sc8; /*!< Read Only */ + +typedef __IO int32_t vs32; +typedef __IO int16_t vs16; +typedef __IO int8_t vs8; + +typedef __I int32_t vsc32; /*!< Read Only */ +typedef __I int16_t vsc16; /*!< Read Only */ +typedef __I int8_t vsc8; /*!< Read Only */ + +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; + +typedef const uint32_t uc32; /*!< Read Only */ +typedef const uint16_t uc16; /*!< Read Only */ +typedef const uint8_t uc8; /*!< Read Only */ + +typedef __IO uint32_t vu32; +typedef __IO uint16_t vu16; +typedef __IO uint8_t vu8; + +typedef __I uint32_t vuc32; /*!< Read Only */ +typedef __I uint16_t vuc16; /*!< Read Only */ +typedef __I uint8_t vuc8; /*!< Read Only */ + +typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; + +typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; +#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE)) + +typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus; + +/*!< STM32F10x Standard Peripheral Library old definitions (maintained for legacy purpose) */ +#define HSEStartUp_TimeOut HSE_STARTUP_TIMEOUT +#define HSE_Value HSE_VALUE +#define HSI_Value HSI_VALUE +/** + * @} + */ + +/** @addtogroup Peripheral_registers_structures + * @{ + */ + +/** + * @brief Analog to Digital Converter + */ + +typedef struct +{ + __IO uint32_t SR; + __IO uint32_t CR1; + __IO uint32_t CR2; + __IO uint32_t SMPR1; + __IO uint32_t SMPR2; + __IO uint32_t JOFR1; + __IO uint32_t JOFR2; + __IO uint32_t JOFR3; + __IO uint32_t JOFR4; + __IO uint32_t HTR; + __IO uint32_t LTR; + __IO uint32_t SQR1; + __IO uint32_t SQR2; + __IO uint32_t SQR3; + __IO uint32_t JSQR; + __IO uint32_t JDR1; + __IO uint32_t JDR2; + __IO uint32_t JDR3; + __IO uint32_t JDR4; + __IO uint32_t DR; +} ADC_TypeDef; + +/** + * @brief Backup Registers + */ + +typedef struct +{ + uint32_t RESERVED0; + __IO uint16_t DR1; + uint16_t RESERVED1; + __IO uint16_t DR2; + uint16_t RESERVED2; + __IO uint16_t DR3; + uint16_t RESERVED3; + __IO uint16_t DR4; + uint16_t RESERVED4; + __IO uint16_t DR5; + uint16_t RESERVED5; + __IO uint16_t DR6; + uint16_t RESERVED6; + __IO uint16_t DR7; + uint16_t RESERVED7; + __IO uint16_t DR8; + uint16_t RESERVED8; + __IO uint16_t DR9; + uint16_t RESERVED9; + __IO uint16_t DR10; + uint16_t RESERVED10; + __IO uint16_t RTCCR; + uint16_t RESERVED11; + __IO uint16_t CR; + uint16_t RESERVED12; + __IO uint16_t CSR; + uint16_t RESERVED13[5]; + __IO uint16_t DR11; + uint16_t RESERVED14; + __IO uint16_t DR12; + uint16_t RESERVED15; + __IO uint16_t DR13; + uint16_t RESERVED16; + __IO uint16_t DR14; + uint16_t RESERVED17; + __IO uint16_t DR15; + uint16_t RESERVED18; + __IO uint16_t DR16; + uint16_t RESERVED19; + __IO uint16_t DR17; + uint16_t RESERVED20; + __IO uint16_t DR18; + uint16_t RESERVED21; + __IO uint16_t DR19; + uint16_t RESERVED22; + __IO uint16_t DR20; + uint16_t RESERVED23; + __IO uint16_t DR21; + uint16_t RESERVED24; + __IO uint16_t DR22; + uint16_t RESERVED25; + __IO uint16_t DR23; + uint16_t RESERVED26; + __IO uint16_t DR24; + uint16_t RESERVED27; + __IO uint16_t DR25; + uint16_t RESERVED28; + __IO uint16_t DR26; + uint16_t RESERVED29; + __IO uint16_t DR27; + uint16_t RESERVED30; + __IO uint16_t DR28; + uint16_t RESERVED31; + __IO uint16_t DR29; + uint16_t RESERVED32; + __IO uint16_t DR30; + uint16_t RESERVED33; + __IO uint16_t DR31; + uint16_t RESERVED34; + __IO uint16_t DR32; + uint16_t RESERVED35; + __IO uint16_t DR33; + uint16_t RESERVED36; + __IO uint16_t DR34; + uint16_t RESERVED37; + __IO uint16_t DR35; + uint16_t RESERVED38; + __IO uint16_t DR36; + uint16_t RESERVED39; + __IO uint16_t DR37; + uint16_t RESERVED40; + __IO uint16_t DR38; + uint16_t RESERVED41; + __IO uint16_t DR39; + uint16_t RESERVED42; + __IO uint16_t DR40; + uint16_t RESERVED43; + __IO uint16_t DR41; + uint16_t RESERVED44; + __IO uint16_t DR42; + uint16_t RESERVED45; +} BKP_TypeDef; + +/** + * @brief Controller Area Network TxMailBox + */ + +typedef struct +{ + __IO uint32_t TIR; + __IO uint32_t TDTR; + __IO uint32_t TDLR; + __IO uint32_t TDHR; +} CAN_TxMailBox_TypeDef; + +/** + * @brief Controller Area Network FIFOMailBox + */ + +typedef struct +{ + __IO uint32_t RIR; + __IO uint32_t RDTR; + __IO uint32_t RDLR; + __IO uint32_t RDHR; +} CAN_FIFOMailBox_TypeDef; + +/** + * @brief Controller Area Network FilterRegister + */ + +typedef struct +{ + __IO uint32_t FR1; + __IO uint32_t FR2; +} CAN_FilterRegister_TypeDef; + +/** + * @brief Controller Area Network + */ + +typedef struct +{ + __IO uint32_t MCR; + __IO uint32_t MSR; + __IO uint32_t TSR; + __IO uint32_t RF0R; + __IO uint32_t RF1R; + __IO uint32_t IER; + __IO uint32_t ESR; + __IO uint32_t BTR; + uint32_t RESERVED0[88]; + CAN_TxMailBox_TypeDef sTxMailBox[3]; + CAN_FIFOMailBox_TypeDef sFIFOMailBox[2]; + uint32_t RESERVED1[12]; + __IO uint32_t FMR; + __IO uint32_t FM1R; + uint32_t RESERVED2; + __IO uint32_t FS1R; + uint32_t RESERVED3; + __IO uint32_t FFA1R; + uint32_t RESERVED4; + __IO uint32_t FA1R; + uint32_t RESERVED5[8]; +#ifndef STM32F10X_CL + CAN_FilterRegister_TypeDef sFilterRegister[14]; +#else + CAN_FilterRegister_TypeDef sFilterRegister[28]; +#endif /* STM32F10X_CL */ +} CAN_TypeDef; + +/** + * @brief Consumer Electronics Control (CEC) + */ +typedef struct +{ + __IO uint32_t CFGR; + __IO uint32_t OAR; + __IO uint32_t PRES; + __IO uint32_t ESR; + __IO uint32_t CSR; + __IO uint32_t TXD; + __IO uint32_t RXD; +} CEC_TypeDef; + +/** + * @brief CRC calculation unit + */ + +typedef struct +{ + __IO uint32_t DR; + __IO uint8_t IDR; + uint8_t RESERVED0; + uint16_t RESERVED1; + __IO uint32_t CR; +} CRC_TypeDef; + +/** + * @brief Digital to Analog Converter + */ + +typedef struct +{ + __IO uint32_t CR; + __IO uint32_t SWTRIGR; + __IO uint32_t DHR12R1; + __IO uint32_t DHR12L1; + __IO uint32_t DHR8R1; + __IO uint32_t DHR12R2; + __IO uint32_t DHR12L2; + __IO uint32_t DHR8R2; + __IO uint32_t DHR12RD; + __IO uint32_t DHR12LD; + __IO uint32_t DHR8RD; + __IO uint32_t DOR1; + __IO uint32_t DOR2; +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) + __IO uint32_t SR; +#endif +} DAC_TypeDef; + +/** + * @brief Debug MCU + */ + +typedef struct +{ + __IO uint32_t IDCODE; + __IO uint32_t CR; +}DBGMCU_TypeDef; + +/** + * @brief DMA Controller + */ + +typedef struct +{ + __IO uint32_t CCR; + __IO uint32_t CNDTR; + __IO uint32_t CPAR; + __IO uint32_t CMAR; +} DMA_Channel_TypeDef; + +typedef struct +{ + __IO uint32_t ISR; + __IO uint32_t IFCR; +} DMA_TypeDef; + +/** + * @brief Ethernet MAC + */ + +typedef struct +{ + __IO uint32_t MACCR; + __IO uint32_t MACFFR; + __IO uint32_t MACHTHR; + __IO uint32_t MACHTLR; + __IO uint32_t MACMIIAR; + __IO uint32_t MACMIIDR; + __IO uint32_t MACFCR; + __IO uint32_t MACVLANTR; /* 8 */ + uint32_t RESERVED0[2]; + __IO uint32_t MACRWUFFR; /* 11 */ + __IO uint32_t MACPMTCSR; + uint32_t RESERVED1[2]; + __IO uint32_t MACSR; /* 15 */ + __IO uint32_t MACIMR; + __IO uint32_t MACA0HR; + __IO uint32_t MACA0LR; + __IO uint32_t MACA1HR; + __IO uint32_t MACA1LR; + __IO uint32_t MACA2HR; + __IO uint32_t MACA2LR; + __IO uint32_t MACA3HR; + __IO uint32_t MACA3LR; /* 24 */ + uint32_t RESERVED2[40]; + __IO uint32_t MMCCR; /* 65 */ + __IO uint32_t MMCRIR; + __IO uint32_t MMCTIR; + __IO uint32_t MMCRIMR; + __IO uint32_t MMCTIMR; /* 69 */ + uint32_t RESERVED3[14]; + __IO uint32_t MMCTGFSCCR; /* 84 */ + __IO uint32_t MMCTGFMSCCR; + uint32_t RESERVED4[5]; + __IO uint32_t MMCTGFCR; + uint32_t RESERVED5[10]; + __IO uint32_t MMCRFCECR; + __IO uint32_t MMCRFAECR; + uint32_t RESERVED6[10]; + __IO uint32_t MMCRGUFCR; + uint32_t RESERVED7[334]; + __IO uint32_t PTPTSCR; + __IO uint32_t PTPSSIR; + __IO uint32_t PTPTSHR; + __IO uint32_t PTPTSLR; + __IO uint32_t PTPTSHUR; + __IO uint32_t PTPTSLUR; + __IO uint32_t PTPTSAR; + __IO uint32_t PTPTTHR; + __IO uint32_t PTPTTLR; + uint32_t RESERVED8[567]; + __IO uint32_t DMABMR; + __IO uint32_t DMATPDR; + __IO uint32_t DMARPDR; + __IO uint32_t DMARDLAR; + __IO uint32_t DMATDLAR; + __IO uint32_t DMASR; + __IO uint32_t DMAOMR; + __IO uint32_t DMAIER; + __IO uint32_t DMAMFBOCR; + uint32_t RESERVED9[9]; + __IO uint32_t DMACHTDR; + __IO uint32_t DMACHRDR; + __IO uint32_t DMACHTBAR; + __IO uint32_t DMACHRBAR; +} ETH_TypeDef; + +/** + * @brief External Interrupt/Event Controller + */ + +typedef struct +{ + __IO uint32_t IMR; + __IO uint32_t EMR; + __IO uint32_t RTSR; + __IO uint32_t FTSR; + __IO uint32_t SWIER; + __IO uint32_t PR; +} EXTI_TypeDef; + +/** + * @brief FLASH Registers + */ + +typedef struct +{ + __IO uint32_t ACR; + __IO uint32_t KEYR; + __IO uint32_t OPTKEYR; + __IO uint32_t SR; + __IO uint32_t CR; + __IO uint32_t AR; + __IO uint32_t RESERVED; + __IO uint32_t OBR; + __IO uint32_t WRPR; +#ifdef STM32F10X_XL + uint32_t RESERVED1[8]; + __IO uint32_t KEYR2; + uint32_t RESERVED2; + __IO uint32_t SR2; + __IO uint32_t CR2; + __IO uint32_t AR2; +#endif /* STM32F10X_XL */ +} FLASH_TypeDef; + +/** + * @brief Option Bytes Registers + */ + +typedef struct +{ + __IO uint16_t RDP; + __IO uint16_t USER; + __IO uint16_t Data0; + __IO uint16_t Data1; + __IO uint16_t WRP0; + __IO uint16_t WRP1; + __IO uint16_t WRP2; + __IO uint16_t WRP3; +} OB_TypeDef; + +/** + * @brief Flexible Static Memory Controller + */ + +typedef struct +{ + __IO uint32_t BTCR[8]; +} FSMC_Bank1_TypeDef; + +/** + * @brief Flexible Static Memory Controller Bank1E + */ + +typedef struct +{ + __IO uint32_t BWTR[7]; +} FSMC_Bank1E_TypeDef; + +/** + * @brief Flexible Static Memory Controller Bank2 + */ + +typedef struct +{ + __IO uint32_t PCR2; + __IO uint32_t SR2; + __IO uint32_t PMEM2; + __IO uint32_t PATT2; + uint32_t RESERVED0; + __IO uint32_t ECCR2; +} FSMC_Bank2_TypeDef; + +/** + * @brief Flexible Static Memory Controller Bank3 + */ + +typedef struct +{ + __IO uint32_t PCR3; + __IO uint32_t SR3; + __IO uint32_t PMEM3; + __IO uint32_t PATT3; + uint32_t RESERVED0; + __IO uint32_t ECCR3; +} FSMC_Bank3_TypeDef; + +/** + * @brief Flexible Static Memory Controller Bank4 + */ + +typedef struct +{ + __IO uint32_t PCR4; + __IO uint32_t SR4; + __IO uint32_t PMEM4; + __IO uint32_t PATT4; + __IO uint32_t PIO4; +} FSMC_Bank4_TypeDef; + +/** + * @brief General Purpose I/O + */ + +typedef struct +{ + __IO uint32_t CRL; + __IO uint32_t CRH; + __IO uint32_t IDR; + __IO uint32_t ODR; + __IO uint32_t BSRR; + __IO uint32_t BRR; + __IO uint32_t LCKR; +} GPIO_TypeDef; + +/** + * @brief Alternate Function I/O + */ + +typedef struct +{ + __IO uint32_t EVCR; + __IO uint32_t MAPR; + __IO uint32_t EXTICR[4]; + uint32_t RESERVED0; + __IO uint32_t MAPR2; +} AFIO_TypeDef; +/** + * @brief Inter Integrated Circuit Interface + */ + +typedef struct +{ + __IO uint16_t CR1; + uint16_t RESERVED0; + __IO uint16_t CR2; + uint16_t RESERVED1; + __IO uint16_t OAR1; + uint16_t RESERVED2; + __IO uint16_t OAR2; + uint16_t RESERVED3; + __IO uint16_t DR; + uint16_t RESERVED4; + __IO uint16_t SR1; + uint16_t RESERVED5; + __IO uint16_t SR2; + uint16_t RESERVED6; + __IO uint16_t CCR; + uint16_t RESERVED7; + __IO uint16_t TRISE; + uint16_t RESERVED8; +} I2C_TypeDef; + +/** + * @brief Independent WATCHDOG + */ + +typedef struct +{ + __IO uint32_t KR; + __IO uint32_t PR; + __IO uint32_t RLR; + __IO uint32_t SR; +} IWDG_TypeDef; + +/** + * @brief Power Control + */ + +typedef struct +{ + __IO uint32_t CR; + __IO uint32_t CSR; +} PWR_TypeDef; + +/** + * @brief Reset and Clock Control + */ + +typedef struct +{ + __IO uint32_t CR; + __IO uint32_t CFGR; + __IO uint32_t CIR; + __IO uint32_t APB2RSTR; + __IO uint32_t APB1RSTR; + __IO uint32_t AHBENR; + __IO uint32_t APB2ENR; + __IO uint32_t APB1ENR; + __IO uint32_t BDCR; + __IO uint32_t CSR; + +#ifdef STM32F10X_CL + __IO uint32_t AHBRSTR; + __IO uint32_t CFGR2; +#endif /* STM32F10X_CL */ + +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) + uint32_t RESERVED0; + __IO uint32_t CFGR2; +#endif /* STM32F10X_LD_VL || STM32F10X_MD_VL || STM32F10X_HD_VL */ +} RCC_TypeDef; + +/** + * @brief Real-Time Clock + */ + +typedef struct +{ + __IO uint16_t CRH; + uint16_t RESERVED0; + __IO uint16_t CRL; + uint16_t RESERVED1; + __IO uint16_t PRLH; + uint16_t RESERVED2; + __IO uint16_t PRLL; + uint16_t RESERVED3; + __IO uint16_t DIVH; + uint16_t RESERVED4; + __IO uint16_t DIVL; + uint16_t RESERVED5; + __IO uint16_t CNTH; + uint16_t RESERVED6; + __IO uint16_t CNTL; + uint16_t RESERVED7; + __IO uint16_t ALRH; + uint16_t RESERVED8; + __IO uint16_t ALRL; + uint16_t RESERVED9; +} RTC_TypeDef; + +/** + * @brief SD host Interface + */ + +typedef struct +{ + __IO uint32_t POWER; + __IO uint32_t CLKCR; + __IO uint32_t ARG; + __IO uint32_t CMD; + __I uint32_t RESPCMD; + __I uint32_t RESP1; + __I uint32_t RESP2; + __I uint32_t RESP3; + __I uint32_t RESP4; + __IO uint32_t DTIMER; + __IO uint32_t DLEN; + __IO uint32_t DCTRL; + __I uint32_t DCOUNT; + __I uint32_t STA; + __IO uint32_t ICR; + __IO uint32_t MASK; + uint32_t RESERVED0[2]; + __I uint32_t FIFOCNT; + uint32_t RESERVED1[13]; + __IO uint32_t FIFO; +} SDIO_TypeDef; + +/** + * @brief Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint16_t CR1; + uint16_t RESERVED0; + __IO uint16_t CR2; + uint16_t RESERVED1; + __IO uint16_t SR; + uint16_t RESERVED2; + __IO uint16_t DR; + uint16_t RESERVED3; + __IO uint16_t CRCPR; + uint16_t RESERVED4; + __IO uint16_t RXCRCR; + uint16_t RESERVED5; + __IO uint16_t TXCRCR; + uint16_t RESERVED6; + __IO uint16_t I2SCFGR; + uint16_t RESERVED7; + __IO uint16_t I2SPR; + uint16_t RESERVED8; +} SPI_TypeDef; + +/** + * @brief TIM + */ + +typedef struct +{ + __IO uint16_t CR1; + uint16_t RESERVED0; + __IO uint16_t CR2; + uint16_t RESERVED1; + __IO uint16_t SMCR; + uint16_t RESERVED2; + __IO uint16_t DIER; + uint16_t RESERVED3; + __IO uint16_t SR; + uint16_t RESERVED4; + __IO uint16_t EGR; + uint16_t RESERVED5; + __IO uint16_t CCMR1; + uint16_t RESERVED6; + __IO uint16_t CCMR2; + uint16_t RESERVED7; + __IO uint16_t CCER; + uint16_t RESERVED8; + __IO uint16_t CNT; + uint16_t RESERVED9; + __IO uint16_t PSC; + uint16_t RESERVED10; + __IO uint16_t ARR; + uint16_t RESERVED11; + __IO uint16_t RCR; + uint16_t RESERVED12; + __IO uint16_t CCR1; + uint16_t RESERVED13; + __IO uint16_t CCR2; + uint16_t RESERVED14; + __IO uint16_t CCR3; + uint16_t RESERVED15; + __IO uint16_t CCR4; + uint16_t RESERVED16; + __IO uint16_t BDTR; + uint16_t RESERVED17; + __IO uint16_t DCR; + uint16_t RESERVED18; + __IO uint16_t DMAR; + uint16_t RESERVED19; +} TIM_TypeDef; + +/** + * @brief Universal Synchronous Asynchronous Receiver Transmitter + */ + +typedef struct +{ + __IO uint16_t SR; + uint16_t RESERVED0; + __IO uint16_t DR; + uint16_t RESERVED1; + __IO uint16_t BRR; + uint16_t RESERVED2; + __IO uint16_t CR1; + uint16_t RESERVED3; + __IO uint16_t CR2; + uint16_t RESERVED4; + __IO uint16_t CR3; + uint16_t RESERVED5; + __IO uint16_t GTPR; + uint16_t RESERVED6; +} USART_TypeDef; + +/** + * @brief Window WATCHDOG + */ + +typedef struct +{ + __IO uint32_t CR; + __IO uint32_t CFR; + __IO uint32_t SR; +} WWDG_TypeDef; + +/** + * @} + */ + +/** @addtogroup Peripheral_memory_map + * @{ + */ + + +#define FLASH_BASE ((uint32_t)0x08000000) /*!< FLASH base address in the alias region */ +#define SRAM_BASE ((uint32_t)0x20000000) /*!< SRAM base address in the alias region */ +#define PERIPH_BASE ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */ + +#define SRAM_BB_BASE ((uint32_t)0x22000000) /*!< SRAM base address in the bit-band region */ +#define PERIPH_BB_BASE ((uint32_t)0x42000000) /*!< Peripheral base address in the bit-band region */ + +#define FSMC_R_BASE ((uint32_t)0xA0000000) /*!< FSMC registers base address */ + +/*!< Peripheral memory map */ +#define APB1PERIPH_BASE PERIPH_BASE +#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) +#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000) + +#define TIM2_BASE (APB1PERIPH_BASE + 0x0000) +#define TIM3_BASE (APB1PERIPH_BASE + 0x0400) +#define TIM4_BASE (APB1PERIPH_BASE + 0x0800) +#define TIM5_BASE (APB1PERIPH_BASE + 0x0C00) +#define TIM6_BASE (APB1PERIPH_BASE + 0x1000) +#define TIM7_BASE (APB1PERIPH_BASE + 0x1400) +#define TIM12_BASE (APB1PERIPH_BASE + 0x1800) +#define TIM13_BASE (APB1PERIPH_BASE + 0x1C00) +#define TIM14_BASE (APB1PERIPH_BASE + 0x2000) +#define RTC_BASE (APB1PERIPH_BASE + 0x2800) +#define WWDG_BASE (APB1PERIPH_BASE + 0x2C00) +#define IWDG_BASE (APB1PERIPH_BASE + 0x3000) +#define SPI2_BASE (APB1PERIPH_BASE + 0x3800) +#define SPI3_BASE (APB1PERIPH_BASE + 0x3C00) +#define USART2_BASE (APB1PERIPH_BASE + 0x4400) +#define USART3_BASE (APB1PERIPH_BASE + 0x4800) +#define UART4_BASE (APB1PERIPH_BASE + 0x4C00) +#define UART5_BASE (APB1PERIPH_BASE + 0x5000) +#define I2C1_BASE (APB1PERIPH_BASE + 0x5400) +#define I2C2_BASE (APB1PERIPH_BASE + 0x5800) +#define CAN1_BASE (APB1PERIPH_BASE + 0x6400) +#define CAN2_BASE (APB1PERIPH_BASE + 0x6800) +#define BKP_BASE (APB1PERIPH_BASE + 0x6C00) +#define PWR_BASE (APB1PERIPH_BASE + 0x7000) +#define DAC_BASE (APB1PERIPH_BASE + 0x7400) +#define CEC_BASE (APB1PERIPH_BASE + 0x7800) + +#define AFIO_BASE (APB2PERIPH_BASE + 0x0000) +#define EXTI_BASE (APB2PERIPH_BASE + 0x0400) +#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) +#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00) +#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000) +#define GPIOD_BASE (APB2PERIPH_BASE + 0x1400) +#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800) +#define GPIOF_BASE (APB2PERIPH_BASE + 0x1C00) +#define GPIOG_BASE (APB2PERIPH_BASE + 0x2000) +#define ADC1_BASE (APB2PERIPH_BASE + 0x2400) +#define ADC2_BASE (APB2PERIPH_BASE + 0x2800) +#define TIM1_BASE (APB2PERIPH_BASE + 0x2C00) +#define SPI1_BASE (APB2PERIPH_BASE + 0x3000) +#define TIM8_BASE (APB2PERIPH_BASE + 0x3400) +#define USART1_BASE (APB2PERIPH_BASE + 0x3800) +#define ADC3_BASE (APB2PERIPH_BASE + 0x3C00) +#define TIM15_BASE (APB2PERIPH_BASE + 0x4000) +#define TIM16_BASE (APB2PERIPH_BASE + 0x4400) +#define TIM17_BASE (APB2PERIPH_BASE + 0x4800) +#define TIM9_BASE (APB2PERIPH_BASE + 0x4C00) +#define TIM10_BASE (APB2PERIPH_BASE + 0x5000) +#define TIM11_BASE (APB2PERIPH_BASE + 0x5400) + +#define SDIO_BASE (PERIPH_BASE + 0x18000) + +#define DMA1_BASE (AHBPERIPH_BASE + 0x0000) +#define DMA1_Channel1_BASE (AHBPERIPH_BASE + 0x0008) +#define DMA1_Channel2_BASE (AHBPERIPH_BASE + 0x001C) +#define DMA1_Channel3_BASE (AHBPERIPH_BASE + 0x0030) +#define DMA1_Channel4_BASE (AHBPERIPH_BASE + 0x0044) +#define DMA1_Channel5_BASE (AHBPERIPH_BASE + 0x0058) +#define DMA1_Channel6_BASE (AHBPERIPH_BASE + 0x006C) +#define DMA1_Channel7_BASE (AHBPERIPH_BASE + 0x0080) +#define DMA2_BASE (AHBPERIPH_BASE + 0x0400) +#define DMA2_Channel1_BASE (AHBPERIPH_BASE + 0x0408) +#define DMA2_Channel2_BASE (AHBPERIPH_BASE + 0x041C) +#define DMA2_Channel3_BASE (AHBPERIPH_BASE + 0x0430) +#define DMA2_Channel4_BASE (AHBPERIPH_BASE + 0x0444) +#define DMA2_Channel5_BASE (AHBPERIPH_BASE + 0x0458) +#define RCC_BASE (AHBPERIPH_BASE + 0x1000) +#define CRC_BASE (AHBPERIPH_BASE + 0x3000) + +#define FLASH_R_BASE (AHBPERIPH_BASE + 0x2000) /*!< Flash registers base address */ +#define OB_BASE ((uint32_t)0x1FFFF800) /*!< Flash Option Bytes base address */ + +#define ETH_BASE (AHBPERIPH_BASE + 0x8000) +#define ETH_MAC_BASE (ETH_BASE) +#define ETH_MMC_BASE (ETH_BASE + 0x0100) +#define ETH_PTP_BASE (ETH_BASE + 0x0700) +#define ETH_DMA_BASE (ETH_BASE + 0x1000) + +#define FSMC_Bank1_R_BASE (FSMC_R_BASE + 0x0000) /*!< FSMC Bank1 registers base address */ +#define FSMC_Bank1E_R_BASE (FSMC_R_BASE + 0x0104) /*!< FSMC Bank1E registers base address */ +#define FSMC_Bank2_R_BASE (FSMC_R_BASE + 0x0060) /*!< FSMC Bank2 registers base address */ +#define FSMC_Bank3_R_BASE (FSMC_R_BASE + 0x0080) /*!< FSMC Bank3 registers base address */ +#define FSMC_Bank4_R_BASE (FSMC_R_BASE + 0x00A0) /*!< FSMC Bank4 registers base address */ + +#define DBGMCU_BASE ((uint32_t)0xE0042000) /*!< Debug MCU registers base address */ + +/** + * @} + */ + +/** @addtogroup Peripheral_declaration + * @{ + */ + +#define TIM2 ((TIM_TypeDef *) TIM2_BASE) +#define TIM3 ((TIM_TypeDef *) TIM3_BASE) +#define TIM4 ((TIM_TypeDef *) TIM4_BASE) +#define TIM5 ((TIM_TypeDef *) TIM5_BASE) +#define TIM6 ((TIM_TypeDef *) TIM6_BASE) +#define TIM7 ((TIM_TypeDef *) TIM7_BASE) +#define TIM12 ((TIM_TypeDef *) TIM12_BASE) +#define TIM13 ((TIM_TypeDef *) TIM13_BASE) +#define TIM14 ((TIM_TypeDef *) TIM14_BASE) +#define RTC ((RTC_TypeDef *) RTC_BASE) +#define WWDG ((WWDG_TypeDef *) WWDG_BASE) +#define IWDG ((IWDG_TypeDef *) IWDG_BASE) +#define SPI2 ((SPI_TypeDef *) SPI2_BASE) +#define SPI3 ((SPI_TypeDef *) SPI3_BASE) +#define USART2 ((USART_TypeDef *) USART2_BASE) +#define USART3 ((USART_TypeDef *) USART3_BASE) +#define UART4 ((USART_TypeDef *) UART4_BASE) +#define UART5 ((USART_TypeDef *) UART5_BASE) +#define I2C1 ((I2C_TypeDef *) I2C1_BASE) +#define I2C2 ((I2C_TypeDef *) I2C2_BASE) +#define CAN1 ((CAN_TypeDef *) CAN1_BASE) +#define CAN2 ((CAN_TypeDef *) CAN2_BASE) +#define BKP ((BKP_TypeDef *) BKP_BASE) +#define PWR ((PWR_TypeDef *) PWR_BASE) +#define DAC ((DAC_TypeDef *) DAC_BASE) +#define CEC ((CEC_TypeDef *) CEC_BASE) +#define AFIO ((AFIO_TypeDef *) AFIO_BASE) +#define EXTI ((EXTI_TypeDef *) EXTI_BASE) +#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE) +#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE) +#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE) +#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE) +#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE) +#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE) +#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE) +#define ADC1 ((ADC_TypeDef *) ADC1_BASE) +#define ADC2 ((ADC_TypeDef *) ADC2_BASE) +#define TIM1 ((TIM_TypeDef *) TIM1_BASE) +#define SPI1 ((SPI_TypeDef *) SPI1_BASE) +#define TIM8 ((TIM_TypeDef *) TIM8_BASE) +#define USART1 ((USART_TypeDef *) USART1_BASE) +#define ADC3 ((ADC_TypeDef *) ADC3_BASE) +#define TIM15 ((TIM_TypeDef *) TIM15_BASE) +#define TIM16 ((TIM_TypeDef *) TIM16_BASE) +#define TIM17 ((TIM_TypeDef *) TIM17_BASE) +#define TIM9 ((TIM_TypeDef *) TIM9_BASE) +#define TIM10 ((TIM_TypeDef *) TIM10_BASE) +#define TIM11 ((TIM_TypeDef *) TIM11_BASE) +#define SDIO ((SDIO_TypeDef *) SDIO_BASE) +#define DMA1 ((DMA_TypeDef *) DMA1_BASE) +#define DMA2 ((DMA_TypeDef *) DMA2_BASE) +#define DMA1_Channel1 ((DMA_Channel_TypeDef *) DMA1_Channel1_BASE) +#define DMA1_Channel2 ((DMA_Channel_TypeDef *) DMA1_Channel2_BASE) +#define DMA1_Channel3 ((DMA_Channel_TypeDef *) DMA1_Channel3_BASE) +#define DMA1_Channel4 ((DMA_Channel_TypeDef *) DMA1_Channel4_BASE) +#define DMA1_Channel5 ((DMA_Channel_TypeDef *) DMA1_Channel5_BASE) +#define DMA1_Channel6 ((DMA_Channel_TypeDef *) DMA1_Channel6_BASE) +#define DMA1_Channel7 ((DMA_Channel_TypeDef *) DMA1_Channel7_BASE) +#define DMA2_Channel1 ((DMA_Channel_TypeDef *) DMA2_Channel1_BASE) +#define DMA2_Channel2 ((DMA_Channel_TypeDef *) DMA2_Channel2_BASE) +#define DMA2_Channel3 ((DMA_Channel_TypeDef *) DMA2_Channel3_BASE) +#define DMA2_Channel4 ((DMA_Channel_TypeDef *) DMA2_Channel4_BASE) +#define DMA2_Channel5 ((DMA_Channel_TypeDef *) DMA2_Channel5_BASE) +#define RCC ((RCC_TypeDef *) RCC_BASE) +#define CRC ((CRC_TypeDef *) CRC_BASE) +#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) +#define OB ((OB_TypeDef *) OB_BASE) +#define ETH ((ETH_TypeDef *) ETH_BASE) +#define FSMC_Bank1 ((FSMC_Bank1_TypeDef *) FSMC_Bank1_R_BASE) +#define FSMC_Bank1E ((FSMC_Bank1E_TypeDef *) FSMC_Bank1E_R_BASE) +#define FSMC_Bank2 ((FSMC_Bank2_TypeDef *) FSMC_Bank2_R_BASE) +#define FSMC_Bank3 ((FSMC_Bank3_TypeDef *) FSMC_Bank3_R_BASE) +#define FSMC_Bank4 ((FSMC_Bank4_TypeDef *) FSMC_Bank4_R_BASE) +#define DBGMCU ((DBGMCU_TypeDef *) DBGMCU_BASE) + +/** + * @} + */ + +/** @addtogroup Exported_constants + * @{ + */ + + /** @addtogroup Peripheral_Registers_Bits_Definition + * @{ + */ + +/******************************************************************************/ +/* Peripheral Registers_Bits_Definition */ +/******************************************************************************/ + +/******************************************************************************/ +/* */ +/* CRC calculation unit */ +/* */ +/******************************************************************************/ + +/******************* Bit definition for CRC_DR register *********************/ +#define CRC_DR_DR ((uint32_t)0xFFFFFFFF) /*!< Data register bits */ + + +/******************* Bit definition for CRC_IDR register ********************/ +#define CRC_IDR_IDR ((uint8_t)0xFF) /*!< General-purpose 8-bit data register bits */ + + +/******************** Bit definition for CRC_CR register ********************/ +#define CRC_CR_RESET ((uint8_t)0x01) /*!< RESET bit */ + +/******************************************************************************/ +/* */ +/* Power Control */ +/* */ +/******************************************************************************/ + +/******************** Bit definition for PWR_CR register ********************/ +#define PWR_CR_LPDS ((uint16_t)0x0001) /*!< Low-Power Deepsleep */ +#define PWR_CR_PDDS ((uint16_t)0x0002) /*!< Power Down Deepsleep */ +#define PWR_CR_CWUF ((uint16_t)0x0004) /*!< Clear Wakeup Flag */ +#define PWR_CR_CSBF ((uint16_t)0x0008) /*!< Clear Standby Flag */ +#define PWR_CR_PVDE ((uint16_t)0x0010) /*!< Power Voltage Detector Enable */ + +#define PWR_CR_PLS ((uint16_t)0x00E0) /*!< PLS[2:0] bits (PVD Level Selection) */ +#define PWR_CR_PLS_0 ((uint16_t)0x0020) /*!< Bit 0 */ +#define PWR_CR_PLS_1 ((uint16_t)0x0040) /*!< Bit 1 */ +#define PWR_CR_PLS_2 ((uint16_t)0x0080) /*!< Bit 2 */ + +/*!< PVD level configuration */ +#define PWR_CR_PLS_2V2 ((uint16_t)0x0000) /*!< PVD level 2.2V */ +#define PWR_CR_PLS_2V3 ((uint16_t)0x0020) /*!< PVD level 2.3V */ +#define PWR_CR_PLS_2V4 ((uint16_t)0x0040) /*!< PVD level 2.4V */ +#define PWR_CR_PLS_2V5 ((uint16_t)0x0060) /*!< PVD level 2.5V */ +#define PWR_CR_PLS_2V6 ((uint16_t)0x0080) /*!< PVD level 2.6V */ +#define PWR_CR_PLS_2V7 ((uint16_t)0x00A0) /*!< PVD level 2.7V */ +#define PWR_CR_PLS_2V8 ((uint16_t)0x00C0) /*!< PVD level 2.8V */ +#define PWR_CR_PLS_2V9 ((uint16_t)0x00E0) /*!< PVD level 2.9V */ + +#define PWR_CR_DBP ((uint16_t)0x0100) /*!< Disable Backup Domain write protection */ + + +/******************* Bit definition for PWR_CSR register ********************/ +#define PWR_CSR_WUF ((uint16_t)0x0001) /*!< Wakeup Flag */ +#define PWR_CSR_SBF ((uint16_t)0x0002) /*!< Standby Flag */ +#define PWR_CSR_PVDO ((uint16_t)0x0004) /*!< PVD Output */ +#define PWR_CSR_EWUP ((uint16_t)0x0100) /*!< Enable WKUP pin */ + +/******************************************************************************/ +/* */ +/* Backup registers */ +/* */ +/******************************************************************************/ + +/******************* Bit definition for BKP_DR1 register ********************/ +#define BKP_DR1_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR2 register ********************/ +#define BKP_DR2_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR3 register ********************/ +#define BKP_DR3_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR4 register ********************/ +#define BKP_DR4_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR5 register ********************/ +#define BKP_DR5_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR6 register ********************/ +#define BKP_DR6_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR7 register ********************/ +#define BKP_DR7_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR8 register ********************/ +#define BKP_DR8_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR9 register ********************/ +#define BKP_DR9_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR10 register *******************/ +#define BKP_DR10_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR11 register *******************/ +#define BKP_DR11_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR12 register *******************/ +#define BKP_DR12_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR13 register *******************/ +#define BKP_DR13_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR14 register *******************/ +#define BKP_DR14_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR15 register *******************/ +#define BKP_DR15_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR16 register *******************/ +#define BKP_DR16_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR17 register *******************/ +#define BKP_DR17_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/****************** Bit definition for BKP_DR18 register ********************/ +#define BKP_DR18_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR19 register *******************/ +#define BKP_DR19_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR20 register *******************/ +#define BKP_DR20_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR21 register *******************/ +#define BKP_DR21_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR22 register *******************/ +#define BKP_DR22_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR23 register *******************/ +#define BKP_DR23_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR24 register *******************/ +#define BKP_DR24_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR25 register *******************/ +#define BKP_DR25_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR26 register *******************/ +#define BKP_DR26_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR27 register *******************/ +#define BKP_DR27_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR28 register *******************/ +#define BKP_DR28_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR29 register *******************/ +#define BKP_DR29_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR30 register *******************/ +#define BKP_DR30_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR31 register *******************/ +#define BKP_DR31_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR32 register *******************/ +#define BKP_DR32_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR33 register *******************/ +#define BKP_DR33_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR34 register *******************/ +#define BKP_DR34_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR35 register *******************/ +#define BKP_DR35_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR36 register *******************/ +#define BKP_DR36_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR37 register *******************/ +#define BKP_DR37_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR38 register *******************/ +#define BKP_DR38_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR39 register *******************/ +#define BKP_DR39_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR40 register *******************/ +#define BKP_DR40_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR41 register *******************/ +#define BKP_DR41_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/******************* Bit definition for BKP_DR42 register *******************/ +#define BKP_DR42_D ((uint16_t)0xFFFF) /*!< Backup data */ + +/****************** Bit definition for BKP_RTCCR register *******************/ +#define BKP_RTCCR_CAL ((uint16_t)0x007F) /*!< Calibration value */ +#define BKP_RTCCR_CCO ((uint16_t)0x0080) /*!< Calibration Clock Output */ +#define BKP_RTCCR_ASOE ((uint16_t)0x0100) /*!< Alarm or Second Output Enable */ +#define BKP_RTCCR_ASOS ((uint16_t)0x0200) /*!< Alarm or Second Output Selection */ + +/******************** Bit definition for BKP_CR register ********************/ +#define BKP_CR_TPE ((uint8_t)0x01) /*!< TAMPER pin enable */ +#define BKP_CR_TPAL ((uint8_t)0x02) /*!< TAMPER pin active level */ + +/******************* Bit definition for BKP_CSR register ********************/ +#define BKP_CSR_CTE ((uint16_t)0x0001) /*!< Clear Tamper event */ +#define BKP_CSR_CTI ((uint16_t)0x0002) /*!< Clear Tamper Interrupt */ +#define BKP_CSR_TPIE ((uint16_t)0x0004) /*!< TAMPER Pin interrupt enable */ +#define BKP_CSR_TEF ((uint16_t)0x0100) /*!< Tamper Event Flag */ +#define BKP_CSR_TIF ((uint16_t)0x0200) /*!< Tamper Interrupt Flag */ + +/******************************************************************************/ +/* */ +/* Reset and Clock Control */ +/* */ +/******************************************************************************/ + +/******************** Bit definition for RCC_CR register ********************/ +#define RCC_CR_HSION ((uint32_t)0x00000001) /*!< Internal High Speed clock enable */ +#define RCC_CR_HSIRDY ((uint32_t)0x00000002) /*!< Internal High Speed clock ready flag */ +#define RCC_CR_HSITRIM ((uint32_t)0x000000F8) /*!< Internal High Speed clock trimming */ +#define RCC_CR_HSICAL ((uint32_t)0x0000FF00) /*!< Internal High Speed clock Calibration */ +#define RCC_CR_HSEON ((uint32_t)0x00010000) /*!< External High Speed clock enable */ +#define RCC_CR_HSERDY ((uint32_t)0x00020000) /*!< External High Speed clock ready flag */ +#define RCC_CR_HSEBYP ((uint32_t)0x00040000) /*!< External High Speed clock Bypass */ +#define RCC_CR_CSSON ((uint32_t)0x00080000) /*!< Clock Security System enable */ +#define RCC_CR_PLLON ((uint32_t)0x01000000) /*!< PLL enable */ +#define RCC_CR_PLLRDY ((uint32_t)0x02000000) /*!< PLL clock ready flag */ + +#ifdef STM32F10X_CL + #define RCC_CR_PLL2ON ((uint32_t)0x04000000) /*!< PLL2 enable */ + #define RCC_CR_PLL2RDY ((uint32_t)0x08000000) /*!< PLL2 clock ready flag */ + #define RCC_CR_PLL3ON ((uint32_t)0x10000000) /*!< PLL3 enable */ + #define RCC_CR_PLL3RDY ((uint32_t)0x20000000) /*!< PLL3 clock ready flag */ +#endif /* STM32F10X_CL */ + +/******************* Bit definition for RCC_CFGR register *******************/ +/*!< SW configuration */ +#define RCC_CFGR_SW ((uint32_t)0x00000003) /*!< SW[1:0] bits (System clock Switch) */ +#define RCC_CFGR_SW_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define RCC_CFGR_SW_1 ((uint32_t)0x00000002) /*!< Bit 1 */ + +#define RCC_CFGR_SW_HSI ((uint32_t)0x00000000) /*!< HSI selected as system clock */ +#define RCC_CFGR_SW_HSE ((uint32_t)0x00000001) /*!< HSE selected as system clock */ +#define RCC_CFGR_SW_PLL ((uint32_t)0x00000002) /*!< PLL selected as system clock */ + +/*!< SWS configuration */ +#define RCC_CFGR_SWS ((uint32_t)0x0000000C) /*!< SWS[1:0] bits (System Clock Switch Status) */ +#define RCC_CFGR_SWS_0 ((uint32_t)0x00000004) /*!< Bit 0 */ +#define RCC_CFGR_SWS_1 ((uint32_t)0x00000008) /*!< Bit 1 */ + +#define RCC_CFGR_SWS_HSI ((uint32_t)0x00000000) /*!< HSI oscillator used as system clock */ +#define RCC_CFGR_SWS_HSE ((uint32_t)0x00000004) /*!< HSE oscillator used as system clock */ +#define RCC_CFGR_SWS_PLL ((uint32_t)0x00000008) /*!< PLL used as system clock */ + +/*!< HPRE configuration */ +#define RCC_CFGR_HPRE ((uint32_t)0x000000F0) /*!< HPRE[3:0] bits (AHB prescaler) */ +#define RCC_CFGR_HPRE_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define RCC_CFGR_HPRE_1 ((uint32_t)0x00000020) /*!< Bit 1 */ +#define RCC_CFGR_HPRE_2 ((uint32_t)0x00000040) /*!< Bit 2 */ +#define RCC_CFGR_HPRE_3 ((uint32_t)0x00000080) /*!< Bit 3 */ + +#define RCC_CFGR_HPRE_DIV1 ((uint32_t)0x00000000) /*!< SYSCLK not divided */ +#define RCC_CFGR_HPRE_DIV2 ((uint32_t)0x00000080) /*!< SYSCLK divided by 2 */ +#define RCC_CFGR_HPRE_DIV4 ((uint32_t)0x00000090) /*!< SYSCLK divided by 4 */ +#define RCC_CFGR_HPRE_DIV8 ((uint32_t)0x000000A0) /*!< SYSCLK divided by 8 */ +#define RCC_CFGR_HPRE_DIV16 ((uint32_t)0x000000B0) /*!< SYSCLK divided by 16 */ +#define RCC_CFGR_HPRE_DIV64 ((uint32_t)0x000000C0) /*!< SYSCLK divided by 64 */ +#define RCC_CFGR_HPRE_DIV128 ((uint32_t)0x000000D0) /*!< SYSCLK divided by 128 */ +#define RCC_CFGR_HPRE_DIV256 ((uint32_t)0x000000E0) /*!< SYSCLK divided by 256 */ +#define RCC_CFGR_HPRE_DIV512 ((uint32_t)0x000000F0) /*!< SYSCLK divided by 512 */ + +/*!< PPRE1 configuration */ +#define RCC_CFGR_PPRE1 ((uint32_t)0x00000700) /*!< PRE1[2:0] bits (APB1 prescaler) */ +#define RCC_CFGR_PPRE1_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define RCC_CFGR_PPRE1_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define RCC_CFGR_PPRE1_2 ((uint32_t)0x00000400) /*!< Bit 2 */ + +#define RCC_CFGR_PPRE1_DIV1 ((uint32_t)0x00000000) /*!< HCLK not divided */ +#define RCC_CFGR_PPRE1_DIV2 ((uint32_t)0x00000400) /*!< HCLK divided by 2 */ +#define RCC_CFGR_PPRE1_DIV4 ((uint32_t)0x00000500) /*!< HCLK divided by 4 */ +#define RCC_CFGR_PPRE1_DIV8 ((uint32_t)0x00000600) /*!< HCLK divided by 8 */ +#define RCC_CFGR_PPRE1_DIV16 ((uint32_t)0x00000700) /*!< HCLK divided by 16 */ + +/*!< PPRE2 configuration */ +#define RCC_CFGR_PPRE2 ((uint32_t)0x00003800) /*!< PRE2[2:0] bits (APB2 prescaler) */ +#define RCC_CFGR_PPRE2_0 ((uint32_t)0x00000800) /*!< Bit 0 */ +#define RCC_CFGR_PPRE2_1 ((uint32_t)0x00001000) /*!< Bit 1 */ +#define RCC_CFGR_PPRE2_2 ((uint32_t)0x00002000) /*!< Bit 2 */ + +#define RCC_CFGR_PPRE2_DIV1 ((uint32_t)0x00000000) /*!< HCLK not divided */ +#define RCC_CFGR_PPRE2_DIV2 ((uint32_t)0x00002000) /*!< HCLK divided by 2 */ +#define RCC_CFGR_PPRE2_DIV4 ((uint32_t)0x00002800) /*!< HCLK divided by 4 */ +#define RCC_CFGR_PPRE2_DIV8 ((uint32_t)0x00003000) /*!< HCLK divided by 8 */ +#define RCC_CFGR_PPRE2_DIV16 ((uint32_t)0x00003800) /*!< HCLK divided by 16 */ + +/*!< ADCPPRE configuration */ +#define RCC_CFGR_ADCPRE ((uint32_t)0x0000C000) /*!< ADCPRE[1:0] bits (ADC prescaler) */ +#define RCC_CFGR_ADCPRE_0 ((uint32_t)0x00004000) /*!< Bit 0 */ +#define RCC_CFGR_ADCPRE_1 ((uint32_t)0x00008000) /*!< Bit 1 */ + +#define RCC_CFGR_ADCPRE_DIV2 ((uint32_t)0x00000000) /*!< PCLK2 divided by 2 */ +#define RCC_CFGR_ADCPRE_DIV4 ((uint32_t)0x00004000) /*!< PCLK2 divided by 4 */ +#define RCC_CFGR_ADCPRE_DIV6 ((uint32_t)0x00008000) /*!< PCLK2 divided by 6 */ +#define RCC_CFGR_ADCPRE_DIV8 ((uint32_t)0x0000C000) /*!< PCLK2 divided by 8 */ + +#define RCC_CFGR_PLLSRC ((uint32_t)0x00010000) /*!< PLL entry clock source */ + +#define RCC_CFGR_PLLXTPRE ((uint32_t)0x00020000) /*!< HSE divider for PLL entry */ + +/*!< PLLMUL configuration */ +#define RCC_CFGR_PLLMULL ((uint32_t)0x003C0000) /*!< PLLMUL[3:0] bits (PLL multiplication factor) */ +#define RCC_CFGR_PLLMULL_0 ((uint32_t)0x00040000) /*!< Bit 0 */ +#define RCC_CFGR_PLLMULL_1 ((uint32_t)0x00080000) /*!< Bit 1 */ +#define RCC_CFGR_PLLMULL_2 ((uint32_t)0x00100000) /*!< Bit 2 */ +#define RCC_CFGR_PLLMULL_3 ((uint32_t)0x00200000) /*!< Bit 3 */ + +#ifdef STM32F10X_CL + #define RCC_CFGR_PLLSRC_HSI_Div2 ((uint32_t)0x00000000) /*!< HSI clock divided by 2 selected as PLL entry clock source */ + #define RCC_CFGR_PLLSRC_PREDIV1 ((uint32_t)0x00010000) /*!< PREDIV1 clock selected as PLL entry clock source */ + + #define RCC_CFGR_PLLXTPRE_PREDIV1 ((uint32_t)0x00000000) /*!< PREDIV1 clock not divided for PLL entry */ + #define RCC_CFGR_PLLXTPRE_PREDIV1_Div2 ((uint32_t)0x00020000) /*!< PREDIV1 clock divided by 2 for PLL entry */ + + #define RCC_CFGR_PLLMULL4 ((uint32_t)0x00080000) /*!< PLL input clock * 4 */ + #define RCC_CFGR_PLLMULL5 ((uint32_t)0x000C0000) /*!< PLL input clock * 5 */ + #define RCC_CFGR_PLLMULL6 ((uint32_t)0x00100000) /*!< PLL input clock * 6 */ + #define RCC_CFGR_PLLMULL7 ((uint32_t)0x00140000) /*!< PLL input clock * 7 */ + #define RCC_CFGR_PLLMULL8 ((uint32_t)0x00180000) /*!< PLL input clock * 8 */ + #define RCC_CFGR_PLLMULL9 ((uint32_t)0x001C0000) /*!< PLL input clock * 9 */ + #define RCC_CFGR_PLLMULL6_5 ((uint32_t)0x00340000) /*!< PLL input clock * 6.5 */ + + #define RCC_CFGR_OTGFSPRE ((uint32_t)0x00400000) /*!< USB OTG FS prescaler */ + +/*!< MCO configuration */ + #define RCC_CFGR_MCO ((uint32_t)0x0F000000) /*!< MCO[3:0] bits (Microcontroller Clock Output) */ + #define RCC_CFGR_MCO_0 ((uint32_t)0x01000000) /*!< Bit 0 */ + #define RCC_CFGR_MCO_1 ((uint32_t)0x02000000) /*!< Bit 1 */ + #define RCC_CFGR_MCO_2 ((uint32_t)0x04000000) /*!< Bit 2 */ + #define RCC_CFGR_MCO_3 ((uint32_t)0x08000000) /*!< Bit 3 */ + + #define RCC_CFGR_MCO_NOCLOCK ((uint32_t)0x00000000) /*!< No clock */ + #define RCC_CFGR_MCO_SYSCLK ((uint32_t)0x04000000) /*!< System clock selected as MCO source */ + #define RCC_CFGR_MCO_HSI ((uint32_t)0x05000000) /*!< HSI clock selected as MCO source */ + #define RCC_CFGR_MCO_HSE ((uint32_t)0x06000000) /*!< HSE clock selected as MCO source */ + #define RCC_CFGR_MCO_PLLCLK_Div2 ((uint32_t)0x07000000) /*!< PLL clock divided by 2 selected as MCO source */ + #define RCC_CFGR_MCO_PLL2CLK ((uint32_t)0x08000000) /*!< PLL2 clock selected as MCO source*/ + #define RCC_CFGR_MCO_PLL3CLK_Div2 ((uint32_t)0x09000000) /*!< PLL3 clock divided by 2 selected as MCO source*/ + #define RCC_CFGR_MCO_Ext_HSE ((uint32_t)0x0A000000) /*!< XT1 external 3-25 MHz oscillator clock selected as MCO source */ + #define RCC_CFGR_MCO_PLL3CLK ((uint32_t)0x0B000000) /*!< PLL3 clock selected as MCO source */ +#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) + #define RCC_CFGR_PLLSRC_HSI_Div2 ((uint32_t)0x00000000) /*!< HSI clock divided by 2 selected as PLL entry clock source */ + #define RCC_CFGR_PLLSRC_PREDIV1 ((uint32_t)0x00010000) /*!< PREDIV1 clock selected as PLL entry clock source */ + + #define RCC_CFGR_PLLXTPRE_PREDIV1 ((uint32_t)0x00000000) /*!< PREDIV1 clock not divided for PLL entry */ + #define RCC_CFGR_PLLXTPRE_PREDIV1_Div2 ((uint32_t)0x00020000) /*!< PREDIV1 clock divided by 2 for PLL entry */ + + #define RCC_CFGR_PLLMULL2 ((uint32_t)0x00000000) /*!< PLL input clock*2 */ + #define RCC_CFGR_PLLMULL3 ((uint32_t)0x00040000) /*!< PLL input clock*3 */ + #define RCC_CFGR_PLLMULL4 ((uint32_t)0x00080000) /*!< PLL input clock*4 */ + #define RCC_CFGR_PLLMULL5 ((uint32_t)0x000C0000) /*!< PLL input clock*5 */ + #define RCC_CFGR_PLLMULL6 ((uint32_t)0x00100000) /*!< PLL input clock*6 */ + #define RCC_CFGR_PLLMULL7 ((uint32_t)0x00140000) /*!< PLL input clock*7 */ + #define RCC_CFGR_PLLMULL8 ((uint32_t)0x00180000) /*!< PLL input clock*8 */ + #define RCC_CFGR_PLLMULL9 ((uint32_t)0x001C0000) /*!< PLL input clock*9 */ + #define RCC_CFGR_PLLMULL10 ((uint32_t)0x00200000) /*!< PLL input clock10 */ + #define RCC_CFGR_PLLMULL11 ((uint32_t)0x00240000) /*!< PLL input clock*11 */ + #define RCC_CFGR_PLLMULL12 ((uint32_t)0x00280000) /*!< PLL input clock*12 */ + #define RCC_CFGR_PLLMULL13 ((uint32_t)0x002C0000) /*!< PLL input clock*13 */ + #define RCC_CFGR_PLLMULL14 ((uint32_t)0x00300000) /*!< PLL input clock*14 */ + #define RCC_CFGR_PLLMULL15 ((uint32_t)0x00340000) /*!< PLL input clock*15 */ + #define RCC_CFGR_PLLMULL16 ((uint32_t)0x00380000) /*!< PLL input clock*16 */ + +/*!< MCO configuration */ + #define RCC_CFGR_MCO ((uint32_t)0x07000000) /*!< MCO[2:0] bits (Microcontroller Clock Output) */ + #define RCC_CFGR_MCO_0 ((uint32_t)0x01000000) /*!< Bit 0 */ + #define RCC_CFGR_MCO_1 ((uint32_t)0x02000000) /*!< Bit 1 */ + #define RCC_CFGR_MCO_2 ((uint32_t)0x04000000) /*!< Bit 2 */ + + #define RCC_CFGR_MCO_NOCLOCK ((uint32_t)0x00000000) /*!< No clock */ + #define RCC_CFGR_MCO_SYSCLK ((uint32_t)0x04000000) /*!< System clock selected as MCO source */ + #define RCC_CFGR_MCO_HSI ((uint32_t)0x05000000) /*!< HSI clock selected as MCO source */ + #define RCC_CFGR_MCO_HSE ((uint32_t)0x06000000) /*!< HSE clock selected as MCO source */ + #define RCC_CFGR_MCO_PLL ((uint32_t)0x07000000) /*!< PLL clock divided by 2 selected as MCO source */ +#else + #define RCC_CFGR_PLLSRC_HSI_Div2 ((uint32_t)0x00000000) /*!< HSI clock divided by 2 selected as PLL entry clock source */ + #define RCC_CFGR_PLLSRC_HSE ((uint32_t)0x00010000) /*!< HSE clock selected as PLL entry clock source */ + + #define RCC_CFGR_PLLXTPRE_HSE ((uint32_t)0x00000000) /*!< HSE clock not divided for PLL entry */ + #define RCC_CFGR_PLLXTPRE_HSE_Div2 ((uint32_t)0x00020000) /*!< HSE clock divided by 2 for PLL entry */ + + #define RCC_CFGR_PLLMULL2 ((uint32_t)0x00000000) /*!< PLL input clock*2 */ + #define RCC_CFGR_PLLMULL3 ((uint32_t)0x00040000) /*!< PLL input clock*3 */ + #define RCC_CFGR_PLLMULL4 ((uint32_t)0x00080000) /*!< PLL input clock*4 */ + #define RCC_CFGR_PLLMULL5 ((uint32_t)0x000C0000) /*!< PLL input clock*5 */ + #define RCC_CFGR_PLLMULL6 ((uint32_t)0x00100000) /*!< PLL input clock*6 */ + #define RCC_CFGR_PLLMULL7 ((uint32_t)0x00140000) /*!< PLL input clock*7 */ + #define RCC_CFGR_PLLMULL8 ((uint32_t)0x00180000) /*!< PLL input clock*8 */ + #define RCC_CFGR_PLLMULL9 ((uint32_t)0x001C0000) /*!< PLL input clock*9 */ + #define RCC_CFGR_PLLMULL10 ((uint32_t)0x00200000) /*!< PLL input clock10 */ + #define RCC_CFGR_PLLMULL11 ((uint32_t)0x00240000) /*!< PLL input clock*11 */ + #define RCC_CFGR_PLLMULL12 ((uint32_t)0x00280000) /*!< PLL input clock*12 */ + #define RCC_CFGR_PLLMULL13 ((uint32_t)0x002C0000) /*!< PLL input clock*13 */ + #define RCC_CFGR_PLLMULL14 ((uint32_t)0x00300000) /*!< PLL input clock*14 */ + #define RCC_CFGR_PLLMULL15 ((uint32_t)0x00340000) /*!< PLL input clock*15 */ + #define RCC_CFGR_PLLMULL16 ((uint32_t)0x00380000) /*!< PLL input clock*16 */ + #define RCC_CFGR_USBPRE ((uint32_t)0x00400000) /*!< USB Device prescaler */ + +/*!< MCO configuration */ + #define RCC_CFGR_MCO ((uint32_t)0x07000000) /*!< MCO[2:0] bits (Microcontroller Clock Output) */ + #define RCC_CFGR_MCO_0 ((uint32_t)0x01000000) /*!< Bit 0 */ + #define RCC_CFGR_MCO_1 ((uint32_t)0x02000000) /*!< Bit 1 */ + #define RCC_CFGR_MCO_2 ((uint32_t)0x04000000) /*!< Bit 2 */ + + #define RCC_CFGR_MCO_NOCLOCK ((uint32_t)0x00000000) /*!< No clock */ + #define RCC_CFGR_MCO_SYSCLK ((uint32_t)0x04000000) /*!< System clock selected as MCO source */ + #define RCC_CFGR_MCO_HSI ((uint32_t)0x05000000) /*!< HSI clock selected as MCO source */ + #define RCC_CFGR_MCO_HSE ((uint32_t)0x06000000) /*!< HSE clock selected as MCO source */ + #define RCC_CFGR_MCO_PLL ((uint32_t)0x07000000) /*!< PLL clock divided by 2 selected as MCO source */ +#endif /* STM32F10X_CL */ + +/*!<****************** Bit definition for RCC_CIR register ********************/ +#define RCC_CIR_LSIRDYF ((uint32_t)0x00000001) /*!< LSI Ready Interrupt flag */ +#define RCC_CIR_LSERDYF ((uint32_t)0x00000002) /*!< LSE Ready Interrupt flag */ +#define RCC_CIR_HSIRDYF ((uint32_t)0x00000004) /*!< HSI Ready Interrupt flag */ +#define RCC_CIR_HSERDYF ((uint32_t)0x00000008) /*!< HSE Ready Interrupt flag */ +#define RCC_CIR_PLLRDYF ((uint32_t)0x00000010) /*!< PLL Ready Interrupt flag */ +#define RCC_CIR_CSSF ((uint32_t)0x00000080) /*!< Clock Security System Interrupt flag */ +#define RCC_CIR_LSIRDYIE ((uint32_t)0x00000100) /*!< LSI Ready Interrupt Enable */ +#define RCC_CIR_LSERDYIE ((uint32_t)0x00000200) /*!< LSE Ready Interrupt Enable */ +#define RCC_CIR_HSIRDYIE ((uint32_t)0x00000400) /*!< HSI Ready Interrupt Enable */ +#define RCC_CIR_HSERDYIE ((uint32_t)0x00000800) /*!< HSE Ready Interrupt Enable */ +#define RCC_CIR_PLLRDYIE ((uint32_t)0x00001000) /*!< PLL Ready Interrupt Enable */ +#define RCC_CIR_LSIRDYC ((uint32_t)0x00010000) /*!< LSI Ready Interrupt Clear */ +#define RCC_CIR_LSERDYC ((uint32_t)0x00020000) /*!< LSE Ready Interrupt Clear */ +#define RCC_CIR_HSIRDYC ((uint32_t)0x00040000) /*!< HSI Ready Interrupt Clear */ +#define RCC_CIR_HSERDYC ((uint32_t)0x00080000) /*!< HSE Ready Interrupt Clear */ +#define RCC_CIR_PLLRDYC ((uint32_t)0x00100000) /*!< PLL Ready Interrupt Clear */ +#define RCC_CIR_CSSC ((uint32_t)0x00800000) /*!< Clock Security System Interrupt Clear */ + +#ifdef STM32F10X_CL + #define RCC_CIR_PLL2RDYF ((uint32_t)0x00000020) /*!< PLL2 Ready Interrupt flag */ + #define RCC_CIR_PLL3RDYF ((uint32_t)0x00000040) /*!< PLL3 Ready Interrupt flag */ + #define RCC_CIR_PLL2RDYIE ((uint32_t)0x00002000) /*!< PLL2 Ready Interrupt Enable */ + #define RCC_CIR_PLL3RDYIE ((uint32_t)0x00004000) /*!< PLL3 Ready Interrupt Enable */ + #define RCC_CIR_PLL2RDYC ((uint32_t)0x00200000) /*!< PLL2 Ready Interrupt Clear */ + #define RCC_CIR_PLL3RDYC ((uint32_t)0x00400000) /*!< PLL3 Ready Interrupt Clear */ +#endif /* STM32F10X_CL */ + +/***************** Bit definition for RCC_APB2RSTR register *****************/ +#define RCC_APB2RSTR_AFIORST ((uint32_t)0x00000001) /*!< Alternate Function I/O reset */ +#define RCC_APB2RSTR_IOPARST ((uint32_t)0x00000004) /*!< I/O port A reset */ +#define RCC_APB2RSTR_IOPBRST ((uint32_t)0x00000008) /*!< I/O port B reset */ +#define RCC_APB2RSTR_IOPCRST ((uint32_t)0x00000010) /*!< I/O port C reset */ +#define RCC_APB2RSTR_IOPDRST ((uint32_t)0x00000020) /*!< I/O port D reset */ +#define RCC_APB2RSTR_ADC1RST ((uint32_t)0x00000200) /*!< ADC 1 interface reset */ + +#if !defined (STM32F10X_LD_VL) && !defined (STM32F10X_MD_VL) && !defined (STM32F10X_HD_VL) +#define RCC_APB2RSTR_ADC2RST ((uint32_t)0x00000400) /*!< ADC 2 interface reset */ +#endif + +#define RCC_APB2RSTR_TIM1RST ((uint32_t)0x00000800) /*!< TIM1 Timer reset */ +#define RCC_APB2RSTR_SPI1RST ((uint32_t)0x00001000) /*!< SPI 1 reset */ +#define RCC_APB2RSTR_USART1RST ((uint32_t)0x00004000) /*!< USART1 reset */ + +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) +#define RCC_APB2RSTR_TIM15RST ((uint32_t)0x00010000) /*!< TIM15 Timer reset */ +#define RCC_APB2RSTR_TIM16RST ((uint32_t)0x00020000) /*!< TIM16 Timer reset */ +#define RCC_APB2RSTR_TIM17RST ((uint32_t)0x00040000) /*!< TIM17 Timer reset */ +#endif + +#if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) + #define RCC_APB2RSTR_IOPERST ((uint32_t)0x00000040) /*!< I/O port E reset */ +#endif /* STM32F10X_LD && STM32F10X_LD_VL */ + +#if defined (STM32F10X_HD) || defined (STM32F10X_XL) + #define RCC_APB2RSTR_IOPFRST ((uint32_t)0x00000080) /*!< I/O port F reset */ + #define RCC_APB2RSTR_IOPGRST ((uint32_t)0x00000100) /*!< I/O port G reset */ + #define RCC_APB2RSTR_TIM8RST ((uint32_t)0x00002000) /*!< TIM8 Timer reset */ + #define RCC_APB2RSTR_ADC3RST ((uint32_t)0x00008000) /*!< ADC3 interface reset */ +#endif + +#if defined (STM32F10X_HD_VL) + #define RCC_APB2RSTR_IOPFRST ((uint32_t)0x00000080) /*!< I/O port F reset */ + #define RCC_APB2RSTR_IOPGRST ((uint32_t)0x00000100) /*!< I/O port G reset */ +#endif + +#ifdef STM32F10X_XL + #define RCC_APB2RSTR_TIM9RST ((uint32_t)0x00080000) /*!< TIM9 Timer reset */ + #define RCC_APB2RSTR_TIM10RST ((uint32_t)0x00100000) /*!< TIM10 Timer reset */ + #define RCC_APB2RSTR_TIM11RST ((uint32_t)0x00200000) /*!< TIM11 Timer reset */ +#endif /* STM32F10X_XL */ + +/***************** Bit definition for RCC_APB1RSTR register *****************/ +#define RCC_APB1RSTR_TIM2RST ((uint32_t)0x00000001) /*!< Timer 2 reset */ +#define RCC_APB1RSTR_TIM3RST ((uint32_t)0x00000002) /*!< Timer 3 reset */ +#define RCC_APB1RSTR_WWDGRST ((uint32_t)0x00000800) /*!< Window Watchdog reset */ +#define RCC_APB1RSTR_USART2RST ((uint32_t)0x00020000) /*!< USART 2 reset */ +#define RCC_APB1RSTR_I2C1RST ((uint32_t)0x00200000) /*!< I2C 1 reset */ + +#if !defined (STM32F10X_LD_VL) && !defined (STM32F10X_MD_VL) && !defined (STM32F10X_HD_VL) +#define RCC_APB1RSTR_CAN1RST ((uint32_t)0x02000000) /*!< CAN1 reset */ +#endif + +#define RCC_APB1RSTR_BKPRST ((uint32_t)0x08000000) /*!< Backup interface reset */ +#define RCC_APB1RSTR_PWRRST ((uint32_t)0x10000000) /*!< Power interface reset */ + +#if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) + #define RCC_APB1RSTR_TIM4RST ((uint32_t)0x00000004) /*!< Timer 4 reset */ + #define RCC_APB1RSTR_SPI2RST ((uint32_t)0x00004000) /*!< SPI 2 reset */ + #define RCC_APB1RSTR_USART3RST ((uint32_t)0x00040000) /*!< USART 3 reset */ + #define RCC_APB1RSTR_I2C2RST ((uint32_t)0x00400000) /*!< I2C 2 reset */ +#endif /* STM32F10X_LD && STM32F10X_LD_VL */ + +#if defined (STM32F10X_HD) || defined (STM32F10X_MD) || defined (STM32F10X_LD) || defined (STM32F10X_XL) + #define RCC_APB1RSTR_USBRST ((uint32_t)0x00800000) /*!< USB Device reset */ +#endif + +#if defined (STM32F10X_HD) || defined (STM32F10X_CL) || defined (STM32F10X_XL) + #define RCC_APB1RSTR_TIM5RST ((uint32_t)0x00000008) /*!< Timer 5 reset */ + #define RCC_APB1RSTR_TIM6RST ((uint32_t)0x00000010) /*!< Timer 6 reset */ + #define RCC_APB1RSTR_TIM7RST ((uint32_t)0x00000020) /*!< Timer 7 reset */ + #define RCC_APB1RSTR_SPI3RST ((uint32_t)0x00008000) /*!< SPI 3 reset */ + #define RCC_APB1RSTR_UART4RST ((uint32_t)0x00080000) /*!< UART 4 reset */ + #define RCC_APB1RSTR_UART5RST ((uint32_t)0x00100000) /*!< UART 5 reset */ + #define RCC_APB1RSTR_DACRST ((uint32_t)0x20000000) /*!< DAC interface reset */ +#endif + +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) + #define RCC_APB1RSTR_TIM6RST ((uint32_t)0x00000010) /*!< Timer 6 reset */ + #define RCC_APB1RSTR_TIM7RST ((uint32_t)0x00000020) /*!< Timer 7 reset */ + #define RCC_APB1RSTR_DACRST ((uint32_t)0x20000000) /*!< DAC interface reset */ + #define RCC_APB1RSTR_CECRST ((uint32_t)0x40000000) /*!< CEC interface reset */ +#endif + +#if defined (STM32F10X_HD_VL) + #define RCC_APB1RSTR_TIM5RST ((uint32_t)0x00000008) /*!< Timer 5 reset */ + #define RCC_APB1RSTR_TIM12RST ((uint32_t)0x00000040) /*!< TIM12 Timer reset */ + #define RCC_APB1RSTR_TIM13RST ((uint32_t)0x00000080) /*!< TIM13 Timer reset */ + #define RCC_APB1RSTR_TIM14RST ((uint32_t)0x00000100) /*!< TIM14 Timer reset */ + #define RCC_APB1RSTR_SPI3RST ((uint32_t)0x00008000) /*!< SPI 3 reset */ + #define RCC_APB1RSTR_UART4RST ((uint32_t)0x00080000) /*!< UART 4 reset */ + #define RCC_APB1RSTR_UART5RST ((uint32_t)0x00100000) /*!< UART 5 reset */ +#endif + +#ifdef STM32F10X_CL + #define RCC_APB1RSTR_CAN2RST ((uint32_t)0x04000000) /*!< CAN2 reset */ +#endif /* STM32F10X_CL */ + +#ifdef STM32F10X_XL + #define RCC_APB1RSTR_TIM12RST ((uint32_t)0x00000040) /*!< TIM12 Timer reset */ + #define RCC_APB1RSTR_TIM13RST ((uint32_t)0x00000080) /*!< TIM13 Timer reset */ + #define RCC_APB1RSTR_TIM14RST ((uint32_t)0x00000100) /*!< TIM14 Timer reset */ +#endif /* STM32F10X_XL */ + +/****************** Bit definition for RCC_AHBENR register ******************/ +#define RCC_AHBENR_DMA1EN ((uint16_t)0x0001) /*!< DMA1 clock enable */ +#define RCC_AHBENR_SRAMEN ((uint16_t)0x0004) /*!< SRAM interface clock enable */ +#define RCC_AHBENR_FLITFEN ((uint16_t)0x0010) /*!< FLITF clock enable */ +#define RCC_AHBENR_CRCEN ((uint16_t)0x0040) /*!< CRC clock enable */ + +#if defined (STM32F10X_HD) || defined (STM32F10X_CL) || defined (STM32F10X_HD_VL) + #define RCC_AHBENR_DMA2EN ((uint16_t)0x0002) /*!< DMA2 clock enable */ +#endif + +#if defined (STM32F10X_HD) || defined (STM32F10X_XL) + #define RCC_AHBENR_FSMCEN ((uint16_t)0x0100) /*!< FSMC clock enable */ + #define RCC_AHBENR_SDIOEN ((uint16_t)0x0400) /*!< SDIO clock enable */ +#endif + +#if defined (STM32F10X_HD_VL) + #define RCC_AHBENR_FSMCEN ((uint16_t)0x0100) /*!< FSMC clock enable */ +#endif + +#ifdef STM32F10X_CL + #define RCC_AHBENR_OTGFSEN ((uint32_t)0x00001000) /*!< USB OTG FS clock enable */ + #define RCC_AHBENR_ETHMACEN ((uint32_t)0x00004000) /*!< ETHERNET MAC clock enable */ + #define RCC_AHBENR_ETHMACTXEN ((uint32_t)0x00008000) /*!< ETHERNET MAC Tx clock enable */ + #define RCC_AHBENR_ETHMACRXEN ((uint32_t)0x00010000) /*!< ETHERNET MAC Rx clock enable */ +#endif /* STM32F10X_CL */ + +/****************** Bit definition for RCC_APB2ENR register *****************/ +#define RCC_APB2ENR_AFIOEN ((uint32_t)0x00000001) /*!< Alternate Function I/O clock enable */ +#define RCC_APB2ENR_IOPAEN ((uint32_t)0x00000004) /*!< I/O port A clock enable */ +#define RCC_APB2ENR_IOPBEN ((uint32_t)0x00000008) /*!< I/O port B clock enable */ +#define RCC_APB2ENR_IOPCEN ((uint32_t)0x00000010) /*!< I/O port C clock enable */ +#define RCC_APB2ENR_IOPDEN ((uint32_t)0x00000020) /*!< I/O port D clock enable */ +#define RCC_APB2ENR_ADC1EN ((uint32_t)0x00000200) /*!< ADC 1 interface clock enable */ + +#if !defined (STM32F10X_LD_VL) && !defined (STM32F10X_MD_VL) && !defined (STM32F10X_HD_VL) +#define RCC_APB2ENR_ADC2EN ((uint32_t)0x00000400) /*!< ADC 2 interface clock enable */ +#endif + +#define RCC_APB2ENR_TIM1EN ((uint32_t)0x00000800) /*!< TIM1 Timer clock enable */ +#define RCC_APB2ENR_SPI1EN ((uint32_t)0x00001000) /*!< SPI 1 clock enable */ +#define RCC_APB2ENR_USART1EN ((uint32_t)0x00004000) /*!< USART1 clock enable */ + +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) +#define RCC_APB2ENR_TIM15EN ((uint32_t)0x00010000) /*!< TIM15 Timer clock enable */ +#define RCC_APB2ENR_TIM16EN ((uint32_t)0x00020000) /*!< TIM16 Timer clock enable */ +#define RCC_APB2ENR_TIM17EN ((uint32_t)0x00040000) /*!< TIM17 Timer clock enable */ +#endif + +#if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) + #define RCC_APB2ENR_IOPEEN ((uint32_t)0x00000040) /*!< I/O port E clock enable */ +#endif /* STM32F10X_LD && STM32F10X_LD_VL */ + +#if defined (STM32F10X_HD) || defined (STM32F10X_XL) + #define RCC_APB2ENR_IOPFEN ((uint32_t)0x00000080) /*!< I/O port F clock enable */ + #define RCC_APB2ENR_IOPGEN ((uint32_t)0x00000100) /*!< I/O port G clock enable */ + #define RCC_APB2ENR_TIM8EN ((uint32_t)0x00002000) /*!< TIM8 Timer clock enable */ + #define RCC_APB2ENR_ADC3EN ((uint32_t)0x00008000) /*!< DMA1 clock enable */ +#endif + +#if defined (STM32F10X_HD_VL) + #define RCC_APB2ENR_IOPFEN ((uint32_t)0x00000080) /*!< I/O port F clock enable */ + #define RCC_APB2ENR_IOPGEN ((uint32_t)0x00000100) /*!< I/O port G clock enable */ +#endif + +#ifdef STM32F10X_XL + #define RCC_APB2ENR_TIM9EN ((uint32_t)0x00080000) /*!< TIM9 Timer clock enable */ + #define RCC_APB2ENR_TIM10EN ((uint32_t)0x00100000) /*!< TIM10 Timer clock enable */ + #define RCC_APB2ENR_TIM11EN ((uint32_t)0x00200000) /*!< TIM11 Timer clock enable */ +#endif + +/***************** Bit definition for RCC_APB1ENR register ******************/ +#define RCC_APB1ENR_TIM2EN ((uint32_t)0x00000001) /*!< Timer 2 clock enabled*/ +#define RCC_APB1ENR_TIM3EN ((uint32_t)0x00000002) /*!< Timer 3 clock enable */ +#define RCC_APB1ENR_WWDGEN ((uint32_t)0x00000800) /*!< Window Watchdog clock enable */ +#define RCC_APB1ENR_USART2EN ((uint32_t)0x00020000) /*!< USART 2 clock enable */ +#define RCC_APB1ENR_I2C1EN ((uint32_t)0x00200000) /*!< I2C 1 clock enable */ + +#if !defined (STM32F10X_LD_VL) && !defined (STM32F10X_MD_VL) && !defined (STM32F10X_HD_VL) +#define RCC_APB1ENR_CAN1EN ((uint32_t)0x02000000) /*!< CAN1 clock enable */ +#endif + +#define RCC_APB1ENR_BKPEN ((uint32_t)0x08000000) /*!< Backup interface clock enable */ +#define RCC_APB1ENR_PWREN ((uint32_t)0x10000000) /*!< Power interface clock enable */ + +#if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) + #define RCC_APB1ENR_TIM4EN ((uint32_t)0x00000004) /*!< Timer 4 clock enable */ + #define RCC_APB1ENR_SPI2EN ((uint32_t)0x00004000) /*!< SPI 2 clock enable */ + #define RCC_APB1ENR_USART3EN ((uint32_t)0x00040000) /*!< USART 3 clock enable */ + #define RCC_APB1ENR_I2C2EN ((uint32_t)0x00400000) /*!< I2C 2 clock enable */ +#endif /* STM32F10X_LD && STM32F10X_LD_VL */ + +#if defined (STM32F10X_HD) || defined (STM32F10X_MD) || defined (STM32F10X_LD) + #define RCC_APB1ENR_USBEN ((uint32_t)0x00800000) /*!< USB Device clock enable */ +#endif + +#if defined (STM32F10X_HD) || defined (STM32F10X_CL) + #define RCC_APB1ENR_TIM5EN ((uint32_t)0x00000008) /*!< Timer 5 clock enable */ + #define RCC_APB1ENR_TIM6EN ((uint32_t)0x00000010) /*!< Timer 6 clock enable */ + #define RCC_APB1ENR_TIM7EN ((uint32_t)0x00000020) /*!< Timer 7 clock enable */ + #define RCC_APB1ENR_SPI3EN ((uint32_t)0x00008000) /*!< SPI 3 clock enable */ + #define RCC_APB1ENR_UART4EN ((uint32_t)0x00080000) /*!< UART 4 clock enable */ + #define RCC_APB1ENR_UART5EN ((uint32_t)0x00100000) /*!< UART 5 clock enable */ + #define RCC_APB1ENR_DACEN ((uint32_t)0x20000000) /*!< DAC interface clock enable */ +#endif + +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) + #define RCC_APB1ENR_TIM6EN ((uint32_t)0x00000010) /*!< Timer 6 clock enable */ + #define RCC_APB1ENR_TIM7EN ((uint32_t)0x00000020) /*!< Timer 7 clock enable */ + #define RCC_APB1ENR_DACEN ((uint32_t)0x20000000) /*!< DAC interface clock enable */ + #define RCC_APB1ENR_CECEN ((uint32_t)0x40000000) /*!< CEC interface clock enable */ +#endif + +#ifdef STM32F10X_HD_VL + #define RCC_APB1ENR_TIM5EN ((uint32_t)0x00000008) /*!< Timer 5 clock enable */ + #define RCC_APB1ENR_TIM12EN ((uint32_t)0x00000040) /*!< TIM12 Timer clock enable */ + #define RCC_APB1ENR_TIM13EN ((uint32_t)0x00000080) /*!< TIM13 Timer clock enable */ + #define RCC_APB1ENR_TIM14EN ((uint32_t)0x00000100) /*!< TIM14 Timer clock enable */ + #define RCC_APB1ENR_SPI3EN ((uint32_t)0x00008000) /*!< SPI 3 clock enable */ + #define RCC_APB1ENR_UART4EN ((uint32_t)0x00080000) /*!< UART 4 clock enable */ + #define RCC_APB1ENR_UART5EN ((uint32_t)0x00100000) /*!< UART 5 clock enable */ +#endif /* STM32F10X_HD_VL */ + +#ifdef STM32F10X_CL + #define RCC_APB1ENR_CAN2EN ((uint32_t)0x04000000) /*!< CAN2 clock enable */ +#endif /* STM32F10X_CL */ + +#ifdef STM32F10X_XL + #define RCC_APB1ENR_TIM12EN ((uint32_t)0x00000040) /*!< TIM12 Timer clock enable */ + #define RCC_APB1ENR_TIM13EN ((uint32_t)0x00000080) /*!< TIM13 Timer clock enable */ + #define RCC_APB1ENR_TIM14EN ((uint32_t)0x00000100) /*!< TIM14 Timer clock enable */ +#endif /* STM32F10X_XL */ + +/******************* Bit definition for RCC_BDCR register *******************/ +#define RCC_BDCR_LSEON ((uint32_t)0x00000001) /*!< External Low Speed oscillator enable */ +#define RCC_BDCR_LSERDY ((uint32_t)0x00000002) /*!< External Low Speed oscillator Ready */ +#define RCC_BDCR_LSEBYP ((uint32_t)0x00000004) /*!< External Low Speed oscillator Bypass */ + +#define RCC_BDCR_RTCSEL ((uint32_t)0x00000300) /*!< RTCSEL[1:0] bits (RTC clock source selection) */ +#define RCC_BDCR_RTCSEL_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define RCC_BDCR_RTCSEL_1 ((uint32_t)0x00000200) /*!< Bit 1 */ + +/*!< RTC congiguration */ +#define RCC_BDCR_RTCSEL_NOCLOCK ((uint32_t)0x00000000) /*!< No clock */ +#define RCC_BDCR_RTCSEL_LSE ((uint32_t)0x00000100) /*!< LSE oscillator clock used as RTC clock */ +#define RCC_BDCR_RTCSEL_LSI ((uint32_t)0x00000200) /*!< LSI oscillator clock used as RTC clock */ +#define RCC_BDCR_RTCSEL_HSE ((uint32_t)0x00000300) /*!< HSE oscillator clock divided by 128 used as RTC clock */ + +#define RCC_BDCR_RTCEN ((uint32_t)0x00008000) /*!< RTC clock enable */ +#define RCC_BDCR_BDRST ((uint32_t)0x00010000) /*!< Backup domain software reset */ + +/******************* Bit definition for RCC_CSR register ********************/ +#define RCC_CSR_LSION ((uint32_t)0x00000001) /*!< Internal Low Speed oscillator enable */ +#define RCC_CSR_LSIRDY ((uint32_t)0x00000002) /*!< Internal Low Speed oscillator Ready */ +#define RCC_CSR_RMVF ((uint32_t)0x01000000) /*!< Remove reset flag */ +#define RCC_CSR_PINRSTF ((uint32_t)0x04000000) /*!< PIN reset flag */ +#define RCC_CSR_PORRSTF ((uint32_t)0x08000000) /*!< POR/PDR reset flag */ +#define RCC_CSR_SFTRSTF ((uint32_t)0x10000000) /*!< Software Reset flag */ +#define RCC_CSR_IWDGRSTF ((uint32_t)0x20000000) /*!< Independent Watchdog reset flag */ +#define RCC_CSR_WWDGRSTF ((uint32_t)0x40000000) /*!< Window watchdog reset flag */ +#define RCC_CSR_LPWRRSTF ((uint32_t)0x80000000) /*!< Low-Power reset flag */ + +#ifdef STM32F10X_CL +/******************* Bit definition for RCC_AHBRSTR register ****************/ + #define RCC_AHBRSTR_OTGFSRST ((uint32_t)0x00001000) /*!< USB OTG FS reset */ + #define RCC_AHBRSTR_ETHMACRST ((uint32_t)0x00004000) /*!< ETHERNET MAC reset */ + +/******************* Bit definition for RCC_CFGR2 register ******************/ +/*!< PREDIV1 configuration */ + #define RCC_CFGR2_PREDIV1 ((uint32_t)0x0000000F) /*!< PREDIV1[3:0] bits */ + #define RCC_CFGR2_PREDIV1_0 ((uint32_t)0x00000001) /*!< Bit 0 */ + #define RCC_CFGR2_PREDIV1_1 ((uint32_t)0x00000002) /*!< Bit 1 */ + #define RCC_CFGR2_PREDIV1_2 ((uint32_t)0x00000004) /*!< Bit 2 */ + #define RCC_CFGR2_PREDIV1_3 ((uint32_t)0x00000008) /*!< Bit 3 */ + + #define RCC_CFGR2_PREDIV1_DIV1 ((uint32_t)0x00000000) /*!< PREDIV1 input clock not divided */ + #define RCC_CFGR2_PREDIV1_DIV2 ((uint32_t)0x00000001) /*!< PREDIV1 input clock divided by 2 */ + #define RCC_CFGR2_PREDIV1_DIV3 ((uint32_t)0x00000002) /*!< PREDIV1 input clock divided by 3 */ + #define RCC_CFGR2_PREDIV1_DIV4 ((uint32_t)0x00000003) /*!< PREDIV1 input clock divided by 4 */ + #define RCC_CFGR2_PREDIV1_DIV5 ((uint32_t)0x00000004) /*!< PREDIV1 input clock divided by 5 */ + #define RCC_CFGR2_PREDIV1_DIV6 ((uint32_t)0x00000005) /*!< PREDIV1 input clock divided by 6 */ + #define RCC_CFGR2_PREDIV1_DIV7 ((uint32_t)0x00000006) /*!< PREDIV1 input clock divided by 7 */ + #define RCC_CFGR2_PREDIV1_DIV8 ((uint32_t)0x00000007) /*!< PREDIV1 input clock divided by 8 */ + #define RCC_CFGR2_PREDIV1_DIV9 ((uint32_t)0x00000008) /*!< PREDIV1 input clock divided by 9 */ + #define RCC_CFGR2_PREDIV1_DIV10 ((uint32_t)0x00000009) /*!< PREDIV1 input clock divided by 10 */ + #define RCC_CFGR2_PREDIV1_DIV11 ((uint32_t)0x0000000A) /*!< PREDIV1 input clock divided by 11 */ + #define RCC_CFGR2_PREDIV1_DIV12 ((uint32_t)0x0000000B) /*!< PREDIV1 input clock divided by 12 */ + #define RCC_CFGR2_PREDIV1_DIV13 ((uint32_t)0x0000000C) /*!< PREDIV1 input clock divided by 13 */ + #define RCC_CFGR2_PREDIV1_DIV14 ((uint32_t)0x0000000D) /*!< PREDIV1 input clock divided by 14 */ + #define RCC_CFGR2_PREDIV1_DIV15 ((uint32_t)0x0000000E) /*!< PREDIV1 input clock divided by 15 */ + #define RCC_CFGR2_PREDIV1_DIV16 ((uint32_t)0x0000000F) /*!< PREDIV1 input clock divided by 16 */ + +/*!< PREDIV2 configuration */ + #define RCC_CFGR2_PREDIV2 ((uint32_t)0x000000F0) /*!< PREDIV2[3:0] bits */ + #define RCC_CFGR2_PREDIV2_0 ((uint32_t)0x00000010) /*!< Bit 0 */ + #define RCC_CFGR2_PREDIV2_1 ((uint32_t)0x00000020) /*!< Bit 1 */ + #define RCC_CFGR2_PREDIV2_2 ((uint32_t)0x00000040) /*!< Bit 2 */ + #define RCC_CFGR2_PREDIV2_3 ((uint32_t)0x00000080) /*!< Bit 3 */ + + #define RCC_CFGR2_PREDIV2_DIV1 ((uint32_t)0x00000000) /*!< PREDIV2 input clock not divided */ + #define RCC_CFGR2_PREDIV2_DIV2 ((uint32_t)0x00000010) /*!< PREDIV2 input clock divided by 2 */ + #define RCC_CFGR2_PREDIV2_DIV3 ((uint32_t)0x00000020) /*!< PREDIV2 input clock divided by 3 */ + #define RCC_CFGR2_PREDIV2_DIV4 ((uint32_t)0x00000030) /*!< PREDIV2 input clock divided by 4 */ + #define RCC_CFGR2_PREDIV2_DIV5 ((uint32_t)0x00000040) /*!< PREDIV2 input clock divided by 5 */ + #define RCC_CFGR2_PREDIV2_DIV6 ((uint32_t)0x00000050) /*!< PREDIV2 input clock divided by 6 */ + #define RCC_CFGR2_PREDIV2_DIV7 ((uint32_t)0x00000060) /*!< PREDIV2 input clock divided by 7 */ + #define RCC_CFGR2_PREDIV2_DIV8 ((uint32_t)0x00000070) /*!< PREDIV2 input clock divided by 8 */ + #define RCC_CFGR2_PREDIV2_DIV9 ((uint32_t)0x00000080) /*!< PREDIV2 input clock divided by 9 */ + #define RCC_CFGR2_PREDIV2_DIV10 ((uint32_t)0x00000090) /*!< PREDIV2 input clock divided by 10 */ + #define RCC_CFGR2_PREDIV2_DIV11 ((uint32_t)0x000000A0) /*!< PREDIV2 input clock divided by 11 */ + #define RCC_CFGR2_PREDIV2_DIV12 ((uint32_t)0x000000B0) /*!< PREDIV2 input clock divided by 12 */ + #define RCC_CFGR2_PREDIV2_DIV13 ((uint32_t)0x000000C0) /*!< PREDIV2 input clock divided by 13 */ + #define RCC_CFGR2_PREDIV2_DIV14 ((uint32_t)0x000000D0) /*!< PREDIV2 input clock divided by 14 */ + #define RCC_CFGR2_PREDIV2_DIV15 ((uint32_t)0x000000E0) /*!< PREDIV2 input clock divided by 15 */ + #define RCC_CFGR2_PREDIV2_DIV16 ((uint32_t)0x000000F0) /*!< PREDIV2 input clock divided by 16 */ + +/*!< PLL2MUL configuration */ + #define RCC_CFGR2_PLL2MUL ((uint32_t)0x00000F00) /*!< PLL2MUL[3:0] bits */ + #define RCC_CFGR2_PLL2MUL_0 ((uint32_t)0x00000100) /*!< Bit 0 */ + #define RCC_CFGR2_PLL2MUL_1 ((uint32_t)0x00000200) /*!< Bit 1 */ + #define RCC_CFGR2_PLL2MUL_2 ((uint32_t)0x00000400) /*!< Bit 2 */ + #define RCC_CFGR2_PLL2MUL_3 ((uint32_t)0x00000800) /*!< Bit 3 */ + + #define RCC_CFGR2_PLL2MUL8 ((uint32_t)0x00000600) /*!< PLL2 input clock * 8 */ + #define RCC_CFGR2_PLL2MUL9 ((uint32_t)0x00000700) /*!< PLL2 input clock * 9 */ + #define RCC_CFGR2_PLL2MUL10 ((uint32_t)0x00000800) /*!< PLL2 input clock * 10 */ + #define RCC_CFGR2_PLL2MUL11 ((uint32_t)0x00000900) /*!< PLL2 input clock * 11 */ + #define RCC_CFGR2_PLL2MUL12 ((uint32_t)0x00000A00) /*!< PLL2 input clock * 12 */ + #define RCC_CFGR2_PLL2MUL13 ((uint32_t)0x00000B00) /*!< PLL2 input clock * 13 */ + #define RCC_CFGR2_PLL2MUL14 ((uint32_t)0x00000C00) /*!< PLL2 input clock * 14 */ + #define RCC_CFGR2_PLL2MUL16 ((uint32_t)0x00000E00) /*!< PLL2 input clock * 16 */ + #define RCC_CFGR2_PLL2MUL20 ((uint32_t)0x00000F00) /*!< PLL2 input clock * 20 */ + +/*!< PLL3MUL configuration */ + #define RCC_CFGR2_PLL3MUL ((uint32_t)0x0000F000) /*!< PLL3MUL[3:0] bits */ + #define RCC_CFGR2_PLL3MUL_0 ((uint32_t)0x00001000) /*!< Bit 0 */ + #define RCC_CFGR2_PLL3MUL_1 ((uint32_t)0x00002000) /*!< Bit 1 */ + #define RCC_CFGR2_PLL3MUL_2 ((uint32_t)0x00004000) /*!< Bit 2 */ + #define RCC_CFGR2_PLL3MUL_3 ((uint32_t)0x00008000) /*!< Bit 3 */ + + #define RCC_CFGR2_PLL3MUL8 ((uint32_t)0x00006000) /*!< PLL3 input clock * 8 */ + #define RCC_CFGR2_PLL3MUL9 ((uint32_t)0x00007000) /*!< PLL3 input clock * 9 */ + #define RCC_CFGR2_PLL3MUL10 ((uint32_t)0x00008000) /*!< PLL3 input clock * 10 */ + #define RCC_CFGR2_PLL3MUL11 ((uint32_t)0x00009000) /*!< PLL3 input clock * 11 */ + #define RCC_CFGR2_PLL3MUL12 ((uint32_t)0x0000A000) /*!< PLL3 input clock * 12 */ + #define RCC_CFGR2_PLL3MUL13 ((uint32_t)0x0000B000) /*!< PLL3 input clock * 13 */ + #define RCC_CFGR2_PLL3MUL14 ((uint32_t)0x0000C000) /*!< PLL3 input clock * 14 */ + #define RCC_CFGR2_PLL3MUL16 ((uint32_t)0x0000E000) /*!< PLL3 input clock * 16 */ + #define RCC_CFGR2_PLL3MUL20 ((uint32_t)0x0000F000) /*!< PLL3 input clock * 20 */ + + #define RCC_CFGR2_PREDIV1SRC ((uint32_t)0x00010000) /*!< PREDIV1 entry clock source */ + #define RCC_CFGR2_PREDIV1SRC_PLL2 ((uint32_t)0x00010000) /*!< PLL2 selected as PREDIV1 entry clock source */ + #define RCC_CFGR2_PREDIV1SRC_HSE ((uint32_t)0x00000000) /*!< HSE selected as PREDIV1 entry clock source */ + #define RCC_CFGR2_I2S2SRC ((uint32_t)0x00020000) /*!< I2S2 entry clock source */ + #define RCC_CFGR2_I2S3SRC ((uint32_t)0x00040000) /*!< I2S3 clock source */ +#endif /* STM32F10X_CL */ + +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) +/******************* Bit definition for RCC_CFGR2 register ******************/ +/*!< PREDIV1 configuration */ + #define RCC_CFGR2_PREDIV1 ((uint32_t)0x0000000F) /*!< PREDIV1[3:0] bits */ + #define RCC_CFGR2_PREDIV1_0 ((uint32_t)0x00000001) /*!< Bit 0 */ + #define RCC_CFGR2_PREDIV1_1 ((uint32_t)0x00000002) /*!< Bit 1 */ + #define RCC_CFGR2_PREDIV1_2 ((uint32_t)0x00000004) /*!< Bit 2 */ + #define RCC_CFGR2_PREDIV1_3 ((uint32_t)0x00000008) /*!< Bit 3 */ + + #define RCC_CFGR2_PREDIV1_DIV1 ((uint32_t)0x00000000) /*!< PREDIV1 input clock not divided */ + #define RCC_CFGR2_PREDIV1_DIV2 ((uint32_t)0x00000001) /*!< PREDIV1 input clock divided by 2 */ + #define RCC_CFGR2_PREDIV1_DIV3 ((uint32_t)0x00000002) /*!< PREDIV1 input clock divided by 3 */ + #define RCC_CFGR2_PREDIV1_DIV4 ((uint32_t)0x00000003) /*!< PREDIV1 input clock divided by 4 */ + #define RCC_CFGR2_PREDIV1_DIV5 ((uint32_t)0x00000004) /*!< PREDIV1 input clock divided by 5 */ + #define RCC_CFGR2_PREDIV1_DIV6 ((uint32_t)0x00000005) /*!< PREDIV1 input clock divided by 6 */ + #define RCC_CFGR2_PREDIV1_DIV7 ((uint32_t)0x00000006) /*!< PREDIV1 input clock divided by 7 */ + #define RCC_CFGR2_PREDIV1_DIV8 ((uint32_t)0x00000007) /*!< PREDIV1 input clock divided by 8 */ + #define RCC_CFGR2_PREDIV1_DIV9 ((uint32_t)0x00000008) /*!< PREDIV1 input clock divided by 9 */ + #define RCC_CFGR2_PREDIV1_DIV10 ((uint32_t)0x00000009) /*!< PREDIV1 input clock divided by 10 */ + #define RCC_CFGR2_PREDIV1_DIV11 ((uint32_t)0x0000000A) /*!< PREDIV1 input clock divided by 11 */ + #define RCC_CFGR2_PREDIV1_DIV12 ((uint32_t)0x0000000B) /*!< PREDIV1 input clock divided by 12 */ + #define RCC_CFGR2_PREDIV1_DIV13 ((uint32_t)0x0000000C) /*!< PREDIV1 input clock divided by 13 */ + #define RCC_CFGR2_PREDIV1_DIV14 ((uint32_t)0x0000000D) /*!< PREDIV1 input clock divided by 14 */ + #define RCC_CFGR2_PREDIV1_DIV15 ((uint32_t)0x0000000E) /*!< PREDIV1 input clock divided by 15 */ + #define RCC_CFGR2_PREDIV1_DIV16 ((uint32_t)0x0000000F) /*!< PREDIV1 input clock divided by 16 */ +#endif + +/******************************************************************************/ +/* */ +/* General Purpose and Alternate Function I/O */ +/* */ +/******************************************************************************/ + +/******************* Bit definition for GPIO_CRL register *******************/ +#define GPIO_CRL_MODE ((uint32_t)0x33333333) /*!< Port x mode bits */ + +#define GPIO_CRL_MODE0 ((uint32_t)0x00000003) /*!< MODE0[1:0] bits (Port x mode bits, pin 0) */ +#define GPIO_CRL_MODE0_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define GPIO_CRL_MODE0_1 ((uint32_t)0x00000002) /*!< Bit 1 */ + +#define GPIO_CRL_MODE1 ((uint32_t)0x00000030) /*!< MODE1[1:0] bits (Port x mode bits, pin 1) */ +#define GPIO_CRL_MODE1_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define GPIO_CRL_MODE1_1 ((uint32_t)0x00000020) /*!< Bit 1 */ + +#define GPIO_CRL_MODE2 ((uint32_t)0x00000300) /*!< MODE2[1:0] bits (Port x mode bits, pin 2) */ +#define GPIO_CRL_MODE2_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define GPIO_CRL_MODE2_1 ((uint32_t)0x00000200) /*!< Bit 1 */ + +#define GPIO_CRL_MODE3 ((uint32_t)0x00003000) /*!< MODE3[1:0] bits (Port x mode bits, pin 3) */ +#define GPIO_CRL_MODE3_0 ((uint32_t)0x00001000) /*!< Bit 0 */ +#define GPIO_CRL_MODE3_1 ((uint32_t)0x00002000) /*!< Bit 1 */ + +#define GPIO_CRL_MODE4 ((uint32_t)0x00030000) /*!< MODE4[1:0] bits (Port x mode bits, pin 4) */ +#define GPIO_CRL_MODE4_0 ((uint32_t)0x00010000) /*!< Bit 0 */ +#define GPIO_CRL_MODE4_1 ((uint32_t)0x00020000) /*!< Bit 1 */ + +#define GPIO_CRL_MODE5 ((uint32_t)0x00300000) /*!< MODE5[1:0] bits (Port x mode bits, pin 5) */ +#define GPIO_CRL_MODE5_0 ((uint32_t)0x00100000) /*!< Bit 0 */ +#define GPIO_CRL_MODE5_1 ((uint32_t)0x00200000) /*!< Bit 1 */ + +#define GPIO_CRL_MODE6 ((uint32_t)0x03000000) /*!< MODE6[1:0] bits (Port x mode bits, pin 6) */ +#define GPIO_CRL_MODE6_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define GPIO_CRL_MODE6_1 ((uint32_t)0x02000000) /*!< Bit 1 */ + +#define GPIO_CRL_MODE7 ((uint32_t)0x30000000) /*!< MODE7[1:0] bits (Port x mode bits, pin 7) */ +#define GPIO_CRL_MODE7_0 ((uint32_t)0x10000000) /*!< Bit 0 */ +#define GPIO_CRL_MODE7_1 ((uint32_t)0x20000000) /*!< Bit 1 */ + +#define GPIO_CRL_CNF ((uint32_t)0xCCCCCCCC) /*!< Port x configuration bits */ + +#define GPIO_CRL_CNF0 ((uint32_t)0x0000000C) /*!< CNF0[1:0] bits (Port x configuration bits, pin 0) */ +#define GPIO_CRL_CNF0_0 ((uint32_t)0x00000004) /*!< Bit 0 */ +#define GPIO_CRL_CNF0_1 ((uint32_t)0x00000008) /*!< Bit 1 */ + +#define GPIO_CRL_CNF1 ((uint32_t)0x000000C0) /*!< CNF1[1:0] bits (Port x configuration bits, pin 1) */ +#define GPIO_CRL_CNF1_0 ((uint32_t)0x00000040) /*!< Bit 0 */ +#define GPIO_CRL_CNF1_1 ((uint32_t)0x00000080) /*!< Bit 1 */ + +#define GPIO_CRL_CNF2 ((uint32_t)0x00000C00) /*!< CNF2[1:0] bits (Port x configuration bits, pin 2) */ +#define GPIO_CRL_CNF2_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define GPIO_CRL_CNF2_1 ((uint32_t)0x00000800) /*!< Bit 1 */ + +#define GPIO_CRL_CNF3 ((uint32_t)0x0000C000) /*!< CNF3[1:0] bits (Port x configuration bits, pin 3) */ +#define GPIO_CRL_CNF3_0 ((uint32_t)0x00004000) /*!< Bit 0 */ +#define GPIO_CRL_CNF3_1 ((uint32_t)0x00008000) /*!< Bit 1 */ + +#define GPIO_CRL_CNF4 ((uint32_t)0x000C0000) /*!< CNF4[1:0] bits (Port x configuration bits, pin 4) */ +#define GPIO_CRL_CNF4_0 ((uint32_t)0x00040000) /*!< Bit 0 */ +#define GPIO_CRL_CNF4_1 ((uint32_t)0x00080000) /*!< Bit 1 */ + +#define GPIO_CRL_CNF5 ((uint32_t)0x00C00000) /*!< CNF5[1:0] bits (Port x configuration bits, pin 5) */ +#define GPIO_CRL_CNF5_0 ((uint32_t)0x00400000) /*!< Bit 0 */ +#define GPIO_CRL_CNF5_1 ((uint32_t)0x00800000) /*!< Bit 1 */ + +#define GPIO_CRL_CNF6 ((uint32_t)0x0C000000) /*!< CNF6[1:0] bits (Port x configuration bits, pin 6) */ +#define GPIO_CRL_CNF6_0 ((uint32_t)0x04000000) /*!< Bit 0 */ +#define GPIO_CRL_CNF6_1 ((uint32_t)0x08000000) /*!< Bit 1 */ + +#define GPIO_CRL_CNF7 ((uint32_t)0xC0000000) /*!< CNF7[1:0] bits (Port x configuration bits, pin 7) */ +#define GPIO_CRL_CNF7_0 ((uint32_t)0x40000000) /*!< Bit 0 */ +#define GPIO_CRL_CNF7_1 ((uint32_t)0x80000000) /*!< Bit 1 */ + +/******************* Bit definition for GPIO_CRH register *******************/ +#define GPIO_CRH_MODE ((uint32_t)0x33333333) /*!< Port x mode bits */ + +#define GPIO_CRH_MODE8 ((uint32_t)0x00000003) /*!< MODE8[1:0] bits (Port x mode bits, pin 8) */ +#define GPIO_CRH_MODE8_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define GPIO_CRH_MODE8_1 ((uint32_t)0x00000002) /*!< Bit 1 */ + +#define GPIO_CRH_MODE9 ((uint32_t)0x00000030) /*!< MODE9[1:0] bits (Port x mode bits, pin 9) */ +#define GPIO_CRH_MODE9_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define GPIO_CRH_MODE9_1 ((uint32_t)0x00000020) /*!< Bit 1 */ + +#define GPIO_CRH_MODE10 ((uint32_t)0x00000300) /*!< MODE10[1:0] bits (Port x mode bits, pin 10) */ +#define GPIO_CRH_MODE10_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define GPIO_CRH_MODE10_1 ((uint32_t)0x00000200) /*!< Bit 1 */ + +#define GPIO_CRH_MODE11 ((uint32_t)0x00003000) /*!< MODE11[1:0] bits (Port x mode bits, pin 11) */ +#define GPIO_CRH_MODE11_0 ((uint32_t)0x00001000) /*!< Bit 0 */ +#define GPIO_CRH_MODE11_1 ((uint32_t)0x00002000) /*!< Bit 1 */ + +#define GPIO_CRH_MODE12 ((uint32_t)0x00030000) /*!< MODE12[1:0] bits (Port x mode bits, pin 12) */ +#define GPIO_CRH_MODE12_0 ((uint32_t)0x00010000) /*!< Bit 0 */ +#define GPIO_CRH_MODE12_1 ((uint32_t)0x00020000) /*!< Bit 1 */ + +#define GPIO_CRH_MODE13 ((uint32_t)0x00300000) /*!< MODE13[1:0] bits (Port x mode bits, pin 13) */ +#define GPIO_CRH_MODE13_0 ((uint32_t)0x00100000) /*!< Bit 0 */ +#define GPIO_CRH_MODE13_1 ((uint32_t)0x00200000) /*!< Bit 1 */ + +#define GPIO_CRH_MODE14 ((uint32_t)0x03000000) /*!< MODE14[1:0] bits (Port x mode bits, pin 14) */ +#define GPIO_CRH_MODE14_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define GPIO_CRH_MODE14_1 ((uint32_t)0x02000000) /*!< Bit 1 */ + +#define GPIO_CRH_MODE15 ((uint32_t)0x30000000) /*!< MODE15[1:0] bits (Port x mode bits, pin 15) */ +#define GPIO_CRH_MODE15_0 ((uint32_t)0x10000000) /*!< Bit 0 */ +#define GPIO_CRH_MODE15_1 ((uint32_t)0x20000000) /*!< Bit 1 */ + +#define GPIO_CRH_CNF ((uint32_t)0xCCCCCCCC) /*!< Port x configuration bits */ + +#define GPIO_CRH_CNF8 ((uint32_t)0x0000000C) /*!< CNF8[1:0] bits (Port x configuration bits, pin 8) */ +#define GPIO_CRH_CNF8_0 ((uint32_t)0x00000004) /*!< Bit 0 */ +#define GPIO_CRH_CNF8_1 ((uint32_t)0x00000008) /*!< Bit 1 */ + +#define GPIO_CRH_CNF9 ((uint32_t)0x000000C0) /*!< CNF9[1:0] bits (Port x configuration bits, pin 9) */ +#define GPIO_CRH_CNF9_0 ((uint32_t)0x00000040) /*!< Bit 0 */ +#define GPIO_CRH_CNF9_1 ((uint32_t)0x00000080) /*!< Bit 1 */ + +#define GPIO_CRH_CNF10 ((uint32_t)0x00000C00) /*!< CNF10[1:0] bits (Port x configuration bits, pin 10) */ +#define GPIO_CRH_CNF10_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define GPIO_CRH_CNF10_1 ((uint32_t)0x00000800) /*!< Bit 1 */ + +#define GPIO_CRH_CNF11 ((uint32_t)0x0000C000) /*!< CNF11[1:0] bits (Port x configuration bits, pin 11) */ +#define GPIO_CRH_CNF11_0 ((uint32_t)0x00004000) /*!< Bit 0 */ +#define GPIO_CRH_CNF11_1 ((uint32_t)0x00008000) /*!< Bit 1 */ + +#define GPIO_CRH_CNF12 ((uint32_t)0x000C0000) /*!< CNF12[1:0] bits (Port x configuration bits, pin 12) */ +#define GPIO_CRH_CNF12_0 ((uint32_t)0x00040000) /*!< Bit 0 */ +#define GPIO_CRH_CNF12_1 ((uint32_t)0x00080000) /*!< Bit 1 */ + +#define GPIO_CRH_CNF13 ((uint32_t)0x00C00000) /*!< CNF13[1:0] bits (Port x configuration bits, pin 13) */ +#define GPIO_CRH_CNF13_0 ((uint32_t)0x00400000) /*!< Bit 0 */ +#define GPIO_CRH_CNF13_1 ((uint32_t)0x00800000) /*!< Bit 1 */ + +#define GPIO_CRH_CNF14 ((uint32_t)0x0C000000) /*!< CNF14[1:0] bits (Port x configuration bits, pin 14) */ +#define GPIO_CRH_CNF14_0 ((uint32_t)0x04000000) /*!< Bit 0 */ +#define GPIO_CRH_CNF14_1 ((uint32_t)0x08000000) /*!< Bit 1 */ + +#define GPIO_CRH_CNF15 ((uint32_t)0xC0000000) /*!< CNF15[1:0] bits (Port x configuration bits, pin 15) */ +#define GPIO_CRH_CNF15_0 ((uint32_t)0x40000000) /*!< Bit 0 */ +#define GPIO_CRH_CNF15_1 ((uint32_t)0x80000000) /*!< Bit 1 */ + +/*!<****************** Bit definition for GPIO_IDR register *******************/ +#define GPIO_IDR_IDR0 ((uint16_t)0x0001) /*!< Port input data, bit 0 */ +#define GPIO_IDR_IDR1 ((uint16_t)0x0002) /*!< Port input data, bit 1 */ +#define GPIO_IDR_IDR2 ((uint16_t)0x0004) /*!< Port input data, bit 2 */ +#define GPIO_IDR_IDR3 ((uint16_t)0x0008) /*!< Port input data, bit 3 */ +#define GPIO_IDR_IDR4 ((uint16_t)0x0010) /*!< Port input data, bit 4 */ +#define GPIO_IDR_IDR5 ((uint16_t)0x0020) /*!< Port input data, bit 5 */ +#define GPIO_IDR_IDR6 ((uint16_t)0x0040) /*!< Port input data, bit 6 */ +#define GPIO_IDR_IDR7 ((uint16_t)0x0080) /*!< Port input data, bit 7 */ +#define GPIO_IDR_IDR8 ((uint16_t)0x0100) /*!< Port input data, bit 8 */ +#define GPIO_IDR_IDR9 ((uint16_t)0x0200) /*!< Port input data, bit 9 */ +#define GPIO_IDR_IDR10 ((uint16_t)0x0400) /*!< Port input data, bit 10 */ +#define GPIO_IDR_IDR11 ((uint16_t)0x0800) /*!< Port input data, bit 11 */ +#define GPIO_IDR_IDR12 ((uint16_t)0x1000) /*!< Port input data, bit 12 */ +#define GPIO_IDR_IDR13 ((uint16_t)0x2000) /*!< Port input data, bit 13 */ +#define GPIO_IDR_IDR14 ((uint16_t)0x4000) /*!< Port input data, bit 14 */ +#define GPIO_IDR_IDR15 ((uint16_t)0x8000) /*!< Port input data, bit 15 */ + +/******************* Bit definition for GPIO_ODR register *******************/ +#define GPIO_ODR_ODR0 ((uint16_t)0x0001) /*!< Port output data, bit 0 */ +#define GPIO_ODR_ODR1 ((uint16_t)0x0002) /*!< Port output data, bit 1 */ +#define GPIO_ODR_ODR2 ((uint16_t)0x0004) /*!< Port output data, bit 2 */ +#define GPIO_ODR_ODR3 ((uint16_t)0x0008) /*!< Port output data, bit 3 */ +#define GPIO_ODR_ODR4 ((uint16_t)0x0010) /*!< Port output data, bit 4 */ +#define GPIO_ODR_ODR5 ((uint16_t)0x0020) /*!< Port output data, bit 5 */ +#define GPIO_ODR_ODR6 ((uint16_t)0x0040) /*!< Port output data, bit 6 */ +#define GPIO_ODR_ODR7 ((uint16_t)0x0080) /*!< Port output data, bit 7 */ +#define GPIO_ODR_ODR8 ((uint16_t)0x0100) /*!< Port output data, bit 8 */ +#define GPIO_ODR_ODR9 ((uint16_t)0x0200) /*!< Port output data, bit 9 */ +#define GPIO_ODR_ODR10 ((uint16_t)0x0400) /*!< Port output data, bit 10 */ +#define GPIO_ODR_ODR11 ((uint16_t)0x0800) /*!< Port output data, bit 11 */ +#define GPIO_ODR_ODR12 ((uint16_t)0x1000) /*!< Port output data, bit 12 */ +#define GPIO_ODR_ODR13 ((uint16_t)0x2000) /*!< Port output data, bit 13 */ +#define GPIO_ODR_ODR14 ((uint16_t)0x4000) /*!< Port output data, bit 14 */ +#define GPIO_ODR_ODR15 ((uint16_t)0x8000) /*!< Port output data, bit 15 */ + +/****************** Bit definition for GPIO_BSRR register *******************/ +#define GPIO_BSRR_BS0 ((uint32_t)0x00000001) /*!< Port x Set bit 0 */ +#define GPIO_BSRR_BS1 ((uint32_t)0x00000002) /*!< Port x Set bit 1 */ +#define GPIO_BSRR_BS2 ((uint32_t)0x00000004) /*!< Port x Set bit 2 */ +#define GPIO_BSRR_BS3 ((uint32_t)0x00000008) /*!< Port x Set bit 3 */ +#define GPIO_BSRR_BS4 ((uint32_t)0x00000010) /*!< Port x Set bit 4 */ +#define GPIO_BSRR_BS5 ((uint32_t)0x00000020) /*!< Port x Set bit 5 */ +#define GPIO_BSRR_BS6 ((uint32_t)0x00000040) /*!< Port x Set bit 6 */ +#define GPIO_BSRR_BS7 ((uint32_t)0x00000080) /*!< Port x Set bit 7 */ +#define GPIO_BSRR_BS8 ((uint32_t)0x00000100) /*!< Port x Set bit 8 */ +#define GPIO_BSRR_BS9 ((uint32_t)0x00000200) /*!< Port x Set bit 9 */ +#define GPIO_BSRR_BS10 ((uint32_t)0x00000400) /*!< Port x Set bit 10 */ +#define GPIO_BSRR_BS11 ((uint32_t)0x00000800) /*!< Port x Set bit 11 */ +#define GPIO_BSRR_BS12 ((uint32_t)0x00001000) /*!< Port x Set bit 12 */ +#define GPIO_BSRR_BS13 ((uint32_t)0x00002000) /*!< Port x Set bit 13 */ +#define GPIO_BSRR_BS14 ((uint32_t)0x00004000) /*!< Port x Set bit 14 */ +#define GPIO_BSRR_BS15 ((uint32_t)0x00008000) /*!< Port x Set bit 15 */ + +#define GPIO_BSRR_BR0 ((uint32_t)0x00010000) /*!< Port x Reset bit 0 */ +#define GPIO_BSRR_BR1 ((uint32_t)0x00020000) /*!< Port x Reset bit 1 */ +#define GPIO_BSRR_BR2 ((uint32_t)0x00040000) /*!< Port x Reset bit 2 */ +#define GPIO_BSRR_BR3 ((uint32_t)0x00080000) /*!< Port x Reset bit 3 */ +#define GPIO_BSRR_BR4 ((uint32_t)0x00100000) /*!< Port x Reset bit 4 */ +#define GPIO_BSRR_BR5 ((uint32_t)0x00200000) /*!< Port x Reset bit 5 */ +#define GPIO_BSRR_BR6 ((uint32_t)0x00400000) /*!< Port x Reset bit 6 */ +#define GPIO_BSRR_BR7 ((uint32_t)0x00800000) /*!< Port x Reset bit 7 */ +#define GPIO_BSRR_BR8 ((uint32_t)0x01000000) /*!< Port x Reset bit 8 */ +#define GPIO_BSRR_BR9 ((uint32_t)0x02000000) /*!< Port x Reset bit 9 */ +#define GPIO_BSRR_BR10 ((uint32_t)0x04000000) /*!< Port x Reset bit 10 */ +#define GPIO_BSRR_BR11 ((uint32_t)0x08000000) /*!< Port x Reset bit 11 */ +#define GPIO_BSRR_BR12 ((uint32_t)0x10000000) /*!< Port x Reset bit 12 */ +#define GPIO_BSRR_BR13 ((uint32_t)0x20000000) /*!< Port x Reset bit 13 */ +#define GPIO_BSRR_BR14 ((uint32_t)0x40000000) /*!< Port x Reset bit 14 */ +#define GPIO_BSRR_BR15 ((uint32_t)0x80000000) /*!< Port x Reset bit 15 */ + +/******************* Bit definition for GPIO_BRR register *******************/ +#define GPIO_BRR_BR0 ((uint16_t)0x0001) /*!< Port x Reset bit 0 */ +#define GPIO_BRR_BR1 ((uint16_t)0x0002) /*!< Port x Reset bit 1 */ +#define GPIO_BRR_BR2 ((uint16_t)0x0004) /*!< Port x Reset bit 2 */ +#define GPIO_BRR_BR3 ((uint16_t)0x0008) /*!< Port x Reset bit 3 */ +#define GPIO_BRR_BR4 ((uint16_t)0x0010) /*!< Port x Reset bit 4 */ +#define GPIO_BRR_BR5 ((uint16_t)0x0020) /*!< Port x Reset bit 5 */ +#define GPIO_BRR_BR6 ((uint16_t)0x0040) /*!< Port x Reset bit 6 */ +#define GPIO_BRR_BR7 ((uint16_t)0x0080) /*!< Port x Reset bit 7 */ +#define GPIO_BRR_BR8 ((uint16_t)0x0100) /*!< Port x Reset bit 8 */ +#define GPIO_BRR_BR9 ((uint16_t)0x0200) /*!< Port x Reset bit 9 */ +#define GPIO_BRR_BR10 ((uint16_t)0x0400) /*!< Port x Reset bit 10 */ +#define GPIO_BRR_BR11 ((uint16_t)0x0800) /*!< Port x Reset bit 11 */ +#define GPIO_BRR_BR12 ((uint16_t)0x1000) /*!< Port x Reset bit 12 */ +#define GPIO_BRR_BR13 ((uint16_t)0x2000) /*!< Port x Reset bit 13 */ +#define GPIO_BRR_BR14 ((uint16_t)0x4000) /*!< Port x Reset bit 14 */ +#define GPIO_BRR_BR15 ((uint16_t)0x8000) /*!< Port x Reset bit 15 */ + +/****************** Bit definition for GPIO_LCKR register *******************/ +#define GPIO_LCKR_LCK0 ((uint32_t)0x00000001) /*!< Port x Lock bit 0 */ +#define GPIO_LCKR_LCK1 ((uint32_t)0x00000002) /*!< Port x Lock bit 1 */ +#define GPIO_LCKR_LCK2 ((uint32_t)0x00000004) /*!< Port x Lock bit 2 */ +#define GPIO_LCKR_LCK3 ((uint32_t)0x00000008) /*!< Port x Lock bit 3 */ +#define GPIO_LCKR_LCK4 ((uint32_t)0x00000010) /*!< Port x Lock bit 4 */ +#define GPIO_LCKR_LCK5 ((uint32_t)0x00000020) /*!< Port x Lock bit 5 */ +#define GPIO_LCKR_LCK6 ((uint32_t)0x00000040) /*!< Port x Lock bit 6 */ +#define GPIO_LCKR_LCK7 ((uint32_t)0x00000080) /*!< Port x Lock bit 7 */ +#define GPIO_LCKR_LCK8 ((uint32_t)0x00000100) /*!< Port x Lock bit 8 */ +#define GPIO_LCKR_LCK9 ((uint32_t)0x00000200) /*!< Port x Lock bit 9 */ +#define GPIO_LCKR_LCK10 ((uint32_t)0x00000400) /*!< Port x Lock bit 10 */ +#define GPIO_LCKR_LCK11 ((uint32_t)0x00000800) /*!< Port x Lock bit 11 */ +#define GPIO_LCKR_LCK12 ((uint32_t)0x00001000) /*!< Port x Lock bit 12 */ +#define GPIO_LCKR_LCK13 ((uint32_t)0x00002000) /*!< Port x Lock bit 13 */ +#define GPIO_LCKR_LCK14 ((uint32_t)0x00004000) /*!< Port x Lock bit 14 */ +#define GPIO_LCKR_LCK15 ((uint32_t)0x00008000) /*!< Port x Lock bit 15 */ +#define GPIO_LCKR_LCKK ((uint32_t)0x00010000) /*!< Lock key */ + +/*----------------------------------------------------------------------------*/ + +/****************** Bit definition for AFIO_EVCR register *******************/ +#define AFIO_EVCR_PIN ((uint8_t)0x0F) /*!< PIN[3:0] bits (Pin selection) */ +#define AFIO_EVCR_PIN_0 ((uint8_t)0x01) /*!< Bit 0 */ +#define AFIO_EVCR_PIN_1 ((uint8_t)0x02) /*!< Bit 1 */ +#define AFIO_EVCR_PIN_2 ((uint8_t)0x04) /*!< Bit 2 */ +#define AFIO_EVCR_PIN_3 ((uint8_t)0x08) /*!< Bit 3 */ + +/*!< PIN configuration */ +#define AFIO_EVCR_PIN_PX0 ((uint8_t)0x00) /*!< Pin 0 selected */ +#define AFIO_EVCR_PIN_PX1 ((uint8_t)0x01) /*!< Pin 1 selected */ +#define AFIO_EVCR_PIN_PX2 ((uint8_t)0x02) /*!< Pin 2 selected */ +#define AFIO_EVCR_PIN_PX3 ((uint8_t)0x03) /*!< Pin 3 selected */ +#define AFIO_EVCR_PIN_PX4 ((uint8_t)0x04) /*!< Pin 4 selected */ +#define AFIO_EVCR_PIN_PX5 ((uint8_t)0x05) /*!< Pin 5 selected */ +#define AFIO_EVCR_PIN_PX6 ((uint8_t)0x06) /*!< Pin 6 selected */ +#define AFIO_EVCR_PIN_PX7 ((uint8_t)0x07) /*!< Pin 7 selected */ +#define AFIO_EVCR_PIN_PX8 ((uint8_t)0x08) /*!< Pin 8 selected */ +#define AFIO_EVCR_PIN_PX9 ((uint8_t)0x09) /*!< Pin 9 selected */ +#define AFIO_EVCR_PIN_PX10 ((uint8_t)0x0A) /*!< Pin 10 selected */ +#define AFIO_EVCR_PIN_PX11 ((uint8_t)0x0B) /*!< Pin 11 selected */ +#define AFIO_EVCR_PIN_PX12 ((uint8_t)0x0C) /*!< Pin 12 selected */ +#define AFIO_EVCR_PIN_PX13 ((uint8_t)0x0D) /*!< Pin 13 selected */ +#define AFIO_EVCR_PIN_PX14 ((uint8_t)0x0E) /*!< Pin 14 selected */ +#define AFIO_EVCR_PIN_PX15 ((uint8_t)0x0F) /*!< Pin 15 selected */ + +#define AFIO_EVCR_PORT ((uint8_t)0x70) /*!< PORT[2:0] bits (Port selection) */ +#define AFIO_EVCR_PORT_0 ((uint8_t)0x10) /*!< Bit 0 */ +#define AFIO_EVCR_PORT_1 ((uint8_t)0x20) /*!< Bit 1 */ +#define AFIO_EVCR_PORT_2 ((uint8_t)0x40) /*!< Bit 2 */ + +/*!< PORT configuration */ +#define AFIO_EVCR_PORT_PA ((uint8_t)0x00) /*!< Port A selected */ +#define AFIO_EVCR_PORT_PB ((uint8_t)0x10) /*!< Port B selected */ +#define AFIO_EVCR_PORT_PC ((uint8_t)0x20) /*!< Port C selected */ +#define AFIO_EVCR_PORT_PD ((uint8_t)0x30) /*!< Port D selected */ +#define AFIO_EVCR_PORT_PE ((uint8_t)0x40) /*!< Port E selected */ + +#define AFIO_EVCR_EVOE ((uint8_t)0x80) /*!< Event Output Enable */ + +/****************** Bit definition for AFIO_MAPR register *******************/ +#define AFIO_MAPR_SPI1_REMAP ((uint32_t)0x00000001) /*!< SPI1 remapping */ +#define AFIO_MAPR_I2C1_REMAP ((uint32_t)0x00000002) /*!< I2C1 remapping */ +#define AFIO_MAPR_USART1_REMAP ((uint32_t)0x00000004) /*!< USART1 remapping */ +#define AFIO_MAPR_USART2_REMAP ((uint32_t)0x00000008) /*!< USART2 remapping */ + +#define AFIO_MAPR_USART3_REMAP ((uint32_t)0x00000030) /*!< USART3_REMAP[1:0] bits (USART3 remapping) */ +#define AFIO_MAPR_USART3_REMAP_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define AFIO_MAPR_USART3_REMAP_1 ((uint32_t)0x00000020) /*!< Bit 1 */ + +/* USART3_REMAP configuration */ +#define AFIO_MAPR_USART3_REMAP_NOREMAP ((uint32_t)0x00000000) /*!< No remap (TX/PB10, RX/PB11, CK/PB12, CTS/PB13, RTS/PB14) */ +#define AFIO_MAPR_USART3_REMAP_PARTIALREMAP ((uint32_t)0x00000010) /*!< Partial remap (TX/PC10, RX/PC11, CK/PC12, CTS/PB13, RTS/PB14) */ +#define AFIO_MAPR_USART3_REMAP_FULLREMAP ((uint32_t)0x00000030) /*!< Full remap (TX/PD8, RX/PD9, CK/PD10, CTS/PD11, RTS/PD12) */ + +#define AFIO_MAPR_TIM1_REMAP ((uint32_t)0x000000C0) /*!< TIM1_REMAP[1:0] bits (TIM1 remapping) */ +#define AFIO_MAPR_TIM1_REMAP_0 ((uint32_t)0x00000040) /*!< Bit 0 */ +#define AFIO_MAPR_TIM1_REMAP_1 ((uint32_t)0x00000080) /*!< Bit 1 */ + +/*!< TIM1_REMAP configuration */ +#define AFIO_MAPR_TIM1_REMAP_NOREMAP ((uint32_t)0x00000000) /*!< No remap (ETR/PA12, CH1/PA8, CH2/PA9, CH3/PA10, CH4/PA11, BKIN/PB12, CH1N/PB13, CH2N/PB14, CH3N/PB15) */ +#define AFIO_MAPR_TIM1_REMAP_PARTIALREMAP ((uint32_t)0x00000040) /*!< Partial remap (ETR/PA12, CH1/PA8, CH2/PA9, CH3/PA10, CH4/PA11, BKIN/PA6, CH1N/PA7, CH2N/PB0, CH3N/PB1) */ +#define AFIO_MAPR_TIM1_REMAP_FULLREMAP ((uint32_t)0x000000C0) /*!< Full remap (ETR/PE7, CH1/PE9, CH2/PE11, CH3/PE13, CH4/PE14, BKIN/PE15, CH1N/PE8, CH2N/PE10, CH3N/PE12) */ + +#define AFIO_MAPR_TIM2_REMAP ((uint32_t)0x00000300) /*!< TIM2_REMAP[1:0] bits (TIM2 remapping) */ +#define AFIO_MAPR_TIM2_REMAP_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define AFIO_MAPR_TIM2_REMAP_1 ((uint32_t)0x00000200) /*!< Bit 1 */ + +/*!< TIM2_REMAP configuration */ +#define AFIO_MAPR_TIM2_REMAP_NOREMAP ((uint32_t)0x00000000) /*!< No remap (CH1/ETR/PA0, CH2/PA1, CH3/PA2, CH4/PA3) */ +#define AFIO_MAPR_TIM2_REMAP_PARTIALREMAP1 ((uint32_t)0x00000100) /*!< Partial remap (CH1/ETR/PA15, CH2/PB3, CH3/PA2, CH4/PA3) */ +#define AFIO_MAPR_TIM2_REMAP_PARTIALREMAP2 ((uint32_t)0x00000200) /*!< Partial remap (CH1/ETR/PA0, CH2/PA1, CH3/PB10, CH4/PB11) */ +#define AFIO_MAPR_TIM2_REMAP_FULLREMAP ((uint32_t)0x00000300) /*!< Full remap (CH1/ETR/PA15, CH2/PB3, CH3/PB10, CH4/PB11) */ + +#define AFIO_MAPR_TIM3_REMAP ((uint32_t)0x00000C00) /*!< TIM3_REMAP[1:0] bits (TIM3 remapping) */ +#define AFIO_MAPR_TIM3_REMAP_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define AFIO_MAPR_TIM3_REMAP_1 ((uint32_t)0x00000800) /*!< Bit 1 */ + +/*!< TIM3_REMAP configuration */ +#define AFIO_MAPR_TIM3_REMAP_NOREMAP ((uint32_t)0x00000000) /*!< No remap (CH1/PA6, CH2/PA7, CH3/PB0, CH4/PB1) */ +#define AFIO_MAPR_TIM3_REMAP_PARTIALREMAP ((uint32_t)0x00000800) /*!< Partial remap (CH1/PB4, CH2/PB5, CH3/PB0, CH4/PB1) */ +#define AFIO_MAPR_TIM3_REMAP_FULLREMAP ((uint32_t)0x00000C00) /*!< Full remap (CH1/PC6, CH2/PC7, CH3/PC8, CH4/PC9) */ + +#define AFIO_MAPR_TIM4_REMAP ((uint32_t)0x00001000) /*!< TIM4_REMAP bit (TIM4 remapping) */ + +#define AFIO_MAPR_CAN_REMAP ((uint32_t)0x00006000) /*!< CAN_REMAP[1:0] bits (CAN Alternate function remapping) */ +#define AFIO_MAPR_CAN_REMAP_0 ((uint32_t)0x00002000) /*!< Bit 0 */ +#define AFIO_MAPR_CAN_REMAP_1 ((uint32_t)0x00004000) /*!< Bit 1 */ + +/*!< CAN_REMAP configuration */ +#define AFIO_MAPR_CAN_REMAP_REMAP1 ((uint32_t)0x00000000) /*!< CANRX mapped to PA11, CANTX mapped to PA12 */ +#define AFIO_MAPR_CAN_REMAP_REMAP2 ((uint32_t)0x00004000) /*!< CANRX mapped to PB8, CANTX mapped to PB9 */ +#define AFIO_MAPR_CAN_REMAP_REMAP3 ((uint32_t)0x00006000) /*!< CANRX mapped to PD0, CANTX mapped to PD1 */ + +#define AFIO_MAPR_PD01_REMAP ((uint32_t)0x00008000) /*!< Port D0/Port D1 mapping on OSC_IN/OSC_OUT */ +#define AFIO_MAPR_TIM5CH4_IREMAP ((uint32_t)0x00010000) /*!< TIM5 Channel4 Internal Remap */ +#define AFIO_MAPR_ADC1_ETRGINJ_REMAP ((uint32_t)0x00020000) /*!< ADC 1 External Trigger Injected Conversion remapping */ +#define AFIO_MAPR_ADC1_ETRGREG_REMAP ((uint32_t)0x00040000) /*!< ADC 1 External Trigger Regular Conversion remapping */ +#define AFIO_MAPR_ADC2_ETRGINJ_REMAP ((uint32_t)0x00080000) /*!< ADC 2 External Trigger Injected Conversion remapping */ +#define AFIO_MAPR_ADC2_ETRGREG_REMAP ((uint32_t)0x00100000) /*!< ADC 2 External Trigger Regular Conversion remapping */ + +/*!< SWJ_CFG configuration */ +#define AFIO_MAPR_SWJ_CFG ((uint32_t)0x07000000) /*!< SWJ_CFG[2:0] bits (Serial Wire JTAG configuration) */ +#define AFIO_MAPR_SWJ_CFG_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define AFIO_MAPR_SWJ_CFG_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define AFIO_MAPR_SWJ_CFG_2 ((uint32_t)0x04000000) /*!< Bit 2 */ + +#define AFIO_MAPR_SWJ_CFG_RESET ((uint32_t)0x00000000) /*!< Full SWJ (JTAG-DP + SW-DP) : Reset State */ +#define AFIO_MAPR_SWJ_CFG_NOJNTRST ((uint32_t)0x01000000) /*!< Full SWJ (JTAG-DP + SW-DP) but without JNTRST */ +#define AFIO_MAPR_SWJ_CFG_JTAGDISABLE ((uint32_t)0x02000000) /*!< JTAG-DP Disabled and SW-DP Enabled */ +#define AFIO_MAPR_SWJ_CFG_DISABLE ((uint32_t)0x04000000) /*!< JTAG-DP Disabled and SW-DP Disabled */ + +#ifdef STM32F10X_CL +/*!< ETH_REMAP configuration */ + #define AFIO_MAPR_ETH_REMAP ((uint32_t)0x00200000) /*!< SPI3_REMAP bit (Ethernet MAC I/O remapping) */ + +/*!< CAN2_REMAP configuration */ + #define AFIO_MAPR_CAN2_REMAP ((uint32_t)0x00400000) /*!< CAN2_REMAP bit (CAN2 I/O remapping) */ + +/*!< MII_RMII_SEL configuration */ + #define AFIO_MAPR_MII_RMII_SEL ((uint32_t)0x00800000) /*!< MII_RMII_SEL bit (Ethernet MII or RMII selection) */ + +/*!< SPI3_REMAP configuration */ + #define AFIO_MAPR_SPI3_REMAP ((uint32_t)0x10000000) /*!< SPI3_REMAP bit (SPI3 remapping) */ + +/*!< TIM2ITR1_IREMAP configuration */ + #define AFIO_MAPR_TIM2ITR1_IREMAP ((uint32_t)0x20000000) /*!< TIM2ITR1_IREMAP bit (TIM2 internal trigger 1 remapping) */ + +/*!< PTP_PPS_REMAP configuration */ + #define AFIO_MAPR_PTP_PPS_REMAP ((uint32_t)0x40000000) /*!< PTP_PPS_REMAP bit (Ethernet PTP PPS remapping) */ +#endif + +/***************** Bit definition for AFIO_EXTICR1 register *****************/ +#define AFIO_EXTICR1_EXTI0 ((uint16_t)0x000F) /*!< EXTI 0 configuration */ +#define AFIO_EXTICR1_EXTI1 ((uint16_t)0x00F0) /*!< EXTI 1 configuration */ +#define AFIO_EXTICR1_EXTI2 ((uint16_t)0x0F00) /*!< EXTI 2 configuration */ +#define AFIO_EXTICR1_EXTI3 ((uint16_t)0xF000) /*!< EXTI 3 configuration */ + +/*!< EXTI0 configuration */ +#define AFIO_EXTICR1_EXTI0_PA ((uint16_t)0x0000) /*!< PA[0] pin */ +#define AFIO_EXTICR1_EXTI0_PB ((uint16_t)0x0001) /*!< PB[0] pin */ +#define AFIO_EXTICR1_EXTI0_PC ((uint16_t)0x0002) /*!< PC[0] pin */ +#define AFIO_EXTICR1_EXTI0_PD ((uint16_t)0x0003) /*!< PD[0] pin */ +#define AFIO_EXTICR1_EXTI0_PE ((uint16_t)0x0004) /*!< PE[0] pin */ +#define AFIO_EXTICR1_EXTI0_PF ((uint16_t)0x0005) /*!< PF[0] pin */ +#define AFIO_EXTICR1_EXTI0_PG ((uint16_t)0x0006) /*!< PG[0] pin */ + +/*!< EXTI1 configuration */ +#define AFIO_EXTICR1_EXTI1_PA ((uint16_t)0x0000) /*!< PA[1] pin */ +#define AFIO_EXTICR1_EXTI1_PB ((uint16_t)0x0010) /*!< PB[1] pin */ +#define AFIO_EXTICR1_EXTI1_PC ((uint16_t)0x0020) /*!< PC[1] pin */ +#define AFIO_EXTICR1_EXTI1_PD ((uint16_t)0x0030) /*!< PD[1] pin */ +#define AFIO_EXTICR1_EXTI1_PE ((uint16_t)0x0040) /*!< PE[1] pin */ +#define AFIO_EXTICR1_EXTI1_PF ((uint16_t)0x0050) /*!< PF[1] pin */ +#define AFIO_EXTICR1_EXTI1_PG ((uint16_t)0x0060) /*!< PG[1] pin */ + +/*!< EXTI2 configuration */ +#define AFIO_EXTICR1_EXTI2_PA ((uint16_t)0x0000) /*!< PA[2] pin */ +#define AFIO_EXTICR1_EXTI2_PB ((uint16_t)0x0100) /*!< PB[2] pin */ +#define AFIO_EXTICR1_EXTI2_PC ((uint16_t)0x0200) /*!< PC[2] pin */ +#define AFIO_EXTICR1_EXTI2_PD ((uint16_t)0x0300) /*!< PD[2] pin */ +#define AFIO_EXTICR1_EXTI2_PE ((uint16_t)0x0400) /*!< PE[2] pin */ +#define AFIO_EXTICR1_EXTI2_PF ((uint16_t)0x0500) /*!< PF[2] pin */ +#define AFIO_EXTICR1_EXTI2_PG ((uint16_t)0x0600) /*!< PG[2] pin */ + +/*!< EXTI3 configuration */ +#define AFIO_EXTICR1_EXTI3_PA ((uint16_t)0x0000) /*!< PA[3] pin */ +#define AFIO_EXTICR1_EXTI3_PB ((uint16_t)0x1000) /*!< PB[3] pin */ +#define AFIO_EXTICR1_EXTI3_PC ((uint16_t)0x2000) /*!< PC[3] pin */ +#define AFIO_EXTICR1_EXTI3_PD ((uint16_t)0x3000) /*!< PD[3] pin */ +#define AFIO_EXTICR1_EXTI3_PE ((uint16_t)0x4000) /*!< PE[3] pin */ +#define AFIO_EXTICR1_EXTI3_PF ((uint16_t)0x5000) /*!< PF[3] pin */ +#define AFIO_EXTICR1_EXTI3_PG ((uint16_t)0x6000) /*!< PG[3] pin */ + +/***************** Bit definition for AFIO_EXTICR2 register *****************/ +#define AFIO_EXTICR2_EXTI4 ((uint16_t)0x000F) /*!< EXTI 4 configuration */ +#define AFIO_EXTICR2_EXTI5 ((uint16_t)0x00F0) /*!< EXTI 5 configuration */ +#define AFIO_EXTICR2_EXTI6 ((uint16_t)0x0F00) /*!< EXTI 6 configuration */ +#define AFIO_EXTICR2_EXTI7 ((uint16_t)0xF000) /*!< EXTI 7 configuration */ + +/*!< EXTI4 configuration */ +#define AFIO_EXTICR2_EXTI4_PA ((uint16_t)0x0000) /*!< PA[4] pin */ +#define AFIO_EXTICR2_EXTI4_PB ((uint16_t)0x0001) /*!< PB[4] pin */ +#define AFIO_EXTICR2_EXTI4_PC ((uint16_t)0x0002) /*!< PC[4] pin */ +#define AFIO_EXTICR2_EXTI4_PD ((uint16_t)0x0003) /*!< PD[4] pin */ +#define AFIO_EXTICR2_EXTI4_PE ((uint16_t)0x0004) /*!< PE[4] pin */ +#define AFIO_EXTICR2_EXTI4_PF ((uint16_t)0x0005) /*!< PF[4] pin */ +#define AFIO_EXTICR2_EXTI4_PG ((uint16_t)0x0006) /*!< PG[4] pin */ + +/* EXTI5 configuration */ +#define AFIO_EXTICR2_EXTI5_PA ((uint16_t)0x0000) /*!< PA[5] pin */ +#define AFIO_EXTICR2_EXTI5_PB ((uint16_t)0x0010) /*!< PB[5] pin */ +#define AFIO_EXTICR2_EXTI5_PC ((uint16_t)0x0020) /*!< PC[5] pin */ +#define AFIO_EXTICR2_EXTI5_PD ((uint16_t)0x0030) /*!< PD[5] pin */ +#define AFIO_EXTICR2_EXTI5_PE ((uint16_t)0x0040) /*!< PE[5] pin */ +#define AFIO_EXTICR2_EXTI5_PF ((uint16_t)0x0050) /*!< PF[5] pin */ +#define AFIO_EXTICR2_EXTI5_PG ((uint16_t)0x0060) /*!< PG[5] pin */ + +/*!< EXTI6 configuration */ +#define AFIO_EXTICR2_EXTI6_PA ((uint16_t)0x0000) /*!< PA[6] pin */ +#define AFIO_EXTICR2_EXTI6_PB ((uint16_t)0x0100) /*!< PB[6] pin */ +#define AFIO_EXTICR2_EXTI6_PC ((uint16_t)0x0200) /*!< PC[6] pin */ +#define AFIO_EXTICR2_EXTI6_PD ((uint16_t)0x0300) /*!< PD[6] pin */ +#define AFIO_EXTICR2_EXTI6_PE ((uint16_t)0x0400) /*!< PE[6] pin */ +#define AFIO_EXTICR2_EXTI6_PF ((uint16_t)0x0500) /*!< PF[6] pin */ +#define AFIO_EXTICR2_EXTI6_PG ((uint16_t)0x0600) /*!< PG[6] pin */ + +/*!< EXTI7 configuration */ +#define AFIO_EXTICR2_EXTI7_PA ((uint16_t)0x0000) /*!< PA[7] pin */ +#define AFIO_EXTICR2_EXTI7_PB ((uint16_t)0x1000) /*!< PB[7] pin */ +#define AFIO_EXTICR2_EXTI7_PC ((uint16_t)0x2000) /*!< PC[7] pin */ +#define AFIO_EXTICR2_EXTI7_PD ((uint16_t)0x3000) /*!< PD[7] pin */ +#define AFIO_EXTICR2_EXTI7_PE ((uint16_t)0x4000) /*!< PE[7] pin */ +#define AFIO_EXTICR2_EXTI7_PF ((uint16_t)0x5000) /*!< PF[7] pin */ +#define AFIO_EXTICR2_EXTI7_PG ((uint16_t)0x6000) /*!< PG[7] pin */ + +/***************** Bit definition for AFIO_EXTICR3 register *****************/ +#define AFIO_EXTICR3_EXTI8 ((uint16_t)0x000F) /*!< EXTI 8 configuration */ +#define AFIO_EXTICR3_EXTI9 ((uint16_t)0x00F0) /*!< EXTI 9 configuration */ +#define AFIO_EXTICR3_EXTI10 ((uint16_t)0x0F00) /*!< EXTI 10 configuration */ +#define AFIO_EXTICR3_EXTI11 ((uint16_t)0xF000) /*!< EXTI 11 configuration */ + +/*!< EXTI8 configuration */ +#define AFIO_EXTICR3_EXTI8_PA ((uint16_t)0x0000) /*!< PA[8] pin */ +#define AFIO_EXTICR3_EXTI8_PB ((uint16_t)0x0001) /*!< PB[8] pin */ +#define AFIO_EXTICR3_EXTI8_PC ((uint16_t)0x0002) /*!< PC[8] pin */ +#define AFIO_EXTICR3_EXTI8_PD ((uint16_t)0x0003) /*!< PD[8] pin */ +#define AFIO_EXTICR3_EXTI8_PE ((uint16_t)0x0004) /*!< PE[8] pin */ +#define AFIO_EXTICR3_EXTI8_PF ((uint16_t)0x0005) /*!< PF[8] pin */ +#define AFIO_EXTICR3_EXTI8_PG ((uint16_t)0x0006) /*!< PG[8] pin */ + +/*!< EXTI9 configuration */ +#define AFIO_EXTICR3_EXTI9_PA ((uint16_t)0x0000) /*!< PA[9] pin */ +#define AFIO_EXTICR3_EXTI9_PB ((uint16_t)0x0010) /*!< PB[9] pin */ +#define AFIO_EXTICR3_EXTI9_PC ((uint16_t)0x0020) /*!< PC[9] pin */ +#define AFIO_EXTICR3_EXTI9_PD ((uint16_t)0x0030) /*!< PD[9] pin */ +#define AFIO_EXTICR3_EXTI9_PE ((uint16_t)0x0040) /*!< PE[9] pin */ +#define AFIO_EXTICR3_EXTI9_PF ((uint16_t)0x0050) /*!< PF[9] pin */ +#define AFIO_EXTICR3_EXTI9_PG ((uint16_t)0x0060) /*!< PG[9] pin */ + +/*!< EXTI10 configuration */ +#define AFIO_EXTICR3_EXTI10_PA ((uint16_t)0x0000) /*!< PA[10] pin */ +#define AFIO_EXTICR3_EXTI10_PB ((uint16_t)0x0100) /*!< PB[10] pin */ +#define AFIO_EXTICR3_EXTI10_PC ((uint16_t)0x0200) /*!< PC[10] pin */ +#define AFIO_EXTICR3_EXTI10_PD ((uint16_t)0x0300) /*!< PD[10] pin */ +#define AFIO_EXTICR3_EXTI10_PE ((uint16_t)0x0400) /*!< PE[10] pin */ +#define AFIO_EXTICR3_EXTI10_PF ((uint16_t)0x0500) /*!< PF[10] pin */ +#define AFIO_EXTICR3_EXTI10_PG ((uint16_t)0x0600) /*!< PG[10] pin */ + +/*!< EXTI11 configuration */ +#define AFIO_EXTICR3_EXTI11_PA ((uint16_t)0x0000) /*!< PA[11] pin */ +#define AFIO_EXTICR3_EXTI11_PB ((uint16_t)0x1000) /*!< PB[11] pin */ +#define AFIO_EXTICR3_EXTI11_PC ((uint16_t)0x2000) /*!< PC[11] pin */ +#define AFIO_EXTICR3_EXTI11_PD ((uint16_t)0x3000) /*!< PD[11] pin */ +#define AFIO_EXTICR3_EXTI11_PE ((uint16_t)0x4000) /*!< PE[11] pin */ +#define AFIO_EXTICR3_EXTI11_PF ((uint16_t)0x5000) /*!< PF[11] pin */ +#define AFIO_EXTICR3_EXTI11_PG ((uint16_t)0x6000) /*!< PG[11] pin */ + +/***************** Bit definition for AFIO_EXTICR4 register *****************/ +#define AFIO_EXTICR4_EXTI12 ((uint16_t)0x000F) /*!< EXTI 12 configuration */ +#define AFIO_EXTICR4_EXTI13 ((uint16_t)0x00F0) /*!< EXTI 13 configuration */ +#define AFIO_EXTICR4_EXTI14 ((uint16_t)0x0F00) /*!< EXTI 14 configuration */ +#define AFIO_EXTICR4_EXTI15 ((uint16_t)0xF000) /*!< EXTI 15 configuration */ + +/* EXTI12 configuration */ +#define AFIO_EXTICR4_EXTI12_PA ((uint16_t)0x0000) /*!< PA[12] pin */ +#define AFIO_EXTICR4_EXTI12_PB ((uint16_t)0x0001) /*!< PB[12] pin */ +#define AFIO_EXTICR4_EXTI12_PC ((uint16_t)0x0002) /*!< PC[12] pin */ +#define AFIO_EXTICR4_EXTI12_PD ((uint16_t)0x0003) /*!< PD[12] pin */ +#define AFIO_EXTICR4_EXTI12_PE ((uint16_t)0x0004) /*!< PE[12] pin */ +#define AFIO_EXTICR4_EXTI12_PF ((uint16_t)0x0005) /*!< PF[12] pin */ +#define AFIO_EXTICR4_EXTI12_PG ((uint16_t)0x0006) /*!< PG[12] pin */ + +/* EXTI13 configuration */ +#define AFIO_EXTICR4_EXTI13_PA ((uint16_t)0x0000) /*!< PA[13] pin */ +#define AFIO_EXTICR4_EXTI13_PB ((uint16_t)0x0010) /*!< PB[13] pin */ +#define AFIO_EXTICR4_EXTI13_PC ((uint16_t)0x0020) /*!< PC[13] pin */ +#define AFIO_EXTICR4_EXTI13_PD ((uint16_t)0x0030) /*!< PD[13] pin */ +#define AFIO_EXTICR4_EXTI13_PE ((uint16_t)0x0040) /*!< PE[13] pin */ +#define AFIO_EXTICR4_EXTI13_PF ((uint16_t)0x0050) /*!< PF[13] pin */ +#define AFIO_EXTICR4_EXTI13_PG ((uint16_t)0x0060) /*!< PG[13] pin */ + +/*!< EXTI14 configuration */ +#define AFIO_EXTICR4_EXTI14_PA ((uint16_t)0x0000) /*!< PA[14] pin */ +#define AFIO_EXTICR4_EXTI14_PB ((uint16_t)0x0100) /*!< PB[14] pin */ +#define AFIO_EXTICR4_EXTI14_PC ((uint16_t)0x0200) /*!< PC[14] pin */ +#define AFIO_EXTICR4_EXTI14_PD ((uint16_t)0x0300) /*!< PD[14] pin */ +#define AFIO_EXTICR4_EXTI14_PE ((uint16_t)0x0400) /*!< PE[14] pin */ +#define AFIO_EXTICR4_EXTI14_PF ((uint16_t)0x0500) /*!< PF[14] pin */ +#define AFIO_EXTICR4_EXTI14_PG ((uint16_t)0x0600) /*!< PG[14] pin */ + +/*!< EXTI15 configuration */ +#define AFIO_EXTICR4_EXTI15_PA ((uint16_t)0x0000) /*!< PA[15] pin */ +#define AFIO_EXTICR4_EXTI15_PB ((uint16_t)0x1000) /*!< PB[15] pin */ +#define AFIO_EXTICR4_EXTI15_PC ((uint16_t)0x2000) /*!< PC[15] pin */ +#define AFIO_EXTICR4_EXTI15_PD ((uint16_t)0x3000) /*!< PD[15] pin */ +#define AFIO_EXTICR4_EXTI15_PE ((uint16_t)0x4000) /*!< PE[15] pin */ +#define AFIO_EXTICR4_EXTI15_PF ((uint16_t)0x5000) /*!< PF[15] pin */ +#define AFIO_EXTICR4_EXTI15_PG ((uint16_t)0x6000) /*!< PG[15] pin */ + +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) +/****************** Bit definition for AFIO_MAPR2 register ******************/ +#define AFIO_MAPR2_TIM15_REMAP ((uint32_t)0x00000001) /*!< TIM15 remapping */ +#define AFIO_MAPR2_TIM16_REMAP ((uint32_t)0x00000002) /*!< TIM16 remapping */ +#define AFIO_MAPR2_TIM17_REMAP ((uint32_t)0x00000004) /*!< TIM17 remapping */ +#define AFIO_MAPR2_CEC_REMAP ((uint32_t)0x00000008) /*!< CEC remapping */ +#define AFIO_MAPR2_TIM1_DMA_REMAP ((uint32_t)0x00000010) /*!< TIM1_DMA remapping */ +#endif + +#ifdef STM32F10X_HD_VL +#define AFIO_MAPR2_TIM13_REMAP ((uint32_t)0x00000100) /*!< TIM13 remapping */ +#define AFIO_MAPR2_TIM14_REMAP ((uint32_t)0x00000200) /*!< TIM14 remapping */ +#define AFIO_MAPR2_FSMC_NADV_REMAP ((uint32_t)0x00000400) /*!< FSMC NADV remapping */ +#define AFIO_MAPR2_TIM67_DAC_DMA_REMAP ((uint32_t)0x00000800) /*!< TIM6/TIM7 and DAC DMA remapping */ +#define AFIO_MAPR2_TIM12_REMAP ((uint32_t)0x00001000) /*!< TIM12 remapping */ +#define AFIO_MAPR2_MISC_REMAP ((uint32_t)0x00002000) /*!< Miscellaneous remapping */ +#endif + +#ifdef STM32F10X_XL +/****************** Bit definition for AFIO_MAPR2 register ******************/ +#define AFIO_MAPR2_TIM9_REMAP ((uint32_t)0x00000020) /*!< TIM9 remapping */ +#define AFIO_MAPR2_TIM10_REMAP ((uint32_t)0x00000040) /*!< TIM10 remapping */ +#define AFIO_MAPR2_TIM11_REMAP ((uint32_t)0x00000080) /*!< TIM11 remapping */ +#define AFIO_MAPR2_TIM13_REMAP ((uint32_t)0x00000100) /*!< TIM13 remapping */ +#define AFIO_MAPR2_TIM14_REMAP ((uint32_t)0x00000200) /*!< TIM14 remapping */ +#define AFIO_MAPR2_FSMC_NADV_REMAP ((uint32_t)0x00000400) /*!< FSMC NADV remapping */ +#endif + +/******************************************************************************/ +/* */ +/* SystemTick */ +/* */ +/******************************************************************************/ + +/***************** Bit definition for SysTick_CTRL register *****************/ +#define SysTick_CTRL_ENABLE ((uint32_t)0x00000001) /*!< Counter enable */ +#define SysTick_CTRL_TICKINT ((uint32_t)0x00000002) /*!< Counting down to 0 pends the SysTick handler */ +#define SysTick_CTRL_CLKSOURCE ((uint32_t)0x00000004) /*!< Clock source */ +#define SysTick_CTRL_COUNTFLAG ((uint32_t)0x00010000) /*!< Count Flag */ + +/***************** Bit definition for SysTick_LOAD register *****************/ +#define SysTick_LOAD_RELOAD ((uint32_t)0x00FFFFFF) /*!< Value to load into the SysTick Current Value Register when the counter reaches 0 */ + +/***************** Bit definition for SysTick_VAL register ******************/ +#define SysTick_VAL_CURRENT ((uint32_t)0x00FFFFFF) /*!< Current value at the time the register is accessed */ + +/***************** Bit definition for SysTick_CALIB register ****************/ +#define SysTick_CALIB_TENMS ((uint32_t)0x00FFFFFF) /*!< Reload value to use for 10ms timing */ +#define SysTick_CALIB_SKEW ((uint32_t)0x40000000) /*!< Calibration value is not exactly 10 ms */ +#define SysTick_CALIB_NOREF ((uint32_t)0x80000000) /*!< The reference clock is not provided */ + +/******************************************************************************/ +/* */ +/* Nested Vectored Interrupt Controller */ +/* */ +/******************************************************************************/ + +/****************** Bit definition for NVIC_ISER register *******************/ +#define NVIC_ISER_SETENA ((uint32_t)0xFFFFFFFF) /*!< Interrupt set enable bits */ +#define NVIC_ISER_SETENA_0 ((uint32_t)0x00000001) /*!< bit 0 */ +#define NVIC_ISER_SETENA_1 ((uint32_t)0x00000002) /*!< bit 1 */ +#define NVIC_ISER_SETENA_2 ((uint32_t)0x00000004) /*!< bit 2 */ +#define NVIC_ISER_SETENA_3 ((uint32_t)0x00000008) /*!< bit 3 */ +#define NVIC_ISER_SETENA_4 ((uint32_t)0x00000010) /*!< bit 4 */ +#define NVIC_ISER_SETENA_5 ((uint32_t)0x00000020) /*!< bit 5 */ +#define NVIC_ISER_SETENA_6 ((uint32_t)0x00000040) /*!< bit 6 */ +#define NVIC_ISER_SETENA_7 ((uint32_t)0x00000080) /*!< bit 7 */ +#define NVIC_ISER_SETENA_8 ((uint32_t)0x00000100) /*!< bit 8 */ +#define NVIC_ISER_SETENA_9 ((uint32_t)0x00000200) /*!< bit 9 */ +#define NVIC_ISER_SETENA_10 ((uint32_t)0x00000400) /*!< bit 10 */ +#define NVIC_ISER_SETENA_11 ((uint32_t)0x00000800) /*!< bit 11 */ +#define NVIC_ISER_SETENA_12 ((uint32_t)0x00001000) /*!< bit 12 */ +#define NVIC_ISER_SETENA_13 ((uint32_t)0x00002000) /*!< bit 13 */ +#define NVIC_ISER_SETENA_14 ((uint32_t)0x00004000) /*!< bit 14 */ +#define NVIC_ISER_SETENA_15 ((uint32_t)0x00008000) /*!< bit 15 */ +#define NVIC_ISER_SETENA_16 ((uint32_t)0x00010000) /*!< bit 16 */ +#define NVIC_ISER_SETENA_17 ((uint32_t)0x00020000) /*!< bit 17 */ +#define NVIC_ISER_SETENA_18 ((uint32_t)0x00040000) /*!< bit 18 */ +#define NVIC_ISER_SETENA_19 ((uint32_t)0x00080000) /*!< bit 19 */ +#define NVIC_ISER_SETENA_20 ((uint32_t)0x00100000) /*!< bit 20 */ +#define NVIC_ISER_SETENA_21 ((uint32_t)0x00200000) /*!< bit 21 */ +#define NVIC_ISER_SETENA_22 ((uint32_t)0x00400000) /*!< bit 22 */ +#define NVIC_ISER_SETENA_23 ((uint32_t)0x00800000) /*!< bit 23 */ +#define NVIC_ISER_SETENA_24 ((uint32_t)0x01000000) /*!< bit 24 */ +#define NVIC_ISER_SETENA_25 ((uint32_t)0x02000000) /*!< bit 25 */ +#define NVIC_ISER_SETENA_26 ((uint32_t)0x04000000) /*!< bit 26 */ +#define NVIC_ISER_SETENA_27 ((uint32_t)0x08000000) /*!< bit 27 */ +#define NVIC_ISER_SETENA_28 ((uint32_t)0x10000000) /*!< bit 28 */ +#define NVIC_ISER_SETENA_29 ((uint32_t)0x20000000) /*!< bit 29 */ +#define NVIC_ISER_SETENA_30 ((uint32_t)0x40000000) /*!< bit 30 */ +#define NVIC_ISER_SETENA_31 ((uint32_t)0x80000000) /*!< bit 31 */ + +/****************** Bit definition for NVIC_ICER register *******************/ +#define NVIC_ICER_CLRENA ((uint32_t)0xFFFFFFFF) /*!< Interrupt clear-enable bits */ +#define NVIC_ICER_CLRENA_0 ((uint32_t)0x00000001) /*!< bit 0 */ +#define NVIC_ICER_CLRENA_1 ((uint32_t)0x00000002) /*!< bit 1 */ +#define NVIC_ICER_CLRENA_2 ((uint32_t)0x00000004) /*!< bit 2 */ +#define NVIC_ICER_CLRENA_3 ((uint32_t)0x00000008) /*!< bit 3 */ +#define NVIC_ICER_CLRENA_4 ((uint32_t)0x00000010) /*!< bit 4 */ +#define NVIC_ICER_CLRENA_5 ((uint32_t)0x00000020) /*!< bit 5 */ +#define NVIC_ICER_CLRENA_6 ((uint32_t)0x00000040) /*!< bit 6 */ +#define NVIC_ICER_CLRENA_7 ((uint32_t)0x00000080) /*!< bit 7 */ +#define NVIC_ICER_CLRENA_8 ((uint32_t)0x00000100) /*!< bit 8 */ +#define NVIC_ICER_CLRENA_9 ((uint32_t)0x00000200) /*!< bit 9 */ +#define NVIC_ICER_CLRENA_10 ((uint32_t)0x00000400) /*!< bit 10 */ +#define NVIC_ICER_CLRENA_11 ((uint32_t)0x00000800) /*!< bit 11 */ +#define NVIC_ICER_CLRENA_12 ((uint32_t)0x00001000) /*!< bit 12 */ +#define NVIC_ICER_CLRENA_13 ((uint32_t)0x00002000) /*!< bit 13 */ +#define NVIC_ICER_CLRENA_14 ((uint32_t)0x00004000) /*!< bit 14 */ +#define NVIC_ICER_CLRENA_15 ((uint32_t)0x00008000) /*!< bit 15 */ +#define NVIC_ICER_CLRENA_16 ((uint32_t)0x00010000) /*!< bit 16 */ +#define NVIC_ICER_CLRENA_17 ((uint32_t)0x00020000) /*!< bit 17 */ +#define NVIC_ICER_CLRENA_18 ((uint32_t)0x00040000) /*!< bit 18 */ +#define NVIC_ICER_CLRENA_19 ((uint32_t)0x00080000) /*!< bit 19 */ +#define NVIC_ICER_CLRENA_20 ((uint32_t)0x00100000) /*!< bit 20 */ +#define NVIC_ICER_CLRENA_21 ((uint32_t)0x00200000) /*!< bit 21 */ +#define NVIC_ICER_CLRENA_22 ((uint32_t)0x00400000) /*!< bit 22 */ +#define NVIC_ICER_CLRENA_23 ((uint32_t)0x00800000) /*!< bit 23 */ +#define NVIC_ICER_CLRENA_24 ((uint32_t)0x01000000) /*!< bit 24 */ +#define NVIC_ICER_CLRENA_25 ((uint32_t)0x02000000) /*!< bit 25 */ +#define NVIC_ICER_CLRENA_26 ((uint32_t)0x04000000) /*!< bit 26 */ +#define NVIC_ICER_CLRENA_27 ((uint32_t)0x08000000) /*!< bit 27 */ +#define NVIC_ICER_CLRENA_28 ((uint32_t)0x10000000) /*!< bit 28 */ +#define NVIC_ICER_CLRENA_29 ((uint32_t)0x20000000) /*!< bit 29 */ +#define NVIC_ICER_CLRENA_30 ((uint32_t)0x40000000) /*!< bit 30 */ +#define NVIC_ICER_CLRENA_31 ((uint32_t)0x80000000) /*!< bit 31 */ + +/****************** Bit definition for NVIC_ISPR register *******************/ +#define NVIC_ISPR_SETPEND ((uint32_t)0xFFFFFFFF) /*!< Interrupt set-pending bits */ +#define NVIC_ISPR_SETPEND_0 ((uint32_t)0x00000001) /*!< bit 0 */ +#define NVIC_ISPR_SETPEND_1 ((uint32_t)0x00000002) /*!< bit 1 */ +#define NVIC_ISPR_SETPEND_2 ((uint32_t)0x00000004) /*!< bit 2 */ +#define NVIC_ISPR_SETPEND_3 ((uint32_t)0x00000008) /*!< bit 3 */ +#define NVIC_ISPR_SETPEND_4 ((uint32_t)0x00000010) /*!< bit 4 */ +#define NVIC_ISPR_SETPEND_5 ((uint32_t)0x00000020) /*!< bit 5 */ +#define NVIC_ISPR_SETPEND_6 ((uint32_t)0x00000040) /*!< bit 6 */ +#define NVIC_ISPR_SETPEND_7 ((uint32_t)0x00000080) /*!< bit 7 */ +#define NVIC_ISPR_SETPEND_8 ((uint32_t)0x00000100) /*!< bit 8 */ +#define NVIC_ISPR_SETPEND_9 ((uint32_t)0x00000200) /*!< bit 9 */ +#define NVIC_ISPR_SETPEND_10 ((uint32_t)0x00000400) /*!< bit 10 */ +#define NVIC_ISPR_SETPEND_11 ((uint32_t)0x00000800) /*!< bit 11 */ +#define NVIC_ISPR_SETPEND_12 ((uint32_t)0x00001000) /*!< bit 12 */ +#define NVIC_ISPR_SETPEND_13 ((uint32_t)0x00002000) /*!< bit 13 */ +#define NVIC_ISPR_SETPEND_14 ((uint32_t)0x00004000) /*!< bit 14 */ +#define NVIC_ISPR_SETPEND_15 ((uint32_t)0x00008000) /*!< bit 15 */ +#define NVIC_ISPR_SETPEND_16 ((uint32_t)0x00010000) /*!< bit 16 */ +#define NVIC_ISPR_SETPEND_17 ((uint32_t)0x00020000) /*!< bit 17 */ +#define NVIC_ISPR_SETPEND_18 ((uint32_t)0x00040000) /*!< bit 18 */ +#define NVIC_ISPR_SETPEND_19 ((uint32_t)0x00080000) /*!< bit 19 */ +#define NVIC_ISPR_SETPEND_20 ((uint32_t)0x00100000) /*!< bit 20 */ +#define NVIC_ISPR_SETPEND_21 ((uint32_t)0x00200000) /*!< bit 21 */ +#define NVIC_ISPR_SETPEND_22 ((uint32_t)0x00400000) /*!< bit 22 */ +#define NVIC_ISPR_SETPEND_23 ((uint32_t)0x00800000) /*!< bit 23 */ +#define NVIC_ISPR_SETPEND_24 ((uint32_t)0x01000000) /*!< bit 24 */ +#define NVIC_ISPR_SETPEND_25 ((uint32_t)0x02000000) /*!< bit 25 */ +#define NVIC_ISPR_SETPEND_26 ((uint32_t)0x04000000) /*!< bit 26 */ +#define NVIC_ISPR_SETPEND_27 ((uint32_t)0x08000000) /*!< bit 27 */ +#define NVIC_ISPR_SETPEND_28 ((uint32_t)0x10000000) /*!< bit 28 */ +#define NVIC_ISPR_SETPEND_29 ((uint32_t)0x20000000) /*!< bit 29 */ +#define NVIC_ISPR_SETPEND_30 ((uint32_t)0x40000000) /*!< bit 30 */ +#define NVIC_ISPR_SETPEND_31 ((uint32_t)0x80000000) /*!< bit 31 */ + +/****************** Bit definition for NVIC_ICPR register *******************/ +#define NVIC_ICPR_CLRPEND ((uint32_t)0xFFFFFFFF) /*!< Interrupt clear-pending bits */ +#define NVIC_ICPR_CLRPEND_0 ((uint32_t)0x00000001) /*!< bit 0 */ +#define NVIC_ICPR_CLRPEND_1 ((uint32_t)0x00000002) /*!< bit 1 */ +#define NVIC_ICPR_CLRPEND_2 ((uint32_t)0x00000004) /*!< bit 2 */ +#define NVIC_ICPR_CLRPEND_3 ((uint32_t)0x00000008) /*!< bit 3 */ +#define NVIC_ICPR_CLRPEND_4 ((uint32_t)0x00000010) /*!< bit 4 */ +#define NVIC_ICPR_CLRPEND_5 ((uint32_t)0x00000020) /*!< bit 5 */ +#define NVIC_ICPR_CLRPEND_6 ((uint32_t)0x00000040) /*!< bit 6 */ +#define NVIC_ICPR_CLRPEND_7 ((uint32_t)0x00000080) /*!< bit 7 */ +#define NVIC_ICPR_CLRPEND_8 ((uint32_t)0x00000100) /*!< bit 8 */ +#define NVIC_ICPR_CLRPEND_9 ((uint32_t)0x00000200) /*!< bit 9 */ +#define NVIC_ICPR_CLRPEND_10 ((uint32_t)0x00000400) /*!< bit 10 */ +#define NVIC_ICPR_CLRPEND_11 ((uint32_t)0x00000800) /*!< bit 11 */ +#define NVIC_ICPR_CLRPEND_12 ((uint32_t)0x00001000) /*!< bit 12 */ +#define NVIC_ICPR_CLRPEND_13 ((uint32_t)0x00002000) /*!< bit 13 */ +#define NVIC_ICPR_CLRPEND_14 ((uint32_t)0x00004000) /*!< bit 14 */ +#define NVIC_ICPR_CLRPEND_15 ((uint32_t)0x00008000) /*!< bit 15 */ +#define NVIC_ICPR_CLRPEND_16 ((uint32_t)0x00010000) /*!< bit 16 */ +#define NVIC_ICPR_CLRPEND_17 ((uint32_t)0x00020000) /*!< bit 17 */ +#define NVIC_ICPR_CLRPEND_18 ((uint32_t)0x00040000) /*!< bit 18 */ +#define NVIC_ICPR_CLRPEND_19 ((uint32_t)0x00080000) /*!< bit 19 */ +#define NVIC_ICPR_CLRPEND_20 ((uint32_t)0x00100000) /*!< bit 20 */ +#define NVIC_ICPR_CLRPEND_21 ((uint32_t)0x00200000) /*!< bit 21 */ +#define NVIC_ICPR_CLRPEND_22 ((uint32_t)0x00400000) /*!< bit 22 */ +#define NVIC_ICPR_CLRPEND_23 ((uint32_t)0x00800000) /*!< bit 23 */ +#define NVIC_ICPR_CLRPEND_24 ((uint32_t)0x01000000) /*!< bit 24 */ +#define NVIC_ICPR_CLRPEND_25 ((uint32_t)0x02000000) /*!< bit 25 */ +#define NVIC_ICPR_CLRPEND_26 ((uint32_t)0x04000000) /*!< bit 26 */ +#define NVIC_ICPR_CLRPEND_27 ((uint32_t)0x08000000) /*!< bit 27 */ +#define NVIC_ICPR_CLRPEND_28 ((uint32_t)0x10000000) /*!< bit 28 */ +#define NVIC_ICPR_CLRPEND_29 ((uint32_t)0x20000000) /*!< bit 29 */ +#define NVIC_ICPR_CLRPEND_30 ((uint32_t)0x40000000) /*!< bit 30 */ +#define NVIC_ICPR_CLRPEND_31 ((uint32_t)0x80000000) /*!< bit 31 */ + +/****************** Bit definition for NVIC_IABR register *******************/ +#define NVIC_IABR_ACTIVE ((uint32_t)0xFFFFFFFF) /*!< Interrupt active flags */ +#define NVIC_IABR_ACTIVE_0 ((uint32_t)0x00000001) /*!< bit 0 */ +#define NVIC_IABR_ACTIVE_1 ((uint32_t)0x00000002) /*!< bit 1 */ +#define NVIC_IABR_ACTIVE_2 ((uint32_t)0x00000004) /*!< bit 2 */ +#define NVIC_IABR_ACTIVE_3 ((uint32_t)0x00000008) /*!< bit 3 */ +#define NVIC_IABR_ACTIVE_4 ((uint32_t)0x00000010) /*!< bit 4 */ +#define NVIC_IABR_ACTIVE_5 ((uint32_t)0x00000020) /*!< bit 5 */ +#define NVIC_IABR_ACTIVE_6 ((uint32_t)0x00000040) /*!< bit 6 */ +#define NVIC_IABR_ACTIVE_7 ((uint32_t)0x00000080) /*!< bit 7 */ +#define NVIC_IABR_ACTIVE_8 ((uint32_t)0x00000100) /*!< bit 8 */ +#define NVIC_IABR_ACTIVE_9 ((uint32_t)0x00000200) /*!< bit 9 */ +#define NVIC_IABR_ACTIVE_10 ((uint32_t)0x00000400) /*!< bit 10 */ +#define NVIC_IABR_ACTIVE_11 ((uint32_t)0x00000800) /*!< bit 11 */ +#define NVIC_IABR_ACTIVE_12 ((uint32_t)0x00001000) /*!< bit 12 */ +#define NVIC_IABR_ACTIVE_13 ((uint32_t)0x00002000) /*!< bit 13 */ +#define NVIC_IABR_ACTIVE_14 ((uint32_t)0x00004000) /*!< bit 14 */ +#define NVIC_IABR_ACTIVE_15 ((uint32_t)0x00008000) /*!< bit 15 */ +#define NVIC_IABR_ACTIVE_16 ((uint32_t)0x00010000) /*!< bit 16 */ +#define NVIC_IABR_ACTIVE_17 ((uint32_t)0x00020000) /*!< bit 17 */ +#define NVIC_IABR_ACTIVE_18 ((uint32_t)0x00040000) /*!< bit 18 */ +#define NVIC_IABR_ACTIVE_19 ((uint32_t)0x00080000) /*!< bit 19 */ +#define NVIC_IABR_ACTIVE_20 ((uint32_t)0x00100000) /*!< bit 20 */ +#define NVIC_IABR_ACTIVE_21 ((uint32_t)0x00200000) /*!< bit 21 */ +#define NVIC_IABR_ACTIVE_22 ((uint32_t)0x00400000) /*!< bit 22 */ +#define NVIC_IABR_ACTIVE_23 ((uint32_t)0x00800000) /*!< bit 23 */ +#define NVIC_IABR_ACTIVE_24 ((uint32_t)0x01000000) /*!< bit 24 */ +#define NVIC_IABR_ACTIVE_25 ((uint32_t)0x02000000) /*!< bit 25 */ +#define NVIC_IABR_ACTIVE_26 ((uint32_t)0x04000000) /*!< bit 26 */ +#define NVIC_IABR_ACTIVE_27 ((uint32_t)0x08000000) /*!< bit 27 */ +#define NVIC_IABR_ACTIVE_28 ((uint32_t)0x10000000) /*!< bit 28 */ +#define NVIC_IABR_ACTIVE_29 ((uint32_t)0x20000000) /*!< bit 29 */ +#define NVIC_IABR_ACTIVE_30 ((uint32_t)0x40000000) /*!< bit 30 */ +#define NVIC_IABR_ACTIVE_31 ((uint32_t)0x80000000) /*!< bit 31 */ + +/****************** Bit definition for NVIC_PRI0 register *******************/ +#define NVIC_IPR0_PRI_0 ((uint32_t)0x000000FF) /*!< Priority of interrupt 0 */ +#define NVIC_IPR0_PRI_1 ((uint32_t)0x0000FF00) /*!< Priority of interrupt 1 */ +#define NVIC_IPR0_PRI_2 ((uint32_t)0x00FF0000) /*!< Priority of interrupt 2 */ +#define NVIC_IPR0_PRI_3 ((uint32_t)0xFF000000) /*!< Priority of interrupt 3 */ + +/****************** Bit definition for NVIC_PRI1 register *******************/ +#define NVIC_IPR1_PRI_4 ((uint32_t)0x000000FF) /*!< Priority of interrupt 4 */ +#define NVIC_IPR1_PRI_5 ((uint32_t)0x0000FF00) /*!< Priority of interrupt 5 */ +#define NVIC_IPR1_PRI_6 ((uint32_t)0x00FF0000) /*!< Priority of interrupt 6 */ +#define NVIC_IPR1_PRI_7 ((uint32_t)0xFF000000) /*!< Priority of interrupt 7 */ + +/****************** Bit definition for NVIC_PRI2 register *******************/ +#define NVIC_IPR2_PRI_8 ((uint32_t)0x000000FF) /*!< Priority of interrupt 8 */ +#define NVIC_IPR2_PRI_9 ((uint32_t)0x0000FF00) /*!< Priority of interrupt 9 */ +#define NVIC_IPR2_PRI_10 ((uint32_t)0x00FF0000) /*!< Priority of interrupt 10 */ +#define NVIC_IPR2_PRI_11 ((uint32_t)0xFF000000) /*!< Priority of interrupt 11 */ + +/****************** Bit definition for NVIC_PRI3 register *******************/ +#define NVIC_IPR3_PRI_12 ((uint32_t)0x000000FF) /*!< Priority of interrupt 12 */ +#define NVIC_IPR3_PRI_13 ((uint32_t)0x0000FF00) /*!< Priority of interrupt 13 */ +#define NVIC_IPR3_PRI_14 ((uint32_t)0x00FF0000) /*!< Priority of interrupt 14 */ +#define NVIC_IPR3_PRI_15 ((uint32_t)0xFF000000) /*!< Priority of interrupt 15 */ + +/****************** Bit definition for NVIC_PRI4 register *******************/ +#define NVIC_IPR4_PRI_16 ((uint32_t)0x000000FF) /*!< Priority of interrupt 16 */ +#define NVIC_IPR4_PRI_17 ((uint32_t)0x0000FF00) /*!< Priority of interrupt 17 */ +#define NVIC_IPR4_PRI_18 ((uint32_t)0x00FF0000) /*!< Priority of interrupt 18 */ +#define NVIC_IPR4_PRI_19 ((uint32_t)0xFF000000) /*!< Priority of interrupt 19 */ + +/****************** Bit definition for NVIC_PRI5 register *******************/ +#define NVIC_IPR5_PRI_20 ((uint32_t)0x000000FF) /*!< Priority of interrupt 20 */ +#define NVIC_IPR5_PRI_21 ((uint32_t)0x0000FF00) /*!< Priority of interrupt 21 */ +#define NVIC_IPR5_PRI_22 ((uint32_t)0x00FF0000) /*!< Priority of interrupt 22 */ +#define NVIC_IPR5_PRI_23 ((uint32_t)0xFF000000) /*!< Priority of interrupt 23 */ + +/****************** Bit definition for NVIC_PRI6 register *******************/ +#define NVIC_IPR6_PRI_24 ((uint32_t)0x000000FF) /*!< Priority of interrupt 24 */ +#define NVIC_IPR6_PRI_25 ((uint32_t)0x0000FF00) /*!< Priority of interrupt 25 */ +#define NVIC_IPR6_PRI_26 ((uint32_t)0x00FF0000) /*!< Priority of interrupt 26 */ +#define NVIC_IPR6_PRI_27 ((uint32_t)0xFF000000) /*!< Priority of interrupt 27 */ + +/****************** Bit definition for NVIC_PRI7 register *******************/ +#define NVIC_IPR7_PRI_28 ((uint32_t)0x000000FF) /*!< Priority of interrupt 28 */ +#define NVIC_IPR7_PRI_29 ((uint32_t)0x0000FF00) /*!< Priority of interrupt 29 */ +#define NVIC_IPR7_PRI_30 ((uint32_t)0x00FF0000) /*!< Priority of interrupt 30 */ +#define NVIC_IPR7_PRI_31 ((uint32_t)0xFF000000) /*!< Priority of interrupt 31 */ + +/****************** Bit definition for SCB_CPUID register *******************/ +#define SCB_CPUID_REVISION ((uint32_t)0x0000000F) /*!< Implementation defined revision number */ +#define SCB_CPUID_PARTNO ((uint32_t)0x0000FFF0) /*!< Number of processor within family */ +#define SCB_CPUID_Constant ((uint32_t)0x000F0000) /*!< Reads as 0x0F */ +#define SCB_CPUID_VARIANT ((uint32_t)0x00F00000) /*!< Implementation defined variant number */ +#define SCB_CPUID_IMPLEMENTER ((uint32_t)0xFF000000) /*!< Implementer code. ARM is 0x41 */ + +/******************* Bit definition for SCB_ICSR register *******************/ +#define SCB_ICSR_VECTACTIVE ((uint32_t)0x000001FF) /*!< Active ISR number field */ +#define SCB_ICSR_RETTOBASE ((uint32_t)0x00000800) /*!< All active exceptions minus the IPSR_current_exception yields the empty set */ +#define SCB_ICSR_VECTPENDING ((uint32_t)0x003FF000) /*!< Pending ISR number field */ +#define SCB_ICSR_ISRPENDING ((uint32_t)0x00400000) /*!< Interrupt pending flag */ +#define SCB_ICSR_ISRPREEMPT ((uint32_t)0x00800000) /*!< It indicates that a pending interrupt becomes active in the next running cycle */ +#define SCB_ICSR_PENDSTCLR ((uint32_t)0x02000000) /*!< Clear pending SysTick bit */ +#define SCB_ICSR_PENDSTSET ((uint32_t)0x04000000) /*!< Set pending SysTick bit */ +#define SCB_ICSR_PENDSVCLR ((uint32_t)0x08000000) /*!< Clear pending pendSV bit */ +#define SCB_ICSR_PENDSVSET ((uint32_t)0x10000000) /*!< Set pending pendSV bit */ +#define SCB_ICSR_NMIPENDSET ((uint32_t)0x80000000) /*!< Set pending NMI bit */ + +/******************* Bit definition for SCB_VTOR register *******************/ +#define SCB_VTOR_TBLOFF ((uint32_t)0x1FFFFF80) /*!< Vector table base offset field */ +#define SCB_VTOR_TBLBASE ((uint32_t)0x20000000) /*!< Table base in code(0) or RAM(1) */ + +/*!<***************** Bit definition for SCB_AIRCR register *******************/ +#define SCB_AIRCR_VECTRESET ((uint32_t)0x00000001) /*!< System Reset bit */ +#define SCB_AIRCR_VECTCLRACTIVE ((uint32_t)0x00000002) /*!< Clear active vector bit */ +#define SCB_AIRCR_SYSRESETREQ ((uint32_t)0x00000004) /*!< Requests chip control logic to generate a reset */ + +#define SCB_AIRCR_PRIGROUP ((uint32_t)0x00000700) /*!< PRIGROUP[2:0] bits (Priority group) */ +#define SCB_AIRCR_PRIGROUP_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define SCB_AIRCR_PRIGROUP_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define SCB_AIRCR_PRIGROUP_2 ((uint32_t)0x00000400) /*!< Bit 2 */ + +/* prority group configuration */ +#define SCB_AIRCR_PRIGROUP0 ((uint32_t)0x00000000) /*!< Priority group=0 (7 bits of pre-emption priority, 1 bit of subpriority) */ +#define SCB_AIRCR_PRIGROUP1 ((uint32_t)0x00000100) /*!< Priority group=1 (6 bits of pre-emption priority, 2 bits of subpriority) */ +#define SCB_AIRCR_PRIGROUP2 ((uint32_t)0x00000200) /*!< Priority group=2 (5 bits of pre-emption priority, 3 bits of subpriority) */ +#define SCB_AIRCR_PRIGROUP3 ((uint32_t)0x00000300) /*!< Priority group=3 (4 bits of pre-emption priority, 4 bits of subpriority) */ +#define SCB_AIRCR_PRIGROUP4 ((uint32_t)0x00000400) /*!< Priority group=4 (3 bits of pre-emption priority, 5 bits of subpriority) */ +#define SCB_AIRCR_PRIGROUP5 ((uint32_t)0x00000500) /*!< Priority group=5 (2 bits of pre-emption priority, 6 bits of subpriority) */ +#define SCB_AIRCR_PRIGROUP6 ((uint32_t)0x00000600) /*!< Priority group=6 (1 bit of pre-emption priority, 7 bits of subpriority) */ +#define SCB_AIRCR_PRIGROUP7 ((uint32_t)0x00000700) /*!< Priority group=7 (no pre-emption priority, 8 bits of subpriority) */ + +#define SCB_AIRCR_ENDIANESS ((uint32_t)0x00008000) /*!< Data endianness bit */ +#define SCB_AIRCR_VECTKEY ((uint32_t)0xFFFF0000) /*!< Register key (VECTKEY) - Reads as 0xFA05 (VECTKEYSTAT) */ + +/******************* Bit definition for SCB_SCR register ********************/ +#define SCB_SCR_SLEEPONEXIT ((uint8_t)0x02) /*!< Sleep on exit bit */ +#define SCB_SCR_SLEEPDEEP ((uint8_t)0x04) /*!< Sleep deep bit */ +#define SCB_SCR_SEVONPEND ((uint8_t)0x10) /*!< Wake up from WFE */ + +/******************** Bit definition for SCB_CCR register *******************/ +#define SCB_CCR_NONBASETHRDENA ((uint16_t)0x0001) /*!< Thread mode can be entered from any level in Handler mode by controlled return value */ +#define SCB_CCR_USERSETMPEND ((uint16_t)0x0002) /*!< Enables user code to write the Software Trigger Interrupt register to trigger (pend) a Main exception */ +#define SCB_CCR_UNALIGN_TRP ((uint16_t)0x0008) /*!< Trap for unaligned access */ +#define SCB_CCR_DIV_0_TRP ((uint16_t)0x0010) /*!< Trap on Divide by 0 */ +#define SCB_CCR_BFHFNMIGN ((uint16_t)0x0100) /*!< Handlers running at priority -1 and -2 */ +#define SCB_CCR_STKALIGN ((uint16_t)0x0200) /*!< On exception entry, the SP used prior to the exception is adjusted to be 8-byte aligned */ + +/******************* Bit definition for SCB_SHPR register ********************/ +#define SCB_SHPR_PRI_N ((uint32_t)0x000000FF) /*!< Priority of system handler 4,8, and 12. Mem Manage, reserved and Debug Monitor */ +#define SCB_SHPR_PRI_N1 ((uint32_t)0x0000FF00) /*!< Priority of system handler 5,9, and 13. Bus Fault, reserved and reserved */ +#define SCB_SHPR_PRI_N2 ((uint32_t)0x00FF0000) /*!< Priority of system handler 6,10, and 14. Usage Fault, reserved and PendSV */ +#define SCB_SHPR_PRI_N3 ((uint32_t)0xFF000000) /*!< Priority of system handler 7,11, and 15. Reserved, SVCall and SysTick */ + +/****************** Bit definition for SCB_SHCSR register *******************/ +#define SCB_SHCSR_MEMFAULTACT ((uint32_t)0x00000001) /*!< MemManage is active */ +#define SCB_SHCSR_BUSFAULTACT ((uint32_t)0x00000002) /*!< BusFault is active */ +#define SCB_SHCSR_USGFAULTACT ((uint32_t)0x00000008) /*!< UsageFault is active */ +#define SCB_SHCSR_SVCALLACT ((uint32_t)0x00000080) /*!< SVCall is active */ +#define SCB_SHCSR_MONITORACT ((uint32_t)0x00000100) /*!< Monitor is active */ +#define SCB_SHCSR_PENDSVACT ((uint32_t)0x00000400) /*!< PendSV is active */ +#define SCB_SHCSR_SYSTICKACT ((uint32_t)0x00000800) /*!< SysTick is active */ +#define SCB_SHCSR_USGFAULTPENDED ((uint32_t)0x00001000) /*!< Usage Fault is pended */ +#define SCB_SHCSR_MEMFAULTPENDED ((uint32_t)0x00002000) /*!< MemManage is pended */ +#define SCB_SHCSR_BUSFAULTPENDED ((uint32_t)0x00004000) /*!< Bus Fault is pended */ +#define SCB_SHCSR_SVCALLPENDED ((uint32_t)0x00008000) /*!< SVCall is pended */ +#define SCB_SHCSR_MEMFAULTENA ((uint32_t)0x00010000) /*!< MemManage enable */ +#define SCB_SHCSR_BUSFAULTENA ((uint32_t)0x00020000) /*!< Bus Fault enable */ +#define SCB_SHCSR_USGFAULTENA ((uint32_t)0x00040000) /*!< UsageFault enable */ + +/******************* Bit definition for SCB_CFSR register *******************/ +/*!< MFSR */ +#define SCB_CFSR_IACCVIOL ((uint32_t)0x00000001) /*!< Instruction access violation */ +#define SCB_CFSR_DACCVIOL ((uint32_t)0x00000002) /*!< Data access violation */ +#define SCB_CFSR_MUNSTKERR ((uint32_t)0x00000008) /*!< Unstacking error */ +#define SCB_CFSR_MSTKERR ((uint32_t)0x00000010) /*!< Stacking error */ +#define SCB_CFSR_MMARVALID ((uint32_t)0x00000080) /*!< Memory Manage Address Register address valid flag */ +/*!< BFSR */ +#define SCB_CFSR_IBUSERR ((uint32_t)0x00000100) /*!< Instruction bus error flag */ +#define SCB_CFSR_PRECISERR ((uint32_t)0x00000200) /*!< Precise data bus error */ +#define SCB_CFSR_IMPRECISERR ((uint32_t)0x00000400) /*!< Imprecise data bus error */ +#define SCB_CFSR_UNSTKERR ((uint32_t)0x00000800) /*!< Unstacking error */ +#define SCB_CFSR_STKERR ((uint32_t)0x00001000) /*!< Stacking error */ +#define SCB_CFSR_BFARVALID ((uint32_t)0x00008000) /*!< Bus Fault Address Register address valid flag */ +/*!< UFSR */ +#define SCB_CFSR_UNDEFINSTR ((uint32_t)0x00010000) /*!< The processor attempt to execute an undefined instruction */ +#define SCB_CFSR_INVSTATE ((uint32_t)0x00020000) /*!< Invalid combination of EPSR and instruction */ +#define SCB_CFSR_INVPC ((uint32_t)0x00040000) /*!< Attempt to load EXC_RETURN into pc illegally */ +#define SCB_CFSR_NOCP ((uint32_t)0x00080000) /*!< Attempt to use a coprocessor instruction */ +#define SCB_CFSR_UNALIGNED ((uint32_t)0x01000000) /*!< Fault occurs when there is an attempt to make an unaligned memory access */ +#define SCB_CFSR_DIVBYZERO ((uint32_t)0x02000000) /*!< Fault occurs when SDIV or DIV instruction is used with a divisor of 0 */ + +/******************* Bit definition for SCB_HFSR register *******************/ +#define SCB_HFSR_VECTTBL ((uint32_t)0x00000002) /*!< Fault occurs because of vector table read on exception processing */ +#define SCB_HFSR_FORCED ((uint32_t)0x40000000) /*!< Hard Fault activated when a configurable Fault was received and cannot activate */ +#define SCB_HFSR_DEBUGEVT ((uint32_t)0x80000000) /*!< Fault related to debug */ + +/******************* Bit definition for SCB_DFSR register *******************/ +#define SCB_DFSR_HALTED ((uint8_t)0x01) /*!< Halt request flag */ +#define SCB_DFSR_BKPT ((uint8_t)0x02) /*!< BKPT flag */ +#define SCB_DFSR_DWTTRAP ((uint8_t)0x04) /*!< Data Watchpoint and Trace (DWT) flag */ +#define SCB_DFSR_VCATCH ((uint8_t)0x08) /*!< Vector catch flag */ +#define SCB_DFSR_EXTERNAL ((uint8_t)0x10) /*!< External debug request flag */ + +/******************* Bit definition for SCB_MMFAR register ******************/ +#define SCB_MMFAR_ADDRESS ((uint32_t)0xFFFFFFFF) /*!< Mem Manage fault address field */ + +/******************* Bit definition for SCB_BFAR register *******************/ +#define SCB_BFAR_ADDRESS ((uint32_t)0xFFFFFFFF) /*!< Bus fault address field */ + +/******************* Bit definition for SCB_afsr register *******************/ +#define SCB_AFSR_IMPDEF ((uint32_t)0xFFFFFFFF) /*!< Implementation defined */ + +/******************************************************************************/ +/* */ +/* External Interrupt/Event Controller */ +/* */ +/******************************************************************************/ + +/******************* Bit definition for EXTI_IMR register *******************/ +#define EXTI_IMR_MR0 ((uint32_t)0x00000001) /*!< Interrupt Mask on line 0 */ +#define EXTI_IMR_MR1 ((uint32_t)0x00000002) /*!< Interrupt Mask on line 1 */ +#define EXTI_IMR_MR2 ((uint32_t)0x00000004) /*!< Interrupt Mask on line 2 */ +#define EXTI_IMR_MR3 ((uint32_t)0x00000008) /*!< Interrupt Mask on line 3 */ +#define EXTI_IMR_MR4 ((uint32_t)0x00000010) /*!< Interrupt Mask on line 4 */ +#define EXTI_IMR_MR5 ((uint32_t)0x00000020) /*!< Interrupt Mask on line 5 */ +#define EXTI_IMR_MR6 ((uint32_t)0x00000040) /*!< Interrupt Mask on line 6 */ +#define EXTI_IMR_MR7 ((uint32_t)0x00000080) /*!< Interrupt Mask on line 7 */ +#define EXTI_IMR_MR8 ((uint32_t)0x00000100) /*!< Interrupt Mask on line 8 */ +#define EXTI_IMR_MR9 ((uint32_t)0x00000200) /*!< Interrupt Mask on line 9 */ +#define EXTI_IMR_MR10 ((uint32_t)0x00000400) /*!< Interrupt Mask on line 10 */ +#define EXTI_IMR_MR11 ((uint32_t)0x00000800) /*!< Interrupt Mask on line 11 */ +#define EXTI_IMR_MR12 ((uint32_t)0x00001000) /*!< Interrupt Mask on line 12 */ +#define EXTI_IMR_MR13 ((uint32_t)0x00002000) /*!< Interrupt Mask on line 13 */ +#define EXTI_IMR_MR14 ((uint32_t)0x00004000) /*!< Interrupt Mask on line 14 */ +#define EXTI_IMR_MR15 ((uint32_t)0x00008000) /*!< Interrupt Mask on line 15 */ +#define EXTI_IMR_MR16 ((uint32_t)0x00010000) /*!< Interrupt Mask on line 16 */ +#define EXTI_IMR_MR17 ((uint32_t)0x00020000) /*!< Interrupt Mask on line 17 */ +#define EXTI_IMR_MR18 ((uint32_t)0x00040000) /*!< Interrupt Mask on line 18 */ +#define EXTI_IMR_MR19 ((uint32_t)0x00080000) /*!< Interrupt Mask on line 19 */ + +/******************* Bit definition for EXTI_EMR register *******************/ +#define EXTI_EMR_MR0 ((uint32_t)0x00000001) /*!< Event Mask on line 0 */ +#define EXTI_EMR_MR1 ((uint32_t)0x00000002) /*!< Event Mask on line 1 */ +#define EXTI_EMR_MR2 ((uint32_t)0x00000004) /*!< Event Mask on line 2 */ +#define EXTI_EMR_MR3 ((uint32_t)0x00000008) /*!< Event Mask on line 3 */ +#define EXTI_EMR_MR4 ((uint32_t)0x00000010) /*!< Event Mask on line 4 */ +#define EXTI_EMR_MR5 ((uint32_t)0x00000020) /*!< Event Mask on line 5 */ +#define EXTI_EMR_MR6 ((uint32_t)0x00000040) /*!< Event Mask on line 6 */ +#define EXTI_EMR_MR7 ((uint32_t)0x00000080) /*!< Event Mask on line 7 */ +#define EXTI_EMR_MR8 ((uint32_t)0x00000100) /*!< Event Mask on line 8 */ +#define EXTI_EMR_MR9 ((uint32_t)0x00000200) /*!< Event Mask on line 9 */ +#define EXTI_EMR_MR10 ((uint32_t)0x00000400) /*!< Event Mask on line 10 */ +#define EXTI_EMR_MR11 ((uint32_t)0x00000800) /*!< Event Mask on line 11 */ +#define EXTI_EMR_MR12 ((uint32_t)0x00001000) /*!< Event Mask on line 12 */ +#define EXTI_EMR_MR13 ((uint32_t)0x00002000) /*!< Event Mask on line 13 */ +#define EXTI_EMR_MR14 ((uint32_t)0x00004000) /*!< Event Mask on line 14 */ +#define EXTI_EMR_MR15 ((uint32_t)0x00008000) /*!< Event Mask on line 15 */ +#define EXTI_EMR_MR16 ((uint32_t)0x00010000) /*!< Event Mask on line 16 */ +#define EXTI_EMR_MR17 ((uint32_t)0x00020000) /*!< Event Mask on line 17 */ +#define EXTI_EMR_MR18 ((uint32_t)0x00040000) /*!< Event Mask on line 18 */ +#define EXTI_EMR_MR19 ((uint32_t)0x00080000) /*!< Event Mask on line 19 */ + +/****************** Bit definition for EXTI_RTSR register *******************/ +#define EXTI_RTSR_TR0 ((uint32_t)0x00000001) /*!< Rising trigger event configuration bit of line 0 */ +#define EXTI_RTSR_TR1 ((uint32_t)0x00000002) /*!< Rising trigger event configuration bit of line 1 */ +#define EXTI_RTSR_TR2 ((uint32_t)0x00000004) /*!< Rising trigger event configuration bit of line 2 */ +#define EXTI_RTSR_TR3 ((uint32_t)0x00000008) /*!< Rising trigger event configuration bit of line 3 */ +#define EXTI_RTSR_TR4 ((uint32_t)0x00000010) /*!< Rising trigger event configuration bit of line 4 */ +#define EXTI_RTSR_TR5 ((uint32_t)0x00000020) /*!< Rising trigger event configuration bit of line 5 */ +#define EXTI_RTSR_TR6 ((uint32_t)0x00000040) /*!< Rising trigger event configuration bit of line 6 */ +#define EXTI_RTSR_TR7 ((uint32_t)0x00000080) /*!< Rising trigger event configuration bit of line 7 */ +#define EXTI_RTSR_TR8 ((uint32_t)0x00000100) /*!< Rising trigger event configuration bit of line 8 */ +#define EXTI_RTSR_TR9 ((uint32_t)0x00000200) /*!< Rising trigger event configuration bit of line 9 */ +#define EXTI_RTSR_TR10 ((uint32_t)0x00000400) /*!< Rising trigger event configuration bit of line 10 */ +#define EXTI_RTSR_TR11 ((uint32_t)0x00000800) /*!< Rising trigger event configuration bit of line 11 */ +#define EXTI_RTSR_TR12 ((uint32_t)0x00001000) /*!< Rising trigger event configuration bit of line 12 */ +#define EXTI_RTSR_TR13 ((uint32_t)0x00002000) /*!< Rising trigger event configuration bit of line 13 */ +#define EXTI_RTSR_TR14 ((uint32_t)0x00004000) /*!< Rising trigger event configuration bit of line 14 */ +#define EXTI_RTSR_TR15 ((uint32_t)0x00008000) /*!< Rising trigger event configuration bit of line 15 */ +#define EXTI_RTSR_TR16 ((uint32_t)0x00010000) /*!< Rising trigger event configuration bit of line 16 */ +#define EXTI_RTSR_TR17 ((uint32_t)0x00020000) /*!< Rising trigger event configuration bit of line 17 */ +#define EXTI_RTSR_TR18 ((uint32_t)0x00040000) /*!< Rising trigger event configuration bit of line 18 */ +#define EXTI_RTSR_TR19 ((uint32_t)0x00080000) /*!< Rising trigger event configuration bit of line 19 */ + +/****************** Bit definition for EXTI_FTSR register *******************/ +#define EXTI_FTSR_TR0 ((uint32_t)0x00000001) /*!< Falling trigger event configuration bit of line 0 */ +#define EXTI_FTSR_TR1 ((uint32_t)0x00000002) /*!< Falling trigger event configuration bit of line 1 */ +#define EXTI_FTSR_TR2 ((uint32_t)0x00000004) /*!< Falling trigger event configuration bit of line 2 */ +#define EXTI_FTSR_TR3 ((uint32_t)0x00000008) /*!< Falling trigger event configuration bit of line 3 */ +#define EXTI_FTSR_TR4 ((uint32_t)0x00000010) /*!< Falling trigger event configuration bit of line 4 */ +#define EXTI_FTSR_TR5 ((uint32_t)0x00000020) /*!< Falling trigger event configuration bit of line 5 */ +#define EXTI_FTSR_TR6 ((uint32_t)0x00000040) /*!< Falling trigger event configuration bit of line 6 */ +#define EXTI_FTSR_TR7 ((uint32_t)0x00000080) /*!< Falling trigger event configuration bit of line 7 */ +#define EXTI_FTSR_TR8 ((uint32_t)0x00000100) /*!< Falling trigger event configuration bit of line 8 */ +#define EXTI_FTSR_TR9 ((uint32_t)0x00000200) /*!< Falling trigger event configuration bit of line 9 */ +#define EXTI_FTSR_TR10 ((uint32_t)0x00000400) /*!< Falling trigger event configuration bit of line 10 */ +#define EXTI_FTSR_TR11 ((uint32_t)0x00000800) /*!< Falling trigger event configuration bit of line 11 */ +#define EXTI_FTSR_TR12 ((uint32_t)0x00001000) /*!< Falling trigger event configuration bit of line 12 */ +#define EXTI_FTSR_TR13 ((uint32_t)0x00002000) /*!< Falling trigger event configuration bit of line 13 */ +#define EXTI_FTSR_TR14 ((uint32_t)0x00004000) /*!< Falling trigger event configuration bit of line 14 */ +#define EXTI_FTSR_TR15 ((uint32_t)0x00008000) /*!< Falling trigger event configuration bit of line 15 */ +#define EXTI_FTSR_TR16 ((uint32_t)0x00010000) /*!< Falling trigger event configuration bit of line 16 */ +#define EXTI_FTSR_TR17 ((uint32_t)0x00020000) /*!< Falling trigger event configuration bit of line 17 */ +#define EXTI_FTSR_TR18 ((uint32_t)0x00040000) /*!< Falling trigger event configuration bit of line 18 */ +#define EXTI_FTSR_TR19 ((uint32_t)0x00080000) /*!< Falling trigger event configuration bit of line 19 */ + +/****************** Bit definition for EXTI_SWIER register ******************/ +#define EXTI_SWIER_SWIER0 ((uint32_t)0x00000001) /*!< Software Interrupt on line 0 */ +#define EXTI_SWIER_SWIER1 ((uint32_t)0x00000002) /*!< Software Interrupt on line 1 */ +#define EXTI_SWIER_SWIER2 ((uint32_t)0x00000004) /*!< Software Interrupt on line 2 */ +#define EXTI_SWIER_SWIER3 ((uint32_t)0x00000008) /*!< Software Interrupt on line 3 */ +#define EXTI_SWIER_SWIER4 ((uint32_t)0x00000010) /*!< Software Interrupt on line 4 */ +#define EXTI_SWIER_SWIER5 ((uint32_t)0x00000020) /*!< Software Interrupt on line 5 */ +#define EXTI_SWIER_SWIER6 ((uint32_t)0x00000040) /*!< Software Interrupt on line 6 */ +#define EXTI_SWIER_SWIER7 ((uint32_t)0x00000080) /*!< Software Interrupt on line 7 */ +#define EXTI_SWIER_SWIER8 ((uint32_t)0x00000100) /*!< Software Interrupt on line 8 */ +#define EXTI_SWIER_SWIER9 ((uint32_t)0x00000200) /*!< Software Interrupt on line 9 */ +#define EXTI_SWIER_SWIER10 ((uint32_t)0x00000400) /*!< Software Interrupt on line 10 */ +#define EXTI_SWIER_SWIER11 ((uint32_t)0x00000800) /*!< Software Interrupt on line 11 */ +#define EXTI_SWIER_SWIER12 ((uint32_t)0x00001000) /*!< Software Interrupt on line 12 */ +#define EXTI_SWIER_SWIER13 ((uint32_t)0x00002000) /*!< Software Interrupt on line 13 */ +#define EXTI_SWIER_SWIER14 ((uint32_t)0x00004000) /*!< Software Interrupt on line 14 */ +#define EXTI_SWIER_SWIER15 ((uint32_t)0x00008000) /*!< Software Interrupt on line 15 */ +#define EXTI_SWIER_SWIER16 ((uint32_t)0x00010000) /*!< Software Interrupt on line 16 */ +#define EXTI_SWIER_SWIER17 ((uint32_t)0x00020000) /*!< Software Interrupt on line 17 */ +#define EXTI_SWIER_SWIER18 ((uint32_t)0x00040000) /*!< Software Interrupt on line 18 */ +#define EXTI_SWIER_SWIER19 ((uint32_t)0x00080000) /*!< Software Interrupt on line 19 */ + +/******************* Bit definition for EXTI_PR register ********************/ +#define EXTI_PR_PR0 ((uint32_t)0x00000001) /*!< Pending bit for line 0 */ +#define EXTI_PR_PR1 ((uint32_t)0x00000002) /*!< Pending bit for line 1 */ +#define EXTI_PR_PR2 ((uint32_t)0x00000004) /*!< Pending bit for line 2 */ +#define EXTI_PR_PR3 ((uint32_t)0x00000008) /*!< Pending bit for line 3 */ +#define EXTI_PR_PR4 ((uint32_t)0x00000010) /*!< Pending bit for line 4 */ +#define EXTI_PR_PR5 ((uint32_t)0x00000020) /*!< Pending bit for line 5 */ +#define EXTI_PR_PR6 ((uint32_t)0x00000040) /*!< Pending bit for line 6 */ +#define EXTI_PR_PR7 ((uint32_t)0x00000080) /*!< Pending bit for line 7 */ +#define EXTI_PR_PR8 ((uint32_t)0x00000100) /*!< Pending bit for line 8 */ +#define EXTI_PR_PR9 ((uint32_t)0x00000200) /*!< Pending bit for line 9 */ +#define EXTI_PR_PR10 ((uint32_t)0x00000400) /*!< Pending bit for line 10 */ +#define EXTI_PR_PR11 ((uint32_t)0x00000800) /*!< Pending bit for line 11 */ +#define EXTI_PR_PR12 ((uint32_t)0x00001000) /*!< Pending bit for line 12 */ +#define EXTI_PR_PR13 ((uint32_t)0x00002000) /*!< Pending bit for line 13 */ +#define EXTI_PR_PR14 ((uint32_t)0x00004000) /*!< Pending bit for line 14 */ +#define EXTI_PR_PR15 ((uint32_t)0x00008000) /*!< Pending bit for line 15 */ +#define EXTI_PR_PR16 ((uint32_t)0x00010000) /*!< Pending bit for line 16 */ +#define EXTI_PR_PR17 ((uint32_t)0x00020000) /*!< Pending bit for line 17 */ +#define EXTI_PR_PR18 ((uint32_t)0x00040000) /*!< Pending bit for line 18 */ +#define EXTI_PR_PR19 ((uint32_t)0x00080000) /*!< Pending bit for line 19 */ + +/******************************************************************************/ +/* */ +/* DMA Controller */ +/* */ +/******************************************************************************/ + +/******************* Bit definition for DMA_ISR register ********************/ +#define DMA_ISR_GIF1 ((uint32_t)0x00000001) /*!< Channel 1 Global interrupt flag */ +#define DMA_ISR_TCIF1 ((uint32_t)0x00000002) /*!< Channel 1 Transfer Complete flag */ +#define DMA_ISR_HTIF1 ((uint32_t)0x00000004) /*!< Channel 1 Half Transfer flag */ +#define DMA_ISR_TEIF1 ((uint32_t)0x00000008) /*!< Channel 1 Transfer Error flag */ +#define DMA_ISR_GIF2 ((uint32_t)0x00000010) /*!< Channel 2 Global interrupt flag */ +#define DMA_ISR_TCIF2 ((uint32_t)0x00000020) /*!< Channel 2 Transfer Complete flag */ +#define DMA_ISR_HTIF2 ((uint32_t)0x00000040) /*!< Channel 2 Half Transfer flag */ +#define DMA_ISR_TEIF2 ((uint32_t)0x00000080) /*!< Channel 2 Transfer Error flag */ +#define DMA_ISR_GIF3 ((uint32_t)0x00000100) /*!< Channel 3 Global interrupt flag */ +#define DMA_ISR_TCIF3 ((uint32_t)0x00000200) /*!< Channel 3 Transfer Complete flag */ +#define DMA_ISR_HTIF3 ((uint32_t)0x00000400) /*!< Channel 3 Half Transfer flag */ +#define DMA_ISR_TEIF3 ((uint32_t)0x00000800) /*!< Channel 3 Transfer Error flag */ +#define DMA_ISR_GIF4 ((uint32_t)0x00001000) /*!< Channel 4 Global interrupt flag */ +#define DMA_ISR_TCIF4 ((uint32_t)0x00002000) /*!< Channel 4 Transfer Complete flag */ +#define DMA_ISR_HTIF4 ((uint32_t)0x00004000) /*!< Channel 4 Half Transfer flag */ +#define DMA_ISR_TEIF4 ((uint32_t)0x00008000) /*!< Channel 4 Transfer Error flag */ +#define DMA_ISR_GIF5 ((uint32_t)0x00010000) /*!< Channel 5 Global interrupt flag */ +#define DMA_ISR_TCIF5 ((uint32_t)0x00020000) /*!< Channel 5 Transfer Complete flag */ +#define DMA_ISR_HTIF5 ((uint32_t)0x00040000) /*!< Channel 5 Half Transfer flag */ +#define DMA_ISR_TEIF5 ((uint32_t)0x00080000) /*!< Channel 5 Transfer Error flag */ +#define DMA_ISR_GIF6 ((uint32_t)0x00100000) /*!< Channel 6 Global interrupt flag */ +#define DMA_ISR_TCIF6 ((uint32_t)0x00200000) /*!< Channel 6 Transfer Complete flag */ +#define DMA_ISR_HTIF6 ((uint32_t)0x00400000) /*!< Channel 6 Half Transfer flag */ +#define DMA_ISR_TEIF6 ((uint32_t)0x00800000) /*!< Channel 6 Transfer Error flag */ +#define DMA_ISR_GIF7 ((uint32_t)0x01000000) /*!< Channel 7 Global interrupt flag */ +#define DMA_ISR_TCIF7 ((uint32_t)0x02000000) /*!< Channel 7 Transfer Complete flag */ +#define DMA_ISR_HTIF7 ((uint32_t)0x04000000) /*!< Channel 7 Half Transfer flag */ +#define DMA_ISR_TEIF7 ((uint32_t)0x08000000) /*!< Channel 7 Transfer Error flag */ + +/******************* Bit definition for DMA_IFCR register *******************/ +#define DMA_IFCR_CGIF1 ((uint32_t)0x00000001) /*!< Channel 1 Global interrupt clear */ +#define DMA_IFCR_CTCIF1 ((uint32_t)0x00000002) /*!< Channel 1 Transfer Complete clear */ +#define DMA_IFCR_CHTIF1 ((uint32_t)0x00000004) /*!< Channel 1 Half Transfer clear */ +#define DMA_IFCR_CTEIF1 ((uint32_t)0x00000008) /*!< Channel 1 Transfer Error clear */ +#define DMA_IFCR_CGIF2 ((uint32_t)0x00000010) /*!< Channel 2 Global interrupt clear */ +#define DMA_IFCR_CTCIF2 ((uint32_t)0x00000020) /*!< Channel 2 Transfer Complete clear */ +#define DMA_IFCR_CHTIF2 ((uint32_t)0x00000040) /*!< Channel 2 Half Transfer clear */ +#define DMA_IFCR_CTEIF2 ((uint32_t)0x00000080) /*!< Channel 2 Transfer Error clear */ +#define DMA_IFCR_CGIF3 ((uint32_t)0x00000100) /*!< Channel 3 Global interrupt clear */ +#define DMA_IFCR_CTCIF3 ((uint32_t)0x00000200) /*!< Channel 3 Transfer Complete clear */ +#define DMA_IFCR_CHTIF3 ((uint32_t)0x00000400) /*!< Channel 3 Half Transfer clear */ +#define DMA_IFCR_CTEIF3 ((uint32_t)0x00000800) /*!< Channel 3 Transfer Error clear */ +#define DMA_IFCR_CGIF4 ((uint32_t)0x00001000) /*!< Channel 4 Global interrupt clear */ +#define DMA_IFCR_CTCIF4 ((uint32_t)0x00002000) /*!< Channel 4 Transfer Complete clear */ +#define DMA_IFCR_CHTIF4 ((uint32_t)0x00004000) /*!< Channel 4 Half Transfer clear */ +#define DMA_IFCR_CTEIF4 ((uint32_t)0x00008000) /*!< Channel 4 Transfer Error clear */ +#define DMA_IFCR_CGIF5 ((uint32_t)0x00010000) /*!< Channel 5 Global interrupt clear */ +#define DMA_IFCR_CTCIF5 ((uint32_t)0x00020000) /*!< Channel 5 Transfer Complete clear */ +#define DMA_IFCR_CHTIF5 ((uint32_t)0x00040000) /*!< Channel 5 Half Transfer clear */ +#define DMA_IFCR_CTEIF5 ((uint32_t)0x00080000) /*!< Channel 5 Transfer Error clear */ +#define DMA_IFCR_CGIF6 ((uint32_t)0x00100000) /*!< Channel 6 Global interrupt clear */ +#define DMA_IFCR_CTCIF6 ((uint32_t)0x00200000) /*!< Channel 6 Transfer Complete clear */ +#define DMA_IFCR_CHTIF6 ((uint32_t)0x00400000) /*!< Channel 6 Half Transfer clear */ +#define DMA_IFCR_CTEIF6 ((uint32_t)0x00800000) /*!< Channel 6 Transfer Error clear */ +#define DMA_IFCR_CGIF7 ((uint32_t)0x01000000) /*!< Channel 7 Global interrupt clear */ +#define DMA_IFCR_CTCIF7 ((uint32_t)0x02000000) /*!< Channel 7 Transfer Complete clear */ +#define DMA_IFCR_CHTIF7 ((uint32_t)0x04000000) /*!< Channel 7 Half Transfer clear */ +#define DMA_IFCR_CTEIF7 ((uint32_t)0x08000000) /*!< Channel 7 Transfer Error clear */ + +/******************* Bit definition for DMA_CCR1 register *******************/ +#define DMA_CCR1_EN ((uint16_t)0x0001) /*!< Channel enable*/ +#define DMA_CCR1_TCIE ((uint16_t)0x0002) /*!< Transfer complete interrupt enable */ +#define DMA_CCR1_HTIE ((uint16_t)0x0004) /*!< Half Transfer interrupt enable */ +#define DMA_CCR1_TEIE ((uint16_t)0x0008) /*!< Transfer error interrupt enable */ +#define DMA_CCR1_DIR ((uint16_t)0x0010) /*!< Data transfer direction */ +#define DMA_CCR1_CIRC ((uint16_t)0x0020) /*!< Circular mode */ +#define DMA_CCR1_PINC ((uint16_t)0x0040) /*!< Peripheral increment mode */ +#define DMA_CCR1_MINC ((uint16_t)0x0080) /*!< Memory increment mode */ + +#define DMA_CCR1_PSIZE ((uint16_t)0x0300) /*!< PSIZE[1:0] bits (Peripheral size) */ +#define DMA_CCR1_PSIZE_0 ((uint16_t)0x0100) /*!< Bit 0 */ +#define DMA_CCR1_PSIZE_1 ((uint16_t)0x0200) /*!< Bit 1 */ + +#define DMA_CCR1_MSIZE ((uint16_t)0x0C00) /*!< MSIZE[1:0] bits (Memory size) */ +#define DMA_CCR1_MSIZE_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define DMA_CCR1_MSIZE_1 ((uint16_t)0x0800) /*!< Bit 1 */ + +#define DMA_CCR1_PL ((uint16_t)0x3000) /*!< PL[1:0] bits(Channel Priority level) */ +#define DMA_CCR1_PL_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define DMA_CCR1_PL_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define DMA_CCR1_MEM2MEM ((uint16_t)0x4000) /*!< Memory to memory mode */ + +/******************* Bit definition for DMA_CCR2 register *******************/ +#define DMA_CCR2_EN ((uint16_t)0x0001) /*!< Channel enable */ +#define DMA_CCR2_TCIE ((uint16_t)0x0002) /*!< Transfer complete interrupt enable */ +#define DMA_CCR2_HTIE ((uint16_t)0x0004) /*!< Half Transfer interrupt enable */ +#define DMA_CCR2_TEIE ((uint16_t)0x0008) /*!< Transfer error interrupt enable */ +#define DMA_CCR2_DIR ((uint16_t)0x0010) /*!< Data transfer direction */ +#define DMA_CCR2_CIRC ((uint16_t)0x0020) /*!< Circular mode */ +#define DMA_CCR2_PINC ((uint16_t)0x0040) /*!< Peripheral increment mode */ +#define DMA_CCR2_MINC ((uint16_t)0x0080) /*!< Memory increment mode */ + +#define DMA_CCR2_PSIZE ((uint16_t)0x0300) /*!< PSIZE[1:0] bits (Peripheral size) */ +#define DMA_CCR2_PSIZE_0 ((uint16_t)0x0100) /*!< Bit 0 */ +#define DMA_CCR2_PSIZE_1 ((uint16_t)0x0200) /*!< Bit 1 */ + +#define DMA_CCR2_MSIZE ((uint16_t)0x0C00) /*!< MSIZE[1:0] bits (Memory size) */ +#define DMA_CCR2_MSIZE_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define DMA_CCR2_MSIZE_1 ((uint16_t)0x0800) /*!< Bit 1 */ + +#define DMA_CCR2_PL ((uint16_t)0x3000) /*!< PL[1:0] bits (Channel Priority level) */ +#define DMA_CCR2_PL_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define DMA_CCR2_PL_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define DMA_CCR2_MEM2MEM ((uint16_t)0x4000) /*!< Memory to memory mode */ + +/******************* Bit definition for DMA_CCR3 register *******************/ +#define DMA_CCR3_EN ((uint16_t)0x0001) /*!< Channel enable */ +#define DMA_CCR3_TCIE ((uint16_t)0x0002) /*!< Transfer complete interrupt enable */ +#define DMA_CCR3_HTIE ((uint16_t)0x0004) /*!< Half Transfer interrupt enable */ +#define DMA_CCR3_TEIE ((uint16_t)0x0008) /*!< Transfer error interrupt enable */ +#define DMA_CCR3_DIR ((uint16_t)0x0010) /*!< Data transfer direction */ +#define DMA_CCR3_CIRC ((uint16_t)0x0020) /*!< Circular mode */ +#define DMA_CCR3_PINC ((uint16_t)0x0040) /*!< Peripheral increment mode */ +#define DMA_CCR3_MINC ((uint16_t)0x0080) /*!< Memory increment mode */ + +#define DMA_CCR3_PSIZE ((uint16_t)0x0300) /*!< PSIZE[1:0] bits (Peripheral size) */ +#define DMA_CCR3_PSIZE_0 ((uint16_t)0x0100) /*!< Bit 0 */ +#define DMA_CCR3_PSIZE_1 ((uint16_t)0x0200) /*!< Bit 1 */ + +#define DMA_CCR3_MSIZE ((uint16_t)0x0C00) /*!< MSIZE[1:0] bits (Memory size) */ +#define DMA_CCR3_MSIZE_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define DMA_CCR3_MSIZE_1 ((uint16_t)0x0800) /*!< Bit 1 */ + +#define DMA_CCR3_PL ((uint16_t)0x3000) /*!< PL[1:0] bits (Channel Priority level) */ +#define DMA_CCR3_PL_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define DMA_CCR3_PL_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define DMA_CCR3_MEM2MEM ((uint16_t)0x4000) /*!< Memory to memory mode */ + +/*!<****************** Bit definition for DMA_CCR4 register *******************/ +#define DMA_CCR4_EN ((uint16_t)0x0001) /*!< Channel enable */ +#define DMA_CCR4_TCIE ((uint16_t)0x0002) /*!< Transfer complete interrupt enable */ +#define DMA_CCR4_HTIE ((uint16_t)0x0004) /*!< Half Transfer interrupt enable */ +#define DMA_CCR4_TEIE ((uint16_t)0x0008) /*!< Transfer error interrupt enable */ +#define DMA_CCR4_DIR ((uint16_t)0x0010) /*!< Data transfer direction */ +#define DMA_CCR4_CIRC ((uint16_t)0x0020) /*!< Circular mode */ +#define DMA_CCR4_PINC ((uint16_t)0x0040) /*!< Peripheral increment mode */ +#define DMA_CCR4_MINC ((uint16_t)0x0080) /*!< Memory increment mode */ + +#define DMA_CCR4_PSIZE ((uint16_t)0x0300) /*!< PSIZE[1:0] bits (Peripheral size) */ +#define DMA_CCR4_PSIZE_0 ((uint16_t)0x0100) /*!< Bit 0 */ +#define DMA_CCR4_PSIZE_1 ((uint16_t)0x0200) /*!< Bit 1 */ + +#define DMA_CCR4_MSIZE ((uint16_t)0x0C00) /*!< MSIZE[1:0] bits (Memory size) */ +#define DMA_CCR4_MSIZE_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define DMA_CCR4_MSIZE_1 ((uint16_t)0x0800) /*!< Bit 1 */ + +#define DMA_CCR4_PL ((uint16_t)0x3000) /*!< PL[1:0] bits (Channel Priority level) */ +#define DMA_CCR4_PL_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define DMA_CCR4_PL_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define DMA_CCR4_MEM2MEM ((uint16_t)0x4000) /*!< Memory to memory mode */ + +/****************** Bit definition for DMA_CCR5 register *******************/ +#define DMA_CCR5_EN ((uint16_t)0x0001) /*!< Channel enable */ +#define DMA_CCR5_TCIE ((uint16_t)0x0002) /*!< Transfer complete interrupt enable */ +#define DMA_CCR5_HTIE ((uint16_t)0x0004) /*!< Half Transfer interrupt enable */ +#define DMA_CCR5_TEIE ((uint16_t)0x0008) /*!< Transfer error interrupt enable */ +#define DMA_CCR5_DIR ((uint16_t)0x0010) /*!< Data transfer direction */ +#define DMA_CCR5_CIRC ((uint16_t)0x0020) /*!< Circular mode */ +#define DMA_CCR5_PINC ((uint16_t)0x0040) /*!< Peripheral increment mode */ +#define DMA_CCR5_MINC ((uint16_t)0x0080) /*!< Memory increment mode */ + +#define DMA_CCR5_PSIZE ((uint16_t)0x0300) /*!< PSIZE[1:0] bits (Peripheral size) */ +#define DMA_CCR5_PSIZE_0 ((uint16_t)0x0100) /*!< Bit 0 */ +#define DMA_CCR5_PSIZE_1 ((uint16_t)0x0200) /*!< Bit 1 */ + +#define DMA_CCR5_MSIZE ((uint16_t)0x0C00) /*!< MSIZE[1:0] bits (Memory size) */ +#define DMA_CCR5_MSIZE_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define DMA_CCR5_MSIZE_1 ((uint16_t)0x0800) /*!< Bit 1 */ + +#define DMA_CCR5_PL ((uint16_t)0x3000) /*!< PL[1:0] bits (Channel Priority level) */ +#define DMA_CCR5_PL_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define DMA_CCR5_PL_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define DMA_CCR5_MEM2MEM ((uint16_t)0x4000) /*!< Memory to memory mode enable */ + +/******************* Bit definition for DMA_CCR6 register *******************/ +#define DMA_CCR6_EN ((uint16_t)0x0001) /*!< Channel enable */ +#define DMA_CCR6_TCIE ((uint16_t)0x0002) /*!< Transfer complete interrupt enable */ +#define DMA_CCR6_HTIE ((uint16_t)0x0004) /*!< Half Transfer interrupt enable */ +#define DMA_CCR6_TEIE ((uint16_t)0x0008) /*!< Transfer error interrupt enable */ +#define DMA_CCR6_DIR ((uint16_t)0x0010) /*!< Data transfer direction */ +#define DMA_CCR6_CIRC ((uint16_t)0x0020) /*!< Circular mode */ +#define DMA_CCR6_PINC ((uint16_t)0x0040) /*!< Peripheral increment mode */ +#define DMA_CCR6_MINC ((uint16_t)0x0080) /*!< Memory increment mode */ + +#define DMA_CCR6_PSIZE ((uint16_t)0x0300) /*!< PSIZE[1:0] bits (Peripheral size) */ +#define DMA_CCR6_PSIZE_0 ((uint16_t)0x0100) /*!< Bit 0 */ +#define DMA_CCR6_PSIZE_1 ((uint16_t)0x0200) /*!< Bit 1 */ + +#define DMA_CCR6_MSIZE ((uint16_t)0x0C00) /*!< MSIZE[1:0] bits (Memory size) */ +#define DMA_CCR6_MSIZE_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define DMA_CCR6_MSIZE_1 ((uint16_t)0x0800) /*!< Bit 1 */ + +#define DMA_CCR6_PL ((uint16_t)0x3000) /*!< PL[1:0] bits (Channel Priority level) */ +#define DMA_CCR6_PL_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define DMA_CCR6_PL_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define DMA_CCR6_MEM2MEM ((uint16_t)0x4000) /*!< Memory to memory mode */ + +/******************* Bit definition for DMA_CCR7 register *******************/ +#define DMA_CCR7_EN ((uint16_t)0x0001) /*!< Channel enable */ +#define DMA_CCR7_TCIE ((uint16_t)0x0002) /*!< Transfer complete interrupt enable */ +#define DMA_CCR7_HTIE ((uint16_t)0x0004) /*!< Half Transfer interrupt enable */ +#define DMA_CCR7_TEIE ((uint16_t)0x0008) /*!< Transfer error interrupt enable */ +#define DMA_CCR7_DIR ((uint16_t)0x0010) /*!< Data transfer direction */ +#define DMA_CCR7_CIRC ((uint16_t)0x0020) /*!< Circular mode */ +#define DMA_CCR7_PINC ((uint16_t)0x0040) /*!< Peripheral increment mode */ +#define DMA_CCR7_MINC ((uint16_t)0x0080) /*!< Memory increment mode */ + +#define DMA_CCR7_PSIZE , ((uint16_t)0x0300) /*!< PSIZE[1:0] bits (Peripheral size) */ +#define DMA_CCR7_PSIZE_0 ((uint16_t)0x0100) /*!< Bit 0 */ +#define DMA_CCR7_PSIZE_1 ((uint16_t)0x0200) /*!< Bit 1 */ + +#define DMA_CCR7_MSIZE ((uint16_t)0x0C00) /*!< MSIZE[1:0] bits (Memory size) */ +#define DMA_CCR7_MSIZE_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define DMA_CCR7_MSIZE_1 ((uint16_t)0x0800) /*!< Bit 1 */ + +#define DMA_CCR7_PL ((uint16_t)0x3000) /*!< PL[1:0] bits (Channel Priority level) */ +#define DMA_CCR7_PL_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define DMA_CCR7_PL_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define DMA_CCR7_MEM2MEM ((uint16_t)0x4000) /*!< Memory to memory mode enable */ + +/****************** Bit definition for DMA_CNDTR1 register ******************/ +#define DMA_CNDTR1_NDT ((uint16_t)0xFFFF) /*!< Number of data to Transfer */ + +/****************** Bit definition for DMA_CNDTR2 register ******************/ +#define DMA_CNDTR2_NDT ((uint16_t)0xFFFF) /*!< Number of data to Transfer */ + +/****************** Bit definition for DMA_CNDTR3 register ******************/ +#define DMA_CNDTR3_NDT ((uint16_t)0xFFFF) /*!< Number of data to Transfer */ + +/****************** Bit definition for DMA_CNDTR4 register ******************/ +#define DMA_CNDTR4_NDT ((uint16_t)0xFFFF) /*!< Number of data to Transfer */ + +/****************** Bit definition for DMA_CNDTR5 register ******************/ +#define DMA_CNDTR5_NDT ((uint16_t)0xFFFF) /*!< Number of data to Transfer */ + +/****************** Bit definition for DMA_CNDTR6 register ******************/ +#define DMA_CNDTR6_NDT ((uint16_t)0xFFFF) /*!< Number of data to Transfer */ + +/****************** Bit definition for DMA_CNDTR7 register ******************/ +#define DMA_CNDTR7_NDT ((uint16_t)0xFFFF) /*!< Number of data to Transfer */ + +/****************** Bit definition for DMA_CPAR1 register *******************/ +#define DMA_CPAR1_PA ((uint32_t)0xFFFFFFFF) /*!< Peripheral Address */ + +/****************** Bit definition for DMA_CPAR2 register *******************/ +#define DMA_CPAR2_PA ((uint32_t)0xFFFFFFFF) /*!< Peripheral Address */ + +/****************** Bit definition for DMA_CPAR3 register *******************/ +#define DMA_CPAR3_PA ((uint32_t)0xFFFFFFFF) /*!< Peripheral Address */ + + +/****************** Bit definition for DMA_CPAR4 register *******************/ +#define DMA_CPAR4_PA ((uint32_t)0xFFFFFFFF) /*!< Peripheral Address */ + +/****************** Bit definition for DMA_CPAR5 register *******************/ +#define DMA_CPAR5_PA ((uint32_t)0xFFFFFFFF) /*!< Peripheral Address */ + +/****************** Bit definition for DMA_CPAR6 register *******************/ +#define DMA_CPAR6_PA ((uint32_t)0xFFFFFFFF) /*!< Peripheral Address */ + + +/****************** Bit definition for DMA_CPAR7 register *******************/ +#define DMA_CPAR7_PA ((uint32_t)0xFFFFFFFF) /*!< Peripheral Address */ + +/****************** Bit definition for DMA_CMAR1 register *******************/ +#define DMA_CMAR1_MA ((uint32_t)0xFFFFFFFF) /*!< Memory Address */ + +/****************** Bit definition for DMA_CMAR2 register *******************/ +#define DMA_CMAR2_MA ((uint32_t)0xFFFFFFFF) /*!< Memory Address */ + +/****************** Bit definition for DMA_CMAR3 register *******************/ +#define DMA_CMAR3_MA ((uint32_t)0xFFFFFFFF) /*!< Memory Address */ + + +/****************** Bit definition for DMA_CMAR4 register *******************/ +#define DMA_CMAR4_MA ((uint32_t)0xFFFFFFFF) /*!< Memory Address */ + +/****************** Bit definition for DMA_CMAR5 register *******************/ +#define DMA_CMAR5_MA ((uint32_t)0xFFFFFFFF) /*!< Memory Address */ + +/****************** Bit definition for DMA_CMAR6 register *******************/ +#define DMA_CMAR6_MA ((uint32_t)0xFFFFFFFF) /*!< Memory Address */ + +/****************** Bit definition for DMA_CMAR7 register *******************/ +#define DMA_CMAR7_MA ((uint32_t)0xFFFFFFFF) /*!< Memory Address */ + +/******************************************************************************/ +/* */ +/* Analog to Digital Converter */ +/* */ +/******************************************************************************/ + +/******************** Bit definition for ADC_SR register ********************/ +#define ADC_SR_AWD ((uint8_t)0x01) /*!< Analog watchdog flag */ +#define ADC_SR_EOC ((uint8_t)0x02) /*!< End of conversion */ +#define ADC_SR_JEOC ((uint8_t)0x04) /*!< Injected channel end of conversion */ +#define ADC_SR_JSTRT ((uint8_t)0x08) /*!< Injected channel Start flag */ +#define ADC_SR_STRT ((uint8_t)0x10) /*!< Regular channel Start flag */ + +/******************* Bit definition for ADC_CR1 register ********************/ +#define ADC_CR1_AWDCH ((uint32_t)0x0000001F) /*!< AWDCH[4:0] bits (Analog watchdog channel select bits) */ +#define ADC_CR1_AWDCH_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define ADC_CR1_AWDCH_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define ADC_CR1_AWDCH_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define ADC_CR1_AWDCH_3 ((uint32_t)0x00000008) /*!< Bit 3 */ +#define ADC_CR1_AWDCH_4 ((uint32_t)0x00000010) /*!< Bit 4 */ + +#define ADC_CR1_EOCIE ((uint32_t)0x00000020) /*!< Interrupt enable for EOC */ +#define ADC_CR1_AWDIE ((uint32_t)0x00000040) /*!< Analog Watchdog interrupt enable */ +#define ADC_CR1_JEOCIE ((uint32_t)0x00000080) /*!< Interrupt enable for injected channels */ +#define ADC_CR1_SCAN ((uint32_t)0x00000100) /*!< Scan mode */ +#define ADC_CR1_AWDSGL ((uint32_t)0x00000200) /*!< Enable the watchdog on a single channel in scan mode */ +#define ADC_CR1_JAUTO ((uint32_t)0x00000400) /*!< Automatic injected group conversion */ +#define ADC_CR1_DISCEN ((uint32_t)0x00000800) /*!< Discontinuous mode on regular channels */ +#define ADC_CR1_JDISCEN ((uint32_t)0x00001000) /*!< Discontinuous mode on injected channels */ + +#define ADC_CR1_DISCNUM ((uint32_t)0x0000E000) /*!< DISCNUM[2:0] bits (Discontinuous mode channel count) */ +#define ADC_CR1_DISCNUM_0 ((uint32_t)0x00002000) /*!< Bit 0 */ +#define ADC_CR1_DISCNUM_1 ((uint32_t)0x00004000) /*!< Bit 1 */ +#define ADC_CR1_DISCNUM_2 ((uint32_t)0x00008000) /*!< Bit 2 */ + +#define ADC_CR1_DUALMOD ((uint32_t)0x000F0000) /*!< DUALMOD[3:0] bits (Dual mode selection) */ +#define ADC_CR1_DUALMOD_0 ((uint32_t)0x00010000) /*!< Bit 0 */ +#define ADC_CR1_DUALMOD_1 ((uint32_t)0x00020000) /*!< Bit 1 */ +#define ADC_CR1_DUALMOD_2 ((uint32_t)0x00040000) /*!< Bit 2 */ +#define ADC_CR1_DUALMOD_3 ((uint32_t)0x00080000) /*!< Bit 3 */ + +#define ADC_CR1_JAWDEN ((uint32_t)0x00400000) /*!< Analog watchdog enable on injected channels */ +#define ADC_CR1_AWDEN ((uint32_t)0x00800000) /*!< Analog watchdog enable on regular channels */ + + +/******************* Bit definition for ADC_CR2 register ********************/ +#define ADC_CR2_ADON ((uint32_t)0x00000001) /*!< A/D Converter ON / OFF */ +#define ADC_CR2_CONT ((uint32_t)0x00000002) /*!< Continuous Conversion */ +#define ADC_CR2_CAL ((uint32_t)0x00000004) /*!< A/D Calibration */ +#define ADC_CR2_RSTCAL ((uint32_t)0x00000008) /*!< Reset Calibration */ +#define ADC_CR2_DMA ((uint32_t)0x00000100) /*!< Direct Memory access mode */ +#define ADC_CR2_ALIGN ((uint32_t)0x00000800) /*!< Data Alignment */ + +#define ADC_CR2_JEXTSEL ((uint32_t)0x00007000) /*!< JEXTSEL[2:0] bits (External event select for injected group) */ +#define ADC_CR2_JEXTSEL_0 ((uint32_t)0x00001000) /*!< Bit 0 */ +#define ADC_CR2_JEXTSEL_1 ((uint32_t)0x00002000) /*!< Bit 1 */ +#define ADC_CR2_JEXTSEL_2 ((uint32_t)0x00004000) /*!< Bit 2 */ + +#define ADC_CR2_JEXTTRIG ((uint32_t)0x00008000) /*!< External Trigger Conversion mode for injected channels */ + +#define ADC_CR2_EXTSEL ((uint32_t)0x000E0000) /*!< EXTSEL[2:0] bits (External Event Select for regular group) */ +#define ADC_CR2_EXTSEL_0 ((uint32_t)0x00020000) /*!< Bit 0 */ +#define ADC_CR2_EXTSEL_1 ((uint32_t)0x00040000) /*!< Bit 1 */ +#define ADC_CR2_EXTSEL_2 ((uint32_t)0x00080000) /*!< Bit 2 */ + +#define ADC_CR2_EXTTRIG ((uint32_t)0x00100000) /*!< External Trigger Conversion mode for regular channels */ +#define ADC_CR2_JSWSTART ((uint32_t)0x00200000) /*!< Start Conversion of injected channels */ +#define ADC_CR2_SWSTART ((uint32_t)0x00400000) /*!< Start Conversion of regular channels */ +#define ADC_CR2_TSVREFE ((uint32_t)0x00800000) /*!< Temperature Sensor and VREFINT Enable */ + +/****************** Bit definition for ADC_SMPR1 register *******************/ +#define ADC_SMPR1_SMP10 ((uint32_t)0x00000007) /*!< SMP10[2:0] bits (Channel 10 Sample time selection) */ +#define ADC_SMPR1_SMP10_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define ADC_SMPR1_SMP10_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define ADC_SMPR1_SMP10_2 ((uint32_t)0x00000004) /*!< Bit 2 */ + +#define ADC_SMPR1_SMP11 ((uint32_t)0x00000038) /*!< SMP11[2:0] bits (Channel 11 Sample time selection) */ +#define ADC_SMPR1_SMP11_0 ((uint32_t)0x00000008) /*!< Bit 0 */ +#define ADC_SMPR1_SMP11_1 ((uint32_t)0x00000010) /*!< Bit 1 */ +#define ADC_SMPR1_SMP11_2 ((uint32_t)0x00000020) /*!< Bit 2 */ + +#define ADC_SMPR1_SMP12 ((uint32_t)0x000001C0) /*!< SMP12[2:0] bits (Channel 12 Sample time selection) */ +#define ADC_SMPR1_SMP12_0 ((uint32_t)0x00000040) /*!< Bit 0 */ +#define ADC_SMPR1_SMP12_1 ((uint32_t)0x00000080) /*!< Bit 1 */ +#define ADC_SMPR1_SMP12_2 ((uint32_t)0x00000100) /*!< Bit 2 */ + +#define ADC_SMPR1_SMP13 ((uint32_t)0x00000E00) /*!< SMP13[2:0] bits (Channel 13 Sample time selection) */ +#define ADC_SMPR1_SMP13_0 ((uint32_t)0x00000200) /*!< Bit 0 */ +#define ADC_SMPR1_SMP13_1 ((uint32_t)0x00000400) /*!< Bit 1 */ +#define ADC_SMPR1_SMP13_2 ((uint32_t)0x00000800) /*!< Bit 2 */ + +#define ADC_SMPR1_SMP14 ((uint32_t)0x00007000) /*!< SMP14[2:0] bits (Channel 14 Sample time selection) */ +#define ADC_SMPR1_SMP14_0 ((uint32_t)0x00001000) /*!< Bit 0 */ +#define ADC_SMPR1_SMP14_1 ((uint32_t)0x00002000) /*!< Bit 1 */ +#define ADC_SMPR1_SMP14_2 ((uint32_t)0x00004000) /*!< Bit 2 */ + +#define ADC_SMPR1_SMP15 ((uint32_t)0x00038000) /*!< SMP15[2:0] bits (Channel 15 Sample time selection) */ +#define ADC_SMPR1_SMP15_0 ((uint32_t)0x00008000) /*!< Bit 0 */ +#define ADC_SMPR1_SMP15_1 ((uint32_t)0x00010000) /*!< Bit 1 */ +#define ADC_SMPR1_SMP15_2 ((uint32_t)0x00020000) /*!< Bit 2 */ + +#define ADC_SMPR1_SMP16 ((uint32_t)0x001C0000) /*!< SMP16[2:0] bits (Channel 16 Sample time selection) */ +#define ADC_SMPR1_SMP16_0 ((uint32_t)0x00040000) /*!< Bit 0 */ +#define ADC_SMPR1_SMP16_1 ((uint32_t)0x00080000) /*!< Bit 1 */ +#define ADC_SMPR1_SMP16_2 ((uint32_t)0x00100000) /*!< Bit 2 */ + +#define ADC_SMPR1_SMP17 ((uint32_t)0x00E00000) /*!< SMP17[2:0] bits (Channel 17 Sample time selection) */ +#define ADC_SMPR1_SMP17_0 ((uint32_t)0x00200000) /*!< Bit 0 */ +#define ADC_SMPR1_SMP17_1 ((uint32_t)0x00400000) /*!< Bit 1 */ +#define ADC_SMPR1_SMP17_2 ((uint32_t)0x00800000) /*!< Bit 2 */ + +/****************** Bit definition for ADC_SMPR2 register *******************/ +#define ADC_SMPR2_SMP0 ((uint32_t)0x00000007) /*!< SMP0[2:0] bits (Channel 0 Sample time selection) */ +#define ADC_SMPR2_SMP0_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define ADC_SMPR2_SMP0_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define ADC_SMPR2_SMP0_2 ((uint32_t)0x00000004) /*!< Bit 2 */ + +#define ADC_SMPR2_SMP1 ((uint32_t)0x00000038) /*!< SMP1[2:0] bits (Channel 1 Sample time selection) */ +#define ADC_SMPR2_SMP1_0 ((uint32_t)0x00000008) /*!< Bit 0 */ +#define ADC_SMPR2_SMP1_1 ((uint32_t)0x00000010) /*!< Bit 1 */ +#define ADC_SMPR2_SMP1_2 ((uint32_t)0x00000020) /*!< Bit 2 */ + +#define ADC_SMPR2_SMP2 ((uint32_t)0x000001C0) /*!< SMP2[2:0] bits (Channel 2 Sample time selection) */ +#define ADC_SMPR2_SMP2_0 ((uint32_t)0x00000040) /*!< Bit 0 */ +#define ADC_SMPR2_SMP2_1 ((uint32_t)0x00000080) /*!< Bit 1 */ +#define ADC_SMPR2_SMP2_2 ((uint32_t)0x00000100) /*!< Bit 2 */ + +#define ADC_SMPR2_SMP3 ((uint32_t)0x00000E00) /*!< SMP3[2:0] bits (Channel 3 Sample time selection) */ +#define ADC_SMPR2_SMP3_0 ((uint32_t)0x00000200) /*!< Bit 0 */ +#define ADC_SMPR2_SMP3_1 ((uint32_t)0x00000400) /*!< Bit 1 */ +#define ADC_SMPR2_SMP3_2 ((uint32_t)0x00000800) /*!< Bit 2 */ + +#define ADC_SMPR2_SMP4 ((uint32_t)0x00007000) /*!< SMP4[2:0] bits (Channel 4 Sample time selection) */ +#define ADC_SMPR2_SMP4_0 ((uint32_t)0x00001000) /*!< Bit 0 */ +#define ADC_SMPR2_SMP4_1 ((uint32_t)0x00002000) /*!< Bit 1 */ +#define ADC_SMPR2_SMP4_2 ((uint32_t)0x00004000) /*!< Bit 2 */ + +#define ADC_SMPR2_SMP5 ((uint32_t)0x00038000) /*!< SMP5[2:0] bits (Channel 5 Sample time selection) */ +#define ADC_SMPR2_SMP5_0 ((uint32_t)0x00008000) /*!< Bit 0 */ +#define ADC_SMPR2_SMP5_1 ((uint32_t)0x00010000) /*!< Bit 1 */ +#define ADC_SMPR2_SMP5_2 ((uint32_t)0x00020000) /*!< Bit 2 */ + +#define ADC_SMPR2_SMP6 ((uint32_t)0x001C0000) /*!< SMP6[2:0] bits (Channel 6 Sample time selection) */ +#define ADC_SMPR2_SMP6_0 ((uint32_t)0x00040000) /*!< Bit 0 */ +#define ADC_SMPR2_SMP6_1 ((uint32_t)0x00080000) /*!< Bit 1 */ +#define ADC_SMPR2_SMP6_2 ((uint32_t)0x00100000) /*!< Bit 2 */ + +#define ADC_SMPR2_SMP7 ((uint32_t)0x00E00000) /*!< SMP7[2:0] bits (Channel 7 Sample time selection) */ +#define ADC_SMPR2_SMP7_0 ((uint32_t)0x00200000) /*!< Bit 0 */ +#define ADC_SMPR2_SMP7_1 ((uint32_t)0x00400000) /*!< Bit 1 */ +#define ADC_SMPR2_SMP7_2 ((uint32_t)0x00800000) /*!< Bit 2 */ + +#define ADC_SMPR2_SMP8 ((uint32_t)0x07000000) /*!< SMP8[2:0] bits (Channel 8 Sample time selection) */ +#define ADC_SMPR2_SMP8_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define ADC_SMPR2_SMP8_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define ADC_SMPR2_SMP8_2 ((uint32_t)0x04000000) /*!< Bit 2 */ + +#define ADC_SMPR2_SMP9 ((uint32_t)0x38000000) /*!< SMP9[2:0] bits (Channel 9 Sample time selection) */ +#define ADC_SMPR2_SMP9_0 ((uint32_t)0x08000000) /*!< Bit 0 */ +#define ADC_SMPR2_SMP9_1 ((uint32_t)0x10000000) /*!< Bit 1 */ +#define ADC_SMPR2_SMP9_2 ((uint32_t)0x20000000) /*!< Bit 2 */ + +/****************** Bit definition for ADC_JOFR1 register *******************/ +#define ADC_JOFR1_JOFFSET1 ((uint16_t)0x0FFF) /*!< Data offset for injected channel 1 */ + +/****************** Bit definition for ADC_JOFR2 register *******************/ +#define ADC_JOFR2_JOFFSET2 ((uint16_t)0x0FFF) /*!< Data offset for injected channel 2 */ + +/****************** Bit definition for ADC_JOFR3 register *******************/ +#define ADC_JOFR3_JOFFSET3 ((uint16_t)0x0FFF) /*!< Data offset for injected channel 3 */ + +/****************** Bit definition for ADC_JOFR4 register *******************/ +#define ADC_JOFR4_JOFFSET4 ((uint16_t)0x0FFF) /*!< Data offset for injected channel 4 */ + +/******************* Bit definition for ADC_HTR register ********************/ +#define ADC_HTR_HT ((uint16_t)0x0FFF) /*!< Analog watchdog high threshold */ + +/******************* Bit definition for ADC_LTR register ********************/ +#define ADC_LTR_LT ((uint16_t)0x0FFF) /*!< Analog watchdog low threshold */ + +/******************* Bit definition for ADC_SQR1 register *******************/ +#define ADC_SQR1_SQ13 ((uint32_t)0x0000001F) /*!< SQ13[4:0] bits (13th conversion in regular sequence) */ +#define ADC_SQR1_SQ13_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define ADC_SQR1_SQ13_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define ADC_SQR1_SQ13_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define ADC_SQR1_SQ13_3 ((uint32_t)0x00000008) /*!< Bit 3 */ +#define ADC_SQR1_SQ13_4 ((uint32_t)0x00000010) /*!< Bit 4 */ + +#define ADC_SQR1_SQ14 ((uint32_t)0x000003E0) /*!< SQ14[4:0] bits (14th conversion in regular sequence) */ +#define ADC_SQR1_SQ14_0 ((uint32_t)0x00000020) /*!< Bit 0 */ +#define ADC_SQR1_SQ14_1 ((uint32_t)0x00000040) /*!< Bit 1 */ +#define ADC_SQR1_SQ14_2 ((uint32_t)0x00000080) /*!< Bit 2 */ +#define ADC_SQR1_SQ14_3 ((uint32_t)0x00000100) /*!< Bit 3 */ +#define ADC_SQR1_SQ14_4 ((uint32_t)0x00000200) /*!< Bit 4 */ + +#define ADC_SQR1_SQ15 ((uint32_t)0x00007C00) /*!< SQ15[4:0] bits (15th conversion in regular sequence) */ +#define ADC_SQR1_SQ15_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define ADC_SQR1_SQ15_1 ((uint32_t)0x00000800) /*!< Bit 1 */ +#define ADC_SQR1_SQ15_2 ((uint32_t)0x00001000) /*!< Bit 2 */ +#define ADC_SQR1_SQ15_3 ((uint32_t)0x00002000) /*!< Bit 3 */ +#define ADC_SQR1_SQ15_4 ((uint32_t)0x00004000) /*!< Bit 4 */ + +#define ADC_SQR1_SQ16 ((uint32_t)0x000F8000) /*!< SQ16[4:0] bits (16th conversion in regular sequence) */ +#define ADC_SQR1_SQ16_0 ((uint32_t)0x00008000) /*!< Bit 0 */ +#define ADC_SQR1_SQ16_1 ((uint32_t)0x00010000) /*!< Bit 1 */ +#define ADC_SQR1_SQ16_2 ((uint32_t)0x00020000) /*!< Bit 2 */ +#define ADC_SQR1_SQ16_3 ((uint32_t)0x00040000) /*!< Bit 3 */ +#define ADC_SQR1_SQ16_4 ((uint32_t)0x00080000) /*!< Bit 4 */ + +#define ADC_SQR1_L ((uint32_t)0x00F00000) /*!< L[3:0] bits (Regular channel sequence length) */ +#define ADC_SQR1_L_0 ((uint32_t)0x00100000) /*!< Bit 0 */ +#define ADC_SQR1_L_1 ((uint32_t)0x00200000) /*!< Bit 1 */ +#define ADC_SQR1_L_2 ((uint32_t)0x00400000) /*!< Bit 2 */ +#define ADC_SQR1_L_3 ((uint32_t)0x00800000) /*!< Bit 3 */ + +/******************* Bit definition for ADC_SQR2 register *******************/ +#define ADC_SQR2_SQ7 ((uint32_t)0x0000001F) /*!< SQ7[4:0] bits (7th conversion in regular sequence) */ +#define ADC_SQR2_SQ7_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define ADC_SQR2_SQ7_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define ADC_SQR2_SQ7_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define ADC_SQR2_SQ7_3 ((uint32_t)0x00000008) /*!< Bit 3 */ +#define ADC_SQR2_SQ7_4 ((uint32_t)0x00000010) /*!< Bit 4 */ + +#define ADC_SQR2_SQ8 ((uint32_t)0x000003E0) /*!< SQ8[4:0] bits (8th conversion in regular sequence) */ +#define ADC_SQR2_SQ8_0 ((uint32_t)0x00000020) /*!< Bit 0 */ +#define ADC_SQR2_SQ8_1 ((uint32_t)0x00000040) /*!< Bit 1 */ +#define ADC_SQR2_SQ8_2 ((uint32_t)0x00000080) /*!< Bit 2 */ +#define ADC_SQR2_SQ8_3 ((uint32_t)0x00000100) /*!< Bit 3 */ +#define ADC_SQR2_SQ8_4 ((uint32_t)0x00000200) /*!< Bit 4 */ + +#define ADC_SQR2_SQ9 ((uint32_t)0x00007C00) /*!< SQ9[4:0] bits (9th conversion in regular sequence) */ +#define ADC_SQR2_SQ9_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define ADC_SQR2_SQ9_1 ((uint32_t)0x00000800) /*!< Bit 1 */ +#define ADC_SQR2_SQ9_2 ((uint32_t)0x00001000) /*!< Bit 2 */ +#define ADC_SQR2_SQ9_3 ((uint32_t)0x00002000) /*!< Bit 3 */ +#define ADC_SQR2_SQ9_4 ((uint32_t)0x00004000) /*!< Bit 4 */ + +#define ADC_SQR2_SQ10 ((uint32_t)0x000F8000) /*!< SQ10[4:0] bits (10th conversion in regular sequence) */ +#define ADC_SQR2_SQ10_0 ((uint32_t)0x00008000) /*!< Bit 0 */ +#define ADC_SQR2_SQ10_1 ((uint32_t)0x00010000) /*!< Bit 1 */ +#define ADC_SQR2_SQ10_2 ((uint32_t)0x00020000) /*!< Bit 2 */ +#define ADC_SQR2_SQ10_3 ((uint32_t)0x00040000) /*!< Bit 3 */ +#define ADC_SQR2_SQ10_4 ((uint32_t)0x00080000) /*!< Bit 4 */ + +#define ADC_SQR2_SQ11 ((uint32_t)0x01F00000) /*!< SQ11[4:0] bits (11th conversion in regular sequence) */ +#define ADC_SQR2_SQ11_0 ((uint32_t)0x00100000) /*!< Bit 0 */ +#define ADC_SQR2_SQ11_1 ((uint32_t)0x00200000) /*!< Bit 1 */ +#define ADC_SQR2_SQ11_2 ((uint32_t)0x00400000) /*!< Bit 2 */ +#define ADC_SQR2_SQ11_3 ((uint32_t)0x00800000) /*!< Bit 3 */ +#define ADC_SQR2_SQ11_4 ((uint32_t)0x01000000) /*!< Bit 4 */ + +#define ADC_SQR2_SQ12 ((uint32_t)0x3E000000) /*!< SQ12[4:0] bits (12th conversion in regular sequence) */ +#define ADC_SQR2_SQ12_0 ((uint32_t)0x02000000) /*!< Bit 0 */ +#define ADC_SQR2_SQ12_1 ((uint32_t)0x04000000) /*!< Bit 1 */ +#define ADC_SQR2_SQ12_2 ((uint32_t)0x08000000) /*!< Bit 2 */ +#define ADC_SQR2_SQ12_3 ((uint32_t)0x10000000) /*!< Bit 3 */ +#define ADC_SQR2_SQ12_4 ((uint32_t)0x20000000) /*!< Bit 4 */ + +/******************* Bit definition for ADC_SQR3 register *******************/ +#define ADC_SQR3_SQ1 ((uint32_t)0x0000001F) /*!< SQ1[4:0] bits (1st conversion in regular sequence) */ +#define ADC_SQR3_SQ1_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define ADC_SQR3_SQ1_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define ADC_SQR3_SQ1_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define ADC_SQR3_SQ1_3 ((uint32_t)0x00000008) /*!< Bit 3 */ +#define ADC_SQR3_SQ1_4 ((uint32_t)0x00000010) /*!< Bit 4 */ + +#define ADC_SQR3_SQ2 ((uint32_t)0x000003E0) /*!< SQ2[4:0] bits (2nd conversion in regular sequence) */ +#define ADC_SQR3_SQ2_0 ((uint32_t)0x00000020) /*!< Bit 0 */ +#define ADC_SQR3_SQ2_1 ((uint32_t)0x00000040) /*!< Bit 1 */ +#define ADC_SQR3_SQ2_2 ((uint32_t)0x00000080) /*!< Bit 2 */ +#define ADC_SQR3_SQ2_3 ((uint32_t)0x00000100) /*!< Bit 3 */ +#define ADC_SQR3_SQ2_4 ((uint32_t)0x00000200) /*!< Bit 4 */ + +#define ADC_SQR3_SQ3 ((uint32_t)0x00007C00) /*!< SQ3[4:0] bits (3rd conversion in regular sequence) */ +#define ADC_SQR3_SQ3_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define ADC_SQR3_SQ3_1 ((uint32_t)0x00000800) /*!< Bit 1 */ +#define ADC_SQR3_SQ3_2 ((uint32_t)0x00001000) /*!< Bit 2 */ +#define ADC_SQR3_SQ3_3 ((uint32_t)0x00002000) /*!< Bit 3 */ +#define ADC_SQR3_SQ3_4 ((uint32_t)0x00004000) /*!< Bit 4 */ + +#define ADC_SQR3_SQ4 ((uint32_t)0x000F8000) /*!< SQ4[4:0] bits (4th conversion in regular sequence) */ +#define ADC_SQR3_SQ4_0 ((uint32_t)0x00008000) /*!< Bit 0 */ +#define ADC_SQR3_SQ4_1 ((uint32_t)0x00010000) /*!< Bit 1 */ +#define ADC_SQR3_SQ4_2 ((uint32_t)0x00020000) /*!< Bit 2 */ +#define ADC_SQR3_SQ4_3 ((uint32_t)0x00040000) /*!< Bit 3 */ +#define ADC_SQR3_SQ4_4 ((uint32_t)0x00080000) /*!< Bit 4 */ + +#define ADC_SQR3_SQ5 ((uint32_t)0x01F00000) /*!< SQ5[4:0] bits (5th conversion in regular sequence) */ +#define ADC_SQR3_SQ5_0 ((uint32_t)0x00100000) /*!< Bit 0 */ +#define ADC_SQR3_SQ5_1 ((uint32_t)0x00200000) /*!< Bit 1 */ +#define ADC_SQR3_SQ5_2 ((uint32_t)0x00400000) /*!< Bit 2 */ +#define ADC_SQR3_SQ5_3 ((uint32_t)0x00800000) /*!< Bit 3 */ +#define ADC_SQR3_SQ5_4 ((uint32_t)0x01000000) /*!< Bit 4 */ + +#define ADC_SQR3_SQ6 ((uint32_t)0x3E000000) /*!< SQ6[4:0] bits (6th conversion in regular sequence) */ +#define ADC_SQR3_SQ6_0 ((uint32_t)0x02000000) /*!< Bit 0 */ +#define ADC_SQR3_SQ6_1 ((uint32_t)0x04000000) /*!< Bit 1 */ +#define ADC_SQR3_SQ6_2 ((uint32_t)0x08000000) /*!< Bit 2 */ +#define ADC_SQR3_SQ6_3 ((uint32_t)0x10000000) /*!< Bit 3 */ +#define ADC_SQR3_SQ6_4 ((uint32_t)0x20000000) /*!< Bit 4 */ + +/******************* Bit definition for ADC_JSQR register *******************/ +#define ADC_JSQR_JSQ1 ((uint32_t)0x0000001F) /*!< JSQ1[4:0] bits (1st conversion in injected sequence) */ +#define ADC_JSQR_JSQ1_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define ADC_JSQR_JSQ1_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define ADC_JSQR_JSQ1_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define ADC_JSQR_JSQ1_3 ((uint32_t)0x00000008) /*!< Bit 3 */ +#define ADC_JSQR_JSQ1_4 ((uint32_t)0x00000010) /*!< Bit 4 */ + +#define ADC_JSQR_JSQ2 ((uint32_t)0x000003E0) /*!< JSQ2[4:0] bits (2nd conversion in injected sequence) */ +#define ADC_JSQR_JSQ2_0 ((uint32_t)0x00000020) /*!< Bit 0 */ +#define ADC_JSQR_JSQ2_1 ((uint32_t)0x00000040) /*!< Bit 1 */ +#define ADC_JSQR_JSQ2_2 ((uint32_t)0x00000080) /*!< Bit 2 */ +#define ADC_JSQR_JSQ2_3 ((uint32_t)0x00000100) /*!< Bit 3 */ +#define ADC_JSQR_JSQ2_4 ((uint32_t)0x00000200) /*!< Bit 4 */ + +#define ADC_JSQR_JSQ3 ((uint32_t)0x00007C00) /*!< JSQ3[4:0] bits (3rd conversion in injected sequence) */ +#define ADC_JSQR_JSQ3_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define ADC_JSQR_JSQ3_1 ((uint32_t)0x00000800) /*!< Bit 1 */ +#define ADC_JSQR_JSQ3_2 ((uint32_t)0x00001000) /*!< Bit 2 */ +#define ADC_JSQR_JSQ3_3 ((uint32_t)0x00002000) /*!< Bit 3 */ +#define ADC_JSQR_JSQ3_4 ((uint32_t)0x00004000) /*!< Bit 4 */ + +#define ADC_JSQR_JSQ4 ((uint32_t)0x000F8000) /*!< JSQ4[4:0] bits (4th conversion in injected sequence) */ +#define ADC_JSQR_JSQ4_0 ((uint32_t)0x00008000) /*!< Bit 0 */ +#define ADC_JSQR_JSQ4_1 ((uint32_t)0x00010000) /*!< Bit 1 */ +#define ADC_JSQR_JSQ4_2 ((uint32_t)0x00020000) /*!< Bit 2 */ +#define ADC_JSQR_JSQ4_3 ((uint32_t)0x00040000) /*!< Bit 3 */ +#define ADC_JSQR_JSQ4_4 ((uint32_t)0x00080000) /*!< Bit 4 */ + +#define ADC_JSQR_JL ((uint32_t)0x00300000) /*!< JL[1:0] bits (Injected Sequence length) */ +#define ADC_JSQR_JL_0 ((uint32_t)0x00100000) /*!< Bit 0 */ +#define ADC_JSQR_JL_1 ((uint32_t)0x00200000) /*!< Bit 1 */ + +/******************* Bit definition for ADC_JDR1 register *******************/ +#define ADC_JDR1_JDATA ((uint16_t)0xFFFF) /*!< Injected data */ + +/******************* Bit definition for ADC_JDR2 register *******************/ +#define ADC_JDR2_JDATA ((uint16_t)0xFFFF) /*!< Injected data */ + +/******************* Bit definition for ADC_JDR3 register *******************/ +#define ADC_JDR3_JDATA ((uint16_t)0xFFFF) /*!< Injected data */ + +/******************* Bit definition for ADC_JDR4 register *******************/ +#define ADC_JDR4_JDATA ((uint16_t)0xFFFF) /*!< Injected data */ + +/******************** Bit definition for ADC_DR register ********************/ +#define ADC_DR_DATA ((uint32_t)0x0000FFFF) /*!< Regular data */ +#define ADC_DR_ADC2DATA ((uint32_t)0xFFFF0000) /*!< ADC2 data */ + +/******************************************************************************/ +/* */ +/* Digital to Analog Converter */ +/* */ +/******************************************************************************/ + +/******************** Bit definition for DAC_CR register ********************/ +#define DAC_CR_EN1 ((uint32_t)0x00000001) /*!< DAC channel1 enable */ +#define DAC_CR_BOFF1 ((uint32_t)0x00000002) /*!< DAC channel1 output buffer disable */ +#define DAC_CR_TEN1 ((uint32_t)0x00000004) /*!< DAC channel1 Trigger enable */ + +#define DAC_CR_TSEL1 ((uint32_t)0x00000038) /*!< TSEL1[2:0] (DAC channel1 Trigger selection) */ +#define DAC_CR_TSEL1_0 ((uint32_t)0x00000008) /*!< Bit 0 */ +#define DAC_CR_TSEL1_1 ((uint32_t)0x00000010) /*!< Bit 1 */ +#define DAC_CR_TSEL1_2 ((uint32_t)0x00000020) /*!< Bit 2 */ + +#define DAC_CR_WAVE1 ((uint32_t)0x000000C0) /*!< WAVE1[1:0] (DAC channel1 noise/triangle wave generation enable) */ +#define DAC_CR_WAVE1_0 ((uint32_t)0x00000040) /*!< Bit 0 */ +#define DAC_CR_WAVE1_1 ((uint32_t)0x00000080) /*!< Bit 1 */ + +#define DAC_CR_MAMP1 ((uint32_t)0x00000F00) /*!< MAMP1[3:0] (DAC channel1 Mask/Amplitude selector) */ +#define DAC_CR_MAMP1_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define DAC_CR_MAMP1_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define DAC_CR_MAMP1_2 ((uint32_t)0x00000400) /*!< Bit 2 */ +#define DAC_CR_MAMP1_3 ((uint32_t)0x00000800) /*!< Bit 3 */ + +#define DAC_CR_DMAEN1 ((uint32_t)0x00001000) /*!< DAC channel1 DMA enable */ +#define DAC_CR_EN2 ((uint32_t)0x00010000) /*!< DAC channel2 enable */ +#define DAC_CR_BOFF2 ((uint32_t)0x00020000) /*!< DAC channel2 output buffer disable */ +#define DAC_CR_TEN2 ((uint32_t)0x00040000) /*!< DAC channel2 Trigger enable */ + +#define DAC_CR_TSEL2 ((uint32_t)0x00380000) /*!< TSEL2[2:0] (DAC channel2 Trigger selection) */ +#define DAC_CR_TSEL2_0 ((uint32_t)0x00080000) /*!< Bit 0 */ +#define DAC_CR_TSEL2_1 ((uint32_t)0x00100000) /*!< Bit 1 */ +#define DAC_CR_TSEL2_2 ((uint32_t)0x00200000) /*!< Bit 2 */ + +#define DAC_CR_WAVE2 ((uint32_t)0x00C00000) /*!< WAVE2[1:0] (DAC channel2 noise/triangle wave generation enable) */ +#define DAC_CR_WAVE2_0 ((uint32_t)0x00400000) /*!< Bit 0 */ +#define DAC_CR_WAVE2_1 ((uint32_t)0x00800000) /*!< Bit 1 */ + +#define DAC_CR_MAMP2 ((uint32_t)0x0F000000) /*!< MAMP2[3:0] (DAC channel2 Mask/Amplitude selector) */ +#define DAC_CR_MAMP2_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define DAC_CR_MAMP2_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define DAC_CR_MAMP2_2 ((uint32_t)0x04000000) /*!< Bit 2 */ +#define DAC_CR_MAMP2_3 ((uint32_t)0x08000000) /*!< Bit 3 */ + +#define DAC_CR_DMAEN2 ((uint32_t)0x10000000) /*!< DAC channel2 DMA enabled */ + +/***************** Bit definition for DAC_SWTRIGR register ******************/ +#define DAC_SWTRIGR_SWTRIG1 ((uint8_t)0x01) /*!< DAC channel1 software trigger */ +#define DAC_SWTRIGR_SWTRIG2 ((uint8_t)0x02) /*!< DAC channel2 software trigger */ + +/***************** Bit definition for DAC_DHR12R1 register ******************/ +#define DAC_DHR12R1_DACC1DHR ((uint16_t)0x0FFF) /*!< DAC channel1 12-bit Right aligned data */ + +/***************** Bit definition for DAC_DHR12L1 register ******************/ +#define DAC_DHR12L1_DACC1DHR ((uint16_t)0xFFF0) /*!< DAC channel1 12-bit Left aligned data */ + +/****************** Bit definition for DAC_DHR8R1 register ******************/ +#define DAC_DHR8R1_DACC1DHR ((uint8_t)0xFF) /*!< DAC channel1 8-bit Right aligned data */ + +/***************** Bit definition for DAC_DHR12R2 register ******************/ +#define DAC_DHR12R2_DACC2DHR ((uint16_t)0x0FFF) /*!< DAC channel2 12-bit Right aligned data */ + +/***************** Bit definition for DAC_DHR12L2 register ******************/ +#define DAC_DHR12L2_DACC2DHR ((uint16_t)0xFFF0) /*!< DAC channel2 12-bit Left aligned data */ + +/****************** Bit definition for DAC_DHR8R2 register ******************/ +#define DAC_DHR8R2_DACC2DHR ((uint8_t)0xFF) /*!< DAC channel2 8-bit Right aligned data */ + +/***************** Bit definition for DAC_DHR12RD register ******************/ +#define DAC_DHR12RD_DACC1DHR ((uint32_t)0x00000FFF) /*!< DAC channel1 12-bit Right aligned data */ +#define DAC_DHR12RD_DACC2DHR ((uint32_t)0x0FFF0000) /*!< DAC channel2 12-bit Right aligned data */ + +/***************** Bit definition for DAC_DHR12LD register ******************/ +#define DAC_DHR12LD_DACC1DHR ((uint32_t)0x0000FFF0) /*!< DAC channel1 12-bit Left aligned data */ +#define DAC_DHR12LD_DACC2DHR ((uint32_t)0xFFF00000) /*!< DAC channel2 12-bit Left aligned data */ + +/****************** Bit definition for DAC_DHR8RD register ******************/ +#define DAC_DHR8RD_DACC1DHR ((uint16_t)0x00FF) /*!< DAC channel1 8-bit Right aligned data */ +#define DAC_DHR8RD_DACC2DHR ((uint16_t)0xFF00) /*!< DAC channel2 8-bit Right aligned data */ + +/******************* Bit definition for DAC_DOR1 register *******************/ +#define DAC_DOR1_DACC1DOR ((uint16_t)0x0FFF) /*!< DAC channel1 data output */ + +/******************* Bit definition for DAC_DOR2 register *******************/ +#define DAC_DOR2_DACC2DOR ((uint16_t)0x0FFF) /*!< DAC channel2 data output */ + +/******************** Bit definition for DAC_SR register ********************/ +#define DAC_SR_DMAUDR1 ((uint32_t)0x00002000) /*!< DAC channel1 DMA underrun flag */ +#define DAC_SR_DMAUDR2 ((uint32_t)0x20000000) /*!< DAC channel2 DMA underrun flag */ + +/******************************************************************************/ +/* */ +/* CEC */ +/* */ +/******************************************************************************/ +/******************** Bit definition for CEC_CFGR register ******************/ +#define CEC_CFGR_PE ((uint16_t)0x0001) /*!< Peripheral Enable */ +#define CEC_CFGR_IE ((uint16_t)0x0002) /*!< Interrupt Enable */ +#define CEC_CFGR_BTEM ((uint16_t)0x0004) /*!< Bit Timing Error Mode */ +#define CEC_CFGR_BPEM ((uint16_t)0x0008) /*!< Bit Period Error Mode */ + +/******************** Bit definition for CEC_OAR register ******************/ +#define CEC_OAR_OA ((uint16_t)0x000F) /*!< OA[3:0]: Own Address */ +#define CEC_OAR_OA_0 ((uint16_t)0x0001) /*!< Bit 0 */ +#define CEC_OAR_OA_1 ((uint16_t)0x0002) /*!< Bit 1 */ +#define CEC_OAR_OA_2 ((uint16_t)0x0004) /*!< Bit 2 */ +#define CEC_OAR_OA_3 ((uint16_t)0x0008) /*!< Bit 3 */ + +/******************** Bit definition for CEC_PRES register ******************/ +#define CEC_PRES_PRES ((uint16_t)0x3FFF) /*!< Prescaler Counter Value */ + +/******************** Bit definition for CEC_ESR register ******************/ +#define CEC_ESR_BTE ((uint16_t)0x0001) /*!< Bit Timing Error */ +#define CEC_ESR_BPE ((uint16_t)0x0002) /*!< Bit Period Error */ +#define CEC_ESR_RBTFE ((uint16_t)0x0004) /*!< Rx Block Transfer Finished Error */ +#define CEC_ESR_SBE ((uint16_t)0x0008) /*!< Start Bit Error */ +#define CEC_ESR_ACKE ((uint16_t)0x0010) /*!< Block Acknowledge Error */ +#define CEC_ESR_LINE ((uint16_t)0x0020) /*!< Line Error */ +#define CEC_ESR_TBTFE ((uint16_t)0x0040) /*!< Tx Block Transfer Finished Error */ + +/******************** Bit definition for CEC_CSR register ******************/ +#define CEC_CSR_TSOM ((uint16_t)0x0001) /*!< Tx Start Of Message */ +#define CEC_CSR_TEOM ((uint16_t)0x0002) /*!< Tx End Of Message */ +#define CEC_CSR_TERR ((uint16_t)0x0004) /*!< Tx Error */ +#define CEC_CSR_TBTRF ((uint16_t)0x0008) /*!< Tx Byte Transfer Request or Block Transfer Finished */ +#define CEC_CSR_RSOM ((uint16_t)0x0010) /*!< Rx Start Of Message */ +#define CEC_CSR_REOM ((uint16_t)0x0020) /*!< Rx End Of Message */ +#define CEC_CSR_RERR ((uint16_t)0x0040) /*!< Rx Error */ +#define CEC_CSR_RBTF ((uint16_t)0x0080) /*!< Rx Block Transfer Finished */ + +/******************** Bit definition for CEC_TXD register ******************/ +#define CEC_TXD_TXD ((uint16_t)0x00FF) /*!< Tx Data register */ + +/******************** Bit definition for CEC_RXD register ******************/ +#define CEC_RXD_RXD ((uint16_t)0x00FF) /*!< Rx Data register */ + +/******************************************************************************/ +/* */ +/* TIM */ +/* */ +/******************************************************************************/ + +/******************* Bit definition for TIM_CR1 register ********************/ +#define TIM_CR1_CEN ((uint16_t)0x0001) /*!< Counter enable */ +#define TIM_CR1_UDIS ((uint16_t)0x0002) /*!< Update disable */ +#define TIM_CR1_URS ((uint16_t)0x0004) /*!< Update request source */ +#define TIM_CR1_OPM ((uint16_t)0x0008) /*!< One pulse mode */ +#define TIM_CR1_DIR ((uint16_t)0x0010) /*!< Direction */ + +#define TIM_CR1_CMS ((uint16_t)0x0060) /*!< CMS[1:0] bits (Center-aligned mode selection) */ +#define TIM_CR1_CMS_0 ((uint16_t)0x0020) /*!< Bit 0 */ +#define TIM_CR1_CMS_1 ((uint16_t)0x0040) /*!< Bit 1 */ + +#define TIM_CR1_ARPE ((uint16_t)0x0080) /*!< Auto-reload preload enable */ + +#define TIM_CR1_CKD ((uint16_t)0x0300) /*!< CKD[1:0] bits (clock division) */ +#define TIM_CR1_CKD_0 ((uint16_t)0x0100) /*!< Bit 0 */ +#define TIM_CR1_CKD_1 ((uint16_t)0x0200) /*!< Bit 1 */ + +/******************* Bit definition for TIM_CR2 register ********************/ +#define TIM_CR2_CCPC ((uint16_t)0x0001) /*!< Capture/Compare Preloaded Control */ +#define TIM_CR2_CCUS ((uint16_t)0x0004) /*!< Capture/Compare Control Update Selection */ +#define TIM_CR2_CCDS ((uint16_t)0x0008) /*!< Capture/Compare DMA Selection */ + +#define TIM_CR2_MMS ((uint16_t)0x0070) /*!< MMS[2:0] bits (Master Mode Selection) */ +#define TIM_CR2_MMS_0 ((uint16_t)0x0010) /*!< Bit 0 */ +#define TIM_CR2_MMS_1 ((uint16_t)0x0020) /*!< Bit 1 */ +#define TIM_CR2_MMS_2 ((uint16_t)0x0040) /*!< Bit 2 */ + +#define TIM_CR2_TI1S ((uint16_t)0x0080) /*!< TI1 Selection */ +#define TIM_CR2_OIS1 ((uint16_t)0x0100) /*!< Output Idle state 1 (OC1 output) */ +#define TIM_CR2_OIS1N ((uint16_t)0x0200) /*!< Output Idle state 1 (OC1N output) */ +#define TIM_CR2_OIS2 ((uint16_t)0x0400) /*!< Output Idle state 2 (OC2 output) */ +#define TIM_CR2_OIS2N ((uint16_t)0x0800) /*!< Output Idle state 2 (OC2N output) */ +#define TIM_CR2_OIS3 ((uint16_t)0x1000) /*!< Output Idle state 3 (OC3 output) */ +#define TIM_CR2_OIS3N ((uint16_t)0x2000) /*!< Output Idle state 3 (OC3N output) */ +#define TIM_CR2_OIS4 ((uint16_t)0x4000) /*!< Output Idle state 4 (OC4 output) */ + +/******************* Bit definition for TIM_SMCR register *******************/ +#define TIM_SMCR_SMS ((uint16_t)0x0007) /*!< SMS[2:0] bits (Slave mode selection) */ +#define TIM_SMCR_SMS_0 ((uint16_t)0x0001) /*!< Bit 0 */ +#define TIM_SMCR_SMS_1 ((uint16_t)0x0002) /*!< Bit 1 */ +#define TIM_SMCR_SMS_2 ((uint16_t)0x0004) /*!< Bit 2 */ + +#define TIM_SMCR_TS ((uint16_t)0x0070) /*!< TS[2:0] bits (Trigger selection) */ +#define TIM_SMCR_TS_0 ((uint16_t)0x0010) /*!< Bit 0 */ +#define TIM_SMCR_TS_1 ((uint16_t)0x0020) /*!< Bit 1 */ +#define TIM_SMCR_TS_2 ((uint16_t)0x0040) /*!< Bit 2 */ + +#define TIM_SMCR_MSM ((uint16_t)0x0080) /*!< Master/slave mode */ + +#define TIM_SMCR_ETF ((uint16_t)0x0F00) /*!< ETF[3:0] bits (External trigger filter) */ +#define TIM_SMCR_ETF_0 ((uint16_t)0x0100) /*!< Bit 0 */ +#define TIM_SMCR_ETF_1 ((uint16_t)0x0200) /*!< Bit 1 */ +#define TIM_SMCR_ETF_2 ((uint16_t)0x0400) /*!< Bit 2 */ +#define TIM_SMCR_ETF_3 ((uint16_t)0x0800) /*!< Bit 3 */ + +#define TIM_SMCR_ETPS ((uint16_t)0x3000) /*!< ETPS[1:0] bits (External trigger prescaler) */ +#define TIM_SMCR_ETPS_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define TIM_SMCR_ETPS_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define TIM_SMCR_ECE ((uint16_t)0x4000) /*!< External clock enable */ +#define TIM_SMCR_ETP ((uint16_t)0x8000) /*!< External trigger polarity */ + +/******************* Bit definition for TIM_DIER register *******************/ +#define TIM_DIER_UIE ((uint16_t)0x0001) /*!< Update interrupt enable */ +#define TIM_DIER_CC1IE ((uint16_t)0x0002) /*!< Capture/Compare 1 interrupt enable */ +#define TIM_DIER_CC2IE ((uint16_t)0x0004) /*!< Capture/Compare 2 interrupt enable */ +#define TIM_DIER_CC3IE ((uint16_t)0x0008) /*!< Capture/Compare 3 interrupt enable */ +#define TIM_DIER_CC4IE ((uint16_t)0x0010) /*!< Capture/Compare 4 interrupt enable */ +#define TIM_DIER_COMIE ((uint16_t)0x0020) /*!< COM interrupt enable */ +#define TIM_DIER_TIE ((uint16_t)0x0040) /*!< Trigger interrupt enable */ +#define TIM_DIER_BIE ((uint16_t)0x0080) /*!< Break interrupt enable */ +#define TIM_DIER_UDE ((uint16_t)0x0100) /*!< Update DMA request enable */ +#define TIM_DIER_CC1DE ((uint16_t)0x0200) /*!< Capture/Compare 1 DMA request enable */ +#define TIM_DIER_CC2DE ((uint16_t)0x0400) /*!< Capture/Compare 2 DMA request enable */ +#define TIM_DIER_CC3DE ((uint16_t)0x0800) /*!< Capture/Compare 3 DMA request enable */ +#define TIM_DIER_CC4DE ((uint16_t)0x1000) /*!< Capture/Compare 4 DMA request enable */ +#define TIM_DIER_COMDE ((uint16_t)0x2000) /*!< COM DMA request enable */ +#define TIM_DIER_TDE ((uint16_t)0x4000) /*!< Trigger DMA request enable */ + +/******************** Bit definition for TIM_SR register ********************/ +#define TIM_SR_UIF ((uint16_t)0x0001) /*!< Update interrupt Flag */ +#define TIM_SR_CC1IF ((uint16_t)0x0002) /*!< Capture/Compare 1 interrupt Flag */ +#define TIM_SR_CC2IF ((uint16_t)0x0004) /*!< Capture/Compare 2 interrupt Flag */ +#define TIM_SR_CC3IF ((uint16_t)0x0008) /*!< Capture/Compare 3 interrupt Flag */ +#define TIM_SR_CC4IF ((uint16_t)0x0010) /*!< Capture/Compare 4 interrupt Flag */ +#define TIM_SR_COMIF ((uint16_t)0x0020) /*!< COM interrupt Flag */ +#define TIM_SR_TIF ((uint16_t)0x0040) /*!< Trigger interrupt Flag */ +#define TIM_SR_BIF ((uint16_t)0x0080) /*!< Break interrupt Flag */ +#define TIM_SR_CC1OF ((uint16_t)0x0200) /*!< Capture/Compare 1 Overcapture Flag */ +#define TIM_SR_CC2OF ((uint16_t)0x0400) /*!< Capture/Compare 2 Overcapture Flag */ +#define TIM_SR_CC3OF ((uint16_t)0x0800) /*!< Capture/Compare 3 Overcapture Flag */ +#define TIM_SR_CC4OF ((uint16_t)0x1000) /*!< Capture/Compare 4 Overcapture Flag */ + +/******************* Bit definition for TIM_EGR register ********************/ +#define TIM_EGR_UG ((uint8_t)0x01) /*!< Update Generation */ +#define TIM_EGR_CC1G ((uint8_t)0x02) /*!< Capture/Compare 1 Generation */ +#define TIM_EGR_CC2G ((uint8_t)0x04) /*!< Capture/Compare 2 Generation */ +#define TIM_EGR_CC3G ((uint8_t)0x08) /*!< Capture/Compare 3 Generation */ +#define TIM_EGR_CC4G ((uint8_t)0x10) /*!< Capture/Compare 4 Generation */ +#define TIM_EGR_COMG ((uint8_t)0x20) /*!< Capture/Compare Control Update Generation */ +#define TIM_EGR_TG ((uint8_t)0x40) /*!< Trigger Generation */ +#define TIM_EGR_BG ((uint8_t)0x80) /*!< Break Generation */ + +/****************** Bit definition for TIM_CCMR1 register *******************/ +#define TIM_CCMR1_CC1S ((uint16_t)0x0003) /*!< CC1S[1:0] bits (Capture/Compare 1 Selection) */ +#define TIM_CCMR1_CC1S_0 ((uint16_t)0x0001) /*!< Bit 0 */ +#define TIM_CCMR1_CC1S_1 ((uint16_t)0x0002) /*!< Bit 1 */ + +#define TIM_CCMR1_OC1FE ((uint16_t)0x0004) /*!< Output Compare 1 Fast enable */ +#define TIM_CCMR1_OC1PE ((uint16_t)0x0008) /*!< Output Compare 1 Preload enable */ + +#define TIM_CCMR1_OC1M ((uint16_t)0x0070) /*!< OC1M[2:0] bits (Output Compare 1 Mode) */ +#define TIM_CCMR1_OC1M_0 ((uint16_t)0x0010) /*!< Bit 0 */ +#define TIM_CCMR1_OC1M_1 ((uint16_t)0x0020) /*!< Bit 1 */ +#define TIM_CCMR1_OC1M_2 ((uint16_t)0x0040) /*!< Bit 2 */ + +#define TIM_CCMR1_OC1CE ((uint16_t)0x0080) /*!< Output Compare 1Clear Enable */ + +#define TIM_CCMR1_CC2S ((uint16_t)0x0300) /*!< CC2S[1:0] bits (Capture/Compare 2 Selection) */ +#define TIM_CCMR1_CC2S_0 ((uint16_t)0x0100) /*!< Bit 0 */ +#define TIM_CCMR1_CC2S_1 ((uint16_t)0x0200) /*!< Bit 1 */ + +#define TIM_CCMR1_OC2FE ((uint16_t)0x0400) /*!< Output Compare 2 Fast enable */ +#define TIM_CCMR1_OC2PE ((uint16_t)0x0800) /*!< Output Compare 2 Preload enable */ + +#define TIM_CCMR1_OC2M ((uint16_t)0x7000) /*!< OC2M[2:0] bits (Output Compare 2 Mode) */ +#define TIM_CCMR1_OC2M_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define TIM_CCMR1_OC2M_1 ((uint16_t)0x2000) /*!< Bit 1 */ +#define TIM_CCMR1_OC2M_2 ((uint16_t)0x4000) /*!< Bit 2 */ + +#define TIM_CCMR1_OC2CE ((uint16_t)0x8000) /*!< Output Compare 2 Clear Enable */ + +/*----------------------------------------------------------------------------*/ + +#define TIM_CCMR1_IC1PSC ((uint16_t)0x000C) /*!< IC1PSC[1:0] bits (Input Capture 1 Prescaler) */ +#define TIM_CCMR1_IC1PSC_0 ((uint16_t)0x0004) /*!< Bit 0 */ +#define TIM_CCMR1_IC1PSC_1 ((uint16_t)0x0008) /*!< Bit 1 */ + +#define TIM_CCMR1_IC1F ((uint16_t)0x00F0) /*!< IC1F[3:0] bits (Input Capture 1 Filter) */ +#define TIM_CCMR1_IC1F_0 ((uint16_t)0x0010) /*!< Bit 0 */ +#define TIM_CCMR1_IC1F_1 ((uint16_t)0x0020) /*!< Bit 1 */ +#define TIM_CCMR1_IC1F_2 ((uint16_t)0x0040) /*!< Bit 2 */ +#define TIM_CCMR1_IC1F_3 ((uint16_t)0x0080) /*!< Bit 3 */ + +#define TIM_CCMR1_IC2PSC ((uint16_t)0x0C00) /*!< IC2PSC[1:0] bits (Input Capture 2 Prescaler) */ +#define TIM_CCMR1_IC2PSC_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define TIM_CCMR1_IC2PSC_1 ((uint16_t)0x0800) /*!< Bit 1 */ + +#define TIM_CCMR1_IC2F ((uint16_t)0xF000) /*!< IC2F[3:0] bits (Input Capture 2 Filter) */ +#define TIM_CCMR1_IC2F_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define TIM_CCMR1_IC2F_1 ((uint16_t)0x2000) /*!< Bit 1 */ +#define TIM_CCMR1_IC2F_2 ((uint16_t)0x4000) /*!< Bit 2 */ +#define TIM_CCMR1_IC2F_3 ((uint16_t)0x8000) /*!< Bit 3 */ + +/****************** Bit definition for TIM_CCMR2 register *******************/ +#define TIM_CCMR2_CC3S ((uint16_t)0x0003) /*!< CC3S[1:0] bits (Capture/Compare 3 Selection) */ +#define TIM_CCMR2_CC3S_0 ((uint16_t)0x0001) /*!< Bit 0 */ +#define TIM_CCMR2_CC3S_1 ((uint16_t)0x0002) /*!< Bit 1 */ + +#define TIM_CCMR2_OC3FE ((uint16_t)0x0004) /*!< Output Compare 3 Fast enable */ +#define TIM_CCMR2_OC3PE ((uint16_t)0x0008) /*!< Output Compare 3 Preload enable */ + +#define TIM_CCMR2_OC3M ((uint16_t)0x0070) /*!< OC3M[2:0] bits (Output Compare 3 Mode) */ +#define TIM_CCMR2_OC3M_0 ((uint16_t)0x0010) /*!< Bit 0 */ +#define TIM_CCMR2_OC3M_1 ((uint16_t)0x0020) /*!< Bit 1 */ +#define TIM_CCMR2_OC3M_2 ((uint16_t)0x0040) /*!< Bit 2 */ + +#define TIM_CCMR2_OC3CE ((uint16_t)0x0080) /*!< Output Compare 3 Clear Enable */ + +#define TIM_CCMR2_CC4S ((uint16_t)0x0300) /*!< CC4S[1:0] bits (Capture/Compare 4 Selection) */ +#define TIM_CCMR2_CC4S_0 ((uint16_t)0x0100) /*!< Bit 0 */ +#define TIM_CCMR2_CC4S_1 ((uint16_t)0x0200) /*!< Bit 1 */ + +#define TIM_CCMR2_OC4FE ((uint16_t)0x0400) /*!< Output Compare 4 Fast enable */ +#define TIM_CCMR2_OC4PE ((uint16_t)0x0800) /*!< Output Compare 4 Preload enable */ + +#define TIM_CCMR2_OC4M ((uint16_t)0x7000) /*!< OC4M[2:0] bits (Output Compare 4 Mode) */ +#define TIM_CCMR2_OC4M_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define TIM_CCMR2_OC4M_1 ((uint16_t)0x2000) /*!< Bit 1 */ +#define TIM_CCMR2_OC4M_2 ((uint16_t)0x4000) /*!< Bit 2 */ + +#define TIM_CCMR2_OC4CE ((uint16_t)0x8000) /*!< Output Compare 4 Clear Enable */ + +/*----------------------------------------------------------------------------*/ + +#define TIM_CCMR2_IC3PSC ((uint16_t)0x000C) /*!< IC3PSC[1:0] bits (Input Capture 3 Prescaler) */ +#define TIM_CCMR2_IC3PSC_0 ((uint16_t)0x0004) /*!< Bit 0 */ +#define TIM_CCMR2_IC3PSC_1 ((uint16_t)0x0008) /*!< Bit 1 */ + +#define TIM_CCMR2_IC3F ((uint16_t)0x00F0) /*!< IC3F[3:0] bits (Input Capture 3 Filter) */ +#define TIM_CCMR2_IC3F_0 ((uint16_t)0x0010) /*!< Bit 0 */ +#define TIM_CCMR2_IC3F_1 ((uint16_t)0x0020) /*!< Bit 1 */ +#define TIM_CCMR2_IC3F_2 ((uint16_t)0x0040) /*!< Bit 2 */ +#define TIM_CCMR2_IC3F_3 ((uint16_t)0x0080) /*!< Bit 3 */ + +#define TIM_CCMR2_IC4PSC ((uint16_t)0x0C00) /*!< IC4PSC[1:0] bits (Input Capture 4 Prescaler) */ +#define TIM_CCMR2_IC4PSC_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define TIM_CCMR2_IC4PSC_1 ((uint16_t)0x0800) /*!< Bit 1 */ + +#define TIM_CCMR2_IC4F ((uint16_t)0xF000) /*!< IC4F[3:0] bits (Input Capture 4 Filter) */ +#define TIM_CCMR2_IC4F_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define TIM_CCMR2_IC4F_1 ((uint16_t)0x2000) /*!< Bit 1 */ +#define TIM_CCMR2_IC4F_2 ((uint16_t)0x4000) /*!< Bit 2 */ +#define TIM_CCMR2_IC4F_3 ((uint16_t)0x8000) /*!< Bit 3 */ + +/******************* Bit definition for TIM_CCER register *******************/ +#define TIM_CCER_CC1E ((uint16_t)0x0001) /*!< Capture/Compare 1 output enable */ +#define TIM_CCER_CC1P ((uint16_t)0x0002) /*!< Capture/Compare 1 output Polarity */ +#define TIM_CCER_CC1NE ((uint16_t)0x0004) /*!< Capture/Compare 1 Complementary output enable */ +#define TIM_CCER_CC1NP ((uint16_t)0x0008) /*!< Capture/Compare 1 Complementary output Polarity */ +#define TIM_CCER_CC2E ((uint16_t)0x0010) /*!< Capture/Compare 2 output enable */ +#define TIM_CCER_CC2P ((uint16_t)0x0020) /*!< Capture/Compare 2 output Polarity */ +#define TIM_CCER_CC2NE ((uint16_t)0x0040) /*!< Capture/Compare 2 Complementary output enable */ +#define TIM_CCER_CC2NP ((uint16_t)0x0080) /*!< Capture/Compare 2 Complementary output Polarity */ +#define TIM_CCER_CC3E ((uint16_t)0x0100) /*!< Capture/Compare 3 output enable */ +#define TIM_CCER_CC3P ((uint16_t)0x0200) /*!< Capture/Compare 3 output Polarity */ +#define TIM_CCER_CC3NE ((uint16_t)0x0400) /*!< Capture/Compare 3 Complementary output enable */ +#define TIM_CCER_CC3NP ((uint16_t)0x0800) /*!< Capture/Compare 3 Complementary output Polarity */ +#define TIM_CCER_CC4E ((uint16_t)0x1000) /*!< Capture/Compare 4 output enable */ +#define TIM_CCER_CC4P ((uint16_t)0x2000) /*!< Capture/Compare 4 output Polarity */ +#define TIM_CCER_CC4NP ((uint16_t)0x8000) /*!< Capture/Compare 4 Complementary output Polarity */ + +/******************* Bit definition for TIM_CNT register ********************/ +#define TIM_CNT_CNT ((uint16_t)0xFFFF) /*!< Counter Value */ + +/******************* Bit definition for TIM_PSC register ********************/ +#define TIM_PSC_PSC ((uint16_t)0xFFFF) /*!< Prescaler Value */ + +/******************* Bit definition for TIM_ARR register ********************/ +#define TIM_ARR_ARR ((uint16_t)0xFFFF) /*!< actual auto-reload Value */ + +/******************* Bit definition for TIM_RCR register ********************/ +#define TIM_RCR_REP ((uint8_t)0xFF) /*!< Repetition Counter Value */ + +/******************* Bit definition for TIM_CCR1 register *******************/ +#define TIM_CCR1_CCR1 ((uint16_t)0xFFFF) /*!< Capture/Compare 1 Value */ + +/******************* Bit definition for TIM_CCR2 register *******************/ +#define TIM_CCR2_CCR2 ((uint16_t)0xFFFF) /*!< Capture/Compare 2 Value */ + +/******************* Bit definition for TIM_CCR3 register *******************/ +#define TIM_CCR3_CCR3 ((uint16_t)0xFFFF) /*!< Capture/Compare 3 Value */ + +/******************* Bit definition for TIM_CCR4 register *******************/ +#define TIM_CCR4_CCR4 ((uint16_t)0xFFFF) /*!< Capture/Compare 4 Value */ + +/******************* Bit definition for TIM_BDTR register *******************/ +#define TIM_BDTR_DTG ((uint16_t)0x00FF) /*!< DTG[0:7] bits (Dead-Time Generator set-up) */ +#define TIM_BDTR_DTG_0 ((uint16_t)0x0001) /*!< Bit 0 */ +#define TIM_BDTR_DTG_1 ((uint16_t)0x0002) /*!< Bit 1 */ +#define TIM_BDTR_DTG_2 ((uint16_t)0x0004) /*!< Bit 2 */ +#define TIM_BDTR_DTG_3 ((uint16_t)0x0008) /*!< Bit 3 */ +#define TIM_BDTR_DTG_4 ((uint16_t)0x0010) /*!< Bit 4 */ +#define TIM_BDTR_DTG_5 ((uint16_t)0x0020) /*!< Bit 5 */ +#define TIM_BDTR_DTG_6 ((uint16_t)0x0040) /*!< Bit 6 */ +#define TIM_BDTR_DTG_7 ((uint16_t)0x0080) /*!< Bit 7 */ + +#define TIM_BDTR_LOCK ((uint16_t)0x0300) /*!< LOCK[1:0] bits (Lock Configuration) */ +#define TIM_BDTR_LOCK_0 ((uint16_t)0x0100) /*!< Bit 0 */ +#define TIM_BDTR_LOCK_1 ((uint16_t)0x0200) /*!< Bit 1 */ + +#define TIM_BDTR_OSSI ((uint16_t)0x0400) /*!< Off-State Selection for Idle mode */ +#define TIM_BDTR_OSSR ((uint16_t)0x0800) /*!< Off-State Selection for Run mode */ +#define TIM_BDTR_BKE ((uint16_t)0x1000) /*!< Break enable */ +#define TIM_BDTR_BKP ((uint16_t)0x2000) /*!< Break Polarity */ +#define TIM_BDTR_AOE ((uint16_t)0x4000) /*!< Automatic Output enable */ +#define TIM_BDTR_MOE ((uint16_t)0x8000) /*!< Main Output enable */ + +/******************* Bit definition for TIM_DCR register ********************/ +#define TIM_DCR_DBA ((uint16_t)0x001F) /*!< DBA[4:0] bits (DMA Base Address) */ +#define TIM_DCR_DBA_0 ((uint16_t)0x0001) /*!< Bit 0 */ +#define TIM_DCR_DBA_1 ((uint16_t)0x0002) /*!< Bit 1 */ +#define TIM_DCR_DBA_2 ((uint16_t)0x0004) /*!< Bit 2 */ +#define TIM_DCR_DBA_3 ((uint16_t)0x0008) /*!< Bit 3 */ +#define TIM_DCR_DBA_4 ((uint16_t)0x0010) /*!< Bit 4 */ + +#define TIM_DCR_DBL ((uint16_t)0x1F00) /*!< DBL[4:0] bits (DMA Burst Length) */ +#define TIM_DCR_DBL_0 ((uint16_t)0x0100) /*!< Bit 0 */ +#define TIM_DCR_DBL_1 ((uint16_t)0x0200) /*!< Bit 1 */ +#define TIM_DCR_DBL_2 ((uint16_t)0x0400) /*!< Bit 2 */ +#define TIM_DCR_DBL_3 ((uint16_t)0x0800) /*!< Bit 3 */ +#define TIM_DCR_DBL_4 ((uint16_t)0x1000) /*!< Bit 4 */ + +/******************* Bit definition for TIM_DMAR register *******************/ +#define TIM_DMAR_DMAB ((uint16_t)0xFFFF) /*!< DMA register for burst accesses */ + +/******************************************************************************/ +/* */ +/* Real-Time Clock */ +/* */ +/******************************************************************************/ + +/******************* Bit definition for RTC_CRH register ********************/ +#define RTC_CRH_SECIE ((uint8_t)0x01) /*!< Second Interrupt Enable */ +#define RTC_CRH_ALRIE ((uint8_t)0x02) /*!< Alarm Interrupt Enable */ +#define RTC_CRH_OWIE ((uint8_t)0x04) /*!< OverfloW Interrupt Enable */ + +/******************* Bit definition for RTC_CRL register ********************/ +#define RTC_CRL_SECF ((uint8_t)0x01) /*!< Second Flag */ +#define RTC_CRL_ALRF ((uint8_t)0x02) /*!< Alarm Flag */ +#define RTC_CRL_OWF ((uint8_t)0x04) /*!< OverfloW Flag */ +#define RTC_CRL_RSF ((uint8_t)0x08) /*!< Registers Synchronized Flag */ +#define RTC_CRL_CNF ((uint8_t)0x10) /*!< Configuration Flag */ +#define RTC_CRL_RTOFF ((uint8_t)0x20) /*!< RTC operation OFF */ + +/******************* Bit definition for RTC_PRLH register *******************/ +#define RTC_PRLH_PRL ((uint16_t)0x000F) /*!< RTC Prescaler Reload Value High */ + +/******************* Bit definition for RTC_PRLL register *******************/ +#define RTC_PRLL_PRL ((uint16_t)0xFFFF) /*!< RTC Prescaler Reload Value Low */ + +/******************* Bit definition for RTC_DIVH register *******************/ +#define RTC_DIVH_RTC_DIV ((uint16_t)0x000F) /*!< RTC Clock Divider High */ + +/******************* Bit definition for RTC_DIVL register *******************/ +#define RTC_DIVL_RTC_DIV ((uint16_t)0xFFFF) /*!< RTC Clock Divider Low */ + +/******************* Bit definition for RTC_CNTH register *******************/ +#define RTC_CNTH_RTC_CNT ((uint16_t)0xFFFF) /*!< RTC Counter High */ + +/******************* Bit definition for RTC_CNTL register *******************/ +#define RTC_CNTL_RTC_CNT ((uint16_t)0xFFFF) /*!< RTC Counter Low */ + +/******************* Bit definition for RTC_ALRH register *******************/ +#define RTC_ALRH_RTC_ALR ((uint16_t)0xFFFF) /*!< RTC Alarm High */ + +/******************* Bit definition for RTC_ALRL register *******************/ +#define RTC_ALRL_RTC_ALR ((uint16_t)0xFFFF) /*!< RTC Alarm Low */ + +/******************************************************************************/ +/* */ +/* Independent WATCHDOG */ +/* */ +/******************************************************************************/ + +/******************* Bit definition for IWDG_KR register ********************/ +#define IWDG_KR_KEY ((uint16_t)0xFFFF) /*!< Key value (write only, read 0000h) */ + +/******************* Bit definition for IWDG_PR register ********************/ +#define IWDG_PR_PR ((uint8_t)0x07) /*!< PR[2:0] (Prescaler divider) */ +#define IWDG_PR_PR_0 ((uint8_t)0x01) /*!< Bit 0 */ +#define IWDG_PR_PR_1 ((uint8_t)0x02) /*!< Bit 1 */ +#define IWDG_PR_PR_2 ((uint8_t)0x04) /*!< Bit 2 */ + +/******************* Bit definition for IWDG_RLR register *******************/ +#define IWDG_RLR_RL ((uint16_t)0x0FFF) /*!< Watchdog counter reload value */ + +/******************* Bit definition for IWDG_SR register ********************/ +#define IWDG_SR_PVU ((uint8_t)0x01) /*!< Watchdog prescaler value update */ +#define IWDG_SR_RVU ((uint8_t)0x02) /*!< Watchdog counter reload value update */ + +/******************************************************************************/ +/* */ +/* Window WATCHDOG */ +/* */ +/******************************************************************************/ + +/******************* Bit definition for WWDG_CR register ********************/ +#define WWDG_CR_T ((uint8_t)0x7F) /*!< T[6:0] bits (7-Bit counter (MSB to LSB)) */ +#define WWDG_CR_T0 ((uint8_t)0x01) /*!< Bit 0 */ +#define WWDG_CR_T1 ((uint8_t)0x02) /*!< Bit 1 */ +#define WWDG_CR_T2 ((uint8_t)0x04) /*!< Bit 2 */ +#define WWDG_CR_T3 ((uint8_t)0x08) /*!< Bit 3 */ +#define WWDG_CR_T4 ((uint8_t)0x10) /*!< Bit 4 */ +#define WWDG_CR_T5 ((uint8_t)0x20) /*!< Bit 5 */ +#define WWDG_CR_T6 ((uint8_t)0x40) /*!< Bit 6 */ + +#define WWDG_CR_WDGA ((uint8_t)0x80) /*!< Activation bit */ + +/******************* Bit definition for WWDG_CFR register *******************/ +#define WWDG_CFR_W ((uint16_t)0x007F) /*!< W[6:0] bits (7-bit window value) */ +#define WWDG_CFR_W0 ((uint16_t)0x0001) /*!< Bit 0 */ +#define WWDG_CFR_W1 ((uint16_t)0x0002) /*!< Bit 1 */ +#define WWDG_CFR_W2 ((uint16_t)0x0004) /*!< Bit 2 */ +#define WWDG_CFR_W3 ((uint16_t)0x0008) /*!< Bit 3 */ +#define WWDG_CFR_W4 ((uint16_t)0x0010) /*!< Bit 4 */ +#define WWDG_CFR_W5 ((uint16_t)0x0020) /*!< Bit 5 */ +#define WWDG_CFR_W6 ((uint16_t)0x0040) /*!< Bit 6 */ + +#define WWDG_CFR_WDGTB ((uint16_t)0x0180) /*!< WDGTB[1:0] bits (Timer Base) */ +#define WWDG_CFR_WDGTB0 ((uint16_t)0x0080) /*!< Bit 0 */ +#define WWDG_CFR_WDGTB1 ((uint16_t)0x0100) /*!< Bit 1 */ + +#define WWDG_CFR_EWI ((uint16_t)0x0200) /*!< Early Wakeup Interrupt */ + +/******************* Bit definition for WWDG_SR register ********************/ +#define WWDG_SR_EWIF ((uint8_t)0x01) /*!< Early Wakeup Interrupt Flag */ + +/******************************************************************************/ +/* */ +/* Flexible Static Memory Controller */ +/* */ +/******************************************************************************/ + +/****************** Bit definition for FSMC_BCR1 register *******************/ +#define FSMC_BCR1_MBKEN ((uint32_t)0x00000001) /*!< Memory bank enable bit */ +#define FSMC_BCR1_MUXEN ((uint32_t)0x00000002) /*!< Address/data multiplexing enable bit */ + +#define FSMC_BCR1_MTYP ((uint32_t)0x0000000C) /*!< MTYP[1:0] bits (Memory type) */ +#define FSMC_BCR1_MTYP_0 ((uint32_t)0x00000004) /*!< Bit 0 */ +#define FSMC_BCR1_MTYP_1 ((uint32_t)0x00000008) /*!< Bit 1 */ + +#define FSMC_BCR1_MWID ((uint32_t)0x00000030) /*!< MWID[1:0] bits (Memory data bus width) */ +#define FSMC_BCR1_MWID_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define FSMC_BCR1_MWID_1 ((uint32_t)0x00000020) /*!< Bit 1 */ + +#define FSMC_BCR1_FACCEN ((uint32_t)0x00000040) /*!< Flash access enable */ +#define FSMC_BCR1_BURSTEN ((uint32_t)0x00000100) /*!< Burst enable bit */ +#define FSMC_BCR1_WAITPOL ((uint32_t)0x00000200) /*!< Wait signal polarity bit */ +#define FSMC_BCR1_WRAPMOD ((uint32_t)0x00000400) /*!< Wrapped burst mode support */ +#define FSMC_BCR1_WAITCFG ((uint32_t)0x00000800) /*!< Wait timing configuration */ +#define FSMC_BCR1_WREN ((uint32_t)0x00001000) /*!< Write enable bit */ +#define FSMC_BCR1_WAITEN ((uint32_t)0x00002000) /*!< Wait enable bit */ +#define FSMC_BCR1_EXTMOD ((uint32_t)0x00004000) /*!< Extended mode enable */ +#define FSMC_BCR1_ASYNCWAIT ((uint32_t)0x00008000) /*!< Asynchronous wait */ +#define FSMC_BCR1_CBURSTRW ((uint32_t)0x00080000) /*!< Write burst enable */ + +/****************** Bit definition for FSMC_BCR2 register *******************/ +#define FSMC_BCR2_MBKEN ((uint32_t)0x00000001) /*!< Memory bank enable bit */ +#define FSMC_BCR2_MUXEN ((uint32_t)0x00000002) /*!< Address/data multiplexing enable bit */ + +#define FSMC_BCR2_MTYP ((uint32_t)0x0000000C) /*!< MTYP[1:0] bits (Memory type) */ +#define FSMC_BCR2_MTYP_0 ((uint32_t)0x00000004) /*!< Bit 0 */ +#define FSMC_BCR2_MTYP_1 ((uint32_t)0x00000008) /*!< Bit 1 */ + +#define FSMC_BCR2_MWID ((uint32_t)0x00000030) /*!< MWID[1:0] bits (Memory data bus width) */ +#define FSMC_BCR2_MWID_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define FSMC_BCR2_MWID_1 ((uint32_t)0x00000020) /*!< Bit 1 */ + +#define FSMC_BCR2_FACCEN ((uint32_t)0x00000040) /*!< Flash access enable */ +#define FSMC_BCR2_BURSTEN ((uint32_t)0x00000100) /*!< Burst enable bit */ +#define FSMC_BCR2_WAITPOL ((uint32_t)0x00000200) /*!< Wait signal polarity bit */ +#define FSMC_BCR2_WRAPMOD ((uint32_t)0x00000400) /*!< Wrapped burst mode support */ +#define FSMC_BCR2_WAITCFG ((uint32_t)0x00000800) /*!< Wait timing configuration */ +#define FSMC_BCR2_WREN ((uint32_t)0x00001000) /*!< Write enable bit */ +#define FSMC_BCR2_WAITEN ((uint32_t)0x00002000) /*!< Wait enable bit */ +#define FSMC_BCR2_EXTMOD ((uint32_t)0x00004000) /*!< Extended mode enable */ +#define FSMC_BCR2_ASYNCWAIT ((uint32_t)0x00008000) /*!< Asynchronous wait */ +#define FSMC_BCR2_CBURSTRW ((uint32_t)0x00080000) /*!< Write burst enable */ + +/****************** Bit definition for FSMC_BCR3 register *******************/ +#define FSMC_BCR3_MBKEN ((uint32_t)0x00000001) /*!< Memory bank enable bit */ +#define FSMC_BCR3_MUXEN ((uint32_t)0x00000002) /*!< Address/data multiplexing enable bit */ + +#define FSMC_BCR3_MTYP ((uint32_t)0x0000000C) /*!< MTYP[1:0] bits (Memory type) */ +#define FSMC_BCR3_MTYP_0 ((uint32_t)0x00000004) /*!< Bit 0 */ +#define FSMC_BCR3_MTYP_1 ((uint32_t)0x00000008) /*!< Bit 1 */ + +#define FSMC_BCR3_MWID ((uint32_t)0x00000030) /*!< MWID[1:0] bits (Memory data bus width) */ +#define FSMC_BCR3_MWID_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define FSMC_BCR3_MWID_1 ((uint32_t)0x00000020) /*!< Bit 1 */ + +#define FSMC_BCR3_FACCEN ((uint32_t)0x00000040) /*!< Flash access enable */ +#define FSMC_BCR3_BURSTEN ((uint32_t)0x00000100) /*!< Burst enable bit */ +#define FSMC_BCR3_WAITPOL ((uint32_t)0x00000200) /*!< Wait signal polarity bit. */ +#define FSMC_BCR3_WRAPMOD ((uint32_t)0x00000400) /*!< Wrapped burst mode support */ +#define FSMC_BCR3_WAITCFG ((uint32_t)0x00000800) /*!< Wait timing configuration */ +#define FSMC_BCR3_WREN ((uint32_t)0x00001000) /*!< Write enable bit */ +#define FSMC_BCR3_WAITEN ((uint32_t)0x00002000) /*!< Wait enable bit */ +#define FSMC_BCR3_EXTMOD ((uint32_t)0x00004000) /*!< Extended mode enable */ +#define FSMC_BCR3_ASYNCWAIT ((uint32_t)0x00008000) /*!< Asynchronous wait */ +#define FSMC_BCR3_CBURSTRW ((uint32_t)0x00080000) /*!< Write burst enable */ + +/****************** Bit definition for FSMC_BCR4 register *******************/ +#define FSMC_BCR4_MBKEN ((uint32_t)0x00000001) /*!< Memory bank enable bit */ +#define FSMC_BCR4_MUXEN ((uint32_t)0x00000002) /*!< Address/data multiplexing enable bit */ + +#define FSMC_BCR4_MTYP ((uint32_t)0x0000000C) /*!< MTYP[1:0] bits (Memory type) */ +#define FSMC_BCR4_MTYP_0 ((uint32_t)0x00000004) /*!< Bit 0 */ +#define FSMC_BCR4_MTYP_1 ((uint32_t)0x00000008) /*!< Bit 1 */ + +#define FSMC_BCR4_MWID ((uint32_t)0x00000030) /*!< MWID[1:0] bits (Memory data bus width) */ +#define FSMC_BCR4_MWID_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define FSMC_BCR4_MWID_1 ((uint32_t)0x00000020) /*!< Bit 1 */ + +#define FSMC_BCR4_FACCEN ((uint32_t)0x00000040) /*!< Flash access enable */ +#define FSMC_BCR4_BURSTEN ((uint32_t)0x00000100) /*!< Burst enable bit */ +#define FSMC_BCR4_WAITPOL ((uint32_t)0x00000200) /*!< Wait signal polarity bit */ +#define FSMC_BCR4_WRAPMOD ((uint32_t)0x00000400) /*!< Wrapped burst mode support */ +#define FSMC_BCR4_WAITCFG ((uint32_t)0x00000800) /*!< Wait timing configuration */ +#define FSMC_BCR4_WREN ((uint32_t)0x00001000) /*!< Write enable bit */ +#define FSMC_BCR4_WAITEN ((uint32_t)0x00002000) /*!< Wait enable bit */ +#define FSMC_BCR4_EXTMOD ((uint32_t)0x00004000) /*!< Extended mode enable */ +#define FSMC_BCR4_ASYNCWAIT ((uint32_t)0x00008000) /*!< Asynchronous wait */ +#define FSMC_BCR4_CBURSTRW ((uint32_t)0x00080000) /*!< Write burst enable */ + +/****************** Bit definition for FSMC_BTR1 register ******************/ +#define FSMC_BTR1_ADDSET ((uint32_t)0x0000000F) /*!< ADDSET[3:0] bits (Address setup phase duration) */ +#define FSMC_BTR1_ADDSET_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define FSMC_BTR1_ADDSET_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define FSMC_BTR1_ADDSET_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define FSMC_BTR1_ADDSET_3 ((uint32_t)0x00000008) /*!< Bit 3 */ + +#define FSMC_BTR1_ADDHLD ((uint32_t)0x000000F0) /*!< ADDHLD[3:0] bits (Address-hold phase duration) */ +#define FSMC_BTR1_ADDHLD_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define FSMC_BTR1_ADDHLD_1 ((uint32_t)0x00000020) /*!< Bit 1 */ +#define FSMC_BTR1_ADDHLD_2 ((uint32_t)0x00000040) /*!< Bit 2 */ +#define FSMC_BTR1_ADDHLD_3 ((uint32_t)0x00000080) /*!< Bit 3 */ + +#define FSMC_BTR1_DATAST ((uint32_t)0x0000FF00) /*!< DATAST [3:0] bits (Data-phase duration) */ +#define FSMC_BTR1_DATAST_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define FSMC_BTR1_DATAST_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define FSMC_BTR1_DATAST_2 ((uint32_t)0x00000400) /*!< Bit 2 */ +#define FSMC_BTR1_DATAST_3 ((uint32_t)0x00000800) /*!< Bit 3 */ + +#define FSMC_BTR1_BUSTURN ((uint32_t)0x000F0000) /*!< BUSTURN[3:0] bits (Bus turnaround phase duration) */ +#define FSMC_BTR1_BUSTURN_0 ((uint32_t)0x00010000) /*!< Bit 0 */ +#define FSMC_BTR1_BUSTURN_1 ((uint32_t)0x00020000) /*!< Bit 1 */ +#define FSMC_BTR1_BUSTURN_2 ((uint32_t)0x00040000) /*!< Bit 2 */ +#define FSMC_BTR1_BUSTURN_3 ((uint32_t)0x00080000) /*!< Bit 3 */ + +#define FSMC_BTR1_CLKDIV ((uint32_t)0x00F00000) /*!< CLKDIV[3:0] bits (Clock divide ratio) */ +#define FSMC_BTR1_CLKDIV_0 ((uint32_t)0x00100000) /*!< Bit 0 */ +#define FSMC_BTR1_CLKDIV_1 ((uint32_t)0x00200000) /*!< Bit 1 */ +#define FSMC_BTR1_CLKDIV_2 ((uint32_t)0x00400000) /*!< Bit 2 */ +#define FSMC_BTR1_CLKDIV_3 ((uint32_t)0x00800000) /*!< Bit 3 */ + +#define FSMC_BTR1_DATLAT ((uint32_t)0x0F000000) /*!< DATLA[3:0] bits (Data latency) */ +#define FSMC_BTR1_DATLAT_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define FSMC_BTR1_DATLAT_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define FSMC_BTR1_DATLAT_2 ((uint32_t)0x04000000) /*!< Bit 2 */ +#define FSMC_BTR1_DATLAT_3 ((uint32_t)0x08000000) /*!< Bit 3 */ + +#define FSMC_BTR1_ACCMOD ((uint32_t)0x30000000) /*!< ACCMOD[1:0] bits (Access mode) */ +#define FSMC_BTR1_ACCMOD_0 ((uint32_t)0x10000000) /*!< Bit 0 */ +#define FSMC_BTR1_ACCMOD_1 ((uint32_t)0x20000000) /*!< Bit 1 */ + +/****************** Bit definition for FSMC_BTR2 register *******************/ +#define FSMC_BTR2_ADDSET ((uint32_t)0x0000000F) /*!< ADDSET[3:0] bits (Address setup phase duration) */ +#define FSMC_BTR2_ADDSET_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define FSMC_BTR2_ADDSET_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define FSMC_BTR2_ADDSET_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define FSMC_BTR2_ADDSET_3 ((uint32_t)0x00000008) /*!< Bit 3 */ + +#define FSMC_BTR2_ADDHLD ((uint32_t)0x000000F0) /*!< ADDHLD[3:0] bits (Address-hold phase duration) */ +#define FSMC_BTR2_ADDHLD_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define FSMC_BTR2_ADDHLD_1 ((uint32_t)0x00000020) /*!< Bit 1 */ +#define FSMC_BTR2_ADDHLD_2 ((uint32_t)0x00000040) /*!< Bit 2 */ +#define FSMC_BTR2_ADDHLD_3 ((uint32_t)0x00000080) /*!< Bit 3 */ + +#define FSMC_BTR2_DATAST ((uint32_t)0x0000FF00) /*!< DATAST [3:0] bits (Data-phase duration) */ +#define FSMC_BTR2_DATAST_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define FSMC_BTR2_DATAST_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define FSMC_BTR2_DATAST_2 ((uint32_t)0x00000400) /*!< Bit 2 */ +#define FSMC_BTR2_DATAST_3 ((uint32_t)0x00000800) /*!< Bit 3 */ + +#define FSMC_BTR2_BUSTURN ((uint32_t)0x000F0000) /*!< BUSTURN[3:0] bits (Bus turnaround phase duration) */ +#define FSMC_BTR2_BUSTURN_0 ((uint32_t)0x00010000) /*!< Bit 0 */ +#define FSMC_BTR2_BUSTURN_1 ((uint32_t)0x00020000) /*!< Bit 1 */ +#define FSMC_BTR2_BUSTURN_2 ((uint32_t)0x00040000) /*!< Bit 2 */ +#define FSMC_BTR2_BUSTURN_3 ((uint32_t)0x00080000) /*!< Bit 3 */ + +#define FSMC_BTR2_CLKDIV ((uint32_t)0x00F00000) /*!< CLKDIV[3:0] bits (Clock divide ratio) */ +#define FSMC_BTR2_CLKDIV_0 ((uint32_t)0x00100000) /*!< Bit 0 */ +#define FSMC_BTR2_CLKDIV_1 ((uint32_t)0x00200000) /*!< Bit 1 */ +#define FSMC_BTR2_CLKDIV_2 ((uint32_t)0x00400000) /*!< Bit 2 */ +#define FSMC_BTR2_CLKDIV_3 ((uint32_t)0x00800000) /*!< Bit 3 */ + +#define FSMC_BTR2_DATLAT ((uint32_t)0x0F000000) /*!< DATLA[3:0] bits (Data latency) */ +#define FSMC_BTR2_DATLAT_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define FSMC_BTR2_DATLAT_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define FSMC_BTR2_DATLAT_2 ((uint32_t)0x04000000) /*!< Bit 2 */ +#define FSMC_BTR2_DATLAT_3 ((uint32_t)0x08000000) /*!< Bit 3 */ + +#define FSMC_BTR2_ACCMOD ((uint32_t)0x30000000) /*!< ACCMOD[1:0] bits (Access mode) */ +#define FSMC_BTR2_ACCMOD_0 ((uint32_t)0x10000000) /*!< Bit 0 */ +#define FSMC_BTR2_ACCMOD_1 ((uint32_t)0x20000000) /*!< Bit 1 */ + +/******************* Bit definition for FSMC_BTR3 register *******************/ +#define FSMC_BTR3_ADDSET ((uint32_t)0x0000000F) /*!< ADDSET[3:0] bits (Address setup phase duration) */ +#define FSMC_BTR3_ADDSET_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define FSMC_BTR3_ADDSET_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define FSMC_BTR3_ADDSET_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define FSMC_BTR3_ADDSET_3 ((uint32_t)0x00000008) /*!< Bit 3 */ + +#define FSMC_BTR3_ADDHLD ((uint32_t)0x000000F0) /*!< ADDHLD[3:0] bits (Address-hold phase duration) */ +#define FSMC_BTR3_ADDHLD_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define FSMC_BTR3_ADDHLD_1 ((uint32_t)0x00000020) /*!< Bit 1 */ +#define FSMC_BTR3_ADDHLD_2 ((uint32_t)0x00000040) /*!< Bit 2 */ +#define FSMC_BTR3_ADDHLD_3 ((uint32_t)0x00000080) /*!< Bit 3 */ + +#define FSMC_BTR3_DATAST ((uint32_t)0x0000FF00) /*!< DATAST [3:0] bits (Data-phase duration) */ +#define FSMC_BTR3_DATAST_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define FSMC_BTR3_DATAST_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define FSMC_BTR3_DATAST_2 ((uint32_t)0x00000400) /*!< Bit 2 */ +#define FSMC_BTR3_DATAST_3 ((uint32_t)0x00000800) /*!< Bit 3 */ + +#define FSMC_BTR3_BUSTURN ((uint32_t)0x000F0000) /*!< BUSTURN[3:0] bits (Bus turnaround phase duration) */ +#define FSMC_BTR3_BUSTURN_0 ((uint32_t)0x00010000) /*!< Bit 0 */ +#define FSMC_BTR3_BUSTURN_1 ((uint32_t)0x00020000) /*!< Bit 1 */ +#define FSMC_BTR3_BUSTURN_2 ((uint32_t)0x00040000) /*!< Bit 2 */ +#define FSMC_BTR3_BUSTURN_3 ((uint32_t)0x00080000) /*!< Bit 3 */ + +#define FSMC_BTR3_CLKDIV ((uint32_t)0x00F00000) /*!< CLKDIV[3:0] bits (Clock divide ratio) */ +#define FSMC_BTR3_CLKDIV_0 ((uint32_t)0x00100000) /*!< Bit 0 */ +#define FSMC_BTR3_CLKDIV_1 ((uint32_t)0x00200000) /*!< Bit 1 */ +#define FSMC_BTR3_CLKDIV_2 ((uint32_t)0x00400000) /*!< Bit 2 */ +#define FSMC_BTR3_CLKDIV_3 ((uint32_t)0x00800000) /*!< Bit 3 */ + +#define FSMC_BTR3_DATLAT ((uint32_t)0x0F000000) /*!< DATLA[3:0] bits (Data latency) */ +#define FSMC_BTR3_DATLAT_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define FSMC_BTR3_DATLAT_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define FSMC_BTR3_DATLAT_2 ((uint32_t)0x04000000) /*!< Bit 2 */ +#define FSMC_BTR3_DATLAT_3 ((uint32_t)0x08000000) /*!< Bit 3 */ + +#define FSMC_BTR3_ACCMOD ((uint32_t)0x30000000) /*!< ACCMOD[1:0] bits (Access mode) */ +#define FSMC_BTR3_ACCMOD_0 ((uint32_t)0x10000000) /*!< Bit 0 */ +#define FSMC_BTR3_ACCMOD_1 ((uint32_t)0x20000000) /*!< Bit 1 */ + +/****************** Bit definition for FSMC_BTR4 register *******************/ +#define FSMC_BTR4_ADDSET ((uint32_t)0x0000000F) /*!< ADDSET[3:0] bits (Address setup phase duration) */ +#define FSMC_BTR4_ADDSET_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define FSMC_BTR4_ADDSET_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define FSMC_BTR4_ADDSET_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define FSMC_BTR4_ADDSET_3 ((uint32_t)0x00000008) /*!< Bit 3 */ + +#define FSMC_BTR4_ADDHLD ((uint32_t)0x000000F0) /*!< ADDHLD[3:0] bits (Address-hold phase duration) */ +#define FSMC_BTR4_ADDHLD_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define FSMC_BTR4_ADDHLD_1 ((uint32_t)0x00000020) /*!< Bit 1 */ +#define FSMC_BTR4_ADDHLD_2 ((uint32_t)0x00000040) /*!< Bit 2 */ +#define FSMC_BTR4_ADDHLD_3 ((uint32_t)0x00000080) /*!< Bit 3 */ + +#define FSMC_BTR4_DATAST ((uint32_t)0x0000FF00) /*!< DATAST [3:0] bits (Data-phase duration) */ +#define FSMC_BTR4_DATAST_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define FSMC_BTR4_DATAST_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define FSMC_BTR4_DATAST_2 ((uint32_t)0x00000400) /*!< Bit 2 */ +#define FSMC_BTR4_DATAST_3 ((uint32_t)0x00000800) /*!< Bit 3 */ + +#define FSMC_BTR4_BUSTURN ((uint32_t)0x000F0000) /*!< BUSTURN[3:0] bits (Bus turnaround phase duration) */ +#define FSMC_BTR4_BUSTURN_0 ((uint32_t)0x00010000) /*!< Bit 0 */ +#define FSMC_BTR4_BUSTURN_1 ((uint32_t)0x00020000) /*!< Bit 1 */ +#define FSMC_BTR4_BUSTURN_2 ((uint32_t)0x00040000) /*!< Bit 2 */ +#define FSMC_BTR4_BUSTURN_3 ((uint32_t)0x00080000) /*!< Bit 3 */ + +#define FSMC_BTR4_CLKDIV ((uint32_t)0x00F00000) /*!< CLKDIV[3:0] bits (Clock divide ratio) */ +#define FSMC_BTR4_CLKDIV_0 ((uint32_t)0x00100000) /*!< Bit 0 */ +#define FSMC_BTR4_CLKDIV_1 ((uint32_t)0x00200000) /*!< Bit 1 */ +#define FSMC_BTR4_CLKDIV_2 ((uint32_t)0x00400000) /*!< Bit 2 */ +#define FSMC_BTR4_CLKDIV_3 ((uint32_t)0x00800000) /*!< Bit 3 */ + +#define FSMC_BTR4_DATLAT ((uint32_t)0x0F000000) /*!< DATLA[3:0] bits (Data latency) */ +#define FSMC_BTR4_DATLAT_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define FSMC_BTR4_DATLAT_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define FSMC_BTR4_DATLAT_2 ((uint32_t)0x04000000) /*!< Bit 2 */ +#define FSMC_BTR4_DATLAT_3 ((uint32_t)0x08000000) /*!< Bit 3 */ + +#define FSMC_BTR4_ACCMOD ((uint32_t)0x30000000) /*!< ACCMOD[1:0] bits (Access mode) */ +#define FSMC_BTR4_ACCMOD_0 ((uint32_t)0x10000000) /*!< Bit 0 */ +#define FSMC_BTR4_ACCMOD_1 ((uint32_t)0x20000000) /*!< Bit 1 */ + +/****************** Bit definition for FSMC_BWTR1 register ******************/ +#define FSMC_BWTR1_ADDSET ((uint32_t)0x0000000F) /*!< ADDSET[3:0] bits (Address setup phase duration) */ +#define FSMC_BWTR1_ADDSET_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define FSMC_BWTR1_ADDSET_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define FSMC_BWTR1_ADDSET_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define FSMC_BWTR1_ADDSET_3 ((uint32_t)0x00000008) /*!< Bit 3 */ + +#define FSMC_BWTR1_ADDHLD ((uint32_t)0x000000F0) /*!< ADDHLD[3:0] bits (Address-hold phase duration) */ +#define FSMC_BWTR1_ADDHLD_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define FSMC_BWTR1_ADDHLD_1 ((uint32_t)0x00000020) /*!< Bit 1 */ +#define FSMC_BWTR1_ADDHLD_2 ((uint32_t)0x00000040) /*!< Bit 2 */ +#define FSMC_BWTR1_ADDHLD_3 ((uint32_t)0x00000080) /*!< Bit 3 */ + +#define FSMC_BWTR1_DATAST ((uint32_t)0x0000FF00) /*!< DATAST [3:0] bits (Data-phase duration) */ +#define FSMC_BWTR1_DATAST_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define FSMC_BWTR1_DATAST_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define FSMC_BWTR1_DATAST_2 ((uint32_t)0x00000400) /*!< Bit 2 */ +#define FSMC_BWTR1_DATAST_3 ((uint32_t)0x00000800) /*!< Bit 3 */ + +#define FSMC_BWTR1_CLKDIV ((uint32_t)0x00F00000) /*!< CLKDIV[3:0] bits (Clock divide ratio) */ +#define FSMC_BWTR1_CLKDIV_0 ((uint32_t)0x00100000) /*!< Bit 0 */ +#define FSMC_BWTR1_CLKDIV_1 ((uint32_t)0x00200000) /*!< Bit 1 */ +#define FSMC_BWTR1_CLKDIV_2 ((uint32_t)0x00400000) /*!< Bit 2 */ +#define FSMC_BWTR1_CLKDIV_3 ((uint32_t)0x00800000) /*!< Bit 3 */ + +#define FSMC_BWTR1_DATLAT ((uint32_t)0x0F000000) /*!< DATLA[3:0] bits (Data latency) */ +#define FSMC_BWTR1_DATLAT_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define FSMC_BWTR1_DATLAT_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define FSMC_BWTR1_DATLAT_2 ((uint32_t)0x04000000) /*!< Bit 2 */ +#define FSMC_BWTR1_DATLAT_3 ((uint32_t)0x08000000) /*!< Bit 3 */ + +#define FSMC_BWTR1_ACCMOD ((uint32_t)0x30000000) /*!< ACCMOD[1:0] bits (Access mode) */ +#define FSMC_BWTR1_ACCMOD_0 ((uint32_t)0x10000000) /*!< Bit 0 */ +#define FSMC_BWTR1_ACCMOD_1 ((uint32_t)0x20000000) /*!< Bit 1 */ + +/****************** Bit definition for FSMC_BWTR2 register ******************/ +#define FSMC_BWTR2_ADDSET ((uint32_t)0x0000000F) /*!< ADDSET[3:0] bits (Address setup phase duration) */ +#define FSMC_BWTR2_ADDSET_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define FSMC_BWTR2_ADDSET_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define FSMC_BWTR2_ADDSET_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define FSMC_BWTR2_ADDSET_3 ((uint32_t)0x00000008) /*!< Bit 3 */ + +#define FSMC_BWTR2_ADDHLD ((uint32_t)0x000000F0) /*!< ADDHLD[3:0] bits (Address-hold phase duration) */ +#define FSMC_BWTR2_ADDHLD_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define FSMC_BWTR2_ADDHLD_1 ((uint32_t)0x00000020) /*!< Bit 1 */ +#define FSMC_BWTR2_ADDHLD_2 ((uint32_t)0x00000040) /*!< Bit 2 */ +#define FSMC_BWTR2_ADDHLD_3 ((uint32_t)0x00000080) /*!< Bit 3 */ + +#define FSMC_BWTR2_DATAST ((uint32_t)0x0000FF00) /*!< DATAST [3:0] bits (Data-phase duration) */ +#define FSMC_BWTR2_DATAST_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define FSMC_BWTR2_DATAST_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define FSMC_BWTR2_DATAST_2 ((uint32_t)0x00000400) /*!< Bit 2 */ +#define FSMC_BWTR2_DATAST_3 ((uint32_t)0x00000800) /*!< Bit 3 */ + +#define FSMC_BWTR2_CLKDIV ((uint32_t)0x00F00000) /*!< CLKDIV[3:0] bits (Clock divide ratio) */ +#define FSMC_BWTR2_CLKDIV_0 ((uint32_t)0x00100000) /*!< Bit 0 */ +#define FSMC_BWTR2_CLKDIV_1 ((uint32_t)0x00200000) /*!< Bit 1*/ +#define FSMC_BWTR2_CLKDIV_2 ((uint32_t)0x00400000) /*!< Bit 2 */ +#define FSMC_BWTR2_CLKDIV_3 ((uint32_t)0x00800000) /*!< Bit 3 */ + +#define FSMC_BWTR2_DATLAT ((uint32_t)0x0F000000) /*!< DATLA[3:0] bits (Data latency) */ +#define FSMC_BWTR2_DATLAT_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define FSMC_BWTR2_DATLAT_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define FSMC_BWTR2_DATLAT_2 ((uint32_t)0x04000000) /*!< Bit 2 */ +#define FSMC_BWTR2_DATLAT_3 ((uint32_t)0x08000000) /*!< Bit 3 */ + +#define FSMC_BWTR2_ACCMOD ((uint32_t)0x30000000) /*!< ACCMOD[1:0] bits (Access mode) */ +#define FSMC_BWTR2_ACCMOD_0 ((uint32_t)0x10000000) /*!< Bit 0 */ +#define FSMC_BWTR2_ACCMOD_1 ((uint32_t)0x20000000) /*!< Bit 1 */ + +/****************** Bit definition for FSMC_BWTR3 register ******************/ +#define FSMC_BWTR3_ADDSET ((uint32_t)0x0000000F) /*!< ADDSET[3:0] bits (Address setup phase duration) */ +#define FSMC_BWTR3_ADDSET_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define FSMC_BWTR3_ADDSET_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define FSMC_BWTR3_ADDSET_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define FSMC_BWTR3_ADDSET_3 ((uint32_t)0x00000008) /*!< Bit 3 */ + +#define FSMC_BWTR3_ADDHLD ((uint32_t)0x000000F0) /*!< ADDHLD[3:0] bits (Address-hold phase duration) */ +#define FSMC_BWTR3_ADDHLD_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define FSMC_BWTR3_ADDHLD_1 ((uint32_t)0x00000020) /*!< Bit 1 */ +#define FSMC_BWTR3_ADDHLD_2 ((uint32_t)0x00000040) /*!< Bit 2 */ +#define FSMC_BWTR3_ADDHLD_3 ((uint32_t)0x00000080) /*!< Bit 3 */ + +#define FSMC_BWTR3_DATAST ((uint32_t)0x0000FF00) /*!< DATAST [3:0] bits (Data-phase duration) */ +#define FSMC_BWTR3_DATAST_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define FSMC_BWTR3_DATAST_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define FSMC_BWTR3_DATAST_2 ((uint32_t)0x00000400) /*!< Bit 2 */ +#define FSMC_BWTR3_DATAST_3 ((uint32_t)0x00000800) /*!< Bit 3 */ + +#define FSMC_BWTR3_CLKDIV ((uint32_t)0x00F00000) /*!< CLKDIV[3:0] bits (Clock divide ratio) */ +#define FSMC_BWTR3_CLKDIV_0 ((uint32_t)0x00100000) /*!< Bit 0 */ +#define FSMC_BWTR3_CLKDIV_1 ((uint32_t)0x00200000) /*!< Bit 1 */ +#define FSMC_BWTR3_CLKDIV_2 ((uint32_t)0x00400000) /*!< Bit 2 */ +#define FSMC_BWTR3_CLKDIV_3 ((uint32_t)0x00800000) /*!< Bit 3 */ + +#define FSMC_BWTR3_DATLAT ((uint32_t)0x0F000000) /*!< DATLA[3:0] bits (Data latency) */ +#define FSMC_BWTR3_DATLAT_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define FSMC_BWTR3_DATLAT_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define FSMC_BWTR3_DATLAT_2 ((uint32_t)0x04000000) /*!< Bit 2 */ +#define FSMC_BWTR3_DATLAT_3 ((uint32_t)0x08000000) /*!< Bit 3 */ + +#define FSMC_BWTR3_ACCMOD ((uint32_t)0x30000000) /*!< ACCMOD[1:0] bits (Access mode) */ +#define FSMC_BWTR3_ACCMOD_0 ((uint32_t)0x10000000) /*!< Bit 0 */ +#define FSMC_BWTR3_ACCMOD_1 ((uint32_t)0x20000000) /*!< Bit 1 */ + +/****************** Bit definition for FSMC_BWTR4 register ******************/ +#define FSMC_BWTR4_ADDSET ((uint32_t)0x0000000F) /*!< ADDSET[3:0] bits (Address setup phase duration) */ +#define FSMC_BWTR4_ADDSET_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define FSMC_BWTR4_ADDSET_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define FSMC_BWTR4_ADDSET_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define FSMC_BWTR4_ADDSET_3 ((uint32_t)0x00000008) /*!< Bit 3 */ + +#define FSMC_BWTR4_ADDHLD ((uint32_t)0x000000F0) /*!< ADDHLD[3:0] bits (Address-hold phase duration) */ +#define FSMC_BWTR4_ADDHLD_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define FSMC_BWTR4_ADDHLD_1 ((uint32_t)0x00000020) /*!< Bit 1 */ +#define FSMC_BWTR4_ADDHLD_2 ((uint32_t)0x00000040) /*!< Bit 2 */ +#define FSMC_BWTR4_ADDHLD_3 ((uint32_t)0x00000080) /*!< Bit 3 */ + +#define FSMC_BWTR4_DATAST ((uint32_t)0x0000FF00) /*!< DATAST [3:0] bits (Data-phase duration) */ +#define FSMC_BWTR4_DATAST_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define FSMC_BWTR4_DATAST_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define FSMC_BWTR4_DATAST_2 ((uint32_t)0x00000400) /*!< Bit 2 */ +#define FSMC_BWTR4_DATAST_3 ((uint32_t)0x00000800) /*!< Bit 3 */ + +#define FSMC_BWTR4_CLKDIV ((uint32_t)0x00F00000) /*!< CLKDIV[3:0] bits (Clock divide ratio) */ +#define FSMC_BWTR4_CLKDIV_0 ((uint32_t)0x00100000) /*!< Bit 0 */ +#define FSMC_BWTR4_CLKDIV_1 ((uint32_t)0x00200000) /*!< Bit 1 */ +#define FSMC_BWTR4_CLKDIV_2 ((uint32_t)0x00400000) /*!< Bit 2 */ +#define FSMC_BWTR4_CLKDIV_3 ((uint32_t)0x00800000) /*!< Bit 3 */ + +#define FSMC_BWTR4_DATLAT ((uint32_t)0x0F000000) /*!< DATLA[3:0] bits (Data latency) */ +#define FSMC_BWTR4_DATLAT_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define FSMC_BWTR4_DATLAT_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define FSMC_BWTR4_DATLAT_2 ((uint32_t)0x04000000) /*!< Bit 2 */ +#define FSMC_BWTR4_DATLAT_3 ((uint32_t)0x08000000) /*!< Bit 3 */ + +#define FSMC_BWTR4_ACCMOD ((uint32_t)0x30000000) /*!< ACCMOD[1:0] bits (Access mode) */ +#define FSMC_BWTR4_ACCMOD_0 ((uint32_t)0x10000000) /*!< Bit 0 */ +#define FSMC_BWTR4_ACCMOD_1 ((uint32_t)0x20000000) /*!< Bit 1 */ + +/****************** Bit definition for FSMC_PCR2 register *******************/ +#define FSMC_PCR2_PWAITEN ((uint32_t)0x00000002) /*!< Wait feature enable bit */ +#define FSMC_PCR2_PBKEN ((uint32_t)0x00000004) /*!< PC Card/NAND Flash memory bank enable bit */ +#define FSMC_PCR2_PTYP ((uint32_t)0x00000008) /*!< Memory type */ + +#define FSMC_PCR2_PWID ((uint32_t)0x00000030) /*!< PWID[1:0] bits (NAND Flash databus width) */ +#define FSMC_PCR2_PWID_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define FSMC_PCR2_PWID_1 ((uint32_t)0x00000020) /*!< Bit 1 */ + +#define FSMC_PCR2_ECCEN ((uint32_t)0x00000040) /*!< ECC computation logic enable bit */ + +#define FSMC_PCR2_TCLR ((uint32_t)0x00001E00) /*!< TCLR[3:0] bits (CLE to RE delay) */ +#define FSMC_PCR2_TCLR_0 ((uint32_t)0x00000200) /*!< Bit 0 */ +#define FSMC_PCR2_TCLR_1 ((uint32_t)0x00000400) /*!< Bit 1 */ +#define FSMC_PCR2_TCLR_2 ((uint32_t)0x00000800) /*!< Bit 2 */ +#define FSMC_PCR2_TCLR_3 ((uint32_t)0x00001000) /*!< Bit 3 */ + +#define FSMC_PCR2_TAR ((uint32_t)0x0001E000) /*!< TAR[3:0] bits (ALE to RE delay) */ +#define FSMC_PCR2_TAR_0 ((uint32_t)0x00002000) /*!< Bit 0 */ +#define FSMC_PCR2_TAR_1 ((uint32_t)0x00004000) /*!< Bit 1 */ +#define FSMC_PCR2_TAR_2 ((uint32_t)0x00008000) /*!< Bit 2 */ +#define FSMC_PCR2_TAR_3 ((uint32_t)0x00010000) /*!< Bit 3 */ + +#define FSMC_PCR2_ECCPS ((uint32_t)0x000E0000) /*!< ECCPS[1:0] bits (ECC page size) */ +#define FSMC_PCR2_ECCPS_0 ((uint32_t)0x00020000) /*!< Bit 0 */ +#define FSMC_PCR2_ECCPS_1 ((uint32_t)0x00040000) /*!< Bit 1 */ +#define FSMC_PCR2_ECCPS_2 ((uint32_t)0x00080000) /*!< Bit 2 */ + +/****************** Bit definition for FSMC_PCR3 register *******************/ +#define FSMC_PCR3_PWAITEN ((uint32_t)0x00000002) /*!< Wait feature enable bit */ +#define FSMC_PCR3_PBKEN ((uint32_t)0x00000004) /*!< PC Card/NAND Flash memory bank enable bit */ +#define FSMC_PCR3_PTYP ((uint32_t)0x00000008) /*!< Memory type */ + +#define FSMC_PCR3_PWID ((uint32_t)0x00000030) /*!< PWID[1:0] bits (NAND Flash databus width) */ +#define FSMC_PCR3_PWID_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define FSMC_PCR3_PWID_1 ((uint32_t)0x00000020) /*!< Bit 1 */ + +#define FSMC_PCR3_ECCEN ((uint32_t)0x00000040) /*!< ECC computation logic enable bit */ + +#define FSMC_PCR3_TCLR ((uint32_t)0x00001E00) /*!< TCLR[3:0] bits (CLE to RE delay) */ +#define FSMC_PCR3_TCLR_0 ((uint32_t)0x00000200) /*!< Bit 0 */ +#define FSMC_PCR3_TCLR_1 ((uint32_t)0x00000400) /*!< Bit 1 */ +#define FSMC_PCR3_TCLR_2 ((uint32_t)0x00000800) /*!< Bit 2 */ +#define FSMC_PCR3_TCLR_3 ((uint32_t)0x00001000) /*!< Bit 3 */ + +#define FSMC_PCR3_TAR ((uint32_t)0x0001E000) /*!< TAR[3:0] bits (ALE to RE delay) */ +#define FSMC_PCR3_TAR_0 ((uint32_t)0x00002000) /*!< Bit 0 */ +#define FSMC_PCR3_TAR_1 ((uint32_t)0x00004000) /*!< Bit 1 */ +#define FSMC_PCR3_TAR_2 ((uint32_t)0x00008000) /*!< Bit 2 */ +#define FSMC_PCR3_TAR_3 ((uint32_t)0x00010000) /*!< Bit 3 */ + +#define FSMC_PCR3_ECCPS ((uint32_t)0x000E0000) /*!< ECCPS[2:0] bits (ECC page size) */ +#define FSMC_PCR3_ECCPS_0 ((uint32_t)0x00020000) /*!< Bit 0 */ +#define FSMC_PCR3_ECCPS_1 ((uint32_t)0x00040000) /*!< Bit 1 */ +#define FSMC_PCR3_ECCPS_2 ((uint32_t)0x00080000) /*!< Bit 2 */ + +/****************** Bit definition for FSMC_PCR4 register *******************/ +#define FSMC_PCR4_PWAITEN ((uint32_t)0x00000002) /*!< Wait feature enable bit */ +#define FSMC_PCR4_PBKEN ((uint32_t)0x00000004) /*!< PC Card/NAND Flash memory bank enable bit */ +#define FSMC_PCR4_PTYP ((uint32_t)0x00000008) /*!< Memory type */ + +#define FSMC_PCR4_PWID ((uint32_t)0x00000030) /*!< PWID[1:0] bits (NAND Flash databus width) */ +#define FSMC_PCR4_PWID_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define FSMC_PCR4_PWID_1 ((uint32_t)0x00000020) /*!< Bit 1 */ + +#define FSMC_PCR4_ECCEN ((uint32_t)0x00000040) /*!< ECC computation logic enable bit */ + +#define FSMC_PCR4_TCLR ((uint32_t)0x00001E00) /*!< TCLR[3:0] bits (CLE to RE delay) */ +#define FSMC_PCR4_TCLR_0 ((uint32_t)0x00000200) /*!< Bit 0 */ +#define FSMC_PCR4_TCLR_1 ((uint32_t)0x00000400) /*!< Bit 1 */ +#define FSMC_PCR4_TCLR_2 ((uint32_t)0x00000800) /*!< Bit 2 */ +#define FSMC_PCR4_TCLR_3 ((uint32_t)0x00001000) /*!< Bit 3 */ + +#define FSMC_PCR4_TAR ((uint32_t)0x0001E000) /*!< TAR[3:0] bits (ALE to RE delay) */ +#define FSMC_PCR4_TAR_0 ((uint32_t)0x00002000) /*!< Bit 0 */ +#define FSMC_PCR4_TAR_1 ((uint32_t)0x00004000) /*!< Bit 1 */ +#define FSMC_PCR4_TAR_2 ((uint32_t)0x00008000) /*!< Bit 2 */ +#define FSMC_PCR4_TAR_3 ((uint32_t)0x00010000) /*!< Bit 3 */ + +#define FSMC_PCR4_ECCPS ((uint32_t)0x000E0000) /*!< ECCPS[2:0] bits (ECC page size) */ +#define FSMC_PCR4_ECCPS_0 ((uint32_t)0x00020000) /*!< Bit 0 */ +#define FSMC_PCR4_ECCPS_1 ((uint32_t)0x00040000) /*!< Bit 1 */ +#define FSMC_PCR4_ECCPS_2 ((uint32_t)0x00080000) /*!< Bit 2 */ + +/******************* Bit definition for FSMC_SR2 register *******************/ +#define FSMC_SR2_IRS ((uint8_t)0x01) /*!< Interrupt Rising Edge status */ +#define FSMC_SR2_ILS ((uint8_t)0x02) /*!< Interrupt Level status */ +#define FSMC_SR2_IFS ((uint8_t)0x04) /*!< Interrupt Falling Edge status */ +#define FSMC_SR2_IREN ((uint8_t)0x08) /*!< Interrupt Rising Edge detection Enable bit */ +#define FSMC_SR2_ILEN ((uint8_t)0x10) /*!< Interrupt Level detection Enable bit */ +#define FSMC_SR2_IFEN ((uint8_t)0x20) /*!< Interrupt Falling Edge detection Enable bit */ +#define FSMC_SR2_FEMPT ((uint8_t)0x40) /*!< FIFO empty */ + +/******************* Bit definition for FSMC_SR3 register *******************/ +#define FSMC_SR3_IRS ((uint8_t)0x01) /*!< Interrupt Rising Edge status */ +#define FSMC_SR3_ILS ((uint8_t)0x02) /*!< Interrupt Level status */ +#define FSMC_SR3_IFS ((uint8_t)0x04) /*!< Interrupt Falling Edge status */ +#define FSMC_SR3_IREN ((uint8_t)0x08) /*!< Interrupt Rising Edge detection Enable bit */ +#define FSMC_SR3_ILEN ((uint8_t)0x10) /*!< Interrupt Level detection Enable bit */ +#define FSMC_SR3_IFEN ((uint8_t)0x20) /*!< Interrupt Falling Edge detection Enable bit */ +#define FSMC_SR3_FEMPT ((uint8_t)0x40) /*!< FIFO empty */ + +/******************* Bit definition for FSMC_SR4 register *******************/ +#define FSMC_SR4_IRS ((uint8_t)0x01) /*!< Interrupt Rising Edge status */ +#define FSMC_SR4_ILS ((uint8_t)0x02) /*!< Interrupt Level status */ +#define FSMC_SR4_IFS ((uint8_t)0x04) /*!< Interrupt Falling Edge status */ +#define FSMC_SR4_IREN ((uint8_t)0x08) /*!< Interrupt Rising Edge detection Enable bit */ +#define FSMC_SR4_ILEN ((uint8_t)0x10) /*!< Interrupt Level detection Enable bit */ +#define FSMC_SR4_IFEN ((uint8_t)0x20) /*!< Interrupt Falling Edge detection Enable bit */ +#define FSMC_SR4_FEMPT ((uint8_t)0x40) /*!< FIFO empty */ + +/****************** Bit definition for FSMC_PMEM2 register ******************/ +#define FSMC_PMEM2_MEMSET2 ((uint32_t)0x000000FF) /*!< MEMSET2[7:0] bits (Common memory 2 setup time) */ +#define FSMC_PMEM2_MEMSET2_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define FSMC_PMEM2_MEMSET2_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define FSMC_PMEM2_MEMSET2_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define FSMC_PMEM2_MEMSET2_3 ((uint32_t)0x00000008) /*!< Bit 3 */ +#define FSMC_PMEM2_MEMSET2_4 ((uint32_t)0x00000010) /*!< Bit 4 */ +#define FSMC_PMEM2_MEMSET2_5 ((uint32_t)0x00000020) /*!< Bit 5 */ +#define FSMC_PMEM2_MEMSET2_6 ((uint32_t)0x00000040) /*!< Bit 6 */ +#define FSMC_PMEM2_MEMSET2_7 ((uint32_t)0x00000080) /*!< Bit 7 */ + +#define FSMC_PMEM2_MEMWAIT2 ((uint32_t)0x0000FF00) /*!< MEMWAIT2[7:0] bits (Common memory 2 wait time) */ +#define FSMC_PMEM2_MEMWAIT2_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define FSMC_PMEM2_MEMWAIT2_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define FSMC_PMEM2_MEMWAIT2_2 ((uint32_t)0x00000400) /*!< Bit 2 */ +#define FSMC_PMEM2_MEMWAIT2_3 ((uint32_t)0x00000800) /*!< Bit 3 */ +#define FSMC_PMEM2_MEMWAIT2_4 ((uint32_t)0x00001000) /*!< Bit 4 */ +#define FSMC_PMEM2_MEMWAIT2_5 ((uint32_t)0x00002000) /*!< Bit 5 */ +#define FSMC_PMEM2_MEMWAIT2_6 ((uint32_t)0x00004000) /*!< Bit 6 */ +#define FSMC_PMEM2_MEMWAIT2_7 ((uint32_t)0x00008000) /*!< Bit 7 */ + +#define FSMC_PMEM2_MEMHOLD2 ((uint32_t)0x00FF0000) /*!< MEMHOLD2[7:0] bits (Common memory 2 hold time) */ +#define FSMC_PMEM2_MEMHOLD2_0 ((uint32_t)0x00010000) /*!< Bit 0 */ +#define FSMC_PMEM2_MEMHOLD2_1 ((uint32_t)0x00020000) /*!< Bit 1 */ +#define FSMC_PMEM2_MEMHOLD2_2 ((uint32_t)0x00040000) /*!< Bit 2 */ +#define FSMC_PMEM2_MEMHOLD2_3 ((uint32_t)0x00080000) /*!< Bit 3 */ +#define FSMC_PMEM2_MEMHOLD2_4 ((uint32_t)0x00100000) /*!< Bit 4 */ +#define FSMC_PMEM2_MEMHOLD2_5 ((uint32_t)0x00200000) /*!< Bit 5 */ +#define FSMC_PMEM2_MEMHOLD2_6 ((uint32_t)0x00400000) /*!< Bit 6 */ +#define FSMC_PMEM2_MEMHOLD2_7 ((uint32_t)0x00800000) /*!< Bit 7 */ + +#define FSMC_PMEM2_MEMHIZ2 ((uint32_t)0xFF000000) /*!< MEMHIZ2[7:0] bits (Common memory 2 databus HiZ time) */ +#define FSMC_PMEM2_MEMHIZ2_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define FSMC_PMEM2_MEMHIZ2_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define FSMC_PMEM2_MEMHIZ2_2 ((uint32_t)0x04000000) /*!< Bit 2 */ +#define FSMC_PMEM2_MEMHIZ2_3 ((uint32_t)0x08000000) /*!< Bit 3 */ +#define FSMC_PMEM2_MEMHIZ2_4 ((uint32_t)0x10000000) /*!< Bit 4 */ +#define FSMC_PMEM2_MEMHIZ2_5 ((uint32_t)0x20000000) /*!< Bit 5 */ +#define FSMC_PMEM2_MEMHIZ2_6 ((uint32_t)0x40000000) /*!< Bit 6 */ +#define FSMC_PMEM2_MEMHIZ2_7 ((uint32_t)0x80000000) /*!< Bit 7 */ + +/****************** Bit definition for FSMC_PMEM3 register ******************/ +#define FSMC_PMEM3_MEMSET3 ((uint32_t)0x000000FF) /*!< MEMSET3[7:0] bits (Common memory 3 setup time) */ +#define FSMC_PMEM3_MEMSET3_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define FSMC_PMEM3_MEMSET3_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define FSMC_PMEM3_MEMSET3_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define FSMC_PMEM3_MEMSET3_3 ((uint32_t)0x00000008) /*!< Bit 3 */ +#define FSMC_PMEM3_MEMSET3_4 ((uint32_t)0x00000010) /*!< Bit 4 */ +#define FSMC_PMEM3_MEMSET3_5 ((uint32_t)0x00000020) /*!< Bit 5 */ +#define FSMC_PMEM3_MEMSET3_6 ((uint32_t)0x00000040) /*!< Bit 6 */ +#define FSMC_PMEM3_MEMSET3_7 ((uint32_t)0x00000080) /*!< Bit 7 */ + +#define FSMC_PMEM3_MEMWAIT3 ((uint32_t)0x0000FF00) /*!< MEMWAIT3[7:0] bits (Common memory 3 wait time) */ +#define FSMC_PMEM3_MEMWAIT3_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define FSMC_PMEM3_MEMWAIT3_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define FSMC_PMEM3_MEMWAIT3_2 ((uint32_t)0x00000400) /*!< Bit 2 */ +#define FSMC_PMEM3_MEMWAIT3_3 ((uint32_t)0x00000800) /*!< Bit 3 */ +#define FSMC_PMEM3_MEMWAIT3_4 ((uint32_t)0x00001000) /*!< Bit 4 */ +#define FSMC_PMEM3_MEMWAIT3_5 ((uint32_t)0x00002000) /*!< Bit 5 */ +#define FSMC_PMEM3_MEMWAIT3_6 ((uint32_t)0x00004000) /*!< Bit 6 */ +#define FSMC_PMEM3_MEMWAIT3_7 ((uint32_t)0x00008000) /*!< Bit 7 */ + +#define FSMC_PMEM3_MEMHOLD3 ((uint32_t)0x00FF0000) /*!< MEMHOLD3[7:0] bits (Common memory 3 hold time) */ +#define FSMC_PMEM3_MEMHOLD3_0 ((uint32_t)0x00010000) /*!< Bit 0 */ +#define FSMC_PMEM3_MEMHOLD3_1 ((uint32_t)0x00020000) /*!< Bit 1 */ +#define FSMC_PMEM3_MEMHOLD3_2 ((uint32_t)0x00040000) /*!< Bit 2 */ +#define FSMC_PMEM3_MEMHOLD3_3 ((uint32_t)0x00080000) /*!< Bit 3 */ +#define FSMC_PMEM3_MEMHOLD3_4 ((uint32_t)0x00100000) /*!< Bit 4 */ +#define FSMC_PMEM3_MEMHOLD3_5 ((uint32_t)0x00200000) /*!< Bit 5 */ +#define FSMC_PMEM3_MEMHOLD3_6 ((uint32_t)0x00400000) /*!< Bit 6 */ +#define FSMC_PMEM3_MEMHOLD3_7 ((uint32_t)0x00800000) /*!< Bit 7 */ + +#define FSMC_PMEM3_MEMHIZ3 ((uint32_t)0xFF000000) /*!< MEMHIZ3[7:0] bits (Common memory 3 databus HiZ time) */ +#define FSMC_PMEM3_MEMHIZ3_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define FSMC_PMEM3_MEMHIZ3_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define FSMC_PMEM3_MEMHIZ3_2 ((uint32_t)0x04000000) /*!< Bit 2 */ +#define FSMC_PMEM3_MEMHIZ3_3 ((uint32_t)0x08000000) /*!< Bit 3 */ +#define FSMC_PMEM3_MEMHIZ3_4 ((uint32_t)0x10000000) /*!< Bit 4 */ +#define FSMC_PMEM3_MEMHIZ3_5 ((uint32_t)0x20000000) /*!< Bit 5 */ +#define FSMC_PMEM3_MEMHIZ3_6 ((uint32_t)0x40000000) /*!< Bit 6 */ +#define FSMC_PMEM3_MEMHIZ3_7 ((uint32_t)0x80000000) /*!< Bit 7 */ + +/****************** Bit definition for FSMC_PMEM4 register ******************/ +#define FSMC_PMEM4_MEMSET4 ((uint32_t)0x000000FF) /*!< MEMSET4[7:0] bits (Common memory 4 setup time) */ +#define FSMC_PMEM4_MEMSET4_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define FSMC_PMEM4_MEMSET4_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define FSMC_PMEM4_MEMSET4_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define FSMC_PMEM4_MEMSET4_3 ((uint32_t)0x00000008) /*!< Bit 3 */ +#define FSMC_PMEM4_MEMSET4_4 ((uint32_t)0x00000010) /*!< Bit 4 */ +#define FSMC_PMEM4_MEMSET4_5 ((uint32_t)0x00000020) /*!< Bit 5 */ +#define FSMC_PMEM4_MEMSET4_6 ((uint32_t)0x00000040) /*!< Bit 6 */ +#define FSMC_PMEM4_MEMSET4_7 ((uint32_t)0x00000080) /*!< Bit 7 */ + +#define FSMC_PMEM4_MEMWAIT4 ((uint32_t)0x0000FF00) /*!< MEMWAIT4[7:0] bits (Common memory 4 wait time) */ +#define FSMC_PMEM4_MEMWAIT4_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define FSMC_PMEM4_MEMWAIT4_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define FSMC_PMEM4_MEMWAIT4_2 ((uint32_t)0x00000400) /*!< Bit 2 */ +#define FSMC_PMEM4_MEMWAIT4_3 ((uint32_t)0x00000800) /*!< Bit 3 */ +#define FSMC_PMEM4_MEMWAIT4_4 ((uint32_t)0x00001000) /*!< Bit 4 */ +#define FSMC_PMEM4_MEMWAIT4_5 ((uint32_t)0x00002000) /*!< Bit 5 */ +#define FSMC_PMEM4_MEMWAIT4_6 ((uint32_t)0x00004000) /*!< Bit 6 */ +#define FSMC_PMEM4_MEMWAIT4_7 ((uint32_t)0x00008000) /*!< Bit 7 */ + +#define FSMC_PMEM4_MEMHOLD4 ((uint32_t)0x00FF0000) /*!< MEMHOLD4[7:0] bits (Common memory 4 hold time) */ +#define FSMC_PMEM4_MEMHOLD4_0 ((uint32_t)0x00010000) /*!< Bit 0 */ +#define FSMC_PMEM4_MEMHOLD4_1 ((uint32_t)0x00020000) /*!< Bit 1 */ +#define FSMC_PMEM4_MEMHOLD4_2 ((uint32_t)0x00040000) /*!< Bit 2 */ +#define FSMC_PMEM4_MEMHOLD4_3 ((uint32_t)0x00080000) /*!< Bit 3 */ +#define FSMC_PMEM4_MEMHOLD4_4 ((uint32_t)0x00100000) /*!< Bit 4 */ +#define FSMC_PMEM4_MEMHOLD4_5 ((uint32_t)0x00200000) /*!< Bit 5 */ +#define FSMC_PMEM4_MEMHOLD4_6 ((uint32_t)0x00400000) /*!< Bit 6 */ +#define FSMC_PMEM4_MEMHOLD4_7 ((uint32_t)0x00800000) /*!< Bit 7 */ + +#define FSMC_PMEM4_MEMHIZ4 ((uint32_t)0xFF000000) /*!< MEMHIZ4[7:0] bits (Common memory 4 databus HiZ time) */ +#define FSMC_PMEM4_MEMHIZ4_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define FSMC_PMEM4_MEMHIZ4_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define FSMC_PMEM4_MEMHIZ4_2 ((uint32_t)0x04000000) /*!< Bit 2 */ +#define FSMC_PMEM4_MEMHIZ4_3 ((uint32_t)0x08000000) /*!< Bit 3 */ +#define FSMC_PMEM4_MEMHIZ4_4 ((uint32_t)0x10000000) /*!< Bit 4 */ +#define FSMC_PMEM4_MEMHIZ4_5 ((uint32_t)0x20000000) /*!< Bit 5 */ +#define FSMC_PMEM4_MEMHIZ4_6 ((uint32_t)0x40000000) /*!< Bit 6 */ +#define FSMC_PMEM4_MEMHIZ4_7 ((uint32_t)0x80000000) /*!< Bit 7 */ + +/****************** Bit definition for FSMC_PATT2 register ******************/ +#define FSMC_PATT2_ATTSET2 ((uint32_t)0x000000FF) /*!< ATTSET2[7:0] bits (Attribute memory 2 setup time) */ +#define FSMC_PATT2_ATTSET2_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define FSMC_PATT2_ATTSET2_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define FSMC_PATT2_ATTSET2_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define FSMC_PATT2_ATTSET2_3 ((uint32_t)0x00000008) /*!< Bit 3 */ +#define FSMC_PATT2_ATTSET2_4 ((uint32_t)0x00000010) /*!< Bit 4 */ +#define FSMC_PATT2_ATTSET2_5 ((uint32_t)0x00000020) /*!< Bit 5 */ +#define FSMC_PATT2_ATTSET2_6 ((uint32_t)0x00000040) /*!< Bit 6 */ +#define FSMC_PATT2_ATTSET2_7 ((uint32_t)0x00000080) /*!< Bit 7 */ + +#define FSMC_PATT2_ATTWAIT2 ((uint32_t)0x0000FF00) /*!< ATTWAIT2[7:0] bits (Attribute memory 2 wait time) */ +#define FSMC_PATT2_ATTWAIT2_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define FSMC_PATT2_ATTWAIT2_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define FSMC_PATT2_ATTWAIT2_2 ((uint32_t)0x00000400) /*!< Bit 2 */ +#define FSMC_PATT2_ATTWAIT2_3 ((uint32_t)0x00000800) /*!< Bit 3 */ +#define FSMC_PATT2_ATTWAIT2_4 ((uint32_t)0x00001000) /*!< Bit 4 */ +#define FSMC_PATT2_ATTWAIT2_5 ((uint32_t)0x00002000) /*!< Bit 5 */ +#define FSMC_PATT2_ATTWAIT2_6 ((uint32_t)0x00004000) /*!< Bit 6 */ +#define FSMC_PATT2_ATTWAIT2_7 ((uint32_t)0x00008000) /*!< Bit 7 */ + +#define FSMC_PATT2_ATTHOLD2 ((uint32_t)0x00FF0000) /*!< ATTHOLD2[7:0] bits (Attribute memory 2 hold time) */ +#define FSMC_PATT2_ATTHOLD2_0 ((uint32_t)0x00010000) /*!< Bit 0 */ +#define FSMC_PATT2_ATTHOLD2_1 ((uint32_t)0x00020000) /*!< Bit 1 */ +#define FSMC_PATT2_ATTHOLD2_2 ((uint32_t)0x00040000) /*!< Bit 2 */ +#define FSMC_PATT2_ATTHOLD2_3 ((uint32_t)0x00080000) /*!< Bit 3 */ +#define FSMC_PATT2_ATTHOLD2_4 ((uint32_t)0x00100000) /*!< Bit 4 */ +#define FSMC_PATT2_ATTHOLD2_5 ((uint32_t)0x00200000) /*!< Bit 5 */ +#define FSMC_PATT2_ATTHOLD2_6 ((uint32_t)0x00400000) /*!< Bit 6 */ +#define FSMC_PATT2_ATTHOLD2_7 ((uint32_t)0x00800000) /*!< Bit 7 */ + +#define FSMC_PATT2_ATTHIZ2 ((uint32_t)0xFF000000) /*!< ATTHIZ2[7:0] bits (Attribute memory 2 databus HiZ time) */ +#define FSMC_PATT2_ATTHIZ2_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define FSMC_PATT2_ATTHIZ2_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define FSMC_PATT2_ATTHIZ2_2 ((uint32_t)0x04000000) /*!< Bit 2 */ +#define FSMC_PATT2_ATTHIZ2_3 ((uint32_t)0x08000000) /*!< Bit 3 */ +#define FSMC_PATT2_ATTHIZ2_4 ((uint32_t)0x10000000) /*!< Bit 4 */ +#define FSMC_PATT2_ATTHIZ2_5 ((uint32_t)0x20000000) /*!< Bit 5 */ +#define FSMC_PATT2_ATTHIZ2_6 ((uint32_t)0x40000000) /*!< Bit 6 */ +#define FSMC_PATT2_ATTHIZ2_7 ((uint32_t)0x80000000) /*!< Bit 7 */ + +/****************** Bit definition for FSMC_PATT3 register ******************/ +#define FSMC_PATT3_ATTSET3 ((uint32_t)0x000000FF) /*!< ATTSET3[7:0] bits (Attribute memory 3 setup time) */ +#define FSMC_PATT3_ATTSET3_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define FSMC_PATT3_ATTSET3_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define FSMC_PATT3_ATTSET3_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define FSMC_PATT3_ATTSET3_3 ((uint32_t)0x00000008) /*!< Bit 3 */ +#define FSMC_PATT3_ATTSET3_4 ((uint32_t)0x00000010) /*!< Bit 4 */ +#define FSMC_PATT3_ATTSET3_5 ((uint32_t)0x00000020) /*!< Bit 5 */ +#define FSMC_PATT3_ATTSET3_6 ((uint32_t)0x00000040) /*!< Bit 6 */ +#define FSMC_PATT3_ATTSET3_7 ((uint32_t)0x00000080) /*!< Bit 7 */ + +#define FSMC_PATT3_ATTWAIT3 ((uint32_t)0x0000FF00) /*!< ATTWAIT3[7:0] bits (Attribute memory 3 wait time) */ +#define FSMC_PATT3_ATTWAIT3_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define FSMC_PATT3_ATTWAIT3_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define FSMC_PATT3_ATTWAIT3_2 ((uint32_t)0x00000400) /*!< Bit 2 */ +#define FSMC_PATT3_ATTWAIT3_3 ((uint32_t)0x00000800) /*!< Bit 3 */ +#define FSMC_PATT3_ATTWAIT3_4 ((uint32_t)0x00001000) /*!< Bit 4 */ +#define FSMC_PATT3_ATTWAIT3_5 ((uint32_t)0x00002000) /*!< Bit 5 */ +#define FSMC_PATT3_ATTWAIT3_6 ((uint32_t)0x00004000) /*!< Bit 6 */ +#define FSMC_PATT3_ATTWAIT3_7 ((uint32_t)0x00008000) /*!< Bit 7 */ + +#define FSMC_PATT3_ATTHOLD3 ((uint32_t)0x00FF0000) /*!< ATTHOLD3[7:0] bits (Attribute memory 3 hold time) */ +#define FSMC_PATT3_ATTHOLD3_0 ((uint32_t)0x00010000) /*!< Bit 0 */ +#define FSMC_PATT3_ATTHOLD3_1 ((uint32_t)0x00020000) /*!< Bit 1 */ +#define FSMC_PATT3_ATTHOLD3_2 ((uint32_t)0x00040000) /*!< Bit 2 */ +#define FSMC_PATT3_ATTHOLD3_3 ((uint32_t)0x00080000) /*!< Bit 3 */ +#define FSMC_PATT3_ATTHOLD3_4 ((uint32_t)0x00100000) /*!< Bit 4 */ +#define FSMC_PATT3_ATTHOLD3_5 ((uint32_t)0x00200000) /*!< Bit 5 */ +#define FSMC_PATT3_ATTHOLD3_6 ((uint32_t)0x00400000) /*!< Bit 6 */ +#define FSMC_PATT3_ATTHOLD3_7 ((uint32_t)0x00800000) /*!< Bit 7 */ + +#define FSMC_PATT3_ATTHIZ3 ((uint32_t)0xFF000000) /*!< ATTHIZ3[7:0] bits (Attribute memory 3 databus HiZ time) */ +#define FSMC_PATT3_ATTHIZ3_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define FSMC_PATT3_ATTHIZ3_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define FSMC_PATT3_ATTHIZ3_2 ((uint32_t)0x04000000) /*!< Bit 2 */ +#define FSMC_PATT3_ATTHIZ3_3 ((uint32_t)0x08000000) /*!< Bit 3 */ +#define FSMC_PATT3_ATTHIZ3_4 ((uint32_t)0x10000000) /*!< Bit 4 */ +#define FSMC_PATT3_ATTHIZ3_5 ((uint32_t)0x20000000) /*!< Bit 5 */ +#define FSMC_PATT3_ATTHIZ3_6 ((uint32_t)0x40000000) /*!< Bit 6 */ +#define FSMC_PATT3_ATTHIZ3_7 ((uint32_t)0x80000000) /*!< Bit 7 */ + +/****************** Bit definition for FSMC_PATT4 register ******************/ +#define FSMC_PATT4_ATTSET4 ((uint32_t)0x000000FF) /*!< ATTSET4[7:0] bits (Attribute memory 4 setup time) */ +#define FSMC_PATT4_ATTSET4_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define FSMC_PATT4_ATTSET4_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define FSMC_PATT4_ATTSET4_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define FSMC_PATT4_ATTSET4_3 ((uint32_t)0x00000008) /*!< Bit 3 */ +#define FSMC_PATT4_ATTSET4_4 ((uint32_t)0x00000010) /*!< Bit 4 */ +#define FSMC_PATT4_ATTSET4_5 ((uint32_t)0x00000020) /*!< Bit 5 */ +#define FSMC_PATT4_ATTSET4_6 ((uint32_t)0x00000040) /*!< Bit 6 */ +#define FSMC_PATT4_ATTSET4_7 ((uint32_t)0x00000080) /*!< Bit 7 */ + +#define FSMC_PATT4_ATTWAIT4 ((uint32_t)0x0000FF00) /*!< ATTWAIT4[7:0] bits (Attribute memory 4 wait time) */ +#define FSMC_PATT4_ATTWAIT4_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define FSMC_PATT4_ATTWAIT4_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define FSMC_PATT4_ATTWAIT4_2 ((uint32_t)0x00000400) /*!< Bit 2 */ +#define FSMC_PATT4_ATTWAIT4_3 ((uint32_t)0x00000800) /*!< Bit 3 */ +#define FSMC_PATT4_ATTWAIT4_4 ((uint32_t)0x00001000) /*!< Bit 4 */ +#define FSMC_PATT4_ATTWAIT4_5 ((uint32_t)0x00002000) /*!< Bit 5 */ +#define FSMC_PATT4_ATTWAIT4_6 ((uint32_t)0x00004000) /*!< Bit 6 */ +#define FSMC_PATT4_ATTWAIT4_7 ((uint32_t)0x00008000) /*!< Bit 7 */ + +#define FSMC_PATT4_ATTHOLD4 ((uint32_t)0x00FF0000) /*!< ATTHOLD4[7:0] bits (Attribute memory 4 hold time) */ +#define FSMC_PATT4_ATTHOLD4_0 ((uint32_t)0x00010000) /*!< Bit 0 */ +#define FSMC_PATT4_ATTHOLD4_1 ((uint32_t)0x00020000) /*!< Bit 1 */ +#define FSMC_PATT4_ATTHOLD4_2 ((uint32_t)0x00040000) /*!< Bit 2 */ +#define FSMC_PATT4_ATTHOLD4_3 ((uint32_t)0x00080000) /*!< Bit 3 */ +#define FSMC_PATT4_ATTHOLD4_4 ((uint32_t)0x00100000) /*!< Bit 4 */ +#define FSMC_PATT4_ATTHOLD4_5 ((uint32_t)0x00200000) /*!< Bit 5 */ +#define FSMC_PATT4_ATTHOLD4_6 ((uint32_t)0x00400000) /*!< Bit 6 */ +#define FSMC_PATT4_ATTHOLD4_7 ((uint32_t)0x00800000) /*!< Bit 7 */ + +#define FSMC_PATT4_ATTHIZ4 ((uint32_t)0xFF000000) /*!< ATTHIZ4[7:0] bits (Attribute memory 4 databus HiZ time) */ +#define FSMC_PATT4_ATTHIZ4_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define FSMC_PATT4_ATTHIZ4_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define FSMC_PATT4_ATTHIZ4_2 ((uint32_t)0x04000000) /*!< Bit 2 */ +#define FSMC_PATT4_ATTHIZ4_3 ((uint32_t)0x08000000) /*!< Bit 3 */ +#define FSMC_PATT4_ATTHIZ4_4 ((uint32_t)0x10000000) /*!< Bit 4 */ +#define FSMC_PATT4_ATTHIZ4_5 ((uint32_t)0x20000000) /*!< Bit 5 */ +#define FSMC_PATT4_ATTHIZ4_6 ((uint32_t)0x40000000) /*!< Bit 6 */ +#define FSMC_PATT4_ATTHIZ4_7 ((uint32_t)0x80000000) /*!< Bit 7 */ + +/****************** Bit definition for FSMC_PIO4 register *******************/ +#define FSMC_PIO4_IOSET4 ((uint32_t)0x000000FF) /*!< IOSET4[7:0] bits (I/O 4 setup time) */ +#define FSMC_PIO4_IOSET4_0 ((uint32_t)0x00000001) /*!< Bit 0 */ +#define FSMC_PIO4_IOSET4_1 ((uint32_t)0x00000002) /*!< Bit 1 */ +#define FSMC_PIO4_IOSET4_2 ((uint32_t)0x00000004) /*!< Bit 2 */ +#define FSMC_PIO4_IOSET4_3 ((uint32_t)0x00000008) /*!< Bit 3 */ +#define FSMC_PIO4_IOSET4_4 ((uint32_t)0x00000010) /*!< Bit 4 */ +#define FSMC_PIO4_IOSET4_5 ((uint32_t)0x00000020) /*!< Bit 5 */ +#define FSMC_PIO4_IOSET4_6 ((uint32_t)0x00000040) /*!< Bit 6 */ +#define FSMC_PIO4_IOSET4_7 ((uint32_t)0x00000080) /*!< Bit 7 */ + +#define FSMC_PIO4_IOWAIT4 ((uint32_t)0x0000FF00) /*!< IOWAIT4[7:0] bits (I/O 4 wait time) */ +#define FSMC_PIO4_IOWAIT4_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define FSMC_PIO4_IOWAIT4_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define FSMC_PIO4_IOWAIT4_2 ((uint32_t)0x00000400) /*!< Bit 2 */ +#define FSMC_PIO4_IOWAIT4_3 ((uint32_t)0x00000800) /*!< Bit 3 */ +#define FSMC_PIO4_IOWAIT4_4 ((uint32_t)0x00001000) /*!< Bit 4 */ +#define FSMC_PIO4_IOWAIT4_5 ((uint32_t)0x00002000) /*!< Bit 5 */ +#define FSMC_PIO4_IOWAIT4_6 ((uint32_t)0x00004000) /*!< Bit 6 */ +#define FSMC_PIO4_IOWAIT4_7 ((uint32_t)0x00008000) /*!< Bit 7 */ + +#define FSMC_PIO4_IOHOLD4 ((uint32_t)0x00FF0000) /*!< IOHOLD4[7:0] bits (I/O 4 hold time) */ +#define FSMC_PIO4_IOHOLD4_0 ((uint32_t)0x00010000) /*!< Bit 0 */ +#define FSMC_PIO4_IOHOLD4_1 ((uint32_t)0x00020000) /*!< Bit 1 */ +#define FSMC_PIO4_IOHOLD4_2 ((uint32_t)0x00040000) /*!< Bit 2 */ +#define FSMC_PIO4_IOHOLD4_3 ((uint32_t)0x00080000) /*!< Bit 3 */ +#define FSMC_PIO4_IOHOLD4_4 ((uint32_t)0x00100000) /*!< Bit 4 */ +#define FSMC_PIO4_IOHOLD4_5 ((uint32_t)0x00200000) /*!< Bit 5 */ +#define FSMC_PIO4_IOHOLD4_6 ((uint32_t)0x00400000) /*!< Bit 6 */ +#define FSMC_PIO4_IOHOLD4_7 ((uint32_t)0x00800000) /*!< Bit 7 */ + +#define FSMC_PIO4_IOHIZ4 ((uint32_t)0xFF000000) /*!< IOHIZ4[7:0] bits (I/O 4 databus HiZ time) */ +#define FSMC_PIO4_IOHIZ4_0 ((uint32_t)0x01000000) /*!< Bit 0 */ +#define FSMC_PIO4_IOHIZ4_1 ((uint32_t)0x02000000) /*!< Bit 1 */ +#define FSMC_PIO4_IOHIZ4_2 ((uint32_t)0x04000000) /*!< Bit 2 */ +#define FSMC_PIO4_IOHIZ4_3 ((uint32_t)0x08000000) /*!< Bit 3 */ +#define FSMC_PIO4_IOHIZ4_4 ((uint32_t)0x10000000) /*!< Bit 4 */ +#define FSMC_PIO4_IOHIZ4_5 ((uint32_t)0x20000000) /*!< Bit 5 */ +#define FSMC_PIO4_IOHIZ4_6 ((uint32_t)0x40000000) /*!< Bit 6 */ +#define FSMC_PIO4_IOHIZ4_7 ((uint32_t)0x80000000) /*!< Bit 7 */ + +/****************** Bit definition for FSMC_ECCR2 register ******************/ +#define FSMC_ECCR2_ECC2 ((uint32_t)0xFFFFFFFF) /*!< ECC result */ + +/****************** Bit definition for FSMC_ECCR3 register ******************/ +#define FSMC_ECCR3_ECC3 ((uint32_t)0xFFFFFFFF) /*!< ECC result */ + +/******************************************************************************/ +/* */ +/* SD host Interface */ +/* */ +/******************************************************************************/ + +/****************** Bit definition for SDIO_POWER register ******************/ +#define SDIO_POWER_PWRCTRL ((uint8_t)0x03) /*!< PWRCTRL[1:0] bits (Power supply control bits) */ +#define SDIO_POWER_PWRCTRL_0 ((uint8_t)0x01) /*!< Bit 0 */ +#define SDIO_POWER_PWRCTRL_1 ((uint8_t)0x02) /*!< Bit 1 */ + +/****************** Bit definition for SDIO_CLKCR register ******************/ +#define SDIO_CLKCR_CLKDIV ((uint16_t)0x00FF) /*!< Clock divide factor */ +#define SDIO_CLKCR_CLKEN ((uint16_t)0x0100) /*!< Clock enable bit */ +#define SDIO_CLKCR_PWRSAV ((uint16_t)0x0200) /*!< Power saving configuration bit */ +#define SDIO_CLKCR_BYPASS ((uint16_t)0x0400) /*!< Clock divider bypass enable bit */ + +#define SDIO_CLKCR_WIDBUS ((uint16_t)0x1800) /*!< WIDBUS[1:0] bits (Wide bus mode enable bit) */ +#define SDIO_CLKCR_WIDBUS_0 ((uint16_t)0x0800) /*!< Bit 0 */ +#define SDIO_CLKCR_WIDBUS_1 ((uint16_t)0x1000) /*!< Bit 1 */ + +#define SDIO_CLKCR_NEGEDGE ((uint16_t)0x2000) /*!< SDIO_CK dephasing selection bit */ +#define SDIO_CLKCR_HWFC_EN ((uint16_t)0x4000) /*!< HW Flow Control enable */ + +/******************* Bit definition for SDIO_ARG register *******************/ +#define SDIO_ARG_CMDARG ((uint32_t)0xFFFFFFFF) /*!< Command argument */ + +/******************* Bit definition for SDIO_CMD register *******************/ +#define SDIO_CMD_CMDINDEX ((uint16_t)0x003F) /*!< Command Index */ + +#define SDIO_CMD_WAITRESP ((uint16_t)0x00C0) /*!< WAITRESP[1:0] bits (Wait for response bits) */ +#define SDIO_CMD_WAITRESP_0 ((uint16_t)0x0040) /*!< Bit 0 */ +#define SDIO_CMD_WAITRESP_1 ((uint16_t)0x0080) /*!< Bit 1 */ + +#define SDIO_CMD_WAITINT ((uint16_t)0x0100) /*!< CPSM Waits for Interrupt Request */ +#define SDIO_CMD_WAITPEND ((uint16_t)0x0200) /*!< CPSM Waits for ends of data transfer (CmdPend internal signal) */ +#define SDIO_CMD_CPSMEN ((uint16_t)0x0400) /*!< Command path state machine (CPSM) Enable bit */ +#define SDIO_CMD_SDIOSUSPEND ((uint16_t)0x0800) /*!< SD I/O suspend command */ +#define SDIO_CMD_ENCMDCOMPL ((uint16_t)0x1000) /*!< Enable CMD completion */ +#define SDIO_CMD_NIEN ((uint16_t)0x2000) /*!< Not Interrupt Enable */ +#define SDIO_CMD_CEATACMD ((uint16_t)0x4000) /*!< CE-ATA command */ + +/***************** Bit definition for SDIO_RESPCMD register *****************/ +#define SDIO_RESPCMD_RESPCMD ((uint8_t)0x3F) /*!< Response command index */ + +/****************** Bit definition for SDIO_RESP0 register ******************/ +#define SDIO_RESP0_CARDSTATUS0 ((uint32_t)0xFFFFFFFF) /*!< Card Status */ + +/****************** Bit definition for SDIO_RESP1 register ******************/ +#define SDIO_RESP1_CARDSTATUS1 ((uint32_t)0xFFFFFFFF) /*!< Card Status */ + +/****************** Bit definition for SDIO_RESP2 register ******************/ +#define SDIO_RESP2_CARDSTATUS2 ((uint32_t)0xFFFFFFFF) /*!< Card Status */ + +/****************** Bit definition for SDIO_RESP3 register ******************/ +#define SDIO_RESP3_CARDSTATUS3 ((uint32_t)0xFFFFFFFF) /*!< Card Status */ + +/****************** Bit definition for SDIO_RESP4 register ******************/ +#define SDIO_RESP4_CARDSTATUS4 ((uint32_t)0xFFFFFFFF) /*!< Card Status */ + +/****************** Bit definition for SDIO_DTIMER register *****************/ +#define SDIO_DTIMER_DATATIME ((uint32_t)0xFFFFFFFF) /*!< Data timeout period. */ + +/****************** Bit definition for SDIO_DLEN register *******************/ +#define SDIO_DLEN_DATALENGTH ((uint32_t)0x01FFFFFF) /*!< Data length value */ + +/****************** Bit definition for SDIO_DCTRL register ******************/ +#define SDIO_DCTRL_DTEN ((uint16_t)0x0001) /*!< Data transfer enabled bit */ +#define SDIO_DCTRL_DTDIR ((uint16_t)0x0002) /*!< Data transfer direction selection */ +#define SDIO_DCTRL_DTMODE ((uint16_t)0x0004) /*!< Data transfer mode selection */ +#define SDIO_DCTRL_DMAEN ((uint16_t)0x0008) /*!< DMA enabled bit */ + +#define SDIO_DCTRL_DBLOCKSIZE ((uint16_t)0x00F0) /*!< DBLOCKSIZE[3:0] bits (Data block size) */ +#define SDIO_DCTRL_DBLOCKSIZE_0 ((uint16_t)0x0010) /*!< Bit 0 */ +#define SDIO_DCTRL_DBLOCKSIZE_1 ((uint16_t)0x0020) /*!< Bit 1 */ +#define SDIO_DCTRL_DBLOCKSIZE_2 ((uint16_t)0x0040) /*!< Bit 2 */ +#define SDIO_DCTRL_DBLOCKSIZE_3 ((uint16_t)0x0080) /*!< Bit 3 */ + +#define SDIO_DCTRL_RWSTART ((uint16_t)0x0100) /*!< Read wait start */ +#define SDIO_DCTRL_RWSTOP ((uint16_t)0x0200) /*!< Read wait stop */ +#define SDIO_DCTRL_RWMOD ((uint16_t)0x0400) /*!< Read wait mode */ +#define SDIO_DCTRL_SDIOEN ((uint16_t)0x0800) /*!< SD I/O enable functions */ + +/****************** Bit definition for SDIO_DCOUNT register *****************/ +#define SDIO_DCOUNT_DATACOUNT ((uint32_t)0x01FFFFFF) /*!< Data count value */ + +/****************** Bit definition for SDIO_STA register ********************/ +#define SDIO_STA_CCRCFAIL ((uint32_t)0x00000001) /*!< Command response received (CRC check failed) */ +#define SDIO_STA_DCRCFAIL ((uint32_t)0x00000002) /*!< Data block sent/received (CRC check failed) */ +#define SDIO_STA_CTIMEOUT ((uint32_t)0x00000004) /*!< Command response timeout */ +#define SDIO_STA_DTIMEOUT ((uint32_t)0x00000008) /*!< Data timeout */ +#define SDIO_STA_TXUNDERR ((uint32_t)0x00000010) /*!< Transmit FIFO underrun error */ +#define SDIO_STA_RXOVERR ((uint32_t)0x00000020) /*!< Received FIFO overrun error */ +#define SDIO_STA_CMDREND ((uint32_t)0x00000040) /*!< Command response received (CRC check passed) */ +#define SDIO_STA_CMDSENT ((uint32_t)0x00000080) /*!< Command sent (no response required) */ +#define SDIO_STA_DATAEND ((uint32_t)0x00000100) /*!< Data end (data counter, SDIDCOUNT, is zero) */ +#define SDIO_STA_STBITERR ((uint32_t)0x00000200) /*!< Start bit not detected on all data signals in wide bus mode */ +#define SDIO_STA_DBCKEND ((uint32_t)0x00000400) /*!< Data block sent/received (CRC check passed) */ +#define SDIO_STA_CMDACT ((uint32_t)0x00000800) /*!< Command transfer in progress */ +#define SDIO_STA_TXACT ((uint32_t)0x00001000) /*!< Data transmit in progress */ +#define SDIO_STA_RXACT ((uint32_t)0x00002000) /*!< Data receive in progress */ +#define SDIO_STA_TXFIFOHE ((uint32_t)0x00004000) /*!< Transmit FIFO Half Empty: at least 8 words can be written into the FIFO */ +#define SDIO_STA_RXFIFOHF ((uint32_t)0x00008000) /*!< Receive FIFO Half Full: there are at least 8 words in the FIFO */ +#define SDIO_STA_TXFIFOF ((uint32_t)0x00010000) /*!< Transmit FIFO full */ +#define SDIO_STA_RXFIFOF ((uint32_t)0x00020000) /*!< Receive FIFO full */ +#define SDIO_STA_TXFIFOE ((uint32_t)0x00040000) /*!< Transmit FIFO empty */ +#define SDIO_STA_RXFIFOE ((uint32_t)0x00080000) /*!< Receive FIFO empty */ +#define SDIO_STA_TXDAVL ((uint32_t)0x00100000) /*!< Data available in transmit FIFO */ +#define SDIO_STA_RXDAVL ((uint32_t)0x00200000) /*!< Data available in receive FIFO */ +#define SDIO_STA_SDIOIT ((uint32_t)0x00400000) /*!< SDIO interrupt received */ +#define SDIO_STA_CEATAEND ((uint32_t)0x00800000) /*!< CE-ATA command completion signal received for CMD61 */ + +/******************* Bit definition for SDIO_ICR register *******************/ +#define SDIO_ICR_CCRCFAILC ((uint32_t)0x00000001) /*!< CCRCFAIL flag clear bit */ +#define SDIO_ICR_DCRCFAILC ((uint32_t)0x00000002) /*!< DCRCFAIL flag clear bit */ +#define SDIO_ICR_CTIMEOUTC ((uint32_t)0x00000004) /*!< CTIMEOUT flag clear bit */ +#define SDIO_ICR_DTIMEOUTC ((uint32_t)0x00000008) /*!< DTIMEOUT flag clear bit */ +#define SDIO_ICR_TXUNDERRC ((uint32_t)0x00000010) /*!< TXUNDERR flag clear bit */ +#define SDIO_ICR_RXOVERRC ((uint32_t)0x00000020) /*!< RXOVERR flag clear bit */ +#define SDIO_ICR_CMDRENDC ((uint32_t)0x00000040) /*!< CMDREND flag clear bit */ +#define SDIO_ICR_CMDSENTC ((uint32_t)0x00000080) /*!< CMDSENT flag clear bit */ +#define SDIO_ICR_DATAENDC ((uint32_t)0x00000100) /*!< DATAEND flag clear bit */ +#define SDIO_ICR_STBITERRC ((uint32_t)0x00000200) /*!< STBITERR flag clear bit */ +#define SDIO_ICR_DBCKENDC ((uint32_t)0x00000400) /*!< DBCKEND flag clear bit */ +#define SDIO_ICR_SDIOITC ((uint32_t)0x00400000) /*!< SDIOIT flag clear bit */ +#define SDIO_ICR_CEATAENDC ((uint32_t)0x00800000) /*!< CEATAEND flag clear bit */ + +/****************** Bit definition for SDIO_MASK register *******************/ +#define SDIO_MASK_CCRCFAILIE ((uint32_t)0x00000001) /*!< Command CRC Fail Interrupt Enable */ +#define SDIO_MASK_DCRCFAILIE ((uint32_t)0x00000002) /*!< Data CRC Fail Interrupt Enable */ +#define SDIO_MASK_CTIMEOUTIE ((uint32_t)0x00000004) /*!< Command TimeOut Interrupt Enable */ +#define SDIO_MASK_DTIMEOUTIE ((uint32_t)0x00000008) /*!< Data TimeOut Interrupt Enable */ +#define SDIO_MASK_TXUNDERRIE ((uint32_t)0x00000010) /*!< Tx FIFO UnderRun Error Interrupt Enable */ +#define SDIO_MASK_RXOVERRIE ((uint32_t)0x00000020) /*!< Rx FIFO OverRun Error Interrupt Enable */ +#define SDIO_MASK_CMDRENDIE ((uint32_t)0x00000040) /*!< Command Response Received Interrupt Enable */ +#define SDIO_MASK_CMDSENTIE ((uint32_t)0x00000080) /*!< Command Sent Interrupt Enable */ +#define SDIO_MASK_DATAENDIE ((uint32_t)0x00000100) /*!< Data End Interrupt Enable */ +#define SDIO_MASK_STBITERRIE ((uint32_t)0x00000200) /*!< Start Bit Error Interrupt Enable */ +#define SDIO_MASK_DBCKENDIE ((uint32_t)0x00000400) /*!< Data Block End Interrupt Enable */ +#define SDIO_MASK_CMDACTIE ((uint32_t)0x00000800) /*!< Command Acting Interrupt Enable */ +#define SDIO_MASK_TXACTIE ((uint32_t)0x00001000) /*!< Data Transmit Acting Interrupt Enable */ +#define SDIO_MASK_RXACTIE ((uint32_t)0x00002000) /*!< Data receive acting interrupt enabled */ +#define SDIO_MASK_TXFIFOHEIE ((uint32_t)0x00004000) /*!< Tx FIFO Half Empty interrupt Enable */ +#define SDIO_MASK_RXFIFOHFIE ((uint32_t)0x00008000) /*!< Rx FIFO Half Full interrupt Enable */ +#define SDIO_MASK_TXFIFOFIE ((uint32_t)0x00010000) /*!< Tx FIFO Full interrupt Enable */ +#define SDIO_MASK_RXFIFOFIE ((uint32_t)0x00020000) /*!< Rx FIFO Full interrupt Enable */ +#define SDIO_MASK_TXFIFOEIE ((uint32_t)0x00040000) /*!< Tx FIFO Empty interrupt Enable */ +#define SDIO_MASK_RXFIFOEIE ((uint32_t)0x00080000) /*!< Rx FIFO Empty interrupt Enable */ +#define SDIO_MASK_TXDAVLIE ((uint32_t)0x00100000) /*!< Data available in Tx FIFO interrupt Enable */ +#define SDIO_MASK_RXDAVLIE ((uint32_t)0x00200000) /*!< Data available in Rx FIFO interrupt Enable */ +#define SDIO_MASK_SDIOITIE ((uint32_t)0x00400000) /*!< SDIO Mode Interrupt Received interrupt Enable */ +#define SDIO_MASK_CEATAENDIE ((uint32_t)0x00800000) /*!< CE-ATA command completion signal received Interrupt Enable */ + +/***************** Bit definition for SDIO_FIFOCNT register *****************/ +#define SDIO_FIFOCNT_FIFOCOUNT ((uint32_t)0x00FFFFFF) /*!< Remaining number of words to be written to or read from the FIFO */ + +/****************** Bit definition for SDIO_FIFO register *******************/ +#define SDIO_FIFO_FIFODATA ((uint32_t)0xFFFFFFFF) /*!< Receive and transmit FIFO data */ + +/******************************************************************************/ +/* */ +/* USB Device FS */ +/* */ +/******************************************************************************/ + +/*!< Endpoint-specific registers */ +/******************* Bit definition for USB_EP0R register *******************/ +#define USB_EP0R_EA ((uint16_t)0x000F) /*!< Endpoint Address */ + +#define USB_EP0R_STAT_TX ((uint16_t)0x0030) /*!< STAT_TX[1:0] bits (Status bits, for transmission transfers) */ +#define USB_EP0R_STAT_TX_0 ((uint16_t)0x0010) /*!< Bit 0 */ +#define USB_EP0R_STAT_TX_1 ((uint16_t)0x0020) /*!< Bit 1 */ + +#define USB_EP0R_DTOG_TX ((uint16_t)0x0040) /*!< Data Toggle, for transmission transfers */ +#define USB_EP0R_CTR_TX ((uint16_t)0x0080) /*!< Correct Transfer for transmission */ +#define USB_EP0R_EP_KIND ((uint16_t)0x0100) /*!< Endpoint Kind */ + +#define USB_EP0R_EP_TYPE ((uint16_t)0x0600) /*!< EP_TYPE[1:0] bits (Endpoint type) */ +#define USB_EP0R_EP_TYPE_0 ((uint16_t)0x0200) /*!< Bit 0 */ +#define USB_EP0R_EP_TYPE_1 ((uint16_t)0x0400) /*!< Bit 1 */ + +#define USB_EP0R_SETUP ((uint16_t)0x0800) /*!< Setup transaction completed */ + +#define USB_EP0R_STAT_RX ((uint16_t)0x3000) /*!< STAT_RX[1:0] bits (Status bits, for reception transfers) */ +#define USB_EP0R_STAT_RX_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define USB_EP0R_STAT_RX_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define USB_EP0R_DTOG_RX ((uint16_t)0x4000) /*!< Data Toggle, for reception transfers */ +#define USB_EP0R_CTR_RX ((uint16_t)0x8000) /*!< Correct Transfer for reception */ + +/******************* Bit definition for USB_EP1R register *******************/ +#define USB_EP1R_EA ((uint16_t)0x000F) /*!< Endpoint Address */ + +#define USB_EP1R_STAT_TX ((uint16_t)0x0030) /*!< STAT_TX[1:0] bits (Status bits, for transmission transfers) */ +#define USB_EP1R_STAT_TX_0 ((uint16_t)0x0010) /*!< Bit 0 */ +#define USB_EP1R_STAT_TX_1 ((uint16_t)0x0020) /*!< Bit 1 */ + +#define USB_EP1R_DTOG_TX ((uint16_t)0x0040) /*!< Data Toggle, for transmission transfers */ +#define USB_EP1R_CTR_TX ((uint16_t)0x0080) /*!< Correct Transfer for transmission */ +#define USB_EP1R_EP_KIND ((uint16_t)0x0100) /*!< Endpoint Kind */ + +#define USB_EP1R_EP_TYPE ((uint16_t)0x0600) /*!< EP_TYPE[1:0] bits (Endpoint type) */ +#define USB_EP1R_EP_TYPE_0 ((uint16_t)0x0200) /*!< Bit 0 */ +#define USB_EP1R_EP_TYPE_1 ((uint16_t)0x0400) /*!< Bit 1 */ + +#define USB_EP1R_SETUP ((uint16_t)0x0800) /*!< Setup transaction completed */ + +#define USB_EP1R_STAT_RX ((uint16_t)0x3000) /*!< STAT_RX[1:0] bits (Status bits, for reception transfers) */ +#define USB_EP1R_STAT_RX_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define USB_EP1R_STAT_RX_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define USB_EP1R_DTOG_RX ((uint16_t)0x4000) /*!< Data Toggle, for reception transfers */ +#define USB_EP1R_CTR_RX ((uint16_t)0x8000) /*!< Correct Transfer for reception */ + +/******************* Bit definition for USB_EP2R register *******************/ +#define USB_EP2R_EA ((uint16_t)0x000F) /*!< Endpoint Address */ + +#define USB_EP2R_STAT_TX ((uint16_t)0x0030) /*!< STAT_TX[1:0] bits (Status bits, for transmission transfers) */ +#define USB_EP2R_STAT_TX_0 ((uint16_t)0x0010) /*!< Bit 0 */ +#define USB_EP2R_STAT_TX_1 ((uint16_t)0x0020) /*!< Bit 1 */ + +#define USB_EP2R_DTOG_TX ((uint16_t)0x0040) /*!< Data Toggle, for transmission transfers */ +#define USB_EP2R_CTR_TX ((uint16_t)0x0080) /*!< Correct Transfer for transmission */ +#define USB_EP2R_EP_KIND ((uint16_t)0x0100) /*!< Endpoint Kind */ + +#define USB_EP2R_EP_TYPE ((uint16_t)0x0600) /*!< EP_TYPE[1:0] bits (Endpoint type) */ +#define USB_EP2R_EP_TYPE_0 ((uint16_t)0x0200) /*!< Bit 0 */ +#define USB_EP2R_EP_TYPE_1 ((uint16_t)0x0400) /*!< Bit 1 */ + +#define USB_EP2R_SETUP ((uint16_t)0x0800) /*!< Setup transaction completed */ + +#define USB_EP2R_STAT_RX ((uint16_t)0x3000) /*!< STAT_RX[1:0] bits (Status bits, for reception transfers) */ +#define USB_EP2R_STAT_RX_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define USB_EP2R_STAT_RX_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define USB_EP2R_DTOG_RX ((uint16_t)0x4000) /*!< Data Toggle, for reception transfers */ +#define USB_EP2R_CTR_RX ((uint16_t)0x8000) /*!< Correct Transfer for reception */ + +/******************* Bit definition for USB_EP3R register *******************/ +#define USB_EP3R_EA ((uint16_t)0x000F) /*!< Endpoint Address */ + +#define USB_EP3R_STAT_TX ((uint16_t)0x0030) /*!< STAT_TX[1:0] bits (Status bits, for transmission transfers) */ +#define USB_EP3R_STAT_TX_0 ((uint16_t)0x0010) /*!< Bit 0 */ +#define USB_EP3R_STAT_TX_1 ((uint16_t)0x0020) /*!< Bit 1 */ + +#define USB_EP3R_DTOG_TX ((uint16_t)0x0040) /*!< Data Toggle, for transmission transfers */ +#define USB_EP3R_CTR_TX ((uint16_t)0x0080) /*!< Correct Transfer for transmission */ +#define USB_EP3R_EP_KIND ((uint16_t)0x0100) /*!< Endpoint Kind */ + +#define USB_EP3R_EP_TYPE ((uint16_t)0x0600) /*!< EP_TYPE[1:0] bits (Endpoint type) */ +#define USB_EP3R_EP_TYPE_0 ((uint16_t)0x0200) /*!< Bit 0 */ +#define USB_EP3R_EP_TYPE_1 ((uint16_t)0x0400) /*!< Bit 1 */ + +#define USB_EP3R_SETUP ((uint16_t)0x0800) /*!< Setup transaction completed */ + +#define USB_EP3R_STAT_RX ((uint16_t)0x3000) /*!< STAT_RX[1:0] bits (Status bits, for reception transfers) */ +#define USB_EP3R_STAT_RX_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define USB_EP3R_STAT_RX_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define USB_EP3R_DTOG_RX ((uint16_t)0x4000) /*!< Data Toggle, for reception transfers */ +#define USB_EP3R_CTR_RX ((uint16_t)0x8000) /*!< Correct Transfer for reception */ + +/******************* Bit definition for USB_EP4R register *******************/ +#define USB_EP4R_EA ((uint16_t)0x000F) /*!< Endpoint Address */ + +#define USB_EP4R_STAT_TX ((uint16_t)0x0030) /*!< STAT_TX[1:0] bits (Status bits, for transmission transfers) */ +#define USB_EP4R_STAT_TX_0 ((uint16_t)0x0010) /*!< Bit 0 */ +#define USB_EP4R_STAT_TX_1 ((uint16_t)0x0020) /*!< Bit 1 */ + +#define USB_EP4R_DTOG_TX ((uint16_t)0x0040) /*!< Data Toggle, for transmission transfers */ +#define USB_EP4R_CTR_TX ((uint16_t)0x0080) /*!< Correct Transfer for transmission */ +#define USB_EP4R_EP_KIND ((uint16_t)0x0100) /*!< Endpoint Kind */ + +#define USB_EP4R_EP_TYPE ((uint16_t)0x0600) /*!< EP_TYPE[1:0] bits (Endpoint type) */ +#define USB_EP4R_EP_TYPE_0 ((uint16_t)0x0200) /*!< Bit 0 */ +#define USB_EP4R_EP_TYPE_1 ((uint16_t)0x0400) /*!< Bit 1 */ + +#define USB_EP4R_SETUP ((uint16_t)0x0800) /*!< Setup transaction completed */ + +#define USB_EP4R_STAT_RX ((uint16_t)0x3000) /*!< STAT_RX[1:0] bits (Status bits, for reception transfers) */ +#define USB_EP4R_STAT_RX_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define USB_EP4R_STAT_RX_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define USB_EP4R_DTOG_RX ((uint16_t)0x4000) /*!< Data Toggle, for reception transfers */ +#define USB_EP4R_CTR_RX ((uint16_t)0x8000) /*!< Correct Transfer for reception */ + +/******************* Bit definition for USB_EP5R register *******************/ +#define USB_EP5R_EA ((uint16_t)0x000F) /*!< Endpoint Address */ + +#define USB_EP5R_STAT_TX ((uint16_t)0x0030) /*!< STAT_TX[1:0] bits (Status bits, for transmission transfers) */ +#define USB_EP5R_STAT_TX_0 ((uint16_t)0x0010) /*!< Bit 0 */ +#define USB_EP5R_STAT_TX_1 ((uint16_t)0x0020) /*!< Bit 1 */ + +#define USB_EP5R_DTOG_TX ((uint16_t)0x0040) /*!< Data Toggle, for transmission transfers */ +#define USB_EP5R_CTR_TX ((uint16_t)0x0080) /*!< Correct Transfer for transmission */ +#define USB_EP5R_EP_KIND ((uint16_t)0x0100) /*!< Endpoint Kind */ + +#define USB_EP5R_EP_TYPE ((uint16_t)0x0600) /*!< EP_TYPE[1:0] bits (Endpoint type) */ +#define USB_EP5R_EP_TYPE_0 ((uint16_t)0x0200) /*!< Bit 0 */ +#define USB_EP5R_EP_TYPE_1 ((uint16_t)0x0400) /*!< Bit 1 */ + +#define USB_EP5R_SETUP ((uint16_t)0x0800) /*!< Setup transaction completed */ + +#define USB_EP5R_STAT_RX ((uint16_t)0x3000) /*!< STAT_RX[1:0] bits (Status bits, for reception transfers) */ +#define USB_EP5R_STAT_RX_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define USB_EP5R_STAT_RX_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define USB_EP5R_DTOG_RX ((uint16_t)0x4000) /*!< Data Toggle, for reception transfers */ +#define USB_EP5R_CTR_RX ((uint16_t)0x8000) /*!< Correct Transfer for reception */ + +/******************* Bit definition for USB_EP6R register *******************/ +#define USB_EP6R_EA ((uint16_t)0x000F) /*!< Endpoint Address */ + +#define USB_EP6R_STAT_TX ((uint16_t)0x0030) /*!< STAT_TX[1:0] bits (Status bits, for transmission transfers) */ +#define USB_EP6R_STAT_TX_0 ((uint16_t)0x0010) /*!< Bit 0 */ +#define USB_EP6R_STAT_TX_1 ((uint16_t)0x0020) /*!< Bit 1 */ + +#define USB_EP6R_DTOG_TX ((uint16_t)0x0040) /*!< Data Toggle, for transmission transfers */ +#define USB_EP6R_CTR_TX ((uint16_t)0x0080) /*!< Correct Transfer for transmission */ +#define USB_EP6R_EP_KIND ((uint16_t)0x0100) /*!< Endpoint Kind */ + +#define USB_EP6R_EP_TYPE ((uint16_t)0x0600) /*!< EP_TYPE[1:0] bits (Endpoint type) */ +#define USB_EP6R_EP_TYPE_0 ((uint16_t)0x0200) /*!< Bit 0 */ +#define USB_EP6R_EP_TYPE_1 ((uint16_t)0x0400) /*!< Bit 1 */ + +#define USB_EP6R_SETUP ((uint16_t)0x0800) /*!< Setup transaction completed */ + +#define USB_EP6R_STAT_RX ((uint16_t)0x3000) /*!< STAT_RX[1:0] bits (Status bits, for reception transfers) */ +#define USB_EP6R_STAT_RX_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define USB_EP6R_STAT_RX_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define USB_EP6R_DTOG_RX ((uint16_t)0x4000) /*!< Data Toggle, for reception transfers */ +#define USB_EP6R_CTR_RX ((uint16_t)0x8000) /*!< Correct Transfer for reception */ + +/******************* Bit definition for USB_EP7R register *******************/ +#define USB_EP7R_EA ((uint16_t)0x000F) /*!< Endpoint Address */ + +#define USB_EP7R_STAT_TX ((uint16_t)0x0030) /*!< STAT_TX[1:0] bits (Status bits, for transmission transfers) */ +#define USB_EP7R_STAT_TX_0 ((uint16_t)0x0010) /*!< Bit 0 */ +#define USB_EP7R_STAT_TX_1 ((uint16_t)0x0020) /*!< Bit 1 */ + +#define USB_EP7R_DTOG_TX ((uint16_t)0x0040) /*!< Data Toggle, for transmission transfers */ +#define USB_EP7R_CTR_TX ((uint16_t)0x0080) /*!< Correct Transfer for transmission */ +#define USB_EP7R_EP_KIND ((uint16_t)0x0100) /*!< Endpoint Kind */ + +#define USB_EP7R_EP_TYPE ((uint16_t)0x0600) /*!< EP_TYPE[1:0] bits (Endpoint type) */ +#define USB_EP7R_EP_TYPE_0 ((uint16_t)0x0200) /*!< Bit 0 */ +#define USB_EP7R_EP_TYPE_1 ((uint16_t)0x0400) /*!< Bit 1 */ + +#define USB_EP7R_SETUP ((uint16_t)0x0800) /*!< Setup transaction completed */ + +#define USB_EP7R_STAT_RX ((uint16_t)0x3000) /*!< STAT_RX[1:0] bits (Status bits, for reception transfers) */ +#define USB_EP7R_STAT_RX_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define USB_EP7R_STAT_RX_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define USB_EP7R_DTOG_RX ((uint16_t)0x4000) /*!< Data Toggle, for reception transfers */ +#define USB_EP7R_CTR_RX ((uint16_t)0x8000) /*!< Correct Transfer for reception */ + +/*!< Common registers */ +/******************* Bit definition for USB_CNTR register *******************/ +#define USB_CNTR_FRES ((uint16_t)0x0001) /*!< Force USB Reset */ +#define USB_CNTR_PDWN ((uint16_t)0x0002) /*!< Power down */ +#define USB_CNTR_LP_MODE ((uint16_t)0x0004) /*!< Low-power mode */ +#define USB_CNTR_FSUSP ((uint16_t)0x0008) /*!< Force suspend */ +#define USB_CNTR_RESUME ((uint16_t)0x0010) /*!< Resume request */ +#define USB_CNTR_ESOFM ((uint16_t)0x0100) /*!< Expected Start Of Frame Interrupt Mask */ +#define USB_CNTR_SOFM ((uint16_t)0x0200) /*!< Start Of Frame Interrupt Mask */ +#define USB_CNTR_RESETM ((uint16_t)0x0400) /*!< RESET Interrupt Mask */ +#define USB_CNTR_SUSPM ((uint16_t)0x0800) /*!< Suspend mode Interrupt Mask */ +#define USB_CNTR_WKUPM ((uint16_t)0x1000) /*!< Wakeup Interrupt Mask */ +#define USB_CNTR_ERRM ((uint16_t)0x2000) /*!< Error Interrupt Mask */ +#define USB_CNTR_PMAOVRM ((uint16_t)0x4000) /*!< Packet Memory Area Over / Underrun Interrupt Mask */ +#define USB_CNTR_CTRM ((uint16_t)0x8000) /*!< Correct Transfer Interrupt Mask */ + +/******************* Bit definition for USB_ISTR register *******************/ +#define USB_ISTR_EP_ID ((uint16_t)0x000F) /*!< Endpoint Identifier */ +#define USB_ISTR_DIR ((uint16_t)0x0010) /*!< Direction of transaction */ +#define USB_ISTR_ESOF ((uint16_t)0x0100) /*!< Expected Start Of Frame */ +#define USB_ISTR_SOF ((uint16_t)0x0200) /*!< Start Of Frame */ +#define USB_ISTR_RESET ((uint16_t)0x0400) /*!< USB RESET request */ +#define USB_ISTR_SUSP ((uint16_t)0x0800) /*!< Suspend mode request */ +#define USB_ISTR_WKUP ((uint16_t)0x1000) /*!< Wake up */ +#define USB_ISTR_ERR ((uint16_t)0x2000) /*!< Error */ +#define USB_ISTR_PMAOVR ((uint16_t)0x4000) /*!< Packet Memory Area Over / Underrun */ +#define USB_ISTR_CTR ((uint16_t)0x8000) /*!< Correct Transfer */ + +/******************* Bit definition for USB_FNR register ********************/ +#define USB_FNR_FN ((uint16_t)0x07FF) /*!< Frame Number */ +#define USB_FNR_LSOF ((uint16_t)0x1800) /*!< Lost SOF */ +#define USB_FNR_LCK ((uint16_t)0x2000) /*!< Locked */ +#define USB_FNR_RXDM ((uint16_t)0x4000) /*!< Receive Data - Line Status */ +#define USB_FNR_RXDP ((uint16_t)0x8000) /*!< Receive Data + Line Status */ + +/****************** Bit definition for USB_DADDR register *******************/ +#define USB_DADDR_ADD ((uint8_t)0x7F) /*!< ADD[6:0] bits (Device Address) */ +#define USB_DADDR_ADD0 ((uint8_t)0x01) /*!< Bit 0 */ +#define USB_DADDR_ADD1 ((uint8_t)0x02) /*!< Bit 1 */ +#define USB_DADDR_ADD2 ((uint8_t)0x04) /*!< Bit 2 */ +#define USB_DADDR_ADD3 ((uint8_t)0x08) /*!< Bit 3 */ +#define USB_DADDR_ADD4 ((uint8_t)0x10) /*!< Bit 4 */ +#define USB_DADDR_ADD5 ((uint8_t)0x20) /*!< Bit 5 */ +#define USB_DADDR_ADD6 ((uint8_t)0x40) /*!< Bit 6 */ + +#define USB_DADDR_EF ((uint8_t)0x80) /*!< Enable Function */ + +/****************** Bit definition for USB_BTABLE register ******************/ +#define USB_BTABLE_BTABLE ((uint16_t)0xFFF8) /*!< Buffer Table */ + +/*!< Buffer descriptor table */ +/***************** Bit definition for USB_ADDR0_TX register *****************/ +#define USB_ADDR0_TX_ADDR0_TX ((uint16_t)0xFFFE) /*!< Transmission Buffer Address 0 */ + +/***************** Bit definition for USB_ADDR1_TX register *****************/ +#define USB_ADDR1_TX_ADDR1_TX ((uint16_t)0xFFFE) /*!< Transmission Buffer Address 1 */ + +/***************** Bit definition for USB_ADDR2_TX register *****************/ +#define USB_ADDR2_TX_ADDR2_TX ((uint16_t)0xFFFE) /*!< Transmission Buffer Address 2 */ + +/***************** Bit definition for USB_ADDR3_TX register *****************/ +#define USB_ADDR3_TX_ADDR3_TX ((uint16_t)0xFFFE) /*!< Transmission Buffer Address 3 */ + +/***************** Bit definition for USB_ADDR4_TX register *****************/ +#define USB_ADDR4_TX_ADDR4_TX ((uint16_t)0xFFFE) /*!< Transmission Buffer Address 4 */ + +/***************** Bit definition for USB_ADDR5_TX register *****************/ +#define USB_ADDR5_TX_ADDR5_TX ((uint16_t)0xFFFE) /*!< Transmission Buffer Address 5 */ + +/***************** Bit definition for USB_ADDR6_TX register *****************/ +#define USB_ADDR6_TX_ADDR6_TX ((uint16_t)0xFFFE) /*!< Transmission Buffer Address 6 */ + +/***************** Bit definition for USB_ADDR7_TX register *****************/ +#define USB_ADDR7_TX_ADDR7_TX ((uint16_t)0xFFFE) /*!< Transmission Buffer Address 7 */ + +/*----------------------------------------------------------------------------*/ + +/***************** Bit definition for USB_COUNT0_TX register ****************/ +#define USB_COUNT0_TX_COUNT0_TX ((uint16_t)0x03FF) /*!< Transmission Byte Count 0 */ + +/***************** Bit definition for USB_COUNT1_TX register ****************/ +#define USB_COUNT1_TX_COUNT1_TX ((uint16_t)0x03FF) /*!< Transmission Byte Count 1 */ + +/***************** Bit definition for USB_COUNT2_TX register ****************/ +#define USB_COUNT2_TX_COUNT2_TX ((uint16_t)0x03FF) /*!< Transmission Byte Count 2 */ + +/***************** Bit definition for USB_COUNT3_TX register ****************/ +#define USB_COUNT3_TX_COUNT3_TX ((uint16_t)0x03FF) /*!< Transmission Byte Count 3 */ + +/***************** Bit definition for USB_COUNT4_TX register ****************/ +#define USB_COUNT4_TX_COUNT4_TX ((uint16_t)0x03FF) /*!< Transmission Byte Count 4 */ + +/***************** Bit definition for USB_COUNT5_TX register ****************/ +#define USB_COUNT5_TX_COUNT5_TX ((uint16_t)0x03FF) /*!< Transmission Byte Count 5 */ + +/***************** Bit definition for USB_COUNT6_TX register ****************/ +#define USB_COUNT6_TX_COUNT6_TX ((uint16_t)0x03FF) /*!< Transmission Byte Count 6 */ + +/***************** Bit definition for USB_COUNT7_TX register ****************/ +#define USB_COUNT7_TX_COUNT7_TX ((uint16_t)0x03FF) /*!< Transmission Byte Count 7 */ + +/*----------------------------------------------------------------------------*/ + +/**************** Bit definition for USB_COUNT0_TX_0 register ***************/ +#define USB_COUNT0_TX_0_COUNT0_TX_0 ((uint32_t)0x000003FF) /*!< Transmission Byte Count 0 (low) */ + +/**************** Bit definition for USB_COUNT0_TX_1 register ***************/ +#define USB_COUNT0_TX_1_COUNT0_TX_1 ((uint32_t)0x03FF0000) /*!< Transmission Byte Count 0 (high) */ + +/**************** Bit definition for USB_COUNT1_TX_0 register ***************/ +#define USB_COUNT1_TX_0_COUNT1_TX_0 ((uint32_t)0x000003FF) /*!< Transmission Byte Count 1 (low) */ + +/**************** Bit definition for USB_COUNT1_TX_1 register ***************/ +#define USB_COUNT1_TX_1_COUNT1_TX_1 ((uint32_t)0x03FF0000) /*!< Transmission Byte Count 1 (high) */ + +/**************** Bit definition for USB_COUNT2_TX_0 register ***************/ +#define USB_COUNT2_TX_0_COUNT2_TX_0 ((uint32_t)0x000003FF) /*!< Transmission Byte Count 2 (low) */ + +/**************** Bit definition for USB_COUNT2_TX_1 register ***************/ +#define USB_COUNT2_TX_1_COUNT2_TX_1 ((uint32_t)0x03FF0000) /*!< Transmission Byte Count 2 (high) */ + +/**************** Bit definition for USB_COUNT3_TX_0 register ***************/ +#define USB_COUNT3_TX_0_COUNT3_TX_0 ((uint16_t)0x000003FF) /*!< Transmission Byte Count 3 (low) */ + +/**************** Bit definition for USB_COUNT3_TX_1 register ***************/ +#define USB_COUNT3_TX_1_COUNT3_TX_1 ((uint16_t)0x03FF0000) /*!< Transmission Byte Count 3 (high) */ + +/**************** Bit definition for USB_COUNT4_TX_0 register ***************/ +#define USB_COUNT4_TX_0_COUNT4_TX_0 ((uint32_t)0x000003FF) /*!< Transmission Byte Count 4 (low) */ + +/**************** Bit definition for USB_COUNT4_TX_1 register ***************/ +#define USB_COUNT4_TX_1_COUNT4_TX_1 ((uint32_t)0x03FF0000) /*!< Transmission Byte Count 4 (high) */ + +/**************** Bit definition for USB_COUNT5_TX_0 register ***************/ +#define USB_COUNT5_TX_0_COUNT5_TX_0 ((uint32_t)0x000003FF) /*!< Transmission Byte Count 5 (low) */ + +/**************** Bit definition for USB_COUNT5_TX_1 register ***************/ +#define USB_COUNT5_TX_1_COUNT5_TX_1 ((uint32_t)0x03FF0000) /*!< Transmission Byte Count 5 (high) */ + +/**************** Bit definition for USB_COUNT6_TX_0 register ***************/ +#define USB_COUNT6_TX_0_COUNT6_TX_0 ((uint32_t)0x000003FF) /*!< Transmission Byte Count 6 (low) */ + +/**************** Bit definition for USB_COUNT6_TX_1 register ***************/ +#define USB_COUNT6_TX_1_COUNT6_TX_1 ((uint32_t)0x03FF0000) /*!< Transmission Byte Count 6 (high) */ + +/**************** Bit definition for USB_COUNT7_TX_0 register ***************/ +#define USB_COUNT7_TX_0_COUNT7_TX_0 ((uint32_t)0x000003FF) /*!< Transmission Byte Count 7 (low) */ + +/**************** Bit definition for USB_COUNT7_TX_1 register ***************/ +#define USB_COUNT7_TX_1_COUNT7_TX_1 ((uint32_t)0x03FF0000) /*!< Transmission Byte Count 7 (high) */ + +/*----------------------------------------------------------------------------*/ + +/***************** Bit definition for USB_ADDR0_RX register *****************/ +#define USB_ADDR0_RX_ADDR0_RX ((uint16_t)0xFFFE) /*!< Reception Buffer Address 0 */ + +/***************** Bit definition for USB_ADDR1_RX register *****************/ +#define USB_ADDR1_RX_ADDR1_RX ((uint16_t)0xFFFE) /*!< Reception Buffer Address 1 */ + +/***************** Bit definition for USB_ADDR2_RX register *****************/ +#define USB_ADDR2_RX_ADDR2_RX ((uint16_t)0xFFFE) /*!< Reception Buffer Address 2 */ + +/***************** Bit definition for USB_ADDR3_RX register *****************/ +#define USB_ADDR3_RX_ADDR3_RX ((uint16_t)0xFFFE) /*!< Reception Buffer Address 3 */ + +/***************** Bit definition for USB_ADDR4_RX register *****************/ +#define USB_ADDR4_RX_ADDR4_RX ((uint16_t)0xFFFE) /*!< Reception Buffer Address 4 */ + +/***************** Bit definition for USB_ADDR5_RX register *****************/ +#define USB_ADDR5_RX_ADDR5_RX ((uint16_t)0xFFFE) /*!< Reception Buffer Address 5 */ + +/***************** Bit definition for USB_ADDR6_RX register *****************/ +#define USB_ADDR6_RX_ADDR6_RX ((uint16_t)0xFFFE) /*!< Reception Buffer Address 6 */ + +/***************** Bit definition for USB_ADDR7_RX register *****************/ +#define USB_ADDR7_RX_ADDR7_RX ((uint16_t)0xFFFE) /*!< Reception Buffer Address 7 */ + +/*----------------------------------------------------------------------------*/ + +/***************** Bit definition for USB_COUNT0_RX register ****************/ +#define USB_COUNT0_RX_COUNT0_RX ((uint16_t)0x03FF) /*!< Reception Byte Count */ + +#define USB_COUNT0_RX_NUM_BLOCK ((uint16_t)0x7C00) /*!< NUM_BLOCK[4:0] bits (Number of blocks) */ +#define USB_COUNT0_RX_NUM_BLOCK_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define USB_COUNT0_RX_NUM_BLOCK_1 ((uint16_t)0x0800) /*!< Bit 1 */ +#define USB_COUNT0_RX_NUM_BLOCK_2 ((uint16_t)0x1000) /*!< Bit 2 */ +#define USB_COUNT0_RX_NUM_BLOCK_3 ((uint16_t)0x2000) /*!< Bit 3 */ +#define USB_COUNT0_RX_NUM_BLOCK_4 ((uint16_t)0x4000) /*!< Bit 4 */ + +#define USB_COUNT0_RX_BLSIZE ((uint16_t)0x8000) /*!< BLock SIZE */ + +/***************** Bit definition for USB_COUNT1_RX register ****************/ +#define USB_COUNT1_RX_COUNT1_RX ((uint16_t)0x03FF) /*!< Reception Byte Count */ + +#define USB_COUNT1_RX_NUM_BLOCK ((uint16_t)0x7C00) /*!< NUM_BLOCK[4:0] bits (Number of blocks) */ +#define USB_COUNT1_RX_NUM_BLOCK_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define USB_COUNT1_RX_NUM_BLOCK_1 ((uint16_t)0x0800) /*!< Bit 1 */ +#define USB_COUNT1_RX_NUM_BLOCK_2 ((uint16_t)0x1000) /*!< Bit 2 */ +#define USB_COUNT1_RX_NUM_BLOCK_3 ((uint16_t)0x2000) /*!< Bit 3 */ +#define USB_COUNT1_RX_NUM_BLOCK_4 ((uint16_t)0x4000) /*!< Bit 4 */ + +#define USB_COUNT1_RX_BLSIZE ((uint16_t)0x8000) /*!< BLock SIZE */ + +/***************** Bit definition for USB_COUNT2_RX register ****************/ +#define USB_COUNT2_RX_COUNT2_RX ((uint16_t)0x03FF) /*!< Reception Byte Count */ + +#define USB_COUNT2_RX_NUM_BLOCK ((uint16_t)0x7C00) /*!< NUM_BLOCK[4:0] bits (Number of blocks) */ +#define USB_COUNT2_RX_NUM_BLOCK_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define USB_COUNT2_RX_NUM_BLOCK_1 ((uint16_t)0x0800) /*!< Bit 1 */ +#define USB_COUNT2_RX_NUM_BLOCK_2 ((uint16_t)0x1000) /*!< Bit 2 */ +#define USB_COUNT2_RX_NUM_BLOCK_3 ((uint16_t)0x2000) /*!< Bit 3 */ +#define USB_COUNT2_RX_NUM_BLOCK_4 ((uint16_t)0x4000) /*!< Bit 4 */ + +#define USB_COUNT2_RX_BLSIZE ((uint16_t)0x8000) /*!< BLock SIZE */ + +/***************** Bit definition for USB_COUNT3_RX register ****************/ +#define USB_COUNT3_RX_COUNT3_RX ((uint16_t)0x03FF) /*!< Reception Byte Count */ + +#define USB_COUNT3_RX_NUM_BLOCK ((uint16_t)0x7C00) /*!< NUM_BLOCK[4:0] bits (Number of blocks) */ +#define USB_COUNT3_RX_NUM_BLOCK_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define USB_COUNT3_RX_NUM_BLOCK_1 ((uint16_t)0x0800) /*!< Bit 1 */ +#define USB_COUNT3_RX_NUM_BLOCK_2 ((uint16_t)0x1000) /*!< Bit 2 */ +#define USB_COUNT3_RX_NUM_BLOCK_3 ((uint16_t)0x2000) /*!< Bit 3 */ +#define USB_COUNT3_RX_NUM_BLOCK_4 ((uint16_t)0x4000) /*!< Bit 4 */ + +#define USB_COUNT3_RX_BLSIZE ((uint16_t)0x8000) /*!< BLock SIZE */ + +/***************** Bit definition for USB_COUNT4_RX register ****************/ +#define USB_COUNT4_RX_COUNT4_RX ((uint16_t)0x03FF) /*!< Reception Byte Count */ + +#define USB_COUNT4_RX_NUM_BLOCK ((uint16_t)0x7C00) /*!< NUM_BLOCK[4:0] bits (Number of blocks) */ +#define USB_COUNT4_RX_NUM_BLOCK_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define USB_COUNT4_RX_NUM_BLOCK_1 ((uint16_t)0x0800) /*!< Bit 1 */ +#define USB_COUNT4_RX_NUM_BLOCK_2 ((uint16_t)0x1000) /*!< Bit 2 */ +#define USB_COUNT4_RX_NUM_BLOCK_3 ((uint16_t)0x2000) /*!< Bit 3 */ +#define USB_COUNT4_RX_NUM_BLOCK_4 ((uint16_t)0x4000) /*!< Bit 4 */ + +#define USB_COUNT4_RX_BLSIZE ((uint16_t)0x8000) /*!< BLock SIZE */ + +/***************** Bit definition for USB_COUNT5_RX register ****************/ +#define USB_COUNT5_RX_COUNT5_RX ((uint16_t)0x03FF) /*!< Reception Byte Count */ + +#define USB_COUNT5_RX_NUM_BLOCK ((uint16_t)0x7C00) /*!< NUM_BLOCK[4:0] bits (Number of blocks) */ +#define USB_COUNT5_RX_NUM_BLOCK_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define USB_COUNT5_RX_NUM_BLOCK_1 ((uint16_t)0x0800) /*!< Bit 1 */ +#define USB_COUNT5_RX_NUM_BLOCK_2 ((uint16_t)0x1000) /*!< Bit 2 */ +#define USB_COUNT5_RX_NUM_BLOCK_3 ((uint16_t)0x2000) /*!< Bit 3 */ +#define USB_COUNT5_RX_NUM_BLOCK_4 ((uint16_t)0x4000) /*!< Bit 4 */ + +#define USB_COUNT5_RX_BLSIZE ((uint16_t)0x8000) /*!< BLock SIZE */ + +/***************** Bit definition for USB_COUNT6_RX register ****************/ +#define USB_COUNT6_RX_COUNT6_RX ((uint16_t)0x03FF) /*!< Reception Byte Count */ + +#define USB_COUNT6_RX_NUM_BLOCK ((uint16_t)0x7C00) /*!< NUM_BLOCK[4:0] bits (Number of blocks) */ +#define USB_COUNT6_RX_NUM_BLOCK_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define USB_COUNT6_RX_NUM_BLOCK_1 ((uint16_t)0x0800) /*!< Bit 1 */ +#define USB_COUNT6_RX_NUM_BLOCK_2 ((uint16_t)0x1000) /*!< Bit 2 */ +#define USB_COUNT6_RX_NUM_BLOCK_3 ((uint16_t)0x2000) /*!< Bit 3 */ +#define USB_COUNT6_RX_NUM_BLOCK_4 ((uint16_t)0x4000) /*!< Bit 4 */ + +#define USB_COUNT6_RX_BLSIZE ((uint16_t)0x8000) /*!< BLock SIZE */ + +/***************** Bit definition for USB_COUNT7_RX register ****************/ +#define USB_COUNT7_RX_COUNT7_RX ((uint16_t)0x03FF) /*!< Reception Byte Count */ + +#define USB_COUNT7_RX_NUM_BLOCK ((uint16_t)0x7C00) /*!< NUM_BLOCK[4:0] bits (Number of blocks) */ +#define USB_COUNT7_RX_NUM_BLOCK_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define USB_COUNT7_RX_NUM_BLOCK_1 ((uint16_t)0x0800) /*!< Bit 1 */ +#define USB_COUNT7_RX_NUM_BLOCK_2 ((uint16_t)0x1000) /*!< Bit 2 */ +#define USB_COUNT7_RX_NUM_BLOCK_3 ((uint16_t)0x2000) /*!< Bit 3 */ +#define USB_COUNT7_RX_NUM_BLOCK_4 ((uint16_t)0x4000) /*!< Bit 4 */ + +#define USB_COUNT7_RX_BLSIZE ((uint16_t)0x8000) /*!< BLock SIZE */ + +/*----------------------------------------------------------------------------*/ + +/**************** Bit definition for USB_COUNT0_RX_0 register ***************/ +#define USB_COUNT0_RX_0_COUNT0_RX_0 ((uint32_t)0x000003FF) /*!< Reception Byte Count (low) */ + +#define USB_COUNT0_RX_0_NUM_BLOCK_0 ((uint32_t)0x00007C00) /*!< NUM_BLOCK_0[4:0] bits (Number of blocks) (low) */ +#define USB_COUNT0_RX_0_NUM_BLOCK_0_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define USB_COUNT0_RX_0_NUM_BLOCK_0_1 ((uint32_t)0x00000800) /*!< Bit 1 */ +#define USB_COUNT0_RX_0_NUM_BLOCK_0_2 ((uint32_t)0x00001000) /*!< Bit 2 */ +#define USB_COUNT0_RX_0_NUM_BLOCK_0_3 ((uint32_t)0x00002000) /*!< Bit 3 */ +#define USB_COUNT0_RX_0_NUM_BLOCK_0_4 ((uint32_t)0x00004000) /*!< Bit 4 */ + +#define USB_COUNT0_RX_0_BLSIZE_0 ((uint32_t)0x00008000) /*!< BLock SIZE (low) */ + +/**************** Bit definition for USB_COUNT0_RX_1 register ***************/ +#define USB_COUNT0_RX_1_COUNT0_RX_1 ((uint32_t)0x03FF0000) /*!< Reception Byte Count (high) */ + +#define USB_COUNT0_RX_1_NUM_BLOCK_1 ((uint32_t)0x7C000000) /*!< NUM_BLOCK_1[4:0] bits (Number of blocks) (high) */ +#define USB_COUNT0_RX_1_NUM_BLOCK_1_0 ((uint32_t)0x04000000) /*!< Bit 1 */ +#define USB_COUNT0_RX_1_NUM_BLOCK_1_1 ((uint32_t)0x08000000) /*!< Bit 1 */ +#define USB_COUNT0_RX_1_NUM_BLOCK_1_2 ((uint32_t)0x10000000) /*!< Bit 2 */ +#define USB_COUNT0_RX_1_NUM_BLOCK_1_3 ((uint32_t)0x20000000) /*!< Bit 3 */ +#define USB_COUNT0_RX_1_NUM_BLOCK_1_4 ((uint32_t)0x40000000) /*!< Bit 4 */ + +#define USB_COUNT0_RX_1_BLSIZE_1 ((uint32_t)0x80000000) /*!< BLock SIZE (high) */ + +/**************** Bit definition for USB_COUNT1_RX_0 register ***************/ +#define USB_COUNT1_RX_0_COUNT1_RX_0 ((uint32_t)0x000003FF) /*!< Reception Byte Count (low) */ + +#define USB_COUNT1_RX_0_NUM_BLOCK_0 ((uint32_t)0x00007C00) /*!< NUM_BLOCK_0[4:0] bits (Number of blocks) (low) */ +#define USB_COUNT1_RX_0_NUM_BLOCK_0_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define USB_COUNT1_RX_0_NUM_BLOCK_0_1 ((uint32_t)0x00000800) /*!< Bit 1 */ +#define USB_COUNT1_RX_0_NUM_BLOCK_0_2 ((uint32_t)0x00001000) /*!< Bit 2 */ +#define USB_COUNT1_RX_0_NUM_BLOCK_0_3 ((uint32_t)0x00002000) /*!< Bit 3 */ +#define USB_COUNT1_RX_0_NUM_BLOCK_0_4 ((uint32_t)0x00004000) /*!< Bit 4 */ + +#define USB_COUNT1_RX_0_BLSIZE_0 ((uint32_t)0x00008000) /*!< BLock SIZE (low) */ + +/**************** Bit definition for USB_COUNT1_RX_1 register ***************/ +#define USB_COUNT1_RX_1_COUNT1_RX_1 ((uint32_t)0x03FF0000) /*!< Reception Byte Count (high) */ + +#define USB_COUNT1_RX_1_NUM_BLOCK_1 ((uint32_t)0x7C000000) /*!< NUM_BLOCK_1[4:0] bits (Number of blocks) (high) */ +#define USB_COUNT1_RX_1_NUM_BLOCK_1_0 ((uint32_t)0x04000000) /*!< Bit 0 */ +#define USB_COUNT1_RX_1_NUM_BLOCK_1_1 ((uint32_t)0x08000000) /*!< Bit 1 */ +#define USB_COUNT1_RX_1_NUM_BLOCK_1_2 ((uint32_t)0x10000000) /*!< Bit 2 */ +#define USB_COUNT1_RX_1_NUM_BLOCK_1_3 ((uint32_t)0x20000000) /*!< Bit 3 */ +#define USB_COUNT1_RX_1_NUM_BLOCK_1_4 ((uint32_t)0x40000000) /*!< Bit 4 */ + +#define USB_COUNT1_RX_1_BLSIZE_1 ((uint32_t)0x80000000) /*!< BLock SIZE (high) */ + +/**************** Bit definition for USB_COUNT2_RX_0 register ***************/ +#define USB_COUNT2_RX_0_COUNT2_RX_0 ((uint32_t)0x000003FF) /*!< Reception Byte Count (low) */ + +#define USB_COUNT2_RX_0_NUM_BLOCK_0 ((uint32_t)0x00007C00) /*!< NUM_BLOCK_0[4:0] bits (Number of blocks) (low) */ +#define USB_COUNT2_RX_0_NUM_BLOCK_0_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define USB_COUNT2_RX_0_NUM_BLOCK_0_1 ((uint32_t)0x00000800) /*!< Bit 1 */ +#define USB_COUNT2_RX_0_NUM_BLOCK_0_2 ((uint32_t)0x00001000) /*!< Bit 2 */ +#define USB_COUNT2_RX_0_NUM_BLOCK_0_3 ((uint32_t)0x00002000) /*!< Bit 3 */ +#define USB_COUNT2_RX_0_NUM_BLOCK_0_4 ((uint32_t)0x00004000) /*!< Bit 4 */ + +#define USB_COUNT2_RX_0_BLSIZE_0 ((uint32_t)0x00008000) /*!< BLock SIZE (low) */ + +/**************** Bit definition for USB_COUNT2_RX_1 register ***************/ +#define USB_COUNT2_RX_1_COUNT2_RX_1 ((uint32_t)0x03FF0000) /*!< Reception Byte Count (high) */ + +#define USB_COUNT2_RX_1_NUM_BLOCK_1 ((uint32_t)0x7C000000) /*!< NUM_BLOCK_1[4:0] bits (Number of blocks) (high) */ +#define USB_COUNT2_RX_1_NUM_BLOCK_1_0 ((uint32_t)0x04000000) /*!< Bit 0 */ +#define USB_COUNT2_RX_1_NUM_BLOCK_1_1 ((uint32_t)0x08000000) /*!< Bit 1 */ +#define USB_COUNT2_RX_1_NUM_BLOCK_1_2 ((uint32_t)0x10000000) /*!< Bit 2 */ +#define USB_COUNT2_RX_1_NUM_BLOCK_1_3 ((uint32_t)0x20000000) /*!< Bit 3 */ +#define USB_COUNT2_RX_1_NUM_BLOCK_1_4 ((uint32_t)0x40000000) /*!< Bit 4 */ + +#define USB_COUNT2_RX_1_BLSIZE_1 ((uint32_t)0x80000000) /*!< BLock SIZE (high) */ + +/**************** Bit definition for USB_COUNT3_RX_0 register ***************/ +#define USB_COUNT3_RX_0_COUNT3_RX_0 ((uint32_t)0x000003FF) /*!< Reception Byte Count (low) */ + +#define USB_COUNT3_RX_0_NUM_BLOCK_0 ((uint32_t)0x00007C00) /*!< NUM_BLOCK_0[4:0] bits (Number of blocks) (low) */ +#define USB_COUNT3_RX_0_NUM_BLOCK_0_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define USB_COUNT3_RX_0_NUM_BLOCK_0_1 ((uint32_t)0x00000800) /*!< Bit 1 */ +#define USB_COUNT3_RX_0_NUM_BLOCK_0_2 ((uint32_t)0x00001000) /*!< Bit 2 */ +#define USB_COUNT3_RX_0_NUM_BLOCK_0_3 ((uint32_t)0x00002000) /*!< Bit 3 */ +#define USB_COUNT3_RX_0_NUM_BLOCK_0_4 ((uint32_t)0x00004000) /*!< Bit 4 */ + +#define USB_COUNT3_RX_0_BLSIZE_0 ((uint32_t)0x00008000) /*!< BLock SIZE (low) */ + +/**************** Bit definition for USB_COUNT3_RX_1 register ***************/ +#define USB_COUNT3_RX_1_COUNT3_RX_1 ((uint32_t)0x03FF0000) /*!< Reception Byte Count (high) */ + +#define USB_COUNT3_RX_1_NUM_BLOCK_1 ((uint32_t)0x7C000000) /*!< NUM_BLOCK_1[4:0] bits (Number of blocks) (high) */ +#define USB_COUNT3_RX_1_NUM_BLOCK_1_0 ((uint32_t)0x04000000) /*!< Bit 0 */ +#define USB_COUNT3_RX_1_NUM_BLOCK_1_1 ((uint32_t)0x08000000) /*!< Bit 1 */ +#define USB_COUNT3_RX_1_NUM_BLOCK_1_2 ((uint32_t)0x10000000) /*!< Bit 2 */ +#define USB_COUNT3_RX_1_NUM_BLOCK_1_3 ((uint32_t)0x20000000) /*!< Bit 3 */ +#define USB_COUNT3_RX_1_NUM_BLOCK_1_4 ((uint32_t)0x40000000) /*!< Bit 4 */ + +#define USB_COUNT3_RX_1_BLSIZE_1 ((uint32_t)0x80000000) /*!< BLock SIZE (high) */ + +/**************** Bit definition for USB_COUNT4_RX_0 register ***************/ +#define USB_COUNT4_RX_0_COUNT4_RX_0 ((uint32_t)0x000003FF) /*!< Reception Byte Count (low) */ + +#define USB_COUNT4_RX_0_NUM_BLOCK_0 ((uint32_t)0x00007C00) /*!< NUM_BLOCK_0[4:0] bits (Number of blocks) (low) */ +#define USB_COUNT4_RX_0_NUM_BLOCK_0_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define USB_COUNT4_RX_0_NUM_BLOCK_0_1 ((uint32_t)0x00000800) /*!< Bit 1 */ +#define USB_COUNT4_RX_0_NUM_BLOCK_0_2 ((uint32_t)0x00001000) /*!< Bit 2 */ +#define USB_COUNT4_RX_0_NUM_BLOCK_0_3 ((uint32_t)0x00002000) /*!< Bit 3 */ +#define USB_COUNT4_RX_0_NUM_BLOCK_0_4 ((uint32_t)0x00004000) /*!< Bit 4 */ + +#define USB_COUNT4_RX_0_BLSIZE_0 ((uint32_t)0x00008000) /*!< BLock SIZE (low) */ + +/**************** Bit definition for USB_COUNT4_RX_1 register ***************/ +#define USB_COUNT4_RX_1_COUNT4_RX_1 ((uint32_t)0x03FF0000) /*!< Reception Byte Count (high) */ + +#define USB_COUNT4_RX_1_NUM_BLOCK_1 ((uint32_t)0x7C000000) /*!< NUM_BLOCK_1[4:0] bits (Number of blocks) (high) */ +#define USB_COUNT4_RX_1_NUM_BLOCK_1_0 ((uint32_t)0x04000000) /*!< Bit 0 */ +#define USB_COUNT4_RX_1_NUM_BLOCK_1_1 ((uint32_t)0x08000000) /*!< Bit 1 */ +#define USB_COUNT4_RX_1_NUM_BLOCK_1_2 ((uint32_t)0x10000000) /*!< Bit 2 */ +#define USB_COUNT4_RX_1_NUM_BLOCK_1_3 ((uint32_t)0x20000000) /*!< Bit 3 */ +#define USB_COUNT4_RX_1_NUM_BLOCK_1_4 ((uint32_t)0x40000000) /*!< Bit 4 */ + +#define USB_COUNT4_RX_1_BLSIZE_1 ((uint32_t)0x80000000) /*!< BLock SIZE (high) */ + +/**************** Bit definition for USB_COUNT5_RX_0 register ***************/ +#define USB_COUNT5_RX_0_COUNT5_RX_0 ((uint32_t)0x000003FF) /*!< Reception Byte Count (low) */ + +#define USB_COUNT5_RX_0_NUM_BLOCK_0 ((uint32_t)0x00007C00) /*!< NUM_BLOCK_0[4:0] bits (Number of blocks) (low) */ +#define USB_COUNT5_RX_0_NUM_BLOCK_0_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define USB_COUNT5_RX_0_NUM_BLOCK_0_1 ((uint32_t)0x00000800) /*!< Bit 1 */ +#define USB_COUNT5_RX_0_NUM_BLOCK_0_2 ((uint32_t)0x00001000) /*!< Bit 2 */ +#define USB_COUNT5_RX_0_NUM_BLOCK_0_3 ((uint32_t)0x00002000) /*!< Bit 3 */ +#define USB_COUNT5_RX_0_NUM_BLOCK_0_4 ((uint32_t)0x00004000) /*!< Bit 4 */ + +#define USB_COUNT5_RX_0_BLSIZE_0 ((uint32_t)0x00008000) /*!< BLock SIZE (low) */ + +/**************** Bit definition for USB_COUNT5_RX_1 register ***************/ +#define USB_COUNT5_RX_1_COUNT5_RX_1 ((uint32_t)0x03FF0000) /*!< Reception Byte Count (high) */ + +#define USB_COUNT5_RX_1_NUM_BLOCK_1 ((uint32_t)0x7C000000) /*!< NUM_BLOCK_1[4:0] bits (Number of blocks) (high) */ +#define USB_COUNT5_RX_1_NUM_BLOCK_1_0 ((uint32_t)0x04000000) /*!< Bit 0 */ +#define USB_COUNT5_RX_1_NUM_BLOCK_1_1 ((uint32_t)0x08000000) /*!< Bit 1 */ +#define USB_COUNT5_RX_1_NUM_BLOCK_1_2 ((uint32_t)0x10000000) /*!< Bit 2 */ +#define USB_COUNT5_RX_1_NUM_BLOCK_1_3 ((uint32_t)0x20000000) /*!< Bit 3 */ +#define USB_COUNT5_RX_1_NUM_BLOCK_1_4 ((uint32_t)0x40000000) /*!< Bit 4 */ + +#define USB_COUNT5_RX_1_BLSIZE_1 ((uint32_t)0x80000000) /*!< BLock SIZE (high) */ + +/*************** Bit definition for USB_COUNT6_RX_0 register ***************/ +#define USB_COUNT6_RX_0_COUNT6_RX_0 ((uint32_t)0x000003FF) /*!< Reception Byte Count (low) */ + +#define USB_COUNT6_RX_0_NUM_BLOCK_0 ((uint32_t)0x00007C00) /*!< NUM_BLOCK_0[4:0] bits (Number of blocks) (low) */ +#define USB_COUNT6_RX_0_NUM_BLOCK_0_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define USB_COUNT6_RX_0_NUM_BLOCK_0_1 ((uint32_t)0x00000800) /*!< Bit 1 */ +#define USB_COUNT6_RX_0_NUM_BLOCK_0_2 ((uint32_t)0x00001000) /*!< Bit 2 */ +#define USB_COUNT6_RX_0_NUM_BLOCK_0_3 ((uint32_t)0x00002000) /*!< Bit 3 */ +#define USB_COUNT6_RX_0_NUM_BLOCK_0_4 ((uint32_t)0x00004000) /*!< Bit 4 */ + +#define USB_COUNT6_RX_0_BLSIZE_0 ((uint32_t)0x00008000) /*!< BLock SIZE (low) */ + +/**************** Bit definition for USB_COUNT6_RX_1 register ***************/ +#define USB_COUNT6_RX_1_COUNT6_RX_1 ((uint32_t)0x03FF0000) /*!< Reception Byte Count (high) */ + +#define USB_COUNT6_RX_1_NUM_BLOCK_1 ((uint32_t)0x7C000000) /*!< NUM_BLOCK_1[4:0] bits (Number of blocks) (high) */ +#define USB_COUNT6_RX_1_NUM_BLOCK_1_0 ((uint32_t)0x04000000) /*!< Bit 0 */ +#define USB_COUNT6_RX_1_NUM_BLOCK_1_1 ((uint32_t)0x08000000) /*!< Bit 1 */ +#define USB_COUNT6_RX_1_NUM_BLOCK_1_2 ((uint32_t)0x10000000) /*!< Bit 2 */ +#define USB_COUNT6_RX_1_NUM_BLOCK_1_3 ((uint32_t)0x20000000) /*!< Bit 3 */ +#define USB_COUNT6_RX_1_NUM_BLOCK_1_4 ((uint32_t)0x40000000) /*!< Bit 4 */ + +#define USB_COUNT6_RX_1_BLSIZE_1 ((uint32_t)0x80000000) /*!< BLock SIZE (high) */ + +/*************** Bit definition for USB_COUNT7_RX_0 register ****************/ +#define USB_COUNT7_RX_0_COUNT7_RX_0 ((uint32_t)0x000003FF) /*!< Reception Byte Count (low) */ + +#define USB_COUNT7_RX_0_NUM_BLOCK_0 ((uint32_t)0x00007C00) /*!< NUM_BLOCK_0[4:0] bits (Number of blocks) (low) */ +#define USB_COUNT7_RX_0_NUM_BLOCK_0_0 ((uint32_t)0x00000400) /*!< Bit 0 */ +#define USB_COUNT7_RX_0_NUM_BLOCK_0_1 ((uint32_t)0x00000800) /*!< Bit 1 */ +#define USB_COUNT7_RX_0_NUM_BLOCK_0_2 ((uint32_t)0x00001000) /*!< Bit 2 */ +#define USB_COUNT7_RX_0_NUM_BLOCK_0_3 ((uint32_t)0x00002000) /*!< Bit 3 */ +#define USB_COUNT7_RX_0_NUM_BLOCK_0_4 ((uint32_t)0x00004000) /*!< Bit 4 */ + +#define USB_COUNT7_RX_0_BLSIZE_0 ((uint32_t)0x00008000) /*!< BLock SIZE (low) */ + +/*************** Bit definition for USB_COUNT7_RX_1 register ****************/ +#define USB_COUNT7_RX_1_COUNT7_RX_1 ((uint32_t)0x03FF0000) /*!< Reception Byte Count (high) */ + +#define USB_COUNT7_RX_1_NUM_BLOCK_1 ((uint32_t)0x7C000000) /*!< NUM_BLOCK_1[4:0] bits (Number of blocks) (high) */ +#define USB_COUNT7_RX_1_NUM_BLOCK_1_0 ((uint32_t)0x04000000) /*!< Bit 0 */ +#define USB_COUNT7_RX_1_NUM_BLOCK_1_1 ((uint32_t)0x08000000) /*!< Bit 1 */ +#define USB_COUNT7_RX_1_NUM_BLOCK_1_2 ((uint32_t)0x10000000) /*!< Bit 2 */ +#define USB_COUNT7_RX_1_NUM_BLOCK_1_3 ((uint32_t)0x20000000) /*!< Bit 3 */ +#define USB_COUNT7_RX_1_NUM_BLOCK_1_4 ((uint32_t)0x40000000) /*!< Bit 4 */ + +#define USB_COUNT7_RX_1_BLSIZE_1 ((uint32_t)0x80000000) /*!< BLock SIZE (high) */ + +/******************************************************************************/ +/* */ +/* Controller Area Network */ +/* */ +/******************************************************************************/ + +/*!< CAN control and status registers */ +/******************* Bit definition for CAN_MCR register ********************/ +#define CAN_MCR_INRQ ((uint16_t)0x0001) /*!< Initialization Request */ +#define CAN_MCR_SLEEP ((uint16_t)0x0002) /*!< Sleep Mode Request */ +#define CAN_MCR_TXFP ((uint16_t)0x0004) /*!< Transmit FIFO Priority */ +#define CAN_MCR_RFLM ((uint16_t)0x0008) /*!< Receive FIFO Locked Mode */ +#define CAN_MCR_NART ((uint16_t)0x0010) /*!< No Automatic Retransmission */ +#define CAN_MCR_AWUM ((uint16_t)0x0020) /*!< Automatic Wakeup Mode */ +#define CAN_MCR_ABOM ((uint16_t)0x0040) /*!< Automatic Bus-Off Management */ +#define CAN_MCR_TTCM ((uint16_t)0x0080) /*!< Time Triggered Communication Mode */ +#define CAN_MCR_RESET ((uint16_t)0x8000) /*!< CAN software master reset */ + +/******************* Bit definition for CAN_MSR register ********************/ +#define CAN_MSR_INAK ((uint16_t)0x0001) /*!< Initialization Acknowledge */ +#define CAN_MSR_SLAK ((uint16_t)0x0002) /*!< Sleep Acknowledge */ +#define CAN_MSR_ERRI ((uint16_t)0x0004) /*!< Error Interrupt */ +#define CAN_MSR_WKUI ((uint16_t)0x0008) /*!< Wakeup Interrupt */ +#define CAN_MSR_SLAKI ((uint16_t)0x0010) /*!< Sleep Acknowledge Interrupt */ +#define CAN_MSR_TXM ((uint16_t)0x0100) /*!< Transmit Mode */ +#define CAN_MSR_RXM ((uint16_t)0x0200) /*!< Receive Mode */ +#define CAN_MSR_SAMP ((uint16_t)0x0400) /*!< Last Sample Point */ +#define CAN_MSR_RX ((uint16_t)0x0800) /*!< CAN Rx Signal */ + +/******************* Bit definition for CAN_TSR register ********************/ +#define CAN_TSR_RQCP0 ((uint32_t)0x00000001) /*!< Request Completed Mailbox0 */ +#define CAN_TSR_TXOK0 ((uint32_t)0x00000002) /*!< Transmission OK of Mailbox0 */ +#define CAN_TSR_ALST0 ((uint32_t)0x00000004) /*!< Arbitration Lost for Mailbox0 */ +#define CAN_TSR_TERR0 ((uint32_t)0x00000008) /*!< Transmission Error of Mailbox0 */ +#define CAN_TSR_ABRQ0 ((uint32_t)0x00000080) /*!< Abort Request for Mailbox0 */ +#define CAN_TSR_RQCP1 ((uint32_t)0x00000100) /*!< Request Completed Mailbox1 */ +#define CAN_TSR_TXOK1 ((uint32_t)0x00000200) /*!< Transmission OK of Mailbox1 */ +#define CAN_TSR_ALST1 ((uint32_t)0x00000400) /*!< Arbitration Lost for Mailbox1 */ +#define CAN_TSR_TERR1 ((uint32_t)0x00000800) /*!< Transmission Error of Mailbox1 */ +#define CAN_TSR_ABRQ1 ((uint32_t)0x00008000) /*!< Abort Request for Mailbox 1 */ +#define CAN_TSR_RQCP2 ((uint32_t)0x00010000) /*!< Request Completed Mailbox2 */ +#define CAN_TSR_TXOK2 ((uint32_t)0x00020000) /*!< Transmission OK of Mailbox 2 */ +#define CAN_TSR_ALST2 ((uint32_t)0x00040000) /*!< Arbitration Lost for mailbox 2 */ +#define CAN_TSR_TERR2 ((uint32_t)0x00080000) /*!< Transmission Error of Mailbox 2 */ +#define CAN_TSR_ABRQ2 ((uint32_t)0x00800000) /*!< Abort Request for Mailbox 2 */ +#define CAN_TSR_CODE ((uint32_t)0x03000000) /*!< Mailbox Code */ + +#define CAN_TSR_TME ((uint32_t)0x1C000000) /*!< TME[2:0] bits */ +#define CAN_TSR_TME0 ((uint32_t)0x04000000) /*!< Transmit Mailbox 0 Empty */ +#define CAN_TSR_TME1 ((uint32_t)0x08000000) /*!< Transmit Mailbox 1 Empty */ +#define CAN_TSR_TME2 ((uint32_t)0x10000000) /*!< Transmit Mailbox 2 Empty */ + +#define CAN_TSR_LOW ((uint32_t)0xE0000000) /*!< LOW[2:0] bits */ +#define CAN_TSR_LOW0 ((uint32_t)0x20000000) /*!< Lowest Priority Flag for Mailbox 0 */ +#define CAN_TSR_LOW1 ((uint32_t)0x40000000) /*!< Lowest Priority Flag for Mailbox 1 */ +#define CAN_TSR_LOW2 ((uint32_t)0x80000000) /*!< Lowest Priority Flag for Mailbox 2 */ + +/******************* Bit definition for CAN_RF0R register *******************/ +#define CAN_RF0R_FMP0 ((uint8_t)0x03) /*!< FIFO 0 Message Pending */ +#define CAN_RF0R_FULL0 ((uint8_t)0x08) /*!< FIFO 0 Full */ +#define CAN_RF0R_FOVR0 ((uint8_t)0x10) /*!< FIFO 0 Overrun */ +#define CAN_RF0R_RFOM0 ((uint8_t)0x20) /*!< Release FIFO 0 Output Mailbox */ + +/******************* Bit definition for CAN_RF1R register *******************/ +#define CAN_RF1R_FMP1 ((uint8_t)0x03) /*!< FIFO 1 Message Pending */ +#define CAN_RF1R_FULL1 ((uint8_t)0x08) /*!< FIFO 1 Full */ +#define CAN_RF1R_FOVR1 ((uint8_t)0x10) /*!< FIFO 1 Overrun */ +#define CAN_RF1R_RFOM1 ((uint8_t)0x20) /*!< Release FIFO 1 Output Mailbox */ + +/******************** Bit definition for CAN_IER register *******************/ +#define CAN_IER_TMEIE ((uint32_t)0x00000001) /*!< Transmit Mailbox Empty Interrupt Enable */ +#define CAN_IER_FMPIE0 ((uint32_t)0x00000002) /*!< FIFO Message Pending Interrupt Enable */ +#define CAN_IER_FFIE0 ((uint32_t)0x00000004) /*!< FIFO Full Interrupt Enable */ +#define CAN_IER_FOVIE0 ((uint32_t)0x00000008) /*!< FIFO Overrun Interrupt Enable */ +#define CAN_IER_FMPIE1 ((uint32_t)0x00000010) /*!< FIFO Message Pending Interrupt Enable */ +#define CAN_IER_FFIE1 ((uint32_t)0x00000020) /*!< FIFO Full Interrupt Enable */ +#define CAN_IER_FOVIE1 ((uint32_t)0x00000040) /*!< FIFO Overrun Interrupt Enable */ +#define CAN_IER_EWGIE ((uint32_t)0x00000100) /*!< Error Warning Interrupt Enable */ +#define CAN_IER_EPVIE ((uint32_t)0x00000200) /*!< Error Passive Interrupt Enable */ +#define CAN_IER_BOFIE ((uint32_t)0x00000400) /*!< Bus-Off Interrupt Enable */ +#define CAN_IER_LECIE ((uint32_t)0x00000800) /*!< Last Error Code Interrupt Enable */ +#define CAN_IER_ERRIE ((uint32_t)0x00008000) /*!< Error Interrupt Enable */ +#define CAN_IER_WKUIE ((uint32_t)0x00010000) /*!< Wakeup Interrupt Enable */ +#define CAN_IER_SLKIE ((uint32_t)0x00020000) /*!< Sleep Interrupt Enable */ + +/******************** Bit definition for CAN_ESR register *******************/ +#define CAN_ESR_EWGF ((uint32_t)0x00000001) /*!< Error Warning Flag */ +#define CAN_ESR_EPVF ((uint32_t)0x00000002) /*!< Error Passive Flag */ +#define CAN_ESR_BOFF ((uint32_t)0x00000004) /*!< Bus-Off Flag */ + +#define CAN_ESR_LEC ((uint32_t)0x00000070) /*!< LEC[2:0] bits (Last Error Code) */ +#define CAN_ESR_LEC_0 ((uint32_t)0x00000010) /*!< Bit 0 */ +#define CAN_ESR_LEC_1 ((uint32_t)0x00000020) /*!< Bit 1 */ +#define CAN_ESR_LEC_2 ((uint32_t)0x00000040) /*!< Bit 2 */ + +#define CAN_ESR_TEC ((uint32_t)0x00FF0000) /*!< Least significant byte of the 9-bit Transmit Error Counter */ +#define CAN_ESR_REC ((uint32_t)0xFF000000) /*!< Receive Error Counter */ + +/******************* Bit definition for CAN_BTR register ********************/ +#define CAN_BTR_BRP ((uint32_t)0x000003FF) /*!< Baud Rate Prescaler */ +#define CAN_BTR_TS1 ((uint32_t)0x000F0000) /*!< Time Segment 1 */ +#define CAN_BTR_TS2 ((uint32_t)0x00700000) /*!< Time Segment 2 */ +#define CAN_BTR_SJW ((uint32_t)0x03000000) /*!< Resynchronization Jump Width */ +#define CAN_BTR_LBKM ((uint32_t)0x40000000) /*!< Loop Back Mode (Debug) */ +#define CAN_BTR_SILM ((uint32_t)0x80000000) /*!< Silent Mode */ + +/*!< Mailbox registers */ +/****************** Bit definition for CAN_TI0R register ********************/ +#define CAN_TI0R_TXRQ ((uint32_t)0x00000001) /*!< Transmit Mailbox Request */ +#define CAN_TI0R_RTR ((uint32_t)0x00000002) /*!< Remote Transmission Request */ +#define CAN_TI0R_IDE ((uint32_t)0x00000004) /*!< Identifier Extension */ +#define CAN_TI0R_EXID ((uint32_t)0x001FFFF8) /*!< Extended Identifier */ +#define CAN_TI0R_STID ((uint32_t)0xFFE00000) /*!< Standard Identifier or Extended Identifier */ + +/****************** Bit definition for CAN_TDT0R register *******************/ +#define CAN_TDT0R_DLC ((uint32_t)0x0000000F) /*!< Data Length Code */ +#define CAN_TDT0R_TGT ((uint32_t)0x00000100) /*!< Transmit Global Time */ +#define CAN_TDT0R_TIME ((uint32_t)0xFFFF0000) /*!< Message Time Stamp */ + +/****************** Bit definition for CAN_TDL0R register *******************/ +#define CAN_TDL0R_DATA0 ((uint32_t)0x000000FF) /*!< Data byte 0 */ +#define CAN_TDL0R_DATA1 ((uint32_t)0x0000FF00) /*!< Data byte 1 */ +#define CAN_TDL0R_DATA2 ((uint32_t)0x00FF0000) /*!< Data byte 2 */ +#define CAN_TDL0R_DATA3 ((uint32_t)0xFF000000) /*!< Data byte 3 */ + +/****************** Bit definition for CAN_TDH0R register *******************/ +#define CAN_TDH0R_DATA4 ((uint32_t)0x000000FF) /*!< Data byte 4 */ +#define CAN_TDH0R_DATA5 ((uint32_t)0x0000FF00) /*!< Data byte 5 */ +#define CAN_TDH0R_DATA6 ((uint32_t)0x00FF0000) /*!< Data byte 6 */ +#define CAN_TDH0R_DATA7 ((uint32_t)0xFF000000) /*!< Data byte 7 */ + +/******************* Bit definition for CAN_TI1R register *******************/ +#define CAN_TI1R_TXRQ ((uint32_t)0x00000001) /*!< Transmit Mailbox Request */ +#define CAN_TI1R_RTR ((uint32_t)0x00000002) /*!< Remote Transmission Request */ +#define CAN_TI1R_IDE ((uint32_t)0x00000004) /*!< Identifier Extension */ +#define CAN_TI1R_EXID ((uint32_t)0x001FFFF8) /*!< Extended Identifier */ +#define CAN_TI1R_STID ((uint32_t)0xFFE00000) /*!< Standard Identifier or Extended Identifier */ + +/******************* Bit definition for CAN_TDT1R register ******************/ +#define CAN_TDT1R_DLC ((uint32_t)0x0000000F) /*!< Data Length Code */ +#define CAN_TDT1R_TGT ((uint32_t)0x00000100) /*!< Transmit Global Time */ +#define CAN_TDT1R_TIME ((uint32_t)0xFFFF0000) /*!< Message Time Stamp */ + +/******************* Bit definition for CAN_TDL1R register ******************/ +#define CAN_TDL1R_DATA0 ((uint32_t)0x000000FF) /*!< Data byte 0 */ +#define CAN_TDL1R_DATA1 ((uint32_t)0x0000FF00) /*!< Data byte 1 */ +#define CAN_TDL1R_DATA2 ((uint32_t)0x00FF0000) /*!< Data byte 2 */ +#define CAN_TDL1R_DATA3 ((uint32_t)0xFF000000) /*!< Data byte 3 */ + +/******************* Bit definition for CAN_TDH1R register ******************/ +#define CAN_TDH1R_DATA4 ((uint32_t)0x000000FF) /*!< Data byte 4 */ +#define CAN_TDH1R_DATA5 ((uint32_t)0x0000FF00) /*!< Data byte 5 */ +#define CAN_TDH1R_DATA6 ((uint32_t)0x00FF0000) /*!< Data byte 6 */ +#define CAN_TDH1R_DATA7 ((uint32_t)0xFF000000) /*!< Data byte 7 */ + +/******************* Bit definition for CAN_TI2R register *******************/ +#define CAN_TI2R_TXRQ ((uint32_t)0x00000001) /*!< Transmit Mailbox Request */ +#define CAN_TI2R_RTR ((uint32_t)0x00000002) /*!< Remote Transmission Request */ +#define CAN_TI2R_IDE ((uint32_t)0x00000004) /*!< Identifier Extension */ +#define CAN_TI2R_EXID ((uint32_t)0x001FFFF8) /*!< Extended identifier */ +#define CAN_TI2R_STID ((uint32_t)0xFFE00000) /*!< Standard Identifier or Extended Identifier */ + +/******************* Bit definition for CAN_TDT2R register ******************/ +#define CAN_TDT2R_DLC ((uint32_t)0x0000000F) /*!< Data Length Code */ +#define CAN_TDT2R_TGT ((uint32_t)0x00000100) /*!< Transmit Global Time */ +#define CAN_TDT2R_TIME ((uint32_t)0xFFFF0000) /*!< Message Time Stamp */ + +/******************* Bit definition for CAN_TDL2R register ******************/ +#define CAN_TDL2R_DATA0 ((uint32_t)0x000000FF) /*!< Data byte 0 */ +#define CAN_TDL2R_DATA1 ((uint32_t)0x0000FF00) /*!< Data byte 1 */ +#define CAN_TDL2R_DATA2 ((uint32_t)0x00FF0000) /*!< Data byte 2 */ +#define CAN_TDL2R_DATA3 ((uint32_t)0xFF000000) /*!< Data byte 3 */ + +/******************* Bit definition for CAN_TDH2R register ******************/ +#define CAN_TDH2R_DATA4 ((uint32_t)0x000000FF) /*!< Data byte 4 */ +#define CAN_TDH2R_DATA5 ((uint32_t)0x0000FF00) /*!< Data byte 5 */ +#define CAN_TDH2R_DATA6 ((uint32_t)0x00FF0000) /*!< Data byte 6 */ +#define CAN_TDH2R_DATA7 ((uint32_t)0xFF000000) /*!< Data byte 7 */ + +/******************* Bit definition for CAN_RI0R register *******************/ +#define CAN_RI0R_RTR ((uint32_t)0x00000002) /*!< Remote Transmission Request */ +#define CAN_RI0R_IDE ((uint32_t)0x00000004) /*!< Identifier Extension */ +#define CAN_RI0R_EXID ((uint32_t)0x001FFFF8) /*!< Extended Identifier */ +#define CAN_RI0R_STID ((uint32_t)0xFFE00000) /*!< Standard Identifier or Extended Identifier */ + +/******************* Bit definition for CAN_RDT0R register ******************/ +#define CAN_RDT0R_DLC ((uint32_t)0x0000000F) /*!< Data Length Code */ +#define CAN_RDT0R_FMI ((uint32_t)0x0000FF00) /*!< Filter Match Index */ +#define CAN_RDT0R_TIME ((uint32_t)0xFFFF0000) /*!< Message Time Stamp */ + +/******************* Bit definition for CAN_RDL0R register ******************/ +#define CAN_RDL0R_DATA0 ((uint32_t)0x000000FF) /*!< Data byte 0 */ +#define CAN_RDL0R_DATA1 ((uint32_t)0x0000FF00) /*!< Data byte 1 */ +#define CAN_RDL0R_DATA2 ((uint32_t)0x00FF0000) /*!< Data byte 2 */ +#define CAN_RDL0R_DATA3 ((uint32_t)0xFF000000) /*!< Data byte 3 */ + +/******************* Bit definition for CAN_RDH0R register ******************/ +#define CAN_RDH0R_DATA4 ((uint32_t)0x000000FF) /*!< Data byte 4 */ +#define CAN_RDH0R_DATA5 ((uint32_t)0x0000FF00) /*!< Data byte 5 */ +#define CAN_RDH0R_DATA6 ((uint32_t)0x00FF0000) /*!< Data byte 6 */ +#define CAN_RDH0R_DATA7 ((uint32_t)0xFF000000) /*!< Data byte 7 */ + +/******************* Bit definition for CAN_RI1R register *******************/ +#define CAN_RI1R_RTR ((uint32_t)0x00000002) /*!< Remote Transmission Request */ +#define CAN_RI1R_IDE ((uint32_t)0x00000004) /*!< Identifier Extension */ +#define CAN_RI1R_EXID ((uint32_t)0x001FFFF8) /*!< Extended identifier */ +#define CAN_RI1R_STID ((uint32_t)0xFFE00000) /*!< Standard Identifier or Extended Identifier */ + +/******************* Bit definition for CAN_RDT1R register ******************/ +#define CAN_RDT1R_DLC ((uint32_t)0x0000000F) /*!< Data Length Code */ +#define CAN_RDT1R_FMI ((uint32_t)0x0000FF00) /*!< Filter Match Index */ +#define CAN_RDT1R_TIME ((uint32_t)0xFFFF0000) /*!< Message Time Stamp */ + +/******************* Bit definition for CAN_RDL1R register ******************/ +#define CAN_RDL1R_DATA0 ((uint32_t)0x000000FF) /*!< Data byte 0 */ +#define CAN_RDL1R_DATA1 ((uint32_t)0x0000FF00) /*!< Data byte 1 */ +#define CAN_RDL1R_DATA2 ((uint32_t)0x00FF0000) /*!< Data byte 2 */ +#define CAN_RDL1R_DATA3 ((uint32_t)0xFF000000) /*!< Data byte 3 */ + +/******************* Bit definition for CAN_RDH1R register ******************/ +#define CAN_RDH1R_DATA4 ((uint32_t)0x000000FF) /*!< Data byte 4 */ +#define CAN_RDH1R_DATA5 ((uint32_t)0x0000FF00) /*!< Data byte 5 */ +#define CAN_RDH1R_DATA6 ((uint32_t)0x00FF0000) /*!< Data byte 6 */ +#define CAN_RDH1R_DATA7 ((uint32_t)0xFF000000) /*!< Data byte 7 */ + +/*!< CAN filter registers */ +/******************* Bit definition for CAN_FMR register ********************/ +#define CAN_FMR_FINIT ((uint8_t)0x01) /*!< Filter Init Mode */ + +/******************* Bit definition for CAN_FM1R register *******************/ +#define CAN_FM1R_FBM ((uint16_t)0x3FFF) /*!< Filter Mode */ +#define CAN_FM1R_FBM0 ((uint16_t)0x0001) /*!< Filter Init Mode bit 0 */ +#define CAN_FM1R_FBM1 ((uint16_t)0x0002) /*!< Filter Init Mode bit 1 */ +#define CAN_FM1R_FBM2 ((uint16_t)0x0004) /*!< Filter Init Mode bit 2 */ +#define CAN_FM1R_FBM3 ((uint16_t)0x0008) /*!< Filter Init Mode bit 3 */ +#define CAN_FM1R_FBM4 ((uint16_t)0x0010) /*!< Filter Init Mode bit 4 */ +#define CAN_FM1R_FBM5 ((uint16_t)0x0020) /*!< Filter Init Mode bit 5 */ +#define CAN_FM1R_FBM6 ((uint16_t)0x0040) /*!< Filter Init Mode bit 6 */ +#define CAN_FM1R_FBM7 ((uint16_t)0x0080) /*!< Filter Init Mode bit 7 */ +#define CAN_FM1R_FBM8 ((uint16_t)0x0100) /*!< Filter Init Mode bit 8 */ +#define CAN_FM1R_FBM9 ((uint16_t)0x0200) /*!< Filter Init Mode bit 9 */ +#define CAN_FM1R_FBM10 ((uint16_t)0x0400) /*!< Filter Init Mode bit 10 */ +#define CAN_FM1R_FBM11 ((uint16_t)0x0800) /*!< Filter Init Mode bit 11 */ +#define CAN_FM1R_FBM12 ((uint16_t)0x1000) /*!< Filter Init Mode bit 12 */ +#define CAN_FM1R_FBM13 ((uint16_t)0x2000) /*!< Filter Init Mode bit 13 */ + +/******************* Bit definition for CAN_FS1R register *******************/ +#define CAN_FS1R_FSC ((uint16_t)0x3FFF) /*!< Filter Scale Configuration */ +#define CAN_FS1R_FSC0 ((uint16_t)0x0001) /*!< Filter Scale Configuration bit 0 */ +#define CAN_FS1R_FSC1 ((uint16_t)0x0002) /*!< Filter Scale Configuration bit 1 */ +#define CAN_FS1R_FSC2 ((uint16_t)0x0004) /*!< Filter Scale Configuration bit 2 */ +#define CAN_FS1R_FSC3 ((uint16_t)0x0008) /*!< Filter Scale Configuration bit 3 */ +#define CAN_FS1R_FSC4 ((uint16_t)0x0010) /*!< Filter Scale Configuration bit 4 */ +#define CAN_FS1R_FSC5 ((uint16_t)0x0020) /*!< Filter Scale Configuration bit 5 */ +#define CAN_FS1R_FSC6 ((uint16_t)0x0040) /*!< Filter Scale Configuration bit 6 */ +#define CAN_FS1R_FSC7 ((uint16_t)0x0080) /*!< Filter Scale Configuration bit 7 */ +#define CAN_FS1R_FSC8 ((uint16_t)0x0100) /*!< Filter Scale Configuration bit 8 */ +#define CAN_FS1R_FSC9 ((uint16_t)0x0200) /*!< Filter Scale Configuration bit 9 */ +#define CAN_FS1R_FSC10 ((uint16_t)0x0400) /*!< Filter Scale Configuration bit 10 */ +#define CAN_FS1R_FSC11 ((uint16_t)0x0800) /*!< Filter Scale Configuration bit 11 */ +#define CAN_FS1R_FSC12 ((uint16_t)0x1000) /*!< Filter Scale Configuration bit 12 */ +#define CAN_FS1R_FSC13 ((uint16_t)0x2000) /*!< Filter Scale Configuration bit 13 */ + +/****************** Bit definition for CAN_FFA1R register *******************/ +#define CAN_FFA1R_FFA ((uint16_t)0x3FFF) /*!< Filter FIFO Assignment */ +#define CAN_FFA1R_FFA0 ((uint16_t)0x0001) /*!< Filter FIFO Assignment for Filter 0 */ +#define CAN_FFA1R_FFA1 ((uint16_t)0x0002) /*!< Filter FIFO Assignment for Filter 1 */ +#define CAN_FFA1R_FFA2 ((uint16_t)0x0004) /*!< Filter FIFO Assignment for Filter 2 */ +#define CAN_FFA1R_FFA3 ((uint16_t)0x0008) /*!< Filter FIFO Assignment for Filter 3 */ +#define CAN_FFA1R_FFA4 ((uint16_t)0x0010) /*!< Filter FIFO Assignment for Filter 4 */ +#define CAN_FFA1R_FFA5 ((uint16_t)0x0020) /*!< Filter FIFO Assignment for Filter 5 */ +#define CAN_FFA1R_FFA6 ((uint16_t)0x0040) /*!< Filter FIFO Assignment for Filter 6 */ +#define CAN_FFA1R_FFA7 ((uint16_t)0x0080) /*!< Filter FIFO Assignment for Filter 7 */ +#define CAN_FFA1R_FFA8 ((uint16_t)0x0100) /*!< Filter FIFO Assignment for Filter 8 */ +#define CAN_FFA1R_FFA9 ((uint16_t)0x0200) /*!< Filter FIFO Assignment for Filter 9 */ +#define CAN_FFA1R_FFA10 ((uint16_t)0x0400) /*!< Filter FIFO Assignment for Filter 10 */ +#define CAN_FFA1R_FFA11 ((uint16_t)0x0800) /*!< Filter FIFO Assignment for Filter 11 */ +#define CAN_FFA1R_FFA12 ((uint16_t)0x1000) /*!< Filter FIFO Assignment for Filter 12 */ +#define CAN_FFA1R_FFA13 ((uint16_t)0x2000) /*!< Filter FIFO Assignment for Filter 13 */ + +/******************* Bit definition for CAN_FA1R register *******************/ +#define CAN_FA1R_FACT ((uint16_t)0x3FFF) /*!< Filter Active */ +#define CAN_FA1R_FACT0 ((uint16_t)0x0001) /*!< Filter 0 Active */ +#define CAN_FA1R_FACT1 ((uint16_t)0x0002) /*!< Filter 1 Active */ +#define CAN_FA1R_FACT2 ((uint16_t)0x0004) /*!< Filter 2 Active */ +#define CAN_FA1R_FACT3 ((uint16_t)0x0008) /*!< Filter 3 Active */ +#define CAN_FA1R_FACT4 ((uint16_t)0x0010) /*!< Filter 4 Active */ +#define CAN_FA1R_FACT5 ((uint16_t)0x0020) /*!< Filter 5 Active */ +#define CAN_FA1R_FACT6 ((uint16_t)0x0040) /*!< Filter 6 Active */ +#define CAN_FA1R_FACT7 ((uint16_t)0x0080) /*!< Filter 7 Active */ +#define CAN_FA1R_FACT8 ((uint16_t)0x0100) /*!< Filter 8 Active */ +#define CAN_FA1R_FACT9 ((uint16_t)0x0200) /*!< Filter 9 Active */ +#define CAN_FA1R_FACT10 ((uint16_t)0x0400) /*!< Filter 10 Active */ +#define CAN_FA1R_FACT11 ((uint16_t)0x0800) /*!< Filter 11 Active */ +#define CAN_FA1R_FACT12 ((uint16_t)0x1000) /*!< Filter 12 Active */ +#define CAN_FA1R_FACT13 ((uint16_t)0x2000) /*!< Filter 13 Active */ + +/******************* Bit definition for CAN_F0R1 register *******************/ +#define CAN_F0R1_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F0R1_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F0R1_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F0R1_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F0R1_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F0R1_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F0R1_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F0R1_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F0R1_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F0R1_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F0R1_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F0R1_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F0R1_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F0R1_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F0R1_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F0R1_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F0R1_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F0R1_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F0R1_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F0R1_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F0R1_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F0R1_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F0R1_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F0R1_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F0R1_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F0R1_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F0R1_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F0R1_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F0R1_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F0R1_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F0R1_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F0R1_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F1R1 register *******************/ +#define CAN_F1R1_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F1R1_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F1R1_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F1R1_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F1R1_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F1R1_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F1R1_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F1R1_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F1R1_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F1R1_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F1R1_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F1R1_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F1R1_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F1R1_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F1R1_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F1R1_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F1R1_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F1R1_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F1R1_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F1R1_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F1R1_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F1R1_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F1R1_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F1R1_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F1R1_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F1R1_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F1R1_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F1R1_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F1R1_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F1R1_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F1R1_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F1R1_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F2R1 register *******************/ +#define CAN_F2R1_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F2R1_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F2R1_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F2R1_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F2R1_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F2R1_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F2R1_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F2R1_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F2R1_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F2R1_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F2R1_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F2R1_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F2R1_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F2R1_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F2R1_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F2R1_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F2R1_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F2R1_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F2R1_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F2R1_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F2R1_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F2R1_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F2R1_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F2R1_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F2R1_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F2R1_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F2R1_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F2R1_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F2R1_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F2R1_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F2R1_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F2R1_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F3R1 register *******************/ +#define CAN_F3R1_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F3R1_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F3R1_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F3R1_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F3R1_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F3R1_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F3R1_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F3R1_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F3R1_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F3R1_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F3R1_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F3R1_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F3R1_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F3R1_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F3R1_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F3R1_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F3R1_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F3R1_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F3R1_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F3R1_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F3R1_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F3R1_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F3R1_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F3R1_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F3R1_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F3R1_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F3R1_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F3R1_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F3R1_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F3R1_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F3R1_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F3R1_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F4R1 register *******************/ +#define CAN_F4R1_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F4R1_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F4R1_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F4R1_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F4R1_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F4R1_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F4R1_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F4R1_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F4R1_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F4R1_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F4R1_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F4R1_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F4R1_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F4R1_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F4R1_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F4R1_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F4R1_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F4R1_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F4R1_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F4R1_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F4R1_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F4R1_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F4R1_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F4R1_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F4R1_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F4R1_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F4R1_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F4R1_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F4R1_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F4R1_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F4R1_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F4R1_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F5R1 register *******************/ +#define CAN_F5R1_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F5R1_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F5R1_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F5R1_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F5R1_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F5R1_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F5R1_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F5R1_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F5R1_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F5R1_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F5R1_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F5R1_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F5R1_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F5R1_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F5R1_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F5R1_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F5R1_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F5R1_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F5R1_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F5R1_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F5R1_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F5R1_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F5R1_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F5R1_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F5R1_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F5R1_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F5R1_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F5R1_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F5R1_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F5R1_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F5R1_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F5R1_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F6R1 register *******************/ +#define CAN_F6R1_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F6R1_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F6R1_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F6R1_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F6R1_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F6R1_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F6R1_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F6R1_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F6R1_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F6R1_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F6R1_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F6R1_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F6R1_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F6R1_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F6R1_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F6R1_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F6R1_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F6R1_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F6R1_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F6R1_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F6R1_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F6R1_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F6R1_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F6R1_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F6R1_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F6R1_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F6R1_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F6R1_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F6R1_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F6R1_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F6R1_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F6R1_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F7R1 register *******************/ +#define CAN_F7R1_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F7R1_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F7R1_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F7R1_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F7R1_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F7R1_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F7R1_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F7R1_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F7R1_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F7R1_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F7R1_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F7R1_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F7R1_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F7R1_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F7R1_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F7R1_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F7R1_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F7R1_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F7R1_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F7R1_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F7R1_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F7R1_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F7R1_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F7R1_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F7R1_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F7R1_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F7R1_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F7R1_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F7R1_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F7R1_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F7R1_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F7R1_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F8R1 register *******************/ +#define CAN_F8R1_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F8R1_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F8R1_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F8R1_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F8R1_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F8R1_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F8R1_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F8R1_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F8R1_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F8R1_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F8R1_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F8R1_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F8R1_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F8R1_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F8R1_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F8R1_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F8R1_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F8R1_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F8R1_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F8R1_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F8R1_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F8R1_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F8R1_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F8R1_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F8R1_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F8R1_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F8R1_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F8R1_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F8R1_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F8R1_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F8R1_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F8R1_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F9R1 register *******************/ +#define CAN_F9R1_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F9R1_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F9R1_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F9R1_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F9R1_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F9R1_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F9R1_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F9R1_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F9R1_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F9R1_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F9R1_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F9R1_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F9R1_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F9R1_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F9R1_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F9R1_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F9R1_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F9R1_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F9R1_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F9R1_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F9R1_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F9R1_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F9R1_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F9R1_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F9R1_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F9R1_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F9R1_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F9R1_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F9R1_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F9R1_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F9R1_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F9R1_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F10R1 register ******************/ +#define CAN_F10R1_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F10R1_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F10R1_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F10R1_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F10R1_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F10R1_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F10R1_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F10R1_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F10R1_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F10R1_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F10R1_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F10R1_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F10R1_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F10R1_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F10R1_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F10R1_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F10R1_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F10R1_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F10R1_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F10R1_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F10R1_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F10R1_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F10R1_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F10R1_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F10R1_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F10R1_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F10R1_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F10R1_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F10R1_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F10R1_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F10R1_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F10R1_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F11R1 register ******************/ +#define CAN_F11R1_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F11R1_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F11R1_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F11R1_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F11R1_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F11R1_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F11R1_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F11R1_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F11R1_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F11R1_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F11R1_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F11R1_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F11R1_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F11R1_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F11R1_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F11R1_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F11R1_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F11R1_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F11R1_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F11R1_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F11R1_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F11R1_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F11R1_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F11R1_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F11R1_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F11R1_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F11R1_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F11R1_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F11R1_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F11R1_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F11R1_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F11R1_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F12R1 register ******************/ +#define CAN_F12R1_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F12R1_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F12R1_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F12R1_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F12R1_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F12R1_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F12R1_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F12R1_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F12R1_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F12R1_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F12R1_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F12R1_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F12R1_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F12R1_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F12R1_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F12R1_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F12R1_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F12R1_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F12R1_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F12R1_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F12R1_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F12R1_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F12R1_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F12R1_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F12R1_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F12R1_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F12R1_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F12R1_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F12R1_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F12R1_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F12R1_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F12R1_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F13R1 register ******************/ +#define CAN_F13R1_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F13R1_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F13R1_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F13R1_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F13R1_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F13R1_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F13R1_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F13R1_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F13R1_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F13R1_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F13R1_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F13R1_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F13R1_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F13R1_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F13R1_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F13R1_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F13R1_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F13R1_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F13R1_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F13R1_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F13R1_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F13R1_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F13R1_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F13R1_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F13R1_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F13R1_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F13R1_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F13R1_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F13R1_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F13R1_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F13R1_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F13R1_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F0R2 register *******************/ +#define CAN_F0R2_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F0R2_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F0R2_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F0R2_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F0R2_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F0R2_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F0R2_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F0R2_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F0R2_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F0R2_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F0R2_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F0R2_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F0R2_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F0R2_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F0R2_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F0R2_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F0R2_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F0R2_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F0R2_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F0R2_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F0R2_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F0R2_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F0R2_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F0R2_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F0R2_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F0R2_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F0R2_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F0R2_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F0R2_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F0R2_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F0R2_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F0R2_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F1R2 register *******************/ +#define CAN_F1R2_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F1R2_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F1R2_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F1R2_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F1R2_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F1R2_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F1R2_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F1R2_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F1R2_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F1R2_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F1R2_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F1R2_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F1R2_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F1R2_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F1R2_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F1R2_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F1R2_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F1R2_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F1R2_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F1R2_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F1R2_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F1R2_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F1R2_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F1R2_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F1R2_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F1R2_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F1R2_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F1R2_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F1R2_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F1R2_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F1R2_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F1R2_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F2R2 register *******************/ +#define CAN_F2R2_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F2R2_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F2R2_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F2R2_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F2R2_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F2R2_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F2R2_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F2R2_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F2R2_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F2R2_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F2R2_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F2R2_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F2R2_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F2R2_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F2R2_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F2R2_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F2R2_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F2R2_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F2R2_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F2R2_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F2R2_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F2R2_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F2R2_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F2R2_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F2R2_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F2R2_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F2R2_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F2R2_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F2R2_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F2R2_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F2R2_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F2R2_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F3R2 register *******************/ +#define CAN_F3R2_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F3R2_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F3R2_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F3R2_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F3R2_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F3R2_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F3R2_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F3R2_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F3R2_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F3R2_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F3R2_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F3R2_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F3R2_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F3R2_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F3R2_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F3R2_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F3R2_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F3R2_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F3R2_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F3R2_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F3R2_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F3R2_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F3R2_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F3R2_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F3R2_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F3R2_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F3R2_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F3R2_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F3R2_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F3R2_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F3R2_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F3R2_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F4R2 register *******************/ +#define CAN_F4R2_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F4R2_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F4R2_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F4R2_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F4R2_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F4R2_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F4R2_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F4R2_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F4R2_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F4R2_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F4R2_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F4R2_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F4R2_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F4R2_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F4R2_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F4R2_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F4R2_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F4R2_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F4R2_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F4R2_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F4R2_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F4R2_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F4R2_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F4R2_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F4R2_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F4R2_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F4R2_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F4R2_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F4R2_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F4R2_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F4R2_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F4R2_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F5R2 register *******************/ +#define CAN_F5R2_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F5R2_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F5R2_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F5R2_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F5R2_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F5R2_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F5R2_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F5R2_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F5R2_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F5R2_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F5R2_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F5R2_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F5R2_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F5R2_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F5R2_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F5R2_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F5R2_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F5R2_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F5R2_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F5R2_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F5R2_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F5R2_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F5R2_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F5R2_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F5R2_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F5R2_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F5R2_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F5R2_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F5R2_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F5R2_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F5R2_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F5R2_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F6R2 register *******************/ +#define CAN_F6R2_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F6R2_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F6R2_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F6R2_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F6R2_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F6R2_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F6R2_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F6R2_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F6R2_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F6R2_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F6R2_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F6R2_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F6R2_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F6R2_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F6R2_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F6R2_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F6R2_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F6R2_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F6R2_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F6R2_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F6R2_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F6R2_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F6R2_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F6R2_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F6R2_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F6R2_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F6R2_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F6R2_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F6R2_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F6R2_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F6R2_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F6R2_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F7R2 register *******************/ +#define CAN_F7R2_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F7R2_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F7R2_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F7R2_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F7R2_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F7R2_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F7R2_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F7R2_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F7R2_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F7R2_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F7R2_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F7R2_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F7R2_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F7R2_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F7R2_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F7R2_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F7R2_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F7R2_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F7R2_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F7R2_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F7R2_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F7R2_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F7R2_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F7R2_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F7R2_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F7R2_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F7R2_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F7R2_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F7R2_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F7R2_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F7R2_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F7R2_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F8R2 register *******************/ +#define CAN_F8R2_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F8R2_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F8R2_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F8R2_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F8R2_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F8R2_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F8R2_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F8R2_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F8R2_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F8R2_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F8R2_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F8R2_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F8R2_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F8R2_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F8R2_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F8R2_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F8R2_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F8R2_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F8R2_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F8R2_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F8R2_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F8R2_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F8R2_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F8R2_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F8R2_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F8R2_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F8R2_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F8R2_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F8R2_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F8R2_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F8R2_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F8R2_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F9R2 register *******************/ +#define CAN_F9R2_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F9R2_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F9R2_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F9R2_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F9R2_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F9R2_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F9R2_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F9R2_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F9R2_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F9R2_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F9R2_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F9R2_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F9R2_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F9R2_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F9R2_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F9R2_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F9R2_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F9R2_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F9R2_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F9R2_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F9R2_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F9R2_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F9R2_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F9R2_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F9R2_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F9R2_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F9R2_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F9R2_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F9R2_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F9R2_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F9R2_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F9R2_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F10R2 register ******************/ +#define CAN_F10R2_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F10R2_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F10R2_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F10R2_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F10R2_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F10R2_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F10R2_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F10R2_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F10R2_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F10R2_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F10R2_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F10R2_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F10R2_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F10R2_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F10R2_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F10R2_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F10R2_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F10R2_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F10R2_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F10R2_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F10R2_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F10R2_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F10R2_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F10R2_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F10R2_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F10R2_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F10R2_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F10R2_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F10R2_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F10R2_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F10R2_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F10R2_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F11R2 register ******************/ +#define CAN_F11R2_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F11R2_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F11R2_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F11R2_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F11R2_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F11R2_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F11R2_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F11R2_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F11R2_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F11R2_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F11R2_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F11R2_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F11R2_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F11R2_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F11R2_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F11R2_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F11R2_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F11R2_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F11R2_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F11R2_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F11R2_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F11R2_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F11R2_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F11R2_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F11R2_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F11R2_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F11R2_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F11R2_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F11R2_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F11R2_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F11R2_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F11R2_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F12R2 register ******************/ +#define CAN_F12R2_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F12R2_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F12R2_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F12R2_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F12R2_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F12R2_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F12R2_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F12R2_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F12R2_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F12R2_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F12R2_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F12R2_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F12R2_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F12R2_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F12R2_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F12R2_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F12R2_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F12R2_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F12R2_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F12R2_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F12R2_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F12R2_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F12R2_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F12R2_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F12R2_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F12R2_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F12R2_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F12R2_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F12R2_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F12R2_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F12R2_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F12R2_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************* Bit definition for CAN_F13R2 register ******************/ +#define CAN_F13R2_FB0 ((uint32_t)0x00000001) /*!< Filter bit 0 */ +#define CAN_F13R2_FB1 ((uint32_t)0x00000002) /*!< Filter bit 1 */ +#define CAN_F13R2_FB2 ((uint32_t)0x00000004) /*!< Filter bit 2 */ +#define CAN_F13R2_FB3 ((uint32_t)0x00000008) /*!< Filter bit 3 */ +#define CAN_F13R2_FB4 ((uint32_t)0x00000010) /*!< Filter bit 4 */ +#define CAN_F13R2_FB5 ((uint32_t)0x00000020) /*!< Filter bit 5 */ +#define CAN_F13R2_FB6 ((uint32_t)0x00000040) /*!< Filter bit 6 */ +#define CAN_F13R2_FB7 ((uint32_t)0x00000080) /*!< Filter bit 7 */ +#define CAN_F13R2_FB8 ((uint32_t)0x00000100) /*!< Filter bit 8 */ +#define CAN_F13R2_FB9 ((uint32_t)0x00000200) /*!< Filter bit 9 */ +#define CAN_F13R2_FB10 ((uint32_t)0x00000400) /*!< Filter bit 10 */ +#define CAN_F13R2_FB11 ((uint32_t)0x00000800) /*!< Filter bit 11 */ +#define CAN_F13R2_FB12 ((uint32_t)0x00001000) /*!< Filter bit 12 */ +#define CAN_F13R2_FB13 ((uint32_t)0x00002000) /*!< Filter bit 13 */ +#define CAN_F13R2_FB14 ((uint32_t)0x00004000) /*!< Filter bit 14 */ +#define CAN_F13R2_FB15 ((uint32_t)0x00008000) /*!< Filter bit 15 */ +#define CAN_F13R2_FB16 ((uint32_t)0x00010000) /*!< Filter bit 16 */ +#define CAN_F13R2_FB17 ((uint32_t)0x00020000) /*!< Filter bit 17 */ +#define CAN_F13R2_FB18 ((uint32_t)0x00040000) /*!< Filter bit 18 */ +#define CAN_F13R2_FB19 ((uint32_t)0x00080000) /*!< Filter bit 19 */ +#define CAN_F13R2_FB20 ((uint32_t)0x00100000) /*!< Filter bit 20 */ +#define CAN_F13R2_FB21 ((uint32_t)0x00200000) /*!< Filter bit 21 */ +#define CAN_F13R2_FB22 ((uint32_t)0x00400000) /*!< Filter bit 22 */ +#define CAN_F13R2_FB23 ((uint32_t)0x00800000) /*!< Filter bit 23 */ +#define CAN_F13R2_FB24 ((uint32_t)0x01000000) /*!< Filter bit 24 */ +#define CAN_F13R2_FB25 ((uint32_t)0x02000000) /*!< Filter bit 25 */ +#define CAN_F13R2_FB26 ((uint32_t)0x04000000) /*!< Filter bit 26 */ +#define CAN_F13R2_FB27 ((uint32_t)0x08000000) /*!< Filter bit 27 */ +#define CAN_F13R2_FB28 ((uint32_t)0x10000000) /*!< Filter bit 28 */ +#define CAN_F13R2_FB29 ((uint32_t)0x20000000) /*!< Filter bit 29 */ +#define CAN_F13R2_FB30 ((uint32_t)0x40000000) /*!< Filter bit 30 */ +#define CAN_F13R2_FB31 ((uint32_t)0x80000000) /*!< Filter bit 31 */ + +/******************************************************************************/ +/* */ +/* Serial Peripheral Interface */ +/* */ +/******************************************************************************/ + +/******************* Bit definition for SPI_CR1 register ********************/ +#define SPI_CR1_CPHA ((uint16_t)0x0001) /*!< Clock Phase */ +#define SPI_CR1_CPOL ((uint16_t)0x0002) /*!< Clock Polarity */ +#define SPI_CR1_MSTR ((uint16_t)0x0004) /*!< Master Selection */ + +#define SPI_CR1_BR ((uint16_t)0x0038) /*!< BR[2:0] bits (Baud Rate Control) */ +#define SPI_CR1_BR_0 ((uint16_t)0x0008) /*!< Bit 0 */ +#define SPI_CR1_BR_1 ((uint16_t)0x0010) /*!< Bit 1 */ +#define SPI_CR1_BR_2 ((uint16_t)0x0020) /*!< Bit 2 */ + +#define SPI_CR1_SPE ((uint16_t)0x0040) /*!< SPI Enable */ +#define SPI_CR1_LSBFIRST ((uint16_t)0x0080) /*!< Frame Format */ +#define SPI_CR1_SSI ((uint16_t)0x0100) /*!< Internal slave select */ +#define SPI_CR1_SSM ((uint16_t)0x0200) /*!< Software slave management */ +#define SPI_CR1_RXONLY ((uint16_t)0x0400) /*!< Receive only */ +#define SPI_CR1_DFF ((uint16_t)0x0800) /*!< Data Frame Format */ +#define SPI_CR1_CRCNEXT ((uint16_t)0x1000) /*!< Transmit CRC next */ +#define SPI_CR1_CRCEN ((uint16_t)0x2000) /*!< Hardware CRC calculation enable */ +#define SPI_CR1_BIDIOE ((uint16_t)0x4000) /*!< Output enable in bidirectional mode */ +#define SPI_CR1_BIDIMODE ((uint16_t)0x8000) /*!< Bidirectional data mode enable */ + +/******************* Bit definition for SPI_CR2 register ********************/ +#define SPI_CR2_RXDMAEN ((uint8_t)0x01) /*!< Rx Buffer DMA Enable */ +#define SPI_CR2_TXDMAEN ((uint8_t)0x02) /*!< Tx Buffer DMA Enable */ +#define SPI_CR2_SSOE ((uint8_t)0x04) /*!< SS Output Enable */ +#define SPI_CR2_ERRIE ((uint8_t)0x20) /*!< Error Interrupt Enable */ +#define SPI_CR2_RXNEIE ((uint8_t)0x40) /*!< RX buffer Not Empty Interrupt Enable */ +#define SPI_CR2_TXEIE ((uint8_t)0x80) /*!< Tx buffer Empty Interrupt Enable */ + +/******************** Bit definition for SPI_SR register ********************/ +#define SPI_SR_RXNE ((uint8_t)0x01) /*!< Receive buffer Not Empty */ +#define SPI_SR_TXE ((uint8_t)0x02) /*!< Transmit buffer Empty */ +#define SPI_SR_CHSIDE ((uint8_t)0x04) /*!< Channel side */ +#define SPI_SR_UDR ((uint8_t)0x08) /*!< Underrun flag */ +#define SPI_SR_CRCERR ((uint8_t)0x10) /*!< CRC Error flag */ +#define SPI_SR_MODF ((uint8_t)0x20) /*!< Mode fault */ +#define SPI_SR_OVR ((uint8_t)0x40) /*!< Overrun flag */ +#define SPI_SR_BSY ((uint8_t)0x80) /*!< Busy flag */ + +/******************** Bit definition for SPI_DR register ********************/ +#define SPI_DR_DR ((uint16_t)0xFFFF) /*!< Data Register */ + +/******************* Bit definition for SPI_CRCPR register ******************/ +#define SPI_CRCPR_CRCPOLY ((uint16_t)0xFFFF) /*!< CRC polynomial register */ + +/****************** Bit definition for SPI_RXCRCR register ******************/ +#define SPI_RXCRCR_RXCRC ((uint16_t)0xFFFF) /*!< Rx CRC Register */ + +/****************** Bit definition for SPI_TXCRCR register ******************/ +#define SPI_TXCRCR_TXCRC ((uint16_t)0xFFFF) /*!< Tx CRC Register */ + +/****************** Bit definition for SPI_I2SCFGR register *****************/ +#define SPI_I2SCFGR_CHLEN ((uint16_t)0x0001) /*!< Channel length (number of bits per audio channel) */ + +#define SPI_I2SCFGR_DATLEN ((uint16_t)0x0006) /*!< DATLEN[1:0] bits (Data length to be transferred) */ +#define SPI_I2SCFGR_DATLEN_0 ((uint16_t)0x0002) /*!< Bit 0 */ +#define SPI_I2SCFGR_DATLEN_1 ((uint16_t)0x0004) /*!< Bit 1 */ + +#define SPI_I2SCFGR_CKPOL ((uint16_t)0x0008) /*!< steady state clock polarity */ + +#define SPI_I2SCFGR_I2SSTD ((uint16_t)0x0030) /*!< I2SSTD[1:0] bits (I2S standard selection) */ +#define SPI_I2SCFGR_I2SSTD_0 ((uint16_t)0x0010) /*!< Bit 0 */ +#define SPI_I2SCFGR_I2SSTD_1 ((uint16_t)0x0020) /*!< Bit 1 */ + +#define SPI_I2SCFGR_PCMSYNC ((uint16_t)0x0080) /*!< PCM frame synchronization */ + +#define SPI_I2SCFGR_I2SCFG ((uint16_t)0x0300) /*!< I2SCFG[1:0] bits (I2S configuration mode) */ +#define SPI_I2SCFGR_I2SCFG_0 ((uint16_t)0x0100) /*!< Bit 0 */ +#define SPI_I2SCFGR_I2SCFG_1 ((uint16_t)0x0200) /*!< Bit 1 */ + +#define SPI_I2SCFGR_I2SE ((uint16_t)0x0400) /*!< I2S Enable */ +#define SPI_I2SCFGR_I2SMOD ((uint16_t)0x0800) /*!< I2S mode selection */ + +/****************** Bit definition for SPI_I2SPR register *******************/ +#define SPI_I2SPR_I2SDIV ((uint16_t)0x00FF) /*!< I2S Linear prescaler */ +#define SPI_I2SPR_ODD ((uint16_t)0x0100) /*!< Odd factor for the prescaler */ +#define SPI_I2SPR_MCKOE ((uint16_t)0x0200) /*!< Master Clock Output Enable */ + +/******************************************************************************/ +/* */ +/* Inter-integrated Circuit Interface */ +/* */ +/******************************************************************************/ + +/******************* Bit definition for I2C_CR1 register ********************/ +#define I2C_CR1_PE ((uint16_t)0x0001) /*!< Peripheral Enable */ +#define I2C_CR1_SMBUS ((uint16_t)0x0002) /*!< SMBus Mode */ +#define I2C_CR1_SMBTYPE ((uint16_t)0x0008) /*!< SMBus Type */ +#define I2C_CR1_ENARP ((uint16_t)0x0010) /*!< ARP Enable */ +#define I2C_CR1_ENPEC ((uint16_t)0x0020) /*!< PEC Enable */ +#define I2C_CR1_ENGC ((uint16_t)0x0040) /*!< General Call Enable */ +#define I2C_CR1_NOSTRETCH ((uint16_t)0x0080) /*!< Clock Stretching Disable (Slave mode) */ +#define I2C_CR1_START ((uint16_t)0x0100) /*!< Start Generation */ +#define I2C_CR1_STOP ((uint16_t)0x0200) /*!< Stop Generation */ +#define I2C_CR1_ACK ((uint16_t)0x0400) /*!< Acknowledge Enable */ +#define I2C_CR1_POS ((uint16_t)0x0800) /*!< Acknowledge/PEC Position (for data reception) */ +#define I2C_CR1_PEC ((uint16_t)0x1000) /*!< Packet Error Checking */ +#define I2C_CR1_ALERT ((uint16_t)0x2000) /*!< SMBus Alert */ +#define I2C_CR1_SWRST ((uint16_t)0x8000) /*!< Software Reset */ + +/******************* Bit definition for I2C_CR2 register ********************/ +#define I2C_CR2_FREQ ((uint16_t)0x003F) /*!< FREQ[5:0] bits (Peripheral Clock Frequency) */ +#define I2C_CR2_FREQ_0 ((uint16_t)0x0001) /*!< Bit 0 */ +#define I2C_CR2_FREQ_1 ((uint16_t)0x0002) /*!< Bit 1 */ +#define I2C_CR2_FREQ_2 ((uint16_t)0x0004) /*!< Bit 2 */ +#define I2C_CR2_FREQ_3 ((uint16_t)0x0008) /*!< Bit 3 */ +#define I2C_CR2_FREQ_4 ((uint16_t)0x0010) /*!< Bit 4 */ +#define I2C_CR2_FREQ_5 ((uint16_t)0x0020) /*!< Bit 5 */ + +#define I2C_CR2_ITERREN ((uint16_t)0x0100) /*!< Error Interrupt Enable */ +#define I2C_CR2_ITEVTEN ((uint16_t)0x0200) /*!< Event Interrupt Enable */ +#define I2C_CR2_ITBUFEN ((uint16_t)0x0400) /*!< Buffer Interrupt Enable */ +#define I2C_CR2_DMAEN ((uint16_t)0x0800) /*!< DMA Requests Enable */ +#define I2C_CR2_LAST ((uint16_t)0x1000) /*!< DMA Last Transfer */ + +/******************* Bit definition for I2C_OAR1 register *******************/ +#define I2C_OAR1_ADD1_7 ((uint16_t)0x00FE) /*!< Interface Address */ +#define I2C_OAR1_ADD8_9 ((uint16_t)0x0300) /*!< Interface Address */ + +#define I2C_OAR1_ADD0 ((uint16_t)0x0001) /*!< Bit 0 */ +#define I2C_OAR1_ADD1 ((uint16_t)0x0002) /*!< Bit 1 */ +#define I2C_OAR1_ADD2 ((uint16_t)0x0004) /*!< Bit 2 */ +#define I2C_OAR1_ADD3 ((uint16_t)0x0008) /*!< Bit 3 */ +#define I2C_OAR1_ADD4 ((uint16_t)0x0010) /*!< Bit 4 */ +#define I2C_OAR1_ADD5 ((uint16_t)0x0020) /*!< Bit 5 */ +#define I2C_OAR1_ADD6 ((uint16_t)0x0040) /*!< Bit 6 */ +#define I2C_OAR1_ADD7 ((uint16_t)0x0080) /*!< Bit 7 */ +#define I2C_OAR1_ADD8 ((uint16_t)0x0100) /*!< Bit 8 */ +#define I2C_OAR1_ADD9 ((uint16_t)0x0200) /*!< Bit 9 */ + +#define I2C_OAR1_ADDMODE ((uint16_t)0x8000) /*!< Addressing Mode (Slave mode) */ + +/******************* Bit definition for I2C_OAR2 register *******************/ +#define I2C_OAR2_ENDUAL ((uint8_t)0x01) /*!< Dual addressing mode enable */ +#define I2C_OAR2_ADD2 ((uint8_t)0xFE) /*!< Interface address */ + +/******************** Bit definition for I2C_DR register ********************/ +#define I2C_DR_DR ((uint8_t)0xFF) /*!< 8-bit Data Register */ + +/******************* Bit definition for I2C_SR1 register ********************/ +#define I2C_SR1_SB ((uint16_t)0x0001) /*!< Start Bit (Master mode) */ +#define I2C_SR1_ADDR ((uint16_t)0x0002) /*!< Address sent (master mode)/matched (slave mode) */ +#define I2C_SR1_BTF ((uint16_t)0x0004) /*!< Byte Transfer Finished */ +#define I2C_SR1_ADD10 ((uint16_t)0x0008) /*!< 10-bit header sent (Master mode) */ +#define I2C_SR1_STOPF ((uint16_t)0x0010) /*!< Stop detection (Slave mode) */ +#define I2C_SR1_RXNE ((uint16_t)0x0040) /*!< Data Register not Empty (receivers) */ +#define I2C_SR1_TXE ((uint16_t)0x0080) /*!< Data Register Empty (transmitters) */ +#define I2C_SR1_BERR ((uint16_t)0x0100) /*!< Bus Error */ +#define I2C_SR1_ARLO ((uint16_t)0x0200) /*!< Arbitration Lost (master mode) */ +#define I2C_SR1_AF ((uint16_t)0x0400) /*!< Acknowledge Failure */ +#define I2C_SR1_OVR ((uint16_t)0x0800) /*!< Overrun/Underrun */ +#define I2C_SR1_PECERR ((uint16_t)0x1000) /*!< PEC Error in reception */ +#define I2C_SR1_TIMEOUT ((uint16_t)0x4000) /*!< Timeout or Tlow Error */ +#define I2C_SR1_SMBALERT ((uint16_t)0x8000) /*!< SMBus Alert */ + +/******************* Bit definition for I2C_SR2 register ********************/ +#define I2C_SR2_MSL ((uint16_t)0x0001) /*!< Master/Slave */ +#define I2C_SR2_BUSY ((uint16_t)0x0002) /*!< Bus Busy */ +#define I2C_SR2_TRA ((uint16_t)0x0004) /*!< Transmitter/Receiver */ +#define I2C_SR2_GENCALL ((uint16_t)0x0010) /*!< General Call Address (Slave mode) */ +#define I2C_SR2_SMBDEFAULT ((uint16_t)0x0020) /*!< SMBus Device Default Address (Slave mode) */ +#define I2C_SR2_SMBHOST ((uint16_t)0x0040) /*!< SMBus Host Header (Slave mode) */ +#define I2C_SR2_DUALF ((uint16_t)0x0080) /*!< Dual Flag (Slave mode) */ +#define I2C_SR2_PEC ((uint16_t)0xFF00) /*!< Packet Error Checking Register */ + +/******************* Bit definition for I2C_CCR register ********************/ +#define I2C_CCR_CCR ((uint16_t)0x0FFF) /*!< Clock Control Register in Fast/Standard mode (Master mode) */ +#define I2C_CCR_DUTY ((uint16_t)0x4000) /*!< Fast Mode Duty Cycle */ +#define I2C_CCR_FS ((uint16_t)0x8000) /*!< I2C Master Mode Selection */ + +/****************** Bit definition for I2C_TRISE register *******************/ +#define I2C_TRISE_TRISE ((uint8_t)0x3F) /*!< Maximum Rise Time in Fast/Standard mode (Master mode) */ + +/******************************************************************************/ +/* */ +/* Universal Synchronous Asynchronous Receiver Transmitter */ +/* */ +/******************************************************************************/ + +/******************* Bit definition for USART_SR register *******************/ +#define USART_SR_PE ((uint16_t)0x0001) /*!< Parity Error */ +#define USART_SR_FE ((uint16_t)0x0002) /*!< Framing Error */ +#define USART_SR_NE ((uint16_t)0x0004) /*!< Noise Error Flag */ +#define USART_SR_ORE ((uint16_t)0x0008) /*!< OverRun Error */ +#define USART_SR_IDLE ((uint16_t)0x0010) /*!< IDLE line detected */ +#define USART_SR_RXNE ((uint16_t)0x0020) /*!< Read Data Register Not Empty */ +#define USART_SR_TC ((uint16_t)0x0040) /*!< Transmission Complete */ +#define USART_SR_TXE ((uint16_t)0x0080) /*!< Transmit Data Register Empty */ +#define USART_SR_LBD ((uint16_t)0x0100) /*!< LIN Break Detection Flag */ +#define USART_SR_CTS ((uint16_t)0x0200) /*!< CTS Flag */ + +/******************* Bit definition for USART_DR register *******************/ +#define USART_DR_DR ((uint16_t)0x01FF) /*!< Data value */ + +/****************** Bit definition for USART_BRR register *******************/ +#define USART_BRR_DIV_Fraction ((uint16_t)0x000F) /*!< Fraction of USARTDIV */ +#define USART_BRR_DIV_Mantissa ((uint16_t)0xFFF0) /*!< Mantissa of USARTDIV */ + +/****************** Bit definition for USART_CR1 register *******************/ +#define USART_CR1_SBK ((uint16_t)0x0001) /*!< Send Break */ +#define USART_CR1_RWU ((uint16_t)0x0002) /*!< Receiver wakeup */ +#define USART_CR1_RE ((uint16_t)0x0004) /*!< Receiver Enable */ +#define USART_CR1_TE ((uint16_t)0x0008) /*!< Transmitter Enable */ +#define USART_CR1_IDLEIE ((uint16_t)0x0010) /*!< IDLE Interrupt Enable */ +#define USART_CR1_RXNEIE ((uint16_t)0x0020) /*!< RXNE Interrupt Enable */ +#define USART_CR1_TCIE ((uint16_t)0x0040) /*!< Transmission Complete Interrupt Enable */ +#define USART_CR1_TXEIE ((uint16_t)0x0080) /*!< PE Interrupt Enable */ +#define USART_CR1_PEIE ((uint16_t)0x0100) /*!< PE Interrupt Enable */ +#define USART_CR1_PS ((uint16_t)0x0200) /*!< Parity Selection */ +#define USART_CR1_PCE ((uint16_t)0x0400) /*!< Parity Control Enable */ +#define USART_CR1_WAKE ((uint16_t)0x0800) /*!< Wakeup method */ +#define USART_CR1_M ((uint16_t)0x1000) /*!< Word length */ +#define USART_CR1_UE ((uint16_t)0x2000) /*!< USART Enable */ +#define USART_CR1_OVER8 ((uint16_t)0x8000) /*!< USART Oversmapling 8-bits */ + +/****************** Bit definition for USART_CR2 register *******************/ +#define USART_CR2_ADD ((uint16_t)0x000F) /*!< Address of the USART node */ +#define USART_CR2_LBDL ((uint16_t)0x0020) /*!< LIN Break Detection Length */ +#define USART_CR2_LBDIE ((uint16_t)0x0040) /*!< LIN Break Detection Interrupt Enable */ +#define USART_CR2_LBCL ((uint16_t)0x0100) /*!< Last Bit Clock pulse */ +#define USART_CR2_CPHA ((uint16_t)0x0200) /*!< Clock Phase */ +#define USART_CR2_CPOL ((uint16_t)0x0400) /*!< Clock Polarity */ +#define USART_CR2_CLKEN ((uint16_t)0x0800) /*!< Clock Enable */ + +#define USART_CR2_STOP ((uint16_t)0x3000) /*!< STOP[1:0] bits (STOP bits) */ +#define USART_CR2_STOP_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define USART_CR2_STOP_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define USART_CR2_LINEN ((uint16_t)0x4000) /*!< LIN mode enable */ + +/****************** Bit definition for USART_CR3 register *******************/ +#define USART_CR3_EIE ((uint16_t)0x0001) /*!< Error Interrupt Enable */ +#define USART_CR3_IREN ((uint16_t)0x0002) /*!< IrDA mode Enable */ +#define USART_CR3_IRLP ((uint16_t)0x0004) /*!< IrDA Low-Power */ +#define USART_CR3_HDSEL ((uint16_t)0x0008) /*!< Half-Duplex Selection */ +#define USART_CR3_NACK ((uint16_t)0x0010) /*!< Smartcard NACK enable */ +#define USART_CR3_SCEN ((uint16_t)0x0020) /*!< Smartcard mode enable */ +#define USART_CR3_DMAR ((uint16_t)0x0040) /*!< DMA Enable Receiver */ +#define USART_CR3_DMAT ((uint16_t)0x0080) /*!< DMA Enable Transmitter */ +#define USART_CR3_RTSE ((uint16_t)0x0100) /*!< RTS Enable */ +#define USART_CR3_CTSE ((uint16_t)0x0200) /*!< CTS Enable */ +#define USART_CR3_CTSIE ((uint16_t)0x0400) /*!< CTS Interrupt Enable */ +#define USART_CR3_ONEBIT ((uint16_t)0x0800) /*!< One Bit method */ + +/****************** Bit definition for USART_GTPR register ******************/ +#define USART_GTPR_PSC ((uint16_t)0x00FF) /*!< PSC[7:0] bits (Prescaler value) */ +#define USART_GTPR_PSC_0 ((uint16_t)0x0001) /*!< Bit 0 */ +#define USART_GTPR_PSC_1 ((uint16_t)0x0002) /*!< Bit 1 */ +#define USART_GTPR_PSC_2 ((uint16_t)0x0004) /*!< Bit 2 */ +#define USART_GTPR_PSC_3 ((uint16_t)0x0008) /*!< Bit 3 */ +#define USART_GTPR_PSC_4 ((uint16_t)0x0010) /*!< Bit 4 */ +#define USART_GTPR_PSC_5 ((uint16_t)0x0020) /*!< Bit 5 */ +#define USART_GTPR_PSC_6 ((uint16_t)0x0040) /*!< Bit 6 */ +#define USART_GTPR_PSC_7 ((uint16_t)0x0080) /*!< Bit 7 */ + +#define USART_GTPR_GT ((uint16_t)0xFF00) /*!< Guard time value */ + +/******************************************************************************/ +/* */ +/* Debug MCU */ +/* */ +/******************************************************************************/ + +/**************** Bit definition for DBGMCU_IDCODE register *****************/ +#define DBGMCU_IDCODE_DEV_ID ((uint32_t)0x00000FFF) /*!< Device Identifier */ + +#define DBGMCU_IDCODE_REV_ID ((uint32_t)0xFFFF0000) /*!< REV_ID[15:0] bits (Revision Identifier) */ +#define DBGMCU_IDCODE_REV_ID_0 ((uint32_t)0x00010000) /*!< Bit 0 */ +#define DBGMCU_IDCODE_REV_ID_1 ((uint32_t)0x00020000) /*!< Bit 1 */ +#define DBGMCU_IDCODE_REV_ID_2 ((uint32_t)0x00040000) /*!< Bit 2 */ +#define DBGMCU_IDCODE_REV_ID_3 ((uint32_t)0x00080000) /*!< Bit 3 */ +#define DBGMCU_IDCODE_REV_ID_4 ((uint32_t)0x00100000) /*!< Bit 4 */ +#define DBGMCU_IDCODE_REV_ID_5 ((uint32_t)0x00200000) /*!< Bit 5 */ +#define DBGMCU_IDCODE_REV_ID_6 ((uint32_t)0x00400000) /*!< Bit 6 */ +#define DBGMCU_IDCODE_REV_ID_7 ((uint32_t)0x00800000) /*!< Bit 7 */ +#define DBGMCU_IDCODE_REV_ID_8 ((uint32_t)0x01000000) /*!< Bit 8 */ +#define DBGMCU_IDCODE_REV_ID_9 ((uint32_t)0x02000000) /*!< Bit 9 */ +#define DBGMCU_IDCODE_REV_ID_10 ((uint32_t)0x04000000) /*!< Bit 10 */ +#define DBGMCU_IDCODE_REV_ID_11 ((uint32_t)0x08000000) /*!< Bit 11 */ +#define DBGMCU_IDCODE_REV_ID_12 ((uint32_t)0x10000000) /*!< Bit 12 */ +#define DBGMCU_IDCODE_REV_ID_13 ((uint32_t)0x20000000) /*!< Bit 13 */ +#define DBGMCU_IDCODE_REV_ID_14 ((uint32_t)0x40000000) /*!< Bit 14 */ +#define DBGMCU_IDCODE_REV_ID_15 ((uint32_t)0x80000000) /*!< Bit 15 */ + +/****************** Bit definition for DBGMCU_CR register *******************/ +#define DBGMCU_CR_DBG_SLEEP ((uint32_t)0x00000001) /*!< Debug Sleep Mode */ +#define DBGMCU_CR_DBG_STOP ((uint32_t)0x00000002) /*!< Debug Stop Mode */ +#define DBGMCU_CR_DBG_STANDBY ((uint32_t)0x00000004) /*!< Debug Standby mode */ +#define DBGMCU_CR_TRACE_IOEN ((uint32_t)0x00000020) /*!< Trace Pin Assignment Control */ + +#define DBGMCU_CR_TRACE_MODE ((uint32_t)0x000000C0) /*!< TRACE_MODE[1:0] bits (Trace Pin Assignment Control) */ +#define DBGMCU_CR_TRACE_MODE_0 ((uint32_t)0x00000040) /*!< Bit 0 */ +#define DBGMCU_CR_TRACE_MODE_1 ((uint32_t)0x00000080) /*!< Bit 1 */ + +#define DBGMCU_CR_DBG_IWDG_STOP ((uint32_t)0x00000100) /*!< Debug Independent Watchdog stopped when Core is halted */ +#define DBGMCU_CR_DBG_WWDG_STOP ((uint32_t)0x00000200) /*!< Debug Window Watchdog stopped when Core is halted */ +#define DBGMCU_CR_DBG_TIM1_STOP ((uint32_t)0x00000400) /*!< TIM1 counter stopped when core is halted */ +#define DBGMCU_CR_DBG_TIM2_STOP ((uint32_t)0x00000800) /*!< TIM2 counter stopped when core is halted */ +#define DBGMCU_CR_DBG_TIM3_STOP ((uint32_t)0x00001000) /*!< TIM3 counter stopped when core is halted */ +#define DBGMCU_CR_DBG_TIM4_STOP ((uint32_t)0x00002000) /*!< TIM4 counter stopped when core is halted */ +#define DBGMCU_CR_DBG_CAN1_STOP ((uint32_t)0x00004000) /*!< Debug CAN1 stopped when Core is halted */ +#define DBGMCU_CR_DBG_I2C1_SMBUS_TIMEOUT ((uint32_t)0x00008000) /*!< SMBUS timeout mode stopped when Core is halted */ +#define DBGMCU_CR_DBG_I2C2_SMBUS_TIMEOUT ((uint32_t)0x00010000) /*!< SMBUS timeout mode stopped when Core is halted */ +#define DBGMCU_CR_DBG_TIM8_STOP ((uint32_t)0x00020000) /*!< TIM8 counter stopped when core is halted */ +#define DBGMCU_CR_DBG_TIM5_STOP ((uint32_t)0x00040000) /*!< TIM5 counter stopped when core is halted */ +#define DBGMCU_CR_DBG_TIM6_STOP ((uint32_t)0x00080000) /*!< TIM6 counter stopped when core is halted */ +#define DBGMCU_CR_DBG_TIM7_STOP ((uint32_t)0x00100000) /*!< TIM7 counter stopped when core is halted */ +#define DBGMCU_CR_DBG_CAN2_STOP ((uint32_t)0x00200000) /*!< Debug CAN2 stopped when Core is halted */ +#define DBGMCU_CR_DBG_TIM15_STOP ((uint32_t)0x00400000) /*!< Debug TIM15 stopped when Core is halted */ +#define DBGMCU_CR_DBG_TIM16_STOP ((uint32_t)0x00800000) /*!< Debug TIM16 stopped when Core is halted */ +#define DBGMCU_CR_DBG_TIM17_STOP ((uint32_t)0x01000000) /*!< Debug TIM17 stopped when Core is halted */ +#define DBGMCU_CR_DBG_TIM12_STOP ((uint32_t)0x02000000) /*!< Debug TIM12 stopped when Core is halted */ +#define DBGMCU_CR_DBG_TIM13_STOP ((uint32_t)0x04000000) /*!< Debug TIM13 stopped when Core is halted */ +#define DBGMCU_CR_DBG_TIM14_STOP ((uint32_t)0x08000000) /*!< Debug TIM14 stopped when Core is halted */ +#define DBGMCU_CR_DBG_TIM9_STOP ((uint32_t)0x10000000) /*!< Debug TIM9 stopped when Core is halted */ +#define DBGMCU_CR_DBG_TIM10_STOP ((uint32_t)0x20000000) /*!< Debug TIM10 stopped when Core is halted */ +#define DBGMCU_CR_DBG_TIM11_STOP ((uint32_t)0x40000000) /*!< Debug TIM11 stopped when Core is halted */ + +/******************************************************************************/ +/* */ +/* FLASH and Option Bytes Registers */ +/* */ +/******************************************************************************/ + +/******************* Bit definition for FLASH_ACR register ******************/ +#define FLASH_ACR_LATENCY ((uint8_t)0x03) /*!< LATENCY[2:0] bits (Latency) */ +#define FLASH_ACR_LATENCY_0 ((uint8_t)0x00) /*!< Bit 0 */ +#define FLASH_ACR_LATENCY_1 ((uint8_t)0x01) /*!< Bit 0 */ +#define FLASH_ACR_LATENCY_2 ((uint8_t)0x02) /*!< Bit 1 */ + +#define FLASH_ACR_HLFCYA ((uint8_t)0x08) /*!< Flash Half Cycle Access Enable */ +#define FLASH_ACR_PRFTBE ((uint8_t)0x10) /*!< Prefetch Buffer Enable */ +#define FLASH_ACR_PRFTBS ((uint8_t)0x20) /*!< Prefetch Buffer Status */ + +/****************** Bit definition for FLASH_KEYR register ******************/ +#define FLASH_KEYR_FKEYR ((uint32_t)0xFFFFFFFF) /*!< FPEC Key */ + +/***************** Bit definition for FLASH_OPTKEYR register ****************/ +#define FLASH_OPTKEYR_OPTKEYR ((uint32_t)0xFFFFFFFF) /*!< Option Byte Key */ + +/****************** Bit definition for FLASH_SR register *******************/ +#define FLASH_SR_BSY ((uint8_t)0x01) /*!< Busy */ +#define FLASH_SR_PGERR ((uint8_t)0x04) /*!< Programming Error */ +#define FLASH_SR_WRPRTERR ((uint8_t)0x10) /*!< Write Protection Error */ +#define FLASH_SR_EOP ((uint8_t)0x20) /*!< End of operation */ + +/******************* Bit definition for FLASH_CR register *******************/ +#define FLASH_CR_PG ((uint16_t)0x0001) /*!< Programming */ +#define FLASH_CR_PER ((uint16_t)0x0002) /*!< Page Erase */ +#define FLASH_CR_MER ((uint16_t)0x0004) /*!< Mass Erase */ +#define FLASH_CR_OPTPG ((uint16_t)0x0010) /*!< Option Byte Programming */ +#define FLASH_CR_OPTER ((uint16_t)0x0020) /*!< Option Byte Erase */ +#define FLASH_CR_STRT ((uint16_t)0x0040) /*!< Start */ +#define FLASH_CR_LOCK ((uint16_t)0x0080) /*!< Lock */ +#define FLASH_CR_OPTWRE ((uint16_t)0x0200) /*!< Option Bytes Write Enable */ +#define FLASH_CR_ERRIE ((uint16_t)0x0400) /*!< Error Interrupt Enable */ +#define FLASH_CR_EOPIE ((uint16_t)0x1000) /*!< End of operation interrupt enable */ + +/******************* Bit definition for FLASH_AR register *******************/ +#define FLASH_AR_FAR ((uint32_t)0xFFFFFFFF) /*!< Flash Address */ + +/****************** Bit definition for FLASH_OBR register *******************/ +#define FLASH_OBR_OPTERR ((uint16_t)0x0001) /*!< Option Byte Error */ +#define FLASH_OBR_RDPRT ((uint16_t)0x0002) /*!< Read protection */ + +#define FLASH_OBR_USER ((uint16_t)0x03FC) /*!< User Option Bytes */ +#define FLASH_OBR_WDG_SW ((uint16_t)0x0004) /*!< WDG_SW */ +#define FLASH_OBR_nRST_STOP ((uint16_t)0x0008) /*!< nRST_STOP */ +#define FLASH_OBR_nRST_STDBY ((uint16_t)0x0010) /*!< nRST_STDBY */ +#define FLASH_OBR_BFB2 ((uint16_t)0x0020) /*!< BFB2 */ + +/****************** Bit definition for FLASH_WRPR register ******************/ +#define FLASH_WRPR_WRP ((uint32_t)0xFFFFFFFF) /*!< Write Protect */ + +/*----------------------------------------------------------------------------*/ + +/****************** Bit definition for FLASH_RDP register *******************/ +#define FLASH_RDP_RDP ((uint32_t)0x000000FF) /*!< Read protection option byte */ +#define FLASH_RDP_nRDP ((uint32_t)0x0000FF00) /*!< Read protection complemented option byte */ + +/****************** Bit definition for FLASH_USER register ******************/ +#define FLASH_USER_USER ((uint32_t)0x00FF0000) /*!< User option byte */ +#define FLASH_USER_nUSER ((uint32_t)0xFF000000) /*!< User complemented option byte */ + +/****************** Bit definition for FLASH_Data0 register *****************/ +#define FLASH_Data0_Data0 ((uint32_t)0x000000FF) /*!< User data storage option byte */ +#define FLASH_Data0_nData0 ((uint32_t)0x0000FF00) /*!< User data storage complemented option byte */ + +/****************** Bit definition for FLASH_Data1 register *****************/ +#define FLASH_Data1_Data1 ((uint32_t)0x00FF0000) /*!< User data storage option byte */ +#define FLASH_Data1_nData1 ((uint32_t)0xFF000000) /*!< User data storage complemented option byte */ + +/****************** Bit definition for FLASH_WRP0 register ******************/ +#define FLASH_WRP0_WRP0 ((uint32_t)0x000000FF) /*!< Flash memory write protection option bytes */ +#define FLASH_WRP0_nWRP0 ((uint32_t)0x0000FF00) /*!< Flash memory write protection complemented option bytes */ + +/****************** Bit definition for FLASH_WRP1 register ******************/ +#define FLASH_WRP1_WRP1 ((uint32_t)0x00FF0000) /*!< Flash memory write protection option bytes */ +#define FLASH_WRP1_nWRP1 ((uint32_t)0xFF000000) /*!< Flash memory write protection complemented option bytes */ + +/****************** Bit definition for FLASH_WRP2 register ******************/ +#define FLASH_WRP2_WRP2 ((uint32_t)0x000000FF) /*!< Flash memory write protection option bytes */ +#define FLASH_WRP2_nWRP2 ((uint32_t)0x0000FF00) /*!< Flash memory write protection complemented option bytes */ + +/****************** Bit definition for FLASH_WRP3 register ******************/ +#define FLASH_WRP3_WRP3 ((uint32_t)0x00FF0000) /*!< Flash memory write protection option bytes */ +#define FLASH_WRP3_nWRP3 ((uint32_t)0xFF000000) /*!< Flash memory write protection complemented option bytes */ + +#ifdef STM32F10X_CL +/******************************************************************************/ +/* Ethernet MAC Registers bits definitions */ +/******************************************************************************/ +/* Bit definition for Ethernet MAC Control Register register */ +#define ETH_MACCR_WD ((uint32_t)0x00800000) /* Watchdog disable */ +#define ETH_MACCR_JD ((uint32_t)0x00400000) /* Jabber disable */ +#define ETH_MACCR_IFG ((uint32_t)0x000E0000) /* Inter-frame gap */ + #define ETH_MACCR_IFG_96Bit ((uint32_t)0x00000000) /* Minimum IFG between frames during transmission is 96Bit */ + #define ETH_MACCR_IFG_88Bit ((uint32_t)0x00020000) /* Minimum IFG between frames during transmission is 88Bit */ + #define ETH_MACCR_IFG_80Bit ((uint32_t)0x00040000) /* Minimum IFG between frames during transmission is 80Bit */ + #define ETH_MACCR_IFG_72Bit ((uint32_t)0x00060000) /* Minimum IFG between frames during transmission is 72Bit */ + #define ETH_MACCR_IFG_64Bit ((uint32_t)0x00080000) /* Minimum IFG between frames during transmission is 64Bit */ + #define ETH_MACCR_IFG_56Bit ((uint32_t)0x000A0000) /* Minimum IFG between frames during transmission is 56Bit */ + #define ETH_MACCR_IFG_48Bit ((uint32_t)0x000C0000) /* Minimum IFG between frames during transmission is 48Bit */ + #define ETH_MACCR_IFG_40Bit ((uint32_t)0x000E0000) /* Minimum IFG between frames during transmission is 40Bit */ +#define ETH_MACCR_CSD ((uint32_t)0x00010000) /* Carrier sense disable (during transmission) */ +#define ETH_MACCR_FES ((uint32_t)0x00004000) /* Fast ethernet speed */ +#define ETH_MACCR_ROD ((uint32_t)0x00002000) /* Receive own disable */ +#define ETH_MACCR_LM ((uint32_t)0x00001000) /* loopback mode */ +#define ETH_MACCR_DM ((uint32_t)0x00000800) /* Duplex mode */ +#define ETH_MACCR_IPCO ((uint32_t)0x00000400) /* IP Checksum offload */ +#define ETH_MACCR_RD ((uint32_t)0x00000200) /* Retry disable */ +#define ETH_MACCR_APCS ((uint32_t)0x00000080) /* Automatic Pad/CRC stripping */ +#define ETH_MACCR_BL ((uint32_t)0x00000060) /* Back-off limit: random integer number (r) of slot time delays before rescheduling + a transmission attempt during retries after a collision: 0 =< r <2^k */ + #define ETH_MACCR_BL_10 ((uint32_t)0x00000000) /* k = min (n, 10) */ + #define ETH_MACCR_BL_8 ((uint32_t)0x00000020) /* k = min (n, 8) */ + #define ETH_MACCR_BL_4 ((uint32_t)0x00000040) /* k = min (n, 4) */ + #define ETH_MACCR_BL_1 ((uint32_t)0x00000060) /* k = min (n, 1) */ +#define ETH_MACCR_DC ((uint32_t)0x00000010) /* Defferal check */ +#define ETH_MACCR_TE ((uint32_t)0x00000008) /* Transmitter enable */ +#define ETH_MACCR_RE ((uint32_t)0x00000004) /* Receiver enable */ + +/* Bit definition for Ethernet MAC Frame Filter Register */ +#define ETH_MACFFR_RA ((uint32_t)0x80000000) /* Receive all */ +#define ETH_MACFFR_HPF ((uint32_t)0x00000400) /* Hash or perfect filter */ +#define ETH_MACFFR_SAF ((uint32_t)0x00000200) /* Source address filter enable */ +#define ETH_MACFFR_SAIF ((uint32_t)0x00000100) /* SA inverse filtering */ +#define ETH_MACFFR_PCF ((uint32_t)0x000000C0) /* Pass control frames: 3 cases */ + #define ETH_MACFFR_PCF_BlockAll ((uint32_t)0x00000040) /* MAC filters all control frames from reaching the application */ + #define ETH_MACFFR_PCF_ForwardAll ((uint32_t)0x00000080) /* MAC forwards all control frames to application even if they fail the Address Filter */ + #define ETH_MACFFR_PCF_ForwardPassedAddrFilter ((uint32_t)0x000000C0) /* MAC forwards control frames that pass the Address Filter. */ +#define ETH_MACFFR_BFD ((uint32_t)0x00000020) /* Broadcast frame disable */ +#define ETH_MACFFR_PAM ((uint32_t)0x00000010) /* Pass all mutlicast */ +#define ETH_MACFFR_DAIF ((uint32_t)0x00000008) /* DA Inverse filtering */ +#define ETH_MACFFR_HM ((uint32_t)0x00000004) /* Hash multicast */ +#define ETH_MACFFR_HU ((uint32_t)0x00000002) /* Hash unicast */ +#define ETH_MACFFR_PM ((uint32_t)0x00000001) /* Promiscuous mode */ + +/* Bit definition for Ethernet MAC Hash Table High Register */ +#define ETH_MACHTHR_HTH ((uint32_t)0xFFFFFFFF) /* Hash table high */ + +/* Bit definition for Ethernet MAC Hash Table Low Register */ +#define ETH_MACHTLR_HTL ((uint32_t)0xFFFFFFFF) /* Hash table low */ + +/* Bit definition for Ethernet MAC MII Address Register */ +#define ETH_MACMIIAR_PA ((uint32_t)0x0000F800) /* Physical layer address */ +#define ETH_MACMIIAR_MR ((uint32_t)0x000007C0) /* MII register in the selected PHY */ +#define ETH_MACMIIAR_CR ((uint32_t)0x0000001C) /* CR clock range: 6 cases */ + #define ETH_MACMIIAR_CR_Div42 ((uint32_t)0x00000000) /* HCLK:60-72 MHz; MDC clock= HCLK/42 */ + #define ETH_MACMIIAR_CR_Div16 ((uint32_t)0x00000008) /* HCLK:20-35 MHz; MDC clock= HCLK/16 */ + #define ETH_MACMIIAR_CR_Div26 ((uint32_t)0x0000000C) /* HCLK:35-60 MHz; MDC clock= HCLK/26 */ +#define ETH_MACMIIAR_MW ((uint32_t)0x00000002) /* MII write */ +#define ETH_MACMIIAR_MB ((uint32_t)0x00000001) /* MII busy */ + +/* Bit definition for Ethernet MAC MII Data Register */ +#define ETH_MACMIIDR_MD ((uint32_t)0x0000FFFF) /* MII data: read/write data from/to PHY */ + +/* Bit definition for Ethernet MAC Flow Control Register */ +#define ETH_MACFCR_PT ((uint32_t)0xFFFF0000) /* Pause time */ +#define ETH_MACFCR_ZQPD ((uint32_t)0x00000080) /* Zero-quanta pause disable */ +#define ETH_MACFCR_PLT ((uint32_t)0x00000030) /* Pause low threshold: 4 cases */ + #define ETH_MACFCR_PLT_Minus4 ((uint32_t)0x00000000) /* Pause time minus 4 slot times */ + #define ETH_MACFCR_PLT_Minus28 ((uint32_t)0x00000010) /* Pause time minus 28 slot times */ + #define ETH_MACFCR_PLT_Minus144 ((uint32_t)0x00000020) /* Pause time minus 144 slot times */ + #define ETH_MACFCR_PLT_Minus256 ((uint32_t)0x00000030) /* Pause time minus 256 slot times */ +#define ETH_MACFCR_UPFD ((uint32_t)0x00000008) /* Unicast pause frame detect */ +#define ETH_MACFCR_RFCE ((uint32_t)0x00000004) /* Receive flow control enable */ +#define ETH_MACFCR_TFCE ((uint32_t)0x00000002) /* Transmit flow control enable */ +#define ETH_MACFCR_FCBBPA ((uint32_t)0x00000001) /* Flow control busy/backpressure activate */ + +/* Bit definition for Ethernet MAC VLAN Tag Register */ +#define ETH_MACVLANTR_VLANTC ((uint32_t)0x00010000) /* 12-bit VLAN tag comparison */ +#define ETH_MACVLANTR_VLANTI ((uint32_t)0x0000FFFF) /* VLAN tag identifier (for receive frames) */ + +/* Bit definition for Ethernet MAC Remote Wake-UpFrame Filter Register */ +#define ETH_MACRWUFFR_D ((uint32_t)0xFFFFFFFF) /* Wake-up frame filter register data */ +/* Eight sequential Writes to this address (offset 0x28) will write all Wake-UpFrame Filter Registers. + Eight sequential Reads from this address (offset 0x28) will read all Wake-UpFrame Filter Registers. */ +/* Wake-UpFrame Filter Reg0 : Filter 0 Byte Mask + Wake-UpFrame Filter Reg1 : Filter 1 Byte Mask + Wake-UpFrame Filter Reg2 : Filter 2 Byte Mask + Wake-UpFrame Filter Reg3 : Filter 3 Byte Mask + Wake-UpFrame Filter Reg4 : RSVD - Filter3 Command - RSVD - Filter2 Command - + RSVD - Filter1 Command - RSVD - Filter0 Command + Wake-UpFrame Filter Re5 : Filter3 Offset - Filter2 Offset - Filter1 Offset - Filter0 Offset + Wake-UpFrame Filter Re6 : Filter1 CRC16 - Filter0 CRC16 + Wake-UpFrame Filter Re7 : Filter3 CRC16 - Filter2 CRC16 */ + +/* Bit definition for Ethernet MAC PMT Control and Status Register */ +#define ETH_MACPMTCSR_WFFRPR ((uint32_t)0x80000000) /* Wake-Up Frame Filter Register Pointer Reset */ +#define ETH_MACPMTCSR_GU ((uint32_t)0x00000200) /* Global Unicast */ +#define ETH_MACPMTCSR_WFR ((uint32_t)0x00000040) /* Wake-Up Frame Received */ +#define ETH_MACPMTCSR_MPR ((uint32_t)0x00000020) /* Magic Packet Received */ +#define ETH_MACPMTCSR_WFE ((uint32_t)0x00000004) /* Wake-Up Frame Enable */ +#define ETH_MACPMTCSR_MPE ((uint32_t)0x00000002) /* Magic Packet Enable */ +#define ETH_MACPMTCSR_PD ((uint32_t)0x00000001) /* Power Down */ + +/* Bit definition for Ethernet MAC Status Register */ +#define ETH_MACSR_TSTS ((uint32_t)0x00000200) /* Time stamp trigger status */ +#define ETH_MACSR_MMCTS ((uint32_t)0x00000040) /* MMC transmit status */ +#define ETH_MACSR_MMMCRS ((uint32_t)0x00000020) /* MMC receive status */ +#define ETH_MACSR_MMCS ((uint32_t)0x00000010) /* MMC status */ +#define ETH_MACSR_PMTS ((uint32_t)0x00000008) /* PMT status */ + +/* Bit definition for Ethernet MAC Interrupt Mask Register */ +#define ETH_MACIMR_TSTIM ((uint32_t)0x00000200) /* Time stamp trigger interrupt mask */ +#define ETH_MACIMR_PMTIM ((uint32_t)0x00000008) /* PMT interrupt mask */ + +/* Bit definition for Ethernet MAC Address0 High Register */ +#define ETH_MACA0HR_MACA0H ((uint32_t)0x0000FFFF) /* MAC address0 high */ + +/* Bit definition for Ethernet MAC Address0 Low Register */ +#define ETH_MACA0LR_MACA0L ((uint32_t)0xFFFFFFFF) /* MAC address0 low */ + +/* Bit definition for Ethernet MAC Address1 High Register */ +#define ETH_MACA1HR_AE ((uint32_t)0x80000000) /* Address enable */ +#define ETH_MACA1HR_SA ((uint32_t)0x40000000) /* Source address */ +#define ETH_MACA1HR_MBC ((uint32_t)0x3F000000) /* Mask byte control: bits to mask for comparison of the MAC Address bytes */ + #define ETH_MACA1HR_MBC_HBits15_8 ((uint32_t)0x20000000) /* Mask MAC Address high reg bits [15:8] */ + #define ETH_MACA1HR_MBC_HBits7_0 ((uint32_t)0x10000000) /* Mask MAC Address high reg bits [7:0] */ + #define ETH_MACA1HR_MBC_LBits31_24 ((uint32_t)0x08000000) /* Mask MAC Address low reg bits [31:24] */ + #define ETH_MACA1HR_MBC_LBits23_16 ((uint32_t)0x04000000) /* Mask MAC Address low reg bits [23:16] */ + #define ETH_MACA1HR_MBC_LBits15_8 ((uint32_t)0x02000000) /* Mask MAC Address low reg bits [15:8] */ + #define ETH_MACA1HR_MBC_LBits7_0 ((uint32_t)0x01000000) /* Mask MAC Address low reg bits [7:0] */ +#define ETH_MACA1HR_MACA1H ((uint32_t)0x0000FFFF) /* MAC address1 high */ + +/* Bit definition for Ethernet MAC Address1 Low Register */ +#define ETH_MACA1LR_MACA1L ((uint32_t)0xFFFFFFFF) /* MAC address1 low */ + +/* Bit definition for Ethernet MAC Address2 High Register */ +#define ETH_MACA2HR_AE ((uint32_t)0x80000000) /* Address enable */ +#define ETH_MACA2HR_SA ((uint32_t)0x40000000) /* Source address */ +#define ETH_MACA2HR_MBC ((uint32_t)0x3F000000) /* Mask byte control */ + #define ETH_MACA2HR_MBC_HBits15_8 ((uint32_t)0x20000000) /* Mask MAC Address high reg bits [15:8] */ + #define ETH_MACA2HR_MBC_HBits7_0 ((uint32_t)0x10000000) /* Mask MAC Address high reg bits [7:0] */ + #define ETH_MACA2HR_MBC_LBits31_24 ((uint32_t)0x08000000) /* Mask MAC Address low reg bits [31:24] */ + #define ETH_MACA2HR_MBC_LBits23_16 ((uint32_t)0x04000000) /* Mask MAC Address low reg bits [23:16] */ + #define ETH_MACA2HR_MBC_LBits15_8 ((uint32_t)0x02000000) /* Mask MAC Address low reg bits [15:8] */ + #define ETH_MACA2HR_MBC_LBits7_0 ((uint32_t)0x01000000) /* Mask MAC Address low reg bits [70] */ +#define ETH_MACA2HR_MACA2H ((uint32_t)0x0000FFFF) /* MAC address1 high */ + +/* Bit definition for Ethernet MAC Address2 Low Register */ +#define ETH_MACA2LR_MACA2L ((uint32_t)0xFFFFFFFF) /* MAC address2 low */ + +/* Bit definition for Ethernet MAC Address3 High Register */ +#define ETH_MACA3HR_AE ((uint32_t)0x80000000) /* Address enable */ +#define ETH_MACA3HR_SA ((uint32_t)0x40000000) /* Source address */ +#define ETH_MACA3HR_MBC ((uint32_t)0x3F000000) /* Mask byte control */ + #define ETH_MACA3HR_MBC_HBits15_8 ((uint32_t)0x20000000) /* Mask MAC Address high reg bits [15:8] */ + #define ETH_MACA3HR_MBC_HBits7_0 ((uint32_t)0x10000000) /* Mask MAC Address high reg bits [7:0] */ + #define ETH_MACA3HR_MBC_LBits31_24 ((uint32_t)0x08000000) /* Mask MAC Address low reg bits [31:24] */ + #define ETH_MACA3HR_MBC_LBits23_16 ((uint32_t)0x04000000) /* Mask MAC Address low reg bits [23:16] */ + #define ETH_MACA3HR_MBC_LBits15_8 ((uint32_t)0x02000000) /* Mask MAC Address low reg bits [15:8] */ + #define ETH_MACA3HR_MBC_LBits7_0 ((uint32_t)0x01000000) /* Mask MAC Address low reg bits [70] */ +#define ETH_MACA3HR_MACA3H ((uint32_t)0x0000FFFF) /* MAC address3 high */ + +/* Bit definition for Ethernet MAC Address3 Low Register */ +#define ETH_MACA3LR_MACA3L ((uint32_t)0xFFFFFFFF) /* MAC address3 low */ + +/******************************************************************************/ +/* Ethernet MMC Registers bits definition */ +/******************************************************************************/ + +/* Bit definition for Ethernet MMC Contol Register */ +#define ETH_MMCCR_MCF ((uint32_t)0x00000008) /* MMC Counter Freeze */ +#define ETH_MMCCR_ROR ((uint32_t)0x00000004) /* Reset on Read */ +#define ETH_MMCCR_CSR ((uint32_t)0x00000002) /* Counter Stop Rollover */ +#define ETH_MMCCR_CR ((uint32_t)0x00000001) /* Counters Reset */ + +/* Bit definition for Ethernet MMC Receive Interrupt Register */ +#define ETH_MMCRIR_RGUFS ((uint32_t)0x00020000) /* Set when Rx good unicast frames counter reaches half the maximum value */ +#define ETH_MMCRIR_RFAES ((uint32_t)0x00000040) /* Set when Rx alignment error counter reaches half the maximum value */ +#define ETH_MMCRIR_RFCES ((uint32_t)0x00000020) /* Set when Rx crc error counter reaches half the maximum value */ + +/* Bit definition for Ethernet MMC Transmit Interrupt Register */ +#define ETH_MMCTIR_TGFS ((uint32_t)0x00200000) /* Set when Tx good frame count counter reaches half the maximum value */ +#define ETH_MMCTIR_TGFMSCS ((uint32_t)0x00008000) /* Set when Tx good multi col counter reaches half the maximum value */ +#define ETH_MMCTIR_TGFSCS ((uint32_t)0x00004000) /* Set when Tx good single col counter reaches half the maximum value */ + +/* Bit definition for Ethernet MMC Receive Interrupt Mask Register */ +#define ETH_MMCRIMR_RGUFM ((uint32_t)0x00020000) /* Mask the interrupt when Rx good unicast frames counter reaches half the maximum value */ +#define ETH_MMCRIMR_RFAEM ((uint32_t)0x00000040) /* Mask the interrupt when when Rx alignment error counter reaches half the maximum value */ +#define ETH_MMCRIMR_RFCEM ((uint32_t)0x00000020) /* Mask the interrupt when Rx crc error counter reaches half the maximum value */ + +/* Bit definition for Ethernet MMC Transmit Interrupt Mask Register */ +#define ETH_MMCTIMR_TGFM ((uint32_t)0x00200000) /* Mask the interrupt when Tx good frame count counter reaches half the maximum value */ +#define ETH_MMCTIMR_TGFMSCM ((uint32_t)0x00008000) /* Mask the interrupt when Tx good multi col counter reaches half the maximum value */ +#define ETH_MMCTIMR_TGFSCM ((uint32_t)0x00004000) /* Mask the interrupt when Tx good single col counter reaches half the maximum value */ + +/* Bit definition for Ethernet MMC Transmitted Good Frames after Single Collision Counter Register */ +#define ETH_MMCTGFSCCR_TGFSCC ((uint32_t)0xFFFFFFFF) /* Number of successfully transmitted frames after a single collision in Half-duplex mode. */ + +/* Bit definition for Ethernet MMC Transmitted Good Frames after More than a Single Collision Counter Register */ +#define ETH_MMCTGFMSCCR_TGFMSCC ((uint32_t)0xFFFFFFFF) /* Number of successfully transmitted frames after more than a single collision in Half-duplex mode. */ + +/* Bit definition for Ethernet MMC Transmitted Good Frames Counter Register */ +#define ETH_MMCTGFCR_TGFC ((uint32_t)0xFFFFFFFF) /* Number of good frames transmitted. */ + +/* Bit definition for Ethernet MMC Received Frames with CRC Error Counter Register */ +#define ETH_MMCRFCECR_RFCEC ((uint32_t)0xFFFFFFFF) /* Number of frames received with CRC error. */ + +/* Bit definition for Ethernet MMC Received Frames with Alignement Error Counter Register */ +#define ETH_MMCRFAECR_RFAEC ((uint32_t)0xFFFFFFFF) /* Number of frames received with alignment (dribble) error */ + +/* Bit definition for Ethernet MMC Received Good Unicast Frames Counter Register */ +#define ETH_MMCRGUFCR_RGUFC ((uint32_t)0xFFFFFFFF) /* Number of good unicast frames received. */ + +/******************************************************************************/ +/* Ethernet PTP Registers bits definition */ +/******************************************************************************/ + +/* Bit definition for Ethernet PTP Time Stamp Contol Register */ +#define ETH_PTPTSCR_TSARU ((uint32_t)0x00000020) /* Addend register update */ +#define ETH_PTPTSCR_TSITE ((uint32_t)0x00000010) /* Time stamp interrupt trigger enable */ +#define ETH_PTPTSCR_TSSTU ((uint32_t)0x00000008) /* Time stamp update */ +#define ETH_PTPTSCR_TSSTI ((uint32_t)0x00000004) /* Time stamp initialize */ +#define ETH_PTPTSCR_TSFCU ((uint32_t)0x00000002) /* Time stamp fine or coarse update */ +#define ETH_PTPTSCR_TSE ((uint32_t)0x00000001) /* Time stamp enable */ + +/* Bit definition for Ethernet PTP Sub-Second Increment Register */ +#define ETH_PTPSSIR_STSSI ((uint32_t)0x000000FF) /* System time Sub-second increment value */ + +/* Bit definition for Ethernet PTP Time Stamp High Register */ +#define ETH_PTPTSHR_STS ((uint32_t)0xFFFFFFFF) /* System Time second */ + +/* Bit definition for Ethernet PTP Time Stamp Low Register */ +#define ETH_PTPTSLR_STPNS ((uint32_t)0x80000000) /* System Time Positive or negative time */ +#define ETH_PTPTSLR_STSS ((uint32_t)0x7FFFFFFF) /* System Time sub-seconds */ + +/* Bit definition for Ethernet PTP Time Stamp High Update Register */ +#define ETH_PTPTSHUR_TSUS ((uint32_t)0xFFFFFFFF) /* Time stamp update seconds */ + +/* Bit definition for Ethernet PTP Time Stamp Low Update Register */ +#define ETH_PTPTSLUR_TSUPNS ((uint32_t)0x80000000) /* Time stamp update Positive or negative time */ +#define ETH_PTPTSLUR_TSUSS ((uint32_t)0x7FFFFFFF) /* Time stamp update sub-seconds */ + +/* Bit definition for Ethernet PTP Time Stamp Addend Register */ +#define ETH_PTPTSAR_TSA ((uint32_t)0xFFFFFFFF) /* Time stamp addend */ + +/* Bit definition for Ethernet PTP Target Time High Register */ +#define ETH_PTPTTHR_TTSH ((uint32_t)0xFFFFFFFF) /* Target time stamp high */ + +/* Bit definition for Ethernet PTP Target Time Low Register */ +#define ETH_PTPTTLR_TTSL ((uint32_t)0xFFFFFFFF) /* Target time stamp low */ + +/******************************************************************************/ +/* Ethernet DMA Registers bits definition */ +/******************************************************************************/ + +/* Bit definition for Ethernet DMA Bus Mode Register */ +#define ETH_DMABMR_AAB ((uint32_t)0x02000000) /* Address-Aligned beats */ +#define ETH_DMABMR_FPM ((uint32_t)0x01000000) /* 4xPBL mode */ +#define ETH_DMABMR_USP ((uint32_t)0x00800000) /* Use separate PBL */ +#define ETH_DMABMR_RDP ((uint32_t)0x007E0000) /* RxDMA PBL */ + #define ETH_DMABMR_RDP_1Beat ((uint32_t)0x00020000) /* maximum number of beats to be transferred in one RxDMA transaction is 1 */ + #define ETH_DMABMR_RDP_2Beat ((uint32_t)0x00040000) /* maximum number of beats to be transferred in one RxDMA transaction is 2 */ + #define ETH_DMABMR_RDP_4Beat ((uint32_t)0x00080000) /* maximum number of beats to be transferred in one RxDMA transaction is 4 */ + #define ETH_DMABMR_RDP_8Beat ((uint32_t)0x00100000) /* maximum number of beats to be transferred in one RxDMA transaction is 8 */ + #define ETH_DMABMR_RDP_16Beat ((uint32_t)0x00200000) /* maximum number of beats to be transferred in one RxDMA transaction is 16 */ + #define ETH_DMABMR_RDP_32Beat ((uint32_t)0x00400000) /* maximum number of beats to be transferred in one RxDMA transaction is 32 */ + #define ETH_DMABMR_RDP_4xPBL_4Beat ((uint32_t)0x01020000) /* maximum number of beats to be transferred in one RxDMA transaction is 4 */ + #define ETH_DMABMR_RDP_4xPBL_8Beat ((uint32_t)0x01040000) /* maximum number of beats to be transferred in one RxDMA transaction is 8 */ + #define ETH_DMABMR_RDP_4xPBL_16Beat ((uint32_t)0x01080000) /* maximum number of beats to be transferred in one RxDMA transaction is 16 */ + #define ETH_DMABMR_RDP_4xPBL_32Beat ((uint32_t)0x01100000) /* maximum number of beats to be transferred in one RxDMA transaction is 32 */ + #define ETH_DMABMR_RDP_4xPBL_64Beat ((uint32_t)0x01200000) /* maximum number of beats to be transferred in one RxDMA transaction is 64 */ + #define ETH_DMABMR_RDP_4xPBL_128Beat ((uint32_t)0x01400000) /* maximum number of beats to be transferred in one RxDMA transaction is 128 */ +#define ETH_DMABMR_FB ((uint32_t)0x00010000) /* Fixed Burst */ +#define ETH_DMABMR_RTPR ((uint32_t)0x0000C000) /* Rx Tx priority ratio */ + #define ETH_DMABMR_RTPR_1_1 ((uint32_t)0x00000000) /* Rx Tx priority ratio */ + #define ETH_DMABMR_RTPR_2_1 ((uint32_t)0x00004000) /* Rx Tx priority ratio */ + #define ETH_DMABMR_RTPR_3_1 ((uint32_t)0x00008000) /* Rx Tx priority ratio */ + #define ETH_DMABMR_RTPR_4_1 ((uint32_t)0x0000C000) /* Rx Tx priority ratio */ +#define ETH_DMABMR_PBL ((uint32_t)0x00003F00) /* Programmable burst length */ + #define ETH_DMABMR_PBL_1Beat ((uint32_t)0x00000100) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 1 */ + #define ETH_DMABMR_PBL_2Beat ((uint32_t)0x00000200) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 2 */ + #define ETH_DMABMR_PBL_4Beat ((uint32_t)0x00000400) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 4 */ + #define ETH_DMABMR_PBL_8Beat ((uint32_t)0x00000800) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 8 */ + #define ETH_DMABMR_PBL_16Beat ((uint32_t)0x00001000) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 16 */ + #define ETH_DMABMR_PBL_32Beat ((uint32_t)0x00002000) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 32 */ + #define ETH_DMABMR_PBL_4xPBL_4Beat ((uint32_t)0x01000100) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 4 */ + #define ETH_DMABMR_PBL_4xPBL_8Beat ((uint32_t)0x01000200) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 8 */ + #define ETH_DMABMR_PBL_4xPBL_16Beat ((uint32_t)0x01000400) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 16 */ + #define ETH_DMABMR_PBL_4xPBL_32Beat ((uint32_t)0x01000800) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 32 */ + #define ETH_DMABMR_PBL_4xPBL_64Beat ((uint32_t)0x01001000) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 64 */ + #define ETH_DMABMR_PBL_4xPBL_128Beat ((uint32_t)0x01002000) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 128 */ +#define ETH_DMABMR_DSL ((uint32_t)0x0000007C) /* Descriptor Skip Length */ +#define ETH_DMABMR_DA ((uint32_t)0x00000002) /* DMA arbitration scheme */ +#define ETH_DMABMR_SR ((uint32_t)0x00000001) /* Software reset */ + +/* Bit definition for Ethernet DMA Transmit Poll Demand Register */ +#define ETH_DMATPDR_TPD ((uint32_t)0xFFFFFFFF) /* Transmit poll demand */ + +/* Bit definition for Ethernet DMA Receive Poll Demand Register */ +#define ETH_DMARPDR_RPD ((uint32_t)0xFFFFFFFF) /* Receive poll demand */ + +/* Bit definition for Ethernet DMA Receive Descriptor List Address Register */ +#define ETH_DMARDLAR_SRL ((uint32_t)0xFFFFFFFF) /* Start of receive list */ + +/* Bit definition for Ethernet DMA Transmit Descriptor List Address Register */ +#define ETH_DMATDLAR_STL ((uint32_t)0xFFFFFFFF) /* Start of transmit list */ + +/* Bit definition for Ethernet DMA Status Register */ +#define ETH_DMASR_TSTS ((uint32_t)0x20000000) /* Time-stamp trigger status */ +#define ETH_DMASR_PMTS ((uint32_t)0x10000000) /* PMT status */ +#define ETH_DMASR_MMCS ((uint32_t)0x08000000) /* MMC status */ +#define ETH_DMASR_EBS ((uint32_t)0x03800000) /* Error bits status */ + /* combination with EBS[2:0] for GetFlagStatus function */ + #define ETH_DMASR_EBS_DescAccess ((uint32_t)0x02000000) /* Error bits 0-data buffer, 1-desc. access */ + #define ETH_DMASR_EBS_ReadTransf ((uint32_t)0x01000000) /* Error bits 0-write trnsf, 1-read transfr */ + #define ETH_DMASR_EBS_DataTransfTx ((uint32_t)0x00800000) /* Error bits 0-Rx DMA, 1-Tx DMA */ +#define ETH_DMASR_TPS ((uint32_t)0x00700000) /* Transmit process state */ + #define ETH_DMASR_TPS_Stopped ((uint32_t)0x00000000) /* Stopped - Reset or Stop Tx Command issued */ + #define ETH_DMASR_TPS_Fetching ((uint32_t)0x00100000) /* Running - fetching the Tx descriptor */ + #define ETH_DMASR_TPS_Waiting ((uint32_t)0x00200000) /* Running - waiting for status */ + #define ETH_DMASR_TPS_Reading ((uint32_t)0x00300000) /* Running - reading the data from host memory */ + #define ETH_DMASR_TPS_Suspended ((uint32_t)0x00600000) /* Suspended - Tx Descriptor unavailabe */ + #define ETH_DMASR_TPS_Closing ((uint32_t)0x00700000) /* Running - closing Rx descriptor */ +#define ETH_DMASR_RPS ((uint32_t)0x000E0000) /* Receive process state */ + #define ETH_DMASR_RPS_Stopped ((uint32_t)0x00000000) /* Stopped - Reset or Stop Rx Command issued */ + #define ETH_DMASR_RPS_Fetching ((uint32_t)0x00020000) /* Running - fetching the Rx descriptor */ + #define ETH_DMASR_RPS_Waiting ((uint32_t)0x00060000) /* Running - waiting for packet */ + #define ETH_DMASR_RPS_Suspended ((uint32_t)0x00080000) /* Suspended - Rx Descriptor unavailable */ + #define ETH_DMASR_RPS_Closing ((uint32_t)0x000A0000) /* Running - closing descriptor */ + #define ETH_DMASR_RPS_Queuing ((uint32_t)0x000E0000) /* Running - queuing the recieve frame into host memory */ +#define ETH_DMASR_NIS ((uint32_t)0x00010000) /* Normal interrupt summary */ +#define ETH_DMASR_AIS ((uint32_t)0x00008000) /* Abnormal interrupt summary */ +#define ETH_DMASR_ERS ((uint32_t)0x00004000) /* Early receive status */ +#define ETH_DMASR_FBES ((uint32_t)0x00002000) /* Fatal bus error status */ +#define ETH_DMASR_ETS ((uint32_t)0x00000400) /* Early transmit status */ +#define ETH_DMASR_RWTS ((uint32_t)0x00000200) /* Receive watchdog timeout status */ +#define ETH_DMASR_RPSS ((uint32_t)0x00000100) /* Receive process stopped status */ +#define ETH_DMASR_RBUS ((uint32_t)0x00000080) /* Receive buffer unavailable status */ +#define ETH_DMASR_RS ((uint32_t)0x00000040) /* Receive status */ +#define ETH_DMASR_TUS ((uint32_t)0x00000020) /* Transmit underflow status */ +#define ETH_DMASR_ROS ((uint32_t)0x00000010) /* Receive overflow status */ +#define ETH_DMASR_TJTS ((uint32_t)0x00000008) /* Transmit jabber timeout status */ +#define ETH_DMASR_TBUS ((uint32_t)0x00000004) /* Transmit buffer unavailable status */ +#define ETH_DMASR_TPSS ((uint32_t)0x00000002) /* Transmit process stopped status */ +#define ETH_DMASR_TS ((uint32_t)0x00000001) /* Transmit status */ + +/* Bit definition for Ethernet DMA Operation Mode Register */ +#define ETH_DMAOMR_DTCEFD ((uint32_t)0x04000000) /* Disable Dropping of TCP/IP checksum error frames */ +#define ETH_DMAOMR_RSF ((uint32_t)0x02000000) /* Receive store and forward */ +#define ETH_DMAOMR_DFRF ((uint32_t)0x01000000) /* Disable flushing of received frames */ +#define ETH_DMAOMR_TSF ((uint32_t)0x00200000) /* Transmit store and forward */ +#define ETH_DMAOMR_FTF ((uint32_t)0x00100000) /* Flush transmit FIFO */ +#define ETH_DMAOMR_TTC ((uint32_t)0x0001C000) /* Transmit threshold control */ + #define ETH_DMAOMR_TTC_64Bytes ((uint32_t)0x00000000) /* threshold level of the MTL Transmit FIFO is 64 Bytes */ + #define ETH_DMAOMR_TTC_128Bytes ((uint32_t)0x00004000) /* threshold level of the MTL Transmit FIFO is 128 Bytes */ + #define ETH_DMAOMR_TTC_192Bytes ((uint32_t)0x00008000) /* threshold level of the MTL Transmit FIFO is 192 Bytes */ + #define ETH_DMAOMR_TTC_256Bytes ((uint32_t)0x0000C000) /* threshold level of the MTL Transmit FIFO is 256 Bytes */ + #define ETH_DMAOMR_TTC_40Bytes ((uint32_t)0x00010000) /* threshold level of the MTL Transmit FIFO is 40 Bytes */ + #define ETH_DMAOMR_TTC_32Bytes ((uint32_t)0x00014000) /* threshold level of the MTL Transmit FIFO is 32 Bytes */ + #define ETH_DMAOMR_TTC_24Bytes ((uint32_t)0x00018000) /* threshold level of the MTL Transmit FIFO is 24 Bytes */ + #define ETH_DMAOMR_TTC_16Bytes ((uint32_t)0x0001C000) /* threshold level of the MTL Transmit FIFO is 16 Bytes */ +#define ETH_DMAOMR_ST ((uint32_t)0x00002000) /* Start/stop transmission command */ +#define ETH_DMAOMR_FEF ((uint32_t)0x00000080) /* Forward error frames */ +#define ETH_DMAOMR_FUGF ((uint32_t)0x00000040) /* Forward undersized good frames */ +#define ETH_DMAOMR_RTC ((uint32_t)0x00000018) /* receive threshold control */ + #define ETH_DMAOMR_RTC_64Bytes ((uint32_t)0x00000000) /* threshold level of the MTL Receive FIFO is 64 Bytes */ + #define ETH_DMAOMR_RTC_32Bytes ((uint32_t)0x00000008) /* threshold level of the MTL Receive FIFO is 32 Bytes */ + #define ETH_DMAOMR_RTC_96Bytes ((uint32_t)0x00000010) /* threshold level of the MTL Receive FIFO is 96 Bytes */ + #define ETH_DMAOMR_RTC_128Bytes ((uint32_t)0x00000018) /* threshold level of the MTL Receive FIFO is 128 Bytes */ +#define ETH_DMAOMR_OSF ((uint32_t)0x00000004) /* operate on second frame */ +#define ETH_DMAOMR_SR ((uint32_t)0x00000002) /* Start/stop receive */ + +/* Bit definition for Ethernet DMA Interrupt Enable Register */ +#define ETH_DMAIER_NISE ((uint32_t)0x00010000) /* Normal interrupt summary enable */ +#define ETH_DMAIER_AISE ((uint32_t)0x00008000) /* Abnormal interrupt summary enable */ +#define ETH_DMAIER_ERIE ((uint32_t)0x00004000) /* Early receive interrupt enable */ +#define ETH_DMAIER_FBEIE ((uint32_t)0x00002000) /* Fatal bus error interrupt enable */ +#define ETH_DMAIER_ETIE ((uint32_t)0x00000400) /* Early transmit interrupt enable */ +#define ETH_DMAIER_RWTIE ((uint32_t)0x00000200) /* Receive watchdog timeout interrupt enable */ +#define ETH_DMAIER_RPSIE ((uint32_t)0x00000100) /* Receive process stopped interrupt enable */ +#define ETH_DMAIER_RBUIE ((uint32_t)0x00000080) /* Receive buffer unavailable interrupt enable */ +#define ETH_DMAIER_RIE ((uint32_t)0x00000040) /* Receive interrupt enable */ +#define ETH_DMAIER_TUIE ((uint32_t)0x00000020) /* Transmit Underflow interrupt enable */ +#define ETH_DMAIER_ROIE ((uint32_t)0x00000010) /* Receive Overflow interrupt enable */ +#define ETH_DMAIER_TJTIE ((uint32_t)0x00000008) /* Transmit jabber timeout interrupt enable */ +#define ETH_DMAIER_TBUIE ((uint32_t)0x00000004) /* Transmit buffer unavailable interrupt enable */ +#define ETH_DMAIER_TPSIE ((uint32_t)0x00000002) /* Transmit process stopped interrupt enable */ +#define ETH_DMAIER_TIE ((uint32_t)0x00000001) /* Transmit interrupt enable */ + +/* Bit definition for Ethernet DMA Missed Frame and Buffer Overflow Counter Register */ +#define ETH_DMAMFBOCR_OFOC ((uint32_t)0x10000000) /* Overflow bit for FIFO overflow counter */ +#define ETH_DMAMFBOCR_MFA ((uint32_t)0x0FFE0000) /* Number of frames missed by the application */ +#define ETH_DMAMFBOCR_OMFC ((uint32_t)0x00010000) /* Overflow bit for missed frame counter */ +#define ETH_DMAMFBOCR_MFC ((uint32_t)0x0000FFFF) /* Number of frames missed by the controller */ + +/* Bit definition for Ethernet DMA Current Host Transmit Descriptor Register */ +#define ETH_DMACHTDR_HTDAP ((uint32_t)0xFFFFFFFF) /* Host transmit descriptor address pointer */ + +/* Bit definition for Ethernet DMA Current Host Receive Descriptor Register */ +#define ETH_DMACHRDR_HRDAP ((uint32_t)0xFFFFFFFF) /* Host receive descriptor address pointer */ + +/* Bit definition for Ethernet DMA Current Host Transmit Buffer Address Register */ +#define ETH_DMACHTBAR_HTBAP ((uint32_t)0xFFFFFFFF) /* Host transmit buffer address pointer */ + +/* Bit definition for Ethernet DMA Current Host Receive Buffer Address Register */ +#define ETH_DMACHRBAR_HRBAP ((uint32_t)0xFFFFFFFF) /* Host receive buffer address pointer */ +#endif /* STM32F10X_CL */ + +/** + * @} + */ + + /** + * @} + */ + +#ifdef USE_STDPERIPH_DRIVER + #include "stm32f10x_conf.h" +#endif + +/** @addtogroup Exported_macro + * @{ + */ + +#define SET_BIT(REG, BIT) ((REG) |= (BIT)) + +#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT)) + +#define READ_BIT(REG, BIT) ((REG) & (BIT)) + +#define CLEAR_REG(REG) ((REG) = (0x0)) + +#define WRITE_REG(REG, VAL) ((REG) = (VAL)) + +#define READ_REG(REG) ((REG)) + +#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK))) + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F10x_H */ + +/** + * @} + */ + + /** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Start/system_stm32f10x.c b/Start/system_stm32f10x.c new file mode 100644 index 0000000..71efc85 --- /dev/null +++ b/Start/system_stm32f10x.c @@ -0,0 +1,1094 @@ +/** + ****************************************************************************** + * @file system_stm32f10x.c + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Source File. + * + * 1. This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): Setups the system clock (System clock source, PLL Multiplier + * factors, AHB/APBx prescalers and Flash settings). + * This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32f10x_xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used + * by the user application to setup the SysTick + * timer or configure other parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * 2. After each device reset the HSI (8 MHz) is used as system clock source. + * Then SystemInit() function is called, in "startup_stm32f10x_xx.s" file, to + * configure the system clock before to branch to main program. + * + * 3. If the system clock source selected by user fails to startup, the SystemInit() + * function will do nothing and HSI still used as system clock source. User can + * add some code to deal with this issue inside the SetSysClock() function. + * + * 4. The default value of HSE crystal is set to 8 MHz (or 25 MHz, depedning on + * the product used), refer to "HSE_VALUE" define in "stm32f10x.h" file. + * When HSE is used as system clock source, directly or through PLL, and you + * are using different crystal you have to adapt the HSE value to your own + * configuration. + * + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

    © COPYRIGHT 2011 STMicroelectronics

    + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f10x_system + * @{ + */ + +/** @addtogroup STM32F10x_System_Private_Includes + * @{ + */ + +#include "stm32f10x.h" + +/** + * @} + */ + +/** @addtogroup STM32F10x_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F10x_System_Private_Defines + * @{ + */ + +/*!< Uncomment the line corresponding to the desired System clock (SYSCLK) + frequency (after reset the HSI is used as SYSCLK source) + + IMPORTANT NOTE: + ============== + 1. After each device reset the HSI is used as System clock source. + + 2. Please make sure that the selected System clock doesn't exceed your device's + maximum frequency. + + 3. If none of the define below is enabled, the HSI is used as System clock + source. + + 4. The System clock configuration functions provided within this file assume that: + - For Low, Medium and High density Value line devices an external 8MHz + crystal is used to drive the System clock. + - For Low, Medium and High density devices an external 8MHz crystal is + used to drive the System clock. + - For Connectivity line devices an external 25MHz crystal is used to drive + the System clock. + If you are using different crystal you have to adapt those functions accordingly. + */ + +#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) +/* #define SYSCLK_FREQ_HSE HSE_VALUE */ + #define SYSCLK_FREQ_24MHz 24000000 +#else +/* #define SYSCLK_FREQ_HSE HSE_VALUE */ +/* #define SYSCLK_FREQ_24MHz 24000000 */ +/* #define SYSCLK_FREQ_36MHz 36000000 */ +/* #define SYSCLK_FREQ_48MHz 48000000 */ +/* #define SYSCLK_FREQ_56MHz 56000000 */ +#define SYSCLK_FREQ_72MHz 72000000 +#endif + +/*!< Uncomment the following line if you need to use external SRAM mounted + on STM3210E-EVAL board (STM32 High density and XL-density devices) or on + STM32100E-EVAL board (STM32 High-density value line devices) as data memory */ +#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL) +/* #define DATA_IN_ExtSRAM */ +#endif + +/*!< Uncomment the following line if you need to relocate your vector Table in + Internal SRAM. */ +/* #define VECT_TAB_SRAM */ +#define VECT_TAB_OFFSET 0x0 /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ + + +/** + * @} + */ + +/** @addtogroup STM32F10x_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F10x_System_Private_Variables + * @{ + */ + +/******************************************************************************* +* Clock Definitions +*******************************************************************************/ +#ifdef SYSCLK_FREQ_HSE + uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /*!< System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_24MHz + uint32_t SystemCoreClock = SYSCLK_FREQ_24MHz; /*!< System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_36MHz + uint32_t SystemCoreClock = SYSCLK_FREQ_36MHz; /*!< System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_48MHz + uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz; /*!< System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_56MHz + uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz; /*!< System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_72MHz + uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz; /*!< System Clock Frequency (Core Clock) */ +#else /*!< HSI Selected as System Clock source */ + uint32_t SystemCoreClock = HSI_VALUE; /*!< System Clock Frequency (Core Clock) */ +#endif + +__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; +/** + * @} + */ + +/** @addtogroup STM32F10x_System_Private_FunctionPrototypes + * @{ + */ + +static void SetSysClock(void); + +#ifdef SYSCLK_FREQ_HSE + static void SetSysClockToHSE(void); +#elif defined SYSCLK_FREQ_24MHz + static void SetSysClockTo24(void); +#elif defined SYSCLK_FREQ_36MHz + static void SetSysClockTo36(void); +#elif defined SYSCLK_FREQ_48MHz + static void SetSysClockTo48(void); +#elif defined SYSCLK_FREQ_56MHz + static void SetSysClockTo56(void); +#elif defined SYSCLK_FREQ_72MHz + static void SetSysClockTo72(void); +#endif + +#ifdef DATA_IN_ExtSRAM + static void SystemInit_ExtMemCtl(void); +#endif /* DATA_IN_ExtSRAM */ + +/** + * @} + */ + +/** @addtogroup STM32F10x_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system + * Initialize the Embedded Flash Interface, the PLL and update the + * SystemCoreClock variable. + * @note This function should be used only after reset. + * @param None + * @retval None + */ +void SystemInit (void) +{ + /* Reset the RCC clock configuration to the default reset state(for debug purpose) */ + /* Set HSION bit */ + RCC->CR |= (uint32_t)0x00000001; + + /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */ +#ifndef STM32F10X_CL + RCC->CFGR &= (uint32_t)0xF8FF0000; +#else + RCC->CFGR &= (uint32_t)0xF0FF0000; +#endif /* STM32F10X_CL */ + + /* Reset HSEON, CSSON and PLLON bits */ + RCC->CR &= (uint32_t)0xFEF6FFFF; + + /* Reset HSEBYP bit */ + RCC->CR &= (uint32_t)0xFFFBFFFF; + + /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */ + RCC->CFGR &= (uint32_t)0xFF80FFFF; + +#ifdef STM32F10X_CL + /* Reset PLL2ON and PLL3ON bits */ + RCC->CR &= (uint32_t)0xEBFFFFFF; + + /* Disable all interrupts and clear pending bits */ + RCC->CIR = 0x00FF0000; + + /* Reset CFGR2 register */ + RCC->CFGR2 = 0x00000000; +#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) + /* Disable all interrupts and clear pending bits */ + RCC->CIR = 0x009F0000; + + /* Reset CFGR2 register */ + RCC->CFGR2 = 0x00000000; +#else + /* Disable all interrupts and clear pending bits */ + RCC->CIR = 0x009F0000; +#endif /* STM32F10X_CL */ + +#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL) + #ifdef DATA_IN_ExtSRAM + SystemInit_ExtMemCtl(); + #endif /* DATA_IN_ExtSRAM */ +#endif + + /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */ + /* Configure the Flash Latency cycles and enable prefetch buffer */ + SetSysClock(); + +#ifdef VECT_TAB_SRAM + SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */ +#else + SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */ +#endif +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) + * or HSI_VALUE(*) multiplied by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in stm32f1xx.h file (default value + * 8 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSE_VALUE is a constant defined in stm32f1xx.h file (default value + * 8 MHz or 25 MHz, depedning on the product used), user has to ensure + * that HSE_VALUE is same as the real frequency of the crystal used. + * Otherwise, this function may have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * @param None + * @retval None + */ +void SystemCoreClockUpdate (void) +{ + uint32_t tmp = 0, pllmull = 0, pllsource = 0; + +#ifdef STM32F10X_CL + uint32_t prediv1source = 0, prediv1factor = 0, prediv2factor = 0, pll2mull = 0; +#endif /* STM32F10X_CL */ + +#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) + uint32_t prediv1factor = 0; +#endif /* STM32F10X_LD_VL or STM32F10X_MD_VL or STM32F10X_HD_VL */ + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) + { + case 0x00: /* HSI used as system clock */ + SystemCoreClock = HSI_VALUE; + break; + case 0x04: /* HSE used as system clock */ + SystemCoreClock = HSE_VALUE; + break; + case 0x08: /* PLL used as system clock */ + + /* Get PLL clock source and multiplication factor ----------------------*/ + pllmull = RCC->CFGR & RCC_CFGR_PLLMULL; + pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; + +#ifndef STM32F10X_CL + pllmull = ( pllmull >> 18) + 2; + + if (pllsource == 0x00) + { + /* HSI oscillator clock divided by 2 selected as PLL clock entry */ + SystemCoreClock = (HSI_VALUE >> 1) * pllmull; + } + else + { + #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) + prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1; + /* HSE oscillator clock selected as PREDIV1 clock entry */ + SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; + #else + /* HSE selected as PLL clock entry */ + if ((RCC->CFGR & RCC_CFGR_PLLXTPRE) != (uint32_t)RESET) + {/* HSE oscillator clock divided by 2 */ + SystemCoreClock = (HSE_VALUE >> 1) * pllmull; + } + else + { + SystemCoreClock = HSE_VALUE * pllmull; + } + #endif + } +#else + pllmull = pllmull >> 18; + + if (pllmull != 0x0D) + { + pllmull += 2; + } + else + { /* PLL multiplication factor = PLL input clock * 6.5 */ + pllmull = 13 / 2; + } + + if (pllsource == 0x00) + { + /* HSI oscillator clock divided by 2 selected as PLL clock entry */ + SystemCoreClock = (HSI_VALUE >> 1) * pllmull; + } + else + {/* PREDIV1 selected as PLL clock entry */ + + /* Get PREDIV1 clock source and division factor */ + prediv1source = RCC->CFGR2 & RCC_CFGR2_PREDIV1SRC; + prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1; + + if (prediv1source == 0) + { + /* HSE oscillator clock selected as PREDIV1 clock entry */ + SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; + } + else + {/* PLL2 clock selected as PREDIV1 clock entry */ + + /* Get PREDIV2 division factor and PLL2 multiplication factor */ + prediv2factor = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> 4) + 1; + pll2mull = ((RCC->CFGR2 & RCC_CFGR2_PLL2MUL) >> 8 ) + 2; + SystemCoreClock = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull; + } + } +#endif /* STM32F10X_CL */ + break; + + default: + SystemCoreClock = HSI_VALUE; + break; + } + + /* Compute HCLK clock frequency ----------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; + /* HCLK clock frequency */ + SystemCoreClock >>= tmp; +} + +/** + * @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers. + * @param None + * @retval None + */ +static void SetSysClock(void) +{ +#ifdef SYSCLK_FREQ_HSE + SetSysClockToHSE(); +#elif defined SYSCLK_FREQ_24MHz + SetSysClockTo24(); +#elif defined SYSCLK_FREQ_36MHz + SetSysClockTo36(); +#elif defined SYSCLK_FREQ_48MHz + SetSysClockTo48(); +#elif defined SYSCLK_FREQ_56MHz + SetSysClockTo56(); +#elif defined SYSCLK_FREQ_72MHz + SetSysClockTo72(); +#endif + + /* If none of the define above is enabled, the HSI is used as System clock + source (default after reset) */ +} + +/** + * @brief Setup the external memory controller. Called in startup_stm32f10x.s + * before jump to __main + * @param None + * @retval None + */ +#ifdef DATA_IN_ExtSRAM +/** + * @brief Setup the external memory controller. + * Called in startup_stm32f10x_xx.s/.c before jump to main. + * This function configures the external SRAM mounted on STM3210E-EVAL + * board (STM32 High density devices). This SRAM will be used as program + * data memory (including heap and stack). + * @param None + * @retval None + */ +void SystemInit_ExtMemCtl(void) +{ +/*!< FSMC Bank1 NOR/SRAM3 is used for the STM3210E-EVAL, if another Bank is + required, then adjust the Register Addresses */ + + /* Enable FSMC clock */ + RCC->AHBENR = 0x00000114; + + /* Enable GPIOD, GPIOE, GPIOF and GPIOG clocks */ + RCC->APB2ENR = 0x000001E0; + +/* --------------- SRAM Data lines, NOE and NWE configuration ---------------*/ +/*---------------- SRAM Address lines configuration -------------------------*/ +/*---------------- NOE and NWE configuration --------------------------------*/ +/*---------------- NE3 configuration ----------------------------------------*/ +/*---------------- NBL0, NBL1 configuration ---------------------------------*/ + + GPIOD->CRL = 0x44BB44BB; + GPIOD->CRH = 0xBBBBBBBB; + + GPIOE->CRL = 0xB44444BB; + GPIOE->CRH = 0xBBBBBBBB; + + GPIOF->CRL = 0x44BBBBBB; + GPIOF->CRH = 0xBBBB4444; + + GPIOG->CRL = 0x44BBBBBB; + GPIOG->CRH = 0x44444B44; + +/*---------------- FSMC Configuration ---------------------------------------*/ +/*---------------- Enable FSMC Bank1_SRAM Bank ------------------------------*/ + + FSMC_Bank1->BTCR[4] = 0x00001011; + FSMC_Bank1->BTCR[5] = 0x00000200; +} +#endif /* DATA_IN_ExtSRAM */ + +#ifdef SYSCLK_FREQ_HSE +/** + * @brief Selects HSE as System clock source and configure HCLK, PCLK2 + * and PCLK1 prescalers. + * @note This function should be used only after reset. + * @param None + * @retval None + */ +static void SetSysClockToHSE(void) +{ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ + /* Enable HSE */ + RCC->CR |= ((uint32_t)RCC_CR_HSEON); + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CR & RCC_CR_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if ((RCC->CR & RCC_CR_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if (HSEStatus == (uint32_t)0x01) + { + +#if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL && !defined STM32F10X_HD_VL + /* Enable Prefetch Buffer */ + FLASH->ACR |= FLASH_ACR_PRFTBE; + + /* Flash 0 wait state */ + FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); + +#ifndef STM32F10X_CL + FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0; +#else + if (HSE_VALUE <= 24000000) + { + FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0; + } + else + { + FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1; + } +#endif /* STM32F10X_CL */ +#endif + + /* HCLK = SYSCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; + + /* PCLK2 = HCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; + + /* PCLK1 = HCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; + + /* Select HSE as system clock source */ + RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); + RCC->CFGR |= (uint32_t)RCC_CFGR_SW_HSE; + + /* Wait till HSE is used as system clock source */ + while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x04) + { + } + } + else + { /* If HSE fails to start-up, the application will have wrong clock + configuration. User can add here some code to deal with this error */ + } +} +#elif defined SYSCLK_FREQ_24MHz +/** + * @brief Sets System clock frequency to 24MHz and configure HCLK, PCLK2 + * and PCLK1 prescalers. + * @note This function should be used only after reset. + * @param None + * @retval None + */ +static void SetSysClockTo24(void) +{ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ + /* Enable HSE */ + RCC->CR |= ((uint32_t)RCC_CR_HSEON); + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CR & RCC_CR_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if ((RCC->CR & RCC_CR_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if (HSEStatus == (uint32_t)0x01) + { +#if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL && !defined STM32F10X_HD_VL + /* Enable Prefetch Buffer */ + FLASH->ACR |= FLASH_ACR_PRFTBE; + + /* Flash 0 wait state */ + FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); + FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0; +#endif + + /* HCLK = SYSCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; + + /* PCLK2 = HCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; + + /* PCLK1 = HCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; + +#ifdef STM32F10X_CL + /* Configure PLLs ------------------------------------------------------*/ + /* PLL configuration: PLLCLK = PREDIV1 * 6 = 24 MHz */ + RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL); + RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | + RCC_CFGR_PLLMULL6); + + /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ + /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 10 = 4 MHz */ + RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL | + RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC); + RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 | + RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV10); + + /* Enable PLL2 */ + RCC->CR |= RCC_CR_PLL2ON; + /* Wait till PLL2 is ready */ + while((RCC->CR & RCC_CR_PLL2RDY) == 0) + { + } +#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) + /* PLL configuration: = (HSE / 2) * 6 = 24 MHz */ + RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); + RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1_Div2 | RCC_CFGR_PLLMULL6); +#else + /* PLL configuration: = (HSE / 2) * 6 = 24 MHz */ + RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); + RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL6); +#endif /* STM32F10X_CL */ + + /* Enable PLL */ + RCC->CR |= RCC_CR_PLLON; + + /* Wait till PLL is ready */ + while((RCC->CR & RCC_CR_PLLRDY) == 0) + { + } + + /* Select PLL as system clock source */ + RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); + RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; + + /* Wait till PLL is used as system clock source */ + while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) + { + } + } + else + { /* If HSE fails to start-up, the application will have wrong clock + configuration. User can add here some code to deal with this error */ + } +} +#elif defined SYSCLK_FREQ_36MHz +/** + * @brief Sets System clock frequency to 36MHz and configure HCLK, PCLK2 + * and PCLK1 prescalers. + * @note This function should be used only after reset. + * @param None + * @retval None + */ +static void SetSysClockTo36(void) +{ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ + /* Enable HSE */ + RCC->CR |= ((uint32_t)RCC_CR_HSEON); + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CR & RCC_CR_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if ((RCC->CR & RCC_CR_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if (HSEStatus == (uint32_t)0x01) + { + /* Enable Prefetch Buffer */ + FLASH->ACR |= FLASH_ACR_PRFTBE; + + /* Flash 1 wait state */ + FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); + FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1; + + /* HCLK = SYSCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; + + /* PCLK2 = HCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; + + /* PCLK1 = HCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; + +#ifdef STM32F10X_CL + /* Configure PLLs ------------------------------------------------------*/ + + /* PLL configuration: PLLCLK = PREDIV1 * 9 = 36 MHz */ + RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL); + RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | + RCC_CFGR_PLLMULL9); + + /*!< PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ + /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 10 = 4 MHz */ + + RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL | + RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC); + RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 | + RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV10); + + /* Enable PLL2 */ + RCC->CR |= RCC_CR_PLL2ON; + /* Wait till PLL2 is ready */ + while((RCC->CR & RCC_CR_PLL2RDY) == 0) + { + } + +#else + /* PLL configuration: PLLCLK = (HSE / 2) * 9 = 36 MHz */ + RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); + RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL9); +#endif /* STM32F10X_CL */ + + /* Enable PLL */ + RCC->CR |= RCC_CR_PLLON; + + /* Wait till PLL is ready */ + while((RCC->CR & RCC_CR_PLLRDY) == 0) + { + } + + /* Select PLL as system clock source */ + RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); + RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; + + /* Wait till PLL is used as system clock source */ + while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) + { + } + } + else + { /* If HSE fails to start-up, the application will have wrong clock + configuration. User can add here some code to deal with this error */ + } +} +#elif defined SYSCLK_FREQ_48MHz +/** + * @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 + * and PCLK1 prescalers. + * @note This function should be used only after reset. + * @param None + * @retval None + */ +static void SetSysClockTo48(void) +{ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ + /* Enable HSE */ + RCC->CR |= ((uint32_t)RCC_CR_HSEON); + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CR & RCC_CR_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if ((RCC->CR & RCC_CR_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if (HSEStatus == (uint32_t)0x01) + { + /* Enable Prefetch Buffer */ + FLASH->ACR |= FLASH_ACR_PRFTBE; + + /* Flash 1 wait state */ + FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); + FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1; + + /* HCLK = SYSCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; + + /* PCLK2 = HCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; + + /* PCLK1 = HCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; + +#ifdef STM32F10X_CL + /* Configure PLLs ------------------------------------------------------*/ + /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ + /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */ + + RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL | + RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC); + RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 | + RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5); + + /* Enable PLL2 */ + RCC->CR |= RCC_CR_PLL2ON; + /* Wait till PLL2 is ready */ + while((RCC->CR & RCC_CR_PLL2RDY) == 0) + { + } + + + /* PLL configuration: PLLCLK = PREDIV1 * 6 = 48 MHz */ + RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL); + RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | + RCC_CFGR_PLLMULL6); +#else + /* PLL configuration: PLLCLK = HSE * 6 = 48 MHz */ + RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); + RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6); +#endif /* STM32F10X_CL */ + + /* Enable PLL */ + RCC->CR |= RCC_CR_PLLON; + + /* Wait till PLL is ready */ + while((RCC->CR & RCC_CR_PLLRDY) == 0) + { + } + + /* Select PLL as system clock source */ + RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); + RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; + + /* Wait till PLL is used as system clock source */ + while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) + { + } + } + else + { /* If HSE fails to start-up, the application will have wrong clock + configuration. User can add here some code to deal with this error */ + } +} + +#elif defined SYSCLK_FREQ_56MHz +/** + * @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 + * and PCLK1 prescalers. + * @note This function should be used only after reset. + * @param None + * @retval None + */ +static void SetSysClockTo56(void) +{ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ + /* Enable HSE */ + RCC->CR |= ((uint32_t)RCC_CR_HSEON); + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CR & RCC_CR_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if ((RCC->CR & RCC_CR_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if (HSEStatus == (uint32_t)0x01) + { + /* Enable Prefetch Buffer */ + FLASH->ACR |= FLASH_ACR_PRFTBE; + + /* Flash 2 wait state */ + FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); + FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2; + + /* HCLK = SYSCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; + + /* PCLK2 = HCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; + + /* PCLK1 = HCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; + +#ifdef STM32F10X_CL + /* Configure PLLs ------------------------------------------------------*/ + /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ + /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */ + + RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL | + RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC); + RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 | + RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5); + + /* Enable PLL2 */ + RCC->CR |= RCC_CR_PLL2ON; + /* Wait till PLL2 is ready */ + while((RCC->CR & RCC_CR_PLL2RDY) == 0) + { + } + + + /* PLL configuration: PLLCLK = PREDIV1 * 7 = 56 MHz */ + RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL); + RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | + RCC_CFGR_PLLMULL7); +#else + /* PLL configuration: PLLCLK = HSE * 7 = 56 MHz */ + RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); + RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL7); + +#endif /* STM32F10X_CL */ + + /* Enable PLL */ + RCC->CR |= RCC_CR_PLLON; + + /* Wait till PLL is ready */ + while((RCC->CR & RCC_CR_PLLRDY) == 0) + { + } + + /* Select PLL as system clock source */ + RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); + RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; + + /* Wait till PLL is used as system clock source */ + while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) + { + } + } + else + { /* If HSE fails to start-up, the application will have wrong clock + configuration. User can add here some code to deal with this error */ + } +} + +#elif defined SYSCLK_FREQ_72MHz +/** + * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 + * and PCLK1 prescalers. + * @note This function should be used only after reset. + * @param None + * @retval None + */ +static void SetSysClockTo72(void) +{ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ + /* Enable HSE */ + RCC->CR |= ((uint32_t)RCC_CR_HSEON); + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CR & RCC_CR_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if ((RCC->CR & RCC_CR_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if (HSEStatus == (uint32_t)0x01) + { + /* Enable Prefetch Buffer */ + FLASH->ACR |= FLASH_ACR_PRFTBE; + + /* Flash 2 wait state */ + FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); + FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2; + + + /* HCLK = SYSCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; + + /* PCLK2 = HCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; + + /* PCLK1 = HCLK */ + RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; + +#ifdef STM32F10X_CL + /* Configure PLLs ------------------------------------------------------*/ + /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ + /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */ + + RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL | + RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC); + RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 | + RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5); + + /* Enable PLL2 */ + RCC->CR |= RCC_CR_PLL2ON; + /* Wait till PLL2 is ready */ + while((RCC->CR & RCC_CR_PLL2RDY) == 0) + { + } + + + /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ + RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL); + RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | + RCC_CFGR_PLLMULL9); +#else + /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */ + RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | + RCC_CFGR_PLLMULL)); + RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9); +#endif /* STM32F10X_CL */ + + /* Enable PLL */ + RCC->CR |= RCC_CR_PLLON; + + /* Wait till PLL is ready */ + while((RCC->CR & RCC_CR_PLLRDY) == 0) + { + } + + /* Select PLL as system clock source */ + RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); + RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; + + /* Wait till PLL is used as system clock source */ + while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) + { + } + } + else + { /* If HSE fails to start-up, the application will have wrong clock + configuration. User can add here some code to deal with this error */ + } +} +#endif + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/Start/system_stm32f10x.h b/Start/system_stm32f10x.h new file mode 100644 index 0000000..54bc1ab --- /dev/null +++ b/Start/system_stm32f10x.h @@ -0,0 +1,98 @@ +/** + ****************************************************************************** + * @file system_stm32f10x.h + * @author MCD Application Team + * @version V3.5.0 + * @date 11-March-2011 + * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Header File. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

    © COPYRIGHT 2011 STMicroelectronics

    + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f10x_system + * @{ + */ + +/** + * @brief Define to prevent recursive inclusion + */ +#ifndef __SYSTEM_STM32F10X_H +#define __SYSTEM_STM32F10X_H + +#ifdef __cplusplus + extern "C" { +#endif + +/** @addtogroup STM32F10x_System_Includes + * @{ + */ + +/** + * @} + */ + + +/** @addtogroup STM32F10x_System_Exported_types + * @{ + */ + +extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ + +/** + * @} + */ + +/** @addtogroup STM32F10x_System_Exported_Constants + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F10x_System_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F10x_System_Exported_Functions + * @{ + */ + +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*__SYSTEM_STM32F10X_H */ + +/** + * @} + */ + +/** + * @} + */ +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/System/Debug.c b/System/Debug.c new file mode 100644 index 0000000..62f1c2c --- /dev/null +++ b/System/Debug.c @@ -0,0 +1,91 @@ +#include "Debug.h" +#include +#include + +#if DEBUG_ENABLE + +// 调试缓冲区 +static char debug_buffer[256]; + +/** + * @brief 初始化调试串口(USART2, PA2=TX, PA3=RX) + */ +void Debug_Init(void) +{ + GPIO_InitTypeDef GPIO_InitStructure; + USART_InitTypeDef USART_InitStructure; + + // 使能时钟 + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); + RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); + + // 配置PA2为推挽输出(TX) + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + // 配置PA3为浮空输入(RX) + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + // 配置USART2 + USART_InitStructure.USART_BaudRate = 115200; + USART_InitStructure.USART_WordLength = USART_WordLength_8b; + USART_InitStructure.USART_StopBits = USART_StopBits_1; + USART_InitStructure.USART_Parity = USART_Parity_No; + USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + USART_InitStructure.USART_Mode = USART_Mode_Tx; // 只需要发送 + USART_Init(USART2, &USART_InitStructure); + + // 使能USART2 + USART_Cmd(USART2, ENABLE); + + // 发送启动信息 + Debug_Printf("\r\n========================================\r\n"); + Debug_Printf(" STM32 Face Recognition System\r\n"); + Debug_Printf(" Debug Console Started\r\n"); + Debug_Printf("========================================\r\n"); +} + +/** + * @brief 通过调试串口发送一个字节 + */ +static void Debug_SendByte(uint8_t byte) +{ + while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); + USART_SendData(USART2, byte); +} + +/** + * @brief 通过调试串口发送字符串 + */ +static void Debug_SendString(const char* str) +{ + while (*str) + { + Debug_SendByte(*str++); + } +} + +/** + * @brief 格式化调试信息输出(类似printf) + */ +void Debug_Printf(const char* format, ...) +{ + va_list args; + va_start(args, format); + vsnprintf(debug_buffer, sizeof(debug_buffer), format, args); + va_end(args); + + Debug_SendString(debug_buffer); +} + +#else + +// 调试关闭时,提供空实现 +void Debug_Init(void) {} +void Debug_Printf(const char* format, ...) {} + +#endif diff --git a/System/Debug.h b/System/Debug.h new file mode 100644 index 0000000..28df13c --- /dev/null +++ b/System/Debug.h @@ -0,0 +1,29 @@ +#ifndef __DEBUG_H +#define __DEBUG_H + +#include "stm32f10x.h" +#include + +// 调试功能开关(1=开启调试,0=关闭调试) +#define DEBUG_ENABLE 1 // 暂时关闭,添加Debug.c后改回1 + +// 调试串口初始化(使用USART2,PA2/PA3) +void Debug_Init(void); + +// 调试信息输出函数 +void Debug_Printf(const char* format, ...); + +// 快捷宏定义 +#if DEBUG_ENABLE + #define DEBUG_PRINT(...) Debug_Printf(__VA_ARGS__) + #define DEBUG_INFO(msg) Debug_Printf("[INFO] %s\r\n", msg) + #define DEBUG_ERROR(msg) Debug_Printf("[ERROR] %s\r\n", msg) + #define DEBUG_OK(msg) Debug_Printf("[OK] %s\r\n", msg) +#else + #define DEBUG_PRINT(...) + #define DEBUG_INFO(msg) + #define DEBUG_ERROR(msg) + #define DEBUG_OK(msg) +#endif + +#endif diff --git a/System/Delay.c b/System/Delay.c new file mode 100644 index 0000000..1086112 --- /dev/null +++ b/System/Delay.c @@ -0,0 +1,60 @@ +// Delay.c (修改后) +#include "stm32f10x.h" + +// 1. 添加一个全局变量,用于记录毫秒数 +// 注意:不使用static,以便中断函数可以访问 +volatile uint32_t g_time_ms = 0; + +/** + * @brief 初始化SysTick定时器,配置为1ms中断一次 + */ +void Delay_Init(void) +{ + // 配置SysTick为1ms中断一次。SystemCoreClock通常是72MHz。 + if (SysTick_Config(SystemCoreClock / 1000)) + { + // 如果配置失败,进入死循环 + while (1); + } +} + +/** + * @brief 获取自启动以来的毫秒数 + * @retval 当前的毫秒时间戳 + */ +uint32_t Get_Time_ms(void) +{ + return g_time_ms; +} + + +// --- 以下是你原本就有的阻塞式延时函数,保持不变 --- + +void Delay_us(uint32_t xus) +{ + SysTick->LOAD = 72 * xus; + SysTick->VAL = 0x00; + SysTick->CTRL = 0x00000005; + while(!(SysTick->CTRL & 0x00010000)); + SysTick->CTRL = 0x00000004; +} + +void Delay_ms(uint32_t xms) +{ + // 使用SysTick计时器实现精确延时 + uint32_t start_time = g_time_ms; + while((g_time_ms - start_time) < xms) { + // 等待 + } +} + +void Delay_s(uint32_t xs) +{ + while(xs--) + { + Delay_ms(1000); + } +} + +// 在这个文件的末尾,或者在 stm32f10x_it.c 中,你需要 SysTick_Handler +// 为了集中管理,我们把它放在 stm32f10x_it.c diff --git a/System/Delay.h b/System/Delay.h new file mode 100644 index 0000000..0d635ab --- /dev/null +++ b/System/Delay.h @@ -0,0 +1,16 @@ +// Delay.h (修改后) +#ifndef __DELAY_H +#define __DELAY_H + +#include "stm32f10x.h" // 确保包含了这个 + +// 添加下面两个函数的声明 +void Delay_Init(void); +uint32_t Get_Time_ms(void); + +// 保留你原有的函数声明 +void Delay_us(uint32_t us); +void Delay_ms(uint32_t ms); +void Delay_s(uint32_t s); + +#endif diff --git a/User/main.c b/User/main.c new file mode 100644 index 0000000..9f96035 --- /dev/null +++ b/User/main.c @@ -0,0 +1,925 @@ +// ====================================================================== +// main.c (人脸识别考勤系统 - AES加密版) +// ====================================================================== +#include "stm32f10x.h" +#include "Delay.h" +#include "OLED.h" +#include "Serial.h" +#include "K210_USART.h" +#include "Buzzer_LED.h" +#include "esp8266.h" +#include "Attendance.h" +#include "Debug.h" +#include "Crypto.h" // ← 新增:加密模块 +#include "DS1302.h" // ← 新增:DS1302 RTC时钟模块 +#include "LightSensor.h" // ← 新增:光敏电阻和补光灯模块 +#include +#include + +/* --- 用户配置区域 --- */ +// 导出配置供ESP8266使用(直接定义字符串常量) +const char* WIFI_SSID = "yzfh"; +const char* WIFI_PASSWORD = "yzfhroot"; +const char* HTTP_SERVER_IP = "27.106.113.205"; // 修改为实际服务器IP +const char* HTTP_SERVER_PORT = "8082"; // HTTP端口(8082) +const char* HTTP_API_TOKEN = "change-me-token"; // 必须与服务端 ATTENDANCE_API_TOKEN 一致 + +/* --- 班级配置 --- */ +// 每个设备对应一个班级,修改此处的班级代码 +#define CLASS_ID "1" // 班级编号(如 "1", "2", "3" 等) +const char* DEVICE_CLASS_ID = CLASS_ID; // 导出给其他模块使用 + +/* --- 全局变量定义 --- */ +volatile char g_k210_rx_buffer[K210_RX_BUFFER_SIZE]; +volatile uint16_t g_k210_rx_counter = 0; +volatile uint8_t g_k210_rx_flag = 0; + +uint8_t g_server_connected = 0; +uint8_t g_wifi_connected = 0; // WiFi连接状态标志 +uint8_t g_esp8266_ready = 0; // ESP8266初始化状态 + +// 时间相关变量(使用DS1302 RTC) +ESP8266_DateTime g_current_time = {1970, 1, 1, 1, 0, 0}; // 默认时间(会被NTP覆盖) +uint32_t last_time_sync = 0; +uint32_t last_rtc_read = 0; // 上次从DS1302读取时间的时刻 +uint8_t g_use_ds1302 = 0; // DS1302可用标志:0=不可用,1=可用 +#define TIME_SYNC_INTERVAL_MS 3600000 // NTP同步间隔:1小时 +#define RTC_READ_INTERVAL_MS 1000 // DS1302读取间隔:1秒 + +uint32_t last_heartbeat_time = 0; +uint32_t last_reconnect_attempt = 0; +uint32_t last_wifi_reconnect_attempt = 0; // WiFi重连尝试时间 +uint32_t last_sync_attempt = 0; +uint32_t last_timeslot_download = 0; // 上次下载时间段配置的时刻 +uint32_t g_stm32_sync_version = 0; // STM32端已应用的服务端同步版本 +#define HEARTBEAT_INTERVAL_MS 10000 +#define RECONNECT_INTERVAL_MS 5000 +#define WIFI_RECONNECT_INTERVAL_MS 30000 // WiFi重连间隔:30秒 +#define SYNC_INTERVAL_MS 5000 +#define TIMESLOT_DOWNLOAD_INTERVAL_MS 30000 // 时间段配置下载间隔:30秒 +#define MAX_RETRY_COUNT 5 +#define SYNC_BATCH_THRESHOLD 3 + +typedef enum { + UI_STATE_IDLE, + UI_STATE_SHOW_RESULT, +} UIState; + +UIState ui_state = UI_STATE_IDLE; +uint32_t ui_state_start_time = 0; +#define UI_RESULT_DISPLAY_TIME 2000 + +typedef enum { + BEEP_IDLE, + BEEP_SUCCESS, + BEEP_DUPLICATE +} BeepState; + +BeepState beep_state = BEEP_IDLE; +uint32_t beep_start_time = 0; +uint8_t beep_count = 0; + +char last_student_id[20] = ""; +uint32_t last_process_time = 0; +#define PROCESS_INTERVAL_MS 2000 + +/* --- 辅助函数 --- */ +void StartBeepSuccess(void) +{ + BUZZER_OFF(); + LED_SUCCESS_OFF(); + beep_state = BEEP_SUCCESS; + beep_start_time = Get_Time_ms(); + beep_count = 0; + BUZZER_ON(); + LED_SUCCESS_ON(); +} + +void StartBeepDuplicate(void) +{ + BUZZER_OFF(); + LED_SUCCESS_OFF(); + beep_state = BEEP_DUPLICATE; + beep_start_time = Get_Time_ms(); + beep_count = 0; + BUZZER_ON(); + LED_SUCCESS_ON(); +} + +void ProcessBeep(void) +{ + if (beep_state == BEEP_IDLE) { + BUZZER_OFF(); + LED_SUCCESS_OFF(); + return; + } + + uint32_t current_time = Get_Time_ms(); + uint32_t elapsed = current_time - beep_start_time; + + if (beep_state == BEEP_SUCCESS) { + if (elapsed >= 80) { + BUZZER_OFF(); + LED_SUCCESS_OFF(); + beep_state = BEEP_IDLE; + } + } + else if (beep_state == BEEP_DUPLICATE) { + if (beep_count == 0) { + if (elapsed >= 80) { + BUZZER_OFF(); + LED_SUCCESS_OFF(); + beep_count = 1; + } + } else if (beep_count == 1) { + if (elapsed >= 160) { + BUZZER_ON(); + LED_SUCCESS_ON(); + beep_count = 2; + } + } else if (beep_count == 2) { + if (elapsed >= 240) { + BUZZER_OFF(); + LED_SUCCESS_OFF(); + beep_state = BEEP_IDLE; + } + } + } +} + +void UpdateIdleScreen(void) +{ + OLED_Clear(); + OLED_ShowString(1, 1, "System Ready"); + OLED_ShowString(2, 1, "Encrypted Mode"); // ← 显示加密模式 + OLED_ShowString(3, 1, "Total:"); + OLED_ShowNum(3, 7, Attendance_GetTotalCount(), 3); + + uint16_t pending = Attendance_GetPendingCount(); + if (pending > 0) { + OLED_ShowString(4, 1, "Pending:"); + OLED_ShowNum(4, 9, pending, 2); + } +} + +/** + * @brief 发送加密的考勤记录到服务器(新版本) + */ +uint8_t SendEncryptedAttendance(AttendanceRecord* record) +{ + char json_data[256]; + char encrypted_data[512]; + + // 1. 构造JSON数据(包含班级编号) + sprintf(json_data, + "{\"student_id\":\"%s\",\"name\":\"%s\",\"confidence\":%.2f,\"status\":\"success\",\"class_id\":\"%s\"}", + record->student_id, + record->student_name, + record->confidence, + DEVICE_CLASS_ID); + + DEBUG_PRINT("[CRYPTO] Original JSON: %s\r\n", json_data); + + // 2. 加密JSON数据 + uint32_t encrypted_len = Crypto_EncryptJSON(json_data, encrypted_data); + + if (encrypted_len == 0) { + DEBUG_ERROR("[CRYPTO] Encryption failed!"); + return 0; + } + + DEBUG_PRINT("[CRYPTO] Encrypted length: %u\r\n", encrypted_len); + DEBUG_PRINT("[CRYPTO] Encrypted data: %s\r\n", encrypted_data); + + // 3. 发送加密数据 + if (!g_server_connected) { + DEBUG_ERROR("[CRYPTO] Server not connected"); + return 0; + } + + if (ESP8266_SendEncryptedData(encrypted_data) == ESP8266_SUCCESS) { + DEBUG_OK("[CRYPTO] Encrypted data sent successfully"); + return 1; + } else { + DEBUG_ERROR("[CRYPTO] Send failed"); + return 0; + } +} + +void SyncPendingRecords(void) +{ + uint32_t current_time = Get_Time_ms(); + + uint16_t pending_count = Attendance_GetPendingCount(); + if (pending_count == 0) return; + + if (!g_server_connected) return; + + uint8_t should_sync = 0; + + if (current_time - last_sync_attempt >= SYNC_INTERVAL_MS) { + should_sync = 1; + DEBUG_PRINT("[Sync] Timed sync: %d records pending\r\n", pending_count); + } + + if (pending_count >= SYNC_BATCH_THRESHOLD) { + should_sync = 1; + DEBUG_PRINT("[Sync] Batch sync: %d records pending\r\n", pending_count); + } + + if (!should_sync) return; + + last_sync_attempt = current_time; + + DEBUG_INFO("[Sync] Starting batch sync (encrypted mode)..."); + uint16_t synced_count = 0; + uint16_t failed_count = 0; + + for (uint16_t i = 0; i < pending_count && i < 10; i++) { + uint16_t record_index; + AttendanceRecord* record = Attendance_GetNextPendingRecord(&record_index); + + if (record == NULL) break; + + if (record->retry_count >= MAX_RETRY_COUNT) { + DEBUG_PRINT("[Sync] Record %d exceeded max retries\r\n", record_index); + Attendance_MarkSyncStatus(record_index, SYNC_FAILED); + failed_count++; + continue; + } + + Attendance_MarkSyncStatus(record_index, SYNC_SYNCING); + + DEBUG_PRINT("[Sync] Syncing %d/%d: %s [retry=%d]\r\n", + i + 1, pending_count, + record->student_id, + record->retry_count); + + // 使用加密发送 + if (SendEncryptedAttendance(record) == 1) { + Attendance_MarkSyncStatus(record_index, SYNC_SYNCED); + synced_count++; + } else { + Attendance_IncrementRetry(record_index); + Attendance_MarkSyncStatus(record_index, SYNC_FAILED); + failed_count++; + DEBUG_ERROR("[Sync] Send failed, stopping batch sync"); + break; + } + + Delay_ms(100); + } + + DEBUG_PRINT("[Sync] Batch complete: %d synced, %d failed\r\n", + synced_count, failed_count); +} + +uint8_t SyncNetworkTime(void) +{ + DEBUG_INFO("Syncing time from network..."); + + if (ESP8266_GetNetworkTime(&g_current_time) == ESP8266_SUCCESS) { + last_time_sync = Get_Time_ms(); + + DEBUG_PRINT("Time synced: %04d-%02d-%02d %02d:%02d:%02d\r\n", + g_current_time.year, g_current_time.month, g_current_time.day, + g_current_time.hour, g_current_time.minute, g_current_time.second); + + // 如果DS1302可用,将网络时间写入DS1302 + if (g_use_ds1302) { + DS1302_Time rtc_time; + rtc_time.year = g_current_time.year; + rtc_time.month = g_current_time.month; + rtc_time.day = g_current_time.day; + rtc_time.hour = g_current_time.hour; + rtc_time.minute = g_current_time.minute; + rtc_time.second = g_current_time.second; + rtc_time.week = 1; + + DS1302_SetTime(&rtc_time); + DEBUG_OK("Network time synchronized to DS1302 RTC"); + + // 延时后验证写入 + Delay_ms(100); + + // 读回验证 + DS1302_Time verify_time; + DS1302_GetTime(&verify_time); + DEBUG_PRINT("[DS1302] Verify: %04d-%02d-%02d %02d:%02d:%02d\r\n", + verify_time.year, verify_time.month, verify_time.day, + verify_time.hour, verify_time.minute, verify_time.second); + + // 检查验证结果(允许1-2秒误差) + if (verify_time.year == g_current_time.year && + verify_time.month == g_current_time.month && + verify_time.day == g_current_time.day && + verify_time.hour == g_current_time.hour) { + DEBUG_OK("[DS1302] Time verified successfully!"); + } else { + DEBUG_ERROR("[DS1302] Time verification failed! Disabling DS1302."); + DEBUG_PRINT("[DS1302] Expected: %04d-%02d-%02d %02d:%02d, Got: %04d-%02d-%02d %02d:%02d\r\n", + g_current_time.year, g_current_time.month, g_current_time.day, + g_current_time.hour, g_current_time.minute, + verify_time.year, verify_time.month, verify_time.day, + verify_time.hour, verify_time.minute); + g_use_ds1302 = 0; // 禁用DS1302 + DEBUG_INFO("[System] Switched to NTP-only mode"); + } + } else { + DEBUG_INFO("[System] Using NTP time (DS1302 disabled)"); + } + + Attendance_SetCurrentTime(g_current_time.hour, g_current_time.minute); + return 1; + } + + DEBUG_ERROR("Time sync failed"); + return 0; +} + +static uint32_t ParseSyncVersion(const char* json) +{ + const char* p; + uint32_t version = 0; + + if (json == NULL) return 0; + + p = strstr(json, "\"version\":"); + if (p == NULL) return 0; + + p += 10; + while (*p >= '0' && *p <= '9') { + version = version * 10 + (uint32_t)(*p - '0'); + p++; + } + + return version; +} + +uint8_t DownloadTimeSlots(void) +{ + char response_buffer[768]; + char path[96]; + uint32_t server_version; + + DEBUG_INFO("Downloading STM32 sync state from server..."); + + sprintf(path, "/api/v1/sync/state?client=stm32&last_version=%lu", (unsigned long)g_stm32_sync_version); + + // 按版本号拉取STM32需要的配置 + if (ESP8266_HttpGet(path, response_buffer, sizeof(response_buffer)) == ESP8266_SUCCESS) { + server_version = ParseSyncVersion(response_buffer); + + if (strstr(response_buffer, "\"changed\":false") != NULL) { + if (server_version > 0) { + g_stm32_sync_version = server_version; + } + last_timeslot_download = Get_Time_ms(); + DEBUG_INFO("STM32 sync state unchanged"); + return 1; + } + + DEBUG_OK("STM32 sync state downloaded successfully"); + + // 解析JSON并更新时间段配置 + uint8_t slot_count = Attendance_ParseTimeSlotsJSON(response_buffer); + + if (slot_count > 0) { + DEBUG_PRINT("Time slot configuration updated: %d slots\r\n", slot_count); + if (server_version > 0) { + g_stm32_sync_version = server_version; + DEBUG_PRINT("[Sync] STM32 version updated: %lu\r\n", (unsigned long)g_stm32_sync_version); + } + + // 更新下载时间戳 + last_timeslot_download = Get_Time_ms(); + + return 1; + } else { + DEBUG_ERROR("Failed to parse time slot JSON"); + return 0; + } + } + + DEBUG_ERROR("Failed to download time slots, using current configuration"); + return 0; +} + +void UpdateTimeSlotConfig(void) +{ + uint32_t current_time = Get_Time_ms(); + + // 如果服务器未连接,不执行下载 + if (!g_server_connected) { + return; + } + + // 检查是否到了更新间隔(每5分钟) + if (current_time - last_timeslot_download >= TIMESLOT_DOWNLOAD_INTERVAL_MS) { + DEBUG_INFO("Auto-updating time slot configuration..."); + + if (DownloadTimeSlots()) { + DEBUG_OK("Time slot configuration updated from server"); + + // 短暂显示更新提示 + OLED_ShowString(4, 1, "Config Synced! "); + } else { + DEBUG_ERROR("Failed to update time slot configuration"); + } + + // 无论成功失败都更新时间戳,避免频繁重试 + last_timeslot_download = current_time; + } +} + +void UpdateCurrentTime(void) +{ + uint32_t current_ms = Get_Time_ms(); + static uint8_t debug_counter = 0; // 调试计数器,每10秒打印一次 + + // 如果DS1302可用,每秒从DS1302读取时间 + if (g_use_ds1302 && current_ms - last_rtc_read >= RTC_READ_INTERVAL_MS) { + last_rtc_read = current_ms; + + DS1302_Time rtc_time; + DS1302_GetTime(&rtc_time); + + // 更新全局时间变量 + g_current_time.year = rtc_time.year; + g_current_time.month = rtc_time.month; + g_current_time.day = rtc_time.day; + g_current_time.hour = rtc_time.hour; + g_current_time.minute = rtc_time.minute; + g_current_time.second = rtc_time.second; + + // 更新考勤模块的当前时间 + Attendance_SetCurrentTime(rtc_time.hour, rtc_time.minute); + + // 每10秒打印一次当前时间(调试用) + debug_counter++; + if (debug_counter >= 10) { + debug_counter = 0; + DEBUG_PRINT("[Time] DS1302: %04d-%02d-%02d %02d:%02d:%02d\r\n", + rtc_time.year, rtc_time.month, rtc_time.day, + rtc_time.hour, rtc_time.minute, rtc_time.second); + } + } + // 如果DS1302不可用,直接使用NTP时间(每秒更新考勤时间) + else if (!g_use_ds1302 && current_ms - last_rtc_read >= RTC_READ_INTERVAL_MS) { + last_rtc_read = current_ms; + + // 直接使用全局NTP时间 + Attendance_SetCurrentTime(g_current_time.hour, g_current_time.minute); + + // 每10秒打印一次当前时间(调试用) + debug_counter++; + if (debug_counter >= 10) { + debug_counter = 0; + DEBUG_PRINT("[Time] NTP: %04d-%02d-%02d %02d:%02d\r\n", + g_current_time.year, g_current_time.month, g_current_time.day, + g_current_time.hour, g_current_time.minute); + } + } + + // 定期从网络同步时间(每小时一次,WiFi在线即可) + if (current_ms - last_time_sync > TIME_SYNC_INTERVAL_MS) { + if (g_wifi_connected) { + SyncNetworkTime(); + } + } +} + +uint8_t TryReconnectWiFi(void) +{ + uint32_t current_time = Get_Time_ms(); + + // 控制重连频率:30秒尝试一次 + if (current_time - last_wifi_reconnect_attempt < WIFI_RECONNECT_INTERVAL_MS) { + return 0; + } + + last_wifi_reconnect_attempt = current_time; + + DEBUG_INFO("Attempting to reconnect WiFi..."); + + // 尝试连接WiFi + if (ESP8266_ConnectWiFi(WIFI_SSID, WIFI_PASSWORD) == ESP8266_SUCCESS) { + DEBUG_OK("WiFi reconnected!"); + g_wifi_connected = 1; + + // WiFi已连通时先做NTP对时(不依赖HTTP服务器连接) + SyncNetworkTime(); + + // WiFi连接成功后,立即尝试连接服务器 + DEBUG_INFO("Connecting to HTTP server..."); + if (ESP8266_ConnectHTTPServer(HTTP_SERVER_IP, HTTP_SERVER_PORT) == ESP8266_SUCCESS) { + DEBUG_OK("HTTP server connected!"); + g_server_connected = 1; + last_heartbeat_time = current_time; + + // 连接成功提示音 + BUZZER_ON(); + Delay_ms(100); + BUZZER_OFF(); + + // 同步时间 + SyncNetworkTime(); + + // 下载时间段配置 + DownloadTimeSlots(); + + return 1; + } else { + DEBUG_ERROR("HTTP server connection failed"); + g_server_connected = 0; + } + + return 1; // WiFi已连接,即使服务器未连接 + } + + DEBUG_ERROR("WiFi reconnect failed, will retry in 30s..."); + return 0; +} + +uint8_t TryReconnectServer(void) +{ + uint32_t current_time = Get_Time_ms(); + + if (current_time - last_reconnect_attempt < RECONNECT_INTERVAL_MS) { + return 0; + } + + last_reconnect_attempt = current_time; + + DEBUG_INFO("Attempting to reconnect to HTTP server..."); + + if (ESP8266_ConnectHTTPServer(HTTP_SERVER_IP, HTTP_SERVER_PORT) == ESP8266_SUCCESS) { + DEBUG_OK("Reconnected to HTTP server!"); + g_server_connected = 1; + last_heartbeat_time = current_time; + + BUZZER_ON(); + Delay_ms(50); + BUZZER_OFF(); + + return 1; + } + + DEBUG_ERROR("Reconnect failed, will retry..."); + return 0; +} + +void CheckServerConnection(void) +{ + uint32_t current_time = Get_Time_ms(); + + // 如果WiFi未连接,尝试重连WiFi + if (!g_wifi_connected) { + TryReconnectWiFi(); + return; // WiFi未连接时,不检查服务器 + } + + // WiFi已连接,检查服务器连接状态 + if (current_time - last_heartbeat_time < HEARTBEAT_INTERVAL_MS) { + return; + } + + last_heartbeat_time = current_time; + + if (g_server_connected) { + // 检查服务器连接是否仍然有效 + if (ESP8266_CheckConnection() == ESP8266_SUCCESS) { + DEBUG_INFO("Server connection OK"); + } else { + DEBUG_INFO("Server TCP connection closed, reconnecting..."); + g_server_connected = 0; + TryReconnectServer(); + } + } else { + // 服务器未连接,尝试重连 + TryReconnectServer(); + } +} + +// ====================================================================== +// 主函数 +// ====================================================================== +// 主函数 +// ====================================================================== +int main(void) +{ + AttendanceStatus att_status; + uint16_t unsynced_temp; + + // 1. 硬件和驱动初始化 + Debug_Init(); + DEBUG_INFO("==========================================="); + DEBUG_INFO(" STM32 Face Recognition System"); + DEBUG_INFO(" with AES-128-CBC Encryption"); + DEBUG_INFO("==========================================="); + + Delay_Init(); + DEBUG_OK("Delay initialized"); + + DEBUG_INFO("Initializing OLED..."); + OLED_Init(); + DEBUG_OK("OLED initialized"); + + DEBUG_INFO("Initializing Buzzer & LED..."); + Buzzer_LED_Init(); + DEBUG_OK("Buzzer & LED initialized"); + + DEBUG_INFO("Initializing USART1 PA9/PA10 (ESP8266)..."); + Serial_Init(); + DEBUG_OK("USART1 PA9/PA10 (ESP8266) initialized"); + + DEBUG_INFO("Initializing USART3 PB10/PB11 (K210)..."); + K210_USART_Init(); + DEBUG_OK("USART3 PB10/PB11 (K210) initialized"); + + DEBUG_INFO("Initializing Attendance module..."); + Attendance_Init(); + DEBUG_OK("Attendance module initialized"); + + // ← 新增:初始化加密模块 + DEBUG_INFO("Initializing Crypto module..."); + Crypto_Init(); + DEBUG_OK("Crypto module initialized (AES-128-CBC)"); + + // ⭐ 新增:初始化DS1302 RTC时钟模块(带硬件检测) + DEBUG_INFO("Initializing DS1302 RTC..."); + DS1302_Init(); + + // 尝试读取DS1302,检测硬件是否正常 + DS1302_Time rtc_time; + DS1302_GetTime(&rtc_time); + DEBUG_PRINT("RTC Time: %04d-%02d-%02d %02d:%02d:%02d\r\n", + rtc_time.year, rtc_time.month, rtc_time.day, + rtc_time.hour, rtc_time.minute, rtc_time.second); + + // 检测DS1302读取的数据是否合理 + if (rtc_time.year >= 2020 && rtc_time.year <= 2100 && + rtc_time.month >= 1 && rtc_time.month <= 12 && + rtc_time.day >= 1 && rtc_time.day <= 31 && + rtc_time.hour <= 23 && rtc_time.minute <= 59 && rtc_time.second <= 59) { + // DS1302数据合理,启用DS1302 + g_use_ds1302 = 1; + DEBUG_OK("DS1302 RTC initialized and verified"); + + // 将DS1302时间同步到全局时间变量 + g_current_time.year = rtc_time.year; + g_current_time.month = rtc_time.month; + g_current_time.day = rtc_time.day; + g_current_time.hour = rtc_time.hour; + g_current_time.minute = rtc_time.minute; + g_current_time.second = rtc_time.second; + + // 设置考勤模块的当前时间 + Attendance_SetCurrentTime(rtc_time.hour, rtc_time.minute); + } else { + // DS1302数据异常,禁用DS1302 + g_use_ds1302 = 0; + DEBUG_ERROR("DS1302 hardware error or not connected!"); + DEBUG_INFO("System will use NTP time only"); + } + + // ⭐ 新增:初始化光敏电阻和补光灯模块 + DEBUG_INFO("Initializing Light Sensor and Fill Light..."); + LightSensor_Init(); + DEBUG_OK("Light Sensor initialized (PB0=ADC, PB1=LED)"); + + last_rtc_read = Get_Time_ms(); + + // 2. ESP8266网络连接流程(优化:失败后继续运行,后台自动重连) + DEBUG_INFO("Starting ESP8266 setup..."); + OLED_ShowString(1, 1, "ESP setup..."); + + if (ESP8266_Setup() == ESP8266_SUCCESS) + { + DEBUG_OK("ESP8266 setup success"); + g_esp8266_ready = 1; + + DEBUG_PRINT("Connecting to WiFi: %s\r\n", WIFI_SSID); + OLED_ShowString(2, 1, "WiFi connecting"); + + if (ESP8266_ConnectWiFi(WIFI_SSID, WIFI_PASSWORD) == ESP8266_SUCCESS) + { + DEBUG_OK("WiFi connected!"); + g_wifi_connected = 1; + + // WiFi已连通时先做NTP对时(不依赖HTTP服务器连接) + SyncNetworkTime(); + + OLED_Clear(); + OLED_ShowString(1, 1, "WiFi OK!"); + OLED_ShowString(2, 1, "HTTP connecting"); + + // 尝试连接HTTP服务器 + if (ESP8266_ConnectHTTPServer(HTTP_SERVER_IP, HTTP_SERVER_PORT) == ESP8266_SUCCESS) + { + DEBUG_OK("HTTP server connected!"); + g_server_connected = 1; + last_heartbeat_time = Get_Time_ms(); + + // 下载时间段配置 + DownloadTimeSlots(); + + // 下载今日已签到记录到本地缓存 + OLED_ShowString(2, 1, "Loading records"); + uint8_t loaded = Attendance_LoadTodayRecordsFromServer(); + DEBUG_PRINT("[Main] Loaded %d today's records from server\r\n", loaded); + } + else + { + DEBUG_ERROR("HTTP connection failed!"); + DEBUG_INFO("Will retry in background..."); + g_server_connected = 0; + } + } + else + { + DEBUG_ERROR("WiFi connection failed!"); + DEBUG_INFO("Will retry in background (every 30s)..."); + g_wifi_connected = 0; + last_wifi_reconnect_attempt = Get_Time_ms(); // 初始化重连时间 + } + } + else + { + DEBUG_ERROR("ESP8266 setup failed!"); + DEBUG_INFO("WiFi module unavailable, system will run offline"); + g_esp8266_ready = 0; + g_wifi_connected = 0; + g_server_connected = 0; + } + + // 3. 根据连接结果给出反馈(无论成功失败都继续运行) + OLED_Clear(); + + if (g_server_connected) + { + DEBUG_INFO("================================="); + DEBUG_INFO("System Ready! Server connected!"); + DEBUG_INFO("Encryption Mode: AES-128-CBC"); + DEBUG_INFO("================================="); + + OLED_ShowString(1, 1, "System Ready"); + OLED_ShowString(2, 1, "Online Mode"); + + // 系统就绪:熄灭PC13状态指示LED + LED_STATUS_OFF(); + + StartBeepSuccess(); + Delay_ms(500); + } + else if (g_wifi_connected) + { + DEBUG_INFO("================================="); + DEBUG_INFO("System Ready! WiFi connected"); + DEBUG_INFO("Server reconnecting..."); + DEBUG_INFO("================================="); + + OLED_ShowString(1, 1, "System Ready"); + OLED_ShowString(2, 1, "Reconnecting.."); + + // 系统就绪:熄灭PC13状态指示LED + LED_STATUS_OFF(); + } + else if (g_esp8266_ready) + { + DEBUG_INFO("================================="); + DEBUG_INFO("System Ready! (WiFi reconnecting)"); + DEBUG_INFO("Auto-retry every 30 seconds"); + DEBUG_INFO("================================="); + + OLED_ShowString(1, 1, "System Ready"); + OLED_ShowString(2, 1, "WiFi retry..."); + + // 系统就绪:熄灭PC13状态指示LED + LED_STATUS_OFF(); + } + else + { + DEBUG_ERROR("ESP8266 not available"); + DEBUG_INFO("================================="); + DEBUG_INFO("System Ready! (Offline mode)"); + DEBUG_INFO("Data will be stored locally"); + DEBUG_INFO("================================="); + + OLED_ShowString(1, 1, "System Ready"); + OLED_ShowString(2, 1, "Offline Mode"); + + // 系统就绪:熄灭PC13状态指示LED + LED_STATUS_OFF(); + + StartBeepDuplicate(); + Delay_ms(1000); + } + + UpdateIdleScreen(); + + // 4. 主循环 + DEBUG_INFO("Entering main loop..."); + + while(1) + { + uint32_t current_time = Get_Time_ms(); + + ProcessBeep(); + UpdateCurrentTime(); + CheckServerConnection(); + SyncPendingRecords(); + UpdateTimeSlotConfig(); // ⭐ 新增:定期更新时间段配置 + LightSensor_Update(); // ⭐ 新增:更新补光灯状态(根据光敏电阻) + + if (K210_GetRxFlag()) + { + if (K210_FaceResult.success) + { + DEBUG_PRINT("Face recognized: ID=%s, Name=%s, Conf=%.2f\r\n", + K210_FaceResult.student_id, + K210_FaceResult.student_name, + K210_FaceResult.confidence); + + // 智能节流 + if (strcmp(last_student_id, K210_FaceResult.student_id) == 0) { + if (current_time - last_process_time < PROCESS_INTERVAL_MS) { + DEBUG_INFO("Same person throttled - skipping"); + continue; + } + } + + strncpy(last_student_id, K210_FaceResult.student_id, sizeof(last_student_id) - 1); + last_process_time = current_time; + + // 确保蜂鸣器关闭(服务器查重可能耗时较长) + BUZZER_OFF(); + LED_SUCCESS_OFF(); + beep_state = BEEP_IDLE; + + OLED_Clear(); + OLED_ShowString(1, 1, "ID:"); + OLED_ShowString(1, 4, K210_FaceResult.student_id); + OLED_ShowString(2, 1, K210_FaceResult.student_name); + OLED_ShowString(3, 1, "Verifying..."); // 显示正在验证 + + att_status = Attendance_ProcessFaceResult(&K210_FaceResult); + + switch(att_status) + { + case ATTENDANCE_SUCCESS: + DEBUG_OK("Attendance SUCCESS! (Encrypted)"); + OLED_ShowString(3, 1, "Check-in OK!"); + OLED_ShowString(4, 1, "Encrypted"); + StartBeepSuccess(); + DEBUG_INFO("Record queued for encrypted sync"); + break; + + case ATTENDANCE_DUPLICATE: + DEBUG_ERROR("Duplicate attendance detected!"); + OLED_ShowString(3, 1, "Already Signed!"); + StartBeepDuplicate(); + break; + + case ATTENDANCE_LOW_CONFIDENCE: + DEBUG_ERROR("Low confidence rejected"); + OLED_ShowString(3, 1, "Low Confidence"); + StartBeepDuplicate(); + break; + + case ATTENDANCE_OUT_OF_TIME: + DEBUG_ERROR("Not in time slot"); + OLED_ShowString(3, 1, "Not Check Time"); + StartBeepDuplicate(); + break; + + default: + DEBUG_ERROR("Attendance processing error"); + OLED_ShowString(3, 1, "Error!"); + StartBeepDuplicate(); + break; + } + + ui_state = UI_STATE_SHOW_RESULT; + ui_state_start_time = current_time; + + unsynced_temp = Attendance_GetPendingCount(); + DEBUG_PRINT("Total: %d, Pending: %d\r\n", + Attendance_GetTotalCount(), unsynced_temp); + } + else + { + DEBUG_INFO("Unknown face - ignored"); + } + } + + if (ui_state == UI_STATE_SHOW_RESULT) { + if (current_time - ui_state_start_time >= UI_RESULT_DISPLAY_TIME) { + ui_state = UI_STATE_IDLE; + UpdateIdleScreen(); + } + } + + Delay_ms(10); + } +} diff --git a/User/stm32f10x_conf.h b/User/stm32f10x_conf.h new file mode 100644 index 0000000..cbb8819 --- /dev/null +++ b/User/stm32f10x_conf.h @@ -0,0 +1,77 @@ +/** + ****************************************************************************** + * @file Project/STM32F10x_StdPeriph_Template/stm32f10x_conf.h + * @author MCD Application Team + * @version V3.5.0 + * @date 08-April-2011 + * @brief Library configuration file. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

    © COPYRIGHT 2011 STMicroelectronics

    + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_CONF_H +#define __STM32F10x_CONF_H + +/* Includes ------------------------------------------------------------------*/ +/* Uncomment/Comment the line below to enable/disable peripheral header file inclusion */ +#include "stm32f10x_adc.h" +#include "stm32f10x_bkp.h" +#include "stm32f10x_can.h" +#include "stm32f10x_cec.h" +#include "stm32f10x_crc.h" +#include "stm32f10x_dac.h" +#include "stm32f10x_dbgmcu.h" +#include "stm32f10x_dma.h" +#include "stm32f10x_exti.h" +#include "stm32f10x_flash.h" +#include "stm32f10x_fsmc.h" +#include "stm32f10x_gpio.h" +#include "stm32f10x_i2c.h" +#include "stm32f10x_iwdg.h" +#include "stm32f10x_pwr.h" +#include "stm32f10x_rcc.h" +#include "stm32f10x_rtc.h" +#include "stm32f10x_sdio.h" +#include "stm32f10x_spi.h" +#include "stm32f10x_tim.h" +#include "stm32f10x_usart.h" +#include "stm32f10x_wwdg.h" +#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Uncomment the line below to expanse the "assert_param" macro in the + Standard Peripheral Library drivers code */ +/* #define USE_FULL_ASSERT 1 */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT + +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function which reports + * the name of the source file and the source line number of the call + * that failed. If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0) +#endif /* USE_FULL_ASSERT */ + +#endif /* __STM32F10x_CONF_H */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/User/stm32f10x_it.c b/User/stm32f10x_it.c new file mode 100644 index 0000000..f41c492 --- /dev/null +++ b/User/stm32f10x_it.c @@ -0,0 +1,55 @@ +#include "stm32f10x_it.h" +#include "K210_USART.h" // 包含头文件以使用宏 + +// 引用 main.c/K210_USART.c 中定义的全局变量 +extern volatile char g_k210_rx_buffer[]; +extern volatile uint16_t g_k210_rx_counter; +extern volatile uint8_t g_k210_rx_flag; + +// 引用 Delay.c 中定义的全局时间变量 +extern volatile uint32_t g_time_ms; + +/** + * @brief SysTick中断处理函数(1ms中断一次) + * @note 用于维护系统时间戳和延时功能 + */ +void SysTick_Handler(void) +{ + g_time_ms++; // 每1ms递增一次 +} + +//... HardFault_Handler 等其他中断保持不变 ... + +// USART3中断(来自K210,根据连接图.md: K210使用USART3 PB10/PB11) +void USART3_IRQHandler(void) +{ + if (USART_GetITStatus(USART3, USART_IT_RXNE) == SET) + { + uint8_t received_char = USART_ReceiveData(USART3); + + // 收到换行符,认为一帧结束 + if (received_char == '\n') + { + if (g_k210_rx_counter > 0) + { + g_k210_rx_buffer[g_k210_rx_counter] = '\0'; + g_k210_rx_flag = 1; // 设置标志 + // 注意:此处不再重置 g_k210_rx_counter,由 K210_GetRxFlag() 负责 + } + } + // 忽略回车符 + else if (received_char != '\r') + { + if (g_k210_rx_counter < K210_RX_BUFFER_SIZE - 1) + { + g_k210_rx_buffer[g_k210_rx_counter++] = received_char; + } + else // 缓冲区满,强制结束 + { + g_k210_rx_buffer[K210_RX_BUFFER_SIZE - 1] = '\0'; + g_k210_rx_flag = 1; + } + } + USART_ClearITPendingBit(USART3, USART_IT_RXNE); + } +} diff --git a/User/stm32f10x_it.h b/User/stm32f10x_it.h new file mode 100644 index 0000000..7c3b1d2 --- /dev/null +++ b/User/stm32f10x_it.h @@ -0,0 +1,44 @@ +/** + ****************************************************************************** + * @file stm32f10x_it.h + * @author MCD Application Team + * @version V3.5.0 + * @date 08-April-2011 + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F10x_IT_H +#define __STM32F10x_IT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" + +/* Exported functions ------------------------------------------------------- */ + +void NMI_Handler(void); +void HardFault_Handler(void); +void MemManage_Handler(void); +void BusFault_Handler(void); +void UsageFault_Handler(void); +void SVC_Handler(void); +void DebugMon_Handler(void); +void PendSV_Handler(void); +void SysTick_Handler(void); + +// 外设中断 +void USART1_IRQHandler(void); +void USART3_IRQHandler(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F10x_IT_H */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/demo_DS1302.md b/demo_DS1302.md new file mode 100644 index 0000000..7a08ac1 --- /dev/null +++ b/demo_DS1302.md @@ -0,0 +1,172 @@ +```c +#ifndef __ds1302_H +#define __ds1302_H + +#include "sys.h" + +#define CE_L GPIO_ResetBits(GPIOC,GPIO_Pin_11)//拉低使能位 +#define CE_H GPIO_SetBits(GPIOC,GPIO_Pin_11)//拉高使能位 +#define SCLK_L GPIO_ResetBits(GPIOC,GPIO_Pin_12)//拉低时钟线 +#define SCLK_H GPIO_SetBits(GPIOC,GPIO_Pin_12)//拉高时钟线 +#define DATA_L GPIO_ResetBits(GPIOC,GPIO_Pin_10)//拉低数据线 +#define DATA_H GPIO_SetBits(GPIOC,GPIO_Pin_10)//拉高数据线 + +struct TIMEData +{ + u16 year; + u8 month; + u8 day; + u8 hour; + u8 minute; + u8 second; + u8 week; +};//创建TIMEData结构体方便存储时间日期数据 +extern struct TIMEData TimeData;//全局变量 +void ds1302_gpio_init();//ds1302端口初始化 +void ds1302_write_onebyte(u8 data);//向ds1302发送一字节数据 +void ds1302_wirte_rig(u8 address,u8 data);//向指定寄存器写一字节数据 +u8 ds1302_read_rig(u8 address);//从指定寄存器读一字节数据 +void ds1032_init();//ds1302初始化函数 +void ds1032_DATAOUT_init();//IO端口配置为输出 +void ds1032_DATAINPUT_init();//IO端口配置为输入 +void ds1032_read_time();//从ds1302读取实时时间(BCD码) +void ds1032_read_realTime();//将BCD码转化为十进制数据 + +#endif +``` + +```c +#include "ds1302.h" +#include "sys.h" +#include "delay.h" + +struct TIMEData TimeData; +u8 read_time[7]; + +void ds1302_gpio_init()//CE,SCLK端口初始化 +{ +GPIO_InitTypeDef GPIO_InitStructure; +RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); +GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //PC.11 CE +GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; +GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出 +GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC.11 +GPIO_ResetBits(GPIOC,GPIO_Pin_11); + +GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PC.12 SCLK +GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; +GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出 +GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC.12 +GPIO_ResetBits(GPIOC,GPIO_Pin_12); +} + +void ds1032_DATAOUT_init()//配置双向I/O端口为输出态 +{ +GPIO_InitTypeDef GPIO_InitStructure; +RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); + +GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PC.10 DATA +GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; +GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; +GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC.10 +GPIO_ResetBits(GPIOC,GPIO_Pin_10); +} + +void ds1032_DATAINPUT_init()//配置双向I/O端口为输入态 +{ +GPIO_InitTypeDef GPIO_InitStructure; +RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); +GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PC.10 DATA +GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; +GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC.10 +} + + +void ds1302_write_onebyte(u8 data)//向DS1302发送一字节数据 +{ +ds1032_DATAOUT_init(); +u8 count=0; +SCLK_L; +for(count=0;count<8;count++) + { SCLK_L; + if(data&0x01) + {DATA_H;} + else{DATA_L;}//先准备好数据再发送 + SCLK_H;//拉高时钟线,发送数据 + data>>=1; + } +} + +void ds1302_wirte_rig(u8 address,u8 data)//向指定寄存器地址发送数据 +{ +u8 temp1=address; +u8 temp2=data; +CE_L;SCLK_L;delay_us(1); +CE_H;delay_us(2); +ds1302_write_onebyte(temp1); +ds1302_write_onebyte(temp2); +CE_L;SCLK_L;delay_us(2); +} + +u8 ds1302_read_rig(u8 address)//从指定地址读取一字节数据 +{ +u8 temp3=address; +u8 count=0; +u8 return_data=0x00; +CE_L;SCLK_L;delay_us(3); +CE_H;delay_us(3); +ds1302_write_onebyte(temp3); +ds1032_DATAINPUT_init();//配置I/O口为输入 +delay_us(2); +for(count=0;count<8;count++) + { + delay_us(2);//使电平持续一段时间 + return_data>>=1; + SCLK_H;delay_us(4);//使高电平持续一段时间 + SCLK_L;delay_us(14);//延时14us后再去读取电压,更加准确 + if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_10)) + {return_data=return_data|0x80;} + + } +delay_us(2); +CE_L;DATA_L; +return return_data; +} + +void ds1032_init() +{ +ds1302_wirte_rig(0x8e,0x00);//关闭写保护 +ds1302_wirte_rig(0x80,0x37);//seconds37秒 +ds1302_wirte_rig(0x82,0x58);//minutes58分 +ds1302_wirte_rig(0x84,0x23);//hours23时 +ds1302_wirte_rig(0x86,0x30);//date30日 +ds1302_wirte_rig(0x88,0x09);//months9月 +ds1302_wirte_rig(0x8a,0x07);//days星期日 +ds1302_wirte_rig(0x8c,0x20);//year2020年 +ds1302_wirte_rig(0x8e,0x80);//关闭写保护 +} + +void ds1032_read_time() +{ +read_time[0]=ds1302_read_rig(0x81);//读秒 +read_time[1]=ds1302_read_rig(0x83);//读分 +read_time[2]=ds1302_read_rig(0x85);//读时 +read_time[3]=ds1302_read_rig(0x87);//读日 +read_time[4]=ds1302_read_rig(0x89);//读月 +read_time[5]=ds1302_read_rig(0x8B);//读星期 +read_time[6]=ds1302_read_rig(0x8D);//读年 +} + +void ds1032_read_realTime() +{ +ds1032_read_time(); //BCD码转换为10进制 +TimeData.second=(read_time[0]>>4)*10+(read_time[0]&0x0f); +TimeData.minute=((read_time[1]>>4)&(0x07))*10+(read_time[1]&0x0f); +TimeData.hour=(read_time[2]>>4)*10+(read_time[2]&0x0f); +TimeData.day=(read_time[3]>>4)*10+(read_time[3]&0x0f); +TimeData.month=(read_time[4]>>4)*10+(read_time[4]&0x0f); +TimeData.week=read_time[5]; +TimeData.year=(read_time[6]>>4)*10+(read_time[6]&0x0f)+2000; +} +``` + diff --git a/docs/00_项目总文档.md b/docs/00_项目总文档.md new file mode 100644 index 0000000..5bf2e12 --- /dev/null +++ b/docs/00_项目总文档.md @@ -0,0 +1,50 @@ +# 项目总文档 + +## 1. 项目概览 +本项目是“人脸识别考勤系统”多端协同工程,包含: +- STM32 固件端(设备控制与签到逻辑) +- K210 识别端(视觉识别与人脸管理) +- C++ 服务端(加密签到、数据管理、同步控制) +- Qt 管理端(后台管理与可视化) + +## 2. 推荐运行链路 +建议使用以下版本组合: +1. 服务端:`server/server_encrypted.cpp`(HTTP 8082) +2. STM32:`User/main.c`(加密上传 + 时间段同步) +3. K210:`k210/main.py`(识别 + 照片上传 + 同步) +4. Qt:`QT/AttendanceViewer.pro` 构建的客户端 + +## 3. 总体架构 +1. K210 识别人脸,经 UART 上报 STM32。 +2. STM32 执行签到策略并加密上传服务端 `POST /api/v1/attendance/checkins`。 +3. 服务端写入 `attendance.db` 并提供管理 API。 +4. 服务端在 SQLite 中维护全局同步版本,作为各端同步的权威版本。 +5. Qt 管理端通过统一同步接口拉取记录/统计、配置、人脸照片和映射。 +6. STM32 与 K210 分别按本地 `last_version` 增量拉取时间段、人脸映射与待删除任务,保持端云一致。 + +## 4. 文档索引(分端) +- STM32 固件端:`docs/01_STM32固件端文档.md` +- K210 识别端:`docs/02_K210识别端文档.md` +- 服务端:`docs/03_服务端文档.md` +- Qt 管理端:`docs/04_Qt管理端文档.md` +- 项目审查问题清单:`docs/05_项目审查问题清单.md` +- 后续优化路线:`docs/07_后续优化路线.md` + +## 5. 各端关键配置位置 +- STM32 网络与班级配置:`User/main.c` +- K210 WiFi/服务器配置:`k210/main.py` +- Qt 默认服务地址与 API 封装:`QT/src/ApiClient.cpp`、`QT/src/AppController.cpp` +- 服务端端口与数据文件:`server/server_encrypted.cpp` + +## 6. 一致性要求 +- AES Key/IV 必须在 STM32、服务端、Qt 三端一致。 +- 服务端建议统一使用加密版本,避免接口行为不一致。 +- 各端时间配置需统一时区(当前代码以 UTC+8 逻辑处理)。 + +## 7. 快速部署顺序 +1. 编译并启动服务端(确认 `:8082` 可访问)。 +2. 启动 Qt,先做 `/api/v1/system/health` 连通性验证。 +3. 烧录 STM32 固件并联网。 +4. 启动 K210 脚本并确认识别/同步正常。 +5. 用 Qt 检查签到记录、照片、映射与删除同步链路。 + diff --git a/docs/01_STM32固件端文档.md b/docs/01_STM32固件端文档.md new file mode 100644 index 0000000..da5f326 --- /dev/null +++ b/docs/01_STM32固件端文档.md @@ -0,0 +1,66 @@ +# STM32固件端文档 + +## 1. 端侧职责 +- 从 K210 串口接收识别结果。 +- 在本地执行签到逻辑(时间段判断、重复判定、缓存与重传)。 +- 通过 ESP8266 将签到数据以 AES-128-CBC 加密后上传服务端。 +- 维护 RTC(DS1302)与网络时间同步。 + +对应入口文件:`User/main.c` + +## 2. 关键模块 +- 主流程:`User/main.c` +- 考勤逻辑:`Hardware/Attendance.c` +- WiFi/HTTP:`Hardware/esp8266.c` +- 加密:`Hardware/Crypto.c` +- RTC:`Hardware/DS1302.c` +- 光照补光:`Hardware/LightSensor.c` +- K210串口解析:`Hardware/K210_USART.c` + +## 3. 当前默认配置(代码内) +文件:`User/main.c` +- `WIFI_SSID`: `YOUR_WIFI_SSID` +- `WIFI_PASSWORD`: `YOUR_WIFI_PASSWORD` +- `HTTP_SERVER_IP`: `127.0.0.1`(部署时改为实际服务端地址) +- `HTTP_SERVER_PORT`: `8082` +- `HTTP_API_TOKEN`: `change-me-token`(部署时必须修改) +- `CLASS_ID`: `1` + +建议将上述配置改为部署环境参数后再编译烧录。 + +## 4. 通信与接口 +STM32 通过 `ESP8266_HttpGet` / `ESP8266_SendEncryptedData` 访问服务端: +- `POST /api/v1/attendance/checkins`:上传加密签到数据(必带 `X-Encrypted: AES128-CBC`)。 +- `GET /api/v1/system/time`:获取服务器时间戳。 +- `GET /api/v1/sync/state?client=stm32&last_version=`:按版本同步时间段配置。 +- `GET /api/v1/attendance/duplicates`:按时段查重。 +- `GET /api/v1/attendance/today`:下载今日已签到学号列表。 + +## 5. 主流程说明 +1. 系统初始化(OLED、串口、考勤模块、加密模块、RTC、传感器)。 +2. 初始化并连接 ESP8266 到 WiFi 与 HTTP 服务器。 +3. 可用时同步网络时间到 DS1302。 +4. 定时拉取时间段配置。 +5. 处理 K210 上报的人脸识别结果: +- 置信度通过阈值后进入签到逻辑。 +- 本地去重 + 服务器时段去重。 +- 记录加入本地队列并尝试上传。 +6. 网络异常时离线缓存,恢复后批量补传。 + +## 6. 调试建议 +- 优先看串口调试输出(`DEBUG_PRINT` 系列)。 +- 检查 `g_wifi_connected`、`g_server_connected` 变化。 +- 若频繁重连,先确认 AP 稳定性、服务器可达性与 8082 端口。 + +## 7. 构建与烧录 +工程为 Keil 工程: +- `Project.uvprojx` +- `Project.uvoptx` + +按当前板卡配置在 Keil 中编译并烧录。 + +## 8. 依赖与注意事项 +- 与服务端 AES Key/IV 必须一致(否则 `/api/v1/attendance/checkins` 解密失败)。 +- DS1302 可用时优先作为本地时钟;不可用则回退网络时间。 +- `Attendance.c` 的默认时间段仅为兜底,实际以服务器下发为准。 + diff --git a/docs/02_K210识别端文档.md b/docs/02_K210识别端文档.md new file mode 100644 index 0000000..4ada3f0 --- /dev/null +++ b/docs/02_K210识别端文档.md @@ -0,0 +1,75 @@ +# K210识别端文档 + +## 1. 端侧职责 +- 进行人脸检测、特征提取、识别。 +- 通过 UART1 将识别结果实时发送给 STM32。 +- 通过 UART2 驱动 ESP8266,与服务端同步人脸映射与删除任务。 +- 上传新增人脸照片到服务端。 + +对应入口文件:`k210/main.py` + +## 2. 通信链路 +- `UART1`(K210 <-> STM32):发送识别结果。 +- `UART2`(K210 <-> ESP8266):HTTP 通信到服务端 `:8082`。 + +识别结果发送格式(给 STM32): +- 已识别:`ID:,NAME:,CONF:` +- 陌生人:`UNKNOWN` + +## 3. 本地数据文件 +- 人脸特征库:`/sd/recordftr.txt` +- 本地映射缓存:`/sd/face_mapping.txt` +- 本地同步版本:`/sd/sync_version.txt` +- 本地人脸照片缓存:`/sd/face_photos/.jpg` + +## 4. 服务端交互接口 +K210 在脚本中使用 HTTP 访问以下接口: +- `GET /api/v1/sync/state?client=k210&last_version=<本地版本>`:按版本拉取统一同步状态。 +- `POST /api/v1/sync/ack`:确认已完成删除任务。 +- `GET /api/v1/sync/request`:轮询是否触发同步。 +- `POST /api/v1/sync/request/ack`:确认收到同步请求。 +- `GET /api/v1/faces/photos`:获取服务端已有照片列表,用于判断本地照片是否需要补传。 +- `POST /api/v1/faces/photos/`:上传 JPEG 人脸照片。 + +v1 兼容辅助接口: +- `GET /api/v1/faces/mappings` +- `GET /api/v1/faces/pending-delete` +- `POST /api/v1/faces/delete-ack` + +## 5. 启动与运行流程 +1. 初始化摄像头、KPU 模型、LCD、按键中断、串口。 +2. 启动 ESP8266,尝试连接 WiFi。 +3. 启动同步: +- 读取 `/sd/sync_version.txt`。 +- 请求统一同步状态。 +- 先删除 `pending_delete` 中的人脸特征。 +- 再应用 `face_mappings`。 +- 成功后保存新的同步版本。 +4. 进入主循环:识别 + 绘制 + 向 STM32 上报。 +5. 分时网络任务(避免阻塞识别帧率): +- 新增人脸时先把 JPEG 保存到 `/sd/face_photos/`,再加入上传队列。 +- 启动时先获取服务端照片列表,再扫描 `/sd/face_photos/`,只补传服务端缺失的照片;如果服务端不可达,则退回全量加入补传队列。 +- 优先处理照片上传队列,上传失败会保留本地照片并等待下次重试。 +- 然后处理同步任务。 + +## 6. 按键功能 +在 `k210/main.py` 中定义: +- 短按:添加人脸。 +- 长按(约2秒):进入删除单个人脸模式。 +- 超长按(约5秒):删除全部人脸。 + +## 7. 当前默认配置(代码内) +- WiFi:`YOUR_WIFI_SSID / YOUR_WIFI_PASSWORD` +- 服务端:`127.0.0.1:8082`(部署时改为实际服务端地址) +- API Token:`change-me-token`(部署时必须修改) + +文件位置:`k210/main.py` + +## 8. 部署注意事项 +- SD 卡需包含模型文件: + - `/sd/FaceDetection.smodel` + - `/sd/FaceLandmarkDetection.smodel` + - `/sd/FeatureExtraction.smodel` +- 与 STM32 使用统一学号语义(映射同步后应发送真实学号语义)。 +- 网络任务失败不会阻塞识别主流程,但会影响照片与映射同步时效;本地照片缓存会用于后续补传。 + diff --git a/docs/03_服务端文档.md b/docs/03_服务端文档.md new file mode 100644 index 0000000..22d368c --- /dev/null +++ b/docs/03_服务端文档.md @@ -0,0 +1,122 @@ +# 服务端文档 + +## 1. 推荐服务端版本 +当前项目推荐使用:`server/server_encrypted.cpp` + +原因: +- 支持 STM32 上传加密签到数据。 +- 支持 Qt 管理端所需管理 API。 +- 支持 K210 人脸照片与映射同步相关 API。 + +## 2. 端口与数据文件 +- HTTP 端口:`8082` +- SQLite 数据库:`attendance.db` +- 日志:运行时生成 `attendance.log` +- 旧数据迁移来源:`attendance_database.csv`、`timeslots_config.json`、`mapping_config.json`、`face_id_mapping.json`、`pending_delete.json`、`sync_request.json`、`sync_version.txt` +- 人脸目录:`faces/` +- 全局同步版本:存储在 `attendance.db` 的 `kv_store` 表中。 + +## 3. 签到数据链路 +1. STM32 调用 `POST /api/v1/attendance/checkins` 上传 Base64 密文。 +2. 服务端按 AES-128-CBC 解密并解析 JSON。 +3. 将记录写入 `attendance.db` 的 `records` 表(含 `class_id` 字段)。 + +## 4. 核心 API(按模块) +### 4.1 考勤与统计 +- `POST /api/v1/attendance/checkins` +- `GET /api/v1/attendance/records?limit=&offset=` +- `GET /api/v1/attendance/statistics` +- `POST /api/v1/attendance/records/clear` +- `DELETE /api/v1/attendance/records?timestamp=&student_id=` +- `GET /api/v1/system/health` +- `GET /api/v1/system/storage` +- `GET /api/v1/system/time` + +说明: +- `/api/v1/attendance/records` 与 `/api/v1/attendance/statistics` 默认返回明文 JSON;请求头包含 `X-Encrypted-Response: true` 时返回加密数据。 + +### 4.2 时间段与查重 +- `POST /api/v1/config/time-slots` +- `GET /api/v1/config/time-slots` +- `GET /api/v1/attendance/duplicates?student_id=&slot_start=&slot_end=` +- `GET /api/v1/attendance/today?slot_start=&slot_end=` + +### 4.3 映射与照片 +- `POST /api/v1/config/mappings` +- `GET /api/v1/config/mappings` +- `GET /api/v1/faces/photos` +- `GET /api/v1/faces/photos/` +- `POST /api/v1/faces/photos/` +- `POST /api/v1/faces/mappings` +- `GET /api/v1/faces/mappings` +- `GET /api/v1/faces/student-ids` + +### 4.4 统一同步接口(推荐) +- `GET /api/v1/sync/state?client=&last_version=` +- `POST /api/v1/sync/ack` +- `GET /api/v1/sync/version` + +说明: +- 服务端是唯一权威状态源。 +- 每次签到、清空/删除记录、修改时间段、修改映射、上传照片、删除人脸,服务端都会递增 `kv_store.sync_version`。 +- 设备端保存自己的 `last_version`,请求时带给服务端。 +- 如果版本无变化,服务端返回 `changed:false`,设备端无需重复解析配置。 +- 如果版本有变化,服务端返回 `changed:true` 和当前客户端需要的状态。 +- `/api/v1/sync/version` 只返回当前版本和服务端时间,适合调试时快速确认同步版本。 + +客户端示例: +- `client=k210`:返回 `face_mappings` 和 `pending_delete`。 +- `client=stm32`:返回 `time_slots` 和 `server_time`。 +- `client=qt`:返回时间段、人脸映射、照片列表、学生ID列表、记录、统计和映射配置。 +- `client=all`:返回全部可同步状态。 + +K210 删除确认示例: + +```json +{ + "client": "k210", + "version": 12, + "deleted": ["2", "3"] +} +``` + +### 4.5 人脸删除与同步控制 +- `DELETE /api/v1/faces/?delete_records=true` +- `GET /api/v1/faces/pending-delete` +- `POST /api/v1/faces/delete-ack` +- `GET /api/v1/sync/request` +- `POST /api/v1/sync/request/ack` +- `POST /api/v1/sync/trigger` + +说明:这些是 v1 下的兼容控制接口;推荐设备端优先使用统一同步接口,只有手动调试或兼容旧流程时才单独调用。 + +### 4.6 旧接口兼容 +服务端内部仍保留旧 `/api/...` 路由兼容层,便于历史程序临时访问;新代码和新文档统一使用 `/api/v1/...`。 + +## 5. 编译与运行 +Windows(示例): +```bash +cd server +g++ -o server_encrypted.exe server_encrypted.cpp -lws2_32 -lcrypto -lssl -lsqlite3 -std=c++11 +server_encrypted.exe +``` + +Linux(示例): +```bash +cd server +g++ -o server_encrypted server_encrypted.cpp -lcrypto -lssl -lsqlite3 -lpthread -std=c++11 +./server_encrypted +``` + +说明:服务端启动时会自动创建 `attendance.db`。如果检测到旧 CSV/JSON 文件,会在首次启动时导入;之后以后端 API 和 SQLite 为准。 + +## 6. 版本说明 +仓库仅保留当前推荐版本:`server_encrypted.cpp`。旧版实验服务端与测试脚本已清理,避免误部署非鉴权接口。 + +## 7. 关键一致性要求 +- AES Key/IV 必须与 STM32、Qt 完全一致。 +- 若 Qt 无法解析记录,先检查是否误连到非加密版本服务端。 + +## 8. 后续优化 +服务端当前已经完成 SQLite 主存储、v1 接口和统一同步模型。后续如需继续增强 JSON 解析、同步版本拆分、删除任务 task_id 化、数据库备份或 Qt 同步状态面板,参考 `docs/07_后续优化路线.md`。 + diff --git a/docs/04_Qt管理端文档.md b/docs/04_Qt管理端文档.md new file mode 100644 index 0000000..4df0482 --- /dev/null +++ b/docs/04_Qt管理端文档.md @@ -0,0 +1,628 @@ +# Qt管理端当前功能文档 + +## 1. 文档目的 + +本文档用于说明 `QT/` 管理端重构后的实际架构、当前已经实现的功能、服务端接口依赖、构建方式和已知限制。 + +本文结论以当前源码为准,不再沿用旧版 Widgets 管理端中 `MainWindow`、`NetworkApiManager`、多个独立 `Dialog` 的描述。 + +## 2. 模块定位 + +Qt 管理端是人脸识别考勤系统的跨平台管理客户端,主要负责: + +- 从服务端拉取考勤记录、统计信息和配置数据。 +- 查看、筛选、导出考勤记录。 +- 按学生维度生成本地统计报表。 +- 管理服务端地址、签到时间段、学生姓名映射、班级名称映射。 +- 管理 K210 上传的人脸照片和人脸 ID 到学号的绑定关系。 +- 在服务端不可达时给出简短状态提示,并自动重连。 + +当前 Qt 端已经重构为 Qt 6 Quick/QML 架构,主要源码位置如下: + +| 模块 | 路径 | 说明 | +| --- | --- | --- | +| 程序入口 | `QT/main.cpp` | 初始化应用信息、图标、QML 引擎和 `AppController` | +| 主界面 | `QT/qml/Main.qml` | 单窗口 QML 页面,包含记录、统计、配置、人脸、关于五个页面 | +| 业务中枢 | `QT/src/AppController.*` | 连接 QML 和业务逻辑,负责筛选、统计、配置保存、重连调度 | +| 网络接口 | `QT/src/ApiClient.*` | 封装 HTTP API、请求超时、加密响应解密和 JSON 解析 | +| 数据结构 | `QT/src/AttendanceTypes.h` | 考勤记录、统计项、签到时段等结构定义 | +| 列表模型 | `QT/src/*ListModel.*` | 向 QML 暴露记录、统计、时间段、映射、人脸列表 | +| 加密工具 | `QT/src/CryptoUtils.*` | AES-128-CBC Base64 响应解密 | +| AES 实现 | `QT/src/crypto/tiny_aes.hpp` | AES 底层实现 | +| 构建配置 | `QT/CMakeLists.txt` | Qt 6 CMake 构建、资源、图标、Android 配置 | +| 平台资源 | `QT/assets/`、`QT/android/`、`QT/cmake/` | 桌面图标、Android 图标与平台模板 | + +## 3. 技术栈与界面结构 + +当前客户端使用: + +- C++17 +- Qt 6.2+ +- Qt Quick / Qt Quick Controls 2 +- Qt Core、Gui、Qml、Quick、QuickControls2、Network +- CMake 3.16+ + +界面由 `ApplicationWindow` 承载,内部使用 `StackLayout` 切换五个页面: + +- 考勤记录 +- 统计分析 +- 配置中心 +- 人脸管理 +- 关于 + +QML 不直接访问网络。所有页面操作统一调用 `AppController` 暴露的 `Q_INVOKABLE` 方法和 `Q_PROPERTY` 状态,数据表格通过 `RecordListModel`、`StatisticsListModel`、`TimeSlotListModel`、`MappingListModel`、`FaceListModel` 渲染。 + +## 4. 当前已实现功能 + +### 4.1 启动与服务连接 + +应用启动流程: + +1. `main.cpp` 创建 `QGuiApplication`。 +2. 设置应用名称、版本、组织名和窗口图标。 +3. Android 平台启用原生文字渲染,改善中文粗体显示。 +4. 创建 `AppController`。 +5. 将 `appController` 注入 QML 上下文。 +6. 加载 `qrc:/qml/Main.qml`。 + +`AppController` 构造时会: + +- 读取本地服务端地址、映射配置和时间段配置。 +- 设置 `ApiClient` 的服务端地址。 +- 启动健康检查。 +- 如果服务端可用,同步记录、统计、时间段和映射配置。 +- 如果服务端不可用,进入自动重连流程。 + +默认服务端地址: + +```text +http://127.0.0.1:8082 +``` + +用户可以在“配置中心”修改服务端地址。保存后会写入 `QSettings` 的 `server/url`,下次启动会读取并使用。 + +### 4.2 自动重连与状态提示 + +当前实现了基于 `/api/v1/system/health` 的连接检查: + +- 网络请求超时时间为 5 秒。 +- 服务端不可达时显示简短提示:`服务器未连接,稍后重试`。 +- 自动重连间隔为 5 秒。 +- 重连期间显示:`正在重连服务器`。 +- 服务恢复后自动刷新记录、统计、时间段、映射和人脸相关数据。 + +底部 Toast 会展示状态信息,避免把底层网络错误、URL 和长异常文本直接暴露给用户。 + +### 4.3 考勤记录查看 + +“考勤记录”页用于查看服务端同步下来的签到记录。 + +当前实现: + +- 默认请求最新 `1000` 条记录。 +- 顶部显示总记录数、今日签到数、筛选结果数。 +- 记录按签到时间倒序显示。 +- 支持刷新记录。 +- 支持清空服务端全部考勤记录。 +- 支持导出当前筛选结果为 CSV。 + +记录表格字段: + +- 签到时间 +- 班级 +- 学号 +- 姓名 +- 置信度 +- 状态 + +显示规则: + +- 班级优先使用“班级编号 -> 班级名称”映射;未配置时显示原班级编号。 +- 姓名优先使用“学号 -> 姓名”映射;未配置时回退到服务端记录中的原始姓名。 +- 状态会被归一化判断是否成功,成功和失败在界面上使用不同样式显示。 + +### 4.4 记录筛选 + +记录页支持本地筛选。筛选条件包括: + +- 班级 +- 学号 +- 姓名关键字 +- 日期范围 + +日期范围支持: + +- 全部时间 +- 今天 +- 最近 7 天 +- 最近 30 天 +- 指定日期 + +筛选基于当前已经加载到客户端内存中的记录执行,不会为每次筛选重新请求服务端。 + +### 4.5 记录导出与清空 + +当前筛选结果可以导出为 CSV 文件。 + +导出内容包括: + +```text +# 考勤记录导出 +# 导出时间: yyyy-MM-dd HH:mm:ss +# 记录总数: N +签到时间,班级编号,班级名称,学号,姓名,置信度,状态 +``` + +“清空记录”会调用服务端 `/api/v1/attendance/records/clear`。界面在执行前会弹出确认对话框,并提示该操作不可恢复。 + +需要注意:当前界面只开放“清空全部记录”,没有在记录表中开放单条删除或批量删除入口。 + +### 4.6 统计分析 + +“统计分析”页基于当前加载到客户端的考勤记录,在本地按学生维度计算统计结果。 + +支持: + +- 快捷选择统计范围。 +- 手动输入开始日期和结束日期。 +- 显示统计学生数、统计记录数、统计范围。 +- 导出统计报表 CSV。 + +统计字段: + +- 学号 +- 姓名 +- 总签到次数 +- 今日签到次数 +- 最后签到时间 +- 平均置信度 + +导出字段: + +```text +学号,姓名,总签到次数,今日签到,最后签到时间,平均置信度 +``` + +统计结果不是服务端全量统计,而是对当前客户端已经拉取的最多 `1000` 条记录进行本地计算。 + +### 4.7 配置中心 + +“配置中心”集中管理服务连接、签到时间段和名称映射。 + +#### 服务端地址 + +支持: + +- 查看当前服务端地址。 +- 修改并保存服务端地址。 +- 测试服务端连接。 + +保存后会写入本地 `QSettings`: + +```text +server/url +``` + +#### 签到时间段 + +支持: + +- 查看当前时间段。 +- 新增时间段。 +- 编辑时间段。 +- 删除时间段。 +- 恢复默认时间段。 +- 从服务端同步时间段。 +- 保存时间段到本地并上传服务端。 + +默认时间段: + +| 名称 | 开始时间 | 结束时间 | 默认状态 | +| --- | --- | --- | --- | +| 上午签到 | 08:00 | 09:30 | 启用 | +| 中午签退 | 12:00 | 13:00 | 启用 | +| 下午签到 | 14:00 | 15:00 | 启用 | +| 晚上签退 | 17:00 | 18:30 | 启用 | + +本地文件: + +```text +timeslot_config.json +``` + +#### 名称映射 + +支持两类映射: + +- 学号 -> 姓名 +- 班级编号 -> 班级名称 + +支持操作: + +- 新增映射。 +- 直接编辑映射键和值。 +- 删除映射。 +- 从服务端加载映射配置。 +- 保存到本地并上传服务端。 + +本地文件: + +```text +mapping_config.json +``` + +映射会影响记录列表和统计报表中的姓名、班级显示。 + +### 4.8 人脸管理 + +“人脸管理”页用于维护 K210 上传的人脸照片和人脸 ID 到学号的绑定关系。 + +当前实现: + +- 从服务端同步人脸照片 ID。 +- 从服务端同步全部学生 ID。 +- 从服务端同步人脸 ID 到学号的映射。 +- 合并照片 ID 和学生 ID,生成统一管理列表。 +- 显示照片或“无照片”状态。 +- 编辑人脸 ID 对应的学号。 +- 保存人脸映射到服务端。 +- 删除指定人脸。 +- 删除时可选择同时删除该学生相关考勤记录。 + +照片加载方式: + +```text +ApiClient -> GET /api/v1/faces/photos/{id} -> 本地 file:// 缓存 -> QML Image +``` + +这样可以在请求照片时携带 `X-Api-Token`,避免 QML `Image` 直接访问受鉴权接口导致照片加载失败。 + +### 4.9 关于页面 + +“关于”页展示: + +- 系统简介。 +- 功能范围。 +- 毕业设计说明。 +- 作者和仓库信息。 + +当前关于页是 QML 页面的一部分,不再是独立窗口。 + +### 4.10 桌面端和移动端适配 + +当前 QML 已对窄屏进行适配: + +- `phoneLayout` 用于手机宽度布局。 +- 顶部导航在窄屏下使用紧凑按钮。 +- 筛选区、统计卡片和配置区会根据宽度调整列数。 +- 表格在窄屏下隐藏部分非关键列或调整宽度。 +- Android 端使用原生文字渲染并降低粗体权重,减少中文粗体重影。 + +## 5. 服务端 API 依赖 + +客户端基于服务端地址拼接 `/api` 前缀访问接口。刷新全部数据时优先使用统一同步接口: + +| 方法 | 路径 | 用途 | +| --- | --- | --- | +| `GET` | `/api/v1/sync/state?client=qt&last_version={version}` | 按版本同步 Qt 所需完整状态 | + +服务端版本无变化时返回 `changed:false`,Qt 不再重复拉取全部数据。局部刷新和保存操作使用下列 v1 子接口。 + +| 方法 | 路径 | 用途 | +| --- | --- | --- | +| `GET` | `/api/v1/attendance/records?limit={limit}&offset={offset}` | 获取考勤记录 | +| `GET` | `/api/v1/attendance/statistics` | 获取总数、今日数和服务端时间 | +| `POST` | `/api/v1/attendance/records/clear` | 清空全部记录 | +| `DELETE` | `/api/v1/attendance/records?timestamp={timestamp}&student_id={studentId}` | 删除单条记录,当前 API 层保留,界面未开放 | +| `GET` | `/api/v1/config/time-slots` | 获取签到时段 | +| `POST` | `/api/v1/config/time-slots` | 保存签到时段 | +| `GET` | `/api/v1/config/mappings` | 获取学生和班级映射 | +| `POST` | `/api/v1/config/mappings` | 保存学生和班级映射 | +| `GET` | `/api/v1/faces/mappings` | 获取人脸 ID 到学号映射 | +| `POST` | `/api/v1/faces/mappings` | 保存人脸 ID 到学号映射 | +| `GET` | `/api/v1/faces/photos` | 获取照片 ID 列表 | +| `GET` | `/api/v1/faces/student-ids` | 获取所有学生 ID | +| `GET` | `/api/v1/faces/photos/{id}` | 获取人脸照片 | +| `DELETE` | `/api/v1/faces/{studentId}` | 删除人脸信息 | +| `DELETE` | `/api/v1/faces/{studentId}?delete_records=true` | 删除人脸信息并删除相关考勤记录 | +| `GET` | `/api/v1/system/health` | 健康检查 | + +### 5.1 考勤记录格式 + +`/api/v1/attendance/records` 解密后应返回 JSON 数组,单条记录示例: + +```json +{ + "timestamp": "2026-04-24 08:10:23", + "student_id": "20240001", + "name": "张三", + "confidence": 0.9821, + "status": "success", + "class_id": "1" +} +``` + +字段处理规则: + +- `timestamp` 需要符合 `yyyy-MM-dd HH:mm:ss`。 +- `student_id` 不能为空。 +- `class_id` 为空时客户端按 `"0"` 处理。 +- `status` 可以是字符串、布尔值或数字,客户端会统一转换为显示状态。 +- `timestamp` 以 `0000-` 开头的记录会被忽略。 + +### 5.2 统计数据格式 + +```json +{ + "total": 120, + "today": 8, + "server_time": "2026-04-24 10:30:00" +} +``` + +### 5.3 签到时段格式 + +```json +{ + "time_slots": [ + { + "name": "上午签到", + "start_time": "08:00", + "end_time": "09:30", + "enabled": true + } + ] +} +``` + +### 5.4 映射配置格式 + +```json +{ + "student_name_map": { + "20240001": "张三" + }, + "class_name_map": { + "1": "软件工程一班" + } +} +``` + +### 5.5 人脸映射格式 + +```json +{ + "mappings": { + "face_001": "20240001" + } +} +``` + +## 6. 加密响应 + +客户端对 `/api/v1/attendance/records` 和 `/api/v1/attendance/statistics` 请求添加请求头: + +```text +X-Encrypted-Response: true +``` + +客户端期望服务端返回 Base64 编码的 AES-128-CBC 密文。收到响应后处理流程为: + +1. Base64 解码。 +2. AES-128-CBC 解密。 +3. PKCS#7 去填充。 +4. 解析 JSON。 + +加密参数位于 `QT/src/CryptoUtils.cpp`: + +| 参数 | 值 | +| --- | --- | +| 算法 | AES-128-CBC | +| Padding | PKCS#7 | +| Key | `2b 7e 15 16 28 ae d2 a6 ab f7 15 88 09 cf 4f 3c` | +| IV | `00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f` | + +如果服务端没有按加密格式返回,记录和统计接口会解析失败。 + +## 7. 本地配置持久化 + +应用使用 `QSettings` 和 `QStandardPaths::AppDataLocation` 保存本地状态。 + +应用信息: + +```text +ApplicationName: 人脸识别考勤系统 +ApplicationVersion: 3.0.0 +OrganizationName: STM32 Face Recognition +``` + +本地保存内容: + +| 配置 | 保存方式 | +| --- | --- | +| 服务端地址 | `QSettings`,键名 `server/url` | +| 学生姓名映射和班级名称映射 | `mapping_config.json` | +| 签到时段配置 | `timeslot_config.json` | + +`mapping_config.json` 和 `timeslot_config.json` 位于 Qt 返回的 `AppDataLocation` 目录中,不在项目源码目录内。 + +## 8. 构建与运行 + +### 8.1 推荐构建方式 + +当前推荐使用 CMake 构建。旧版 `qmake` / `.pro` 文档不再适用于重构后的 Qt Quick 版本。 + +基础要求: + +- Qt 6.2 或更高版本 +- CMake 3.16 或更高版本 +- 支持 C++17 的编译器 + +Windows 桌面端推荐使用 Qt 6.x MinGW 64-bit Kit。 + +### 8.2 Qt Creator 构建 + +1. 打开 Qt Creator。 +2. 打开 `QT/CMakeLists.txt`。 +3. 选择 Desktop Qt 6.x 或 Android Kit。 +4. 等待 CMake 配置完成。 +5. 构建目标 `apprewrite_qt`。 +6. 桌面端直接运行;Android 端部署到设备或模拟器。 + +### 8.3 命令行构建 + +Windows 示例: + +```powershell +cmake -S QT -B QT/build -DCMAKE_PREFIX_PATH=D:/Qt/6.10.0/mingw_64 +cmake --build QT/build --target apprewrite_qt +``` + +Linux 示例: + +```bash +cmake -S QT -B QT/build -DCMAKE_PREFIX_PATH=/path/to/Qt/6.x/gcc_64 +cmake --build QT/build --target apprewrite_qt +``` + +安装: + +```bash +cmake --install QT/build +``` + +当前 `QT/CMakeLists.txt` 将运行产物输出到: + +```text +QT/dist +``` + +### 8.4 Windows 独立运行 + +直接双击 `apprewrite_qt.exe` 时,如果提示缺少 `Qt6Gui.dll`、`Qt6Core.dll` 等运行库,需要使用和构建 Kit 一致的 `windeployqt` 收集依赖。 + +示例: + +```powershell +D:\Qt\6.10.0\mingw_64\bin\windeployqt.exe QT\dist\apprewrite_qt.exe +``` + +如果路径包含中文导致部署工具异常,可以把 exe 复制到纯英文路径后部署。 + +### 8.5 Android 构建 + +Android 相关配置位于 `QT/CMakeLists.txt`: + +```cmake +QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android" +QT_ANDROID_APP_NAME "${REWRITE_QT_DISPLAY_NAME}" +QT_ANDROID_APP_ICON "@mipmap/ic_launcher" +``` + +补充配置位于 `QT/android/gradle.properties`: + +```properties +android.overridePathCheck=true +android.useAndroidX=true +``` + +说明: + +- `android.overridePathCheck=true` 用于绕过 Windows 下 Android Gradle 对中文路径的检查。 +- `android.useAndroidX=true` 用于启用 AndroidX。 +- Android 应用显示名为“人脸识别考勤系统”。 +- Android 启动图标位于 `QT/android/res/mipmap-*`。 + +## 9. 图标与资源 + +桌面图标资源位于: + +```text +QT/assets/favicon.ico +QT/assets/favicon-16x16.png +QT/assets/favicon-32x32.png +QT/assets/favicon-48x48.png +QT/assets/favicon-64x64.png +QT/assets/favicon-128x128.png +QT/assets/favicon-192x192.png +QT/assets/favicon-256x256.png +``` + +Android 启动图标位于: + +```text +QT/android/res/mipmap-mdpi/ic_launcher.png +QT/android/res/mipmap-hdpi/ic_launcher.png +QT/android/res/mipmap-xhdpi/ic_launcher.png +QT/android/res/mipmap-xxhdpi/ic_launcher.png +QT/android/res/mipmap-xxxhdpi/ic_launcher.png +``` + +Linux 桌面文件模板位于: + +```text +QT/cmake/rewrite_qt.desktop.in +``` + +Windows 图标资源模板位于: + +```text +QT/cmake/app_icon.rc.in +``` + +## 10. 当前已知限制 + +### 10.1 记录和统计最多基于当前加载的 1000 条记录 + +`AppController::refreshRecords()` 当前固定调用: + +```cpp +m_apiClient.fetchRecords(1000, 0); +``` + +因此记录列表、筛选结果和本地统计都只覆盖客户端当前加载的记录。如果服务端历史记录超过 `1000` 条,统计页不等于全量历史统计。 + +### 10.2 筛选和统计为本地计算 + +班级、学号、姓名、日期筛选以及统计分析都在客户端内存中完成,不会向服务端传递筛选条件。 + +优点是交互响应快;限制是数据范围受当前加载记录影响。 + +### 10.3 单条删除 API 保留但界面未开放 + +`ApiClient` 中保留了 `deleteRecord()` 和 `/api/v1/attendance/records` 调用,`AppController` 也连接了删除完成信号,但当前 QML 记录表没有提供单条删除或批量删除入口。 + +因此当前对外说明时,不应把“单条记录删除”或“批量删除记录”描述为已开放功能。 + +### 10.4 自动刷新不是定时拉取记录 + +当前代码实现的是服务端不可达后的自动重连检查,不是固定周期自动刷新记录。 + +用户需要手动点击“刷新”或“刷新全部数据”同步最新数据;服务恢复连接时也会自动刷新。 + +### 10.5 时间输入缺少强校验 + +签到时间段编辑框使用字符串输入,代码按 `HH:mm` 解析。如果输入非法时间,模型层不会弹出明确错误提示,可能产生无效时间值。后续可补充输入掩码或校验提示。 + +### 10.6 CSV 导出未做字段转义 + +导出逻辑直接用逗号拼接字段。如果姓名、班级名或状态中包含逗号、换行或引号,CSV 可能被表格软件解析成错误列。后续可补充标准 CSV 转义函数。 + +### 10.7 照片 URL 依赖服务端静态接口 + +人脸照片由 `ApiClient` 通过 `/api/v1/faces/photos/{id}` 携带鉴权头下载,并缓存为本地 `file://` 地址后交给 QML 显示。如果服务端返回格式或图片 ID 与学生 ID 规则变化,客户端的人脸列表合并逻辑需要同步调整。 + +## 11. 当前结论 + +重构后的 Qt 管理端已经从旧版 Widgets 多窗口结构迁移为 Qt 6 Quick/QML 单窗口客户端。当前核心链路已经完整: + +- 服务端连接与健康检查。 +- 加密记录和统计接口访问。 +- 考勤记录查看、筛选、导出、清空。 +- 本地统计分析和统计导出。 +- 服务端地址、时间段、学生映射、班级映射配置。 +- 人脸照片、人脸映射和删除管理。 +- Windows 桌面端与 Android 端构建配置。 + +当前主要不足集中在数据分页、全量统计、记录级删除入口、输入校验和 CSV 转义。后续如果要提升为更完整的管理端,应优先补充分页加载或服务端筛选统计接口,再补齐记录级管理操作。 + diff --git a/docs/05_项目审查问题清单.md b/docs/05_项目审查问题清单.md new file mode 100644 index 0000000..3dbf868 --- /dev/null +++ b/docs/05_项目审查问题清单.md @@ -0,0 +1,142 @@ +# 项目审查问题清单 + +审查日期:2026-05-01 + +本文档用于记录当前项目中已发现的高风险问题,并作为后续逐项修复的跟踪清单。状态说明: + +- `待处理`:尚未开始修复。 +- `处理中`:已经开始改动或验证。 +- `已修复`:代码已修复并通过基本验证。 +- `暂缓`:因演示环境、硬件依赖或其他原因暂不处理。 + +## 1. 优先级概览 + +| 编号 | 优先级 | 状态 | 模块 | 问题 | +| --- | --- | --- | --- | --- | +| R-001 | P0 | 已修复 | 服务端 | 公网接口无鉴权且允许任意来源 | +| R-002 | P0 | 部分修复 | 全项目 | 明文密钥和凭据已进入项目文件 | +| R-003 | P1 | 已修复 | 服务端 | `face_id` 可造成路径穿越写读删文件 | +| R-004 | P1 | 已修复 | 服务端 | 大请求体会被静默截断 | +| R-005 | P1 | 已修复 | 服务端 / Qt | CSV/JSON 没有转义会破坏数据和响应 | +| R-006 | P1 | 已修复 | STM32 固件 | `sscanf` 未限制宽度,UART 输入可溢出栈缓冲 | +| R-007 | P2 | 已修复 | 服务端 | 多个 `std::stoi` 可被非法参数打崩服务线程 | +| R-008 | P2 | 已修复 | Qt 管理端 | 删除人脸 URL 未编码 | + +## 2. 详细问题 + +### R-001 公网接口无鉴权且允许任意来源 + +- 优先级:P0 +- 状态:已修复 +- 位置:`server/server_encrypted.cpp:1666` +- 影响:服务端暴露清空记录、删除人脸、上传映射、上传照片等写操作,但没有鉴权;响应固定允许任意跨域来源。只要端口可访问,外部请求就可能改写或删除考勤数据。 +- 建议处理: + 1. 给所有写接口增加 API Token 或签名校验。 + 2. 按部署环境限制 CORS 来源,不再使用通配符。 + 3. 公网部署时使用 HTTPS 和反向代理鉴权。 + 4. 将管理类接口与设备上传接口区分权限。 +- 本次处理:主服务端 `server/server_encrypted.cpp` 已增加 `X-Api-Token` 校验,健康检查和 OPTIONS 预检除外;CORS 来源改为 `ATTENDANCE_CORS_ORIGIN` 配置,默认仅本地来源。Qt、STM32、K210 请求均已补 `X-Api-Token`。 + +### R-002 明文密钥和凭据已进入项目文件 + +- 优先级:P0 +- 状态:部分修复 +- 位置:`k210/main.py:34`、`User/main.c:23`、`QT/qml/Main.qml:2725`、`server/attendance.log` +- 影响:项目文件中包含 WiFi 密码、公网服务地址、固定 AES Key/IV、查看账号密码、日志中的疑似 API Key 等敏感信息。泄露后即使代码修复,旧凭据仍可能被继续使用。 +- 建议处理: + 1. 立即轮换已暴露的 WiFi 密码、API Key、演示账号密码和 AES Key/IV。 + 2. 将服务地址、WiFi、Token 等改为外部配置文件或烧录参数。 + 3. 日志输出中屏蔽敏感请求头。 + 4. 清理已有日志文件中的敏感内容。 +- 本次处理:主链路代码和文档中的 WiFi 密码、公网地址改为占位配置;日志中的疑似 API Key 已脱敏;Qt 默认服务地址改为本机地址。仍需在真实环境中轮换已暴露的 WiFi、API Key、演示账号和 AES Key/IV。 + +### R-003 `face_id` 可造成路径穿越写读删文件 + +- 优先级:P1 +- 状态:已修复 +- 位置:`server/server_encrypted.cpp:837` +- 影响:`face_id` 直接来自 URL 并拼接成 `faces/.jpg`,用于写入、读取和删除。包含路径分隔符或 `..` 时,可能越过 `faces` 目录操作其他文件。 +- 建议处理: + 1. 增加 `face_id` 白名单校验,只允许数字、字母、下划线、短横线等明确字符。 + 2. 对最终路径做规范化检查,确认仍位于 `faces` 目录下。 + 3. 所有照片读写删入口共用同一个安全路径构造函数。 +- 本次处理:主服务端已增加 `isSafeId` 与 `buildFacePhotoPath`,照片读写删和重命名路径统一走安全 ID 校验。 + +### R-004 大请求体会被静默截断 + +- 优先级:P1 +- 状态:已修复 +- 位置:`server/server_encrypted.cpp:1228` +- 影响:读取 POST body 时,如果剩余数据超过约 40KB,循环不会继续读取,导致照片或配置内容被截断。K210 JPEG 上传很容易触发该问题。 +- 建议处理: + 1. 按 `Content-Length` 循环读取完整 body。 + 2. 设置明确最大请求大小,例如照片接口单独允许更大上限。 + 3. 超限时返回 HTTP 413。 + 4. 对读取不足的请求返回 400,不保存半截文件。 +- 本次处理:主服务端按 `Content-Length` 读取完整请求体,普通 JSON 请求限制 64KB,照片请求限制 512KB,超限返回 413,读取不足返回 400。 + +### R-005 CSV/JSON 没有转义会破坏数据和响应 + +- 优先级:P1 +- 状态:已修复 +- 位置:`server/server_encrypted.cpp:459`、`QT/src/AppController.cpp:284`、`QT/src/AppController.cpp:317` +- 影响:签到记录直接用逗号拼 CSV,读取时也直接按逗号拆,再手写 JSON 字符串。姓名、状态、班级等字段包含逗号、引号、换行或反斜杠时,会导致 CSV 列错位、JSON 非法或 Qt 解析失败。 +- 建议处理: + 1. 服务端增加 CSV 字段转义和解析函数。 + 2. 服务端 JSON 响应统一经过 JSON 转义函数。 + 3. Qt 导出 CSV 时对每个字段做标准 CSV 转义。 + 4. 使用 SQLite 替代 CSV/多 JSON 文件,减少数据状态不一致。 +- 本次处理:主服务端增加 CSV 解析/转义和 JSON 转义;Qt 导出 CSV 已对字段做标准转义;后端主存储已迁移到 `attendance.db`,旧 CSV/JSON 仅作为首次导入来源。 + +### R-006 `sscanf` 未限制宽度,UART 输入可溢出栈缓冲 + +- 优先级:P1 +- 状态:已修复 +- 位置:`Hardware/K210_USART.c:80` +- 影响:`%[^,]` 没有宽度限制,但目标缓冲只有 `id[20]` 和 `name[32]`。串口收到异常长字段时可能覆盖栈内存,造成固件异常。 +- 建议处理: + 1. 将格式改为 `%19[^,]`、`%31[^,]`。 + 2. 对接收缓冲做最大帧长、换行结束符和字段合法性校验。 + 3. 异常帧直接丢弃并清空缓冲。 +- 本次处理:`Hardware/K210_USART.c` 和示例文件中的 `sscanf` 已增加字段宽度限制。 + +### R-007 多个 `std::stoi` 可被非法参数打崩服务线程 + +- 优先级:P2 +- 状态:已修复 +- 位置:`server/server_encrypted.cpp:1310` +- 影响:`limit`、`offset`、时间段参数直接调用 `std::stoi`,没有异常捕获和范围校验。非法请求参数可能让请求处理线程异常终止。 +- 建议处理: + 1. 增加安全整数解析函数。 + 2. 参数非法时返回 400。 + 3. 限制 `limit`、`offset` 和时间范围。 + 4. 所有 URL 参数统一走校验函数。 +- 本次处理:主服务端已增加安全整数和时间解析,`limit`、`offset`、时间段和记录时间解析不再直接裸用 `std::stoi`。 + +### R-008 删除人脸 URL 未编码 + +- 优先级:P2 +- 状态:已修复 +- 位置:`QT/src/ApiClient.cpp:453` +- 影响:Qt 端删除人脸时直接把 `studentId` 拼进路径。如果学号包含空格、`#`、`?`、`/` 或中文,URL 会被截断或路由错乱。 +- 建议处理: + 1. 使用 `QUrl::toPercentEncoding` 编码路径段。 + 2. 服务端接收后进行 URL 解码和 ID 校验。 + 3. 为删除人脸接口补充异常 ID 的测试用例。 +- 本次处理:Qt 删除人脸路径段已使用 `QUrl::toPercentEncoding` 编码。 + +## 3. 建议修复顺序 + +1. 处理 R-002:轮换凭据,清理敏感日志,避免继续泄露。 +2. 处理 R-001:服务端写接口增加鉴权,限制跨域来源。 +3. 处理 R-003、R-004:修复文件路径安全和请求体读取,防止文件被覆盖或照片损坏。 +4. 处理 R-006:修复固件串口解析溢出风险。 +5. 处理 R-005:统一 CSV/JSON 转义,避免数据格式破坏。 +6. 处理 R-007、R-008:增强参数健壮性和 Qt URL 构造。 + +## 4. 验证记录 + +- `k210/main.py`、`k210/view_attendance.py` 已通过普通 Python 语法检查;MaixPy 运行时仍需上板验证。 +- `server/server_encrypted.cpp` 因当前本机缺少 OpenSSL 头文件,未完成语法编译验证。 +- 现有 Keil 构建日志显示固件旧构建为 `0 Error(s), 0 Warning(s)`,但尚未在本次审查中重新编译固件。 +- 2026-05-01:已完成主链路安全修复;旧版备用服务端与测试脚本已清理,避免误部署非鉴权接口。 diff --git a/docs/06_后端接口Windows测试命令.md b/docs/06_后端接口Windows测试命令.md new file mode 100644 index 0000000..32bec0e --- /dev/null +++ b/docs/06_后端接口Windows测试命令.md @@ -0,0 +1,329 @@ +# 后端接口 Windows 手动测试命令 + +当前后端 `server_encrypted.cpp` 只监听 HTTP 端口: + +```text +8082 +``` + +以下命令适合在 Windows PowerShell 或 CMD 中复制执行。Windows 下建议使用 `curl.exe`,避免 PowerShell 把 `curl` 解析成别名。 + +如果后端在本机运行,使用: + +```text +http://127.0.0.1:8082 +``` + +如果测试公网服务器,替换成: + +```text +http://27.106.113.205:8082 +``` + +下面示例默认使用本机地址。 + +## 1. 测试端口和服务健康 + +```powershell +curl.exe -i --max-time 8 "http://27.106.113.205:8082/api/v1/system/health" +``` + +预期能看到 `HTTP/1.1 200 OK` 或类似成功响应。 + +## 2. 获取服务器时间 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/system/time" +``` + +## 2.0 查看 SQLite 存储状态 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/system/storage" +``` + +重点看: + +```text +"storage":"sqlite" +"database":"attendance.db" +"ok":true +"quick_check":"ok" +"records": 考勤记录数量 +"face_photos": 服务端照片数量 +"pending_deletes": K210待删除任务数量 +``` + +## 2.0.1 查看当前同步版本 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/sync/version" +``` + +## 2.1 统一同步状态:K210 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/sync/state?client=k210&last_version=0" +``` + +重点看: + +```text +"version": 当前服务端同步版本 +"changed": true/false +"face_mappings": 人脸ID到学号映射 +"pending_delete": K210需要删除的本地人脸ID +``` + +## 2.2 统一同步状态:STM32 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/sync/state?client=stm32&last_version=0" +``` + +重点看 `time_slots` 是否正确返回。 + +## 2.3 统一同步状态:Qt + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/sync/state?client=qt&last_version=0" +``` + +## 2.4 K210 确认统一同步删除 + +把 `2` 换成真实已删除成功的人脸 ID。 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" -H "Content-Type: application/json" -X POST --data-binary "{\"client\":\"k210\",\"version\":1,\"deleted\":[\"2\"]}" "http://27.106.113.205:8082/api/v1/sync/ack" +``` + +## 3. 获取全部考勤记录 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/attendance/records?limit=1000&offset=0" +``` + +后端当前以 `attendance.db` 为准。旧 `attendance_database.csv` 只会在首次启动 SQLite 时作为迁移来源,之后新增记录不会再写回 CSV。 + +如果本机安装了 `sqlite3.exe`,也可以在服务端运行目录执行: + +```powershell +sqlite3.exe attendance.db "SELECT timestamp,student_id,name,confidence,status,class_id FROM records ORDER BY id DESC LIMIT 10;" +``` + +备份当前数据库: + +```powershell +sqlite3.exe attendance.db ".backup attendance_backup.db" +``` + +## 4. 获取统计信息 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/attendance/statistics" +``` + +## 5. 获取签到时间段 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/config/time-slots" +``` + +## 6. 保存签到时间段 + +用于测试 Qt 端 `/api/v1/config/time-slots` 保存失败的问题。执行后观察后端日志,正常应该显示 `POST body size` 大于 0。 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" -H "Content-Type: application/json" -X POST --data-binary "{\"time_slots\":[{\"name\":\"上午签到\",\"start_time\":\"08:00\",\"end_time\":\"09:30\",\"enabled\":true},{\"name\":\"中午签退\",\"start_time\":\"12:00\",\"end_time\":\"13:00\",\"enabled\":true},{\"name\":\"下午签到\",\"start_time\":\"14:00\",\"end_time\":\"15:00\",\"enabled\":true},{\"name\":\"晚上签退\",\"start_time\":\"17:00\",\"end_time\":\"18:30\",\"enabled\":true}]}" "http://27.106.113.205:8082/api/v1/config/time-slots" +``` + +## 7. 检查是否重复签到 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/attendance/duplicates?student_id=1&slot_start=00:00&slot_end=23:59" +``` + +## 8. 获取今天指定时间段记录 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/attendance/today?slot_start=00:00&slot_end=23:59" +``` + +也可以测试指定签到时间段: + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/attendance/today?slot_start=14:00&slot_end=15:00" +``` + +## 9. 获取映射配置 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/config/mappings" +``` + +## 10. 保存映射配置 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" -H "Content-Type: application/json" -X POST --data-binary "{\"student_name_map\":{\"1\":\"ID1\"},\"class_name_map\":{\"1\":\"一班\"}}" "http://27.106.113.205:8082/api/v1/config/mappings" +``` + +## 11. 获取人脸照片列表 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/faces/photos" +``` + +## 12. 下载指定人脸照片 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" "http://27.106.113.205:8082/api/v1/faces/photos/1" --output "%TEMP%\backend_face_1.jpg" +``` + +如果 `face_id=1` 存在,照片会保存到: + +```text +%TEMP%\backend_face_1.jpg +``` + +## 13. 上传人脸照片 + +把 `C:\path\to\face.jpg` 换成真实 jpg 文件路径。 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Content-Type: image/jpeg" --data-binary "@C:\path\to\face.jpg" "http://27.106.113.205:8082/api/v1/faces/photos/1" +``` + +## 14. 获取人脸 ID 映射 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/faces/mappings" +``` + +## 15. 保存人脸 ID 映射 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" -H "Content-Type: application/json" -X POST --data-binary "{\"mappings\":{\"1\":\"1\"}}" "http://27.106.113.205:8082/api/v1/faces/mappings" +``` + +## 16. 获取全部学生 ID + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/faces/student-ids" +``` + +## 17. 获取待删除列表 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/faces/pending-delete" +``` + +## 18. 确认删除同步完成 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" -H "Content-Type: application/json" -X POST --data-binary "{\"face_id\":\"1\"}" "http://27.106.113.205:8082/api/v1/faces/delete-ack" +``` + +## 19. K210 查询是否需要同步 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" "http://27.106.113.205:8082/api/v1/sync/request" +``` + +## 20. 触发 K210 同步 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" -H "Content-Type: application/json" -X POST --data-binary "{\"sync\":true}" "http://27.106.113.205:8082/api/v1/sync/trigger" +``` + +## 21. K210 同步确认 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" -H "Content-Type: application/json" -X POST --data-binary "{\"ack\":true}" "http://27.106.113.205:8082/api/v1/sync/request/ack" +``` + +## 22. 加密签到接口 + +`/api/v1/attendance/checkins` 需要 STM32 生成的 AES-128-CBC Base64 加密正文。把 `BODY` 替换成真实加密数据。 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "X-Encrypted: AES128-CBC" -H "Content-Type: application/octet-stream" --data-binary "BODY" "http://27.106.113.205:8082/api/v1/attendance/checkins" +``` + +## 23. 删除单条考勤记录 + +危险操作,会删除真实数据。执行前把时间和学生 ID 改成要删除的记录。 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -X DELETE "http://27.106.113.205:8082/api/v1/attendance/records?timestamp=2026-05-01%2014%3A30%3A38&student_id=1" +``` + +## 24. 删除指定人脸 + +危险操作,只删除人脸信息,不删除考勤记录。 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -X DELETE "http://27.106.113.205:8082/api/v1/faces/1" +``` + +## 25. 删除指定人脸并删除相关考勤记录 + +危险操作,会删除人脸和相关记录。 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -X DELETE "http://27.106.113.205:8082/api/v1/faces/1?delete_records=true" +``` + +## 26. 清空全部考勤记录 + +危险操作,会清空考勤数据库。 + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Content-Type: application/json" -X POST --data-binary "{}" "http://27.106.113.205:8082/api/v1/attendance/records/clear" +``` + +## 27. Windows 上检查端口占用 + +```powershell +netstat -ano | findstr :8082 +``` + +如果能看到 `LISTENING`,说明本机有程序正在监听 `8082`。 + +## 28. Windows 上测试 TCP 端口连通 + +```powershell +Test-NetConnection 127.0.0.1 -Port 8082 +``` + +公网服务器测试: + +```powershell +Test-NetConnection 27.106.113.205 -Port 8082 +``` + +`TcpTestSucceeded : True` 表示 TCP 端口可连通。 + +## 29. 判断 Qt POST 是否真的发送了请求体 + +先手动执行这条: + +```powershell +curl.exe -i --max-time 8 -H "X-Api-Token: change-me-token" -H "Accept: application/json" -H "Content-Type: application/json" -X POST --data-binary "{\"time_slots\":[{\"name\":\"下午签到\",\"start_time\":\"14:00\",\"end_time\":\"15:00\",\"enabled\":true}]}" "http://27.106.113.205:8082/api/v1/config/time-slots" +``` + +如果后端日志显示: + +```text +[HTTP] POST body size: xx bytes +``` + +说明服务端可以正常接收请求体。 + +如果 Qt 保存时后端仍显示: + +```text +[HTTP] POST body size: 0 bytes +``` + +说明问题在 Qt 端发送 POST 的方式上。 + diff --git a/docs/07_后续优化路线.md b/docs/07_后续优化路线.md new file mode 100644 index 0000000..aa52c92 --- /dev/null +++ b/docs/07_后续优化路线.md @@ -0,0 +1,272 @@ +# 后续优化路线 + +本文档记录当前项目在“可继续优化但非当前阻塞”的方向,方便后续开发、答辩扩展或二次重构时逐项推进。 + +## 1. 当前架构状态 + +当前项目已经完成以下核心升级: + +- API 已统一到 `/api/v1/...`,旧 `/api/...` 仅作为服务端内部兼容层。 +- 服务端使用 `attendance.db` 作为主存储,旧 CSV/JSON 文件仅作为首次迁移来源。 +- 服务端维护全局同步版本,Qt、STM32、K210 按 `last_version` 增量同步。 +- K210 删除人脸使用待删除任务和 ACK 确认。 +- K210 新增人脸照片先保存到本地 `/sd/face_photos/`,再补传服务端。 +- Qt 端照片由 `ApiClient` 携带鉴权头下载并缓存为本地 `file://` 地址显示。 +- 服务端提供 `/api/v1/system/storage` 和 `/api/v1/sync/version` 用于调试存储和同步状态。 + +结论:当前架构已经适合联调、演示和毕业设计答辩。后续优化以工程质量、稳定性和可维护性为主,不建议在演示前集中大改。 + +## 2. 优化优先级 + +| 优先级 | 方向 | 当前是否建议立即做 | 主要收益 | +| --- | --- | --- | --- | +| P1 | 服务端 JSON 解析换成 `nlohmann/json` | 暂缓 | 降低手写解析风险,提升维护性 | +| P1 | 数据库自动备份与恢复文档 | 可做 | 防止误删或调试破坏数据 | +| P2 | 同步版本按模块拆分 | 暂缓 | 降低无关数据重复同步 | +| P2 | 删除任务 task_id 化 | 暂缓 | 删除同步更严谨,避免 ID 歧义 | +| P2 | 设备同步 ACK 状态表 | 暂缓 | 可追踪每台设备同步进度 | +| P2 | 外部配置文件/环境变量统一管理 | 可做 | 降低硬编码凭据风险 | +| P3 | HTTPS/反向代理部署 | 视部署环境 | 公网安全性更好 | +| P3 | 自动化测试脚本 | 可做 | 回归验证更方便 | +| P3 | Qt 同步状态面板 | 可做 | 调试体验更好 | + +## 3. 服务端 JSON 库化 + +当前状态: + +- 服务端部分请求解析和响应构造仍使用字符串查找和手写 JSON 拼接。 +- 已有 `jsonEscape()`,可以避免大多数响应字符串破坏。 +- SQLite 已解决 CSV/多 JSON 文件存储不一致问题。 + +建议方案: + +- 引入 `nlohmann/json` 单头文件版本。 +- 文件建议放到: + +```text +server/third_party/json.hpp +``` + +- 服务端引用方式: + +```cpp +#include "third_party/json.hpp" +using json = nlohmann::json; +``` + +建议分阶段替换: + +1. 替换签到请求体解析:`/api/v1/attendance/checkins` +2. 替换时间段保存校验:`/api/v1/config/time-slots` +3. 替换人脸映射保存:`/api/v1/faces/mappings` +4. 替换同步 ACK 解析:`/api/v1/sync/ack` +5. 最后替换大型响应构造:`/api/v1/sync/state` + +注意事项: + +- `nlohmann/json` 不需要额外链接库,只需要头文件。 +- 引入后编译命令通常不变。 +- 不建议一次性替换所有 JSON 逻辑,容易引入新问题。 + +## 4. 同步版本拆分 + +当前状态: + +- 服务端维护一个全局同步版本。 +- 任何数据变化都会让 Qt、STM32、K210 看到版本变化。 +- 对当前规模足够清晰,也方便调试。 + +后续可升级为: + +```text +records_version +config_version +faces_version +delete_tasks_version +``` + +收益: + +- STM32 只关心 `config_version`。 +- K210 只关心 `faces_version` 和 `delete_tasks_version`。 +- Qt 可按模块决定是否刷新记录、配置、照片。 + +代价: + +- 服务端同步响应结构要调整。 +- Qt、STM32、K210 都要保存多个版本号。 +- 调试复杂度会上升。 + +建议:当前不急,除非后续记录量明显变大或同步频率变高。 + +## 5. 删除任务 task_id 化 + +当前状态: + +- 待删除任务以 `face_id` 列表形式保存。 +- K210 删除成功后通过 ACK 返回已删除 ID。 + +后续可升级为: + +```json +{ + "task_id": "delete_20260501_0001", + "face_id": "1", + "student_id": "20210001", + "created_at": "2026-05-01 14:30:00", + "status": "pending" +} +``` + +收益: + +- 删除任务可追踪。 +- 重复删除、重新添加同 ID 时更不容易混淆。 +- 可以在 Qt 端显示待删除任务状态。 + +建议表结构: + +```sql +CREATE TABLE delete_tasks ( + task_id TEXT PRIMARY KEY, + face_id TEXT NOT NULL, + student_id TEXT, + status TEXT NOT NULL, + created_at TEXT NOT NULL, + ack_at TEXT +); +``` + +建议:如果后续要增强多设备同步审计,再做。 + +## 6. 设备同步状态表 + +当前状态: + +- 各设备本地保存自己的 `last_version`。 +- 服务端不记录每台设备最后同步到哪个版本。 + +后续可增加: + +```sql +CREATE TABLE device_sync_state ( + client TEXT PRIMARY KEY, + last_seen_version INTEGER, + last_ack_version INTEGER, + last_seen_at TEXT +); +``` + +收益: + +- 可以知道 K210、STM32、Qt 是否长期未同步。 +- 服务端可以在 `/api/v1/system/storage` 中显示设备同步状态。 +- 方便做 Qt 同步状态面板。 + +建议:当前不是必须,适合作为后续展示增强。 + +## 7. 数据库备份与恢复 + +当前手动备份命令: + +```powershell +sqlite3.exe attendance.db ".backup attendance_backup.db" +``` + +后续可增加: + +- 服务端启动时自动备份前一天数据库。 +- Qt 端提供“导出数据库备份”按钮。 +- 文档中增加恢复步骤。 + +恢复示例: + +```powershell +Copy-Item attendance_backup.db attendance.db +``` + +注意:恢复前应先停止服务端,避免写入冲突。 + +## 8. 配置外部化 + +当前仍存在部分硬编码配置: + +- K210 WiFi 名称和密码。 +- K210 服务端 IP 和端口。 +- STM32 服务端 IP、WiFi、班级 ID。 +- 默认 `X-Api-Token`。 +- AES Key/IV。 + +建议方向: + +- 服务端继续使用环境变量管理: + +```text +ATTENDANCE_API_TOKEN +ATTENDANCE_CORS_ORIGIN +``` + +- K210 可使用 `/sd/config.txt` 保存 WiFi、服务端和 token。 +- STM32 可集中放在 `User/main.c` 顶部,并在文档中标记部署必改项。 +- Qt 可在设置页保存服务端地址,token 可后续加入设置项。 + +建议:真实公网部署前必须轮换默认 token、WiFi 密码和 AES Key/IV。 + +## 9. Qt 同步状态面板 + +后续可在 Qt 管理端增加一个调试/状态区域,展示: + +- 服务器连接状态。 +- 当前服务端同步版本。 +- 最近同步时间。 +- `records` 数量。 +- `face_mappings` 数量。 +- `face_photos` 数量。 +- `pending_deletes` 数量。 + +数据来源: + +```text +GET /api/v1/system/storage +GET /api/v1/sync/version +``` + +收益: + +- 联调时不用一直看服务端日志。 +- 演示时可以直观看到多端同步状态。 + +## 10. 自动化测试 + +当前已有手动 curl 文档: + +```text +docs/06_后端接口Windows测试命令.md +``` + +后续可增加脚本化测试,但不要替代手动文档: + +- Windows PowerShell 测试脚本。 +- Linux shell 测试脚本。 +- 服务端启动后自动测试 health、storage、records、time-slots、sync/state。 + +建议先保持手动命令文档为主,因为硬件联调环境经常变化。 + +## 11. 暂不建议立刻做的优化 + +以下方向有价值,但当前阶段不建议马上做: + +- 删除旧 `/api/...` 兼容层:会降低调试容错,建议答辩后再考虑。 +- 全量重写同步协议:当前全局版本方案已经足够。 +- 把照片二进制直接存 SQLite:会让数据库变大,当前文件系统存照片、SQLite 存元数据更合适。 +- 一次性替换所有 JSON 逻辑:风险高,建议分阶段。 +- 引入复杂权限系统:当前 `X-Api-Token` 已满足演示需求,公网正式部署再细分权限。 + +## 12. 推荐后续开发顺序 + +1. 先完成 SQLite 版服务端手动编译和接口验证。 +2. 用 `/api/v1/system/storage` 验证记录、映射、照片、待删除任务数量。 +3. 如需继续提升服务端质量,先引入 `nlohmann/json` 替换请求解析。 +4. 如需继续提升演示体验,再做 Qt 同步状态面板。 +5. 如需继续提升同步严谨性,再做 task_id 删除任务和设备同步状态表。 + diff --git a/image/image-20260206145924158.png b/image/image-20260206145924158.png new file mode 100644 index 0000000000000000000000000000000000000000..b630c6b80a5933ae4c39c08ab785851412569329 GIT binary patch literal 123809 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

    2WB!rD1LiXWa z35QXWRYY3uPwe(2%DcY+YJLm&IoKl5tn?#!9=J4eT&@+!^KPY9bG7i-?_eo%P#_S8 zLlBLCa6QbKNUa~f{3UTNaX&c#8IN!tAZ%u>U3rT?x8c6!{+ROL%uEG*<&%R2%r}p& zk#q1-nS;>unKbV}|JWvxy0z7uDZYyR`aHK8W9fRh!-q=VM~(P8e;4D#P{mc7dVY5X zYEun~qWVJBNscU?)Pr_E(AQ(Ufinf~-cdc`k``Zh(vycVX>ob9;!m<;m`>+Kj0%W( zqm3#e$7VGtDvhmR6Z8R-$z1eNc3{z)E<3^cIeK5~>T*W2CjRY@I#-q5^%!wff(Sbq z5goXI+~#K9FVJ1N5Qy5L$vdd#yI+}p(15$BrQV_C9#p01GzaG|={t%cbMp~)EJ=hk9 z3l)MK++)d!7uw577*jwQ%76^_)090TS@Y`T1`XoXxnatFaQ#rwRDc_d5+OY0pKuTS zLv|yY*s`Z%AWKZ2g&~E4`^$fly@dp{*7H4hpdg^bgQ}-Bs{4cw9I2BIeg?joEm7c6 zs5npndUF#J#OTz@=l?h5^9QwR_JEj}7+p^r$Q|V5obK$X0^{G|V4z8EeSLlTb|8#N zd8dE)Lp=>{6R#)e`Mrv=vaOw+NF8O=ib9QII7qyppg>SaD9VqAkrovK4-bE|Se<${ z{kQ!8y#UZ+q`M_$s?j|KIkPEAdnbv;%Y z4&l6gMPmK`@R@%Jk#RJzKQ{p4Lz8dM(j%QHNbrwG88v|kD{x)-L{Tq}g8@VWD3YJE zep%`*LbZ%no6B^h&K6toVZ*(jCCeuUX2`|U(iy%5HvOJwD27It{1DlvkSESvf0Dro z#-ktHmk5E_#_Xm!OU-tZ2}#ln)f2vt%~e{l5{kd&94PE74Z8P?8cLo*gdZZY&|PJiMBel-IU>KM&FkUqQiQCf}5Qx=qCIl>3} zk{xNAy(_cTT2XG07@J>|#|HC3`biy^SD~ksD^TGyqMyAYVc51SP1e%O-#1ejPG2-8 zZV}&3p62Sb+pCxouGUBmokC*f)a$Zf8xFnI6GGUn9;WyQi#4BULU!&Gu+fGbD3a7=XueW>mO`g!G_dwb3Ti(ZQfxENNC&v&_W?cTJd=w?%K2d!7Nu|7xey&XFbH zewC-1>IgFgltmJ?DQFnjeLwVIMHCAwpRF?waGH+mV-bp@0+-MT5?`;sCmeEOI@D;n zI9dzUdG{9F?RkGU*jXYSjW*a{Vf=#D^VGPhah2XM-R;zAU0hLudC>mab0nUC2$zv_ z=hW~10h@9_ho{=hb+NZqAlBr9kA}oNSa~E9BhG>3Y;$*YH36VPq7+g)+IIWVd32-!bf)@7X}2A#OFDY%a#bB3fu_~Re{{ActJJ5BOfIA2e>O%P=dPNB?6Ufslpm^-hD~A0Y`B#KlzAbNQi5&QD-TPx zR>iOyF{E#Ym7fIV(lqDmB^NiSXnO>!Gr3*7M~zgv?6gRXgz|9S_68r(oC?d7u6|Fh z4o-h!M-t<8G&EQZ2E$k|RrCDheni#$O!Q@}q*!njGe-5*QetESTnewS2+x43E^~6`1v99ovkdBs4 z6yzpdHiw|BP_EI(+ng4zd<`3St!bge64g83lQe=%QltmZ$Ua6YN^1Hi-N@?*rhNT{ zx@f#)n*~evt>Ky`T*36Lve01(hYvF`P2Js`8dDY{om8^ z+)T;J>Pa}R4{JypZIZKX$rZa_TYe>qN9nJcvr z%TkrEb$p(_osMG#@hCVD+;6knxYNM>Tdd=!p!7c#hoXLmDMG;uK=%?zOoQcYW@E7M zll(^a>+iYYQTxDa!Q;w)1*E`kXP@1KuLHm2$4xPcfR$Rq?rc{!Y1>wR?MaW_ipb}= zjFKM&DWzK7r{iBr?AKb|Zx?oT-m4rYGlgNI(I|XMX3^QZ*%fg+69N@qg4uo(A&bHN zJqrKwQCeQ`>z}(FQl_qFtL#{wW~6Q=a;>B&bNWt@tbuB)_=V(GAIHB9aL$3Zt$eozC)xYm};u-lHRS|w-+0iDl z!xTyrQJ3AkE&c#XDi`Q}@sz*rlK|S#c^mA}oy-gO7B98DV#e=uPe{bYfpK@K+U%Mh zRorjXDF+`U4pVmCWe$N3{n^9>C~&?@=pXXbnVq?99h2)paL^j1%m%|v>{Yy?k zy~#6u-@eh=sQJ)|tU2$)5r@?U1UOpUi-Y`fr~pGwj`ocAzgk$&I_`}**B^YutkU8p zs61zNy{qdEQcM6E+@70iF{~@ryZovVn?Z&m)sY>dqESQxMy1m8_M6O%u6|vMP}cKG zlr?AYdl$bpEm6i{KGV&e830;YDl>Ds;^xMD_-Lu|GL@4{Qc;Pq0wa^Y;&tLNS1xpu z=;CWK(6H$Zm#=22UiYB(x?Z^+AgPplxUw=qd3kBji6ehMScm)aN0d@2mEI`%hC37? zzREoH!_oC>blym}YN2qikG#RG+vU74GoSp_0phaLQY+YF}e)Dtpy)0CdRM=(-KZpxg_KG;0}H`#ZEBdo>jl3HQu zt8EXDFi5;4K>MiV{ik@r_FCVmph{oB>kqfohIrqy{Dt7~VE8D zU`$Xl3gtA%>a&OvM?-4(p|c*P$DjL#NL;q+QX~i|@+XS7K(QtW6@oDY_v7WeNqKqd zBsDcvhu6O=eN9z~Xvj#A*x!dnn}13y-(!fFw!zThsPNRmOcpQLZH;99%Y`CbjaU>` z6giySid%>4?%_szNg{TkLT+2s$sqzNmN-VRW(t?|X8S88zsm?BQ86)GJm|yySkZ8i zFICFdtyeHARtW6H6HX%Oqr)kmYbGe;ac#ZOMRAmWUNcOoRb8{)Wc0qUTRxrDcRURD z#hR~=Jgt%X#o9X9*S%mMjTHkvAcLmvJ*2nLn`hnH#SU8)0ba4nd^ICS3n0<(b%Ctw|72 zl^h+KzpThY=>n$mW;3spy^jjO1G~YZq1jRDx8dfY8&gyr>|V6T!iuf1nPxOJ{>r(< z#RTm2_Y(ZNvToKO)heILwwHwW&S$xFdFj%H4x!)Q;>D>sGUmbHXf=LB-iYrSAQZzU zquWXI-<}>K!RvKX`BOhy`ORC#1Ba%+u>H1#l)hEhs-RJvoV+3EU zn5IV)(C?Mx z8-Y3!Hmg{JwiBhch{paWZNhLcj$(7qp(_u^{RB5Q&h?+bLFT-USq*L!iI8KxFN6i$ zf*zS#!+P0ZTt5M<>vxR*H0(dY!EMC5Sx!t_{=*gaOcl<&yCG~Z>P9igq1wnPN5Jf&lyG=!#bHO-Eb^bDwJI4Fn(ZlZ$%-4sj zlYToIZ>Lb@M385yoyo16Tqj;OA*@lv?`aNLL=#gQXoU+PCSaf&UWveqLS-^-J8@=wF9NhnuA z$@FX_qNZnue)lEWqd1X%&nV3z9-KvTpI7l3**~(ZFL-2Gtv}oFFFut0)Ld$|-QcjG zLf}38w>uj*Bkq3s-bqa&ax~S6c(r)w{=v+cEGGh34yuoTpif?{WjTF4zl@ZTc)%c9 zbMr`z7YSNz$%6r2!O&A7D`amRVCxoM=AL0$-|2bTRoW<+%rimk>LAR|`?Itri0nz? z`1tr@vInCNTO28nCr%DeGP-xd{q~GzBCDJDlDpHX6Dj6!u_2iiP7%#w-Tey2KCsqr z^bV-%suSz$zEvrQ3&H4XdNe0L`)ikTGs&)-Ouc!!uKD7)#G$X;x%jIL7urSrPQ@h0g2}H1WOecdI z@ZF77RDZpZ?kS=x%0{gevcBt@`~IcqBqv+Ic>>0<&k~doT(ZDoplf18Ddp;JXwDLK7uuYB)coxFU@Kmx=`3HOolJjjEANXN zJ`%$7q;0a}Il6=6PYc_dw>@V*ph;zb%LCl}oGZUFQ#X%x$ILGQeY&r=_xQR%gxI_D zZ!^VwRBUwglLz`d9`cRXw3~29T$BD)nOZse&Bw=-cVqSM%)!VeW31uIhO9d(KVp}x z@4*>wApM6*CnBEf+U1jArk54Ir=oAp(j2+1>`Y1CmM& zZH?yj_g4qAfR58#MWCD^uC2WSRHsCRSZ2^hA_t2Bwg1m(U4fi&eBL(|!>07uOjbkR z;~U;uOk`Qv^e%;dYj9QlZIrfu`F*ekgMlyB$A+5~1DN12kdcw;IP=e#_a4la+SBqlh4>1_Jv^rT}<_=nCVX+?@NPG z-n*Tw%rEFBQ`%;wr!P0!EXG*~Ov{S}vIzra_du7Foj({4CnTPL!yKoD!91-)#W1?I z;djbu(f&3rmUuBVxo-LLcUl@aX&46tGJIqMpcfe#gt)l4z;D-sa|bTW%*=qaw7@07 z|2}2d^yTHHiHr{wqP$TEaK*k=a5 z)Js*R06858yxkj4=+z0CjH+WCb?yL0-J`ostsOr%Cu2zj&d>(L_i8)aRbrOikPwM(w0m{kj+gGgk_P~n55T@oIulzwj!Fu+y}ahb3@<0tI3A*(POZKZ zz`@aael>GAT3BCrax)zLQ?28AM3N0Nw_`Y2s!dXWLCtbB%V*8ZO^X0ub+DL2Iw1*g zU{3~E;uvhn0lD$je5;y|%9(DkcP}|g8zZ~UbA3fl$F1RNw)*v`$-s0ToV~0X{%$l9-IB@ZNJ%;v8C_60W;!zh=9x7uHKL@#UjpAr&lH1r=Kq)6Znd~ z`mKyaK^-H(daZzU0MyAY@I{iv5D9?psfA5cK6Im#&Db}WiYaJLsj4W&b>o>Rjbg+~k! zLjLbnPFs^)_8S&X|GW$VjW|{aZO+7!=maYXv~m=L7vHmS9kJtfyfrx~w*gMTFd6Ys zt!H-%Tey)HDqMr+xDAvJq6tDoCm*e09Q~|8%7!PUL>W>?Jj9BD7@$lMnP#-?&$zFb z1`@BK4NoKQXJup=@#|+RCC}plB(veh?(ZEL{-c4IX!> zaWrr&&PS`208%q%81RWffCLzU!_4f|kx>u=b~gOFXt~*Hk(trx{I1UBThGI8bTD4g z@T9EbFNiZ&bqi<>Wy!^fZ%HGKTX6}oLcmctqA5lde!;J=$WXdLijc&|r#SUwbnQH1 ze{s~5Ck#o9(HaaJp}5-#N*bC@J})#X@CTqEn@yyVev=4VYw728tGUTME-n!yfRW|F z1BpQ(N8h{qw*S$qxl&QM;W>4?YKYoUyvFiyI)7_$jY`Gp+gYo*_ z+h&rvw-m*ytOu`4oZVuTQ|E`SpP1IJ*hj7aLmbkomMQ|~T^cZU-CPv40phAsl<9}#A=8q{6 zDRr6q-#W=nXfOmpG~DC%B2ajpC^Q6SGgUdcMf84L9IIueuR{rg!QwDsQat%SKsgb| zx$#R0e7@c%hxLaqM{xOiC6hVkXjU?D$WqZRWzWlDOsfw(^g_l{@#Sdg;3(umnSKhY z{$905sU9E06L;_2izxNiI-k8?Ux-TV+KJ_AJZxU$-ukt3n*2+-{$lZ)BWmA%B^Zr6 zJvxZiIGV|B*T!)A>hbW*g6#8?(S2JnM;Ng-zvsbA`2s5uAPg89j{;*8t;+I*xj4itS2ESBeE-(X3U=d{4Mp zxRTT z=G4hLr}NqsmzI}MK8|8MskhVLma}pO~BQ~&e{Q1&K>yHHI^ z#e1MN*Cr%l(3-l^v2QV69^!JoWC}#poTV7$cWl1w`Zun8(<_wxz{HlbYF*b|(5(2lxi5ylrJ+~?T$jeS>mi+*SEj= zSeEJNF16p*IeT26+GQlWOrJiPJx3KaB-fjxu;f5dxsR0JpK5l#&Q+pc>ohv(Z>m++ zq{piC|AMy6bRDJYH)bGPeSBTlF`jPt`fzS%kt8wtV6kh9AOw(zZ0B!;R-3=VoOgSB zV^8k@Mc68TAZxlDM_LCl$~Xs}(U{Sky}<*ywj%p8CZ6r(UE`g~^0&w9d}^M!3Oq`j48; zVntT{ZBUg(CkVNA-22^RI3K6`vVsVZQSqH#=9VJ@TruR1?-gGC9+WD>Tut0rz*pnP zE``PJQnJ#{P6%`w-@)SHMoW3W17LRo>C(0b5fG%1_)L8JZ+({6r8M0_Qzi5l>(Vc5)nTRzg=dIre9bauOBPQ z`YU#I@Z^unO<%Vu!4yq$lhfS}Ix5S}ny1>e(Dtn;i&!VvB`Spedw)?{a8xOI%>f(+ z-0!;%J}r=FKkLj(ROq3p5;};CnAmUouJuG|v2Lu$^^zPhpwOLbV3f<|U2f&segfEe z_hJ^&0{^4roZoC1T|1{Z z0AZqMRm;`%jQL%f3v(CMIx*G$$)7C&w7)7el&ag~j*mW$=WrWe zTwz@rCH8ToM})|M^RgKE=^OD@<9sO4%%fNd*#)J{WRf;5%!6l}IXAW@NH* zliN+k?!En@CFBR@im&8yIV;N{X4Mz!a(k*6Xj~YFhvREWb)2RLQEKCBM8Y?EoJ)Y} zFmRj~I?W5Q#24sos8Is|C^afP4jd}#AY$KBsS_@;Q%VVEJH8SeViIlha=)bj8A1rO zQpMF^c~FE|!3rYcisG}k>xc$;j_EFU`!Mp|?-gUWL5LZD=7svt3a-JTKb+89Tor2= z3te5`;B-L_(Xr?aYTJUgK|%DD$dO*&19d^cgD;JazoX^ScK9r-r^;5xwtVlKcOlA9 zHtwo)4s!|B+D2!T@?`W;!Yr~S9?JP57K2?QJmHYv`;Kv)BMZz2KY~EK-bkq|RD;6a zk$r;1K4mX{zp>v0(jDE`(CL8bgzc{8?wH$ zZ{1bAuh3L381u@MjW98Wy_M16L7IPgpL4g&I_epsJ#&;6<;2h;qP)tK@lr4Ga`PqN zu+Y&jSFTg@faS3q-?{DjZD3P!Xv`KV>rKn6}%|pBg;nugrBU@oy|D! zrUtsTB|~mvOnGi+%%)bI$t^GHz2BP4wqzY#9?hIVd95P*b@?9?ZJ0w8fx1J~AaZSU z7DBd)W{2gaFaCo?<^&iIsc}_$EuX%4dRi2Bf&ZCxe^5|HtUs_C>pWsvny|Ch`I*!F z266;e9Ej8R1DmlEVj^#!e4%+mKezBhC{xw3)$y`!1F!;JP2>BSWRLK!45BN1R}4kO zS*`POZrg}YxOrL(-bb+Jo^wh$O9oL;|FAFr_2FA?u?6tltBY}IKJ?$(mqOU7f$&H2 zAnn0v_Ru7z*ZSzvM-64%n9e!8v;bw>2gkJlbT#W2rzho8=7?p}JMIFt*7FtoT#L>} zKi=a0w0|zEf$KrEe?L@flxyuDKTEEToHXGYeqIL*`xYA2?MtmX40z^bV(0Iubkto0 zYR+zDvjK={R%kpS0H# zr}OGsZ?@jEJ#Y0!MbACAy_h@C#S-5N54!UG-fvI@)V-zHqD zbkNvQ6^%c)`TX8F`7{|J{}Ts}PA?pUPA&-&M?EO#f~UeE2Mm;m+bBaR70cgr=4~R! zAHGdb^A{4B$U=Nl#Zk!ML2MX9j;P{A7xuH1$KT$@$~|RaAprXj#whUo4w*k8$5uOO zr+2B=17o)Q!-D|TB-@Mugt9pAQt%u346nC3`oA0zFeT}-`y z@e@;~GzT_Vtpe`V-HW5?<9nUnw_%~7_m7X=kH1P_;X!mvOnN^>s}!vp3Gu{4OP6hd zA_UI#2=T({G8n3OkfWDZ+enYtAUk4GbTp@QmD1?FyAMP3zn)+ez^C$&g5p9+8`VT9 zH93Eg2r^neXPqqm4xSv5=(=sJf)PP8S-Mi49}Zq{K-7qSTo3bL~&?%zLk_HM>}kaCvx%9xh*2o*1%K1YJ7NT7P&oo_jG zKXdy%-F1&!()A3M8n_6It6^{3+pgV5H3yYQ3f6jEy&qCO%@S(fI-cjJ;)MM!DoOBu zpY^AczR^xqs{A*E3gva}k4CnPT2)rbmyvpuw{^r8{r};DCkFF^R(!{xTKu`2bof-OTCh90jT@a`uKS zNdqC`4`zno8ul1*ct|pG-RA(^;^`ka7>Lw`!YVBMd{$bBQa!MYDrXlLQxNMR2M2qM zH4TmJ%p2fZ3}c0O>4ho5X~$$VCfu7D1+m#LR4jM-KBC)#_eAOB<>b|@8w4kx7em4h z**OqLEa#xeJr&UnjM?z}r*vXJ6a{##VMtsIz2MuERrmQaHKfOcK5>SwEy6r#F%UVd zUVIxA%1J~nNnHKaS)=2hp8j{21UiFP(!RP0X6Bh!tUg};R?WfQV|NS9%HaA1$RrPz zG0eJBxzhKV33Xn(WQ~P4ePjU2{En>xy8UB@S9|}&;Egz?$`4cYOx`zsA5gXA_l^&Z zl6l-+oNw6)dB{2i^3^=2)9OxsR}R`e2=cm+4Y%$}x<0|w{E!tAq{MT%T0Mf2jFogcu2bVN zRCTiJD`=?1OT@rQKE#lfT`v@^Tbf|;i2Gw)(;jZgrmx1qB zKSZ3bmfws-q+Nn=QqxvU79#{sJ~f@L);>Hxo35Ro^4=2~w&c7S^4Vyh$5Zj{H(eEQay$0P0>=#USi7K_*9QRo6w?PT3mjvy*>MQrX(Mv0=L+&7emOwl(}1>| zjuoH!N~c0Z*AH5~rWWx*M`9Kg^-7!!ms4&2?*U3Fm$!SKvHN_Vc;4Ig0&0V3KY3{y z%IH5~ePQCs+N{B0H7aal6{=6ifTZ>o(2b6yB#p@NkPiOF>td+@aDW!UpE6T| z?>etCxHhiQUu4ZypGQ(K8LN^d0>1e*{v4(OqXGHiH^&HlfKEq^(bqu`4F4;(mz#yxXh--|$Wpc#Q!f7a<8rCs6wXSSMF9$`jT1 z3uyiBcTbaOpo}X9;KgE$gUyQQ+pYZOuJ%|ek?^@pj1cXAS z1_lPk$Hxziw$BWsNr;IXv@6@&+fRl7O+G0pNxRa`-M!h%+Es1O~U z`XJkD%8QHy43js#a5MRN4Fcc5VfSFJ3`=?I-tzbM>$Nxjh{+8u1Y!3jzi-=gkOP#_ zAwk5WxcN;ygmUVn!?5t%YU1O$CaY~~Od=i!ey1DgM{2~(X1SANeC&-MO2FNdh|5;9 z+pfCDe?5*SBul7+FHbzxqo+3lZmvQ>m*4Jl()Vj3F8jH<(S3h?&(F@n0m58OW-acY z3l)@QgXSD1dsy?FcN;&kXtA9|DJO!RJ-^1OyApE#SgbLso>s{<&8RSomdUO4TKK_# zeK_Z!*e$cD5W5jsn+@Y-L?3Emv0nRO57Y}=bJ;XG-J%(DH0@G=U2XPblL%{+O6*ap zL~6X=C{sK&+DMfTUK4U!D|Sm=0$)^I{+tJVt%^a_FWf5vdA5Dh*w+9rPr$ox0;ACI zWM5?mQt)r5i7dnQFuRE3c{aYo|2TDlN#`@rn<7RsXRx3M5@byO z&{tId%G(IIRkCDj+(e~+dq=X|?(991?t0|ViHJiUW;5--mf!a&mRQ*5@9*5}wLkk4 zT4vnk-%6wAH#Y`aq-V*1`B3$q|mmK zD&A*a4ZbL7k0y>RHAk&GCX zMcj`6PM3Dl%Nx{8n5y|YL1ol0>Is||-R}L?6C^$@j1x5b9rl;Yc&%FVM8QGI=5A)+ zpu8s$_SyNhwXL(~Uu!;+CWP;R7DUShBTti~t|yO7ys4*+q!{GGo|5dRXd2d`T##ZV zdRe;Di_5Q{iFw`Ic|+v3`MCe`5jaVFK9)|eUOBsjKJ$fGqd3JvsKH{nG|2Ugqjea4 zKn{elFcT5NYV>!nNF1bu0HZISHbel4qH3k=nz0kGY-@VX*VH|X;lKk8yUP`uwe}Mw zB&)734Yvv?EE%;_UNvZM8O!%P@!)VI?GNr6hE5*CRW9QJ9S#be6OB zVWlQLRU48zDnZXVvSLawsn~G>Sq~I2P^JyMSRxFy@zg21a1iUFV5$^Lw@J(`Ez;i zQ(=98`x({#t&8}=RXk;Rg{*gh+}}36_L4u1yG|hFRS}m2&T2Jxmp5mh1N&@J)6wZ~ z5gnCY1D^2rC($u;h(exO(OnccJl^bG7O2nVWZh)=mwsVahM=EEGcEW=YQQ)E0UE*l z@x=3~-s0asCHD#DHMcU)Nqxe12%<78#c$(G8Mtjvwb#v*UndvtNKs`<|-kfN% z1cDw*Fo!|R7jyUh7c6apFLZ2~%I|XHUdkLUrI|7a$w-Cp36g~RaO=74h36=ZFBC>g zgqNG04z@nOZFfzY&Pqfa@eq)J1NGg({>dmrETq>I`%)sordAhEy<0s$;~H{m$0W*l zoeTE$hIQaV|30t2Z-6SaMkh~bMR|TrEihPtO@Q)u7LwZs^n{Ao-K=Av<0WfRlQrLC zV29XbWt_zxh!Dx}#fJx4z>0W|RTX@RfMqOh&8^Vp2T|fY(`K_ey6-O)snY5;56nG1 zTr0L=&7UANKS?wjmJY<;S{x_JxjcR6v^ug_53g9RKwX)`QS3xe?arrJf}mGO(*ye{}gm z-@xknaC|6X(+^({4Z{2y`@X>uPb`g7A)CL|f}V8wixm^-P2r)KZvlo1ZO>Tw`4>7Q ze}lo#WypIC?QeOq94^6w6a6;4wkH_X0vd z3C#eB9ZJHK3nzAdt*Yx&h5VE$_KT1zeQ#7xo{{fL1VZ>VJP$_$Re?wEuTbTf9NFAb zc%94-AmsQ^t6muRIUiwkKU%=)!ACcecDshZ2n+6KvCH+1EAga3D{;kFsLO>7!H#{h zl2!vbubpkXdi$B+Kea6f-n#0X~5aULq>!Eezo2@FF8X6^GB;P7Tf4hH0OZi}QJf*8lG4 zWtnJ+q7^cJ-*Qb4I_SB+)X;BXTy5f?QerlHm4CFp>o~#p`>RB-lVzf5(@2ptsvDWF zqZEND2sNS*ZXv34q_0e5OR*P31&JG}Nig^Kn~0MK9atS`1v!hdHHKn(GJpzxp650A z(p*W4mHuJH$`$6|zHqH8H9i34JI#-fbYjJ!iJ_VUDn%MGLX=H~6-5XXhz3VXAdBz7 z3?){cXyQGe2t3Y{(Q6;zbZ_73%8NSPbh0lvM>JLQTxjCw4l0Gjucw!*ouw5uT z`ry_6u^lc^IO05nSiFkG%uLvb77?_Y`ff6skh({Ls}nZ@!0(AW!J6&C<&iAVR!zRY z*I_(dL_6$!0g9k8yi$5N&;7`);*gkc3JvsRqOu2{6!HYpd4yh^E2cnZqGB`-)EpT|IixcTd2f=0eROkzeN7u=xu!a^L1#D}#svf-Yi6M6Xw+%RO$dE9j9jCX)jAH4s z95+Y9n|?gb+YPk8f3LS{bYrdCh`lNU0zh&lQUgv9wxL*W#mwByf*-92D3K@V1LZf**SKfdL$ z)5K0O!=Cs^f@CWh#5RTKL?s&gBTKT%TS=%rFqC4ke#i*Z{5!~t9SplMO-vw+VBiO zm}!q*1+)_Y2_C3OysuKD(}Fz%2(D(i0$MLmPhiW3JD{BmOB6gPufEP-i%ni-oeBOB zt;HdIBU8?Q^(}|Xj*{&Uu#e=iS+L#g@(tB4S9T(N-B_(pY83YQ{DcqQ1|+>I?Zz@g z5hqQ{0YM=+6D&A@zE;{I3Ewp<@&*#(zZw_#+E9J&b`KGi4qKdRE!@)EO#RoFwJ<`tvuCclpe@Y(>0B zNoP;*Y0#Uo*A^RUl>;7Q1tjeP+Vc)Z|LGi%)8oxabTkH$Enc*vs_I<5#blL!r}bk7 zW=K2`{QI(?-N`0Lts*YoJ72B=?4?!zteLXwb^EO^sDfVJ6<-Y}(V(HB0nW7gM#8y7 zdu1OVVB54o;2KGN$;ac_oPKFWF;bVTAZFy$3pp6lp6qsLz6m-v7GfPOYW0D$e3_{%$^= zp&sY+zce=GQrpVp zhL0=gNu-zo>iB;O#aCXL{T?J zNi+)bS-jJSnY4HkI0Jsq54aw>ec=6w9%c4~qQT@deyuYrvnn^ErW=E*6kU7t_kDG( zXi_1D;_yMNn?`j07D=st95MR##)b0{KSZ;I#`_l6N=ac!gbR1fMcCyQ;k|NG<-u7}NB^kT#)iqOBVt(xMjkPyY6T?d>OGFyB}9jL!_cb2Wy<X>lEW83L-B9FJ% z@igjkbT1Wr&W=&UBVV=dwz&H!Mgo3J^CLs;q4s@vI@nYvyVC1R)P|$&8SE4A->AF% zTo&;UvzpCzDqyDSa7`@v;do@J8sD8*q}=rfeo#DiR{F)&(Z3H*nV8_YR$&VVZvls( z_jc+3M!DQxqHCGa--&&$@p$arka_F>`tZ#&*;lvHZes{&YFl>}z^{IJwo?AC@wK=M zE0`hK$%Nd)<*2_7H}h0j{wpKFQsHZ!v{CV9j;Oqqx%HaDsK21=KkgYEhn0NqTRc}z zbgh-k%rAJ=yzbixz%DE^$9HueBiXr0?THyb#q6?zx|m38MoY;kOJqM(Ig%{<`TmH? z8^yQXa=w60=2ObVy(bYwGdJh!ko_FTUuk21{vze2e-1l`Z5j&|0lNVFOfPpebu%yFs1!L8-pe>B!F}W|!i)Q_V z2K;dSoCm|pj>6-gdlgEu!`i|{Dj7b2Wov-@tbwV^uz|`Y$s1IFQJzBNEu=>RH$Q`0N_(o zwMJ6eg7y2v7eg3D^hGKxMJdqHEvF|~^4`$tS*98*FYBISdodX)OTuIJ)nz-Bop502 z?ORC^4y?1Y7{uf%678TI(!Eu~7K~M?73JPzW-s_m~;IHxfH4kC) zl{g!xXSiH!`Kn_DR3ZRFGjTZCs!^@N)xpJj$#y8;Uf}t9zyDL27bJ~ycd^&h`D=7G z*JE?H9XRBit)7JiJ;5+%ZFMD+fOf&+WPozj;|48qYpLkEV@Y0v`?tr99?5Ke(B`ey}A9N-#U`>92=Ho^KI%p^+d13t1C7%EWnJM zf33x6FC5i)zw&ukGd%_vV_ARP`oj`#GV#wjOtyDDqwb<2qQ28NmNUrN0st)guPTgT z>GklP6{QX1{@HHpw=cq1-KZGsv9|S;sO}%%_V4URt_gC%Dv9W4 z=CWqJZ@A;$&&Fuf&`Z1cFyH zDeV*Mv^u;{4lb@$dQ}hktq2S{t!?HD_P?vdUs>#MD2e!e-$&n0*?sP+`5Dy_pS<2y zpsH|zDa#$X=E>|;k?36syJ`H8`<61%_xr8B1It|6xq5XLcX>;J(vdI5@!6^r-6{Sb z5-^Dil`5_|KL#vGsGE8!6nGga79OtbWgEE|&TE<*$vy_EixoOz2qO zk6v$ko*Wz;9h$q1$q$3FlPsT}lEPk>nwLBeJtZZXJp3&G{eI&#Mu#z8YO2C7eyg3X zP@#r{^L|}>cSh+|wM1oZ$Xe(lQq$*lcbMNhF8C_%s5ndl`l>s9@!i*LWr#|7{`s!j zH0bN(BugaV_y5}FvgFT8Pe-TWbF;9~)0<6RY-Bt#fN0&N{Sv8O2%=i`>HHFX`N{Do1bKGiyBxs>k{y+5Q|X~|!4}!IrnsU&5^0lUZb%3LV{E72 zW5|?bxJbbkg)C#08ZPFuMuY18vzc59TSnp=^^1E6hJyI6W)!Q9PW@8I+^Up8d+OcG zb1<4nI2R|j#M3l6G$tV2aL&0*d}hOxEsM2#b3OONsKV4KH4Xq_Y;1S>j;@)OF@K7+ zdz?L@h6~=n*b-DaQibP1zS!-c7PYGPK8is5ESL%Yymt ziKJT1Lle&++|YAwm!~s1emFU8GN#|66}taHdr1 z<-O!;$1UAv0s&qZHx|O{3eP2Er%tz-<8+Z|uY5!@ z;%KIR@TwDYu!(x&mnbEgP`!4fk`)KeXACYXk8p#-TqgC#Krx{*HzOug+Xm!+C@3OA z`sW@fLPKPtk`rXb;x>M)BUw>Vm?6!aUq=-RCNn#PVyt_7e)$kqVA^uRK$4 z*Y}yuWtn6_0R>(TBVaR}_^&-&`N5D-1ViK9lWU>^_U-XbJNJ#))ocEQ?@TNMLPBmO z)S7iLgLQZ5laHaMI5N)eKVXfqgyV!i!&#hde&IM21G;T_LbqSC;>*+KWR9I83{s$j-@mWQ>VBR|&oKjm zaOcxiZ{Gz2GFfs9c?5Pp70p5AY7j|`$q_thTPlN1fnkkaQ6!m^{b`0%tW;2qP>i&P z3X=q&W(J?400x0;m z^>c|kBUI=BXi%eFb}Yloyz^MB>++q=baj1!cs7rx$sG$UkR?G|u8!$Rd_%Q&`EbTB z1BMMxOGre^4H|)*ZdA;ilK>KbsQLau+}HF6l`7P|3{wwdxXR#)#CqqlL>1~_(paVUx^Kn0t1Up3-U^h+0CG##+ zZa5zAJtol=7|gHoc83i~bM1Blx^on4U*q|eoL;Nu8z<*lkJvB}sqH07rr-TjfjQ|{ z>Puw16{%ZB{J#3Sm{nf;N4J~o`gopts&qtT`yB0?8OF87V_rv&r;bQG6jII3kE&-` ze0bL^t0rR)#;;bcKT&?3bdN$4_i@;-(Foj$m;a>QJUuOi=JnIPCmzS~+>XdbCgds9 z-(FH}t$aqdFDb@7fmFE#G|>L*@+~>wRd*FS+|^YY|H)ymgP&*!#LItnf+ymul}}t! zHPG5AXfLDwiqEe@XZ4#!m_*YYDbo`tOli{u$Dt@1# zsCKSA6}e2SK)APKwnlwLlcP($>M#ST4U2XnO$q5#aIMT4Apupn-RJknw`Tqb@2#6> z+GgDf)vEj|aN}z<=VTC&lX0gihKg}l2ND@_Nbgx^z~Sb~SL_^T!79WZa+jXJqzghx zjK_J`9Q`Pj4V!cj{c+tZ3tJYq(j=Y`!r2;s15ekB^#%inbzRL>DEl+pR-4C4HP8Uw zcF|s?qz%k`t97qmz937u;u|{l{kv$*q{Zbfpm)j;0cnOBq9mAojxzb>+xEgB1R@#h zREtGXt~oCC9c**8TGJT*E=pGK@k$Q+o2lw0%E}aMgFQSdttd9o#s={IIHL_G1>&EH$b24vu;nM$L}rG7<4x zTa)W7l@g*zUsUq5Ofob9MjQxqqbu$H z*PVI{L`xwW7%o4{08xQFstRVg+O3lk3CN{P9x1CMfsAtSAy@@`d7I!&2NGf{{vznh z%+!$*TM>ccbA9DF!B1Y=u;1RH+0}?ZO%b^Ga&nn9#QSSPATK%47n6_jN8+bIZu-OF zqU(4sIaD0Iyvh>ZQBq0EKQp|{mRCoHekcJz9wja3w$)rsu~&}Y#pY6o7@Cw=kIUuC zVgjaB^4}5i5Gh@=r7G)veG}&03KiPJa^F#(P^GB)iL4HVVk35UO4+-6Fe>bJ;g}|`#U{Lts8S!F_Bay+gChUT{LA398{~No zR)eRZ-+sURn`OYvzWG*meg8!YP8IPk`I;|?xW`E6W}LR!C=xC>B=vH$1)8g#k^EFd zaD9W1nd`S;+P-I~q0Cowk+D^8&b8y+t0E#BZUIrje^)+*%>QDce%;{l{_9VJe5K)>2qu}p#&lp2nUhxl!-KRt z48@T&QPV)c%s*x5GUz8PY@OdelA5(8RC?X8{ zT|O@lmjF>ivy&M}dpcRHFOkc#(q%35)C24r0q;B;=j?l)1if1T;sdVK+PYebCZ6B_ z?FE%gTw`_AII6R=6Of8l3gE{rnf$9YBpB3O6-yi6>yN|+`kCpYl$S42jumQEZx7qZ z%S55Dup}lMzrVwtMUaeCWc0DnktCt~Vfx&=W6nn$yyNuf4XKpILrp`mbR=`-3S`dn zgeQdvk_HQeaCje?LhHV$QU#iz`Bv zIK1QJ2_+tL@+Lt|qtO3NB;2G#hvEI=AiMNPNeWWSvogJFhW)TU=PJbeP2B)oey7=gV^;DJE z7mCO_G@^;LW)@|8Ki9#W-4Tu>=3Lds@e03-iuHOkg|a`*2}aIKBa6=b_-?l96$Btq zoJ_~RqeT|eBEnXmGC@n}(gOH;C%E_(Up`&xD^9|@as zJl|Mf6S<_NEfE~PApg?!`rDJv-FmLmJFBj!(vLP?>FH*(sH*!ceA0x5-D)P!P!-dj z(ZTlH&SiI+QIzAv$~>BZVtAKZsb{M2r{BXh!8U7YjM(qD0nl;Dk4}@nX4XuDfS|Mg zHj!`8KE61j_PYF@F9YZZkx2@HGuisbi@%OfRhm>B$BQjdw^LqdQ1a!yn{1ys<_lab zka~K0*6g$b`xC?5)*_`F!d>G)3?xSzXM*yd(i8$^L;Ga$7wq)fxOg<>0mSiQKXeWf zXfR#!*0rs^rAEU=PEO7>G#TxKJ>~om+C3JcH=bEc!H>trwDp(2GpG5eGJN_VJ`W`S7@EjmdeolK#1> zvR}N+VkDEJa($(WlHW&)pR2BXd;`}~yk0dOF)~zDSst4S?)g9eK01Bklet!V$W2dd-gd|Aik_J6+Ml;Vf2sf;8+t4=?&^1 z?M@MXiie|+?o4aMG+s+`%qY1IyQ9El)Z0B&k@$g5^=`kjMJy38HA$L*4GZpezI|r5 zSB;BCW5jm>nN9VFq9i@;I!Xvum)+6A8DAAXm@MU7?!68@4})|z|JhvDCrdac8CZLZ z4i5jCxVc$1vtZu|E>jk)O;g^~MGFhJUdkPK5Cjw$@rIkD?d`f1u6Hp{*Aty-1`8-Q zQM{hVyQPesBq&s%=(Zax?Ey^T2xd3M2xIdxyqO|3YF8455NeWGGI#t}JbPU(vHm=- zm@Yf1dnHR&(B=^_Jr4se|1aN>vTT9>Y_OBJv1u66b{65w~ z`%(f}3@x(M!x7yrPZx=p%Xg|Yr)Fn!m)G*%YqB1i1r3yS9#tAsX>Zr_zN=qfxyr0% zgKw>rC&x3~=5n4WMAS}XOzsCvBg(U|e0bLsd)O;>xZGZezAY`pYc5|e$N$!-y|WYy z)+>6c&(`h4#6-uw-w}5436a92Sf|?sgr&|f|B8C$u1K#Yp@KrIv>NNwQ{6`8R=#3s zC<<@j;}jYs*sXhB>s4+;CIZnxGO+~MPK$?bZ7N5k-VoLQg&h7x)l zZTA+WqIkF~V>SIYYKg%Tvn`zjR_N;Rrq@$HIDbJ>5FylS%XPV<-8=bx-7($6JA_LV zBh^gJtsymBrR)z26JmwQ60;xa4Qnw?q~itn=c7|o{A4_5p6D^von^^(r`uD`!|~p= zD#TRFNfKzqq;{g{bH$Wy|*Wc;=(@)+tIhQvJWG0!;f>=cwN-l;-+T{z3~@LkC<(fOY)htW1&S33tF(35@@I&Mw3|N z4CRK|u(mR~Sd*rKMBE`Rb%_24;ZjFc@Jz?r--zy#T@=%Zn$OQhU40W*y z9>}2~9Rk8p&T;Nw4FH3{xhsvqTSW~0SI*c{mLglyDUMs*A4NbUE>|uc8QG@EkfdR9 z6EhO*Xc?td=UWCdmi2)&1%!jYonNHHjCIPXMK{y%~cB&#Zb=5$BmdC@Znp9;XPW{6(~Tlz3FgeG0522 zmtz1rSSU|T;~%V{@cm#Of~uC73f(RgwdLjFg{wCYKScH(Cdn|Zjed#q()*P!%?K5A z(|tF=D-eLMx?kUVC|6ET1$gUuStnWL^HkwKD&*qo ziGV->F3&Mp`nvC6A-u91y{Wu;(^7U-sqmgNS8& zi>qT`slY}{CH*C>-s$_kfNpnRUMU3Lw`uyLUGt1qNVeTLy3x@!z z*YQtiYQJ!{M@Wr@+$VQl)o3*B8C4ATYHJemYe{NE`=6My=^%(y;&UVNmUZf=wrB`N z`LewMDVSAnv7opd&$|U>Zq9WFnDUG4Z_mf+iq-94@$4qCZ{Tl1H|ow(4{~`)5(*+JME0aeMK9CCSvIQfY!+R{u@;B;*n z5XfexI%xOQ)w^?<|L%kjPeCZ}Y>MnH+5R3ztnv7$0EYcm4p%KtfhxmM1q7P@@_e^? zH>a7nEx`D3XWvw#!@F>-K5Z<@ROw9 z@EO&ZDX{%8&U-K0KUER5;n*IxuEa|_UE)!X06soq`afi;rf=OZn5djezo*t#-uU0g~b3A@n<|uKE{kab}X~)^*g2c)dE^UN9@TW z=906ON^a~TG<7hN&oB1TZZB~tl%sqeeiwW9gRcVQhY0CPN+2N}9fEI|IWh>V)68-C zpkSGMJ^o0&wE5%RMmlnM?hDB(c95aT{;!eUZK6yw!i0_c@rhOA9DQt`f~TNyWRL!c z0toZ~CxL8N;IkD!j2wlVcDKxFH2q43-ph}IfRM}4upE_#>TE7}`+G>wJm!q~iPGH; z^B}%dN4zNK?&4w!Av?v1P&sYd{Z*yzu>DhI7=59`NntAyau(OVn7I?v!_CZ>#PyYG zJ1CM*h(U$ikBn1G_^?(`&b2I-zX9|Ryma4tIW1LdaGT=zszjXI;qo1Mom1^JoA{#w z%J1N_Z!c-{AO+B$vTia+=hp;DReME-Ii02p zht;&j^r90P3vmT)X@yw7iSy%q!4*kC{DKB2%+LhshrzgrJh*ttY^CB`3j>m8s6emF zH=fsztyy8WB#&)LdQj*@8S?|`t1rEU@&-F$ME3vuFVELo1&xw!1#8?_+SAGrT&y#6b~OhrxrYF7(>m zlo#x~I^%xka5=q|hYcL5!pFMM^p<98w9%g|XHha@-4Sq}fB&@o!Y&m{r$9VT9-Hm{ zoA>DVFIFXkKQW#5cXs$Em$FhdxrLMNeqHYC_Y_#QF1^jhaK#>cIP}lQaUA2w1sTTngrgZ>f8Y&^-w3Yj=q~bLrxBx{s1`pRyj%O4^%$1Yq zlk^|iRY&I9;$SDc!2E^qVS`^My?9WKkK~j-alnFvbcOo*$`A;vo93GvKBbW=>siSB z87pZcjtF#5`EbjSe}m-hFr5j<^mRZe_HY+e+6c8x_>&dO*ofvjHv}ZYVY%@T{C2O% zP8L!^-iicLbX?8$W5CTz7cI$7ksN@9X`K1T@>zR3Zf@bb}T6-q|=)4lR% z+g=CAbolx_)avZuFOmcl!*rue*W~e5+PF4O(WQ2rhM)`Gp$^f62=v9Xfw~WoM%$(d zpF85oCic-e}sWq+4M|@4puNTD;_p+;v%4bpArURVqxiZdbt9*9E7R!hc4MXu2#T) zHfB&#iyIdKz>2x_h|bauWUekPZ2@$iM{^b0TC3zNQG|kinfX+)sa+)K7r>YNYbD@3 zbV|9nKp4X2aB!dl0L7#zi2V`(=K=QS?-2_Zc2mD4cf~WC)DWc5NLN=6tf4?&cPF^0 zsE+D8?d`I88&RkDV&&sOYyr1~POtEan zMdfN4A5fB!2XufC;)3vd_PX3Sf)6Li{O3ut&x!R^h z5#h;VAR{B==58%QRPDp^y*Zdl`J0eH&ipwsGxOwfE`S^&`2OOoq?90%ckxj7W4lG) z|CJp$92Q9}f&9>=ZSRC7IL>ws=SQ+!%VTBvCLiw{Ah0Z}UhaA~Ym{_~H;-u5e$)?||?gYn3fj}jN2Ak3E zaMZ_Wwz1xBp989bR^X!CcBvMgs&U8e|MD==BJI6B(APq>zjdjc3e$YS4I-&PBx0|N z4g8Z&oQCL0DVOC;Dz-rAoBzRABea-GDnYblF3oK(mX=~Z;GZ1zQF{&+=|SLhH3@B)-bTFbPy#wyLQUStAT}qAoIW5s^x?8bGd%|x zUg;}zV%sfvs_bV*jBoD1Y1Jmb1zp=yuf6{dJ6>lHs7OuF;jaM^VkG&LRT}YHllKP@30IN!dHT*cAr_p^EH9yv+FLxSJ!V{680ff%W|36R)U{~Xtvv2j{ou`u_1_r*JrR!WJ@wKJvQ3q zU=Zye7g@D@)BQk{&12B_`qukhq#yt#6on;j@)W}JHI$S@q$WOq0)v7e?*C5RqJGJhIMYv&LueQn z>;V09?{ldf`doStY!76nAsDE>i!+ROV^Hg~r55P38n-nZb89%8{YGa~*V0+I;zK}? z{9ZeOmqUEoZrZi>eO63a2x<3Im3q!%o1kQcm07<6TF6*8vP{nVN0mdIJ~;O-^HXic zP>+g}y_d%s09q}<`1i=D*nV3NXk4KE1z!$}^&8;4+?3dCP4F37z1&7a3XR?czq^Z!{;vVTD&`J$4BydeEN$~UfU^Pc()~%C|+(+PI`V*kC4-@6f*}e zzCkxK)OWv7d4!VR{lOL=Tld9wd*EDDkqv*eZq(+JBQx80!y)rlcGqzJMu*SU(5SR} z3bzHK^zzAGIN|o1udA?1z=Rpyn?wJfEWw?FTP^ZSOsvhHoC|We^Ur5ySS(n2i!F{p z#1Z)h@}m>yDA2i6}PB5ux!IBwmL?-6ZzVat?`Md7D zZ$HkftIPdZ(Q^BMxG;zrZ4B!=U=XW|XCIXab99+@p}X_q`hz7;Cuhn7OQP>t!W^r_ zy>&Vc4qZg3y1q{Cjr}*QW4Flf(I=NvOPst-@GuxWkG)OiSpK3Fof>#)RTWF0y>>cN z&ESsNWH*s)X!tnICr)b9+`KTQ6*0s`6n|~LiJjB^b<-Za9;TWO_jwA0MCBK;F-N*j{FPOKky!RwxFqkCj*PPY(=qLghECg<~A^b0J zv7)>jc(Q=e)1U+Dh5;OGEUb^Pu<@)^81Rw(N_u*P1Oz8-5~(w$WT6UbJ!%yf!GGgw z)i&d+w8X?kMa3irHu9$yA@!bE_NfheZdGBM``rG-?-v=Fi_0mMH zh#WGIaMLd@Yq8v>DsmJIU9X%V8n(*D!v0v2N&5XkPg<#$QB><_qbG>S=K_lPdJSpF zY{L5_d&1sU&|=ra*>vhC_3QZhg?+a3iN@RC2X1K^8@Y^Dmr;CVSzqJM-ourvyRqzo zoH7R|(XnN;Y278DLZQ>|dPxz)_Sk=XWh@a8SlHTN9>5`i>~#6ro1HrDAT7yLonsqQfJR7bv(+mm0UZ&Qku&3Zub(TWn>xU$J)M8lnV4DEC0zi zbx=7xF7B7a5Hb0_8VY03M#$aaa_xwUS0`e_uEo2ag$Yn+`L`vJtv2LY=_)2n&&;IK zYk!?>7@$WLdrLj%4E~&9Qqv_IOzyax9`b9L?A@88cOnwny!&DQ-nX5yYRO+pWZE8X zz8U}K;&Fxa6Ul_3fWMEr)VrZrCh_XgPm~lqiLq&_ zScOAo;^k6Ih$BzIHf78awEBJ1Zx%LVIr?Re(Q1Lf=+qH=O$?y~qA;&tJkd zK)xKUT4n8`jfqMpMF@5m0wOYRx~{OE(wZfA)A9J!;$?Ew^cK$VXG z55JP57uFk}no0={B!>hNV_;xh@ST@im^W$x?0ukW_Vn}w&evlwG&+h7IA#j2zml6A ziGhLNjl^b*$RBcCNv2hoR2kYCPUMaOW{@46EA;IB8of@M)jgA)d|8<=Ed8 zT)rxo>fI2T|Lrl~7cE^zv88-x#F|k?@N#Ay$+wSoR4wX!p>dH#&>-p*Gj&bt`Zeml zODZZd7^IN&mBDamnYPL-r8rJO&&rrLA%y1Q3NeG@zR0a4GD8xJ{8In)U)A~LLjl>d z7d4KM;`gepR0eAah>Y3n~D*w7?aF{k!XzsPyIA5E@ve=$9nWpUHo#EzX=W1SQb#~z$kJ-N6SUl|HsAU^?X9E_;zS0XX7CG+>$O(s zmuQ5BVieisuvr{NBAj&56;p-vLmS)*Kv&#EoO9UCN%P=wdh)o6m)Xs6R*kZv`L0~Dw^K5fi&Q4Q1HQTt|;Gqg%0}HON`xpa%(zM7qwxUD2#quVYnK&hTe{)3JLUOEJ zsf=9Bx>HX+3W_Fq#Da}9*vQDpBikGYa3hjV5dCV;qOMh?26O`dmY1KK1{hgg5M>()huK%KV&MUS|0!O0pUT(nNILDXK(T}6d_SqwA_vC+kndCcGwC}z6}*Cm zkK1B>?3fPEL3@?%(`P~+n_2$Owiv?ICTcWw!>D*-o#EkA{#Q)bXkT0r9Gqo$FFIJz z0kefnhAjFZ64BCEAou3&gG4mW5-+>z)QvR_>6e6&_cjgY=R=&-cc@^Ou$}LxiB#YK zcZKOrT@?UdLq%UNv#)t08;m-d=2tCKU^Ca!0&ZxG9lT^(B`sa-1hv8#&m?kV$O&iu z>tN10r;$ZQFk#RWG6Db9TJ{HJ%m}lgKS1obQky&b>5?fM@3wL%c`g1q5qpQM$UT(r zQ!F8S>RmFiT-Tm(JXzw|8Geq_N`$DhR>m@ncZ`u$R&)2}fKvd;f@l+E}NICio zCJ2xN4OOCJV8D<7{@1{i%NezXB{pTkA|@sVd@7r>s#43y$iThZ=4st~PtQGrcT|U(`o9vCcQ4E&YuiRX~>X?y{F`tSSBjPDugiTgL zTzr0AfKt2lYa*mfB_UCRE`?{%fx!Hi22Q9j7^vey4PAJ$#?1<-q{>v_19RuB0MJ58 zN(!*DR!~6sg@lIC)VoRCW%;=`4)G*32&J5YVPHXaMixC*2V0Vr+Bd9`3Xf1yPU2k51V(r$hGIOdC~k8Auc_XfD!&2MoZ#+HJT1R&Bogqc1E|@ z3-0&pHQakdZ;u{pPt_DNhWJQkO2w$qt}c{L!qxz4Ux$@DUx_tMzLMxb-Zty)7C-(R zU-t^xq;v_%WbtU`f$*!V*tMqpi*yS4{<0ALdz&wUwf8T{_*EVM_~>D&gl5=Ga3G=} zCgcgdChO7i&DCvqhL@|Yn=mE7tb?Wf;LN1B1vP<6fYb6%I4W5irR&M8wMpAQuhlT? z-diiMfy)4T`|5mfWf3nqberW4=Cs4as(3NwO708MzySfP8=&T zq}Y-)j~oK*Y;zeURlf&XG%n@l5|g?Cpjl0gy`!U}m{`cL38@;?)-cdS)8?O-tCVm2 zw;6Qm)hJK_wGPl0e1L|wb8mzLsY)Yfm>l^rP(vR89Wk{mc4?Vx9%qTt|dp_6-<4KAsk2e{} zU|$m@(&_Cvhs#*6^MC-`j1@;RM&V>S^L~c61pgX$Def3kz}-D^;T7!{u(44^A6Rol zicuptn|bqRHxbozgY1{Pg8)PHFB}zlZ1%%}gB*md`;BmLzxN`vpfCbtO0jEqHTuA| z(b6;`yNioOR=R_=0q9}(o|J_#UJiE$aOO*6#a9U@Kb1?)@R;qSQge%&ySDyR`T%{J z3UkR@XX+`J!M_Je@u(cLX06Xf>gF<8SG(cASQE+8jkUl3LCRP)bo>~46v^=B$D&Wb zYGk5x9^Wxz$Cl)Can*Zn`)IUWXPzzzRix?mSbW+^>QfFsDU;1cRz3Lp?Q#>4jhYU3 zoyQ>I2yXuHj4a_F&X65g?^@@xJlY=i&yqp9xBO!Ug;Auy&tb19W%T^udMu#Xdcj$~ z`p>(qK8^)zpMck~Y(3oYRjUyjHrtu!s>Zat?x^6dD)qS)@vg6aa8;*r%7Oq1P7!|f zI|`bwO2HJ$!Y**9wXfFnMU0B;XgIE~$U9?c-#abiLOhwV}@lbol+ z)LF7TY1FA(ySTEhK$r=tBR3N-0aErpNpM$J7f=TSQ3$uau)1wf!3q^~02Yq2&jLI+ zySuO}r9}NZZ*#VJ3bRevzbXUGa3bU)D$WBw+8 z(!xtKRwF5mOev;3Pu8DZ9D~#=HQp{ZvO`atKdpW&PkPf$@VSPs`>~pPH3IP!!Uyx~ z2or!d@KZPTq123V_xg6`TVw|f7@6sdiLv%f-=Cc>i)e^SXiAfW3n%L zRL$513a)f=I8WNvx9_rIN}P-X@VV2l87u*HtGcWg&wcG2LKi6zDvBXy-Eq@XwR9tC zWzD3Op^W$uR9mSZJMo>!r)Bhy>Y$qAT{-f)=EI+3{F6YByS@c`+r{%Z6i`Fz8Y3M` zmu#WGWpdSFNFSR0s^`J}{HLHmmxzX$=M>u&V{B0nZgjJ}$FbZmMW|hIUaORWKVVbc zm*L#QxFrFFy5jE3dF{t!v*7Par7;;F%in&reppb8=c$j zr-g+xUJ^;kt#S_khrQHyZdy{&dMTprfWkuZ2+n10sP$LQDh`lUgPuTFmzVF*wY}d? zM&tP^V!Kn#ZZeh`jx>uDJOc9oe9?&Xe!;@==OS1RO8L2P(XR$*z1!)E;XjgXire(V zPNEXxUbnW4@~PBSRb5Y)lKb`&UUe7x#J>tw%;DkVYokMHzp5@b*$#(Q>-2*_>CtQ6 zU$?i4MwN?Y9v}B}-e0aKA&FmYS6VJ(1>XQ_{WH){G3s@sWv2kfI`Yh)qfzrMmnJ7C z*Z;RQ;>+ILPERX!>LG&+H0Rl?+K?P@hku;AsHvrpL)O;T2nI2+u@gN?j;j!WwSvdT z$FpuLw!onUUHk;PFKof%iK;-eV?pD09YQI%_MS1NQ2Q2y%swck5zFkHQC%F8e>}4mnG|9T(xooZ=D6e)>OogUCQVN~Y zasQU1t(VhcA*-fn3GrLH!Y;Ob9PcoB0>775BT%|}U;o6-K+Y^>`sp+s!>CtRews$f z`_Vchf0(53Jg2LclI!~4j%V1U`Ohd*xaOMd+v&aMy-u97eSV`q1(X7QerLx-SZa9E z@GP7)>96Ku7Y&3}=|wKYpg6+Y1HQdK*`E^ka>i(=7`vLBucd4JJS?s!TzjmAa+h$@XJ23O;)-EXEKILyzui!F z|4ixP(C@ALcJBW&W*%wIsF`YCN<%%gbTtu`gWzL!6JZmPkAy>}xM8bSv1r3E0`c~L zOw@nh^*HQb^h$QxXeqPg)z4|%dCi=TxZ27br!9GsfJ$l z>eqPs+-1zuO60)V4W=yz1mESXgqGSmh zFM6_%u>>=ob|vN?<1y&1>;)!r|#6kKZU4X5gB;c-75_NhJXQK#oBm1~4Rmy2-N zJkzbkzTFzBx$HyftvvQV-|I|tXsPMx#kt?E&YiQKD)WXMK}6%m%>Z;zy+#l5(*@eTTa>u5rKKfMo(#7Fs3cWHK2vphxl+ZP ztBdj#oa_uxs{oU(=x1RRt{7*_F$}SI)iDJ21PjDB#%lX|KnIWUFsKWl!-v$QqVr^0- z78Hem;>F;?vo0EnGFn{h90LUVuY#(QtjG*Hwoea1A@ydSVa<9sd(V(~VU)nyK5FS~ z7aMQeJWR`TPou*d$Fk3|VG^#A%w-y2Pyl>QTsF1t?8sN0zaU9(xF*Pvg`v*r$HU)4 zggLhB5B=)T`ad}{N)8StIt7>S9NL)#B{x4^3rvgoUvA$YBipbruL<)HGHCD~LhY`m zX@LUXgi&A7xE3-%AQh|L_4m6W^<}pczvup2tR6-hyF&^67}-;~Z~p{LAJ(!mx>nsS z&KjtN@_ty(xE>G2KGCEVA1H%zMK)JispDNc-$4%{{r2mP+mSVHHLnYN_<=oD#`89h zHj+t1!3u!+PS1dCyW5%9bI~IbQkZz7xA_bu|CSc}AqXCHbBlbQ`Y+zi`gdvYl;F$q zex&ZRem1MFfeLdL&-v1|no=!iFjLd$hJDvc!~Sy6b#|H*^U*;XQU)jAQAueA;Q<5q zqoIOEhTXx*>~JC!NazrAhT|+!w}t}FdxkA4;{5qGRl95T{bv@iq$(#GA^?Se- zuCRJP&W1HM|J>Vkg9vgaY74aOp?!2x{^tQiIP4?V` zsm@g;iMpIOnJ+PDsj(!bNUr`-go>Ozn5qZIxJvDKq_t43Vz{{Gd3Q*ybkT<6rwn-_ zh9c+im=()Upyq%THqhjtq#Rsd*RNT~koj6LRSHxyR_xr)K>ulCLhfke_9%(&z#O;w4Cg~hU<(K>P{gyC~kJUn<3a>6AOwXYIR1SKKeC$v?ZEqSIf#Q zFC)5IiTW@(z5@(_eW2Mog3%`p7F9$ML-Pue+`#7kNb&>Qqil03-5rC-M;9k%Urf=Z zyOjI~-{hr;tHM_iNfa2g_9&Eu!Xx~a)lqhU+Dk&NYhUCA?JSp#-M7>n6-N%{8*~i( zOT37OL!{%|&Hnx3OfrG$f?&{5}M>11b5BxrFdrJv0bf1%9oeVr_IdvN#x$Kg35xwl#XQbW=tZPK#SEJ?cg}73%gicG_mjd+}Zp6 z%QzJd!1-4Pi5ATBso>dl)%K&UWn?O}eJ*7CsDM~7YHDFH;0DwE{>EBzsL{ZF>@u^f~Idx!nNE`;<|jJ`Gy45BW(7T}>th>Fhr zKvqLXc9LYJQ6;M%N)YR@rAGvTWMtQ-cm#vlH(hY_C#wUQi>ZFcDeQgJAEv;`+uUkJ zQ0{zjdgcek8RkAySlJT_;jN^kamL-Hz%A(Pe5~4^4>;3@O7F_9-cL!j@c6$iW(;_{ zG30pygTh-esmR-lzWO`ebDGyC6B*6+{rU1~IX$Nh7x@|g{T$9K{%PA1Rt5ue5urn` zPsP|O#x^?e<{z+fx))`@ans6iQR$I_=^wt8Hs7AW!qB!-xF%-%*1Xpr^R^i1Wv8rt zzEkZe)6Wfp{o8*Z?5(&G`?&vgyMR+yiLdQMspUs@+TZ?P;^X1L@$>NM)2qFw>#Ym# z*VuQYb;rN+qFk=P`sU=B(Erho?u9a`!+95ZC4R+^G(OZ8FOyNsS6D!|n(71Oo# zxx*P4n3jX?2vBVK^Y?G`q1W;9J%zx5{3xgCrs{jEzV3RR&9~Gm)cd}_53o>IYMHQX zp#q1v{@k5wFAFleK0dT$R->3+Ty4hz-G`d$f$X}Dlm4&s%Q<;zo6OA<=VH8Pe2Y=L zCiZECa!b^*MK_Cft+|=8C_3-{K4;nJEpwMCx(P5GyIZ=uaZAhhpK4nQKEAqK#FEG9 zEVS_H7Ek94uqiRWzsM~Ia=Wvp{o0apb5@7iuGD$!W#!Kl`gJj_X=)YVa@xEsd zW#Yu2^{mHs_^tEum}BaZ()*lcGDK9KJvqjke_1A*Q$v8UXwC$vTJO6zR9c(Xo^<1V zwZrE$@T?~wxa0cj)j^%pK_UXKAKR`frKW(vJ29TKSH5<$E!fqy;qE=5=|iXBS8yUPwUFbGU~o&cQWk(8XdjENy2n=edD z#N_M+lO-Bl43@s_V8eZa1I^vpPj6xf5nnm|?;@z#eA7a&%xae9TW<6D6xd@X%%!;( zC#fXxFidz1bAZ_Ft3l?PCWj4 zveYLEz`5o_lYsXhUdu3T)`Vqu%JDF$PWPJx4&zL#jJCCpC#wQy zj0{X#F1&nVqdo%~A{Ju1*8;O4hobLgp2HrK<}7vwo3!j?L&;ss8Ho}t6Yl0sPo4}3 i|5 {}".format(cmd, text[:180])) + +def esp_send_cmd(cmd, timeout=1000, expected=None): + """发送AT命令到ESP8266并等待响应""" + esp_clear_rx() + uart2.write(cmd + "\r\n") + utime.sleep_ms(50) + start = utime.ticks_ms() + response = "" + if expected is None: + expected = ("OK", "ERROR", "FAIL", "ready") + while utime.ticks_diff(utime.ticks_ms(), start) < timeout: + if uart2.any(): + data = uart2.read() + if data: + response += data.decode('utf-8', 'ignore') + if any(token in response for token in expected): + break + utime.sleep_ms(5) + esp_log_response(cmd, response) + return response + +def esp_probe_uart(): + """探测ESP8266实际AT波特率""" + print("[ESP] Probing UART baud rate...") + for baud in ESP_BAUD_RATES: + print("[ESP] Try baud:", baud) + esp_reopen_uart(baud) + for _ in range(2): + resp = esp_send_cmd("AT", 1500) + if "OK" in resp: + print("[ESP] UART baud detected:", baud) + return True + utime.sleep_ms(300) + esp_reopen_uart(115200) + print("[ESP] No AT response on tested baud rates") + return False + +def esp_wait_boot(): + """等待ESP8266启动完成,避免K210太早发送AT命令""" + print("[ESP] Waiting for module boot...") + start = utime.ticks_ms() + boot_log = "" + while utime.ticks_diff(utime.ticks_ms(), start) < ESP_BOOT_WAIT_MS: + if uart2.any(): + data = uart2.read() + if data: + boot_log += data.decode('utf-8', 'ignore') + utime.sleep_ms(100) + if ESP_DEBUG and boot_log: + print("[ESP] Boot log:", boot_log.replace('\r\n', ' ')[:180]) + esp_clear_rx() + +def esp_check_wifi_status(): + """检查WiFi连接状态(快速检查)""" + resp = esp_send_cmd("AT+CWJAP?", 1500) + return WIFI_SSID in resp + +def esp_connect_wifi(): + """连接WiFi(单次尝试)""" + print("[ESP] Connecting to WiFi:", WIFI_SSID) + + resp = esp_send_cmd("ATE0", 1000) + + resp = esp_send_cmd("AT+CWMODE_CUR=1", 1500) + if "OK" not in resp: + resp = esp_send_cmd("AT+CWMODE=1", 1500) + + if "OK" not in resp and "no change" not in resp: + print("[ESP] Set mode failed") + return False + + if esp_check_wifi_status(): + print("[ESP] WiFi already connected!") + return True + + # 连接WiFi。部分路由器获取IP较慢,等待时间不能太短。 + cmd = 'AT+CWJAP_CUR="{}","{}"'.format(WIFI_SSID, WIFI_PASSWORD) + resp = esp_send_cmd(cmd, 20000, ("WIFI GOT IP", "OK", "FAIL", "ERROR")) + + if "OK" not in resp and "CONNECTED" not in resp and "WIFI GOT IP" not in resp: + cmd = 'AT+CWJAP="{}","{}"'.format(WIFI_SSID, WIFI_PASSWORD) + resp = esp_send_cmd(cmd, 20000, ("WIFI GOT IP", "OK", "FAIL", "ERROR")) + + if "OK" in resp or "CONNECTED" in resp or "WIFI GOT IP" in resp: + utime.sleep_ms(1000) + status = esp_send_cmd("AT+CWJAP?", 1500) + ip = esp_send_cmd("AT+CIFSR", 1500) + if WIFI_SSID not in status and "STAIP" not in ip: + print("[ESP] WiFi command returned OK, but no station IP found") + return False + print("[ESP] WiFi connected!") + return True + + print("[ESP] WiFi connect failed") + return False + +def esp_init_wifi(max_retries=5): + """初始化ESP8266并连接WiFi(减少重试次数)""" + print("[ESP] Initializing...") + esp_wait_boot() + esp_clear_rx() + + # 测试AT响应 + for i in range(max_retries): + resp = esp_send_cmd("AT", 2500) + if "OK" in resp: + print("[ESP] AT OK") + break + print("[ESP] AT retry {}/{}".format(i+1, max_retries)) + utime.sleep_ms(500) + else: + if not esp_probe_uart(): + print("[ESP] ESP8266 not responding!") + return False + + # 连接WiFi + for i in range(max_retries): + if esp_connect_wifi(): + return True + utime.sleep_ms(1000) + + return False + +def esp_ensure_wifi(): + """确保WiFi已连接(快速检查)""" + global wifi_connected + if not wifi_connected: + wifi_connected = esp_init_wifi(1) + return wifi_connected + return wifi_connected + +def ensure_local_photo_dir(): + """确保SD卡本地照片目录存在""" + try: + os.listdir(LOCAL_FACE_PHOTO_DIR) + return True + except: + try: + os.mkdir(LOCAL_FACE_PHOTO_DIR) + print("[PHOTO] Created local dir:", LOCAL_FACE_PHOTO_DIR) + return True + except Exception as e: + print("[PHOTO] Create local dir failed:", e) + return False + +def local_face_photo_path(face_id): + return "{}/{}.jpg".format(LOCAL_FACE_PHOTO_DIR, face_id) + +def save_local_face_photo(face_id, jpeg_data): + """先把人脸照片保存到SD卡,保证本地特征和照片一致""" + if not ensure_local_photo_dir(): + return False + path = local_face_photo_path(face_id) + try: + with open(path, "wb") as f: + f.write(jpeg_data) + print("[PHOTO] Saved local photo:", path) + return True + except Exception as e: + print("[PHOTO] Save local photo failed:", e) + return False + +def load_local_face_photo(face_id): + path = local_face_photo_path(face_id) + try: + with open(path, "rb") as f: + return f.read() + except Exception as e: + print("[PHOTO] Read local photo failed {}: {}".format(path, e)) + return None + +def remove_photo_from_queue(face_id): + global photo_upload_queue + face_id = str(face_id) + photo_upload_queue = [x for x in photo_upload_queue if x != face_id] + +def delete_local_face_photo(face_id): + face_id = str(face_id) + remove_photo_from_queue(face_id) + path = local_face_photo_path(face_id) + try: + os.remove(path) + print("[PHOTO] Deleted local photo:", path) + return True + except: + return False + +def delete_all_local_face_photos(): + if not ensure_local_photo_dir(): + return + try: + for name in os.listdir(LOCAL_FACE_PHOTO_DIR): + if name.endswith(".jpg"): + try: + os.remove("{}/{}".format(LOCAL_FACE_PHOTO_DIR, name)) + except: + pass + photo_upload_queue[:] = [] + print("[PHOTO] Deleted all local face photos") + except Exception as e: + print("[PHOTO] Delete all local photos failed:", e) + +def esp_send_data(data, timeout=1500): + """发送数据并等待SEND OK(优化超时)""" + cmd = "AT+CIPSEND={}".format(len(data)) + uart2.write(cmd + "\r\n") + utime.sleep_ms(50) + + # 等待 > 提示符(缩短超时) + start = utime.ticks_ms() + resp = "" + got_prompt = False + while utime.ticks_diff(utime.ticks_ms(), start) < 1000: + if uart2.any(): + resp += uart2.read().decode('utf-8', 'ignore') + if ">" in resp: + got_prompt = True + break + if "ERROR" in resp or "link is not" in resp: + return False + utime.sleep_ms(5) + + if not got_prompt: + return False + + # 发送数据 + uart2.write(data) + + # 等待 SEND OK(缩短超时) + start = utime.ticks_ms() + resp = "" + while utime.ticks_diff(utime.ticks_ms(), start) < timeout: + if uart2.any(): + resp += uart2.read().decode('utf-8', 'ignore') + if "SEND OK" in resp: + return True + if "SEND FAIL" in resp or "ERROR" in resp: + return False + utime.sleep_ms(10) + + return False + +def esp_http_post_photo(face_id, jpeg_data, max_retries=2): + """通过ESP8266发送HTTP POST请求上传照片""" + # 直接使用face_id作为照片ID(不加时间戳) + print("[ESP] Uploading photo for face ID:", face_id, "size:", len(jpeg_data)) + + for attempt in range(max_retries): + # 确保WiFi连接 + if not esp_ensure_wifi(): + print("[ESP] No WiFi, retry {}/{}".format(attempt+1, max_retries)) + utime.sleep_ms(2000) + continue + + # 关闭之前的连接 + esp_send_cmd("AT+CIPCLOSE", 500) + utime.sleep_ms(100) + + # 设置单连接模式 + esp_send_cmd("AT+CIPMUX=0", 500) + + # 建立TCP连接 + cmd = 'AT+CIPSTART="TCP","{}",{}'.format(SERVER_IP, SERVER_PORT) + resp = esp_send_cmd(cmd, 3000) + if "OK" not in resp and "CONNECT" not in resp: + print("[ESP] TCP failed, retry {}/{}".format(attempt+1, max_retries)) + utime.sleep_ms(1000) + continue + + print("[ESP] TCP connected, sending data...") + + # 使用face_id作为文件名 + http_header = "POST /api/v1/faces/photos/{} HTTP/1.1\r\n".format(face_id) + http_header += "Host: {}:{}\r\n".format(SERVER_IP, SERVER_PORT) + http_header += "Content-Type: image/jpeg\r\n" + http_header += "X-Api-Token: {}\r\n".format(API_TOKEN) + http_header += "Content-Length: {}\r\n".format(len(jpeg_data)) + http_header += "Connection: close\r\n\r\n" + + # 发送HTTP头 + if not esp_send_data(http_header): + print("[ESP] Send header failed") + esp_send_cmd("AT+CIPCLOSE", 500) + continue + + # 分块发送JPEG数据 + CHUNK_SIZE = 1024 + offset = 0 + send_ok = True + + while offset < len(jpeg_data): + chunk = jpeg_data[offset:offset + CHUNK_SIZE] + if not esp_send_data(chunk): + print("[ESP] Send chunk failed at", offset) + send_ok = False + break + offset += CHUNK_SIZE + print("[ESP] Sent {}/{}".format(min(offset, len(jpeg_data)), len(jpeg_data))) + + if not send_ok: + esp_send_cmd("AT+CIPCLOSE", 500) + utime.sleep_ms(500) + continue + + # 等待服务器响应 + print("[ESP] Waiting for response...") + resp = "" + start = utime.ticks_ms() + while utime.ticks_diff(utime.ticks_ms(), start) < 3000: + if uart2.any(): + data = uart2.read() + if data: + resp += data.decode('utf-8', 'ignore') + if "200" in resp or "success" in resp or "HTTP/1.1" in resp: + print("[ESP] Got response!") + break + utime.sleep_ms(50) + + esp_send_cmd("AT+CIPCLOSE", 300) + + # 数据发送成功就算成功 + if send_ok: + print("[ESP] Photo uploaded successfully!") + return True + else: + print("[ESP] Response:", resp[:100] if resp else "(empty)") + print("[ESP] Retry {}/{}".format(attempt+1, max_retries)) + utime.sleep_ms(1000) + + print("[ESP] Upload failed after {} retries".format(max_retries)) + return False + +def capture_and_upload_face(face_id, img): + """拍摄人脸照片并加入上传队列(非阻塞)""" + try: + # 先复制图像,避免修改原图 + img_copy = img.copy() + + # 转换为RGB565格式(如果需要)后压缩为JPEG + try: + jpeg_img = img_copy.compress(quality=50) # 降低质量减小体积 + jpeg_data = jpeg_img.to_bytes() + except Exception as e1: + print("[PHOTO] Compress method 1 failed:", e1) + # 尝试另一种方式 + try: + jpeg_data = img_copy.to_bytes() # 直接尝试转换 + except Exception as e2: + print("[PHOTO] Compress method 2 failed:", e2) + return False + + print("[PHOTO] JPEG size:", len(jpeg_data), "bytes") + + if len(jpeg_data) < 100: + print("[PHOTO] JPEG too small, skip upload") + return False + + # 先保存本地,再加入上传队列(非阻塞)。上传失败也不会丢照片。 + if not save_local_face_photo(face_id, jpeg_data): + return False + + queue_photo_upload(face_id) + print("[PHOTO] Face {} saved locally and queued for upload".format(face_id)) + return True + + except Exception as e: + print("[PHOTO] Error:", e) + return False + +# 初始化WiFi连接(启动时尝试连接) +wifi_connected = False +print("[BOOT] Starting ESP8266 WiFi init...") +try: + wifi_connected = esp_init_wifi() + print("[BOOT] WiFi status:", "connected" if wifi_connected else "not connected") +except Exception as e: + print("[BOOT] ESP8266 init error:", e) + +# --- 人脸ID到真实学号的映射表 --- +face_id_mapping = {} # 格式: {"1": "20210001", "2": "20210002"} +MAPPING_FILE = "/sd/face_mapping.txt" # SD卡上的映射文件 +SYNC_VERSION_FILE = "/sd/sync_version.txt" # 本地已应用的服务端同步版本 +RECORD_PATH = "/sd/recordftr.txt" # 人脸特征记录文件路径 +sync_last_version = 0 + +def load_local_mapping(): + """从SD卡加载本地映射配置""" + global face_id_mapping + face_id_mapping.clear() + try: + with open(MAPPING_FILE, "r") as f: + for line in f: + line = line.strip() + if '=' in line: + parts = line.split('=') + if len(parts) == 2: + face_id_mapping[parts[0]] = parts[1] + print("[LOCAL] Loaded {} mappings from SD".format(len(face_id_mapping))) + except: + print("[LOCAL] No local mapping file") + +def save_local_mapping(): + """保存映射配置到SD卡""" + try: + with open(MAPPING_FILE, "w") as f: + for k, v in face_id_mapping.items(): + f.write("{}={}\n".format(k, v)) + print("[LOCAL] Saved {} mappings to SD".format(len(face_id_mapping))) + return True + except Exception as e: + print("[LOCAL] Save error:", e) + return False + +def load_sync_version(): + """从SD卡加载本地已同步版本""" + global sync_last_version + try: + with open(SYNC_VERSION_FILE, "r") as f: + value = f.read().strip() + sync_last_version = int(value) if value else 0 + except: + sync_last_version = 0 + print("[LOCAL] Sync version:", sync_last_version) + +def save_sync_version(version): + """保存本地已同步版本""" + global sync_last_version + sync_last_version = version + try: + with open(SYNC_VERSION_FILE, "w") as f: + f.write(str(version)) + except Exception as e: + print("[LOCAL] Save sync version error:", e) + +def update_face_record(face_id, new_student_id): + """更新SD卡中人脸记录的学号""" + global face_id_mapping, peoples + + # 更新内存中的映射表 + face_id_mapping[face_id] = new_student_id + save_local_mapping() + + # 先打印当前peoples列表中的名称,用于调试 + print("[UPDATE] 当前peoples列表:") + for i, p in enumerate(peoples): + print("[UPDATE] [{}] {}".format(i, p.name)) + + # 更新 recordftr.txt 中的名称 + try: + new_lines = [] + updated = False + with open(record_path, "r") as f: + for line in f: + parts = line.strip().split('#', 1) + if len(parts) == 2: + name = parts[0] + feature = parts[1] + + # 打印当前处理的记录 + print("[UPDATE] 检查记录: name='{}', face_id='{}'".format(name, face_id)) + + # 检查是否是要更新的ID(支持多种格式匹配) + should_update = False + + # 格式1: ID:X(原始格式)- 匹配 ID:1, ID:2 等 + if name == "ID:{}".format(face_id): + should_update = True + print("[UPDATE] 匹配格式1: ID:X") + + # 格式2: 名称中包含 :X + if ':' in name: + current_id = name.split(':')[1] + if current_id == face_id: + should_update = True + print("[UPDATE] 匹配格式2: :X") + + # 格式3: 直接匹配face_id本身 + if name == face_id: + should_update = True + print("[UPDATE] 匹配格式3: 直接匹配") + + if should_update: + # 更新为新学号 + new_name = new_student_id + new_lines.append(new_name + '#' + feature + '\n') + updated = True + print("[UPDATE] {} -> {}".format(name, new_name)) + continue + + new_lines.append(line) + + if updated: + with open(record_path, "w") as f: + for line in new_lines: + f.write(line) + # 重新加载人脸数据 + load_faces() + print("[UPDATE] Face record updated successfully") + return True + else: + print("[UPDATE] Face ID {} not found in records".format(face_id)) + except Exception as e: + print("[UPDATE] Error:", e) + return False + +def esp_http_get(url_path, timeout=8000): + """发送HTTP GET请求并返回响应内容""" + if not wifi_connected: + print("[HTTP_GET] WiFi未连接") + return None + + print("[HTTP_GET] 关闭旧连接...") + esp_send_cmd("AT+CIPCLOSE", 500) + utime.sleep_ms(300) + esp_send_cmd("AT+CIPMUX=0", 500) + utime.sleep_ms(100) + + # 建立TCP连接 + print("[HTTP_GET] 建立TCP连接: {}:{}".format(SERVER_IP, SERVER_PORT)) + cmd = 'AT+CIPSTART="TCP","{}",{}'.format(SERVER_IP, SERVER_PORT) + resp = esp_send_cmd(cmd, 5000) + print("[HTTP_GET] TCP响应: {}".format(resp.replace('\r\n', ' ')[:80] if resp else "(空)")) + + if "OK" not in resp and "CONNECT" not in resp: + print("[HTTP_GET] TCP连接失败") + return None + + print("[HTTP_GET] TCP连接成功") + utime.sleep_ms(200) + + # 构建HTTP GET请求 + http_request = "GET {} HTTP/1.1\r\nHost: {}:{}\r\nX-Api-Token: {}\r\nConnection: close\r\n\r\n".format( + url_path, SERVER_IP, SERVER_PORT, API_TOKEN) + + # 使用AT+CIPSEND发送 + print("[HTTP_GET] 准备发送 {} bytes".format(len(http_request))) + cmd = "AT+CIPSEND={}".format(len(http_request)) + uart2.write(cmd + "\r\n") + utime.sleep_ms(100) + + # 等待 > 提示符 + start = utime.ticks_ms() + prompt_resp = "" + while utime.ticks_diff(utime.ticks_ms(), start) < 2000: + if uart2.any(): + data = uart2.read() + if data: + prompt_resp += data.decode('utf-8', 'ignore') + if ">" in prompt_resp: + break + utime.sleep_ms(10) + + if ">" not in prompt_resp: + print("[HTTP_GET] 未收到>提示符: {}".format(prompt_resp[:50])) + esp_send_cmd("AT+CIPCLOSE", 300) + return None + + print("[HTTP_GET] 收到>提示符,发送请求...") + + # 发送HTTP请求 + uart2.write(http_request) + + # 等待SEND OK + start = utime.ticks_ms() + send_resp = "" + while utime.ticks_diff(utime.ticks_ms(), start) < 3000: + if uart2.any(): + data = uart2.read() + if data: + send_resp += data.decode('utf-8', 'ignore') + if "SEND OK" in send_resp: + print("[HTTP_GET] SEND OK") + break + utime.sleep_ms(10) + + if "SEND OK" not in send_resp: + print("[HTTP_GET] 发送失败: {}".format(send_resp[:50])) + esp_send_cmd("AT+CIPCLOSE", 300) + return None + + # 等待服务器响应(关键:要等足够长的时间) + print("[HTTP_GET] 等待服务器响应...") + resp = send_resp # 继续累积数据 + start = utime.ticks_ms() + + while utime.ticks_diff(utime.ticks_ms(), start) < timeout: + if uart2.any(): + data = uart2.read() + if data: + try: + resp += data.decode('utf-8', 'ignore') + print("[HTTP_GET] 累积数据: {} bytes".format(len(resp))) + except: + pass + # 检查是否收到完整响应(有JSON且连接关闭) + if "}" in resp and "{" in resp: + if "CLOSED" in resp: + print("[HTTP_GET] 连接已关闭,数据完整") + break + # 继续等一下看有没有更多数据 + utime.sleep_ms(500) + if uart2.any(): + extra = uart2.read() + if extra: + resp += extra.decode('utf-8', 'ignore') + if "CLOSED" in resp or utime.ticks_diff(utime.ticks_ms(), start) > 3000: + break + utime.sleep_ms(30) + + esp_send_cmd("AT+CIPCLOSE", 300) + + print("[HTTP_GET] 原始响应长度: {}".format(len(resp))) + if len(resp) > 0: + print("[HTTP_GET] 响应片段: {}".format(resp[:300].replace('\r\n', '\\n'))) + + # 提取JSON + json_start = resp.find('{"') + if json_start != -1: + json_end = resp.rfind('}') + if json_end != -1 and json_end > json_start: + result = resp[json_start:json_end+1] + print("[HTTP_GET] 提取JSON成功: {}".format(result[:100])) + return result + + print("[HTTP_GET] 未找到JSON") + return None + +def sync_face_id_mapping(): + """从服务器同步人脸ID映射配置并更新本地记录""" + global face_id_mapping + + if not wifi_connected: + print("[SYNC] WiFi not connected, skip sync") + return False + + try: + print("[SYNC] ========== 开始同步映射配置 ==========") + print("[SYNC] 请求: GET /api/v1/faces/mappings") + response = esp_http_get("/api/v1/faces/mappings", 2000) + + if response is None: + print("[SYNC] 服务器无响应") + return False + + print("[SYNC] 收到响应: {}".format(response[:150] if len(response) > 150 else response)) + + # 简单解析JSON + mappings_start = response.find('"mappings":{') + if mappings_start == -1: + print("[SYNC] 响应中无mappings字段") + return False + + mappings_start += len('"mappings":{') + mappings_end = response.find('}', mappings_start) + if mappings_end == -1: + return False + + mappings_str = response[mappings_start:mappings_end] + print("[SYNC] 解析映射字符串: {}".format(mappings_str)) + + # 解析键值对 + server_mappings = {} + parts = mappings_str.split(',') + for part in parts: + part = part.strip() + if ':' in part: + kv = part.split(':') + if len(kv) == 2: + key = kv[0].strip().strip('"') + value = kv[1].strip().strip('"') + if key and value: + server_mappings[key] = value + + print("[SYNC] 服务器映射数量: {}".format(len(server_mappings))) + for k, v in server_mappings.items(): + print("[SYNC] 人脸ID: {} -> 学号: {}".format(k, v)) + + if len(server_mappings) == 0: + print("[SYNC] 服务器无映射配置") + return True + + # 对比本地映射 + print("[SYNC] 本地映射数量: {}".format(len(face_id_mapping))) + for k, v in face_id_mapping.items(): + print("[SYNC] 本地: {} -> {}".format(k, v)) + + # 更新本地人脸记录文件(recordftr.txt) + updated_count = 0 + for face_id, student_id in server_mappings.items(): + print("[SYNC] 检查是否需要更新: ID:{} -> {}".format(face_id, student_id)) + if update_face_record(face_id, student_id): + updated_count += 1 + + # 更新内存中的映射表 + face_id_mapping = server_mappings + save_local_mapping() + + print("[SYNC] ========== 同步完成,更新了 {} 条记录 ==========".format(updated_count)) + return True + + except Exception as e: + print("[SYNC] 同步出错:", e) + return False + return False + +def get_display_name(face_name): + """获取用于显示的名称(直接使用人脸记录中的名称)""" + return face_name + +# 加载本地映射配置 +load_local_mapping() +load_sync_version() + +# 启动时同步将在所有函数定义后执行(见文件末尾) + +# --- 定时同步配置 --- +last_sync_time = utime.ticks_ms() +sync_in_progress = False # 同步状态标志 +sync_step = 0 # 同步步骤(分步执行避免长时间阻塞) + +# --- 远程删除人脸功能 --- +def delete_face_by_id(face_id): + """根据人脸ID删除本地人脸数据""" + global peoples + + # 构建所有可能匹配的模式 + target_patterns = [ + "ID:{}".format(face_id), # 原始格式 ID:5 + face_id # 直接匹配 (可能是学号如 20210001) + ] + + # 如果face_id在映射表中,也添加映射后的学号作为匹配模式 + if face_id in face_id_mapping: + target_patterns.append(face_id_mapping[face_id]) + + # 反向查找:如果face_id是学号,查找对应的原始ID + for orig_id, student_id in face_id_mapping.items(): + if student_id == face_id: + target_patterns.append("ID:{}".format(orig_id)) + target_patterns.append(orig_id) + + print("[DELETE] Looking for patterns:", target_patterns) + + deleted_index = -1 + for i, p in enumerate(peoples): + for pattern in target_patterns: + if p.name == pattern: + deleted_index = i + break + if deleted_index >= 0: + break + + if deleted_index >= 0: + deleted_name = peoples[deleted_index].name + peoples.pop(deleted_index) + try: + with open(record_path, "w") as f: + for p in peoples: + f.write(p.name + '#' + str(p.feature) + "\n") + print("[DELETE] 删除人脸成功: {}".format(deleted_name)) + + # 同时删除本地照片,避免下次启动补传已删除的人脸照片 + delete_local_face_photo(face_id) + if deleted_name.startswith("ID:"): + delete_local_face_photo(deleted_name.split(":", 1)[1]) + else: + delete_local_face_photo(deleted_name) + for pattern in target_patterns: + if pattern.startswith("ID:"): + delete_local_face_photo(pattern.split(":", 1)[1]) + else: + delete_local_face_photo(pattern) + + # 同时删除映射 + if face_id in face_id_mapping: + del face_id_mapping[face_id] + save_local_mapping() + + # 重新加载 + load_faces() + return True + except Exception as e: + print("[DELETE] 重写文件失败:", e) + load_faces() + return False + else: + print("[DELETE] 未找到人脸ID: {}".format(face_id)) + return False + +def esp_http_post_json(url_path, json_data, timeout=2000): + """发送HTTP POST请求(优化版)""" + if not wifi_connected: + return None + + esp_send_cmd("AT+CIPCLOSE", 300) + utime.sleep_ms(50) + esp_send_cmd("AT+CIPMUX=0", 300) + + cmd = 'AT+CIPSTART="TCP","{}",{}'.format(SERVER_IP, SERVER_PORT) + resp = esp_send_cmd(cmd, 2000) + if "OK" not in resp and "CONNECT" not in resp: + return None + + http_request = "POST {} HTTP/1.1\r\nHost: {}:{}\r\nContent-Type: application/json\r\nX-Api-Token: {}\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}".format( + url_path, SERVER_IP, SERVER_PORT, API_TOKEN, len(json_data), json_data) + + if not esp_send_data(http_request, 1500): + esp_send_cmd("AT+CIPCLOSE", 300) + return None + + resp = "" + start = utime.ticks_ms() + while utime.ticks_diff(utime.ticks_ms(), start) < timeout: + if uart2.any(): + data = uart2.read() + if data: + resp += data.decode('utf-8', 'ignore') + if "success" in resp or "}" in resp: + break + utime.sleep_ms(10) + + esp_send_cmd("AT+CIPCLOSE", 300) + return resp + +def sync_pending_delete(): + """从服务器同步待删除的人脸列表""" + if not wifi_connected: + print("[DELETE_SYNC] WiFi未连接,跳过") + return False + + try: + print("[DELETE_SYNC] ========== 开始同步删除列表 ==========") + print("[DELETE_SYNC] 请求: GET /api/v1/faces/pending-delete") + response = esp_http_get("/api/v1/faces/pending-delete", 8000) + + if response is None: + print("[DELETE_SYNC] 服务器无响应") + return False + + print("[DELETE_SYNC] 收到响应: {}".format(response)) + + # 解析JSON + start = response.find('"pending_delete":[') + if start == -1: + print("[DELETE_SYNC] 响应中无pending_delete字段") + return True + + start += len('"pending_delete":[') + end = response.find(']', start) + if end == -1: + return False + + arr_str = response[start:end] + print("[DELETE_SYNC] 待删除列表字符串: '{}'".format(arr_str)) + + if not arr_str.strip(): + print("[DELETE_SYNC] 无待删除的人脸") + return True + + # 解析数组 + ids_to_delete = [] + parts = arr_str.split(',') + for part in parts: + part = part.strip().strip('"') + if part: + ids_to_delete.append(part) + + print("[DELETE_SYNC] 待删除人脸ID列表: {}".format(ids_to_delete)) + + if not ids_to_delete: + print("[DELETE_SYNC] 解析后无待删除项") + return True + + # 显示当前本地人脸列表 + print("[DELETE_SYNC] 当前本地人脸数量: {}".format(len(peoples))) + for i, p in enumerate(peoples): + print("[DELETE_SYNC] [{}] {}".format(i, p.name)) + + # 执行删除(每次最多处理一个,避免长时间阻塞) + face_id = ids_to_delete[0] + print("[DELETE_SYNC] 正在删除: {}".format(face_id)) + + delete_result = delete_face_by_id(face_id) + print("[DELETE_SYNC] 删除结果: {}".format("成功" if delete_result else "失败")) + + if delete_result: + # 只有本地特征真正删除成功后才确认,避免服务端过早清掉待删除任务 + print("[DELETE_SYNC] 发送确认: POST /api/v1/faces/delete-ack") + confirm_result = esp_http_post_confirm(face_id) + print("[DELETE_SYNC] 确认结果: {}".format("成功" if confirm_result else "失败")) + else: + print("[DELETE_SYNC] 本地未删除成功,暂不确认,等待下次同步重试") + + # 显示删除后的人脸列表 + print("[DELETE_SYNC] 删除后本地人脸数量: {}".format(len(peoples))) + for i, p in enumerate(peoples): + print("[DELETE_SYNC] [{}] {}".format(i, p.name)) + + print("[DELETE_SYNC] ========== 删除同步完成 ==========") + return True + + except Exception as e: + print("[DELETE_SYNC] 同步出错:", e) + return False + +def esp_http_post_confirm(face_id): + """发送删除确认请求""" + if not wifi_connected: + return False + + try: + esp_send_cmd("AT+CIPCLOSE", 500) + utime.sleep_ms(200) + esp_send_cmd("AT+CIPMUX=0", 500) + + # 建立TCP连接 + cmd = 'AT+CIPSTART="TCP","{}",{}'.format(SERVER_IP, SERVER_PORT) + resp = esp_send_cmd(cmd, 3000) + if "OK" not in resp and "CONNECT" not in resp: + print("[CONFIRM] TCP连接失败") + return False + + # 构建POST请求 + json_data = '{{"face_id":"{}"}}'.format(face_id) + http_request = "POST /api/v1/faces/delete-ack HTTP/1.1\r\n" + http_request += "Host: {}:{}\r\n".format(SERVER_IP, SERVER_PORT) + http_request += "Content-Type: application/json\r\n" + http_request += "X-Api-Token: {}\r\n".format(API_TOKEN) + http_request += "Content-Length: {}\r\n".format(len(json_data)) + http_request += "Connection: close\r\n\r\n" + http_request += json_data + + # 发送请求 + cmd = "AT+CIPSEND={}".format(len(http_request)) + uart2.write(cmd + "\r\n") + utime.sleep_ms(100) + + # 等待>提示符 + start = utime.ticks_ms() + prompt = "" + while utime.ticks_diff(utime.ticks_ms(), start) < 2000: + if uart2.any(): + prompt += uart2.read().decode('utf-8', 'ignore') + if ">" in prompt: + break + utime.sleep_ms(10) + + if ">" not in prompt: + esp_send_cmd("AT+CIPCLOSE", 300) + return False + + # 发送数据 + uart2.write(http_request) + + # 等待响应 + resp = "" + start = utime.ticks_ms() + while utime.ticks_diff(utime.ticks_ms(), start) < 5000: + if uart2.any(): + data = uart2.read() + if data: + resp += data.decode('utf-8', 'ignore') + if "success" in resp: + print("[CONFIRM] 服务器确认成功") + esp_send_cmd("AT+CIPCLOSE", 300) + return True + utime.sleep_ms(20) + + esp_send_cmd("AT+CIPCLOSE", 300) + print("[CONFIRM] 响应: {}".format(resp[:100] if resp else "(空)")) + return "success" in resp + + except Exception as e: + print("[CONFIRM] 错误:", e) + return False + +def json_get_int(text, key, default=0): + marker = '"{}":'.format(key) + start = text.find(marker) + if start == -1: + return default + start += len(marker) + while start < len(text) and text[start] == ' ': + start += 1 + end = start + while end < len(text) and text[end].isdigit(): + end += 1 + try: + return int(text[start:end]) + except: + return default + +def extract_json_block(text, key, open_ch, close_ch): + marker = '"{}":'.format(key) + pos = text.find(marker) + if pos == -1: + return "" + start = text.find(open_ch, pos + len(marker)) + if start == -1: + return "" + depth = 0 + for i in range(start, len(text)): + ch = text[i] + if ch == open_ch: + depth += 1 + elif ch == close_ch: + depth -= 1 + if depth == 0: + return text[start:i + 1] + return "" + +def parse_string_array_block(arr_str): + values = [] + pos = 0 + while pos < len(arr_str): + start = arr_str.find('"', pos) + if start == -1: + break + end = arr_str.find('"', start + 1) + if end == -1: + break + values.append(arr_str[start + 1:end]) + pos = end + 1 + return values + +def parse_photo_ids(response): + """解析服务端 /api/v1/faces/photos 返回的照片ID列表""" + ids = {} + pos = 0 + marker = '"id":"' + while pos < len(response): + start = response.find(marker, pos) + if start == -1: + break + start += len(marker) + end = response.find('"', start) + if end == -1: + break + photo_id = response[start:end] + if photo_id: + ids[photo_id] = 1 + pos = end + 1 + return ids + +def parse_mapping_object(obj_str): + mappings = {} + if len(obj_str) < 2: + return mappings + inner = obj_str[1:-1].strip() + if not inner: + return mappings + parts = inner.split(',') + for part in parts: + if ':' not in part: + continue + kv = part.split(':', 1) + key = kv[0].strip().strip('"') + value = kv[1].strip().strip('"') + if key and value: + mappings[key] = value + return mappings + +def apply_face_mappings(server_mappings): + global face_id_mapping + print("[SYNC_STATE] 服务器映射数量: {}".format(len(server_mappings))) + updated_count = 0 + for face_id, student_id in server_mappings.items(): + print("[SYNC_STATE] 映射: ID:{} -> {}".format(face_id, student_id)) + if update_face_record(face_id, student_id): + updated_count += 1 + face_id_mapping = server_mappings + save_local_mapping() + print("[SYNC_STATE] 映射应用完成,更新 {} 条".format(updated_count)) + +def sync_unified_state(): + """按服务端统一版本号同步K210所需状态""" + global sync_last_version + if not wifi_connected: + print("[SYNC_STATE] WiFi未连接,跳过") + return False + + path = "/api/v1/sync/state?client=k210&last_version={}".format(sync_last_version) + print("[SYNC_STATE] GET {}".format(path)) + response = esp_http_get(path, 8000) + if response is None: + print("[SYNC_STATE] 服务器无响应") + return False + + server_version = json_get_int(response, "version", sync_last_version) + changed = ('"changed":true' in response) + print("[SYNC_STATE] local={}, server={}, changed={}".format(sync_last_version, server_version, changed)) + + if not changed: + save_sync_version(server_version) + return True + + pending_arr = extract_json_block(response, "pending_delete", '[', ']') + pending_delete = parse_string_array_block(pending_arr) + deleted_ids = [] + delete_failed = False + print("[SYNC_STATE] 待删除: {}".format(pending_delete)) + + for face_id in pending_delete: + if delete_face_by_id(face_id): + deleted_ids.append(face_id) + else: + delete_failed = True + + if deleted_ids: + deleted_json = ",".join(['"{}"'.format(x) for x in deleted_ids]) + ack_body = '{{"client":"k210","version":{},"deleted":[{}]}}'.format(server_version, deleted_json) + ack_resp = esp_http_post_json("/api/v1/sync/ack", ack_body, 3000) + print("[SYNC_STATE] ACK响应:", ack_resp[:120] if ack_resp else "(空)") + + mappings_obj = extract_json_block(response, "face_mappings", '{', '}') + server_mappings = parse_mapping_object(mappings_obj) + apply_face_mappings(server_mappings) + + if not delete_failed: + save_sync_version(server_version) + else: + print("[SYNC_STATE] 有删除失败项,暂不推进本地版本,等待下次重试") + + return not delete_failed + +# --- K210时间管理 --- +k210_base_timestamp = 0 # 基准时间戳(Unix时间戳) +k210_base_ticks = 0 # 基准时刻的ticks + +def set_base_time(unix_timestamp): + """设置K210的基准时间""" + global k210_base_timestamp, k210_base_ticks + k210_base_timestamp = unix_timestamp + k210_base_ticks = utime.ticks_ms() + print("[TIME] Base time set:", unix_timestamp) + +def get_current_timestamp(): + """获取当前Unix时间戳""" + if k210_base_timestamp == 0: + # 如果还没设置基准时间,使用运行时间 + return utime.ticks_ms() // 1000 + else: + # 计算当前时间戳 + elapsed_seconds = (utime.ticks_ms() - k210_base_ticks) // 1000 + return k210_base_timestamp + elapsed_seconds + +# --- 2. KPU模型和硬件初始化 --- +try: + task_fd = kpu.load("/sd/FaceDetection.smodel") + task_ld = kpu.load("/sd/FaceLandmarkDetection.smodel") + task_fe = kpu.load("/sd/FeatureExtraction.smodel") +except Exception as e: + print("Error loading KPU models:", e) + while True: + utime.sleep_ms(1000) + +clock = time.clock() +fm.register(12, fm.fpioa.GPIO0) +fm.register(13, fm.fpioa.GPIO1) +fm.register(14, fm.fpioa.GPIO2) +LED_B = GPIO(GPIO.GPIO0, GPIO.OUT, value=1) +LED_G = GPIO(GPIO.GPIO1, GPIO.OUT, value=1) +LED_R = GPIO(GPIO.GPIO2, GPIO.OUT, value=1) +key_pin = 16 +fm.register(key_pin, fm.fpioa.GPIOHS0) +KEY = GPIO(GPIO.GPIOHS0, GPIO.IN) +lcd.init() +sensor.reset() +sensor.set_pixformat(sensor.RGB565) +sensor.set_framesize(sensor.QVGA) +sensor.set_hmirror(CAMERA_HMIRROR) +sensor.set_vflip(CAMERA_VFLIP) +sensor.run(1) +anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025) +dst_point = [(44, 59), (84, 59), (64, 82), (47, 105), (81, 105)] +kpu.init_yolo2(task_fd, 0.5, 0.3, 5, anchor) +img_face = image.Image(size=(128, 128)) +img_face.pix_to_ai() + +# --- 3. 按键中断处理 --- +key_Flag = 0 +key_pressed = 0 # 0=无, 1=短按, 2=长按(2秒), 3=超长按(5秒删除全部) +t_key = 0 +def fun(KEY): + global key_Flag, key_pressed, t_key + utime.sleep_ms(10) + if KEY.value() == 0: + if key_Flag == 0: + key_Flag = 1 + t_key = utime.ticks_ms() + else: + if key_Flag == 1: + press_duration = utime.ticks_diff(utime.ticks_ms(), t_key) + if press_duration > 5000: + key_pressed = 3 # 超长按5秒:删除全部人脸 + elif press_duration > 2000: + key_pressed = 2 # 长按2秒:删除模式 + else: + key_pressed = 1 # 短按:添加人脸 + key_Flag = 0 +KEY.irq(fun, GPIO.IRQ_BOTH) + +def delete_all_faces(): + """删除全部人脸数据""" + global peoples, face_id_mapping + try: + # 清空人脸列表 + peoples = [] + # 清空记录文件 + with open(record_path, "w") as f: + pass # 写入空文件 + # 清空映射 + face_id_mapping = {} + save_local_mapping() + delete_all_local_face_photos() + print("[DELETE_ALL] 已删除全部人脸数据") + return True + except Exception as e: + print("[DELETE_ALL] 删除失败:", e) + load_faces() + return False + +# --- 4. 数据库和人脸管理函数 (已包含之前修复的bug) --- +class People: + def __init__(self, name="", feature=[]): self.name = name; self.feature = feature + def feature_max(self, feature): + if not self.feature: return 0 + return kpu.face_compare(self.feature, feature) +peoples = [] +record_path = "/sd/recordftr.txt" +def load_faces(): + global peoples; peoples = [] + try: + with open(record_path, "r") as f: + for line in f: + # 使用 maxsplit=1 参数,只按第一个 '#' 分割,防止特征数据中的'#'导致错误 + parts = line.strip().split('#', 1) + if len(parts) == 2 and parts[1]: + try: peoples.append(People(parts[0], eval(parts[1]))) + except Exception as e_eval: print("Eval error on line for {}: {}".format(parts[0], e_eval)) + print("成功加载 %d 条人脸数据" % len(peoples)) + except Exception as e: print("读取人脸数据库失败:", e) +def add_face(feature, face_img=None): + new_id_num = 1 + if peoples: + id_nums = [int(p.name.split(':')[1]) for p in peoples if ':' in p.name and p.name.split(':')[1].isdigit()] + if id_nums: new_id_num = max(id_nums) + 1 + else: new_id_num = len(peoples) + 1 + new_name = "ID:{}".format(new_id_num) + peoples.append(People(new_name, feature)) + try: + if face_img is not None: + print("[PHOTO] 正在保存人脸照片并加入上传队列...") + if not capture_and_upload_face(new_id_num, face_img): + print("[PHOTO] 本地照片保存失败,取消添加人脸") + peoples.pop() + return False + + with open(record_path, "a") as f: f.write(new_name + '#' + str(feature) + "\n") + print("添加成功:", new_name) + + return True + except Exception as e: + print("写入文件失败:", e) + delete_local_face_photo(new_id_num) + peoples.pop() + return False +def delete_face_by_index(idx): + if not (0 <= idx < len(peoples)): return False + deleted_name = peoples[idx].name + peoples.pop(idx) + try: + with open(record_path, "w") as f: + for p in peoples: f.write(p.name + '#' + str(p.feature) + "\n") + if deleted_name.startswith("ID:"): + delete_local_face_photo(deleted_name.split(":", 1)[1]) + else: + delete_local_face_photo(deleted_name) + print("删除 %s 成功" % deleted_name); return True + except Exception as e: print("重写文件失败:", e); load_faces(); return False + +# --- 5. 支持多张人脸检测的函数 (保持不变) --- +def detect_and_recognize_faces(img): + codes = kpu.run_yolo2(task_fd, img) + if not codes: return [] + results = [] + for item in codes: + face_cut = img.cut(item.x(), item.y(), item.w(), item.h()) + face_cut_128 = face_cut.resize(128, 128); face_cut_128.pix_to_ai() + fmap = kpu.forward(task_ld, face_cut_128) + plist = fmap[:] + le=(item.x()+int(plist[0]*item.w()-10), item.y()+int(plist[1]*item.h())); re=(item.x()+int(plist[2]*item.w()), item.y()+int(plist[3]*item.h())); nose=(item.x()+int(plist[4]*item.w()), item.y()+int(plist[5]*item.h())); lm=(item.x()+int(plist[6]*item.w()), item.y()+int(plist[7]*item.h())); rm=(item.x()+int(plist[8]*item.w()), item.y()+int(plist[9]*item.h())) + src_point = [le, re, nose, lm, rm] + T = image.get_affine_transform(src_point, dst_point) + image.warp_affine_ai(img, img_face, T) + del(face_cut); del(face_cut_128) + fmap = kpu.forward(task_fe, img_face) + feature = kpu.face_encode(fmap[:]) + max_score = 0; match_index = -1 + for i, p in enumerate(peoples): + score = p.feature_max(feature) + if score > max_score: max_score = score; match_index = i + result_item = {'score': max_score, 'rect': item.rect(), 'feature': feature} + if max_score > 85: result_item['state'] = peoples[match_index].name + else: result_item['state'] = "stranger" + results.append(result_item) + return results + +# --- 6. 主程序启动前准备 - 添加发送逻辑所需变量 --- +load_faces() +last_send_time = 0 +SEND_INTERVAL_MS = 1000 +last_sent_data = "" # 改为记录完整数据而不是state +last_saved_id = "" # ✨ 添加:初始化上次保存的学号 + +# --- 分时网络:照片上传队列操作 --- +def queue_photo_upload(face_id): + """将本地照片ID添加到上传队列(非阻塞)""" + global photo_upload_queue + face_id = str(face_id) + if face_id in photo_upload_queue: + print("[QUEUE] 照片已在队列中: ID={}".format(face_id)) + return + photo_upload_queue.append(face_id) + print("[QUEUE] 照片已加入队列: ID={},队列长度: {}".format(face_id, len(photo_upload_queue))) + +def queue_local_photos_for_upload(): + """启动时扫描SD卡照片,补传可能遗漏到服务器的照片""" + if not ensure_local_photo_dir(): + return + + server_photo_ids = None + if wifi_connected: + print("[QUEUE] 正在获取服务端照片列表,用于判断缺失照片...") + response = esp_http_get("/api/v1/faces/photos", 8000) + if response: + server_photo_ids = parse_photo_ids(response) + print("[QUEUE] 服务端已有照片: {} 张".format(len(server_photo_ids))) + else: + print("[QUEUE] 服务端照片列表获取失败,将本地照片全部加入补传队列") + + queued = 0 + skipped = 0 + try: + for name in os.listdir(LOCAL_FACE_PHOTO_DIR): + if name.endswith(".jpg"): + face_id = name[:-4] + if face_id: + if server_photo_ids is not None: + server_has_photo = face_id in server_photo_ids + if not server_has_photo and face_id in face_id_mapping: + server_has_photo = face_id_mapping[face_id] in server_photo_ids + if not server_has_photo: + for orig_id, student_id in face_id_mapping.items(): + if student_id == face_id and orig_id in server_photo_ids: + server_has_photo = True + break + if server_has_photo: + skipped += 1 + continue + queue_photo_upload(face_id) + queued += 1 + print("[QUEUE] 本地照片补传扫描完成: queued={}, skipped={}".format(queued, skipped)) + except Exception as e: + print("[QUEUE] 扫描本地照片失败:", e) + +def do_network_task(): + """执行一个网络任务(每次只做一件事)""" + global photo_upload_queue, last_sync_time + + # 优先处理照片上传 + if len(photo_upload_queue) > 0: + face_id = photo_upload_queue.pop(0) + jpeg_data = load_local_face_photo(face_id) + if jpeg_data is None or len(jpeg_data) < 100: + print("[NET] 本地照片无效,跳过上传: ID={}".format(face_id)) + return True + + print("[NET] 上传照片: ID={}".format(face_id)) + try: + if esp_http_post_photo(face_id, jpeg_data): + print("[NET] 照片上传完成") + else: + print("[NET] 照片上传失败,保留队列等待重试") + queue_photo_upload(face_id) + except Exception as e: + print("[NET] 上传错误:", e) + queue_photo_upload(face_id) + return True + + return False + +# 启动时扫描本地照片,补传可能遗漏到服务器的照片 +queue_local_photos_for_upload() + +# 启动时执行一次同步 +print("[BOOT] 启动同步...") +if wifi_connected: + try: + sync_unified_state() + except Exception as e: + print("[BOOT] 统一同步错误:", e) + print("[BOOT] 同步完成") +else: + print("[BOOT] WiFi未连接,跳过同步") + +# QT触发同步标志 +sync_requested = False +last_sync_check_time = 0 + +def check_sync_request(): + """检查服务器是否有同步请求""" + global sync_requested + if not wifi_connected: + return False + + try: + response = esp_http_get("/api/v1/sync/request", 2000) + if response and '"sync":true' in response: + print("[SYNC] 收到服务器同步请求") + sync_requested = True + # 确认收到请求 + esp_http_post_json("/api/v1/sync/request/ack", '{"ack":true}', 1000) + return True + except Exception as e: + print("[SYNC] 检查同步请求错误:", e) + return False + +def trigger_sync(): + """执行一次完整同步(由QT端触发)""" + global sync_requested + if not wifi_connected: + print("[SYNC] WiFi未连接,无法同步") + return False + + print("[SYNC] ========== QT触发同步开始 ==========") + try: + sync_unified_state() + except Exception as e: + print("[SYNC] 统一同步错误:", e) + + print("[SYNC] ========== QT触发同步完成 ==========") + sync_requested = False + return True + +# --- 7. 主循环 (状态机) --- +while True: + clock.tick() + # ------------------ 模式0:人脸识别与智能通信 (多人脸 & 无脸不发送) ------------------ + if key_pressed == 0: + img = sensor.snapshot() + detected_faces = detect_and_recognize_faces(img) + current_state = "" + recognized_ids = [] + if not detected_faces: + LED_G.value(1); LED_R.value(1) + else: + has_stranger = False; has_known_person = False + for face in detected_faces: + rect = face['rect'] + img.draw_rectangle(rect) + if face['state'] == "stranger": + img.draw_string(rect[0], rect[1], "Stranger", color=(255, 0, 0), scale=2) + recognized_ids.append("0"); has_stranger = True + else: + # 使用映射后的学号显示 + display_name = get_display_name(face['state']) + img.draw_string(rect[0], rect[1], display_name, color=(0, 255, 0), scale=2) + recognized_ids.append(face['state']); has_known_person = True + if has_known_person: LED_G.value(0); LED_R.value(1) + elif has_stranger: LED_G.value(1); LED_R.value(0) + recognized_ids.sort(); current_state = ",".join(recognized_ids) + time_now = utime.ticks_ms() + if utime.ticks_diff(time_now, last_send_time) > SEND_INTERVAL_MS: + if detected_faces: + # 发送第一个识别到的人脸数据(可以改为发送得分最高的) + best_face = max(detected_faces, key=lambda x: x['score']) + + if best_face['state'] == "stranger": + # 陌生人,发送UNKNOWN + msg_to_send = "UNKNOWN\r\n" + + # 陌生人不保存到SD卡 + last_saved_id = "" # 重置保存记录 + else: + # 已识别用户,发送完整信息(STM32期望的格式) + student_id = best_face['state'] # 例如 "ID:2" + student_name = best_face['state'].replace(":", "_") # 将 "ID:2" 转为 "ID_2" + confidence = best_face['score'] / 100.0 + + # 构造STM32期望的格式:ID:2,NAME:ID_2,CONF:0.95 + msg_to_send = "ID:{},NAME:{},CONF:{:.2f}\r\n".format( + student_id.split(':')[1] if ':' in student_id else student_id, + student_name, + confidence + ) + + if msg_to_send != last_sent_data: + uart.write(msg_to_send) + print("[UART SEND] -> {}".format(msg_to_send.strip())) + last_sent_data = msg_to_send + last_send_time = time_now + else: + # 没有检测到人脸 + if last_sent_data != "": + print("[STATE CHANGE] Faces disappeared. No data sent.") + last_sent_data = "" + last_saved_id = "" # 重置保存记录 + last_send_time = time_now + lcd.display(img) + + # ------------------ 【核心修改】模式1:添加人脸 (添加了实时框) ------------------ + elif key_pressed == 1: + key_pressed = 0 + last_sent_data = "" # 修改变量名 + last_saved_id = "" # 重置保存记录 + last_send_time = 0 + print("进入添加人脸模式...") + while True: + img = sensor.snapshot() + img.draw_string(0, 0, "Add Face Mode", color=(0, 0, 255), scale=2) + img.draw_string(0, 24, "Click to Confirm", color=(0, 0, 255), scale=2) + detected_faces = detect_and_recognize_faces(img) + best_face = None + if detected_faces: + # 选出最清晰(得分最高)的脸进行操作 + best_face = max(detected_faces, key=lambda x: x['score']) + + if best_face: + rect = best_face['rect'] # 获取目标人脸的框 + if best_face['state'] != "stranger": + # 【新】如果是已存在的用户,画一个橙色的框 + img.draw_rectangle(rect, color=(255, 128, 0), thickness=2) + img.draw_string(rect[0], rect[1], "Exists!", color=(255, 128, 0), scale=2) + else: + # 【新】如果是可以添加的陌生人,画一个绿色的框 + img.draw_rectangle(rect, color=(0, 255, 0), thickness=2) + img.draw_string(rect[0], rect[1], "Ready", color=(0, 255, 0), scale=2) + + # 按键确认逻辑 (保持不变) + if key_pressed == 1: + key_pressed = 0 + if best_face: + if best_face['state'] != "stranger": + img.draw_string(best_face['rect'][0], best_face['rect'][1] + 24, "Already exists!", color=(255, 0, 0), scale=2); LED_R.value(0) + else: + if add_face(best_face['feature'], img): + img.draw_string(best_face['rect'][0], best_face['rect'][1] + 24, "Add OK!", color=(0, 255, 0), scale=2); LED_G.value(0) + else: + img.draw_string(best_face['rect'][0], best_face['rect'][1] + 24, "Add Failed!", color=(255, 0, 0), scale=2); LED_R.value(0) + else: + img.draw_string(10, 100, "No Face!", color=(255, 0, 0), scale=2); LED_R.value(0) + lcd.display(img); utime.sleep_ms(2000); LED_R.value(1); LED_G.value(1); break + if key_pressed == 2: + key_pressed = 0; break # 长按退出 + lcd.display(img) + print("退出添加人脸模式") + + # ------------------ 模式2:删除人脸 (保持不变) ------------------ + elif key_pressed == 2: + key_pressed = 0 + last_sent_data = "" # 修改变量名 + last_saved_id = "" # 重置保存记录 + last_send_time = 0 + print("进入删除人脸模式...") + select_index = -1 + while True: + img = image.Image(); img.clear() + img.draw_string(10, 10, "Delete Mode", color=(255, 0, 0), scale=2); img.draw_string(10, 40, "Click=Next, Long Press=Confirm", scale=1.8) + if key_pressed == 1: + key_pressed = 0; select_index += 1 + if select_index >= len(peoples): select_index = -1 + if select_index == -1: img.draw_string(50, 100, "-> Cancel", color=(0, 255, 0), scale=2) + else: img.draw_string(50, 100, "-> Del: {}".format(peoples[select_index].name), color=(255, 128, 0), scale=2) + if key_pressed == 2: + key_pressed = 0 + if select_index != -1: + if delete_face_by_index(select_index): + img.clear(); img.draw_string(50, 100, "Delete Success!", color=(0, 255, 0), scale=2); LED_G.value(0) + else: + img.clear(); img.draw_string(50, 100, "Delete Failed!", color=(255, 0, 0), scale=2); LED_R.value(0) + else: + img.clear(); img.draw_string(50, 100, "Canceled", color=(255, 255, 0), scale=2) + lcd.display(img); utime.sleep_ms(2000); LED_G.value(1); LED_R.value(1); load_faces(); break + lcd.display(img) + print("退出删除人脸模式") + + # ------------------ 模式3:删除全部人脸 (长按5秒) ------------------ + elif key_pressed == 3: + key_pressed = 0 + print("进入删除全部人脸模式...") + img = image.Image(); img.clear() + img.draw_string(10, 10, "DELETE ALL FACES?", color=(255, 0, 0), scale=2) + img.draw_string(10, 50, "Count: {}".format(len(peoples)), color=(255, 255, 0), scale=2) + img.draw_string(10, 90, "Click=Confirm", color=(255, 128, 0), scale=1.8) + img.draw_string(10, 120, "Long Press=Cancel", color=(0, 255, 0), scale=1.8) + lcd.display(img) + LED_R.value(0) # 红灯警告 + + # 等待用户确认 + confirm_timeout = utime.ticks_ms() + while utime.ticks_diff(utime.ticks_ms(), confirm_timeout) < 10000: # 10秒超时 + if key_pressed == 1: # 短按确认删除 + key_pressed = 0 + img.clear() + img.draw_string(30, 80, "Deleting...", color=(255, 0, 0), scale=2) + lcd.display(img) + if delete_all_faces(): + img.clear() + img.draw_string(20, 80, "All Deleted!", color=(0, 255, 0), scale=2) + LED_R.value(1); LED_G.value(0) + else: + img.clear() + img.draw_string(20, 80, "Delete Failed!", color=(255, 0, 0), scale=2) + lcd.display(img) + utime.sleep_ms(2000) + break + elif key_pressed == 2 or key_pressed == 3: # 长按取消 + key_pressed = 0 + img.clear() + img.draw_string(50, 80, "Canceled", color=(255, 255, 0), scale=2) + lcd.display(img) + utime.sleep_ms(1500) + break + utime.sleep_ms(50) + + LED_R.value(1); LED_G.value(1) + print("退出删除全部人脸模式") + + # 分时网络处理:每N帧检查一次网络任务(只处理照片上传和同步请求) + frames_since_network += 1 + if frames_since_network >= NETWORK_FRAME_INTERVAL: + frames_since_network = 0 + # 优先处理照片上传队列 + if len(photo_upload_queue) > 0: + do_network_task() + # 检查是否有同步请求待执行 + elif sync_requested: + trigger_sync() + # 定期检查服务器是否有新的同步请求 + elif wifi_connected and utime.ticks_diff(utime.ticks_ms(), last_sync_check_time) > SYNC_CHECK_INTERVAL_MS: + last_sync_check_time = utime.ticks_ms() + check_sync_request() + + gc.collect() + diff --git a/k210/view_attendance.py b/k210/view_attendance.py new file mode 100644 index 0000000..fd4f258 --- /dev/null +++ b/k210/view_attendance.py @@ -0,0 +1,50 @@ +# K210考勤数据查看工具 +# 用于读取和显示SD卡中的考勤记录 + +import os + +ATTENDANCE_FILE = "/sd/attendance_records.csv" + +def view_attendance_records(limit=20): + """查看最近的考勤记录""" + try: + if ATTENDANCE_FILE not in os.listdir("/sd"): + print("No attendance file found!") + return + + with open(ATTENDANCE_FILE, "r") as f: + lines = f.readlines() + + print("=" * 50) + print("Attendance Records (Total: {})".format(len(lines) - 1)) + print("=" * 50) + + # 显示表头 + if len(lines) > 0: + print(lines[0].strip()) + print("-" * 50) + + # 显示最近的记录 + start = max(1, len(lines) - limit) + for i in range(start, len(lines)): + print(lines[i].strip()) + + print("=" * 50) + + except Exception as e: + print("Error reading file:", e) + +def clear_attendance_records(): + """清空考勤记录(保留表头)""" + try: + with open(ATTENDANCE_FILE, "w") as f: + f.write("Timestamp,Student_ID,Name,Confidence,Status\n") + print("Attendance records cleared!") + except Exception as e: + print("Error clearing file:", e) + +# 显示最近20条记录 +view_attendance_records(20) + +# 如果需要清空记录,取消下面这行的注释 +# clear_attendance_records() diff --git a/keilkill.bat b/keilkill.bat new file mode 100644 index 0000000..accc110 --- /dev/null +++ b/keilkill.bat @@ -0,0 +1,27 @@ +del *.bak /s +del *.ddk /s +del *.edk /s +del *.lst /s +del *.lnp /s +del *.mpf /s +del *.mpj /s +del *.obj /s +del *.omf /s +::del *.opt /s ::²»ÔÊÐíɾ³ýJLINKµÄÉèÖà +del *.plg /s +del *.rpt /s +del *.tmp /s +del *.__i /s +del *.crf /s +del *.o /s +del *.d /s +del *.axf /s +del *.tra /s +del *.dep /s +del JLinkLog.txt /s + +del *.iex /s +del *.htm /s +del *.sct /s +del *.map /s +exit diff --git a/server/server_encrypted.cpp b/server/server_encrypted.cpp new file mode 100644 index 0000000..1fd5b9f --- /dev/null +++ b/server/server_encrypted.cpp @@ -0,0 +1,2558 @@ +/* + * 增强版考勤服务器 - 支持AES加密数据 + * + * 功能: + * 1. HTTP端口8082 - 接收STM32加密签到数据 + * 2. HTTP API - 提供Qt客户端接口 + * 3. AES-128-CBC解密支持 + * + * 编译:g++ -o server_encrypted.exe server_encrypted.cpp -lws2_32 -lcrypto -lssl -lsqlite3 -std=c++11 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 + #include + #include + #include + #pragma comment(lib, "ws2_32.lib") + typedef int socklen_t; +#else + #include + #include + #include + #include + #include + #include + #include + #define SOCKET int + #define INVALID_SOCKET -1 + #define SOCKET_ERROR -1 + #define closesocket(s) close(s) + #define _mkdir(d) mkdir(d, 0755) +#endif + +// OpenSSL库用于AES解密和Base64 +#include +#include +#include +#include +#include + +const int HTTP_PORT = 8082; +const int BUFFER_SIZE = 4096; +const std::string SQLITE_DB_FILE = "attendance.db"; +const std::string LOG_FILE = "attendance.log"; +const std::string DB_FILE = "attendance_database.csv"; +const std::string TIMESLOTS_FILE = "timeslots_config.json"; // 时间段配置文件 +const std::string MAPPING_CONFIG_FILE = "mapping_config.json"; // 映射配置文件 +const std::string FACE_ID_MAPPING_FILE = "face_id_mapping.json"; // 人脸ID映射文件 +const std::string FACES_DIR = "faces"; // 人脸照片目录 +const std::string PENDING_DELETE_FILE = "pending_delete.json"; // 待删除人脸列表 +const std::string SYNC_REQUEST_FILE = "sync_request.json"; // K210同步请求标志文件 +const std::string SYNC_VERSION_FILE = "sync_version.txt"; // 全局同步版本号 +const size_t MAX_JSON_BODY_SIZE = 64 * 1024; +const size_t MAX_PHOTO_BODY_SIZE = 512 * 1024; +const char* DEFAULT_API_TOKEN = "change-me-token"; +const char* DEFAULT_CORS_ORIGIN = "http://localhost"; +const char* DEFAULT_TIMESLOTS_JSON = + "{\"time_slots\":[" + "{\"name\":\"上午签到\",\"start_time\":\"08:00\",\"end_time\":\"09:30\",\"enabled\":true}," + "{\"name\":\"中午签退\",\"start_time\":\"12:00\",\"end_time\":\"13:00\",\"enabled\":true}," + "{\"name\":\"下午签到\",\"start_time\":\"14:00\",\"end_time\":\"15:00\",\"enabled\":true}," + "{\"name\":\"晚上签退\",\"start_time\":\"17:00\",\"end_time\":\"18:30\",\"enabled\":true}" + "]}"; + +std::string getEnvOrDefault(const char* name, const char* fallback) { + const char* value = std::getenv(name); + if (value && value[0] != '\0') { + return std::string(value); + } + return std::string(fallback); +} + +const std::string& apiToken() { + static const std::string token = getEnvOrDefault("ATTENDANCE_API_TOKEN", DEFAULT_API_TOKEN); + return token; +} + +const std::string& allowedCorsOrigin() { + static const std::string origin = getEnvOrDefault("ATTENDANCE_CORS_ORIGIN", DEFAULT_CORS_ORIGIN); + return origin; +} + +std::string readFaceIdMapping(); +std::string getPendingDeleteList(); +std::string getFacePhotosList(); +std::string getAllStudentIds(); +bool setSyncRequest(bool sync); +bool removeFromPendingDelete(const std::string& face_id); +bool initializeSqliteStorage(); +bool saveAttendanceRecord(const std::string& timestamp, const std::string& student_id, + const std::string& name, const std::string& confidence, + const std::string& status, const std::string& class_id); +std::string readMappingConfig(); +bool saveMappingConfig(const std::string& json_data); +std::map parseFaceIdMappings(const std::string& json_data); + +std::string jsonEscape(const std::string& value) { + std::ostringstream out; + for (unsigned char c : value) { + switch (c) { + case '\"': out << "\\\""; break; + case '\\': out << "\\\\"; break; + case '\b': out << "\\b"; break; + case '\f': out << "\\f"; break; + case '\n': out << "\\n"; break; + case '\r': out << "\\r"; break; + case '\t': out << "\\t"; break; + default: + if (c < 0x20) { + const char* hex = "0123456789abcdef"; + out << "\\u00" << hex[(c >> 4) & 0x0f] << hex[c & 0x0f]; + } else { + out << static_cast(c); + } + break; + } + } + return out.str(); +} + +std::string csvEscape(const std::string& value) { + bool needs_quotes = false; + for (char c : value) { + if (c == ',' || c == '"' || c == '\r' || c == '\n') { + needs_quotes = true; + break; + } + } + if (!needs_quotes) { + return value; + } + + std::string escaped = "\""; + for (char c : value) { + if (c == '"') { + escaped += "\"\""; + } else { + escaped += c; + } + } + escaped += "\""; + return escaped; +} + +std::vector parseCsvLine(const std::string& line) { + std::vector fields; + std::string current; + bool in_quotes = false; + + for (size_t i = 0; i < line.size(); ++i) { + char c = line[i]; + if (in_quotes) { + if (c == '"' && i + 1 < line.size() && line[i + 1] == '"') { + current += '"'; + ++i; + } else if (c == '"') { + in_quotes = false; + } else { + current += c; + } + } else if (c == '"') { + in_quotes = true; + } else if (c == ',') { + fields.push_back(current); + current.clear(); + } else { + current += c; + } + } + + fields.push_back(current); + return fields; +} + +bool parseIntInRange(const std::string& value, int min_value, int max_value, int& output) { + if (value.empty()) { + return false; + } + + try { + size_t pos = 0; + int parsed = std::stoi(value, &pos); + if (pos != value.size() || parsed < min_value || parsed > max_value) { + return false; + } + output = parsed; + return true; + } catch (...) { + return false; + } +} + +bool parseTimeParts(const std::string& value, int& hour, int& minute) { + if (value.size() != 5 || value[2] != ':' + || !std::isdigit(static_cast(value[0])) + || !std::isdigit(static_cast(value[1])) + || !std::isdigit(static_cast(value[3])) + || !std::isdigit(static_cast(value[4]))) { + return false; + } + + int parsed_hour = (value[0] - '0') * 10 + (value[1] - '0'); + int parsed_minute = (value[3] - '0') * 10 + (value[4] - '0'); + if (parsed_hour < 0 || parsed_hour > 23 || parsed_minute < 0 || parsed_minute > 59) { + return false; + } + hour = parsed_hour; + minute = parsed_minute; + return true; +} + +bool isSafeId(const std::string& value) { + if (value.empty() || value.size() > 64) { + return false; + } + for (unsigned char c : value) { + if (!(std::isalnum(c) || c == '_' || c == '-')) { + return false; + } + } + return true; +} + +bool buildFacePhotoPath(const std::string& face_id, std::string& filepath) { + if (!isSafeId(face_id)) { + return false; + } + filepath = FACES_DIR + "/" + face_id + ".jpg"; + return true; +} + +bool getHeaderValue(const std::string& request, const std::string& header_name, std::string& output) { + size_t headers_end = request.find("\r\n\r\n"); + std::string headers = headers_end == std::string::npos ? request : request.substr(0, headers_end); + std::istringstream stream(headers); + std::string line; + + std::string expected_key = header_name; + std::transform(expected_key.begin(), expected_key.end(), expected_key.begin(), + [](unsigned char c) { return static_cast(std::tolower(c)); }); + + while (std::getline(stream, line)) { + if (!line.empty() && line.back() == '\r') { + line.pop_back(); + } + + size_t colon = line.find(':'); + if (colon == std::string::npos) { + continue; + } + + std::string key = line.substr(0, colon); + std::string value = line.substr(colon + 1); + key.erase(std::remove_if(key.begin(), key.end(), + [](unsigned char c) { return std::isspace(c); }), key.end()); + std::transform(key.begin(), key.end(), key.begin(), + [](unsigned char c) { return static_cast(std::tolower(c)); }); + + if (key != expected_key) { + continue; + } + + size_t first = value.find_first_not_of(" \t"); + if (first == std::string::npos) { + output.clear(); + } else { + value.erase(0, first); + size_t last = value.find_last_not_of(" \t"); + if (last != std::string::npos) { + value.erase(last + 1); + } + output = value; + } + return true; + } + + return false; +} + +bool hasHeaderToken(const std::string& request, const std::string& header_name, const std::string& expected) { + size_t headers_end = request.find("\r\n\r\n"); + std::string headers = headers_end == std::string::npos ? request : request.substr(0, headers_end); + std::istringstream stream(headers); + std::string line; + + while (std::getline(stream, line)) { + if (!line.empty() && line.back() == '\r') { + line.pop_back(); + } + size_t colon = line.find(':'); + if (colon == std::string::npos) { + continue; + } + std::string key = line.substr(0, colon); + std::string value = line.substr(colon + 1); + key.erase(std::remove_if(key.begin(), key.end(), + [](unsigned char c) { return std::isspace(c); }), key.end()); + size_t first = value.find_first_not_of(" \t"); + if (first == std::string::npos) { + value.clear(); + } else { + value.erase(0, first); + size_t last = value.find_last_not_of(" \t"); + if (last != std::string::npos) { + value.erase(last + 1); + } + } + + std::transform(key.begin(), key.end(), key.begin(), + [](unsigned char c) { return static_cast(std::tolower(c)); }); + std::string expected_key = header_name; + std::transform(expected_key.begin(), expected_key.end(), expected_key.begin(), + [](unsigned char c) { return static_cast(std::tolower(c)); }); + + if (key == expected_key && value == expected) { + return true; + } + } + return false; +} + +bool isPublicEndpoint(const std::string& method, const std::string& endpoint) { + return method == "OPTIONS" || (method == "GET" && endpoint == "/api/health"); +} + +std::string normalizeApiEndpoint(const std::string& method, const std::string& endpoint) { + if (endpoint.find("/api/v1/") != 0) { + return endpoint; + } + + if (endpoint == "/api/v1/system/health") return "/api/health"; + if (endpoint == "/api/v1/system/time") return "/api/time"; + + if (method == "POST" && endpoint == "/api/v1/attendance/checkins") return "/api/checkin"; + if (method == "GET" && endpoint == "/api/v1/attendance/records") return "/api/records"; + if (method == "DELETE" && endpoint == "/api/v1/attendance/records") return "/api/record"; + if (method == "POST" && endpoint == "/api/v1/attendance/records/clear") return "/api/clear"; + if (method == "GET" && endpoint == "/api/v1/attendance/statistics") return "/api/statistics"; + if (method == "GET" && endpoint == "/api/v1/attendance/duplicates") return "/api/check_duplicate"; + if (method == "GET" && endpoint == "/api/v1/attendance/today") return "/api/today_records"; + + if (endpoint == "/api/v1/config/time-slots") return "/api/timeslots"; + if (endpoint == "/api/v1/config/mappings") return "/api/mapping_config"; + + if (endpoint == "/api/v1/faces/mappings") return "/api/face_id_mapping"; + if (endpoint == "/api/v1/faces/photos") return "/api/face_photos"; + if (endpoint.find("/api/v1/faces/photos/") == 0) { + const std::string id = endpoint.substr(std::string("/api/v1/faces/photos/").size()); + return method == "POST" ? "/api/face_photo_simple/" + id : "/api/face_photo/" + id; + } + if (endpoint == "/api/v1/faces/student-ids") return "/api/all_student_ids"; + if (endpoint == "/api/v1/faces/pending-delete") return "/api/pending_delete"; + if (method == "POST" && endpoint == "/api/v1/faces/delete-ack") return "/api/confirm_delete"; + if (method == "DELETE" && endpoint.find("/api/v1/faces/") == 0) { + return "/api/face/" + endpoint.substr(std::string("/api/v1/faces/").size()); + } + + if (endpoint == "/api/v1/sync/request") return "/api/sync_request"; + if (endpoint == "/api/v1/sync/request/ack") return "/api/sync_ack"; + if (endpoint == "/api/v1/sync/trigger") return "/api/trigger_sync"; + + return endpoint; +} + +bool isAuthorizedRequest(const std::string& request, const std::string& method, const std::string& endpoint) { + if (isPublicEndpoint(method, endpoint)) { + return true; + } + return hasHeaderToken(request, "X-Api-Token", apiToken()); +} + +std::string makeJsonError(const std::string& message) { + return "{\"success\":false,\"message\":\"" + jsonEscape(message) + "\"}"; +} + +// ⚠️ 重要:密钥和IV必须与STM32端完全一致! +static const unsigned char MY_AES_KEY[16] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; + +static const unsigned char MY_AES_IV[16] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f +}; + +// ============= Base64解码 ============= +std::string base64_decode(const std::string& encoded_string) { + BIO *bio, *b64; + int decode_len = encoded_string.length(); + char* buffer = new char[decode_len]; + + bio = BIO_new_mem_buf(encoded_string.c_str(), -1); + b64 = BIO_new(BIO_f_base64()); + bio = BIO_push(b64, bio); + + BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); + int length = BIO_read(bio, buffer, decode_len); + BIO_free_all(bio); + + std::string result(buffer, length); + delete[] buffer; + + return result; +} + +// ============= 添加PKCS#7填充 ============= +std::string add_pkcs7_padding(const std::string& data) { + size_t padding_len = 16 - (data.length() % 16); + std::string result = data; + for (size_t i = 0; i < padding_len; i++) { + result += (char)padding_len; + } + return result; +} + +// ============= 手动移除PKCS#7填充 ============= +std::string remove_pkcs7_padding(const std::string& data) { + if (data.empty()) return ""; + + // 获取最后一个字节(填充长度) + unsigned char padding_len = (unsigned char)data[data.length() - 1]; + + // 验证填充长度 + if (padding_len < 1 || padding_len > 16 || padding_len > data.length()) { + std::cerr << "[CRYPTO] Invalid padding length: " << (int)padding_len << std::endl; + return data; // 返回原数据 + } + + // 验证所有填充字节都相同 + for (size_t i = data.length() - padding_len; i < data.length(); i++) { + if ((unsigned char)data[i] != padding_len) { + std::cerr << "[CRYPTO] Invalid padding at position " << i << std::endl; + return data; // 返回原数据 + } + } + + // 移除填充 + return data.substr(0, data.length() - padding_len); +} + +// ============= AES-CBC加密 (用于响应Qt客户端) ============= +std::string aes_encrypt_cbc(const std::string& plaintext) { + // 添加PKCS#7填充 + std::string padded = add_pkcs7_padding(plaintext); + + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + if (!ctx) { + std::cerr << "[CRYPTO] Failed to create context" << std::endl; + return ""; + } + + // 初始化加密 + if (EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, MY_AES_KEY, MY_AES_IV) != 1) { + std::cerr << "[CRYPTO] EncryptInit failed" << std::endl; + EVP_CIPHER_CTX_free(ctx); + return ""; + } + + // 禁用自动填充(我们已手动添加) + EVP_CIPHER_CTX_set_padding(ctx, 0); + + // 加密数据 + std::vector ciphertext(padded.length() + 16); + int len; + int ciphertext_len = 0; + + if (EVP_EncryptUpdate(ctx, ciphertext.data(), &len, + (unsigned char*)padded.c_str(), + padded.length()) != 1) { + std::cerr << "[CRYPTO] EncryptUpdate failed" << std::endl; + EVP_CIPHER_CTX_free(ctx); + return ""; + } + ciphertext_len = len; + + // 完成加密 + if (EVP_EncryptFinal_ex(ctx, ciphertext.data() + len, &len) != 1) { + std::cerr << "[CRYPTO] EncryptFinal failed" << std::endl; + EVP_CIPHER_CTX_free(ctx); + return ""; + } + ciphertext_len += len; + + EVP_CIPHER_CTX_free(ctx); + + return std::string((char*)ciphertext.data(), ciphertext_len); +} + +// ============= AES-CBC解密 (使用OpenSSL标准库) ============= +std::string aes_decrypt_cbc(const std::string& encrypted_data) { + if (encrypted_data.empty() || encrypted_data.length() % 16 != 0) { + std::cerr << "[CRYPTO] Invalid encrypted data length: " << encrypted_data.length() << std::endl; + return ""; + } + + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + if (!ctx) { + std::cerr << "[CRYPTO] Failed to create context" << std::endl; + return ""; + } + + // 初始化解密(使用标准AES-128-CBC) + if (EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, MY_AES_KEY, MY_AES_IV) != 1) { + std::cerr << "[CRYPTO] DecryptInit failed" << std::endl; + EVP_CIPHER_CTX_free(ctx); + return ""; + } + + // 禁用自动填充,我们手动处理PKCS#7 + EVP_CIPHER_CTX_set_padding(ctx, 0); + + // 解密数据 + std::vector plaintext(encrypted_data.length() + 16); + int len; + int plaintext_len = 0; + + if (EVP_DecryptUpdate(ctx, plaintext.data(), &len, + (unsigned char*)encrypted_data.c_str(), + encrypted_data.length()) != 1) { + std::cerr << "[CRYPTO] DecryptUpdate failed" << std::endl; + EVP_CIPHER_CTX_free(ctx); + return ""; + } + plaintext_len = len; + + // 完成解密 + if (EVP_DecryptFinal_ex(ctx, plaintext.data() + len, &len) != 1) { + std::cerr << "[CRYPTO] DecryptFinal failed" << std::endl; + EVP_CIPHER_CTX_free(ctx); + return ""; + } + plaintext_len += len; + + EVP_CIPHER_CTX_free(ctx); + + std::string result((char*)plaintext.data(), plaintext_len); + + // 手动移除PKCS#7填充 + result = remove_pkcs7_padding(result); + + return result; +} + +// ============= 十六进制输出辅助函数 ============= +void print_hex(const std::string& label, const unsigned char* data, size_t len) { + std::cout << label << " (" << len << " bytes): "; + for (size_t i = 0; i < len && i < 32; i++) { + printf("%02x ", data[i]); + } + if (len > 32) std::cout << "..."; + std::cout << std::endl; +} + +// ============= Base64编码 ============= +std::string base64_encode(const std::string& input) { + BIO *bio, *b64; + BUF_MEM *bufferPtr; + + b64 = BIO_new(BIO_f_base64()); + bio = BIO_new(BIO_s_mem()); + bio = BIO_push(b64, bio); + + BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); + BIO_write(bio, input.c_str(), input.length()); + BIO_flush(bio); + BIO_get_mem_ptr(bio, &bufferPtr); + + std::string result(bufferPtr->data, bufferPtr->length); + BIO_free_all(bio); + + return result; +} + +// ============= 加密JSON数据(用于响应Qt客户端)============= +std::string encryptJSON(const std::string& json_data) { + std::cout << "[CRYPTO] Encrypting response..." << std::endl; + + // AES加密 + std::string encrypted = aes_encrypt_cbc(json_data); + if (encrypted.empty()) { + std::cerr << "[CRYPTO] Encryption failed!" << std::endl; + return ""; + } + + // Base64编码 + std::string encrypted_base64 = base64_encode(encrypted); + + std::cout << "[CRYPTO] ✓ Response encrypted" << std::endl; + return encrypted_base64; +} + +// ============= 解密JSON数据 ============= +std::string decryptJSON(const std::string& encrypted_base64) { + try { + std::cout << "[CRYPTO] Decrypting data..." << std::endl; + std::cout << "[CRYPTO] Base64 input: " << encrypted_base64 << std::endl; + std::cout << "[CRYPTO] Base64 length: " << encrypted_base64.length() << std::endl; + + // 1. Base64解码 + std::string encrypted_binary = base64_decode(encrypted_base64); + std::cout << "[CRYPTO] Binary length: " << encrypted_binary.length() << std::endl; + print_hex("[CRYPTO] Encrypted binary", (unsigned char*)encrypted_binary.c_str(), encrypted_binary.length()); + + // 调试:打印密钥和IV + print_hex("[CRYPTO] Using KEY", MY_AES_KEY, 16); + print_hex("[CRYPTO] Using IV", MY_AES_IV, 16); + + // 2. AES解密 + std::string decrypted = aes_decrypt_cbc(encrypted_binary); + + if (decrypted.empty()) { + std::cerr << "[CRYPTO] Decryption failed!" << std::endl; + return ""; + } + + std::cout << "[CRYPTO] ✓ Decryption successful" << std::endl; + std::cout << "[CRYPTO] Decrypted length: " << decrypted.length() << std::endl; + print_hex("[CRYPTO] Decrypted hex", (unsigned char*)decrypted.c_str(), decrypted.length()); + std::cout << "[CRYPTO] Decrypted text: " << decrypted << std::endl; + + return decrypted; + + } catch (const std::exception& e) { + std::cerr << "[CRYPTO] Exception: " << e.what() << std::endl; + return ""; + } +} + +// ============= 工具函数 ============= +std::string getCurrentTimestamp() { + time_t now = time(0); + tm ltm; +#ifdef _WIN32 + localtime_s(<m, &now); +#else + localtime_r(&now, <m); +#endif + char buffer[80]; + strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", <m); + return std::string(buffer); +} + +// 清理字符串中的控制字符(\r, \n等) +std::string cleanString(const std::string& str) { + std::string result; + result.reserve(str.length()); + for (char c : str) { + // 只保留可打印字符和空格,过滤掉\r\n\t等控制字符 + if (c >= 32 && c <= 126) { + result += c; + } + } + return result; +} + +std::string urlDecode(const std::string& str) { + std::string result; + for (size_t i = 0; i < str.length(); ++i) { + if (str[i] == '%' && i + 2 < str.length()) { + int value; + std::istringstream is(str.substr(i + 1, 2)); + if (is >> std::hex >> value) { + result += static_cast(value); + i += 2; + } else { + result += str[i]; + } + } else if (str[i] == '+') { + result += ' '; + } else { + result += str[i]; + } + } + return result; +} + +std::map parseQueryParams(const std::string& query) { + std::map params; + std::istringstream stream(query); + std::string pair; + + while (std::getline(stream, pair, '&')) { + size_t pos = pair.find('='); + if (pos != std::string::npos) { + std::string key = urlDecode(pair.substr(0, pos)); + std::string value = urlDecode(pair.substr(pos + 1)); + params[key] = value; + } + } + return params; +} + +// 简单的JSON解析 +std::map parseJSON(const std::string& json) { + std::map result; + + std::string content = json; + size_t start = content.find('{'); + size_t end = content.rfind('}'); + if (start != std::string::npos && end != std::string::npos) { + content = content.substr(start + 1, end - start - 1); + } + + std::istringstream ss(content); + std::string token; + + while (std::getline(ss, token, ',')) { + size_t colon = token.find(':'); + if (colon != std::string::npos) { + std::string key = token.substr(0, colon); + std::string value = token.substr(colon + 1); + + // 移除引号和空格 + key.erase(std::remove_if(key.begin(), key.end(), + [](char c) { return c == '\"' || c == ' ' || c == '\t'; }), key.end()); + value.erase(std::remove_if(value.begin(), value.end(), + [](char c) { return c == '\"'; }), value.end()); + + // 保留timestamp中的空格 + if (key != "timestamp") { + value.erase(std::remove(value.begin(), value.end(), ' '), value.end()); + } + + result[key] = value; + } + } + + return result; +} + +// ============= SQLite存储层 ============= +sqlite3* openSqliteDb() { + sqlite3* db = nullptr; + if (sqlite3_open(SQLITE_DB_FILE.c_str(), &db) != SQLITE_OK) { + std::cerr << "[SQLITE] Open failed: " << (db ? sqlite3_errmsg(db) : "unknown") << std::endl; + if (db) sqlite3_close(db); + return nullptr; + } + sqlite3_busy_timeout(db, 3000); + return db; +} + +bool sqliteExec(sqlite3* db, const std::string& sql) { + char* err = nullptr; + if (sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &err) != SQLITE_OK) { + std::cerr << "[SQLITE] Exec failed: " << (err ? err : sqlite3_errmsg(db)) << std::endl; + sqlite3_free(err); + return false; + } + return true; +} + +std::string sqliteColumnText(sqlite3_stmt* stmt, int col) { + const unsigned char* text = sqlite3_column_text(stmt, col); + return text ? reinterpret_cast(text) : ""; +} + +bool sqliteBindText(sqlite3_stmt* stmt, int index, const std::string& value) { + return sqlite3_bind_text(stmt, index, value.c_str(), -1, SQLITE_TRANSIENT) == SQLITE_OK; +} + +bool sqliteTableHasRows(sqlite3* db, const std::string& table) { + std::string sql = "SELECT 1 FROM " + table + " LIMIT 1"; + sqlite3_stmt* stmt = nullptr; + bool has_rows = false; + if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + has_rows = sqlite3_step(stmt) == SQLITE_ROW; + } + sqlite3_finalize(stmt); + return has_rows; +} + +std::string readWholeFileOrDefault(const std::string& path, const std::string& fallback) { + std::ifstream file(path.c_str(), std::ios::binary); + if (!file.is_open()) return fallback; + std::stringstream buffer; + buffer << file.rdbuf(); + std::string content = buffer.str(); + return content.empty() ? fallback : content; +} + +bool sqliteSetKv(sqlite3* db, const std::string& key, const std::string& value) { + sqlite3_stmt* stmt = nullptr; + const char* sql = "REPLACE INTO kv_store(key,value) VALUES(?,?)"; + if (sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) != SQLITE_OK) return false; + sqliteBindText(stmt, 1, key); + sqliteBindText(stmt, 2, value); + bool ok = sqlite3_step(stmt) == SQLITE_DONE; + sqlite3_finalize(stmt); + return ok; +} + +std::string sqliteGetKv(sqlite3* db, const std::string& key, const std::string& fallback) { + sqlite3_stmt* stmt = nullptr; + std::string value = fallback; + const char* sql = "SELECT value FROM kv_store WHERE key=?"; + if (sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) == SQLITE_OK) { + sqliteBindText(stmt, 1, key); + if (sqlite3_step(stmt) == SQLITE_ROW) { + value = sqliteColumnText(stmt, 0); + } + } + sqlite3_finalize(stmt); + return value; +} + +bool sqliteSetKvValue(const std::string& key, const std::string& value) { + sqlite3* db = openSqliteDb(); + if (!db) return false; + bool ok = sqliteSetKv(db, key, value); + sqlite3_close(db); + return ok; +} + +std::string sqliteGetKvValue(const std::string& key, const std::string& fallback) { + sqlite3* db = openSqliteDb(); + if (!db) return fallback; + std::string value = sqliteGetKv(db, key, fallback); + sqlite3_close(db); + return value; +} + +int sqliteCountRows(sqlite3* db, const std::string& table) { + sqlite3_stmt* stmt = nullptr; + std::string sql = "SELECT COUNT(*) FROM " + table; + int count = 0; + if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr) == SQLITE_OK + && sqlite3_step(stmt) == SQLITE_ROW) { + count = sqlite3_column_int(stmt, 0); + } + sqlite3_finalize(stmt); + return count; +} + +bool sqliteQuickCheck(std::string& message) { + sqlite3* db = openSqliteDb(); + if (!db) { + message = "open_failed"; + return false; + } + sqlite3_stmt* stmt = nullptr; + bool ok = false; + message = "unknown"; + if (sqlite3_prepare_v2(db, "PRAGMA quick_check", -1, &stmt, nullptr) == SQLITE_OK + && sqlite3_step(stmt) == SQLITE_ROW) { + message = sqliteColumnText(stmt, 0); + ok = message == "ok"; + } + sqlite3_finalize(stmt); + sqlite3_close(db); + return ok; +} + +int countFacePhotoFiles() { + int count = 0; +#ifdef _WIN32 + WIN32_FIND_DATAA findData; + std::string searchPath = FACES_DIR + "\\*.jpg"; + HANDLE hFind = FindFirstFileA(searchPath.c_str(), &findData); + if (hFind != INVALID_HANDLE_VALUE) { + do { + count++; + } while (FindNextFileA(hFind, &findData)); + FindClose(hFind); + } +#else + DIR* dir = opendir(FACES_DIR.c_str()); + if (dir) { + struct dirent* entry; + while ((entry = readdir(dir)) != NULL) { + std::string name = entry->d_name; + if (name.size() > 4 && name.substr(name.size() - 4) == ".jpg") { + count++; + } + } + closedir(dir); + } +#endif + return count; +} + +bool sqliteInsertRecord(sqlite3* db, const std::string& timestamp, const std::string& student_id, + const std::string& name, const std::string& confidence, + const std::string& status, const std::string& class_id) { + sqlite3_stmt* stmt = nullptr; + const char* sql = + "INSERT INTO records(timestamp,student_id,name,confidence,status,class_id) " + "VALUES(?,?,?,?,?,?)"; + if (sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) != SQLITE_OK) return false; + sqliteBindText(stmt, 1, timestamp); + sqliteBindText(stmt, 2, student_id); + sqliteBindText(stmt, 3, name); + sqliteBindText(stmt, 4, confidence); + sqliteBindText(stmt, 5, status); + sqliteBindText(stmt, 6, class_id.empty() ? "0" : class_id); + bool ok = sqlite3_step(stmt) == SQLITE_DONE; + sqlite3_finalize(stmt); + return ok; +} + +bool saveAttendanceRecord(const std::string& timestamp, const std::string& student_id, + const std::string& name, const std::string& confidence, + const std::string& status, const std::string& class_id) { + sqlite3* db = openSqliteDb(); + if (!db) return false; + bool ok = sqliteInsertRecord(db, timestamp, student_id, name, confidence, status, class_id); + sqlite3_close(db); + return ok; +} + +std::vector parseJsonStringList(const std::string& json, const std::string& key) { + std::vector values; + std::string marker = "\"" + key + "\":["; + size_t start = json.find(marker); + if (start == std::string::npos) return values; + start = json.find('[', start); + size_t end = json.find(']', start); + if (start == std::string::npos || end == std::string::npos) return values; + std::string arr = json.substr(start + 1, end - start - 1); + std::istringstream ss(arr); + std::string token; + while (std::getline(ss, token, ',')) { + token.erase(std::remove(token.begin(), token.end(), '"'), token.end()); + token.erase(std::remove_if(token.begin(), token.end(), + [](unsigned char c) { return std::isspace(c); }), token.end()); + if (!token.empty()) values.push_back(token); + } + return values; +} + +bool initializeSqliteStorage() { + sqlite3* db = openSqliteDb(); + if (!db) return false; + + bool ok = sqliteExec(db, + "PRAGMA journal_mode=WAL;" + "CREATE TABLE IF NOT EXISTS records(" + "id INTEGER PRIMARY KEY AUTOINCREMENT," + "timestamp TEXT NOT NULL," + "student_id TEXT NOT NULL," + "name TEXT," + "confidence TEXT," + "status TEXT," + "class_id TEXT DEFAULT '0'" + ");" + "CREATE INDEX IF NOT EXISTS idx_records_student_time ON records(student_id,timestamp);" + "CREATE INDEX IF NOT EXISTS idx_records_timestamp ON records(timestamp);" + "CREATE TABLE IF NOT EXISTS kv_store(" + "key TEXT PRIMARY KEY," + "value TEXT NOT NULL" + ");" + "CREATE TABLE IF NOT EXISTS face_mappings(" + "face_id TEXT PRIMARY KEY," + "student_id TEXT NOT NULL" + ");" + "CREATE TABLE IF NOT EXISTS pending_delete(" + "face_id TEXT PRIMARY KEY" + ");"); + + if (!ok) { + sqlite3_close(db); + return false; + } + + if (!sqliteTableHasRows(db, "records")) { + std::ifstream csv(DB_FILE.c_str()); + if (csv.is_open()) { + std::string line; + std::getline(csv, line); + int imported = 0; + sqliteExec(db, "BEGIN"); + while (std::getline(csv, line)) { + if (line.empty()) continue; + std::vector fields = parseCsvLine(line); + std::string timestamp = fields.size() > 0 ? fields[0] : ""; + std::string student_id = fields.size() > 1 ? fields[1] : ""; + std::string name = fields.size() > 2 ? fields[2] : ""; + std::string confidence = fields.size() > 3 ? fields[3] : "0"; + std::string status = fields.size() > 4 ? fields[4] : ""; + std::string class_id = fields.size() > 5 ? fields[5] : "0"; + if (!timestamp.empty() && !student_id.empty() + && sqliteInsertRecord(db, timestamp, student_id, name, confidence, status, class_id)) { + imported++; + } + } + sqliteExec(db, "COMMIT"); + std::cout << "[SQLITE] Imported records from CSV: " << imported << std::endl; + } + } + + if (sqliteGetKv(db, "time_slots", "").empty()) { + sqliteSetKv(db, "time_slots", readWholeFileOrDefault(TIMESLOTS_FILE, DEFAULT_TIMESLOTS_JSON)); + } + if (sqliteGetKv(db, "mapping_config", "").empty()) { + sqliteSetKv(db, "mapping_config", readWholeFileOrDefault(MAPPING_CONFIG_FILE, "{\"student_name_map\":{},\"class_name_map\":{}}")); + } + if (sqliteGetKv(db, "sync_request", "").empty()) { + sqliteSetKv(db, "sync_request", readWholeFileOrDefault(SYNC_REQUEST_FILE, "{\"sync\":false}")); + } + if (sqliteGetKv(db, "sync_version", "").empty()) { + sqliteSetKv(db, "sync_version", readWholeFileOrDefault(SYNC_VERSION_FILE, "1")); + } + + if (!sqliteTableHasRows(db, "face_mappings")) { + std::map mappings = parseFaceIdMappings( + readWholeFileOrDefault(FACE_ID_MAPPING_FILE, "{\"mappings\":{}}")); + sqlite3_stmt* stmt = nullptr; + const char* sql = "REPLACE INTO face_mappings(face_id,student_id) VALUES(?,?)"; + if (sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) == SQLITE_OK) { + for (const auto& m : mappings) { + sqlite3_reset(stmt); + sqlite3_clear_bindings(stmt); + sqliteBindText(stmt, 1, m.first); + sqliteBindText(stmt, 2, m.second); + sqlite3_step(stmt); + } + } + sqlite3_finalize(stmt); + std::cout << "[SQLITE] Imported face mappings: " << mappings.size() << std::endl; + } + + if (!sqliteTableHasRows(db, "pending_delete")) { + std::vector pending = parseJsonStringList( + readWholeFileOrDefault(PENDING_DELETE_FILE, "{\"pending_delete\":[]}"), "pending_delete"); + sqlite3_stmt* stmt = nullptr; + const char* sql = "REPLACE INTO pending_delete(face_id) VALUES(?)"; + if (sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) == SQLITE_OK) { + for (const auto& id : pending) { + sqlite3_reset(stmt); + sqlite3_clear_bindings(stmt); + sqliteBindText(stmt, 1, id); + sqlite3_step(stmt); + } + } + sqlite3_finalize(stmt); + std::cout << "[SQLITE] Imported pending deletes: " << pending.size() << std::endl; + } + + _mkdir(FACES_DIR.c_str()); + sqlite3_close(db); + std::cout << "[SQLITE] Storage ready: " << SQLITE_DB_FILE << std::endl; + return true; +} + +// ============= 数据库操作 ============= +std::string readDatabase(int limit = -1, int offset = 0) { + sqlite3* db = openSqliteDb(); + if (!db) return "[]"; + + std::ostringstream json; + json << "["; + sqlite3_stmt* stmt = nullptr; + std::string sql = "SELECT timestamp,student_id,name,confidence,status,class_id FROM records ORDER BY id DESC"; + if (limit > 0) { + sql += " LIMIT ? OFFSET ?"; + } + + bool first = true; + if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + if (limit > 0) { + sqlite3_bind_int(stmt, 1, limit); + sqlite3_bind_int(stmt, 2, offset); + } + while (sqlite3_step(stmt) == SQLITE_ROW) { + if (!first) json << ","; + first = false; + std::string conf = sqliteColumnText(stmt, 3); + if (conf.empty()) conf = "0"; + std::string class_id = sqliteColumnText(stmt, 5); + if (class_id.empty()) class_id = "0"; + json << "{" + << "\"timestamp\":\"" << jsonEscape(sqliteColumnText(stmt, 0)) << "\"," + << "\"student_id\":\"" << jsonEscape(sqliteColumnText(stmt, 1)) << "\"," + << "\"name\":\"" << jsonEscape(sqliteColumnText(stmt, 2)) << "\"," + << "\"confidence\":" << conf << "," + << "\"status\":\"" << jsonEscape(sqliteColumnText(stmt, 4)) << "\"," + << "\"class_id\":\"" << jsonEscape(class_id) << "\"" + << "}"; + } + } + sqlite3_finalize(stmt); + sqlite3_close(db); + + json << "]"; + return json.str(); +} + +std::string getStatistics() { + sqlite3* db = openSqliteDb(); + if (!db) return "{\"total\":0,\"today\":0}"; + int total = 0; + int today = 0; + std::string todayDate = getCurrentTimestamp().substr(0, 10); + sqlite3_stmt* stmt = nullptr; + if (sqlite3_prepare_v2(db, "SELECT COUNT(*) FROM records", -1, &stmt, nullptr) == SQLITE_OK + && sqlite3_step(stmt) == SQLITE_ROW) { + total = sqlite3_column_int(stmt, 0); + } + sqlite3_finalize(stmt); + stmt = nullptr; + if (sqlite3_prepare_v2(db, "SELECT COUNT(*) FROM records WHERE substr(timestamp,1,10)=?", -1, &stmt, nullptr) == SQLITE_OK) { + sqliteBindText(stmt, 1, todayDate); + if (sqlite3_step(stmt) == SQLITE_ROW) { + today = sqlite3_column_int(stmt, 0); + } + } + sqlite3_finalize(stmt); + sqlite3_close(db); + + std::ostringstream json; + json << "{" + << "\"total\":" << total << "," + << "\"today\":" << today << "," + << "\"server_time\":\"" << getCurrentTimestamp() << "\"" + << "}"; + return json.str(); +} + +bool clearDatabase() { + sqlite3* db = openSqliteDb(); + if (!db) return false; + bool ok = sqliteExec(db, "DELETE FROM records"); + sqlite3_close(db); + return ok; +} + +// ============= 时间段配置管理 ============= +bool saveTimeSlots(const std::string& json_data) { + std::cout << "[TIMESLOTS] Attempting to save " << json_data.size() << " bytes" << std::endl; + + if (json_data.empty()) { + std::cerr << "[TIMESLOTS] ERROR: json_data is empty!" << std::endl; + return false; + } + + if (!sqliteSetKvValue("time_slots", json_data)) { + std::cerr << "[TIMESLOTS] Failed to save configuration to SQLite" << std::endl; + return false; + } + std::cout << "[TIMESLOTS] ✓ Configuration saved successfully to SQLite" << std::endl; + std::cout << "[TIMESLOTS] Preview: " << json_data.substr(0, 100) << "..." << std::endl; + return true; +} + +std::string readTimeSlots() { + std::string content = sqliteGetKvValue("time_slots", DEFAULT_TIMESLOTS_JSON); + std::cout << "[TIMESLOTS] Read " << content.size() << " bytes from SQLite" << std::endl; + return content; +} + +bool saveMappingConfig(const std::string& json_data) { + if (json_data.empty()) return false; + return sqliteSetKvValue("mapping_config", json_data); +} + +std::string readMappingConfig() { + return sqliteGetKvValue("mapping_config", "{\"student_name_map\":{},\"class_name_map\":{}}"); +} + +unsigned long long readSyncVersion() { + unsigned long long version = 1; + std::string value = sqliteGetKvValue("sync_version", "1"); + std::istringstream ss(value); + if (!(ss >> version)) { + version = 1; + } + if (version == 0) version = 1; + return version; +} + +unsigned long long bumpSyncVersion(const std::string& reason) { + unsigned long long version = readSyncVersion() + 1; + sqliteSetKvValue("sync_version", std::to_string(version)); + std::cout << "[SYNC] Version bumped to " << version << " (" << reason << ")" << std::endl; + return version; +} + +unsigned long long parseVersionParam(const std::map& params) { + auto it = params.find("last_version"); + if (it == params.end()) return 0; + unsigned long long value = 0; + for (char c : it->second) { + if (!std::isdigit(static_cast(c))) return 0; + value = value * 10 + static_cast(c - '0'); + } + return value; +} + +size_t findMatchingJsonEnd(const std::string& text, size_t start) { + if (start >= text.size()) return std::string::npos; + const char open = text[start]; + const char close = (open == '{') ? '}' : ']'; + int depth = 0; + bool in_string = false; + bool escape = false; + + for (size_t i = start; i < text.size(); ++i) { + char c = text[i]; + if (escape) { + escape = false; + continue; + } + if (c == '\\' && in_string) { + escape = true; + continue; + } + if (c == '"') { + in_string = !in_string; + continue; + } + if (in_string) continue; + if (c == open) depth++; + if (c == close) { + depth--; + if (depth == 0) return i; + } + } + return std::string::npos; +} + +std::string extractJsonMemberValue(const std::string& json, const std::string& key, const std::string& fallback) { + std::string marker = "\"" + key + "\":"; + size_t pos = json.find(marker); + if (pos == std::string::npos) return fallback; + pos += marker.size(); + while (pos < json.size() && std::isspace(static_cast(json[pos]))) pos++; + if (pos >= json.size()) return fallback; + + if (json[pos] == '{' || json[pos] == '[') { + size_t end = findMatchingJsonEnd(json, pos); + if (end != std::string::npos) { + return json.substr(pos, end - pos + 1); + } + } + + size_t end = json.find_first_of(",}", pos); + if (end != std::string::npos) { + return json.substr(pos, end - pos); + } + return fallback; +} + +std::string extractJsonStringValue(const std::string& json, const std::string& key, const std::string& fallback = "") { + std::string marker = "\"" + key + "\":\""; + size_t pos = json.find(marker); + if (pos == std::string::npos) return fallback; + pos += marker.size(); + size_t end = json.find("\"", pos); + if (end == std::string::npos) return fallback; + return json.substr(pos, end - pos); +} + +std::vector extractJsonStringArray(const std::string& json, const std::string& key) { + std::vector values; + std::string arr = extractJsonMemberValue(json, key, "[]"); + if (arr.size() < 2) return values; + size_t pos = 0; + while (pos < arr.size()) { + size_t start = arr.find("\"", pos); + if (start == std::string::npos) break; + size_t end = arr.find("\"", start + 1); + if (end == std::string::npos) break; + values.push_back(arr.substr(start + 1, end - start - 1)); + pos = end + 1; + } + return values; +} + +std::string makeSyncStateResponse(const std::string& client, unsigned long long last_version) { + const unsigned long long version = readSyncVersion(); + const bool changed = last_version < version; + + std::ostringstream json; + json << "{\"version\":" << version + << ",\"changed\":" << (changed ? "true" : "false") + << ",\"client\":\"" << jsonEscape(client) << "\"" + << ",\"server_time\":\"" << jsonEscape(getCurrentTimestamp()) << "\""; + + if (changed) { + json << ",\"state\":{"; + bool first = true; + + if (client == "k210" || client == "qt" || client == "all" || client.empty()) { + const std::string mappings = extractJsonMemberValue(readFaceIdMapping(), "mappings", "{}"); + const std::string pending = extractJsonMemberValue(getPendingDeleteList(), "pending_delete", "[]"); + json << "\"face_mappings\":" << mappings + << ",\"pending_delete\":" << pending; + first = false; + } + + if (client == "stm32" || client == "qt" || client == "all" || client.empty()) { + if (!first) json << ","; + const std::string slots = extractJsonMemberValue(readTimeSlots(), "time_slots", "[]"); + json << "\"time_slots\":" << slots; + first = false; + } + + if (client == "qt" || client == "all" || client.empty()) { + if (!first) json << ","; + std::string mapping_config = readMappingConfig(); + json << "\"mapping_config\":" << mapping_config + << ",\"face_photos\":" << extractJsonMemberValue(getFacePhotosList(), "photos", "[]") + << ",\"all_student_ids\":" << extractJsonMemberValue(getAllStudentIds(), "student_ids", "[]") + << ",\"records\":" << readDatabase(1000, 0) + << ",\"statistics\":" << getStatistics(); + } + + json << "}"; + } + + json << "}"; + return json.str(); +} + +std::string makeSyncAckResponse(const std::string& request_body) { + const std::string client = extractJsonStringValue(request_body, "client", "unknown"); + const std::vector deleted = extractJsonStringArray(request_body, "deleted"); + int confirmed_delete_count = 0; + + for (const std::string& id : deleted) { + if (!id.empty() && removeFromPendingDelete(id)) { + confirmed_delete_count++; + } + } + + if (confirmed_delete_count > 0) { + bumpSyncVersion("sync_ack_delete"); + } + + std::ostringstream json; + json << "{\"success\":true," + << "\"client\":\"" << jsonEscape(client) << "\"," + << "\"version\":" << readSyncVersion() << "," + << "\"confirmed_delete_count\":" << confirmed_delete_count << "}"; + return json.str(); +} + +std::string makeSyncVersionResponse() { + std::ostringstream json; + json << "{" + << "\"version\":" << readSyncVersion() << "," + << "\"server_time\":\"" << jsonEscape(getCurrentTimestamp()) << "\"" + << "}"; + return json.str(); +} + +std::string makeStorageStatusResponse() { + std::string quick_check_message; + const bool quick_ok = sqliteQuickCheck(quick_check_message); + sqlite3* db = openSqliteDb(); + + int records = 0; + int face_mappings = 0; + int pending_deletes = 0; + int face_photos = countFacePhotoFiles(); + if (db) { + records = sqliteCountRows(db, "records"); + face_mappings = sqliteCountRows(db, "face_mappings"); + pending_deletes = sqliteCountRows(db, "pending_delete"); + sqlite3_close(db); + } + + std::ostringstream json; + json << "{" + << "\"storage\":\"sqlite\"," + << "\"database\":\"" << jsonEscape(SQLITE_DB_FILE) << "\"," + << "\"ok\":" << (quick_ok ? "true" : "false") << "," + << "\"quick_check\":\"" << jsonEscape(quick_check_message) << "\"," + << "\"records\":" << records << "," + << "\"face_mappings\":" << face_mappings << "," + << "\"face_photos\":" << face_photos << "," + << "\"pending_deletes\":" << pending_deletes << "," + << "\"sync_version\":" << readSyncVersion() << "," + << "\"server_time\":\"" << jsonEscape(getCurrentTimestamp()) << "\"" + << "}"; + return json.str(); +} + +std::string makeHealthResponse() { + std::string quick_check_message; + const bool quick_ok = sqliteQuickCheck(quick_check_message); + std::ostringstream json; + json << "{" + << "\"status\":\"" << (quick_ok ? "healthy" : "degraded") << "\"," + << "\"time\":\"" << jsonEscape(getCurrentTimestamp()) << "\"," + << "\"storage\":\"sqlite\"," + << "\"database\":\"" << jsonEscape(SQLITE_DB_FILE) << "\"," + << "\"database_ok\":" << (quick_ok ? "true" : "false") << "," + << "\"quick_check\":\"" << jsonEscape(quick_check_message) << "\"," + << "\"sync_version\":" << readSyncVersion() + << "}"; + return json.str(); +} + +// ============= 检查重复签到 ============= +// 参数: student_id - 学号, slot_start - 时段开始时间(HH:MM), slot_end - 时段结束时间(HH:MM) +// 返回: JSON格式 {"duplicate": true/false, "record_time": "..."} +std::string checkDuplicate(const std::string& student_id, const std::string& slot_start, const std::string& slot_end) { + std::string todayDate = getCurrentTimestamp().substr(0, 10); + int start_hour = 0, start_minute = 0, end_hour = 23, end_minute = 59; + parseTimeParts(slot_start, start_hour, start_minute); + parseTimeParts(slot_end, end_hour, end_minute); + int start_total_minutes = start_hour * 60 + start_minute; + int end_total_minutes = end_hour * 60 + end_minute; + + sqlite3* db = openSqliteDb(); + if (!db) return "{\"duplicate\":false}"; + sqlite3_stmt* stmt = nullptr; + const char* sql = "SELECT timestamp FROM records WHERE student_id=? AND substr(timestamp,1,10)=? ORDER BY id DESC"; + if (sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) == SQLITE_OK) { + sqliteBindText(stmt, 1, student_id); + sqliteBindText(stmt, 2, todayDate); + while (sqlite3_step(stmt) == SQLITE_ROW) { + std::string timestamp = sqliteColumnText(stmt, 0); + if (timestamp.length() < 16) continue; + int record_hour = 0; + int record_minute = 0; + if (!parseIntInRange(timestamp.substr(11, 2), 0, 23, record_hour) + || !parseIntInRange(timestamp.substr(14, 2), 0, 59, record_minute)) continue; + int record_total_minutes = record_hour * 60 + record_minute; + if (record_total_minutes >= start_total_minutes && record_total_minutes <= end_total_minutes) { + sqlite3_finalize(stmt); + sqlite3_close(db); + std::cout << "[CHECK] Duplicate found: " << student_id << " at " << timestamp << std::endl; + return "{\"duplicate\":true,\"record_time\":\"" + jsonEscape(timestamp) + "\"}"; + } + } + } + sqlite3_finalize(stmt); + sqlite3_close(db); + return "{\"duplicate\":false}"; +} + +// ============= 删除记录 ============= +bool deleteRecord(const std::string& timestamp, const std::string& student_id) { + sqlite3* db = openSqliteDb(); + if (!db) return false; + sqlite3_stmt* stmt = nullptr; + const char* sql = "DELETE FROM records WHERE timestamp=? AND student_id=?"; + bool ok = false; + if (sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) == SQLITE_OK) { + sqliteBindText(stmt, 1, timestamp); + sqliteBindText(stmt, 2, student_id); + ok = sqlite3_step(stmt) == SQLITE_DONE && sqlite3_changes(db) > 0; + } + sqlite3_finalize(stmt); + sqlite3_close(db); + return ok; +} + +// ============= 人脸照片管理函数 ============= + +// 保存人脸ID映射配置 +bool saveFaceIdMapping(const std::string& json_data) { + std::cout << "[FACE_MAPPING] Saving " << json_data.size() << " bytes" << std::endl; + std::map mappings = parseFaceIdMappings(json_data); + sqlite3* db = openSqliteDb(); + if (!db) return false; + bool ok = sqliteExec(db, "BEGIN") && sqliteExec(db, "DELETE FROM face_mappings"); + sqlite3_stmt* stmt = nullptr; + const char* sql = "REPLACE INTO face_mappings(face_id,student_id) VALUES(?,?)"; + if (ok && sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) == SQLITE_OK) { + for (const auto& m : mappings) { + sqlite3_reset(stmt); + sqlite3_clear_bindings(stmt); + sqliteBindText(stmt, 1, m.first); + sqliteBindText(stmt, 2, m.second); + if (sqlite3_step(stmt) != SQLITE_DONE) { + ok = false; + break; + } + } + } else { + ok = false; + } + sqlite3_finalize(stmt); + sqliteExec(db, ok ? "COMMIT" : "ROLLBACK"); + sqlite3_close(db); + return ok; +} + +std::map parseFaceIdMappings(const std::string& json_data) { + // 解析JSON: {"mappings":{"1":"20210001","2":"20210002"}} + std::map mappings; + size_t mappings_start = json_data.find("\"mappings\":{"); + if (mappings_start == std::string::npos) return mappings; + + mappings_start += 12; // 跳过 "mappings":{ + size_t mappings_end = json_data.find("}", mappings_start); + if (mappings_end == std::string::npos) return mappings; + + std::string mappings_str = json_data.substr(mappings_start, mappings_end - mappings_start); + + // 解析每个映射对 + size_t pos = 0; + while (pos < mappings_str.length()) { + // 找到键 + size_t key_start = mappings_str.find("\"", pos); + if (key_start == std::string::npos) break; + size_t key_end = mappings_str.find("\"", key_start + 1); + if (key_end == std::string::npos) break; + + // 找到值 + size_t val_start = mappings_str.find("\"", key_end + 1); + if (val_start == std::string::npos) break; + size_t val_end = mappings_str.find("\"", val_start + 1); + if (val_end == std::string::npos) break; + + std::string key = mappings_str.substr(key_start + 1, key_end - key_start - 1); + std::string value = mappings_str.substr(val_start + 1, val_end - val_start - 1); + + if (!key.empty() && !value.empty()) { + mappings[key] = value; + } + + pos = val_end + 1; + } + + return mappings; +} + +std::map loadFaceIdMappings() { + std::map mappings; + sqlite3* db = openSqliteDb(); + if (!db) return mappings; + sqlite3_stmt* stmt = nullptr; + if (sqlite3_prepare_v2(db, "SELECT face_id,student_id FROM face_mappings ORDER BY face_id", -1, &stmt, nullptr) == SQLITE_OK) { + while (sqlite3_step(stmt) == SQLITE_ROW) { + mappings[sqliteColumnText(stmt, 0)] = sqliteColumnText(stmt, 1); + } + } + sqlite3_finalize(stmt); + sqlite3_close(db); + return mappings; +} + +std::set resolveK210FaceIdsForDelete(const std::string& requested_id) { + std::set ids; + bool matched_mapping = false; + + const auto mappings = loadFaceIdMappings(); + for (const auto& m : mappings) { + if (m.first == requested_id || m.second == requested_id) { + ids.insert(m.first); + matched_mapping = true; + } + } + if (!matched_mapping) { + ids.insert(requested_id); + } + return ids; +} + +std::set resolveStudentIdsForDelete(const std::string& requested_id) { + std::set ids; + ids.insert(requested_id); + + const auto mappings = loadFaceIdMappings(); + for (const auto& m : mappings) { + if (m.first == requested_id || m.second == requested_id) { + ids.insert(m.second); + } + } + return ids; +} + +// 根据映射重命名照片文件 +void renameFacePhotos(const std::string& json_data) { + std::cout << "[FACE_PHOTO] Renaming photos based on mapping..." << std::endl; + const std::map mappings = parseFaceIdMappings(json_data); + + // 遍历faces目录,重命名匹配的照片 + std::vector> rename_list; + +#ifdef _WIN32 + WIN32_FIND_DATAA findData; + std::string searchPath = FACES_DIR + "\\*.jpg"; + HANDLE hFind = FindFirstFileA(searchPath.c_str(), &findData); + if (hFind != INVALID_HANDLE_VALUE) { + do { + std::string filename = findData.cFileName; + std::string base_name = filename.substr(0, filename.length() - 4); // 去掉.jpg + + // 检查是否以某个face_id开头 + for (const auto& m : mappings) { + // 匹配 "face_id.jpg" 或 "face_id_xxx.jpg" + if (base_name == m.first || + (base_name.find(m.first + "_") == 0)) { + // 直接使用学号作为新文件名(不保留时间戳) + std::string new_filename = m.second + ".jpg"; + + if (filename != new_filename) { + rename_list.push_back({filename, new_filename}); + } + break; + } + } + } while (FindNextFileA(hFind, &findData)); + FindClose(hFind); + } +#else + DIR* dir = opendir(FACES_DIR.c_str()); + if (dir) { + struct dirent* entry; + while ((entry = readdir(dir)) != NULL) { + std::string filename = entry->d_name; + if (filename.size() > 4 && filename.substr(filename.size() - 4) == ".jpg") { + std::string base_name = filename.substr(0, filename.length() - 4); + + for (const auto& m : mappings) { + if (base_name == m.first || + (base_name.find(m.first + "_") == 0)) { + std::string new_filename = m.second + ".jpg"; + + if (filename != new_filename) { + rename_list.push_back({filename, new_filename}); + } + break; + } + } + } + } + closedir(dir); + } +#endif + + // 执行重命名 + for (const auto& r : rename_list) { + std::string old_id = r.first.substr(0, r.first.size() - 4); + std::string new_id = r.second.substr(0, r.second.size() - 4); + std::string old_path; + std::string new_path; + if (!buildFacePhotoPath(old_id, old_path) || !buildFacePhotoPath(new_id, new_path)) { + std::cerr << "[FACE_PHOTO] Skip unsafe rename: " << r.first << " -> " << r.second << std::endl; + continue; + } + + std::remove(new_path.c_str()); + + if (std::rename(old_path.c_str(), new_path.c_str()) == 0) { + std::cout << "[FACE_PHOTO] Renamed: " << r.first << " -> " << r.second << std::endl; + } else { + std::cerr << "[FACE_PHOTO] Rename failed: " << r.first << std::endl; + } + } + + std::cout << "[FACE_PHOTO] Renamed " << rename_list.size() << " photos" << std::endl; +} + +// 读取人脸ID映射配置 +std::string readFaceIdMapping() { + std::map mappings = loadFaceIdMappings(); + std::ostringstream json; + json << "{\"mappings\":{"; + bool first = true; + for (const auto& m : mappings) { + if (!first) json << ","; + json << "\"" << jsonEscape(m.first) << "\":\"" << jsonEscape(m.second) << "\""; + first = false; + } + json << "}}"; + return json.str(); +} + +// 获取人脸照片列表 +std::string getFacePhotosList() { + std::ostringstream json; + json << "{\"photos\":["; + + std::vector photos; + +#ifdef _WIN32 + WIN32_FIND_DATAA findData; + std::string searchPath = FACES_DIR + "\\*.jpg"; + HANDLE hFind = FindFirstFileA(searchPath.c_str(), &findData); + if (hFind != INVALID_HANDLE_VALUE) { + do { + photos.push_back(findData.cFileName); + } while (FindNextFileA(hFind, &findData)); + FindClose(hFind); + } +#else + DIR* dir = opendir(FACES_DIR.c_str()); + if (dir) { + struct dirent* entry; + while ((entry = readdir(dir)) != NULL) { + std::string name = entry->d_name; + if (name.size() > 4 && name.substr(name.size() - 4) == ".jpg") { + photos.push_back(name); + } + } + closedir(dir); + } +#endif + + std::sort(photos.begin(), photos.end()); + + for (size_t i = 0; i < photos.size(); ++i) { + if (i > 0) json << ","; + std::string id = photos[i].substr(0, photos[i].size() - 4); + json << "{\"id\":\"" << jsonEscape(id) << "\",\"filename\":\"" << jsonEscape(photos[i]) << "\"}"; + } + + json << "]}"; + return json.str(); +} + +// 保存人脸照片 +bool saveFacePhoto(const std::string& face_id, const std::string& photo_data) { + _mkdir(FACES_DIR.c_str()); + std::string filepath; + if (!buildFacePhotoPath(face_id, filepath)) { + std::cerr << "[FACE_PHOTO] Invalid face_id: " << face_id << std::endl; + return false; + } + std::ofstream file(filepath, std::ios::binary); + if (!file.is_open()) { + std::cerr << "[FACE_PHOTO] Failed to create: " << filepath << std::endl; + return false; + } + file.write(photo_data.c_str(), photo_data.size()); + file.close(); + std::cout << "[FACE_PHOTO] Saved: " << filepath << " (" << photo_data.size() << " bytes)" << std::endl; + return true; +} + +// 读取人脸照片 +std::string readFacePhoto(const std::string& face_id) { + std::string filepath; + if (!buildFacePhotoPath(face_id, filepath)) return ""; + std::ifstream file(filepath, std::ios::binary); + if (!file.is_open()) return ""; + std::string content((std::istreambuf_iterator(file)), std::istreambuf_iterator()); + file.close(); + return content; +} + +// 删除人脸照片 +bool deleteFacePhoto(const std::string& face_id) { + std::string filepath; + if (!buildFacePhotoPath(face_id, filepath)) return false; + if (std::remove(filepath.c_str()) == 0) { + std::cout << "[FACE_PHOTO] Deleted: " << filepath << std::endl; + return true; + } + return false; +} + +// 从人脸ID映射中删除指定ID +bool removeFaceIdFromMapping(const std::string& face_id) { + sqlite3* db = openSqliteDb(); + if (!db) return false; + sqlite3_stmt* stmt = nullptr; + bool ok = false; + if (sqlite3_prepare_v2(db, "DELETE FROM face_mappings WHERE face_id=?", -1, &stmt, nullptr) == SQLITE_OK) { + sqliteBindText(stmt, 1, face_id); + ok = sqlite3_step(stmt) == SQLITE_DONE && sqlite3_changes(db) > 0; + } + sqlite3_finalize(stmt); + sqlite3_close(db); + if (ok) std::cout << "[FACE_MAPPING] Removed face_id: " << face_id << std::endl; + return ok; +} + +// 删除指定学生ID的所有考勤记录 +int deleteRecordsByStudentId(const std::string& student_id) { + sqlite3* db = openSqliteDb(); + if (!db) return 0; + sqlite3_stmt* stmt = nullptr; + int deleted_count = 0; + if (sqlite3_prepare_v2(db, "DELETE FROM records WHERE student_id=?", -1, &stmt, nullptr) == SQLITE_OK) { + sqliteBindText(stmt, 1, student_id); + if (sqlite3_step(stmt) == SQLITE_DONE) { + deleted_count = sqlite3_changes(db); + } + } + sqlite3_finalize(stmt); + sqlite3_close(db); + return deleted_count; +} + +// 获取所有学生ID(从考勤记录提取,包括没有照片的) +std::string getAllStudentIds() { + std::set student_ids; + + sqlite3* db = openSqliteDb(); + if (db) { + sqlite3_stmt* stmt = nullptr; + if (sqlite3_prepare_v2(db, "SELECT DISTINCT student_id FROM records WHERE student_id<>'' ORDER BY student_id", -1, &stmt, nullptr) == SQLITE_OK) { + while (sqlite3_step(stmt) == SQLITE_ROW) { + student_ids.insert(sqliteColumnText(stmt, 0)); + } + } + sqlite3_finalize(stmt); + sqlite3_close(db); + } + + // 构建JSON响应 + std::ostringstream json; + json << "{\"student_ids\":["; + + bool first = true; + for (const auto& id : student_ids) { + if (!first) json << ","; + json << "\"" << jsonEscape(id) << "\""; + first = false; + } + + json << "]}"; + return json.str(); +} + +// 添加人脸ID到待删除列表 +bool addToPendingDelete(const std::string& face_id) { + sqlite3* db = openSqliteDb(); + if (!db) return false; + sqlite3_stmt* stmt = nullptr; + bool ok = false; + if (sqlite3_prepare_v2(db, "REPLACE INTO pending_delete(face_id) VALUES(?)", -1, &stmt, nullptr) == SQLITE_OK) { + sqliteBindText(stmt, 1, face_id); + ok = sqlite3_step(stmt) == SQLITE_DONE; + } + sqlite3_finalize(stmt); + sqlite3_close(db); + std::cout << "[PENDING_DELETE] Added: " << face_id << std::endl; + return ok; +} + +// 获取待删除列表 +std::string getPendingDeleteList() { + sqlite3* db = openSqliteDb(); + if (!db) return "{\"pending_delete\":[]}"; + sqlite3_stmt* stmt = nullptr; + std::ostringstream json; + json << "{\"pending_delete\":["; + bool first = true; + if (sqlite3_prepare_v2(db, "SELECT face_id FROM pending_delete ORDER BY face_id", -1, &stmt, nullptr) == SQLITE_OK) { + while (sqlite3_step(stmt) == SQLITE_ROW) { + if (!first) json << ","; + json << "\"" << jsonEscape(sqliteColumnText(stmt, 0)) << "\""; + first = false; + } + } + sqlite3_finalize(stmt); + sqlite3_close(db); + json << "]}"; + return json.str(); +} + +// 从待删除列表中移除指定ID(K210确认删除后调用) +bool removeFromPendingDelete(const std::string& face_id) { + sqlite3* db = openSqliteDb(); + if (!db) return false; + sqlite3_stmt* stmt = nullptr; + bool ok = false; + if (sqlite3_prepare_v2(db, "DELETE FROM pending_delete WHERE face_id=?", -1, &stmt, nullptr) == SQLITE_OK) { + sqliteBindText(stmt, 1, face_id); + ok = sqlite3_step(stmt) == SQLITE_DONE && sqlite3_changes(db) > 0; + } + sqlite3_finalize(stmt); + sqlite3_close(db); + std::cout << "[PENDING_DELETE] Removed: " << face_id << std::endl; + return ok; +} + +// ============= K210同步请求管理 ============= +// 设置同步请求标志(QT端调用) +bool setSyncRequest(bool sync) { + if (!sqliteSetKvValue("sync_request", std::string("{\"sync\":") + (sync ? "true" : "false") + "}")) { + return false; + } + std::cout << "[SYNC] Sync request set to: " << (sync ? "true" : "false") << std::endl; + return true; +} + +// 获取同步请求状态(K210轮询调用) +std::string getSyncRequest() { + return sqliteGetKvValue("sync_request", "{\"sync\":false}"); +} + +// 清除同步请求标志(K210确认后调用) +bool clearSyncRequest() { + return setSyncRequest(false); +} + +// 根据K210的face_id查询真实学号 +std::string getMappedStudentId(const std::string& face_id) { + std::cout << "[MAPPING] Looking up face_id: " << face_id << std::endl; + + const auto mappings = loadFaceIdMappings(); + auto it = mappings.find(face_id); + if (it != mappings.end() && !it->second.empty()) { + std::cout << "[MAPPING] ✓ Face ID " << face_id << " -> Student ID " << it->second << std::endl; + return it->second; + } + + std::cout << "[MAPPING] No mapping found for face_id: " << face_id << std::endl; + return face_id; // 没找到映射,返回原ID +} + +// ============= HTTP请求处理 ============= +void handleHttpRequest(SOCKET client_socket) { + char buffer[BUFFER_SIZE] = {0}; + int bytes = recv(client_socket, buffer, BUFFER_SIZE - 1, 0); + + if (bytes <= 0) { + closesocket(client_socket); + return; + } + + std::string request(buffer, bytes); + std::istringstream stream(request); + std::string method, path, version; + stream >> method >> path >> version; + + std::cout << "[HTTP] " << method << " " << path << std::endl; + + std::string response_body; + std::string content_type = "application/json"; + int status_code = 200; + std::string status_text = "OK"; + auto sendResponse = [&]() { + std::ostringstream response; + response << "HTTP/1.1 " << status_code << " " << status_text << "\r\n"; + response << "Content-Type: " << content_type << "; charset=utf-8\r\n"; + response << "Content-Length: " << response_body.length() << "\r\n"; + response << "Access-Control-Allow-Origin: " << allowedCorsOrigin() << "\r\n"; + response << "Access-Control-Allow-Headers: Content-Type, X-Api-Token, X-Encrypted-Response, X-Encrypted\r\n"; + response << "Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS\r\n"; + response << "Connection: close\r\n"; + response << "\r\n"; + response << response_body; + + std::string resp_str = response.str(); + send(client_socket, resp_str.c_str(), resp_str.length(), 0); + closesocket(client_socket); + }; + + std::string endpoint = path; + std::string query; + size_t q_pos = path.find('?'); + if (q_pos != std::string::npos) { + endpoint = path.substr(0, q_pos); + query = path.substr(q_pos + 1); + } + const std::string original_endpoint = endpoint; + endpoint = normalizeApiEndpoint(method, endpoint); + if (endpoint != original_endpoint) { + std::cout << "[HTTP] Route alias: " << original_endpoint << " -> " << endpoint << std::endl; + } + + if (!isAuthorizedRequest(request, method, endpoint)) { + response_body = makeJsonError("Unauthorized"); + status_code = 401; + status_text = "Unauthorized"; + sendResponse(); + return; + } + + // 提取请求体 + std::string request_body; + if (method == "POST") { + size_t content_length = 0; + std::string cl_str; + if (getHeaderValue(request, "Content-Length", cl_str)) { + int parsed_content_length = 0; + if (!parseIntInRange(cl_str, 0, static_cast(MAX_PHOTO_BODY_SIZE), parsed_content_length)) { + response_body = makeJsonError("Invalid Content-Length"); + status_code = 400; + status_text = "Bad Request"; + sendResponse(); + return; + } + content_length = static_cast(parsed_content_length); + } + + const bool is_photo_upload = endpoint.find("/api/face_photo") == 0; + const size_t max_body_size = is_photo_upload ? MAX_PHOTO_BODY_SIZE : MAX_JSON_BODY_SIZE; + if (content_length > max_body_size) { + response_body = makeJsonError("Request body too large"); + status_code = 413; + status_text = "Payload Too Large"; + sendResponse(); + return; + } + + size_t header_end = request.find("\r\n\r\n"); + if (header_end != std::string::npos) { + size_t body_start = header_end + 4; + size_t current_body_size = request.size() - body_start; + + if (current_body_size >= content_length) { + request_body = request.substr(body_start, content_length); + } else { + request_body = request.substr(body_start); + size_t remaining = content_length - current_body_size; + + while (remaining > 0) { + char extra_buffer[BUFFER_SIZE] = {0}; + int extra_bytes = recv(client_socket, extra_buffer, + static_cast(std::min(remaining, (size_t)BUFFER_SIZE)), 0); + if (extra_bytes <= 0) break; + + request_body.append(extra_buffer, extra_bytes); + remaining -= extra_bytes; + } + } + } + + std::cout << "[HTTP] POST body size: " << request_body.size() + << " bytes (expected: " << content_length << ")" << std::endl; + + if (request_body.size() != content_length) { + response_body = makeJsonError("Incomplete request body"); + status_code = 400; + status_text = "Bad Request"; + sendResponse(); + return; + } + } + + // ============= 路由处理 ============= + + if (method == "OPTIONS") { + response_body = "{}"; + + } else if (method == "GET" && endpoint == "/api/v1/sync/version") { + response_body = makeSyncVersionResponse(); + std::cout << "[SYNC] Version fetched: " << readSyncVersion() << std::endl; + + } else if (method == "GET" && (endpoint == "/api/sync/state" || endpoint == "/api/v1/sync/state")) { + auto params = parseQueryParams(query); + const std::string client = params.count("client") ? params["client"] : "all"; + const unsigned long long last_version = parseVersionParam(params); + response_body = makeSyncStateResponse(client, last_version); + std::cout << "[SYNC] State fetched: client=" << client + << ", last_version=" << last_version + << ", current_version=" << readSyncVersion() << std::endl; + + } else if (method == "POST" && (endpoint == "/api/sync/ack" || endpoint == "/api/v1/sync/ack")) { + response_body = makeSyncAckResponse(request_body); + std::cout << "[SYNC] Ack received: " << request_body << std::endl; + + // 新增:处理加密签到数据 + } else if (method == "POST" && endpoint == "/api/checkin") { + std::cout << "[CHECKIN] Processing encrypted checkin data..." << std::endl; + + // 检查是否是加密数据 + if (request.find("X-Encrypted: AES128-CBC") != std::string::npos) { + std::cout << "[CHECKIN] Encrypted data detected" << std::endl; + + // 解密数据 + std::string decrypted_json = decryptJSON(request_body); + + if (decrypted_json.empty()) { + response_body = "{\"success\":false,\"message\":\"解密失败\"}"; + status_code = 400; + status_text = "Bad Request"; + } else { + // 解析JSON + auto json_data = parseJSON(decrypted_json); + + if (json_data.find("student_id") != json_data.end()) { + // 构建考勤记录 + std::string timestamp = getCurrentTimestamp(); + std::string student_id = json_data["student_id"]; // K210已发送真实学号 + std::string name = json_data["name"]; + std::string confidence = json_data["confidence"]; + std::string status = json_data["status"]; + std::string class_id = json_data.count("class_id") ? json_data["class_id"] : "0"; + + std::cout << "[CHECKIN] Student ID: " << student_id << std::endl; + + // 保存到SQLite(包含班级编号) + if (saveAttendanceRecord(timestamp, student_id, name, confidence, status, class_id)) { + response_body = "{\"success\":true,\"message\":\"签到成功\",\"timestamp\":\"" + + jsonEscape(timestamp) + "\"}"; + bumpSyncVersion("checkin"); + std::cout << "[CHECKIN] ✓ " << name << " (ID:" << student_id << ", Class:" << class_id << ")" << std::endl; + } else { + response_body = "{\"success\":false,\"message\":\"数据库写入失败\"}"; + status_code = 500; + status_text = "Internal Server Error"; + } + } else { + response_body = "{\"success\":false,\"message\":\"缺少必要字段\"}"; + status_code = 400; + status_text = "Bad Request"; + } + } + } else { + response_body = "{\"success\":false,\"message\":\"未加密数据\"}"; + status_code = 400; + status_text = "Bad Request"; + } + } + // API端点:返回加密数据 + else if (method == "GET" && endpoint == "/api/records") { + auto params = parseQueryParams(query); + int limit = 100; + int offset = 0; + if (params.count("limit") && !parseIntInRange(params["limit"], 1, 5000, limit)) { + response_body = makeJsonError("Invalid limit"); + status_code = 400; + status_text = "Bad Request"; + } else if (params.count("offset") && !parseIntInRange(params["offset"], 0, 1000000, offset)) { + response_body = makeJsonError("Invalid offset"); + status_code = 400; + status_text = "Bad Request"; + } else { + + std::string json_data = readDatabase(limit, offset); + + if (hasHeaderToken(request, "X-Encrypted-Response", "true")) { + response_body = encryptJSON(json_data); + if (response_body.empty()) { + response_body = makeJsonError("Encryption failed"); + status_code = 500; + status_text = "Internal Server Error"; + } + } else { + response_body = json_data; + } + } + + } else if (method == "GET" && endpoint == "/api/statistics") { + std::string json_data = getStatistics(); + + if (hasHeaderToken(request, "X-Encrypted-Response", "true")) { + response_body = encryptJSON(json_data); + if (response_body.empty()) { + response_body = makeJsonError("Encryption failed"); + status_code = 500; + status_text = "Internal Server Error"; + } + } else { + response_body = json_data; + } + + } else if (method == "POST" && endpoint == "/api/clear") { + if (clearDatabase()) { + response_body = "{\"success\":true,\"message\":\"Database cleared\"}"; + bumpSyncVersion("clear_records"); + } else { + response_body = "{\"success\":false,\"message\":\"Failed to clear database\"}"; + status_code = 500; + status_text = "Internal Server Error"; + } + + } else if (method == "DELETE" && endpoint == "/api/record") { + auto params = parseQueryParams(query); + if (params.count("timestamp") && params.count("student_id")) { + std::string timestamp = params["timestamp"]; + std::string student_id = params["student_id"]; + + if (deleteRecord(timestamp, student_id)) { + response_body = "{\"success\":true,\"message\":\"Record deleted\"}"; + bumpSyncVersion("delete_record"); + } else { + response_body = "{\"success\":false,\"message\":\"Record not found\"}"; + status_code = 404; + status_text = "Not Found"; + } + } else { + response_body = "{\"success\":false,\"message\":\"Missing parameters\"}"; + status_code = 400; + status_text = "Bad Request"; + } + + } else if (method == "GET" && endpoint == "/api/health") { + response_body = makeHealthResponse(); + + } else if (method == "GET" && endpoint == "/api/v1/system/storage") { + response_body = makeStorageStatusResponse(); + + } else if (method == "GET" && endpoint == "/api/time") { + // 返回服务器当前Unix时间戳(UTC秒)和可读时间 + std::ostringstream json; + json << "{" + << "\"epoch\":" << static_cast(time(0)) << "," + << "\"server_time\":\"" << getCurrentTimestamp() << "\"" + << "}"; + response_body = json.str(); + + } else if (method == "POST" && endpoint == "/api/timeslots") { + // 上传时间段配置: POST /api/timeslots + std::cout << "[TIMESLOTS] Received upload request, data size: " << request_body.size() << " bytes" << std::endl; + + if (saveTimeSlots(request_body)) { + response_body = "{\"success\":true,\"message\":\"时间段配置已更新\"}"; + bumpSyncVersion("timeslots"); + std::cout << "[TIMESLOTS] ✓ Configuration uploaded successfully" << std::endl; + } else { + response_body = "{\"success\":false,\"message\":\"保存时间段配置失败\"}"; + status_code = 500; + status_text = "Internal Server Error"; + } + + } else if (method == "GET" && endpoint == "/api/timeslots") { + // 获取时间段配置: GET /api/timeslots + std::cout << "[TIMESLOTS] Reading configuration" << std::endl; + response_body = readTimeSlots(); + + } else if (method == "GET" && endpoint == "/api/check_duplicate") { + // 检查重复签到: GET /api/check_duplicate?student_id=xxx&slot_start=08:00&slot_end=09:30 + auto params = parseQueryParams(query); + if (params.count("student_id") && params.count("slot_start") && params.count("slot_end")) { + response_body = checkDuplicate(params["student_id"], params["slot_start"], params["slot_end"]); + std::cout << "[CHECK] student_id=" << params["student_id"] + << ", slot=" << params["slot_start"] << "-" << params["slot_end"] + << ", result=" << response_body << std::endl; + } else { + response_body = "{\"error\":\"Missing parameters: student_id, slot_start, slot_end\"}"; + status_code = 400; + status_text = "Bad Request"; + } + + } else if (method == "GET" && endpoint == "/api/today_records") { + // 获取今日已签到记录(供STM32开机下载) + // GET /api/today_records?slot_start=08:00&slot_end=09:30 + auto params = parseQueryParams(query); + std::string slot_start = params.count("slot_start") ? params["slot_start"] : "00:00"; + std::string slot_end = params.count("slot_end") ? params["slot_end"] : "23:59"; + + std::string todayDate = getCurrentTimestamp().substr(0, 10); + + int start_hour = 0, start_minute = 0, end_hour = 23, end_minute = 59; + parseTimeParts(slot_start, start_hour, start_minute); + parseTimeParts(slot_end, end_hour, end_minute); + + std::ostringstream json; + json << "{\"date\":\"" << jsonEscape(todayDate) << "\",\"records\":["; + + sqlite3* db = openSqliteDb(); + if (db) { + sqlite3_stmt* stmt = nullptr; + bool first = true; + const char* sql = "SELECT timestamp,student_id FROM records WHERE substr(timestamp,1,10)=? ORDER BY id ASC"; + if (sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) == SQLITE_OK) { + sqliteBindText(stmt, 1, todayDate); + while (sqlite3_step(stmt) == SQLITE_ROW) { + std::string timestamp = sqliteColumnText(stmt, 0); + if (timestamp.length() < 16) continue; + int record_hour = 0; + int record_minute = 0; + if (!parseIntInRange(timestamp.substr(11, 2), 0, 23, record_hour) + || !parseIntInRange(timestamp.substr(14, 2), 0, 59, record_minute)) continue; + int record_total = record_hour * 60 + record_minute; + int start_total = start_hour * 60 + start_minute; + int end_total = end_hour * 60 + end_minute; + + if (record_total < start_total || record_total > end_total) continue; + if (!first) json << ","; + json << "\"" << jsonEscape(sqliteColumnText(stmt, 1)) << "\""; + first = false; + } + } + sqlite3_finalize(stmt); + sqlite3_close(db); + } + + json << "]}"; + response_body = json.str(); + std::cout << "[TODAY] Returning today's records: " << response_body << std::endl; + + } else if (method == "POST" && endpoint == "/api/mapping_config") { + // 上传映射配置: POST /api/mapping_config + std::cout << "[MAPPING] Received upload request, data size: " << request_body.size() << " bytes" << std::endl; + + if (saveMappingConfig(request_body)) { + response_body = "{\"success\":true,\"message\":\"映射配置已保存\"}"; + bumpSyncVersion("mapping_config"); + std::cout << "[MAPPING] ✓ Configuration saved successfully" << std::endl; + } else { + response_body = "{\"success\":false,\"message\":\"保存映射配置失败\"}"; + status_code = 500; + status_text = "Internal Server Error"; + } + + } else if (method == "GET" && endpoint == "/api/mapping_config") { + // 获取映射配置: GET /api/mapping_config + std::cout << "[MAPPING] Reading configuration" << std::endl; + + response_body = readMappingConfig(); + std::cout << "[MAPPING] Returning config: " << response_body.size() << " bytes" << std::endl; + + // ============= 人脸照片管理 API ============= + } else if (method == "GET" && endpoint == "/api/face_photos") { + // 获取人脸照片列表 + _mkdir(FACES_DIR.c_str()); + response_body = getFacePhotosList(); + std::cout << "[FACE_PHOTO] Photos list fetched" << std::endl; + + } else if (method == "GET" && endpoint.find("/api/face_photo/") == 0) { + // 获取指定人脸照片: GET /api/face_photo/ + std::string face_id = urlDecode(endpoint.substr(16)); + std::string photo_data = readFacePhoto(face_id); + + if (!photo_data.empty()) { + response_body = photo_data; + content_type = "image/jpeg"; + std::cout << "[FACE_PHOTO] Photo fetched for id: " << face_id << std::endl; + } else { + response_body = "{\"error\":\"Photo not found\"}"; + status_code = 404; + status_text = "Not Found"; + } + + } else if (method == "POST" && endpoint.find("/api/face_photo_simple/") == 0) { + // 简化版人脸照片上传: POST /api/face_photo_simple/ + std::string face_id = urlDecode(endpoint.substr(23)); + std::cout << "[FACE_PHOTO] Simple upload for face_id: " << face_id << ", size: " << request_body.size() << " bytes" << std::endl; + + if (!isSafeId(face_id)) { + response_body = "{\"success\":false,\"message\":\"Invalid face_id\"}"; + status_code = 400; + status_text = "Bad Request"; + } else if (!request_body.empty()) { + if (saveFacePhoto(face_id, request_body)) { + response_body = "{\"success\":true,\"message\":\"Photo saved\",\"face_id\":\"" + jsonEscape(face_id) + "\"}"; + bumpSyncVersion("face_photo"); + } else { + response_body = "{\"success\":false,\"message\":\"Failed to save photo\"}"; + status_code = 500; + status_text = "Internal Server Error"; + } + } else { + response_body = "{\"success\":false,\"message\":\"Invalid face_id or empty data\"}"; + status_code = 400; + status_text = "Bad Request"; + } + + } else if (method == "POST" && endpoint == "/api/face_id_mapping") { + // 保存人脸ID映射 + std::cout << "[FACE_MAPPING] Saving mapping, size: " << request_body.size() << " bytes" << std::endl; + if (saveFaceIdMapping(request_body)) { + // 根据新映射重命名照片文件 + renameFacePhotos(request_body); + // 自动触发K210同步 + bumpSyncVersion("face_id_mapping"); + setSyncRequest(true); + std::cout << "[FACE_MAPPING] Auto-triggered K210 sync" << std::endl; + response_body = "{\"success\":true,\"message\":\"Face ID mapping saved, K210 sync triggered\"}"; + } else { + response_body = "{\"success\":false,\"message\":\"Failed to save mapping\"}"; + status_code = 500; + status_text = "Internal Server Error"; + } + + } else if (method == "GET" && endpoint == "/api/face_id_mapping") { + // 获取人脸ID映射 + response_body = readFaceIdMapping(); + std::cout << "[FACE_MAPPING] Mapping fetched" << std::endl; + + } else if (method == "GET" && endpoint == "/api/all_student_ids") { + // 获取所有学生ID(从考勤记录提取) + response_body = getAllStudentIds(); + std::cout << "[STUDENT_IDS] All student IDs fetched" << std::endl; + + } else if (method == "DELETE" && endpoint.find("/api/face/") == 0) { + // 删除人脸信息: DELETE /api/face/?delete_records=true + std::string student_id = urlDecode(endpoint.substr(10)); // 去掉 "/api/face/" + auto params = parseQueryParams(query); + bool delete_records = (params.count("delete_records") && params["delete_records"] == "true"); + + std::cout << "[DELETE_FACE] Deleting face for student_id: " << student_id + << ", delete_records: " << (delete_records ? "yes" : "no") << std::endl; + + if (!isSafeId(student_id)) { + response_body = "{\"success\":false,\"message\":\"Invalid student_id\"}"; + status_code = 400; + status_text = "Bad Request"; + } else { + const std::set k210_face_ids = resolveK210FaceIdsForDelete(student_id); + const std::set student_ids = resolveStudentIdsForDelete(student_id); + bool photo_deleted = deleteFacePhoto(student_id); + bool mapping_deleted = removeFaceIdFromMapping(student_id); + int records_deleted = 0; + + if (delete_records) { + for (const auto& id : student_ids) { + records_deleted += deleteRecordsByStudentId(id); + } + } + + // 添加K210原始face_id到待删除列表,等待K210同步删除本地特征 + bool pending_added = false; + for (const auto& face_id : k210_face_ids) { + if (face_id != student_id) { + photo_deleted = deleteFacePhoto(face_id) || photo_deleted; + mapping_deleted = removeFaceIdFromMapping(face_id) || mapping_deleted; + } + pending_added = addToPendingDelete(face_id) || pending_added; + } + for (const auto& id : student_ids) { + photo_deleted = deleteFacePhoto(id) || photo_deleted; + } + bumpSyncVersion("delete_face"); + setSyncRequest(true); + + std::ostringstream result; + result << "{\"success\":true," + << "\"photo_deleted\":" << (photo_deleted ? "true" : "false") << "," + << "\"mapping_deleted\":" << (mapping_deleted ? "true" : "false") << "," + << "\"records_deleted\":" << records_deleted << "," + << "\"k210_pending\":" << (pending_added ? "true" : "false") << "," + << "\"sync_requested\":true}"; + response_body = result.str(); + + std::cout << "[DELETE_FACE] Result: " << response_body << std::endl; + } + + } else if (method == "GET" && endpoint == "/api/pending_delete") { + // K210查询待删除列表 + response_body = getPendingDeleteList(); + std::cout << "[PENDING_DELETE] List fetched" << std::endl; + + } else if (method == "POST" && endpoint == "/api/confirm_delete") { + // K210确认删除完成,从待删除列表移除 + // 请求体格式: {"face_id":"xxx"} + std::string face_id; + size_t pos = request_body.find("\"face_id\":\""); + if (pos != std::string::npos) { + size_t start = pos + 11; + size_t end = request_body.find("\"", start); + if (end != std::string::npos) { + face_id = request_body.substr(start, end - start); + } + } + + if (!face_id.empty() && removeFromPendingDelete(face_id)) { + response_body = "{\"success\":true,\"message\":\"Confirmed delete: " + jsonEscape(face_id) + "\"}"; + bumpSyncVersion("confirm_delete"); + std::cout << "[PENDING_DELETE] K210 confirmed delete: " << face_id << std::endl; + } else { + response_body = "{\"success\":false,\"message\":\"Invalid face_id or not in pending list\"}"; + status_code = 400; + status_text = "Bad Request"; + } + + // ============= K210同步请求 API ============= + } else if (method == "GET" && endpoint == "/api/sync_request") { + // K210查询是否需要同步 + response_body = getSyncRequest(); + std::cout << "[SYNC] K210 checking sync request: " << response_body << std::endl; + + } else if (method == "POST" && endpoint == "/api/sync_ack") { + // K210确认收到同步请求,清除标志 + if (clearSyncRequest()) { + response_body = "{\"success\":true,\"message\":\"Sync acknowledged\"}"; + std::cout << "[SYNC] K210 acknowledged sync request" << std::endl; + } else { + response_body = "{\"success\":false,\"message\":\"Failed to clear sync request\"}"; + status_code = 500; + status_text = "Internal Server Error"; + } + + } else if (method == "POST" && endpoint == "/api/trigger_sync") { + // QT端触发K210同步 + if (setSyncRequest(true)) { + response_body = "{\"success\":true,\"message\":\"Sync request sent to K210\"}"; + std::cout << "[SYNC] QT triggered K210 sync" << std::endl; + } else { + response_body = "{\"success\":false,\"message\":\"Failed to set sync request\"}"; + status_code = 500; + status_text = "Internal Server Error"; + } + + } else { + response_body = "{\"error\":\"Not Found\"}"; + status_code = 404; + status_text = "Not Found"; + } + + sendResponse(); +} + +// ============= HTTP服务器线程 ============= +void httpServerThread() { + SOCKET server_socket = socket(AF_INET, SOCK_STREAM, 0); + if (server_socket == INVALID_SOCKET) { + std::cerr << "[HTTP] Failed to create socket" << std::endl; + return; + } + + int opt = 1; + setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)); + + sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(HTTP_PORT); + + if (bind(server_socket, (sockaddr*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) { + std::cerr << "[HTTP] Bind failed" << std::endl; + closesocket(server_socket); + return; + } + + listen(server_socket, 10); + std::cout << "[HTTP] Server listening on port " << HTTP_PORT << std::endl; + + while (true) { + sockaddr_in client_addr; + socklen_t client_len = sizeof(client_addr); + SOCKET client_socket = accept(server_socket, (sockaddr*)&client_addr, &client_len); + + if (client_socket != INVALID_SOCKET) { + std::thread(handleHttpRequest, client_socket).detach(); + } + } +} + +int main() { +#ifdef _WIN32 + WSADATA wsa; + WSAStartup(MAKEWORD(2, 2), &wsa); +#endif + + std::cout << "========================================" << std::endl; + std::cout << " Face Recognition Attendance Server" << std::endl; + std::cout << " with AES-128-CBC Encryption" << std::endl; + std::cout << "========================================" << std::endl; + std::cout << "HTTP Port " << HTTP_PORT << " - Encrypted API" << std::endl; + std::cout << "Database: " << SQLITE_DB_FILE << std::endl; + std::cout << "----------------------------------------" << std::endl; + + // 初始化SQLite,并首次导入旧CSV/JSON配置 + if (!initializeSqliteStorage()) { + std::cerr << "[SQLITE] Failed to initialize storage" << std::endl; + return 1; + } + std::cout << "[SYNC] Current version: " << readSyncVersion() << std::endl; + + // 启动HTTP服务器 + std::thread http_thread(httpServerThread); + http_thread.join(); + +#ifdef _WIN32 + WSACleanup(); +#endif + + return 0; +} diff --git a/server/tiny_aes.hpp b/server/tiny_aes.hpp new file mode 100644 index 0000000..f285859 --- /dev/null +++ b/server/tiny_aes.hpp @@ -0,0 +1,291 @@ +/* + * Tiny AES128 C++ 移植版本 + * 与STM32端使用相同的AES实现,保证兼容性 + */ + +#ifndef _TINY_AES_HPP_ +#define _TINY_AES_HPP_ + +#include +#include + +#define AES_BLOCKLEN 16 +#define AES_KEYLEN 16 +#define AES_keyExpSize 176 + +struct AES_ctx +{ + uint8_t RoundKey[AES_keyExpSize]; + uint8_t Iv[AES_BLOCKLEN]; +}; + +// S-box +static const uint8_t sbox[256] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +// Inverse S-box +static const uint8_t rsbox[256] = { + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d +}; + +// Rcon +static const uint8_t Rcon[11] = { + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 +}; + +#define getSBoxValue(num) (sbox[(num)]) +#define getSBoxInvert(num) (rsbox[(num)]) + +// 导出这些函数供外部使用 +void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key); +void InvCipher(uint8_t* state, const uint8_t* RoundKey); + +inline void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) +{ + unsigned i, j, k; + uint8_t tempa[4]; + + for (i = 0; i < 4; ++i) { + RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; + RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; + RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; + RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; + } + + for (i = 4; i < 44; ++i) { + k = (i - 1) * 4; + tempa[0] = RoundKey[k + 0]; + tempa[1] = RoundKey[k + 1]; + tempa[2] = RoundKey[k + 2]; + tempa[3] = RoundKey[k + 3]; + + if (i % 4 == 0) { + const uint8_t u8tmp = tempa[0]; + tempa[0] = tempa[1]; + tempa[1] = tempa[2]; + tempa[2] = tempa[3]; + tempa[3] = u8tmp; + + tempa[0] = getSBoxValue(tempa[0]); + tempa[1] = getSBoxValue(tempa[1]); + tempa[2] = getSBoxValue(tempa[2]); + tempa[3] = getSBoxValue(tempa[3]); + + tempa[0] = tempa[0] ^ Rcon[i / 4]; + } + + j = i * 4; k = (i - 4) * 4; + RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0]; + RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1]; + RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2]; + RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3]; + } +} + +static void AddRoundKey(uint8_t round, uint8_t* state, const uint8_t* RoundKey) +{ + uint8_t i, j; + for (i = 0; i < 4; ++i) { + for (j = 0; j < 4; ++j) { + state[i * 4 + j] ^= RoundKey[(round * 16) + (i * 4 + j)]; + } + } +} + +static void SubBytes(uint8_t* state) +{ + uint8_t i; + for (i = 0; i < 16; ++i) { + state[i] = getSBoxValue(state[i]); + } +} + +static void InvSubBytes(uint8_t* state) +{ + uint8_t i; + for (i = 0; i < 16; ++i) { + state[i] = getSBoxInvert(state[i]); + } +} + +static void ShiftRows(uint8_t* state) +{ + uint8_t temp; + temp = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = temp; + + temp = state[2]; + state[2] = state[10]; + state[10] = temp; + temp = state[6]; + state[6] = state[14]; + state[14] = temp; + + temp = state[15]; + state[15] = state[11]; + state[11] = state[7]; + state[7] = state[3]; + state[3] = temp; +} + +static void InvShiftRows(uint8_t* state) +{ + uint8_t temp; + temp = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = temp; + + temp = state[2]; + state[2] = state[10]; + state[10] = temp; + temp = state[6]; + state[6] = state[14]; + state[14] = temp; + + temp = state[3]; + state[3] = state[7]; + state[7] = state[11]; + state[11] = state[15]; + state[15] = temp; +} + +static uint8_t xtime(uint8_t x) +{ + return ((x << 1) ^ (((x >> 7) & 1) * 0x1b)); +} + +static void MixColumns(uint8_t* state) +{ + uint8_t i; + uint8_t Tmp, Tm, t; + for (i = 0; i < 4; ++i) { + t = state[i * 4 + 0]; + Tmp = state[i * 4 + 0] ^ state[i * 4 + 1] ^ state[i * 4 + 2] ^ state[i * 4 + 3]; + Tm = state[i * 4 + 0] ^ state[i * 4 + 1]; Tm = xtime(Tm); state[i * 4 + 0] ^= Tm ^ Tmp; + Tm = state[i * 4 + 1] ^ state[i * 4 + 2]; Tm = xtime(Tm); state[i * 4 + 1] ^= Tm ^ Tmp; + Tm = state[i * 4 + 2] ^ state[i * 4 + 3]; Tm = xtime(Tm); state[i * 4 + 2] ^= Tm ^ Tmp; + Tm = state[i * 4 + 3] ^ t; Tm = xtime(Tm); state[i * 4 + 3] ^= Tm ^ Tmp; + } +} + +static uint8_t Multiply(uint8_t x, uint8_t y) +{ + return (((y & 1) * x) ^ + ((y >> 1 & 1) * xtime(x)) ^ + ((y >> 2 & 1) * xtime(xtime(x))) ^ + ((y >> 3 & 1) * xtime(xtime(xtime(x)))) ^ + ((y >> 4 & 1) * xtime(xtime(xtime(xtime(x)))))); +} + +static void InvMixColumns(uint8_t* state) +{ + int i; + uint8_t a, b, c, d; + for (i = 0; i < 4; ++i) { + a = state[i * 4 + 0]; + b = state[i * 4 + 1]; + c = state[i * 4 + 2]; + d = state[i * 4 + 3]; + + state[i * 4 + 0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); + state[i * 4 + 1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); + state[i * 4 + 2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); + state[i * 4 + 3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); + } +} + +static void Cipher(uint8_t* state, const uint8_t* RoundKey) +{ + uint8_t round = 0; + + AddRoundKey(0, state, RoundKey); + + for (round = 1; ; ++round) { + SubBytes(state); + ShiftRows(state); + if (round == 10) { + break; + } + MixColumns(state); + AddRoundKey(round, state, RoundKey); + } + AddRoundKey(10, state, RoundKey); +} + +inline void InvCipher(uint8_t* state, const uint8_t* RoundKey) +{ + uint8_t round = 0; + + AddRoundKey(10, state, RoundKey); + + for (round = 9; ; --round) { + InvShiftRows(state); + InvSubBytes(state); + AddRoundKey(round, state, RoundKey); + if (round == 0) { + break; + } + InvMixColumns(state); + } +} + +inline void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv) +{ + KeyExpansion(ctx->RoundKey, key); + memcpy(ctx->Iv, iv, AES_BLOCKLEN); +} + +inline void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) +{ + size_t i; + uint8_t storeNextIv[AES_BLOCKLEN]; + + for (i = 0; i < length; i += AES_BLOCKLEN) { + memcpy(storeNextIv, buf + i, AES_BLOCKLEN); + InvCipher(buf + i, ctx->RoundKey); + + uint8_t j; + for (j = 0; j < AES_BLOCKLEN; ++j) { + buf[i + j] ^= ctx->Iv[j]; + } + memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN); + } +} + +#endif // _TINY_AES_HPP_ diff --git a/连接图.md b/连接图.md new file mode 100644 index 0000000..cc90e01 --- /dev/null +++ b/连接图.md @@ -0,0 +1,22 @@ +| 外设模块 | STM32引脚 | 功能说明 | 电气参数 | +| ------------------ | -------------------- | ----------------- | --------------- | +| **ESP8266-stm32 (WiFi)** | PA9 (USART1_TX) | 发送数据到ESP8266 | 3.3V, 115200bps | +| | PA10 (USART1_RX) | 接收ESP8266数据 | 3.3V | +| **K210 (AI视觉)** | PB10 (USART3_TX) | 发送命令到K210 | 3.3V, 115200bps | +| | PB11 (USART3_RX) | 接收识别结果 | 3.3V | +| **OLED显示屏** | PB8 (I2C_SCL) | I2C时钟信号 | 3.3V, 400kHz | +| | PB9 (I2C_SDA) | I2C数据信号 | 3.3V | +| **调试串口** | PA2 (USART2_TX) | 调试信息输出 | 3.3V, 115200bps | +| | PA3 (USART2_RX) | 调试信息输入 | 3.3V | +| **LED指示灯** | PB4 | 绿色LED控制 | 高电平点亮 | +| **蜂鸣器** | PB5 | 蜂鸣器控制 | 低电平触发 | +| **光敏传感器** | PB0 | 检测环境光照强度 (ADC输入) | 3.3V | +| **补光灯(LED)** | PB1 | 作为补光灯 | 高电平点亮 | +| **DS1302 时钟** | CLK | PA4 | GPIO模拟时序 | +| | DAT | PA5 | GPIO模拟时序 | +| | RST | PA6 | GPIO模拟时序 | + +| 外设模块 | K210 引脚 | 功能说明 | 电气参数 | +| ----------------------- | ------------- | ----------------- | --------------- | +| **ESP8266-k210 (WiFi)** | 34 (USART_TX) | 发送数据到ESP8266 | 3.3V, 115200bps | +| | 35 (USART_RX) | 接收ESP8266数据 | 3.3V |