Compare commits

...
10 Commits
Author SHA1 Message Date
cbb c357a8af6f feat(cbuild): 更新GD32C10x_DFP包到1.5.0版本并修复多个设备驱动文件
更新了项目中使用的GD32C10x_DFP包从1.0.1版本升级到1.5.0版本,
同时更新了多个RTE设备驱动文件以匹配新版本固件,包括ADC、BKP、CAN、CRC、CTC、DAC、DBG、DMA、EXMC、EXTI、FMC等外设驱动。修复了CAN驱动中的消息传输逻辑,改进了错误处理机制,并统一了标志位获取函数的返回值处理方式。
2026-05-05 23:39:10 +08:00
cbb 46d4bfe8ef feat(bootloader): 实现APP延迟启动模式支持OTA请求检测
当APP可用但未激活时,系统现在会进入延迟启动模式,在指定时间内
监听CAN总线上的OTA请求。如果在此期间收到OTA请求,则进入OTA模式;
否则超时后自动跳转到APP。

新增配置参数APP_DELAY_BOOT_TIME用于设置延迟启动时间,默认为10秒。
在延迟期间,系统持续进行CAN通信检查和OTA心跳消息发送,确保能够
及时响应OTA更新请求。

此功能增强了系统的OTA更新灵活性,允许在启动过程中动态决定
是否进行固件更新而不是强制进入OTA模式。
2026-04-26 03:36:45 +08:00
cbb d019b41ed6 feat(CAN): 实现CAN FD协议栈优化和发送队列机制
- 将CAN收发缓冲区扩展至64字节以支持CAN FD协议
- 添加发送队列机制防止高负载时消息丢失
- 优化中断处理流程,直接读取消息数据避免DMA竞争
- 修改编译配置指向Release版本目录
- 调整OTA处理逻辑将Flash擦除操作移至主循环执行

BREAKING CHANGE: 缓冲区大小调整可能影响现有CAN通信协议实现
2026-04-26 02:27:34 +08:00
cbb 26cf5af14f 修复BOOT丢帧问题,优化标志位的存储 2026-03-08 01:08:27 +08:00
cbb 1e6d47ddae feat(bootloader): 添加了完整的系统休眠和唤醒机制,包括:
- 实现深睡眠模式下的功耗优化
- 添加PB8引脚的外部中断唤醒功能
- 新增Flash区域用于睡眠状态管理
- 实现睡眠配置的自动检查和恢复逻辑

同时重构了OTA_SET函数,改进了Flash配置参数的写入机制,
解决了GD32 Flash特性导致的0到1写入问题,并添加了详细的
调试信息输出和错误处理。
2026-01-12 01:06:05 +08:00
cbb aefb7d4ee4 feat(ota): 修复备份APP区域恢复功能和OTA流程优化、启用BRS、减小延时
- 添加sendBackup方法用于在备份APP激活时发送确认消息
- 优化OTA跳转逻辑,在jumpToApplication中清除复位标志
- 修复move_app_data函数中数据源地址错误,从备份区域正确读取数据
- 在OTA流程中正确设置APP状态标志,确保应用验证状态管理

refactor(can): 清理调试代码和函数签名优化

- 移除调试用的printf语句和未使用的cstdio头文件
- 统一函数参数类型为u8和u32,提高代码一致性
- 优化CAN通信检查逻辑,移除冗余的调试输出

perf(ota): 优化OTA处理中的延时函数

- 将delay_1ms(1)改为delay_1us(100),提高延时精度
- 添加微秒级延时函数delay_1us实现
- 增加OTA超时时间从10秒到100秒

fix(ota): 修复OTA状态管理和错误处理

- 在各种错误情况下正确设置ota_state为OTA_STATE_IDLE
- 在eraseApplicationArea中正确初始化APP状态标志
- 添加CRC校验失败时的调试输出选项
- 修复数据包大小验证逻辑
2026-01-07 23:14:15 +08:00
cbb c7c4451d57 refactor(build): 支持A/B分区逻辑
移除sys/flash.h、sys/flash.cpp、sys/initial.h和sys/OTA相关文件的
引用,清理cproject.yml和cbuild.yml中的未使用组件和文件配置。

BREAKING CHANGE: 移除了FlashEEPROM相关功能和接口。
2026-01-05 00:52:20 +08:00
cbb 2f482554f0 feat(ota): OTA功能测试通过,CANFD解包效率优化
- 添加OTA固件升级功能,包括应用程序验证和跳转机制
- 实现CANFD数据传输协议,支持加密和CRC校验
- 优化CAN通信处理,添加调试输出和错误处理
- 更新RTE组件配置,升级csolution版本到2.12.0
- 增加Flash擦除和写入的安全验证机制
- 添加应用程序区域扫描和验证功能

refactor(can): 重构CAN通信模块和OTA数据处理

- 移除未使用的常量定义和辅助函数
- 改进数据解包和加密解密流程
- 添加条件编译调试输出
- 优化Flash操作的安全性和可靠性

chore(build): 更新项目配置和忽略文件

- 添加tmp/和out/目录到.gitignore
- 扩展ROM0_SIZE从0x0020000到0x08005000
- 添加bin输出格式支持
2026-01-03 18:00:28 +08:00
cbb 9c7145ef99 feat(ota): 实现安全OTA更新协议支持AES加密和CRC校验
- 添加AES128加密解密功能支持安全固件传输
- 实现基于随机数握手的安全会话密钥协商机制
- 集成CRC32带密钥校验确保数据完整性
- 重构OTA状态机支持握手、数据传输和验证流程
- 添加CANFD数据长度规范处理和安全跳转逻辑
- 移除调试打印语句优化性能

refactor(can): 优化CANFD发送和OTA确认处理逻辑

- 重构CANFD_AsyncSend函数支持规范数据长度
- 重命名sendACK为sendDATA_ACK并添加重载函数
- 修复数据长度处理和缓冲区填充逻辑
- 优化CAN消息发送的数据复制和验证流程
- 移除未使用的联合体类型定义

chore(project): 添加AES加密模块和系统初始化配置

- 在项目配置中添加AES128加密解密文件
- 在main.cpp中初始化CRC外设模块
- 添加安全十六进制打印调试函数
- 集成AES加密库到OTA处理流程中
- 优化系统时钟初始化配置
2026-01-01 01:39:19 +08:00
cbb a25ec5f029 基础响应功能的实现 2025-12-27 19:20:23 +08:00
825 changed files with 5220 additions and 5331 deletions
+84
View File
@@ -0,0 +1,84 @@
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# Clangd
.clangd
# uv2csolution generated log file
uv2csolution.log
# CMSIS Solution files and folders not to be tracked
# default directory of build artifacts
**/out
# directory containing intermediate files to be regenerated
**/tmp
# Update config files must be merged before commit
*.update@*
# cbuild output files
*.cbuild.yml
*.cbuild-idx.yml
*.cbuild-run.yml
*.cbuild-set.yml
# .vscode JSON and debug adapter files generated by CMSIS Solution
.vscode/launch.json
.vscode/tasks.json
.vscode/settings.json
.cmd.jlink
# legacy intermediate project file
*.cprj
tmp/
out/
+20 -4
View File
@@ -1,5 +1,5 @@
build-idx:
generated-by: csolution version 2.12.0+p41-gfeadfc5e
generated-by: csolution version 2.13.0+p3-g40b6564e
cdefault: ${CMSIS_COMPILER_ROOT}/cdefault.yml
csolution: Robot_V2.csolution.yml
cbuild-run: out/Robot_V2+GD32C103CB.cbuild-run.yml
@@ -11,7 +11,23 @@ build-idx:
project: Robot_V2
configuration: .Release+GD32C103CB
messages:
warnings:
- file 'G:/Robot_v2/BOOT/Robot_V2/RTE/Device/GD32C103CB/gd32c10x_can.c' update recommended; merge content from update file, rename update file to base file and remove previous base file
- file 'G:/Robot_v2/BOOT/Robot_V2/RTE/Device/GD32C103CB/gd32c10x_crc.c' update recommended; merge content from update file, rename update file to base file and remove previous base file
- file 'G:/Robot_v2/BOOT/Robot_V2/RTE/Device/GD32C103CB/gd32c10x_dbg.c' update recommended; merge content from update file, rename update file to base file and remove previous base file
- file 'G:/Robot_v2/BOOT/Robot_V2/RTE/Device/GD32C103CB/gd32c10x_dma.c' update recommended; merge content from update file, rename update file to base file and remove previous base file
- file 'G:/Robot_v2/BOOT/Robot_V2/RTE/Device/GD32C103CB/gd32c10x_eval.c' update recommended; merge content from update file, rename update file to base file and remove previous base file
- file 'G:/Robot_v2/BOOT/Robot_V2/RTE/Device/GD32C103CB/gd32c10x_exti.c' update recommended; merge content from update file, rename update file to base file and remove previous base file
- file 'G:/Robot_v2/BOOT/Robot_V2/RTE/Device/GD32C103CB/gd32c10x_fmc.c' update recommended; merge content from update file, rename update file to base file and remove previous base file
- file 'G:/Robot_v2/BOOT/Robot_V2/RTE/Device/GD32C103CB/gd32c10x_fwdgt.c' update recommended; merge content from update file, rename update file to base file and remove previous base file
- file 'G:/Robot_v2/BOOT/Robot_V2/RTE/Device/GD32C103CB/gd32c10x_gpio.c' update recommended; merge content from update file, rename update file to base file and remove previous base file
- file 'G:/Robot_v2/BOOT/Robot_V2/RTE/Device/GD32C103CB/gd32c10x_misc.c' update recommended; merge content from update file, rename update file to base file and remove previous base file
- file 'G:/Robot_v2/BOOT/Robot_V2/RTE/Device/GD32C103CB/gd32c10x_pmu.c' update recommended; merge content from update file, rename update file to base file and remove previous base file
- file 'G:/Robot_v2/BOOT/Robot_V2/RTE/Device/GD32C103CB/gd32c10x_rcu.c' update recommended; merge content from update file, rename update file to base file and remove previous base file
- file 'G:/Robot_v2/BOOT/Robot_V2/RTE/Device/GD32C103CB/gd32c10x_usart.c' update recommended; merge content from update file, rename update file to base file and remove previous base file
- file 'G:/Robot_v2/BOOT/Robot_V2/RTE/Device/GD32C103CB/startup_gd32c10x.s' update recommended; merge content from update file, rename update file to base file and remove previous base file
- file 'G:/Robot_v2/BOOT/Robot_V2/RTE/Device/GD32C103CB/system_gd32c10x.c' update recommended; merge content from update file, rename update file to base file and remove previous base file
info:
- Robot_V2.cbuild-pack.yml - file is already up-to-date
- Robot_V2+GD32C103CB.cbuild-run.yml - file is already up-to-date
- Robot_V2.Release+GD32C103CB.cbuild.yml - file is already up-to-date
- Robot_V2.cbuild-pack.yml - file generated successfully
- Robot_V2+GD32C103CB.cbuild-run.yml - file generated successfully
- Robot_V2.Release+GD32C103CB.cbuild.yml - file generated successfully
+1 -1
View File
@@ -3,6 +3,6 @@ cbuild-pack:
- resolved-pack: ARM::CMSIS@4.5.0
selected-by-pack:
- ARM::CMSIS
- resolved-pack: GigaDevice::GD32C10x_DFP@1.0.1
- resolved-pack: GigaDevice::GD32C10x_DFP@1.5.0
selected-by-pack:
- GigaDevice::GD32C10x_DFP
+2 -2
View File
@@ -1,6 +1,6 @@
# A solution is a collection of related projects that share same base configuration.
solution:
created-for: CMSIS-Toolbox@2.12.0
created-for: CMSIS-Toolbox@2.13.0
cdefault: # use CMSIS-Toolbox default Compiler options
# Compilers that can be selected
@@ -33,7 +33,7 @@ solution:
- project-context: Robot_V2.Release
debugger:
name: ST-Link@pyOCD
clock: 10000000
clock: 4000000
protocol: swd
# List of different build configurations.
+409 -409
View File
@@ -1,415 +1,415 @@
CompileFlags:
CompilationDatabase: g:\Robot_v2\BOOT\out\Robot_V2\GD32C103CB\Release
Add:
- '-D_ILP32=1'
- '-D_USE_STATIC_INLINE=1'
- '-D__APCS_32__=1'
- '-D__ARMCC_VERSION=6240002'
- '-D__ARMCOMPILER_VERSION=6240002'
- '-D__ARMEL__=1'
- '-D__ARM_32BIT_STATE=1'
- '-D__ARM_ACLE=200'
- '-D__ARM_ARCH=7'
- '-D__ARM_ARCH_7EM__=1'
- '-D__ARM_ARCH_EXT_IDIV__=1'
- '-D__ARM_ARCH_ISA_THUMB=2'
- '-D__ARM_ARCH_PROFILE=''M'''
- '-D__ARM_EABI__=1'
- '-D__ARM_FEATURE_CLZ=1'
- '-D__ARM_FEATURE_COPROC=0xf'
- '-D__ARM_FEATURE_DSP=1'
- '-D__ARM_FEATURE_FMA=1'
- '-D__ARM_FEATURE_IDIV=1'
- '-D__ARM_FEATURE_LDREX=0x7'
- '-D__ARM_FEATURE_QBIT=1'
- '-D__ARM_FEATURE_SAT=1'
- '-D__ARM_FEATURE_SIMD32=1'
- '-D__ARM_FEATURE_UNALIGNED=1'
- '-D__ARM_FP=0x6'
- '-D__ARM_FP16_ARGS=1'
- '-D__ARM_FP16_FORMAT_IEEE=1'
- '-D__ARM_NO_IMAGINARY_TYPE=1'
- '-D__ARM_PCS=1'
- '-D__ARM_PCS_VFP=1'
- '-D__ARM_PROMISE=__builtin_assume'
- '-D__ARM_SIZEOF_MINIMAL_ENUM=1'
- '-D__ARM_SIZEOF_WCHAR_T=2'
- '-D__ARM_VFPV2__=1'
- '-D__ARM_VFPV3__=1'
- '-D__ARM_VFPV4__=1'
- '-D__ATOMIC_ACQUIRE=2'
- '-D__ATOMIC_ACQ_REL=4'
- '-D__ATOMIC_CONSUME=1'
- '-D__ATOMIC_RELAXED=0'
- '-D__ATOMIC_RELEASE=3'
- '-D__ATOMIC_SEQ_CST=5'
- '-D__BIGGEST_ALIGNMENT__=8'
- '-D__BITINT_MAXWIDTH__=128'
- '-D__BOOL_WIDTH__=8'
- '-D__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__'
- '-D__CHAR16_TYPE__=unsigned short'
- '-D__CHAR32_TYPE__=unsigned int'
- '-D__CHAR_BIT__=8'
- '-D__CHAR_UNSIGNED__=1'
- '-D__CLANG_ATOMIC_BOOL_LOCK_FREE=2'
- '-D__CLANG_ATOMIC_CHAR16_T_LOCK_FREE=2'
- '-D__CLANG_ATOMIC_CHAR32_T_LOCK_FREE=2'
- '-D__CLANG_ATOMIC_CHAR_LOCK_FREE=2'
- '-D__CLANG_ATOMIC_INT_LOCK_FREE=2'
- '-D__CLANG_ATOMIC_LLONG_LOCK_FREE=1'
- '-D__CLANG_ATOMIC_LONG_LOCK_FREE=2'
- '-D__CLANG_ATOMIC_POINTER_LOCK_FREE=2'
- '-D__CLANG_ATOMIC_SHORT_LOCK_FREE=2'
- '-D__CLANG_ATOMIC_WCHAR_T_LOCK_FREE=2'
- '-D__CONSTANT_CFSTRINGS__=1'
- '-D__DBL_DECIMAL_DIG__=17'
- '-D__DBL_DENORM_MIN__=4.9406564584124654e-324'
- '-D__DBL_DIG__=15'
- '-D__DBL_EPSILON__=2.2204460492503131e-16'
- '-D__DBL_HAS_DENORM__=1'
- '-D__DBL_HAS_INFINITY__=1'
- '-D__DBL_HAS_QUIET_NAN__=1'
- '-D__DBL_MANT_DIG__=53'
- '-D__DBL_MAX_10_EXP__=308'
- '-D__DBL_MAX_EXP__=1024'
- '-D__DBL_MAX__=1.7976931348623157e+308'
- '-D__DBL_MIN_10_EXP__=(-307)'
- '-D__DBL_MIN_EXP__=(-1021)'
- '-D__DBL_MIN__=2.2250738585072014e-308'
- '-D__DBL_NORM_MAX__=1.7976931348623157e+308'
- '-D__DECIMAL_DIG__=__LDBL_DECIMAL_DIG__'
- '-D__ELF__=1'
- '-D__ESCAPE__='
- '-D__FINITE_MATH_ONLY__=1'
- '-D__FLT16_DECIMAL_DIG__=5'
- '-D__FLT16_DENORM_MIN__=5.9604644775390625e-8F16'
- '-D__FLT16_DIG__=3'
- '-D__FLT16_EPSILON__=9.765625e-4F16'
- '-D__FLT16_HAS_DENORM__=1'
- '-D__FLT16_HAS_INFINITY__=1'
- '-D__FLT16_HAS_QUIET_NAN__=1'
- '-D__FLT16_MANT_DIG__=11'
- '-D__FLT16_MAX_10_EXP__=4'
- '-D__FLT16_MAX_EXP__=16'
- '-D__FLT16_MAX__=6.5504e+4F16'
- '-D__FLT16_MIN_10_EXP__=(-4)'
- '-D__FLT16_MIN_EXP__=(-13)'
- '-D__FLT16_MIN__=6.103515625e-5F16'
- '-D__FLT16_NORM_MAX__=6.5504e+4F16'
- '-D__FLT_DECIMAL_DIG__=9'
- '-D__FLT_DENORM_MIN__=1.40129846e-45F'
- '-D__FLT_DIG__=6'
- '-D__FLT_EPSILON__=1.19209290e-7F'
- '-D__FLT_HAS_DENORM__=1'
- '-D__FLT_HAS_INFINITY__=1'
- '-D__FLT_HAS_QUIET_NAN__=1'
- '-D__FLT_MANT_DIG__=24'
- '-D__FLT_MAX_10_EXP__=38'
- '-D__FLT_MAX_EXP__=128'
- '-D__FLT_MAX__=3.40282347e+38F'
- '-D__FLT_MIN_10_EXP__=(-37)'
- '-D__FLT_MIN_EXP__=(-125)'
- '-D__FLT_MIN__=1.17549435e-38F'
- '-D__FLT_NORM_MAX__=3.40282347e+38F'
- '-D__FLT_RADIX__=2'
- '-D__FPCLASS_NEGINF=0x0004'
- '-D__FPCLASS_NEGNORMAL=0x0008'
- '-D__FPCLASS_NEGSUBNORMAL=0x0010'
- '-D__FPCLASS_NEGZERO=0x0020'
- '-D__FPCLASS_POSINF=0x0200'
- '-D__FPCLASS_POSNORMAL=0x0100'
- '-D__FPCLASS_POSSUBNORMAL=0x0080'
- '-D__FPCLASS_POSZERO=0x0040'
- '-D__FPCLASS_QNAN=0x0002'
- '-D__FPCLASS_SNAN=0x0001'
- '-D__GCC_ATOMIC_BOOL_LOCK_FREE=2'
- '-D__GCC_ATOMIC_CHAR16_T_LOCK_FREE=2'
- '-D__GCC_ATOMIC_CHAR32_T_LOCK_FREE=2'
- '-D__GCC_ATOMIC_CHAR_LOCK_FREE=2'
- '-D__GCC_ATOMIC_INT_LOCK_FREE=2'
- '-D__GCC_ATOMIC_LLONG_LOCK_FREE=1'
- '-D__GCC_ATOMIC_LONG_LOCK_FREE=2'
- '-D__GCC_ATOMIC_POINTER_LOCK_FREE=2'
- '-D__GCC_ATOMIC_SHORT_LOCK_FREE=2'
- '-D__GCC_ATOMIC_TEST_AND_SET_TRUEVAL=1'
- '-D__GCC_ATOMIC_WCHAR_T_LOCK_FREE=2'
- '-D__GCC_CONSTRUCTIVE_SIZE=64'
- '-D__GCC_DESTRUCTIVE_SIZE=64'
- '-D__GCC_HAVE_DWARF2_CFI_ASM=1'
- '-D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1=1'
- '-D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2=1'
- '-D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4=1'
- '-D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8=1'
- '-D__GNUC_MINOR__=2'
- '-D__GNUC_PATCHLEVEL__=1'
- '-D__GNUC_STDC_INLINE__=1'
- '-D__GNUC__=4'
- '-D__GXX_ABI_VERSION=1002'
- '-D__ILP32__=1'
- '-D__INT16_C_SUFFIX__='
- '-D__INT16_FMTd__="hd"'
- '-D__INT16_FMTi__="hi"'
- '-D__INT16_MAX__=32767'
- '-D__INT16_TYPE__=short'
- '-D__INT32_C_SUFFIX__='
- '-D__INT32_FMTd__="d"'
- '-D__INT32_FMTi__="i"'
- '-D__INT32_MAX__=2147483647'
- '-D__INT32_TYPE__=int'
- '-D__INT64_C_SUFFIX__=LL'
- '-D__INT64_FMTd__="lld"'
- '-D__INT64_FMTi__="lli"'
- '-D__INT64_MAX__=9223372036854775807LL'
- '-D__INT64_TYPE__=long long int'
- '-D__INT8_C_SUFFIX__='
- '-D__INT8_FMTd__="hhd"'
- '-D__INT8_FMTi__="hhi"'
- '-D__INT8_MAX__=127'
- '-D__INT8_TYPE__=signed char'
- '-D__INTMAX_C_SUFFIX__=LL'
- '-D__INTMAX_FMTd__="lld"'
- '-D__INTMAX_FMTi__="lli"'
- '-D__INTMAX_MAX__=9223372036854775807LL'
- '-D__INTMAX_TYPE__=long long int'
- '-D__INTMAX_WIDTH__=64'
- '-D__INTPTR_FMTd__="d"'
- '-D__INTPTR_FMTi__="i"'
- '-D__INTPTR_MAX__=2147483647'
- '-D__INTPTR_TYPE__=int'
- '-D__INTPTR_WIDTH__=32'
- '-D__INT_FAST16_FMTd__="hd"'
- '-D__INT_FAST16_FMTi__="hi"'
- '-D__INT_FAST16_MAX__=32767'
- '-D__INT_FAST16_TYPE__=short'
- '-D__INT_FAST16_WIDTH__=16'
- '-D__INT_FAST32_FMTd__="d"'
- '-D__INT_FAST32_FMTi__="i"'
- '-D__INT_FAST32_MAX__=2147483647'
- '-D__INT_FAST32_TYPE__=int'
- '-D__INT_FAST32_WIDTH__=32'
- '-D__INT_FAST64_FMTd__="lld"'
- '-D__INT_FAST64_FMTi__="lli"'
- '-D__INT_FAST64_MAX__=9223372036854775807LL'
- '-D__INT_FAST64_TYPE__=long long int'
- '-D__INT_FAST64_WIDTH__=64'
- '-D__INT_FAST8_FMTd__="hhd"'
- '-D__INT_FAST8_FMTi__="hhi"'
- '-D__INT_FAST8_MAX__=127'
- '-D__INT_FAST8_TYPE__=signed char'
- '-D__INT_FAST8_WIDTH__=8'
- '-D__INT_LEAST16_FMTd__="hd"'
- '-D__INT_LEAST16_FMTi__="hi"'
- '-D__INT_LEAST16_MAX__=32767'
- '-D__INT_LEAST16_TYPE__=short'
- '-D__INT_LEAST16_WIDTH__=16'
- '-D__INT_LEAST32_FMTd__="d"'
- '-D__INT_LEAST32_FMTi__="i"'
- '-D__INT_LEAST32_MAX__=2147483647'
- '-D__INT_LEAST32_TYPE__=int'
- '-D__INT_LEAST32_WIDTH__=32'
- '-D__INT_LEAST64_FMTd__="lld"'
- '-D__INT_LEAST64_FMTi__="lli"'
- '-D__INT_LEAST64_MAX__=9223372036854775807LL'
- '-D__INT_LEAST64_TYPE__=long long int'
- '-D__INT_LEAST64_WIDTH__=64'
- '-D__INT_LEAST8_FMTd__="hhd"'
- '-D__INT_LEAST8_FMTi__="hhi"'
- '-D__INT_LEAST8_MAX__=127'
- '-D__INT_LEAST8_TYPE__=signed char'
- '-D__INT_LEAST8_WIDTH__=8'
- '-D__INT_MAX__=2147483647'
- '-D__INT_WIDTH__=32'
- '-D__I__=1.0if'
- '-D__LDBL_DECIMAL_DIG__=17'
- '-D__LDBL_DENORM_MIN__=4.9406564584124654e-324L'
- '-D__LDBL_DIG__=15'
- '-D__LDBL_EPSILON__=2.2204460492503131e-16L'
- '-D__LDBL_HAS_DENORM__=1'
- '-D__LDBL_HAS_INFINITY__=1'
- '-D__LDBL_HAS_QUIET_NAN__=1'
- '-D__LDBL_MANT_DIG__=53'
- '-D__LDBL_MAX_10_EXP__=308'
- '-D__LDBL_MAX_EXP__=1024'
- '-D__LDBL_MAX__=1.7976931348623157e+308L'
- '-D__LDBL_MIN_10_EXP__=(-307)'
- '-D__LDBL_MIN_EXP__=(-1021)'
- '-D__LDBL_MIN__=2.2250738585072014e-308L'
- '-D__LDBL_NORM_MAX__=1.7976931348623157e+308L'
- '-D__LITTLE_ENDIAN__=1'
- '-D__LLONG_WIDTH__=64'
- '-D__LONG_LONG_MAX__=9223372036854775807LL'
- '-D__LONG_MAX__=2147483647L'
- '-D__LONG_WIDTH__=32'
- '-D__MEMORY_SCOPE_DEVICE=1'
- '-D__MEMORY_SCOPE_SINGLE=4'
- '-D__MEMORY_SCOPE_SYSTEM=0'
- '-D__MEMORY_SCOPE_WRKGRP=2'
- '-D__MEMORY_SCOPE_WVFRNT=3'
- '-D__OBJC_BOOL_IS_BOOL=0'
- '-D__OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES=3'
- '-D__OPENCL_MEMORY_SCOPE_DEVICE=2'
- '-D__OPENCL_MEMORY_SCOPE_SUB_GROUP=4'
- '-D__OPENCL_MEMORY_SCOPE_WORK_GROUP=1'
- '-D__OPENCL_MEMORY_SCOPE_WORK_ITEM=0'
- '-D__OPTIMIZE__=1'
- '-D__ORDER_BIG_ENDIAN__=4321'
- '-D__ORDER_LITTLE_ENDIAN__=1234'
- '-D__ORDER_PDP_ENDIAN__=3412'
- '-D__POINTER_WIDTH__=32'
- '-D__PRAGMA_REDEFINE_EXTNAME=1'
- '-D__PTRDIFF_FMTd__="d"'
- '-D__PTRDIFF_FMTi__="i"'
- '-D__PTRDIFF_MAX__=2147483647'
- '-D__PTRDIFF_TYPE__=int'
- '-D__PTRDIFF_WIDTH__=32'
- '-D__REGISTER_PREFIX__='
- '-D__SCHAR_MAX__=127'
- '-D__SHRT_MAX__=32767'
- '-D__SHRT_WIDTH__=16'
- '-D__SIG_ATOMIC_MAX__=2147483647'
- '-D__SIG_ATOMIC_WIDTH__=32'
- '-D__SIZEOF_DOUBLE__=8'
- '-D__SIZEOF_FLOAT__=4'
- '-D__SIZEOF_INT__=4'
- '-D__SIZEOF_LONG_DOUBLE__=8'
- '-D__SIZEOF_LONG_LONG__=8'
- '-D__SIZEOF_LONG__=4'
- '-D__SIZEOF_POINTER__=4'
- '-D__SIZEOF_PTRDIFF_T__=4'
- '-D__SIZEOF_SHORT__=2'
- '-D__SIZEOF_SIZE_T__=4'
- '-D__SIZEOF_WCHAR_T__=2'
- '-D__SIZEOF_WINT_T__=4'
- '-D__SIZE_FMTX__="X"'
- '-D__SIZE_FMTo__="o"'
- '-D__SIZE_FMTu__="u"'
- '-D__SIZE_FMTx__="x"'
- '-D__SIZE_MAX__=4294967295U'
- '-D__SIZE_TYPE__=unsigned int'
- '-D__SIZE_WIDTH__=32'
- '-D__STDC_EMBED_EMPTY__=2'
- '-D__STDC_EMBED_FOUND__=1'
- '-D__STDC_EMBED_NOT_FOUND__=0'
- '-D__STDC_HOSTED__=1'
- '-D__STDC_UTF_16__=1'
- '-D__STDC_UTF_32__=1'
- '-D__STDC_VERSION__=201710L'
- '-D__STDC__=1'
- '-D__THUMBEL__=1'
- '-D__THUMB_INTERWORK__=1'
- '-D__UINT16_C_SUFFIX__='
- '-D__UINT16_FMTX__="hX"'
- '-D__UINT16_FMTo__="ho"'
- '-D__UINT16_FMTu__="hu"'
- '-D__UINT16_FMTx__="hx"'
- '-D__UINT16_MAX__=65535'
- '-D__UINT16_TYPE__=unsigned short'
- '-D__UINT32_C_SUFFIX__=U'
- '-D__UINT32_FMTX__="X"'
- '-D__UINT32_FMTo__="o"'
- '-D__UINT32_FMTu__="u"'
- '-D__UINT32_FMTx__="x"'
- '-D__UINT32_MAX__=4294967295U'
- '-D__UINT32_TYPE__=unsigned int'
- '-D__UINT64_C_SUFFIX__=ULL'
- '-D__UINT64_FMTX__="llX"'
- '-D__UINT64_FMTo__="llo"'
- '-D__UINT64_FMTu__="llu"'
- '-D__UINT64_FMTx__="llx"'
- '-D__UINT64_MAX__=18446744073709551615ULL'
- '-D__UINT64_TYPE__=long long unsigned int'
- '-D__UINT8_C_SUFFIX__='
- '-D__UINT8_FMTX__="hhX"'
- '-D__UINT8_FMTo__="hho"'
- '-D__UINT8_FMTu__="hhu"'
- '-D__UINT8_FMTx__="hhx"'
- '-D__UINT8_MAX__=255'
- '-D__UINT8_TYPE__=unsigned char'
- '-D__UINTMAX_C_SUFFIX__=ULL'
- '-D__UINTMAX_FMTX__="llX"'
- '-D__UINTMAX_FMTo__="llo"'
- '-D__UINTMAX_FMTu__="llu"'
- '-D__UINTMAX_FMTx__="llx"'
- '-D__UINTMAX_MAX__=18446744073709551615ULL'
- '-D__UINTMAX_TYPE__=long long unsigned int'
- '-D__UINTMAX_WIDTH__=64'
- '-D__UINTPTR_FMTX__="X"'
- '-D__UINTPTR_FMTo__="o"'
- '-D__UINTPTR_FMTu__="u"'
- '-D__UINTPTR_FMTx__="x"'
- '-D__UINTPTR_MAX__=4294967295U'
- '-D__UINTPTR_TYPE__=unsigned int'
- '-D__UINTPTR_WIDTH__=32'
- '-D__UINT_FAST16_FMTX__="hX"'
- '-D__UINT_FAST16_FMTo__="ho"'
- '-D__UINT_FAST16_FMTu__="hu"'
- '-D__UINT_FAST16_FMTx__="hx"'
- '-D__UINT_FAST16_MAX__=65535'
- '-D__UINT_FAST16_TYPE__=unsigned short'
- '-D__UINT_FAST32_FMTX__="X"'
- '-D__UINT_FAST32_FMTo__="o"'
- '-D__UINT_FAST32_FMTu__="u"'
- '-D__UINT_FAST32_FMTx__="x"'
- '-D__UINT_FAST32_MAX__=4294967295U'
- '-D__UINT_FAST32_TYPE__=unsigned int'
- '-D__UINT_FAST64_FMTX__="llX"'
- '-D__UINT_FAST64_FMTo__="llo"'
- '-D__UINT_FAST64_FMTu__="llu"'
- '-D__UINT_FAST64_FMTx__="llx"'
- '-D__UINT_FAST64_MAX__=18446744073709551615ULL'
- '-D__UINT_FAST64_TYPE__=long long unsigned int'
- '-D__UINT_FAST8_FMTX__="hhX"'
- '-D__UINT_FAST8_FMTo__="hho"'
- '-D__UINT_FAST8_FMTu__="hhu"'
- '-D__UINT_FAST8_FMTx__="hhx"'
- '-D__UINT_FAST8_MAX__=255'
- '-D__UINT_FAST8_TYPE__=unsigned char'
- '-D__UINT_LEAST16_FMTX__="hX"'
- '-D__UINT_LEAST16_FMTo__="ho"'
- '-D__UINT_LEAST16_FMTu__="hu"'
- '-D__UINT_LEAST16_FMTx__="hx"'
- '-D__UINT_LEAST16_MAX__=65535'
- '-D__UINT_LEAST16_TYPE__=unsigned short'
- '-D__UINT_LEAST32_FMTX__="X"'
- '-D__UINT_LEAST32_FMTo__="o"'
- '-D__UINT_LEAST32_FMTu__="u"'
- '-D__UINT_LEAST32_FMTx__="x"'
- '-D__UINT_LEAST32_MAX__=4294967295U'
- '-D__UINT_LEAST32_TYPE__=unsigned int'
- '-D__UINT_LEAST64_FMTX__="llX"'
- '-D__UINT_LEAST64_FMTo__="llo"'
- '-D__UINT_LEAST64_FMTu__="llu"'
- '-D__UINT_LEAST64_FMTx__="llx"'
- '-D__UINT_LEAST64_MAX__=18446744073709551615ULL'
- '-D__UINT_LEAST64_TYPE__=long long unsigned int'
- '-D__UINT_LEAST8_FMTX__="hhX"'
- '-D__UINT_LEAST8_FMTo__="hho"'
- '-D__UINT_LEAST8_FMTu__="hhu"'
- '-D__UINT_LEAST8_FMTx__="hhx"'
- '-D__UINT_LEAST8_MAX__=255'
- '-D__UINT_LEAST8_TYPE__=unsigned char'
- '-D__USER_LABEL_PREFIX__='
- '-D__VERSION__="Clang 20.0.0git"'
- '-D__VFP_FP__=1'
- '-D__WCHAR_MAX__=65535'
- '-D__WCHAR_TYPE__=unsigned short'
- '-D__WCHAR_UNSIGNED__=1'
- '-D__WCHAR_WIDTH__=16'
- '-D__WINT_MAX__=2147483647'
- '-D__WINT_TYPE__=int'
- '-D__WINT_WIDTH__=32'
- '-D__arm=1'
- '-D__arm__=1'
- '-D__clang__=1'
- '-D__clang_literal_encoding__="UTF-8"'
- '-D__clang_major__=20'
- '-D__clang_minor__=0'
- '-D__clang_patchlevel__=0'
- '-D__clang_version__="20.0.0git "'
- '-D__clang_wide_literal_encoding__="UTF-16"'
- '-D__llvm__=1'
- '-D__thumb2__=1'
- '-D__thumb__=1'
- "-D_ILP32=1\r\n"
- "-D_USE_STATIC_INLINE=1\r\n"
- "-D__APCS_32__=1\r\n"
- "-D__ARMCC_VERSION=6240002\r\n"
- "-D__ARMCOMPILER_VERSION=6240002\r\n"
- "-D__ARMEL__=1\r\n"
- "-D__ARM_32BIT_STATE=1\r\n"
- "-D__ARM_ACLE=200\r\n"
- "-D__ARM_ARCH=7\r\n"
- "-D__ARM_ARCH_7EM__=1\r\n"
- "-D__ARM_ARCH_EXT_IDIV__=1\r\n"
- "-D__ARM_ARCH_ISA_THUMB=2\r\n"
- "-D__ARM_ARCH_PROFILE='M'\r\n"
- "-D__ARM_EABI__=1\r\n"
- "-D__ARM_FEATURE_CLZ=1\r\n"
- "-D__ARM_FEATURE_COPROC=0xf\r\n"
- "-D__ARM_FEATURE_DSP=1\r\n"
- "-D__ARM_FEATURE_FMA=1\r\n"
- "-D__ARM_FEATURE_IDIV=1\r\n"
- "-D__ARM_FEATURE_LDREX=0x7\r\n"
- "-D__ARM_FEATURE_QBIT=1\r\n"
- "-D__ARM_FEATURE_SAT=1\r\n"
- "-D__ARM_FEATURE_SIMD32=1\r\n"
- "-D__ARM_FEATURE_UNALIGNED=1\r\n"
- "-D__ARM_FP=0x6\r\n"
- "-D__ARM_FP16_ARGS=1\r\n"
- "-D__ARM_FP16_FORMAT_IEEE=1\r\n"
- "-D__ARM_NO_IMAGINARY_TYPE=1\r\n"
- "-D__ARM_PCS=1\r\n"
- "-D__ARM_PCS_VFP=1\r\n"
- "-D__ARM_PROMISE=__builtin_assume\r\n"
- "-D__ARM_SIZEOF_MINIMAL_ENUM=1\r\n"
- "-D__ARM_SIZEOF_WCHAR_T=2\r\n"
- "-D__ARM_VFPV2__=1\r\n"
- "-D__ARM_VFPV3__=1\r\n"
- "-D__ARM_VFPV4__=1\r\n"
- "-D__ATOMIC_ACQUIRE=2\r\n"
- "-D__ATOMIC_ACQ_REL=4\r\n"
- "-D__ATOMIC_CONSUME=1\r\n"
- "-D__ATOMIC_RELAXED=0\r\n"
- "-D__ATOMIC_RELEASE=3\r\n"
- "-D__ATOMIC_SEQ_CST=5\r\n"
- "-D__BIGGEST_ALIGNMENT__=8\r\n"
- "-D__BITINT_MAXWIDTH__=128\r\n"
- "-D__BOOL_WIDTH__=8\r\n"
- "-D__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__\r\n"
- "-D__CHAR16_TYPE__=unsigned short\r\n"
- "-D__CHAR32_TYPE__=unsigned int\r\n"
- "-D__CHAR_BIT__=8\r\n"
- "-D__CHAR_UNSIGNED__=1\r\n"
- "-D__CLANG_ATOMIC_BOOL_LOCK_FREE=2\r\n"
- "-D__CLANG_ATOMIC_CHAR16_T_LOCK_FREE=2\r\n"
- "-D__CLANG_ATOMIC_CHAR32_T_LOCK_FREE=2\r\n"
- "-D__CLANG_ATOMIC_CHAR_LOCK_FREE=2\r\n"
- "-D__CLANG_ATOMIC_INT_LOCK_FREE=2\r\n"
- "-D__CLANG_ATOMIC_LLONG_LOCK_FREE=1\r\n"
- "-D__CLANG_ATOMIC_LONG_LOCK_FREE=2\r\n"
- "-D__CLANG_ATOMIC_POINTER_LOCK_FREE=2\r\n"
- "-D__CLANG_ATOMIC_SHORT_LOCK_FREE=2\r\n"
- "-D__CLANG_ATOMIC_WCHAR_T_LOCK_FREE=2\r\n"
- "-D__CONSTANT_CFSTRINGS__=1\r\n"
- "-D__DBL_DECIMAL_DIG__=17\r\n"
- "-D__DBL_DENORM_MIN__=4.9406564584124654e-324\r\n"
- "-D__DBL_DIG__=15\r\n"
- "-D__DBL_EPSILON__=2.2204460492503131e-16\r\n"
- "-D__DBL_HAS_DENORM__=1\r\n"
- "-D__DBL_HAS_INFINITY__=1\r\n"
- "-D__DBL_HAS_QUIET_NAN__=1\r\n"
- "-D__DBL_MANT_DIG__=53\r\n"
- "-D__DBL_MAX_10_EXP__=308\r\n"
- "-D__DBL_MAX_EXP__=1024\r\n"
- "-D__DBL_MAX__=1.7976931348623157e+308\r\n"
- "-D__DBL_MIN_10_EXP__=(-307)\r\n"
- "-D__DBL_MIN_EXP__=(-1021)\r\n"
- "-D__DBL_MIN__=2.2250738585072014e-308\r\n"
- "-D__DBL_NORM_MAX__=1.7976931348623157e+308\r\n"
- "-D__DECIMAL_DIG__=__LDBL_DECIMAL_DIG__\r\n"
- "-D__ELF__=1\r\n"
- "-D__ESCAPE__=\r\n"
- "-D__FINITE_MATH_ONLY__=1\r\n"
- "-D__FLT16_DECIMAL_DIG__=5\r\n"
- "-D__FLT16_DENORM_MIN__=5.9604644775390625e-8F16\r\n"
- "-D__FLT16_DIG__=3\r\n"
- "-D__FLT16_EPSILON__=9.765625e-4F16\r\n"
- "-D__FLT16_HAS_DENORM__=1\r\n"
- "-D__FLT16_HAS_INFINITY__=1\r\n"
- "-D__FLT16_HAS_QUIET_NAN__=1\r\n"
- "-D__FLT16_MANT_DIG__=11\r\n"
- "-D__FLT16_MAX_10_EXP__=4\r\n"
- "-D__FLT16_MAX_EXP__=16\r\n"
- "-D__FLT16_MAX__=6.5504e+4F16\r\n"
- "-D__FLT16_MIN_10_EXP__=(-4)\r\n"
- "-D__FLT16_MIN_EXP__=(-13)\r\n"
- "-D__FLT16_MIN__=6.103515625e-5F16\r\n"
- "-D__FLT16_NORM_MAX__=6.5504e+4F16\r\n"
- "-D__FLT_DECIMAL_DIG__=9\r\n"
- "-D__FLT_DENORM_MIN__=1.40129846e-45F\r\n"
- "-D__FLT_DIG__=6\r\n"
- "-D__FLT_EPSILON__=1.19209290e-7F\r\n"
- "-D__FLT_HAS_DENORM__=1\r\n"
- "-D__FLT_HAS_INFINITY__=1\r\n"
- "-D__FLT_HAS_QUIET_NAN__=1\r\n"
- "-D__FLT_MANT_DIG__=24\r\n"
- "-D__FLT_MAX_10_EXP__=38\r\n"
- "-D__FLT_MAX_EXP__=128\r\n"
- "-D__FLT_MAX__=3.40282347e+38F\r\n"
- "-D__FLT_MIN_10_EXP__=(-37)\r\n"
- "-D__FLT_MIN_EXP__=(-125)\r\n"
- "-D__FLT_MIN__=1.17549435e-38F\r\n"
- "-D__FLT_NORM_MAX__=3.40282347e+38F\r\n"
- "-D__FLT_RADIX__=2\r\n"
- "-D__FPCLASS_NEGINF=0x0004\r\n"
- "-D__FPCLASS_NEGNORMAL=0x0008\r\n"
- "-D__FPCLASS_NEGSUBNORMAL=0x0010\r\n"
- "-D__FPCLASS_NEGZERO=0x0020\r\n"
- "-D__FPCLASS_POSINF=0x0200\r\n"
- "-D__FPCLASS_POSNORMAL=0x0100\r\n"
- "-D__FPCLASS_POSSUBNORMAL=0x0080\r\n"
- "-D__FPCLASS_POSZERO=0x0040\r\n"
- "-D__FPCLASS_QNAN=0x0002\r\n"
- "-D__FPCLASS_SNAN=0x0001\r\n"
- "-D__GCC_ATOMIC_BOOL_LOCK_FREE=2\r\n"
- "-D__GCC_ATOMIC_CHAR16_T_LOCK_FREE=2\r\n"
- "-D__GCC_ATOMIC_CHAR32_T_LOCK_FREE=2\r\n"
- "-D__GCC_ATOMIC_CHAR_LOCK_FREE=2\r\n"
- "-D__GCC_ATOMIC_INT_LOCK_FREE=2\r\n"
- "-D__GCC_ATOMIC_LLONG_LOCK_FREE=1\r\n"
- "-D__GCC_ATOMIC_LONG_LOCK_FREE=2\r\n"
- "-D__GCC_ATOMIC_POINTER_LOCK_FREE=2\r\n"
- "-D__GCC_ATOMIC_SHORT_LOCK_FREE=2\r\n"
- "-D__GCC_ATOMIC_TEST_AND_SET_TRUEVAL=1\r\n"
- "-D__GCC_ATOMIC_WCHAR_T_LOCK_FREE=2\r\n"
- "-D__GCC_CONSTRUCTIVE_SIZE=64\r\n"
- "-D__GCC_DESTRUCTIVE_SIZE=64\r\n"
- "-D__GCC_HAVE_DWARF2_CFI_ASM=1\r\n"
- "-D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1=1\r\n"
- "-D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2=1\r\n"
- "-D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4=1\r\n"
- "-D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8=1\r\n"
- "-D__GNUC_MINOR__=2\r\n"
- "-D__GNUC_PATCHLEVEL__=1\r\n"
- "-D__GNUC_STDC_INLINE__=1\r\n"
- "-D__GNUC__=4\r\n"
- "-D__GXX_ABI_VERSION=1002\r\n"
- "-D__ILP32__=1\r\n"
- "-D__INT16_C_SUFFIX__=\r\n"
- "-D__INT16_FMTd__=\"hd\"\r\n"
- "-D__INT16_FMTi__=\"hi\"\r\n"
- "-D__INT16_MAX__=32767\r\n"
- "-D__INT16_TYPE__=short\r\n"
- "-D__INT32_C_SUFFIX__=\r\n"
- "-D__INT32_FMTd__=\"d\"\r\n"
- "-D__INT32_FMTi__=\"i\"\r\n"
- "-D__INT32_MAX__=2147483647\r\n"
- "-D__INT32_TYPE__=int\r\n"
- "-D__INT64_C_SUFFIX__=LL\r\n"
- "-D__INT64_FMTd__=\"lld\"\r\n"
- "-D__INT64_FMTi__=\"lli\"\r\n"
- "-D__INT64_MAX__=9223372036854775807LL\r\n"
- "-D__INT64_TYPE__=long long int\r\n"
- "-D__INT8_C_SUFFIX__=\r\n"
- "-D__INT8_FMTd__=\"hhd\"\r\n"
- "-D__INT8_FMTi__=\"hhi\"\r\n"
- "-D__INT8_MAX__=127\r\n"
- "-D__INT8_TYPE__=signed char\r\n"
- "-D__INTMAX_C_SUFFIX__=LL\r\n"
- "-D__INTMAX_FMTd__=\"lld\"\r\n"
- "-D__INTMAX_FMTi__=\"lli\"\r\n"
- "-D__INTMAX_MAX__=9223372036854775807LL\r\n"
- "-D__INTMAX_TYPE__=long long int\r\n"
- "-D__INTMAX_WIDTH__=64\r\n"
- "-D__INTPTR_FMTd__=\"d\"\r\n"
- "-D__INTPTR_FMTi__=\"i\"\r\n"
- "-D__INTPTR_MAX__=2147483647\r\n"
- "-D__INTPTR_TYPE__=int\r\n"
- "-D__INTPTR_WIDTH__=32\r\n"
- "-D__INT_FAST16_FMTd__=\"hd\"\r\n"
- "-D__INT_FAST16_FMTi__=\"hi\"\r\n"
- "-D__INT_FAST16_MAX__=32767\r\n"
- "-D__INT_FAST16_TYPE__=short\r\n"
- "-D__INT_FAST16_WIDTH__=16\r\n"
- "-D__INT_FAST32_FMTd__=\"d\"\r\n"
- "-D__INT_FAST32_FMTi__=\"i\"\r\n"
- "-D__INT_FAST32_MAX__=2147483647\r\n"
- "-D__INT_FAST32_TYPE__=int\r\n"
- "-D__INT_FAST32_WIDTH__=32\r\n"
- "-D__INT_FAST64_FMTd__=\"lld\"\r\n"
- "-D__INT_FAST64_FMTi__=\"lli\"\r\n"
- "-D__INT_FAST64_MAX__=9223372036854775807LL\r\n"
- "-D__INT_FAST64_TYPE__=long long int\r\n"
- "-D__INT_FAST64_WIDTH__=64\r\n"
- "-D__INT_FAST8_FMTd__=\"hhd\"\r\n"
- "-D__INT_FAST8_FMTi__=\"hhi\"\r\n"
- "-D__INT_FAST8_MAX__=127\r\n"
- "-D__INT_FAST8_TYPE__=signed char\r\n"
- "-D__INT_FAST8_WIDTH__=8\r\n"
- "-D__INT_LEAST16_FMTd__=\"hd\"\r\n"
- "-D__INT_LEAST16_FMTi__=\"hi\"\r\n"
- "-D__INT_LEAST16_MAX__=32767\r\n"
- "-D__INT_LEAST16_TYPE__=short\r\n"
- "-D__INT_LEAST16_WIDTH__=16\r\n"
- "-D__INT_LEAST32_FMTd__=\"d\"\r\n"
- "-D__INT_LEAST32_FMTi__=\"i\"\r\n"
- "-D__INT_LEAST32_MAX__=2147483647\r\n"
- "-D__INT_LEAST32_TYPE__=int\r\n"
- "-D__INT_LEAST32_WIDTH__=32\r\n"
- "-D__INT_LEAST64_FMTd__=\"lld\"\r\n"
- "-D__INT_LEAST64_FMTi__=\"lli\"\r\n"
- "-D__INT_LEAST64_MAX__=9223372036854775807LL\r\n"
- "-D__INT_LEAST64_TYPE__=long long int\r\n"
- "-D__INT_LEAST64_WIDTH__=64\r\n"
- "-D__INT_LEAST8_FMTd__=\"hhd\"\r\n"
- "-D__INT_LEAST8_FMTi__=\"hhi\"\r\n"
- "-D__INT_LEAST8_MAX__=127\r\n"
- "-D__INT_LEAST8_TYPE__=signed char\r\n"
- "-D__INT_LEAST8_WIDTH__=8\r\n"
- "-D__INT_MAX__=2147483647\r\n"
- "-D__INT_WIDTH__=32\r\n"
- "-D__I__=1.0if\r\n"
- "-D__LDBL_DECIMAL_DIG__=17\r\n"
- "-D__LDBL_DENORM_MIN__=4.9406564584124654e-324L\r\n"
- "-D__LDBL_DIG__=15\r\n"
- "-D__LDBL_EPSILON__=2.2204460492503131e-16L\r\n"
- "-D__LDBL_HAS_DENORM__=1\r\n"
- "-D__LDBL_HAS_INFINITY__=1\r\n"
- "-D__LDBL_HAS_QUIET_NAN__=1\r\n"
- "-D__LDBL_MANT_DIG__=53\r\n"
- "-D__LDBL_MAX_10_EXP__=308\r\n"
- "-D__LDBL_MAX_EXP__=1024\r\n"
- "-D__LDBL_MAX__=1.7976931348623157e+308L\r\n"
- "-D__LDBL_MIN_10_EXP__=(-307)\r\n"
- "-D__LDBL_MIN_EXP__=(-1021)\r\n"
- "-D__LDBL_MIN__=2.2250738585072014e-308L\r\n"
- "-D__LDBL_NORM_MAX__=1.7976931348623157e+308L\r\n"
- "-D__LITTLE_ENDIAN__=1\r\n"
- "-D__LLONG_WIDTH__=64\r\n"
- "-D__LONG_LONG_MAX__=9223372036854775807LL\r\n"
- "-D__LONG_MAX__=2147483647L\r\n"
- "-D__LONG_WIDTH__=32\r\n"
- "-D__MEMORY_SCOPE_DEVICE=1\r\n"
- "-D__MEMORY_SCOPE_SINGLE=4\r\n"
- "-D__MEMORY_SCOPE_SYSTEM=0\r\n"
- "-D__MEMORY_SCOPE_WRKGRP=2\r\n"
- "-D__MEMORY_SCOPE_WVFRNT=3\r\n"
- "-D__OBJC_BOOL_IS_BOOL=0\r\n"
- "-D__OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES=3\r\n"
- "-D__OPENCL_MEMORY_SCOPE_DEVICE=2\r\n"
- "-D__OPENCL_MEMORY_SCOPE_SUB_GROUP=4\r\n"
- "-D__OPENCL_MEMORY_SCOPE_WORK_GROUP=1\r\n"
- "-D__OPENCL_MEMORY_SCOPE_WORK_ITEM=0\r\n"
- "-D__OPTIMIZE__=1\r\n"
- "-D__ORDER_BIG_ENDIAN__=4321\r\n"
- "-D__ORDER_LITTLE_ENDIAN__=1234\r\n"
- "-D__ORDER_PDP_ENDIAN__=3412\r\n"
- "-D__POINTER_WIDTH__=32\r\n"
- "-D__PRAGMA_REDEFINE_EXTNAME=1\r\n"
- "-D__PTRDIFF_FMTd__=\"d\"\r\n"
- "-D__PTRDIFF_FMTi__=\"i\"\r\n"
- "-D__PTRDIFF_MAX__=2147483647\r\n"
- "-D__PTRDIFF_TYPE__=int\r\n"
- "-D__PTRDIFF_WIDTH__=32\r\n"
- "-D__REGISTER_PREFIX__=\r\n"
- "-D__SCHAR_MAX__=127\r\n"
- "-D__SHRT_MAX__=32767\r\n"
- "-D__SHRT_WIDTH__=16\r\n"
- "-D__SIG_ATOMIC_MAX__=2147483647\r\n"
- "-D__SIG_ATOMIC_WIDTH__=32\r\n"
- "-D__SIZEOF_DOUBLE__=8\r\n"
- "-D__SIZEOF_FLOAT__=4\r\n"
- "-D__SIZEOF_INT__=4\r\n"
- "-D__SIZEOF_LONG_DOUBLE__=8\r\n"
- "-D__SIZEOF_LONG_LONG__=8\r\n"
- "-D__SIZEOF_LONG__=4\r\n"
- "-D__SIZEOF_POINTER__=4\r\n"
- "-D__SIZEOF_PTRDIFF_T__=4\r\n"
- "-D__SIZEOF_SHORT__=2\r\n"
- "-D__SIZEOF_SIZE_T__=4\r\n"
- "-D__SIZEOF_WCHAR_T__=2\r\n"
- "-D__SIZEOF_WINT_T__=4\r\n"
- "-D__SIZE_FMTX__=\"X\"\r\n"
- "-D__SIZE_FMTo__=\"o\"\r\n"
- "-D__SIZE_FMTu__=\"u\"\r\n"
- "-D__SIZE_FMTx__=\"x\"\r\n"
- "-D__SIZE_MAX__=4294967295U\r\n"
- "-D__SIZE_TYPE__=unsigned int\r\n"
- "-D__SIZE_WIDTH__=32\r\n"
- "-D__STDC_EMBED_EMPTY__=2\r\n"
- "-D__STDC_EMBED_FOUND__=1\r\n"
- "-D__STDC_EMBED_NOT_FOUND__=0\r\n"
- "-D__STDC_HOSTED__=1\r\n"
- "-D__STDC_UTF_16__=1\r\n"
- "-D__STDC_UTF_32__=1\r\n"
- "-D__STDC_VERSION__=201710L\r\n"
- "-D__STDC__=1\r\n"
- "-D__THUMBEL__=1\r\n"
- "-D__THUMB_INTERWORK__=1\r\n"
- "-D__UINT16_C_SUFFIX__=\r\n"
- "-D__UINT16_FMTX__=\"hX\"\r\n"
- "-D__UINT16_FMTo__=\"ho\"\r\n"
- "-D__UINT16_FMTu__=\"hu\"\r\n"
- "-D__UINT16_FMTx__=\"hx\"\r\n"
- "-D__UINT16_MAX__=65535\r\n"
- "-D__UINT16_TYPE__=unsigned short\r\n"
- "-D__UINT32_C_SUFFIX__=U\r\n"
- "-D__UINT32_FMTX__=\"X\"\r\n"
- "-D__UINT32_FMTo__=\"o\"\r\n"
- "-D__UINT32_FMTu__=\"u\"\r\n"
- "-D__UINT32_FMTx__=\"x\"\r\n"
- "-D__UINT32_MAX__=4294967295U\r\n"
- "-D__UINT32_TYPE__=unsigned int\r\n"
- "-D__UINT64_C_SUFFIX__=ULL\r\n"
- "-D__UINT64_FMTX__=\"llX\"\r\n"
- "-D__UINT64_FMTo__=\"llo\"\r\n"
- "-D__UINT64_FMTu__=\"llu\"\r\n"
- "-D__UINT64_FMTx__=\"llx\"\r\n"
- "-D__UINT64_MAX__=18446744073709551615ULL\r\n"
- "-D__UINT64_TYPE__=long long unsigned int\r\n"
- "-D__UINT8_C_SUFFIX__=\r\n"
- "-D__UINT8_FMTX__=\"hhX\"\r\n"
- "-D__UINT8_FMTo__=\"hho\"\r\n"
- "-D__UINT8_FMTu__=\"hhu\"\r\n"
- "-D__UINT8_FMTx__=\"hhx\"\r\n"
- "-D__UINT8_MAX__=255\r\n"
- "-D__UINT8_TYPE__=unsigned char\r\n"
- "-D__UINTMAX_C_SUFFIX__=ULL\r\n"
- "-D__UINTMAX_FMTX__=\"llX\"\r\n"
- "-D__UINTMAX_FMTo__=\"llo\"\r\n"
- "-D__UINTMAX_FMTu__=\"llu\"\r\n"
- "-D__UINTMAX_FMTx__=\"llx\"\r\n"
- "-D__UINTMAX_MAX__=18446744073709551615ULL\r\n"
- "-D__UINTMAX_TYPE__=long long unsigned int\r\n"
- "-D__UINTMAX_WIDTH__=64\r\n"
- "-D__UINTPTR_FMTX__=\"X\"\r\n"
- "-D__UINTPTR_FMTo__=\"o\"\r\n"
- "-D__UINTPTR_FMTu__=\"u\"\r\n"
- "-D__UINTPTR_FMTx__=\"x\"\r\n"
- "-D__UINTPTR_MAX__=4294967295U\r\n"
- "-D__UINTPTR_TYPE__=unsigned int\r\n"
- "-D__UINTPTR_WIDTH__=32\r\n"
- "-D__UINT_FAST16_FMTX__=\"hX\"\r\n"
- "-D__UINT_FAST16_FMTo__=\"ho\"\r\n"
- "-D__UINT_FAST16_FMTu__=\"hu\"\r\n"
- "-D__UINT_FAST16_FMTx__=\"hx\"\r\n"
- "-D__UINT_FAST16_MAX__=65535\r\n"
- "-D__UINT_FAST16_TYPE__=unsigned short\r\n"
- "-D__UINT_FAST32_FMTX__=\"X\"\r\n"
- "-D__UINT_FAST32_FMTo__=\"o\"\r\n"
- "-D__UINT_FAST32_FMTu__=\"u\"\r\n"
- "-D__UINT_FAST32_FMTx__=\"x\"\r\n"
- "-D__UINT_FAST32_MAX__=4294967295U\r\n"
- "-D__UINT_FAST32_TYPE__=unsigned int\r\n"
- "-D__UINT_FAST64_FMTX__=\"llX\"\r\n"
- "-D__UINT_FAST64_FMTo__=\"llo\"\r\n"
- "-D__UINT_FAST64_FMTu__=\"llu\"\r\n"
- "-D__UINT_FAST64_FMTx__=\"llx\"\r\n"
- "-D__UINT_FAST64_MAX__=18446744073709551615ULL\r\n"
- "-D__UINT_FAST64_TYPE__=long long unsigned int\r\n"
- "-D__UINT_FAST8_FMTX__=\"hhX\"\r\n"
- "-D__UINT_FAST8_FMTo__=\"hho\"\r\n"
- "-D__UINT_FAST8_FMTu__=\"hhu\"\r\n"
- "-D__UINT_FAST8_FMTx__=\"hhx\"\r\n"
- "-D__UINT_FAST8_MAX__=255\r\n"
- "-D__UINT_FAST8_TYPE__=unsigned char\r\n"
- "-D__UINT_LEAST16_FMTX__=\"hX\"\r\n"
- "-D__UINT_LEAST16_FMTo__=\"ho\"\r\n"
- "-D__UINT_LEAST16_FMTu__=\"hu\"\r\n"
- "-D__UINT_LEAST16_FMTx__=\"hx\"\r\n"
- "-D__UINT_LEAST16_MAX__=65535\r\n"
- "-D__UINT_LEAST16_TYPE__=unsigned short\r\n"
- "-D__UINT_LEAST32_FMTX__=\"X\"\r\n"
- "-D__UINT_LEAST32_FMTo__=\"o\"\r\n"
- "-D__UINT_LEAST32_FMTu__=\"u\"\r\n"
- "-D__UINT_LEAST32_FMTx__=\"x\"\r\n"
- "-D__UINT_LEAST32_MAX__=4294967295U\r\n"
- "-D__UINT_LEAST32_TYPE__=unsigned int\r\n"
- "-D__UINT_LEAST64_FMTX__=\"llX\"\r\n"
- "-D__UINT_LEAST64_FMTo__=\"llo\"\r\n"
- "-D__UINT_LEAST64_FMTu__=\"llu\"\r\n"
- "-D__UINT_LEAST64_FMTx__=\"llx\"\r\n"
- "-D__UINT_LEAST64_MAX__=18446744073709551615ULL\r\n"
- "-D__UINT_LEAST64_TYPE__=long long unsigned int\r\n"
- "-D__UINT_LEAST8_FMTX__=\"hhX\"\r\n"
- "-D__UINT_LEAST8_FMTo__=\"hho\"\r\n"
- "-D__UINT_LEAST8_FMTu__=\"hhu\"\r\n"
- "-D__UINT_LEAST8_FMTx__=\"hhx\"\r\n"
- "-D__UINT_LEAST8_MAX__=255\r\n"
- "-D__UINT_LEAST8_TYPE__=unsigned char\r\n"
- "-D__USER_LABEL_PREFIX__=\r\n"
- "-D__VERSION__=\"Clang 20.0.0git\"\r\n"
- "-D__VFP_FP__=1\r\n"
- "-D__WCHAR_MAX__=65535\r\n"
- "-D__WCHAR_TYPE__=unsigned short\r\n"
- "-D__WCHAR_UNSIGNED__=1\r\n"
- "-D__WCHAR_WIDTH__=16\r\n"
- "-D__WINT_MAX__=2147483647\r\n"
- "-D__WINT_TYPE__=int\r\n"
- "-D__WINT_WIDTH__=32\r\n"
- "-D__arm=1\r\n"
- "-D__arm__=1\r\n"
- "-D__clang__=1\r\n"
- "-D__clang_literal_encoding__=\"UTF-8\"\r\n"
- "-D__clang_major__=20\r\n"
- "-D__clang_minor__=0\r\n"
- "-D__clang_patchlevel__=0\r\n"
- "-D__clang_version__=\"20.0.0git \"\r\n"
- "-D__clang_wide_literal_encoding__=\"UTF-16\"\r\n"
- "-D__llvm__=1\r\n"
- "-D__thumb2__=1\r\n"
- "-D__thumb__=1\r\n"
- '-D__ARMCOMPILER_LIBCXX=1'
- '-IG:/Robot_v2/BOOT/Robot_V2/RTE/_Release_GD32C103CB'
- '-IC:/Users/cbb/AppData/Local/arm/packs/ARM/CMSIS/4.5.0/CMSIS/Include'
-290
View File
@@ -1,290 +0,0 @@
#include "DengFOC.h"
#include "Can.h"
#include "Timer.h"
#include "adc.h"
#include "ang_sensor.h"
#include "initial.h"
#include "pid.h"
#include <cmath>
#include <gd32c10x.h>
#include <stdint.h>
#include "motor.h"
constexpr double PI = 3.1415926535897932384626433832795f;
constexpr float ANGLE_FACTOR = 25.0f / 360.0f * 2.0f * 3.14159265358979323846f;
constexpr float _1_SQRT3 = 0.57735026919f;
constexpr float _2_SQRT3 = 1.15470053838f;
constexpr float _3PI_2 = 4.71238898038f;
constexpr u8 PP = 11;
constexpr float DIR = 1.0;
constexpr float sqrt3 = 1.73205080757f; // sqrt(3)的预计算值
constexpr float sqrt3dv2 = 0.86602540378f; // sqrt(3)/2的预计算值
constexpr float zero_electric_angle = 0.0f;
constexpr u16 LUT_SCALE = (LUT_SIZE / (2.0f * PI));
FOC_Controlroller FOC; // FOC控制初始化
extern sampler sampler;
extern angle_sensor KTH7823;
extern CAN_transmiter CAN0_transmiter;
// 初始变量及函数定义
#define _constrain(amt, low, high) \
((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
#define constrain(value, min, max, target_min, target_max) \
((value - min) / (max - min) * (target_max - target_min))
/**
* @brief 归一化角度
*
* @param angle
* @return float
*/
inline float _normalizeAngle(float angle) {
float a = fmod(angle, 2 * PI);
// 取余运算可以用于归一化,列出特殊值例子算便知
return a >= 0 ? a : (a + 2 * PI);
}
// 通过Ia,Ib,Ic计算Iq,Id(目前仅输出Iq)
inline float FOC_Controlroller::cal_Iq_Id(float current_a, float current_b,
float current_c) {
// 计算电气角度
float angle_el = _normalizeAngle(shaft_angle * PP);
// Clarke变换 (使用三相电流)
float I_alpha = (2.0f / 3.0f) * current_a - (1.0f / 3.0f) * current_b -
(1.0f / 3.0f) * current_c;
float I_beta = _1_SQRT3 * current_b - _1_SQRT3 * current_c;
// Park变换
float sin_el, cos_el;
cos_el = cos_lut[(u16)(angle_el * LUT_SCALE) & LUT_MASK];
sin_el = sin_lut[(u16)(angle_el * LUT_SCALE) & LUT_MASK];
float I_q = I_beta * cos_el - I_alpha * sin_el;
return I_q*1000.0f; // 返回Iq值,乘以1000以转换为mA
}
/**
* @brief 电机控制类构造函数
*
*/
FOC_Controlroller::FOC_Controlroller() { ; }
/**
* @brief 设置电机输出,使用优化的SVPWM算法
*
* @param Uq: q轴电压
* @param Ud: d轴电压
* @param angle_el: 电机轴角度
*/
inline void FOC_Controlroller::setPhaseVoltage(float Uq, float Ud) {
// 计算电气角度
float angle_el = _normalizeAngle(shaft_angle * PP);
// 帕克逆变换 (直接计算,避免函数调用开销)
float sin_el, cos_el;
sin_el = sin_lut[(u16)(angle_el * LUT_SCALE) & LUT_MASK];
cos_el = cos_lut[(u16)(angle_el * LUT_SCALE) & LUT_MASK];
float Ualpha = Ud * cos_el - Uq * sin_el;
float Ubeta = Ud * sin_el + Uq * cos_el;
// 克拉克逆变换 (使用预计算常量优化)
Ua = Ualpha + v_half;
Ub = sqrt3dv2 * Ubeta - 0.5f * Ualpha + v_half;
Uc = -0.5f * Ualpha - sqrt3dv2 * Ubeta + v_half;
// 计算占空比并限制范围
duty_a = _constrain(Ua / v_safe, 0.0f, 1.0f);
duty_b = _constrain(Ub / v_safe, 0.0f, 1.0f);
duty_c = _constrain(Uc / v_safe, 0.0f, 1.0f);
// 设置PWM输出
float voltage_exchange = limit_voltage / v_safe;
duty_a = duty_a * voltage_exchange;
duty_b = duty_b * voltage_exchange;
duty_c = duty_c * voltage_exchange;
Set_3Pwm(duty_a, duty_b, duty_c);
// std::printf("PWM:%f,%f,%f\n", dc_a, dc_b, dc_c);
}
/**
* @brief 电机关机
*
*/
void FOC_Controlroller::shut_down() {
is_shut_down = 1;
motor_sleep();
}
/**
* @brief 占空比置0
*
*/
void FOC_Controlroller::drv_stop() { Set_3Pwm(0.0f, 0.0f, 0.0f); }
/**
* @brief 电机锁止
*/
void FOC_Controlroller::drv_hold(float duty) {
if (duty > 0.95f) {
duty = 0.95f;
} else if (duty < 0.0f) {
duty = 0.0f;
}
Set_3Pwm(duty, duty, duty);
}
/**
* @brief 电机恢复
*
*/
void FOC_Controlroller::resume() {
over_current = false;
voltage_error = false;
is_shut_down = false;
motor_resume();
}
/**
* @brief 更新电源电压
*
*/
void FOC_Controlroller::update_power(void) {
voltage_power_supply = sampler.get_vbus_voltage();
if (voltage_power_supply < 36.0f and voltage_power_supply > 8.0f) {
voltage_error = false;
v_half = voltage_power_supply * 0.5f;
v_safe = voltage_power_supply * 0.95f;
} else {
voltage_error = true;
}
}
/**
* @brief 速度开环控制
*
* @param target_velocity: 目标速度
* @return float: q轴电压
*/
float FOC_Controlroller::velocity_open_loop() {
// 通过时间间隔和目标速度计算需要转动的机械角度,存储在shaft_angle中,在此之前,还需要对轴角度归一化
// 预计算常量 1e-4 = 100微秒控制周期
shaft_angle =
_normalizeAngle(shaft_angle + target_velocity * ANGLE_FACTOR * 1e-4f);
// 因为在开环控制中,Ud始终为0,只控制Uq
const float Uq = voltage_power_supply / 2.0f;
setPhaseVoltage(Uq, 0.0f);
// CAN0_transmiter.testfloat_union.f =
cal_Iq_Id(sampler.get_current('U'), sampler.get_current('V'), sampler.get_current('W'));
return limit_voltage;
}
/**
* @brief 电机初始化
*
* @param _PP: 电机极队数
*/
// void FOC_Controlroller::DFOC_alignSensor(int _PP) {
// u8 PP = _PP;
// setPhaseVoltage(3, 0, _3PI_2);
// delay_1ms(3000);
// zero_electric_angle = _electricalAngle();
// setPhaseVoltage(0, 0, _3PI_2);
// std::printf("0电角度:%f", zero_electric_angle);
// }
/**
* @brief 角度闭环控制
*
* @param target_angle: 目标角度
* @return float: 当前角度
*/
float FOC_Controlroller::angle_control(float target_angle) {
// PID 控制计算
float Uq = angle_loop(target_angle - rt_angle);
// 获取电机轴角度
shaft_angle = KTH7823.getcurrent_sensorangle() * DEG2RAD;
// 设置相电压
setPhaseVoltage(Uq, 0.0f);
return shaft_angle;
}
/**
* @brief 带速度限制的角度闭环控制
*
* @param target_angle: 目标角度
* @param max_velocity: 最大速度限制 (单位: rad/s)
* @return float: 当前角度
*/
float FOC_Controlroller::angle_control_with_velocity_limit(float target_angle) {
// 计算角度误差
float angle_error = target_angle - rt_angle;
// 使用角度PID控制器计算目标速度
float target_velocity = ang_inVelAngloop(angle_error);
// 对目标速度进行限幅
target_velocity = _constrain(target_velocity, -limit_velocity, limit_velocity);
// 使用速度PID控制器计算最终输出电压
float Uq = vel_inVelAngloop(target_velocity - rt_velocity);
// CAN0_transmiter.testfloat_union.f = target_velocity - rt_velocity;
// 获取电机轴角度
shaft_angle = KTH7823.getcurrent_sensorangle() * DEG2RAD;
// 设置相电压
setPhaseVoltage(Uq, 0.0f);
return shaft_angle;
}
/**
* @brief 角度闭环控制
*
* @param target_angle: 目标角度
* @return float: 当前角度
*/
float FOC_Controlroller::angle_control_NPID(float target_angle) {
static float Kp = 20.0f;
// 控制力矩计算
float Uq = _constrain(Kp * (target_angle - rt_angle), -voltage_power_supply,
voltage_power_supply);
// 获取电机轴角度
shaft_angle = KTH7823.getcurrent_sensorangle() * DEG2RAD;
// 设置相电压
setPhaseVoltage(Uq, 0.0f);
return shaft_angle;
}
/**
* @brief 速度闭环控制
*
* @param target_velocity: 目标速度
* @return float: 当前速度
*/
float FOC_Controlroller::velocity_control(float target_velocity) {
// PID 控制计算
float Uq = vel_loop((target_velocity - rt_velocity)*25);
// 获取电机轴角度
shaft_angle = KTH7823.getcurrent_sensorangle() * DEG2RAD;
// 设置相电压
setPhaseVoltage(Uq, 0.0f);
// CAN0_transmiter.testfloat_union.f =
cal_Iq_Id(sampler.get_current('U'), sampler.get_current('V'), sampler.get_current('W'));
return rt_velocity;
}
float FOC_Controlroller::current_control(float target_current) {
// PID 控制计算
float Iq = cal_Iq_Id(sampler.get_current('U'), sampler.get_current('V'), sampler.get_current('W'));
float Uq = current_loop(target_current - Iq);
CAN0_transmiter.testfloat_union.f = Iq;
// 获取电机轴角度
shaft_angle = KTH7823.getcurrent_sensorangle() * DEG2RAD;
// 设置相电压
setPhaseVoltage(Uq, 0.0f);
return 1;
}
-411
View File
@@ -1,411 +0,0 @@
// 函数声明
#ifndef _DENGFOC_H
#define _DENGFOC_H
#include "pid.h"
#include <stdint.h>
class FOC_Controlroller {
public:
FOC_Controlroller();
u8 control_mode = 0;
float limit_voltage = 0.0f;
float limit_velocity = 0.0f;
float target_angle = 0.0f;
float target_velocity = 0.0f;
float rt_angle = 0.0f;
float rt_velocity = 0.0f;
bool over_current = false;
bool voltage_error = false;
bool is_shut_down = false;
float voltage_power_supply = 24.0f; // 电源电压
float v_safe = voltage_power_supply * 1.05f;
float duty_a = 0, duty_b = 0, duty_c = 0;
float Ua = 0, Ub = 0, Uc = 0;
float velocity_open_loop();
float angle_control(float target_angle);
float angle_control_with_velocity_limit(float target_angle);
float velocity_control(float target_velocity);
float current_control(float target_current);
float angle_control_NPID(float target_angle);
void update_power(void);
void DFOC_alignSensor(int _PP);
void shut_down(void);
void resume(void);
void drv_stop(void);
void drv_hold(float duty = 0.5f);
protected:
float shaft_angle = 0;
float Ualpha, Ubeta = 0;
float zero_electric_angle = 0;
float v_half = voltage_power_supply * 0.5f; // 电源电压的一半
PIDController vel_loop =
PIDController{0.028f, 0.2f, 1e-4, 1000000, voltage_power_supply}; // 12V
PIDController angle_loop = PIDController{20.0f, 100.0f, 0.2f, 10000000,
voltage_power_supply}; // 12V
PIDController current_loop =
PIDController{0.006f, 0.02f, 0, 100000, voltage_power_supply}; // 12V
PIDController vel_inVelAngloop =
PIDController{0.35f, 5.0f,1e-3, 1000000, voltage_power_supply};
PIDController ang_inVelAngloop =
PIDController{30.0f, 0.0f, 1e-3, 1000000, 999};
void setPhaseVoltage(float Uq, float Ud);
float cal_Iq_Id(float current_a, float current_b, float current_c);
};
float _normalizeAngle(float angle);
inline float _electricalAngle();
constexpr u16 LUT_SIZE = 1024;
constexpr u16 LUT_MASK = (LUT_SIZE - 1);
__attribute__((aligned(4))) const float sin_lut[LUT_SIZE] = {
0.000000f, 0.006136f, 0.012272f, 0.018407f, 0.024541f, 0.030675f,
0.036807f, 0.042938f, 0.049068f, 0.055195f, 0.061321f, 0.067444f,
0.073565f, 0.079682f, 0.085797f, 0.091909f, 0.098017f, 0.104122f,
0.110222f, 0.116319f, 0.122411f, 0.128498f, 0.134581f, 0.140658f,
0.146730f, 0.152797f, 0.158858f, 0.164913f, 0.170962f, 0.177004f,
0.183040f, 0.189069f, 0.195090f, 0.201105f, 0.207111f, 0.213110f,
0.219101f, 0.225084f, 0.231058f, 0.237024f, 0.242980f, 0.248928f,
0.254866f, 0.260794f, 0.266713f, 0.272621f, 0.278520f, 0.284408f,
0.290285f, 0.296151f, 0.302006f, 0.307850f, 0.313682f, 0.319502f,
0.325310f, 0.331106f, 0.336890f, 0.342661f, 0.348419f, 0.354164f,
0.359895f, 0.365613f, 0.371317f, 0.377007f, 0.382683f, 0.388345f,
0.393992f, 0.399624f, 0.405241f, 0.410843f, 0.416430f, 0.422000f,
0.427555f, 0.433094f, 0.438616f, 0.444122f, 0.449611f, 0.455084f,
0.460539f, 0.465976f, 0.471397f, 0.476799f, 0.482184f, 0.487550f,
0.492898f, 0.498228f, 0.503538f, 0.508830f, 0.514103f, 0.519356f,
0.524590f, 0.529804f, 0.534998f, 0.540171f, 0.545325f, 0.550458f,
0.555570f, 0.560662f, 0.565732f, 0.570781f, 0.575808f, 0.580814f,
0.585798f, 0.590760f, 0.595699f, 0.600616f, 0.605511f, 0.610383f,
0.615232f, 0.620057f, 0.624859f, 0.629638f, 0.634393f, 0.639124f,
0.643832f, 0.648514f, 0.653173f, 0.657807f, 0.662416f, 0.667000f,
0.671559f, 0.676093f, 0.680601f, 0.685084f, 0.689541f, 0.693971f,
0.698376f, 0.702755f, 0.707107f, 0.711432f, 0.715731f, 0.720003f,
0.724247f, 0.728464f, 0.732654f, 0.736817f, 0.740951f, 0.745058f,
0.749136f, 0.753187f, 0.757209f, 0.761202f, 0.765167f, 0.769103f,
0.773010f, 0.776888f, 0.780737f, 0.784557f, 0.788346f, 0.792107f,
0.795837f, 0.799537f, 0.803208f, 0.806848f, 0.810457f, 0.814036f,
0.817585f, 0.821103f, 0.824589f, 0.828045f, 0.831470f, 0.834863f,
0.838225f, 0.841555f, 0.844854f, 0.848120f, 0.851355f, 0.854558f,
0.857729f, 0.860867f, 0.863973f, 0.867046f, 0.870087f, 0.873095f,
0.876070f, 0.879012f, 0.881921f, 0.884797f, 0.887640f, 0.890449f,
0.893224f, 0.895966f, 0.898674f, 0.901349f, 0.903989f, 0.906596f,
0.909168f, 0.911706f, 0.914210f, 0.916679f, 0.919114f, 0.921514f,
0.923880f, 0.926210f, 0.928506f, 0.930767f, 0.932993f, 0.935184f,
0.937339f, 0.939459f, 0.941544f, 0.943593f, 0.945607f, 0.947586f,
0.949528f, 0.951435f, 0.953306f, 0.955141f, 0.956940f, 0.958703f,
0.960431f, 0.962121f, 0.963776f, 0.965394f, 0.966976f, 0.968522f,
0.970031f, 0.971504f, 0.972940f, 0.974339f, 0.975702f, 0.977028f,
0.978317f, 0.979570f, 0.980785f, 0.981964f, 0.983105f, 0.984210f,
0.985278f, 0.986308f, 0.987301f, 0.988258f, 0.989177f, 0.990058f,
0.990903f, 0.991710f, 0.992480f, 0.993212f, 0.993907f, 0.994565f,
0.995185f, 0.995767f, 0.996313f, 0.996820f, 0.997290f, 0.997723f,
0.998118f, 0.998476f, 0.998795f, 0.999078f, 0.999322f, 0.999529f,
0.999699f, 0.999831f, 0.999925f, 0.999981f, 1.000000f, 0.999981f,
0.999925f, 0.999831f, 0.999699f, 0.999529f, 0.999322f, 0.999078f,
0.998795f, 0.998476f, 0.998118f, 0.997723f, 0.997290f, 0.996820f,
0.996313f, 0.995767f, 0.995185f, 0.994565f, 0.993907f, 0.993212f,
0.992480f, 0.991710f, 0.990903f, 0.990058f, 0.989177f, 0.988258f,
0.987301f, 0.986308f, 0.985278f, 0.984210f, 0.983105f, 0.981964f,
0.980785f, 0.979570f, 0.978317f, 0.977028f, 0.975702f, 0.974339f,
0.972940f, 0.971504f, 0.970031f, 0.968522f, 0.966976f, 0.965394f,
0.963776f, 0.962121f, 0.960431f, 0.958703f, 0.956940f, 0.955141f,
0.953306f, 0.951435f, 0.949528f, 0.947586f, 0.945607f, 0.943593f,
0.941544f, 0.939459f, 0.937339f, 0.935184f, 0.932993f, 0.930767f,
0.928506f, 0.926210f, 0.923880f, 0.921514f, 0.919114f, 0.916679f,
0.914210f, 0.911706f, 0.909168f, 0.906596f, 0.903989f, 0.901349f,
0.898674f, 0.895966f, 0.893224f, 0.890449f, 0.887640f, 0.884797f,
0.881921f, 0.879012f, 0.876070f, 0.873095f, 0.870087f, 0.867046f,
0.863973f, 0.860867f, 0.857729f, 0.854558f, 0.851355f, 0.848120f,
0.844854f, 0.841555f, 0.838225f, 0.834863f, 0.831470f, 0.828045f,
0.824589f, 0.821103f, 0.817585f, 0.814036f, 0.810457f, 0.806848f,
0.803208f, 0.799537f, 0.795837f, 0.792107f, 0.788346f, 0.784557f,
0.780737f, 0.776888f, 0.773010f, 0.769103f, 0.765167f, 0.761202f,
0.757209f, 0.753187f, 0.749136f, 0.745058f, 0.740951f, 0.736817f,
0.732654f, 0.728464f, 0.724247f, 0.720003f, 0.715731f, 0.711432f,
0.707107f, 0.702755f, 0.698376f, 0.693971f, 0.689541f, 0.685084f,
0.680601f, 0.676093f, 0.671559f, 0.667000f, 0.662416f, 0.657807f,
0.653173f, 0.648514f, 0.643832f, 0.639124f, 0.634393f, 0.629638f,
0.624859f, 0.620057f, 0.615232f, 0.610383f, 0.605511f, 0.600616f,
0.595699f, 0.590760f, 0.585798f, 0.580814f, 0.575808f, 0.570781f,
0.565732f, 0.560662f, 0.555570f, 0.550458f, 0.545325f, 0.540171f,
0.534998f, 0.529804f, 0.524590f, 0.519356f, 0.514103f, 0.508830f,
0.503538f, 0.498228f, 0.492898f, 0.487550f, 0.482184f, 0.476799f,
0.471397f, 0.465976f, 0.460539f, 0.455084f, 0.449611f, 0.444122f,
0.438616f, 0.433094f, 0.427555f, 0.422000f, 0.416430f, 0.410843f,
0.405241f, 0.399624f, 0.393992f, 0.388345f, 0.382683f, 0.377007f,
0.371317f, 0.365613f, 0.359895f, 0.354164f, 0.348419f, 0.342661f,
0.336890f, 0.331106f, 0.325310f, 0.319502f, 0.313682f, 0.307850f,
0.302006f, 0.296151f, 0.290285f, 0.284408f, 0.278520f, 0.272621f,
0.266713f, 0.260794f, 0.254866f, 0.248928f, 0.242980f, 0.237024f,
0.231058f, 0.225084f, 0.219101f, 0.213110f, 0.207111f, 0.201105f,
0.195090f, 0.189069f, 0.183040f, 0.177004f, 0.170962f, 0.164913f,
0.158858f, 0.152797f, 0.146730f, 0.140658f, 0.134581f, 0.128498f,
0.122411f, 0.116319f, 0.110222f, 0.104122f, 0.098017f, 0.091909f,
0.085797f, 0.079682f, 0.073565f, 0.067444f, 0.061321f, 0.055195f,
0.049068f, 0.042938f, 0.036807f, 0.030675f, 0.024541f, 0.018407f,
0.012272f, 0.006136f, 0.000000f, -0.006136f, -0.012272f, -0.018407f,
-0.024541f, -0.030675f, -0.036807f, -0.042938f, -0.049068f, -0.055195f,
-0.061321f, -0.067444f, -0.073565f, -0.079682f, -0.085797f, -0.091909f,
-0.098017f, -0.104122f, -0.110222f, -0.116319f, -0.122411f, -0.128498f,
-0.134581f, -0.140658f, -0.146730f, -0.152797f, -0.158858f, -0.164913f,
-0.170962f, -0.177004f, -0.183040f, -0.189069f, -0.195090f, -0.201105f,
-0.207111f, -0.213110f, -0.219101f, -0.225084f, -0.231058f, -0.237024f,
-0.242980f, -0.248928f, -0.254866f, -0.260794f, -0.266713f, -0.272621f,
-0.278520f, -0.284408f, -0.290285f, -0.296151f, -0.302006f, -0.307850f,
-0.313682f, -0.319502f, -0.325310f, -0.331106f, -0.336890f, -0.342661f,
-0.348419f, -0.354164f, -0.359895f, -0.365613f, -0.371317f, -0.377007f,
-0.382683f, -0.388345f, -0.393992f, -0.399624f, -0.405241f, -0.410843f,
-0.416430f, -0.422000f, -0.427555f, -0.433094f, -0.438616f, -0.444122f,
-0.449611f, -0.455084f, -0.460539f, -0.465976f, -0.471397f, -0.476799f,
-0.482184f, -0.487550f, -0.492898f, -0.498228f, -0.503538f, -0.508830f,
-0.514103f, -0.519356f, -0.524590f, -0.529804f, -0.534998f, -0.540171f,
-0.545325f, -0.550458f, -0.555570f, -0.560662f, -0.565732f, -0.570781f,
-0.575808f, -0.580814f, -0.585798f, -0.590760f, -0.595699f, -0.600616f,
-0.605511f, -0.610383f, -0.615232f, -0.620057f, -0.624859f, -0.629638f,
-0.634393f, -0.639124f, -0.643832f, -0.648514f, -0.653173f, -0.657807f,
-0.662416f, -0.667000f, -0.671559f, -0.676093f, -0.680601f, -0.685084f,
-0.689541f, -0.693971f, -0.698376f, -0.702755f, -0.707107f, -0.711432f,
-0.715731f, -0.720003f, -0.724247f, -0.728464f, -0.732654f, -0.736817f,
-0.740951f, -0.745058f, -0.749136f, -0.753187f, -0.757209f, -0.761202f,
-0.765167f, -0.769103f, -0.773010f, -0.776888f, -0.780737f, -0.784557f,
-0.788346f, -0.792107f, -0.795837f, -0.799537f, -0.803208f, -0.806848f,
-0.810457f, -0.814036f, -0.817585f, -0.821103f, -0.824589f, -0.828045f,
-0.831470f, -0.834863f, -0.838225f, -0.841555f, -0.844854f, -0.848120f,
-0.851355f, -0.854558f, -0.857729f, -0.860867f, -0.863973f, -0.867046f,
-0.870087f, -0.873095f, -0.876070f, -0.879012f, -0.881921f, -0.884797f,
-0.887640f, -0.890449f, -0.893224f, -0.895966f, -0.898674f, -0.901349f,
-0.903989f, -0.906596f, -0.909168f, -0.911706f, -0.914210f, -0.916679f,
-0.919114f, -0.921514f, -0.923880f, -0.926210f, -0.928506f, -0.930767f,
-0.932993f, -0.935184f, -0.937339f, -0.939459f, -0.941544f, -0.943593f,
-0.945607f, -0.947586f, -0.949528f, -0.951435f, -0.953306f, -0.955141f,
-0.956940f, -0.958703f, -0.960431f, -0.962121f, -0.963776f, -0.965394f,
-0.966976f, -0.968522f, -0.970031f, -0.971504f, -0.972940f, -0.974339f,
-0.975702f, -0.977028f, -0.978317f, -0.979570f, -0.980785f, -0.981964f,
-0.983105f, -0.984210f, -0.985278f, -0.986308f, -0.987301f, -0.988258f,
-0.989177f, -0.990058f, -0.990903f, -0.991710f, -0.992480f, -0.993212f,
-0.993907f, -0.994565f, -0.995185f, -0.995767f, -0.996313f, -0.996820f,
-0.997290f, -0.997723f, -0.998118f, -0.998476f, -0.998795f, -0.999078f,
-0.999322f, -0.999529f, -0.999699f, -0.999831f, -0.999925f, -0.999981f,
-1.000000f, -0.999981f, -0.999925f, -0.999831f, -0.999699f, -0.999529f,
-0.999322f, -0.999078f, -0.998795f, -0.998476f, -0.998118f, -0.997723f,
-0.997290f, -0.996820f, -0.996313f, -0.995767f, -0.995185f, -0.994565f,
-0.993907f, -0.993212f, -0.992480f, -0.991710f, -0.990903f, -0.990058f,
-0.989177f, -0.988258f, -0.987301f, -0.986308f, -0.985278f, -0.984210f,
-0.983105f, -0.981964f, -0.980785f, -0.979570f, -0.978317f, -0.977028f,
-0.975702f, -0.974339f, -0.972940f, -0.971504f, -0.970031f, -0.968522f,
-0.966976f, -0.965394f, -0.963776f, -0.962121f, -0.960431f, -0.958703f,
-0.956940f, -0.955141f, -0.953306f, -0.951435f, -0.949528f, -0.947586f,
-0.945607f, -0.943593f, -0.941544f, -0.939459f, -0.937339f, -0.935184f,
-0.932993f, -0.930767f, -0.928506f, -0.926210f, -0.923880f, -0.921514f,
-0.919114f, -0.916679f, -0.914210f, -0.911706f, -0.909168f, -0.906596f,
-0.903989f, -0.901349f, -0.898674f, -0.895966f, -0.893224f, -0.890449f,
-0.887640f, -0.884797f, -0.881921f, -0.879012f, -0.876070f, -0.873095f,
-0.870087f, -0.867046f, -0.863973f, -0.860867f, -0.857729f, -0.854558f,
-0.851355f, -0.848120f, -0.844854f, -0.841555f, -0.838225f, -0.834863f,
-0.831470f, -0.828045f, -0.824589f, -0.821103f, -0.817585f, -0.814036f,
-0.810457f, -0.806848f, -0.803208f, -0.799537f, -0.795837f, -0.792107f,
-0.788346f, -0.784557f, -0.780737f, -0.776888f, -0.773010f, -0.769103f,
-0.765167f, -0.761202f, -0.757209f, -0.753187f, -0.749136f, -0.745058f,
-0.740951f, -0.736817f, -0.732654f, -0.728464f, -0.724247f, -0.720003f,
-0.715731f, -0.711432f, -0.707107f, -0.702755f, -0.698376f, -0.693971f,
-0.689541f, -0.685084f, -0.680601f, -0.676093f, -0.671559f, -0.667000f,
-0.662416f, -0.657807f, -0.653173f, -0.648514f, -0.643832f, -0.639124f,
-0.634393f, -0.629638f, -0.624859f, -0.620057f, -0.615232f, -0.610383f,
-0.605511f, -0.600616f, -0.595699f, -0.590760f, -0.585798f, -0.580814f,
-0.575808f, -0.570781f, -0.565732f, -0.560662f, -0.555570f, -0.550458f,
-0.545325f, -0.540171f, -0.534998f, -0.529804f, -0.524590f, -0.519356f,
-0.514103f, -0.508830f, -0.503538f, -0.498228f, -0.492898f, -0.487550f,
-0.482184f, -0.476799f, -0.471397f, -0.465976f, -0.460539f, -0.455084f,
-0.449611f, -0.444122f, -0.438616f, -0.433094f, -0.427555f, -0.422000f,
-0.416430f, -0.410843f, -0.405241f, -0.399624f, -0.393992f, -0.388345f,
-0.382683f, -0.377007f, -0.371317f, -0.365613f, -0.359895f, -0.354164f,
-0.348419f, -0.342661f, -0.336890f, -0.331106f, -0.325310f, -0.319502f,
-0.313682f, -0.307850f, -0.302006f, -0.296151f, -0.290285f, -0.284408f,
-0.278520f, -0.272621f, -0.266713f, -0.260794f, -0.254866f, -0.248928f,
-0.242980f, -0.237024f, -0.231058f, -0.225084f, -0.219101f, -0.213110f,
-0.207111f, -0.201105f, -0.195090f, -0.189069f, -0.183040f, -0.177004f,
-0.170962f, -0.164913f, -0.158858f, -0.152797f, -0.146730f, -0.140658f,
-0.134581f, -0.128498f, -0.122411f, -0.116319f, -0.110222f, -0.104122f,
-0.098017f, -0.091909f, -0.085797f, -0.079682f, -0.073565f, -0.067444f,
-0.061321f, -0.055195f, -0.049068f, -0.042938f, -0.036807f, -0.030675f,
-0.024541f, -0.018407f, -0.012272f, -0.006136f};
__attribute__((aligned(4))) const float cos_lut[LUT_SIZE] = {
1.000000f, 0.999981f, 0.999925f, 0.999831f, 0.999699f, 0.999529f,
0.999322f, 0.999078f, 0.998795f, 0.998476f, 0.998118f, 0.997723f,
0.997290f, 0.996820f, 0.996313f, 0.995767f, 0.995185f, 0.994565f,
0.993907f, 0.993212f, 0.992480f, 0.991710f, 0.990903f, 0.990058f,
0.989177f, 0.988258f, 0.987301f, 0.986308f, 0.985278f, 0.984210f,
0.983105f, 0.981964f, 0.980785f, 0.979570f, 0.978317f, 0.977028f,
0.975702f, 0.974339f, 0.972940f, 0.971504f, 0.970031f, 0.968522f,
0.966976f, 0.965394f, 0.963776f, 0.962121f, 0.960431f, 0.958703f,
0.956940f, 0.955141f, 0.953306f, 0.951435f, 0.949528f, 0.947586f,
0.945607f, 0.943593f, 0.941544f, 0.939459f, 0.937339f, 0.935184f,
0.932993f, 0.930767f, 0.928506f, 0.926210f, 0.923880f, 0.921514f,
0.919114f, 0.916679f, 0.914210f, 0.911706f, 0.909168f, 0.906596f,
0.903989f, 0.901349f, 0.898674f, 0.895966f, 0.893224f, 0.890449f,
0.887640f, 0.884797f, 0.881921f, 0.879012f, 0.876070f, 0.873095f,
0.870087f, 0.867046f, 0.863973f, 0.860867f, 0.857729f, 0.854558f,
0.851355f, 0.848120f, 0.844854f, 0.841555f, 0.838225f, 0.834863f,
0.831470f, 0.828045f, 0.824589f, 0.821103f, 0.817585f, 0.814036f,
0.810457f, 0.806848f, 0.803208f, 0.799537f, 0.795837f, 0.792107f,
0.788346f, 0.784557f, 0.780737f, 0.776888f, 0.773010f, 0.769103f,
0.765167f, 0.761202f, 0.757209f, 0.753187f, 0.749136f, 0.745058f,
0.740951f, 0.736817f, 0.732654f, 0.728464f, 0.724247f, 0.720003f,
0.715731f, 0.711432f, 0.707107f, 0.702755f, 0.698376f, 0.693971f,
0.689541f, 0.685084f, 0.680601f, 0.676093f, 0.671559f, 0.667000f,
0.662416f, 0.657807f, 0.653173f, 0.648514f, 0.643832f, 0.639124f,
0.634393f, 0.629638f, 0.624859f, 0.620057f, 0.615232f, 0.610383f,
0.605511f, 0.600616f, 0.595699f, 0.590760f, 0.585798f, 0.580814f,
0.575808f, 0.570781f, 0.565732f, 0.560662f, 0.555570f, 0.550458f,
0.545325f, 0.540171f, 0.534998f, 0.529804f, 0.524590f, 0.519356f,
0.514103f, 0.508830f, 0.503538f, 0.498228f, 0.492898f, 0.487550f,
0.482184f, 0.476799f, 0.471397f, 0.465976f, 0.460539f, 0.455084f,
0.449611f, 0.444122f, 0.438616f, 0.433094f, 0.427555f, 0.422000f,
0.416430f, 0.410843f, 0.405241f, 0.399624f, 0.393992f, 0.388345f,
0.382683f, 0.377007f, 0.371317f, 0.365613f, 0.359895f, 0.354164f,
0.348419f, 0.342661f, 0.336890f, 0.331106f, 0.325310f, 0.319502f,
0.313682f, 0.307850f, 0.302006f, 0.296151f, 0.290285f, 0.284408f,
0.278520f, 0.272621f, 0.266713f, 0.260794f, 0.254866f, 0.248928f,
0.242980f, 0.237024f, 0.231058f, 0.225084f, 0.219101f, 0.213110f,
0.207111f, 0.201105f, 0.195090f, 0.189069f, 0.183040f, 0.177004f,
0.170962f, 0.164913f, 0.158858f, 0.152797f, 0.146730f, 0.140658f,
0.134581f, 0.128498f, 0.122411f, 0.116319f, 0.110222f, 0.104122f,
0.098017f, 0.091909f, 0.085797f, 0.079682f, 0.073565f, 0.067444f,
0.061321f, 0.055195f, 0.049068f, 0.042938f, 0.036807f, 0.030675f,
0.024541f, 0.018407f, 0.012272f, 0.006136f, 0.000000f, -0.006136f,
-0.012272f, -0.018407f, -0.024541f, -0.030675f, -0.036807f, -0.042938f,
-0.049068f, -0.055195f, -0.061321f, -0.067444f, -0.073565f, -0.079682f,
-0.085797f, -0.091909f, -0.098017f, -0.104122f, -0.110222f, -0.116319f,
-0.122411f, -0.128498f, -0.134581f, -0.140658f, -0.146730f, -0.152797f,
-0.158858f, -0.164913f, -0.170962f, -0.177004f, -0.183040f, -0.189069f,
-0.195090f, -0.201105f, -0.207111f, -0.213110f, -0.219101f, -0.225084f,
-0.231058f, -0.237024f, -0.242980f, -0.248928f, -0.254866f, -0.260794f,
-0.266713f, -0.272621f, -0.278520f, -0.284408f, -0.290285f, -0.296151f,
-0.302006f, -0.307850f, -0.313682f, -0.319502f, -0.325310f, -0.331106f,
-0.336890f, -0.342661f, -0.348419f, -0.354164f, -0.359895f, -0.365613f,
-0.371317f, -0.377007f, -0.382683f, -0.388345f, -0.393992f, -0.399624f,
-0.405241f, -0.410843f, -0.416430f, -0.422000f, -0.427555f, -0.433094f,
-0.438616f, -0.444122f, -0.449611f, -0.455084f, -0.460539f, -0.465976f,
-0.471397f, -0.476799f, -0.482184f, -0.487550f, -0.492898f, -0.498228f,
-0.503538f, -0.508830f, -0.514103f, -0.519356f, -0.524590f, -0.529804f,
-0.534998f, -0.540171f, -0.545325f, -0.550458f, -0.555570f, -0.560662f,
-0.565732f, -0.570781f, -0.575808f, -0.580814f, -0.585798f, -0.590760f,
-0.595699f, -0.600616f, -0.605511f, -0.610383f, -0.615232f, -0.620057f,
-0.624859f, -0.629638f, -0.634393f, -0.639124f, -0.643832f, -0.648514f,
-0.653173f, -0.657807f, -0.662416f, -0.667000f, -0.671559f, -0.676093f,
-0.680601f, -0.685084f, -0.689541f, -0.693971f, -0.698376f, -0.702755f,
-0.707107f, -0.711432f, -0.715731f, -0.720003f, -0.724247f, -0.728464f,
-0.732654f, -0.736817f, -0.740951f, -0.745058f, -0.749136f, -0.753187f,
-0.757209f, -0.761202f, -0.765167f, -0.769103f, -0.773010f, -0.776888f,
-0.780737f, -0.784557f, -0.788346f, -0.792107f, -0.795837f, -0.799537f,
-0.803208f, -0.806848f, -0.810457f, -0.814036f, -0.817585f, -0.821103f,
-0.824589f, -0.828045f, -0.831470f, -0.834863f, -0.838225f, -0.841555f,
-0.844854f, -0.848120f, -0.851355f, -0.854558f, -0.857729f, -0.860867f,
-0.863973f, -0.867046f, -0.870087f, -0.873095f, -0.876070f, -0.879012f,
-0.881921f, -0.884797f, -0.887640f, -0.890449f, -0.893224f, -0.895966f,
-0.898674f, -0.901349f, -0.903989f, -0.906596f, -0.909168f, -0.911706f,
-0.914210f, -0.916679f, -0.919114f, -0.921514f, -0.923880f, -0.926210f,
-0.928506f, -0.930767f, -0.932993f, -0.935184f, -0.937339f, -0.939459f,
-0.941544f, -0.943593f, -0.945607f, -0.947586f, -0.949528f, -0.951435f,
-0.953306f, -0.955141f, -0.956940f, -0.958703f, -0.960431f, -0.962121f,
-0.963776f, -0.965394f, -0.966976f, -0.968522f, -0.970031f, -0.971504f,
-0.972940f, -0.974339f, -0.975702f, -0.977028f, -0.978317f, -0.979570f,
-0.980785f, -0.981964f, -0.983105f, -0.984210f, -0.985278f, -0.986308f,
-0.987301f, -0.988258f, -0.989177f, -0.990058f, -0.990903f, -0.991710f,
-0.992480f, -0.993212f, -0.993907f, -0.994565f, -0.995185f, -0.995767f,
-0.996313f, -0.996820f, -0.997290f, -0.997723f, -0.998118f, -0.998476f,
-0.998795f, -0.999078f, -0.999322f, -0.999529f, -0.999699f, -0.999831f,
-0.999925f, -0.999981f, -1.000000f, -0.999981f, -0.999925f, -0.999831f,
-0.999699f, -0.999529f, -0.999322f, -0.999078f, -0.998795f, -0.998476f,
-0.998118f, -0.997723f, -0.997290f, -0.996820f, -0.996313f, -0.995767f,
-0.995185f, -0.994565f, -0.993907f, -0.993212f, -0.992480f, -0.991710f,
-0.990903f, -0.990058f, -0.989177f, -0.988258f, -0.987301f, -0.986308f,
-0.985278f, -0.984210f, -0.983105f, -0.981964f, -0.980785f, -0.979570f,
-0.978317f, -0.977028f, -0.975702f, -0.974339f, -0.972940f, -0.971504f,
-0.970031f, -0.968522f, -0.966976f, -0.965394f, -0.963776f, -0.962121f,
-0.960431f, -0.958703f, -0.956940f, -0.955141f, -0.953306f, -0.951435f,
-0.949528f, -0.947586f, -0.945607f, -0.943593f, -0.941544f, -0.939459f,
-0.937339f, -0.935184f, -0.932993f, -0.930767f, -0.928506f, -0.926210f,
-0.923880f, -0.921514f, -0.919114f, -0.916679f, -0.914210f, -0.911706f,
-0.909168f, -0.906596f, -0.903989f, -0.901349f, -0.898674f, -0.895966f,
-0.893224f, -0.890449f, -0.887640f, -0.884797f, -0.881921f, -0.879012f,
-0.876070f, -0.873095f, -0.870087f, -0.867046f, -0.863973f, -0.860867f,
-0.857729f, -0.854558f, -0.851355f, -0.848120f, -0.844854f, -0.841555f,
-0.838225f, -0.834863f, -0.831470f, -0.828045f, -0.824589f, -0.821103f,
-0.817585f, -0.814036f, -0.810457f, -0.806848f, -0.803208f, -0.799537f,
-0.795837f, -0.792107f, -0.788346f, -0.784557f, -0.780737f, -0.776888f,
-0.773010f, -0.769103f, -0.765167f, -0.761202f, -0.757209f, -0.753187f,
-0.749136f, -0.745058f, -0.740951f, -0.736817f, -0.732654f, -0.728464f,
-0.724247f, -0.720003f, -0.715731f, -0.711432f, -0.707107f, -0.702755f,
-0.698376f, -0.693971f, -0.689541f, -0.685084f, -0.680601f, -0.676093f,
-0.671559f, -0.667000f, -0.662416f, -0.657807f, -0.653173f, -0.648514f,
-0.643832f, -0.639124f, -0.634393f, -0.629638f, -0.624859f, -0.620057f,
-0.615232f, -0.610383f, -0.605511f, -0.600616f, -0.595699f, -0.590760f,
-0.585798f, -0.580814f, -0.575808f, -0.570781f, -0.565732f, -0.560662f,
-0.555570f, -0.550458f, -0.545325f, -0.540171f, -0.534998f, -0.529804f,
-0.524590f, -0.519356f, -0.514103f, -0.508830f, -0.503538f, -0.498228f,
-0.492898f, -0.487550f, -0.482184f, -0.476799f, -0.471397f, -0.465976f,
-0.460539f, -0.455084f, -0.449611f, -0.444122f, -0.438616f, -0.433094f,
-0.427555f, -0.422000f, -0.416430f, -0.410843f, -0.405241f, -0.399624f,
-0.393992f, -0.388345f, -0.382683f, -0.377007f, -0.371317f, -0.365613f,
-0.359895f, -0.354164f, -0.348419f, -0.342661f, -0.336890f, -0.331106f,
-0.325310f, -0.319502f, -0.313682f, -0.307850f, -0.302006f, -0.296151f,
-0.290285f, -0.284408f, -0.278520f, -0.272621f, -0.266713f, -0.260794f,
-0.254866f, -0.248928f, -0.242980f, -0.237024f, -0.231058f, -0.225084f,
-0.219101f, -0.213110f, -0.207111f, -0.201105f, -0.195090f, -0.189069f,
-0.183040f, -0.177004f, -0.170962f, -0.164913f, -0.158858f, -0.152797f,
-0.146730f, -0.140658f, -0.134581f, -0.128498f, -0.122411f, -0.116319f,
-0.110222f, -0.104122f, -0.098017f, -0.091909f, -0.085797f, -0.079682f,
-0.073565f, -0.067444f, -0.061321f, -0.055195f, -0.049068f, -0.042938f,
-0.036807f, -0.030675f, -0.024541f, -0.018407f, -0.012272f, -0.006136f,
-0.000000f, 0.006136f, 0.012272f, 0.018407f, 0.024541f, 0.030675f,
0.036807f, 0.042938f, 0.049068f, 0.055195f, 0.061321f, 0.067444f,
0.073565f, 0.079682f, 0.085797f, 0.091909f, 0.098017f, 0.104122f,
0.110222f, 0.116319f, 0.122411f, 0.128498f, 0.134581f, 0.140658f,
0.146730f, 0.152797f, 0.158858f, 0.164913f, 0.170962f, 0.177004f,
0.183040f, 0.189069f, 0.195090f, 0.201105f, 0.207111f, 0.213110f,
0.219101f, 0.225084f, 0.231058f, 0.237024f, 0.242980f, 0.248928f,
0.254866f, 0.260794f, 0.266713f, 0.272621f, 0.278520f, 0.284408f,
0.290285f, 0.296151f, 0.302006f, 0.307850f, 0.313682f, 0.319502f,
0.325310f, 0.331106f, 0.336890f, 0.342661f, 0.348419f, 0.354164f,
0.359895f, 0.365613f, 0.371317f, 0.377007f, 0.382683f, 0.388345f,
0.393992f, 0.399624f, 0.405241f, 0.410843f, 0.416430f, 0.422000f,
0.427555f, 0.433094f, 0.438616f, 0.444122f, 0.449611f, 0.455084f,
0.460539f, 0.465976f, 0.471397f, 0.476799f, 0.482184f, 0.487550f,
0.492898f, 0.498228f, 0.503538f, 0.508830f, 0.514103f, 0.519356f,
0.524590f, 0.529804f, 0.534998f, 0.540171f, 0.545325f, 0.550458f,
0.555570f, 0.560662f, 0.565732f, 0.570781f, 0.575808f, 0.580814f,
0.585798f, 0.590760f, 0.595699f, 0.600616f, 0.605511f, 0.610383f,
0.615232f, 0.620057f, 0.624859f, 0.629638f, 0.634393f, 0.639124f,
0.643832f, 0.648514f, 0.653173f, 0.657807f, 0.662416f, 0.667000f,
0.671559f, 0.676093f, 0.680601f, 0.685084f, 0.689541f, 0.693971f,
0.698376f, 0.702755f, 0.707107f, 0.711432f, 0.715731f, 0.720003f,
0.724247f, 0.728464f, 0.732654f, 0.736817f, 0.740951f, 0.745058f,
0.749136f, 0.753187f, 0.757209f, 0.761202f, 0.765167f, 0.769103f,
0.773010f, 0.776888f, 0.780737f, 0.784557f, 0.788346f, 0.792107f,
0.795837f, 0.799537f, 0.803208f, 0.806848f, 0.810457f, 0.814036f,
0.817585f, 0.821103f, 0.824589f, 0.828045f, 0.831470f, 0.834863f,
0.838225f, 0.841555f, 0.844854f, 0.848120f, 0.851355f, 0.854558f,
0.857729f, 0.860867f, 0.863973f, 0.867046f, 0.870087f, 0.873095f,
0.876070f, 0.879012f, 0.881921f, 0.884797f, 0.887640f, 0.890449f,
0.893224f, 0.895966f, 0.898674f, 0.901349f, 0.903989f, 0.906596f,
0.909168f, 0.911706f, 0.914210f, 0.916679f, 0.919114f, 0.921514f,
0.923880f, 0.926210f, 0.928506f, 0.930767f, 0.932993f, 0.935184f,
0.937339f, 0.939459f, 0.941544f, 0.943593f, 0.945607f, 0.947586f,
0.949528f, 0.951435f, 0.953306f, 0.955141f, 0.956940f, 0.958703f,
0.960431f, 0.962121f, 0.963776f, 0.965394f, 0.966976f, 0.968522f,
0.970031f, 0.971504f, 0.972940f, 0.974339f, 0.975702f, 0.977028f,
0.978317f, 0.979570f, 0.980785f, 0.981964f, 0.983105f, 0.984210f,
0.985278f, 0.986308f, 0.987301f, 0.988258f, 0.989177f, 0.990058f,
0.990903f, 0.991710f, 0.992480f, 0.993212f, 0.993907f, 0.994565f,
0.995185f, 0.995767f, 0.996313f, 0.996820f, 0.997290f, 0.997723f,
0.998118f, 0.998476f, 0.998795f, 0.999078f, 0.999322f, 0.999529f,
0.999699f, 0.999831f, 0.999925f, 0.999981f};
#endif
-151
View File
@@ -1,151 +0,0 @@
#include "Filter.h"
#include "Can.h"
#include "ang_sensor.h"
#include <algorithm>
#include <cstring>
#include <stdint.h>
extern angle_sensor KTH7823;
extern CAN_transmiter CAN0_transmiter;
extern u32 system_runtime_us;
EncoderAngleKalman Angle_kalman(0, 1.0f, 1e-4f, 0.25f);
EncoderVelocityKalman Vel_kalman(0, 1e-5f, 1e-6f, 0.02f);
constexpr u8 SIZE_FLOAT = sizeof(float);
/*!
\brief 中值滤波器函数
\param[in] values 待滤波的数据数组
\param[in] size 数组大小
\retval 滤波后的中值
\note 使用部分排序优化算法提高效率
*/
float medium_filter(float values[], u8 size) {
// 使用局部数组避免动态内存分配
float sorted[size];
memcpy(sorted, values, size * SIZE_FLOAT);
// 这比完整排序更高效,时间复杂度从O(n log n)降低到O(n)
std::nth_element(sorted, sorted + size / 2, sorted + size);
return sorted[size / 2]; // 返回中值
}
// EncoderVelocityKalman类的实现
/*!
\brief 构造函数,初始化编码器速度卡尔曼滤波器参数
\param[in] initial_velocity 初始速度值 (rad/s)
\param[in] T 控制周期(s)
\param[in] Q 过程噪声协方差(典型值: 1e-4 ~ 1e-2)
\param[in] R 测量噪声协方差(典型值: 速度范围的1%~5%)
\retval none
*/
EncoderVelocityKalman::EncoderVelocityKalman(float initial_velocity, float T,
float Q, float R)
: kalman(initial_velocity, T, Q, R) {}
/*!
\brief 更新卡尔曼滤波器状态
\param[in] measured_velocity 测量的速度值 (rad/s)
\retval 估计的速度值 (rad/s)
\note 实现卡尔曼滤波的预测和更新步骤,假设速度变化符合随机游走模型
*/
float EncoderVelocityKalman::update(float measured_velocity) {
// 1. 预测步骤 - 假设速度符合随机游走模型(加速度为0)
// 由于速度变化缓慢,我们可以简单预测速度保持不变
kalman.predict(kalman.getState());
// 2. 更新步骤 - 直接使用测量值更新
return kalman.update(measured_velocity);
}
/*!
\brief 获取当前速度估计值
\retval 当前速度估计值 (deg/s)
*/
float EncoderVelocityKalman::getVelocity() const { return kalman.getState(); }
/*!
\brief 设置过程噪声协方差
\param[in] q 过程噪声协方差值
\retval none
*/
void EncoderVelocityKalman::setProcessNoise(float q) {
kalman.setProcessNoise(q);
}
/*!
\brief 设置测量噪声协方差
\param[in] r 测量噪声协方差值
\retval none
*/
void EncoderVelocityKalman::setMeasurementNoise(float r) {
kalman.setMeasurementNoise(r);
}
// EncoderAngleKalman类的实现
/*!
\brief 构造函数,初始化编码器角度卡尔曼滤波器参数
\param[in] initial_angle 初始角度值 (degree)
\param[in] initial_error_covariance 初始误差协方差
\param[in] process_noise 过程噪声协方差
\param[in] measurement_noise 测量噪声协方差
\retval none
*/
EncoderAngleKalman::EncoderAngleKalman(float initial_angle,
float initial_error_covariance,
float process_noise,
float measurement_noise)
: kalman(initial_angle, initial_error_covariance, process_noise,
measurement_noise),
last_angle(initial_angle), initialized(true) {}
/*!
\brief 更新卡尔曼滤波器状态
\param[in] measured_angle 测量的角度值 (degree)
\retval 估计的角度值 (degree)
\note 实现卡尔曼滤波的预测和更新步骤
*/
float EncoderAngleKalman::update(float measured_angle) {
// 更新last_angle以支持速度计算
last_angle = kalman.getState();
// 1. 预测步骤 - 速度估计
kalman.predict(last_angle);
// 2. 更新步骤 - 使用处理后的角度值更新
float filtered_angle = kalman.update(measured_angle);
return filtered_angle;
}
/*!
\brief 获取当前角度估计值
\retval 当前角度估计值 (degree)
*/
float EncoderAngleKalman::getAngle() const { return kalman.getState(); }
/*!
\brief 获取当前角度估计值
\retval 当前角度估计值 (degree)
*/
float EncoderAngleKalman::getVelocity() const {
static u32 last_us100_counter = system_runtime_us;
float vel = (kalman.getState() - last_angle) * 1e4 *
(system_runtime_us - last_us100_counter);
last_us100_counter = system_runtime_us;
return vel;
}
/*!
\brief 设置过程噪声协方差
\param[in] q 过程噪声协方差值
\retval none
*/
void EncoderAngleKalman::setProcessNoise(float q) { kalman.setProcessNoise(q); }
/*!
\brief 设置测量噪声协方差
\param[in] r 测量噪声协方差值
\retval none
*/
void EncoderAngleKalman::setMeasurementNoise(float r) {
kalman.setMeasurementNoise(r);
}
-164
View File
@@ -1,164 +0,0 @@
#ifndef _FILTER_H
#define _FILTER_H
#ifdef __cplusplus
extern "C" {
#endif
// C风格函数声明可以放在这里
// 例如: void some_c_function(float* data, int size);
#ifdef __cplusplus
} // extern "C"
#endif
#ifdef __cplusplus
#include <cstring>
#include <stdint.h>
float medium_filter(float values[], u8 size);
/*!
\brief 通用卡尔曼滤波器模板类
\note 可用于各种基于线性系统的状态估计
*/
template <typename T> class KalmanFilter {
private:
T P; // 估计误差协方差
T Q; // 过程噪声协方差
T R; // 测量噪声协方差
public:
T x; // 状态估计
/*!
\brief 构造函数
\param[in] initial_state 初始状态值
\param[in] initial_error_covariance 初始误差协方差
\param[in] process_noise 过程噪声协方差
\param[in] measurement_noise 测量噪声协方差
*/
KalmanFilter(T initial_state, T initial_error_covariance, T process_noise,
T measurement_noise)
: x(initial_state), P(initial_error_covariance), Q(process_noise),
R(measurement_noise) {}
/*!
\brief 预测步骤
\param[in] state_prediction 状态预测值
\retval none
*/
void predict(T state_prediction) {
x = state_prediction;
P += Q;
}
/*!
\brief 更新步骤
\param[in] measurement 测量值
\param[in] measurement_prediction 测量预测值
\retval 估计的状态值
*/
T update(T measurement, T measurement_prediction) {
T y = measurement - measurement_prediction; // 测量残差
T S = P + R; // 残差协方差
T K = P / S; // 卡尔曼增益
x += K * y; // 更新状态估计
P = (1 - K) * P; // 更新误差协方差
return x;
}
/*!
\brief 直接更新步骤(适用于状态直接可测的情况)
\param[in] measurement 测量值
\retval 估计的状态值
*/
T update(T measurement) {
T K = P / (P + R); // 卡尔曼增益
x += K * (measurement - x); // 更新状态估计
P = (1 - K) * P; // 更新误差协方差
return x;
}
/*!
\brief 获取当前状态估计值
\retval 当前状态估计值
*/
T getState() const { return x; }
/*!
\brief 设置过程噪声协方差
\param[in] process_noise 过程噪声协方差值
\retval none
*/
void setProcessNoise(T process_noise) { Q = process_noise; }
/*!
\brief 设置测量噪声协方差
\param[in] measurement_noise 测量噪声协方差值
\retval none
*/
void setMeasurementNoise(T measurement_noise) { R = measurement_noise; }
};
/*!
\brief 编码器速度卡尔曼滤波器类
\note 用于滤除编码器速度测量噪声的卡尔曼滤波器实现
*/
class EncoderVelocityKalman {
private:
KalmanFilter<float> kalman;
public:
EncoderVelocityKalman(float initial_velocity,
float initial_error_covariance, float process_noise,
float measurement_noise);
float update(float measured_velocity);
float getVelocity() const;
void setProcessNoise(float q);
void setMeasurementNoise(float r);
u8 init(float init_velocity) {
kalman.x = init_velocity;
return 0;
}
};
/*!
\brief 编码器角度卡尔曼滤波器类
\note 用于滤除编码器角度测量噪声的卡尔曼滤波器实现
*/
class EncoderAngleKalman {
private:
KalmanFilter<float> kalman;
bool initialized;
float last_angle;
public:
EncoderAngleKalman(float initial_angle, float initial_error_covariance,
float process_noise, float measurement_noise);
float update(float measured_angle);
float getAngle() const;
float getVelocity() const;
void setProcessNoise(float q);
float getstate() const { return kalman.getState(); };
void setMeasurementNoise(float r);
u8 init(float init_angle) {
kalman.x = init_angle;
return 0;
}
};
#endif // __cplusplus
#endif // _FILTER_H
-60
View File
@@ -1,60 +0,0 @@
#include "pid.h"
#define _constrain(amt, low, high) \
((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
#include "Can.h"
#include "math.h"
extern CAN_transmiter CAN0_transmiter;
constexpr float TIME_SLICE = 1e-4;
PIDController::PIDController(float P, float I, float D, float ramp, float limit)
: P(P), I(I), D(D), output_ramp(ramp) // PID控制器加速度限幅
,
limit(limit) // PID控制器输出限幅
,
error_prev(0.0f), output_prev(0.0f), integral_prev(0.0f) {}
// PID 控制器函数
float PIDController::operator()(float error) {
// P环
float proportional = P * error;
// Tustin 散点积分(I环)
// 添加积分限幅,防止积分饱和
float integral = integral_prev + I * TIME_SLICE * 0.5f * (error + error_prev);
integral = _constrain(integral, -limit, limit);
// D环(微分环节)
float derivative = D * (error - error_prev) / TIME_SLICE;
// 将P,I,D三环的计算值加起来
float output = proportional + integral + derivative;
output = _constrain(output, -limit, limit);
// 输出斜坡限制
// 简化的斜坡限制(单行逻辑)
if (output_ramp > 0) {
float max_delta = output_ramp * TIME_SLICE;
output = output_prev + fmaxf(-max_delta, fminf(max_delta, output - output_prev));
}
// 保存值(为了下一次循环)
integral_prev = integral;
output_prev = output;
error_prev = error;
return output;
}
/**
* @brief 设置PID参数
*
* @param P: P参数
* @param I: I参数
* @param D: D参数
* @return void
*/
void PIDController::set_PID(float P, float I, float D) {
this->P = P;
this->I = I;
this->D = D;
}
-25
View File
@@ -1,25 +0,0 @@
#ifndef PID_H
#define PID_H
class PIDController
{
public:
PIDController(float P, float I, float D, float ramp, float limit);
~PIDController() = default;
float operator() (float error);
void set_PID(float P, float I, float D);
float P; //!< 比例增益(P环增益)
float I; //!< 积分增益(I环增益)
float D; //!< 微分增益(D环增益)
float output_ramp;
float limit;
protected:
float error_prev; //!< 最后的跟踪误差值
float output_prev; //!< 最后一个 pid 输出值
float integral_prev; //!< 最后一个积分分量值
unsigned long timestamp_prev; //!< 上次执行时间戳
};
#endif
View File
-7
View File
@@ -1,7 +0,0 @@
#ifndef THERMAL_H
#define THERMAL_H
#endif
@@ -2,11 +2,11 @@
\file gd32c10x_adc.c
\brief ADC driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -508,8 +508,8 @@ void adc_inserted_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t ad
inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U);
/* the channel number is written to these bits to select a channel as the nth conversion in the inserted channel group */
isq = ADC_ISQ(adc_periph);
isq &= ~((uint32_t)(ADC_ISQ_ISQN << (5U * ((3 + rank) - inserted_length))));
isq |= ((uint32_t)adc_channel << (5U * ((3 + rank) - inserted_length)));
isq &= ~((uint32_t)(ADC_ISQ_ISQN << (5U * ((3U + rank) - inserted_length))));
isq |= ((uint32_t)adc_channel << (5U * ((3U + rank) - inserted_length)));
ADC_ISQ(adc_periph) = isq;
/* ADC sampling time config */
@@ -669,7 +669,6 @@ void adc_software_trigger_enable(uint32_t adc_periph , uint8_t adc_channel_group
/*!
\brief read ADC regular group data register
\param[in] adc_periph: ADCx,x=0,1
\param[in] none
\param[out] none
\retval the conversion value
*/
@@ -848,7 +847,6 @@ void adc_flag_clear(uint32_t adc_periph , uint32_t adc_flag)
/*!
\brief get the bit state of ADCx software start conversion
\param[in] adc_periph: ADCx, x=0,1, only one among these parameters can be selected
\param[in] none
\param[out] none
\retval FlagStatus: SET or RESET
*/
@@ -864,7 +862,6 @@ FlagStatus adc_regular_software_startconv_flag_get(uint32_t adc_periph)
/*!
\brief get the bit state of ADCx software inserted channel start conversion
\param[in] adc_periph: ADCx, x=0,1 only one among these parameters can be selected
\param[in] none
\param[out] none
\retval FlagStatus: SET or RESET
*/
+12 -6
View File
@@ -2,11 +2,11 @@
\file gd32c10x_bkp.c
\brief BKP driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -287,11 +287,14 @@ void bkp_interrupt_disable(void)
*/
FlagStatus bkp_flag_get(void)
{
FlagStatus ret;
if(RESET != (BKP_TPCS & BKP_FLAG_TAMPER)){
return SET;
ret = SET;
}else{
return RESET;
ret = RESET;
}
return ret;
}
/*!
@@ -313,11 +316,14 @@ void bkp_flag_clear(void)
*/
FlagStatus bkp_interrupt_flag_get(void)
{
FlagStatus ret;
if(RESET != (BKP_TPCS & BKP_INT_FLAG_TAMPER)){
return SET;
ret = SET;
}else{
return RESET;
ret = RESET;
}
return ret;
}
/*!
+137 -99
View File
@@ -2,11 +2,11 @@
\file gd32c10x_can.c
\brief CAN driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -33,7 +33,6 @@ OF SUCH DAMAGE.
*/
#include "gd32c10x_can.h"
#include "stdio.h"
#include <stdlib.h>
#define CAN_ERROR_HANDLE(s) do{}while(1)
@@ -301,10 +300,11 @@ ErrStatus can_fd_init(uint32_t can_periph, can_fdframe_struct *can_fdframe_init)
{
uint32_t timeout = CAN_TIMEOUT;
uint32_t tempreg = 0U;
ErrStatus reval = SUCCESS;
/* check null pointer */
if(0 == can_fdframe_init) {
return ERROR;
reval = ERROR;
}
/* disable sleep mode */
CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD;
@@ -316,7 +316,7 @@ ErrStatus can_fd_init(uint32_t can_periph, can_fdframe_struct *can_fdframe_init)
}
/* check initialize working success */
if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) {
return ERROR;
reval = ERROR;
} else {
/* set the data bit timing register */
CAN_DBT(can_periph) = (BT_DSJW((uint32_t)can_fdframe_init->data_resync_jump_width) | \
@@ -342,7 +342,7 @@ ErrStatus can_fd_init(uint32_t can_periph, can_fdframe_struct *can_fdframe_init)
CAN_FDTDC(can_periph) = (FDTDC_TDCF(can_fdframe_init->p_delay_compensation->tdc_filter) | FDTDC_TDCO(
can_fdframe_init->p_delay_compensation->tdc_offset));
} else {
return ERROR;
reval = ERROR;
}
} else {
/* Transmitter delay compensation mode is disabled */
@@ -366,11 +366,11 @@ ErrStatus can_fd_init(uint32_t can_periph, can_fdframe_struct *can_fdframe_init)
}
/* check exit initialize mode */
if(0U == timeout) {
return ERROR;
reval = ERROR;
}
}
return SUCCESS;
return reval;
}
/*!
@@ -747,90 +747,89 @@ uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct *t
} else {
mailbox_number = CAN_NOMAILBOX;
}
/* return no mailbox empty */
if(CAN_NOMAILBOX == mailbox_number) {
return CAN_NOMAILBOX;
}
/* got one empty mailbox */
if(CAN_NOMAILBOX != mailbox_number) {
CAN_TMI(can_periph, mailbox_number) &= CAN_TMI_TEN;
if(CAN_FF_STANDARD == transmit_message->tx_ff) {
/* set transmit mailbox standard identifier */
CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_SFID(transmit_message->tx_sfid) | \
transmit_message->tx_ft);
} else {
/* set transmit mailbox extended identifier */
CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_EFID(transmit_message->tx_efid) | \
transmit_message->tx_ff | \
transmit_message->tx_ft);
}
if(CAN_FDF_CLASSIC == transmit_message->fd_flag) {
/* set the data length */
CAN_TMP(can_periph, mailbox_number) &= ~(CAN_TMP_DLENC | CAN_TMP_ESI | CAN_TMP_BRS | CAN_TMP_FDF);
/* Classic CAN frame data length does not exceed 8 */
if (transmit_message->tx_dlen > 8U) {
transmit_message->tx_dlen = 8U;
CAN_TMI(can_periph, mailbox_number) &= CAN_TMI_TEN;
if(CAN_FF_STANDARD == transmit_message->tx_ff) {
/* set transmit mailbox standard identifier */
CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_SFID(transmit_message->tx_sfid) | \
transmit_message->tx_ft);
} else {
/* set transmit mailbox extended identifier */
CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_EFID(transmit_message->tx_efid) | \
transmit_message->tx_ff | \
transmit_message->tx_ft);
}
CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen;
/* set the data */
CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \
TMDATA0_DB2(transmit_message->tx_data[2]) | \
TMDATA0_DB1(transmit_message->tx_data[1]) | \
TMDATA0_DB0(transmit_message->tx_data[0]);
CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \
TMDATA1_DB6(transmit_message->tx_data[6]) | \
TMDATA1_DB5(transmit_message->tx_data[5]) | \
TMDATA1_DB4(transmit_message->tx_data[4]);
} else {
canfd_en = CAN_FDCTL(can_periph) & CAN_FDCTL_FDEN;
/* check FD function has been enabled */
if(canfd_en) {
if(transmit_message->tx_dlen <= 8U) {
/* set the data length */
reg_temp |= transmit_message->tx_dlen;
} else {
/* data length greater than 8 */
for(i = 0U; i < 7U; i++) {
if(transmit_message->tx_dlen == g_can_fdlength_table[i]) {
hit = 1U;
break;
if(CAN_FDF_CLASSIC == transmit_message->fd_flag) {
/* set the data length */
CAN_TMP(can_periph, mailbox_number) &= ~(CAN_TMP_DLENC | CAN_TMP_ESI | CAN_TMP_BRS | CAN_TMP_FDF);
/* Classic CAN frame data length does not exceed 8 */
if (transmit_message->tx_dlen > 8U) {
transmit_message->tx_dlen = 8U;
}
CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen;
/* set the data */
CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \
TMDATA0_DB2(transmit_message->tx_data[2]) | \
TMDATA0_DB1(transmit_message->tx_data[1]) | \
TMDATA0_DB0(transmit_message->tx_data[0]);
CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \
TMDATA1_DB6(transmit_message->tx_data[6]) | \
TMDATA1_DB5(transmit_message->tx_data[5]) | \
TMDATA1_DB4(transmit_message->tx_data[4]);
} else {
canfd_en = CAN_FDCTL(can_periph) & CAN_FDCTL_FDEN;
/* check FD function has been enabled */
if(canfd_en) {
if(transmit_message->tx_dlen <= 8U) {
/* set the data length */
reg_temp |= transmit_message->tx_dlen;
} else {
/* data length greater than 8 */
for(i = 0U; i < 7U; i++) {
if(transmit_message->tx_dlen == g_can_fdlength_table[i]) {
hit = 1U;
break;
}
}
/* data length is valid */
if(1U == hit) {
reg_temp |= 9U + i;
} else {
CAN_ERROR_HANDLE("dlen is invalid \r\n");
}
}
/* data length is valid */
if(1U == hit) {
reg_temp |= 9U + i;
} else {
CAN_ERROR_HANDLE("dlen is invalid \r\n");
reg_temp |= (((uint32_t)transmit_message->fd_brs << 5U) | ((uint32_t)transmit_message->fd_esi << 4U) | ((uint32_t)transmit_message->fd_flag << 7U));
CAN_TMP(can_periph, mailbox_number) = reg_temp;
/* set the data */
i = transmit_message->tx_dlen / 4U;
/* data length is 5-7 need send 2 word */
if((1U == i) && (4U != transmit_message->tx_dlen)) {
i++;
}
}
reg_temp |= (((uint32_t)transmit_message->fd_brs << 5U) | ((uint32_t)transmit_message->fd_esi << 4U) | ((uint32_t)transmit_message->fd_flag << 7U));
CAN_TMP(can_periph, mailbox_number) = reg_temp;
/* set the data */
i = transmit_message->tx_dlen / 4U;
/* data length is 5-7 need send 2 word */
if((1U == i) && (4U != transmit_message->tx_dlen)) {
i++;
}
p_temp = (uint32_t)transmit_message->tx_data;
if((0U == i)) {
CAN_TMDATA0(can_periph, mailbox_number) = *(uint32_t *)p_temp;
} else {
for(; i > 0U; i--) {
p_temp = (uint32_t)transmit_message->tx_data;
if((0U == i)) {
CAN_TMDATA0(can_periph, mailbox_number) = *(uint32_t *)p_temp;
p_temp = ((uint32_t)((uint32_t)p_temp + 4U));
} else {
for(; i > 0U; i--) {
CAN_TMDATA0(can_periph, mailbox_number) = *(uint32_t *)p_temp;
p_temp = ((uint32_t)((uint32_t)p_temp + 4U));
}
}
} else {
CAN_ERROR_HANDLE("CAN FD function disabled \r\n");
}
} else {
CAN_ERROR_HANDLE("CAN FD function disabled \r\n");
}
/* enable transmission */
CAN_TMI(can_periph, mailbox_number) |= CAN_TMI_TEN;
}
/* enable transmission */
CAN_TMI(can_periph, mailbox_number) |= CAN_TMI_TEN;
return mailbox_number;
}
@@ -901,25 +900,63 @@ can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox
only one parameter can be selected which is shown as below:
\arg CAN_MAILBOXx(x=0,1,2)
\param[out] none
\retval none
\retval ErrStatus: ERROR or SUCCESS
*/
void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number)
ErrStatus can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number)
{
ErrStatus reval = SUCCESS;
/* timeout for CAN_TSTAT_MSTx bits */
uint32_t timeout = CAN_TIMEOUT;
uint32_t reg_value0 = 0U;
uint32_t reg_value1 = 0U;
/* get the status of transmit FIFO order */
reg_value0 = CAN_CTL(can_periph) & CAN_CTL_TFO;
if(CAN_MAILBOX0 == mailbox_number) {
CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0;
while(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)) {
reg_value1 = CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS0 | CAN_ALL_MAILBOX_EMPTY);
if((CAN_CTL_TFO == reg_value0) && (CAN_TSTAT_TMLS0 == reg_value1)){
reval = ERROR;
} else {
CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0;
while((CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)) && (0U != timeout)) {
timeout--;
}
if(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)){
reval = ERROR;
}
}
} else if(CAN_MAILBOX1 == mailbox_number) {
CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1;
while(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)) {
reg_value1 = CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS1 | CAN_ALL_MAILBOX_EMPTY);
if((CAN_CTL_TFO == reg_value0) && (CAN_TSTAT_TMLS1 == reg_value1)){
reval = ERROR;
}else{
CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1;
while((CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)) && (0U != timeout)) {
timeout--;
}
if(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)){
reval = ERROR;
}
}
} else if(CAN_MAILBOX2 == mailbox_number) {
CAN_TSTAT(can_periph) |= CAN_TSTAT_MST2;
while(CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)) {
reg_value1 = CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS2 | CAN_ALL_MAILBOX_EMPTY);
if((CAN_CTL_TFO == reg_value0) && (CAN_TSTAT_TMLS2 == reg_value1)){
reval = ERROR;
}else{
CAN_TSTAT(can_periph) |= CAN_TSTAT_MST2;
while((CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)) && (0U != timeout)) {
timeout--;
}
if(CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)){
reval = ERROR;
}
}
} else {
/* illegal parameters */
}
return reval;
}
/*!
@@ -976,13 +1013,10 @@ void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_m
receive_message->rx_data[5] = (uint8_t)(GET_RFIFOMDATA1_DB5(CAN_RFIFOMDATA1(can_periph, fifo_number)));
receive_message->rx_data[6] = (uint8_t)(GET_RFIFOMDATA1_DB6(CAN_RFIFOMDATA1(can_periph, fifo_number)));
receive_message->rx_data[7] = (uint8_t)(GET_RFIFOMDATA1_DB7(CAN_RFIFOMDATA1(can_periph, fifo_number)));
} else {
printf("CAN FD function disabled but FD frame received\r\n");
// CAN_ERROR_HANDLE("CAN FD function disabled \r\n");
} else {
CAN_ERROR_HANDLE("CAN FD function disabled \r\n");
}
} else {
/* check FD function has been enabled */
/* get receive data length */
canfd_recv_cnt = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number)));
@@ -1322,12 +1356,14 @@ void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt)
*/
FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag)
{
FlagStatus retval;
/* get flag and interrupt enable state */
if(RESET != (CAN_REG_VAL(can_periph, flag) & BIT(CAN_BIT_POS(flag)))) {
return SET;
retval = SET;
} else {
return RESET;
retval = RESET;
}
return retval;
}
/*!
@@ -1390,6 +1426,7 @@ void can_flag_clear(uint32_t can_periph, can_flag_enum flag)
*/
FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum flag)
{
FlagStatus retval;
uint32_t ret1 = RESET;
uint32_t ret2 = RESET;
@@ -1406,10 +1443,11 @@ FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum f
/* get the status of interrupt enable bit */
ret2 = CAN_INTEN(can_periph) & BIT(CAN_BIT_POS1(flag));
if(ret1 && ret2) {
return SET;
retval = SET;
} else {
return RESET;
retval = RESET;
}
return retval;
}
/*!
@@ -2,11 +2,11 @@
\file gd32c10x_crc.c
\brief CRC driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -117,11 +117,11 @@ uint32_t crc_single_data_calculate(uint32_t sdata)
\param[out] none
\retval 32-bit value calculated by CRC
*/
uint32_t crc_block_data_calculate(const uint32_t *array, uint32_t size)
uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size)
{
uint32_t index;
for(index = 0U; index < size; index++){
CRC_DATA = *(array+index);
CRC_DATA = array[index];
}
return (CRC_DATA);
}
+18 -10
View File
@@ -2,11 +2,11 @@
\file gd32c10x_ctc.c
\brief CTC driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -79,7 +79,7 @@ void ctc_counter_disable(void)
/*!
\brief configure the IRC48M trim value
\param[in] ctc_trim_value: 8-bit IRC48M trim value
\param[in] trim_value: 8-bit IRC48M trim value
\arg 0x00 - 0x3F
\param[out] none
\retval none
@@ -218,11 +218,14 @@ uint16_t ctc_counter_capture_value_read(void)
*/
FlagStatus ctc_counter_direction_read(void)
{
FlagStatus ret;
if(RESET != (CTC_STAT & CTC_STAT_REFDIR)){
return SET;
ret = SET;
}else{
return RESET;
ret = RESET;
}
return ret;
}
/*!
@@ -300,7 +303,8 @@ void ctc_interrupt_disable(uint32_t interrupt)
FlagStatus ctc_interrupt_flag_get(uint32_t interrupt)
{
uint32_t intflag = 0U, intenable = 0U;
FlagStatus ret;
/* check whether the interrupt is enabled */
if(RESET != (interrupt & CTC_FLAG_MASK)){
intenable = CTC_CTL0 & CTC_CTL0_ERRIE;
@@ -312,10 +316,11 @@ FlagStatus ctc_interrupt_flag_get(uint32_t interrupt)
intflag = CTC_STAT & interrupt;
if(intflag && intenable){
return SET;
ret = SET;
}else{
return RESET;
ret = RESET;
}
return ret;
}
/*!
@@ -357,11 +362,14 @@ void ctc_interrupt_flag_clear(uint32_t interrupt)
*/
FlagStatus ctc_flag_get(uint32_t flag)
{
FlagStatus ret;
if(RESET != (CTC_STAT & flag)){
return SET;
ret = SET;
}else{
return RESET;
ret = RESET;
}
return ret;
}
/*!
@@ -2,11 +2,11 @@
\file gd32c10x_dac.c
\brief DAC driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -318,6 +318,7 @@ void dac_trigger_source_config(uint32_t dac_periph, uint8_t dac_out, uint32_t tr
\brief enable DAC software trigger
\param[in] dac_periph: DACx(x=0)
\param[in] dac_out: DAC_OUTx(x=0,1)
\param[out] none
\retval none
*/
void dac_software_trigger_enable(uint32_t dac_periph, uint8_t dac_out)
@@ -2,11 +2,11 @@
\file gd32c10x_dbg.c
\brief DBG driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -2,11 +2,11 @@
\file gd32c10x_dma.c
\brief DMA driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -614,6 +614,7 @@ void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t fla
FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
{
uint32_t interrupt_enable = 0U, interrupt_flag = 0U;
FlagStatus status = RESET;
switch(flag){
case DMA_INT_FLAG_FTF:
@@ -637,10 +638,11 @@ FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx
/* when the interrupt flag is set and enabled, return SET */
if((0U != interrupt_flag) && (0U != interrupt_enable)){
return SET;
status = SET;
}else{
return RESET;
status = RESET;
}
return status;
}
/*!
@@ -2,11 +2,11 @@
\file gd32c10x_exmc.c
\brief EXMC driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
+12 -6
View File
@@ -2,11 +2,11 @@
\file gd32c10x_exti.c
\brief EXTI driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -196,11 +196,14 @@ void exti_software_interrupt_disable(exti_line_enum linex)
*/
FlagStatus exti_flag_get(exti_line_enum linex)
{
FlagStatus ret;
if(RESET != (EXTI_PD & (uint32_t)linex)) {
return SET;
ret = SET;
} else {
return RESET;
ret = RESET;
}
return ret;
}
/*!
@@ -226,11 +229,14 @@ void exti_flag_clear(exti_line_enum linex)
*/
FlagStatus exti_interrupt_flag_get(exti_line_enum linex)
{
FlagStatus ret;
if(RESET != (EXTI_PD & (uint32_t)linex)) {
return SET;
ret = SET;
} else {
return RESET;
ret = RESET;
}
return ret;
}
/*!
+13 -10
View File
@@ -2,11 +2,11 @@
\file gd32c10x_fmc.c
\brief FMC driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -33,7 +33,6 @@ OF SUCH DAMAGE.
*/
#include "gd32c10x_fmc.h"
#include "stdio.h"
/* FMC mask */
#define LOW_8BITS_MASK ((uint32_t)0x000000FFU)
@@ -508,7 +507,7 @@ fmc_state_enum ob_write_protection_enable(uint32_t ob_wp)
*/
fmc_state_enum ob_security_protection_config(uint8_t ob_spc)
{
uint8_t i;
uint32_t i;
uint32_t op_byte[4];
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
for(i = 0U; i < 4U; i++){
@@ -574,7 +573,7 @@ fmc_state_enum ob_security_protection_config(uint8_t ob_spc)
*/
fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby)
{
uint8_t i;
uint32_t i;
uint32_t temp;
uint32_t op_byte[4];
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
@@ -582,7 +581,7 @@ fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_
for(i = 0U; i < 4U; i++){
op_byte[i] = OP_BYTE(i);
}
temp = ((uint8_t)((uint8_t)((uint8_t)(ob_fwdgt) | ob_deepsleep) | ob_stdby) | (OB_USER_MASK));
temp = (uint32_t)(((uint32_t)((uint32_t)(ob_fwdgt) | ob_deepsleep) | ob_stdby) | OB_USER_MASK);
op_byte[0] = ((uint32_t)(temp) << 16U) | ((op_byte[0] & LOW_16BITS_MASK));
if(FMC_READY == fmc_state){
@@ -632,7 +631,7 @@ fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_
fmc_state_enum ob_data_program(uint16_t ob_data)
{
uint8_t i;
uint32_t i;
uint32_t op_byte[4];
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
for(i = 0U; i < 4U; i++){
@@ -774,17 +773,21 @@ void fmc_ecc_interrupt_disable(uint32_t interrupt)
FlagStatus fmc_ecc_interrupt_flag_get(uint32_t int_flag)
{
uint32_t intenable = 0U, flagstatus = 0U;
FlagStatus status = RESET;
/* get the interrupt enable bit status */
intenable = (FMC_REG_VAL(int_flag) & BIT(FMC_BIT_POS(int_flag)));
/* get the corresponding flag bit status */
flagstatus = (FMC_REG_VAL2(int_flag) & BIT(FMC_BIT_POS2(int_flag)));
if(flagstatus && intenable) {
return SET;
status = SET;
} else {
return RESET;
status = RESET;
}
/* return the state of corresponding FMC interrupt flag */
return status;
}
/*!
@@ -989,7 +992,7 @@ void fmc_interrupt_flag_clear(uint32_t flag)
static fmc_state_enum fmc_state_get(void)
{
fmc_state_enum fmc_state = FMC_READY;
if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_BUSY)){
fmc_state = FMC_BUSY;
}else{
+54 -41
View File
@@ -2,11 +2,11 @@
\file gd32c10x_fwdgt.c
\brief FWDGT driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -84,24 +84,25 @@ void fwdgt_enable(void)
ErrStatus fwdgt_prescaler_value_config(uint16_t prescaler_value)
{
uint32_t timeout = FWDGT_PSC_TIMEOUT;
uint32_t flag_status = RESET;
uint32_t flag_status;
ErrStatus status = SUCCESS;
/* enable write access to FWDGT_PSC */
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
/* configure FWDGT_PSC */
FWDGT_PSC = (uint32_t)prescaler_value;
/* wait until the PUD flag to be reset */
do {
flag_status = FWDGT_STAT & FWDGT_STAT_PUD;
} while((--timeout > 0U) && ((uint32_t)RESET != flag_status));
} while((--timeout > 0U) && (0U != flag_status));
if((uint32_t)RESET != flag_status) {
return ERROR;
if(0U != flag_status) {
status = ERROR;
}
/* configure FWDGT */
FWDGT_PSC = (uint32_t)prescaler_value;
return SUCCESS;
return status;
}
/*!
@@ -113,23 +114,25 @@ ErrStatus fwdgt_prescaler_value_config(uint16_t prescaler_value)
ErrStatus fwdgt_reload_value_config(uint16_t reload_value)
{
uint32_t timeout = FWDGT_RLD_TIMEOUT;
uint32_t flag_status = RESET;
uint32_t flag_status;
ErrStatus status = SUCCESS;
/* enable write access to FWDGT_RLD */
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
/* configure FWDGT_RLD */
FWDGT_RLD = RLD_RLD(reload_value);
/* wait until the RUD flag to be reset */
do {
flag_status = FWDGT_STAT & FWDGT_STAT_RUD;
} while((--timeout > 0U) && ((uint32_t)RESET != flag_status));
} while((--timeout > 0U) && (0U != flag_status));
if((uint32_t)RESET != flag_status) {
return ERROR;
if(0U != flag_status) {
status = ERROR;
}
FWDGT_RLD = RLD_RLD(reload_value);
return SUCCESS;
return status;
}
/*!
@@ -146,7 +149,7 @@ void fwdgt_counter_reload(void)
/*!
\brief configure counter reload value, and prescaler divider value
\param[in] reload_value: specify reload value(0x0000 - 0x0FFF)
\param[in] prescaler_div: FWDGT prescaler value
\param[in] prescaler_value: FWDGT prescaler value
only one parameter can be selected which is shown as below:
\arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4
\arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8
@@ -158,42 +161,51 @@ void fwdgt_counter_reload(void)
\param[out] none
\retval ErrStatus: ERROR or SUCCESS
*/
ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div)
ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_value)
{
uint32_t timeout = FWDGT_PSC_TIMEOUT;
uint32_t flag_status = RESET;
uint32_t flag_status;
ErrStatus status = SUCCESS;
/* start the free watchdog timer counter */
FWDGT_CTL = FWDGT_KEY_ENABLE;
/* enable write access to FWDGT_PSC,and FWDGT_RLD */
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
/* configure FWDGT_PSC */
FWDGT_PSC = (uint32_t)prescaler_value;
/* wait until the PUD flag to be reset */
do {
flag_status = FWDGT_STAT & FWDGT_STAT_PUD;
} while((--timeout > 0U) && ((uint32_t)RESET != flag_status));
} while((--timeout > 0U) && (0U != flag_status));
if((uint32_t)RESET != flag_status) {
return ERROR;
if(0U != flag_status) {
status = ERROR;
}
/* configure FWDGT */
FWDGT_PSC = (uint32_t)prescaler_div;
if(SUCCESS == status) {
/* configure FWDGT_RLD */
FWDGT_RLD = RLD_RLD(reload_value);
timeout = FWDGT_RLD_TIMEOUT;
/* wait until the RUD flag to be reset */
do {
flag_status = FWDGT_STAT & FWDGT_STAT_RUD;
} while((--timeout > 0U) && ((uint32_t)RESET != flag_status));
/* wait until the RUD flag to be reset */
timeout = FWDGT_RLD_TIMEOUT;
do {
flag_status = FWDGT_STAT & FWDGT_STAT_RUD;
} while((--timeout > 0U) && (0U != flag_status));
if((uint32_t)RESET != flag_status) {
return ERROR;
if(0U != flag_status) {
status = ERROR;
}
}
FWDGT_RLD = RLD_RLD(reload_value);
if(SUCCESS == status) {
/* reload the counter */
FWDGT_CTL = FWDGT_KEY_RELOAD;
}
/* reload the counter */
FWDGT_CTL = FWDGT_KEY_RELOAD;
return SUCCESS;
return status;
}
/*!
@@ -207,9 +219,10 @@ ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div)
*/
FlagStatus fwdgt_flag_get(uint16_t flag)
{
if(FWDGT_STAT & flag) {
return SET;
}
FlagStatus flag_status = RESET;
return RESET;
if(RESET != (FWDGT_STAT & flag)) {
flag_status = SET;
}
return flag_status;
}
+14 -8
View File
@@ -2,11 +2,11 @@
\file gd32c10x_gpio.c
\brief GPIO driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -264,11 +264,13 @@ void gpio_port_write(uint32_t gpio_periph,uint16_t data)
*/
FlagStatus gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin)
{
FlagStatus status = RESET;
if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph)&(pin))){
return SET;
status = SET;
}else{
return RESET;
status = RESET;
}
return status;
}
/*!
@@ -293,11 +295,13 @@ uint16_t gpio_input_port_get(uint32_t gpio_periph)
*/
FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin)
{
FlagStatus status = RESET;
if((uint32_t)RESET !=(GPIO_OCTL(gpio_periph)&(pin))){
return SET;
status = SET;
}else{
return RESET;
status = RESET;
}
return status;
}
/*!
@@ -530,9 +534,11 @@ void gpio_compensation_config(uint32_t compensation)
*/
FlagStatus gpio_compensation_flag_get(void)
{
FlagStatus status = RESET;
if(((uint32_t)RESET) != (AFIO_CPSCTL & AFIO_CPSCTL_CPS_RDY)){
return SET;
status = SET;
}else{
return RESET;
status = RESET;
}
return status;
}
+10 -6
View File
@@ -2,11 +2,11 @@
\file gd32c10x_i2c.c
\brief I2C driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -635,11 +635,13 @@ void i2c_sam_timeout_disable(uint32_t i2c_periph)
*/
FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag)
{
FlagStatus status = RESET;
if(RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))){
return SET;
status = SET;
}else{
return RESET;
status = RESET;
}
return status;
}
/*!
@@ -742,6 +744,7 @@ void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt)
FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag)
{
uint32_t intenable = 0U, flagstatus = 0U, bufie;
FlagStatus status = RESET;
/* check BUFIE */
bufie = I2C_CTL1(i2c_periph)&I2C_CTL1_BUFIE;
@@ -759,10 +762,11 @@ FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum i
}
}
if((0U != flagstatus) && (0U != intenable)){
return SET;
status = SET;
}else{
return RESET;
status = RESET;
}
return status;
}
/*!
+14 -28
View File
@@ -2,11 +2,11 @@
\file gd32c10x_misc.c
\brief MISC driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -63,45 +63,31 @@ void nvic_irq_enable(IRQn_Type nvic_irq,
uint8_t nvic_irq_pre_priority,
uint8_t nvic_irq_sub_priority)
{
uint32_t temp_priority = 0x00U, temp_pre = 0x00U, temp_sub = 0x00U;
uint32_t nvic_prigroup, nvic_priority;
/* use the priority group value to get the temp_pre and the temp_sub */
switch((SCB->AIRCR) & (uint32_t)0x700U) {
/* check current priority group */
switch(SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) {
case NVIC_PRIGROUP_PRE0_SUB4:
temp_pre = 0U;
temp_sub = 0x4U;
break;
case NVIC_PRIGROUP_PRE1_SUB3:
temp_pre = 1U;
temp_sub = 0x3U;
break;
case NVIC_PRIGROUP_PRE2_SUB2:
temp_pre = 2U;
temp_sub = 0x2U;
break;
case NVIC_PRIGROUP_PRE3_SUB1:
temp_pre = 3U;
temp_sub = 0x1U;
break;
case NVIC_PRIGROUP_PRE4_SUB0:
temp_pre = 4U;
temp_sub = 0x0U;
break;
default:
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
temp_pre = 2U;
temp_sub = 0x2U;
break;
}
/* get the temp_priority to fill the NVIC->IP register */
temp_priority = (uint32_t)nvic_irq_pre_priority << (0x4U - temp_pre);
temp_priority |= nvic_irq_sub_priority & (0x0FU >> (0x4U - temp_sub));
temp_priority = temp_priority << 0x04U;
NVIC->IP[nvic_irq] = (uint8_t)temp_priority;
/* get the priority group value */
nvic_prigroup = NVIC_GetPriorityGrouping();
/* encoding the pre-emption, subpriority priority */
nvic_priority = NVIC_EncodePriority(nvic_prigroup, (uint32_t)nvic_irq_pre_priority, (uint32_t)nvic_irq_sub_priority);
/* set priority */
NVIC_SetPriority(nvic_irq, nvic_priority);
/* enable the selected IRQ */
NVIC->ISER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU);
NVIC_EnableIRQ(nvic_irq);
}
/*!
@@ -113,7 +99,7 @@ void nvic_irq_enable(IRQn_Type nvic_irq,
void nvic_irq_disable(IRQn_Type nvic_irq)
{
/* disable the selected IRQ.*/
NVIC->ICER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU);
NVIC->ICER[(uint32_t)nvic_irq >> 0x05U] = (uint32_t)0x01U << ((uint32_t)nvic_irq & (uint8_t)0x1FU);
}
/*!
@@ -2,11 +2,11 @@
\file gd32c10x_pmu.c
\brief PMU driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -261,11 +261,14 @@ void pmu_backup_write_disable(void)
*/
FlagStatus pmu_flag_get(uint32_t flag)
{
FlagStatus ret;
if(RESET != (PMU_CS & flag)){
return SET;
ret = SET;
}else{
return RESET;
ret = RESET;
}
return ret;
}
/*!
+15 -7
View File
@@ -2,11 +2,11 @@
\file gd32c10x_rcu.c
\brief RCU driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -565,7 +565,7 @@ void rcu_adc_clock_config(uint32_t adc_psc)
/*!
\brief configure the USBFS prescaler factor
\param[in] adc_div: USB prescaler factor
\param[in] usb_psc: USB prescaler factor
only one parameter can be selected which is shown as below:
\arg RCU_CKUSB_CKPLL_DIV1_5: USBFS prescaler select CK_PLL/1.5
\arg RCU_CKUSB_CKPLL_DIV1: USBFS prescaler select CK_PLL/1
@@ -690,12 +690,16 @@ void rcu_ck48m_clock_config(uint32_t ck48m_clock_source)
*/
FlagStatus rcu_flag_get(rcu_flag_enum flag)
{
FlagStatus rcu_flag = RESET;
/* get the rcu flag */
if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){
return SET;
rcu_flag = SET;
}else{
return RESET;
rcu_flag = RESET;
}
return rcu_flag;
}
/*!
@@ -727,12 +731,16 @@ void rcu_all_reset_flag_clear(void)
*/
FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag)
{
FlagStatus rcu_int_flag = RESET;
/* get the rcu interrupt flag */
if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){
return SET;
rcu_int_flag = SET;
}else{
return RESET;
rcu_int_flag = RESET;
}
return rcu_int_flag;
}
/*!
+12 -6
View File
@@ -2,11 +2,11 @@
\file gd32c10x_rtc.c
\brief RTC driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -191,11 +191,14 @@ uint32_t rtc_divider_get(void)
*/
FlagStatus rtc_flag_get(uint32_t flag)
{
FlagStatus ret;
if(RESET != (RTC_CTL & flag)){
return SET;
ret = SET;
}else{
return RESET;
ret = RESET;
}
return ret;
}
/*!
@@ -227,11 +230,14 @@ void rtc_flag_clear(uint32_t flag)
*/
FlagStatus rtc_interrupt_flag_get(uint32_t flag)
{
FlagStatus ret;
if(RESET != (RTC_CTL & flag)){
return SET;
ret = SET;
}else{
return RESET;
ret = RESET;
}
return ret;
}
/*!
+17 -30
View File
@@ -2,11 +2,11 @@
\file gd32c10x_spi.c
\brief SPI driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -564,11 +564,14 @@ void spi_crc_next(uint32_t spi_periph)
*/
uint16_t spi_crc_get(uint32_t spi_periph,uint8_t crc)
{
uint16_t crc_value;
if(SPI_CRC_TX == crc){
return ((uint16_t)(SPI_TCRC(spi_periph)));
crc_value = ((uint16_t)(SPI_TCRC(spi_periph)));
}else{
return ((uint16_t)(SPI_RCRC(spi_periph)));
crc_value = ((uint16_t)(SPI_RCRC(spi_periph)));
}
return crc_value;
}
/*!
@@ -670,28 +673,6 @@ void spi_quad_read_enable(uint32_t spi_periph)
SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QRD;
}
/*!
\brief enable SPI quad wire mode SPI_IO2 and SPI_IO3 pin output
\param[in] spi_periph: SPIx(only x=0)
\param[out] none
\retval none
*/
void spi_quad_io23_output_enable(uint32_t spi_periph)
{
SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_IO23_DRV;
}
/*!
\brief disable SPI quad wire mode SPI_IO2 and SPI_IO3 pin output
\param[in] spi_periph: SPIx(only x=0)
\param[out] none
\retval none
*/
void spi_quad_io23_output_disable(uint32_t spi_periph)
{
SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_IO23_DRV);
}
/*!
\brief enable SPI and I2S interrupt
\param[in] spi_periph: SPIx(x=0,1,2)
@@ -773,6 +754,7 @@ void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt)
*/
FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt)
{
FlagStatus status = RESET;
uint32_t reg1 = SPI_STAT(spi_periph);
uint32_t reg2 = SPI_CTL1(spi_periph);
@@ -817,10 +799,12 @@ FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt)
}
/* get SPI/I2S interrupt flag status */
if((0U != reg1) && (0U != reg2)){
return SET;
status = SET;
}else{
return RESET;
status = RESET;
}
return status;
}
/*!
@@ -847,9 +831,12 @@ FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt)
*/
FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag)
{
FlagStatus status = RESET;
if(RESET != (SPI_STAT(spi_periph) & flag)){
return SET;
status = SET;
}else{
return RESET;
status = RESET;
}
return status;
}
@@ -2,11 +2,11 @@
\file gd32c10x_timer.c
\brief TIMER driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -1955,12 +1955,14 @@ void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt)
FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt)
{
uint32_t val;
FlagStatus ret;
val = (TIMER_DMAINTEN(timer_periph) & interrupt);
if((RESET != (TIMER_INTF(timer_periph) & interrupt)) && (RESET != val)){
return SET;
ret = SET;
}else{
return RESET;
ret = RESET;
}
return ret;
}
/*!
@@ -2006,11 +2008,13 @@ void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt)
*/
FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag)
{
FlagStatus ret;
if(RESET != (TIMER_INTF(timer_periph) & flag)){
return SET;
ret = SET;
}else{
return RESET;
ret = RESET;
}
return ret;
}
/*!
@@ -2,11 +2,11 @@
\file gd32c10x_usart.c
\brief USART driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -757,11 +757,14 @@ void usart_hardware_flow_coherence_config(uint32_t usart_periph, uint32_t hcm)
*/
FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag)
{
FlagStatus ret;
if(RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))) {
return SET;
ret = SET;
} else {
return RESET;
ret = RESET;
}
return ret;
}
/*!
@@ -858,16 +861,18 @@ void usart_interrupt_disable(uint32_t usart_periph, usart_interrupt_enum interru
FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, usart_interrupt_flag_enum int_flag)
{
uint32_t intenable = 0U, flagstatus = 0U;
FlagStatus ret;
/* get the interrupt enable bit status */
intenable = (USART_REG_VAL(usart_periph, int_flag) & BIT(USART_BIT_POS(int_flag)));
/* get the corresponding flag bit status */
flagstatus = (USART_REG_VAL2(usart_periph, int_flag) & BIT(USART_BIT_POS2(int_flag)));
if((0U != flagstatus) && (0U != intenable)) {
return SET;
ret = SET;
} else {
return RESET;
ret = RESET;
}
return ret;
}
/*!
@@ -2,11 +2,11 @@
\file gd32c10x_wwdgt.c
\brief WWDGT driver
\version 2025-08-07, V1.6.0, firmware for GD32C10x
\version 2026-01-30, V1.7.0, firmware for GD32C10x
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Copyright (c) 2026, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -95,11 +95,13 @@ void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler)
*/
FlagStatus wwdgt_flag_get(void)
{
FlagStatus flag_status = RESET;
if(RESET != (WWDGT_STAT & WWDGT_STAT_EWIF)) {
return SET;
flag_status = SET;
}
return RESET;
return flag_status;
}
/*!
@@ -17,7 +17,7 @@
#define __ROM0_BASE 0x08000000
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
// <i> Defines size of memory region. Default: 0x00020000
#define __ROM0_SIZE 0x00020000
#define __ROM0_SIZE 0x08006000
// </h>
// <h> __ROM1 (unused)
@@ -1,6 +1,6 @@
/*
* CSOLUTION generated file: DO NOT EDIT!
* Generated by: csolution version 2.11.0
* Generated by: csolution version 2.12.0+p41-gfeadfc5e
*
* Project: 'Robot_V2.Debug+GD32C103CB'
* Target: 'Debug+GD32C103CB'
@@ -15,10 +15,10 @@
*/
#define CMSIS_device_header "gd32c10x.h"
/* GigaDevice::Device:GD32C10x_StdPeripherals:ADC@1.0.0 */
#define RTE_DEVICE_STDPERIPHERALS_ADC
/* GigaDevice::Device:GD32C10x_StdPeripherals:CAN@1.0.0 */
#define RTE_DEVICE_STDPERIPHERALS_CAN
/* GigaDevice::Device:GD32C10x_StdPeripherals:CRC@1.0.0 */
#define RTE_DEVICE_STDPERIPHERALS_CRC
/* GigaDevice::Device:GD32C10x_StdPeripherals:DBG@1.0.0 */
#define RTE_DEVICE_STDPERIPHERALS_DBG
/* GigaDevice::Device:GD32C10x_StdPeripherals:DMA@1.0.0 */
@@ -37,14 +37,8 @@
#define RTE_DEVICE_STDPERIPHERALS_PMU
/* GigaDevice::Device:GD32C10x_StdPeripherals:RCU@1.0.0 */
#define RTE_DEVICE_STDPERIPHERALS_RCU
/* GigaDevice::Device:GD32C10x_StdPeripherals:SPI_I2S@1.0.0 */
#define RTE_DEVICE_STDPERIPHERALS_SPI
/* GigaDevice::Device:GD32C10x_StdPeripherals:TIMER@1.0.0 */
#define RTE_DEVICE_STDPERIPHERALS_TIMER
/* GigaDevice::Device:GD32C10x_StdPeripherals:USART@1.0.0 */
#define RTE_DEVICE_STDPERIPHERALS_USART
/* GigaDevice::Device:GD32C10x_StdPeripherals:WWDGT@1.0.0 */
#define RTE_DEVICE_STDPERIPHERALS_WWDGT
#endif /* RTE_COMPONENTS_H */
@@ -1,6 +1,6 @@
/*
* CSOLUTION generated file: DO NOT EDIT!
* Generated by: csolution version 2.12.0+p41-gfeadfc5e
* Generated by: csolution version 2.13.0+p3-g40b6564e
*
* Project: 'Robot_V2.Release+GD32C103CB'
* Target: 'Release+GD32C103CB'
@@ -15,31 +15,29 @@
*/
#define CMSIS_device_header "gd32c10x.h"
/* GigaDevice::Device:GD32C10x_StdPeripherals:BKP@1.0.0 */
#define RTE_DEVICE_STDPERIPHERALS_BKP
/* GigaDevice::Device:GD32C10x_StdPeripherals:CAN@1.0.0 */
/* GigaDevice::Device:GD32C10x_StdPeripherals:CAN@1.3.0 */
#define RTE_DEVICE_STDPERIPHERALS_CAN
/* GigaDevice::Device:GD32C10x_StdPeripherals:CRC@1.0.0 */
/* GigaDevice::Device:GD32C10x_StdPeripherals:CRC@1.3.0 */
#define RTE_DEVICE_STDPERIPHERALS_CRC
/* GigaDevice::Device:GD32C10x_StdPeripherals:DBG@1.0.0 */
/* GigaDevice::Device:GD32C10x_StdPeripherals:DBG@1.3.0 */
#define RTE_DEVICE_STDPERIPHERALS_DBG
/* GigaDevice::Device:GD32C10x_StdPeripherals:DMA@1.0.0 */
/* GigaDevice::Device:GD32C10x_StdPeripherals:DMA@1.3.0 */
#define RTE_DEVICE_STDPERIPHERALS_DMA
/* GigaDevice::Device:GD32C10x_StdPeripherals:EXTI@1.0.0 */
/* GigaDevice::Device:GD32C10x_StdPeripherals:EXTI@1.3.0 */
#define RTE_DEVICE_STDPERIPHERALS_EXTI
/* GigaDevice::Device:GD32C10x_StdPeripherals:FMC@1.0.0 */
/* GigaDevice::Device:GD32C10x_StdPeripherals:FMC@1.3.0 */
#define RTE_DEVICE_STDPERIPHERALS_FMC
/* GigaDevice::Device:GD32C10x_StdPeripherals:FWDGT@1.0.0 */
/* GigaDevice::Device:GD32C10x_StdPeripherals:FWDGT@1.3.0 */
#define RTE_DEVICE_STDPERIPHERALS_FWDGT
/* GigaDevice::Device:GD32C10x_StdPeripherals:GPIO@1.0.0 */
/* GigaDevice::Device:GD32C10x_StdPeripherals:GPIO@1.3.0 */
#define RTE_DEVICE_STDPERIPHERALS_GPIO
/* GigaDevice::Device:GD32C10x_StdPeripherals:MISC@1.0.0 */
/* GigaDevice::Device:GD32C10x_StdPeripherals:MISC@1.3.0 */
#define RTE_DEVICE_STDPERIPHERALS_MISC
/* GigaDevice::Device:GD32C10x_StdPeripherals:PMU@1.0.0 */
/* GigaDevice::Device:GD32C10x_StdPeripherals:PMU@1.3.0 */
#define RTE_DEVICE_STDPERIPHERALS_PMU
/* GigaDevice::Device:GD32C10x_StdPeripherals:RCU@1.0.0 */
/* GigaDevice::Device:GD32C10x_StdPeripherals:RCU@1.3.0 */
#define RTE_DEVICE_STDPERIPHERALS_RCU
/* GigaDevice::Device:GD32C10x_StdPeripherals:USART@1.0.0 */
/* GigaDevice::Device:GD32C10x_StdPeripherals:USART@1.3.0 */
#define RTE_DEVICE_STDPERIPHERALS_USART
+6 -6
View File
@@ -4,14 +4,14 @@ project:
files:
- file: main.h
- file: main.cpp
- file: sys/aes128.h
- file: sys/aes128.cpp
- group: sys
files:
- file: sys/systick.cpp
- file: sys/systick.h
- file: sys/initial.cpp
- file: sys/initial.h
- file: sys/flash.h
- file: sys/flash.cpp
- file: sys/OTA.h
- file: sys/OTA.cpp
- file: sys/config.h
@@ -24,23 +24,23 @@ project:
- component: Device:Startup
- component: Device:GD32C10x_StdPeripherals:CAN
- component: Device:GD32C10x_StdPeripherals:DMA
- component: Device:GD32C10x_StdPeripherals:EXTI
- component: Device:GD32C10x_StdPeripherals:FMC
- component: Device:GD32C10x_StdPeripherals:GPIO
- component: Device:GD32C10x_StdPeripherals:MISC
- component: Device:GD32C10x_StdPeripherals:PMU
- component: Device:GD32C10x_StdPeripherals:RCU
- component: Device:GD32C10x_StdPeripherals:USART
- component: Device:GD32C10x_libopt
- component: Device:GD32C10x_StdPeripherals:DBG
- component: Device:EVAL:GD32C10x
- component: Device:GD32C10x_StdPeripherals:FWDGT
- component: Device:GD32C10x_StdPeripherals:BKP
- component: Device:GD32C10x_StdPeripherals:DBG
- component: Device:GD32C10x_StdPeripherals:EXTI
- component: Device:GD32C10x_StdPeripherals:USART
- component: Device:GD32C10x_StdPeripherals:CRC
output:
type:
- elf
- hex
- bin
- map
packs:
- pack: ARM::CMSIS
-274
View File
@@ -1,274 +0,0 @@
#include "adc.h"
#include "Can.h"
#include "DengFOC.h"
#include "Filter.h"
#include "math.h"
#include <cstring>
#include <gd32c10x_dma.h>
#include <stdint.h>
#include "systick.h"
constexpr float ERROR_ADC_VAL = 255.0f;
constexpr float ADC_SCALE = 3.3f / 4096.0f;
constexpr float TEMP_FACTOR = 1000.0f / 4.3f;
constexpr float VCC_FACTOR = 11.0f;
constexpr float CURRENT_OFFSET = -1.60f;
constexpr float CURRENT_FACTOR =
1.0f / 50.0f * 100.0f; // 50倍放大,100倍电流采样电阻, 单位mA
constexpr float MAX_TEMP = 150.0f;
constexpr float MIN_TEMP = -40.0f;
constexpr float MAX_CURRENT = 40.0f;
constexpr float MIN_CURRENT = -40.0f;
constexpr float MAX_VCC = 65.0f;
constexpr float MIN_VCC = -0.1f;
extern CAN_transmiter CAN0_transmiter;
extern FOC_Controlroller FOC;
sampler sampler; // 采样器初始化
u16 adc_value[6] = {0}; // 显式初始化数组元素为0
/*!
\brief configure the DMA peripheral
\param[in] none
\param[out] none
\retval none
*/
void dma_config(void) {
/* enable DMA0 clock */
rcu_periph_clock_enable(RCU_DMA0);
/* ADC_DMA_channel configuration */
dma_parameter_struct dma_data_parameter;
/* ADC DMA_channel configuration */
dma_deinit(DMA0, DMA_CH0);
/* initialize DMA single data mode */
dma_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA(ADC0));
dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_data_parameter.memory_addr = (uint32_t)(adc_value);
dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_16BIT;
dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_data_parameter.number = 6;
dma_data_parameter.priority = DMA_PRIORITY_HIGH;
dma_init(DMA0, DMA_CH0, &dma_data_parameter);
dma_circulation_enable(DMA0, DMA_CH0);
/* enable DMA channel */
dma_channel_enable(DMA0, DMA_CH0);
}
/*!
\brief configure the ADC peripheral
\param[in] none
\param[out] none
\retval none
*/
void adc_config(void) {
/* enable ADC clock */
rcu_periph_clock_enable(RCU_ADC0);
/* config ADC clock */
rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV4);
/* 复位ADC */
adc_deinit(ADC0);
/* ADC模式配置 */
adc_mode_config(ADC_MODE_FREE);
/* 使能ADC连续转换功能 */
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);
/* 使能ADC扫描模式 */
adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);
/* ADC数据右对齐配置 */
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);
/* 使能ADC温度传感器和内部参考电压 */
adc_tempsensor_vrefint_enable();
/* 配置ADC通道长度 */
adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 6);
/* 配置ADC规则通道 */
adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_16,
ADC_SAMPLETIME_239POINT5);
adc_regular_channel_config(ADC0, 1, ADC_CHANNEL_9, ADC_SAMPLETIME_28POINT5);
adc_regular_channel_config(ADC0, 2, ADC_CHANNEL_3, ADC_SAMPLETIME_28POINT5);
adc_regular_channel_config(ADC0, 3, ADC_CHANNEL_4, ADC_SAMPLETIME_28POINT5);
adc_regular_channel_config(ADC0, 4, ADC_CHANNEL_5, ADC_SAMPLETIME_28POINT5);
adc_regular_channel_config(ADC0, 5, ADC_CHANNEL_6, ADC_SAMPLETIME_28POINT5);
/* ADC触发配置 */
adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL,
ADC0_1_EXTTRIG_REGULAR_NONE);
adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE);
/* 使能ADC接口 */
adc_enable(ADC0);
/* ADC校准 */
adc_calibration_enable(ADC0);
/* 使能ADC DMA功能 */
adc_dma_mode_enable(ADC0);
/* 使能ADC软件触发 */
adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
}
/**
* @brief 采样类初始化
*/
u8 sampler::init() {
dma_config(); // DMA采样ADC初始化
adc_config(); // ADC初始化
delay_1ms(1);
// 初始采样
for (int i = 0; i < FILTER_SIZE + 1; i++) {
mcu_temp_samples[i] =
(1.43f - adc_value[0] * ADC_SCALE) * TEMP_FACTOR + 35.0f;
currU_samples[i] =
(adc_value[2] * ADC_SCALE + CURRENT_OFFSET) * CURRENT_FACTOR;
currV_samples[i] =
(adc_value[3] * ADC_SCALE + CURRENT_OFFSET) * CURRENT_FACTOR;
currW_samples[i] =
(adc_value[4] * ADC_SCALE + CURRENT_OFFSET) * CURRENT_FACTOR;
vbus_samples[i] = adc_value[5] * ADC_SCALE * VCC_FACTOR;
float R_now = (float)adc_value[1] / (4096 - (float)adc_value[1]) * 4700;
drv_temp_samples[i] =
1.0f / (0.00335f + 0.00025f * log(R_now / 10000.0f)) - 273.15f;
delay_1ms(1);
}
return 0;
}
/**
* @brief 获取MCU温度
* @return float
* 温度值,单位为摄氏度,范围应在-40到145之间,如果读取失败则返回0.0f
*/
float sampler::get_mcu_temp() {
tempora_sample = medium_filter(mcu_temp_samples, FILTER_SIZE + 1);
// 检查温度读数是否在有效范围内
if (tempora_sample < MIN_TEMP or tempora_sample > MAX_TEMP) {
return ERROR_ADC_VAL;
}
return tempora_sample;
}
/**
* @brief 获取电机驱动温度
* @return float 温度值,单位为摄氏度
*
* 通过热敏电阻分压电路计算温度值,使用Steinhart-Hart方程进行温度转换。
* 如果计算结果超出有效范围(-40到255摄氏度),则重新采样计算。
*/
float sampler::get_drv_temp() {
tempora_sample = medium_filter(drv_temp_samples, FILTER_SIZE + 1);
// 检查温度读数是否在有效范围内
if (tempora_sample < MIN_TEMP || tempora_sample > MAX_TEMP) {
return ERROR_ADC_VAL;
}
return tempora_sample;
}
/**
* @brief 获取电流值
* @param type 电流类型,'U'表示U相电流,'V'表示V相电流,'W'表示W相电流
* @return float 电流值,单位为安培
*
* 通过ADC采样计算各相电流值
*/
float sampler::get_current(char type) {
switch (type) {
case 'U': {
// return currU_samples[current_sample_index];
tempora_sample = medium_filter(currU_samples, FILTER_SIZE + 1);
break;
}
case 'V': {
// return currV_samples[current_sample_index];
tempora_sample = medium_filter(currV_samples, FILTER_SIZE + 1);
break;
}
case 'W': {
// return currW_samples[current_sample_index];
tempora_sample = medium_filter(currW_samples, FILTER_SIZE + 1);
break;
}
default: {
return ERROR_ADC_VAL;
}
}
if (tempora_sample < MIN_CURRENT or tempora_sample > MAX_CURRENT) {
return ERROR_ADC_VAL;
}
return tempora_sample;
}
/**
* @brief 获取供电电压
* @return float 电压值,单位为伏特
*
* 通过ADC采样计算供电电压值,使用迭代方式确保获取有效的电压读数。
* 如果计算结果超出有效范围(-40到255伏特),则重新采样计算。
*/
float sampler::get_vbus_voltage() {
tempora_sample = medium_filter(vbus_samples, FILTER_SIZE + 1);
// 检查电压读数是否在有效范围内
if (vbus_samples[FILTER_SIZE / 2] > MAX_VCC or
vbus_samples[FILTER_SIZE / 2] < MIN_VCC) {
return ERROR_ADC_VAL;
}
return tempora_sample;
}
/**
* @brief 更新MCU温度
*
* 通过ADC采样计算MCU温度值,使用Steinhart-Hart方程进行温度转换。
* 如果计算结果超出有效范围(-40到255摄氏度),则重新采样计算。
*/
void sampler::update_mcu_temp() {
memmove(mcu_temp_samples, mcu_temp_samples + 1,
FILTER_SIZE * sizeof(float));
mcu_temp_samples[FILTER_SIZE] =
(1.43f - adc_value[0] * ADC_SCALE) * TEMP_FACTOR + 35.0f;
}
/**
* @brief 更新MCU温度
*/
void sampler::update_drv_temp() {
memmove(drv_temp_samples, drv_temp_samples + 1,
FILTER_SIZE * sizeof(float));
float R_now = (float)adc_value[1] / (4096 - (float)adc_value[1]) * 4700;
drv_temp_samples[FILTER_SIZE] =
1.0f / (0.00335f + 0.00025f * log(R_now / 10000.0f)) - 273.15f;
}
/**
* @brief 更新相电流
*/
void sampler::update_current() {
u8 idx = current_sample_index;
extern FOC_Controlroller FOC;
// 优化计算
const float scale = ADC_SCALE * CURRENT_FACTOR;
const float offset = CURRENT_OFFSET * CURRENT_FACTOR;
currU_samples[idx] = adc_value[2] * scale + offset;
currV_samples[idx] = adc_value[3] * scale + offset;
currW_samples[idx] = adc_value[4] * scale + offset;
// 更新索引
current_sample_index++;
if (current_sample_index >= FILTER_SIZE - 1) {
current_sample_index = 0;
}
// 卡尔曼滤波更新
float voltage = FOC.voltage_power_supply;
}
/**
* @brief 更新供电电压
*/
void sampler::update_vbus_voltage() {
memmove(vbus_samples, vbus_samples + 1, FILTER_SIZE * sizeof(float));
vbus_samples[FILTER_SIZE] = adc_value[5] * ADC_SCALE * VCC_FACTOR;
}
+267 -464
View File
@@ -1,32 +1,41 @@
#include "Can.h"
#include "flash.h"
#include "OTA.h"
#include "config.h"
#include "gd32c10x.h"
#include "gd32c10x_can.h"
#include "gd32c10x_dma.h"
#include "gd32c10x_gpio.h"
#include "systick.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <random>
#include "main.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
constexpr u16 CANX = CAN0;
constexpr u16 DEV_CAN0_ID = 0x0000;
constexpr u16 DEV_CAN0_MASK = 0x0000;
constexpr u16 DEV_CAN_LOOPBACK_ID = 0x0000;
constexpr float ANGLE_FACTOR = 25.0f / 360.0f * 2.0f * 3.14159265358979323846f;
CAN_transmiter CAN0_transmiter; // CAN初始化
extern FlashEEPROM flashEEP;
extern BootloaderSystem sys;
extern OTAHandler ota;
// 添加DMA相关变量
dma_parameter_struct dma_rx_parameter;
dma_parameter_struct dma_tx_parameter;
uint8_t can_rx_buffer[8]; // CAN接收缓冲区
uint8_t can_tx_buffer[8]; // CAN发送缓冲区
uint8_t can_rx_buffer[64]; // CAN接收缓冲区(支持CAN FD最大64字节)
uint8_t can_tx_buffer[64]; // CAN发送缓冲区(支持CAN FD最大64字节)
// CAN发送队列结构
#define CAN_TX_QUEUE_SIZE 8
typedef struct {
u32 id;
u8 length;
u8 data[64];
u8 valid;
} can_tx_queue_item_t;
static can_tx_queue_item_t tx_queue[CAN_TX_QUEUE_SIZE];
static volatile u8 tx_queue_head = 0;
static volatile u8 tx_queue_tail = 0;
static volatile u8 tx_queue_count = 0;
// 发送队列使用的独立消息结构体
static can_trasnmit_message_struct queue_transmit_message;
/*!
\brief initialize CAN GPIO
@@ -91,68 +100,6 @@ void can_dma_init(void) {
// 使能DMA通道
dma_channel_enable(DMA0, DMA_CH4);
dma_channel_enable(DMA0, DMA_CH5);
// 使能CAN接收DMA
// can_dma_enable(CAN0, CAN_DMA_RECEIVE);
}
/*!
\brief 初始化CAN0 2.0B 模式
\param[in] none
\param[out] none
\retval none
*/
void can_config(void) {
can_gpio_init();
can_dma_init(); // 初始化DMA
can_parameter_struct can_parameter;
can_filter_parameter_struct can_filter;
can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
/* initialize CAN register */
can_deinit(CAN0);
/* initialize CAN parameters */
can_parameter.time_triggered = DISABLE;
can_parameter.auto_bus_off_recovery = DISABLE;
can_parameter.auto_wake_up = DISABLE;
can_parameter.auto_retrans = DISABLE;
can_parameter.rec_fifo_overwrite = DISABLE;
can_parameter.trans_fifo_order = DISABLE;
can_parameter.working_mode = CAN_NORMAL_MODE;
/* configure CAN0 baud rate 1MBps, sample point at 80% */
can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;
can_parameter.time_segment_1 = CAN_BT_BS1_7TQ;
can_parameter.time_segment_2 = CAN_BT_BS2_2TQ;
can_parameter.prescaler = 6;
/* initialize CAN */
if (can_init(CAN0, &can_parameter) != SUCCESS) {
while (1)
printf("can init error \r\n");
}
/* initialize filter */
/* configure filter mode */
can_filter.filter_mode = CAN_FILTERMODE_MASK;
can_filter.filter_bits = CAN_FILTERBITS_32BIT;
/* configure filter mask */
can_filter.filter_mask_high = 0x0000;
can_filter.filter_mask_low = 0x0000;
/* select receiver fifo */
can_filter.filter_fifo_number = CAN_FIFO0;
can_filter.filter_enable = ENABLE;
/* configure filter number */
can_filter.filter_number = 0;
can_filter_init(&can_filter);
/* configure CAN0 NVIC */
nvic_irq_enable(CAN0_RX0_IRQn, 1, 0);
/* enable can receive FIFO0 not empty interrupt */
can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0);
// 使能DMA中断
nvic_irq_enable(DMA0_Channel4_IRQn, 1, 1);
dma_interrupt_enable(DMA0, DMA_CH4, DMA_INT_FTF);
}
/*!
@@ -163,6 +110,7 @@ void can_config(void) {
*/
void canfd_config(void) {
can_gpio_init();
can_dma_init();
can_parameter_struct can_parameter;
can_fdframe_struct can_fd_parameter;
can_fd_tdc_struct can_fd_tdc_parameter;
@@ -176,7 +124,7 @@ void canfd_config(void) {
can_parameter.auto_bus_off_recovery = DISABLE;
can_parameter.auto_wake_up = DISABLE;
can_parameter.auto_retrans = ENABLE;
can_parameter.rec_fifo_overwrite = ENABLE;
can_parameter.rec_fifo_overwrite = ENABLE; // 改回覆盖模式,丢失旧消息比丢失新消息更可取
can_parameter.trans_fifo_order = ENABLE;
can_parameter.working_mode = CAN_NORMAL_MODE;
/* baudrate 1Mbps, sample piont at 80% */
@@ -225,183 +173,9 @@ void canfd_config(void) {
nvic_irq_enable(CAN0_RX0_IRQn, 1, 0);
/* enable can receive FIFO0 not empty interrupt */
can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0);
}
/*!
\brief 初始化CAN0回环测试
\param[in] none
\param[out] none
\retval none
*/
void can_loopback_init(void) {
can_gpio_init();
can_parameter_struct can_parameter;
can_filter_parameter_struct can_filter;
/* initialize CAN register */
can_deinit(CANX);
/* initialize CAN */
can_parameter.time_triggered = DISABLE;
can_parameter.auto_bus_off_recovery = DISABLE;
can_parameter.auto_wake_up = DISABLE;
can_parameter.auto_retrans = DISABLE;
can_parameter.rec_fifo_overwrite = DISABLE;
can_parameter.trans_fifo_order = DISABLE;
can_parameter.working_mode = CAN_NORMAL_MODE;
/* baudrate 1Mbps, sample piont at 80% */
can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;
can_parameter.time_segment_1 = CAN_BT_BS1_7TQ;
can_parameter.time_segment_2 = CAN_BT_BS2_2TQ;
can_parameter.prescaler = 6;
if (can_init(CANX, &can_parameter) != SUCCESS) {
u16 i = 200;
while (--i > 0) {
delay_1ms(10);
printf("can init error \r\n");
}
system_soft_reset();
}
/* initialize filter */
/* configure filter mode */
can_filter.filter_mode = CAN_FILTERMODE_MASK;
can_filter.filter_bits = CAN_FILTERBITS_32BIT;
/* configure filter ID */
can_filter.filter_list_high = (uint16_t)(DEV_CAN_LOOPBACK_ID >> 13U);
can_filter.filter_list_low =
((uint16_t)(DEV_CAN_LOOPBACK_ID)) << 3U | (1U << 2);
/* configure filter mask */
can_filter.filter_mask_high = 0x0000;
can_filter.filter_mask_low = 0x0000;
/* select receiver fifo */
can_filter.filter_fifo_number = CAN_FIFO0;
can_filter.filter_enable = ENABLE;
/* configure filter number */
can_filter.filter_number = 0;
can_filter_init(&can_filter);
}
/*!
\brief CAN0 FD回环测试
\param[in] none
\param[out] none
\retval ErrStatus
*/
void canfd_loopback_test(void) {
can_trasnmit_message_struct transmit_message;
can_receive_message_struct receive_message;
uint32_t timeout = 0xFFFF;
uint8_t transmit_mailbox = 0;
std::mt19937 gen;
std::uniform_int_distribution<int> dis(0, 255);
can_struct_para_init(CAN_FD_FRAME_STRUCT, &transmit_message);
transmit_message.tx_sfid = DEV_CAN_LOOPBACK_ID;
transmit_message.tx_efid = 0x00;
transmit_message.tx_ft = CAN_FT_DATA;
transmit_message.tx_ff = CAN_FF_EXTENDED;
transmit_message.tx_dlen = 7;
transmit_message.fd_flag = 1;
transmit_message.fd_brs = 1;
transmit_message.fd_esi = 0;
int i = 0;
while (i++ < transmit_message.tx_dlen) {
transmit_message.tx_data[i] = dis(gen);
std::printf("%x\n", transmit_message.tx_data[i]);
}
/* transmit message */
transmit_mailbox = can_message_transmit(CAN0, &transmit_message);
/* waiting for transmit completed */
while ((CAN_TRANSMIT_OK != can_transmit_states(CAN0, transmit_mailbox)) &&
(0 != timeout)) {
timeout--;
}
timeout = 0xFFFF;
/* waiting for receive completed */
while ((can_receive_message_length_get(CAN0, CAN_FIFO0) < 1) &&
(0 != timeout)) {
timeout--;
}
can_struct_para_init(CAN_RX_MESSAGE_STRUCT, &receive_message);
can_message_receive(CAN0, CAN_FIFO0, &receive_message);
/* check the receive message */
if ((transmit_message.tx_sfid == receive_message.rx_sfid) &&
(transmit_message.tx_ff == receive_message.rx_ff) &&
(transmit_message.tx_dlen == receive_message.rx_dlen)) {
/* loopback test is success */
std::printf("CAN LO0PBACK SUCCESS\r\n");
} else {
/* loopback test is failed */
std::printf("CAN LO0PBACK FAIL\r\n");
}
}
/**
\brief CAN0 回环测试
\param[in] none
\param[out] none
\retval none
*/
void can_loopback_test(void) {
can_trasnmit_message_struct transmit_message;
can_receive_message_struct receive_message;
uint32_t timeout = 0xFF;
uint8_t transmit_mailbox = 0;
std::mt19937 gen(rand()); // 使用随机设备生成的种子
std::uniform_int_distribution<int> dis(0, 0xff);
can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &transmit_message);
/* initialize transmit message */
transmit_message.tx_sfid = DEV_CAN_LOOPBACK_ID;
transmit_message.tx_ft = CAN_FT_DATA;
transmit_message.tx_ff = CAN_FF_STANDARD;
transmit_message.tx_dlen = 7;
int i = 0;
while (i++ < transmit_message.tx_dlen) {
// transmit_message.tx_data[i] = dis(gen);
transmit_message.tx_data[i] = i;
}
/* transmit message */
transmit_mailbox = can_message_transmit(CANX, &transmit_message);
/* waiting for transmit completed */
while ((CAN_TRANSMIT_OK != can_transmit_states(CANX, transmit_mailbox)) &&
(0 != timeout)) {
printf("sending:%x...\n", can_transmit_states(CANX, transmit_mailbox));
timeout--;
}
timeout = 0xFF;
/* waiting for receive completed */
while ((can_receive_message_length_get(CANX, CAN_FIFO0) < 1) &&
(0 != timeout)) {
timeout--;
}
can_struct_para_init(CAN_RX_MESSAGE_STRUCT, &receive_message);
can_message_receive(CANX, CAN_FIFO0, &receive_message);
/* check the receive message */
if ((DEV_CAN_LOOPBACK_ID == receive_message.rx_sfid) &&
(CAN_FF_STANDARD == receive_message.rx_ff) &&
(transmit_message.tx_dlen == receive_message.rx_dlen)) {
i = transmit_message.tx_dlen;
while (i-- > 0) {
std::printf("rx %d:%x:%x\n", i, transmit_message.tx_data[i],
receive_message.rx_data[i]);
}
if (std::memcmp(receive_message.rx_data, transmit_message.tx_data,
transmit_message.tx_dlen) == 0) {
/* loopback test is success */
std::printf("loopback success\n");
} else {
std::printf("loopback failed\n");
}
} else {
/* loopback test is failed */
std::printf("loopback failed\n");
}
// 使能DMA中断
nvic_irq_enable(DMA0_Channel4_IRQn, 1, 1);
dma_interrupt_enable(DMA0, DMA_CH4, DMA_INT_FTF);
}
/*!
@@ -410,7 +184,6 @@ void can_loopback_test(void) {
*/
u8 CAN_transmiter::init() {
// 初始化CAN硬件
// can_config();
canfd_config();
// 初始化发送消息结构体
@@ -418,220 +191,64 @@ u8 CAN_transmiter::init() {
/* initialize receive message */
can_struct_para_init(CAN_RX_MESSAGE_STRUCT, &receive_message);
// 初始化计数器和标志位
can0_receive_count = 0;
can0_send_flag = RESET;
// 初始化DMA缓冲区
memset(can_rx_buffer, 0, sizeof(can_rx_buffer));
memset(can_tx_buffer, 0, sizeof(can_tx_buffer));
return 0;
}
/*!
\brief CAN 数据发送
\param id CAN ID
\param length 数据长度
\param data 数据
*/
u8 CAN_transmiter::CAN_Send(u32 id, u8 length, u8 *data) {
// 检查数据长度是否符合CAN规范
if (length > 8) {
printf("CAN data length exceeds maximum of 8 bytes\r\n");
return 0;
}
// 检查数据指针是否有效
if (data == nullptr) {
printf("Invalid data pointer\r\n");
return 0;
}
/* 配置发送消息参数 */
transmit_message.tx_ft = CAN_FT_DATA; // 数据帧
transmit_message.tx_ff = CAN_FF_STANDARD; // 标准帧格式
transmit_message.tx_sfid = id; // 设置帧ID
transmit_message.tx_dlen = length; // 设置数据长度
// 复制数据到发送缓冲区
for (int i = 0; i < length && i < 8; i++) {
transmit_message.tx_data[i] = *(data + i);
}
// 将数据复制到DMA缓冲区
memcpy(can_tx_buffer, data, length);
// 配置DMA发送参数
dma_tx_parameter.number = length;
dma_init(DMA0, DMA_CH5, &dma_tx_parameter);
// 启动DMA传输
dma_channel_enable(DMA0, DMA_CH5);
// 自动选择空闲mailbox发送消息,不需要人为指定
transmit_mailbox = can_message_transmit(CAN0, &transmit_message);
// 检查是否成功获取mailbox
if (CAN_NOMAILBOX == transmit_mailbox) {
// 没有可用的mailbox,可能所有mailbox都在使用中
printf("No available mailbox for CAN transmission\r\n");
return 0;
}
return 1;
}
/*!
\brief CANFD 数据发送
\param id CAN消息ID
\param length CAN消息长度
\param data CAN消息数据
*/
u8 CAN_transmiter::CANFD_Send(u32 id, u8 length, u8 *data) {
// 检查CANFD模式是否启用
if (!(CAN_CTL(CAN0) & CAN_CTL_DFZ)) {
printf("CANFD mode not enabled\r\n");
return 0;
}
// 检查数据指针是否有效
if (data == nullptr) {
printf("Invalid data pointer\r\n");
return 0;
}
// 检查数据长度是否符合CANFD规范
if (length > 64) {
printf("CANFD data length exceeds maximum of 64 bytes\r\n");
return 0;
}
/* 配置发送消息参数 */
transmit_message.tx_ft = CAN_FT_DATA; // 数据帧
transmit_message.tx_ff = CAN_FF_EXTENDED; // 扩展帧格式
// transmit_message.tx_sfid = id; // 设置帧ID
transmit_message.tx_efid = id; // 扩展帧ID
transmit_message.tx_dlen = length; // 设置数据长度
// 设置CANFD特定参数
transmit_message.fd_flag = CAN_FDF_FDFRAME; // CANFD帧格式
transmit_message.fd_brs = ENABLE; // 使能比特率切换
transmit_message.fd_esi = DISABLE; // 错误状态指示
// 复制数据到发送缓冲区
for (int i = 0; i < length && i < 64; i++) {
transmit_message.tx_data[i] = *(data + i);
}
// 将数据复制到DMA缓冲区
memcpy(can_tx_buffer, data, length);
// 配置DMA发送参数
dma_tx_parameter.number = length;
dma_init(DMA0, DMA_CH5, &dma_tx_parameter);
// 启动DMA传输
dma_channel_enable(DMA0, DMA_CH5);
// 自动选择空闲mailbox发送消息,不需要人为指定
transmit_mailbox = can_message_transmit(CAN0, &transmit_message);
// 检查是否成功获取mailbox
if (CAN_NOMAILBOX == transmit_mailbox) {
static u32 count = 0;
// 没有可用的mailbox,可能所有mailbox都在使用中
count++;
// printf("No available mailbox for CANFD transmission\r\n");
if (count > 0xff and !is_sleep) {
printf("No available mailbox for CANFD transmission\r\n");
init();
count = 0;
}
return 0;
}
return 1;
}
/**
* @brief CANFD发送函数
* @retval 0: 发送失败
* 1: 发送成功
*/
u8 CAN_transmiter::CANFD_all_Send() {
u32 success_flag = 0;
constexpr u32 STATUS_ID = 0x00010100;
constexpr u32 CONFIG_ID = 0x00010101;
// 打包status数据 - 只清零实际使用的32字节
memset(transmit_data, 0, 32);
success_flag += CANFD_Send(STATUS_ID, 32, transmit_data);
return success_flag;
}
/**
* @brief CAN通信检查函数
* @retval 0: 无新消息
* 1: 有新消息
* @retval 无
*/
void CAN_transmiter::communication_check() {
// CAN0 发送数据标志
if (SET == can0_send_flag) {
// printf("\r\n can0 %X receive data:", receive_message.rx_efid);
// CAN0_transmiter.CAN_all_Send();
CANFD_all_Send();
can0_send_flag = RESET;
}
// CAN0 接收数据标志
if (SET == can0_receive_flag) {
// printf("\r\n can0 %X receive data:", receive_message.rx_efid);
// for (i = 0; i < receive_message.rx_dlen; i++) {
// printf(" %02x", receive_message.rx_data[i]);
// }
if (receive_message.rx_efid == 0x00010200) {
;
} else if (receive_message.rx_efid == 0x00010301) {
;
} else {
printf("Unknown CAN ID: %X\n", receive_message.rx_efid);
}
can0_receive_flag = RESET;
// CAN0 接收数据计数器
if (can0_receive_count > 0) {
can0_receive_count--;
// 处理OTA消息(中断处理程序已确保只接收OTA相关ID)
ota.handleOTAMessage(receive_message.rx_efid,
receive_message.rx_data,
receive_message.rx_dlen);
}
}
u8 CAN_transmiter::sendACK(u32 CANFD_OTA_ACK_ID, u32 packet_num) {
u32_union_t pack_data;
pack_data.u = packet_num;
u8 CAN_transmiter::sendDATA_ACK(u32 packet_num, u8 *data) { // 握手的时候
memset(transmit_data, 0, sizeof(transmit_data));
transmit_data[0] = 0xBA;
transmit_data[1] = 0xC0;
// 修复原始代码中不完整的循环
for (int i = 2; i < 6; i++) {
transmit_data[i] = data[i - 2];
}
return CANFD_AsyncSend(CANFD_OTA_ACK_ID, 6, transmit_data);
}
u8 CAN_transmiter::sendBackup() { // 握手的时候
return CANFD_AsyncSend(CANFD_OTA_ACK_ID, 0, transmit_data);
}
u8 CAN_transmiter::sendDATA_ACK(u32 packet_num,
bool if_success) { // 发送数据的时候
memset(transmit_data, 0, 4);
pack_u32_to_bytes(transmit_data, 3, pack_data);
if (if_success) {
transmit_data[0] = 0x01;
transmit_data[1] = 0x00;
}
return CANFD_Send(CANFD_OTA_ACK_ID, 4, transmit_data);
return CANFD_AsyncSend(CANFD_OTA_ACK_ID, 4, transmit_data);
}
/**
* @brief CAN睡眠
* @param None
* @retval None
*/
u8 CAN_transmiter::CAN_Sleep() {
gpio_bit_set(GPIOB, GPIO_PIN_13);
is_sleep = true;
return 0;
}
/**
* @brief CAN唤醒
* @param None
* @retval None
*/
u8 CAN_transmiter::CAN_Wakeup() {
printf("can wake\r\n");
is_sleep = false;
canfd_config();
return 0;
}
/**
* @brief CAN0中断服务程序
* @brief CAN0中断服务程序(优化版:直接读取数据,减少DMA竞态条件)
* @retval 无
*/
void CAN0_RX0_IRQHandler(void) {
@@ -640,36 +257,49 @@ void CAN0_RX0_IRQHandler(void) {
// 清除中断标志
can_interrupt_flag_clear(CAN0, CAN_INT_FLAG_RFL0);
// 使用DMA读取接收到的数据
dma_channel_disable(DMA0, DMA_CH4);
dma_rx_parameter.number =
can_receive_message_length_get(CAN0, CAN_FIFO0);
dma_init(DMA0, DMA_CH4, &dma_rx_parameter);
dma_channel_enable(DMA0, DMA_CH4);
// 直接读取消息(包括数据),不依赖DMA
can_receive_message_struct temp_message;
can_message_receive(CAN0, CAN_FIFO0, &temp_message);
// 读取接收到的数据
can_message_receive(CAN0, CAN_FIFO0, &CAN0_transmiter.receive_message);
// 接收标志位置1
CAN0_transmiter.can0_receive_flag = SET;
// 只处理指定的OTA相关ID(硬件过滤器已经确保只接收这些ID)
if (temp_message.rx_efid == CANFD_OTA_DATA_ID ||
temp_message.rx_efid == CANFD_OTA_REQ_ID ||
temp_message.rx_efid == CANFD_OTA_ACK_ID ||
temp_message.rx_efid == CANFD_OTA_WAIT_ID ||
temp_message.rx_efid == CANFD_OTA_CANCEL_ID) {
// 将消息复制到接收缓冲区(包括数据)
CAN0_transmiter.receive_message = temp_message;
// 增加待处理消息计数器
if (CAN0_transmiter.can0_receive_count < 255) {
CAN0_transmiter.can0_receive_count++;
}
} else {
#if CAN_DEBUG
printf("Unknown CAN ID: %X\n", temp_message.rx_efid);
#endif
}
}
// 检查其他可能的中断源
if (can_interrupt_flag_get(CAN0, CAN_INT_FLAG_RFF0) != RESET) {
// FIFO0满中断
can_interrupt_flag_clear(CAN0, CAN_INT_FLAG_RFF0);
#if CAN_DEBUG
printf("CAN FIFO0 full\n");
#endif
}
if (can_interrupt_flag_get(CAN0, CAN_INT_FLAG_RFO0) != RESET) {
// FIFO0溢出中断
can_interrupt_flag_clear(CAN0, CAN_INT_FLAG_RFO0);
#if CAN_DEBUG
printf("CAN FIFO0 overflow\n");
#endif
}
}
/**
* @brief DMA通道4中断服务程序(CAN接收DMA)
* @brief DMA通道4中断服务程序(CAN接收DMA) - 优化版:支持64字节
* @retval 无
*/
void DMA0_Channel4_IRQHandler(void) {
@@ -677,9 +307,12 @@ void DMA0_Channel4_IRQHandler(void) {
// 清除DMA传输完成中断标志
dma_interrupt_flag_clear(DMA0, DMA_CH4, DMA_INT_FLAG_G);
// 将DMA缓冲区的数据复制到接收消息结构体
for (int i = 0; i < CAN0_transmiter.receive_message.rx_dlen && i < 8;
i++) {
// 获取实际接收的数据长度
u8 data_len = CAN0_transmiter.receive_message.rx_dlen;
if (data_len > 64) data_len = 64; // 安全限制
// 将DMA缓冲区的数据复制到接收消息结构体(支持最大64字节)
for (int i = 0; i < data_len; i++) {
CAN0_transmiter.receive_message.rx_data[i] = can_rx_buffer[i];
}
}
@@ -691,7 +324,177 @@ void DMA0_Channel4_IRQHandler(void) {
*/
void DMA0_Channel5_IRQHandler(void) {
if (dma_interrupt_flag_get(DMA0, DMA_CH5, DMA_INT_FLAG_FTF)) {
// DMA传输完成,可以在此处执行后续处理
// 清除DMA传输完成中断标志
dma_interrupt_flag_clear(DMA0, DMA_CH5, DMA_INT_FLAG_G);
dma_interrupt_flag_clear(DMA0, DMA_CH5, DMA_INT_FLAG_FTF);
// 可以在此添加后续处理逻辑,如发送下一个数据包等
}
}
/**
* @brief 向发送队列添加消息
* @param id CAN消息ID
* @param length CAN消息长度
* @param data CAN消息数据
* @retval 1=成功, 0=队列满
*/
static u8 CAN_TX_QueuePush(u32 id, u8 length, u8 *data) {
if (tx_queue_count >= CAN_TX_QUEUE_SIZE) {
#if CAN_DEBUG
printf("TX queue full, message dropped\r\n");
#endif
return 0; // 队列满,丢弃消息
}
tx_queue[tx_queue_tail].id = id;
tx_queue[tx_queue_tail].length = length;
for (int i = 0; i < length && i < 64; i++) {
tx_queue[tx_queue_tail].data[i] = data[i];
}
tx_queue[tx_queue_tail].valid = 1;
tx_queue_tail = (tx_queue_tail + 1) % CAN_TX_QUEUE_SIZE;
tx_queue_count++;
return 1;
}
/**
* @brief 从发送队列取出消息
* @param item 指向队列项的指针
* @retval 1=成功, 0=队列空
*/
static u8 CAN_TX_QueuePop(can_tx_queue_item_t *item) {
if (tx_queue_count == 0) {
return 0; // 队列空
}
*item = tx_queue[tx_queue_head];
tx_queue[tx_queue_head].valid = 0;
tx_queue_head = (tx_queue_head + 1) % CAN_TX_QUEUE_SIZE;
tx_queue_count--;
return 1;
}
/**
* @brief 异步CANFD数据发送(使用队列机制防止丢帧)
* @param id CAN消息ID
* @param length CAN消息长度
* @param data CAN消息数据
*/
u8 CAN_transmiter::CANFD_AsyncSend(u32 id, u8 length, u8 *data) {
u8 valid_length = length;
// 检查CANFD模式是否启用
if (!(CAN_CTL(CAN0) & CAN_CTL_DFZ)) {
#if CAN_DEBUG
printf("CANFD mode not enabled\r\n");
#endif
return 0;
}
// 检查数据指针是否有效
if (data == nullptr) {
#if CAN_DEBUG
printf("Invalid data pointer\r\n");
#endif
return 0;
}
// 检查数据长度是否符合CANFD规范
if (length > 8) {
if (length > 8 and length < 13) {
valid_length = 12;
} else if (length > 12 and length < 17) {
valid_length = 16;
} else if (length > 16 and length < 21) {
valid_length = 20;
} else if (length > 20 and length < 24) {
valid_length = 24;
} else if (length > 28 and length < 33) {
valid_length = 32;
} else if (length > 32 and length < 49) {
valid_length = 48;
} else if (length > 48 and length < 65) {
valid_length = 64;
} else {
#if CAN_DEBUG
printf("CANFD data length error\r\n");
#endif
return 0;
}
}
/* 配置发送消息参数 */
transmit_message.tx_ft = CAN_FT_DATA; // 数据帧
transmit_message.tx_ff = CAN_FF_EXTENDED; // 扩展帧格式
transmit_message.tx_efid = id; // 扩展帧ID
transmit_message.tx_dlen = valid_length; // 设置数据长度
// 设置CANFD特定参数
transmit_message.fd_flag = CAN_FDF_FDFRAME; // CANFD帧格式
transmit_message.fd_brs = ENABLE; // 使能比特率切换
transmit_message.fd_esi = DISABLE; // 错误状态指示
// 复制数据到发送缓冲区
for (int i = 0; i < valid_length; i++) {
if (i < length) {
transmit_message.tx_data[i] = *(data + i);
} else {
transmit_message.tx_data[i] = 0;
}
}
// 自动选择空闲mailbox发送消息
transmit_mailbox = can_message_transmit(CAN0, &transmit_message);
// 检查是否成功获取mailbox
if (transmit_mailbox == CAN_NOMAILBOX) {
// 没有可用的mailbox,将消息加入发送队列
#if CAN_DEBUG
printf("No available mailbox, adding to TX queue\r\n");
#endif
return CAN_TX_QueuePush(id, valid_length, data);
}
// 启用CAN发送中断以检测传输完成(用于队列发送)
can_interrupt_enable(CAN0, CAN_INTEN_TMEIE);
return 1;
}
/**
* @brief CAN传输中断处理函数(支持队列发送)
*/
void CAN0_TX_IRQHandler(void) {
// 检查是否有发送邮箱空闲
if (can_flag_get(CAN0, CAN_FLAG_TME0) != RESET ||
can_flag_get(CAN0, CAN_FLAG_TME1) != RESET ||
can_flag_get(CAN0, CAN_FLAG_TME2) != RESET) {
can_tx_queue_item_t next_msg;
// 尝试从队列中取出下一条消息发送
if (CAN_TX_QueuePop(&next_msg)) {
// 配置并发送队列中的消息(使用独立的队列消息结构体)
queue_transmit_message.tx_ft = CAN_FT_DATA;
queue_transmit_message.tx_ff = CAN_FF_EXTENDED;
queue_transmit_message.tx_efid = next_msg.id;
queue_transmit_message.tx_dlen = next_msg.length;
queue_transmit_message.fd_flag = CAN_FDF_FDFRAME;
queue_transmit_message.fd_brs = ENABLE;
queue_transmit_message.fd_esi = DISABLE;
for (int i = 0; i < next_msg.length; i++) {
queue_transmit_message.tx_data[i] = next_msg.data[i];
}
can_message_transmit(CAN0, &queue_transmit_message);
} else {
// 队列为空,禁用发送中断
can_interrupt_disable(CAN0, CAN_INTEN_TMEIE);
}
// 清除发送中断标志
can_flag_clear(CAN0, CAN_FLAG_TME0);
can_flag_clear(CAN0, CAN_FLAG_TME1);
can_flag_clear(CAN0, CAN_FLAG_TME2);
}
}
+7 -68
View File
@@ -1,69 +1,20 @@
#ifndef _CAN_H
#define _CAN_H
#include <stdint.h>
#include "cstdint"
#ifdef __cplusplus
extern "C" {
#endif
#include "gd32c10x_can.h"
#include "stdint.h"
#include <stdio.h>
// 定义一个联合体类型用于float和byte数组之间的转换
typedef union {
u32 u;
u8 b[4];
} u32_union_t;
// 添加辅助函数用于将u16类型数据打包到u8数组中
static inline void pack_u16_to_bytes(u8 *buffer, u16 offset, u16 value) {
buffer[offset] = (u8)(value & 0xFF);
buffer[offset + 1] = (u8)((value >> 8) & 0xFF);
}
// 添加辅助函数用于将float类型数据打包到u8数组中
static inline void pack_u32_to_bytes(u8 *buffer, u16 offset,
u32_union_t &u32_union) {
buffer[offset] = u32_union.b[0];
buffer[offset + 1] = u32_union.b[1];
buffer[offset + 2] = u32_union.b[2];
buffer[offset + 3] = u32_union.b[3];
}
// 添加辅助函数用于从u8数组中解包short类型数据
static inline short unpack_bytes_to_short(u8 *buffer, u16 offset) {
short value = (short)(buffer[offset] | (buffer[offset + 1] << 8));
return value;
}
// 添加辅助函数用于从u8数组中解包u16类型数据
static inline u16 unpack_bytes_to_u16(u8 *buffer, u16 offset) {
u16 value = (u16)(buffer[offset] | (buffer[offset + 1] << 8));
return value;
}
// 添加辅助函数用于从u8数组中解包float类型数据
static inline u32_union_t unpack_bytes_to_float(u8 *buffer, u16 offset) {
u32_union_t u32_union;
u32_union.b[0] = buffer[offset];
u32_union.b[1] = buffer[offset + 1];
u32_union.b[2] = buffer[offset + 2];
u32_union.b[3] = buffer[offset + 3];
return u32_union;
}
u8 can_gpio_init(void); // CAN引脚初始化
void can_config(void); // CAN初始化
void canfd_config(void); // CANFD初始化
void can_dma_init(void); // CAN DMA初始化
void CAN0_RX0_IRQHandler(void); // CAN接收中断处理函数
void DMA0_Channel4_IRQHandler(void); // DMA通道4中断处理函数(CAN接收)
void DMA0_Channel5_IRQHandler(void); // DMA通道5中断处理函数(CAN发送)
void can_loopback_init(void);
void can_loopback_test(void);
/*!
\brief CAN通信类
\note 封装CAN发送和接收功能
@@ -71,35 +22,23 @@ void can_loopback_test(void);
class CAN_transmiter {
private:
bool is_sleep = false; // 是否休眠
can_trasnmit_message_struct transmit_message; // 发送消息结构体
u8 transmit_mailbox = CAN_NOMAILBOX; // 初始化为无mailbox状态
u8 transmit_data[64]; // CANFD最大64字节
void update(); // 更新数据
u8 CAN_Receive(); // CAN接收
u8 CANFD_Receive(); // CANFD接收
u8 CAN_all_Send(); // CAN发送
u8 CANFD_all_Send(); // CANFD发送
public:
// 添加构造函数声明
u8 init(void);
can_receive_message_struct receive_message; // 接收消息结构体
FlagStatus can0_receive_flag; // CAN0接收标志
u8 can0_receive_count; // CAN0待处理消息计数器
FlagStatus can0_send_flag; // CAN0发送标志
u32_union_t testfloat_union = {0}; // 测试用
bool MagStatus = 0; // 磁状态码
bool ThermalStatus = 0; // 热能状态码
void communication_check(); // 通信检查
u8 CAN_Sleep(); // CAN进入睡眠
u8 CAN_Wakeup(); // CAN进入睡眠
u8 CAN_Send(u32 ID, u8 length, u8 *data); // CAN发送
u8 CANFD_Send(u32 ID, u8 length, u8 *data); // CANFD发送
u8 sendACK(u32 CANFD_OTA_ACK_ID, u32 packet_num);
void communication_check(); // 通信检查
u8 CANFD_AsyncSend(u32 ID, u8 length, u8 *data); // CANFD异步发送(使用DMA)
u8 sendDATA_ACK(u32 packet_num, bool if_success);
u8 sendDATA_ACK(u32 packet_num, u8 *data); // 恢复原函数签名
u8 sendBackup();
};
#ifdef __cplusplus
-109
View File
@@ -1,109 +0,0 @@
#include "Timer.h"
#include "Can.h"
#include "Timer.h"
#include "gd32c10x.h"
#include "gd32c10x_gpio.h"
#include "gd32c10x_misc.h"
#include "gd32c10x_rcu.h"
#include "gd32c10x_timer.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
constexpr int TIMER2_PRESCALER = 119; // 120MHz / 120 = 1MHz
constexpr int TIMER2_PERIOD = 99; // 1MHz / 100 = 100us
constexpr int TIMER1_PRESCALER = 0; // 不分频,计数器时钟为120MHz
constexpr int TIMER1_PERIOD = 5999; // 120MHz / (0+1) / (5999+1) = 20kHz
constexpr int TIMER1_CH0_PULSE = 0;
constexpr int TIMER1_CH1_PULSE = 0;
constexpr int TIMER1_CH2_PULSE = 0;
constexpr int TIMER1_CH3_COMPARE_VALUE =
(TIMER1_PERIOD + 1) * 0.5 - 1; // PWM周期50%位置触发中断
volatile u32 total_us100_counter = 0; // 总计数器,每100微秒增加1
extern u16 adc_value[7];
extern CAN_transmiter CAN0_transmiter;
// 添加系统运行时间计数器
extern u32 cnt_test;
/**
* @brief 设置引脚中断优先级
* @return void
*
*设置引脚中断优先级
*/
void nvic_config(void) {
/* 设置NVIC优先级分组,1位抢占优先级,3位响应优先级 */
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
/* 使能TIMER2中断,设置抢占优先级为1,子优先级为1 */
nvic_irq_enable(TIMER2_IRQn, 0, 1);
nvic_irq_enable(TIMER1_IRQn, 0, 2);
}
/**
* @brief 配置定时器2
* @return void
*
*配置定时器2,用于定时执行FOC控制、采样、CAN发送等任务
*/
void TIMER2_config(void) {
/* ----------------------------------------------------------------------------
TIMER2 Configuration:
TIMER2CLK = SystemCoreClock/120 = 1MHz, the period is 100us(100/1000000 =
100us).
----------------------------------------------------------------------------
*/
timer_parameter_struct timer_struct;
/* 使能TIMER2时钟 */
rcu_periph_clock_enable(RCU_TIMER2);
/* 复位TIMER2外设到默认状态 */
timer_deinit(TIMER2);
/* 初始化TIMER初始化参数结构体 */
timer_struct_para_init(&timer_struct);
/* TIMER2配置参数设置 */
timer_struct.prescaler =
TIMER2_PRESCALER; /* 预分频值:120分频(从0开始计数) */
timer_struct.alignedmode = TIMER_COUNTER_EDGE; /* 边沿对齐模式 */
timer_struct.counterdirection = TIMER_COUNTER_UP; /* 向上计数模式 */
timer_struct.period =
TIMER2_PERIOD; /* 自动重装载值:100次计数(从0开始计数) */
timer_struct.clockdivision = TIMER_CKDIV_DIV1; /* 时钟分频值:1分频 */
timer_init(TIMER2, &timer_struct);
/* 清除更新中断标志位 */
timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_UP);
/* 使能更新中断 */
timer_interrupt_enable(TIMER2, TIMER_INT_UP);
/* 使能TIMER2 */
timer_enable(TIMER2);
}
/**
* @brief 配置TIMER2中断
* @return void
*/
void User_timer_init(void) {
/* 配置TIMER2 */
TIMER2_config();
/* 配置TIMER2中断 */
nvic_config();
}
/**
* @brief TIMER2中断处理函数
* @return void
*/
void TIMER2_IRQHandler(void) {
// 检查更新中断标志并处理
if (timer_interrupt_flag_get(TIMER2, TIMER_INT_UP) != RESET) {
// 清除更新中断标志
timer_interrupt_flag_clear(TIMER2, TIMER_INT_UP);
// 每100us执行一次的操作
}
}
-27
View File
@@ -1,27 +0,0 @@
#ifndef _TIMER_H
#define _TIMER_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void User_timer_init(void);
void Set_Pwm(uint16_t channel, float duty_cycle);
void Set_3Pwm(float duty_cycle0, float duty_cycle1,float duty_cycle2);
void TIMER2_IRQHandler(void);
void timer1_pwm_config(void);
void timer1_gpio_config(void);
void TIMER1_IRQHandler(void); // 添加TIMER1中断处理函数声明
/* 获取系统运行时间 */
uint64_t get_system_runtime_us(void);
#ifdef __cplusplus
}
#endif
#endif
-40
View File
@@ -1,40 +0,0 @@
#ifndef _ADC_H
#define _ADC_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"
constexpr u8 FILTER_SIZE = 6;
constexpr u8 BLOCK_SIZE = FILTER_SIZE * sizeof(float);
class sampler {
private:
float vbus_samples[FILTER_SIZE + 1];
float currU_samples[FILTER_SIZE + 1];
float currV_samples[FILTER_SIZE + 1];
float currW_samples[FILTER_SIZE + 1];
float mcu_temp_samples[FILTER_SIZE + 1];
float drv_temp_samples[FILTER_SIZE + 1];
u8 current_sample_index;
float tempora_sample;
public:
u8 init(void);
void update_mcu_temp(void);
void update_drv_temp(void);
void update_vbus_voltage(void);
void update_current(void);
float get_mcu_temp(void);
float get_drv_temp(void);
float get_vbus_voltage(void);
float get_current(char);
};
#ifdef __cplusplus
}
#endif
#endif
-306
View File
@@ -1,306 +0,0 @@
#include "ang_sensor.h"
#include "Filter.h"
#include "core_cmFunc.h"
#include "gd32c10x_can.h"
#include "gd32c10x_dma.h"
#include "gd32c10x_gpio.h"
#include "gd32c10x_spi.h"
#include "initial.h"
#include "flash.h"
#include <cstdio>
#include <cstring>
#include "Can.h"
#include <stdint.h>
#define ANG_SPI_CS_ENABLE() gpio_bit_reset(GPIOA, GPIO_PIN_15)
#define ANG_SPI_CS_DISABLE() gpio_bit_set(GPIOA, GPIO_PIN_15)
#define DRV_SPI_CS_ENABLE() gpio_bit_reset(GPIOB, GPIO_PIN_14)
#define DRV_SPI_CS_DISABLE() gpio_bit_set(GPIOB, GPIO_PIN_14)
constexpr float ANGLE_FACTOR = 1.0f / 65536.0f * 360.0f;
constexpr float RAD_FACTOR = 1.0f / 65536.0f * 2.0f * 3.14159265358979323846f;
constexpr u16 DEFAULT_COMMAND = 0x0000;
constexpr u16 FAULT_RECEIVE = 0xFFFF;
constexpr float VELOCITY_SCALE = 1e4f;
constexpr float ANGLE_WRAP_THRESHOLD = 300.0f;
constexpr float ANGLE_WRAP_VALUE = 360.0f;
constexpr u8 SIZE_FLOAT = sizeof(float);
// DMA传输完成标志
volatile bool spi_dma_tx_complete = false;
volatile bool spi_dma_rx_complete = false;
angle_sensor KTH7823; // 角度传感器初始化
extern FlashEEPROM flashEEP;
extern EncoderAngleKalman Angle_kalman;
extern EncoderVelocityKalman Vel_kalman;
extern CAN_transmiter CAN0_transmiter; // CAN初始化
/**
* @brief SPI DMA initialization
*/
void spi_dma_init(void) {
dma_parameter_struct dma_init_struct;
// 使能DMA时钟
rcu_periph_clock_enable(RCU_DMA0);
// 初始化发送DMA通道
dma_deinit(DMA0, DMA_CH2);
dma_struct_para_init(&dma_init_struct);
dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
dma_init_struct.memory_addr = (uint32_t)0; // 实际地址将在传输时设置
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;
dma_init_struct.number = 1;
dma_init_struct.periph_addr = (uint32_t)(&SPI_DATA(SPI0));
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
dma_init_struct.priority = DMA_PRIORITY_HIGH;
dma_init(DMA0, DMA_CH2, &dma_init_struct);
// 初始化接收DMA通道
dma_deinit(DMA0, DMA_CH1);
dma_struct_para_init(&dma_init_struct);
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_init_struct.memory_addr = (uint32_t)0; // 实际地址将在传输时设置
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;
dma_init_struct.number = 1;
dma_init_struct.periph_addr = (uint32_t)(&SPI_DATA(SPI0));
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
dma_init_struct.priority = DMA_PRIORITY_HIGH;
dma_init(DMA0, DMA_CH1, &dma_init_struct);
// 使能SPI的DMA发送和接收功能
spi_dma_enable(SPI0, SPI_DMA_TRANSMIT);
spi_dma_enable(SPI0, SPI_DMA_RECEIVE);
// 配置DMA中断
nvic_irq_enable(DMA0_Channel2_IRQn, 0, 1);
nvic_irq_enable(DMA0_Channel1_IRQn, 0, 1);
// 使能DMA传输完成中断
dma_interrupt_enable(DMA0, DMA_CH2, DMA_INT_FTF);
dma_interrupt_enable(DMA0, DMA_CH1, DMA_INT_FTF);
}
/**
* @brief Send or read half word through SPI using DMA
*
* @param[in] spi_periph SPI peripheral
* @param[in] tx_data Data to transmit
* @param[out] rx_data Pointer to store received data
* @return 0 if success, -1 if error
*/
int spi_rw_half_word_dma(uint32_t spi_periph, uint16_t tx_data,
uint16_t *rx_data) {
// 重置完成标志
spi_dma_tx_complete = false;
spi_dma_rx_complete = false;
// 配置发送DMA
dma_channel_disable(DMA0, DMA_CH2);
dma_memory_address_config(DMA0, DMA_CH2, (uint32_t)&tx_data);
dma_transfer_number_config(DMA0, DMA_CH2, 1);
dma_channel_enable(DMA0, DMA_CH2);
// 配置接收DMA
dma_channel_disable(DMA0, DMA_CH1);
dma_memory_address_config(DMA0, DMA_CH1, (uint32_t)rx_data);
dma_transfer_number_config(DMA0, DMA_CH1, 1);
dma_channel_enable(DMA0, DMA_CH1);
// 等待传输完成,超时时间为100个循环
uint32_t timeout = 100;
while ((!spi_dma_tx_complete || !spi_dma_rx_complete) && --timeout) {
// 空循环等待DMA传输完成
}
// 检查是否超时
if (timeout == 0) {
// 禁用DMA通道
dma_channel_disable(DMA0, DMA_CH2);
dma_channel_disable(DMA0, DMA_CH1);
printf("SPI DMA transfer timeout\r\n");
return -1;
}
return 0;
}
/**
* @brief DMA0_Channel2中断处理函数
* @param 无
*/
extern "C" void DMA0_Channel2_IRQHandler(void) {
if (dma_interrupt_flag_get(DMA0, DMA_CH2, DMA_INT_FLAG_FTF)) {
dma_interrupt_flag_clear(DMA0, DMA_CH2, DMA_INT_FLAG_FTF);
spi_dma_tx_complete = true;
}
}
/**
* @brief DMA0_Channel1中断处理函数
* @param 无
*/
extern "C" void DMA0_Channel1_IRQHandler(void) {
if (dma_interrupt_flag_get(DMA0, DMA_CH1, DMA_INT_FLAG_FTF)) {
dma_interrupt_flag_clear(DMA0, DMA_CH1, DMA_INT_FLAG_FTF);
spi_dma_rx_complete = true;
}
}
/**
* @brief 角度传感器初始化
* @param 无
*/
void KTH7823_gpio_init(void) {
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_SPI0);
rcu_periph_clock_enable(RCU_AF);
/* 关闭 JTAG,仅保留 SWD(释放 PA15、PB3、PB4) */
gpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP, ENABLE);
/* -------- SPI0 全 remap:PB3/4/5 + PA15 -------- */
gpio_pin_remap_config(GPIO_SPI0_REMAP, ENABLE);
/* PA15 → NSS, 推挽输出 */
gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_15);
/* PB3 → SCK, PB5 → MOSI, 推挽输出 */
gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ,
GPIO_PIN_3 | GPIO_PIN_5);
/* PB4 → MISO, 浮空输入 */
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ,
GPIO_PIN_4 | GPIO_PIN_10 | GPIO_PIN_11);
}
/**
* @brief SPI 初始化
*
* @details Configures SPI hardware and initializes necessary settings
*/
void KTH7823_spi_init(void) {
spi_parameter_struct spi_init_str;
spi_struct_para_init(&spi_init_str);
/* SPI参数:16bit, 主机, 全双工, CPOL=1 CPHA=1, MSB first */
spi_init_str.device_mode = SPI_MASTER;
spi_init_str.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
spi_init_str.frame_size = SPI_FRAMESIZE_16BIT;
spi_init_str.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE;
spi_init_str.nss = SPI_NSS_SOFT;
spi_init_str.endian = SPI_ENDIAN_MSB;
spi_init_str.prescale = 24; /* 5MHz @ 120MHz */
spi_init(SPI0, &spi_init_str);
spi_nss_output_enable(SPI0);
spi_nssp_mode_enable(SPI0);
spi_enable(SPI0);
}
/**
* @ 角度传感器类 初始化
* @return 0:初始化成功 1:初始化失败
*/
u8 angle_sensor::init(void) {
KTH7823_gpio_init(); // GPIO初始化
KTH7823_spi_init(); // SPI初始化
spi_dma_init(); // DMA初始化
return 0;
}
/**
* @ 角度传感器类 设置当前角度
* @param angle 输出级角度值
* @return 0成功/1失败
*/
u8 angle_sensor::angle_set(float angle){
m_cumulativeAngle = angle*REDUCTION_RATIO; // 从Flash读取上次保存的角度
m_firstUpdate = true;
return 0;
}
/**
* @brief 读取传感器数据
* @return 传感器数据
*/
inline float angle_sensor::read_sensorAngle(void) {
uint16_t raw_data;
ANG_SPI_CS_ENABLE();
u8 result = spi_rw_half_word_dma(SPI0, DEFAULT_COMMAND, &raw_data);
ANG_SPI_CS_DISABLE();
if (result == 0) {
// 单次浮点乘法优化:只计算一次度数,然后转换为弧度
float angle_deg = (float)raw_data * ANGLE_FACTOR;
current_angle_deg = angle_deg;
current_angle_rad = angle_deg * DEG2RAD; // M_PI/180.0f
return angle_deg;
}
#ifdef DEBUG
// 仅在调试模式下输出错误,避免发布版本中的I/O开销
if (result != 0) {
// 使用更高效的串口输出替代printf(如果可用)
printf("Error reading angle from sensor.\n");
}
#endif
return (float)FAULT_RECEIVE;
}
/**
* @brief 更新传感器角度(输出级)
* @return 累积角度值
*/
float angle_sensor::update(void) {
read_sensorAngle();
if (m_firstUpdate) {
m_lastAngle = current_angle_deg;
m_firstUpdate = false;
return m_cumulativeAngle;
}
// 计算角度变化
float delta = current_angle_deg - m_lastAngle;
// 处理角度绕回情况(0度和360度之间的跳变)
// 如果变化超过180度,说明发生了绕回
if (delta > ANGLE_WRAP_THRESHOLD) {
// 从接近360度绕回到接近0度
delta -= ANGLE_WRAP_VALUE;
} else if (delta < -ANGLE_WRAP_THRESHOLD) {
// 从接近0度绕到接近360度
delta += ANGLE_WRAP_VALUE;
}
m_cumulativeAngle += delta;
m_lastAngle = current_angle_deg;
return m_cumulativeAngle;
}
/**
* @brief 获取累积角度值(输出级)
* @return 累积角度值
*/
float angle_sensor::getAngle(void) const {
return m_cumulativeAngle / REDUCTION_RATIO;
}
/**
* @brief 获取累积角度值(原始级)
* @return 累积角度值
*/
float angle_sensor::getRawAngle(void) const { return m_cumulativeAngle; }
/**
* @brief 获取角度值(原始级)
* @return 角度值(原始级)
*/
float angle_sensor::getcurrent_sensorangle(void) const {
return current_angle_deg;
}
-40
View File
@@ -1,40 +0,0 @@
#ifndef _angsensor_H
#define _angsensor_H
#ifdef __cplusplus
extern "C" {
#endif
#include "gd32c10x_eval.h"
#include "stdio.h"
u16 spi_rw_half_word(u32 spi_periph, const u16 i_HalfWord);
int spi_rw_half_word_dma(uint32_t spi_periph, uint16_t tx_data,
uint16_t *rx_data);
constexpr u16 VEL_FILTER_SIZE = 4;
class angle_sensor {
public:
u8 init(void);
float read_sensorAngle(void);
float update(void);
void reset(void);
float getAngle(void) const;
float getRawAngle(void) const;
float getcurrent_sensorangle(void) const;
u8 angle_set(float angle);
protected:
float m_cumulativeAngle;
float current_angle_deg;
float current_angle_rad;
bool m_firstUpdate;
float m_lastAngle;
float m_lastcumulativeAngle;
float velocity[VEL_FILTER_SIZE] = {0.0f};
};
#ifdef __cplusplus
}
#endif
#endif
-38
View File
@@ -1,38 +0,0 @@
#include "motor.h"
#include "Timer.h"
#include "gd32c10x_eval.h"
#include <cstdio>
/**
* @brief driver输出初始化
*/
void motor_init(void) {
timer1_gpio_config();
timer1_pwm_config();
// 使能GPIOB时钟
rcu_periph_clock_enable(RCU_GPIOB);
// 配置PB2为输入引脚,用于读取电机状态
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
/* 配置GPIOB的PB14为推挽输出 SPICS */
gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,
GPIO_PIN_14 | GPIO_PIN_12);
}
/**
* @brief 电机复位
*/
void motor_reset(void) {
motor_sleep();
printf("motor reseting...\r\n");
motor_resume();
}
/**
* @brief 电机休眠
*/
void motor_sleep(void) { gpio_bit_reset(GPIOB, GPIO_PIN_12); }
/**
* @brief 电机启动
*/
void motor_resume(void) { gpio_bit_set(GPIOB, GPIO_PIN_12); }
-11
View File
@@ -1,11 +0,0 @@
#ifndef _MOTOR_H
#define _MOTOR_H
void motor_init(void);
void motor_reset(void);
void motor_resume(void);
void motor_sleep(void);
#endif
-25
View File
@@ -1,25 +0,0 @@
#include "adc.h"
#include <cstdio>
constexpr int status_print = 0;
extern sampler sampler;
void test_1111() {
// 初始化CAN回环测试
// can_loopback_init();
// can_config();
if (status_print) {
/* value print */
printf(" the temperature data is %2.2f degrees Celsius\r\n",
sampler.get_mcu_temp());
printf(" the drv_temperature data is %2.2f degrees Celsius\r\n",
sampler.get_drv_temp());
printf(" the U current data is %2.2f mA\r\n", sampler.get_current('U'));
printf(" the V current data is %2.2f mA\r\n", sampler.get_current('V'));
printf(" the W current data is %2.2f mA\r\n", sampler.get_current('W'));
printf(" the VBUS is %2.2f V\r\n", sampler.get_vbus_voltage());
// printf(" the angle is %2.2f\r\n", tle5012b_read());
printf("\n----------------------------------------------------\n");
}
// can_loopback_test();
}
+89 -22
View File
@@ -1,43 +1,110 @@
#include "main.h"
#include "Can.h"
#include "config.h"
#include "gd32c10x.h"
#include "gd32c10x_can.h"
#include "initial.h"
#include "sys/OTA.h"
#include "sys/config.h"
#include "sys/initial.h"
#include "sys/systick.h"
#include <cstdio>
#include <gd32c10x_fmc.h>
class BootloaderSystem {
private:
OTAHandler ota;
extern CAN_transmiter CAN0_transmiter; // CAN初始化
BootloaderSystem sys;
extern OTAHandler ota;
public:
void initHardware() {
extern CAN_transmiter CAN0_transmiter; // CAN初始化
systick_config(); // 系统时钟初始化
SystemCoreClockUpdate(); // 更新系统时钟变量
CAN0_transmiter.init();
}
void BootloaderSystem::initHardware() {
systick_config(); // 系统时钟初始化
USART0_init(); // 调试串口初始化
void run() {
// 检查是否触发OTA模式
if (1) {
// OTA模式
CAN0_transmiter.init();
check_sleep();
}
void BootloaderSystem::run() {
volatile u32 *flash_ptr = (volatile u32 *)n_APP_LATEST_EN_ADDR;
u32 app_enable = *flash_ptr;
flash_ptr = (volatile u32 *)n_APP_LATEST_CHECK_ADDR;
u32 app_check = *flash_ptr;
if (app_check == OTA_AVAL and
app_enable == OTA_AVAL) { // APP已确认且激活,直接进入
#if DEBUG_OTA
printf("Normal Mode\r\n");
#endif
// 正常模式:跳转到APP
ota.jumpToApplication();
} else if (app_check == OTA_AVAL and
app_enable == OTA_NOT_AVAL) { // APP可用但未激活,延迟进入APP
#if DEBUG_OTA
printf("Delay Boot Mode: APP available but not enabled, jumping in %d ms...\r\n", APP_DELAY_BOOT_TIME);
#endif
// 延迟启动模式:倒计时期间监听CAN,收到OTA请求则进入OTA模式
u32 delay_count = 0;
bool ota_requested = false;
while (delay_count < APP_DELAY_BOOT_TIME) {
// 检查CAN通信并处理接收到的消息
CAN0_transmiter.communication_check();
// 调用ota.process()发送心跳消息(IDAEL状态下会发送CANFD_OTA_WAIT_ID)
ota.process();
// 检查是否收到OTA请求
if (ota.isActive()) {
ota_requested = true;
break;
}
delay_count+=10;
}
if (ota_requested) {
#if DEBUG_OTA
printf("OTA request received during delay, entering OTA mode...\r\n");
#endif
// 收到OTA请求,进入OTA模式
while (1) {
CAN0_transmiter.communication_check();
ota.process();
for (volatile int i = 0; i < 500000; i++)
; // 简单延时
}
} else {
// 正常模式:跳转到APP
#if DEBUG_OTA
printf("Delay timeout, jumping to APP...\r\n");
#endif
// 超时未收到OTA请求,跳转APP
ota.jumpToApplication();
}
} else { // APP无效,确认backup
volatile u32 *flash_ptr = (volatile u32 *)n_APP_BACKUP_AVAL_ADDR;
u32 back_aval = *flash_ptr;
flash_ptr = (volatile u32 *)n_APP_BACKUP_CHECK_ADDR;
u32 back_check = *flash_ptr;
if (back_check == OTA_AVAL and
back_aval == OTA_AVAL) { // backup已确认且激活,复制到主APP区域
#if DEBUG_OTA
printf("OTA Mode3\r\n");
#endif
CAN0_transmiter.sendBackup();
move_app_data(); // 恢复BACKUP
ota.jumpToApplication(); // 跳转到APP
} else { // backup无效,进入OTA模式
#if DEBUG_OTA
printf("OTA Mode4\r\n");
#endif
// OTA模式
while (1) {
CAN0_transmiter.communication_check();
ota.process();
}
}
}
};
}
int main(void) {
BootloaderSystem sys;
sys.initHardware();
// test_decrypt();
sys.run();
while (1)
; // 不应该执行到这里
}
}
+9 -1
View File
@@ -34,8 +34,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef MAIN_H
#define MAIN_H
#include "cstdint"
#include "stdint.h"
#include "sys/OTA.h"
void do_task(u32 currentTasks);
class BootloaderSystem {
private:
public:
void initHardware();
void run();
};
#endif /* MAIN_H */
+736 -67
View File
@@ -1,120 +1,789 @@
#include "OTA.h"
#include "Can.h"
#include "aes128.h"
#include "config.h"
#include "core_cmFunc.h"
#include "gd32c10x.h" // 主头文件,包含了gd32c10x_crc.h的内容
#include "gd32c10x_fmc.h"
#include <cstring>
#include "initial.h"
#include "systick.h"
#include <stdint.h>
extern CAN_transmiter CAN0_transmiter; // CAN初始化
OTAHandler ota;
extern "C" {
void canfd_rx_irq_handler(void);
}
OTAHandler::OTAHandler() : ota_active(false), received_size(0) {}
inline fmc_state_enum write_ADDRESS(u32 address, u32 data) {
fmc_unlock();
fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_PGAERR | FMC_FLAG_WPERR);
void OTAHandler::init() {
// 初始化CANFD接收中断
nvic_irq_enable(CAN0_RX0_IRQn, 1, 1);
// 确保使用对齐地址
fmc_state_enum fmc_status = fmc_word_program(address, data);
fmc_lock();
return fmc_status;
}
/**
* @brief 设置OTA配置参数到Flash
*
* 此函数用于更新存储在Flash中的OTA相关标志位(如APP可用、启用、校验等)。
* GD32的Flash特性是:只能将1写为0,不能将0写为1。若要将0变为1,必须先擦除整个页面。
* 因此,本函数通过读取同一页内的所有参数,擦除该页,然后重新写入有效的参数来实现“写1”操作。
*
* @param addr: 要设置的Flash地址
* @param data: 要写入的数据 (通常为OTA_AVAL=0x00000000 或
* OTA_NOT_AVAL=0xFFFFFFFF)
* @retval FLASH_EEPROM_OK (0) 表示成功, 其他值表示失败
*/
u8 OTA_SET(u32 addr, u32 data) {
fmc_state_enum fmc_status;
u32 temp_val[OTA_CONFIG_NUM]; // 临时数组,用于存储当前所有配置参数的值
volatile u32 *flash_ptr = (volatile u32 *)addr;
// 1. 检查目标地址的值是否已与期望值相同,如果相同则无需操作
temp_val[0] = *flash_ptr;
if (temp_val[0] == data) {
return FLASH_EEPROM_OK; // 值已正确,直接返回成功
}
// 2. 尝试直接写入数据。这适用于将1修改为0的情况(因为Flash允许1->0)
if (data == OTA_AVAL) {
fmc_status = write_ADDRESS(addr, data);
// 如果写入成功,则返回成功
if (fmc_status == FMC_READY) {
return FLASH_EEPROM_OK;
}
// 如果写入失败(例如地址已被写为0),则继续执行后续的擦除-重写流程
}
// 3. 对于需要将0改回1的操作,必须先擦除整个Flash页
flash_ptr = (volatile u32 *)n_APP_LATEST_AVAL_ADDR;
temp_val[0] = *flash_ptr;
flash_ptr = (volatile u32 *)n_APP_BACKUP_AVAL_ADDR;
temp_val[1] = *flash_ptr;
flash_ptr = (volatile u32 *)n_APP_LATEST_EN_ADDR;
temp_val[2] = *flash_ptr;
flash_ptr = (volatile u32 *)n_APP_BACKUP_EN_ADDR;
temp_val[3] = *flash_ptr;
flash_ptr = (volatile u32 *)n_APP_LATEST_CHECK_ADDR;
temp_val[4] = *flash_ptr;
flash_ptr = (volatile u32 *)n_APP_BACKUP_CHECK_ADDR;
temp_val[5] = *flash_ptr;
#if EEP_DEBUG
printf("OTA_prepare write%08x at %08x\r\n", data, addr);
// 修复:完整输出所有6个配置项的值,便于调试
printf("LatestAval:0x%x, BackupAval:0x%x, LatestEn:0x%x, "
"BackupEn:0x%x, LatestCheck:0x%x, BackupCheck:0x%x\r\n",
temp_val[0], temp_val[1], temp_val[2], temp_val[3], temp_val[4],
temp_val[5]);
#endif
// 4. 擦除包含所有配置参数的Flash页
fmc_status = fmc_page_erase(n_APP_LATEST_AVAL_ADDR);
if (fmc_status != FMC_READY) {
#if EEP_DEBUG
printf("OTA_SET - Page erase failed! Status: %d\r\n", fmc_status);
#endif
return FLASH_EEPROM_ERROR;
}
// 5. 重新写入所有之前读取的配置项值,只有0改F需要写,所以最后不用写
for (int i = 0; i < OTA_CONFIG_NUM; i++) {
u32 current_addr = n_APP_LATEST_AVAL_ADDR + 4 * i;
if (current_addr != addr and temp_val[i] != OTA_NOT_AVAL) {
fmc_status = write_ADDRESS(current_addr, temp_val[i]);
}
}
#if EEP_DEBUG
// 3. 对于需要将0改回1的操作,必须先擦除整个Flash页
flash_ptr = (volatile u32 *)n_APP_LATEST_AVAL_ADDR;
temp_val[0] = *flash_ptr;
flash_ptr = (volatile u32 *)n_APP_BACKUP_AVAL_ADDR;
temp_val[1] = *flash_ptr;
flash_ptr = (volatile u32 *)n_APP_LATEST_EN_ADDR;
temp_val[2] = *flash_ptr;
flash_ptr = (volatile u32 *)n_APP_BACKUP_EN_ADDR;
temp_val[3] = *flash_ptr;
flash_ptr = (volatile u32 *)n_APP_LATEST_CHECK_ADDR;
temp_val[4] = *flash_ptr;
flash_ptr = (volatile u32 *)n_APP_BACKUP_CHECK_ADDR;
temp_val[5] = *flash_ptr;
// 修复:完整输出所有6个配置项的值,便于调试
printf("LatestAval:0x%x, BackupAval:0x%x, LatestEn:0x%x, "
"BackupEn:0x%x, LatestCheck:0x%x, BackupCheck:0x%x\r\n",
temp_val[0], temp_val[1], temp_val[2], temp_val[3], temp_val[4],
temp_val[5]);
#endif
return FLASH_EEPROM_OK;
}
/**
* @brief 从4字节数组中提取一个32位无符号整数
* @param array: 4字节数组
* @retval 32位无符号整数
*/
static inline uint32_t extract_u32_from_4bytes(const uint8_t *array) {
return ((uint32_t)array[3] << 24) | ((uint32_t)array[2] << 16) |
((uint32_t)array[1] << 8) | (uint32_t)array[0];
}
void OTAHandler::init() {}
/**
* @brief OTA处理函数
* @param 无
* @retval 无
*/
void OTAHandler::process() {
if (!ota_active)
// 执行待处理的Flash擦除操作(在主循环中执行,避免中断中耗时操作)
if (pending_flash_erase) {
pending_flash_erase = false;
#if DEBUG_OTA
printf("Executing pending Flash erase...\r\n");
#endif
eraseApplicationArea();
#if DEBUG_OTA
printf("Flash erase completed.\r\n");
#endif
// Flash擦除完成后,更新状态为接收固件
ota_state = OTA_STATE_RECEIVING_FIRMWARE;
}
if (ota_state == OTA_STATE_IDLE) {
ota_time = 0; // 重置计时器
static u8 zero[1] = {0};
CAN0_transmiter.CANFD_AsyncSend(CANFD_OTA_WAIT_ID, 0, zero);
#if DEBUG_OTA
printf("OTA status:%d\r\n", ota_state);
#endif
delay_1ms(10);
return;
} else {
delay_1us(100);
ota_time++;
}
// 这里可以添加超时处理逻辑
// 例如:10秒无数据则退出OTA模式
// 检查是否超时(例如:10秒无数据则退出OTA模式)
if (ota_time > OTA_TIMEOUT) { // 10秒超时(10000 x 1ms)
ota_time = 0;
ota_state = OTA_STATE_IDLE;
ota_error = OTA_ERROR_TIMEOUT;
volatile u32 *flash_ptr =
(volatile u32 *)n_APP_LATEST_CHECK_ADDR; // 如果是实际可以运行
u32 if_checked = *flash_ptr;
flash_ptr = (volatile u32 *)n_APP_LATEST_AVAL_ADDR; // 如果是实际已刷入
u32 if_aval = *flash_ptr;
send_error_frame(OTA_ERROR_TIMEOUT); // OTA超时
if (if_checked == OTA_AVAL and if_aval == OTA_AVAL) {
fmc_unlock();
OTA_SET(n_APP_LATEST_AVAL_ADDR,
OTA_AVAL); // 实际可用,设置APP为启用
fmc_lock();
jumpToApplication();
}
}
}
bool validateApplication() {
u32 *app_vector = (u32 *)APPLATEST_START_ADDR;
u32 stack_ptr = app_vector[0];
u32 reset_handler = app_vector[1];
bool OTAHandler::validateApplication() {
uint32_t *app_vector = (uint32_t *)APP_START_ADDR;
uint32_t stack_ptr = app_vector[0];
uint32_t reset_handler = app_vector[1];
#if DEBUG_OTA
printf("APPLATEST_START_ADDR: 0x%08X\r\n", APPLATEST_START_ADDR);
printf("Stack Pointer: 0x%08X\r\n", stack_ptr);
printf("Reset Handler: 0x%08X\r\n", reset_handler);
printf("APP Range: 0x%08X - 0x%08X\r\n", APPLATEST_START_ADDR,
APPLATEST_START_ADDR + APP_MAX_SIZE);
#endif
// 简单验证:检查栈指针是否在SRAM范围内
return (stack_ptr >= 0x20000000 && stack_ptr < 0x20008000) &&
(reset_handler >= APP_START_ADDR &&
reset_handler < (APP_START_ADDR + APP_MAX_SIZE));
bool stack_valid = (stack_ptr >= 0x20000000 && stack_ptr < 0x20008000);
bool reset_valid = (reset_handler >= APPLATEST_START_ADDR &&
reset_handler < (APPLATEST_START_ADDR + APP_MAX_SIZE));
#if DEBUG_OTA
if (!stack_valid) {
printf("Stack pointer validation failed!\r\n");
}
if (!reset_valid) {
printf("Reset handler validation failed!\r\n");
}
#endif
return stack_valid && reset_valid;
}
/**
* @brief 跳转应用处理模块
* @param 无
* @retval 无
*/
void OTAHandler::jumpToApplication() {
#if DEBUG_OTA
printf("try jump to app\r\n");
if (!validateApplication()) {
// 无效APP,停留在bootloader
return;
}
printf("jumping1\r\n");
#endif
fmc_unlock();
OTA_SET(n_APP_LATEST_AVAL_ADDR, OTA_AVAL); // 设置APP为可用
OTA_SET(n_APP_LATEST_EN_ADDR, OTA_AVAL); // 设置APP为激活
fmc_lock();
// 关闭所有中断
__disable_irq();
for (int i = 0; i < 8; i++) {
NVIC->ICER[i] = 0xFFFFFFFF;
}
// 2. 重置外设(特别是CAN,防止冲突)
can_deinit(CAN0);
// 设置主栈指针
uint32_t msp_value = *(__IO uint32_t *)APP_START_ADDR;
__set_MSP(msp_value);
// 3. 重置系统时钟到默认状态
rcu_system_clock_source_config(RCU_CKSYSSRC_IRC8M);
// 获取复位地址
uint32_t reset_handler = *(__IO uint32_t *)(APP_START_ADDR + 4);
#if DEBUG_OTA
printf("jumping2\r\n");
#endif
// 4. 关闭一些关键外设时钟
rcu_periph_clock_disable(RCU_GPIOA);
rcu_periph_clock_disable(RCU_GPIOB);
rcu_periph_clock_disable(RCU_GPIOC);
rcu_periph_clock_disable(RCU_USART0);
rcu_periph_clock_disable(RCU_CAN0);
rcu_periph_clock_disable(RCU_TIMER0);
rcu_periph_clock_disable(RCU_DMA0);
#if DEBUG_OTA
printf("jumping3\r\n");
#endif
// 5. 设置中断向量表偏移到应用程序起始地址
SCB->VTOR = APPLATEST_START_ADDR;
// 6. 设置MSP并跳转
uint32_t msp_value = *(__IO uint32_t *)APPLATEST_START_ADDR;
uint32_t reset_handler = *(__IO uint32_t *)(APPLATEST_START_ADDR + 4);
typedef void (*AppEntryFunc)(void);
AppEntryFunc app_entry = (AppEntryFunc)reset_handler;
// 跳转
#if DEBUG_OTA
printf("jumping5, MSP:0x%08X, Reset Handler:0x%08X\r\n", msp_value,
reset_handler);
#endif
__set_MSP(msp_value);
// 在跳转前清除复位标志
rcu_all_reset_flag_clear();
// 7. 跳转
app_entry();
// 如果程序执行到这里,说明跳转失败
#if DEBUG_OTA
printf("Jump to application failed!\r\n");
#endif
}
/**
* @brief 擦除应用程序区域
* @param 无
* @retval 无
*/
void OTAHandler::eraseApplicationArea() {
// 擦除APP区域
fmc_unlock();
for (uint32_t addr = APP_START_ADDR; addr < (APP_START_ADDR + APP_MAX_SIZE);
addr += FMC_PAGE_SIZE) {
fmc_page_erase(addr);
OTA_SET(n_APP_LATEST_CHECK_ADDR, OTA_NOT_AVAL); // 设置APP为未确认
OTA_SET(n_APP_LATEST_EN_ADDR, OTA_NOT_AVAL); // 设置APP为未激活
OTA_SET(n_APP_LATEST_AVAL_ADDR, OTA_NOT_AVAL); // 设置APP为不可用
// 擦除前禁用中断,防止中断处理程序执行期间发生Flash操作导致问题
__disable_irq();
fmc_unlock();
fmc_state_enum fmc_status;
for (u32 addr = APPLATEST_START_ADDR;
addr < (APPLATEST_START_ADDR + APP_MAX_SIZE); addr += FMC_PAGE_SIZE) {
fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_PGAERR | FMC_FLAG_WPERR);
fmc_status = fmc_page_erase(addr);
if (fmc_status != FMC_READY) {
// 如果擦除失败,记录错误并退出
#if DEBUG_OTA
printf("Flash erase failed at address 0x%08X, status: %d\r\n", addr,
fmc_status);
delay_1ms(5000);
#endif
ota_error = OTA_ERROR_FLASH_ERROR;
send_error_frame(OTA_ERROR_FLASH_ERROR);
break;
} else {
#if DEBUG_OTA
printf("Flash erase SUCCESS\r\n");
#endif
}
}
// 重新启用中断
__enable_irq();
fmc_lock();
}
void OTAHandler::writeApplicationData(uint32_t offset, uint8_t *data,
uint32_t size) {
/**
* @brief 写入应用程序数据
* @param offset: 写入偏移量
* @param data: 数据指针
* @param size: 数据大小
* @retval 无
*/
void OTAHandler::writeApplicationData(u32 offset, u8 *data, u32 size) {
fmc_unlock();
uint32_t write_addr = APP_START_ADDR + offset;
u32 write_addr = APPLATEST_START_ADDR + offset;
fmc_state_enum fmc_state;
u32 i = 0;
u8 *src = data;
// 32位对齐写入 - 处理完整的32位字
for (; i <= size - 4; i += 4) {
fmc_state = fmc_word_program(write_addr + i, *(u32 *)&src[i]);
if (fmc_state != FMC_READY) {
printf("FMC_WRITE_ERROR\r\n");
}
}
// 处理剩余字节(如果有的话)
if (i < size) {
u32 word = 0;
u8 *word_ptr = (u8 *)&word;
u32 remaining_bytes = size - i;
// 直接复制剩余字节到word变量
for (u32 j = 0; j < remaining_bytes; j++) {
word_ptr[j] = src[i + j];
}
// 32位对齐写入
for (uint32_t i = 0; i < size; i += 4) {
uint32_t word = 0;
memcpy(&word, &data[i], 4);
fmc_word_program(write_addr + i, word);
}
fmc_lock();
}
void OTAHandler::handleOTAMessage(uint32_t id, uint8_t *data, uint8_t len) {
if (id == CANFD_OTA_REQ_ID) {
// OTA请求包
uint32_t new_size = *(uint32_t *)data;
if (new_size <= APP_MAX_SIZE) {
expected_size = new_size;
received_size = 0;
eraseApplicationArea();
ota_active = true;
sendACK(0xFFFFFFFF); // 确认开始
}
} else if (id == CANFD_OTA_DATA_ID && ota_active) {
// 数据包格式:[4字节包序号][实际数据]
if (len >= 4) {
uint32_t packet_num = *(uint32_t *)data;
uint32_t offset = packet_num * (len - 4);
/**
* @brief 处理OTA数据包
* @param id: CAN帧ID
* @param data: CAN帧数据
* @param len: CAN帧数据长度
* @retval 无
*/
void OTAHandler::handleOTAMessage(u32 id, u8 *data, u8 len) {
if (id == CANFD_OTA_CANCEL_ID) {
// 取消OTA过程
ota_state = OTA_STATE_IDLE;
ota_time = 0;
ota_error = OTA_ERROR_NONE;
#if DEBUG_OTA
printf("OTA process cancelled by CANFD_OTA_CANCEL_ID\r\n");
#endif
return;
} else if (id == CANFD_OTA_DATA_ID) {
ota_time = 0;
if (len == 64 and ota_state == OTA_STATE_RECEIVING_FIRMWARE) {
#if DEBUG_OTA
printf("stage8:OTA_RECEIVING_FIRMWARE\r\n");
#endif
// 使用安全的数据解包方式
u32 receive_session_num = extract_u32_from_4bytes(data);
u32 receive_packet_num = extract_u32_from_4bytes(data + 4);
u32 receive_IFEND = extract_u32_from_4bytes(data + 56);
if (offset < expected_size) {
writeApplicationData(offset, &data[4], len - 4);
received_size += (len - 4);
sendACK(packet_num);
// 直接使用数据指针,避免不必要的内存复制
const u8 *receive_encrypted_data =
data + 8; // 加密数据从偏移8字节开始
const u8 *receive_dataCRC32 = data + 60; // CRC数据从偏移60字节开始
// 检查是否完成
if (received_size >= expected_size) {
ota_active = false;
// 跳转前延时让ACK发出
for (volatile int i = 0; i < 100000; i++)
;
jumpToApplication();
// 解密 - 使用栈上数组存储解密结果
u8 decrypted_data[OTA_PACKET_SIZE];
u8 calculated_dataCRC32[4];
aes128_set_key(&aes_ctx, current_K_session);
aes128_ecb_decrypt_48bytes(&aes_ctx,
const_cast<u8 *>(receive_encrypted_data),
decrypted_data);
// 计算解密后CRC数据
calculate_crc32_with_key(current_K_session, decrypted_data,
calculated_dataCRC32);
// CRC数据匹配
if (memcmp(receive_dataCRC32, calculated_dataCRC32, SIZE_U32) !=
0) {
ota_error = OTA_ERROR_INVALID_CRC;
send_error_frame(OTA_ERROR_INVALID_CRC);
#if DEBUG_OTA
std::printf("CRC32 :%x,%x!\r\n", receive_dataCRC32[0],
calculated_dataCRC32[0]);
#endif
receive_packet_num -= 1;
} else {
// 写入Flash前验证数据
u32 offset = receive_packet_num * OTA_PACKET_SIZE;
if (offset + OTA_PACKET_SIZE <= APP_MAX_SIZE) {
writeApplicationData(offset, decrypted_data,
OTA_PACKET_SIZE);
} else {
ota_error = OTA_ERROR_INVALID_SIZE;
ota_state = OTA_STATE_IDLE;
send_error_frame(OTA_ERROR_INVALID_SIZE);
}
}
if (receive_IFEND == 0xFFFFFFFF) { // 接收到尾帧,发送结束信号
u8 pack_number[4] = {0xFF, 0xFF, 0xFF, 0xFF};
CAN0_transmiter.sendDATA_ACK(CANFD_OTA_ACK_ID, pack_number);
ota_state = OTA_STATE_FINISHED;
jumpToApplication();
return;
}
// 下一个请求
u32 request_packet = receive_packet_num + 1;
u8 pack_number[4];
// 封包
memcpy(&pack_number, &request_packet, 4);
CAN0_transmiter.sendDATA_ACK(CANFD_OTA_ACK_ID, pack_number);
} else if (len == 4 and ota_state == OTA_STATE_CHECKING_FIRMWARE) {
#if DEBUG_OTA
printf("stage7:OTA_STATE_CHECKING_FIRMWARE\r\n");
#endif
// OTA请求包
u32 new_size = *(u32 *)data;
if (new_size <= APP_MAX_SIZE) {
expected_size = new_size;
received_size = 0;
} else {
ota_error = OTA_ERROR_INVALID_SIZE;
ota_state = OTA_STATE_IDLE;
send_error_frame(OTA_ERROR_INVALID_SIZE);
return;
}
// 设置待执行的Flash擦除标志,在process()中执行(避免中断中耗时操作)
pending_flash_erase = true;
// 注意:不立即改变状态,等待Flash擦除完成后在process()中改变
// 发送确认信号,告诉上位机可以开始发送数据
u8 send_data[6] = {0xBA, 0xC0, 0x00,
0x00, 0x00, 0x00}; // 确认开始传输
CAN0_transmiter.CANFD_AsyncSend(CANFD_OTA_ACK_ID, 6, send_data);
} else if (len == 2 and ota_state == OTA_STATE_FINISHED) {
#if DEBUG_OTA
printf("stage--:OTA_STATE_FINISHED\r\n");
#endif
;
} else {
ota_error = OTA_ERROR_INVALID_PACKET;
ota_state = OTA_STATE_IDLE;
send_error_frame(OTA_ERROR_INVALID_PACKET);
}
} else if (id == CANFD_OTA_REQ_ID) {
ota_time = 0;
#if DEBUG_OTA
printf("stage2:OTA_STATE_WAITING_RANDOM\r\n");
#endif
if (data[0] == 0x00 and data[1] == 0xAC and len == 2 and
ota_state == OTA_STATE_IDLE) { // 收到发起信号
u8 send_data[2] = {0x00, 0xac}; // 确认握手开始,请求随机数
CAN0_transmiter.CANFD_AsyncSend(CANFD_OTA_ACK_ID, 2,
send_data); // 发送握手开始信号
ota_state = OTA_STATE_WAITING_RANDOM;
} else if (len == 16 and ota_state == OTA_STATE_WAITING_RANDOM) {
#if DEBUG_OTA
printf("stage4:OTA_STATE_WAITING_CONFIRM\r\n");
#endif
while (len-- > 0) {
nonce_server[len] = data[len];
}
// 1. 获取设备唯一码
getDeviceSerialNumber(device_uid);
// 2. 初始化AES上下文(设置主密钥)
aes128_set_key(&aes_ctx, K_master);
// 3. 生成会话密钥 K_session (16字节)
u8 K_session[16];
aes128_encrypt_block(&aes_ctx, nonce_server,
K_session); // 用主密钥加密随机数
// 4. 用主密钥加密明文 (AES-128-ECB)
u8 encrypted_Ksession[16];
u8 temp_block[AES_BLOCK_SIZE];
// 加密第一个16字节块
aes128_encrypt_block(&aes_ctx, K_session, temp_block);
memcpy(encrypted_Ksession, temp_block, 16);
// 5. 构造握手响应包 (36字节)
u8 handshake_response[36];
// 5.1 前12字节:设备UID
memcpy(handshake_response, device_uid, 12);
// 5.2 接下来8字节:nonce后半部分
memcpy(handshake_response + 12, nonce_server + 8, 8);
// 5.3 最后16字节:加密数据的K-session
memcpy(handshake_response + 20, encrypted_Ksession, 16);
// 6. 通过CAN发送响应
CAN0_transmiter.CANFD_AsyncSend(CANFD_OTA_ACK_ID, 36,
handshake_response);
// 7. 保存会话密钥供后续使用
memcpy(current_K_session, K_session, 16);
// 8. 更新状态机
ota_state = OTA_STATE_WAITING_CONFIRM;
} else if (len == 16 and ota_state == OTA_STATE_WAITING_CONFIRM) {
#if DEBUG_OTA
printf("stage6:OTA_STATE_CHECKING_SESSION\r\n");
#endif
u8 plaintext[16];
u8 expected[16];
// 1. 用K_session解密
u8 encrypted_confirm[16];
memcpy(encrypted_confirm, data, 16);
aes128_set_key(&aes_ctx, current_K_session);
aes128_decrypt_block(&aes_ctx, encrypted_confirm, plaintext);
// 2. 计算期望值 (nonce_server XOR 0x55)
// 注意:需要保存原始的nonce_server
for (int i = 0; i < 16; i++) {
expected[i] = nonce_server[i] ^ 0x55;
}
// 3. 验证解密结果
if (memcmp(plaintext, expected, 16) != 0) {
// 验证失败 - 可能密钥错误或攻击
ota_error = OTA_ERROR_INVALID_KEY;
ota_state = OTA_STATE_IDLE;
send_error_frame(OTA_ERROR_INVALID_KEY); // 验证失败
return;
}
u8 send_data[2] = {0xBA, 0xC0}; // 确认开始传输
// 4. 验证成功 - 发送最终ACK
CAN0_transmiter.CANFD_AsyncSend(CANFD_OTA_ACK_ID, 2, send_data);
// 5. 更新状态 - 进入固件接收阶段
ota_state = OTA_STATE_CHECKING_FIRMWARE;
} else {
// 其他握手异常
ota_error = OTA_ERROR_INVALID_HANDSHAKE;
ota_state = OTA_STATE_IDLE;
send_error_frame(OTA_ERROR_INVALID_HANDSHAKE);
return;
}
}
}
void OTAHandler::sendACK(uint32_t packet_num) {
CAN0_transmiter.sendACK(CANFD_OTA_ACK_ID, packet_num);
}
/**
* @brief 发送错误帧
* @param error: 错误码
* @retval 无
*/
void send_error_frame(u8 error) {
u8 error_frame[1] = {error};
CAN0_transmiter.CANFD_AsyncSend(CANFD_OTA_ACK_ID, 1, error_frame);
}
/**
* @brief 获取GD32设备唯一码
* @param buffer 存储唯一码的缓冲区,至少需要12字节
* @return void
*/
void getDeviceSerialNumber(u8 *buffer) {
uint32_t serial_msb = DEVICE_SERIAL_ADDR_MSB;
uint32_t serial_mid = DEVICE_SERIAL_ADDR_MID;
uint32_t serial_lsb = DEVICE_SERIAL_ADDR_LSB;
// 将96位唯一ID复制到缓冲区 (以小端序存储)
for (int i = 0; i < 4; i++) {
buffer[i] = (u8)(serial_lsb >> (i * 8));
buffer[i + 4] = (u8)(serial_mid >> (i * 8));
buffer[i + 8] = (u8)(serial_msb >> (i * 8));
}
}
/**
* @brief 获取GD32设备唯一码为字符串格式
* @param str 存储唯一码字符串的缓冲区,至少需要25字节(包含结束符)
* @return void
*/
void getDeviceSerialNumberString(char *str) {
u8 serial[12];
getDeviceSerialNumber(serial);
// 将字节序列转换为十六进制字符串表示
for (int i = 0; i < 12; i++) {
sprintf(&str[i * 2], "%02X", serial[i]);
}
str[24] = '\0'; // 确保字符串结束
}
/**
* @brief 将0x08010500地址后0xC000大小区域内的数据搬运到0x08011000地址
* @param None
* @retval fmc_state_enum: 操作状态
*/
fmc_state_enum move_app_data() {
fmc_state_enum fmc_status = FMC_READY;
scanAppFlashContent();
// 关闭全局中断以防止Flash操作期间的中断干扰
__disable_irq();
fmc_unlock();
// 首先擦除目标地址的Flash页面
uint32_t num_pages =
(APP_MAX_SIZE + FMC_PAGE_SIZE - 1) / FMC_PAGE_SIZE; // 向上取整
for (uint32_t i = 0; i < num_pages; i++) {
uint32_t page_addr = APPLATEST_START_ADDR + i * FMC_PAGE_SIZE;
// 擦除页面
fmc_status = fmc_page_erase(page_addr);
if (fmc_status != FMC_READY) {
fmc_lock();
#if OTA_DEBUG
printf("move_app_data erase error\r\n");
#endif
__enable_irq(); // 重新开启中断
return fmc_status;
}
}
// 复制数据 - 按字(32位)进行复制以提高效率
uint32_t offset = 0;
uint32_t write_count = 0; // 记录实际写入的字数
const uint32_t *src_ptr = (const uint32_t *)APPBACK_START_ADDR;
// 预计算源数据的CRC,避免重复访问内存
crc_deinit();
crc_data_register_reset();
uint32_t src_crc = crc_block_data_calculate((uint32_t *)APPBACK_START_ADDR,
APP_MAX_SIZE / 4);
while (offset < APP_MAX_SIZE) {
uint32_t src_data = src_ptr[offset / 4];
// 检查源地址是否为有效的Flash数据(非0xFFFFFFFF表示有数据)
if (src_data != 0xFFFFFFFF) {
// 清除之前的标志位
fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGAERR |
FMC_FLAG_PGERR);
fmc_status =
fmc_word_program(APPLATEST_START_ADDR + offset, src_data);
// 检查写入操作是否成功
if (fmc_status != FMC_READY) {
#if OTA_DEBUG
printf(
"Flash write failed at offset 0x%08X with status: %d\r\n",
offset, fmc_status);
#endif
fmc_lock();
__enable_irq(); // 重新开启中断
return fmc_status;
}
write_count++;
}
offset += 4;
}
fmc_lock();
// 重新开启全局中断
__enable_irq();
crc_data_register_reset(); // 确保CRC计算从初始状态开始
// 计算目标数据的CRC值
uint32_t dst_crc = crc_block_data_calculate(
(uint32_t *)APPLATEST_START_ADDR, APP_MAX_SIZE / 4);
// 比较CRC值,确保数据完整性
if (src_crc != dst_crc) {
#if OTA_DEBUG
printf("CRC mismatch: src_crc=0x%08X, dst_crc=0x%08X\r\n", src_crc,
dst_crc);
#endif
return (fmc_state_enum)0xFF; // CRC校验失败
}
return fmc_status;
}
/**
* 带密钥的CRC32校验函数
*
* @param key 16字节密钥
* @param data 48字节待校验数据
* @param output 4字节输出缓冲区,存储CRC32校验值
*
* 特点:
* - 使用标准CRC32算法
* - 16字节密钥用于初始化CRC32状态
*/
void calculate_crc32_with_key(const uint8_t *key, const uint8_t *data,
u8 *output) {
// CRC32查找表(标准多项式0xEDB88320)
static const uint32_t crc_table[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D};
// 用16字节密钥初始化CRC32状态
uint32_t crc = 0xFFFFFFFF;
for (int i = 0; i < 16; i++) {
crc = crc_table[(crc ^ key[i]) & 0xFF] ^ (crc >> 8);
}
// 计算48字节数据的CRC32
for (int i = 0; i < 48; i++) {
crc = crc_table[(crc ^ data[i]) & 0xFF] ^ (crc >> 8);
}
// 取反得到最终结果
crc = ~crc;
// 将CRC32结果拆分为4字节(小端格式)
output[0] = (uint8_t)(crc >> 0);
output[1] = (uint8_t)(crc >> 8);
output[2] = (uint8_t)(crc >> 16);
output[3] = (uint8_t)(crc >> 24);
}
+50 -9
View File
@@ -2,27 +2,68 @@
#define __OTA_H
#include "Can.h"
#include "aes128.h"
#include "config.h"
#include "gd32c10x.h"
#include <stdint.h>
class OTAHandler {
public:
bool ota_active;
uint32_t received_size;
uint32_t expected_size;
u32 ota_stateota_time;
u32 received_size;
u32 expected_size;
OTAHandler();
void init();
void process();
bool isActive() const { return ota_active; }
bool isActive() const { return ota_state; }
void handleOTAMessage(uint32_t id, uint8_t *data, uint8_t len);
void handleOTAMessage(u32 id, u8 *data, u8 len);
void jumpToApplication();
private:
bool validateApplication();
u32 ota_time;
void eraseApplicationArea();
void writeApplicationData(uint32_t offset, uint8_t *data, uint32_t size);
void sendACK(uint32_t packet_num);
void writeApplicationData(u32 offset, u8 *data, u32 size);
bool verifyApplicationData(u32 offset, u8 *data, u32 size);
// Flash操作标志(用于延迟执行,避免中断中耗时操作)
bool pending_flash_erase = false;
u32 pending_flash_offset = 0;
u8 pending_flash_data[64];
u8 pending_flash_size = 0;
typedef enum {
OTA_STATE_IDLE = 0,
OTA_STATE_WAITING_RANDOM, // 第二阶段等待随机数
OTA_STATE_WAITING_CONFIRM, // 等待上位机确认
OTA_STATE_CHECKING_FIRMWARE,
OTA_STATE_RECEIVING_FIRMWARE,
OTA_STATE_FINISHED
} ota_state_t;
typedef enum {
OTA_ERROR_NONE = 0,
OTA_ERROR_TIMEOUT,
OTA_ERROR_FLASH_ERROR,
OTA_ERROR_INVALID_KEY,
OTA_ERROR_INVALID_PACKET,
OTA_ERROR_INVALID_HANDSHAKE,
OTA_ERROR_INVALID_CRC,
OTA_ERROR_INVALID_SIZE
} ota_error_t;
u8 device_uid[12]; // 从GD32 UID寄存器读取
u8 current_K_session[16];
u8 nonce_server[16];
aes128_context aes_ctx; // AES上下文
ota_state_t ota_state = OTA_STATE_IDLE;
ota_error_t ota_error = OTA_ERROR_NONE;
};
void getDeviceSerialNumber(u8 *buffer);
void calculate_crc32_with_key(const u8 *key, const u8 *data,
u8 *output);
void send_error_frame(u8 error);
bool validateApplication();
fmc_state_enum move_app_data();
u8 OTA_SET(u32 addr, u32 data);
#endif
+373
View File
@@ -0,0 +1,373 @@
#include "aes128.h"
// S盒 (Substitution Box)
static const u8 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};
// 逆S盒 (InvSBox)
const u8 inv_sbox[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 u8 rcon[10] = {0x01, 0x02, 0x04, 0x08, 0x10,
0x20, 0x40, 0x80, 0x1b, 0x36};
// 伽罗瓦域乘法 (xtime) - 确保正确
static u8 xtime(u8 x) { return (x << 1) ^ (((x >> 7) & 1) * 0x1b); }
// 关键修复:AES状态矩阵是列优先排列!
// 内存布局应该是:s00, s10, s20, s30, s01, s11, s21, s31, ...
// 而不是行优先
// 轮密钥加 - 无需修改
void add_round_key(u8 *state, const u8 *round_key) {
for (u8 i = 0; i < 16; i++) {
state[i] ^= round_key[i];
}
}
// 字节替换 - 无需修改
void sub_bytes(u8 *state) {
for (u8 i = 0; i < 16; i++) {
state[i] = sbox[state[i]];
}
}
// 行移位 - 修复为列优先排列
void shift_rows(u8 *state) {
u8 temp;
// AES状态矩阵(列优先):
// 列0: state[0], state[1], state[2], state[3] -> 行0,1,2,3
// 列1: state[4], state[5], state[6], state[7] -> 行0,1,2,3
// 列2: state[8], state[9], state[10], state[11] -> 行0,1,2,3
// 列3: state[12], state[13], state[14], state[15] -> 行0,1,2,3
// 第1行(索引0,4,8,12)不移位
// 第2行(索引1,5,9,13)左移1位
temp = state[1];
state[1] = state[5];
state[5] = state[9];
state[9] = state[13];
state[13] = temp;
// 第3行(索引2,6,10,14)左移2位
temp = state[2];
state[2] = state[10];
state[10] = temp;
temp = state[6];
state[6] = state[14];
state[14] = temp;
// 第4行(索引3,7,11,15)左移3位
temp = state[3];
state[3] = state[15];
state[15] = state[11];
state[11] = state[7];
state[7] = temp;
}
// 列混合 - 修复为正确的实现
void mix_columns(u8 *state) {
u8 a[4], b[4];
// 处理每一列
for (u8 col = 0; col < 4; col++) {
// 获取当前列的4个字节
a[0] = state[col * 4 + 0];
a[1] = state[col * 4 + 1];
a[2] = state[col * 4 + 2];
a[3] = state[col * 4 + 3];
// 计算混合后的值
b[0] = xtime(a[0]) ^ xtime(a[1]) ^ a[1] ^ a[2] ^ a[3];
b[1] = a[0] ^ xtime(a[1]) ^ xtime(a[2]) ^ a[2] ^ a[3];
b[2] = a[0] ^ a[1] ^ xtime(a[2]) ^ xtime(a[3]) ^ a[3];
b[3] = xtime(a[0]) ^ a[0] ^ a[1] ^ a[2] ^ xtime(a[3]);
// 存回结果
state[col * 4 + 0] = b[0];
state[col * 4 + 1] = b[1];
state[col * 4 + 2] = b[2];
state[col * 4 + 3] = b[3];
}
}
// 伽罗瓦域乘法 (用于逆列混合)
static u8 gf_mul(u8 a, u8 b) {
u8 p = 0;
u8 high_bit;
while (b) {
if (b & 1) {
p ^= a;
}
high_bit = a & 0x80;
a <<= 1;
if (high_bit) {
a ^= 0x1b; // x^8 + x^4 + x^3 + x + 1
}
b >>= 1;
}
return p;
}
// 逆字节替换
void inv_sub_bytes(u8 *state) {
for (u8 i = 0; i < 16; i++) {
state[i] = inv_sbox[state[i]];
}
}
// 逆行移位 - 与shift_rows对应
void inv_shift_rows(u8 *state) {
u8 temp;
// 第2行右移1位
temp = state[13];
state[13] = state[9];
state[9] = state[5];
state[5] = state[1];
state[1] = temp;
// 第3行右移2位
temp = state[2];
state[2] = state[10];
state[10] = temp;
temp = state[6];
state[6] = state[14];
state[14] = temp;
// 第4行右移3位
temp = state[7];
state[7] = state[11];
state[11] = state[15];
state[15] = state[3];
state[3] = temp;
}
// 逆列混合 - 正确实现
void inv_mix_columns(u8 *state) {
u8 a[4], b[4];
// 处理每一列
for (u8 col = 0; col < 4; col++) {
// 获取当前列的4个字节
a[0] = state[col * 4 + 0];
a[1] = state[col * 4 + 1];
a[2] = state[col * 4 + 2];
a[3] = state[col * 4 + 3];
// 计算逆混合后的值
b[0] = gf_mul(0x0e, a[0]) ^ gf_mul(0x0b, a[1]) ^ gf_mul(0x0d, a[2]) ^
gf_mul(0x09, a[3]);
b[1] = gf_mul(0x09, a[0]) ^ gf_mul(0x0e, a[1]) ^ gf_mul(0x0b, a[2]) ^
gf_mul(0x0d, a[3]);
b[2] = gf_mul(0x0d, a[0]) ^ gf_mul(0x09, a[1]) ^ gf_mul(0x0e, a[2]) ^
gf_mul(0x0b, a[3]);
b[3] = gf_mul(0x0b, a[0]) ^ gf_mul(0x0d, a[1]) ^ gf_mul(0x09, a[2]) ^
gf_mul(0x0e, a[3]);
// 存回结果
state[col * 4 + 0] = b[0];
state[col * 4 + 1] = b[1];
state[col * 4 + 2] = b[2];
state[col * 4 + 3] = b[3];
}
}
// 密钥扩展 - 修复为标准实现
static void key_expansion(aes128_context *ctx) {
u8 temp[4];
u8 i, rcon_iter = 0;
// 复制原始密钥到第一轮密钥
memcpy(ctx->round_keys[0], ctx->key, 16);
// 生成10轮密钥
for (i = 1; i <= 10; i++) {
// 复制前一轮最后一列
temp[0] = ctx->round_keys[i - 1][12];
temp[1] = ctx->round_keys[i - 1][13];
temp[2] = ctx->round_keys[i - 1][14];
temp[3] = ctx->round_keys[i - 1][15];
// 字循环 (RotWord)
u8 t = temp[0];
temp[0] = temp[1];
temp[1] = temp[2];
temp[2] = temp[3];
temp[3] = t;
// 字节替换 (SubWord)
temp[0] = sbox[temp[0]];
temp[1] = sbox[temp[1]];
temp[2] = sbox[temp[2]];
temp[3] = sbox[temp[3]];
// 轮常量异或
temp[0] ^= rcon[i - 1];
// 生成新的第一列
ctx->round_keys[i][0] = ctx->round_keys[i - 1][0] ^ temp[0];
ctx->round_keys[i][1] = ctx->round_keys[i - 1][1] ^ temp[1];
ctx->round_keys[i][2] = ctx->round_keys[i - 1][2] ^ temp[2];
ctx->round_keys[i][3] = ctx->round_keys[i - 1][3] ^ temp[3];
// 生成其他列
for (u8 j = 1; j < 4; j++) {
ctx->round_keys[i][j * 4 + 0] =
ctx->round_keys[i][(j - 1) * 4 + 0] ^
ctx->round_keys[i - 1][j * 4 + 0];
ctx->round_keys[i][j * 4 + 1] =
ctx->round_keys[i][(j - 1) * 4 + 1] ^
ctx->round_keys[i - 1][j * 4 + 1];
ctx->round_keys[i][j * 4 + 2] =
ctx->round_keys[i][(j - 1) * 4 + 2] ^
ctx->round_keys[i - 1][j * 4 + 2];
ctx->round_keys[i][j * 4 + 3] =
ctx->round_keys[i][(j - 1) * 4 + 3] ^
ctx->round_keys[i - 1][j * 4 + 3];
}
}
}
// 设置密钥
void aes128_set_key(aes128_context *ctx, const u8 *key) {
memcpy(ctx->key, key, AES128_KEY_LEN);
key_expansion(ctx);
}
// 加密单个块
void aes128_encrypt_block(aes128_context *ctx, const u8 *input, u8 *output) {
// 复制输入到状态
memcpy(ctx->state, input, AES_BLOCK_SIZE);
// 初始轮密钥加
add_round_key(ctx->state, ctx->round_keys[0]);
// 9轮标准轮
for (u8 round = 1; round <= 9; round++) {
sub_bytes(ctx->state);
shift_rows(ctx->state);
mix_columns(ctx->state);
add_round_key(ctx->state, ctx->round_keys[round]);
}
// 最终轮 (没有mix_columns)
sub_bytes(ctx->state);
shift_rows(ctx->state);
add_round_key(ctx->state, ctx->round_keys[10]);
// 复制结果到输出
memcpy(output, ctx->state, AES_BLOCK_SIZE);
}
// ECB模式加密48字节数据
void aes128_ecb_encrypt_48bytes(aes128_context *ctx, const u8 *input,
u8 *output) {
// 分3块加密 (48 = 16 * 3)
aes128_encrypt_block(ctx, input, output);
aes128_encrypt_block(ctx, input + 16, output + 16);
aes128_encrypt_block(ctx, input + 32, output + 32);
}
// 解密单个块
void aes128_decrypt_block(aes128_context *ctx, const u8 *input, u8 *output) {
// 复制输入到状态
memcpy(ctx->state, input, AES_BLOCK_SIZE);
// 初始轮密钥加(使用最后一轮密钥)
add_round_key(ctx->state, ctx->round_keys[10]);
// 9轮标准解密轮
for (u8 round = 9; round >= 1; round--) {
inv_shift_rows(ctx->state);
inv_sub_bytes(ctx->state);
add_round_key(ctx->state, ctx->round_keys[round]);
inv_mix_columns(ctx->state);
}
// 最终轮(没有inv_mix_columns)
inv_shift_rows(ctx->state);
inv_sub_bytes(ctx->state);
add_round_key(ctx->state, ctx->round_keys[0]);
// 复制结果到输出
memcpy(output, ctx->state, AES_BLOCK_SIZE);
}
// ECB模式解密48字节数据
void aes128_ecb_decrypt_48bytes(aes128_context *ctx, const u8 *input,
u8 *output) {
// 分3块解密 (48 = 16 * 3)
aes128_decrypt_block(ctx, input, output);
aes128_decrypt_block(ctx, input + 16, output + 16);
aes128_decrypt_block(ctx, input + 32, output + 32);
}
// 验证函数:加密后解密,对比原始数据
u8 aes128_verify_encryption(aes128_context *ctx, const u8 *original_data,
size_t length) {
u8 temp_ciphertext[48];
u8 temp_plaintext[48];
u8 result = 1; // 1表示验证成功,0表示失败
// 1. 加密原始数据
aes128_ecb_encrypt_48bytes(ctx, original_data, temp_ciphertext);
// 2. 解密密文
aes128_ecb_decrypt_48bytes(ctx, temp_ciphertext, temp_plaintext);
// 3. 对比原始数据和解密后的数据
for (size_t i = 0; i < length; i++) {
if (original_data[i] != temp_plaintext[i]) {
result = 0; // 验证失败
break;
}
}
return result;
}
+41
View File
@@ -0,0 +1,41 @@
#ifndef __AES_H
#define __AES_H
#include "cstdint"
#include <string.h>
// AES-128 密钥长度 (16 bytes)
#define AES128_KEY_LEN 16
// AES 块大小 (16 bytes)
#define AES_BLOCK_SIZE 16
// AES 状态结构
typedef struct {
u8 key[AES128_KEY_LEN]; // 128位/16字节密钥
u8 round_keys[11][16]; // 10轮 + 初始轮密钥
u8 state[AES_BLOCK_SIZE]; // 状态矩阵
} aes128_context;
// 内部函数声明(需要在头文件中声明,因为解密函数会使用)
void add_round_key(u8 *state, const u8 *round_key);
void sub_bytes(u8 *state);
void shift_rows(u8 *state);
void mix_columns(u8 *state);
void inv_sub_bytes(u8 *state);
void inv_shift_rows(u8 *state);
void inv_mix_columns(u8 *state);
// 公共函数声明
void aes128_set_key(aes128_context *ctx, const u8 *key);
void aes128_encrypt_block(aes128_context *ctx, const u8 *input, u8 *output);
void aes128_ecb_encrypt_48bytes(aes128_context *ctx, const u8 *input,
u8 *output);
void aes128_decrypt_block(aes128_context *ctx, const u8 *input, u8 *output);
void aes128_ecb_decrypt_48bytes(aes128_context *ctx, const u8 *input,
u8 *output);
u8 aes128_verify_encryption(aes128_context *ctx, const u8 *original_data,
size_t length);
// 逆S盒 (用于解密)
extern const u8 inv_sbox[256];
#endif /* __AES_H */
+61 -15
View File
@@ -1,21 +1,67 @@
#pragma once
#ifndef __CONFIG_H__
#define __CONFIG_H__
#include "stdint.h"
#define EEP_DEBUG 0
#define DEBUG_OTA 0
#define CAN_DEBUG 0
#define SLEEP_DEBUG 0
// Flash分区配置
constexpr uint32_t BOOTLOADER_SIZE = 0x4000; // 16KB
constexpr uint32_t APP_START_ADDR = 0x08004000; // APP起始地址
constexpr uint32_t APP_MAX_SIZE = 0x0001C000; // 112KB
constexpr uint32_t FMC_PAGE_SIZE = 0x400;
constexpr u32 BOOTLOADER_SIZE = 0x6000; // 24KB
constexpr u32 BOOTLOADER_START_ADDR = 0x08000000; // BOOT起始地址
constexpr u32 APPLATEST_START_ADDR = 0x08012000; // APP起始地址
constexpr u32 APPBACK_START_ADDR = 0x08006000; // APPBACK起始地址
constexpr u32 APP_MAX_SIZE = 0xC000; // 48KB
constexpr u32 FMC_PAGE_SIZE = 0x400; // 1KB
constexpr u32 SLEEP_CONFIG_START = 0x0801E400; // 睡眠配置起始地址
constexpr u32 SLEEP_CONFIG_END = 0x0801E800; // 睡眠配置结束地址
constexpr u32 FLASH_EMPTY = 0xFFFFFFFF; // 空数据
constexpr u32 SLEEP_ENABLE = 0x11111111; // 睡眠使能
constexpr u32 SLEEP_DISABLE = 0x00000000; // 睡眠禁止
// BOOT 相关
constexpr u32 OTA_CONFIG_NUM = 6;
constexpr u32 n_APP_LATEST_AVAL_ADDR = 0x0801E000; // 最新APP可用地址
constexpr u32 n_APP_BACKUP_AVAL_ADDR = 0x0801E004; // 备份APP可用地址
constexpr u32 n_APP_LATEST_EN_ADDR = 0x0801E008; // 最新APP激活
constexpr u32 n_APP_BACKUP_EN_ADDR = 0x0801E00C; // 备份APP激活
constexpr u32 n_APP_LATEST_CHECK_ADDR = 0x0801E010; // 最新APP校验
constexpr u32 n_APP_BACKUP_CHECK_ADDR = 0x0801E014; // 备份APP校验
constexpr u32 OTA_NOT_AVAL = 0xFFFFFFFF;
constexpr u32 OTA_AVAL = 0x00000000; // 全零表示可用
constexpr u32 FLASH_EEPROM_OK = 0;
constexpr u32 FLASH_EEPROM_ERROR = 1;
// CANFD配置
constexpr uint32_t CANFD_OTA_REQ_ID = 0x00000100;
constexpr uint32_t CANFD_OTA_DATA_ID = 0x00000101;
constexpr uint32_t CANFD_OTA_ACK_ID = 0x00000102;
constexpr u32 CANFD_OTA_REQ_ID = 0x00000100;
constexpr u32 CANFD_OTA_DATA_ID = 0x00000101;
constexpr u32 CANFD_OTA_ACK_ID = 0x00000102;
constexpr u32 CANFD_OTA_WAIT_ID = 0x00000103;
constexpr u32 CANFD_OTA_CANCEL_ID = 0x00000000;
// CANFD数据段最大64字节,我们用32字节数据 + 4字节头部
constexpr uint32_t OTA_PACKET_SIZE = 32;
typedef struct {
uint32_t packet_num; // 包序号
uint8_t data[OTA_PACKET_SIZE]; // 32字节有效数据
uint32_t crc32; // 简单校验
} canfd_ota_packet_t;
// 设备唯一ID寄存器地址 (GD32C10x系列)
constexpr u32 DEVICE_SERIAL_ADDR_MSB = 0x1FFFF7E8; // 最高32位
constexpr u32 DEVICE_SERIAL_ADDR_MID = 0x1FFFF7EC; // 中间32位
constexpr u32 DEVICE_SERIAL_ADDR_LSB = 0x1FFFF7F0; // 最低32位
// CANFD数据段最大64字节,我们用1字节序号 + 48字节数据 + 1字节CRC校验
constexpr u32 OTA_PACKET_SIZE = 48;
// 定义一个联合体类型用于float和byte数组之间的转换
typedef union {
u32 u;
u8 b[4];
} u32_union_t;
// 全局变量(需在安全区域存储)
constexpr uint8_t K_master[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB,
0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98,
0x76, 0x54, 0x32, 0x10}; // 预置主密钥
// 其他
constexpr u32 OTA_TIMEOUT = 10000;
constexpr u32 APP_DELAY_BOOT_TIME = 10000; // APP延迟启动时间(毫秒),可配置
constexpr u8 SIZE_U32 = sizeof(uint32_t);
constexpr u8 SIZE_FLOAT = sizeof(float);
#endif
+2 -400
View File
@@ -10,12 +10,6 @@
#include <stdint.h>
FlashEEPROM flashEEP = FlashEEPROM();
extern CAN_transmiter CAN0_transmiter;
constexpr u8 SIZE_U32 = sizeof(uint32_t);
constexpr u8 SIZE_FLOAT = sizeof(float);
constexpr u8 DEFAULT_VALUE = 0;
constexpr u8 NUM_SAVED = 6;
#define EEPDEBUG 0
// FlashEEPROM类实现
FlashEEPROM::FlashEEPROM() {
@@ -31,322 +25,7 @@ u8 FlashEEPROM::init() {
rcu_periph_clock_enable(RCU_CRC);
crc_deinit(); // 初始化CRC模块
FlashEepromStatus status = FLASH_EEPROM_OK;
// 读取系统配置
read_saved_system_config();
if (EEPROMStatus == FLASH_EEPROM_OK) {
return FLASH_EEPROM_OK;
} else {
return FLASH_EEPROM_READ_ERROR;
}
return 1; // 正常不会返回这个,未预料的异常情况返回
}
/**
* @brief 读取EEPROM数据
* @param virtualAddr: 虚拟地址
* @param data: 存储读取数据的指针
* @retval EEPROMStatus: 是否成功
*/
u8 FlashEEPROM::read_saved_system_config(void) {
// 读取保存的参数
u32 CRC_NUM = 0x0000;
FlashEepromStatus status_read[NUM_SAVED + 1] = {FLASH_EEPROM_OK};
float data[NUM_SAVED] = {0.0f};
// 尝试从Flash读取参数,如果不存在则使用默认值
status_read[1] = readFloat(ADDR_CONTROL_MODE, &data[0]);
status_read[2] = readFloat(ADDR_VOLTAGE_LIMIT, &data[1]);
status_read[3] = readFloat(ADDR_VEL_LIMIT, &data[2]);
status_read[4] = readFloat(ADDR_ANGLE, &data[3]);
status_read[5] = readFloat(ADDR_TARGET_ANGLE, &data[4]);
status_read[6] = readFloat(ADDR_TARGET_VEL, &data[5]);
// 读取失败则使用默认值
for (u8 i = 1; i < NUM_SAVED + 1; i++) {
if (status_read[i] ==
FLASH_EEPROM_DATA_NOT_FOUND) { // 首次读取,不保存报错
data[i - 1] = DEFAULT_VALUE;
} else if (status_read[i] != FLASH_EEPROM_OK) { // 其余错误,保存报错
data[i - 1] = DEFAULT_VALUE;
status_read[0] = status_read[i];
}
}
// 读取到全部数据
if (status_read[0] == FLASH_EEPROM_OK) {
u32 next_address = EEPROM_END_ADDRESS;
// 遍历Flash页面寻找下一个可写入位置
for (u32 address = EEPROM_DATA_START_ADDRESS - SIZE_U32;
address > EEPROM_START_ADDRESS; address -= SIZE_U32) {
// 安全读取Flash数据
volatile u32 *flash_ptr = (volatile u32 *)address;
u32 data_word = *flash_ptr;
// 找到空位置
if (data_word == 0xFFFFFFFF) {
next_address = address + SIZE_U32; // 上一个位置为有效存储的数据
break;
}
// 更新下一个可能的写入位置(如果需要格式化)
next_address = address - SIZE_U32;
}
if (next_address == EEPROM_DATA_START_ADDRESS) {
// 从来没有存储过,直接返回
return FLASH_EEPROM_OK;
}
crc_data_register_reset(); // 确保CRC计算从初始状态开始
CRC_NUM = crc_block_data_calculate((uint32_t *)data, NUM_SAVED);
#if EEPDEBUG
printf("CRC cmp1,0x%X_0x%x \r\n", CRC_NUM, *((u32 *)next_address));
#endif
if (CRC_NUM != *((u32 *)next_address)) { // CRC错误
for (u8 i = 0; i < NUM_SAVED; i++) {
data[i] = DEFAULT_VALUE;
}
EEPROMStatus = FLASH_EEPROM_CRC_ERROR;
} else { // CRC正确
EEPROMStatus = FLASH_EEPROM_OK;
}
} else {
// 读取失败,报错
EEPROMStatus = status_read[0];
}
return EEPROMStatus;
}
/**
* @brief 从Flash EEPROM读取数据
* @param virtualAddr: 虚拟地址
* @param data: 指向存储读取数据的指针
* @retval FlashEepromStatus: 操作状态
*/
FlashEepromStatus FlashEEPROM::read(u8 virtualAddr, u16 *data) const {
// 参数检查
if (data == nullptr) {
return FLASH_EEPROM_INVALID_ADDR;
}
// 从Flash末尾开始向前搜索,找到最新的数据
for (u32 address = EEPROM_END_ADDRESS - SIZE_U32;
address >= EEPROM_START_ADDRESS; address -= SIZE_U32) {
u32 data_word = *((u32 *)address);
// 检查是否是有效数据(非擦除状态)
if (data_word != 0xFFFFFFFF) {
u8 addr = (u8)(data_word & DATA_ADDR_MASK);
// 找到匹配的虚拟地址
if (addr == virtualAddr) {
*data = (u16)(data_word & DATA_U16_MASK);
return FLASH_EEPROM_OK;
}
}
}
return FLASH_EEPROM_DATA_NOT_FOUND;
}
/**
* @brief 从Flash EEPROM读取float数据
* @param virtualAddr: 虚拟地址
* @param data: 指向存储读取数据的指针
* @retval FlashEepromStatus: 操作状态
*/
FlashEepromStatus FlashEEPROM::readFloat(u8 virtualAddr, float *data) const {
// 检查参数有效性
if (data == nullptr) {
return FLASH_EEPROM_INVALID_ADDR;
}
// 从Flash末尾开始向前搜索,找到最新的数据
for (u32 address = EEPROM_END_ADDRESS - SIZE_U32;
address >= EEPROM_START_ADDRESS; address -= SIZE_U32) {
// 使用volatile确保每次都从内存读取,防止编译器优化
volatile u32 *flash_ptr = (volatile u32 *)address;
u32 data_word = *flash_ptr;
// 检查是否是有效数据(非擦除状态)
if (data_word != 0xFFFFFFFF) {
u8 addr = (u8)(data_word & DATA_ADDR_MASK);
// 找到匹配的虚拟地址
if (addr == virtualAddr) {
// 清除最低的8位地址信息,保留高24位数据
u32 float_data = data_word & DATA_FLOAT_MASK;
// 使用内存拷贝将处理后的数据解释为float
memcpy(data, &float_data, SIZE_FLOAT);
#if EEPDEBUG
printf("read:0x%x=%f\r\n", address, *data);
#endif
return FLASH_EEPROM_OK;
}
}
}
// 未找到指定虚拟地址的数据
return FLASH_EEPROM_DATA_NOT_FOUND;
}
/**
* @brief 向Flash EEPROM写入数据
* @param virtualAddr: 虚拟地址
* @param data: 要写入的数据
* @retval FlashEepromStatus: 操作状态
*/
FlashEepromStatus FlashEEPROM::write(u8 virtualAddr, u16 data) {
// 查找下一个可写入的位置
u32 next_address = EEPROM_START_ADDRESS;
u32 data_read;
// 插入虚拟地址到低8位 格式: [data:16bit][reserved:8bit][addr:8bit]
data = (data & DATA_U16_MASK) | (u32)virtualAddr;
for (u32 address = EEPROM_END_ADDRESS - SIZE_U32;
address >= EEPROM_DATA_START_ADDRESS; address -= SIZE_U32) {
// 安全读取Flash数据
volatile u32 *flash_ptr = (volatile u32 *)address;
data_read = *flash_ptr;
if ((data_read & DATA_ADDR_MASK) == (u32)virtualAddr) { // 虚拟地址相同
if ((data_read & DATA_U16_MASK) ==
(data & DATA_U16_MASK)) { // 数据相同
#if EEPDEBUG
data_read = data_read & DATA_U16_MASK;
u16 float_data_read = *((u16 *)&data_read);
printf("Found data in:0x%x=%u\r\n", address, data_read);
#endif
return FLASH_EEPROM_OK;
} else {
break;
}
}
}
// 遍历Flash页面寻找下一个可写入位置
for (u32 address = EEPROM_DATA_START_ADDRESS; address < EEPROM_END_ADDRESS;
address += SIZE_U32) {
// 安全读取Flash数据
volatile u32 *flash_ptr = (volatile u32 *)address;
u32 data_word = *flash_ptr;
// 找到空位置
if (data_word == 0xFFFFFFFF) {
next_address = address;
break;
}
// 更新下一个可能的写入位置(如果需要格式化)
next_address = address + SIZE_U32;
}
// 如果有足够空间,直接写入
if (next_address < EEPROM_END_ADDRESS) {
u32 data_word = ((u32)data << 16) | (u32)virtualAddr;
// 使用GD32库函数进行安全编程
fmc_unlock();
fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_PGAERR | FMC_FLAG_WPERR);
fmc_state_enum fmc_status =
fmc_word_program(next_address, data_word); // 写入数据
fmc_lock();
if (fmc_status != FMC_READY) {
return FLASH_EEPROM_WRITE_ERROR;
}
return FLASH_EEPROM_OK;
} else { // 空间不足,需要格式化页面
#if EEPDEBUG
printf("no enough space\r\n");
#endif
FlashEepromStatus status = format();
if (status == FLASH_EEPROM_OK) {
return status;
} else {
return FLASH_EEPROM_ERASE_ERROR;
}
}
}
/**
* @brief 向Flash EEPROM写入float数据
* @param virtualAddr: 虚拟地址
* @param data: 要写入的数据
* @retval FlashEepromStatus: 操作状态
*/
FlashEepromStatus FlashEEPROM::writeFloat(u8 virtualAddr, float data) {
// 查找下一个可写入的位置
u32 next_address = EEPROM_START_ADDRESS;
u32 data_word;
// 将完整的float数据复制到32位变量中
memcpy(&data_word, &data, SIZE_FLOAT);
// 插入虚拟地址到低8位 格式: [data:24bit][addr:8bit]
data_word = (data_word & DATA_FLOAT_MASK) | (u32)virtualAddr;
// 从Flash末尾开始向前搜索,找到最新的数据
for (u32 address = EEPROM_END_ADDRESS - SIZE_U32;
address >= EEPROM_DATA_START_ADDRESS; address -= SIZE_U32) {
// 安全读取Flash数据
volatile u32 *flash_ptr = (volatile u32 *)address;
u32 data_word_read = *flash_ptr;
if ((data_word_read & DATA_ADDR_MASK) ==
(u32)virtualAddr) { // 虚拟地址相同
if ((data_word_read & DATA_FLOAT_MASK) ==
(data_word & DATA_FLOAT_MASK)) { // 数据相同
#if EEPDEBUG
data_word_read = data_word_read & DATA_FLOAT_MASK;
float float_data_read = *((float *)&data_word_read);
printf("Found data in:0x%x=%f\r\n", address, float_data_read);
#endif
return FLASH_EEPROM_OK;
} else {
break; // 找到相同地址但数据不同,需要更新
}
}
}
// 遍历Flash页面寻找下一个可写入位置
for (u32 address = EEPROM_DATA_START_ADDRESS; address < EEPROM_END_ADDRESS;
address += SIZE_U32) {
// 安全读取Flash数据
volatile u32 *flash_ptr = (volatile u32 *)address;
u32 data_word_read = *flash_ptr;
// 找到空位置
if (data_word_read == 0xFFFFFFFF) {
next_address = address;
break;
}
// 更新下一个可能的写入位置(如果需要格式化)
next_address = address + SIZE_U32;
}
// 如果有足够空间,直接写入
if (next_address < EEPROM_END_ADDRESS) {
// 使用GD32库函数进行安全编程
fmc_unlock();
fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_PGAERR | FMC_FLAG_WPERR);
// 确保使用对齐地址
fmc_state_enum fmc_status = fmc_word_program(next_address, data_word);
fmc_lock();
#if EEPDEBUG
u32 data_word_c = *((u32 *)next_address);
data_word_c = data_word_c & DATA_FLOAT_MASK;
float float_data = *((float *)&data_word_c);
printf("save:0x%x=%f\r\n", next_address, float_data);
#endif
if (fmc_status != FMC_READY) {
return FLASH_EEPROM_WRITE_ERROR;
}
return FLASH_EEPROM_OK;
} else {
// 空间不足,需要格式化页面
#if EEPDEBUG
printf("no enough space\r\n");
#endif
FlashEepromStatus status = format();
if (status == FLASH_EEPROM_OK) {
return status;
} else {
return FLASH_EEPROM_ERASE_ERROR;
}
}
return 0; // 正常不会返回这个,未预料的异常情况返回
}
/**
@@ -356,7 +35,7 @@ FlashEepromStatus FlashEEPROM::writeFloat(u8 virtualAddr, float data) {
*/
FlashEepromStatus FlashEEPROM::format() {
fmc_state_enum fmc_status;
#if EEPDEBUG
#if EEP_DEBUG
printf("擦除页面\r\n");
#endif
@@ -373,81 +52,4 @@ FlashEepromStatus FlashEEPROM::format() {
}
fmc_lock();
return FLASH_EEPROM_OK;
}
/**
* @brief 读取角度数据从Flash
* @return float: 角度数据
*/
float FlashEEPROM::read_angle() {
float angle = DEFAULT_VALUE;
if (readFloat(ADDR_ANGLE, &angle) != FLASH_EEPROM_OK) {
angle = DEFAULT_VALUE;
}
return angle;
}
/**
* @brief 保存CRC数据到Flash
* @param saved: 是否一次性保存
* @return FlashEepromStatus: 状态
*/
FlashEepromStatus FlashEEPROM::writeCRC(u32 CRC_NUM, bool saved) {
static u32 next_address;
// 遍历Flash页面寻找下一个可写入crc的位置
for (u32 address = EEPROM_DATA_START_ADDRESS - SIZE_U32;
address > EEPROM_START_ADDRESS; address -= SIZE_U32) {
// 安全读取Flash数据
volatile u32 *flash_ptr = (volatile u32 *)address;
u32 data_word = *flash_ptr;
// 找到空位置
if (data_word == 0xFFFFFFFF) {
next_address = address;
break;
}
// 更新下一个可能的写入位置(如果需要格式化)
next_address = address - SIZE_U32;
}
// 如果当前CRC与现在的crc值不同,则写入
if (*((u32 *)next_address) != CRC_NUM) {
// 如果有足够空间,直接写入crc值
if (next_address > EEPROM_START_ADDRESS) {
fmc_unlock();
fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_PGAERR | FMC_FLAG_WPERR);
fmc_state_enum fmc_status = fmc_word_program(next_address, CRC_NUM);
fmc_lock();
#if EEPDEBUG
printf("CRC cmp1,0x%X_0x%x \r\n", CRC_NUM, *((u32 *)next_address));
#endif
// 检查写入是否成功
if (fmc_status != FMC_READY) {
EEPROMStatus = fmc_status;
return FLASH_EEPROM_WRITE_ERROR;
}
} else {
// 空间不足,需要格式化页面
#if EEPDEBUG
printf("no enough space\r\n");
#endif
FlashEepromStatus status = format();
if (status == FLASH_EEPROM_OK) {
return status;
} else {
EEPROMStatus = FLASH_EEPROM_ERASE_ERROR;
return FLASH_EEPROM_ERASE_ERROR;
}
}
}
// 重新读取CRC校验
if (CRC_NUM == *((u32 *)next_address)) {
system_config_saved = saved; // 标记已保存过
EEPROMStatus = FLASH_EEPROM_OK; // 设置EEPROM状态
return FLASH_EEPROM_OK;
} else {
EEPROMStatus = FLASH_EEPROM_CRC_ERROR; // 设置EEPROM错误状态
return FLASH_EEPROM_CRC_ERROR;
}
}
+2 -30
View File
@@ -2,8 +2,6 @@
#define __FLASH_H
#include <stdint.h>
// 修改后 - 强制4字节对齐
#define ALIGN_4BYTE(addr) ((addr) & 0xFFFFFFFC) // 4字节对齐
// EEPROM操作状态
typedef enum {
@@ -26,21 +24,8 @@ class FlashEEPROM {
static constexpr u32 EEPROM_END_ADDRESS = 0x08020000; // Flash结束地址
static constexpr u32 EEPROM_MAX_SIZE = 0x800; // EEPROM最大容量
static constexpr u32 EEPROM_DATA_START_ADDRESS =
0x0801F900; // DATA段开始地址
static constexpr u32 DATA_FLOAT_MASK = 0xFFFFFF00; // float存储地址掩码
static constexpr u32 DATA_U16_MASK = 0xFFFF0000; // u16存储地址掩码
static constexpr u32 DATA_ADDR_MASK = 0x000000FF; // 虚拟地址掩码
0x0801F900; // DATA段开始地址
// 定义用户自定义的虚拟地址
static constexpr u8 ADDR_CONTROL_MODE = 0x0; // 控制模式
static constexpr u8 ADDR_ANGLE = 0x01; // 角度数据存储地址
static constexpr u8 ADDR_TARGET_ANGLE = 0x02; // 角度命令数据存储地址
static constexpr u8 ADDR_TARGET_VEL = 0x03; // 速度命令数据存储地址
static constexpr u8 ADDR_VOLTAGE_LIMIT = 0x4; // 电压限制
static constexpr u8 ADDR_VEL_LIMIT = 0x05; // 角度数据存储地址
bool angle_saved = false;
bool system_config_saved = false;
u8 EEPROMStatus;
// 构造函数
FlashEEPROM();
@@ -48,24 +33,11 @@ class FlashEEPROM {
// 初始化Flash EEPROM模拟
u8 init();
// 从Flash EEPROM中读取数据
FlashEepromStatus read(u8 virtualAddr, u16 *data) const;
// 向Flash EEPROM写入数据
FlashEepromStatus write(u8 virtualAddr, u16 data);
// Float数据读相关函数
FlashEepromStatus readFloat(u8 virtualAddr, float *data) const;
// Float数据存储相关函数
FlashEepromStatus writeFloat(u8 virtualAddr, float data);
// 格式化Flash EEPROM页面
FlashEepromStatus format();
u8 read_saved_system_config(void);
float read_angle();
FlashEepromStatus writeCRC(u32 CRC_NUM);
private:
FlashEepromStatus writeCRC(u32 CRC_NUM, bool saved);
};
void flash_eeprom_example_main(void);
#endif /* __FLASH_H */
-103
View File
@@ -1,103 +0,0 @@
#include "health.h"
#include "Can.h"
#include "DengFOC.h"
#include "adc.h"
#include "flash.h"
#include <stdint.h>
extern sampler sampler;
extern CAN_transmiter CAN0_transmiter;
extern FOC_Controlroller FOC;
extern FlashEEPROM flashEEP;
ThermalController thermalController; // 热量控制器初始化
#define max(a, b, c) \
((a) > (b) ? ((a) > (c) ? (a) : (c)) : ((b) > (c) ? (b) : (c)))
constexpr u16 PROTECT_TIME = 6000; // 过热保护时间,单位*10ms
/**
** @brief 热能计算
** @param None
** @retval 热量值
*/
u32 ThermalController::update() {
thermal_value = Q16_16_MUL(thermal_value, thermalRate);
// 添加温度积累
int drv_temp = (int)sampler.get_drv_temp();
int mcu_temp = (int)sampler.get_mcu_temp();
if (drv_temp == 255)
drv_temp = 0;
if (mcu_temp == 255)
mcu_temp = 0;
thermal_value += drv_temp * drv_temp + mcu_temp * mcu_temp;
if (remainingTime10Ms) {
// 过热停机状态
// 检查是否可以恢复
q16_16_t recovery_threshold =
Q16_16_MUL(thermal_capacity, recoveryRate);
if (thermal_value < recovery_threshold) {
remainingTime10Ms = 1; // 可以恢复工作
}
if (remainingTime10Ms == 1) { // 过热恢复
FOC.resume();
CAN0_transmiter.ThermalStatus = 0;
return --remainingTime10Ms;
}
return --remainingTime10Ms;
} else {
// 当前没有过热停机
// 添加电流热积累
u32 currents[3] = {(u32)(sampler.get_current('U') * 1000),
(u32)(sampler.get_current('V') * 1000),
(u32)(sampler.get_current('W') * 1000)};
// 找最大电流(原始ADC值)
current_max = max(currents[0], currents[1], currents[2]);
if (current_max < 2000) {
thermal_value += current_max * current_max * gapTimeMs *
0.00007f; // 计算当前电流热积累值
} else if (current_max > 3800) {
thermal_value += current_max * current_max * gapTimeMs *
0.01f; // 添加当前电流热积累值
} else if (current_max > 3400) {
thermal_value += current_max * current_max * gapTimeMs *
0.005f; // 计算当前电流热积累值
} else if (current_max > 3000) {
thermal_value += current_max * current_max * gapTimeMs *
0.0002f; // 计算当前电流热积累值
} else if (current_max > 2000) {
thermal_value += current_max * current_max * gapTimeMs *
0.0001f; // 计算当前电流热积累值
}
}
if (thermal_value > thermal_capacity) {
FOC.shut_down();
remainingTime10Ms = PROTECT_TIME; // 过热停机
CAN0_transmiter.ThermalStatus = 1;
return remainingTime10Ms;
}
return thermal_value;
}
/**
** @brief 温度检测
** @param None
*/
void angsens_MG_check(void) {
bool MGH = gpio_input_bit_get(GPIOB, GPIO_PIN_10);
bool MGL = gpio_input_bit_get(GPIOB, GPIO_PIN_11);
CAN0_transmiter.MagStatus = MGH or MGL;
}
void power_manage(void) {
float last_vbus = sampler.get_vbus_voltage();
sampler.update_vbus_voltage();
FOC.update_power();
float vbus = sampler.get_vbus_voltage();
if ((vbus < 22.0f) and (last_vbus > vbus) and vbus > 8.0f) {
FOC.shut_down();
flashEEP.save_system_config(true);
} else {
FOC.resume();
}
}
-40
View File
@@ -1,40 +0,0 @@
#ifndef _HEALTH_H
#define _HEALTH_H
#include "stdint.h"
typedef int32_t q16_16_t; // Q16.16格式
// 定点数运算宏
#define Q16_16_ONE 65536 // 1.0 in Q16.16
#define FLOAT_TO_Q16_16(x) ((q16_16_t)((x) * Q16_16_ONE))
#define Q16_16_TO_FLOAT(x) ((float)(x) / Q16_16_ONE)
#define Q16_16_MUL(a, b) ((q16_16_t)(((int64_t)(a) * (b)) >> 16))
#define Q16_16_SQUARE(x) Q16_16_MUL((x), (x))
class ThermalController {
private:
u8 temperature;
u16 current_max;
q16_16_t thermalRate; // 热耗散系数(每单位时间散热比例)
q16_16_t recoveryRate; // 自然恢复率(散热到多少以下开始工作)
u32 thermal_value = 0;
u32 thermal_capacity = 3600000; // 热容量
u16 gapTimeMs = 10; // 单次计算间隔ms
u16 remainingTime10Ms = 0; // 过热冷却剩余ms
public:
ThermalController()
: thermalRate(FLOAT_TO_Q16_16(0.995f)),
recoveryRate(FLOAT_TO_Q16_16(0.33f)) {}
u32 update();
void reset() {
thermal_value = 0;
remainingTime10Ms = 0;
}
};
void angsens_MG_check(void);
void power_manage(void);
#endif
+362 -47
View File
@@ -1,33 +1,24 @@
#include "initial.h"
#include "OTA.h"
#include "config.h"
#include "core_cmFunc.h"
#include "gd32c10x.h"
#include "gd32c10x_gpio.h"
#include "gd32c10x_rcu.h"
#include "main.h"
#include "systick.h"
#include <cstdio>
#include <stdint.h>
#include <stdio.h>
extern BootloaderSystem sys;
/* retarget the C library printf function to the USART */
u8 USART0_init() {
gd_eval_com_init(EVAL_COM0);
return 1;
}
/*!
\brief configure the watchdog peripheral
\param[in] none
\param[out] none
\retval none
*/
u8 watchdog_init(u32 time) {
u8 status = 0;
/* configure FWDGT counter clock: 40KHz(IRC40K) / 64 = 0.625 KHz */
/* time = reload_value / clock_frequency */
status = fwdgt_config(time * 0.625, FWDGT_PSC_DIV64);
fwdgt_enable();
return status;
}
int fputc(int ch, FILE *f) throw() {
usart_data_transmit(EVAL_COM0, (uint8_t)ch);
while (RESET == usart_flag_get(EVAL_COM0, USART_FLAG_TBE))
@@ -50,44 +41,368 @@ void unused_pin_init() {
gpio_bit_reset(GPIOC, GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
}
/**
* @brief 扫描APP地址范围内的Flash内容
* @param print_content 是否打印Flash内容,默认为true
* @param page_count 扫描的页数,默认为0表示扫描整个APP区域
* @retval 无
*/
void scanAppFlashContent(bool print_content, u32 page_count) {
u32 start_addr = APPLATEST_START_ADDR;
u32 total_size = 0xC000;
// 如果指定了页数,则按页数计算大小
if (page_count > 0) {
total_size = page_count * FMC_PAGE_SIZE;
}
u32 end_addr = start_addr + total_size;
#if DEBUG_OTA
printf("Scanning Flash from 0x%08X to 0x%08X (%d bytes)\r\n", start_addr,
end_addr, total_size);
#endif
u32 page_count_scanned = 0;
u32 empty_pages = 0;
u32 data_pages = 0;
for (u32 addr = start_addr; addr < end_addr; addr += FMC_PAGE_SIZE) {
bool page_empty = true;
// 检查当前页是否全为0xFF(空页)
for (u32 offset = 0; offset < FMC_PAGE_SIZE; offset += 4) {
u32 data = *(u32 *)(addr + offset);
if (data != 0xFFFFFFFF) {
page_empty = false;
break; // 找到非空数据,立即退出检查
}
}
if (page_empty) {
empty_pages++;
} else {
data_pages++;
// // 只有在非空页面且需要打印时才输出内容
// if (print_content) {
// printf("Page 0x%08X: \r\n", addr);
// // 打印所有内容
// for (u32 offset = 0; offset < FMC_PAGE_SIZE;
// offset += 16) { // 每行打印16字节
// // 打印地址偏移
// printf(" +%03X: ", offset);
// // 打印十六进制数据
// for (u32 byte_idx = 0; byte_idx < 16; byte_idx++) {
// if ((offset + byte_idx) < FMC_PAGE_SIZE) {
// u8 data = *(__IO u8 *)(addr + offset + byte_idx);
// printf("%02X ", data);
// } else {
// printf(" "); // 空白填充
// }
// // 每8字节加个小空格,便于阅读
// if (byte_idx == 7) {
// printf(" ");
// }
// }
// // 打印可打印字符
// printf("|");
// for (u32 byte_idx = 0; byte_idx < 16; byte_idx++) {
// if ((offset + byte_idx) < FMC_PAGE_SIZE) {
// u8 data = *(__IO u8 *)(addr + offset + byte_idx);
// if (data >= 32 && data <= 126) { // 可打印字符范围
// printf("%c", data);
// } else {
// printf(".");
// }
// } else {
// printf(" "); // 空白填充
// }
// }
// printf("|\r\n");
// }
// }
}
page_count_scanned++;
}
#if DEBUG_OTA
printf("Scan complete: %d pages scanned, %d empty pages, %d data pages\r\n",
page_count_scanned, empty_pages, data_pages);
#endif
}
/*!
\brief 检测并打印复位源信息
\brief prepare system to enter deep sleep mode
\param[in] none
\param[out] none
\retval none
*/
u16 get_reset_cause(void) {
u16 cause = 0;
if (RESET != rcu_flag_get(RCU_FLAG_FWDGTRST)) {
// printf("Free Watchdog Timer Reset\r\n");
cause = RCU_FLAG_FWDGTRST;
}
if (RESET != rcu_flag_get(RCU_FLAG_EPRST)) {
// printf("External Pin Reset\r\n");
cause = RCU_FLAG_EPRST;
}
void enter_deep_sleep() {
// 关闭不必要的外设时钟
rcu_periph_clock_disable(RCU_TIMER0); // 关闭定时器时钟
rcu_periph_clock_disable(RCU_TIMER1);
rcu_periph_clock_disable(RCU_SPI0); // 关闭SPI时钟
rcu_periph_clock_disable(RCU_I2C0); // 关闭I2C时钟
rcu_periph_clock_disable(RCU_ADC0); // 关闭ADC时钟
// 注意不要关闭GPIOB和AF的时钟,因为需要它们来处理唤醒中断
if (RESET != rcu_flag_get(RCU_FLAG_PORRST)) {
// printf("Power Reset\r\n");
cause = RCU_FLAG_PORRST;
}
// 设置深睡眠模式下的电压以进一步降低功耗
rcu_deepsleep_voltage_set(RCU_DEEPSLEEP_V_0_8); // 设置最低电压
if (RESET != rcu_flag_get(RCU_FLAG_WWDGTRST)) {
// printf("Window Watchdog Timer Reset\r\n");
cause = RCU_FLAG_WWDGTRST;
}
// 配置PB8为输入模式,用于外部中断
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_AF);
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_8);
if (RESET != rcu_flag_get(RCU_FLAG_LPRST)) {
// printf("Low Power Reset\r\n");
cause = RCU_FLAG_LPRST;
}
// 配置EXTI中断(连接到PB8引脚)
gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB,
GPIO_PIN_SOURCE_8); // 配置GPIOB的PIN8作为EXTI8的源
exti_init(EXTI_8, EXTI_INTERRUPT, EXTI_TRIG_RISING); // 边沿触发
exti_interrupt_enable(EXTI_8);
nvic_irq_enable(EXTI5_9_IRQn, 0, 0); //
if (RESET != rcu_flag_get(RCU_FLAG_SWRST)) {
// printf("Software Reset\r\n");
cause = RCU_FLAG_SWRST;
}
// 清除所有复位标志
rcu_all_reset_flag_clear();
// printf("cause:%d\r\n", cause);
return cause;
// 确保中断标志已被清除
exti_interrupt_flag_clear(EXTI_8);
__enable_irq();
delay_1ms(10);
// 进入深度睡眠
pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD);
}
/**
* @brief 写地址
* @return fmc_state_enum
*/
fmc_state_enum write_ADDRESS(u32 address, u32 data) {
fmc_unlock();
fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_PGAERR | FMC_FLAG_WPERR);
// 确保使用对齐地址
fmc_state_enum fmc_status = fmc_word_program(address, data);
fmc_lock();
return fmc_status;
}
/**
* @brief EXTI5_9中断处理函数
* @param 无
* @retval 无
*/
void EXTI5_9_IRQHandler(void) {
if (exti_interrupt_flag_get(EXTI_8) != RESET) {
// 清除中断标志
exti_interrupt_flag_clear(EXTI_8);
// 禁用EXTI线8的中断,防止重复触发
exti_interrupt_disable(EXTI_8);
#if SLEEP_DEBUG
printf("MCU wake up\r\n");
#endif
OTA_SET(n_APP_LATEST_EN_ADDR, OTA_AVAL); // 设置APP为不激活
// 遍历睡眠存储区
for (u32 address = SLEEP_CONFIG_END - SIZE_U32;
address >= SLEEP_CONFIG_START; address -= SIZE_U32) {
volatile u32 *flash_ptr = (volatile u32 *)address;
u32 sleep_check = *flash_ptr;
if (sleep_check == FLASH_EMPTY and
address > SLEEP_CONFIG_START) { // 空则跳过该次循环
continue;
} else if (
sleep_check == SLEEP_ENABLE and
address >
SLEEP_CONFIG_START) { // 如果检查到睡眠启用,写入非启用
#if SLEEP_DEBUG
printf("boot sleep found %08x at %08x\r\n", sleep_check,
address);
#endif
if (address == SLEEP_CONFIG_END - SIZE_U32) {
fmc_unlock();
fmc_state_enum fmc_status =
fmc_page_erase(SLEEP_CONFIG_START); // 擦除已满的页
if (fmc_status != FMC_READY) { // 擦除失败报错
fmc_lock();
return;
}
address = SLEEP_CONFIG_START - SIZE_U32; // 重新开始写入
}
fmc_state_enum fmc_status =
write_ADDRESS(address + SIZE_U32, SLEEP_DISABLE);
if (fmc_status != FMC_READY) { // 写入失败报错
;
}
break; // 完成,跳出遍历
} else if (sleep_check == SLEEP_DISABLE) { // 已经是非休眠则跳出遍历
break;
} else {
fmc_state_enum fmc_status =
write_ADDRESS(address, SLEEP_DISABLE);
if (fmc_status != FMC_READY) { // 写入失败报错
;
}
break;
}
}
// 唤醒后软重启,确保正常初始化
system_soft_reset();
}
}
int check_sleep() {
#if SLEEP_DEBUG
printf("sleep check\r\n");
#endif
for (u32 address = SLEEP_CONFIG_END - SIZE_U32;
address >= SLEEP_CONFIG_START; address -= SIZE_U32) { // 遍历睡眠存储区
volatile u32 *flash_ptr = (volatile u32 *)address;
u32 sleep_check = *flash_ptr;
#if SLEEP_DEBUG
printf("sleep check %8x-----%x\r\n", address, sleep_check);
#endif
if (sleep_check == FLASH_EMPTY) { // 空则跳过
continue;
} else if (sleep_check == SLEEP_ENABLE) { // 睡眠使能则继续休眠
#if SLEEP_DEBUG
printf("sleep enable\r\n");
#endif
enter_deep_sleep();
return 0;
} else if (sleep_check == SLEEP_DISABLE) { // 禁用睡眠则跳出
#if SLEEP_DEBUG
printf("sleep disable\r\n");
#endif
return 0;
}
}
// 遍历到头都未找到,写入第一次的数据
#if SLEEP_DEBUG
printf("boot sleep not found\r\n");
#endif
fmc_state_enum fmc_status =
write_ADDRESS(SLEEP_CONFIG_START, SLEEP_DISABLE);
if (fmc_status != FMC_READY) { // 写入失败报错
#if SLEEP_DEBUG
printf("boot sleep write error\r\n");
#endif
return 1;
}
return 2; // 第一次启动
}
// // 发送单个字节到串口 (用于调试)
// void uart_send_byte(uint8_t data) {
// // 实际的串口发送代码
// while (RESET == usart_flag_get(USART0, USART_FLAG_TBE))
// ;
// usart_data_transmit(USART0, data);
// }
// // 以十六进制格式打印数据
// // 安全的十六进制打印函数,不使用sprintf,不使用大缓冲区
// void safe_print_hex(const char *prefix, const uint8_t *data, size_t length) {
// // 1. 先打印前缀
// const char *p = prefix;
// while (*p) {
// while (RESET == usart_flag_get(USART0, USART_FLAG_TBE))
// ;
// usart_data_transmit(USART0, *p++);
// }
// while (RESET == usart_flag_get(USART0, USART_FLAG_TBE))
// ;
// usart_data_transmit(USART0, ':');
// while (RESET == usart_flag_get(USART0, USART_FLAG_TBE))
// ;
// usart_data_transmit(USART0, ' ');
// // 2. 逐字节打印数据,每16字节换行
// for (size_t i = 0; i < length; i++) {
// uint8_t byte = data[i];
// // 打印高4位
// uint8_t high = (byte >> 4) & 0x0F;
// char high_char = (high < 10) ? ('0' + high) : ('A' + high - 10);
// while (RESET == usart_flag_get(USART0, USART_FLAG_TBE))
// ;
// usart_data_transmit(USART0, high_char);
// // 打印低4位
// uint8_t low = byte & 0x0F;
// char low_char = (low < 10) ? ('0' + low) : ('A' + low - 10);
// while (RESET == usart_flag_get(USART0, USART_FLAG_TBE))
// ;
// usart_data_transmit(USART0, low_char);
// // 打印空格
// while (RESET == usart_flag_get(USART0, USART_FLAG_TBE))
// ;
// usart_data_transmit(USART0, ' ');
// // 每16字节换行
// if ((i + 1) % 16 == 0 && i < length - 1) {
// // 换行
// while (RESET == usart_flag_get(USART0, USART_FLAG_TBE))
// ;
// usart_data_transmit(USART0, '\r');
// while (RESET == usart_flag_get(USART0, USART_FLAG_TBE))
// ;
// usart_data_transmit(USART0, '\n');
// // 缩进(4个空格)
// for (int j = 0; j < 4; j++) {
// while (RESET == usart_flag_get(USART0, USART_FLAG_TBE))
// ;
// usart_data_transmit(USART0, ' ');
// }
// }
// }
// // 3. 打印换行
// while (RESET == usart_flag_get(USART0, USART_FLAG_TBE))
// ;
// usart_data_transmit(USART0, '\r');
// while (RESET == usart_flag_get(USART0, USART_FLAG_TBE))
// ;
// usart_data_transmit(USART0, '\n');
// }
// void test_decrypt() {
// printf("AES Encryption Verification Starting...\r\n");
// // 定义48字节测试数据
// uint8_t plaintext[48] = {
// 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
// 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
// 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
// 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F};
// // 定义128位密钥 (16字节)
// uint8_t key[16] = {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
// 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c};
// // 创建AES上下文
// aes128_context ctx;
// // 设置密钥
// aes128_set_key(&ctx, key);
// // 打印原始数据
// safe_print_hex("Original Data", plaintext, 48);
// uint8_t ciphertext[48];
// uint8_t decrypted[48];
// // 加密
// aes128_ecb_encrypt_48bytes(&ctx, plaintext, ciphertext);
// safe_print_hex("Encrypted Data", ciphertext, 48);
// // 解密
// aes128_ecb_decrypt_48bytes(&ctx, ciphertext, decrypted);
// safe_print_hex("Decrypted Data", decrypted, 48);
// }
+8 -12
View File
@@ -6,25 +6,21 @@ extern "C" {
#endif
#include "gd32c10x_eval.h"
#include "stdint.h"
#include "cstdint"
#include <stdio.h>
constexpr u16 REDUCTION_RATIO = 25;
constexpr float DEG2RAD = 1.0f / 360.0f * 6.28318530718f;
constexpr float RAD2DEG = 360.0f / 6.28318530718f;
void rcu_config(void);
static volatile uint32_t timer_delay_count = 0; // volatile 很重要!
int fputc(int ch, FILE *f); // 声明fputc函数以重载标准库实现
int fputc(int ch, FILE *f); // 声明fputc函数以重载标准库实现
u8 USART0_init(void);
u8 watchdog_init(u32 time);
u16 get_reset_cause(void);
void unused_pin_init();
void print_system_clock_info(void);
void enter_deep_sleep(void);
int check_sleep(void);
void EXTI5_9_IRQHandler(void);
void scanAppFlashContent(bool print_content = true, u32 page_count = 0);
#ifdef __cplusplus
}
#endif
#endif
#endif
+12 -10
View File
@@ -34,12 +34,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "systick.h"
#include "Can.h"
#include "flash.h"
#include "gd32c10x.h"
volatile static uint32_t delay;
extern CAN_transmiter CAN0_transmiter;
extern FlashEEPROM flashEEP;
/*!
\brief configure systick
@@ -57,16 +55,22 @@ void systick_config(void) {
/* configure the systick handler priority */
NVIC_SetPriority(SysTick_IRQn, 0x00U);
}
/*!
\brief delay a time in seconds
\param[in] count: count in seconds
\brief delay a time in microseconds
\param[in] count: count in microseconds
\param[out] none
\retval none
*/
void delay_1s(uint32_t count) {
uint32_t i;
for (i = 0; i < count; i++) {
delay_1ms(1000);
void delay_1us(uint32_t count) {
/* 计算循环次数以实现微秒延时
假设CPU每执行一条nop指令需要1个时钟周期
根据系统时钟频率计算需要的循环次数 */
uint32_t cycles = (SystemCoreClock / 4000000UL) * count; // 每微秒的时钟周期数
/* 循环减去执行指令所需的周期数 */
for(uint32_t i = 0; i < cycles; i++) {
__NOP(); // 空操作指令
}
}
@@ -79,8 +83,6 @@ void delay_1s(uint32_t count) {
void delay_1ms(uint32_t count) {
delay = count;
while (0U != delay) {
fwdgt_counter_reload();
fwdgt_counter_reload();
}
}
+2 -4
View File
@@ -44,14 +44,12 @@ extern "C" {
void systick_config(void);
/* delay a time in milliseconds */
void delay_1ms(uint32_t count);
/* delay a time in microseconds */
void delay_1us(uint32_t count);
/* delay a time in seconds */
void delay_1s(uint32_t count);
/* delay decrement */
void delay_decrement(void);
/* 空闲任务计数 */
void idle_task_count(void);
/* 获取CPU使用率 */
uint8_t get_cpu_usage(void);
/* 系统软复位 */
void system_soft_reset(void);
+11 -7
View File
@@ -1,11 +1,11 @@
cbuild-run:
generated-by: csolution version 2.12.0+p41-gfeadfc5e
generated-by: csolution version 2.13.0+p3-g40b6564e
solution: ../Robot_V2.csolution.yml
target-type: GD32C103CB
target-set: <default>
compiler: AC6
device: GigaDevice::GD32C103CB
device-pack: GigaDevice::GD32C10x_DFP@1.0.1
device-pack: GigaDevice::GD32C10x_DFP@1.5.0
output:
- file: Robot_V2/GD32C103CB/Release/Robot_V2.axf
info: generate by Robot_V2.Release+GD32C103CB
@@ -15,29 +15,33 @@ cbuild-run:
info: generate by Robot_V2.Release+GD32C103CB
type: hex
load: image
- file: Robot_V2/GD32C103CB/Release/Robot_V2.bin
info: generate by Robot_V2.Release+GD32C103CB
type: bin
load: none
system-resources:
memory:
- name: IROM1
access: rx
start: 0x08000000
size: 0x00020000
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
from-pack: GigaDevice::GD32C10x_DFP@1.5.0
- name: IRAM1
access: rwx
start: 0x20000000
size: 0x00008000
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
from-pack: GigaDevice::GD32C10x_DFP@1.5.0
system-descriptions:
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/SVD/GD32C10x.svd
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.5.0/SVD/GD32C10x.svd
type: svd
debugger:
name: ST-Link@pyOCD
protocol: swd
clock: 10000000
clock: 4000000
gdbserver:
- port: 3333
programming:
- algorithm: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Flash/GD32C10x.FLM
- algorithm: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.5.0/Flash/GD32C10x.FLM
start: 0x08000000
size: 0x00020000
ram-start: 0x20000000
@@ -1,5 +1,5 @@
build:
generated-by: csolution version 2.12.0
generated-by: csolution version 2.13.0+p3-g40b6564e
solution: ../../../../Robot_V2.csolution.yml
project: ../../../../Robot_V2/Robot_V2.cproject.yml
context: Robot_V2.Debug+GD32C103CB
@@ -74,12 +74,16 @@ build:
outdir: .
rtedir: ../../../../Robot_V2/RTE
output:
- type: bin
file: Robot_V2.bin
- type: elf
file: Robot_V2.axf
- type: hex
file: Robot_V2.hex
- type: map
file: Robot_V2.axf.map
- type: comp-db
file: compile_commands.json
components:
- component: ARM::CMSIS:CORE@4.3.0
condition: Cortex-M Device
@@ -104,18 +108,6 @@ build:
category: source
attr: config
version: 1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:ADC@1.0.0
condition: GD32C10x STDPERIPHERALS RCU
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
selected-by: Device:GD32C10x_StdPeripherals:ADC
files:
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc/gd32c10x_adc.h
category: header
version: 1.0.0
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/gd32c10x_adc.c
category: source
attr: config
version: 1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:CAN@1.0.0
condition: GD32C10x STDPERIPHERALS RCU
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
@@ -128,6 +120,18 @@ build:
category: source
attr: config
version: 1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:CRC@1.0.0
condition: GD32C10x STDPERIPHERALS RCU
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
selected-by: Device:GD32C10x_StdPeripherals:CRC
files:
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc/gd32c10x_crc.h
category: header
version: 1.0.0
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/gd32c10x_crc.c
category: source
attr: config
version: 1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:DBG@1.0.0
condition: GD32C10x STDPERIPHERALS RCU
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
@@ -236,30 +240,6 @@ build:
category: source
attr: config
version: 1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:SPI_I2S@1.0.0
condition: GD32C10x STDPERIPHERALS RCU
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
selected-by: Device:GD32C10x_StdPeripherals:SPI_I2S
files:
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc/gd32c10x_spi.h
category: header
version: 1.0.0
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/gd32c10x_spi.c
category: source
attr: config
version: 1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:TIMER@1.0.0
condition: GD32C10x STDPERIPHERALS RCU
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
selected-by: Device:GD32C10x_StdPeripherals:TIMER
files:
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc/gd32c10x_timer.h
category: header
version: 1.0.0
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/gd32c10x_timer.c
category: source
attr: config
version: 1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:USART@1.0.0
condition: GD32C10x STDPERIPHERALS RCU
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
@@ -272,18 +252,6 @@ build:
category: source
attr: config
version: 1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:WWDGT@1.0.0
condition: GD32C10x STDPERIPHERALS RCU
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
selected-by: Device:GD32C10x_StdPeripherals:WWDGT
files:
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc/gd32c10x_wwdgt.h
category: header
version: 1.0.0
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/gd32c10x_wwdgt.c
category: source
attr: config
version: 1.0.0
- component: GigaDevice::Device:GD32C10x_libopt@1.0.0
condition: GD32C10x CMSIS
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
@@ -321,6 +289,10 @@ build:
category: header
- file: ../../../../Robot_V2/main.cpp
category: sourceCpp
- file: ../../../../Robot_V2/sys/aes128.h
category: header
- file: ../../../../Robot_V2/sys/aes128.cpp
category: sourceCpp
- group: sys
files:
- file: ../../../../Robot_V2/sys/systick.cpp
@@ -331,48 +303,18 @@ build:
category: sourceCpp
- file: ../../../../Robot_V2/sys/initial.h
category: header
- file: ../../../../Robot_V2/sys/health.h
- file: ../../../../Robot_V2/sys/OTA.h
category: header
- file: ../../../../Robot_V2/sys/health.cpp
- file: ../../../../Robot_V2/sys/OTA.cpp
category: sourceCpp
- file: ../../../../Robot_V2/sys/config.h
category: header
- group: device
files:
- file: ../../../../Robot_V2/device/Can.cpp
category: sourceCpp
- file: ../../../../Robot_V2/device/Can.h
category: header
- file: ../../../../Robot_V2/device/ang_sensor.cpp
category: sourceCpp
- file: ../../../../Robot_V2/device/ang_sensor.h
category: header
- file: ../../../../Robot_V2/device/ADC.cpp
category: sourceCpp
- file: ../../../../Robot_V2/device/adc.h
category: header
- file: ../../../../Robot_V2/device/Timer.cpp
category: sourceCpp
- file: ../../../../Robot_V2/device/Timer.h
category: header
- file: ../../../../Robot_V2/device/test.cpp
category: sourceCpp
- file: ../../../../Robot_V2/device/motor.cpp
category: sourceCpp
- file: ../../../../Robot_V2/device/motor.h
category: header
- group: Algorithm
files:
- file: ../../../../Robot_V2/Algorithm/Filter.cpp
category: sourceCpp
- file: ../../../../Robot_V2/Algorithm/Filter.h
category: header
- file: ../../../../Robot_V2/Algorithm/DengFOC.cpp
category: sourceCpp
- file: ../../../../Robot_V2/Algorithm/DengFOC.h
category: header
- file: ../../../../Robot_V2/Algorithm/pid.cpp
category: sourceCpp
- file: ../../../../Robot_V2/pid.h
category: header
constructed-files:
- file: ../../../../Robot_V2/RTE/_Debug_GD32C103CB/RTE_Components.h
category: header
@@ -387,8 +329,8 @@ build:
- pack: GigaDevice::GD32C10x_DFP@1.0.1
components:
- component: GigaDevice::Device:EVAL:GD32C10x@1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:ADC@1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:CAN@1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:CRC@1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:DBG@1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:DMA@1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:EXTI@1.0.0
@@ -398,9 +340,6 @@ build:
- component: GigaDevice::Device:GD32C10x_StdPeripherals:MISC@1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:PMU@1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:RCU@1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:SPI_I2S@1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:TIMER@1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:USART@1.0.0
- component: GigaDevice::Device:GD32C10x_StdPeripherals:WWDGT@1.0.0
- component: GigaDevice::Device:GD32C10x_libopt@1.0.0
- component: GigaDevice::Device:Startup@1.0.0

Some files were not shown because too many files have changed in this diff Show More