Compare commits
10
Commits
26e73f451e
...
c357a8af6f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c357a8af6f | ||
|
|
46d4bfe8ef | ||
|
|
d019b41ed6 | ||
|
|
26cf5af14f | ||
|
|
1e6d47ddae | ||
|
|
aefb7d4ee4 | ||
|
|
c7c4451d57 | ||
|
|
2f482554f0 | ||
|
|
9c7145ef99 | ||
|
|
a25ec5f029 |
+84
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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'
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -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,10 +747,9 @@ 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) {
|
||||
@@ -830,7 +829,7 @@ uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct *t
|
||||
|
||||
/* 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) {
|
||||
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)) {
|
||||
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) {
|
||||
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)) {
|
||||
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) {
|
||||
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)) {
|
||||
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");
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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,6 +303,7 @@ 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)){
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/* configure FWDGT */
|
||||
FWDGT_PSC = (uint32_t)prescaler_div;
|
||||
|
||||
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));
|
||||
|
||||
if((uint32_t)RESET != flag_status) {
|
||||
return ERROR;
|
||||
if(0U != flag_status) {
|
||||
status = ERROR;
|
||||
}
|
||||
|
||||
if(SUCCESS == status) {
|
||||
/* configure FWDGT_RLD */
|
||||
FWDGT_RLD = RLD_RLD(reload_value);
|
||||
|
||||
/* 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(0U != flag_status) {
|
||||
status = ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if(SUCCESS == status) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-67
@@ -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);
|
||||
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
|
||||
|
||||
@@ -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执行一次的操作
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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); }
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
+90
-23
@@ -1,41 +1,108 @@
|
||||
#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初始化
|
||||
void BootloaderSystem::initHardware() {
|
||||
systick_config(); // 系统时钟初始化
|
||||
SystemCoreClockUpdate(); // 更新系统时钟变量
|
||||
CAN0_transmiter.init();
|
||||
}
|
||||
USART0_init(); // 调试串口初始化
|
||||
|
||||
void run() {
|
||||
// 检查是否触发OTA模式
|
||||
if (1) {
|
||||
// OTA模式
|
||||
while (1) {
|
||||
ota.process();
|
||||
for (volatile int i = 0; i < 500000; i++)
|
||||
; // 简单延时
|
||||
}
|
||||
} else {
|
||||
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();
|
||||
}
|
||||
} else {
|
||||
#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
@@ -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 */
|
||||
|
||||
+765
-96
@@ -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)
|
||||
return;
|
||||
|
||||
// 这里可以添加超时处理逻辑
|
||||
// 例如:10秒无数据则退出OTA模式
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
// 简单验证:检查栈指针是否在SRAM范围内
|
||||
return (stack_ptr >= 0x20000000 && stack_ptr < 0x20008000) &&
|
||||
(reset_handler >= APP_START_ADDR &&
|
||||
reset_handler < (APP_START_ADDR + APP_MAX_SIZE));
|
||||
}
|
||||
|
||||
void OTAHandler::jumpToApplication() {
|
||||
if (!validateApplication()) {
|
||||
// 无效APP,停留在bootloader
|
||||
return;
|
||||
}
|
||||
|
||||
// 关闭所有中断
|
||||
__disable_irq();
|
||||
|
||||
// 设置主栈指针
|
||||
uint32_t msp_value = *(__IO uint32_t *)APP_START_ADDR;
|
||||
__set_MSP(msp_value);
|
||||
|
||||
// 获取复位地址
|
||||
uint32_t reset_handler = *(__IO uint32_t *)(APP_START_ADDR + 4);
|
||||
typedef void (*AppEntryFunc)(void);
|
||||
AppEntryFunc app_entry = (AppEntryFunc)reset_handler;
|
||||
|
||||
// 跳转
|
||||
app_entry();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
fmc_lock();
|
||||
}
|
||||
|
||||
void OTAHandler::writeApplicationData(uint32_t offset, uint8_t *data,
|
||||
uint32_t size) {
|
||||
fmc_unlock();
|
||||
uint32_t write_addr = APP_START_ADDR + offset;
|
||||
|
||||
// 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;
|
||||
// 执行待处理的Flash擦除操作(在主循环中执行,避免中断中耗时操作)
|
||||
if (pending_flash_erase) {
|
||||
pending_flash_erase = false;
|
||||
#if DEBUG_OTA
|
||||
printf("Executing pending Flash erase...\r\n");
|
||||
#endif
|
||||
eraseApplicationArea();
|
||||
ota_active = true;
|
||||
sendACK(0xFFFFFFFF); // 确认开始
|
||||
#if DEBUG_OTA
|
||||
printf("Flash erase completed.\r\n");
|
||||
#endif
|
||||
// Flash擦除完成后,更新状态为接收固件
|
||||
ota_state = OTA_STATE_RECEIVING_FIRMWARE;
|
||||
}
|
||||
} 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);
|
||||
|
||||
if (offset < expected_size) {
|
||||
writeApplicationData(offset, &data[4], len - 4);
|
||||
received_size += (len - 4);
|
||||
sendACK(packet_num);
|
||||
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++;
|
||||
}
|
||||
|
||||
// 检查是否完成
|
||||
if (received_size >= expected_size) {
|
||||
ota_active = false;
|
||||
// 跳转前延时让ACK发出
|
||||
for (volatile int i = 0; i < 100000; i++)
|
||||
;
|
||||
// 检查是否超时(例如: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];
|
||||
|
||||
#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范围内
|
||||
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()) {
|
||||
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();
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
NVIC->ICER[i] = 0xFFFFFFFF;
|
||||
}
|
||||
// 2. 重置外设(特别是CAN,防止冲突)
|
||||
can_deinit(CAN0);
|
||||
|
||||
// 3. 重置系统时钟到默认状态
|
||||
rcu_system_clock_source_config(RCU_CKSYSSRC_IRC8M);
|
||||
|
||||
#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() {
|
||||
|
||||
fmc_unlock();
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 写入应用程序数据
|
||||
* @param offset: 写入偏移量
|
||||
* @param data: 数据指针
|
||||
* @param size: 数据大小
|
||||
* @retval 无
|
||||
*/
|
||||
void OTAHandler::writeApplicationData(u32 offset, u8 *data, u32 size) {
|
||||
fmc_unlock();
|
||||
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];
|
||||
}
|
||||
|
||||
fmc_word_program(write_addr + i, word);
|
||||
}
|
||||
fmc_lock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
// 直接使用数据指针,避免不必要的内存复制
|
||||
const u8 *receive_encrypted_data =
|
||||
data + 8; // 加密数据从偏移8字节开始
|
||||
const u8 *receive_dataCRC32 = data + 60; // CRC数据从偏移60字节开始
|
||||
|
||||
// 解密 - 使用栈上数组存储解密结果
|
||||
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
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -374,80 +53,3 @@ 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;
|
||||
}
|
||||
}
|
||||
+1
-29
@@ -2,8 +2,6 @@
|
||||
#define __FLASH_H
|
||||
|
||||
#include <stdint.h>
|
||||
// 修改后 - 强制4字节对齐
|
||||
#define ALIGN_4BYTE(addr) ((addr) & 0xFFFFFFFC) // 4字节对齐
|
||||
|
||||
// EEPROM操作状态
|
||||
typedef enum {
|
||||
@@ -27,20 +25,7 @@ class FlashEEPROM {
|
||||
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; // 虚拟地址掩码
|
||||
|
||||
// 定义用户自定义的虚拟地址
|
||||
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 */
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
// }
|
||||
|
||||
+6
-10
@@ -6,23 +6,19 @@ 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函数以重载标准库实现
|
||||
|
||||
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
|
||||
|
||||
+12
-10
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user